diff --git a/.changeset/breezy-knives-greet.md b/.changeset/breezy-knives-greet.md new file mode 100644 index 00000000..cc0035bd --- /dev/null +++ b/.changeset/breezy-knives-greet.md @@ -0,0 +1,27 @@ +--- +"@dpkit/camtrap": minor +"@dpkit/datahub": minor +"@dpkit/parquet": minor +"@dpkit/extend": minor +"@dpkit/folder": minor +"@dpkit/github": minor +"@dpkit/inline": minor +"@dpkit/zenodo": minor +"@dpkit/arrow": minor +"dpkit": minor +"@dpkit/excel": minor +"@dpkit/table": minor +"@dpkit/ckan": minor +"@dpkit/core": minor +"@dpkit/file": minor +"@dpkit/json": minor +"@dpkit/test": minor +"@dpkit/cli": minor +"@dpkit/csv": minor +"@dpkit/ods": minor +"@dpkit/zip": minor +"@dpkit/db": minor +"@dpkit/ui": minor +--- + +Added Json/Jsonl/Arrow/Parquet support; Bootstrapped CLI diff --git a/.gitignore b/.gitignore index a9ffb100..33dea10d 100644 --- a/.gitignore +++ b/.gitignore @@ -60,9 +60,10 @@ pids .vscode/ .wrangler/ build/ +compile/ dist/ .astro/ -/docs/content/docs/packages/ +/docs/content/docs/reference/ **/.claude/settings.local.json AGENTS.md CLAUDE.md diff --git a/arrow/CHANGELOG.md b/arrow/CHANGELOG.md new file mode 100644 index 00000000..1993a313 --- /dev/null +++ b/arrow/CHANGELOG.md @@ -0,0 +1,2 @@ +# @dpkit/arrow + diff --git a/bin/README.md b/arrow/README.md similarity index 95% rename from bin/README.md rename to arrow/README.md index 9fbb48a6..6a3d5f20 100644 --- a/bin/README.md +++ b/arrow/README.md @@ -1,3 +1,3 @@ -# @dpkit/bin +# @dpkit/arrow dpkit is a fast TypeScript data management framework built on top of the Data Package standard and Polars DataFrames. It supports various formats like CSV, JSON, and Parquet and integrates with data platforms such as CKAN, Zenodo, and GitHub. For more information, please visit the [documentation portal](https://dpkit.datist.io). diff --git a/arrow/index.ts b/arrow/index.ts new file mode 100644 index 00000000..5f4f33d9 --- /dev/null +++ b/arrow/index.ts @@ -0,0 +1,2 @@ +export * from "./table/index.ts" +export * from "./plugin.ts" diff --git a/avro/package.json b/arrow/package.json similarity index 54% rename from avro/package.json rename to arrow/package.json index 3281b069..338466ef 100644 --- a/avro/package.json +++ b/arrow/package.json @@ -1,8 +1,8 @@ { - "name": "@dpkit/avro", + "name": "@dpkit/arrow", "type": "module", - "main": "build/index.js", - "version": "0.2.0", + "version": "0.1.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -17,9 +17,19 @@ "validation", "quality", "fair", - "avro" + "parquet" ], "scripts": { - "build": "tsc --build" + "build": "tsc" + }, + "dependencies": { + "@dpkit/core": "workspace:*", + "@dpkit/file": "workspace:*", + "@dpkit/table": "workspace:*", + "csv-sniffer": "^0.1.1", + "nodejs-polars": "^0.21.0" + }, + "devDependencies": { + "@dpkit/test": "workspace:*" } } diff --git a/arrow/plugin.ts b/arrow/plugin.ts new file mode 100644 index 00000000..133ee938 --- /dev/null +++ b/arrow/plugin.ts @@ -0,0 +1,26 @@ +import type { Resource } from "@dpkit/core" +import { inferFormat } from "@dpkit/core" +import type { TablePlugin } from "@dpkit/table" +import type { SaveTableOptions, Table } from "@dpkit/table" +import { loadArrowTable, saveArrowTable } from "./table/index.ts" + +export class ArrowPlugin implements TablePlugin { + async loadTable(resource: Partial) { + const isArrow = getIsArrow(resource) + if (!isArrow) return undefined + + return await loadArrowTable(resource) + } + + async saveTable(table: Table, options: SaveTableOptions) { + const isArrow = getIsArrow(options) + if (!isArrow) return undefined + + return await saveArrowTable(table, options) + } +} + +function getIsArrow(resource: Partial) { + const format = inferFormat(resource) + return format === "arrow" || format === "feather" +} diff --git a/arrow/table.arrow b/arrow/table.arrow new file mode 100644 index 00000000..83e3baa0 Binary files /dev/null and b/arrow/table.arrow differ diff --git a/arrow/table/fixtures/table.arrow b/arrow/table/fixtures/table.arrow new file mode 100644 index 00000000..83e3baa0 Binary files /dev/null and b/arrow/table/fixtures/table.arrow differ diff --git a/arrow/table/index.ts b/arrow/table/index.ts new file mode 100644 index 00000000..a65e5663 --- /dev/null +++ b/arrow/table/index.ts @@ -0,0 +1,2 @@ +export { loadArrowTable } from "./load.ts" +export { saveArrowTable } from "./save.ts" diff --git a/arrow/table/load.spec.ts b/arrow/table/load.spec.ts new file mode 100644 index 00000000..cd78f74e --- /dev/null +++ b/arrow/table/load.spec.ts @@ -0,0 +1,64 @@ +import { getTempFilePath } from "@dpkit/file" +import { useRecording } from "@dpkit/test" +import { DataFrame } from "nodejs-polars" +import { describe, expect, it } from "vitest" +import { loadArrowTable } from "./load.ts" + +describe("loadArrowTable", () => { + useRecording() + + describe("file variations", () => { + it("should load local file", async () => { + const path = getTempFilePath() + DataFrame({ id: [1, 2], name: ["english", "中文"] }).writeIPC(path) + + const table = await loadArrowTable({ path }) + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + ]) + }) + + it("should load local file (multipart)", async () => { + const path1 = getTempFilePath() + const path2 = getTempFilePath() + DataFrame({ id: [1, 2], name: ["english", "中文"] }).writeIPC(path1) + DataFrame({ id: [1, 2], name: ["english", "中文"] }).writeIPC(path2) + + const table = await loadArrowTable({ path: [path1, path2] }) + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + ]) + }) + + it.skip("should load remote file", async () => { + const table = await loadArrowTable({ + path: "https://github.com/frictionlessdata/frictionless-py/raw/refs/heads/main/data/table.arrow", + }) + + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中国人" }, + ]) + }) + + it.skip("should load remote file (multipart)", async () => { + const table = await loadArrowTable({ + path: [ + "https://github.com/frictionlessdata/frictionless-py/raw/refs/heads/main/data/table.arrow", + "https://github.com/frictionlessdata/frictionless-py/raw/refs/heads/main/data/table.arrow", + ], + }) + + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中国人" }, + { id: 1, name: "english" }, + { id: 2, name: "中国人" }, + ]) + }) + }) +}) diff --git a/arrow/table/load.ts b/arrow/table/load.ts new file mode 100644 index 00000000..931b0057 --- /dev/null +++ b/arrow/table/load.ts @@ -0,0 +1,19 @@ +import type { Resource } from "@dpkit/core" +import { prefetchFiles } from "@dpkit/file" +import { concat } from "nodejs-polars" +import { DataFrame } from "nodejs-polars" +import { scanIPC } from "nodejs-polars" + +export async function loadArrowTable(resource: Partial) { + const [firstPath, ...restPaths] = await prefetchFiles(resource.path) + if (!firstPath) { + return DataFrame().lazy() + } + + let table = scanIPC(firstPath) + if (restPaths.length) { + table = concat([table, ...restPaths.map(path => scanIPC(path))]) + } + + return table +} diff --git a/arrow/table/save.spec.ts b/arrow/table/save.spec.ts new file mode 100644 index 00000000..41eef947 --- /dev/null +++ b/arrow/table/save.spec.ts @@ -0,0 +1,24 @@ +import { getTempFilePath } from "@dpkit/file" +import { DataFrame } from "nodejs-polars" +import { describe, expect, it } from "vitest" +import { loadArrowTable } from "./load.ts" +import { saveArrowTable } from "./save.ts" + +describe("saveArrowTable", () => { + it("should save table to Arrow file", async () => { + const path = getTempFilePath() + const source = DataFrame({ + id: [1.0, 2.0, 3.0], + name: ["Alice", "Bob", "Charlie"], + }).lazy() + + await saveArrowTable(source, { path }) + + const target = await loadArrowTable({ path }) + expect((await target.collect()).toRecords()).toEqual([ + { id: 1.0, name: "Alice" }, + { id: 2.0, name: "Bob" }, + { id: 3.0, name: "Charlie" }, + ]) + }) +}) diff --git a/arrow/table/save.ts b/arrow/table/save.ts new file mode 100644 index 00000000..087e5143 --- /dev/null +++ b/arrow/table/save.ts @@ -0,0 +1,13 @@ +import type { SaveTableOptions, Table } from "@dpkit/table" + +// TODO: rebase on sinkIPC when it is available +// https://github.com/pola-rs/nodejs-polars/issues/353 + +export async function saveArrowTable(table: Table, options: SaveTableOptions) { + const { path } = options + + const df = await table.collect() + df.writeIPC(path) + + return path +} diff --git a/arrow/tsconfig.json b/arrow/tsconfig.json new file mode 100644 index 00000000..3c43903c --- /dev/null +++ b/arrow/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../tsconfig.json" +} diff --git a/arrow/typedoc.json b/arrow/typedoc.json new file mode 100644 index 00000000..f8e49f3a --- /dev/null +++ b/arrow/typedoc.json @@ -0,0 +1,4 @@ +{ + "entryPoints": ["index.ts"], + "skipErrorChecking": true +} diff --git a/avro/CHANGELOG.md b/avro/CHANGELOG.md deleted file mode 100644 index ee89a705..00000000 --- a/avro/CHANGELOG.md +++ /dev/null @@ -1,7 +0,0 @@ -# @dpkit/avro - -## 0.2.0 - -### Minor Changes - -- edfde49: General framework improvements diff --git a/avro/README.md b/avro/README.md deleted file mode 100644 index 5ced2e65..00000000 --- a/avro/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# @dpkit/avro - -dpkit is a fast TypeScript data management framework built on top of the Data Package standard and Polars DataFrames. It supports various formats like CSV, JSON, and Parquet and integrates with data platforms such as CKAN, Zenodo, and GitHub. For more information, please visit the [documentation portal](https://dpkit.datist.io). diff --git a/avro/tsconfig.json b/avro/tsconfig.json deleted file mode 100644 index 7be40230..00000000 --- a/avro/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } -} diff --git a/bin/package.json b/bin/package.json deleted file mode 100644 index 17ff3cdc..00000000 --- a/bin/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "@dpkit/bin", - "type": "module", - "private": true -} diff --git a/camtrap/OVERVIEW.md b/camtrap/OVERVIEW.md deleted file mode 100644 index ee2ed4ad..00000000 --- a/camtrap/OVERVIEW.md +++ /dev/null @@ -1,6 +0,0 @@ -# @dpkit/camtrap - -:::note -This overview is under development. -::: - diff --git a/camtrap/index.ts b/camtrap/index.ts index 58d9fce6..a35642cf 100644 --- a/camtrap/index.ts +++ b/camtrap/index.ts @@ -1 +1 @@ -export * from "./package/index.js" +export * from "./package/index.ts" diff --git a/camtrap/package.json b/camtrap/package.json index eb2ae0e4..c165f8a5 100644 --- a/camtrap/package.json +++ b/camtrap/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/camtrap", "type": "module", - "main": "build/index.js", "version": "0.5.1", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,7 +20,7 @@ "camtrap" ], "scripts": { - "build": "tsc --build" + "build": "tsc" }, "dependencies": { "@dpkit/core": "workspace:*" diff --git a/camtrap/package/assert.ts b/camtrap/package/assert.ts index 9394daf1..1f5915df 100644 --- a/camtrap/package/assert.ts +++ b/camtrap/package/assert.ts @@ -1,6 +1,6 @@ import { AssertionError, validatePackageDescriptor } from "@dpkit/core" import type { Descriptor, Package } from "@dpkit/core" -import type { CamtrapPackage } from "./Package.js" +import type { CamtrapPackage } from "./Package.ts" const SUPPORTED_PROFILES = [ "https://raw.githubusercontent.com/tdwg/camtrap-dp/1.0/camtrap-dp-profile.json", diff --git a/camtrap/package/index.ts b/camtrap/package/index.ts index 9b8ce884..4d7e73c5 100644 --- a/camtrap/package/index.ts +++ b/camtrap/package/index.ts @@ -1,2 +1,2 @@ -export type { CamtrapPackage } from "./Package.js" -export { assertCamtrapPackage } from "./assert.js" +export type { CamtrapPackage } from "./Package.ts" +export { assertCamtrapPackage } from "./assert.ts" diff --git a/camtrap/tsconfig.json b/camtrap/tsconfig.json index 7be40230..3c43903c 100644 --- a/camtrap/tsconfig.json +++ b/camtrap/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/camtrap/typedoc.json b/camtrap/typedoc.json index fc33b815..f8e49f3a 100644 --- a/camtrap/typedoc.json +++ b/camtrap/typedoc.json @@ -1,5 +1,4 @@ { "entryPoints": ["index.ts"], - "projectDocuments": ["CHANGELOG.md", "OVERVIEW.md"], "skipErrorChecking": true } diff --git a/ckan/OVERVIEW.md b/ckan/OVERVIEW.md deleted file mode 100644 index abec8174..00000000 --- a/ckan/OVERVIEW.md +++ /dev/null @@ -1,6 +0,0 @@ -# @dpkit/ckan - -:::note -This overview is under development. -::: - diff --git a/ckan/ckan/index.ts b/ckan/ckan/index.ts new file mode 100644 index 00000000..f149c005 --- /dev/null +++ b/ckan/ckan/index.ts @@ -0,0 +1 @@ +export { makeCkanApiRequest } from "./request.ts" diff --git a/ckan/general/request.ts b/ckan/ckan/request.ts similarity index 100% rename from ckan/general/request.ts rename to ckan/ckan/request.ts diff --git a/ckan/general/index.ts b/ckan/general/index.ts deleted file mode 100644 index bc7f046f..00000000 --- a/ckan/general/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { makeCkanApiRequest } from "./request.js" diff --git a/ckan/index.ts b/ckan/index.ts index 461b024e..9f97e644 100644 --- a/ckan/index.ts +++ b/ckan/index.ts @@ -1,4 +1,4 @@ -export * from "./package/index.js" -export * from "./resource/index.js" -export * from "./schema/index.js" -export * from "./plugin.js" +export * from "./package/index.ts" +export * from "./resource/index.ts" +export * from "./schema/index.ts" +export * from "./plugin.ts" diff --git a/ckan/package.json b/ckan/package.json index 9f8d297c..258d1db9 100644 --- a/ckan/package.json +++ b/ckan/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/ckan", "type": "module", - "main": "build/index.js", "version": "0.6.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,7 +20,7 @@ "ckan" ], "scripts": { - "build": "tsc --build" + "build": "tsc" }, "dependencies": { "@dpkit/core": "workspace:*", diff --git a/ckan/package/Package.ts b/ckan/package/Package.ts index 7e9bdaf9..c0fa7413 100644 --- a/ckan/package/Package.ts +++ b/ckan/package/Package.ts @@ -1,6 +1,6 @@ -import type { CkanResource } from "../resource/index.js" -import type { CkanOrganization } from "./Organization.js" -import type { CkanTag } from "./Tag.js" +import type { CkanResource } from "../resource/index.ts" +import type { CkanOrganization } from "./Organization.ts" +import type { CkanTag } from "./Tag.ts" /** * CKAN Package interface diff --git a/ckan/package/fixtures/generated/load.spec.ts.snap b/ckan/package/fixtures/generated/load.spec.ts.snap index e9a4ccb4..0c226733 100644 --- a/ckan/package/fixtures/generated/load.spec.ts.snap +++ b/ckan/package/fixtures/generated/load.spec.ts.snap @@ -64,7 +64,7 @@ The criteria underpinning collection units and the methodology by which they are "fields": [ { "name": "Collection unit ID", - "type": "string", + "type": "number", }, { "name": "Department", @@ -104,7 +104,7 @@ The criteria underpinning collection units and the methodology by which they are }, { "name": "Type collection", - "type": "string", + "type": "boolean", }, { "name": "Geographic origin", @@ -140,7 +140,7 @@ The criteria underpinning collection units and the methodology by which they are }, { "name": "Reporting count", - "type": "string", + "type": "number", }, { "name": "Reporting metric used", @@ -148,7 +148,7 @@ The criteria underpinning collection units and the methodology by which they are }, { "name": "Item count", - "type": "string", + "type": "number", }, { "name": "Item count confidence", @@ -156,7 +156,7 @@ The criteria underpinning collection units and the methodology by which they are }, { "name": "Curatorial unit count", - "type": "string", + "type": "number", }, { "name": "Curatorial unit count confidence", @@ -164,43 +164,43 @@ The criteria underpinning collection units and the methodology by which they are }, { "name": "C1: Physical accessibility", - "type": "string", + "type": "number", }, { "name": "S1: Strategy/mission/research", - "type": "string", + "type": "number", }, { "name": "S2: Scope and depth", - "type": "string", + "type": "number", }, { "name": "S3: Significance by comparison", - "type": "string", + "type": "number", }, { "name": "S4: Usage", - "type": "string", + "type": "number", }, { "name": "I1: Digitisation", - "type": "string", + "type": "number", }, { "name": "I2: Identification", - "type": "string", + "type": "number", }, { "name": "I4: Development potential", - "type": "string", + "type": "number", }, { "name": "O1: Education suitability", - "type": "string", + "type": "number", }, { "name": "O3: Exhibition suitability", - "type": "string", + "type": "number", }, ], }, @@ -235,7 +235,7 @@ The criteria underpinning collection units and the methodology by which they are }, { "name": "nullable", - "type": "string", + "type": "boolean", }, { "name": "Documentation reference", diff --git a/ckan/package/fixtures/generated/should-load-a-package_2675098929/recording.har b/ckan/package/fixtures/generated/loadPackageFromCkan-should-load-a-package_3615031657/recording.har similarity index 86% rename from ckan/package/fixtures/generated/should-load-a-package_2675098929/recording.har rename to ckan/package/fixtures/generated/loadPackageFromCkan-should-load-a-package_3615031657/recording.har index 7cc3d6b2..3ad969c1 100644 --- a/ckan/package/fixtures/generated/should-load-a-package_2675098929/recording.har +++ b/ckan/package/fixtures/generated/loadPackageFromCkan-should-load-a-package_3615031657/recording.har @@ -1,6 +1,6 @@ { "log": { - "_recordingName": "should load a package", + "_recordingName": "loadPackageFromCkan-should load a package", "creator": { "comment": "persister:fs", "name": "Polly.JS", @@ -62,7 +62,7 @@ }, { "name": "date", - "value": "Fri, 23 May 2025 09:29:45 GMT" + "value": "Thu, 07 Aug 2025 07:49:26 GMT" }, { "name": "server", @@ -83,8 +83,8 @@ "status": 200, "statusText": "OK" }, - "startedDateTime": "2025-05-23T09:29:45.284Z", - "time": 1486, + "startedDateTime": "2025-08-07T07:49:25.398Z", + "time": 1371, "timings": { "blocked": -1, "connect": -1, @@ -92,7 +92,7 @@ "receive": 0, "send": 0, "ssl": -1, - "wait": 1486 + "wait": 1371 } }, { @@ -120,11 +120,11 @@ "url": "https://data.nhm.ac.uk/api/3/action/datastore_search" }, "response": { - "bodySize": 2531, + "bodySize": 2514, "content": { "mimeType": "application/json;charset=utf-8", - "size": 2531, - "text": "{\"help\": \"https://data.nhm.ac.uk/api/3/action/help_show?name=datastore_search\", \"success\": true, \"result\": {\"total\": 2916, \"records\": [], \"facets\": {}, \"fields\": [{\"id\": \"_id\", \"type\": \"string\"}, {\"id\": \"Collection unit ID\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Department\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Division\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Section\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Collection unit name\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Taxon\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Taxon rank\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Taxon ID\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Taxon ID source\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Informal taxon\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Type collection\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Geographic origin\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Earliest geological period\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Latest geological period\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Item type\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Preservation method\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Curatorial unit type\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Bibliographic level\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Fond reference\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Reporting count\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Reporting metric used\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Item count\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Item count confidence\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Curatorial unit count\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Curatorial unit count confidence\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"C1: Physical accessibility\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"S1: Strategy/mission/research\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"S2: Scope and depth\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"S3: Significance by comparison\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"S4: Usage\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"I1: Digitisation\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"I2: Identification\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"I4: Development potential\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"O1: Education suitability\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"O3: Exhibition suitability\", \"type\": \"string\", \"sortable\": true}], \"raw_fields\": {}, \"after\": null}}" + "size": 2514, + "text": "{\"help\": \"https://data.nhm.ac.uk/api/3/action/help_show?name=datastore_search\", \"success\": true, \"result\": {\"total\": 2916, \"records\": [], \"facets\": {}, \"fields\": [{\"id\": \"_id\", \"type\": \"string\"}, {\"id\": \"Collection unit ID\", \"type\": \"number\", \"sortable\": true}, {\"id\": \"Department\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Division\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Section\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Collection unit name\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Taxon\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Taxon rank\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Taxon ID\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Taxon ID source\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Informal taxon\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Type collection\", \"type\": \"boolean\", \"sortable\": true}, {\"id\": \"Geographic origin\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Earliest geological period\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Latest geological period\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Item type\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Preservation method\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Curatorial unit type\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Bibliographic level\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Fond reference\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Reporting count\", \"type\": \"number\", \"sortable\": true}, {\"id\": \"Reporting metric used\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Item count\", \"type\": \"number\", \"sortable\": true}, {\"id\": \"Item count confidence\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Curatorial unit count\", \"type\": \"number\", \"sortable\": true}, {\"id\": \"Curatorial unit count confidence\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"C1: Physical accessibility\", \"type\": \"number\", \"sortable\": true}, {\"id\": \"S1: Strategy/mission/research\", \"type\": \"number\", \"sortable\": true}, {\"id\": \"S2: Scope and depth\", \"type\": \"number\", \"sortable\": true}, {\"id\": \"S3: Significance by comparison\", \"type\": \"number\", \"sortable\": true}, {\"id\": \"S4: Usage\", \"type\": \"number\", \"sortable\": true}, {\"id\": \"I1: Digitisation\", \"type\": \"number\", \"sortable\": true}, {\"id\": \"I2: Identification\", \"type\": \"number\", \"sortable\": true}, {\"id\": \"I4: Development potential\", \"type\": \"number\", \"sortable\": true}, {\"id\": \"O1: Education suitability\", \"type\": \"number\", \"sortable\": true}, {\"id\": \"O3: Exhibition suitability\", \"type\": \"number\", \"sortable\": true}], \"after\": null}}" }, "cookies": [], "headers": [ @@ -150,7 +150,7 @@ }, { "name": "date", - "value": "Fri, 23 May 2025 09:29:46 GMT" + "value": "Thu, 07 Aug 2025 07:49:26 GMT" }, { "name": "server", @@ -171,8 +171,8 @@ "status": 200, "statusText": "OK" }, - "startedDateTime": "2025-05-23T09:29:46.771Z", - "time": 127, + "startedDateTime": "2025-08-07T07:49:26.770Z", + "time": 532, "timings": { "blocked": -1, "connect": -1, @@ -180,7 +180,7 @@ "receive": 0, "send": 0, "ssl": -1, - "wait": 127 + "wait": 532 } }, { @@ -208,11 +208,11 @@ "url": "https://data.nhm.ac.uk/api/3/action/datastore_search" }, "response": { - "bodySize": 586, + "bodySize": 569, "content": { "mimeType": "application/json;charset=utf-8", - "size": 586, - "text": "{\"help\": \"https://data.nhm.ac.uk/api/3/action/help_show?name=datastore_search\", \"success\": true, \"result\": {\"total\": 35, \"records\": [], \"facets\": {}, \"fields\": [{\"id\": \"_id\", \"type\": \"string\"}, {\"id\": \"fieldname\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"description\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"datatype\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"constraints\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"nullable\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"Documentation reference\", \"type\": \"string\", \"sortable\": true}], \"raw_fields\": {}, \"after\": null}}" + "size": 569, + "text": "{\"help\": \"https://data.nhm.ac.uk/api/3/action/help_show?name=datastore_search\", \"success\": true, \"result\": {\"total\": 35, \"records\": [], \"facets\": {}, \"fields\": [{\"id\": \"_id\", \"type\": \"string\"}, {\"id\": \"fieldname\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"description\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"datatype\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"constraints\", \"type\": \"string\", \"sortable\": true}, {\"id\": \"nullable\", \"type\": \"boolean\", \"sortable\": true}, {\"id\": \"Documentation reference\", \"type\": \"string\", \"sortable\": true}], \"after\": null}}" }, "cookies": [], "headers": [ @@ -238,7 +238,7 @@ }, { "name": "date", - "value": "Fri, 23 May 2025 09:29:46 GMT" + "value": "Thu, 07 Aug 2025 07:49:26 GMT" }, { "name": "server", @@ -259,8 +259,8 @@ "status": 200, "statusText": "OK" }, - "startedDateTime": "2025-05-23T09:29:46.899Z", - "time": 127, + "startedDateTime": "2025-08-07T07:49:27.303Z", + "time": 189, "timings": { "blocked": -1, "connect": -1, @@ -268,7 +268,7 @@ "receive": 0, "send": 0, "ssl": -1, - "wait": 127 + "wait": 189 } } ], diff --git a/ckan/package/index.ts b/ckan/package/index.ts index b044a3b3..d4712fdc 100644 --- a/ckan/package/index.ts +++ b/ckan/package/index.ts @@ -1,5 +1,5 @@ -export type { CkanPackage } from "./Package.js" -export type { CkanOrganization } from "./Organization.js" -export type { CkanTag } from "./Tag.js" -export { loadPackageFromCkan } from "./load.js" -export { savePackageToCkan } from "./save.js" +export type { CkanPackage } from "./Package.ts" +export type { CkanOrganization } from "./Organization.ts" +export type { CkanTag } from "./Tag.ts" +export { loadPackageFromCkan } from "./load.ts" +export { savePackageToCkan } from "./save.ts" diff --git a/ckan/package/load.spec.ts b/ckan/package/load.spec.ts index 02c3062e..2501ee43 100644 --- a/ckan/package/load.spec.ts +++ b/ckan/package/load.spec.ts @@ -1,6 +1,6 @@ import { useRecording } from "@dpkit/test" import { describe, expect, it } from "vitest" -import { loadPackageFromCkan } from "./load.js" +import { loadPackageFromCkan } from "./load.ts" describe("loadPackageFromCkan", () => { useRecording() diff --git a/ckan/package/load.ts b/ckan/package/load.ts index a3871ffc..d63e92e0 100644 --- a/ckan/package/load.ts +++ b/ckan/package/load.ts @@ -1,7 +1,7 @@ import { mergePackages } from "@dpkit/core" -import { makeCkanApiRequest } from "../general/index.js" -import type { CkanPackage } from "./Package.js" -import { normalizeCkanPackage } from "./process/normalize.js" +import { makeCkanApiRequest } from "../ckan/index.ts" +import type { CkanPackage } from "./Package.ts" +import { normalizeCkanPackage } from "./process/normalize.ts" /** * Load a package from a CKAN instance diff --git a/ckan/package/process/denormalize.spec.ts b/ckan/package/process/denormalize.spec.ts index 358e73b9..17ae1f3d 100644 --- a/ckan/package/process/denormalize.spec.ts +++ b/ckan/package/process/denormalize.spec.ts @@ -1,11 +1,11 @@ import type { Package } from "@dpkit/core" import { describe, expect, it } from "vitest" -import type { CkanPackage } from "../Package.js" +import type { CkanPackage } from "../Package.ts" import ckanPackageFixture from "../fixtures/ckan-package.json" with { type: "json", } -import { denormalizeCkanPackage } from "./denormalize.js" -import { normalizeCkanPackage } from "./normalize.js" +import { denormalizeCkanPackage } from "./denormalize.ts" +import { normalizeCkanPackage } from "./normalize.ts" describe("denormalizeCkanPackage", () => { it("denormalizes a Frictionless Data Package to a CKAN package", () => { diff --git a/ckan/package/process/denormalize.ts b/ckan/package/process/denormalize.ts index 0eb3b9cf..24e845bf 100644 --- a/ckan/package/process/denormalize.ts +++ b/ckan/package/process/denormalize.ts @@ -1,9 +1,9 @@ import type { Package } from "@dpkit/core" import type { SetRequired } from "type-fest" -import type { CkanResource } from "../../resource/Resource.js" -import { denormalizeCkanResource } from "../../resource/process/denormalize.js" -import type { CkanPackage } from "../Package.js" -import type { CkanTag } from "../Tag.js" +import type { CkanResource } from "../../resource/Resource.ts" +import { denormalizeCkanResource } from "../../resource/process/denormalize.ts" +import type { CkanPackage } from "../Package.ts" +import type { CkanTag } from "../Tag.ts" /** * Denormalizes a Frictionless Data Package to CKAN Package format diff --git a/ckan/package/process/normalize.spec.ts b/ckan/package/process/normalize.spec.ts index ae5e1f2b..a7b15f1a 100644 --- a/ckan/package/process/normalize.spec.ts +++ b/ckan/package/process/normalize.spec.ts @@ -1,9 +1,9 @@ import { describe, expect, it } from "vitest" -import type { CkanPackage } from "../Package.js" +import type { CkanPackage } from "../Package.ts" import ckanPackageFixture from "../fixtures/ckan-package.json" with { type: "json", } -import { normalizeCkanPackage } from "./normalize.js" +import { normalizeCkanPackage } from "./normalize.ts" describe("normalizeCkanPackage", () => { it("normalizes a CKAN package to a Frictionless Data Package", () => { diff --git a/ckan/package/process/normalize.ts b/ckan/package/process/normalize.ts index 7a5e7103..2fb73e04 100644 --- a/ckan/package/process/normalize.ts +++ b/ckan/package/process/normalize.ts @@ -1,7 +1,7 @@ import type { Contributor, Package } from "@dpkit/core" import type { License } from "@dpkit/core" -import { normalizeCkanResource } from "../../resource/process/normalize.js" -import type { CkanPackage } from "../Package.js" +import { normalizeCkanResource } from "../../resource/process/normalize.ts" +import type { CkanPackage } from "../Package.ts" /** * Normalizes a CKAN package to Frictionless Data package format diff --git a/ckan/package/save.spec.ts b/ckan/package/save.spec.ts index 4537798b..d0963cef 100644 --- a/ckan/package/save.spec.ts +++ b/ckan/package/save.spec.ts @@ -1,7 +1,7 @@ import { loadPackageDescriptor } from "@dpkit/core" //import { useRecording } from "@dpkit/test" import { describe, expect, it } from "vitest" -import { savePackageToCkan } from "./save.js" +import { savePackageToCkan } from "./save.ts" describe("savePackageToCkan", () => { //useRecording() diff --git a/ckan/package/save.ts b/ckan/package/save.ts index 13b5b544..72fd4b81 100644 --- a/ckan/package/save.ts +++ b/ckan/package/save.ts @@ -11,10 +11,10 @@ import { loadFileStream, saveResourceFiles, } from "@dpkit/file" -import { makeCkanApiRequest } from "../general/index.js" -import type { CkanResource } from "../resource/index.js" -import { denormalizeCkanResource } from "../resource/index.js" -import { denormalizeCkanPackage } from "./process/denormalize.js" +import { makeCkanApiRequest } from "../ckan/index.ts" +import type { CkanResource } from "../resource/index.ts" +import { denormalizeCkanResource } from "../resource/index.ts" +import { denormalizeCkanPackage } from "./process/denormalize.ts" export async function savePackageToCkan( dataPackage: Package, @@ -97,7 +97,7 @@ export async function savePackageToCkan( const upload = { name: denormalizedPath, - data: new Blob([stringifyDescriptor({ descriptor })]), + data: new Blob([stringifyDescriptor(descriptor)]), } await makeCkanApiRequest({ diff --git a/ckan/plugin.ts b/ckan/plugin.ts index 594214b6..cf84f1de 100644 --- a/ckan/plugin.ts +++ b/ckan/plugin.ts @@ -1,6 +1,6 @@ import type { Plugin } from "@dpkit/core" import { isRemotePath } from "@dpkit/core" -import { loadPackageFromCkan } from "./package/load.js" +import { loadPackageFromCkan } from "./package/load.ts" export class CkanPlugin implements Plugin { async loadPackage(source: string) { diff --git a/ckan/resource/Resource.ts b/ckan/resource/Resource.ts index e5f5798b..ea788a40 100644 --- a/ckan/resource/Resource.ts +++ b/ckan/resource/Resource.ts @@ -1,5 +1,5 @@ import type { SetRequired } from "type-fest" -import type { CkanSchema } from "../schema/index.js" +import type { CkanSchema } from "../schema/index.ts" /** * CKAN Resource interface diff --git a/ckan/resource/index.ts b/ckan/resource/index.ts index 289209b3..35de3bcb 100644 --- a/ckan/resource/index.ts +++ b/ckan/resource/index.ts @@ -1,2 +1,2 @@ -export type { CkanResource } from "./Resource.js" -export { denormalizeCkanResource } from "./process/denormalize.js" +export type { CkanResource } from "./Resource.ts" +export { denormalizeCkanResource } from "./process/denormalize.ts" diff --git a/ckan/resource/process/denormalize.ts b/ckan/resource/process/denormalize.ts index 35480bb7..a5369387 100644 --- a/ckan/resource/process/denormalize.ts +++ b/ckan/resource/process/denormalize.ts @@ -1,5 +1,5 @@ import type { Resource } from "@dpkit/core" -import type { CkanResource } from "../Resource.js" +import type { CkanResource } from "../Resource.ts" /** * Denormalizes a Frictionless Data Resource to CKAN Resource format diff --git a/ckan/resource/process/normalize.ts b/ckan/resource/process/normalize.ts index 80b1f252..ac130ec3 100644 --- a/ckan/resource/process/normalize.ts +++ b/ckan/resource/process/normalize.ts @@ -1,7 +1,7 @@ import type { Resource } from "@dpkit/core" import { getFilename } from "@dpkit/core" -import { normalizeCkanSchema } from "../../schema/index.js" -import type { CkanResource } from "../Resource.js" +import { normalizeCkanSchema } from "../../schema/index.ts" +import type { CkanResource } from "../Resource.ts" /** * Normalizes a CKAN resource to Frictionless Data Resource format diff --git a/ckan/schema/Schema.ts b/ckan/schema/Schema.ts index 2c495b7e..2397efb2 100644 --- a/ckan/schema/Schema.ts +++ b/ckan/schema/Schema.ts @@ -1,4 +1,4 @@ -import type { CkanField } from "./Field.js" +import type { CkanField } from "./Field.ts" /** * CKAN Schema interface diff --git a/ckan/schema/index.ts b/ckan/schema/index.ts index 36622694..b4084269 100644 --- a/ckan/schema/index.ts +++ b/ckan/schema/index.ts @@ -1,3 +1,3 @@ -export type { CkanSchema } from "./Schema.js" -export type { CkanField } from "./Field.js" -export { normalizeCkanSchema } from "./process/normalize.js" +export type { CkanSchema } from "./Schema.ts" +export type { CkanField } from "./Field.ts" +export { normalizeCkanSchema } from "./process/normalize.ts" diff --git a/ckan/schema/process/denormalize.ts b/ckan/schema/process/denormalize.ts index 3c0c4ad6..220cd6ff 100644 --- a/ckan/schema/process/denormalize.ts +++ b/ckan/schema/process/denormalize.ts @@ -1,6 +1,6 @@ import type { Field, Schema } from "@dpkit/core" -import type { CkanField, CkanFieldInfo } from "../Field.js" -import type { CkanSchema } from "../Schema.js" +import type { CkanField, CkanFieldInfo } from "../Field.ts" +import type { CkanSchema } from "../Schema.ts" /** * Denormalizes a Table Schema to a CKAN schema format diff --git a/ckan/schema/process/normalize.ts b/ckan/schema/process/normalize.ts index fe0ebaa7..ddf5314b 100644 --- a/ckan/schema/process/normalize.ts +++ b/ckan/schema/process/normalize.ts @@ -10,8 +10,8 @@ import type { StringField, TimeField, } from "@dpkit/core" -import type { CkanField } from "../Field.js" -import type { CkanSchema } from "../Schema.js" +import type { CkanField } from "../Field.ts" +import type { CkanSchema } from "../Schema.ts" /** * Normalizes a CKAN schema to a Table Schema format diff --git a/ckan/tsconfig.json b/ckan/tsconfig.json index 7be40230..3c43903c 100644 --- a/ckan/tsconfig.json +++ b/ckan/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/ckan/typedoc.json b/ckan/typedoc.json index fc33b815..f8e49f3a 100644 --- a/ckan/typedoc.json +++ b/ckan/typedoc.json @@ -1,5 +1,4 @@ { "entryPoints": ["index.ts"], - "projectDocuments": ["CHANGELOG.md", "OVERVIEW.md"], "skipErrorChecking": true } diff --git a/cli/.oclifrc.js b/cli/.oclifrc.js new file mode 100644 index 00000000..726cf92b --- /dev/null +++ b/cli/.oclifrc.js @@ -0,0 +1,6 @@ +export default { + bin: "dp", + commands: "./commands", + topicSeparator: " ", + plugins: ["@oclif/plugin-autocomplete"], +} diff --git a/cli/commands/dialect/infer.ts b/cli/commands/dialect/infer.ts new file mode 100644 index 00000000..6c9ca7b8 --- /dev/null +++ b/cli/commands/dialect/infer.ts @@ -0,0 +1,29 @@ +import { Command } from "@oclif/core" +import { inferDialect } from "dpkit" +import * as options from "../../options/index.ts" +import * as params from "../../params/index.ts" + +export default class InferDialect extends Command { + static override description = "Infer a dialect from a table" + + static override args = { + path: params.requriedTablePath, + } + + static override flags = { + json: options.json, + } + + public async run() { + const { args, flags } = await this.parse(InferDialect) + + const dialect = await inferDialect({ path: args.path }) + + if (flags.json) { + this.logJson(dialect) + return + } + + console.log(dialect) + } +} diff --git a/cli/commands/package/load.ts b/cli/commands/package/load.ts new file mode 100644 index 00000000..ce6c21b0 --- /dev/null +++ b/cli/commands/package/load.ts @@ -0,0 +1,29 @@ +import { Command } from "@oclif/core" +import { loadPackage } from "dpkit" +import * as options from "../../options/index.ts" +import * as params from "../../params/index.ts" + +export default class LoadPackage extends Command { + static override description = "Load a Data Package descriptor" + + static override args = { + path: params.requriedDescriptorPath, + } + + static override flags = { + json: options.json, + } + + public async run() { + const { args, flags } = await this.parse(LoadPackage) + + const dp = await loadPackage(args.path) + + if (flags.json) { + this.logJson(dp) + return + } + + console.log(dp) + } +} diff --git a/avro/index.ts b/cli/commands/resource/.keep similarity index 100% rename from avro/index.ts rename to cli/commands/resource/.keep diff --git a/cli/index.ts b/cli/commands/schema/.keep similarity index 100% rename from cli/index.ts rename to cli/commands/schema/.keep diff --git a/cli/commands/table/convert.tsx b/cli/commands/table/convert.tsx new file mode 100644 index 00000000..cfc29fe2 --- /dev/null +++ b/cli/commands/table/convert.tsx @@ -0,0 +1,46 @@ +import { Command } from "@oclif/core" +import { getTempFilePath, loadFile } from "dpkit" +import { readTable, saveTable } from "dpkit" +import * as options from "../../options/index.ts" +import * as params from "../../params/index.ts" + +export default class ConvertTable extends Command { + static override description = + "Convert a table from a local or remote source path to a target path" + + static override args = { + path: params.requriedTablePath, + } + + // TODO: support toDialectOptions + static override flags = { + toPath: options.toPath, + toFormat: options.toFormat, + ...options.dialectOptions, + ...options.toDialectOptions, + } + + public async run() { + const { args, flags } = await this.parse(ConvertTable) + + const dialect = options.createDialectFromFlags(flags) + const table = await readTable({ path: args.path, dialect }) + + const toPath = flags.toPath ?? getTempFilePath() + const toDialect = options.createToDialectFromFlags(flags) + await saveTable(table, { + path: toPath, + format: flags.toFormat, + dialect: toDialect, + }) + + if (!flags.toPath) { + // TODO: stream to stdout + const buffer = await loadFile(toPath) + this.log(buffer.toString().trim()) + return + } + + this.log(`Converted table from ${args.path} to ${flags.toPath}`) + } +} diff --git a/cli/commands/table/describe.tsx b/cli/commands/table/describe.tsx new file mode 100644 index 00000000..4e7bc690 --- /dev/null +++ b/cli/commands/table/describe.tsx @@ -0,0 +1,37 @@ +import { Command } from "@oclif/core" +import { readTable } from "dpkit" +import { render } from "ink" +import React from "react" +import { TableGrid } from "../../components/TableGrid.tsx" +import * as options from "../../options/index.ts" +import * as params from "../../params/index.ts" + +export default class DescribeTable extends Command { + static override description = "Describe a table from a local or remote path" + + static override args = { + path: params.requriedTablePath, + } + + static override flags = { + ...options.dialectOptions, + json: options.json, + } + + public async run() { + const { args, flags } = await this.parse(DescribeTable) + + const dialect = options.createDialectFromFlags(flags) + const table = await readTable({ path: args.path, dialect }) + + const df = await table.collect() + const stats = df.describe() + + if (flags.json) { + this.logJson(stats) + return + } + + render() + } +} diff --git a/cli/commands/table/explore.tsx b/cli/commands/table/explore.tsx new file mode 100644 index 00000000..76bc38ed --- /dev/null +++ b/cli/commands/table/explore.tsx @@ -0,0 +1,35 @@ +import { Command } from "@oclif/core" +import { readTable } from "dpkit" +import { render } from "ink" +import React from "react" +import { TableGrid } from "../../components/TableGrid.tsx" +import * as options from "../../options/index.ts" +import * as params from "../../params/index.ts" + +export default class ExploreTable extends Command { + static override description = "Explore a table from a local or remote path" + + static override args = { + path: params.requriedTablePath, + } + + static override flags = { + ...options.dialectOptions, + } + + public async run() { + const { args, flags } = await this.parse(ExploreTable) + + const dialect = options.createDialectFromFlags(flags) + const table = await readTable({ path: args.path, dialect }) + + if (flags.json) { + const df = await table.slice(0, 10).collect() + const data = df.toRecords() + this.logJson(data) + return + } + + render() + } +} diff --git a/cli/commands/table/query.tsx b/cli/commands/table/query.tsx new file mode 100644 index 00000000..acd278a9 --- /dev/null +++ b/cli/commands/table/query.tsx @@ -0,0 +1,22 @@ +import { Command } from "@oclif/core" +//import { readTable } from "dpkit" +import * as options from "../../options/index.ts" +import * as params from "../../params/index.ts" + +export default class QueryTable extends Command { + static override description = + "Start a querying session for a table from a local or remote path" + + static override args = { + path: params.requriedTablePath, + } + + static override flags = { + ...options.dialectOptions, + } + + public async run() { + //const { args, flags } = await this.parse(QueryTable) + throw new Error("Not implemented") + } +} diff --git a/cli/commands/table/script.tsx b/cli/commands/table/script.tsx new file mode 100644 index 00000000..102dd237 --- /dev/null +++ b/cli/commands/table/script.tsx @@ -0,0 +1,28 @@ +import repl from "node:repl" +import { Command } from "@oclif/core" +import { readTable } from "dpkit" +import * as options from "../../options/index.ts" +import * as params from "../../params/index.ts" + +export default class ScriptTable extends Command { + static override description = + "Start a scripting session for a table from a local or remote path" + + static override args = { + path: params.requriedTablePath, + } + + static override flags = { + ...options.dialectOptions, + } + + public async run() { + const { args, flags } = await this.parse(ScriptTable) + + const dialect = options.createDialectFromFlags(flags) + const table = await readTable({ path: args.path, dialect }) + + const session = repl.start({ prompt: "dp> " }) + session.context.table = table + } +} diff --git a/cli/commands/table/validate.tsx b/cli/commands/table/validate.tsx new file mode 100644 index 00000000..d3571d8f --- /dev/null +++ b/cli/commands/table/validate.tsx @@ -0,0 +1,46 @@ +import { Command } from "@oclif/core" +import { validateTable } from "dpkit" +import { render } from "ink" +import React from "react" +import { ErrorGrid } from "../../components/ErrorGrid.tsx" +import * as options from "../../options/index.ts" +import * as params from "../../params/index.ts" + +export default class ExploreTable extends Command { + static override description = "Explore a table from a local or remote path" + + static override args = { + path: params.requriedTablePath, + } + + static override flags = { + ...options.dialectOptions, + json: options.json, + } + + public async run() { + const { args, flags } = await this.parse(ExploreTable) + + const dialect = options.createDialectFromFlags(flags) + const { errors } = await validateTable({ path: args.path, dialect }) + + if (flags.json) { + this.logJson(errors) + return + } + + render( + , + ) + } +} diff --git a/cli/components/DataGrid.tsx b/cli/components/DataGrid.tsx new file mode 100644 index 00000000..398da95a --- /dev/null +++ b/cli/components/DataGrid.tsx @@ -0,0 +1,77 @@ +import { Box, Text } from "ink" +import React from "react" + +const MIN_COLUMN_WIDTH = 15 +export type Order = { col: number; dir: "asc" | "desc" } + +export function DataGrid(props: { + data: Record[] + col?: number + order?: Order +}) { + const { data, col, order } = props + + const colNames = Object.keys(data[0] ?? {}) + const colWidth = Math.min( + process.stdout.columns / colNames.length, + MIN_COLUMN_WIDTH, + ) + + const tableWidth = colNames.length * colWidth + + const selectIndex = col ? col - 1 : -1 + const orderIndex = order?.col ? order?.col - 1 : -1 + const orderSign = order?.dir === "desc" ? " ▲" : " ▼" + + return ( + + + {colNames.map((name, index) => ( + + + {name} + {index === orderIndex ? orderSign : " "} + + + ))} + + + {data.map((row, rowIndex) => ( + + {colNames.map((name, index) => ( + + {(row[name] ?? "").toString()} + + ))} + + ))} + + ) +} diff --git a/cli/components/ErrorGrid.tsx b/cli/components/ErrorGrid.tsx new file mode 100644 index 00000000..71818bfc --- /dev/null +++ b/cli/components/ErrorGrid.tsx @@ -0,0 +1,38 @@ +import type { TableError } from "dpkit" +import { Box } from "ink" +import SelectInput from "ink-select-input" +import { DataFrame } from "nodejs-polars" +import { useState } from "react" +import React from "react" +import { objectKeys } from "ts-extras" +import { TableGrid } from "./TableGrid.tsx" + +export function ErrorGrid(props: { errors: TableError[] }) { + const { errors } = props + const [errorType, setErrorType] = useState(errors[0]?.type ?? "") + + const errorsByType = Object.groupBy(errors, error => error.type) + // @ts-ignore + const selectErrors = errorsByType[errorType] + + const table = DataFrame(selectErrors).lazy() + + const handleSelect = async (item: any) => { + setErrorType(item.value) + } + + return ( + + + ({ + label: type, + value: type, + }))} + /> + + + + ) +} diff --git a/cli/components/TableGrid.tsx b/cli/components/TableGrid.tsx new file mode 100644 index 00000000..a261af21 --- /dev/null +++ b/cli/components/TableGrid.tsx @@ -0,0 +1,145 @@ +import type { Table } from "dpkit" +import { useApp, useInput } from "ink" +import { Box, Text } from "ink" +import { useEffect, useState } from "react" +import React from "react" +import type { Order } from "./DataGrid.tsx" +import { DataGrid } from "./DataGrid.tsx" + +const PAGE_SIZE = 10 +type Data = Record[] + +export function TableGrid(props: { table: Table }) { + const { table } = props + const { exit } = useApp() + const [col, setCol] = useState(0) + const [page, setPage] = useState(1) + const [order, setOrder] = useState() + const [data, setData] = useState([]) + + const handleColChange = async (col: number) => { + if (col === 0) return + if (col > table.columns.length) return + + setCol(col) + } + + const handleOrderChange = async (order?: Order) => { + setOrder(order) + + if (order) { + handlePageChange(1, order) + } + } + + const handlePageChange = async (page: number, order?: Order) => { + if (page === 0) return + + let ldf = table + if (order) { + const name = table.columns[order.col - 1] + if (name) { + ldf = ldf.sort(name, order.dir === "desc") + } + } + + const offset = (page - 1) * PAGE_SIZE + const df = await ldf.slice(offset, PAGE_SIZE).collect() + const data = df.toRecords() + + if (data.length) { + setPage(page) + setData(data) + } + } + + useEffect(() => { + handlePageChange(1) + }, [table]) + + useInput((input, key) => { + if (key.escape || input === "q") { + exit() + } + + if (key.upArrow || input === "k") { + handlePageChange(page - 1) + } + + if (key.downArrow || input === "j") { + handlePageChange(page + 1) + } + + if (key.leftArrow || input === "h") { + handleColChange(col - 1) + } + + if (key.rightArrow || input === "l") { + handleColChange(col + 1) + } + + if (key.return || input === "o") { + let nextOrder: Order | undefined = { col, dir: "desc" } + + if (order?.col === col) { + if (order?.dir === "desc") nextOrder = { col, dir: "asc" } + if (order?.dir === "asc") nextOrder = undefined + } + + handleOrderChange(nextOrder) + } + }) + + return ( + + + + + ) +} + +function Help() { + const { exit } = useApp() + const [isOpen, setIsOpen] = useState(false) + + useInput((input, key) => { + if (key.escape || input === "q") { + exit() + } + + if (input === "d") { + setIsOpen(!isOpen) + } + }) + + if (!isOpen) { + return ( + + + {", "} + + + ) + } + + return ( + + Table Usage + + + + + + + + ) +} + +function HelpItem(props: { button: string; description: string }) { + return ( + + press {props.button}{" "} + {props.description} + + ) +} diff --git a/cli/entrypoints/dev.cmd b/cli/entrypoints/dev.cmd new file mode 100644 index 00000000..8ae2b12c --- /dev/null +++ b/cli/entrypoints/dev.cmd @@ -0,0 +1,3 @@ +@echo off + +node "%~dp0\dev" %* diff --git a/cli/entrypoints/dev.ts b/cli/entrypoints/dev.ts new file mode 100755 index 00000000..cefc0f18 --- /dev/null +++ b/cli/entrypoints/dev.ts @@ -0,0 +1,4 @@ +#!cli/node_modules/.bin/tsx +import { execute } from "@oclif/core" + +await execute({ dir: import.meta.url, development: true }) diff --git a/cli/entrypoints/run.cmd b/cli/entrypoints/run.cmd new file mode 100644 index 00000000..968fc307 --- /dev/null +++ b/cli/entrypoints/run.cmd @@ -0,0 +1,3 @@ +@echo off + +node "%~dp0\run" %* diff --git a/cli/entrypoints/run.ts b/cli/entrypoints/run.ts new file mode 100755 index 00000000..c036c876 --- /dev/null +++ b/cli/entrypoints/run.ts @@ -0,0 +1,4 @@ +#!/usr/bin/env node +import { execute } from "@oclif/core" + +await execute({ dir: import.meta.url }) diff --git a/cli/options/dialect.ts b/cli/options/dialect.ts new file mode 100644 index 00000000..d5db981e --- /dev/null +++ b/cli/options/dialect.ts @@ -0,0 +1,178 @@ +import { Flags } from "@oclif/core" +import type { Dialect } from "dpkit" + +export const header = Flags.boolean({ + description: "whether the file includes a header row with field names", + default: true, +}) + +export const headerRows = Flags.string({ + description: + "comma-separated row numbers (zero-based) that are considered header rows", +}) + +export const headerJoin = Flags.string({ + description: "character used to join multi-line headers", +}) + +export const commentRows = Flags.string({ + description: "comma-separated rows to be excluded from the data (zero-based)", +}) + +export const commentChar = Flags.string({ + description: "character sequence denoting the start of a comment line", +}) + +export const delimiter = Flags.string({ + description: "character used to separate fields in the data", + char: "d", +}) + +export const lineTerminator = Flags.string({ + description: "character sequence used to terminate rows", +}) + +export const quoteChar = Flags.string({ + description: "character used to quote fields", +}) + +export const doubleQuote = Flags.boolean({ + description: + "whether a sequence of two quote characters represents a single quote", +}) + +export const escapeChar = Flags.string({ + description: "character used to escape the delimiter or quote characters", +}) + +export const nullSequence = Flags.string({ + description: + "character sequence representing null or missing values in the data", +}) + +export const skipInitialSpace = Flags.boolean({ + description: + "whether to ignore whitespace immediately following the delimiter", +}) + +export const property = Flags.string({ + description: "for JSON data, the property name containing the data array", +}) + +export const itemType = Flags.string({ + description: "the type of data item in the source", + options: ["array", "object"], +}) + +export const itemKeys = Flags.string({ + description: + "comma-separated object properties to extract as values (for object-based data items)", +}) + +export const sheetNumber = Flags.integer({ + description: "for spreadsheet data, the sheet number to read (zero-based)", +}) + +export const sheetName = Flags.string({ + description: "for spreadsheet data, the sheet name to read", +}) + +export const table = Flags.string({ + description: "for database sources, the table name to read", +}) + +export const dialectOptions = { + delimiter, + header, + headerRows, + headerJoin, + commentRows, + commentChar, + quoteChar, + doubleQuote, + escapeChar, + nullSequence, + skipInitialSpace, + property, + itemType, + itemKeys, + sheetNumber, + table, +} + +// TODO: rebase on types flags +export function createDialectFromFlags(flags: any) { + let dialect: Dialect | undefined + + if (flags.delimiter) { + dialect = { ...dialect, delimiter: flags.delimiter } + } + + if (flags.header === false) { + dialect = { ...dialect, header: flags.header } + } + + if (flags.headerRows) { + dialect = { + ...dialect, + headerRows: flags.headerRows.split(",").map(Number), + } + } + + if (flags.headerJoin) { + dialect = { ...dialect, headerJoin: flags.headerJoin } + } + + if (flags.commentRows) { + dialect = { + ...dialect, + commentRows: flags.commentRows.split(",").map(Number), + } + } + + if (flags.commentChar) { + dialect = { ...dialect, commentChar: flags.commentChar } + } + + if (flags.quoteChar) { + dialect = { ...dialect, quoteChar: flags.quoteChar } + } + + if (flags.doubleQuote) { + dialect = { ...dialect, doubleQuote: flags.doubleQuote } + } + + if (flags.escapeChar) { + dialect = { ...dialect, escapeChar: flags.escapeChar } + } + + if (flags.nullSequence) { + dialect = { ...dialect, nullSequence: flags.nullSequence } + } + + if (flags.skipInitialSpace) { + dialect = { ...dialect, skipInitialSpace: flags.skipInitialSpace } + } + + if (flags.property) { + dialect = { ...dialect, property: flags.property } + } + + if (flags.itemType) { + dialect = { ...dialect, itemType: flags.itemType } + } + + if (flags.itemKeys) { + dialect = { ...dialect, itemKeys: flags.itemKeys.split(",") } + } + + if (flags.sheetNumber) { + dialect = { ...dialect, sheetNumber: flags.sheetNumber } + } + + if (flags.table) { + dialect = { ...dialect, table: flags.table } + } + + return dialect +} diff --git a/cli/options/index.ts b/cli/options/index.ts new file mode 100644 index 00000000..ea9f8d80 --- /dev/null +++ b/cli/options/index.ts @@ -0,0 +1,5 @@ +export * from "./json.ts" +export * from "./dialect.ts" +export * from "./path.ts" +export * from "./resource.ts" +export * from "./toDialect.ts" diff --git a/cli/options/json.ts b/cli/options/json.ts new file mode 100644 index 00000000..f7d62b3f --- /dev/null +++ b/cli/options/json.ts @@ -0,0 +1,6 @@ +import { Flags } from "@oclif/core" + +export const json = Flags.boolean({ + description: "output as JSON", + char: "j", +}) diff --git a/cli/options/path.ts b/cli/options/path.ts new file mode 100644 index 00000000..df4e97b5 --- /dev/null +++ b/cli/options/path.ts @@ -0,0 +1,5 @@ +import { Flags } from "@oclif/core" + +export const toPath = Flags.string({ + description: "a local output path", +}) diff --git a/cli/options/resource.ts b/cli/options/resource.ts new file mode 100644 index 00000000..f42643f1 --- /dev/null +++ b/cli/options/resource.ts @@ -0,0 +1,5 @@ +import { Flags } from "@oclif/core" + +export const toFormat = Flags.string({ + description: "output resource format", +}) diff --git a/cli/options/toDialect.ts b/cli/options/toDialect.ts new file mode 100644 index 00000000..bdb2b459 --- /dev/null +++ b/cli/options/toDialect.ts @@ -0,0 +1,180 @@ +import { Flags } from "@oclif/core" +import type { Dialect } from "dpkit" + +// TODO: merge with dialect.ts + +export const toHeader = Flags.boolean({ + description: "whether the file includes a header row with field names", + default: true, +}) + +export const toHeaderRows = Flags.string({ + description: + "comma-separated row numbers (zero-based) that are considered header rows", +}) + +export const toHeaderJoin = Flags.string({ + description: "character used to join multi-line headers", +}) + +export const toCommentRows = Flags.string({ + description: "comma-separated rows to be excluded from the data (zero-based)", +}) + +export const toCommentChar = Flags.string({ + description: "character sequence denoting the start of a comment line", +}) + +export const toDelimiter = Flags.string({ + description: "character used to separate fields in the data", + char: "d", +}) + +export const toLineTerminator = Flags.string({ + description: "character sequence used to terminate rows", +}) + +export const toQuoteChar = Flags.string({ + description: "character used to quote fields", +}) + +export const toDoubleQuote = Flags.boolean({ + description: + "whether a sequence of two quote characters represents a single quote", +}) + +export const toEscapeChar = Flags.string({ + description: "character used to escape the delimiter or quote characters", +}) + +export const toNullSequence = Flags.string({ + description: + "character sequence representing null or missing values in the data", +}) + +export const toSkipInitialSpace = Flags.boolean({ + description: + "whether to ignore whitespace immediately following the delimiter", +}) + +export const toProperty = Flags.string({ + description: "for JSON data, the property name containing the data array", +}) + +export const toItemType = Flags.string({ + description: "the type of data item in the source", + options: ["array", "object"], +}) + +export const toItemKeys = Flags.string({ + description: + "comma-separated object properties to extract as values (for object-based data items)", +}) + +export const toSheetNumber = Flags.integer({ + description: "for spreadsheet data, the sheet number to read (zero-based)", +}) + +export const toSheetName = Flags.string({ + description: "for spreadsheet data, the sheet name to read", +}) + +export const toTable = Flags.string({ + description: "for database sources, the table name to read", +}) + +export const toDialectOptions = { + toDelimiter, + toHeader, + toHeaderRows, + toHeaderJoin, + toCommentRows, + toCommentChar, + toQuoteChar, + toDoubleQuote, + toEscapeChar, + toNullSequence, + toSkipInitialSpace, + toProperty, + toItemType, + toItemKeys, + toSheetNumber, + toTable, +} + +// TODO: rebase on types flags +export function createToDialectFromFlags(flags: any) { + let dialect: Dialect | undefined + + if (flags.toDelimiter) { + dialect = { ...dialect, delimiter: flags.toDelimiter } + } + + if (flags.toHeader === false) { + dialect = { ...dialect, header: flags.toHeader } + } + + if (flags.toHeaderRows) { + dialect = { + ...dialect, + headerRows: flags.toHeaderRows.split(",").map(Number), + } + } + + if (flags.toHeaderJoin) { + dialect = { ...dialect, headerJoin: flags.toHeaderJoin } + } + + if (flags.toCommentRows) { + dialect = { + ...dialect, + commentRows: flags.toCommentRows.split(",").map(Number), + } + } + + if (flags.toCommentChar) { + dialect = { ...dialect, commentChar: flags.toCommentChar } + } + + if (flags.toQuoteChar) { + dialect = { ...dialect, quoteChar: flags.toQuoteChar } + } + + if (flags.toDoubleQuote) { + dialect = { ...dialect, doubleQuote: flags.toDoubleQuote } + } + + if (flags.toEscapeChar) { + dialect = { ...dialect, escapeChar: flags.toEscapeChar } + } + + if (flags.toNullSequence) { + dialect = { ...dialect, nullSequence: flags.toNullSequence } + } + + if (flags.toSkipInitialSpace) { + dialect = { ...dialect, skipInitialSpace: flags.toSkipInitialSpace } + } + + if (flags.toProperty) { + dialect = { ...dialect, property: flags.toProperty } + } + + if (flags.toItemType) { + dialect = { ...dialect, itemType: flags.toItemType } + } + + if (flags.toItemKeys) { + dialect = { ...dialect, itemKeys: flags.toItemKeys.split(",") } + } + + if (flags.toSheetNumber) { + dialect = { ...dialect, sheetNumber: flags.toSheetNumber } + } + + if (flags.toTable) { + dialect = { ...dialect, table: flags.toTable } + } + + return dialect +} diff --git a/cli/package.json b/cli/package.json index 4d29d4e4..afc8973c 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,8 +1,16 @@ { "name": "@dpkit/cli", "type": "module", - "main": "build/index.js", "version": "0.2.0", + "bin": { + "dp": "./build/entrypoints/run.js" + }, + "oclif": { + "bin": "dp", + "commands": "./commands", + "topicSeparator": " ", + "plugins": ["@oclif/plugin-autocomplete"] + }, "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,6 +28,25 @@ "cli" ], "scripts": { - "build": "tsc --build" + "build": "tsc && pnpm build:copy && pnpm build:mode", + "build:copy": "cp entrypoints/*.cmd build/entrypoints && cp package.json build && cp .oclifrc.js build", + "build:mode": "chmod +x ./build/entrypoints/*.js", + "compile": "node ./scripts/compile.ts", + "dev": "node ./scripts/dev.ts", + "run": "node ./scripts/run.ts" + }, + "dependencies": { + "@oclif/core": "^4.5.2", + "@oclif/plugin-autocomplete": "^3.2.34", + "dpkit": "workspace:*", + "ink": "^6.1.0", + "ink-select-input": "^6.2.0", + "nodejs-polars": "^0.21.0", + "react": "^19.1.1", + "ts-extras": "^0.14.0" + }, + "devDependencies": { + "@types/react": "19.1.9", + "tsx": "4.20.3" } } diff --git a/cli/params/index.ts b/cli/params/index.ts new file mode 100644 index 00000000..5bec7a0e --- /dev/null +++ b/cli/params/index.ts @@ -0,0 +1 @@ +export * from "./path.ts" diff --git a/cli/params/path.ts b/cli/params/path.ts new file mode 100644 index 00000000..b94b40b8 --- /dev/null +++ b/cli/params/path.ts @@ -0,0 +1,11 @@ +import { Args } from "@oclif/core" + +export const requriedDescriptorPath = Args.string({ + description: "local or remote path to the descriptor", + required: true, +}) + +export const requriedTablePath = Args.string({ + description: "local or remote path to the table", + required: true, +}) diff --git a/cli/scripts/compile.ts b/cli/scripts/compile.ts new file mode 100644 index 00000000..6b919e34 --- /dev/null +++ b/cli/scripts/compile.ts @@ -0,0 +1,21 @@ +import { execa } from "execa" +const $ = execa({ preferLocal: true, stdout: ["inherit"] }) + +// Cleanup + +await $`rm -rf compile` +await $`mkdir compile` + +// Prepare dependencies + +await $` +pnpm deploy compile +--legacy +--production +--filter cli +--config.node-linker=hoisted +` + +// Compile application + +await $({ cwd: "compile" })`deno compile --allow-all entrypoints/run.ts` diff --git a/cli/tsconfig.json b/cli/tsconfig.json index 7be40230..3c43903c 100644 --- a/cli/tsconfig.json +++ b/cli/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/core/OVERVIEW.md b/core/OVERVIEW.md deleted file mode 100644 index 1480d04e..00000000 --- a/core/OVERVIEW.md +++ /dev/null @@ -1,6 +0,0 @@ -# @dpkit/core - -:::note -This overview is under development. -::: - diff --git a/core/dialect/Dialect.ts b/core/dialect/Dialect.ts index 960bf4fa..73249daf 100644 --- a/core/dialect/Dialect.ts +++ b/core/dialect/Dialect.ts @@ -1,4 +1,4 @@ -import type { Metadata } from "../general/index.js" +import type { Metadata } from "../general/index.ts" /** * Descriptor that describes the structure of tabular data, such as delimiters, diff --git a/core/dialect/assert.spec.ts b/core/dialect/assert.spec.ts index 52dad36d..f0fc9eb5 100644 --- a/core/dialect/assert.spec.ts +++ b/core/dialect/assert.spec.ts @@ -1,7 +1,7 @@ import { describe, expect, expectTypeOf, it } from "vitest" -import { AssertionError } from "../general/index.js" -import type { Dialect } from "./Dialect.js" -import { assertDialect } from "./assert.js" +import { AssertionError } from "../general/index.ts" +import type { Dialect } from "./Dialect.ts" +import { assertDialect } from "./assert.ts" describe("assertDialect", () => { it("returns typed dialect when valid", async () => { diff --git a/core/dialect/assert.ts b/core/dialect/assert.ts index 090e4bc7..b87140eb 100644 --- a/core/dialect/assert.ts +++ b/core/dialect/assert.ts @@ -1,6 +1,6 @@ -import { AssertionError, type Descriptor } from "../general/index.js" -import type { Dialect } from "./Dialect.js" -import { validateDialect } from "./validate.js" +import { AssertionError, type Descriptor } from "../general/index.ts" +import type { Dialect } from "./Dialect.ts" +import { validateDialect } from "./validate.ts" /** * Assert a Dialect descriptor (JSON Object) against its profile diff --git a/core/dialect/index.ts b/core/dialect/index.ts index fd850fa3..8ddda4d2 100644 --- a/core/dialect/index.ts +++ b/core/dialect/index.ts @@ -1,7 +1,7 @@ -export { assertDialect } from "./assert.js" -export { validateDialect } from "./validate.js" -export type { Dialect } from "./Dialect.js" -export { loadDialect } from "./load.js" -export { saveDialect } from "./save.js" -export { normalizeDialect } from "./process/normalize.js" -export { denormalizeDialect } from "./process/denormalize.js" +export { assertDialect } from "./assert.ts" +export { validateDialect } from "./validate.ts" +export type { Dialect } from "./Dialect.ts" +export { loadDialect } from "./load.ts" +export { saveDialect } from "./save.ts" +export { normalizeDialect } from "./process/normalize.ts" +export { denormalizeDialect } from "./process/denormalize.ts" diff --git a/core/dialect/load.spec.ts b/core/dialect/load.spec.ts index 2b0c18bc..b58aaef0 100644 --- a/core/dialect/load.spec.ts +++ b/core/dialect/load.spec.ts @@ -1,7 +1,7 @@ import { join } from "node:path" import { describe, expect, expectTypeOf, it } from "vitest" -import type { Dialect } from "./Dialect.js" -import { loadDialect } from "./load.js" +import type { Dialect } from "./Dialect.ts" +import { loadDialect } from "./load.ts" describe("loadDialect", async () => { const getFixturePath = (name: string) => join(__dirname, "fixtures", name) diff --git a/core/dialect/load.ts b/core/dialect/load.ts index c7966b6e..6beba344 100644 --- a/core/dialect/load.ts +++ b/core/dialect/load.ts @@ -1,5 +1,5 @@ -import { loadDescriptor } from "../general/index.js" -import { assertDialect } from "./assert.js" +import { loadDescriptor } from "../general/index.ts" +import { assertDialect } from "./assert.ts" /** * Load a Dialect descriptor (JSON Object) from a file or URL diff --git a/core/dialect/process/denormalize.ts b/core/dialect/process/denormalize.ts index ff212a4b..17666b10 100644 --- a/core/dialect/process/denormalize.ts +++ b/core/dialect/process/denormalize.ts @@ -1,5 +1,5 @@ -import type { Descriptor } from "../../general/index.js" -import type { Dialect } from "../Dialect.js" +import type { Descriptor } from "../../general/index.ts" +import type { Dialect } from "../Dialect.ts" export function denormalizeDialect(dialect: Dialect) { dialect = globalThis.structuredClone(dialect) diff --git a/core/dialect/process/normalize.ts b/core/dialect/process/normalize.ts index e7e13052..8da6af89 100644 --- a/core/dialect/process/normalize.ts +++ b/core/dialect/process/normalize.ts @@ -1,4 +1,4 @@ -import type { Descriptor } from "../../general/index.js" +import type { Descriptor } from "../../general/index.ts" export function normalizeDialect(descriptor: Descriptor) { descriptor = globalThis.structuredClone(descriptor) diff --git a/core/dialect/save.spec.ts b/core/dialect/save.spec.ts index 4cbcfcd4..9daa4963 100644 --- a/core/dialect/save.spec.ts +++ b/core/dialect/save.spec.ts @@ -2,8 +2,8 @@ import * as fs from "node:fs/promises" import * as path from "node:path" import { temporaryDirectory } from "tempy" import { afterEach, beforeEach, describe, expect, it } from "vitest" -import type { Dialect } from "./Dialect.js" -import { saveDialect } from "./save.js" +import type { Dialect } from "./Dialect.ts" +import { saveDialect } from "./save.ts" describe("saveDialect", () => { const testDialect: Dialect = { diff --git a/core/dialect/save.ts b/core/dialect/save.ts index bf50476e..bdcd89e7 100644 --- a/core/dialect/save.ts +++ b/core/dialect/save.ts @@ -1,6 +1,6 @@ -import { saveDescriptor } from "../general/index.js" -import type { Dialect } from "./Dialect.js" -import { denormalizeDialect } from "./process/denormalize.js" +import { saveDescriptor } from "../general/index.ts" +import type { Dialect } from "./Dialect.ts" +import { denormalizeDialect } from "./process/denormalize.ts" const CURRENT_PROFILE = "https://datapackage.org/profiles/2.0/tabledialect.json" diff --git a/core/dialect/validate.spec.ts b/core/dialect/validate.spec.ts index b4ae018b..4fb4cad6 100644 --- a/core/dialect/validate.spec.ts +++ b/core/dialect/validate.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest" -import { validateDialect } from "./validate.js" +import { validateDialect } from "./validate.ts" describe("validateDialect", () => { it("returns valid result for valid dialect", async () => { diff --git a/core/dialect/validate.ts b/core/dialect/validate.ts index 25ebf818..f676dc6b 100644 --- a/core/dialect/validate.ts +++ b/core/dialect/validate.ts @@ -1,7 +1,7 @@ -import { type Descriptor, validateDescriptor } from "../general/index.js" -import { loadProfile } from "../general/index.js" -import type { Dialect } from "./Dialect.js" -import { normalizeDialect } from "./process/normalize.js" +import { type Descriptor, validateDescriptor } from "../general/index.ts" +import { loadProfile } from "../general/index.ts" +import type { Dialect } from "./Dialect.ts" +import { normalizeDialect } from "./process/normalize.ts" const DEFAULT_PROFILE = "https://datapackage.org/profiles/1.0/tabledialect.json" diff --git a/core/field/Field.ts b/core/field/Field.ts index cf78669a..526d6c74 100644 --- a/core/field/Field.ts +++ b/core/field/Field.ts @@ -1,4 +1,4 @@ -import type * as fields from "./types/index.js" +import type * as fields from "./types/index.ts" /** * A Table Schema field diff --git a/core/field/index.ts b/core/field/index.ts index 1dfbcf00..2c797109 100644 --- a/core/field/index.ts +++ b/core/field/index.ts @@ -1,3 +1,3 @@ -export type { Field } from "./Field.js" -export type * from "./types/index.js" -export { normalizeField } from "./process/normalize.js" +export type { Field } from "./Field.ts" +export type * from "./types/index.ts" +export { normalizeField } from "./process/normalize.ts" diff --git a/core/field/process/denormalize.ts b/core/field/process/denormalize.ts index e2b24ed6..264b70e9 100644 --- a/core/field/process/denormalize.ts +++ b/core/field/process/denormalize.ts @@ -1,5 +1,5 @@ -import type { Descriptor } from "../../general/index.js" -import type { Field } from "../Field.js" +import type { Descriptor } from "../../general/index.ts" +import type { Field } from "../Field.ts" export function denormalizeField(field: Field) { field = globalThis.structuredClone(field) diff --git a/core/field/process/normalize.ts b/core/field/process/normalize.ts index 4c8d546a..af4af06a 100644 --- a/core/field/process/normalize.ts +++ b/core/field/process/normalize.ts @@ -1,4 +1,4 @@ -import type { Descriptor } from "../../general/index.js" +import type { Descriptor } from "../../general/index.ts" export function normalizeField(descriptor: Descriptor) { descriptor = globalThis.structuredClone(descriptor) diff --git a/core/field/types/Any.ts b/core/field/types/Any.ts index 8fd2b7d5..e3a6e13a 100644 --- a/core/field/types/Any.ts +++ b/core/field/types/Any.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * Any field type (unspecified/mixed) diff --git a/core/field/types/Array.ts b/core/field/types/Array.ts index 2030646e..4f25a898 100644 --- a/core/field/types/Array.ts +++ b/core/field/types/Array.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * Array field type (serialized JSON array) diff --git a/core/field/types/Base.ts b/core/field/types/Base.ts index 81340175..b8371bd6 100644 --- a/core/field/types/Base.ts +++ b/core/field/types/Base.ts @@ -1,4 +1,4 @@ -import type { Metadata } from "../../general/index.js" +import type { Metadata } from "../../general/index.ts" /** * Base field properties common to all field types diff --git a/core/field/types/Boolean.ts b/core/field/types/Boolean.ts index 3dfd706d..21252989 100644 --- a/core/field/types/Boolean.ts +++ b/core/field/types/Boolean.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * Boolean field type diff --git a/core/field/types/Date.ts b/core/field/types/Date.ts index 82522db8..99438926 100644 --- a/core/field/types/Date.ts +++ b/core/field/types/Date.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * Date field type diff --git a/core/field/types/Datetime.ts b/core/field/types/Datetime.ts index 829ceb84..af37faf2 100644 --- a/core/field/types/Datetime.ts +++ b/core/field/types/Datetime.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * Datetime field type diff --git a/core/field/types/Duration.ts b/core/field/types/Duration.ts index 6fed9c98..96d22708 100644 --- a/core/field/types/Duration.ts +++ b/core/field/types/Duration.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * Duration field type (ISO 8601 duration) diff --git a/core/field/types/Geojson.ts b/core/field/types/Geojson.ts index a445667c..1151dea0 100644 --- a/core/field/types/Geojson.ts +++ b/core/field/types/Geojson.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * GeoJSON field type diff --git a/core/field/types/Geopoint.ts b/core/field/types/Geopoint.ts index e1e3ebae..eef21af6 100644 --- a/core/field/types/Geopoint.ts +++ b/core/field/types/Geopoint.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * Geopoint field type diff --git a/core/field/types/Integer.ts b/core/field/types/Integer.ts index b5fc447e..86fa1462 100644 --- a/core/field/types/Integer.ts +++ b/core/field/types/Integer.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * Integer field type diff --git a/core/field/types/List.ts b/core/field/types/List.ts index 9357b045..cb2d595d 100644 --- a/core/field/types/List.ts +++ b/core/field/types/List.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * List field type (primitive values ordered collection) diff --git a/core/field/types/Number.ts b/core/field/types/Number.ts index b64534ea..271c72f6 100644 --- a/core/field/types/Number.ts +++ b/core/field/types/Number.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * Number field type diff --git a/core/field/types/Object.ts b/core/field/types/Object.ts index d4aa8825..ccfc6c62 100644 --- a/core/field/types/Object.ts +++ b/core/field/types/Object.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * Object field type (serialized JSON object) diff --git a/core/field/types/String.ts b/core/field/types/String.ts index 0dd6ccac..1fa494b5 100644 --- a/core/field/types/String.ts +++ b/core/field/types/String.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * String field type diff --git a/core/field/types/Time.ts b/core/field/types/Time.ts index 92edd511..8b9128ea 100644 --- a/core/field/types/Time.ts +++ b/core/field/types/Time.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * Time field type diff --git a/core/field/types/Year.ts b/core/field/types/Year.ts index 8432cd21..ed664d5b 100644 --- a/core/field/types/Year.ts +++ b/core/field/types/Year.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * Year field type diff --git a/core/field/types/Yearmonth.ts b/core/field/types/Yearmonth.ts index 6d7b0475..6e06c9c6 100644 --- a/core/field/types/Yearmonth.ts +++ b/core/field/types/Yearmonth.ts @@ -1,4 +1,4 @@ -import type { BaseConstraints, BaseField } from "./Base.js" +import type { BaseConstraints, BaseField } from "./Base.ts" /** * Year and month field type diff --git a/core/field/types/index.ts b/core/field/types/index.ts index 06dbe21c..b4ee200a 100644 --- a/core/field/types/index.ts +++ b/core/field/types/index.ts @@ -1,16 +1,16 @@ -export * from "./Any.js" -export * from "./String.js" -export * from "./Number.js" -export * from "./Integer.js" -export * from "./Boolean.js" -export * from "./Object.js" -export * from "./Array.js" -export * from "./List.js" -export * from "./Date.js" -export * from "./Time.js" -export * from "./Datetime.js" -export * from "./Year.js" -export * from "./Yearmonth.js" -export * from "./Duration.js" -export * from "./Geopoint.js" -export * from "./Geojson.js" +export * from "./Any.ts" +export * from "./String.ts" +export * from "./Number.ts" +export * from "./Integer.ts" +export * from "./Boolean.ts" +export * from "./Object.ts" +export * from "./Array.ts" +export * from "./List.ts" +export * from "./Date.ts" +export * from "./Time.ts" +export * from "./Datetime.ts" +export * from "./Year.ts" +export * from "./Yearmonth.ts" +export * from "./Duration.ts" +export * from "./Geopoint.ts" +export * from "./Geojson.ts" diff --git a/core/general/descriptor/load.spec.ts b/core/general/descriptor/load.spec.ts index deb81715..bfc9b75b 100644 --- a/core/general/descriptor/load.spec.ts +++ b/core/general/descriptor/load.spec.ts @@ -1,6 +1,6 @@ import path from "node:path" import { afterEach, describe, expect, it, vi } from "vitest" -import { loadDescriptor } from "./load.js" +import { loadDescriptor } from "./load.ts" describe("loadDescriptor", () => { const getFixturePath = (name?: string) => diff --git a/core/general/descriptor/load.ts b/core/general/descriptor/load.ts index 395a7271..4898a382 100644 --- a/core/general/descriptor/load.ts +++ b/core/general/descriptor/load.ts @@ -1,6 +1,6 @@ -import { node } from "../node.js" -import { getBasepath, isRemotePath } from "../path.js" -import { parseDescriptor } from "./process/parse.js" +import { node } from "../node.ts" +import { getBasepath, isRemotePath } from "../path.ts" +import { parseDescriptor } from "./process/parse.ts" /** * Load a descriptor (JSON Object) from a file or URL diff --git a/core/general/descriptor/process/parse.ts b/core/general/descriptor/process/parse.ts index f2f3cde7..0c42cb1d 100644 --- a/core/general/descriptor/process/parse.ts +++ b/core/general/descriptor/process/parse.ts @@ -1,4 +1,4 @@ -import type { Descriptor } from "../Descriptor.js" +import type { Descriptor } from "../Descriptor.ts" export function parseDescriptor(text: string) { const value = JSON.parse(text) diff --git a/core/general/descriptor/process/stringify.ts b/core/general/descriptor/process/stringify.ts index 92c9ee68..a782f77b 100644 --- a/core/general/descriptor/process/stringify.ts +++ b/core/general/descriptor/process/stringify.ts @@ -1,4 +1,4 @@ -import type { Descriptor } from "../Descriptor.js" +import type { Descriptor } from "../Descriptor.ts" export function stringifyDescriptor(descriptor: Descriptor) { return JSON.stringify(descriptor, null, 2) diff --git a/core/general/descriptor/save.spec.ts b/core/general/descriptor/save.spec.ts index e75ad313..1951ca6a 100644 --- a/core/general/descriptor/save.spec.ts +++ b/core/general/descriptor/save.spec.ts @@ -2,7 +2,7 @@ import * as fs from "node:fs/promises" import * as path from "node:path" import { temporaryDirectory } from "tempy" import { afterEach, beforeEach, describe, expect, it } from "vitest" -import { saveDescriptor } from "./save.js" +import { saveDescriptor } from "./save.ts" describe("saveDescriptor", () => { const testDescriptor = { diff --git a/core/general/descriptor/save.ts b/core/general/descriptor/save.ts index e87d5e2e..cd97ab0f 100644 --- a/core/general/descriptor/save.ts +++ b/core/general/descriptor/save.ts @@ -1,6 +1,6 @@ -import { node } from "../node.js" -import type { Descriptor } from "./Descriptor.js" -import { stringifyDescriptor } from "./process/stringify.js" +import { node } from "../node.ts" +import type { Descriptor } from "./Descriptor.ts" +import { stringifyDescriptor } from "./process/stringify.ts" /** * Save a descriptor (JSON Object) to a file path diff --git a/core/general/descriptor/validate.spec.ts b/core/general/descriptor/validate.spec.ts index c4c8dd42..accf7f2c 100644 --- a/core/general/descriptor/validate.spec.ts +++ b/core/general/descriptor/validate.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest" -import { validateDescriptor } from "./validate.js" +import { validateDescriptor } from "./validate.ts" describe("validateDescriptor", () => { it("returns empty array for valid descriptor", async () => { diff --git a/core/general/descriptor/validate.ts b/core/general/descriptor/validate.ts index a7e5d2f6..b046c164 100644 --- a/core/general/descriptor/validate.ts +++ b/core/general/descriptor/validate.ts @@ -1,6 +1,6 @@ -import type { MetadataError } from "../Error.js" -import { ajv } from "../profile/ajv.js" -import type { Descriptor } from "./Descriptor.js" +import type { MetadataError } from "../Error.ts" +import { ajv } from "../profile/ajv.ts" +import type { Descriptor } from "./Descriptor.ts" /** * Validate a descriptor (JSON Object) against a JSON Schema diff --git a/core/general/index.ts b/core/general/index.ts index 762c0675..57c1b3e9 100644 --- a/core/general/index.ts +++ b/core/general/index.ts @@ -1,13 +1,14 @@ -export { parseDescriptor } from "./descriptor/process/parse.js" -export { stringifyDescriptor } from "./descriptor/process/stringify.js" -export { loadDescriptor } from "./descriptor/load.js" -export { saveDescriptor } from "./descriptor/save.js" -export { validateDescriptor } from "./descriptor/validate.js" -export type { Descriptor } from "./descriptor/Descriptor.js" -export type { Metadata } from "./metadata/Metadata.js" -export { isDescriptor } from "./descriptor/Descriptor.js" -export { loadProfile } from "./profile/load.js" -export { AssertionError, type MetadataError } from "./Error.js" +// TODO: split this general module into more focused descriptor/metadata/etc +export { parseDescriptor } from "./descriptor/process/parse.ts" +export { stringifyDescriptor } from "./descriptor/process/stringify.ts" +export { loadDescriptor } from "./descriptor/load.ts" +export { saveDescriptor } from "./descriptor/save.ts" +export { validateDescriptor } from "./descriptor/validate.ts" +export type { Descriptor } from "./descriptor/Descriptor.ts" +export type { Metadata } from "./metadata/Metadata.ts" +export { isDescriptor } from "./descriptor/Descriptor.ts" +export { loadProfile } from "./profile/load.ts" +export { AssertionError, type MetadataError } from "./Error.ts" export { getName, getFormat, @@ -16,4 +17,4 @@ export { normalizePath, denormalizePath, getFilename, -} from "./path.js" +} from "./path.ts" diff --git a/core/general/path.spec.ts b/core/general/path.spec.ts index d8ce2c56..a9fe96ad 100644 --- a/core/general/path.spec.ts +++ b/core/general/path.spec.ts @@ -6,7 +6,7 @@ import { getFilename, isRemotePath, normalizePath, -} from "./path.js" +} from "./path.ts" describe("isRemotePath", () => { it.each([ diff --git a/core/general/path.ts b/core/general/path.ts index 39f25f1e..35975ddb 100644 --- a/core/general/path.ts +++ b/core/general/path.ts @@ -1,5 +1,5 @@ -import Slugger from "github-slugger" -import { node } from "./node.js" +import slugify from "@sindresorhus/slugify" +import { node } from "./node.ts" export function isRemotePath(path: string) { try { @@ -20,8 +20,7 @@ export function getName(filename?: string) { return undefined } - const slugger = new Slugger() - return slugger.slug(name) + return slugify(name) } export function getFormat(filename?: string) { diff --git a/core/general/profile/Profile.ts b/core/general/profile/Profile.ts index a699293d..5ec52525 100644 --- a/core/general/profile/Profile.ts +++ b/core/general/profile/Profile.ts @@ -1,3 +1,3 @@ -import type { Descriptor } from "../descriptor/Descriptor.js" +import type { Descriptor } from "../descriptor/Descriptor.ts" export type Profile = Descriptor diff --git a/core/general/profile/ajv.ts b/core/general/profile/ajv.ts index ed2c7c86..55bfed9f 100644 --- a/core/general/profile/ajv.ts +++ b/core/general/profile/ajv.ts @@ -1,5 +1,5 @@ import { Ajv } from "ajv" -import { loadProfile } from "./load.js" +import { loadProfile } from "./load.ts" export const ajv = new Ajv({ strict: false, diff --git a/core/general/profile/cache.ts b/core/general/profile/cache.ts index 737a86a1..6044a49b 100644 --- a/core/general/profile/cache.ts +++ b/core/general/profile/cache.ts @@ -1,6 +1,6 @@ import QuickLRU from "quick-lru" -import type { Descriptor } from "../descriptor/Descriptor.js" -import { profileRegistry } from "./registry.js" +import type { Descriptor } from "../descriptor/Descriptor.ts" +import { profileRegistry } from "./registry.ts" export const cache = new QuickLRU({ maxSize: 100 }) for (const { path, profile } of Object.values(profileRegistry)) { diff --git a/core/general/profile/load.ts b/core/general/profile/load.ts index 3b8f349f..4811b552 100644 --- a/core/general/profile/load.ts +++ b/core/general/profile/load.ts @@ -1,7 +1,7 @@ -import { loadDescriptor } from "../descriptor/load.js" -import { cache } from "./cache.js" -import type { ProfileType } from "./registry.js" -import { validateProfile } from "./validate.js" +import { loadDescriptor } from "../descriptor/load.ts" +import { cache } from "./cache.ts" +import type { ProfileType } from "./registry.ts" +import { validateProfile } from "./validate.ts" export async function loadProfile( path: string, diff --git a/core/general/profile/validate.ts b/core/general/profile/validate.ts index 70a6b90f..193211f3 100644 --- a/core/general/profile/validate.ts +++ b/core/general/profile/validate.ts @@ -1,8 +1,8 @@ -import type { Descriptor } from "../descriptor/Descriptor.js" -import type { Profile } from "./Profile.js" -import { ajv } from "./ajv.js" -import type { ProfileType } from "./registry.js" -import { profileRegistry } from "./registry.js" +import type { Descriptor } from "../descriptor/Descriptor.ts" +import type { Profile } from "./Profile.ts" +import { ajv } from "./ajv.ts" +import type { ProfileType } from "./registry.ts" +import { profileRegistry } from "./registry.ts" export async function validateProfile( descriptor: Descriptor, diff --git a/core/index.ts b/core/index.ts index 71e4b6bd..735a4049 100644 --- a/core/index.ts +++ b/core/index.ts @@ -1,7 +1,7 @@ -export * from "./general/index.js" -export * from "./dialect/index.js" -export * from "./field/index.js" -export * from "./package/index.js" -export * from "./resource/index.js" -export * from "./schema/index.js" -export * from "./plugin.js" +export * from "./general/index.ts" +export * from "./dialect/index.ts" +export * from "./field/index.ts" +export * from "./package/index.ts" +export * from "./resource/index.ts" +export * from "./schema/index.ts" +export * from "./plugin.ts" diff --git a/core/package.json b/core/package.json index 4ef97686..94f8d9e1 100644 --- a/core/package.json +++ b/core/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/core", "type": "module", - "main": "build/index.js", "version": "0.7.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,11 +20,11 @@ "core" ], "scripts": { - "build": "tsc --build" + "build": "tsc" }, "dependencies": { + "@sindresorhus/slugify": "^0.9.0", "ajv": "^8.17.1", - "github-slugger": "^2.0.0", "quick-lru": "^7.0.1", "tiny-invariant": "^1.3.3" } diff --git a/core/package/Package.ts b/core/package/Package.ts index 2582263d..a4ff6852 100644 --- a/core/package/Package.ts +++ b/core/package/Package.ts @@ -1,6 +1,6 @@ -import type { Metadata } from "../general/index.js" -import type { License, Resource, Source } from "../resource/index.js" -import type { Contributor } from "./Contributor.js" +import type { Metadata } from "../general/index.ts" +import type { License, Resource, Source } from "../resource/index.ts" +import type { Contributor } from "./Contributor.ts" /** * Data Package interface built on top of the Frictionless Data specification diff --git a/core/package/assert.spec.ts b/core/package/assert.spec.ts index 108391ec..c167e8c6 100644 --- a/core/package/assert.spec.ts +++ b/core/package/assert.spec.ts @@ -1,7 +1,7 @@ import { describe, expect, expectTypeOf, it } from "vitest" -import { AssertionError } from "../general/index.js" -import type { Package } from "./Package.js" -import { assertPackage } from "./assert.js" +import { AssertionError } from "../general/index.ts" +import type { Package } from "./Package.ts" +import { assertPackage } from "./assert.ts" describe("assertPackage", () => { it("returns typed package when valid", async () => { diff --git a/core/package/assert.ts b/core/package/assert.ts index 9a45df35..92570015 100644 --- a/core/package/assert.ts +++ b/core/package/assert.ts @@ -1,6 +1,6 @@ -import { AssertionError, type Descriptor } from "../general/index.js" -import type { Package } from "./Package.js" -import { validatePackageDescriptor } from "./validate.js" +import { AssertionError, type Descriptor } from "../general/index.ts" +import type { Package } from "./Package.ts" +import { validatePackageDescriptor } from "./validate.ts" /** * Assert a Package descriptor (JSON Object) against its profile diff --git a/core/package/index.ts b/core/package/index.ts index 17958a22..a019a487 100644 --- a/core/package/index.ts +++ b/core/package/index.ts @@ -1,9 +1,9 @@ -export type { Package } from "./Package.js" -export { assertPackage } from "./assert.js" -export { loadPackageDescriptor } from "./load.js" -export { savePackageDescriptor } from "./save.js" -export { validatePackageDescriptor } from "./validate.js" -export { normalizePackage } from "./process/normalize.js" -export { denormalizePackage } from "./process/denormalize.js" -export type { Contributor } from "./Contributor.js" -export { mergePackages } from "./merge.js" +export type { Package } from "./Package.ts" +export { assertPackage } from "./assert.ts" +export { loadPackageDescriptor } from "./load.ts" +export { savePackageDescriptor } from "./save.ts" +export { validatePackageDescriptor } from "./validate.ts" +export { normalizePackage } from "./process/normalize.ts" +export { denormalizePackage } from "./process/denormalize.ts" +export type { Contributor } from "./Contributor.ts" +export { mergePackages } from "./merge.ts" diff --git a/core/package/load.spec.ts b/core/package/load.spec.ts index 54055548..c053212f 100644 --- a/core/package/load.spec.ts +++ b/core/package/load.spec.ts @@ -1,7 +1,7 @@ import { join, relative } from "node:path" import { describe, expect, expectTypeOf, it } from "vitest" -import type { Package } from "./Package.js" -import { loadPackageDescriptor } from "./load.js" +import type { Package } from "./Package.ts" +import { loadPackageDescriptor } from "./load.ts" describe("loadPackageDescriptor", async () => { const getFixturePath = (name: string) => diff --git a/core/package/load.ts b/core/package/load.ts index 267d45e5..0cdf374f 100644 --- a/core/package/load.ts +++ b/core/package/load.ts @@ -1,5 +1,5 @@ -import { loadDescriptor } from "../general/index.js" -import { assertPackage } from "./assert.js" +import { loadDescriptor } from "../general/index.ts" +import { assertPackage } from "./assert.ts" /** * Load a Package descriptor (JSON Object) from a file or URL diff --git a/core/package/merge.ts b/core/package/merge.ts index cef4b204..a8765208 100644 --- a/core/package/merge.ts +++ b/core/package/merge.ts @@ -1,5 +1,5 @@ -import type { Package } from "./Package.js" -import { loadPackageDescriptor } from "./load.js" +import type { Package } from "./Package.ts" +import { loadPackageDescriptor } from "./load.ts" /** * Merges a system data package into a user data package if provided diff --git a/core/package/process/denormalize.ts b/core/package/process/denormalize.ts index 7cd64060..82954bab 100644 --- a/core/package/process/denormalize.ts +++ b/core/package/process/denormalize.ts @@ -1,6 +1,6 @@ -import type { Descriptor } from "../../general/index.js" -import { denormalizeResource } from "../../resource/index.js" -import type { Package } from "../Package.js" +import type { Descriptor } from "../../general/index.ts" +import { denormalizeResource } from "../../resource/index.ts" +import type { Package } from "../Package.ts" export function denormalizePackage( dataPackage: Package, diff --git a/core/package/process/normalize.ts b/core/package/process/normalize.ts index 5b039539..de87b3b3 100644 --- a/core/package/process/normalize.ts +++ b/core/package/process/normalize.ts @@ -1,5 +1,5 @@ -import type { Descriptor } from "../../general/index.js" -import { normalizeResource } from "../../resource/index.js" +import type { Descriptor } from "../../general/index.ts" +import { normalizeResource } from "../../resource/index.ts" export function normalizePackage( descriptor: Descriptor, diff --git a/core/package/save.ts b/core/package/save.ts index e684d200..bed14a7b 100644 --- a/core/package/save.ts +++ b/core/package/save.ts @@ -1,6 +1,6 @@ -import { getBasepath, saveDescriptor } from "../general/index.js" -import type { Package } from "./Package.js" -import { denormalizePackage } from "./process/denormalize.js" +import { getBasepath, saveDescriptor } from "../general/index.ts" +import type { Package } from "./Package.ts" +import { denormalizePackage } from "./process/denormalize.ts" const CURRENT_PROFILE = "https://datapackage.org/profiles/2.0/datapackage.json" diff --git a/core/package/validate.spec.ts b/core/package/validate.spec.ts index fbd9885d..1357f90c 100644 --- a/core/package/validate.spec.ts +++ b/core/package/validate.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest" -import { validatePackageDescriptor } from "./validate.js" +import { validatePackageDescriptor } from "./validate.ts" describe("validatePackageDescriptor", () => { it("returns valid result for valid package", async () => { diff --git a/core/package/validate.ts b/core/package/validate.ts index f2a05b8b..c3df5290 100644 --- a/core/package/validate.ts +++ b/core/package/validate.ts @@ -1,7 +1,7 @@ -import { type Descriptor, validateDescriptor } from "../general/index.js" -import { loadProfile } from "../general/index.js" -import type { Package } from "./Package.js" -import { normalizePackage } from "./process/normalize.js" +import { type Descriptor, validateDescriptor } from "../general/index.ts" +import { loadProfile } from "../general/index.ts" +import type { Package } from "./Package.ts" +import { normalizePackage } from "./process/normalize.ts" const DEFAULT_PROFILE = "https://datapackage.org/profiles/1.0/datapackage.json" diff --git a/core/plugin.ts b/core/plugin.ts index 02e33725..a5d2b0b5 100644 --- a/core/plugin.ts +++ b/core/plugin.ts @@ -1,4 +1,4 @@ -import type { Package } from "./package/index.js" +import type { Package } from "./package/index.ts" export interface Plugin { loadPackage?(source: string): Promise diff --git a/core/resource/Resource.ts b/core/resource/Resource.ts index f23e0e83..00792e03 100644 --- a/core/resource/Resource.ts +++ b/core/resource/Resource.ts @@ -1,8 +1,8 @@ -import type { Dialect } from "../dialect/Dialect.js" -import type { Metadata } from "../general/index.js" -import type { Schema } from "../schema/Schema.js" -import type { License } from "./License.js" -import type { Source } from "./Source.js" +import type { Dialect } from "../dialect/Dialect.ts" +import type { Metadata } from "../general/index.ts" +import type { Schema } from "../schema/Schema.ts" +import type { License } from "./License.ts" +import type { Source } from "./Source.ts" /** * Data Resource interface built on top of the Data Package standard and Polars DataFrames diff --git a/core/resource/assert.spec.ts b/core/resource/assert.spec.ts index 07f9f07c..0299c8ad 100644 --- a/core/resource/assert.spec.ts +++ b/core/resource/assert.spec.ts @@ -1,7 +1,7 @@ import { describe, expect, expectTypeOf, it } from "vitest" -import { AssertionError } from "../general/index.js" -import type { Resource } from "./Resource.js" -import { assertResource } from "./assert.js" +import { AssertionError } from "../general/index.ts" +import type { Resource } from "./Resource.ts" +import { assertResource } from "./assert.ts" describe("assertResource", () => { it("returns typed resource when valid", async () => { diff --git a/core/resource/assert.ts b/core/resource/assert.ts index 772babe8..68375be2 100644 --- a/core/resource/assert.ts +++ b/core/resource/assert.ts @@ -1,6 +1,6 @@ -import { AssertionError, type Descriptor } from "../general/index.js" -import type { Resource } from "./Resource.js" -import { validateResourceDescriptor } from "./validate.js" +import { AssertionError, type Descriptor } from "../general/index.ts" +import type { Resource } from "./Resource.ts" +import { validateResourceDescriptor } from "./validate.ts" /** * Assert a Resource descriptor (JSON Object) against its profile diff --git a/core/resource/index.ts b/core/resource/index.ts index 7b3d3229..c17827f1 100644 --- a/core/resource/index.ts +++ b/core/resource/index.ts @@ -1,10 +1,10 @@ -export type { Resource } from "./Resource.js" -export { inferFormat } from "./infer.js" -export { assertResource } from "./assert.js" -export { loadResourceDescriptor } from "./load.js" -export { saveResourceDescriptor } from "./save.js" -export { validateResourceDescriptor } from "./validate.js" -export { normalizeResource } from "./process/normalize.js" -export { denormalizeResource } from "./process/denormalize.js" -export type { Source } from "./Source.js" -export type { License } from "./License.js" +export type { Resource } from "./Resource.ts" +export { inferFormat } from "./infer.ts" +export { assertResource } from "./assert.ts" +export { loadResourceDescriptor } from "./load.ts" +export { saveResourceDescriptor } from "./save.ts" +export { validateResourceDescriptor } from "./validate.ts" +export { normalizeResource } from "./process/normalize.ts" +export { denormalizeResource } from "./process/denormalize.ts" +export type { Source } from "./Source.ts" +export type { License } from "./License.ts" diff --git a/core/resource/infer.ts b/core/resource/infer.ts index 2edb9d98..64416d1f 100644 --- a/core/resource/infer.ts +++ b/core/resource/infer.ts @@ -1,5 +1,5 @@ -import { getFilename, getFormat } from "../general/index.js" -import type { Resource } from "./Resource.js" +import { getFilename, getFormat } from "../general/index.ts" +import type { Resource } from "./Resource.ts" export function inferFormat(resource: Partial) { let format = resource.format diff --git a/core/resource/load.spec.ts b/core/resource/load.spec.ts index ecb29560..366c16b5 100644 --- a/core/resource/load.spec.ts +++ b/core/resource/load.spec.ts @@ -1,7 +1,7 @@ import { join, relative } from "node:path" import { describe, expect, expectTypeOf, it } from "vitest" -import type { Resource } from "./Resource.js" -import { loadResourceDescriptor } from "./load.js" +import type { Resource } from "./Resource.ts" +import { loadResourceDescriptor } from "./load.ts" describe("loadResourceDescriptor", async () => { const getFixturePath = (name: string) => diff --git a/core/resource/load.ts b/core/resource/load.ts index 78a02a11..1d82e88b 100644 --- a/core/resource/load.ts +++ b/core/resource/load.ts @@ -1,5 +1,5 @@ -import { loadDescriptor } from "../general/index.js" -import { assertResource } from "./assert.js" +import { loadDescriptor } from "../general/index.ts" +import { assertResource } from "./assert.ts" /** * Load a Resource descriptor (JSON Object) from a file or URL diff --git a/core/resource/process/denormalize.ts b/core/resource/process/denormalize.ts index 690ed830..528b4f89 100644 --- a/core/resource/process/denormalize.ts +++ b/core/resource/process/denormalize.ts @@ -1,8 +1,8 @@ -import { denormalizeDialect } from "../../dialect/index.js" -import { denormalizePath } from "../../general/index.js" -import type { Descriptor } from "../../general/index.js" -import { denormalizeSchema } from "../../schema/index.js" -import type { Resource } from "../Resource.js" +import { denormalizeDialect } from "../../dialect/index.ts" +import { denormalizePath } from "../../general/index.ts" +import type { Descriptor } from "../../general/index.ts" +import { denormalizeSchema } from "../../schema/index.ts" +import type { Resource } from "../Resource.ts" export function denormalizeResource( resource: Resource, diff --git a/core/resource/process/normalize.ts b/core/resource/process/normalize.ts index 442fefc4..018ced18 100644 --- a/core/resource/process/normalize.ts +++ b/core/resource/process/normalize.ts @@ -1,7 +1,7 @@ -import { normalizeDialect } from "../../dialect/index.js" -import { isDescriptor, normalizePath } from "../../general/index.js" -import type { Descriptor } from "../../general/index.js" -import { normalizeSchema } from "../../schema/index.js" +import { normalizeDialect } from "../../dialect/index.ts" +import { isDescriptor, normalizePath } from "../../general/index.ts" +import type { Descriptor } from "../../general/index.ts" +import { normalizeSchema } from "../../schema/index.ts" export function normalizeResource( descriptor: Descriptor, @@ -77,12 +77,12 @@ function normalizePaths( function normalizeResourceDialect(descriptor: Descriptor) { if (isDescriptor(descriptor.dialect)) { - descriptor.dialect = normalizeDialect({ descriptor: descriptor.dialect }) + descriptor.dialect = normalizeDialect(descriptor.dialect) } } function normalizeResourceSchema(descriptor: Descriptor) { if (isDescriptor(descriptor.schema)) { - descriptor.schema = normalizeSchema({ descriptor: descriptor.schema }) + descriptor.schema = normalizeSchema(descriptor.schema) } } diff --git a/core/resource/save.ts b/core/resource/save.ts index f44a8994..bc83ae37 100644 --- a/core/resource/save.ts +++ b/core/resource/save.ts @@ -1,6 +1,6 @@ -import { getBasepath, saveDescriptor } from "../general/index.js" -import type { Resource } from "./Resource.js" -import { denormalizeResource } from "./process/denormalize.js" +import { getBasepath, saveDescriptor } from "../general/index.ts" +import type { Resource } from "./Resource.ts" +import { denormalizeResource } from "./process/denormalize.ts" const CURRENT_PROFILE = "https://datapackage.org/profiles/2.0/dataresource.json" diff --git a/core/resource/validate.spec.ts b/core/resource/validate.spec.ts index 7e18e7d4..a6bf646d 100644 --- a/core/resource/validate.spec.ts +++ b/core/resource/validate.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest" -import { validateResourceDescriptor } from "./validate.js" +import { validateResourceDescriptor } from "./validate.ts" describe("validateResourceDescriptor", () => { it("returns valid result for valid resource", async () => { diff --git a/core/resource/validate.ts b/core/resource/validate.ts index f6051ee5..f5a80da5 100644 --- a/core/resource/validate.ts +++ b/core/resource/validate.ts @@ -1,10 +1,10 @@ -import { loadDialect } from "../dialect/index.js" -import { type Descriptor, validateDescriptor } from "../general/index.js" -import { AssertionError } from "../general/index.js" -import { loadProfile } from "../general/index.js" -import { loadSchema } from "../schema/index.js" -import type { Resource } from "./Resource.js" -import { normalizeResource } from "./process/normalize.js" +import { loadDialect } from "../dialect/index.ts" +import { type Descriptor, validateDescriptor } from "../general/index.ts" +import { AssertionError } from "../general/index.ts" +import { loadProfile } from "../general/index.ts" +import { loadSchema } from "../schema/index.ts" +import type { Resource } from "./Resource.ts" +import { normalizeResource } from "./process/normalize.ts" const DEFAULT_PROFILE = "https://datapackage.org/profiles/1.0/dataresource.json" diff --git a/core/schema/Schema.ts b/core/schema/Schema.ts index 5aa642e1..508edcc7 100644 --- a/core/schema/Schema.ts +++ b/core/schema/Schema.ts @@ -1,6 +1,6 @@ -import type { Field } from "../field/index.js" -import type { Metadata } from "../general/index.js" -import type { ForeignKey } from "./ForeignKey.js" +import type { Field } from "../field/index.ts" +import type { Metadata } from "../general/index.ts" +import type { ForeignKey } from "./ForeignKey.ts" /** * Table Schema definition diff --git a/core/schema/assert.spec.ts b/core/schema/assert.spec.ts index 230f77d0..db0a8cb0 100644 --- a/core/schema/assert.spec.ts +++ b/core/schema/assert.spec.ts @@ -1,7 +1,7 @@ import { describe, expect, expectTypeOf, it } from "vitest" -import { AssertionError } from "../general/index.js" -import type { Schema } from "./Schema.js" -import { assertSchema } from "./assert.js" +import { AssertionError } from "../general/index.ts" +import type { Schema } from "./Schema.ts" +import { assertSchema } from "./assert.ts" describe("assertSchema", () => { it("returns typed schema when valid", async () => { diff --git a/core/schema/assert.ts b/core/schema/assert.ts index ddb61063..0a078986 100644 --- a/core/schema/assert.ts +++ b/core/schema/assert.ts @@ -1,6 +1,6 @@ -import { AssertionError, type Descriptor } from "../general/index.js" -import type { Schema } from "./Schema.js" -import { validateSchema } from "./validate.js" +import { AssertionError, type Descriptor } from "../general/index.ts" +import type { Schema } from "./Schema.ts" +import { validateSchema } from "./validate.ts" /** * Assert a Schema descriptor (JSON Object) against its profile diff --git a/core/schema/index.ts b/core/schema/index.ts index f6b52e62..4c8341dd 100644 --- a/core/schema/index.ts +++ b/core/schema/index.ts @@ -1,8 +1,8 @@ -export type { Schema } from "./Schema.js" -export type { ForeignKey } from "./ForeignKey.js" -export { assertSchema } from "./assert.js" -export { loadSchema } from "./load.js" -export { saveSchema } from "./save.js" -export { validateSchema } from "./validate.js" -export { normalizeSchema } from "./process/normalize.js" -export { denormalizeSchema } from "./process/denormalize.js" +export type { Schema } from "./Schema.ts" +export type { ForeignKey } from "./ForeignKey.ts" +export { assertSchema } from "./assert.ts" +export { loadSchema } from "./load.ts" +export { saveSchema } from "./save.ts" +export { validateSchema } from "./validate.ts" +export { normalizeSchema } from "./process/normalize.ts" +export { denormalizeSchema } from "./process/denormalize.ts" diff --git a/core/schema/load.spec.ts b/core/schema/load.spec.ts index 73d20a8c..f9a33b4b 100644 --- a/core/schema/load.spec.ts +++ b/core/schema/load.spec.ts @@ -1,7 +1,7 @@ import { join } from "node:path" import { describe, expect, expectTypeOf, it } from "vitest" -import type { Schema } from "./Schema.js" -import { loadSchema } from "./load.js" +import type { Schema } from "./Schema.ts" +import { loadSchema } from "./load.ts" describe("loadSchema", () => { const getFixturePath = (name: string) => join(__dirname, "fixtures", name) diff --git a/core/schema/load.ts b/core/schema/load.ts index 27a6bdf8..00bd37b0 100644 --- a/core/schema/load.ts +++ b/core/schema/load.ts @@ -1,5 +1,5 @@ -import { loadDescriptor } from "../general/index.js" -import { assertSchema } from "./assert.js" +import { loadDescriptor } from "../general/index.ts" +import { assertSchema } from "./assert.ts" /** * Load a Schema descriptor (JSON Object) from a file or URL diff --git a/core/schema/process/denormalize.ts b/core/schema/process/denormalize.ts index 8cf53de7..8e1d4383 100644 --- a/core/schema/process/denormalize.ts +++ b/core/schema/process/denormalize.ts @@ -1,5 +1,5 @@ -import type { Descriptor } from "../../general/index.js" -import type { Schema } from "../Schema.js" +import type { Descriptor } from "../../general/index.ts" +import type { Schema } from "../Schema.ts" export function denormalizeSchema(schema: Schema) { schema = globalThis.structuredClone(schema) diff --git a/core/schema/process/normalize.ts b/core/schema/process/normalize.ts index a2201a5f..4b35afd3 100644 --- a/core/schema/process/normalize.ts +++ b/core/schema/process/normalize.ts @@ -1,6 +1,6 @@ import invariant from "tiny-invariant" -import { normalizeField } from "../../field/index.js" -import type { Descriptor } from "../../general/index.js" +import { normalizeField } from "../../field/index.ts" +import type { Descriptor } from "../../general/index.ts" export function normalizeSchema(descriptor: Descriptor) { descriptor = globalThis.structuredClone(descriptor) diff --git a/core/schema/save.spec.ts b/core/schema/save.spec.ts index 60c527d8..c6752f35 100644 --- a/core/schema/save.spec.ts +++ b/core/schema/save.spec.ts @@ -2,8 +2,8 @@ import * as fs from "node:fs/promises" import * as path from "node:path" import { temporaryDirectory } from "tempy" import { afterEach, beforeEach, describe, expect, it } from "vitest" -import type { Schema } from "./Schema.js" -import { saveSchema } from "./save.js" +import type { Schema } from "./Schema.ts" +import { saveSchema } from "./save.ts" describe("saveSchema", () => { const testSchema: Schema = { diff --git a/core/schema/save.ts b/core/schema/save.ts index 91f3cd91..5f6c801e 100644 --- a/core/schema/save.ts +++ b/core/schema/save.ts @@ -1,6 +1,6 @@ -import { saveDescriptor } from "../general/index.js" -import type { Schema } from "./Schema.js" -import { denormalizeSchema } from "./process/denormalize.js" +import { saveDescriptor } from "../general/index.ts" +import type { Schema } from "./Schema.ts" +import { denormalizeSchema } from "./process/denormalize.ts" const CURRENT_PROFILE = "https://datapackage.org/profiles/2.0/tableschema.json" diff --git a/core/schema/validate.spec.ts b/core/schema/validate.spec.ts index 4e553d0f..9fdf814a 100644 --- a/core/schema/validate.spec.ts +++ b/core/schema/validate.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest" -import { validateSchema } from "./validate.js" +import { validateSchema } from "./validate.ts" describe("validateSchema", () => { it("returns empty array for valid schema", async () => { diff --git a/core/schema/validate.ts b/core/schema/validate.ts index f1aec71a..242681d5 100644 --- a/core/schema/validate.ts +++ b/core/schema/validate.ts @@ -1,7 +1,7 @@ -import { type Descriptor, validateDescriptor } from "../general/index.js" -import { loadProfile } from "../general/index.js" -import type { Schema } from "./Schema.js" -import { normalizeSchema } from "./process/normalize.js" +import { type Descriptor, validateDescriptor } from "../general/index.ts" +import { loadProfile } from "../general/index.ts" +import type { Schema } from "./Schema.ts" +import { normalizeSchema } from "./process/normalize.ts" const DEFAULT_PROFILE = "https://datapackage.org/profiles/1.0/tableschema.json" diff --git a/core/tsconfig.json b/core/tsconfig.json index 7be40230..3c43903c 100644 --- a/core/tsconfig.json +++ b/core/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/core/typedoc.json b/core/typedoc.json index fc33b815..f8e49f3a 100644 --- a/core/typedoc.json +++ b/core/typedoc.json @@ -1,5 +1,4 @@ { "entryPoints": ["index.ts"], - "projectDocuments": ["CHANGELOG.md", "OVERVIEW.md"], "skipErrorChecking": true } diff --git a/csv/dialect/index.ts b/csv/dialect/index.ts index 12e94327..1b388ce8 100644 --- a/csv/dialect/index.ts +++ b/csv/dialect/index.ts @@ -1 +1 @@ -export { inferCsvDialect } from "./infer.js" +export { inferCsvDialect } from "./infer.ts" diff --git a/csv/dialect/infer.spec.ts b/csv/dialect/infer.spec.ts index 84acb196..3d9222b2 100644 --- a/csv/dialect/infer.spec.ts +++ b/csv/dialect/infer.spec.ts @@ -1,6 +1,6 @@ import { writeTempFile } from "@dpkit/file" import { describe, expect, it } from "vitest" -import { inferCsvDialect } from "./infer.js" +import { inferCsvDialect } from "./infer.ts" describe("inferCsvDialect", () => { it("should infer a simple CSV file", async () => { @@ -32,7 +32,8 @@ describe("inferCsvDialect", () => { }) }) - it("should infer header false when no header present", async () => { + // TODO: it gives false positives + it.skip("should infer header false when no header present", async () => { const path = await writeTempFile("1,english\n2,中文\n3,español") const dialect = await inferCsvDialect({ path }) diff --git a/csv/dialect/infer.ts b/csv/dialect/infer.ts index c0be8726..e2df3fb3 100644 --- a/csv/dialect/infer.ts +++ b/csv/dialect/infer.ts @@ -36,9 +36,10 @@ export async function inferCsvDialect( // dialect.lineTerminator = result.lineTerminator //} - if (!result.hasHeader) { - dialect.header = false - } + // TODO: it gives false positives + //if (!result.hasHeader) { + // dialect.header = false + //} } return dialect diff --git a/csv/index.ts b/csv/index.ts index ef2a40d5..0bb8be6b 100644 --- a/csv/index.ts +++ b/csv/index.ts @@ -1,3 +1,3 @@ -export * from "./dialect/index.js" -export * from "./table/index.js" -export * from "./plugin.js" +export * from "./dialect/index.ts" +export * from "./table/index.ts" +export * from "./plugin.ts" diff --git a/csv/package.json b/csv/package.json index b04021e6..46fb56ec 100644 --- a/csv/package.json +++ b/csv/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/csv", "type": "module", - "main": "build/index.js", "version": "0.3.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,17 +20,16 @@ "csv" ], "scripts": { - "build": "tsc --build" + "build": "tsc" }, "dependencies": { "@dpkit/core": "workspace:*", "@dpkit/file": "workspace:*", "@dpkit/table": "workspace:*", "csv-sniffer": "^0.1.1", - "nodejs-polars": "^0.18.0" + "nodejs-polars": "^0.21.0" }, "devDependencies": { - "@dpkit/test": "workspace:*", - "tempy": "^3.1.0" + "@dpkit/test": "workspace:*" } } diff --git a/csv/plugin.ts b/csv/plugin.ts index a0490935..d34bc16f 100644 --- a/csv/plugin.ts +++ b/csv/plugin.ts @@ -2,8 +2,8 @@ import type { Resource } from "@dpkit/core" import { inferFormat } from "@dpkit/core" import type { InferDialectOptions, TablePlugin } from "@dpkit/table" import type { SaveTableOptions, Table } from "@dpkit/table" -import { inferCsvDialect } from "./dialect/index.js" -import { loadCsvTable, saveCsvTable } from "./table/index.js" +import { inferCsvDialect } from "./dialect/index.ts" +import { loadCsvTable, saveCsvTable } from "./table/index.ts" export class CsvPlugin implements TablePlugin { async inferDialect( @@ -24,7 +24,7 @@ export class CsvPlugin implements TablePlugin { } async saveTable(table: Table, options: SaveTableOptions) { - const isCsv = getIsCsv({ path: options.path }) + const isCsv = getIsCsv(options) if (!isCsv) return undefined return await saveCsvTable(table, options) diff --git a/csv/table/fixtures/generated/should-load-remote-file-multipart_2595965849/recording.har b/csv/table/fixtures/generated/loadCsvTable-file-variations-should-load-remote-file-multipart_2684063187/recording.har similarity index 85% rename from csv/table/fixtures/generated/should-load-remote-file-multipart_2595965849/recording.har rename to csv/table/fixtures/generated/loadCsvTable-file-variations-should-load-remote-file-multipart_2684063187/recording.har index 57e9a4fa..b35e26df 100644 --- a/csv/table/fixtures/generated/should-load-remote-file-multipart_2595965849/recording.har +++ b/csv/table/fixtures/generated/loadCsvTable-file-variations-should-load-remote-file-multipart_2684063187/recording.har @@ -1,6 +1,6 @@ { "log": { - "_recordingName": "should load remote file (multipart)", + "_recordingName": "loadCsvTable-file variations-should load remote file (multipart)", "creator": { "comment": "persister:fs", "name": "Polly.JS", @@ -8,25 +8,25 @@ }, "entries": [ { - "_id": "4c7b0fb73c46c7315d57cbb41752f90c", + "_id": "26b4c877aae0bbdbc9889671caf26f73", "_order": 0, "cache": {}, "request": { "bodySize": 0, "cookies": [], "headers": [], - "headersSize": 146, + "headersSize": 147, "httpVersion": "HTTP/1.1", "method": "GET", "queryString": [], - "url": "https://gist.githubusercontent.com/roll/d20416f5e6dfc3fc1a7c4eef8452d581/raw/1c9cd1a020389921bf83e5a0395bb00c6b27402d/tabl1.csv" + "url": "https://gist.githubusercontent.com/roll/ba1c358f1daa994f8094633669d60f50/raw/03e0e54f9d4df7ff08b0d0db937fe5d720d8dfe6/table2.csv" }, "response": { - "bodySize": 29, + "bodySize": 8, "content": { "mimeType": "text/plain; charset=utf-8", - "size": 29, - "text": "id,name\n1,english\n2,中国人" + "size": 8, + "text": "3,german" }, "cookies": [], "headers": [ @@ -48,7 +48,7 @@ }, { "name": "content-length", - "value": "29" + "value": "8" }, { "name": "content-security-policy", @@ -64,19 +64,19 @@ }, { "name": "date", - "value": "Fri, 27 Jun 2025 11:08:00 GMT" + "value": "Thu, 07 Aug 2025 07:49:22 GMT" }, { "name": "etag", - "value": "W/\"7e7cf438cb55bf28aa7f609346bfa9dc9efadbcfe2c8e2ea5c7d093632951d62\"" + "value": "W/\"5b8bd499e42ca79dc52ec0b203194d24d475f240c0b8ff6e0aab54d5798e008a\"" }, { "name": "expires", - "value": "Fri, 27 Jun 2025 11:13:00 GMT" + "value": "Thu, 07 Aug 2025 07:54:22 GMT" }, { "name": "source-age", - "value": "67" + "value": "0" }, { "name": "strict-transport-security", @@ -92,11 +92,11 @@ }, { "name": "x-cache", - "value": "HIT" + "value": "MISS" }, { "name": "x-cache-hits", - "value": "1" + "value": "0" }, { "name": "x-content-type-options", @@ -104,7 +104,7 @@ }, { "name": "x-fastly-request-id", - "value": "1a812923feaad90809c9c7877a640b355f7a8dc5" + "value": "e3f6b1cd316c828a6d26a6c7abf4eacabcd7427c" }, { "name": "x-frame-options", @@ -112,29 +112,29 @@ }, { "name": "x-github-request-id", - "value": "317B:3663E4:D636E:EF3FF:685E7B4C" + "value": "C776:1DBBBF:159D488:18A1D41:68945A7A" }, { "name": "x-served-by", - "value": "cache-lis1490022-LIS" + "value": "cache-lis1490045-LIS" }, { "name": "x-timer", - "value": "S1751022480.239594,VS0,VE1" + "value": "S1754552962.188191,VS0,VE191" }, { "name": "x-xss-protection", "value": "1; mode=block" } ], - "headersSize": 873, + "headersSize": 878, "httpVersion": "HTTP/1.1", "redirectURL": "", "status": 200, "statusText": "OK" }, - "startedDateTime": "2025-06-27T11:08:00.063Z", - "time": 178, + "startedDateTime": "2025-08-07T07:49:22.095Z", + "time": 396, "timings": { "blocked": -1, "connect": -1, @@ -142,29 +142,29 @@ "receive": 0, "send": 0, "ssl": -1, - "wait": 178 + "wait": 396 } }, { - "_id": "26b4c877aae0bbdbc9889671caf26f73", + "_id": "4c7b0fb73c46c7315d57cbb41752f90c", "_order": 0, "cache": {}, "request": { "bodySize": 0, "cookies": [], "headers": [], - "headersSize": 147, + "headersSize": 146, "httpVersion": "HTTP/1.1", "method": "GET", "queryString": [], - "url": "https://gist.githubusercontent.com/roll/ba1c358f1daa994f8094633669d60f50/raw/03e0e54f9d4df7ff08b0d0db937fe5d720d8dfe6/table2.csv" + "url": "https://gist.githubusercontent.com/roll/d20416f5e6dfc3fc1a7c4eef8452d581/raw/1c9cd1a020389921bf83e5a0395bb00c6b27402d/tabl1.csv" }, "response": { - "bodySize": 8, + "bodySize": 29, "content": { "mimeType": "text/plain; charset=utf-8", - "size": 8, - "text": "3,german" + "size": 29, + "text": "id,name\n1,english\n2,中国人" }, "cookies": [], "headers": [ @@ -186,7 +186,7 @@ }, { "name": "content-length", - "value": "8" + "value": "29" }, { "name": "content-security-policy", @@ -202,19 +202,19 @@ }, { "name": "date", - "value": "Fri, 27 Jun 2025 11:08:00 GMT" + "value": "Thu, 07 Aug 2025 07:49:22 GMT" }, { "name": "etag", - "value": "W/\"5b8bd499e42ca79dc52ec0b203194d24d475f240c0b8ff6e0aab54d5798e008a\"" + "value": "W/\"7e7cf438cb55bf28aa7f609346bfa9dc9efadbcfe2c8e2ea5c7d093632951d62\"" }, { "name": "expires", - "value": "Fri, 27 Jun 2025 11:13:00 GMT" + "value": "Thu, 07 Aug 2025 07:54:22 GMT" }, { "name": "source-age", - "value": "9" + "value": "0" }, { "name": "strict-transport-security", @@ -230,11 +230,11 @@ }, { "name": "x-cache", - "value": "HIT" + "value": "MISS" }, { "name": "x-cache-hits", - "value": "1" + "value": "0" }, { "name": "x-content-type-options", @@ -242,7 +242,7 @@ }, { "name": "x-fastly-request-id", - "value": "a9c8e4b9a305628ef72ef83689b4b8140501b803" + "value": "b119a2897ff927f7e523c0d19c3bd2e598e02caa" }, { "name": "x-frame-options", @@ -250,29 +250,29 @@ }, { "name": "x-github-request-id", - "value": "89C9:33FD66:D620E:EF85E:685E7B85" + "value": "DEC0:24DBEA:15E02C0:193FD98:68945A7D" }, { "name": "x-served-by", - "value": "cache-lis1490040-LIS" + "value": "cache-lis1490046-LIS" }, { "name": "x-timer", - "value": "S1751022480.244457,VS0,VE1" + "value": "S1754552962.178760,VS0,VE204" }, { "name": "x-xss-protection", "value": "1; mode=block" } ], - "headersSize": 871, + "headersSize": 879, "httpVersion": "HTTP/1.1", "redirectURL": "", "status": 200, "statusText": "OK" }, - "startedDateTime": "2025-06-27T11:08:00.063Z", - "time": 180, + "startedDateTime": "2025-08-07T07:49:22.095Z", + "time": 406, "timings": { "blocked": -1, "connect": -1, @@ -280,7 +280,7 @@ "receive": 0, "send": 0, "ssl": -1, - "wait": 180 + "wait": 406 } } ], diff --git a/csv/table/fixtures/generated/should-load-remote-file_1137408454/recording.har b/csv/table/fixtures/generated/loadCsvTable-file-variations-should-load-remote-file_4234893388/recording.har similarity index 86% rename from csv/table/fixtures/generated/should-load-remote-file_1137408454/recording.har rename to csv/table/fixtures/generated/loadCsvTable-file-variations-should-load-remote-file_4234893388/recording.har index e3adcae7..1897e489 100644 --- a/csv/table/fixtures/generated/should-load-remote-file_1137408454/recording.har +++ b/csv/table/fixtures/generated/loadCsvTable-file-variations-should-load-remote-file_4234893388/recording.har @@ -1,6 +1,6 @@ { "log": { - "_recordingName": "should load remote file", + "_recordingName": "loadCsvTable-file variations-should load remote file", "creator": { "comment": "persister:fs", "name": "Polly.JS", @@ -68,7 +68,7 @@ }, { "name": "date", - "value": "Fri, 27 Jun 2025 11:00:42 GMT" + "value": "Thu, 07 Aug 2025 07:49:21 GMT" }, { "name": "etag", @@ -76,7 +76,7 @@ }, { "name": "expires", - "value": "Fri, 27 Jun 2025 11:05:42 GMT" + "value": "Thu, 07 Aug 2025 07:54:21 GMT" }, { "name": "source-age", @@ -96,7 +96,7 @@ }, { "name": "x-cache", - "value": "HIT" + "value": "MISS" }, { "name": "x-cache-hits", @@ -108,7 +108,7 @@ }, { "name": "x-fastly-request-id", - "value": "ef6f299a2d5a3def740b8b3bf4b2014349750906" + "value": "3c3523724b8cd2b888233b8accaa910abd099969" }, { "name": "x-frame-options", @@ -116,29 +116,29 @@ }, { "name": "x-github-request-id", - "value": "574A:2F9F3:2787D:2C8BD:685E6F3A" + "value": "D0E2:1C49BB:154BB4B:18AC644:68945A7D" }, { "name": "x-served-by", - "value": "cache-lis1490037-LIS" + "value": "cache-lis1490032-LIS" }, { "name": "x-timer", - "value": "S1751022042.364693,VS0,VE181" + "value": "S1754552962.771787,VS0,VE182" }, { "name": "x-xss-protection", "value": "1; mode=block" } ], - "headersSize": 897, + "headersSize": 903, "httpVersion": "HTTP/1.1", "redirectURL": "", "status": 200, "statusText": "OK" }, - "startedDateTime": "2025-06-27T11:00:42.220Z", - "time": 321, + "startedDateTime": "2025-08-07T07:49:21.578Z", + "time": 499, "timings": { "blocked": -1, "connect": -1, @@ -146,7 +146,7 @@ "receive": 0, "send": 0, "ssl": -1, - "wait": 321 + "wait": 499 } } ], diff --git a/csv/table/index.ts b/csv/table/index.ts index 0181af2e..1286ac75 100644 --- a/csv/table/index.ts +++ b/csv/table/index.ts @@ -1,2 +1,2 @@ -export { loadCsvTable } from "./load.js" -export { saveCsvTable } from "./save.js" +export { loadCsvTable } from "./load.ts" +export { saveCsvTable } from "./save.ts" diff --git a/csv/table/load.spec.ts b/csv/table/load.spec.ts index eb811b56..0ba8bb56 100644 --- a/csv/table/load.spec.ts +++ b/csv/table/load.spec.ts @@ -1,7 +1,8 @@ +import { Buffer } from "node:buffer" import { writeTempFile } from "@dpkit/file" import { useRecording } from "@dpkit/test" import { describe, expect, it } from "vitest" -import { loadCsvTable } from "./load.js" +import { loadCsvTable } from "./load.ts" describe("loadCsvTable", () => { useRecording() diff --git a/csv/table/load.ts b/csv/table/load.ts index fda2281d..db11ee7c 100644 --- a/csv/table/load.ts +++ b/csv/table/load.ts @@ -11,18 +11,17 @@ import { Utf8, concat } from "nodejs-polars" // (consult with the Data Package Working Group) export async function loadCsvTable(resource: Partial) { + const [firstPath, ...restPaths] = await prefetchFiles(resource.path) + if (!firstPath) { + return DataFrame().lazy() + } + const dialect = typeof resource.dialect === "string" ? await loadDialect(resource.dialect) : resource.dialect - const [firstPath, ...restPaths] = await prefetchFiles(resource.path) const scanOptions = getScanOptions(resource, dialect) - - if (!firstPath) { - return DataFrame().lazy() - } - let table = scanCSV(firstPath, scanOptions) const polarsSchema = Object.fromEntries( @@ -87,6 +86,8 @@ function getScanOptions(resource: Partial, dialect?: Dialect) { return options } +// TODO: move to the table package? + async function joinHeaderRows(table: Table, dialect: Dialect) { const headerOffset = getHeaderOffset(dialect) const headerRows = getHeaderRows(dialect) diff --git a/csv/table/save.spec.ts b/csv/table/save.spec.ts index f5b28a08..691482f3 100644 --- a/csv/table/save.spec.ts +++ b/csv/table/save.spec.ts @@ -1,74 +1,70 @@ import { readFile } from "node:fs/promises" +import { getTempFilePath } from "@dpkit/file" import { DataFrame } from "nodejs-polars" -import { temporaryFileTask } from "tempy" import { describe, expect, it } from "vitest" -import { saveCsvTable } from "./save.js" +import { saveCsvTable } from "./save.ts" describe("saveCsvTable", () => { - it("should save table to CSV file", async () => { - await temporaryFileTask(async path => { - const table = DataFrame({ - id: [1.0, 2.0, 3.0], - name: ["Alice", "Bob", "Charlie"], - }).lazy() + it("should save table to file", async () => { + const path = getTempFilePath() + const table = DataFrame({ + id: [1.0, 2.0, 3.0], + name: ["Alice", "Bob", "Charlie"], + }).lazy() - await saveCsvTable(table, { path }) + await saveCsvTable(table, { path }) - const content = await readFile(path, "utf-8") - expect(content).toEqual("id,name\n1.0,Alice\n2.0,Bob\n3.0,Charlie\n") - }) + const content = await readFile(path, "utf-8") + expect(content).toEqual("id,name\n1.0,Alice\n2.0,Bob\n3.0,Charlie\n") }) it("should save with custom delimiter", async () => { - await temporaryFileTask(async path => { - const table = DataFrame({ - id: [1.0, 2.0, 3.0], - name: ["Alice", "Bob", "Charlie"], - }).lazy() - - await saveCsvTable(table, { - path, - dialect: { delimiter: ";" }, - }) + const path = getTempFilePath() + const table = DataFrame({ + id: [1.0, 2.0, 3.0], + name: ["Alice", "Bob", "Charlie"], + }).lazy() - const content = await readFile(path, "utf-8") - expect(content).toEqual("id;name\n1.0;Alice\n2.0;Bob\n3.0;Charlie\n") + await saveCsvTable(table, { + path, + dialect: { delimiter: ";" }, }) + + const content = await readFile(path, "utf-8") + expect(content).toEqual("id;name\n1.0;Alice\n2.0;Bob\n3.0;Charlie\n") }) it("should save without header", async () => { - await temporaryFileTask(async path => { - const table = DataFrame({ - id: [1.0, 2.0, 3.0], - name: ["Alice", "Bob", "Charlie"], - }).lazy() - - await saveCsvTable(table, { - path, - dialect: { header: false }, - }) + const path = getTempFilePath() + const table = DataFrame({ + id: [1.0, 2.0, 3.0], + name: ["Alice", "Bob", "Charlie"], + }).lazy() - const content = await readFile(path, "utf-8") - expect(content).toEqual("1.0,Alice\n2.0,Bob\n3.0,Charlie\n") + await saveCsvTable(table, { + path, + dialect: { header: false }, }) + + const content = await readFile(path, "utf-8") + expect(content).toEqual("1.0,Alice\n2.0,Bob\n3.0,Charlie\n") }) it("should save with custom quote char", async () => { - await temporaryFileTask(async path => { - const table = DataFrame({ - id: [1.0, 2.0, 3.0], - name: ["Alice,Smith", "Bob,Jones", "Charlie,Brown"], - }).lazy() - - await saveCsvTable(table, { - path, - dialect: { quoteChar: "'" }, - }) + const path = getTempFilePath() + const table = DataFrame({ + id: [1.0, 2.0, 3.0], + name: ["Alice,Smith", "Bob,Jones", "Charlie,Brown"], + }).lazy() - const content = await readFile(path, "utf-8") - expect(content).toEqual( - "id,name\n1.0,'Alice,Smith'\n2.0,'Bob,Jones'\n3.0,'Charlie,Brown'\n", - ) + await saveCsvTable(table, { + path, + dialect: { quoteChar: "'" }, }) + + const content = await readFile(path, "utf-8") + expect(content).toEqual( + "id,name\n1.0,'Alice,Smith'\n2.0,'Bob,Jones'\n3.0,'Charlie,Brown'\n", + ) }) }) diff --git a/csv/table/save.ts b/csv/table/save.ts index 12ab6377..bc2bdbb9 100644 --- a/csv/table/save.ts +++ b/csv/table/save.ts @@ -1,15 +1,17 @@ import type { SaveTableOptions, Table } from "@dpkit/table" -// TODO: so currently, nodejs-polars uses sync sink/write functions?? - export async function saveCsvTable(table: Table, options: SaveTableOptions) { - table.sinkCSV(options?.path, { - maintainOrder: true, - includeHeader: options?.dialect?.header ?? true, - separator: options?.dialect?.delimiter ?? ",", - //lineTerminator: options?.dialect?.lineTerminator ?? "\r\n", - quoteChar: options?.dialect?.quoteChar ?? '"', - }) + const { path } = options + + await table + .sinkCSV(path, { + maintainOrder: true, + includeHeader: options.dialect?.header ?? true, + separator: options.dialect?.delimiter ?? ",", + //lineTerminator: options.dialect?.lineTerminator ?? "\r\n", + quoteChar: options.dialect?.quoteChar ?? '"', + }) + .collect() - return options.path + return path } diff --git a/csv/tsconfig.json b/csv/tsconfig.json index 7be40230..3c43903c 100644 --- a/csv/tsconfig.json +++ b/csv/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/csv/typedoc.json b/csv/typedoc.json index fc33b815..f8e49f3a 100644 --- a/csv/typedoc.json +++ b/csv/typedoc.json @@ -1,5 +1,4 @@ { "entryPoints": ["index.ts"], - "projectDocuments": ["CHANGELOG.md", "OVERVIEW.md"], "skipErrorChecking": true } diff --git a/datahub/OVERVIEW.md b/datahub/OVERVIEW.md deleted file mode 100644 index 340e14b6..00000000 --- a/datahub/OVERVIEW.md +++ /dev/null @@ -1,6 +0,0 @@ -# @dpkit/datahub - -:::note -This overview is under development. -::: - diff --git a/datahub/index.ts b/datahub/index.ts index af05c222..8e03d380 100644 --- a/datahub/index.ts +++ b/datahub/index.ts @@ -1,2 +1,2 @@ -export * from "./package/index.js" -export * from "./plugin.js" +export * from "./package/index.ts" +export * from "./plugin.ts" diff --git a/datahub/package.json b/datahub/package.json index 63e0fd1b..3cea5813 100644 --- a/datahub/package.json +++ b/datahub/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/datahub", "type": "module", - "main": "build/index.js", "version": "0.7.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,7 +20,7 @@ "datahub" ], "scripts": { - "build": "tsc --build" + "build": "tsc" }, "dependencies": { "@dpkit/core": "workspace:*" diff --git a/datahub/package/fixtures/generated/load.spec.ts.snap b/datahub/package/fixtures/generated/load.spec.ts.snap deleted file mode 100644 index 0bce5116..00000000 --- a/datahub/package/fixtures/generated/load.spec.ts.snap +++ /dev/null @@ -1,78 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`loadPackageFromDatahub > should load a package 1`] = ` -{ - "$schema": undefined, - "collection": "air-pollution", - "description": "Data about the EU emission trading system (ETS). The EU emission trading system (ETS) is one of the main measures introduced by the EU to achieve cost-efficient reductions of greenhouse gas emissions and reach its targets under the Kyoto Protocol and other commitments. The data mainly comes from the EU Transaction Log (EUTL). ", - "homepage": "http://www.eea.europa.eu/data-and-maps/data/european-union-emissions-trading-scheme-eu-ets-data-from-citl-7/", - "licenses": [ - { - "name": "ODC-PDDL-1.0", - "path": "http://opendatacommons.org/licenses/pddl/", - "title": "Open Data Commons Public Domain Dedication and License v1.0", - }, - ], - "name": "eu-emissions-trading-system", - "resources": [ - { - "$schema": undefined, - "format": "csv", - "mediatype": "text/csv", - "name": "eu-ets", - "path": "https://datahub.io/core/eu-emissions-trading-system/data/eu-ets.csv", - "schema": { - "$schema": undefined, - "descriptor": { - "fields": [ - { - "description": "International Country Code (ISO 3166-1-Alpha-2 code elements)", - "name": "country_code", - "type": "string", - }, - { - "description": "Country name", - "name": "country", - "type": "string", - }, - { - "description": "Main activity label", - "name": "main activity sector name", - "type": "string", - }, - { - "description": "ETS information", - "name": "ETS information", - "type": "string", - }, - { - "description": "Annual data mainly in YYYY format, but also may include stings Eg: Total 1st trading period (05-07)", - "name": "year", - "type": "string", - }, - { - "description": "measure value", - "name": "value", - "type": "number", - }, - { - "description": "Unit of the measure value (in tonne of CO2-equ.)", - "name": "unit", - "type": "string", - }, - ], - }, - }, - }, - ], - "sources": [ - { - "name": "EU ETS data", - "path": "http://www.eea.europa.eu/data-and-maps/data/european-union-emissions-trading-scheme-eu-ets-data-from-citl-7/eu-ets-data-download-latest-version/citl_v19.zip/at_download/file", - "title": "EU ETS data", - }, - ], - "title": "European Union Emissions Trading System (EU ETS) data from EUTL", - "version": "19", -} -`; diff --git a/datahub/package/fixtures/generated/should-load-a-package_2675098929/recording.har b/datahub/package/fixtures/generated/should-load-a-package_2675098929/recording.har deleted file mode 100644 index d8c1c445..00000000 --- a/datahub/package/fixtures/generated/should-load-a-package_2675098929/recording.har +++ /dev/null @@ -1,120 +0,0 @@ -{ - "log": { - "_recordingName": "should load a package", - "creator": { - "comment": "persister:fs", - "name": "Polly.JS", - "version": "6.0.6" - }, - "entries": [ - { - "_id": "112b2b5082e12d69e05cd1b01899c663", - "_order": 0, - "cache": {}, - "request": { - "bodySize": 0, - "cookies": [], - "headers": [], - "headersSize": 87, - "httpVersion": "HTTP/1.1", - "method": "GET", - "queryString": [], - "url": "https://datahub.io/core/eu-emissions-trading-system/datapackage.json" - }, - "response": { - "bodySize": 2430, - "content": { - "mimeType": "application/json", - "size": 2430, - "text": "{\n \"name\": \"eu-emissions-trading-system\",\n \"title\": \"European Union Emissions Trading System (EU ETS) data from EUTL\",\n \"description\": \"Data about the EU emission trading system (ETS). The EU emission trading system (ETS) is one of the main measures introduced by the EU to achieve cost-efficient reductions of greenhouse gas emissions and reach its targets under the Kyoto Protocol and other commitments. The data mainly comes from the EU Transaction Log (EUTL). \",\n \"homepage\": \"http://www.eea.europa.eu/data-and-maps/data/european-union-emissions-trading-scheme-eu-ets-data-from-citl-7/\",\n \"version\": \"19\",\n \"licenses\": [\n {\n \"name\": \"ODC-PDDL-1.0\",\n \"path\": \"http://opendatacommons.org/licenses/pddl/\",\n \"title\": \"Open Data Commons Public Domain Dedication and License v1.0\"\n }\n ],\n \"sources\": [\n {\n \"name\": \"EU ETS data\",\n \"path\": \"http://www.eea.europa.eu/data-and-maps/data/european-union-emissions-trading-scheme-eu-ets-data-from-citl-7/eu-ets-data-download-latest-version/citl_v19.zip/at_download/file\",\n \"title\": \"EU ETS data\"\n }\n ],\n \"resources\": [\n {\n \"name\": \"eu-ets\",\n \"path\": \"data/eu-ets.csv\",\n \"format\": \"csv\",\n \"mediatype\": \"text/csv\",\n \"schema\": {\n \"fields\": [\n {\n \"name\": \"country_code\",\n \"type\": \"string\",\n \"description\": \"International Country Code (ISO 3166-1-Alpha-2 code elements)\"\n },\n {\n \"name\": \"country\",\n \"type\": \"string\",\n \"description\": \"Country name\"\n },\n {\n \"name\": \"main activity sector name\",\n \"type\": \"string\",\n \"description\": \"Main activity label\"\n },\n {\n \"name\": \"ETS information\",\n \"type\": \"string\",\n \"description\": \"ETS information\"\n },\n {\n \"name\": \"year\",\n \"type\": \"string\",\n \"description\": \"Annual data mainly in YYYY format, but also may include stings Eg: Total 1st trading period (05-07)\"\n },\n {\n \"name\": \"value\",\n \"type\": \"number\",\n \"description\": \"measure value\"\n },\n {\n \"name\": \"unit\",\n \"type\": \"string\",\n \"description\": \"Unit of the measure value (in tonne of CO2-equ.)\"\n }\n ]\n }\n }\n ],\n \"collection\": \"air-pollution\"\n}" - }, - "cookies": [], - "headers": [ - { - "name": "alt-svc", - "value": "h3=\":443\"; ma=86400" - }, - { - "name": "cache-control", - "value": "no-cache" - }, - { - "name": "cf-cache-status", - "value": "DYNAMIC" - }, - { - "name": "cf-ray", - "value": "94da27d18aa4f767-MAD" - }, - { - "name": "connection", - "value": "keep-alive" - }, - { - "name": "content-encoding", - "value": "br" - }, - { - "name": "content-type", - "value": "application/json" - }, - { - "name": "date", - "value": "Tue, 10 Jun 2025 16:13:21 GMT" - }, - { - "name": "etag", - "value": "W/\"ad344f81f0b1918873111810eca6be93\"" - }, - { - "name": "last-modified", - "value": "Fri, 11 Oct 2024 15:54:28 GMT" - }, - { - "name": "nel", - "value": "{\"success_fraction\":0,\"report_to\":\"cf-nel\",\"max_age\":604800}" - }, - { - "name": "report-to", - "value": "{\"endpoints\":[{\"url\":\"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=Pd3MEybKwJQbXN75Ak0GZqTkYHeYS6thN6bUsIfPk1qn8huNN97%2BTOaT5lBH%2FIOJozE56Th8UhrCv0BmIVsuSEaJQLwxn1MW41ATAeT%2BVuErcHOW8iiys%2BhS8IWxTj7Q\"}],\"group\":\"cf-nel\",\"max_age\":604800}" - }, - { - "name": "server", - "value": "cloudflare" - }, - { - "name": "server-timing", - "value": "cfL4;desc=\"?proto=TCP&rtt=48497&min_rtt=48254&rtt_var=14031&sent=5&recv=6&lost=0&retrans=0&sent_bytes=2830&recv_bytes=711&delivery_rate=84793&cwnd=252&unsent_bytes=0&cid=5978938543d4c050&ts=144&x=0\"" - }, - { - "name": "transfer-encoding", - "value": "chunked" - }, - { - "name": "vary", - "value": "Accept-Encoding" - } - ], - "headersSize": 925, - "httpVersion": "HTTP/1.1", - "redirectURL": "", - "status": 200, - "statusText": "OK" - }, - "startedDateTime": "2025-06-10T16:13:20.721Z", - "time": 908, - "timings": { - "blocked": -1, - "connect": -1, - "dns": -1, - "receive": 0, - "send": 0, - "ssl": -1, - "wait": 908 - } - } - ], - "pages": [], - "version": "1.2" - } -} diff --git a/datahub/package/index.ts b/datahub/package/index.ts index 9ed689d5..548ee727 100644 --- a/datahub/package/index.ts +++ b/datahub/package/index.ts @@ -1 +1 @@ -export { loadPackageFromDatahub } from "./load.js" +export { loadPackageFromDatahub } from "./load.ts" diff --git a/datahub/package/load.spec.ts b/datahub/package/load.spec.ts index acdf0b04..433566ec 100644 --- a/datahub/package/load.spec.ts +++ b/datahub/package/load.spec.ts @@ -1,6 +1,6 @@ import { useRecording } from "@dpkit/test" import { describe, expect, it } from "vitest" -import { loadPackageFromDatahub } from "./load.js" +import { loadPackageFromDatahub } from "./load.ts" describe.skip("loadPackageFromDatahub", () => { useRecording() diff --git a/datahub/plugin.ts b/datahub/plugin.ts index 62830240..14b0950f 100644 --- a/datahub/plugin.ts +++ b/datahub/plugin.ts @@ -1,6 +1,6 @@ import type { Plugin } from "@dpkit/core" import { isRemotePath } from "@dpkit/core" -import { loadPackageFromDatahub } from "./package/index.js" +import { loadPackageFromDatahub } from "./package/index.ts" export class DatahubPlugin implements Plugin { async loadPackage(source: string) { diff --git a/datahub/tsconfig.json b/datahub/tsconfig.json index 7be40230..3c43903c 100644 --- a/datahub/tsconfig.json +++ b/datahub/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/datahub/typedoc.json b/datahub/typedoc.json index fc33b815..f8e49f3a 100644 --- a/datahub/typedoc.json +++ b/datahub/typedoc.json @@ -1,5 +1,4 @@ { "entryPoints": ["index.ts"], - "projectDocuments": ["CHANGELOG.md", "OVERVIEW.md"], "skipErrorChecking": true } diff --git a/db/package.json b/db/package.json index 103373a1..69064351 100644 --- a/db/package.json +++ b/db/package.json @@ -1,7 +1,7 @@ { "name": "@dpkit/db", + "exports": "./build/index.js", "type": "module", - "main": "build/index.js", "version": "0.2.0", "license": "MIT", "author": "Evgeny Karev", @@ -20,6 +20,6 @@ "db" ], "scripts": { - "build": "tsc --build" + "build": "tsc" } } diff --git a/db/tsconfig.json b/db/tsconfig.json index 7be40230..3c43903c 100644 --- a/db/tsconfig.json +++ b/db/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/docs/astro.config.ts b/docs/astro.config.ts index 4d1fa973..8332cbe0 100644 --- a/docs/astro.config.ts +++ b/docs/astro.config.ts @@ -5,6 +5,7 @@ import starlightTypeDoc from "starlight-typedoc" const PACKAGES = { dpkit: "../dpkit", + "@dpkit/arrow": "../arrow", "@dpkit/camtrap": "../camtrap", "@dpkit/ckan": "../ckan", "@dpkit/core": "../core", @@ -13,6 +14,7 @@ const PACKAGES = { "@dpkit/file": "../file", "@dpkit/github": "../github", "@dpkit/inline": "../inline", + "@dpkit/parquet": "../parquet", "@dpkit/table": "../table", "@dpkit/zenodo": "../zenodo", "@dpkit/zip": "../zip", @@ -56,9 +58,9 @@ export default defineConfig({ entryPoints: generatePackageEntrypoints(), tsconfig: "../tsconfig.json", typeDoc: { entryPointStrategy: "packages", router: "structure" }, - output: "packages", + output: "reference", sidebar: { - label: "Packages", + label: "API Reference", collapsed: true, }, }), @@ -66,8 +68,9 @@ export default defineConfig({ sidebar: [ { label: "Overview", autogenerate: { directory: "overview" } }, { label: "Guides", autogenerate: { directory: "guides" } }, + { label: "Command-Line", autogenerate: { directory: "cli" } }, { - label: "Packages", + label: "API Reference", collapsed: true, items: generatePackageSidebars(), }, @@ -76,7 +79,7 @@ export default defineConfig({ { tag: "script", attrs: { - src: "https://plausible.io/js/script.js", + src: "https://plausible.io/js/script.ts", "data-domain": "dpkit.datist.io", defer: true, }, @@ -103,20 +106,6 @@ function generatePackageSidebar(props: { name: string }) { return { label: name, collapsed: true, - items: [ - { - label: "Overview", - slug: `packages/${slug}/overview`, - }, - { - label: "Changelog", - slug: `packages/${slug}/changelog`, - }, - { - label: "API Reference", - autogenerate: { directory: `packages/${slug}/index` }, - //collapsed: true, - }, - ], + autogenerate: { directory: `reference/${slug}` }, } } diff --git a/docs/content/docs/cli/commands.md b/docs/content/docs/cli/commands.md new file mode 100644 index 00000000..2df1ab49 --- /dev/null +++ b/docs/content/docs/cli/commands.md @@ -0,0 +1,58 @@ +--- +title: Commands +sidebar: + order: 2 +--- + +:::note +After instalation, the dpkit's command-line tool is available in your terminal under name `dp` +::: + +## Command categories + +The CLI commands are organized into categories named after the main objects they support: + +- package +- resource +- dialect +- schema +- table + +Each category has its own commands for example the `table` category: + +- `dp table convert` +- `dp table describe` +- `dp table explore` +- `dp table query` +- `dp table validate` + +## Working with data packages + +:::caution +This functionality is under development. +::: + +Usually non-package command support the `-p/--package` and `-r/--resource` options to specify the datapackage file path and a resource name to access an object inside a data package. + +For example, we can explore a table using this command: + +```bash +dp table explore table.csv +``` + +Or this command using an interactive mode: + +```bash +dp table explore -p datapackage.json +# it will ask you to select a resource +``` + +Or this command using both the datapackage file path and the resource name making it non-interactive similarly to the plain path-based command: + +```bash +dp table explore -p datapackage.json -r table +``` + +:::tip +When you use the `-p` option, the CLI will open any supported Data Package source including Zenodo, Ckan, and others. +::: diff --git a/docs/content/docs/cli/dialect.md b/docs/content/docs/cli/dialect.md new file mode 100644 index 00000000..027e36c4 --- /dev/null +++ b/docs/content/docs/cli/dialect.md @@ -0,0 +1,9 @@ +--- +title: Dialect +sidebar: + order: 5 +--- + +:::caution +This article is under development. +::: diff --git a/docs/content/docs/cli/installation.md b/docs/content/docs/cli/installation.md new file mode 100644 index 00000000..dd12a5eb --- /dev/null +++ b/docs/content/docs/cli/installation.md @@ -0,0 +1,21 @@ +--- +title: Installation +sidebar: + order: 1 +--- + +:::tip +CLI binary distributions are in under development. Soon you will be able to install the CLI without using Node and its package manager. +::: + +You can install the CLI using this command: + +```bash +npm install @dpkit/cli +``` + +After that you can use the CLI binary: + +```bash +dp --version +``` diff --git a/docs/content/docs/cli/package.md b/docs/content/docs/cli/package.md new file mode 100644 index 00000000..1eea7ba2 --- /dev/null +++ b/docs/content/docs/cli/package.md @@ -0,0 +1,9 @@ +--- +title: Package +sidebar: + order: 3 +--- + +:::caution +This article is under development. +::: diff --git a/docs/content/docs/cli/resource.md b/docs/content/docs/cli/resource.md new file mode 100644 index 00000000..9f66f3b9 --- /dev/null +++ b/docs/content/docs/cli/resource.md @@ -0,0 +1,9 @@ +--- +title: Resource +sidebar: + order: 4 +--- + +:::caution +This article is under development. +::: diff --git a/docs/content/docs/cli/schema.md b/docs/content/docs/cli/schema.md new file mode 100644 index 00000000..eff29a19 --- /dev/null +++ b/docs/content/docs/cli/schema.md @@ -0,0 +1,9 @@ +--- +title: Schema +sidebar: + order: 6 +--- + +:::caution +This article is under development. +::: diff --git a/docs/content/docs/cli/table.md b/docs/content/docs/cli/table.md new file mode 100644 index 00000000..95e7eaeb --- /dev/null +++ b/docs/content/docs/cli/table.md @@ -0,0 +1,9 @@ +--- +title: Table +sidebar: + order: 7 +--- + +:::caution +This article is under development. +::: diff --git a/docs/content/docs/guides/arrow.md b/docs/content/docs/guides/arrow.md new file mode 100644 index 00000000..87a6ce5d --- /dev/null +++ b/docs/content/docs/guides/arrow.md @@ -0,0 +1,39 @@ +--- +title: Working with Arrow +sidebar: + label: Arrow + order: 3 +--- + +The `@dpkit/arrow` package provides efficient support for loading and saving data in Apache Arrow format. It uses Polars DataFrames for high-performance columnar data processing. + +## Installation + +```bash +npm install @dpkit/arrow +``` + +## Basic Usage + +### Loading Data + +```typescript +import { loadArrowTable } from "@dpkit/arrow" + +// Load from local file +const table = await loadArrowTable({ path: "data.arrow" }) + +// Load multiple files (concatenated) +const table = await loadArrowTable({ + path: ["file1.arrow", "file2.arrow"] +}) +``` + +### Saving Data + +```typescript +import { saveArrowTable } from "@dpkit/arrow" + +// Save as Arrow format +await saveArrowTable(table, { path: "output.arrow" }) +``` diff --git a/docs/content/docs/guides/assets/jupyter.png b/docs/content/docs/guides/assets/jupyter.png new file mode 100644 index 00000000..5fd6bed4 Binary files /dev/null and b/docs/content/docs/guides/assets/jupyter.png differ diff --git a/csv/OVERVIEW.md b/docs/content/docs/guides/csv.md similarity index 97% rename from csv/OVERVIEW.md rename to docs/content/docs/guides/csv.md index a8128bb2..d8e4bf48 100644 --- a/csv/OVERVIEW.md +++ b/docs/content/docs/guides/csv.md @@ -1,5 +1,9 @@ -# @dpkit/csv - +--- +title: Working with CSV +sidebar: + label: CSV + order: 1 +--- Comprehensive CSV and TSV file handling with automatic format detection, advanced header processing, and high-performance data operations. ## Introduction diff --git a/docs/content/docs/guides/inline.md b/docs/content/docs/guides/inline.md new file mode 100644 index 00000000..0ed632e2 --- /dev/null +++ b/docs/content/docs/guides/inline.md @@ -0,0 +1,100 @@ +--- +title: Working with inline data +sidebar: + label: Inline data + order: 5 +--- + +Dpkit provides a package for reading inline data tables embedded directly in data package resources. + +## Array Format Data + +```typescript +import { readInlineTable } from "@dpkit/inline" + +const resource = { + name: "languages", + type: "table", + data: [ + ["id", "name"], + [1, "english"], + [2, "中文"] + ] +} + +const table = await readInlineTable(resource) +``` + +## Object Format Data + +```typescript +const resource = { + name: "languages", + type: "table", + data: [ + { id: 1, name: "english" }, + { id: 2, name: "中文" } + ] +} + +const table = await readInlineTable(resource) +``` + +## With Processing Based on Schema + +```typescript +const resource = { + name: "languages", + type: "table", + data: [ + ["id", "name"], + [1, "english"], + [2, "中文"] + ], + schema: { + fields: [ + { name: "id", type: "integer" }, + { name: "name", type: "string" } + ] + } +} + +const table = await readInlineTable(resource) +``` + +## Inline Resource Validation + +```typescript +import { validateInlineTable } from "@dpkit/inline" + +const resource = { + name: "languages", + type: "table", + data: [ + ["id", "name"], + [1, "english"], + [2, "中文"] + ], + schema: { + fields: [ + { name: "id", type: "integer" }, + { name: "name", type: "integer" } + ] + } +} + +const {valid, errors} = await validateInlineTable(resource) +//{ +// type: "cell/type", +// fieldName: "name", +// rowNumber: 1, +// cell: "english", +//} +//{ +// type: "cell/type", +// fieldName: "name", +// rowNumber: 2, +// cell: "中文", +//} +``` + diff --git a/docs/content/docs/guides/json.md b/docs/content/docs/guides/json.md new file mode 100644 index 00000000..62b1aa8b --- /dev/null +++ b/docs/content/docs/guides/json.md @@ -0,0 +1,118 @@ +--- +title: Working with JSON +sidebar: + label: JSON + order: 2 +--- + +The `@dpkit/json` package provides comprehensive support for loading and saving data in JSON and JSONL (JSON Lines) formats. It leverages Polars DataFrames for efficient data processing and supports flexible data transformations through dialect configurations. + +## Installation + +The JSON package is part of dpkit's modular architecture: + +```bash +npm install @dpkit/json +``` + +## Basic Usage + +### Loading JSON Data + +```typescript +import { loadJsonTable } from "@dpkit/json" + +// Load from local file +const table = await loadJsonTable({ path: "data.json" }) + +// Load from remote URL +const table = await loadJsonTable({ + path: "https://example.com/data.json" +}) + +// Load multiple files (concatenated) +const table = await loadJsonTable({ + path: ["file1.json", "file2.json"] +}) +``` + +### Loading JSONL Data + +```typescript +import { loadJsonlTable } from "@dpkit/json" + +// Load JSONL (JSON Lines) format +const table = await loadJsonlTable({ path: "data.jsonl" }) +``` + +### Saving Data + +```typescript +import { saveJsonTable, saveJsonlTable } from "@dpkit/json" + +// Save as JSON +await saveJsonTable(table, { path: "output.json" }) + +// Save as JSONL +await saveJsonlTable(table, { path: "output.jsonl" }) +``` + +## Data Formats + +The package supports two main JSON formats: + +### JSON Format +Standard JSON arrays of objects: +```json +[ + {"id": 1, "name": "Alice"}, + {"id": 2, "name": "Bob"} +] +``` + +### JSONL Format +Newline-delimited JSON objects: +```jsonl +{"id": 1, "name": "Alice"} +{"id": 2, "name": "Bob"} +``` + +## Dialect Support + +Dialects provide flexible data transformation capabilities: + +### Property Extraction + +Extract data from nested objects using the `property` option: + +```typescript +// Input: {"users": [{"id": 1, "name": "Alice"}]} +const table = await loadJsonTable({ + path: "data.json", + dialect: { property: "users" } +}) +``` + +### Item Keys Filtering + +Select specific fields using `itemKeys`: + +```typescript +// Only load 'name' field from each record +const table = await loadJsonTable({ + path: "data.json", + dialect: { itemKeys: ["name"] } +}) +``` + +### Array Format Handling + +Handle CSV-style array data with `itemType: "array"`: + +```typescript +// Input: [["id", "name"], [1, "Alice"], [2, "Bob"]] +const table = await loadJsonTable({ + path: "data.json", + dialect: { itemType: "array" } +}) +``` diff --git a/docs/content/docs/guides/jupyter.md b/docs/content/docs/guides/jupyter.md new file mode 100644 index 00000000..117171d6 --- /dev/null +++ b/docs/content/docs/guides/jupyter.md @@ -0,0 +1,31 @@ +--- +title: Using dpkit in Jupyter Notebooks +sidebar: + label: Jupyter Notebooks + order: 10 +--- + +For data scientists and data engineers, [Jupyter Notebooks](https://docs.jupyter.org/en/latest/) provide a powerful and flexible environment for exploring, visualizing, and analyzing data. + +## Installation + +1. **Install Jupyter:** `pip install jupyterlab` - Installs Jupyter Notebook, a web-based interactive computing environment for data science and data engineering. You can user another UI such as Jupyter CLI or Jupyter Desktop. + +1. **Install Deno:** `curl -fsSL https://deno.land/install.sh | sh` - Downloads and installs the Deno runtime required for TypeScript execution in Jupyter notebooks. Visit [Deno](https://deno.com) for official documentation. + +1. **Install Deno Jupyter Kernel:** `deno jupyter --install` - Sets up the Deno kernel for Jupyter, enabling TypeScript support within notebooks. + +1. **Activate Deno Jupyter Kernel:** `deno jupyter --unstable` - Enables the Deno kernel for Jupyter notebook usage. + +## Usage + +1. **Run Jupyter Notebooks:** `jupyter-lab` - Launches the Jupyter Notebook server in the current working directory, which allows you to create and run Jupyter notebooks. + +1. **Select Deno Kernel in Notebook:** Choose the Deno kernel from your notebook's kernel selection menu. VSCode users may need to install the default Jupyter kernel extensions. + +![dpkit in Jupyter Notebooks](./assets/jupyter.png) + +## References + +- [Typescript Jupyter Notebooks: How to set them up](https://alex-goff.medium.com/typescript-jupyter-notebooks-how-to-set-them-up-1ab9fd464ea4) +- [Bringing Modern JavaScript to the Jupyter Notebook](https://blog.jupyter.org/bringing-modern-javascript-to-the-jupyter-notebook-fc998095081e) diff --git a/docs/content/docs/guides/parquet.md b/docs/content/docs/guides/parquet.md new file mode 100644 index 00000000..36634cd1 --- /dev/null +++ b/docs/content/docs/guides/parquet.md @@ -0,0 +1,44 @@ +--- +title: Working with Parquet +sidebar: + label: Parquet + order: 4 +--- + +The `@dpkit/parquet` package provides efficient support for loading and saving data in Apache Parquet format. It uses Polars DataFrames for high-performance columnar data processing. + +## Installation + +```bash +npm install @dpkit/parquet +``` + +## Basic Usage + +### Loading Data + +```typescript +import { loadParquetTable } from "@dpkit/parquet" + +// Load from local file +const table = await loadParquetTable({ path: "data.parquet" }) + +// Load from remote URL +const table = await loadParquetTable({ + path: "https://example.com/data.parquet" +}) + +// Load multiple files (concatenated) +const table = await loadParquetTable({ + path: ["file1.parquet", "file2.parquet"] +}) +``` + +### Saving Data + +```typescript +import { saveParquetTable } from "@dpkit/parquet" + +// Save as Parquet format +await saveParquetTable(table, { path: "output.parquet" }) +``` diff --git a/docs/content/docs/guides/table.md b/docs/content/docs/guides/table.md new file mode 100644 index 00000000..a996fc20 --- /dev/null +++ b/docs/content/docs/guides/table.md @@ -0,0 +1,227 @@ +--- +title: Working with tabular data +sidebar: + label: Tabular data + order: 6 +--- + +The `@dpkit/table` package provides high-performance data validation and processing capabilities for tabular data. Built on top of **nodejs-polars** (a Rust-based DataFrame library), it offers robust schema validation, type inference, and error handling for CSV, Excel, and other tabular data formats. + +## Examples + +### Basic Table Inspection + +```typescript +import { DataFrame } from "nodejs-polars" +import { inspectTable } from "@dpkit/table" +import type { Schema } from "@dpkit/core" + +// Create a table from data +const table = DataFrame({ + id: [1, 2, 3], + name: ["John", "Jane", "Bob"], + email: ["john@example.com", "jane@example.com", "bob@example.com"] +}).lazy() + +// Define schema with constraints +const schema: Schema = { + fields: [ + { name: "id", type: "integer", constraints: { required: true, unique: true } }, + { name: "name", type: "string", constraints: { required: true } }, + { name: "email", type: "string", constraints: { pattern: "^[^@]+@[^@]+\\.[^@]+$" } } + ] +} + +// Inspect the table +const errors = await inspectTable(table, { schema }) +console.log(errors) // Array of validation errors +``` + +### Schema Inference + +```typescript +import { inferSchema } from "@dpkit/table" + +// Automatically infer schema from data patterns +const table = DataFrame({ + id: ["1", "2", "3"], + price: ["10.50", "25.00", "15.75"], + date: ["2023-01-15", "2023-02-20", "2023-03-25"], + active: ["true", "false", "true"] +}).lazy() + +const inferredSchema = await inferSchema(table, { + sampleSize: 100, // Sample size for inference + confidence: 0.9, // Confidence threshold + monthFirst: false, // Date format preference + commaDecimal: false // Decimal separator preference +}) + +// Result: automatically detected integer, number, date, and boolean types +``` + +### Field Matching Strategies + +```typescript +// Subset matching - data can have extra fields +const schema: Schema = { + fieldsMatch: "subset", + fields: [ + { name: "id", type: "number" }, + { name: "name", type: "string" } + ] +} + +// Equal matching - field names must match regardless of order +const equalSchema: Schema = { + fieldsMatch: "equal", + fields: [ + { name: "id", type: "number" }, + { name: "name", type: "string" } + ] +} +``` + +### Table Processing + +```typescript +import { processTable } from "@dpkit/table" + +// Process table with schema (converts string columns to proper types) +const table = DataFrame({ + id: ["1", "2", "3"], // String data + price: ["10.50", "25.00", "15.75"], + active: ["true", "false", "true"], + date: ["2023-01-15", "2023-02-20", "2023-03-25"] +}).lazy() + +const schema: Schema = { + fields: [ + { name: "id", type: "integer" }, + { name: "price", type: "number" }, + { name: "active", type: "boolean" }, + { name: "date", type: "date" } + ] +} + +const processedTable = await processTable(table, { schema }) +const result = await processedTable.collect() + +// Result will have properly typed columns: +// { id: 1, price: 10.50, active: true, date: Date('2023-01-15') } +// { id: 2, price: 25.00, active: false, date: Date('2023-02-20') } +// { id: 3, price: 15.75, active: true, date: Date('2023-03-25') } +``` + +### Error Handling + +```typescript +const result = await inspectTable(table, { schema }) + +result.errors.forEach(error => { + switch (error.type) { + case "cell/required": + console.log(`Required field missing in row ${error.rowNumber}: '${error.fieldName}'`) + break + case "cell/unique": + console.log(`Duplicate value in row ${error.rowNumber}: '${error.cell}'`) + break + case "cell/pattern": + console.log(`Pattern mismatch: '${error.cell}' doesn't match ${error.constraint}`) + break + } +}) +``` + +## Core Architecture + +### Table Type +The package uses `LazyDataFrame` from nodejs-polars as its core table representation, enabling lazy evaluation and efficient processing of large datasets through vectorized operations. + +### Schema Integration +Integrates seamlessly with `@dpkit/core` schemas, bridging Data Package field definitions with Polars data types for comprehensive validation workflows. + +## Key Features + +### 1. Multi-Level Validation System + +**Field-Level Validation:** +- **Type Validation**: Converts and validates data types (string → integer, etc.) +- **Name Validation**: Ensures field names match schema requirements +- **Constraint Validation**: Enforces required, unique, enum, pattern, min/max values, and length constraints + +**Table-Level Validation:** +- **Field Presence**: Validates missing/extra fields based on flexible matching strategies +- **Schema Compatibility**: Ensures data structure aligns with schema definitions + +**Row-Level Validation:** +- **Primary Key Uniqueness**: Validates unique identifiers +- **Composite Keys**: Supports multi-column unique constraints + +### 2. Comprehensive Field Types + +**Primitive Types:** +- `string`, `integer`, `number`, `boolean` + +**Temporal Types:** +- `date`, `datetime`, `time`, `year`, `yearmonth`, `duration` + +**Spatial Types:** +- `geopoint`, `geojson` + +**Complex Types:** +- `array`, `list`, `object` + +### 3. Smart Schema Inference + +Automatically infers field types and formats from data using: +- Regex pattern matching with configurable confidence thresholds +- Locale-specific format detection (comma decimals, date formats) +- Complex type recognition (objects, arrays, temporal data) + +### 4. Flexible Field Matching Strategies + +- **exact**: Fields must match exactly in order and count +- **equal**: Same fields in any order +- **subset**: Data must contain all schema fields (extras allowed) +- **superset**: Schema must contain all data fields +- **partial**: At least one field must match + +### 5. Advanced Data Processing + +**Format-Aware Parsing:** +- Handles missing values at schema and field levels +- Supports group/decimal character customization +- Processes currency symbols and whitespace +- Parses complex formats (ISO dates, scientific notation) + +**Performance Optimizations:** +- Sample-based validation for large datasets +- Lazy evaluation for memory efficiency +- Vectorized constraint checking +- Configurable error limits and batch processing + +## Error Handling + +### Comprehensive Error Taxonomy + +**Field Errors:** +- Name mismatches between schema and data +- Type conversion failures +- Missing or extra field violations + +**Cell Errors:** +- Type validation failures with specific conversion details +- Constraint violations (required, unique, enum, pattern, range, length) +- Format parsing errors with problematic values + +**Row Errors:** +- Unique key constraint violations +- Composite constraint failures + +### Error Details +Each error includes: +- Precise row and column locations +- Actual vs expected values +- Specific error type classification +- Actionable error messages for debugging diff --git a/docs/content/docs/guides/validation.md b/docs/content/docs/guides/validation.md deleted file mode 100644 index beea8e8a..00000000 --- a/docs/content/docs/guides/validation.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Validation ---- - -:::note -This guide is under development. -::: - - diff --git a/docs/content/docs/overview/changelog.md b/docs/content/docs/overview/changelog.md new file mode 120000 index 00000000..eedd1ec2 --- /dev/null +++ b/docs/content/docs/overview/changelog.md @@ -0,0 +1 @@ +../../../../dpkit/CHANGELOG.md \ No newline at end of file diff --git a/docs/content/docs/overview/getting-started.md b/docs/content/docs/overview/getting-started.md index 8883afc4..81d997fe 100644 --- a/docs/content/docs/overview/getting-started.md +++ b/docs/content/docs/overview/getting-started.md @@ -6,11 +6,29 @@ sidebar: This guide will help you get started with dpkit. If you are new to the core framework's tecnhologies, please take a look at the [Data Package standard](https://datapackage.org/) and [Polars DataFrames](https://pola.rs/) documentation. +## Runtimes + +:::tip +- It is possible to use dpkit in [Jupyter Notebooks](/guides/jupyter)! +::: + +dpkit and all its packages support all the prominent TypeScript runtimes: + +- **Node.js v22+** +- **Deno v2+** +- **Bun v1+** + +The core package `@dpkit/core` additionally supports browser environments: + +- **Edge v92+** +- **Chrome v92+** +- **Firefox v90+** +- and others ## Installation -:::note[Prerequisites] -- **Node.js v20+** +:::note +The documentation uses `npm` command to install packages. If you are using other package managers, please adjust the commands accordingly. ::: The framework can be installed as one package: @@ -25,6 +43,12 @@ Or cherry-picked from individual packages: npm install @dpkit/core @dpkit/zenodo ``` +Or the core package can be just imported in browsers using NPM CDNs: + +```js +import { loadPackageDescriptor } from "https://esm.sh/@dpkit/core" +``` + ## TypeScript :::tip @@ -95,18 +119,17 @@ import { loadPackageDescriptor, loadPackageFromZip, savePackageToZip, + getTempFilePath, } from "dpkit" -import { temporaryFileTask } from "tempy" -const sourcePackage = await loadPackageDescriptor( +const archivePath = getTempFilePath() +const sourcePath = await loadPackageDescriptor( "https://raw.githubusercontent.com/roll/currency-codes/refs/heads/master/datapackage.json", ) -await temporaryFileTask(async archivePath => { - await savePackageToZip(sourcePackage, { archivePath }) - const targetPackage = await loadPackageFromZip(archivePath) - console.log(targetPackage) -}) +await savePackageToZip(sourcePackage, { archivePath }) +const targetPackage = await loadPackageFromZip(archivePath) +console.log(targetPackage) ``` Reading a CSV table: diff --git a/docs/examples/getting-started-1.ts b/docs/examples/getting-started-1.ts index fc0cc58e..0dad7fb8 100644 --- a/docs/examples/getting-started-1.ts +++ b/docs/examples/getting-started-1.ts @@ -1,5 +1,5 @@ import { loadPackage } from "dpkit" -const { dataPackage } = await loadPackage("https://zenodo.org/records/10053903") +const dataPackage = await loadPackage("https://zenodo.org/records/10053903") console.log(dataPackage) diff --git a/docs/examples/getting-started-2.ts b/docs/examples/getting-started-2.ts index 2f931c23..e921ec92 100644 --- a/docs/examples/getting-started-2.ts +++ b/docs/examples/getting-started-2.ts @@ -1,6 +1,6 @@ import { assertCamtrapPackage, loadPackage } from "dpkit" -const { dataPackage } = await loadPackage( +const dataPackage = await loadPackage( "https://raw.githubusercontent.com/tdwg/camtrap-dp/refs/tags/1.0.1/example/datapackage.json", ) diff --git a/docs/examples/getting-started-4.ts b/docs/examples/getting-started-4.ts index fd7896b0..e4a255cd 100644 --- a/docs/examples/getting-started-4.ts +++ b/docs/examples/getting-started-4.ts @@ -1,16 +1,15 @@ import { + getTempFilePath, loadPackageDescriptor, loadPackageFromZip, savePackageToZip, } from "dpkit" -import { temporaryFileTask } from "tempy" +const archivePath = getTempFilePath() const sourcePackage = await loadPackageDescriptor( "https://raw.githubusercontent.com/roll/currency-codes/refs/heads/master/datapackage.json", ) -await temporaryFileTask(async archivePath => { - await savePackageToZip(sourcePackage, { archivePath }) - const targetPackage = await loadPackageFromZip(archivePath) - console.log(targetPackage) -}) +await savePackageToZip(sourcePackage, { archivePath }) +const targetPackage = await loadPackageFromZip(archivePath) +console.log(targetPackage) diff --git a/docs/package.json b/docs/package.json index 91d8bfb9..22721e3a 100644 --- a/docs/package.json +++ b/docs/package.json @@ -7,18 +7,16 @@ "preview": "astro preview", "start": "astro dev" }, - "dependencies": { + "devDependencies": { "@astrojs/starlight": "0.34.3", "astro": "5.7.12", "dpkit": "workspace:*", "sharp": "0.34.2", "starlight-scroll-to-top": "0.1.1", "starlight-typedoc": "0.21.3", - "typedoc": "0.28.5", - "typedoc-plugin-markdown": "4.6.3" - }, - "devDependencies": { - "nodejs-polars": "^0.18.0", + "typedoc": "0.28.9", + "typedoc-plugin-markdown": "4.8.0", + "nodejs-polars": "0.21.0", "tempy": "3.1.0" } } diff --git a/dpkit/CHANGELOG.md b/dpkit/CHANGELOG.md index e43a0da4..f1a84089 100644 --- a/dpkit/CHANGELOG.md +++ b/dpkit/CHANGELOG.md @@ -1,3 +1,7 @@ +--- +title: Changelog +--- + # dpkit ## 0.5.0 diff --git a/dpkit/OVERVIEW.md b/dpkit/OVERVIEW.md deleted file mode 100644 index 7a052227..00000000 --- a/dpkit/OVERVIEW.md +++ /dev/null @@ -1,6 +0,0 @@ -# dpkit - -:::note -This overview is under development. -::: - diff --git a/dpkit/dialect/index.ts b/dpkit/dialect/index.ts index dd7102da..2650dc4e 100644 --- a/dpkit/dialect/index.ts +++ b/dpkit/dialect/index.ts @@ -1 +1 @@ -export { inferDialect } from "./infer.js" +export { inferDialect } from "./infer.ts" diff --git a/dpkit/dialect/infer.ts b/dpkit/dialect/infer.ts index 06bbd9a3..c37b8087 100644 --- a/dpkit/dialect/infer.ts +++ b/dpkit/dialect/infer.ts @@ -1,6 +1,6 @@ import type { Dialect, Resource } from "@dpkit/core" import type { InferDialectOptions } from "@dpkit/table" -import { dpkit } from "../plugin.js" +import { dpkit } from "../plugin.ts" // TODO: implement inferDialect diff --git a/dpkit/index.ts b/dpkit/index.ts index 273b0d2b..a28b8c61 100644 --- a/dpkit/index.ts +++ b/dpkit/index.ts @@ -11,7 +11,7 @@ export * from "@dpkit/table" export * from "@dpkit/zenodo" export * from "@dpkit/zip" -export * from "./dialect/index.js" -export * from "./package/index.js" -export * from "./table/index.js" -export * from "./plugin.js" +export * from "./dialect/index.ts" +export * from "./package/index.ts" +export * from "./table/index.ts" +export * from "./plugin.ts" diff --git a/dpkit/package.json b/dpkit/package.json index 26d2e621..ac58137f 100644 --- a/dpkit/package.json +++ b/dpkit/package.json @@ -1,8 +1,8 @@ { "name": "dpkit", "type": "module", - "main": "build/index.js", "version": "0.5.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,6 +20,7 @@ "cli" ], "dependencies": { + "@dpkit/arrow": "workspace:*", "@dpkit/camtrap": "workspace:*", "@dpkit/ckan": "workspace:*", "@dpkit/csv": "workspace:*", @@ -29,11 +30,13 @@ "@dpkit/folder": "workspace:*", "@dpkit/github": "workspace:*", "@dpkit/inline": "workspace:*", + "@dpkit/json": "workspace:*", + "@dpkit/parquet": "workspace:*", "@dpkit/table": "workspace:*", "@dpkit/zenodo": "workspace:*", "@dpkit/zip": "workspace:*" }, "scripts": { - "build": "tsc --build" + "build": "tsc" } } diff --git a/dpkit/package/index.ts b/dpkit/package/index.ts index 31a45bc9..3a5cbd54 100644 --- a/dpkit/package/index.ts +++ b/dpkit/package/index.ts @@ -1,2 +1,2 @@ -export { loadPackage } from "./load.js" -export { savePackage } from "./save.js" +export { loadPackage } from "./load.ts" +export { savePackage } from "./save.ts" diff --git a/dpkit/package/load.ts b/dpkit/package/load.ts index 43d70e6e..bfa090fe 100644 --- a/dpkit/package/load.ts +++ b/dpkit/package/load.ts @@ -1,5 +1,5 @@ import { loadPackageDescriptor } from "@dpkit/core" -import { dpkit } from "../plugin.js" +import { dpkit } from "../plugin.ts" export async function loadPackage(source: string) { for (const plugin of dpkit.plugins) { @@ -7,10 +7,6 @@ export async function loadPackage(source: string) { if (result) return result } - if (source.endsWith("datapackage.json")) { - const dataPackage = await loadPackageDescriptor(source) - return dataPackage - } - - throw new Error(`No plugin can load the package: ${source}`) + const dataPackage = await loadPackageDescriptor(source) + return dataPackage } diff --git a/dpkit/package/save.ts b/dpkit/package/save.ts index 7b78c1fc..bab6ec6e 100644 --- a/dpkit/package/save.ts +++ b/dpkit/package/save.ts @@ -1,6 +1,6 @@ import type { Package } from "@dpkit/core" import { savePackageDescriptor } from "@dpkit/core" -import { dpkit } from "../plugin.js" +import { dpkit } from "../plugin.ts" export async function savePackage( dataPackage: Package, diff --git a/dpkit/plugin.ts b/dpkit/plugin.ts index 7d6a4226..43ab813a 100644 --- a/dpkit/plugin.ts +++ b/dpkit/plugin.ts @@ -1,9 +1,12 @@ +import { ArrowPlugin } from "@dpkit/arrow" import { CkanPlugin } from "@dpkit/ckan" import { CsvPlugin } from "@dpkit/csv" import { DatahubPlugin } from "@dpkit/datahub" import { FolderPlugin } from "@dpkit/folder" import { GithubPlugin } from "@dpkit/github" import { InlinePlugin } from "@dpkit/inline" +import { JsonPlugin } from "@dpkit/json" +import { ParquetPlugin } from "@dpkit/parquet" import type { TablePlugin } from "@dpkit/table" import { ZenodoPlugin } from "@dpkit/zenodo" import { ZipPlugin } from "@dpkit/zip" @@ -27,5 +30,8 @@ dpkit.register(FolderPlugin) dpkit.register(ZipPlugin) // Table functions +dpkit.register(ArrowPlugin) dpkit.register(CsvPlugin) +dpkit.register(JsonPlugin) dpkit.register(InlinePlugin) +dpkit.register(ParquetPlugin) diff --git a/dpkit/table/index.ts b/dpkit/table/index.ts index 7ac79642..09df76ca 100644 --- a/dpkit/table/index.ts +++ b/dpkit/table/index.ts @@ -1,4 +1,4 @@ -export { loadTable } from "./load.js" -export { readTable } from "./read.js" -export { saveTable } from "./save.js" -export { validateTable } from "./validate.js" +export { loadTable } from "./load.ts" +export { readTable } from "./read.ts" +export { saveTable } from "./save.ts" +export { validateTable } from "./validate.ts" diff --git a/dpkit/table/infer.ts b/dpkit/table/infer.ts index 0f52f101..49213a03 100644 --- a/dpkit/table/infer.ts +++ b/dpkit/table/infer.ts @@ -2,8 +2,8 @@ import type { Dialect, Resource, Schema } from "@dpkit/core" import { loadDialect, loadSchema } from "@dpkit/core" import type { Table } from "@dpkit/table" import { inferSchema } from "@dpkit/table" -import { inferDialect } from "../dialect/index.js" -import { loadTable } from "./load.js" +import { inferDialect } from "../dialect/index.ts" +import { loadTable } from "./load.ts" export async function inferTable( resource: Partial, diff --git a/dpkit/table/load.ts b/dpkit/table/load.ts index 5e1c1d62..2674f30d 100644 --- a/dpkit/table/load.ts +++ b/dpkit/table/load.ts @@ -1,6 +1,6 @@ import type { Resource } from "@dpkit/core" import type { Table } from "@dpkit/table" -import { dpkit } from "../plugin.js" +import { dpkit } from "../plugin.ts" export async function loadTable(resource: Partial): Promise { for (const plugin of dpkit.plugins) { diff --git a/dpkit/table/read.ts b/dpkit/table/read.ts index c26ef2e2..3d8c0550 100644 --- a/dpkit/table/read.ts +++ b/dpkit/table/read.ts @@ -1,7 +1,7 @@ import type { Resource } from "@dpkit/core" import type { Table } from "@dpkit/table" import { processTable } from "@dpkit/table" -import { inferTable } from "./infer.js" +import { inferTable } from "./infer.ts" export async function readTable(resource: Partial): Promise
{ const { table, schema } = await inferTable(resource) diff --git a/dpkit/table/save.ts b/dpkit/table/save.ts index 8fe7de63..204ed4ec 100644 --- a/dpkit/table/save.ts +++ b/dpkit/table/save.ts @@ -1,5 +1,5 @@ import type { SaveTableOptions, Table } from "@dpkit/table" -import { dpkit } from "../plugin.js" +import { dpkit } from "../plugin.ts" export async function saveTable(table: Table, options: SaveTableOptions) { for (const plugin of dpkit.plugins) { diff --git a/dpkit/table/validate.ts b/dpkit/table/validate.ts index 3714fab0..53589a2a 100644 --- a/dpkit/table/validate.ts +++ b/dpkit/table/validate.ts @@ -1,6 +1,6 @@ import type { Resource } from "@dpkit/core" import { inspectTable } from "@dpkit/table" -import { inferTable } from "./infer.js" +import { inferTable } from "./infer.ts" export async function validateTable(resource: Partial) { const { table, schema } = await inferTable(resource) diff --git a/dpkit/tsconfig.json b/dpkit/tsconfig.json index 7be40230..3c43903c 100644 --- a/dpkit/tsconfig.json +++ b/dpkit/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/dpkit/typedoc.json b/dpkit/typedoc.json index fc33b815..f8e49f3a 100644 --- a/dpkit/typedoc.json +++ b/dpkit/typedoc.json @@ -1,5 +1,4 @@ { "entryPoints": ["index.ts"], - "projectDocuments": ["CHANGELOG.md", "OVERVIEW.md"], "skipErrorChecking": true } diff --git a/excel/package.json b/excel/package.json index 13a73607..c69b35d3 100644 --- a/excel/package.json +++ b/excel/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/excel", "type": "module", - "main": "build/index.js", "version": "0.2.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,6 +20,6 @@ "excel" ], "scripts": { - "build": "tsc --build" + "build": "tsc" } } diff --git a/excel/tsconfig.json b/excel/tsconfig.json index 7be40230..3c43903c 100644 --- a/excel/tsconfig.json +++ b/excel/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/extend/package.json b/extend/package.json index 077f7acd..1168970e 100644 --- a/extend/package.json +++ b/extend/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/extend", "type": "module", - "main": "build/index.js", "version": "0.2.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,6 +20,6 @@ "extend" ], "scripts": { - "build": "tsc --build" + "build": "tsc" } } diff --git a/extend/tsconfig.json b/extend/tsconfig.json index 7be40230..3c43903c 100644 --- a/extend/tsconfig.json +++ b/extend/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/file/OVERVIEW.md b/file/OVERVIEW.md deleted file mode 100644 index 0f9cc6b6..00000000 --- a/file/OVERVIEW.md +++ /dev/null @@ -1,6 +0,0 @@ -# @dpkit/file - -:::note -This overview is under development. -::: - diff --git a/file/file/copy.ts b/file/file/copy.ts new file mode 100644 index 00000000..ceae3fd7 --- /dev/null +++ b/file/file/copy.ts @@ -0,0 +1,10 @@ +import { loadFileStream } from "../stream/load.ts" +import { saveFileStream } from "../stream/save.ts" + +export async function copyFile(options: { + sourcePath: string + targetPath: string +}) { + const stream = await loadFileStream(options.sourcePath) + await saveFileStream(stream, { path: options.targetPath }) +} diff --git a/file/file/fetch.ts b/file/file/fetch.ts index 1aa85834..87616634 100644 --- a/file/file/fetch.ts +++ b/file/file/fetch.ts @@ -1,6 +1,6 @@ import { isRemotePath } from "@dpkit/core" -import { saveFileToDisc } from "./save.js" -import { getTempFilePath } from "./temp.js" +import { copyFile } from "./copy.ts" +import { getTempFilePath } from "./temp.ts" export async function prefetchFiles(path?: string | string[]) { if (!path) return [] @@ -12,6 +12,6 @@ export async function prefetchFiles(path?: string | string[]) { export async function prefetchFile(path: string) { if (!isRemotePath(path)) return path const newPath = getTempFilePath() - await saveFileToDisc({ sourcePath: path, targetPath: newPath }) + await copyFile({ sourcePath: path, targetPath: newPath }) return newPath } diff --git a/file/file/index.ts b/file/file/index.ts index 05ed5664..da2aea7a 100644 --- a/file/file/index.ts +++ b/file/file/index.ts @@ -1,4 +1,6 @@ -export { saveFileToDisc } from "./save.js" -export { getTempFilePath, writeTempFile } from "./temp.js" -export { assertLocalPathVacant, isLocalPathExist } from "./path.js" -export { prefetchFile, prefetchFiles } from "./fetch.js" +export { loadFile } from "./load.ts" +export { copyFile } from "./copy.ts" +export { saveFile } from "./save.ts" +export { getTempFilePath, writeTempFile } from "./temp.ts" +export { assertLocalPathVacant, isLocalPathExist } from "./path.ts" +export { prefetchFile, prefetchFiles } from "./fetch.ts" diff --git a/file/file/load.ts b/file/file/load.ts new file mode 100644 index 00000000..6ff4e6b5 --- /dev/null +++ b/file/file/load.ts @@ -0,0 +1,7 @@ +import { buffer } from "node:stream/consumers" +import { loadFileStream } from "../stream/index.ts" + +export async function loadFile(path: string, options?: { maxBytes?: number }) { + const stream = await loadFileStream(path, options) + return await buffer(stream) +} diff --git a/file/file/save.ts b/file/file/save.ts index c29f717c..e96e1003 100644 --- a/file/file/save.ts +++ b/file/file/save.ts @@ -1,10 +1,6 @@ -import { loadFileStream } from "../stream/load.js" -import { saveFileStream } from "../stream/save.js" +import { Readable } from "node:stream" +import { saveFileStream } from "../stream/index.ts" -export async function saveFileToDisc(options: { - sourcePath: string - targetPath: string -}) { - const stream = await loadFileStream(options.sourcePath) - await saveFileStream(stream, { path: options.targetPath }) +export async function saveFile(path: string, buffer: Buffer) { + await saveFileStream(Readable.from(buffer), { path }) } diff --git a/file/file/temp.ts b/file/file/temp.ts index 02905602..5fbae9ed 100644 --- a/file/file/temp.ts +++ b/file/file/temp.ts @@ -1,3 +1,4 @@ +import type { Buffer } from "node:buffer" import { unlinkSync } from "node:fs" import { writeFile } from "node:fs/promises" import exitHook from "exit-hook" diff --git a/file/index.ts b/file/index.ts index 1be89d1f..d7427de1 100644 --- a/file/index.ts +++ b/file/index.ts @@ -1,4 +1,4 @@ -export * from "./file/index.js" -export * from "./package/index.js" -export * from "./resource/index.js" -export * from "./stream/index.js" +export * from "./file/index.ts" +export * from "./package/index.ts" +export * from "./resource/index.ts" +export * from "./stream/index.ts" diff --git a/file/package.json b/file/package.json index 8e54575e..9f1db731 100644 --- a/file/package.json +++ b/file/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/file", "type": "module", - "main": "build/index.js", "version": "0.7.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,7 +20,7 @@ "file" ], "scripts": { - "build": "tsc --build" + "build": "tsc" }, "dependencies": { "@dpkit/core": "workspace:*", diff --git a/file/package/index.ts b/file/package/index.ts index 24952f8e..8b08f57a 100644 --- a/file/package/index.ts +++ b/file/package/index.ts @@ -1 +1 @@ -export { getPackageBasepath } from "./path.js" +export { getPackageBasepath } from "./path.ts" diff --git a/file/package/path.spec.ts b/file/package/path.spec.ts index 08b7124c..639bb1db 100644 --- a/file/package/path.spec.ts +++ b/file/package/path.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest" -import { getCommonLocalBasepath } from "./path.js" +import { getCommonLocalBasepath } from "./path.ts" describe("getCommonLocalBasepath", () => { it.each([ diff --git a/file/resource/index.ts b/file/resource/index.ts index fb7f9886..c69d13f9 100644 --- a/file/resource/index.ts +++ b/file/resource/index.ts @@ -1 +1 @@ -export { saveResourceFiles } from "./save.js" +export { saveResourceFiles } from "./save.ts" diff --git a/file/resource/save.spec.ts b/file/resource/save.spec.ts index 78936ef7..a2a8c60f 100644 --- a/file/resource/save.spec.ts +++ b/file/resource/save.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest" -import { saveResourceFiles } from "./save.js" +import { saveResourceFiles } from "./save.ts" describe("saveResourceFiles", () => { it.each([ diff --git a/file/stream/index.ts b/file/stream/index.ts index a2db58d0..471bbcc2 100644 --- a/file/stream/index.ts +++ b/file/stream/index.ts @@ -1,2 +1,2 @@ -export { loadFileStream } from "./load.js" -export { saveFileStream } from "./save.js" +export { loadFileStream } from "./load.ts" +export { saveFileStream } from "./save.ts" diff --git a/file/stream/save.ts b/file/stream/save.ts index 4c6b9be4..c29e54dc 100644 --- a/file/stream/save.ts +++ b/file/stream/save.ts @@ -10,7 +10,9 @@ export async function saveFileStream( path: string }, ) { - // The "wx" flag ensures that the file won't overwrite an existing file + // It is an equivalent to ensureDir function await mkdir(dirname(options.path), { recursive: true }) + + // The "wx" flag ensures that the file won't overwrite an existing file await pipeline(stream, createWriteStream(options.path, { flags: "wx" })) } diff --git a/file/tsconfig.json b/file/tsconfig.json index 7be40230..3c43903c 100644 --- a/file/tsconfig.json +++ b/file/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/file/typedoc.json b/file/typedoc.json index fc33b815..f8e49f3a 100644 --- a/file/typedoc.json +++ b/file/typedoc.json @@ -1,5 +1,4 @@ { "entryPoints": ["index.ts"], - "projectDocuments": ["CHANGELOG.md", "OVERVIEW.md"], "skipErrorChecking": true } diff --git a/folder/OVERVIEW.md b/folder/OVERVIEW.md deleted file mode 100644 index d048012b..00000000 --- a/folder/OVERVIEW.md +++ /dev/null @@ -1,6 +0,0 @@ -# @dpkit/folder - -:::note -This overview is under development. -::: - diff --git a/folder/folder/index.ts b/folder/folder/index.ts index ea4921ee..ea9a6587 100644 --- a/folder/folder/index.ts +++ b/folder/folder/index.ts @@ -1,2 +1,2 @@ -export { createFolder } from "./create.js" -export { getTempFolderPath } from "./temp.js" +export { createFolder } from "./create.ts" +export { getTempFolderPath } from "./temp.ts" diff --git a/folder/index.ts b/folder/index.ts index e37bb747..502a8f4a 100644 --- a/folder/index.ts +++ b/folder/index.ts @@ -1,3 +1,3 @@ -export * from "./package/index.js" -export * from "./folder/index.js" -export * from "./plugin.js" +export * from "./package/index.ts" +export * from "./folder/index.ts" +export * from "./plugin.ts" diff --git a/folder/package.json b/folder/package.json index 083d6f88..8eebdd11 100644 --- a/folder/package.json +++ b/folder/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/folder", "type": "module", - "main": "build/index.js", "version": "0.7.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,7 +20,7 @@ "folder" ], "scripts": { - "build": "tsc --build" + "build": "tsc" }, "dependencies": { "@dpkit/core": "workspace:*", diff --git a/folder/package/index.ts b/folder/package/index.ts index b12588cd..9efd23e2 100644 --- a/folder/package/index.ts +++ b/folder/package/index.ts @@ -1,2 +1,2 @@ -export { loadPackageFromFolder } from "./load.js" -export { savePackageToFolder } from "./save.js" +export { loadPackageFromFolder } from "./load.ts" +export { savePackageToFolder } from "./save.ts" diff --git a/folder/package/save.ts b/folder/package/save.ts index 25c77635..2a81302e 100644 --- a/folder/package/save.ts +++ b/folder/package/save.ts @@ -3,11 +3,11 @@ import { denormalizePackage, saveDescriptor } from "@dpkit/core" import type { Descriptor, Package } from "@dpkit/core" import { assertLocalPathVacant, + copyFile, getPackageBasepath, - saveFileToDisc, saveResourceFiles, } from "@dpkit/file" -import { createFolder } from "../folder/index.js" +import { createFolder } from "../folder/index.ts" export async function savePackageToFolder( dataPackage: Package, @@ -29,7 +29,7 @@ export async function savePackageToFolder( basepath, withRemote, saveFile: async props => { - await saveFileToDisc({ + await copyFile({ sourcePath: props.normalizedPath, targetPath: props.denormalizedPath, }) diff --git a/folder/plugin.ts b/folder/plugin.ts index 23dbf566..932c3d02 100644 --- a/folder/plugin.ts +++ b/folder/plugin.ts @@ -1,11 +1,11 @@ import { stat } from "node:fs/promises" import type { Plugin } from "@dpkit/core" import { isRemotePath } from "@dpkit/core" -import { loadPackageFromFolder } from "./package/index.js" +import { loadPackageFromFolder } from "./package/index.ts" export class FolderPlugin implements Plugin { async loadPackage(source: string) { - const isFolder = getIsFolder(source) + const isFolder = await getIsFolder(source) if (!isFolder) return undefined const dataPackage = await loadPackageFromFolder(source) diff --git a/folder/tsconfig.json b/folder/tsconfig.json index 7be40230..3c43903c 100644 --- a/folder/tsconfig.json +++ b/folder/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/folder/typedoc.json b/folder/typedoc.json index fc33b815..f8e49f3a 100644 --- a/folder/typedoc.json +++ b/folder/typedoc.json @@ -1,5 +1,4 @@ { "entryPoints": ["index.ts"], - "projectDocuments": ["CHANGELOG.md", "OVERVIEW.md"], "skipErrorChecking": true } diff --git a/github/OVERVIEW.md b/github/OVERVIEW.md deleted file mode 100644 index aabb7f73..00000000 --- a/github/OVERVIEW.md +++ /dev/null @@ -1,6 +0,0 @@ -# @dpkit/github - -:::note -This overview is under development. -::: - diff --git a/github/general/index.ts b/github/general/index.ts deleted file mode 100644 index 5d5ad435..00000000 --- a/github/general/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { makeGithubApiRequest } from "./request.js" diff --git a/github/github/index.ts b/github/github/index.ts new file mode 100644 index 00000000..72213bd6 --- /dev/null +++ b/github/github/index.ts @@ -0,0 +1 @@ +export { makeGithubApiRequest } from "./request.ts" diff --git a/github/general/path.ts b/github/github/path.ts similarity index 100% rename from github/general/path.ts rename to github/github/path.ts diff --git a/github/general/request.ts b/github/github/request.ts similarity index 100% rename from github/general/request.ts rename to github/github/request.ts diff --git a/github/index.ts b/github/index.ts index c3c86163..ae6326f6 100644 --- a/github/index.ts +++ b/github/index.ts @@ -1,3 +1,3 @@ -export * from "./package/index.js" -export * from "./resource/index.js" -export * from "./plugin.js" +export * from "./package/index.ts" +export * from "./resource/index.ts" +export * from "./plugin.ts" diff --git a/github/package.json b/github/package.json index 39048c14..1659d102 100644 --- a/github/package.json +++ b/github/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/github", "type": "module", - "main": "build/index.js", "version": "0.7.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,7 +20,7 @@ "github" ], "scripts": { - "build": "tsc --build" + "build": "tsc" }, "dependencies": { "@dpkit/core": "workspace:*", diff --git a/github/package/Package.ts b/github/package/Package.ts index 8890a745..82bdc2e4 100644 --- a/github/package/Package.ts +++ b/github/package/Package.ts @@ -1,6 +1,6 @@ -import type { GithubResource } from "../resource/index.js" -import type { GithubLicense } from "./License.js" -import type { GithubOwner } from "./Owner.js" +import type { GithubResource } from "../resource/index.ts" +import type { GithubLicense } from "./License.ts" +import type { GithubOwner } from "./Owner.ts" /** * Github repository as a package diff --git a/github/package/fixtures/generated/load.spec.ts.snap b/github/package/fixtures/generated/load.spec.ts.snap index 7b9126bf..fadcca50 100644 --- a/github/package/fixtures/generated/load.spec.ts.snap +++ b/github/package/fixtures/generated/load.spec.ts.snap @@ -151,44 +151,42 @@ exports[`loadPackageFromGithub > should merge datapackage.json if present 1`] = "path": "https://raw.githubusercontent.com/roll/currency-codes/refs/heads/master/data/codes-all.csv", "schema": { "$schema": undefined, - "descriptor": { - "fields": [ - { - "description": "Country or region name", - "name": "Entity", - "type": "string", - }, - { - "description": "Name of the currency", - "name": "Currency", - "type": "string", - }, - { - "description": "3 digit alphabetic code for the currency", - "name": "AlphabeticCode", - "title": "Alphabetic Code", - "type": "string", - }, - { - "description": "3 digit numeric code", - "name": "NumericCode", - "title": "Numeric Code", - "type": "number", - }, - { - "description": "", - "name": "MinorUnit", - "title": "Minor Unit", - "type": "string", - }, - { - "description": "Date currency withdrawn (values can be ranges or months", - "name": "WithdrawalDate", - "title": "Withdrawal Date", - "type": "string", - }, - ], - }, + "fields": [ + { + "description": "Country or region name", + "name": "Entity", + "type": "string", + }, + { + "description": "Name of the currency", + "name": "Currency", + "type": "string", + }, + { + "description": "3 digit alphabetic code for the currency", + "name": "AlphabeticCode", + "title": "Alphabetic Code", + "type": "string", + }, + { + "description": "3 digit numeric code", + "name": "NumericCode", + "title": "Numeric Code", + "type": "number", + }, + { + "description": "", + "name": "MinorUnit", + "title": "Minor Unit", + "type": "string", + }, + { + "description": "Date currency withdrawn (values can be ranges or months", + "name": "WithdrawalDate", + "title": "Withdrawal Date", + "type": "string", + }, + ], }, "size": "16863", }, diff --git a/github/package/fixtures/generated/should-load-a-package_2675098929/recording.har b/github/package/fixtures/generated/loadPackageFromGithub-should-load-a-package_1044819575/recording.har similarity index 96% rename from github/package/fixtures/generated/should-load-a-package_2675098929/recording.har rename to github/package/fixtures/generated/loadPackageFromGithub-should-load-a-package_1044819575/recording.har index 2017f36b..eb7d49e9 100644 --- a/github/package/fixtures/generated/should-load-a-package_2675098929/recording.har +++ b/github/package/fixtures/generated/loadPackageFromGithub-should-load-a-package_1044819575/recording.har @@ -1,6 +1,6 @@ { "log": { - "_recordingName": "should load a package", + "_recordingName": "loadPackageFromGithub-should load a package", "creator": { "comment": "persister:fs", "name": "Polly.JS", @@ -64,7 +64,7 @@ }, { "name": "date", - "value": "Wed, 28 May 2025 09:59:41 GMT" + "value": "Thu, 07 Aug 2025 07:49:25 GMT" }, { "name": "etag", @@ -108,7 +108,7 @@ }, { "name": "x-github-request-id", - "value": "3878:1F0C59:13CFC:1456C:6836DE8D" + "value": "2359:39D094:F0DA73:E1E475:68945A85" }, { "name": "x-ratelimit-limit", @@ -120,7 +120,7 @@ }, { "name": "x-ratelimit-reset", - "value": "1748429981" + "value": "1754556565" }, { "name": "x-ratelimit-resource", @@ -135,14 +135,14 @@ "value": "0" } ], - "headersSize": 1292, + "headersSize": 1294, "httpVersion": "HTTP/1.1", "redirectURL": "", "status": 200, "statusText": "OK" }, - "startedDateTime": "2025-05-28T09:59:40.738Z", - "time": 759, + "startedDateTime": "2025-08-07T07:49:25.318Z", + "time": 520, "timings": { "blocked": -1, "connect": -1, @@ -150,7 +150,7 @@ "receive": 0, "send": 0, "ssl": -1, - "wait": 759 + "wait": 520 } }, { @@ -215,7 +215,7 @@ }, { "name": "date", - "value": "Wed, 28 May 2025 09:59:41 GMT" + "value": "Thu, 07 Aug 2025 07:49:25 GMT" }, { "name": "etag", @@ -259,7 +259,7 @@ }, { "name": "x-github-request-id", - "value": "3878:1F0C59:13E18:146B0:6836DE8D" + "value": "2359:39D094:F0DC2F:E1E5F1:68945A85" }, { "name": "x-ratelimit-limit", @@ -271,7 +271,7 @@ }, { "name": "x-ratelimit-reset", - "value": "1748429981" + "value": "1754556565" }, { "name": "x-ratelimit-resource", @@ -286,14 +286,14 @@ "value": "0" } ], - "headersSize": 1291, + "headersSize": 1293, "httpVersion": "HTTP/1.1", "redirectURL": "", "status": 200, "statusText": "OK" }, - "startedDateTime": "2025-05-28T09:59:41.502Z", - "time": 288, + "startedDateTime": "2025-08-07T07:49:25.841Z", + "time": 281, "timings": { "blocked": -1, "connect": -1, @@ -301,7 +301,7 @@ "receive": 0, "send": 0, "ssl": -1, - "wait": 288 + "wait": 281 } } ], diff --git a/github/package/fixtures/generated/should-merge-datapackage-json-if-present_1884846678/recording.har b/github/package/fixtures/generated/loadPackageFromGithub-should-merge-datapackage-json-if-present_618226504/recording.har similarity index 93% rename from github/package/fixtures/generated/should-merge-datapackage-json-if-present_1884846678/recording.har rename to github/package/fixtures/generated/loadPackageFromGithub-should-merge-datapackage-json-if-present_618226504/recording.har index 55aa6aec..f89c040d 100644 --- a/github/package/fixtures/generated/should-merge-datapackage-json-if-present_1884846678/recording.har +++ b/github/package/fixtures/generated/loadPackageFromGithub-should-merge-datapackage-json-if-present_618226504/recording.har @@ -1,6 +1,6 @@ { "log": { - "_recordingName": "should merge datapackage.json if present", + "_recordingName": "loadPackageFromGithub-should merge datapackage.json if present", "creator": { "comment": "persister:fs", "name": "Polly.JS", @@ -22,11 +22,11 @@ "url": "https://api.github.com/repos/roll/currency-codes" }, "response": { - "bodySize": 1990, + "bodySize": 15526, "content": { "mimeType": "application/json; charset=utf-8", - "size": 1990, - "text": "{\"id\":383820850,\"node_id\":\"MDEwOlJlcG9zaXRvcnkzODM4MjA4NTA=\",\"name\":\"currency-codes\",\"full_name\":\"roll/currency-codes\",\"private\":false,\"owner\":{\"login\":\"roll\",\"id\":557395,\"node_id\":\"MDQ6VXNlcjU1NzM5NQ==\",\"avatar_url\":\"https://avatars.githubusercontent.com/u/557395?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/roll\",\"html_url\":\"https://github.com/roll\",\"followers_url\":\"https://api.github.com/users/roll/followers\",\"following_url\":\"https://api.github.com/users/roll/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/roll/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/roll/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/roll/subscriptions\",\"organizations_url\":\"https://api.github.com/users/roll/orgs\",\"repos_url\":\"https://api.github.com/users/roll/repos\",\"events_url\":\"https://api.github.com/users/roll/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/roll/received_events\",\"type\":\"User\",\"user_view_type\":\"public\",\"site_admin\":false},\"html_url\":\"https://github.com/roll/currency-codes\",\"description\":\"ISO 4217 List of Currencies and Currency Codes\",\"fork\":true,\"url\":\"https://api.github.com/repos/roll/currency-codes\",\"forks_url\":\"https://api.github.com/repos/roll/currency-codes/forks\",\"keys_url\":\"https://api.github.com/repos/roll/currency-codes/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/roll/currency-codes/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/roll/currency-codes/teams\",\"hooks_url\":\"https://api.github.com/repos/roll/currency-codes/hooks\",\"issue_events_url\":\"https://api.github.com/repos/roll/currency-codes/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/roll/currency-codes/events\",\"assignees_url\":\"https://api.github.com/repos/roll/currency-codes/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/roll/currency-codes/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/roll/currency-codes/tags\",\"blobs_url\":\"https://api.github.com/repos/roll/currency-codes/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/roll/currency-codes/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/roll/currency-codes/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/roll/currency-codes/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/roll/currency-codes/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/roll/currency-codes/languages\",\"stargazers_url\":\"https://api.github.com/repos/roll/currency-codes/stargazers\",\"contributors_url\":\"https://api.github.com/repos/roll/currency-codes/contributors\",\"subscribers_url\":\"https://api.github.com/repos/roll/currency-codes/subscribers\",\"subscription_url\":\"https://api.github.com/repos/roll/currency-codes/subscription\",\"commits_url\":\"https://api.github.com/repos/roll/currency-codes/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/roll/currency-codes/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/roll/currency-codes/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/roll/currency-codes/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/roll/currency-codes/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/roll/currency-codes/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/roll/currency-codes/merges\",\"archive_url\":\"https://api.github.com/repos/roll/currency-codes/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/roll/currency-codes/downloads\",\"issues_url\":\"https://api.github.com/repos/roll/currency-codes/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/roll/currency-codes/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/roll/currency-codes/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/roll/currency-codes/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/roll/currency-codes/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/roll/currency-codes/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/roll/currency-codes/deployments\",\"created_at\":\"2021-07-07T14:09:49Z\",\"updated_at\":\"2021-07-07T14:47:03Z\",\"pushed_at\":\"2021-07-07T14:47:01Z\",\"git_url\":\"git://github.com/roll/currency-codes.git\",\"ssh_url\":\"git@github.com:roll/currency-codes.git\",\"clone_url\":\"https://github.com/roll/currency-codes.git\",\"svn_url\":\"https://github.com/roll/currency-codes\",\"homepage\":\"https://datahub.io/core/currency-codes\",\"size\":87,\"stargazers_count\":0,\"watchers_count\":0,\"language\":\"Shell\",\"has_issues\":false,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"has_discussions\":false,\"forks_count\":0,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":0,\"license\":null,\"allow_forking\":true,\"is_template\":false,\"web_commit_signoff_required\":false,\"topics\":[],\"visibility\":\"public\",\"forks\":0,\"open_issues\":0,\"watchers\":0,\"default_branch\":\"master\",\"temp_clone_token\":null,\"parent\":{\"id\":6696644,\"node_id\":\"MDEwOlJlcG9zaXRvcnk2Njk2NjQ0\",\"name\":\"currency-codes\",\"full_name\":\"datasets/currency-codes\",\"private\":false,\"owner\":{\"login\":\"datasets\",\"id\":1643515,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjE2NDM1MTU=\",\"avatar_url\":\"https://avatars.githubusercontent.com/u/1643515?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/datasets\",\"html_url\":\"https://github.com/datasets\",\"followers_url\":\"https://api.github.com/users/datasets/followers\",\"following_url\":\"https://api.github.com/users/datasets/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/datasets/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/datasets/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/datasets/subscriptions\",\"organizations_url\":\"https://api.github.com/users/datasets/orgs\",\"repos_url\":\"https://api.github.com/users/datasets/repos\",\"events_url\":\"https://api.github.com/users/datasets/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/datasets/received_events\",\"type\":\"Organization\",\"user_view_type\":\"public\",\"site_admin\":false},\"html_url\":\"https://github.com/datasets/currency-codes\",\"description\":\"ISO 4217 List of Currencies and Currency Codes\",\"fork\":false,\"url\":\"https://api.github.com/repos/datasets/currency-codes\",\"forks_url\":\"https://api.github.com/repos/datasets/currency-codes/forks\",\"keys_url\":\"https://api.github.com/repos/datasets/currency-codes/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/datasets/currency-codes/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/datasets/currency-codes/teams\",\"hooks_url\":\"https://api.github.com/repos/datasets/currency-codes/hooks\",\"issue_events_url\":\"https://api.github.com/repos/datasets/currency-codes/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/datasets/currency-codes/events\",\"assignees_url\":\"https://api.github.com/repos/datasets/currency-codes/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/datasets/currency-codes/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/datasets/currency-codes/tags\",\"blobs_url\":\"https://api.github.com/repos/datasets/currency-codes/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/datasets/currency-codes/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/datasets/currency-codes/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/datasets/currency-codes/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/datasets/currency-codes/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/datasets/currency-codes/languages\",\"stargazers_url\":\"https://api.github.com/repos/datasets/currency-codes/stargazers\",\"contributors_url\":\"https://api.github.com/repos/datasets/currency-codes/contributors\",\"subscribers_url\":\"https://api.github.com/repos/datasets/currency-codes/subscribers\",\"subscription_url\":\"https://api.github.com/repos/datasets/currency-codes/subscription\",\"commits_url\":\"https://api.github.com/repos/datasets/currency-codes/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/datasets/currency-codes/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/datasets/currency-codes/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/datasets/currency-codes/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/datasets/currency-codes/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/datasets/currency-codes/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/datasets/currency-codes/merges\",\"archive_url\":\"https://api.github.com/repos/datasets/currency-codes/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/datasets/currency-codes/downloads\",\"issues_url\":\"https://api.github.com/repos/datasets/currency-codes/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/datasets/currency-codes/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/datasets/currency-codes/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/datasets/currency-codes/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/datasets/currency-codes/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/datasets/currency-codes/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/datasets/currency-codes/deployments\",\"created_at\":\"2012-11-14T23:19:47Z\",\"updated_at\":\"2025-04-15T19:49:30Z\",\"pushed_at\":\"2025-04-01T01:26:10Z\",\"git_url\":\"git://github.com/datasets/currency-codes.git\",\"ssh_url\":\"git@github.com:datasets/currency-codes.git\",\"clone_url\":\"https://github.com/datasets/currency-codes.git\",\"svn_url\":\"https://github.com/datasets/currency-codes\",\"homepage\":\"https://datahub.io/core/currency-codes\",\"size\":79,\"stargazers_count\":158,\"watchers_count\":158,\"language\":\"Shell\",\"has_issues\":true,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"has_discussions\":false,\"forks_count\":179,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":3,\"license\":null,\"allow_forking\":true,\"is_template\":false,\"web_commit_signoff_required\":false,\"topics\":[],\"visibility\":\"public\",\"forks\":179,\"open_issues\":3,\"watchers\":158,\"default_branch\":\"main\"},\"source\":{\"id\":6696644,\"node_id\":\"MDEwOlJlcG9zaXRvcnk2Njk2NjQ0\",\"name\":\"currency-codes\",\"full_name\":\"datasets/currency-codes\",\"private\":false,\"owner\":{\"login\":\"datasets\",\"id\":1643515,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjE2NDM1MTU=\",\"avatar_url\":\"https://avatars.githubusercontent.com/u/1643515?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/datasets\",\"html_url\":\"https://github.com/datasets\",\"followers_url\":\"https://api.github.com/users/datasets/followers\",\"following_url\":\"https://api.github.com/users/datasets/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/datasets/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/datasets/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/datasets/subscriptions\",\"organizations_url\":\"https://api.github.com/users/datasets/orgs\",\"repos_url\":\"https://api.github.com/users/datasets/repos\",\"events_url\":\"https://api.github.com/users/datasets/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/datasets/received_events\",\"type\":\"Organization\",\"user_view_type\":\"public\",\"site_admin\":false},\"html_url\":\"https://github.com/datasets/currency-codes\",\"description\":\"ISO 4217 List of Currencies and Currency Codes\",\"fork\":false,\"url\":\"https://api.github.com/repos/datasets/currency-codes\",\"forks_url\":\"https://api.github.com/repos/datasets/currency-codes/forks\",\"keys_url\":\"https://api.github.com/repos/datasets/currency-codes/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/datasets/currency-codes/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/datasets/currency-codes/teams\",\"hooks_url\":\"https://api.github.com/repos/datasets/currency-codes/hooks\",\"issue_events_url\":\"https://api.github.com/repos/datasets/currency-codes/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/datasets/currency-codes/events\",\"assignees_url\":\"https://api.github.com/repos/datasets/currency-codes/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/datasets/currency-codes/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/datasets/currency-codes/tags\",\"blobs_url\":\"https://api.github.com/repos/datasets/currency-codes/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/datasets/currency-codes/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/datasets/currency-codes/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/datasets/currency-codes/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/datasets/currency-codes/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/datasets/currency-codes/languages\",\"stargazers_url\":\"https://api.github.com/repos/datasets/currency-codes/stargazers\",\"contributors_url\":\"https://api.github.com/repos/datasets/currency-codes/contributors\",\"subscribers_url\":\"https://api.github.com/repos/datasets/currency-codes/subscribers\",\"subscription_url\":\"https://api.github.com/repos/datasets/currency-codes/subscription\",\"commits_url\":\"https://api.github.com/repos/datasets/currency-codes/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/datasets/currency-codes/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/datasets/currency-codes/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/datasets/currency-codes/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/datasets/currency-codes/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/datasets/currency-codes/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/datasets/currency-codes/merges\",\"archive_url\":\"https://api.github.com/repos/datasets/currency-codes/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/datasets/currency-codes/downloads\",\"issues_url\":\"https://api.github.com/repos/datasets/currency-codes/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/datasets/currency-codes/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/datasets/currency-codes/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/datasets/currency-codes/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/datasets/currency-codes/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/datasets/currency-codes/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/datasets/currency-codes/deployments\",\"created_at\":\"2012-11-14T23:19:47Z\",\"updated_at\":\"2025-04-15T19:49:30Z\",\"pushed_at\":\"2025-04-01T01:26:10Z\",\"git_url\":\"git://github.com/datasets/currency-codes.git\",\"ssh_url\":\"git@github.com:datasets/currency-codes.git\",\"clone_url\":\"https://github.com/datasets/currency-codes.git\",\"svn_url\":\"https://github.com/datasets/currency-codes\",\"homepage\":\"https://datahub.io/core/currency-codes\",\"size\":79,\"stargazers_count\":158,\"watchers_count\":158,\"language\":\"Shell\",\"has_issues\":true,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"has_discussions\":false,\"forks_count\":179,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":3,\"license\":null,\"allow_forking\":true,\"is_template\":false,\"web_commit_signoff_required\":false,\"topics\":[],\"visibility\":\"public\",\"forks\":179,\"open_issues\":3,\"watchers\":158,\"default_branch\":\"main\"},\"network_count\":179,\"subscribers_count\":0}" + "size": 15526, + "text": "{\"id\":383820850,\"node_id\":\"MDEwOlJlcG9zaXRvcnkzODM4MjA4NTA=\",\"name\":\"currency-codes\",\"full_name\":\"roll/currency-codes\",\"private\":false,\"owner\":{\"login\":\"roll\",\"id\":557395,\"node_id\":\"MDQ6VXNlcjU1NzM5NQ==\",\"avatar_url\":\"https://avatars.githubusercontent.com/u/557395?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/roll\",\"html_url\":\"https://github.com/roll\",\"followers_url\":\"https://api.github.com/users/roll/followers\",\"following_url\":\"https://api.github.com/users/roll/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/roll/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/roll/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/roll/subscriptions\",\"organizations_url\":\"https://api.github.com/users/roll/orgs\",\"repos_url\":\"https://api.github.com/users/roll/repos\",\"events_url\":\"https://api.github.com/users/roll/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/roll/received_events\",\"type\":\"User\",\"user_view_type\":\"public\",\"site_admin\":false},\"html_url\":\"https://github.com/roll/currency-codes\",\"description\":\"ISO 4217 List of Currencies and Currency Codes\",\"fork\":true,\"url\":\"https://api.github.com/repos/roll/currency-codes\",\"forks_url\":\"https://api.github.com/repos/roll/currency-codes/forks\",\"keys_url\":\"https://api.github.com/repos/roll/currency-codes/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/roll/currency-codes/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/roll/currency-codes/teams\",\"hooks_url\":\"https://api.github.com/repos/roll/currency-codes/hooks\",\"issue_events_url\":\"https://api.github.com/repos/roll/currency-codes/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/roll/currency-codes/events\",\"assignees_url\":\"https://api.github.com/repos/roll/currency-codes/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/roll/currency-codes/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/roll/currency-codes/tags\",\"blobs_url\":\"https://api.github.com/repos/roll/currency-codes/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/roll/currency-codes/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/roll/currency-codes/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/roll/currency-codes/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/roll/currency-codes/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/roll/currency-codes/languages\",\"stargazers_url\":\"https://api.github.com/repos/roll/currency-codes/stargazers\",\"contributors_url\":\"https://api.github.com/repos/roll/currency-codes/contributors\",\"subscribers_url\":\"https://api.github.com/repos/roll/currency-codes/subscribers\",\"subscription_url\":\"https://api.github.com/repos/roll/currency-codes/subscription\",\"commits_url\":\"https://api.github.com/repos/roll/currency-codes/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/roll/currency-codes/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/roll/currency-codes/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/roll/currency-codes/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/roll/currency-codes/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/roll/currency-codes/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/roll/currency-codes/merges\",\"archive_url\":\"https://api.github.com/repos/roll/currency-codes/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/roll/currency-codes/downloads\",\"issues_url\":\"https://api.github.com/repos/roll/currency-codes/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/roll/currency-codes/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/roll/currency-codes/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/roll/currency-codes/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/roll/currency-codes/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/roll/currency-codes/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/roll/currency-codes/deployments\",\"created_at\":\"2021-07-07T14:09:49Z\",\"updated_at\":\"2021-07-07T14:47:03Z\",\"pushed_at\":\"2021-07-07T14:47:01Z\",\"git_url\":\"git://github.com/roll/currency-codes.git\",\"ssh_url\":\"git@github.com:roll/currency-codes.git\",\"clone_url\":\"https://github.com/roll/currency-codes.git\",\"svn_url\":\"https://github.com/roll/currency-codes\",\"homepage\":\"https://datahub.io/core/currency-codes\",\"size\":87,\"stargazers_count\":0,\"watchers_count\":0,\"language\":\"Shell\",\"has_issues\":false,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"has_discussions\":false,\"forks_count\":0,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":0,\"license\":null,\"allow_forking\":true,\"is_template\":false,\"web_commit_signoff_required\":false,\"topics\":[],\"visibility\":\"public\",\"forks\":0,\"open_issues\":0,\"watchers\":0,\"default_branch\":\"master\",\"temp_clone_token\":null,\"parent\":{\"id\":6696644,\"node_id\":\"MDEwOlJlcG9zaXRvcnk2Njk2NjQ0\",\"name\":\"currency-codes\",\"full_name\":\"datasets/currency-codes\",\"private\":false,\"owner\":{\"login\":\"datasets\",\"id\":1643515,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjE2NDM1MTU=\",\"avatar_url\":\"https://avatars.githubusercontent.com/u/1643515?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/datasets\",\"html_url\":\"https://github.com/datasets\",\"followers_url\":\"https://api.github.com/users/datasets/followers\",\"following_url\":\"https://api.github.com/users/datasets/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/datasets/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/datasets/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/datasets/subscriptions\",\"organizations_url\":\"https://api.github.com/users/datasets/orgs\",\"repos_url\":\"https://api.github.com/users/datasets/repos\",\"events_url\":\"https://api.github.com/users/datasets/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/datasets/received_events\",\"type\":\"Organization\",\"user_view_type\":\"public\",\"site_admin\":false},\"html_url\":\"https://github.com/datasets/currency-codes\",\"description\":\"ISO 4217 List of Currencies and Currency Codes\",\"fork\":false,\"url\":\"https://api.github.com/repos/datasets/currency-codes\",\"forks_url\":\"https://api.github.com/repos/datasets/currency-codes/forks\",\"keys_url\":\"https://api.github.com/repos/datasets/currency-codes/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/datasets/currency-codes/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/datasets/currency-codes/teams\",\"hooks_url\":\"https://api.github.com/repos/datasets/currency-codes/hooks\",\"issue_events_url\":\"https://api.github.com/repos/datasets/currency-codes/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/datasets/currency-codes/events\",\"assignees_url\":\"https://api.github.com/repos/datasets/currency-codes/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/datasets/currency-codes/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/datasets/currency-codes/tags\",\"blobs_url\":\"https://api.github.com/repos/datasets/currency-codes/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/datasets/currency-codes/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/datasets/currency-codes/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/datasets/currency-codes/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/datasets/currency-codes/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/datasets/currency-codes/languages\",\"stargazers_url\":\"https://api.github.com/repos/datasets/currency-codes/stargazers\",\"contributors_url\":\"https://api.github.com/repos/datasets/currency-codes/contributors\",\"subscribers_url\":\"https://api.github.com/repos/datasets/currency-codes/subscribers\",\"subscription_url\":\"https://api.github.com/repos/datasets/currency-codes/subscription\",\"commits_url\":\"https://api.github.com/repos/datasets/currency-codes/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/datasets/currency-codes/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/datasets/currency-codes/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/datasets/currency-codes/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/datasets/currency-codes/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/datasets/currency-codes/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/datasets/currency-codes/merges\",\"archive_url\":\"https://api.github.com/repos/datasets/currency-codes/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/datasets/currency-codes/downloads\",\"issues_url\":\"https://api.github.com/repos/datasets/currency-codes/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/datasets/currency-codes/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/datasets/currency-codes/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/datasets/currency-codes/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/datasets/currency-codes/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/datasets/currency-codes/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/datasets/currency-codes/deployments\",\"created_at\":\"2012-11-14T23:19:47Z\",\"updated_at\":\"2025-08-02T21:09:44Z\",\"pushed_at\":\"2025-06-01T01:47:03Z\",\"git_url\":\"git://github.com/datasets/currency-codes.git\",\"ssh_url\":\"git@github.com:datasets/currency-codes.git\",\"clone_url\":\"https://github.com/datasets/currency-codes.git\",\"svn_url\":\"https://github.com/datasets/currency-codes\",\"homepage\":\"https://datahub.io/core/currency-codes\",\"size\":80,\"stargazers_count\":162,\"watchers_count\":162,\"language\":\"Shell\",\"has_issues\":true,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"has_discussions\":false,\"forks_count\":177,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":3,\"license\":null,\"allow_forking\":true,\"is_template\":false,\"web_commit_signoff_required\":false,\"topics\":[],\"visibility\":\"public\",\"forks\":177,\"open_issues\":3,\"watchers\":162,\"default_branch\":\"main\"},\"source\":{\"id\":6696644,\"node_id\":\"MDEwOlJlcG9zaXRvcnk2Njk2NjQ0\",\"name\":\"currency-codes\",\"full_name\":\"datasets/currency-codes\",\"private\":false,\"owner\":{\"login\":\"datasets\",\"id\":1643515,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjE2NDM1MTU=\",\"avatar_url\":\"https://avatars.githubusercontent.com/u/1643515?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/datasets\",\"html_url\":\"https://github.com/datasets\",\"followers_url\":\"https://api.github.com/users/datasets/followers\",\"following_url\":\"https://api.github.com/users/datasets/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/datasets/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/datasets/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/datasets/subscriptions\",\"organizations_url\":\"https://api.github.com/users/datasets/orgs\",\"repos_url\":\"https://api.github.com/users/datasets/repos\",\"events_url\":\"https://api.github.com/users/datasets/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/datasets/received_events\",\"type\":\"Organization\",\"user_view_type\":\"public\",\"site_admin\":false},\"html_url\":\"https://github.com/datasets/currency-codes\",\"description\":\"ISO 4217 List of Currencies and Currency Codes\",\"fork\":false,\"url\":\"https://api.github.com/repos/datasets/currency-codes\",\"forks_url\":\"https://api.github.com/repos/datasets/currency-codes/forks\",\"keys_url\":\"https://api.github.com/repos/datasets/currency-codes/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/datasets/currency-codes/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/datasets/currency-codes/teams\",\"hooks_url\":\"https://api.github.com/repos/datasets/currency-codes/hooks\",\"issue_events_url\":\"https://api.github.com/repos/datasets/currency-codes/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/datasets/currency-codes/events\",\"assignees_url\":\"https://api.github.com/repos/datasets/currency-codes/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/datasets/currency-codes/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/datasets/currency-codes/tags\",\"blobs_url\":\"https://api.github.com/repos/datasets/currency-codes/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/datasets/currency-codes/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/datasets/currency-codes/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/datasets/currency-codes/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/datasets/currency-codes/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/datasets/currency-codes/languages\",\"stargazers_url\":\"https://api.github.com/repos/datasets/currency-codes/stargazers\",\"contributors_url\":\"https://api.github.com/repos/datasets/currency-codes/contributors\",\"subscribers_url\":\"https://api.github.com/repos/datasets/currency-codes/subscribers\",\"subscription_url\":\"https://api.github.com/repos/datasets/currency-codes/subscription\",\"commits_url\":\"https://api.github.com/repos/datasets/currency-codes/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/datasets/currency-codes/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/datasets/currency-codes/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/datasets/currency-codes/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/datasets/currency-codes/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/datasets/currency-codes/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/datasets/currency-codes/merges\",\"archive_url\":\"https://api.github.com/repos/datasets/currency-codes/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/datasets/currency-codes/downloads\",\"issues_url\":\"https://api.github.com/repos/datasets/currency-codes/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/datasets/currency-codes/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/datasets/currency-codes/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/datasets/currency-codes/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/datasets/currency-codes/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/datasets/currency-codes/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/datasets/currency-codes/deployments\",\"created_at\":\"2012-11-14T23:19:47Z\",\"updated_at\":\"2025-08-02T21:09:44Z\",\"pushed_at\":\"2025-06-01T01:47:03Z\",\"git_url\":\"git://github.com/datasets/currency-codes.git\",\"ssh_url\":\"git@github.com:datasets/currency-codes.git\",\"clone_url\":\"https://github.com/datasets/currency-codes.git\",\"svn_url\":\"https://github.com/datasets/currency-codes\",\"homepage\":\"https://datahub.io/core/currency-codes\",\"size\":80,\"stargazers_count\":162,\"watchers_count\":162,\"language\":\"Shell\",\"has_issues\":true,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"has_discussions\":false,\"forks_count\":177,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":3,\"license\":null,\"allow_forking\":true,\"is_template\":false,\"web_commit_signoff_required\":false,\"topics\":[],\"visibility\":\"public\",\"forks\":177,\"open_issues\":3,\"watchers\":162,\"default_branch\":\"main\"},\"network_count\":177,\"subscribers_count\":0}" }, "cookies": [], "headers": [ @@ -50,10 +50,6 @@ "name": "content-encoding", "value": "gzip" }, - { - "name": "content-length", - "value": "1990" - }, { "name": "content-security-policy", "value": "default-src 'none'" @@ -64,11 +60,11 @@ }, { "name": "date", - "value": "Wed, 28 May 2025 09:59:41 GMT" + "value": "Thu, 07 Aug 2025 07:49:26 GMT" }, { "name": "etag", - "value": "W/\"93b52f692b954e6d1e8278d893c276f5a3c874a87588d75f27a83cd431427974\"" + "value": "W/\"5910a4781b626f2a41e1824960503e8a43c24b955cb667a2217c33eb1c444ee8\"" }, { "name": "last-modified", @@ -86,6 +82,10 @@ "name": "strict-transport-security", "value": "max-age=31536000; includeSubdomains; preload" }, + { + "name": "transfer-encoding", + "value": "chunked" + }, { "name": "vary", "value": "Accept,Accept-Encoding, Accept, X-Requested-With" @@ -108,7 +108,7 @@ }, { "name": "x-github-request-id", - "value": "3878:1F0C59:13F54:147EE:6836DE8D" + "value": "2359:39D094:F0DE0F:E1E7C5:68945A85" }, { "name": "x-ratelimit-limit", @@ -120,7 +120,7 @@ }, { "name": "x-ratelimit-reset", - "value": "1748429981" + "value": "1754556565" }, { "name": "x-ratelimit-resource", @@ -135,14 +135,14 @@ "value": "0" } ], - "headersSize": 1292, + "headersSize": 1300, "httpVersion": "HTTP/1.1", "redirectURL": "", "status": 200, "statusText": "OK" }, - "startedDateTime": "2025-05-28T09:59:41.798Z", - "time": 277, + "startedDateTime": "2025-08-07T07:49:26.129Z", + "time": 335, "timings": { "blocked": -1, "connect": -1, @@ -150,7 +150,7 @@ "receive": 0, "send": 0, "ssl": -1, - "wait": 277 + "wait": 335 } }, { @@ -215,7 +215,7 @@ }, { "name": "date", - "value": "Wed, 28 May 2025 09:59:42 GMT" + "value": "Thu, 07 Aug 2025 07:49:26 GMT" }, { "name": "etag", @@ -259,7 +259,7 @@ }, { "name": "x-github-request-id", - "value": "3878:1F0C59:140AA:1493F:6836DE8E" + "value": "2359:39D094:F0E017:E1E96A:68945A86" }, { "name": "x-ratelimit-limit", @@ -271,7 +271,7 @@ }, { "name": "x-ratelimit-reset", - "value": "1748429981" + "value": "1754556565" }, { "name": "x-ratelimit-resource", @@ -286,14 +286,14 @@ "value": "0" } ], - "headersSize": 1291, + "headersSize": 1293, "httpVersion": "HTTP/1.1", "redirectURL": "", "status": 200, "statusText": "OK" }, - "startedDateTime": "2025-05-28T09:59:42.077Z", - "time": 261, + "startedDateTime": "2025-08-07T07:49:26.465Z", + "time": 292, "timings": { "blocked": -1, "connect": -1, @@ -301,7 +301,7 @@ "receive": 0, "send": 0, "ssl": -1, - "wait": 261 + "wait": 292 } }, { @@ -365,7 +365,7 @@ }, { "name": "date", - "value": "Wed, 28 May 2025 09:59:42 GMT" + "value": "Thu, 07 Aug 2025 07:49:27 GMT" }, { "name": "etag", @@ -373,11 +373,11 @@ }, { "name": "expires", - "value": "Wed, 28 May 2025 10:04:42 GMT" + "value": "Thu, 07 Aug 2025 07:54:27 GMT" }, { "name": "source-age", - "value": "177" + "value": "0" }, { "name": "strict-transport-security", @@ -393,7 +393,7 @@ }, { "name": "x-cache", - "value": "HIT" + "value": "MISS" }, { "name": "x-cache-hits", @@ -405,7 +405,7 @@ }, { "name": "x-fastly-request-id", - "value": "b3139e6fb7d5d49cc6fc18b6ed9349583bc805bf" + "value": "485833d62b1c0cbf6673f946e8b2bed21876f2c6" }, { "name": "x-frame-options", @@ -413,29 +413,29 @@ }, { "name": "x-github-request-id", - "value": "DE55:1500CA:D108E3:E7A375:6836DDDD" + "value": "0EAB:27570B:15BE0F9:191ED61:68945A86" }, { "name": "x-served-by", - "value": "cache-lis1490032-LIS" + "value": "cache-lis1490057-LIS" }, { "name": "x-timer", - "value": "S1748426383.589923,VS0,VE1" + "value": "S1754552967.823769,VS0,VE177" }, { "name": "x-xss-protection", "value": "1; mode=block" } ], - "headersSize": 901, + "headersSize": 904, "httpVersion": "HTTP/1.1", "redirectURL": "", "status": 200, "statusText": "OK" }, - "startedDateTime": "2025-05-28T09:59:42.340Z", - "time": 436, + "startedDateTime": "2025-08-07T07:49:26.760Z", + "time": 346, "timings": { "blocked": -1, "connect": -1, @@ -443,7 +443,7 @@ "receive": 0, "send": 0, "ssl": -1, - "wait": 436 + "wait": 346 } } ], diff --git a/github/package/index.ts b/github/package/index.ts index 7f94f3e0..69bcf427 100644 --- a/github/package/index.ts +++ b/github/package/index.ts @@ -1,5 +1,5 @@ -export type { GithubPackage } from "./Package.js" -export type { GithubOwner } from "./Owner.js" -export type { GithubLicense } from "./License.js" -export { loadPackageFromGithub } from "./load.js" -export { savePackageToGithub } from "./save.js" +export type { GithubPackage } from "./Package.ts" +export type { GithubOwner } from "./Owner.ts" +export type { GithubLicense } from "./License.ts" +export { loadPackageFromGithub } from "./load.ts" +export { savePackageToGithub } from "./save.ts" diff --git a/github/package/load.spec.ts b/github/package/load.spec.ts index 8bf5c0bf..f3cba35b 100644 --- a/github/package/load.spec.ts +++ b/github/package/load.spec.ts @@ -1,6 +1,6 @@ import { useRecording } from "@dpkit/test" import { describe, expect, it } from "vitest" -import { loadPackageFromGithub } from "./load.js" +import { loadPackageFromGithub } from "./load.ts" describe("loadPackageFromGithub", () => { useRecording() diff --git a/github/package/load.ts b/github/package/load.ts index e8006533..98a708b3 100644 --- a/github/package/load.ts +++ b/github/package/load.ts @@ -1,8 +1,8 @@ import { mergePackages } from "@dpkit/core" -import { makeGithubApiRequest } from "../general/index.js" -import type { GithubResource } from "../resource/index.js" -import type { GithubPackage } from "./Package.js" -import { normalizeGithubPackage } from "./process/normalize.js" +import { makeGithubApiRequest } from "../github/index.ts" +import type { GithubResource } from "../resource/index.ts" +import type { GithubPackage } from "./Package.ts" +import { normalizeGithubPackage } from "./process/normalize.ts" /** * Load a package from a Github repository diff --git a/github/package/process/denormalize.ts b/github/package/process/denormalize.ts index 5ab172a9..caae857a 100644 --- a/github/package/process/denormalize.ts +++ b/github/package/process/denormalize.ts @@ -1,5 +1,5 @@ import type { Package } from "@dpkit/core" -import type { GithubPackage } from "../Package.js" +import type { GithubPackage } from "../Package.ts" /** * Denormalizes a Frictionless Data Package to Github repository metadata format diff --git a/github/package/process/normalize.ts b/github/package/process/normalize.ts index 8df161f7..06aab98b 100644 --- a/github/package/process/normalize.ts +++ b/github/package/process/normalize.ts @@ -1,6 +1,6 @@ import type { Contributor, License, Package } from "@dpkit/core" -import { normalizeGithubResource } from "../../resource/process/normalize.js" -import type { GithubPackage } from "../Package.js" +import { normalizeGithubResource } from "../../resource/process/normalize.ts" +import type { GithubPackage } from "../Package.ts" /** * Normalizes a Github repository to Frictionless Data package format diff --git a/github/package/save.spec.ts b/github/package/save.spec.ts index 0152824c..a644dfc6 100644 --- a/github/package/save.spec.ts +++ b/github/package/save.spec.ts @@ -1,7 +1,7 @@ import { loadPackageDescriptor } from "@dpkit/core" //import { useRecording } from "@dpkit/test" import { describe, expect, it } from "vitest" -import { savePackageToGithub } from "./save.js" +import { savePackageToGithub } from "./save.ts" describe("savePackageToGithub", () => { //useRecording() diff --git a/github/package/save.ts b/github/package/save.ts index 153cfbb6..acaa833d 100644 --- a/github/package/save.ts +++ b/github/package/save.ts @@ -1,10 +1,11 @@ +import { Buffer } from "node:buffer" import { buffer } from "node:stream/consumers" import type { Descriptor, Package } from "@dpkit/core" import { denormalizePackage, stringifyDescriptor } from "@dpkit/core" import { getPackageBasepath, loadFileStream } from "@dpkit/file" import { saveResourceFiles } from "@dpkit/file" -import { makeGithubApiRequest } from "../general/index.js" -import type { GithubPackage } from "./Package.js" +import { makeGithubApiRequest } from "../github/index.ts" +import type { GithubPackage } from "./Package.ts" /** * Save a package to a Github repository @@ -68,9 +69,7 @@ export async function savePackageToGithub( const payload = { path: denormalizedPath, message: `Added file "${denormalizedPath}"`, - content: Buffer.from(stringifyDescriptor({ descriptor })).toString( - "base64", - ), + content: Buffer.from(stringifyDescriptor(descriptor)).toString("base64"), } await makeGithubApiRequest({ diff --git a/github/plugin.ts b/github/plugin.ts index 5817355b..543d193f 100644 --- a/github/plugin.ts +++ b/github/plugin.ts @@ -1,6 +1,6 @@ import type { Plugin } from "@dpkit/core" import { isRemotePath } from "@dpkit/core" -import { loadPackageFromGithub } from "./package/load.js" +import { loadPackageFromGithub } from "./package/load.ts" export class GithubPlugin implements Plugin { async loadPackage(source: string) { diff --git a/github/resource/index.ts b/github/resource/index.ts index 0923d91a..b9685df7 100644 --- a/github/resource/index.ts +++ b/github/resource/index.ts @@ -1,3 +1,3 @@ -export type { GithubResource } from "./Resource.js" -export { normalizeGithubResource } from "./process/normalize.js" -export { denormalizeGithubResource } from "./process/denormalize.js" +export type { GithubResource } from "./Resource.ts" +export { normalizeGithubResource } from "./process/normalize.ts" +export { denormalizeGithubResource } from "./process/denormalize.ts" diff --git a/github/resource/process/denormalize.ts b/github/resource/process/denormalize.ts index c82c8f1a..863fd5fc 100644 --- a/github/resource/process/denormalize.ts +++ b/github/resource/process/denormalize.ts @@ -1,5 +1,5 @@ import type { Resource } from "@dpkit/core" -import type { GithubResource } from "../Resource.js" +import type { GithubResource } from "../Resource.ts" /** * Denormalizes a Frictionless Data resource to Github file format diff --git a/github/resource/process/normalize.ts b/github/resource/process/normalize.ts index 7f6e8fa0..9a724356 100644 --- a/github/resource/process/normalize.ts +++ b/github/resource/process/normalize.ts @@ -1,6 +1,6 @@ import type { Resource } from "@dpkit/core" import { getFilename, getFormat, getName } from "@dpkit/core" -import type { GithubResource } from "../Resource.js" +import type { GithubResource } from "../Resource.ts" /** * Normalizes a Github file to Frictionless Data resource format diff --git a/github/tsconfig.json b/github/tsconfig.json index 7be40230..3c43903c 100644 --- a/github/tsconfig.json +++ b/github/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/github/typedoc.json b/github/typedoc.json index fc33b815..f8e49f3a 100644 --- a/github/typedoc.json +++ b/github/typedoc.json @@ -1,5 +1,4 @@ { "entryPoints": ["index.ts"], - "projectDocuments": ["CHANGELOG.md", "OVERVIEW.md"], "skipErrorChecking": true } diff --git a/inline/index.ts b/inline/index.ts index 14397550..5f4f33d9 100644 --- a/inline/index.ts +++ b/inline/index.ts @@ -1,2 +1,2 @@ -export * from "./table/index.js" -export * from "./plugin.js" +export * from "./table/index.ts" +export * from "./plugin.ts" diff --git a/inline/package.json b/inline/package.json index 312b62db..2ea72582 100644 --- a/inline/package.json +++ b/inline/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/inline", "type": "module", - "main": "build/index.js", "version": "0.5.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,10 +20,10 @@ "inline" ], "scripts": { - "build": "tsc --build" + "build": "tsc" }, "dependencies": { - "nodejs-polars": "^0.18.0", + "nodejs-polars": "^0.21.0", "@dpkit/core": "workspace:*", "@dpkit/table": "workspace:*" } diff --git a/inline/plugin.ts b/inline/plugin.ts index 1a98a540..f06a395c 100644 --- a/inline/plugin.ts +++ b/inline/plugin.ts @@ -1,6 +1,6 @@ import type { Resource } from "@dpkit/core" import type { TablePlugin } from "@dpkit/table" -import { loadInlineTable } from "./table/index.js" +import { loadInlineTable } from "./table/index.ts" export class InlinePlugin implements TablePlugin { async loadTable(resource: Resource) { diff --git a/inline/table/index.ts b/inline/table/index.ts index d22422e2..34861391 100644 --- a/inline/table/index.ts +++ b/inline/table/index.ts @@ -1 +1 @@ -export { loadInlineTable } from "./load.js" +export { loadInlineTable } from "./load.ts" diff --git a/inline/table/load.spec.ts b/inline/table/load.spec.ts index d6711cae..d5f7635c 100644 --- a/inline/table/load.spec.ts +++ b/inline/table/load.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest" -import { loadInlineTable } from "./load.js" +import { loadInlineTable } from "./load.ts" describe("loadInlineTable", () => { it.each([ diff --git a/inline/tsconfig.json b/inline/tsconfig.json index 7be40230..3c43903c 100644 --- a/inline/tsconfig.json +++ b/inline/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/inline/typedoc.json b/inline/typedoc.json index fc33b815..f8e49f3a 100644 --- a/inline/typedoc.json +++ b/inline/typedoc.json @@ -1,5 +1,4 @@ { "entryPoints": ["index.ts"], - "projectDocuments": ["CHANGELOG.md", "OVERVIEW.md"], "skipErrorChecking": true } diff --git a/json/buffer/decode.ts b/json/buffer/decode.ts new file mode 100644 index 00000000..0a672643 --- /dev/null +++ b/json/buffer/decode.ts @@ -0,0 +1,15 @@ +import type { Buffer } from "node:buffer" + +export function decodeJsonBuffer( + buffer: Buffer, + options: { isLines: boolean }, +) { + const string = buffer.toString("utf-8") + + return options.isLines + ? string + .split("\n") + .filter(Boolean) + .map(line => JSON.parse(line)) + : JSON.parse(string) +} diff --git a/json/buffer/encode.ts b/json/buffer/encode.ts new file mode 100644 index 00000000..952e85cd --- /dev/null +++ b/json/buffer/encode.ts @@ -0,0 +1,9 @@ +import { Buffer } from "node:buffer" + +export function encodeJsonBuffer(data: any, options: { isLines: boolean }) { + const string = options.isLines + ? data.map((line: any) => JSON.stringify(line)).join("\n") + : JSON.stringify(data, null, 2) + + return Buffer.from(string) +} diff --git a/json/buffer/index.ts b/json/buffer/index.ts new file mode 100644 index 00000000..e1f1ad14 --- /dev/null +++ b/json/buffer/index.ts @@ -0,0 +1,2 @@ +export { encodeJsonBuffer } from "./encode.ts" +export { decodeJsonBuffer } from "./decode.ts" diff --git a/json/index.ts b/json/index.ts index e69de29b..5f4f33d9 100644 --- a/json/index.ts +++ b/json/index.ts @@ -0,0 +1,2 @@ +export * from "./table/index.ts" +export * from "./plugin.ts" diff --git a/json/package.json b/json/package.json index b8df02ee..0e262662 100644 --- a/json/package.json +++ b/json/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/json", "type": "module", - "main": "build/index.js", "version": "0.2.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,6 +20,16 @@ "json" ], "scripts": { - "build": "tsc --build" + "build": "tsc" + }, + "dependencies": { + "@dpkit/core": "workspace:*", + "@dpkit/file": "workspace:*", + "@dpkit/table": "workspace:*", + "csv-sniffer": "^0.1.1", + "nodejs-polars": "^0.21.0" + }, + "devDependencies": { + "@dpkit/test": "workspace:*" } } diff --git a/json/plugin.ts b/json/plugin.ts new file mode 100644 index 00000000..eab7b74e --- /dev/null +++ b/json/plugin.ts @@ -0,0 +1,43 @@ +import type { Resource } from "@dpkit/core" +import { inferFormat } from "@dpkit/core" +import type { TablePlugin } from "@dpkit/table" +import type { SaveTableOptions, Table } from "@dpkit/table" +import { loadJsonTable, loadJsonlTable } from "./table/index.ts" +import { saveJsonTable, saveJsonlTable } from "./table/index.ts" + +export class JsonPlugin implements TablePlugin { + async loadTable(resource: Partial) { + const formatInfo = getFormatInfo(resource) + + if (formatInfo.isJson) { + return await loadJsonTable(resource) + } + + if (formatInfo.isJsonl) { + return await loadJsonlTable(resource) + } + + return undefined + } + + async saveTable(table: Table, options: SaveTableOptions) { + const formatInfo = getFormatInfo(options) + + if (formatInfo.isJson) { + return await saveJsonTable(table, options) + } + + if (formatInfo.isJsonl) { + return await saveJsonlTable(table, options) + } + + return undefined + } +} + +function getFormatInfo(resource: Partial) { + const format = inferFormat(resource) + const isJson = format === "json" + const isJsonl = format === "jsonl" || format === "ndjson" + return { isJson, isJsonl } +} diff --git a/json/table/fixtures/generated/loadJsonTable-file-variations-should-load-remote-file-multipart_2057098191/recording.har b/json/table/fixtures/generated/loadJsonTable-file-variations-should-load-remote-file-multipart_2057098191/recording.har new file mode 100644 index 00000000..05e0e45d --- /dev/null +++ b/json/table/fixtures/generated/loadJsonTable-file-variations-should-load-remote-file-multipart_2057098191/recording.har @@ -0,0 +1,298 @@ +{ + "log": { + "_recordingName": "loadJsonTable-file variations-should load remote file (multipart)", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.6" + }, + "entries": [ + { + "_id": "9c1d4218bc0b2124f4ba05daec949590", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [], + "headersSize": 123, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [], + "url": "https://raw.githubusercontent.com/frictionlessdata/frictionless-py/refs/heads/main/data/table.keyed.json" + }, + "response": { + "bodySize": 78, + "content": { + "mimeType": "text/plain; charset=utf-8", + "size": 78, + "text": "[\n {\n \"id\": 1,\n \"name\": \"english\"\n },\n {\n \"id\": 2,\n \"name\": \"中国人\"\n }\n]\n" + }, + "cookies": [], + "headers": [ + { + "name": "accept-ranges", + "value": "bytes" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "cache-control", + "value": "max-age=300" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-encoding", + "value": "gzip" + }, + { + "name": "content-length", + "value": "78" + }, + { + "name": "content-security-policy", + "value": "default-src 'none'; style-src 'unsafe-inline'; sandbox" + }, + { + "name": "content-type", + "value": "text/plain; charset=utf-8" + }, + { + "name": "cross-origin-resource-policy", + "value": "cross-origin" + }, + { + "name": "date", + "value": "Thu, 07 Aug 2025 07:49:21 GMT" + }, + { + "name": "etag", + "value": "W/\"6f3db326388b97300ef06688ba9a05ac48b9af407f4cea02dee6a3c83568b3cb\"" + }, + { + "name": "expires", + "value": "Thu, 07 Aug 2025 07:54:21 GMT" + }, + { + "name": "source-age", + "value": "260" + }, + { + "name": "strict-transport-security", + "value": "max-age=31536000" + }, + { + "name": "vary", + "value": "Authorization,Accept-Encoding" + }, + { + "name": "via", + "value": "1.1 varnish" + }, + { + "name": "x-cache", + "value": "HIT" + }, + { + "name": "x-cache-hits", + "value": "1" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + }, + { + "name": "x-fastly-request-id", + "value": "c91a63c4ee43c97cbf760cf367b532e05e12efd2" + }, + { + "name": "x-frame-options", + "value": "deny" + }, + { + "name": "x-github-request-id", + "value": "D0F0:331C7:156A386:18B3FB7:68944CAF" + }, + { + "name": "x-served-by", + "value": "cache-lis1490034-LIS" + }, + { + "name": "x-timer", + "value": "S1754552962.863617,VS0,VE1" + }, + { + "name": "x-xss-protection", + "value": "1; mode=block" + } + ], + "headersSize": 901, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2025-08-07T07:49:21.915Z", + "time": 61, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 61 + } + }, + { + "_id": "9c1d4218bc0b2124f4ba05daec949590", + "_order": 1, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [], + "headersSize": 123, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [], + "url": "https://raw.githubusercontent.com/frictionlessdata/frictionless-py/refs/heads/main/data/table.keyed.json" + }, + "response": { + "bodySize": 78, + "content": { + "mimeType": "text/plain; charset=utf-8", + "size": 78, + "text": "[\n {\n \"id\": 1,\n \"name\": \"english\"\n },\n {\n \"id\": 2,\n \"name\": \"中国人\"\n }\n]\n" + }, + "cookies": [], + "headers": [ + { + "name": "accept-ranges", + "value": "bytes" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "cache-control", + "value": "max-age=300" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-encoding", + "value": "gzip" + }, + { + "name": "content-length", + "value": "78" + }, + { + "name": "content-security-policy", + "value": "default-src 'none'; style-src 'unsafe-inline'; sandbox" + }, + { + "name": "content-type", + "value": "text/plain; charset=utf-8" + }, + { + "name": "cross-origin-resource-policy", + "value": "cross-origin" + }, + { + "name": "date", + "value": "Thu, 07 Aug 2025 07:49:21 GMT" + }, + { + "name": "etag", + "value": "W/\"6f3db326388b97300ef06688ba9a05ac48b9af407f4cea02dee6a3c83568b3cb\"" + }, + { + "name": "expires", + "value": "Thu, 07 Aug 2025 07:54:21 GMT" + }, + { + "name": "source-age", + "value": "260" + }, + { + "name": "strict-transport-security", + "value": "max-age=31536000" + }, + { + "name": "vary", + "value": "Authorization,Accept-Encoding" + }, + { + "name": "via", + "value": "1.1 varnish" + }, + { + "name": "x-cache", + "value": "HIT" + }, + { + "name": "x-cache-hits", + "value": "1" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + }, + { + "name": "x-fastly-request-id", + "value": "100c17346b28b7276ed143d9108408dbcffcb353" + }, + { + "name": "x-frame-options", + "value": "deny" + }, + { + "name": "x-github-request-id", + "value": "D0F0:331C7:156A386:18B3FB7:68944CAF" + }, + { + "name": "x-served-by", + "value": "cache-lis1490038-LIS" + }, + { + "name": "x-timer", + "value": "S1754552962.975833,VS0,VE1" + }, + { + "name": "x-xss-protection", + "value": "1; mode=block" + } + ], + "headersSize": 901, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2025-08-07T07:49:21.915Z", + "time": 186, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 186 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/json/table/fixtures/generated/loadJsonTable-file-variations-should-load-remote-file_3069001120/recording.har b/json/table/fixtures/generated/loadJsonTable-file-variations-should-load-remote-file_3069001120/recording.har new file mode 100644 index 00000000..aa64606e --- /dev/null +++ b/json/table/fixtures/generated/loadJsonTable-file-variations-should-load-remote-file_3069001120/recording.har @@ -0,0 +1,156 @@ +{ + "log": { + "_recordingName": "loadJsonTable-file variations-should load remote file", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.6" + }, + "entries": [ + { + "_id": "9c1d4218bc0b2124f4ba05daec949590", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [], + "headersSize": 123, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [], + "url": "https://raw.githubusercontent.com/frictionlessdata/frictionless-py/refs/heads/main/data/table.keyed.json" + }, + "response": { + "bodySize": 78, + "content": { + "mimeType": "text/plain; charset=utf-8", + "size": 78, + "text": "[\n {\n \"id\": 1,\n \"name\": \"english\"\n },\n {\n \"id\": 2,\n \"name\": \"中国人\"\n }\n]\n" + }, + "cookies": [], + "headers": [ + { + "name": "accept-ranges", + "value": "bytes" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "cache-control", + "value": "max-age=300" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-encoding", + "value": "gzip" + }, + { + "name": "content-length", + "value": "78" + }, + { + "name": "content-security-policy", + "value": "default-src 'none'; style-src 'unsafe-inline'; sandbox" + }, + { + "name": "content-type", + "value": "text/plain; charset=utf-8" + }, + { + "name": "cross-origin-resource-policy", + "value": "cross-origin" + }, + { + "name": "date", + "value": "Thu, 07 Aug 2025 07:49:21 GMT" + }, + { + "name": "etag", + "value": "W/\"6f3db326388b97300ef06688ba9a05ac48b9af407f4cea02dee6a3c83568b3cb\"" + }, + { + "name": "expires", + "value": "Thu, 07 Aug 2025 07:54:21 GMT" + }, + { + "name": "source-age", + "value": "259" + }, + { + "name": "strict-transport-security", + "value": "max-age=31536000" + }, + { + "name": "vary", + "value": "Authorization,Accept-Encoding" + }, + { + "name": "via", + "value": "1.1 varnish" + }, + { + "name": "x-cache", + "value": "HIT" + }, + { + "name": "x-cache-hits", + "value": "0" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + }, + { + "name": "x-fastly-request-id", + "value": "7cab98025ce4f5c8a8866dbc5e8764ad39a459c9" + }, + { + "name": "x-frame-options", + "value": "deny" + }, + { + "name": "x-github-request-id", + "value": "D0F0:331C7:156A386:18B3FB7:68944CAF" + }, + { + "name": "x-served-by", + "value": "cache-lis1490034-LIS" + }, + { + "name": "x-timer", + "value": "S1754552962.766187,VS0,VE1" + }, + { + "name": "x-xss-protection", + "value": "1; mode=block" + } + ], + "headersSize": 901, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2025-08-07T07:49:21.619Z", + "time": 277, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 277 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/json/table/fixtures/generated/loadJsonlTable-file-variations-should-load-remote-file-multipart_4008902101/recording.har b/json/table/fixtures/generated/loadJsonlTable-file-variations-should-load-remote-file-multipart_4008902101/recording.har new file mode 100644 index 00000000..9c6b260d --- /dev/null +++ b/json/table/fixtures/generated/loadJsonlTable-file-variations-should-load-remote-file-multipart_4008902101/recording.har @@ -0,0 +1,298 @@ +{ + "log": { + "_recordingName": "loadJsonlTable-file variations-should load remote file (multipart)", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.6" + }, + "entries": [ + { + "_id": "d30ef9a2f7ea66a64aee2d7670e18212", + "_order": 1, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [], + "headersSize": 118, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [], + "url": "https://raw.githubusercontent.com/frictionlessdata/frictionless-py/refs/heads/main/data/table.jsonl" + }, + "response": { + "bodySize": 63, + "content": { + "mimeType": "text/plain; charset=utf-8", + "size": 63, + "text": "{\"id\":1,\"name\":\"english\"}\n{\"id\":2,\"name\":\"中国人\"}\n" + }, + "cookies": [], + "headers": [ + { + "name": "accept-ranges", + "value": "bytes" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "cache-control", + "value": "max-age=300" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-encoding", + "value": "gzip" + }, + { + "name": "content-length", + "value": "63" + }, + { + "name": "content-security-policy", + "value": "default-src 'none'; style-src 'unsafe-inline'; sandbox" + }, + { + "name": "content-type", + "value": "text/plain; charset=utf-8" + }, + { + "name": "cross-origin-resource-policy", + "value": "cross-origin" + }, + { + "name": "date", + "value": "Thu, 07 Aug 2025 07:49:22 GMT" + }, + { + "name": "etag", + "value": "W/\"645c6d84ada374adbb879fdf78d3dedcd90e40bc81e8eeb882d1022ceff52f8f\"" + }, + { + "name": "expires", + "value": "Thu, 07 Aug 2025 07:54:22 GMT" + }, + { + "name": "source-age", + "value": "259" + }, + { + "name": "strict-transport-security", + "value": "max-age=31536000" + }, + { + "name": "vary", + "value": "Authorization,Accept-Encoding" + }, + { + "name": "via", + "value": "1.1 varnish" + }, + { + "name": "x-cache", + "value": "HIT" + }, + { + "name": "x-cache-hits", + "value": "1" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + }, + { + "name": "x-fastly-request-id", + "value": "aead4d190ccdf84757517b4492db0ee64dedcdf5" + }, + { + "name": "x-frame-options", + "value": "deny" + }, + { + "name": "x-github-request-id", + "value": "AC95:3B27B5:145971F:17A3483:68944CB0" + }, + { + "name": "x-served-by", + "value": "cache-lis1490038-LIS" + }, + { + "name": "x-timer", + "value": "S1754552962.137183,VS0,VE1" + }, + { + "name": "x-xss-protection", + "value": "1; mode=block" + } + ], + "headersSize": 902, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2025-08-07T07:49:22.199Z", + "time": 54, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 54 + } + }, + { + "_id": "d30ef9a2f7ea66a64aee2d7670e18212", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [], + "headersSize": 118, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [], + "url": "https://raw.githubusercontent.com/frictionlessdata/frictionless-py/refs/heads/main/data/table.jsonl" + }, + "response": { + "bodySize": 63, + "content": { + "mimeType": "text/plain; charset=utf-8", + "size": 63, + "text": "{\"id\":1,\"name\":\"english\"}\n{\"id\":2,\"name\":\"中国人\"}\n" + }, + "cookies": [], + "headers": [ + { + "name": "accept-ranges", + "value": "bytes" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "cache-control", + "value": "max-age=300" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-encoding", + "value": "gzip" + }, + { + "name": "content-length", + "value": "63" + }, + { + "name": "content-security-policy", + "value": "default-src 'none'; style-src 'unsafe-inline'; sandbox" + }, + { + "name": "content-type", + "value": "text/plain; charset=utf-8" + }, + { + "name": "cross-origin-resource-policy", + "value": "cross-origin" + }, + { + "name": "date", + "value": "Thu, 07 Aug 2025 07:49:22 GMT" + }, + { + "name": "etag", + "value": "W/\"645c6d84ada374adbb879fdf78d3dedcd90e40bc81e8eeb882d1022ceff52f8f\"" + }, + { + "name": "expires", + "value": "Thu, 07 Aug 2025 07:54:22 GMT" + }, + { + "name": "source-age", + "value": "259" + }, + { + "name": "strict-transport-security", + "value": "max-age=31536000" + }, + { + "name": "vary", + "value": "Authorization,Accept-Encoding" + }, + { + "name": "via", + "value": "1.1 varnish" + }, + { + "name": "x-cache", + "value": "HIT" + }, + { + "name": "x-cache-hits", + "value": "1" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + }, + { + "name": "x-fastly-request-id", + "value": "29249ef2d21279598580c6161ea3247a4656c9fa" + }, + { + "name": "x-frame-options", + "value": "deny" + }, + { + "name": "x-github-request-id", + "value": "AC95:3B27B5:145971F:17A3483:68944CB0" + }, + { + "name": "x-served-by", + "value": "cache-lis1490034-LIS" + }, + { + "name": "x-timer", + "value": "S1754552962.137213,VS0,VE1" + }, + { + "name": "x-xss-protection", + "value": "1; mode=block" + } + ], + "headersSize": 902, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2025-08-07T07:49:22.199Z", + "time": 55, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 55 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/json/table/fixtures/generated/loadJsonlTable-file-variations-should-load-remote-file_2569240298/recording.har b/json/table/fixtures/generated/loadJsonlTable-file-variations-should-load-remote-file_2569240298/recording.har new file mode 100644 index 00000000..1124a37a --- /dev/null +++ b/json/table/fixtures/generated/loadJsonlTable-file-variations-should-load-remote-file_2569240298/recording.har @@ -0,0 +1,156 @@ +{ + "log": { + "_recordingName": "loadJsonlTable-file variations-should load remote file", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.6" + }, + "entries": [ + { + "_id": "d30ef9a2f7ea66a64aee2d7670e18212", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [], + "headersSize": 118, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [], + "url": "https://raw.githubusercontent.com/frictionlessdata/frictionless-py/refs/heads/main/data/table.jsonl" + }, + "response": { + "bodySize": 63, + "content": { + "mimeType": "text/plain; charset=utf-8", + "size": 63, + "text": "{\"id\":1,\"name\":\"english\"}\n{\"id\":2,\"name\":\"中国人\"}\n" + }, + "cookies": [], + "headers": [ + { + "name": "accept-ranges", + "value": "bytes" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "cache-control", + "value": "max-age=300" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-encoding", + "value": "gzip" + }, + { + "name": "content-length", + "value": "63" + }, + { + "name": "content-security-policy", + "value": "default-src 'none'; style-src 'unsafe-inline'; sandbox" + }, + { + "name": "content-type", + "value": "text/plain; charset=utf-8" + }, + { + "name": "cross-origin-resource-policy", + "value": "cross-origin" + }, + { + "name": "date", + "value": "Thu, 07 Aug 2025 07:49:22 GMT" + }, + { + "name": "etag", + "value": "W/\"645c6d84ada374adbb879fdf78d3dedcd90e40bc81e8eeb882d1022ceff52f8f\"" + }, + { + "name": "expires", + "value": "Thu, 07 Aug 2025 07:54:22 GMT" + }, + { + "name": "source-age", + "value": "259" + }, + { + "name": "strict-transport-security", + "value": "max-age=31536000" + }, + { + "name": "vary", + "value": "Authorization,Accept-Encoding" + }, + { + "name": "via", + "value": "1.1 varnish" + }, + { + "name": "x-cache", + "value": "HIT" + }, + { + "name": "x-cache-hits", + "value": "0" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + }, + { + "name": "x-fastly-request-id", + "value": "2df8ccbbc50fd27f0d8ebdeb91757d8bfa3a7a5b" + }, + { + "name": "x-frame-options", + "value": "deny" + }, + { + "name": "x-github-request-id", + "value": "AC95:3B27B5:145971F:17A3483:68944CB0" + }, + { + "name": "x-served-by", + "value": "cache-lis1490034-LIS" + }, + { + "name": "x-timer", + "value": "S1754552962.062668,VS0,VE1" + }, + { + "name": "x-xss-protection", + "value": "1; mode=block" + } + ], + "headersSize": 902, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2025-08-07T07:49:22.121Z", + "time": 67, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 67 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/json/table/index.ts b/json/table/index.ts new file mode 100644 index 00000000..357f58c2 --- /dev/null +++ b/json/table/index.ts @@ -0,0 +1,2 @@ +export { loadJsonTable, loadJsonlTable } from "./load.ts" +export { saveJsonTable, saveJsonlTable } from "./save.ts" diff --git a/json/table/load.spec.ts b/json/table/load.spec.ts new file mode 100644 index 00000000..8251c6ea --- /dev/null +++ b/json/table/load.spec.ts @@ -0,0 +1,227 @@ +import { writeTempFile } from "@dpkit/file" +import { useRecording } from "@dpkit/test" +import { describe, expect, it } from "vitest" +import { loadJsonTable, loadJsonlTable } from "./load.ts" + +useRecording() + +describe("loadJsonTable", () => { + describe("file variations", () => { + it("should load local file", async () => { + const body = '[{"id":1,"name":"english"},{"id":2,"name":"中文"}]' + const path = await writeTempFile(body) + + const table = await loadJsonTable({ path }) + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + ]) + }) + + it("should load local file (multipart)", async () => { + const body = '[{"id":1,"name":"english"},{"id":2,"name":"中文"}]' + const path1 = await writeTempFile(body) + const path2 = await writeTempFile(body) + + const table = await loadJsonTable({ path: [path1, path2] }) + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + ]) + }) + + it("should load remote file", async () => { + const table = await loadJsonTable({ + path: "https://raw.githubusercontent.com/frictionlessdata/frictionless-py/refs/heads/main/data/table.keyed.json", + }) + + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中国人" }, + ]) + }) + + it("should load remote file (multipart)", async () => { + const table = await loadJsonTable({ + path: [ + "https://raw.githubusercontent.com/frictionlessdata/frictionless-py/refs/heads/main/data/table.keyed.json", + "https://raw.githubusercontent.com/frictionlessdata/frictionless-py/refs/heads/main/data/table.keyed.json", + ], + }) + + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中国人" }, + { id: 1, name: "english" }, + { id: 2, name: "中国人" }, + ]) + }) + }) + + describe("dialect variations", () => { + it("should handle property", async () => { + const body = '{"key": [{"id":1,"name":"english"},{"id":2,"name":"中文"}]}' + const path = await writeTempFile(body) + + const table = await loadJsonTable({ + path, + dialect: { property: "key" }, + }) + + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + ]) + }) + + it("should handle item keys", async () => { + const body = '[{"id":1,"name":"english"},{"id":2,"name":"中文"}]' + const path = await writeTempFile(body) + + const table = await loadJsonTable({ + path, + dialect: { itemKeys: ["name"] }, + }) + + expect((await table.collect()).toRecords()).toEqual([ + { name: "english" }, + { name: "中文" }, + ]) + }) + + it("should handle item type (array)", async () => { + const body = '[["id","name"],[1,"english"],[2,"中文"]]' + const path = await writeTempFile(body) + + const table = await loadJsonTable({ + path, + dialect: { itemType: "array" }, + }) + + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + ]) + }) + + it("should load item type (object)", async () => { + const body = '[{"id":1,"name":"english"},{"id":2,"name":"中文"}]' + const path = await writeTempFile(body) + + const table = await loadJsonTable({ + path, + dialect: { itemType: "object" }, + }) + + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + ]) + }) + }) +}) + +describe("loadJsonlTable", () => { + describe("file variations", () => { + it("should load local file", async () => { + const body = '{"id":1,"name":"english"}\n{"id":2,"name":"中文"}' + const path = await writeTempFile(body) + + const table = await loadJsonlTable({ path }) + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + ]) + }) + + it("should load local file (multipart)", async () => { + const body = '{"id":1,"name":"english"}\n{"id":2,"name":"中文"}' + const path1 = await writeTempFile(body) + const path2 = await writeTempFile(body) + + const table = await loadJsonlTable({ path: [path1, path2] }) + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + ]) + }) + + it("should load remote file", async () => { + const table = await loadJsonlTable({ + path: "https://raw.githubusercontent.com/frictionlessdata/frictionless-py/refs/heads/main/data/table.jsonl", + }) + + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中国人" }, + ]) + }) + + it("should load remote file (multipart)", async () => { + const table = await loadJsonlTable({ + path: [ + "https://raw.githubusercontent.com/frictionlessdata/frictionless-py/refs/heads/main/data/table.jsonl", + "https://raw.githubusercontent.com/frictionlessdata/frictionless-py/refs/heads/main/data/table.jsonl", + ], + }) + + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中国人" }, + { id: 1, name: "english" }, + { id: 2, name: "中国人" }, + ]) + }) + }) + + describe("dialect variations", () => { + it("should handle item keys", async () => { + const body = '{"id":1,"name":"english"}\n{"id":2,"name":"中文"}' + const path = await writeTempFile(body) + + const table = await loadJsonlTable({ + path, + dialect: { itemKeys: ["name"] }, + }) + + expect((await table.collect()).toRecords()).toEqual([ + { name: "english" }, + { name: "中文" }, + ]) + }) + + it("should handle item type (array)", async () => { + const body = '["id","name"]\n[1,"english"]\n[2,"中文"]' + const path = await writeTempFile(body) + + const table = await loadJsonlTable({ + path, + dialect: { itemType: "array" }, + }) + + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + ]) + }) + + it("should load item type (object)", async () => { + const body = '{"id":1,"name":"english"}\n{"id":2,"name":"中文"}' + const path = await writeTempFile(body) + + const table = await loadJsonlTable({ + path, + dialect: { itemType: "object" }, + }) + + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + ]) + }) + }) +}) diff --git a/json/table/load.ts b/json/table/load.ts new file mode 100644 index 00000000..0158befc --- /dev/null +++ b/json/table/load.ts @@ -0,0 +1,82 @@ +import { readFile } from "node:fs/promises" +import type { Dialect, Resource } from "@dpkit/core" +import { loadDialect } from "@dpkit/core" +import { prefetchFiles } from "@dpkit/file" +import type { Table } from "@dpkit/table" +import { concat } from "nodejs-polars" +import { DataFrame, scanJson } from "nodejs-polars" +import { decodeJsonBuffer } from "../buffer/index.ts" + +export async function loadJsonTable(resource: Partial) { + return await loadTable(resource, { isLines: false }) +} + +export async function loadJsonlTable(resource: Partial) { + return await loadTable(resource, { isLines: true }) +} + +async function loadTable( + resource: Partial, + options: { isLines: boolean }, +) { + const { isLines } = options + + const paths = await prefetchFiles(resource.path) + if (!paths.length) { + return DataFrame().lazy() + } + + const dialect = + typeof resource.dialect === "string" + ? await loadDialect(resource.dialect) + : resource.dialect + + const tables: Table[] = [] + for (const path of paths) { + if (isLines && !dialect) { + const table = scanJson(path) + tables.push(table) + continue + } + + const buffer = await readFile(path) + let data = decodeJsonBuffer(buffer, { isLines }) + if (dialect) { + data = processData(data, dialect) + } + + const table = DataFrame(data).lazy() + tables.push(table) + } + + const table = concat(tables) + return table +} + +function processData(data: any, dialect: Dialect) { + if (dialect.property) { + data = data[dialect.property] + } + + if (dialect.itemType === "array") { + const keys = data[0] + + data = data + .slice(1) + .map((row: any) => + Object.fromEntries( + keys.map((key: any, index: number) => [key, row[index]]), + ), + ) + } + + if (dialect.itemKeys) { + const keys = dialect.itemKeys + + data = data.map((row: any) => + Object.fromEntries(keys.map((key: any) => [key, row[key]])), + ) + } + + return data +} diff --git a/json/table/parse.ts b/json/table/parse.ts new file mode 100644 index 00000000..a516b88d --- /dev/null +++ b/json/table/parse.ts @@ -0,0 +1,5 @@ +export function parseJson(string: string, options: { isLines: boolean }) { + return options.isLines + ? string.split("\n").map(line => JSON.parse(line)) + : JSON.parse(string) +} diff --git a/json/table/save.spec.ts b/json/table/save.spec.ts new file mode 100644 index 00000000..b3ce57a7 --- /dev/null +++ b/json/table/save.spec.ts @@ -0,0 +1,100 @@ +import { readFile } from "node:fs/promises" +import { getTempFilePath } from "@dpkit/file" +import { readRecords } from "nodejs-polars" +import { describe, expect, it } from "vitest" +import { saveJsonTable, saveJsonlTable } from "./save.ts" + +const row1 = { id: 1, name: "english" } +const row2 = { id: 2, name: "中文" } +const table = readRecords([row1, row2]).lazy() + +describe("saveJsonTable", () => { + it("should save table to file", async () => { + const path = getTempFilePath() + await saveJsonTable(table, { path }) + + const content = await readFile(path, "utf-8") + expect(content).toEqual(JSON.stringify([row1, row2], null, 2)) + }) + + it("should handle property", async () => { + const path = getTempFilePath() + await saveJsonTable(table, { path, dialect: { property: "key" } }) + + const content = await readFile(path, "utf-8") + expect(content).toEqual(JSON.stringify({ key: [row1, row2] }, null, 2)) + }) + + it("should handle item keys", async () => { + const path = getTempFilePath() + await saveJsonTable(table, { path, dialect: { itemKeys: ["name"] } }) + + const content = await readFile(path, "utf-8") + expect(content).toEqual( + JSON.stringify([{ name: row1.name }, { name: row2.name }], null, 2), + ) + }) + + it("should handle item type (array)", async () => { + const path = getTempFilePath() + await saveJsonTable(table, { path, dialect: { itemType: "array" } }) + + const content = await readFile(path, "utf-8") + expect(content).toEqual( + JSON.stringify( + [Object.keys(row1), Object.values(row1), Object.values(row2)], + null, + 2, + ), + ) + }) +}) + +describe("saveJsonlTable", () => { + it("should save table to file", async () => { + const path = getTempFilePath() + await saveJsonlTable(table, { path }) + + const content = await readFile(path, "utf-8") + expect(content).toEqual( + [JSON.stringify(row1), JSON.stringify(row2)].join("\n"), + ) + }) + + it("should handle item keys", async () => { + const path = getTempFilePath() + await saveJsonlTable(table, { path, dialect: { itemKeys: ["name"] } }) + + const content = await readFile(path, "utf-8") + expect(content).toEqual( + [ + JSON.stringify({ name: row1.name }), + JSON.stringify({ name: row2.name }), + ].join("\n"), + ) + }) + + it("should handle item type (array)", async () => { + const path = getTempFilePath() + await saveJsonlTable(table, { path, dialect: { itemType: "array" } }) + + const content = await readFile(path, "utf-8") + expect(content).toEqual( + [ + JSON.stringify(Object.keys(row1)), + JSON.stringify(Object.values(row1)), + JSON.stringify(Object.values(row2)), + ].join("\n"), + ) + }) + + it("should handle item type (object)", async () => { + const path = getTempFilePath() + await saveJsonlTable(table, { path, dialect: { itemType: "object" } }) + + const content = await readFile(path, "utf-8") + expect(content).toEqual( + [JSON.stringify(row1), JSON.stringify(row2)].join("\n"), + ) + }) +}) diff --git a/json/table/save.ts b/json/table/save.ts new file mode 100644 index 00000000..4298d6e2 --- /dev/null +++ b/json/table/save.ts @@ -0,0 +1,59 @@ +import type { Dialect } from "@dpkit/core" +import { saveFile } from "@dpkit/file" +import type { SaveTableOptions, Table } from "@dpkit/table" +import { decodeJsonBuffer, encodeJsonBuffer } from "../buffer/index.ts" + +// TODO: rebase on sinkJSON when it is available +// https://github.com/pola-rs/nodejs-polars/issues/353 + +export async function saveJsonTable(table: Table, options: SaveTableOptions) { + return await saveTable(table, { ...options, isLines: false }) +} + +export async function saveJsonlTable(table: Table, options: SaveTableOptions) { + return await saveTable(table, { ...options, isLines: true }) +} + +async function saveTable( + table: Table, + options: SaveTableOptions & { isLines: boolean }, +) { + const { path, dialect, isLines } = options + const df = await table.collect() + + // We use polars to serialize the data + // But encode it manually to support dialects/formatting + let buffer = df.writeJSON({ format: isLines ? "lines" : "json" }) + let data = decodeJsonBuffer(buffer, { isLines }) + + if (dialect) { + data = processData(data, dialect) + } + + buffer = encodeJsonBuffer(data, { isLines }) + await saveFile(path, buffer) + + return path +} + +function processData(records: Record[], dialect: Dialect) { + let data: any = records + + if (dialect.itemKeys) { + const keys = dialect.itemKeys + data = data.map((row: any) => + Object.fromEntries(keys.map((key: any) => [key, row[key]])), + ) + } + + if (dialect.itemType === "array") { + const keys = dialect.itemKeys ?? Object.keys(data[0]) + data = [keys, ...data.map((row: any) => keys.map((key: any) => row[key]))] + } + + if (dialect.property) { + data = { [dialect.property]: data } + } + + return data +} diff --git a/json/tsconfig.json b/json/tsconfig.json index 7be40230..3c43903c 100644 --- a/json/tsconfig.json +++ b/json/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/json/typedoc.json b/json/typedoc.json new file mode 100644 index 00000000..f8e49f3a --- /dev/null +++ b/json/typedoc.json @@ -0,0 +1,4 @@ +{ + "entryPoints": ["index.ts"], + "skipErrorChecking": true +} diff --git a/ods/package.json b/ods/package.json index 41fac771..278ebc85 100644 --- a/ods/package.json +++ b/ods/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/ods", "type": "module", - "main": "build/index.js", "version": "0.2.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,6 +20,6 @@ "ods" ], "scripts": { - "build": "tsc --build" + "build": "tsc" } } diff --git a/ods/tsconfig.json b/ods/tsconfig.json index 7be40230..3c43903c 100644 --- a/ods/tsconfig.json +++ b/ods/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/package.json b/package.json index 0faad37a..d7856e83 100644 --- a/package.json +++ b/package.json @@ -7,31 +7,32 @@ "pnpm": "^10.0.0" }, "scripts": { - "build": "pnpm -r build", + "build": "pnpm -F '!docs' build", "bump": "ncu -ws -u", "ci:install": "pnpm install --ignore-scripts", "ci:publish": "pnpm -r publish --access public --ignore-scripts && changeset tag", "check": "pnpm run lint && pnpm run type", + "clean": "rm pnpm-lock.yaml && find . -name 'node_modules' -type d -prune -print -exec rm -rf '{}' +", "coverage": "vitest --ui", "format": "biome check --write", "lint": "biome check", "prepare": "husky", - "start": "pnpm -F docs start", "spec": "vitest run", "test": "pnpm check && pnpm run spec", - "type": "tsc" + "type": "tsc --noEmit" }, "devDependencies": { "@biomejs/biome": "1.9.4", "@changesets/cli": "2.29.5", - "@types/node": "22.15.31", + "@types/node": "24.2.0", "@vitest/coverage-v8": "3.1.4", "@vitest/ui": "3.1.4", + "execa": "9.6.0", "husky": "9.1.7", "npm-check-updates": "18.0.1", "tempy": "3.1.0", "type-fest": "^4.41.0", - "typescript": "5.8.3", + "typescript": "5.9.2", "vitest": "3.1.4" }, "packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977" diff --git a/parquet/index.ts b/parquet/index.ts index e69de29b..5f4f33d9 100644 --- a/parquet/index.ts +++ b/parquet/index.ts @@ -0,0 +1,2 @@ +export * from "./table/index.ts" +export * from "./plugin.ts" diff --git a/parquet/package.json b/parquet/package.json index 19693cdf..07418497 100644 --- a/parquet/package.json +++ b/parquet/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/parquet", "type": "module", - "main": "build/index.js", "version": "0.2.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,6 +20,16 @@ "parquet" ], "scripts": { - "build": "tsc --build" + "build": "tsc" + }, + "dependencies": { + "@dpkit/core": "workspace:*", + "@dpkit/file": "workspace:*", + "@dpkit/table": "workspace:*", + "csv-sniffer": "^0.1.1", + "nodejs-polars": "^0.21.0" + }, + "devDependencies": { + "@dpkit/test": "workspace:*" } } diff --git a/parquet/plugin.ts b/parquet/plugin.ts new file mode 100644 index 00000000..4aacf435 --- /dev/null +++ b/parquet/plugin.ts @@ -0,0 +1,26 @@ +import type { Resource } from "@dpkit/core" +import { inferFormat } from "@dpkit/core" +import type { TablePlugin } from "@dpkit/table" +import type { SaveTableOptions, Table } from "@dpkit/table" +import { loadParquetTable, saveParquetTable } from "./table/index.ts" + +export class ParquetPlugin implements TablePlugin { + async loadTable(resource: Partial) { + const isParquet = getIsParquet(resource) + if (!isParquet) return undefined + + return await loadParquetTable(resource) + } + + async saveTable(table: Table, options: SaveTableOptions) { + const isParquet = getIsParquet(options) + if (!isParquet) return undefined + + return await saveParquetTable(table, options) + } +} + +function getIsParquet(resource: Partial) { + const format = inferFormat(resource) + return format === "parquet" +} diff --git a/parquet/table/fixtures/generated/loadParquetTable-file-variations-should-load-remote-file-multipart_3893757127/recording.har b/parquet/table/fixtures/generated/loadParquetTable-file-variations-should-load-remote-file-multipart_3893757127/recording.har new file mode 100644 index 00000000..ede41ba8 --- /dev/null +++ b/parquet/table/fixtures/generated/loadParquetTable-file-variations-should-load-remote-file-multipart_3893757127/recording.har @@ -0,0 +1,292 @@ +{ + "log": { + "_recordingName": "loadParquetTable-file variations-should load remote file (multipart)", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.6" + }, + "entries": [ + { + "_id": "a64f4353af2adbbc2f2eed3c4889f479", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [], + "headersSize": 109, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [], + "url": "https://github.com/frictionlessdata/frictionless-py/raw/refs/heads/main/data/table.parquet" + }, + "response": { + "bodySize": 897, + "content": { + "encoding": "base64", + "mimeType": "application/octet-stream", + "size": 897, + "text": "UEFSMRUAFTwVPCwVBBUAFQYVCAAAAgAAAAQBAQAAAAAAAAACAAAAAAAAAAAAAAAAAAAAFQAVTBVMLBUEFQAVBhUIAAACAAAABAEHAAAAZW5nbGlzaAkAAADkuK3lm73kuroAAAAAAAAAABUCGTxIBnNjaGVtYRUEABUEFYABFQIYAmlkABUMJQIYBG5hbWUlAAAWBBkcGSwmZhwVBBkVABkYAmlkFQAWBBZeFl4ZABYIPBgIAgAAAAAAAAAYCAEAAAAAAAAAFgAAGRwVABUAFQIAAAAm1AEcFQwZFQAZGARuYW1lFQAWBBZuFm4ZABZmPBgJ5Lit5Zu95Lq6GAdlbmdsaXNoFgAAGRwVABUAFQIAAAAWzAEWBAAZHBgGcGFuZGFzGKUEeyJjb2x1bW5faW5kZXhlcyI6IFt7ImZpZWxkX25hbWUiOiBudWxsLCAibWV0YWRhdGEiOiBudWxsLCAibmFtZSI6IG51bGwsICJudW1weV90eXBlIjogIm9iamVjdCIsICJwYW5kYXNfdHlwZSI6ICJtaXhlZC1pbnRlZ2VyIn1dLCAiY29sdW1ucyI6IFt7ImZpZWxkX25hbWUiOiAiaWQiLCAibWV0YWRhdGEiOiBudWxsLCAibmFtZSI6ICJpZCIsICJudW1weV90eXBlIjogImludDY0IiwgInBhbmRhc190eXBlIjogImludDY0In0sIHsiZmllbGRfbmFtZSI6ICJuYW1lIiwgIm1ldGFkYXRhIjogbnVsbCwgIm5hbWUiOiAibmFtZSIsICJudW1weV90eXBlIjogIm9iamVjdCIsICJwYW5kYXNfdHlwZSI6ICJ1bmljb2RlIn1dLCAiY3JlYXRvciI6IHsibGlicmFyeSI6ICJmYXN0cGFycXVldCIsICJ2ZXJzaW9uIjogIjAuOC4xIn0sICJpbmRleF9jb2x1bW5zIjogW3sia2luZCI6ICJyYW5nZSIsICJuYW1lIjogbnVsbCwgInN0YXJ0IjogMCwgInN0ZXAiOiAxLCAic3RvcCI6IDJ9XSwgInBhbmRhc192ZXJzaW9uIjogIjEuNC4zIiwgInBhcnRpdGlvbl9jb2x1bW5zIjogW119ABgqZmFzdHBhcnF1ZXQtcHl0aG9uIHZlcnNpb24gMC44LjEgKGJ1aWxkIDApAA8DAABQQVIx" + }, + "cookies": [], + "headers": [ + { + "name": "accept-ranges", + "value": "bytes" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "cache-control", + "value": "max-age=300" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "897" + }, + { + "name": "content-security-policy", + "value": "default-src 'none'; style-src 'unsafe-inline'; sandbox" + }, + { + "name": "content-type", + "value": "application/octet-stream" + }, + { + "name": "cross-origin-resource-policy", + "value": "cross-origin" + }, + { + "name": "date", + "value": "Thu, 07 Aug 2025 07:49:23 GMT" + }, + { + "name": "etag", + "value": "W/\"8c6326a59a7e2ed794cec3dc0f545bff3f4eed4c8d715908f45ffbd920b77adb\"" + }, + { + "name": "expires", + "value": "Thu, 07 Aug 2025 07:54:23 GMT" + }, + { + "name": "source-age", + "value": "0" + }, + { + "name": "strict-transport-security", + "value": "max-age=31536000" + }, + { + "name": "vary", + "value": "Authorization,Accept-Encoding" + }, + { + "name": "via", + "value": "1.1 varnish" + }, + { + "name": "x-cache", + "value": "HIT" + }, + { + "name": "x-cache-hits", + "value": "1" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + }, + { + "name": "x-fastly-request-id", + "value": "89390f25c8caca11f9b7de596ca61cb53da4f98b" + }, + { + "name": "x-frame-options", + "value": "deny" + }, + { + "name": "x-github-request-id", + "value": "85FE:256E19:15CE1E6:192ED85:68945A82" + }, + { + "name": "x-served-by", + "value": "cache-lis1490023-LIS" + }, + { + "name": "x-timer", + "value": "S1754552964.741242,VS0,VE1" + }, + { + "name": "x-xss-protection", + "value": "1; mode=block" + } + ], + "headersSize": 876, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2025-08-07T07:49:23.683Z", + "time": 167, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 167 + } + }, + { + "_id": "a64f4353af2adbbc2f2eed3c4889f479", + "_order": 1, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [], + "headersSize": 109, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [], + "url": "https://github.com/frictionlessdata/frictionless-py/raw/refs/heads/main/data/table.parquet" + }, + "response": { + "bodySize": 897, + "content": { + "encoding": "base64", + "mimeType": "application/octet-stream", + "size": 897, + "text": "UEFSMRUAFTwVPCwVBBUAFQYVCAAAAgAAAAQBAQAAAAAAAAACAAAAAAAAAAAAAAAAAAAAFQAVTBVMLBUEFQAVBhUIAAACAAAABAEHAAAAZW5nbGlzaAkAAADkuK3lm73kuroAAAAAAAAAABUCGTxIBnNjaGVtYRUEABUEFYABFQIYAmlkABUMJQIYBG5hbWUlAAAWBBkcGSwmZhwVBBkVABkYAmlkFQAWBBZeFl4ZABYIPBgIAgAAAAAAAAAYCAEAAAAAAAAAFgAAGRwVABUAFQIAAAAm1AEcFQwZFQAZGARuYW1lFQAWBBZuFm4ZABZmPBgJ5Lit5Zu95Lq6GAdlbmdsaXNoFgAAGRwVABUAFQIAAAAWzAEWBAAZHBgGcGFuZGFzGKUEeyJjb2x1bW5faW5kZXhlcyI6IFt7ImZpZWxkX25hbWUiOiBudWxsLCAibWV0YWRhdGEiOiBudWxsLCAibmFtZSI6IG51bGwsICJudW1weV90eXBlIjogIm9iamVjdCIsICJwYW5kYXNfdHlwZSI6ICJtaXhlZC1pbnRlZ2VyIn1dLCAiY29sdW1ucyI6IFt7ImZpZWxkX25hbWUiOiAiaWQiLCAibWV0YWRhdGEiOiBudWxsLCAibmFtZSI6ICJpZCIsICJudW1weV90eXBlIjogImludDY0IiwgInBhbmRhc190eXBlIjogImludDY0In0sIHsiZmllbGRfbmFtZSI6ICJuYW1lIiwgIm1ldGFkYXRhIjogbnVsbCwgIm5hbWUiOiAibmFtZSIsICJudW1weV90eXBlIjogIm9iamVjdCIsICJwYW5kYXNfdHlwZSI6ICJ1bmljb2RlIn1dLCAiY3JlYXRvciI6IHsibGlicmFyeSI6ICJmYXN0cGFycXVldCIsICJ2ZXJzaW9uIjogIjAuOC4xIn0sICJpbmRleF9jb2x1bW5zIjogW3sia2luZCI6ICJyYW5nZSIsICJuYW1lIjogbnVsbCwgInN0YXJ0IjogMCwgInN0ZXAiOiAxLCAic3RvcCI6IDJ9XSwgInBhbmRhc192ZXJzaW9uIjogIjEuNC4zIiwgInBhcnRpdGlvbl9jb2x1bW5zIjogW119ABgqZmFzdHBhcnF1ZXQtcHl0aG9uIHZlcnNpb24gMC44LjEgKGJ1aWxkIDApAA8DAABQQVIx" + }, + "cookies": [], + "headers": [ + { + "name": "accept-ranges", + "value": "bytes" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "cache-control", + "value": "max-age=300" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "897" + }, + { + "name": "content-security-policy", + "value": "default-src 'none'; style-src 'unsafe-inline'; sandbox" + }, + { + "name": "content-type", + "value": "application/octet-stream" + }, + { + "name": "cross-origin-resource-policy", + "value": "cross-origin" + }, + { + "name": "date", + "value": "Thu, 07 Aug 2025 07:49:23 GMT" + }, + { + "name": "etag", + "value": "W/\"8c6326a59a7e2ed794cec3dc0f545bff3f4eed4c8d715908f45ffbd920b77adb\"" + }, + { + "name": "expires", + "value": "Thu, 07 Aug 2025 07:54:23 GMT" + }, + { + "name": "source-age", + "value": "0" + }, + { + "name": "strict-transport-security", + "value": "max-age=31536000" + }, + { + "name": "vary", + "value": "Authorization,Accept-Encoding" + }, + { + "name": "via", + "value": "1.1 varnish" + }, + { + "name": "x-cache", + "value": "HIT" + }, + { + "name": "x-cache-hits", + "value": "2" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + }, + { + "name": "x-fastly-request-id", + "value": "8a0c127150f660b5a9169f6da3d0ff8e8380431b" + }, + { + "name": "x-frame-options", + "value": "deny" + }, + { + "name": "x-github-request-id", + "value": "85FE:256E19:15CE1E6:192ED85:68945A82" + }, + { + "name": "x-served-by", + "value": "cache-lis1490023-LIS" + }, + { + "name": "x-timer", + "value": "S1754552964.948899,VS0,VE0" + }, + { + "name": "x-xss-protection", + "value": "1; mode=block" + } + ], + "headersSize": 876, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2025-08-07T07:49:23.683Z", + "time": 382, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 382 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/parquet/table/fixtures/generated/loadParquetTable-file-variations-should-load-remote-file_3029162600/recording.har b/parquet/table/fixtures/generated/loadParquetTable-file-variations-should-load-remote-file_3029162600/recording.har new file mode 100644 index 00000000..0f756c8a --- /dev/null +++ b/parquet/table/fixtures/generated/loadParquetTable-file-variations-should-load-remote-file_3029162600/recording.har @@ -0,0 +1,153 @@ +{ + "log": { + "_recordingName": "loadParquetTable-file variations-should load remote file", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.6" + }, + "entries": [ + { + "_id": "a64f4353af2adbbc2f2eed3c4889f479", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [], + "headersSize": 109, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [], + "url": "https://github.com/frictionlessdata/frictionless-py/raw/refs/heads/main/data/table.parquet" + }, + "response": { + "bodySize": 897, + "content": { + "encoding": "base64", + "mimeType": "application/octet-stream", + "size": 897, + "text": "UEFSMRUAFTwVPCwVBBUAFQYVCAAAAgAAAAQBAQAAAAAAAAACAAAAAAAAAAAAAAAAAAAAFQAVTBVMLBUEFQAVBhUIAAACAAAABAEHAAAAZW5nbGlzaAkAAADkuK3lm73kuroAAAAAAAAAABUCGTxIBnNjaGVtYRUEABUEFYABFQIYAmlkABUMJQIYBG5hbWUlAAAWBBkcGSwmZhwVBBkVABkYAmlkFQAWBBZeFl4ZABYIPBgIAgAAAAAAAAAYCAEAAAAAAAAAFgAAGRwVABUAFQIAAAAm1AEcFQwZFQAZGARuYW1lFQAWBBZuFm4ZABZmPBgJ5Lit5Zu95Lq6GAdlbmdsaXNoFgAAGRwVABUAFQIAAAAWzAEWBAAZHBgGcGFuZGFzGKUEeyJjb2x1bW5faW5kZXhlcyI6IFt7ImZpZWxkX25hbWUiOiBudWxsLCAibWV0YWRhdGEiOiBudWxsLCAibmFtZSI6IG51bGwsICJudW1weV90eXBlIjogIm9iamVjdCIsICJwYW5kYXNfdHlwZSI6ICJtaXhlZC1pbnRlZ2VyIn1dLCAiY29sdW1ucyI6IFt7ImZpZWxkX25hbWUiOiAiaWQiLCAibWV0YWRhdGEiOiBudWxsLCAibmFtZSI6ICJpZCIsICJudW1weV90eXBlIjogImludDY0IiwgInBhbmRhc190eXBlIjogImludDY0In0sIHsiZmllbGRfbmFtZSI6ICJuYW1lIiwgIm1ldGFkYXRhIjogbnVsbCwgIm5hbWUiOiAibmFtZSIsICJudW1weV90eXBlIjogIm9iamVjdCIsICJwYW5kYXNfdHlwZSI6ICJ1bmljb2RlIn1dLCAiY3JlYXRvciI6IHsibGlicmFyeSI6ICJmYXN0cGFycXVldCIsICJ2ZXJzaW9uIjogIjAuOC4xIn0sICJpbmRleF9jb2x1bW5zIjogW3sia2luZCI6ICJyYW5nZSIsICJuYW1lIjogbnVsbCwgInN0YXJ0IjogMCwgInN0ZXAiOiAxLCAic3RvcCI6IDJ9XSwgInBhbmRhc192ZXJzaW9uIjogIjEuNC4zIiwgInBhcnRpdGlvbl9jb2x1bW5zIjogW119ABgqZmFzdHBhcnF1ZXQtcHl0aG9uIHZlcnNpb24gMC44LjEgKGJ1aWxkIDApAA8DAABQQVIx" + }, + "cookies": [], + "headers": [ + { + "name": "accept-ranges", + "value": "bytes" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "cache-control", + "value": "max-age=300" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "897" + }, + { + "name": "content-security-policy", + "value": "default-src 'none'; style-src 'unsafe-inline'; sandbox" + }, + { + "name": "content-type", + "value": "application/octet-stream" + }, + { + "name": "cross-origin-resource-policy", + "value": "cross-origin" + }, + { + "name": "date", + "value": "Thu, 07 Aug 2025 07:49:23 GMT" + }, + { + "name": "etag", + "value": "W/\"8c6326a59a7e2ed794cec3dc0f545bff3f4eed4c8d715908f45ffbd920b77adb\"" + }, + { + "name": "expires", + "value": "Thu, 07 Aug 2025 07:54:23 GMT" + }, + { + "name": "source-age", + "value": "0" + }, + { + "name": "strict-transport-security", + "value": "max-age=31536000" + }, + { + "name": "vary", + "value": "Authorization,Accept-Encoding" + }, + { + "name": "via", + "value": "1.1 varnish" + }, + { + "name": "x-cache", + "value": "MISS" + }, + { + "name": "x-cache-hits", + "value": "0" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + }, + { + "name": "x-fastly-request-id", + "value": "09370dcce05b24421c183e299afc926975498506" + }, + { + "name": "x-frame-options", + "value": "deny" + }, + { + "name": "x-github-request-id", + "value": "85FE:256E19:15CE1E6:192ED85:68945A82" + }, + { + "name": "x-served-by", + "value": "cache-lis1490023-LIS" + }, + { + "name": "x-timer", + "value": "S1754552963.274766,VS0,VE188" + }, + { + "name": "x-xss-protection", + "value": "1; mode=block" + } + ], + "headersSize": 879, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2025-08-07T07:49:22.588Z", + "time": 1053, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1053 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/parquet/table/fixtures/table.parquet b/parquet/table/fixtures/table.parquet new file mode 100644 index 00000000..4dd3202a Binary files /dev/null and b/parquet/table/fixtures/table.parquet differ diff --git a/parquet/table/index.ts b/parquet/table/index.ts new file mode 100644 index 00000000..9287f51f --- /dev/null +++ b/parquet/table/index.ts @@ -0,0 +1,2 @@ +export { loadParquetTable } from "./load.ts" +export { saveParquetTable } from "./save.ts" diff --git a/parquet/table/load.spec.ts b/parquet/table/load.spec.ts new file mode 100644 index 00000000..36a7cbf9 --- /dev/null +++ b/parquet/table/load.spec.ts @@ -0,0 +1,64 @@ +import { getTempFilePath } from "@dpkit/file" +import { useRecording } from "@dpkit/test" +import { DataFrame } from "nodejs-polars" +import { describe, expect, it } from "vitest" +import { loadParquetTable } from "./load.ts" + +describe("loadParquetTable", () => { + useRecording() + + describe("file variations", () => { + it("should load local file", async () => { + const path = getTempFilePath() + DataFrame({ id: [1, 2], name: ["english", "中文"] }).writeParquet(path) + + const table = await loadParquetTable({ path }) + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + ]) + }) + + it("should load local file (multipart)", async () => { + const path1 = getTempFilePath() + const path2 = getTempFilePath() + DataFrame({ id: [1, 2], name: ["english", "中文"] }).writeParquet(path1) + DataFrame({ id: [1, 2], name: ["english", "中文"] }).writeParquet(path2) + + const table = await loadParquetTable({ path: [path1, path2] }) + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + { id: 1, name: "english" }, + { id: 2, name: "中文" }, + ]) + }) + + it("should load remote file", async () => { + const table = await loadParquetTable({ + path: "https://github.com/frictionlessdata/frictionless-py/raw/refs/heads/main/data/table.parquet", + }) + + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中国人" }, + ]) + }) + + it("should load remote file (multipart)", async () => { + const table = await loadParquetTable({ + path: [ + "https://github.com/frictionlessdata/frictionless-py/raw/refs/heads/main/data/table.parquet", + "https://github.com/frictionlessdata/frictionless-py/raw/refs/heads/main/data/table.parquet", + ], + }) + + expect((await table.collect()).toRecords()).toEqual([ + { id: 1, name: "english" }, + { id: 2, name: "中国人" }, + { id: 1, name: "english" }, + { id: 2, name: "中国人" }, + ]) + }) + }) +}) diff --git a/parquet/table/load.ts b/parquet/table/load.ts new file mode 100644 index 00000000..6622669a --- /dev/null +++ b/parquet/table/load.ts @@ -0,0 +1,19 @@ +import type { Resource } from "@dpkit/core" +import { prefetchFiles } from "@dpkit/file" +import { concat } from "nodejs-polars" +import { DataFrame } from "nodejs-polars" +import { scanParquet } from "nodejs-polars" + +export async function loadParquetTable(resource: Partial) { + const [firstPath, ...restPaths] = await prefetchFiles(resource.path) + if (!firstPath) { + return DataFrame().lazy() + } + + let table = scanParquet(firstPath) + if (restPaths.length) { + table = concat([table, ...restPaths.map(path => scanParquet(path))]) + } + + return table +} diff --git a/parquet/table/save.spec.ts b/parquet/table/save.spec.ts new file mode 100644 index 00000000..ae0c1abc --- /dev/null +++ b/parquet/table/save.spec.ts @@ -0,0 +1,24 @@ +import { getTempFilePath } from "@dpkit/file" +import { DataFrame } from "nodejs-polars" +import { describe, expect, it } from "vitest" +import { loadParquetTable } from "./load.ts" +import { saveParquetTable } from "./save.ts" + +describe("saveParquetTable", () => { + it("should save table to Parquet file", async () => { + const path = getTempFilePath() + const source = DataFrame({ + id: [1.0, 2.0, 3.0], + name: ["Alice", "Bob", "Charlie"], + }).lazy() + + await saveParquetTable(source, { path }) + + const target = await loadParquetTable({ path }) + expect((await target.collect()).toRecords()).toEqual([ + { id: 1.0, name: "Alice" }, + { id: 2.0, name: "Bob" }, + { id: 3.0, name: "Charlie" }, + ]) + }) +}) diff --git a/parquet/table/save.ts b/parquet/table/save.ts new file mode 100644 index 00000000..4fae1f09 --- /dev/null +++ b/parquet/table/save.ts @@ -0,0 +1,16 @@ +import type { SaveTableOptions, Table } from "@dpkit/table" + +export async function saveParquetTable( + table: Table, + options: SaveTableOptions, +) { + const { path } = options + + await table + .sinkParquet(path, { + maintainOrder: true, + }) + .collect() + + return path +} diff --git a/parquet/tsconfig.json b/parquet/tsconfig.json index 7be40230..3c43903c 100644 --- a/parquet/tsconfig.json +++ b/parquet/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/parquet/typedoc.json b/parquet/typedoc.json new file mode 100644 index 00000000..f8e49f3a --- /dev/null +++ b/parquet/typedoc.json @@ -0,0 +1,4 @@ +{ + "entryPoints": ["index.ts"], + "skipErrorChecking": true +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 942673db..1dc950e3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,14 +15,17 @@ importers: specifier: 2.29.5 version: 2.29.5 '@types/node': - specifier: 22.15.31 - version: 22.15.31 + specifier: 24.2.0 + version: 24.2.0 '@vitest/coverage-v8': specifier: 3.1.4 version: 3.1.4(vitest@3.1.4) '@vitest/ui': specifier: 3.1.4 version: 3.1.4(vitest@3.1.4) + execa: + specifier: 9.6.0 + version: 9.6.0 husky: specifier: 9.1.7 version: 9.1.7 @@ -36,15 +39,33 @@ importers: specifier: ^4.41.0 version: 4.41.0 typescript: - specifier: 5.8.3 - version: 5.8.3 + specifier: 5.9.2 + version: 5.9.2 vitest: specifier: 3.1.4 - version: 3.1.4(@types/debug@4.1.12)(@types/node@22.15.31)(@vitest/ui@3.1.4)(yaml@2.7.1) + version: 3.1.4(@types/debug@4.1.12)(@types/node@24.2.0)(@vitest/ui@3.1.4)(tsx@4.20.3)(yaml@2.8.1) - avro: {} - - bin: {} + arrow: + dependencies: + '@dpkit/core': + specifier: workspace:* + version: link:../core + '@dpkit/file': + specifier: workspace:* + version: link:../file + '@dpkit/table': + specifier: workspace:* + version: link:../table + csv-sniffer: + specifier: ^0.1.1 + version: 0.1.1 + nodejs-polars: + specifier: ^0.21.0 + version: 0.21.0 + devDependencies: + '@dpkit/test': + specifier: workspace:* + version: link:../test camtrap: dependencies: @@ -65,16 +86,48 @@ importers: specifier: workspace:* version: link:../test - cli: {} + cli: + dependencies: + '@oclif/core': + specifier: ^4.5.2 + version: 4.5.2 + '@oclif/plugin-autocomplete': + specifier: ^3.2.34 + version: 3.2.34 + dpkit: + specifier: workspace:* + version: link:../dpkit + ink: + specifier: ^6.1.0 + version: 6.1.0(@types/react@19.1.9)(react@19.1.1) + ink-select-input: + specifier: ^6.2.0 + version: 6.2.0(ink@6.1.0(@types/react@19.1.9)(react@19.1.1))(react@19.1.1) + nodejs-polars: + specifier: ^0.21.0 + version: 0.21.0 + react: + specifier: ^19.1.1 + version: 19.1.1 + ts-extras: + specifier: ^0.14.0 + version: 0.14.0 + devDependencies: + '@types/react': + specifier: 19.1.9 + version: 19.1.9 + tsx: + specifier: 4.20.3 + version: 4.20.3 core: dependencies: + '@sindresorhus/slugify': + specifier: ^0.9.0 + version: 0.9.1 ajv: specifier: ^8.17.1 version: 8.17.1 - github-slugger: - specifier: ^2.0.0 - version: 2.0.0 quick-lru: specifier: ^7.0.1 version: 7.0.1 @@ -97,15 +150,12 @@ importers: specifier: ^0.1.1 version: 0.1.1 nodejs-polars: - specifier: ^0.18.0 - version: 0.18.0 + specifier: ^0.21.0 + version: 0.21.0 devDependencies: '@dpkit/test': specifier: workspace:* version: link:../test - tempy: - specifier: ^3.1.0 - version: 3.1.0 datahub: dependencies: @@ -120,41 +170,43 @@ importers: db: {} docs: - dependencies: + devDependencies: '@astrojs/starlight': specifier: 0.34.3 - version: 0.34.3(astro@5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1)) + version: 0.34.3(astro@5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1)) astro: specifier: 5.7.12 - version: 5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1) + version: 5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1) dpkit: specifier: workspace:* version: link:../dpkit + nodejs-polars: + specifier: 0.21.0 + version: 0.21.0 sharp: specifier: 0.34.2 version: 0.34.2 starlight-scroll-to-top: specifier: 0.1.1 - version: 0.1.1(@astrojs/starlight@0.34.3(astro@5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1))) + version: 0.1.1(@astrojs/starlight@0.34.3(astro@5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1))) starlight-typedoc: specifier: 0.21.3 - version: 0.21.3(@astrojs/starlight@0.34.3(astro@5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1)))(typedoc-plugin-markdown@4.6.3(typedoc@0.28.5(typescript@5.8.3)))(typedoc@0.28.5(typescript@5.8.3)) - typedoc: - specifier: 0.28.5 - version: 0.28.5(typescript@5.8.3) - typedoc-plugin-markdown: - specifier: 4.6.3 - version: 4.6.3(typedoc@0.28.5(typescript@5.8.3)) - devDependencies: - nodejs-polars: - specifier: ^0.18.0 - version: 0.18.0 + version: 0.21.3(@astrojs/starlight@0.34.3(astro@5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1)))(typedoc-plugin-markdown@4.8.0(typedoc@0.28.9(typescript@5.9.2)))(typedoc@0.28.9(typescript@5.9.2)) tempy: specifier: 3.1.0 version: 3.1.0 + typedoc: + specifier: 0.28.9 + version: 0.28.9(typescript@5.9.2) + typedoc-plugin-markdown: + specifier: 4.8.0 + version: 4.8.0(typedoc@0.28.9(typescript@5.9.2)) dpkit: dependencies: + '@dpkit/arrow': + specifier: workspace:* + version: link:../arrow '@dpkit/camtrap': specifier: workspace:* version: link:../camtrap @@ -182,6 +234,12 @@ importers: '@dpkit/inline': specifier: workspace:* version: link:../inline + '@dpkit/json': + specifier: workspace:* + version: link:../json + '@dpkit/parquet': + specifier: workspace:* + version: link:../parquet '@dpkit/table': specifier: workspace:* version: link:../table @@ -245,14 +303,54 @@ importers: specifier: workspace:* version: link:../table nodejs-polars: - specifier: ^0.18.0 - version: 0.18.0 + specifier: ^0.21.0 + version: 0.21.0 - json: {} + json: + dependencies: + '@dpkit/core': + specifier: workspace:* + version: link:../core + '@dpkit/file': + specifier: workspace:* + version: link:../file + '@dpkit/table': + specifier: workspace:* + version: link:../table + csv-sniffer: + specifier: ^0.1.1 + version: 0.1.1 + nodejs-polars: + specifier: ^0.21.0 + version: 0.21.0 + devDependencies: + '@dpkit/test': + specifier: workspace:* + version: link:../test ods: {} - parquet: {} + parquet: + dependencies: + '@dpkit/core': + specifier: workspace:* + version: link:../core + '@dpkit/file': + specifier: workspace:* + version: link:../file + '@dpkit/table': + specifier: workspace:* + version: link:../table + csv-sniffer: + specifier: ^0.1.1 + version: 0.1.1 + nodejs-polars: + specifier: ^0.21.0 + version: 0.21.0 + devDependencies: + '@dpkit/test': + specifier: workspace:* + version: link:../test table: dependencies: @@ -260,14 +358,14 @@ importers: specifier: workspace:* version: link:../core nodejs-polars: - specifier: ^0.18.0 - version: 0.18.0 + specifier: ^0.21.0 + version: 0.21.0 test: dependencies: '@pollyjs/adapter-fetch': specifier: ^6.0.6 - version: 6.0.6 + version: 6.0.7 '@pollyjs/core': specifier: ^6.0.6 version: 6.0.6 @@ -317,22 +415,32 @@ importers: packages: + '@alcalzone/ansi-tokenize@0.1.3': + resolution: {integrity: sha512-3yWxPTq3UQ/FY9p1ErPxIyfT64elWaMvM9lIHnaqpyft63tkxodF5aUElYHrdisWve5cETkh1+KBw1yJuW0aRw==} + engines: {node: '>=14.13.1'} + '@ampproject/remapping@2.3.0': resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@astrojs/compiler@2.12.0': - resolution: {integrity: sha512-7bCjW6tVDpUurQLeKBUN9tZ5kSv5qYrGmcn0sG0IwacL7isR2ZbyyA3AdZ4uxsuUFOS2SlgReTH7wkxO6zpqWA==} + '@astrojs/compiler@2.12.2': + resolution: {integrity: sha512-w2zfvhjNCkNMmMMOn5b0J8+OmUaBL1o40ipMvqcG6NRpdC+lKxmTi48DT8Xw0SzJ3AfmeFLB45zXZXtmbsjcgw==} '@astrojs/internal-helpers@0.6.1': resolution: {integrity: sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A==} + '@astrojs/internal-helpers@0.7.1': + resolution: {integrity: sha512-7dwEVigz9vUWDw3nRwLQ/yH/xYovlUA0ZD86xoeKEBmkz9O6iELG1yri67PgAPW6VLL/xInA4t7H0CK6VmtkKQ==} + '@astrojs/markdown-remark@6.3.1': resolution: {integrity: sha512-c5F5gGrkczUaTVgmMW9g1YMJGzOtRvjjhw6IfGuxarM6ct09MpwysP10US729dy07gg8y+ofVifezvP3BNsWZg==} - '@astrojs/mdx@4.2.6': - resolution: {integrity: sha512-0i/GmOm6d0qq1/SCfcUgY/IjDc/bS0i42u7h85TkPFBmlFOcBZfkYhR5iyz6hZLwidvJOEq5yGfzt9B1Azku4w==} - engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} + '@astrojs/markdown-remark@6.3.5': + resolution: {integrity: sha512-MiR92CkE2BcyWf3b86cBBw/1dKiOH0qhLgXH2OXA6cScrrmmks1Rr4Tl0p/lFpvmgQQrP54Pd1uidJfmxGrpWQ==} + + '@astrojs/mdx@4.3.3': + resolution: {integrity: sha512-+9+xGP2TBXxcm84cpiq4S9JbuHOHM1fcvREfqW7VHxlUyfUQPByoJ9YYliqHkLS6BMzG+O/+o7n8nguVhuEv4w==} + engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} peerDependencies: astro: ^5.0.0 @@ -340,8 +448,12 @@ packages: resolution: {integrity: sha512-GilTHKGCW6HMq7y3BUv9Ac7GMe/MO9gi9GW62GzKtth0SwukCu/qp2wLiGpEujhY+VVhaG9v7kv/5vFzvf4NYw==} engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} - '@astrojs/sitemap@3.4.0': - resolution: {integrity: sha512-C5m/xsKvRSILKM3hy47n5wKtTQtJXn8epoYuUmCCstaE9XBt20yInym3Bz2uNbEiNfv11bokoW0MqeXPIvjFIQ==} + '@astrojs/prism@3.3.0': + resolution: {integrity: sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==} + engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} + + '@astrojs/sitemap@3.4.2': + resolution: {integrity: sha512-wfN2dZzdkto6yaMtOFa/J9gc60YE3wl3rgSBoNJ+MU3lJVUMsDY9xf9uAVi8Mp/zEQKFDSJlQzBvqQUpw0Hf6g==} '@astrojs/starlight@0.34.3': resolution: {integrity: sha512-MAuD3NF+E+QXJJuVKofoR6xcPTP4BJmYWeOBd03udVdubNGVnPnSWVZAi+ZtnTofES4+mJdp8BNGf+ubUxkiiA==} @@ -360,17 +472,17 @@ packages: resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} engines: {node: '>=6.9.0'} - '@babel/parser@7.27.2': - resolution: {integrity: sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==} + '@babel/parser@7.28.0': + resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/runtime@7.27.1': - resolution: {integrity: sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==} + '@babel/runtime@7.28.2': + resolution: {integrity: sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==} engines: {node: '>=6.9.0'} - '@babel/types@7.27.1': - resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==} + '@babel/types@7.28.2': + resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==} engines: {node: '>=6.9.0'} '@bcoe/v8-coverage@1.0.2': @@ -492,179 +604,185 @@ packages: resolution: {integrity: sha512-WyOx8cJQ+FQus4Mm4uPIZA64gbk3Wxh0so5Lcii0aJifqwoVOlfFtorjLE0Hen4OYyHZMXDWqMmaQemBhgxFRQ==} engines: {node: '>=14'} - '@emnapi/core@1.4.3': - resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==} + '@emnapi/core@1.4.5': + resolution: {integrity: sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==} - '@emnapi/runtime@1.4.3': - resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} + '@emnapi/runtime@1.4.5': + resolution: {integrity: sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==} - '@emnapi/wasi-threads@1.0.2': - resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==} + '@emnapi/wasi-threads@1.0.4': + resolution: {integrity: sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==} - '@esbuild/aix-ppc64@0.25.4': - resolution: {integrity: sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==} + '@esbuild/aix-ppc64@0.25.8': + resolution: {integrity: sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.4': - resolution: {integrity: sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==} + '@esbuild/android-arm64@0.25.8': + resolution: {integrity: sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.4': - resolution: {integrity: sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==} + '@esbuild/android-arm@0.25.8': + resolution: {integrity: sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.4': - resolution: {integrity: sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==} + '@esbuild/android-x64@0.25.8': + resolution: {integrity: sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.4': - resolution: {integrity: sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==} + '@esbuild/darwin-arm64@0.25.8': + resolution: {integrity: sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.4': - resolution: {integrity: sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==} + '@esbuild/darwin-x64@0.25.8': + resolution: {integrity: sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.4': - resolution: {integrity: sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==} + '@esbuild/freebsd-arm64@0.25.8': + resolution: {integrity: sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.4': - resolution: {integrity: sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==} + '@esbuild/freebsd-x64@0.25.8': + resolution: {integrity: sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.4': - resolution: {integrity: sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==} + '@esbuild/linux-arm64@0.25.8': + resolution: {integrity: sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.4': - resolution: {integrity: sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==} + '@esbuild/linux-arm@0.25.8': + resolution: {integrity: sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.4': - resolution: {integrity: sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==} + '@esbuild/linux-ia32@0.25.8': + resolution: {integrity: sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.4': - resolution: {integrity: sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==} + '@esbuild/linux-loong64@0.25.8': + resolution: {integrity: sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.4': - resolution: {integrity: sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==} + '@esbuild/linux-mips64el@0.25.8': + resolution: {integrity: sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.4': - resolution: {integrity: sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==} + '@esbuild/linux-ppc64@0.25.8': + resolution: {integrity: sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.4': - resolution: {integrity: sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==} + '@esbuild/linux-riscv64@0.25.8': + resolution: {integrity: sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.4': - resolution: {integrity: sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==} + '@esbuild/linux-s390x@0.25.8': + resolution: {integrity: sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.4': - resolution: {integrity: sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==} + '@esbuild/linux-x64@0.25.8': + resolution: {integrity: sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.4': - resolution: {integrity: sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==} + '@esbuild/netbsd-arm64@0.25.8': + resolution: {integrity: sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.4': - resolution: {integrity: sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==} + '@esbuild/netbsd-x64@0.25.8': + resolution: {integrity: sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.4': - resolution: {integrity: sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==} + '@esbuild/openbsd-arm64@0.25.8': + resolution: {integrity: sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.4': - resolution: {integrity: sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==} + '@esbuild/openbsd-x64@0.25.8': + resolution: {integrity: sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.25.4': - resolution: {integrity: sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==} + '@esbuild/openharmony-arm64@0.25.8': + resolution: {integrity: sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.8': + resolution: {integrity: sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.4': - resolution: {integrity: sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==} + '@esbuild/win32-arm64@0.25.8': + resolution: {integrity: sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.4': - resolution: {integrity: sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==} + '@esbuild/win32-ia32@0.25.8': + resolution: {integrity: sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.4': - resolution: {integrity: sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==} + '@esbuild/win32-x64@0.25.8': + resolution: {integrity: sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==} engines: {node: '>=18'} cpu: [x64] os: [win32] - '@expressive-code/core@0.41.2': - resolution: {integrity: sha512-AJW5Tp9czbLqKMzwudL9Rv4js9afXBxkSGLmCNPq1iRgAYcx9NkTPJiSNCesjKRWoVC328AdSu6fqrD22zDgDg==} + '@expressive-code/core@0.41.3': + resolution: {integrity: sha512-9qzohqU7O0+JwMEEgQhnBPOw5DtsQRBXhW++5fvEywsuX44vCGGof1SL5OvPElvNgaWZ4pFZAFSlkNOkGyLwSQ==} - '@expressive-code/plugin-frames@0.41.2': - resolution: {integrity: sha512-pfy0hkJI4nbaONjmksFDcuHmIuyPTFmi1JpABe4q2ajskiJtfBf+WDAL2pg595R9JNoPrrH5+aT9lbkx2noicw==} + '@expressive-code/plugin-frames@0.41.3': + resolution: {integrity: sha512-rFQtmf/3N2CK3Cq/uERweMTYZnBu+CwxBdHuOftEmfA9iBE7gTVvwpbh82P9ZxkPLvc40UMhYt7uNuAZexycRQ==} - '@expressive-code/plugin-shiki@0.41.2': - resolution: {integrity: sha512-xD4zwqAkDccXqye+235BH5bN038jYiSMLfUrCOmMlzxPDGWdxJDk5z4uUB/aLfivEF2tXyO2zyaarL3Oqht0fQ==} + '@expressive-code/plugin-shiki@0.41.3': + resolution: {integrity: sha512-RlTARoopzhFJIOVHLGvuXJ8DCEme/hjV+ZnRJBIxzxsKVpGPW4Oshqg9xGhWTYdHstTsxO663s0cdBLzZj9TQA==} - '@expressive-code/plugin-text-markers@0.41.2': - resolution: {integrity: sha512-JFWBz2qYxxJOJkkWf96LpeolbnOqJY95TvwYc0hXIHf9oSWV0h0SY268w/5N3EtQaD9KktzDE+VIVwb9jdb3nw==} + '@expressive-code/plugin-text-markers@0.41.3': + resolution: {integrity: sha512-SN8tkIzDpA0HLAscEYD2IVrfLiid6qEdE9QLlGVSxO1KEw7qYvjpbNBQjUjMr5/jvTJ7ys6zysU2vLPHE0sb2g==} - '@gerrit0/mini-shiki@3.4.0': - resolution: {integrity: sha512-48lKoQegmfJ0iyR/jRz5OrYOSM3WewG9YWCPqUvYFEC54shQO8RsAaspaK/2PRHVVnjekRqfAFvq8pwCpIo5ig==} + '@gerrit0/mini-shiki@3.9.2': + resolution: {integrity: sha512-Tvsj+AOO4Z8xLRJK900WkyfxHsZQu+Zm1//oT1w443PO6RiYMoq/4NGOhaNuZoUMYsjKIAPVQ6eOFMddj6yphQ==} '@img/sharp-darwin-arm64@0.33.5': resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} @@ -895,23 +1013,18 @@ packages: resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} - '@jridgewell/gen-mapping@0.3.8': - resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} - engines: {node: '>=6.0.0'} + '@jridgewell/gen-mapping@0.3.12': + resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==} '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/sourcemap-codec@1.5.4': + resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.29': + resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -922,8 +1035,8 @@ packages: '@mdx-js/mdx@3.1.0': resolution: {integrity: sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==} - '@napi-rs/wasm-runtime@0.2.10': - resolution: {integrity: sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==} + '@napi-rs/wasm-runtime@0.2.12': + resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} '@node-rs/crc32-android-arm-eabi@1.10.6': resolution: {integrity: sha512-vZAMuJXm3TpWPOkkhxdrofWDv+Q+I2oO7ucLRbXyAPmXFNDhHtBxbO1rk9Qzz+M3eep8ieS4/+jCL1Q0zacNMQ==} @@ -1024,6 +1137,14 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@oclif/core@4.5.2': + resolution: {integrity: sha512-eQcKyrEcDYeZJKu4vUWiu0ii/1Gfev6GF4FsLSgNez5/+aQyAUCjg3ZWlurf491WiYZTXCWyKAxyPWk8DKv2MA==} + engines: {node: '>=18.0.0'} + + '@oclif/plugin-autocomplete@3.2.34': + resolution: {integrity: sha512-KhbPcNjitAU7jUojMXJ3l7duWVub0L0pEr3r3bLrpJBNuIJhoIJ7p56Ropcb7OMH2xcaz5B8HGq56cTOe1FHEg==} + engines: {node: '>=18.0.0'} + '@oslojs/encoding@1.1.0': resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} @@ -1062,8 +1183,8 @@ packages: '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} - '@pollyjs/adapter-fetch@6.0.6': - resolution: {integrity: sha512-euWzM5TnA2jptdJgjIkEd/Q2hNFB652XivPKerWpLMFB13IKlrERX9wn2Dw3pquDAP0LvXH1qVBZt5DK0Xhzyg==} + '@pollyjs/adapter-fetch@6.0.7': + resolution: {integrity: sha512-kv44DROx/2qzlcgS71EccGr2/I5nK40Xt92paGNI+1/Kmz290bw/ykt8cvXDg4O4xCc9Fh/jXeAkS7qwGpCx2g==} '@pollyjs/adapter@6.0.6': resolution: {integrity: sha512-szhys0NiFQqCJDMC0kpDyjhLqSI7aWc6m6iATCRKgcMcN/7QN85pb3GmRzvnNV8+/Bi2AUSCwxZljcsKhbYVWQ==} @@ -1083,8 +1204,8 @@ packages: '@pollyjs/utils@6.0.6': resolution: {integrity: sha512-nhVJoI3nRgRimE0V2DVSvsXXNROUH6iyJbroDu4IdsOIOFC1Ds0w+ANMB4NMwFaqE+AisWOmXFzwAGdAfyiQVg==} - '@rollup/pluginutils@5.1.4': - resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} + '@rollup/pluginutils@5.2.0': + resolution: {integrity: sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==} engines: {node: '>=14.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 @@ -1092,123 +1213,126 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.40.2': - resolution: {integrity: sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==} + '@rollup/rollup-android-arm-eabi@4.46.2': + resolution: {integrity: sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.40.2': - resolution: {integrity: sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==} + '@rollup/rollup-android-arm64@4.46.2': + resolution: {integrity: sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.40.2': - resolution: {integrity: sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==} + '@rollup/rollup-darwin-arm64@4.46.2': + resolution: {integrity: sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.40.2': - resolution: {integrity: sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==} + '@rollup/rollup-darwin-x64@4.46.2': + resolution: {integrity: sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.40.2': - resolution: {integrity: sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==} + '@rollup/rollup-freebsd-arm64@4.46.2': + resolution: {integrity: sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.40.2': - resolution: {integrity: sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==} + '@rollup/rollup-freebsd-x64@4.46.2': + resolution: {integrity: sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.40.2': - resolution: {integrity: sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==} + '@rollup/rollup-linux-arm-gnueabihf@4.46.2': + resolution: {integrity: sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.40.2': - resolution: {integrity: sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==} + '@rollup/rollup-linux-arm-musleabihf@4.46.2': + resolution: {integrity: sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.40.2': - resolution: {integrity: sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==} + '@rollup/rollup-linux-arm64-gnu@4.46.2': + resolution: {integrity: sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.40.2': - resolution: {integrity: sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==} + '@rollup/rollup-linux-arm64-musl@4.46.2': + resolution: {integrity: sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.40.2': - resolution: {integrity: sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==} + '@rollup/rollup-linux-loongarch64-gnu@4.46.2': + resolution: {integrity: sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.40.2': - resolution: {integrity: sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==} + '@rollup/rollup-linux-ppc64-gnu@4.46.2': + resolution: {integrity: sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.40.2': - resolution: {integrity: sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==} + '@rollup/rollup-linux-riscv64-gnu@4.46.2': + resolution: {integrity: sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.40.2': - resolution: {integrity: sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==} + '@rollup/rollup-linux-riscv64-musl@4.46.2': + resolution: {integrity: sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.40.2': - resolution: {integrity: sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==} + '@rollup/rollup-linux-s390x-gnu@4.46.2': + resolution: {integrity: sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.40.2': - resolution: {integrity: sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==} + '@rollup/rollup-linux-x64-gnu@4.46.2': + resolution: {integrity: sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.40.2': - resolution: {integrity: sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==} + '@rollup/rollup-linux-x64-musl@4.46.2': + resolution: {integrity: sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.40.2': - resolution: {integrity: sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==} + '@rollup/rollup-win32-arm64-msvc@4.46.2': + resolution: {integrity: sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.40.2': - resolution: {integrity: sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==} + '@rollup/rollup-win32-ia32-msvc@4.46.2': + resolution: {integrity: sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.40.2': - resolution: {integrity: sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==} + '@rollup/rollup-win32-x64-msvc@4.46.2': + resolution: {integrity: sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg==} cpu: [x64] os: [win32] - '@shikijs/core@3.4.0': - resolution: {integrity: sha512-0YOzTSRDn/IAfQWtK791gs1u8v87HNGToU6IwcA3K7nPoVOrS2Dh6X6A6YfXgPTSkTwR5y6myk0MnI0htjnwrA==} + '@sec-ant/readable-stream@0.4.1': + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + + '@shikijs/core@3.9.2': + resolution: {integrity: sha512-3q/mzmw09B2B6PgFNeiaN8pkNOixWS726IHmJEpjDAcneDPMQmUg2cweT9cWXY4XcyQS3i6mOOUgQz9RRUP6HA==} - '@shikijs/engine-javascript@3.4.0': - resolution: {integrity: sha512-1ywDoe+z/TPQKj9Jw0eU61B003J9DqUFRfH+DVSzdwPUFhR7yOmfyLzUrFz0yw8JxFg/NgzXoQyyykXgO21n5Q==} + '@shikijs/engine-javascript@3.9.2': + resolution: {integrity: sha512-kUTRVKPsB/28H5Ko6qEsyudBiWEDLst+Sfi+hwr59E0GLHV0h8RfgbQU7fdN5Lt9A8R1ulRiZyTvAizkROjwDA==} - '@shikijs/engine-oniguruma@3.4.0': - resolution: {integrity: sha512-zwcWlZ4OQuJ/+1t32ClTtyTU1AiDkK1lhtviRWoq/hFqPjCNyLj22bIg9rB7BfoZKOEOfrsGz7No33BPCf+WlQ==} + '@shikijs/engine-oniguruma@3.9.2': + resolution: {integrity: sha512-Vn/w5oyQ6TUgTVDIC/BrpXwIlfK6V6kGWDVVz2eRkF2v13YoENUvaNwxMsQU/t6oCuZKzqp9vqtEtEzKl9VegA==} - '@shikijs/langs@3.4.0': - resolution: {integrity: sha512-bQkR+8LllaM2duU9BBRQU0GqFTx7TuF5kKlw/7uiGKoK140n1xlLAwCgXwSxAjJ7Htk9tXTFwnnsJTCU5nDPXQ==} + '@shikijs/langs@3.9.2': + resolution: {integrity: sha512-X1Q6wRRQXY7HqAuX3I8WjMscjeGjqXCg/Sve7J2GWFORXkSrXud23UECqTBIdCSNKJioFtmUGJQNKtlMMZMn0w==} - '@shikijs/themes@3.4.0': - resolution: {integrity: sha512-YPP4PKNFcFGLxItpbU0ZW1Osyuk8AyZ24YEFaq04CFsuCbcqydMvMUTi40V2dkc0qs1U2uZFrnU6s5zI6IH+uA==} + '@shikijs/themes@3.9.2': + resolution: {integrity: sha512-6z5lBPBMRfLyyEsgf6uJDHPa6NAGVzFJqH4EAZ+03+7sedYir2yJBRu2uPZOKmj43GyhVHWHvyduLDAwJQfDjA==} - '@shikijs/types@3.4.0': - resolution: {integrity: sha512-EUT/0lGiE//7j5N/yTMNMT3eCWNcHJLrRKxT0NDXWIfdfSmFJKfPX7nMmRBrQnWboAzIsUziCThrYMMhjbMS1A==} + '@shikijs/types@3.9.2': + resolution: {integrity: sha512-/M5L0Uc2ljyn2jKvj4Yiah7ow/W+DJSglVafvWAJ/b8AZDeeRAdMu3c2riDzB7N42VD+jSnWxeP9AKtd4TfYVw==} '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} @@ -1217,11 +1341,19 @@ packages: resolution: {integrity: sha512-suq9tRQ6bkpMukTG5K5z0sPWB7t0zExMzZCdmYm6xTSSIm/yCKNm7VCL36wVeyTsFr597/UhU1OAYdHGMDiHrw==} engines: {node: '>=10'} + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} + + '@sindresorhus/slugify@0.9.1': + resolution: {integrity: sha512-b6heYM9dzZD13t2GOiEQTDE0qX+I1GyOotMwKh9VQqzuNiVdPVT8dM43fe9HNb/3ul+Qwd5oKSEDrDIfhq3bnQ==} + engines: {node: '>=8'} + '@swc/helpers@0.5.17': resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} - '@tybys/wasm-util@0.9.0': - resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} + '@tybys/wasm-util@0.10.0': + resolution: {integrity: sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==} '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -1229,8 +1361,8 @@ packages: '@types/estree-jsx@1.0.5': resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} - '@types/estree@1.0.7': - resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} '@types/fontkit@2.0.8': resolution: {integrity: sha512-wN+8bYxIpJf+5oZdrdtaX04qUuWHcKxcDEgRS9Qm9ZClSHjzEn13SxUC+5eRM+4yXIeTYk8mTzLAWGF64847ew==} @@ -1259,14 +1391,11 @@ packages: '@types/node@17.0.45': resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} - '@types/node@22.14.1': - resolution: {integrity: sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==} - - '@types/node@22.15.24': - resolution: {integrity: sha512-w9CZGm9RDjzTh/D+hFwlBJ3ziUaVw7oufKA3vOFSOZlzmW9AkZnfjPb+DLnrV6qtgL/LNmP0/2zBNCFHL3F0ng==} + '@types/node@24.2.0': + resolution: {integrity: sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw==} - '@types/node@22.15.31': - resolution: {integrity: sha512-jnVe5ULKl6tijxUhvQeNbQG/84fHfg+yMak02cT8QVhBx/F05rAVxCGBYYTh2EKz22D6JF5ktXuNwdx7b9iEGw==} + '@types/react@19.1.9': + resolution: {integrity: sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==} '@types/sax@1.2.7': resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} @@ -1315,6 +1444,9 @@ packages: '@vitest/pretty-format@3.1.4': resolution: {integrity: sha512-cqv9H9GvAEoTaoq+cYqUTCGscUjKqlJZC7PRwY5FMySVj5J+xOm1KQcCiYHJOEzOKRUhLH4R2pTwvFlWCEScsg==} + '@vitest/pretty-format@3.2.4': + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + '@vitest/runner@3.1.4': resolution: {integrity: sha512-djTeF1/vt985I/wpKVFBMWUlk/I7mb5hmD5oP8K9ACRmVXgKTae3TUOtXAEBfslNKPzUQvnKhNd34nnRSYgLNQ==} @@ -1341,8 +1473,8 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.14.1: - resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} hasBin: true @@ -1356,6 +1488,14 @@ packages: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-escapes@7.0.0: + resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} + engines: {node: '>=18'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1372,6 +1512,10 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + ansis@3.17.0: + resolution: {integrity: sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==} + engines: {node: '>=14'} + anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} @@ -1407,8 +1551,8 @@ packages: resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} hasBin: true - astro-expressive-code@0.41.2: - resolution: {integrity: sha512-HN0jWTnhr7mIV/2e6uu4PPRNNo/k4UEgTLZqbp3MrHU+caCARveG2yZxaZVBmxyiVdYqW5Pd3u3n2zjnshixbw==} + astro-expressive-code@0.41.3: + resolution: {integrity: sha512-u+zHMqo/QNLE2eqYRCrK3+XMlKakv33Bzuz+56V1gs8H0y6TZ0hIi3VNbIxeTn51NLn+mJfUV/A0kMNfE4rANw==} peerDependencies: astro: ^4.0.0-beta || ^5.0.0-beta || ^3.3.0 @@ -1417,6 +1561,13 @@ packages: engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} hasBin: true + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + auto-bind@5.0.1: + resolution: {integrity: sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} @@ -1467,8 +1618,8 @@ packages: resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} engines: {node: '>=18'} - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -1504,12 +1655,12 @@ packages: ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - chai@5.2.0: - resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} - engines: {node: '>=12'} + chai@5.2.1: + resolution: {integrity: sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==} + engines: {node: '>=18'} - chalk@5.4.1: - resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} + chalk@5.5.0: + resolution: {integrity: sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} character-entities-html4@2.1.0: @@ -1539,14 +1690,30 @@ packages: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} - ci-info@4.2.0: - resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==} + ci-info@4.3.0: + resolution: {integrity: sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==} engines: {node: '>=8'} + clean-stack@3.0.1: + resolution: {integrity: sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==} + engines: {node: '>=10'} + cli-boxes@3.0.0: resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} engines: {node: '>=10'} + cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + clone@2.1.2: resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} engines: {node: '>=0.8'} @@ -1555,6 +1722,10 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + code-excerpt@4.0.0: + resolution: {integrity: sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + collapse-white-space@2.1.0: resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==} @@ -1586,6 +1757,10 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} + convert-to-spaces@2.0.1: + resolution: {integrity: sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + cookie-es@1.2.2: resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==} @@ -1618,8 +1793,8 @@ packages: resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} engines: {node: '>=12'} - css-selector-parser@3.1.2: - resolution: {integrity: sha512-WfUcL99xWDs7b3eZPoRszWVfbNo8ErCF15PTvVROjkShGlAfjIkG6hlfj/sl6/rfo5Q9x9ryJ3VqVnAZDA+gcw==} + css-selector-parser@3.1.3: + resolution: {integrity: sha512-gJMigczVZqYAk0hPVzx/M4Hm1D9QOtqkdQk9005TNzDIUGzo5cnHEDiKUT7jGPximL/oYb+LIitcHFQ4aKupxg==} css-tree@3.1.0: resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} @@ -1630,6 +1805,9 @@ packages: engines: {node: '>=4'} hasBin: true + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + csv-sniffer@0.1.1: resolution: {integrity: sha512-HMFcKMGCaJNBtkEk1RYZxngODTx0gQnN5x494fWJizua2mdoM1h/LRooZQMkxx5RRHNP0mowlTw9xiS7QhXt/g==} @@ -1641,8 +1819,8 @@ packages: supports-color: optional: true - debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -1650,8 +1828,8 @@ packages: supports-color: optional: true - decode-named-character-reference@1.1.0: - resolution: {integrity: sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==} + decode-named-character-reference@1.2.0: + resolution: {integrity: sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==} deep-eql@5.0.2: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} @@ -1691,9 +1869,6 @@ packages: resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} engines: {node: '>=8'} - detect-node@2.1.0: - resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} - deterministic-object-hash@2.0.2: resolution: {integrity: sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==} engines: {node: '>=18'} @@ -1736,6 +1911,11 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + emoji-regex@10.4.0: resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} @@ -1761,10 +1941,14 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - entities@6.0.0: - resolution: {integrity: sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==} + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -1780,20 +1964,35 @@ packages: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} + es-toolkit@1.39.8: + resolution: {integrity: sha512-A8QO9TfF+rltS8BXpdu8OS+rpGgEdnRhqIVxO/ZmNvnXBYgOdSsxukT55ELyP94gZIntWJ+Li9QRrT2u1Kitpg==} + esast-util-from-estree@2.0.0: resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==} esast-util-from-js@2.0.1: resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==} - esbuild@0.25.4: - resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==} + esbuild@0.25.8: + resolution: {integrity: sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==} engines: {node: '>=18'} hasBin: true escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + escape-string-regexp@5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} @@ -1834,20 +2033,24 @@ packages: eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + execa@9.6.0: + resolution: {integrity: sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==} + engines: {node: ^18.19.0 || >=20.5.0} + exit-hook@4.0.0: resolution: {integrity: sha512-Fqs7ChZm72y40wKjOFXBKg7nJZvQJmewP5/7LtePDdnah/+FH9Hp5sgMujSCMPXlxOAW2//1jrW9pnsY7o20vQ==} engines: {node: '>=18'} - expect-type@1.2.1: - resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==} + expect-type@1.2.2: + resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==} engines: {node: '>=12.0.0'} express@4.21.2: resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} - expressive-code@0.41.2: - resolution: {integrity: sha512-aLZiZaqorRtNExtGpUjK9zFH9aTpWeoTXMyLo4b4IcuXfPqtLPPxhRm/QlPb8QqIcMMXnSiGRHSFpQfX0m7HJw==} + expressive-code@0.41.3: + resolution: {integrity: sha512-YLnD62jfgBZYrXIPQcJ0a51Afv9h8VlWqEGK9uU2T5nL/5rb8SnA86+7+mgCZe5D34Tff5RNEA5hjNVJYHzrFg==} extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -1875,8 +2078,8 @@ packages: fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} - fdir@6.4.4: - resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==} + fdir@6.4.6: + resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} peerDependencies: picomatch: ^3 || ^4 peerDependenciesMeta: @@ -1886,6 +2089,13 @@ packages: fflate@0.8.2: resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + figures@6.1.0: + resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} + engines: {node: '>=18'} + + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -1951,10 +2161,21 @@ packages: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + get-proto@1.0.1: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} + get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} + + get-tsconfig@4.10.1: + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} + github-slugger@2.0.0: resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} @@ -1981,8 +2202,8 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - h3@1.15.3: - resolution: {integrity: sha512-z6GknHqyX0h9aQaTx22VZDf6QyZn+0Nh+Ym8O/u0SGSkyF5cuTJYKlc8MkzW3Nzf9LE1ivcpmYC3FUGpywhuUQ==} + h3@1.15.4: + resolution: {integrity: sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==} has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} @@ -2086,6 +2307,10 @@ packages: resolution: {integrity: sha512-3gKm/gCSUipeLsRYZbbdA1BD83lBoWUkZ7G9VFrhWPAU76KwYo5KR8V28bpoPm/ygy0x5/GCbpRQdY7VLYCoIg==} hasBin: true + human-signals@8.0.1: + resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} + engines: {node: '>=18.18.0'} + husky@9.1.7: resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} engines: {node: '>=18'} @@ -2105,9 +2330,37 @@ packages: import-meta-resolve@4.1.0: resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + indent-string@5.0.0: + resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} + engines: {node: '>=12'} + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + ink-select-input@6.2.0: + resolution: {integrity: sha512-304fZXxkpYxJ9si5lxRCaX01GNlmPBgOZumXXRnPYbHW/iI31cgQynqk2tRypGLOF1cMIwPUzL2LSm6q4I5rQQ==} + engines: {node: '>=18'} + peerDependencies: + ink: '>=5.0.0' + react: '>=18.0.0' + + ink@6.1.0: + resolution: {integrity: sha512-YQ+lbMD79y3FBAJXXZnuRajLEgaMFp102361eY5NrBIEVCi9oFo7gNZU4z2LBWlcjZFiTt7jetlkIbKCCH4KJA==} + engines: {node: '>=20'} + peerDependencies: + '@types/react': '>=19.0.0' + react: '>=19.0.0' + react-devtools-core: ^4.19.1 + peerDependenciesMeta: + '@types/react': + optional: true + react-devtools-core: + optional: true + inline-style-parser@0.2.4: resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==} @@ -2134,6 +2387,11 @@ packages: is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -2147,6 +2405,14 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -2154,13 +2420,18 @@ packages: is-hexadecimal@2.0.1: resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + is-in-ci@1.0.0: + resolution: {integrity: sha512-eUuAjybVTHMYWm/U+vBO1sY/JOCgoPCXRxzdju0K+K0BiGW0SChEL1MLC0PoCIR1OlPo5YAp8HuQoUlsWEICwg==} + engines: {node: '>=18'} + hasBin: true + is-inside-container@1.0.0: resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} engines: {node: '>=14.16'} hasBin: true - is-it-type@5.1.2: - resolution: {integrity: sha512-q/gOZQTNYABAxaXWnBKZjTFH4yACvWEFtgVOj+LbgxYIgAJG1xVmUZOsECSrZPIemYUQvaQWVilSFVbh4Eyt8A==} + is-it-type@5.1.3: + resolution: {integrity: sha512-AX2uU0HW+TxagTgQXOJY7+2fbFHemC7YFBwN1XqD8qQMKdtfbOC8OC3fUb4s5NU59a3662Dzwto8tWDdZYRXxg==} engines: {node: '>=12'} is-number@7.0.0: @@ -2175,14 +2446,26 @@ packages: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + is-subdir@1.2.0: resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} engines: {node: '>=4'} + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + is-wsl@3.1.0: resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} engines: {node: '>=16'} @@ -2209,6 +2492,14 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jake@10.9.4: + resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} + engines: {node: '>=10'} + hasBin: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-yaml@3.14.1: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} hasBin: true @@ -2238,6 +2529,10 @@ packages: resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} engines: {node: '>= 8'} + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + linkify-it@5.0.0: resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} @@ -2248,6 +2543,9 @@ packages: lodash-es@4.17.21: resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + lodash.deburr@4.1.0: + resolution: {integrity: sha512-m/M1U1f3ddMCs6Hq2tAsYThTBDaAKFDX3dwDo97GEYzamXi9SqUpjWi/Rrj/gf3X2n8ktwgZrlP1z6E3v/IExQ==} + lodash.startcase@4.4.0: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} @@ -2258,8 +2556,12 @@ packages: longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - loupe@3.1.3: - resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + loupe@3.2.0: + resolution: {integrity: sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==} lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -2492,6 +2794,14 @@ packages: engines: {node: '>=4'} hasBin: true + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -2500,8 +2810,8 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} - morgan@1.10.0: - resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==} + morgan@1.10.1: + resolution: {integrity: sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==} engines: {node: '>= 0.8.0'} mri@1.2.0: @@ -2538,8 +2848,8 @@ packages: resolution: {integrity: sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==} engines: {node: '>=12.0.0'} - node-fetch-native@1.6.6: - resolution: {integrity: sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==} + node-fetch-native@1.6.7: + resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} @@ -2550,59 +2860,59 @@ packages: encoding: optional: true - node-mock-http@1.0.0: - resolution: {integrity: sha512-0uGYQ1WQL1M5kKvGRXWQ3uZCHtLTO8hln3oBjIusM75WoesZ909uQJs/Hb946i2SS+Gsrhkaa6iAO17jRIv6DQ==} + node-mock-http@1.0.2: + resolution: {integrity: sha512-zWaamgDUdo9SSLw47we78+zYw/bDr5gH8pH7oRRs8V3KmBtu8GLgGIbV2p/gRPd3LWpEOpjQj7X1FOU3VFMJ8g==} - nodejs-polars-android-arm64@0.18.0: - resolution: {integrity: sha512-ksmL8X2xsMkI9WMlzRw7Mt7csIDfNJVDlyybSDMMAfO1YWfC2aCFUroFc8UnXVK+8bIZXB7W+k1ZzTRhtSxPsQ==} + nodejs-polars-android-arm64@0.21.0: + resolution: {integrity: sha512-X2Y6iulWGJttGxOIqcZjSJ256TW4FJH/otkBdA6qnmS8jLTD6oDmrxvoMXEOroIBUOTWLC4wqFCeVIDHFMyUDQ==} engines: {node: '>= 16'} cpu: [arm64] os: [android] - nodejs-polars-darwin-arm64@0.18.0: - resolution: {integrity: sha512-Hs8pbyPZCvOLSVoPx6X07vmYu1NmGAvLFYVHry945alesjsMOXZ//9D8psKOsZAh8WRU36CHXHSS18+RxdzLyA==} + nodejs-polars-darwin-arm64@0.21.0: + resolution: {integrity: sha512-0QUeH7VW4hnojHBm5fUMfoWdWHfpt313cspK9sAjkhWtKtXEHs9Ade2Xqg7a2T2XTRpvcakhdQ4SkG6Wq9mJRg==} engines: {node: '>= 16'} cpu: [arm64] os: [darwin] - nodejs-polars-darwin-x64@0.18.0: - resolution: {integrity: sha512-AmLHJ4a4ufTAFohr7b7cQmPvn1Owl6AQBwwows447GfwEO65lu0PSUcmJbeiGJcLtjM9Dji6uiJdadRnGXC4sw==} + nodejs-polars-darwin-x64@0.21.0: + resolution: {integrity: sha512-xJh3JGWn3ZMAKwpFpv0EA8Z8IoiMgXs2WfE6ibTfLxVIHGJMZoI0eEGTnrQaPIkX+bXfiqEWtCcQrgQXfu4sew==} engines: {node: '>= 16'} cpu: [x64] os: [darwin] - nodejs-polars-linux-arm64-gnu@0.18.0: - resolution: {integrity: sha512-lqOA0b6XXd/8D0q4tfrlr9g+awN/lz1WoWlDJXlYDCXeEdiPzodHuKOROi/J8cwcM6RpiWLWviFkJ2FkxZBv7w==} + nodejs-polars-linux-arm64-gnu@0.21.0: + resolution: {integrity: sha512-UUVfc7Kjiwpdsh9YoIP/jTUSMWpEmbJk7/LWCEZAZsOiQKbHriPKNdzoG+4zhaNsu/mPDgOKZyXjY2OI5JEUYg==} engines: {node: '>= 16'} cpu: [arm64] os: [linux] - nodejs-polars-linux-arm64-musl@0.18.0: - resolution: {integrity: sha512-lylaOGB3c94UBpsDt4XtrS2RJymgICfAnMVlbvN+2bftejh7blDaYTJeLvZr4POHfltpWeSXjl28Zck7goDJCA==} + nodejs-polars-linux-arm64-musl@0.21.0: + resolution: {integrity: sha512-L26Xs1PAThiAcz9Om9KtEdyhreaFPhgdH0SI0MXATS63bLsIYK12CKC3DkEn+dwqqt/UBT8ApHnqQjeiluWJ2g==} engines: {node: '>= 16'} cpu: [arm64] os: [linux] - nodejs-polars-linux-x64-gnu@0.18.0: - resolution: {integrity: sha512-Gk6HJba0Hrea6yjDEj0u4jArWgry+s8/17g646vJdlcAWoaQYXDdfCseObGjtTqajVkFf2msrn76KWZ2Nadq5A==} + nodejs-polars-linux-x64-gnu@0.21.0: + resolution: {integrity: sha512-zvYOo8GeQBN+U9ZyXEEDSwjzmQyZIvGydmD5IYUX5iR6SwFrJ6EiYx6Lr8Pv4QPdYH9DQXxIb44xgst8FCjIWA==} engines: {node: '>= 16'} cpu: [x64] os: [linux] - nodejs-polars-linux-x64-musl@0.18.0: - resolution: {integrity: sha512-KAb72TGTphCUfTZj1mMyDAJ+/3pgifAucWjdCr6aO3Jw4XHJVu6mMRhfDUZgIGWilpwADwPLHnqPjs+qydOoCg==} + nodejs-polars-linux-x64-musl@0.21.0: + resolution: {integrity: sha512-FfvZjx4AuH+zCLNoM9OhlrQyeAEsh0gzGE6UDIvc+/FqsV2ISkn6NLSvwhWj9lvDK+8mZZWCTlxIj/aLqWq2Pw==} engines: {node: '>= 16'} cpu: [x64] os: [linux] - nodejs-polars-win32-x64-msvc@0.18.0: - resolution: {integrity: sha512-jQJST6yDmY/q4kBCCErSaxNrJClL7Dpk7IsdoPrFHXaFzL25nmDxfgow7VWDaEiE45jNL7TXANAgDs7dT61H2Q==} + nodejs-polars-win32-x64-msvc@0.21.0: + resolution: {integrity: sha512-+KAyDvfeEV4naz2XdGGCZlGIv5Jd4dxm7vSvlL63bUeSk0yrPdbCRUCIwsFLV3dpsJDmBCiwBwJpQe7sT4atUA==} engines: {node: '>= 16'} cpu: [x64] os: [win32] - nodejs-polars@0.18.0: - resolution: {integrity: sha512-TN0InAOCzXS2Nrpr+8Sh9oAvILBjIoKMscz9P5XDJ+Q2F6EMb39Um9gwRzJ2kmEqYsufw6NwsafgbY41xKwVWg==} + nodejs-polars@0.21.0: + resolution: {integrity: sha512-EBPp1YlRWcghkFMYZ7eXoGm0UhbA9AHUuBRaseZrtww/F10yphyXdgjN+0riJJjL+XFs5AFXc3k5IQjoobs0BQ==} engines: {node: '>= 18'} normalize-path@3.0.0: @@ -2614,6 +2924,10 @@ packages: engines: {node: ^18.18.0 || >=20.0.0, npm: '>=8.12.1'} hasBin: true + npm-run-path@6.0.0: + resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} + engines: {node: '>=18'} + nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} @@ -2643,10 +2957,14 @@ packages: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} - on-headers@1.0.2: - resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} + on-headers@1.1.0: + resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==} engines: {node: '>= 0.8'} + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + oniguruma-parser@0.12.1: resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==} @@ -2714,6 +3032,10 @@ packages: parse-latin@7.0.0: resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==} + parse-ms@4.0.0: + resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} + engines: {node: '>=18'} + parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} @@ -2721,6 +3043,10 @@ packages: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} + patch-console@2.0.0: + resolution: {integrity: sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -2729,6 +3055,10 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + path-scurry@1.11.1: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} @@ -2743,8 +3073,8 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - pathval@2.0.0: - resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + pathval@2.0.1: + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} engines: {node: '>= 14.16'} picocolors@1.1.1: @@ -2754,8 +3084,8 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - picomatch@4.0.2: - resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} pify@4.0.1: @@ -2772,8 +3102,8 @@ packages: resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} engines: {node: '>=4'} - postcss@8.5.3: - resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} prettier@2.8.8: @@ -2781,6 +3111,10 @@ packages: engines: {node: '>=10.13.0'} hasBin: true + pretty-ms@9.2.0: + resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==} + engines: {node: '>=18'} + prismjs@1.30.0: resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} engines: {node: '>=6'} @@ -2835,6 +3169,16 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} + react-reconciler@0.32.0: + resolution: {integrity: sha512-2NPMOzgTlG0ZWdIf3qG+dcbLSoAc/uLfOwckc3ofy5sSK0pLJqnQLpUFxvGcN2rlXSjnVtGeeFLNimCQEj5gOQ==} + engines: {node: '>=0.10.0'} + peerDependencies: + react: ^19.1.0 + + react@19.1.1: + resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==} + engines: {node: '>=0.10.0'} + read-yaml-file@1.1.0: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} @@ -2846,8 +3190,10 @@ packages: recma-build-jsx@1.0.0: resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} - recma-jsx@1.0.0: - resolution: {integrity: sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q==} + recma-jsx@1.0.1: + resolution: {integrity: sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 recma-parse@1.0.0: resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==} @@ -2864,8 +3210,8 @@ packages: regex@6.0.1: resolution: {integrity: sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==} - rehype-expressive-code@0.41.2: - resolution: {integrity: sha512-vHYfWO9WxAw6kHHctddOt+P4266BtyT1mrOIuxJD+1ELuvuJAa5uBIhYt0OVMyOhlvf57hzWOXJkHnMhpaHyxw==} + rehype-expressive-code@0.41.3: + resolution: {integrity: sha512-8d9Py4c/V6I/Od2VIXFAdpiO2kc0SV2qTJsRAaqSIcM9aruW4ASLNe2kOEo1inXAAkIhpFzAHTc358HKbvpNUg==} rehype-format@5.0.1: resolution: {integrity: sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==} @@ -2918,6 +3264,13 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + restructure@3.0.2: resolution: {integrity: sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==} @@ -2937,8 +3290,8 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rollup@4.40.2: - resolution: {integrity: sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==} + rollup@4.46.2: + resolution: {integrity: sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2960,6 +3313,12 @@ packages: sax@1.4.1: resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + + scheduler@0.26.0: + resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + semver@7.7.2: resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} engines: {node: '>=10'} @@ -2995,8 +3354,8 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shiki@3.4.0: - resolution: {integrity: sha512-Ni80XHcqhOEXv5mmDAvf5p6PAJqbUc/RzFeaOqk+zP5DLvTPS3j0ckvA+MI87qoxTQ5RGJDVTbdl/ENLSyyAnQ==} + shiki@3.9.2: + resolution: {integrity: sha512-t6NKl5e/zGTvw/IyftLcumolgOczhuroqwXngDeMqJ3h3EQiTY/7wmfgPlsmloD8oYfqkEDqxiaH37Pjm1zUhQ==} side-channel-list@1.0.0: resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} @@ -3017,6 +3376,9 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -3044,21 +3406,29 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + slugify@1.6.6: resolution: {integrity: sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==} engines: {node: '>=8.0.0'} - smol-toml@1.3.4: - resolution: {integrity: sha512-UOPtVuYkzYGee0Bd2Szz8d2G3RfMfJ2t3qVdZUAozZyAk+a0Sxa+QKix0YCwjL/A1RR0ar44nCxaoN9FxdJGwA==} + smol-toml@1.4.1: + resolution: {integrity: sha512-CxdwHXyYTONGHThDbq5XdwbFsuY4wlClRGejfE2NtwUtiHYsP1QtNsHb/hnj31jKYSchztJsaA8pSQoVzkfCFg==} engines: {node: '>= 18'} source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map@0.7.4: - resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} - engines: {node: '>= 8'} + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} @@ -3069,6 +3439,10 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -3123,16 +3497,24 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - style-to-js@1.1.16: - resolution: {integrity: sha512-/Q6ld50hKYPH3d/r6nr117TZkHR0w0kGGIVfpG9N6D8NymRPM9RqCUv4pRpJ62E5DqOYx2AFpbZMyCPnjQCnOw==} + strip-final-newline@4.0.0: + resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} + engines: {node: '>=18'} + + style-to-js@1.1.17: + resolution: {integrity: sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA==} - style-to-object@1.0.8: - resolution: {integrity: sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==} + style-to-object@1.0.9: + resolution: {integrity: sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==} supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + temp-dir@3.0.0: resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} engines: {node: '>=14.16'} @@ -3161,12 +3543,12 @@ packages: tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - tinyglobby@0.2.13: - resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==} + tinyglobby@0.2.14: + resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} engines: {node: '>=12.0.0'} - tinypool@1.0.2: - resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} engines: {node: ^18.0.0 || >=20.0.0} tinyrainbow@2.0.0: @@ -3188,6 +3570,10 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + to-rotated@1.0.0: + resolution: {integrity: sha512-KsEID8AfgUy+pxVRLsWp0VzCa69wxzUDZnzGbyIST/bcgcrMvTYoFBX/QORH4YApoD89EDuUovx4BTdpOn319Q==} + engines: {node: '>=18'} + toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} @@ -3205,8 +3591,12 @@ packages: trough@2.2.0: resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} - tsconfck@3.1.5: - resolution: {integrity: sha512-CLDfGgUp7XPswWnezWwsCRxNmgQjhYq3VXHM0/XIRxhVrKw0M1if9agzryh1QS3nxjCROvV+xWxoJO1YctzzWg==} + ts-extras@0.14.0: + resolution: {integrity: sha512-hxaLXbdiDxTAMES3MLwdQhIY7B8+ZaS9GXht9aEIv1dVi2lB8C6syN6UmkCjdXpNzk/aBi3fOs/4NV9bo5+PtQ==} + engines: {node: '>=18'} + + tsconfck@3.1.6: + resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==} engines: {node: ^18 || >=20} hasBin: true peerDependencies: @@ -3218,6 +3608,15 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsx@4.20.3: + resolution: {integrity: sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==} + engines: {node: '>=18.0.0'} + hasBin: true + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + type-fest@1.4.0: resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} engines: {node: '>=10'} @@ -3234,21 +3633,21 @@ packages: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} - typedoc-plugin-markdown@4.6.3: - resolution: {integrity: sha512-86oODyM2zajXwLs4Wok2mwVEfCwCnp756QyhLGX2IfsdRYr1DXLCgJgnLndaMUjJD7FBhnLk2okbNE9PdLxYRw==} + typedoc-plugin-markdown@4.8.0: + resolution: {integrity: sha512-BQqXnT9PETe6WEFf8bcsvvGEGQHbwTo/BFyY+RUIsSB05Y0Wn56iF+fK1PY2OKJJIhV4kp4dp7osaP9Bm5a0Zw==} engines: {node: '>= 18'} peerDependencies: typedoc: 0.28.x - typedoc@0.28.5: - resolution: {integrity: sha512-5PzUddaA9FbaarUzIsEc4wNXCiO4Ot3bJNeMF2qKpYlTmM9TTaSHQ7162w756ERCkXER/+o2purRG6YOAv6EMA==} + typedoc@0.28.9: + resolution: {integrity: sha512-aw45vwtwOl3QkUAmWCnLV9QW1xY+FSX2zzlit4MAfE99wX+Jij4ycnpbAWgBXsRrxmfs9LaYktg/eX5Bpthd3g==} engines: {node: '>= 18', pnpm: '>= 10'} hasBin: true peerDependencies: - typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x + typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x - typescript@5.8.3: - resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + typescript@5.9.2: + resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} engines: {node: '>=14.17'} hasBin: true @@ -3264,8 +3663,8 @@ packages: uncrypto@0.1.3: resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} - undici-types@6.21.0: - resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici-types@7.10.0: + resolution: {integrity: sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==} unicode-properties@1.4.1: resolution: {integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==} @@ -3273,11 +3672,15 @@ packages: unicode-trie@2.0.0: resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==} + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} - unifont@0.5.0: - resolution: {integrity: sha512-4DueXMP5Hy4n607sh+vJ+rajoLu778aU3GzqeTCqsD/EaUcvqZT9wPC8kgK6Vjh22ZskrxyRCR71FwNOaYn6jA==} + unifont@0.5.2: + resolution: {integrity: sha512-LzR4WUqzH9ILFvjLAUU7dK3Lnou/qd5kD+IakBtBK4S15/+x2y9VX+DcWQv6s551R6W+vzwgVS6tFg3XggGBgg==} unique-string@3.0.0: resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} @@ -3325,8 +3728,8 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - unstorage@1.16.0: - resolution: {integrity: sha512-WQ37/H5A7LcRPWfYOrDa1Ys02xAbpPJq6q5GkO88FBXVSQzHd7+BjEwfRqyaSWCv9MbsJy058GWjjPjcJ16GGA==} + unstorage@1.16.1: + resolution: {integrity: sha512-gdpZ3guLDhz+zWIlYP1UwQ259tG5T5vYRzDaHMkQ1bBY1SQPutvZnrRjTFaWUUpseErJIgAZS51h6NOcZVZiqQ==} peerDependencies: '@azure/app-configuration': ^1.8.0 '@azure/cosmos': ^4.2.0 @@ -3336,7 +3739,7 @@ packages: '@azure/storage-blob': ^12.26.0 '@capacitor/preferences': ^6.0.3 || ^7.0.0 '@deno/kv': '>=0.9.0' - '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 + '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0 '@planetscale/database': ^1.19.0 '@upstash/redis': ^1.34.3 '@vercel/blob': '>=0.27.1' @@ -3404,8 +3807,8 @@ packages: vfile-location@5.0.3: resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} - vfile-message@4.0.2: - resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} @@ -3455,10 +3858,10 @@ packages: yaml: optional: true - vitefu@1.0.6: - resolution: {integrity: sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==} + vitefu@1.1.1: + resolution: {integrity: sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==} peerDependencies: - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0 peerDependenciesMeta: vite: optional: true @@ -3514,10 +3917,17 @@ packages: engines: {node: '>=8'} hasBin: true + widest-line@3.1.0: + resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} + engines: {node: '>=8'} + widest-line@5.0.0: resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} engines: {node: '>=18'} + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -3530,12 +3940,24 @@ packages: resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} engines: {node: '>=18'} + ws@8.18.3: + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xxhash-wasm@1.1.0: resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} - yaml@2.7.1: - resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} - engines: {node: '>= 14'} + yaml@2.8.1: + resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==} + engines: {node: '>= 14.6'} hasBin: true yargs-parser@21.1.1: @@ -3553,16 +3975,19 @@ packages: resolution: {integrity: sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==} engines: {node: '>=12.20'} - yocto-spinner@0.2.2: - resolution: {integrity: sha512-21rPcM3e4vCpOXThiFRByX8amU5By1R0wNS8Oex+DP3YgC8xdU0vEJ/K8cbPLiIJVosSSysgcFof6s6MSD5/Vw==} + yocto-spinner@0.2.3: + resolution: {integrity: sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==} engines: {node: '>=18.19'} yoctocolors@2.1.1: resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} engines: {node: '>=18'} - zod-to-json-schema@3.24.5: - resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==} + yoga-layout@3.2.1: + resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==} + + zod-to-json-schema@3.24.6: + resolution: {integrity: sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==} peerDependencies: zod: ^3.24.1 @@ -3572,23 +3997,30 @@ packages: typescript: ^4.9.4 || ^5.0.2 zod: ^3 - zod@3.24.4: - resolution: {integrity: sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==} + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} snapshots: + '@alcalzone/ansi-tokenize@0.1.3': + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + '@ampproject/remapping@2.3.0': dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 - '@astrojs/compiler@2.12.0': {} + '@astrojs/compiler@2.12.2': {} '@astrojs/internal-helpers@0.6.1': {} + '@astrojs/internal-helpers@0.7.1': {} + '@astrojs/markdown-remark@6.3.1': dependencies: '@astrojs/internal-helpers': 0.6.1 @@ -3605,8 +4037,8 @@ snapshots: remark-parse: 11.0.0 remark-rehype: 11.1.2 remark-smartypants: 3.0.2 - shiki: 3.4.0 - smol-toml: 1.3.4 + shiki: 3.9.2 + smol-toml: 1.4.1 unified: 11.0.5 unist-util-remove-position: 5.0.0 unist-util-visit: 5.0.0 @@ -3615,12 +4047,38 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/mdx@4.2.6(astro@5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1))': + '@astrojs/markdown-remark@6.3.5': dependencies: - '@astrojs/markdown-remark': 6.3.1 - '@mdx-js/mdx': 3.1.0(acorn@8.14.1) - acorn: 8.14.1 - astro: 5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1) + '@astrojs/internal-helpers': 0.7.1 + '@astrojs/prism': 3.3.0 + github-slugger: 2.0.0 + hast-util-from-html: 2.0.3 + hast-util-to-text: 4.0.2 + import-meta-resolve: 4.1.0 + js-yaml: 4.1.0 + mdast-util-definitions: 6.0.0 + rehype-raw: 7.0.0 + rehype-stringify: 10.0.1 + remark-gfm: 4.0.1 + remark-parse: 11.0.0 + remark-rehype: 11.1.2 + remark-smartypants: 3.0.2 + shiki: 3.9.2 + smol-toml: 1.4.1 + unified: 11.0.5 + unist-util-remove-position: 5.0.0 + unist-util-visit: 5.0.0 + unist-util-visit-parents: 6.0.1 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@astrojs/mdx@4.3.3(astro@5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1))': + dependencies: + '@astrojs/markdown-remark': 6.3.5 + '@mdx-js/mdx': 3.1.0(acorn@8.15.0) + acorn: 8.15.0 + astro: 5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1) es-module-lexer: 1.7.0 estree-util-visit: 2.0.0 hast-util-to-html: 9.0.5 @@ -3628,7 +4086,7 @@ snapshots: rehype-raw: 7.0.0 remark-gfm: 4.0.1 remark-smartypants: 3.0.2 - source-map: 0.7.4 + source-map: 0.7.6 unist-util-visit: 5.0.0 vfile: 6.0.3 transitivePeerDependencies: @@ -3638,23 +4096,27 @@ snapshots: dependencies: prismjs: 1.30.0 - '@astrojs/sitemap@3.4.0': + '@astrojs/prism@3.3.0': + dependencies: + prismjs: 1.30.0 + + '@astrojs/sitemap@3.4.2': dependencies: sitemap: 8.0.0 stream-replace-string: 2.0.0 - zod: 3.24.4 + zod: 3.25.76 - '@astrojs/starlight@0.34.3(astro@5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1))': + '@astrojs/starlight@0.34.3(astro@5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1))': dependencies: - '@astrojs/markdown-remark': 6.3.1 - '@astrojs/mdx': 4.2.6(astro@5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1)) - '@astrojs/sitemap': 3.4.0 + '@astrojs/markdown-remark': 6.3.5 + '@astrojs/mdx': 4.3.3(astro@5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1)) + '@astrojs/sitemap': 3.4.2 '@pagefind/default-ui': 1.3.0 '@types/hast': 3.0.4 '@types/js-yaml': 4.0.9 '@types/mdast': 4.0.4 - astro: 5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1) - astro-expressive-code: 0.41.2(astro@5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1)) + astro: 5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1) + astro-expressive-code: 0.41.3(astro@5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1)) bcp-47: 2.1.0 hast-util-from-html: 2.0.3 hast-util-select: 6.0.4 @@ -3679,8 +4141,8 @@ snapshots: '@astrojs/telemetry@3.2.1': dependencies: - ci-info: 4.2.0 - debug: 4.4.0 + ci-info: 4.3.0 + debug: 4.4.1(supports-color@8.1.1) dlv: 1.1.3 dset: 3.1.4 is-docker: 3.0.0 @@ -3693,13 +4155,13 @@ snapshots: '@babel/helper-validator-identifier@7.27.1': {} - '@babel/parser@7.27.2': + '@babel/parser@7.28.0': dependencies: - '@babel/types': 7.27.1 + '@babel/types': 7.28.2 - '@babel/runtime@7.27.1': {} + '@babel/runtime@7.28.2': {} - '@babel/types@7.27.1': + '@babel/types@7.28.2': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 @@ -3893,128 +4355,131 @@ snapshots: '@ctrl/tinycolor@4.1.0': {} - '@emnapi/core@1.4.3': + '@emnapi/core@1.4.5': dependencies: - '@emnapi/wasi-threads': 1.0.2 + '@emnapi/wasi-threads': 1.0.4 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.4.3': + '@emnapi/runtime@1.4.5': dependencies: tslib: 2.8.1 optional: true - '@emnapi/wasi-threads@1.0.2': + '@emnapi/wasi-threads@1.0.4': dependencies: tslib: 2.8.1 optional: true - '@esbuild/aix-ppc64@0.25.4': + '@esbuild/aix-ppc64@0.25.8': + optional: true + + '@esbuild/android-arm64@0.25.8': optional: true - '@esbuild/android-arm64@0.25.4': + '@esbuild/android-arm@0.25.8': optional: true - '@esbuild/android-arm@0.25.4': + '@esbuild/android-x64@0.25.8': optional: true - '@esbuild/android-x64@0.25.4': + '@esbuild/darwin-arm64@0.25.8': optional: true - '@esbuild/darwin-arm64@0.25.4': + '@esbuild/darwin-x64@0.25.8': optional: true - '@esbuild/darwin-x64@0.25.4': + '@esbuild/freebsd-arm64@0.25.8': optional: true - '@esbuild/freebsd-arm64@0.25.4': + '@esbuild/freebsd-x64@0.25.8': optional: true - '@esbuild/freebsd-x64@0.25.4': + '@esbuild/linux-arm64@0.25.8': optional: true - '@esbuild/linux-arm64@0.25.4': + '@esbuild/linux-arm@0.25.8': optional: true - '@esbuild/linux-arm@0.25.4': + '@esbuild/linux-ia32@0.25.8': optional: true - '@esbuild/linux-ia32@0.25.4': + '@esbuild/linux-loong64@0.25.8': optional: true - '@esbuild/linux-loong64@0.25.4': + '@esbuild/linux-mips64el@0.25.8': optional: true - '@esbuild/linux-mips64el@0.25.4': + '@esbuild/linux-ppc64@0.25.8': optional: true - '@esbuild/linux-ppc64@0.25.4': + '@esbuild/linux-riscv64@0.25.8': optional: true - '@esbuild/linux-riscv64@0.25.4': + '@esbuild/linux-s390x@0.25.8': optional: true - '@esbuild/linux-s390x@0.25.4': + '@esbuild/linux-x64@0.25.8': optional: true - '@esbuild/linux-x64@0.25.4': + '@esbuild/netbsd-arm64@0.25.8': optional: true - '@esbuild/netbsd-arm64@0.25.4': + '@esbuild/netbsd-x64@0.25.8': optional: true - '@esbuild/netbsd-x64@0.25.4': + '@esbuild/openbsd-arm64@0.25.8': optional: true - '@esbuild/openbsd-arm64@0.25.4': + '@esbuild/openbsd-x64@0.25.8': optional: true - '@esbuild/openbsd-x64@0.25.4': + '@esbuild/openharmony-arm64@0.25.8': optional: true - '@esbuild/sunos-x64@0.25.4': + '@esbuild/sunos-x64@0.25.8': optional: true - '@esbuild/win32-arm64@0.25.4': + '@esbuild/win32-arm64@0.25.8': optional: true - '@esbuild/win32-ia32@0.25.4': + '@esbuild/win32-ia32@0.25.8': optional: true - '@esbuild/win32-x64@0.25.4': + '@esbuild/win32-x64@0.25.8': optional: true - '@expressive-code/core@0.41.2': + '@expressive-code/core@0.41.3': dependencies: '@ctrl/tinycolor': 4.1.0 hast-util-select: 6.0.4 hast-util-to-html: 9.0.5 hast-util-to-text: 4.0.2 hastscript: 9.0.1 - postcss: 8.5.3 - postcss-nested: 6.2.0(postcss@8.5.3) + postcss: 8.5.6 + postcss-nested: 6.2.0(postcss@8.5.6) unist-util-visit: 5.0.0 unist-util-visit-parents: 6.0.1 - '@expressive-code/plugin-frames@0.41.2': + '@expressive-code/plugin-frames@0.41.3': dependencies: - '@expressive-code/core': 0.41.2 + '@expressive-code/core': 0.41.3 - '@expressive-code/plugin-shiki@0.41.2': + '@expressive-code/plugin-shiki@0.41.3': dependencies: - '@expressive-code/core': 0.41.2 - shiki: 3.4.0 + '@expressive-code/core': 0.41.3 + shiki: 3.9.2 - '@expressive-code/plugin-text-markers@0.41.2': + '@expressive-code/plugin-text-markers@0.41.3': dependencies: - '@expressive-code/core': 0.41.2 + '@expressive-code/core': 0.41.3 - '@gerrit0/mini-shiki@3.4.0': + '@gerrit0/mini-shiki@3.9.2': dependencies: - '@shikijs/engine-oniguruma': 3.4.0 - '@shikijs/langs': 3.4.0 - '@shikijs/themes': 3.4.0 - '@shikijs/types': 3.4.0 + '@shikijs/engine-oniguruma': 3.9.2 + '@shikijs/langs': 3.9.2 + '@shikijs/themes': 3.9.2 + '@shikijs/types': 3.9.2 '@shikijs/vscode-textmate': 10.0.2 '@img/sharp-darwin-arm64@0.33.5': @@ -4150,12 +4615,12 @@ snapshots: '@img/sharp-wasm32@0.33.5': dependencies: - '@emnapi/runtime': 1.4.3 + '@emnapi/runtime': 1.4.5 optional: true '@img/sharp-wasm32@0.34.2': dependencies: - '@emnapi/runtime': 1.4.3 + '@emnapi/runtime': 1.4.5 optional: true '@img/sharp-win32-arm64@0.34.2': @@ -4184,42 +4649,39 @@ snapshots: '@istanbuljs/schema@0.1.3': {} - '@jridgewell/gen-mapping@0.3.8': + '@jridgewell/gen-mapping@0.3.12': dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/trace-mapping': 0.3.29 '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/set-array@1.2.1': {} + '@jridgewell/sourcemap-codec@1.5.4': {} - '@jridgewell/sourcemap-codec@1.5.0': {} - - '@jridgewell/trace-mapping@0.3.25': + '@jridgewell/trace-mapping@0.3.29': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.4 '@manypkg/find-root@1.1.0': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.2 '@types/node': 12.20.55 find-up: 4.1.0 fs-extra: 8.1.0 '@manypkg/get-packages@1.1.3': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.2 '@changesets/types': 4.1.0 '@manypkg/find-root': 1.1.0 fs-extra: 8.1.0 globby: 11.1.0 read-yaml-file: 1.1.0 - '@mdx-js/mdx@3.1.0(acorn@8.14.1)': + '@mdx-js/mdx@3.1.0(acorn@8.15.0)': dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 '@types/estree-jsx': 1.0.5 '@types/hast': 3.0.4 '@types/mdx': 2.0.13 @@ -4231,13 +4693,13 @@ snapshots: hast-util-to-jsx-runtime: 2.3.6 markdown-extensions: 2.0.0 recma-build-jsx: 1.0.0 - recma-jsx: 1.0.0(acorn@8.14.1) + recma-jsx: 1.0.1(acorn@8.15.0) recma-stringify: 1.0.0 rehype-recma: 1.0.0 remark-mdx: 3.1.0 remark-parse: 11.0.0 remark-rehype: 11.1.2 - source-map: 0.7.4 + source-map: 0.7.6 unified: 11.0.5 unist-util-position-from-estree: 2.0.0 unist-util-stringify-position: 4.0.0 @@ -4247,11 +4709,11 @@ snapshots: - acorn - supports-color - '@napi-rs/wasm-runtime@0.2.10': + '@napi-rs/wasm-runtime@0.2.12': dependencies: - '@emnapi/core': 1.4.3 - '@emnapi/runtime': 1.4.3 - '@tybys/wasm-util': 0.9.0 + '@emnapi/core': 1.4.5 + '@emnapi/runtime': 1.4.5 + '@tybys/wasm-util': 0.10.0 optional: true '@node-rs/crc32-android-arm-eabi@1.10.6': @@ -4286,7 +4748,7 @@ snapshots: '@node-rs/crc32-wasm32-wasi@1.10.6': dependencies: - '@napi-rs/wasm-runtime': 0.2.10 + '@napi-rs/wasm-runtime': 0.2.12 optional: true '@node-rs/crc32-win32-arm64-msvc@1.10.6': @@ -4327,6 +4789,36 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 + '@oclif/core@4.5.2': + dependencies: + ansi-escapes: 4.3.2 + ansis: 3.17.0 + clean-stack: 3.0.1 + cli-spinners: 2.9.2 + debug: 4.4.1(supports-color@8.1.1) + ejs: 3.1.10 + get-package-type: 0.1.0 + indent-string: 4.0.0 + is-wsl: 2.2.0 + lilconfig: 3.1.3 + minimatch: 9.0.5 + semver: 7.7.2 + string-width: 4.2.3 + supports-color: 8.1.1 + tinyglobby: 0.2.14 + widest-line: 3.1.0 + wordwrap: 1.0.0 + wrap-ansi: 7.0.0 + + '@oclif/plugin-autocomplete@3.2.34': + dependencies: + '@oclif/core': 4.5.2 + ansis: 3.17.0 + debug: 4.4.1(supports-color@8.1.1) + ejs: 3.1.10 + transitivePeerDependencies: + - supports-color + '@oslojs/encoding@1.1.0': {} '@pagefind/darwin-arm64@1.3.0': @@ -4351,11 +4843,10 @@ snapshots: '@polka/url@1.0.0-next.29': {} - '@pollyjs/adapter-fetch@6.0.6': + '@pollyjs/adapter-fetch@6.0.7': dependencies: '@pollyjs/adapter': 6.0.6 '@pollyjs/utils': 6.0.6 - detect-node: 2.1.0 to-arraybuffer: 1.0.1 '@pollyjs/adapter@6.0.6': @@ -4382,7 +4873,7 @@ snapshots: express: 4.21.2 fs-extra: 10.1.0 http-graceful-shutdown: 3.1.14 - morgan: 1.10.0 + morgan: 1.10.1 nocache: 3.0.4 transitivePeerDependencies: - supports-color @@ -4409,101 +4900,103 @@ snapshots: qs: 6.14.0 url-parse: 1.5.10 - '@rollup/pluginutils@5.1.4(rollup@4.40.2)': + '@rollup/pluginutils@5.2.0(rollup@4.46.2)': dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 estree-walker: 2.0.2 - picomatch: 4.0.2 + picomatch: 4.0.3 optionalDependencies: - rollup: 4.40.2 + rollup: 4.46.2 - '@rollup/rollup-android-arm-eabi@4.40.2': + '@rollup/rollup-android-arm-eabi@4.46.2': optional: true - '@rollup/rollup-android-arm64@4.40.2': + '@rollup/rollup-android-arm64@4.46.2': optional: true - '@rollup/rollup-darwin-arm64@4.40.2': + '@rollup/rollup-darwin-arm64@4.46.2': optional: true - '@rollup/rollup-darwin-x64@4.40.2': + '@rollup/rollup-darwin-x64@4.46.2': optional: true - '@rollup/rollup-freebsd-arm64@4.40.2': + '@rollup/rollup-freebsd-arm64@4.46.2': optional: true - '@rollup/rollup-freebsd-x64@4.40.2': + '@rollup/rollup-freebsd-x64@4.46.2': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.40.2': + '@rollup/rollup-linux-arm-gnueabihf@4.46.2': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.40.2': + '@rollup/rollup-linux-arm-musleabihf@4.46.2': optional: true - '@rollup/rollup-linux-arm64-gnu@4.40.2': + '@rollup/rollup-linux-arm64-gnu@4.46.2': optional: true - '@rollup/rollup-linux-arm64-musl@4.40.2': + '@rollup/rollup-linux-arm64-musl@4.46.2': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.40.2': + '@rollup/rollup-linux-loongarch64-gnu@4.46.2': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.40.2': + '@rollup/rollup-linux-ppc64-gnu@4.46.2': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.40.2': + '@rollup/rollup-linux-riscv64-gnu@4.46.2': optional: true - '@rollup/rollup-linux-riscv64-musl@4.40.2': + '@rollup/rollup-linux-riscv64-musl@4.46.2': optional: true - '@rollup/rollup-linux-s390x-gnu@4.40.2': + '@rollup/rollup-linux-s390x-gnu@4.46.2': optional: true - '@rollup/rollup-linux-x64-gnu@4.40.2': + '@rollup/rollup-linux-x64-gnu@4.46.2': optional: true - '@rollup/rollup-linux-x64-musl@4.40.2': + '@rollup/rollup-linux-x64-musl@4.46.2': optional: true - '@rollup/rollup-win32-arm64-msvc@4.40.2': + '@rollup/rollup-win32-arm64-msvc@4.46.2': optional: true - '@rollup/rollup-win32-ia32-msvc@4.40.2': + '@rollup/rollup-win32-ia32-msvc@4.46.2': optional: true - '@rollup/rollup-win32-x64-msvc@4.40.2': + '@rollup/rollup-win32-x64-msvc@4.46.2': optional: true - '@shikijs/core@3.4.0': + '@sec-ant/readable-stream@0.4.1': {} + + '@shikijs/core@3.9.2': dependencies: - '@shikijs/types': 3.4.0 + '@shikijs/types': 3.9.2 '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 hast-util-to-html: 9.0.5 - '@shikijs/engine-javascript@3.4.0': + '@shikijs/engine-javascript@3.9.2': dependencies: - '@shikijs/types': 3.4.0 + '@shikijs/types': 3.9.2 '@shikijs/vscode-textmate': 10.0.2 oniguruma-to-es: 4.3.3 - '@shikijs/engine-oniguruma@3.4.0': + '@shikijs/engine-oniguruma@3.9.2': dependencies: - '@shikijs/types': 3.4.0 + '@shikijs/types': 3.9.2 '@shikijs/vscode-textmate': 10.0.2 - '@shikijs/langs@3.4.0': + '@shikijs/langs@3.9.2': dependencies: - '@shikijs/types': 3.4.0 + '@shikijs/types': 3.9.2 - '@shikijs/themes@3.4.0': + '@shikijs/themes@3.9.2': dependencies: - '@shikijs/types': 3.4.0 + '@shikijs/types': 3.9.2 - '@shikijs/types@3.4.0': + '@shikijs/types@3.9.2': dependencies: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 @@ -4512,11 +5005,18 @@ snapshots: '@sindresorhus/fnv1a@2.0.1': {} + '@sindresorhus/merge-streams@4.0.0': {} + + '@sindresorhus/slugify@0.9.1': + dependencies: + escape-string-regexp: 1.0.5 + lodash.deburr: 4.1.0 + '@swc/helpers@0.5.17': dependencies: tslib: 2.8.1 - '@tybys/wasm-util@0.9.0': + '@tybys/wasm-util@0.10.0': dependencies: tslib: 2.8.1 optional: true @@ -4527,13 +5027,13 @@ snapshots: '@types/estree-jsx@1.0.5': dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 - '@types/estree@1.0.7': {} + '@types/estree@1.0.8': {} '@types/fontkit@2.0.8': dependencies: - '@types/node': 22.15.31 + '@types/node': 24.2.0 '@types/hast@3.0.4': dependencies: @@ -4557,25 +5057,21 @@ snapshots: '@types/node@17.0.45': {} - '@types/node@22.14.1': - dependencies: - undici-types: 6.21.0 - - '@types/node@22.15.24': + '@types/node@24.2.0': dependencies: - undici-types: 6.21.0 + undici-types: 7.10.0 - '@types/node@22.15.31': + '@types/react@19.1.9': dependencies: - undici-types: 6.21.0 + csstype: 3.1.3 '@types/sax@1.2.7': dependencies: - '@types/node': 22.15.31 + '@types/node': 24.2.0 '@types/set-cookie-parser@2.4.10': dependencies: - '@types/node': 22.15.31 + '@types/node': 24.2.0 '@types/unist@2.0.11': {} @@ -4583,11 +5079,11 @@ snapshots: '@types/yauzl-promise@4.0.1': dependencies: - '@types/node': 22.14.1 + '@types/node': 24.2.0 '@types/yazl@3.3.0': dependencies: - '@types/node': 22.15.24 + '@types/node': 24.2.0 '@ungap/structured-clone@1.3.0': {} @@ -4595,7 +5091,7 @@ snapshots: dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 - debug: 4.4.0 + debug: 4.4.1(supports-color@8.1.1) istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 @@ -4605,7 +5101,7 @@ snapshots: std-env: 3.9.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.1.4(@types/debug@4.1.12)(@types/node@22.15.31)(@vitest/ui@3.1.4)(yaml@2.7.1) + vitest: 3.1.4(@types/debug@4.1.12)(@types/node@24.2.0)(@vitest/ui@3.1.4)(tsx@4.20.3)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -4613,21 +5109,25 @@ snapshots: dependencies: '@vitest/spy': 3.1.4 '@vitest/utils': 3.1.4 - chai: 5.2.0 + chai: 5.2.1 tinyrainbow: 2.0.0 - '@vitest/mocker@3.1.4(vite@6.3.5(@types/node@22.15.31)(yaml@2.7.1))': + '@vitest/mocker@3.1.4(vite@6.3.5(@types/node@24.2.0)(tsx@4.20.3)(yaml@2.8.1))': dependencies: '@vitest/spy': 3.1.4 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.3.5(@types/node@22.15.31)(yaml@2.7.1) + vite: 6.3.5(@types/node@24.2.0)(tsx@4.20.3)(yaml@2.8.1) '@vitest/pretty-format@3.1.4': dependencies: tinyrainbow: 2.0.0 + '@vitest/pretty-format@3.2.4': + dependencies: + tinyrainbow: 2.0.0 + '@vitest/runner@3.1.4': dependencies: '@vitest/utils': 3.1.4 @@ -4650,14 +5150,14 @@ snapshots: flatted: 3.3.3 pathe: 2.0.3 sirv: 3.0.1 - tinyglobby: 0.2.13 + tinyglobby: 0.2.14 tinyrainbow: 2.0.0 - vitest: 3.1.4(@types/debug@4.1.12)(@types/node@22.15.31)(@vitest/ui@3.1.4)(yaml@2.7.1) + vitest: 3.1.4(@types/debug@4.1.12)(@types/node@24.2.0)(@vitest/ui@3.1.4)(tsx@4.20.3)(yaml@2.8.1) '@vitest/utils@3.1.4': dependencies: '@vitest/pretty-format': 3.1.4 - loupe: 3.1.3 + loupe: 3.2.0 tinyrainbow: 2.0.0 accepts@1.3.8: @@ -4665,11 +5165,11 @@ snapshots: mime-types: 2.1.35 negotiator: 0.6.3 - acorn-jsx@5.3.2(acorn@8.14.1): + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: - acorn: 8.14.1 + acorn: 8.15.0 - acorn@8.14.1: {} + acorn@8.15.0: {} ajv@8.17.1: dependencies: @@ -4684,6 +5184,14 @@ snapshots: ansi-colors@4.1.3: {} + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-escapes@7.0.0: + dependencies: + environment: 1.1.0 + ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} @@ -4694,6 +5202,8 @@ snapshots: ansi-styles@6.2.1: {} + ansis@3.17.0: {} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 @@ -4719,37 +5229,37 @@ snapshots: astring@1.9.0: {} - astro-expressive-code@0.41.2(astro@5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1)): + astro-expressive-code@0.41.3(astro@5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1)): dependencies: - astro: 5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1) - rehype-expressive-code: 0.41.2 + astro: 5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1) + rehype-expressive-code: 0.41.3 - astro@5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1): + astro@5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1): dependencies: - '@astrojs/compiler': 2.12.0 + '@astrojs/compiler': 2.12.2 '@astrojs/internal-helpers': 0.6.1 '@astrojs/markdown-remark': 6.3.1 '@astrojs/telemetry': 3.2.1 '@capsizecss/unpack': 2.4.0 '@oslojs/encoding': 1.1.0 - '@rollup/pluginutils': 5.1.4(rollup@4.40.2) - acorn: 8.14.1 + '@rollup/pluginutils': 5.2.0(rollup@4.46.2) + acorn: 8.15.0 aria-query: 5.3.2 axobject-query: 4.1.0 boxen: 8.0.1 - ci-info: 4.2.0 + ci-info: 4.3.0 clsx: 2.1.1 common-ancestor-path: 1.0.1 cookie: 1.0.2 cssesc: 3.0.0 - debug: 4.4.0 + debug: 4.4.1(supports-color@8.1.1) deterministic-object-hash: 2.0.2 devalue: 5.1.1 diff: 5.2.0 dlv: 1.1.3 dset: 3.1.4 es-module-lexer: 1.7.0 - esbuild: 0.25.4 + esbuild: 0.25.8 estree-walker: 3.0.3 flattie: 1.1.1 fontace: 0.3.0 @@ -4765,27 +5275,27 @@ snapshots: p-limit: 6.2.0 p-queue: 8.1.0 package-manager-detector: 1.3.0 - picomatch: 4.0.2 + picomatch: 4.0.3 prompts: 2.4.2 rehype: 13.0.2 semver: 7.7.2 - shiki: 3.4.0 + shiki: 3.9.2 tinyexec: 0.3.2 - tinyglobby: 0.2.13 - tsconfck: 3.1.5(typescript@5.8.3) + tinyglobby: 0.2.14 + tsconfck: 3.1.6(typescript@5.9.2) ultrahtml: 1.6.0 - unifont: 0.5.0 + unifont: 0.5.2 unist-util-visit: 5.0.0 - unstorage: 1.16.0 + unstorage: 1.16.1 vfile: 6.0.3 - vite: 6.3.5(@types/node@22.15.31)(yaml@2.7.1) - vitefu: 1.0.6(vite@6.3.5(@types/node@22.15.31)(yaml@2.7.1)) + vite: 6.3.5(@types/node@24.2.0)(tsx@4.20.3)(yaml@2.8.1) + vitefu: 1.1.1(vite@6.3.5(@types/node@24.2.0)(tsx@4.20.3)(yaml@2.8.1)) xxhash-wasm: 1.1.0 yargs-parser: 21.1.1 - yocto-spinner: 0.2.2 - zod: 3.24.4 - zod-to-json-schema: 3.24.5(zod@3.24.4) - zod-to-ts: 1.2.0(typescript@5.8.3)(zod@3.24.4) + yocto-spinner: 0.2.3 + zod: 3.25.76 + zod-to-json-schema: 3.24.6(zod@3.25.76) + zod-to-ts: 1.2.0(typescript@5.9.2)(zod@3.25.76) optionalDependencies: sharp: 0.33.5 transitivePeerDependencies: @@ -4823,6 +5333,10 @@ snapshots: - uploadthing - yaml + async@3.2.6: {} + + auto-bind@5.0.1: {} + axobject-query@4.1.0: {} bail@2.0.2: {} @@ -4878,14 +5392,14 @@ snapshots: dependencies: ansi-align: 3.0.1 camelcase: 8.0.0 - chalk: 5.4.1 + chalk: 5.5.0 cli-boxes: 3.0.0 string-width: 7.2.0 type-fest: 4.41.0 widest-line: 5.0.0 wrap-ansi: 9.0.0 - brace-expansion@2.0.1: + brace-expansion@2.0.2: dependencies: balanced-match: 1.0.2 @@ -4917,15 +5431,15 @@ snapshots: ccount@2.0.1: {} - chai@5.2.0: + chai@5.2.1: dependencies: assertion-error: 2.0.1 check-error: 2.1.1 deep-eql: 5.0.2 - loupe: 3.1.3 - pathval: 2.0.0 + loupe: 3.2.0 + pathval: 2.0.1 - chalk@5.4.1: {} + chalk@5.5.0: {} character-entities-html4@2.1.0: {} @@ -4945,14 +5459,33 @@ snapshots: ci-info@3.9.0: {} - ci-info@4.2.0: {} + ci-info@4.3.0: {} + + clean-stack@3.0.1: + dependencies: + escape-string-regexp: 4.0.0 cli-boxes@3.0.0: {} + cli-cursor@4.0.0: + dependencies: + restore-cursor: 4.0.0 + + cli-spinners@2.9.2: {} + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.2.0 + clone@2.1.2: {} clsx@2.1.1: {} + code-excerpt@4.0.0: + dependencies: + convert-to-spaces: 2.0.1 + collapse-white-space@2.1.0: {} color-convert@2.0.1: @@ -4981,6 +5514,8 @@ snapshots: content-type@1.0.5: {} + convert-to-spaces@2.0.1: {} + cookie-es@1.2.2: {} cookie-signature@1.0.6: {} @@ -5014,7 +5549,7 @@ snapshots: dependencies: type-fest: 1.4.0 - css-selector-parser@3.1.2: {} + css-selector-parser@3.1.3: {} css-tree@3.1.0: dependencies: @@ -5023,17 +5558,21 @@ snapshots: cssesc@3.0.0: {} + csstype@3.1.3: {} + csv-sniffer@0.1.1: {} debug@2.6.9: dependencies: ms: 2.0.0 - debug@4.4.0: + debug@4.4.1(supports-color@8.1.1): dependencies: ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 - decode-named-character-reference@1.1.0: + decode-named-character-reference@1.2.0: dependencies: character-entities: 2.0.2 @@ -5065,8 +5604,6 @@ snapshots: detect-libc@2.0.4: {} - detect-node@2.1.0: {} - deterministic-object-hash@2.0.2: dependencies: base-64: 1.0.0 @@ -5101,6 +5638,10 @@ snapshots: ee-first@1.1.1: {} + ejs@3.1.10: + dependencies: + jake: 10.9.4 + emoji-regex@10.4.0: {} emoji-regex@8.0.0: {} @@ -5118,7 +5659,9 @@ snapshots: entities@4.5.0: {} - entities@6.0.0: {} + entities@6.0.1: {} + + environment@1.1.0: {} es-define-property@1.0.1: {} @@ -5130,6 +5673,8 @@ snapshots: dependencies: es-errors: 1.3.0 + es-toolkit@1.39.8: {} + esast-util-from-estree@2.0.0: dependencies: '@types/estree-jsx': 1.0.5 @@ -5140,47 +5685,54 @@ snapshots: esast-util-from-js@2.0.1: dependencies: '@types/estree-jsx': 1.0.5 - acorn: 8.14.1 + acorn: 8.15.0 esast-util-from-estree: 2.0.0 - vfile-message: 4.0.2 + vfile-message: 4.0.3 - esbuild@0.25.4: + esbuild@0.25.8: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.4 - '@esbuild/android-arm': 0.25.4 - '@esbuild/android-arm64': 0.25.4 - '@esbuild/android-x64': 0.25.4 - '@esbuild/darwin-arm64': 0.25.4 - '@esbuild/darwin-x64': 0.25.4 - '@esbuild/freebsd-arm64': 0.25.4 - '@esbuild/freebsd-x64': 0.25.4 - '@esbuild/linux-arm': 0.25.4 - '@esbuild/linux-arm64': 0.25.4 - '@esbuild/linux-ia32': 0.25.4 - '@esbuild/linux-loong64': 0.25.4 - '@esbuild/linux-mips64el': 0.25.4 - '@esbuild/linux-ppc64': 0.25.4 - '@esbuild/linux-riscv64': 0.25.4 - '@esbuild/linux-s390x': 0.25.4 - '@esbuild/linux-x64': 0.25.4 - '@esbuild/netbsd-arm64': 0.25.4 - '@esbuild/netbsd-x64': 0.25.4 - '@esbuild/openbsd-arm64': 0.25.4 - '@esbuild/openbsd-x64': 0.25.4 - '@esbuild/sunos-x64': 0.25.4 - '@esbuild/win32-arm64': 0.25.4 - '@esbuild/win32-ia32': 0.25.4 - '@esbuild/win32-x64': 0.25.4 + '@esbuild/aix-ppc64': 0.25.8 + '@esbuild/android-arm': 0.25.8 + '@esbuild/android-arm64': 0.25.8 + '@esbuild/android-x64': 0.25.8 + '@esbuild/darwin-arm64': 0.25.8 + '@esbuild/darwin-x64': 0.25.8 + '@esbuild/freebsd-arm64': 0.25.8 + '@esbuild/freebsd-x64': 0.25.8 + '@esbuild/linux-arm': 0.25.8 + '@esbuild/linux-arm64': 0.25.8 + '@esbuild/linux-ia32': 0.25.8 + '@esbuild/linux-loong64': 0.25.8 + '@esbuild/linux-mips64el': 0.25.8 + '@esbuild/linux-ppc64': 0.25.8 + '@esbuild/linux-riscv64': 0.25.8 + '@esbuild/linux-s390x': 0.25.8 + '@esbuild/linux-x64': 0.25.8 + '@esbuild/netbsd-arm64': 0.25.8 + '@esbuild/netbsd-x64': 0.25.8 + '@esbuild/openbsd-arm64': 0.25.8 + '@esbuild/openbsd-x64': 0.25.8 + '@esbuild/openharmony-arm64': 0.25.8 + '@esbuild/sunos-x64': 0.25.8 + '@esbuild/win32-arm64': 0.25.8 + '@esbuild/win32-ia32': 0.25.8 + '@esbuild/win32-x64': 0.25.8 escape-html@1.0.3: {} + escape-string-regexp@1.0.5: {} + + escape-string-regexp@2.0.0: {} + + escape-string-regexp@4.0.0: {} + escape-string-regexp@5.0.0: {} esprima@4.0.1: {} estree-util-attach-comments@3.0.0: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 estree-util-build-jsx@3.0.1: dependencies: @@ -5193,14 +5745,14 @@ snapshots: estree-util-scope@1.0.0: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 devlop: 1.1.0 estree-util-to-js@2.0.0: dependencies: '@types/estree-jsx': 1.0.5 astring: 1.9.0 - source-map: 0.7.4 + source-map: 0.7.6 estree-util-visit@2.0.0: dependencies: @@ -5211,15 +5763,30 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 etag@1.8.1: {} eventemitter3@5.0.1: {} + execa@9.6.0: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + cross-spawn: 7.0.6 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 8.0.1 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 6.0.0 + pretty-ms: 9.2.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.1.1 + exit-hook@4.0.0: {} - expect-type@1.2.1: {} + expect-type@1.2.2: {} express@4.21.2: dependencies: @@ -5257,12 +5824,12 @@ snapshots: transitivePeerDependencies: - supports-color - expressive-code@0.41.2: + expressive-code@0.41.3: dependencies: - '@expressive-code/core': 0.41.2 - '@expressive-code/plugin-frames': 0.41.2 - '@expressive-code/plugin-shiki': 0.41.2 - '@expressive-code/plugin-text-markers': 0.41.2 + '@expressive-code/core': 0.41.3 + '@expressive-code/plugin-frames': 0.41.3 + '@expressive-code/plugin-shiki': 0.41.3 + '@expressive-code/plugin-text-markers': 0.41.3 extend@3.0.2: {} @@ -5292,12 +5859,20 @@ snapshots: dependencies: reusify: 1.1.0 - fdir@6.4.4(picomatch@4.0.2): + fdir@6.4.6(picomatch@4.0.3): optionalDependencies: - picomatch: 4.0.2 + picomatch: 4.0.3 fflate@0.8.2: {} + figures@6.1.0: + dependencies: + is-unicode-supported: 2.1.0 + + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -5387,11 +5962,22 @@ snapshots: hasown: 2.0.2 math-intrinsics: 1.1.0 + get-package-type@0.1.0: {} + get-proto@1.0.1: dependencies: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 + get-stream@9.0.1: + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + + get-tsconfig@4.10.1: + dependencies: + resolve-pkg-maps: 1.0.0 + github-slugger@2.0.0: {} glob-parent@5.1.2: @@ -5425,14 +6011,14 @@ snapshots: graceful-fs@4.2.11: {} - h3@1.15.3: + h3@1.15.4: dependencies: cookie-es: 1.2.2 crossws: 0.3.5 defu: 6.1.4 destr: 2.0.5 iron-webcrypto: 1.2.1 - node-mock-http: 1.0.0 + node-mock-http: 1.0.2 radix3: 1.1.2 ufo: 1.6.1 uncrypto: 0.1.3 @@ -5471,7 +6057,7 @@ snapshots: hast-util-from-parse5: 8.0.3 parse5: 7.3.0 vfile: 6.0.3 - vfile-message: 4.0.2 + vfile-message: 4.0.3 hast-util-from-parse5@8.0.3: dependencies: @@ -5538,7 +6124,7 @@ snapshots: '@types/unist': 3.0.3 bcp-47-match: 2.0.3 comma-separated-tokens: 2.0.3 - css-selector-parser: 3.1.2 + css-selector-parser: 3.1.3 devlop: 1.1.0 direction: 2.0.1 hast-util-has-property: 3.0.0 @@ -5552,7 +6138,7 @@ snapshots: hast-util-to-estree@3.1.3: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 '@types/estree-jsx': 1.0.5 '@types/hast': 3.0.4 comma-separated-tokens: 2.0.3 @@ -5565,7 +6151,7 @@ snapshots: mdast-util-mdxjs-esm: 2.0.1 property-information: 7.1.0 space-separated-tokens: 2.0.2 - style-to-js: 1.1.16 + style-to-js: 1.1.17 unist-util-position: 5.0.0 zwitch: 2.0.4 transitivePeerDependencies: @@ -5587,7 +6173,7 @@ snapshots: hast-util-to-jsx-runtime@2.3.6: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 '@types/hast': 3.0.4 '@types/unist': 3.0.3 comma-separated-tokens: 2.0.3 @@ -5599,9 +6185,9 @@ snapshots: mdast-util-mdxjs-esm: 2.0.1 property-information: 7.1.0 space-separated-tokens: 2.0.2 - style-to-js: 1.1.16 + style-to-js: 1.1.17 unist-util-position: 5.0.0 - vfile-message: 4.0.2 + vfile-message: 4.0.3 transitivePeerDependencies: - supports-color @@ -5658,17 +6244,19 @@ snapshots: http-graceful-shutdown@3.1.14: dependencies: - debug: 4.4.0 + debug: 4.4.1(supports-color@8.1.1) transitivePeerDependencies: - supports-color human-id@4.1.1: {} + human-signals@8.0.1: {} + husky@9.1.7: {} i18next@23.16.8: dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.2 iconv-lite@0.4.24: dependencies: @@ -5678,8 +6266,52 @@ snapshots: import-meta-resolve@4.1.0: {} + indent-string@4.0.0: {} + + indent-string@5.0.0: {} + inherits@2.0.4: {} + ink-select-input@6.2.0(ink@6.1.0(@types/react@19.1.9)(react@19.1.1))(react@19.1.1): + dependencies: + figures: 6.1.0 + ink: 6.1.0(@types/react@19.1.9)(react@19.1.1) + react: 19.1.1 + to-rotated: 1.0.0 + + ink@6.1.0(@types/react@19.1.9)(react@19.1.1): + dependencies: + '@alcalzone/ansi-tokenize': 0.1.3 + ansi-escapes: 7.0.0 + ansi-styles: 6.2.1 + auto-bind: 5.0.1 + chalk: 5.5.0 + cli-boxes: 3.0.0 + cli-cursor: 4.0.0 + cli-truncate: 4.0.0 + code-excerpt: 4.0.0 + es-toolkit: 1.39.8 + indent-string: 5.0.0 + is-in-ci: 1.0.0 + patch-console: 2.0.0 + react: 19.1.1 + react-reconciler: 0.32.0(react@19.1.1) + scheduler: 0.23.2 + signal-exit: 3.0.7 + slice-ansi: 7.1.0 + stack-utils: 2.0.6 + string-width: 7.2.0 + type-fest: 4.41.0 + widest-line: 5.0.0 + wrap-ansi: 9.0.0 + ws: 8.18.3 + yoga-layout: 3.2.1 + optionalDependencies: + '@types/react': 19.1.9 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + inline-style-parser@0.2.4: {} ipaddr.js@1.9.1: {} @@ -5699,25 +6331,34 @@ snapshots: is-decimal@2.0.1: {} + is-docker@2.2.1: {} + is-docker@3.0.0: {} is-extglob@2.1.1: {} is-fullwidth-code-point@3.0.0: {} + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.0.0: + dependencies: + get-east-asian-width: 1.3.0 + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 is-hexadecimal@2.0.1: {} + is-in-ci@1.0.0: {} + is-inside-container@1.0.0: dependencies: is-docker: 3.0.0 - is-it-type@5.1.2: + is-it-type@5.1.3: dependencies: - '@babel/runtime': 7.27.1 globalthis: 1.0.4 is-number@7.0.0: {} @@ -5726,12 +6367,20 @@ snapshots: is-stream@3.0.0: {} + is-stream@4.0.1: {} + is-subdir@1.2.0: dependencies: better-path-resolve: 1.0.0 + is-unicode-supported@2.1.0: {} + is-windows@1.0.2: {} + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + is-wsl@3.1.0: dependencies: is-inside-container: 1.0.0 @@ -5748,8 +6397,8 @@ snapshots: istanbul-lib-source-maps@5.0.6: dependencies: - '@jridgewell/trace-mapping': 0.3.25 - debug: 4.4.0 + '@jridgewell/trace-mapping': 0.3.29 + debug: 4.4.1(supports-color@8.1.1) istanbul-lib-coverage: 3.2.2 transitivePeerDependencies: - supports-color @@ -5765,6 +6414,14 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jake@10.9.4: + dependencies: + async: 3.2.6 + filelist: 1.0.4 + picocolors: 1.1.1 + + js-tokens@4.0.0: {} + js-yaml@3.14.1: dependencies: argparse: 1.0.10 @@ -5792,6 +6449,8 @@ snapshots: klona@2.0.6: {} + lilconfig@3.1.3: {} + linkify-it@5.0.0: dependencies: uc.micro: 2.1.0 @@ -5802,13 +6461,19 @@ snapshots: lodash-es@4.17.21: {} + lodash.deburr@4.1.0: {} + lodash.startcase@4.4.0: {} loglevel@1.9.2: {} longest-streak@3.1.0: {} - loupe@3.1.3: {} + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + loupe@3.2.0: {} lru-cache@10.4.3: {} @@ -5816,12 +6481,12 @@ snapshots: magic-string@0.30.17: dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.4 magicast@0.3.5: dependencies: - '@babel/parser': 7.27.2 - '@babel/types': 7.27.1 + '@babel/parser': 7.28.0 + '@babel/types': 7.28.2 source-map-js: 1.2.1 make-dir@4.0.0: @@ -5874,7 +6539,7 @@ snapshots: dependencies: '@types/mdast': 4.0.4 '@types/unist': 3.0.3 - decode-named-character-reference: 1.1.0 + decode-named-character-reference: 1.2.0 devlop: 1.1.0 mdast-util-to-string: 4.0.0 micromark: 4.0.2 @@ -5968,7 +6633,7 @@ snapshots: parse-entities: 4.0.2 stringify-entities: 4.0.4 unist-util-stringify-position: 4.0.0 - vfile-message: 4.0.2 + vfile-message: 4.0.3 transitivePeerDependencies: - supports-color @@ -6040,7 +6705,7 @@ snapshots: micromark-core-commonmark@2.0.3: dependencies: - decode-named-character-reference: 1.1.0 + decode-named-character-reference: 1.2.0 devlop: 1.1.0 micromark-factory-destination: 2.0.1 micromark-factory-label: 2.0.1 @@ -6127,7 +6792,7 @@ snapshots: micromark-extension-mdx-expression@3.0.1: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 devlop: 1.1.0 micromark-factory-mdx-expression: 2.0.3 micromark-factory-space: 2.0.1 @@ -6138,7 +6803,7 @@ snapshots: micromark-extension-mdx-jsx@3.0.2: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 devlop: 1.1.0 estree-util-is-identifier-name: 3.0.0 micromark-factory-mdx-expression: 2.0.3 @@ -6147,7 +6812,7 @@ snapshots: micromark-util-events-to-acorn: 2.0.3 micromark-util-symbol: 2.0.1 micromark-util-types: 2.0.2 - vfile-message: 4.0.2 + vfile-message: 4.0.3 micromark-extension-mdx-md@2.0.0: dependencies: @@ -6155,7 +6820,7 @@ snapshots: micromark-extension-mdxjs-esm@3.0.0: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 devlop: 1.1.0 micromark-core-commonmark: 2.0.3 micromark-util-character: 2.1.1 @@ -6163,12 +6828,12 @@ snapshots: micromark-util-symbol: 2.0.1 micromark-util-types: 2.0.2 unist-util-position-from-estree: 2.0.0 - vfile-message: 4.0.2 + vfile-message: 4.0.3 micromark-extension-mdxjs@3.0.0: dependencies: - acorn: 8.14.1 - acorn-jsx: 5.3.2(acorn@8.14.1) + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) micromark-extension-mdx-expression: 3.0.1 micromark-extension-mdx-jsx: 3.0.2 micromark-extension-mdx-md: 2.0.0 @@ -6191,7 +6856,7 @@ snapshots: micromark-factory-mdx-expression@2.0.3: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 devlop: 1.1.0 micromark-factory-space: 2.0.1 micromark-util-character: 2.1.1 @@ -6199,7 +6864,7 @@ snapshots: micromark-util-symbol: 2.0.1 micromark-util-types: 2.0.2 unist-util-position-from-estree: 2.0.0 - vfile-message: 4.0.2 + vfile-message: 4.0.3 micromark-factory-space@2.0.1: dependencies: @@ -6246,7 +6911,7 @@ snapshots: micromark-util-decode-string@2.0.1: dependencies: - decode-named-character-reference: 1.1.0 + decode-named-character-reference: 1.2.0 micromark-util-character: 2.1.1 micromark-util-decode-numeric-character-reference: 2.0.2 micromark-util-symbol: 2.0.1 @@ -6255,13 +6920,13 @@ snapshots: micromark-util-events-to-acorn@2.0.3: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 '@types/unist': 3.0.3 devlop: 1.1.0 estree-util-visit: 2.0.0 micromark-util-symbol: 2.0.1 micromark-util-types: 2.0.2 - vfile-message: 4.0.2 + vfile-message: 4.0.3 micromark-util-html-tag-name@2.0.1: {} @@ -6293,8 +6958,8 @@ snapshots: micromark@4.0.2: dependencies: '@types/debug': 4.1.12 - debug: 4.4.0 - decode-named-character-reference: 1.1.0 + debug: 4.4.1(supports-color@8.1.1) + decode-named-character-reference: 1.2.0 devlop: 1.1.0 micromark-core-commonmark: 2.0.3 micromark-factory-space: 2.0.1 @@ -6325,19 +6990,25 @@ snapshots: mime@1.6.0: {} + mimic-fn@2.1.0: {} + + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.2 + minimatch@9.0.5: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 minipass@7.1.2: {} - morgan@1.10.0: + morgan@1.10.1: dependencies: basic-auth: 2.0.1 debug: 2.6.9 depd: 2.0.0 on-finished: 2.3.0 - on-headers: 1.0.2 + on-headers: 1.1.0 transitivePeerDependencies: - supports-color @@ -6361,53 +7032,58 @@ snapshots: nocache@3.0.4: {} - node-fetch-native@1.6.6: {} + node-fetch-native@1.6.7: {} node-fetch@2.7.0: dependencies: whatwg-url: 5.0.0 - node-mock-http@1.0.0: {} + node-mock-http@1.0.2: {} - nodejs-polars-android-arm64@0.18.0: + nodejs-polars-android-arm64@0.21.0: optional: true - nodejs-polars-darwin-arm64@0.18.0: + nodejs-polars-darwin-arm64@0.21.0: optional: true - nodejs-polars-darwin-x64@0.18.0: + nodejs-polars-darwin-x64@0.21.0: optional: true - nodejs-polars-linux-arm64-gnu@0.18.0: + nodejs-polars-linux-arm64-gnu@0.21.0: optional: true - nodejs-polars-linux-arm64-musl@0.18.0: + nodejs-polars-linux-arm64-musl@0.21.0: optional: true - nodejs-polars-linux-x64-gnu@0.18.0: + nodejs-polars-linux-x64-gnu@0.21.0: optional: true - nodejs-polars-linux-x64-musl@0.18.0: + nodejs-polars-linux-x64-musl@0.21.0: optional: true - nodejs-polars-win32-x64-msvc@0.18.0: + nodejs-polars-win32-x64-msvc@0.21.0: optional: true - nodejs-polars@0.18.0: + nodejs-polars@0.21.0: optionalDependencies: - nodejs-polars-android-arm64: 0.18.0 - nodejs-polars-darwin-arm64: 0.18.0 - nodejs-polars-darwin-x64: 0.18.0 - nodejs-polars-linux-arm64-gnu: 0.18.0 - nodejs-polars-linux-arm64-musl: 0.18.0 - nodejs-polars-linux-x64-gnu: 0.18.0 - nodejs-polars-linux-x64-musl: 0.18.0 - nodejs-polars-win32-x64-msvc: 0.18.0 + nodejs-polars-android-arm64: 0.21.0 + nodejs-polars-darwin-arm64: 0.21.0 + nodejs-polars-darwin-x64: 0.21.0 + nodejs-polars-linux-arm64-gnu: 0.21.0 + nodejs-polars-linux-arm64-musl: 0.21.0 + nodejs-polars-linux-x64-gnu: 0.21.0 + nodejs-polars-linux-x64-musl: 0.21.0 + nodejs-polars-win32-x64-msvc: 0.21.0 normalize-path@3.0.0: {} npm-check-updates@18.0.1: {} + npm-run-path@6.0.0: + dependencies: + path-key: 4.0.0 + unicorn-magic: 0.3.0 + nth-check@2.1.1: dependencies: boolbase: 1.0.0 @@ -6421,7 +7097,7 @@ snapshots: ofetch@1.4.1: dependencies: destr: 2.0.5 - node-fetch-native: 1.6.6 + node-fetch-native: 1.6.7 ufo: 1.6.1 ohash@2.0.11: {} @@ -6434,7 +7110,11 @@ snapshots: dependencies: ee-first: 1.1.1 - on-headers@1.0.2: {} + on-headers@1.1.0: {} + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 oniguruma-parser@0.12.1: {} @@ -6498,7 +7178,7 @@ snapshots: '@types/unist': 2.0.11 character-entities-legacy: 3.0.0 character-reference-invalid: 2.0.1 - decode-named-character-reference: 1.1.0 + decode-named-character-reference: 1.2.0 is-alphanumerical: 2.0.1 is-decimal: 2.0.1 is-hexadecimal: 2.0.1 @@ -6512,16 +7192,22 @@ snapshots: unist-util-visit-children: 3.0.0 vfile: 6.0.3 + parse-ms@4.0.0: {} + parse5@7.3.0: dependencies: - entities: 6.0.0 + entities: 6.0.1 parseurl@1.3.3: {} + patch-console@2.0.0: {} + path-exists@4.0.0: {} path-key@3.1.1: {} + path-key@4.0.0: {} + path-scurry@1.11.1: dependencies: lru-cache: 10.4.3 @@ -6533,19 +7219,19 @@ snapshots: pathe@2.0.3: {} - pathval@2.0.0: {} + pathval@2.0.1: {} picocolors@1.1.1: {} picomatch@2.3.1: {} - picomatch@4.0.2: {} + picomatch@4.0.3: {} pify@4.0.1: {} - postcss-nested@6.2.0(postcss@8.5.3): + postcss-nested@6.2.0(postcss@8.5.6): dependencies: - postcss: 8.5.3 + postcss: 8.5.6 postcss-selector-parser: 6.1.2 postcss-selector-parser@6.1.2: @@ -6553,7 +7239,7 @@ snapshots: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss@8.5.3: + postcss@8.5.6: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 @@ -6561,6 +7247,10 @@ snapshots: prettier@2.8.8: {} + pretty-ms@9.2.0: + dependencies: + parse-ms: 4.0.0 + prismjs@1.30.0: {} prompts@2.4.2: @@ -6606,6 +7296,13 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 + react-reconciler@0.32.0(react@19.1.1): + dependencies: + react: 19.1.1 + scheduler: 0.26.0 + + react@19.1.1: {} + read-yaml-file@1.1.0: dependencies: graceful-fs: 4.2.11 @@ -6617,30 +7314,29 @@ snapshots: recma-build-jsx@1.0.0: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 estree-util-build-jsx: 3.0.1 vfile: 6.0.3 - recma-jsx@1.0.0(acorn@8.14.1): + recma-jsx@1.0.1(acorn@8.15.0): dependencies: - acorn-jsx: 5.3.2(acorn@8.14.1) + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) estree-util-to-js: 2.0.0 recma-parse: 1.0.0 recma-stringify: 1.0.0 unified: 11.0.5 - transitivePeerDependencies: - - acorn recma-parse@1.0.0: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 esast-util-from-js: 2.0.1 unified: 11.0.5 vfile: 6.0.3 recma-stringify@1.0.0: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 estree-util-to-js: 2.0.0 unified: 11.0.5 vfile: 6.0.3 @@ -6655,9 +7351,9 @@ snapshots: dependencies: regex-utilities: 2.3.0 - rehype-expressive-code@0.41.2: + rehype-expressive-code@0.41.3: dependencies: - expressive-code: 0.41.2 + expressive-code: 0.41.3 rehype-format@5.0.1: dependencies: @@ -6678,7 +7374,7 @@ snapshots: rehype-recma@1.0.0: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 '@types/hast': 3.0.4 hast-util-to-estree: 3.1.3 transitivePeerDependencies: @@ -6760,6 +7456,13 @@ snapshots: resolve-from@5.0.0: {} + resolve-pkg-maps@1.0.0: {} + + restore-cursor@4.0.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + restructure@3.0.2: {} retext-latin@4.0.0: @@ -6789,30 +7492,30 @@ snapshots: reusify@1.1.0: {} - rollup@4.40.2: + rollup@4.46.2: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.40.2 - '@rollup/rollup-android-arm64': 4.40.2 - '@rollup/rollup-darwin-arm64': 4.40.2 - '@rollup/rollup-darwin-x64': 4.40.2 - '@rollup/rollup-freebsd-arm64': 4.40.2 - '@rollup/rollup-freebsd-x64': 4.40.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.40.2 - '@rollup/rollup-linux-arm-musleabihf': 4.40.2 - '@rollup/rollup-linux-arm64-gnu': 4.40.2 - '@rollup/rollup-linux-arm64-musl': 4.40.2 - '@rollup/rollup-linux-loongarch64-gnu': 4.40.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.40.2 - '@rollup/rollup-linux-riscv64-gnu': 4.40.2 - '@rollup/rollup-linux-riscv64-musl': 4.40.2 - '@rollup/rollup-linux-s390x-gnu': 4.40.2 - '@rollup/rollup-linux-x64-gnu': 4.40.2 - '@rollup/rollup-linux-x64-musl': 4.40.2 - '@rollup/rollup-win32-arm64-msvc': 4.40.2 - '@rollup/rollup-win32-ia32-msvc': 4.40.2 - '@rollup/rollup-win32-x64-msvc': 4.40.2 + '@rollup/rollup-android-arm-eabi': 4.46.2 + '@rollup/rollup-android-arm64': 4.46.2 + '@rollup/rollup-darwin-arm64': 4.46.2 + '@rollup/rollup-darwin-x64': 4.46.2 + '@rollup/rollup-freebsd-arm64': 4.46.2 + '@rollup/rollup-freebsd-x64': 4.46.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.46.2 + '@rollup/rollup-linux-arm-musleabihf': 4.46.2 + '@rollup/rollup-linux-arm64-gnu': 4.46.2 + '@rollup/rollup-linux-arm64-musl': 4.46.2 + '@rollup/rollup-linux-loongarch64-gnu': 4.46.2 + '@rollup/rollup-linux-ppc64-gnu': 4.46.2 + '@rollup/rollup-linux-riscv64-gnu': 4.46.2 + '@rollup/rollup-linux-riscv64-musl': 4.46.2 + '@rollup/rollup-linux-s390x-gnu': 4.46.2 + '@rollup/rollup-linux-x64-gnu': 4.46.2 + '@rollup/rollup-linux-x64-musl': 4.46.2 + '@rollup/rollup-win32-arm64-msvc': 4.46.2 + '@rollup/rollup-win32-ia32-msvc': 4.46.2 + '@rollup/rollup-win32-x64-msvc': 4.46.2 fsevents: 2.3.3 route-recognizer@0.3.4: {} @@ -6829,6 +7532,12 @@ snapshots: sax@1.4.1: {} + scheduler@0.23.2: + dependencies: + loose-envify: 1.4.0 + + scheduler@0.26.0: {} + semver@7.7.2: {} send@0.19.0: @@ -6923,14 +7632,14 @@ snapshots: shebang-regex@3.0.0: {} - shiki@3.4.0: + shiki@3.9.2: dependencies: - '@shikijs/core': 3.4.0 - '@shikijs/engine-javascript': 3.4.0 - '@shikijs/engine-oniguruma': 3.4.0 - '@shikijs/langs': 3.4.0 - '@shikijs/themes': 3.4.0 - '@shikijs/types': 3.4.0 + '@shikijs/core': 3.9.2 + '@shikijs/engine-javascript': 3.9.2 + '@shikijs/engine-oniguruma': 3.9.2 + '@shikijs/langs': 3.9.2 + '@shikijs/themes': 3.9.2 + '@shikijs/types': 3.9.2 '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 @@ -6964,6 +7673,8 @@ snapshots: siginfo@2.0.0: {} + signal-exit@3.0.7: {} + signal-exit@4.1.0: {} simple-invariant@2.0.1: {} @@ -6989,13 +7700,23 @@ snapshots: slash@3.0.0: {} + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 + slugify@1.6.6: {} - smol-toml@1.3.4: {} + smol-toml@1.4.1: {} source-map-js@1.2.1: {} - source-map@0.7.4: {} + source-map@0.7.6: {} space-separated-tokens@2.0.2: {} @@ -7006,18 +7727,22 @@ snapshots: sprintf-js@1.0.3: {} + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + stackback@0.0.2: {} - starlight-scroll-to-top@0.1.1(@astrojs/starlight@0.34.3(astro@5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1))): + starlight-scroll-to-top@0.1.1(@astrojs/starlight@0.34.3(astro@5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1))): dependencies: - '@astrojs/starlight': 0.34.3(astro@5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1)) + '@astrojs/starlight': 0.34.3(astro@5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1)) - starlight-typedoc@0.21.3(@astrojs/starlight@0.34.3(astro@5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1)))(typedoc-plugin-markdown@4.6.3(typedoc@0.28.5(typescript@5.8.3)))(typedoc@0.28.5(typescript@5.8.3)): + starlight-typedoc@0.21.3(@astrojs/starlight@0.34.3(astro@5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1)))(typedoc-plugin-markdown@4.8.0(typedoc@0.28.9(typescript@5.9.2)))(typedoc@0.28.9(typescript@5.9.2)): dependencies: - '@astrojs/starlight': 0.34.3(astro@5.7.12(@types/node@22.15.31)(rollup@4.40.2)(typescript@5.8.3)(yaml@2.7.1)) + '@astrojs/starlight': 0.34.3(astro@5.7.12(@types/node@24.2.0)(rollup@4.46.2)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.1)) github-slugger: 2.0.0 - typedoc: 0.28.5(typescript@5.8.3) - typedoc-plugin-markdown: 4.6.3(typedoc@0.28.5(typescript@5.8.3)) + typedoc: 0.28.9(typescript@5.9.2) + typedoc-plugin-markdown: 4.8.0(typedoc@0.28.9(typescript@5.9.2)) statuses@2.0.1: {} @@ -7058,11 +7783,13 @@ snapshots: strip-bom@3.0.0: {} - style-to-js@1.1.16: + strip-final-newline@4.0.0: {} + + style-to-js@1.1.17: dependencies: - style-to-object: 1.0.8 + style-to-object: 1.0.9 - style-to-object@1.0.8: + style-to-object@1.0.9: dependencies: inline-style-parser: 0.2.4 @@ -7070,6 +7797,10 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + temp-dir@3.0.0: {} tempy@3.1.0: @@ -7095,12 +7826,12 @@ snapshots: tinyexec@0.3.2: {} - tinyglobby@0.2.13: + tinyglobby@0.2.14: dependencies: - fdir: 6.4.4(picomatch@4.0.2) - picomatch: 4.0.2 + fdir: 6.4.6(picomatch@4.0.3) + picomatch: 4.0.3 - tinypool@1.0.2: {} + tinypool@1.1.1: {} tinyrainbow@2.0.0: {} @@ -7116,6 +7847,8 @@ snapshots: dependencies: is-number: 7.0.0 + to-rotated@1.0.0: {} + toidentifier@1.0.1: {} totalist@3.0.1: {} @@ -7126,12 +7859,25 @@ snapshots: trough@2.2.0: {} - tsconfck@3.1.5(typescript@5.8.3): + ts-extras@0.14.0: + dependencies: + type-fest: 4.41.0 + + tsconfck@3.1.6(typescript@5.9.2): optionalDependencies: - typescript: 5.8.3 + typescript: 5.9.2 tslib@2.8.1: {} + tsx@4.20.3: + dependencies: + esbuild: 0.25.8 + get-tsconfig: 4.10.1 + optionalDependencies: + fsevents: 2.3.3 + + type-fest@0.21.3: {} + type-fest@1.4.0: {} type-fest@2.19.0: {} @@ -7143,20 +7889,20 @@ snapshots: media-typer: 0.3.0 mime-types: 2.1.35 - typedoc-plugin-markdown@4.6.3(typedoc@0.28.5(typescript@5.8.3)): + typedoc-plugin-markdown@4.8.0(typedoc@0.28.9(typescript@5.9.2)): dependencies: - typedoc: 0.28.5(typescript@5.8.3) + typedoc: 0.28.9(typescript@5.9.2) - typedoc@0.28.5(typescript@5.8.3): + typedoc@0.28.9(typescript@5.9.2): dependencies: - '@gerrit0/mini-shiki': 3.4.0 + '@gerrit0/mini-shiki': 3.9.2 lunr: 2.3.9 markdown-it: 14.1.0 minimatch: 9.0.5 - typescript: 5.8.3 - yaml: 2.7.1 + typescript: 5.9.2 + yaml: 2.8.1 - typescript@5.8.3: {} + typescript@5.9.2: {} uc.micro@2.1.0: {} @@ -7166,7 +7912,7 @@ snapshots: uncrypto@0.1.3: {} - undici-types@6.21.0: {} + undici-types@7.10.0: {} unicode-properties@1.4.1: dependencies: @@ -7178,6 +7924,8 @@ snapshots: pako: 0.2.9 tiny-inflate: 1.0.3 + unicorn-magic@0.3.0: {} + unified@11.0.5: dependencies: '@types/unist': 3.0.3 @@ -7188,9 +7936,10 @@ snapshots: trough: 2.2.0 vfile: 6.0.3 - unifont@0.5.0: + unifont@0.5.2: dependencies: css-tree: 3.1.0 + ofetch: 1.4.1 ohash: 2.0.11 unique-string@3.0.0: @@ -7249,14 +7998,14 @@ snapshots: unpipe@1.0.0: {} - unstorage@1.16.0: + unstorage@1.16.1: dependencies: anymatch: 3.1.3 chokidar: 4.0.3 destr: 2.0.5 - h3: 1.15.3 + h3: 1.15.4 lru-cache: 10.4.3 - node-fetch-native: 1.6.6 + node-fetch-native: 1.6.7 ofetch: 1.4.1 ufo: 1.6.1 @@ -7278,7 +8027,7 @@ snapshots: '@types/unist': 3.0.3 vfile: 6.0.3 - vfile-message@4.0.2: + vfile-message@4.0.3: dependencies: '@types/unist': 3.0.3 unist-util-stringify-position: 4.0.0 @@ -7286,15 +8035,15 @@ snapshots: vfile@6.0.3: dependencies: '@types/unist': 3.0.3 - vfile-message: 4.0.2 + vfile-message: 4.0.3 - vite-node@3.1.4(@types/node@22.15.31)(yaml@2.7.1): + vite-node@3.1.4(@types/node@24.2.0)(tsx@4.20.3)(yaml@2.8.1): dependencies: cac: 6.7.14 - debug: 4.4.0 + debug: 4.4.1(supports-color@8.1.1) es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.5(@types/node@22.15.31)(yaml@2.7.1) + vite: 6.3.5(@types/node@24.2.0)(tsx@4.20.3)(yaml@2.8.1) transitivePeerDependencies: - '@types/node' - jiti @@ -7309,49 +8058,50 @@ snapshots: - tsx - yaml - vite@6.3.5(@types/node@22.15.31)(yaml@2.7.1): + vite@6.3.5(@types/node@24.2.0)(tsx@4.20.3)(yaml@2.8.1): dependencies: - esbuild: 0.25.4 - fdir: 6.4.4(picomatch@4.0.2) - picomatch: 4.0.2 - postcss: 8.5.3 - rollup: 4.40.2 - tinyglobby: 0.2.13 + esbuild: 0.25.8 + fdir: 6.4.6(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.46.2 + tinyglobby: 0.2.14 optionalDependencies: - '@types/node': 22.15.31 + '@types/node': 24.2.0 fsevents: 2.3.3 - yaml: 2.7.1 + tsx: 4.20.3 + yaml: 2.8.1 - vitefu@1.0.6(vite@6.3.5(@types/node@22.15.31)(yaml@2.7.1)): + vitefu@1.1.1(vite@6.3.5(@types/node@24.2.0)(tsx@4.20.3)(yaml@2.8.1)): optionalDependencies: - vite: 6.3.5(@types/node@22.15.31)(yaml@2.7.1) + vite: 6.3.5(@types/node@24.2.0)(tsx@4.20.3)(yaml@2.8.1) - vitest@3.1.4(@types/debug@4.1.12)(@types/node@22.15.31)(@vitest/ui@3.1.4)(yaml@2.7.1): + vitest@3.1.4(@types/debug@4.1.12)(@types/node@24.2.0)(@vitest/ui@3.1.4)(tsx@4.20.3)(yaml@2.8.1): dependencies: '@vitest/expect': 3.1.4 - '@vitest/mocker': 3.1.4(vite@6.3.5(@types/node@22.15.31)(yaml@2.7.1)) - '@vitest/pretty-format': 3.1.4 + '@vitest/mocker': 3.1.4(vite@6.3.5(@types/node@24.2.0)(tsx@4.20.3)(yaml@2.8.1)) + '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.1.4 '@vitest/snapshot': 3.1.4 '@vitest/spy': 3.1.4 '@vitest/utils': 3.1.4 - chai: 5.2.0 - debug: 4.4.0 - expect-type: 1.2.1 + chai: 5.2.1 + debug: 4.4.1(supports-color@8.1.1) + expect-type: 1.2.2 magic-string: 0.30.17 pathe: 2.0.3 std-env: 3.9.0 tinybench: 2.9.0 tinyexec: 0.3.2 - tinyglobby: 0.2.13 - tinypool: 1.0.2 + tinyglobby: 0.2.14 + tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.3.5(@types/node@22.15.31)(yaml@2.7.1) - vite-node: 3.1.4(@types/node@22.15.31)(yaml@2.7.1) + vite: 6.3.5(@types/node@24.2.0)(tsx@4.20.3)(yaml@2.8.1) + vite-node: 3.1.4(@types/node@24.2.0)(tsx@4.20.3)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 - '@types/node': 22.15.31 + '@types/node': 24.2.0 '@vitest/ui': 3.1.4(vitest@3.1.4) transitivePeerDependencies: - jiti @@ -7387,10 +8137,16 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 + widest-line@3.1.0: + dependencies: + string-width: 4.2.3 + widest-line@5.0.0: dependencies: string-width: 7.2.0 + wordwrap@1.0.0: {} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -7409,16 +8165,18 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.1.0 + ws@8.18.3: {} + xxhash-wasm@1.1.0: {} - yaml@2.7.1: {} + yaml@2.8.1: {} yargs-parser@21.1.1: {} yauzl-promise@4.0.0: dependencies: '@node-rs/crc32': 1.10.6 - is-it-type: 5.1.2 + is-it-type: 5.1.3 simple-invariant: 2.0.1 yazl@3.3.1: @@ -7427,21 +8185,23 @@ snapshots: yocto-queue@1.2.1: {} - yocto-spinner@0.2.2: + yocto-spinner@0.2.3: dependencies: yoctocolors: 2.1.1 yoctocolors@2.1.1: {} - zod-to-json-schema@3.24.5(zod@3.24.4): + yoga-layout@3.2.1: {} + + zod-to-json-schema@3.24.6(zod@3.25.76): dependencies: - zod: 3.24.4 + zod: 3.25.76 - zod-to-ts@1.2.0(typescript@5.8.3)(zod@3.24.4): + zod-to-ts@1.2.0(typescript@5.9.2)(zod@3.25.76): dependencies: - typescript: 5.8.3 - zod: 3.24.4 + typescript: 5.9.2 + zod: 3.25.76 - zod@3.24.4: {} + zod@3.25.76: {} zwitch@2.0.4: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 73911b7e..717b560a 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,7 +1,6 @@ dangerouslyAllowAllBuilds: true packages: - - avro - - bin + - arrow - camtrap - ckan - cli diff --git a/table/error/Cell.ts b/table/error/Cell.ts index 12597b75..2eaf5407 100644 --- a/table/error/Cell.ts +++ b/table/error/Cell.ts @@ -1,4 +1,4 @@ -import type { BaseTableError } from "./Base.js" +import type { BaseTableError } from "./Base.ts" export interface BaseCellError extends BaseTableError { fieldName: string diff --git a/table/error/Field.ts b/table/error/Field.ts index 6ed1d632..b421f4e6 100644 --- a/table/error/Field.ts +++ b/table/error/Field.ts @@ -1,5 +1,5 @@ import type { Field } from "@dpkit/core" -import type { BaseTableError } from "./Base.js" +import type { BaseTableError } from "./Base.ts" export interface BaseFieldError extends BaseTableError { fieldName: string diff --git a/table/error/Fields.ts b/table/error/Fields.ts index 001bc867..1e7da0a7 100644 --- a/table/error/Fields.ts +++ b/table/error/Fields.ts @@ -1,4 +1,4 @@ -import type { BaseTableError } from "./Base.js" +import type { BaseTableError } from "./Base.ts" export interface BaseFieldsError extends BaseTableError { fieldNames: string[] diff --git a/table/error/Row.ts b/table/error/Row.ts index e912827b..0569a3e3 100644 --- a/table/error/Row.ts +++ b/table/error/Row.ts @@ -1,4 +1,4 @@ -import type { BaseTableError } from "./Base.js" +import type { BaseTableError } from "./Base.ts" export interface BaseRowError extends BaseTableError { rowNumber: number diff --git a/table/error/Table.ts b/table/error/Table.ts index 26e5d02e..e6f1d362 100644 --- a/table/error/Table.ts +++ b/table/error/Table.ts @@ -10,10 +10,10 @@ import type { CellRequiredError, CellTypeError, CellUniqueError, -} from "./Cell.js" -import type { FieldNameError, FieldTypeError } from "./Field.js" -import type { FieldsExtraError, FieldsMissingError } from "./Fields.js" -import type { RowUniqueError } from "./Row.js" +} from "./Cell.ts" +import type { FieldNameError, FieldTypeError } from "./Field.ts" +import type { FieldsExtraError, FieldsMissingError } from "./Fields.ts" +import type { RowUniqueError } from "./Row.ts" export type TableError = | FieldsMissingError diff --git a/table/error/index.ts b/table/error/index.ts index 4ad31778..97f6c08e 100644 --- a/table/error/index.ts +++ b/table/error/index.ts @@ -1 +1 @@ -export type { TableError } from "./Table.js" +export type { TableError } from "./Table.ts" diff --git a/table/field/checks/enum.spec.ts b/table/field/checks/enum.spec.ts index 634f877c..5d6100a8 100644 --- a/table/field/checks/enum.spec.ts +++ b/table/field/checks/enum.spec.ts @@ -1,7 +1,7 @@ import type { Schema } from "@dpkit/core" import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { inspectTable } from "../../table/index.js" +import { inspectTable } from "../../table/index.ts" describe("inspectTable (cell/enum)", () => { it("should not report errors for string values that are in the enum", async () => { diff --git a/table/field/checks/enum.ts b/table/field/checks/enum.ts index e08b32c7..5ad37c52 100644 --- a/table/field/checks/enum.ts +++ b/table/field/checks/enum.ts @@ -1,6 +1,6 @@ import type { Field } from "@dpkit/core" import { col } from "nodejs-polars" -import type { Table } from "../../table/index.js" +import type { Table } from "../../table/index.ts" export function checkCellEnum(field: Field, errorTable: Table) { if (field.type === "string") { diff --git a/table/field/checks/maxLength.spec.ts b/table/field/checks/maxLength.spec.ts index 93598810..c4e90d19 100644 --- a/table/field/checks/maxLength.spec.ts +++ b/table/field/checks/maxLength.spec.ts @@ -1,7 +1,7 @@ import type { Schema } from "@dpkit/core" import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { inspectTable } from "../../table/index.js" +import { inspectTable } from "../../table/index.ts" describe("inspectTable (cell/maxLength)", () => { it("should not report errors for string values that meet the maxLength constraint", async () => { diff --git a/table/field/checks/maxLength.ts b/table/field/checks/maxLength.ts index ebf7d9c7..d1b6ef2a 100644 --- a/table/field/checks/maxLength.ts +++ b/table/field/checks/maxLength.ts @@ -1,6 +1,6 @@ import type { Field } from "@dpkit/core" import { col } from "nodejs-polars" -import type { Table } from "../../table/index.js" +import type { Table } from "../../table/index.ts" export function checkCellMaxLength(field: Field, errorTable: Table) { if (field.type === "string") { diff --git a/table/field/checks/maximum.spec.ts b/table/field/checks/maximum.spec.ts index 378cea81..6c3acb81 100644 --- a/table/field/checks/maximum.spec.ts +++ b/table/field/checks/maximum.spec.ts @@ -1,7 +1,7 @@ import type { Schema } from "@dpkit/core" import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { inspectTable } from "../../table/index.js" +import { inspectTable } from "../../table/index.ts" describe("inspectTable (cell/maximum)", () => { it("should not report errors for valid values", async () => { diff --git a/table/field/checks/maximum.ts b/table/field/checks/maximum.ts index 4a8ffbd9..ccb7d8be 100644 --- a/table/field/checks/maximum.ts +++ b/table/field/checks/maximum.ts @@ -1,6 +1,6 @@ import type { Field } from "@dpkit/core" import { col, lit } from "nodejs-polars" -import type { Table } from "../../table/index.js" +import type { Table } from "../../table/index.ts" export function checkCellMaximum( field: Field, diff --git a/table/field/checks/minLength.spec.ts b/table/field/checks/minLength.spec.ts index 71d23f38..c13aa025 100644 --- a/table/field/checks/minLength.spec.ts +++ b/table/field/checks/minLength.spec.ts @@ -1,7 +1,7 @@ import type { Schema } from "@dpkit/core" import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { inspectTable } from "../../table/index.js" +import { inspectTable } from "../../table/index.ts" describe("inspectTable (cell/minLength)", () => { it("should not report errors for string values that meet the minLength constraint", async () => { diff --git a/table/field/checks/minLength.ts b/table/field/checks/minLength.ts index f532d5fb..aa9106a3 100644 --- a/table/field/checks/minLength.ts +++ b/table/field/checks/minLength.ts @@ -1,6 +1,6 @@ import type { Field } from "@dpkit/core" import { col } from "nodejs-polars" -import type { Table } from "../../table/index.js" +import type { Table } from "../../table/index.ts" export function checkCellMinLength(field: Field, errorTable: Table) { if (field.type === "string") { diff --git a/table/field/checks/minimum.spec.ts b/table/field/checks/minimum.spec.ts index c5a3e43e..8e1a307f 100644 --- a/table/field/checks/minimum.spec.ts +++ b/table/field/checks/minimum.spec.ts @@ -1,7 +1,7 @@ import type { Schema } from "@dpkit/core" import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { inspectTable } from "../../table/index.js" +import { inspectTable } from "../../table/index.ts" describe("inspectTable (cell/minimum)", () => { it("should not report errors for valid values", async () => { diff --git a/table/field/checks/minimum.ts b/table/field/checks/minimum.ts index 4b23685a..c193df3c 100644 --- a/table/field/checks/minimum.ts +++ b/table/field/checks/minimum.ts @@ -1,6 +1,6 @@ import type { Field } from "@dpkit/core" import { col, lit } from "nodejs-polars" -import type { Table } from "../../table/index.js" +import type { Table } from "../../table/index.ts" export function checkCellMinimum( field: Field, diff --git a/table/field/checks/pattern.spec.ts b/table/field/checks/pattern.spec.ts index 615e98c9..29e60d60 100644 --- a/table/field/checks/pattern.spec.ts +++ b/table/field/checks/pattern.spec.ts @@ -1,7 +1,7 @@ import type { Schema } from "@dpkit/core" import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { inspectTable } from "../../table/index.js" +import { inspectTable } from "../../table/index.ts" describe("inspectTable (cell/pattern)", () => { it("should not report errors for string values that match the pattern", async () => { diff --git a/table/field/checks/pattern.ts b/table/field/checks/pattern.ts index f0dbc8b4..82acbe3c 100644 --- a/table/field/checks/pattern.ts +++ b/table/field/checks/pattern.ts @@ -1,6 +1,6 @@ import type { Field } from "@dpkit/core" import { col } from "nodejs-polars" -import type { Table } from "../../table/index.js" +import type { Table } from "../../table/index.ts" export function checkCellPattern(field: Field, errorTable: Table) { if (field.type === "string") { diff --git a/table/field/checks/required.spec.ts b/table/field/checks/required.spec.ts index 1845fb64..1468ebd5 100644 --- a/table/field/checks/required.spec.ts +++ b/table/field/checks/required.spec.ts @@ -1,7 +1,7 @@ import type { Schema } from "@dpkit/core" import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { inspectTable } from "../../table/index.js" +import { inspectTable } from "../../table/index.ts" describe("inspectTable (cell/required)", () => { it("should report a cell/required error", async () => { diff --git a/table/field/checks/required.ts b/table/field/checks/required.ts index 3511aeb7..b7eac84d 100644 --- a/table/field/checks/required.ts +++ b/table/field/checks/required.ts @@ -1,6 +1,6 @@ import type { Field } from "@dpkit/core" import { col } from "nodejs-polars" -import type { Table } from "../../table/index.js" +import type { Table } from "../../table/index.ts" export function checkCellRequired(field: Field, errorTable: Table) { if (field.constraints?.required) { diff --git a/table/field/checks/type.spec.ts b/table/field/checks/type.spec.ts index ef07068d..027a5215 100644 --- a/table/field/checks/type.spec.ts +++ b/table/field/checks/type.spec.ts @@ -1,7 +1,7 @@ import type { Schema } from "@dpkit/core" import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { inspectTable } from "../../table/index.js" +import { inspectTable } from "../../table/index.ts" describe("inspectTable", () => { it("should inspect string to integer conversion errors", async () => { diff --git a/table/field/checks/type.ts b/table/field/checks/type.ts index a1098447..eb5db3e8 100644 --- a/table/field/checks/type.ts +++ b/table/field/checks/type.ts @@ -1,6 +1,6 @@ import type { Field } from "@dpkit/core" import { col } from "nodejs-polars" -import type { Table } from "../../table/index.js" +import type { Table } from "../../table/index.ts" export function checkCellType(field: Field, errorTable: Table) { const source = col(`source:${field.name}`) diff --git a/table/field/checks/unique.spec.ts b/table/field/checks/unique.spec.ts index dbd4e4d6..c53727c8 100644 --- a/table/field/checks/unique.spec.ts +++ b/table/field/checks/unique.spec.ts @@ -1,7 +1,7 @@ import type { Schema } from "@dpkit/core" import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { inspectTable } from "../../table/index.js" +import { inspectTable } from "../../table/index.ts" // TODO: recover describe("inspectTable (cell/unique)", () => { diff --git a/table/field/checks/unique.ts b/table/field/checks/unique.ts index 4d8b5caa..5078afba 100644 --- a/table/field/checks/unique.ts +++ b/table/field/checks/unique.ts @@ -1,6 +1,6 @@ import type { Field } from "@dpkit/core" import { col } from "nodejs-polars" -import type { Table } from "../../table/index.js" +import type { Table } from "../../table/index.ts" // TODO: Support schema.primaryKey and schema.uniqueKeys export function checkCellUnique(field: Field, errorTable: Table) { diff --git a/table/field/index.ts b/table/field/index.ts index 5c065616..a9480dfe 100644 --- a/table/field/index.ts +++ b/table/field/index.ts @@ -1,4 +1,4 @@ -export { parseField } from "./parse.js" -export { inspectField } from "./inspect.js" -export type { PolarsField } from "./Field.js" -export { matchField } from "./match.js" +export { parseField } from "./parse.ts" +export { inspectField } from "./inspect.ts" +export type { PolarsField } from "./Field.ts" +export { matchField } from "./match.ts" diff --git a/table/field/inspect.spec.ts b/table/field/inspect.spec.ts index 1ec33245..978dcd25 100644 --- a/table/field/inspect.spec.ts +++ b/table/field/inspect.spec.ts @@ -1,7 +1,7 @@ import type { Schema } from "@dpkit/core" import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { inspectTable } from "../table/inspect.js" +import { inspectTable } from "../table/inspect.ts" describe("inspectField", () => { describe("field name validation", () => { diff --git a/table/field/inspect.ts b/table/field/inspect.ts index f81eb315..095a368d 100644 --- a/table/field/inspect.ts +++ b/table/field/inspect.ts @@ -1,16 +1,16 @@ import type { Field } from "@dpkit/core" -import type { TableError } from "../error/index.js" -import type { Table } from "../table/index.js" -import type { PolarsField } from "./Field.js" -import { checkCellEnum } from "./checks/enum.js" -import { checkCellMaxLength } from "./checks/maxLength.js" -import { checkCellMaximum } from "./checks/maximum.js" -import { checkCellMinLength } from "./checks/minLength.js" -import { checkCellMinimum } from "./checks/minimum.js" -import { checkCellPattern } from "./checks/pattern.js" -import { checkCellRequired } from "./checks/required.js" -import { checkCellType } from "./checks/type.js" -import { checkCellUnique } from "./checks/unique.js" +import type { TableError } from "../error/index.ts" +import type { Table } from "../table/index.ts" +import type { PolarsField } from "./Field.ts" +import { checkCellEnum } from "./checks/enum.ts" +import { checkCellMaxLength } from "./checks/maxLength.ts" +import { checkCellMaximum } from "./checks/maximum.ts" +import { checkCellMinLength } from "./checks/minLength.ts" +import { checkCellMinimum } from "./checks/minimum.ts" +import { checkCellPattern } from "./checks/pattern.ts" +import { checkCellRequired } from "./checks/required.ts" +import { checkCellType } from "./checks/type.ts" +import { checkCellUnique } from "./checks/unique.ts" export function inspectField( field: Field, diff --git a/table/field/match.ts b/table/field/match.ts index 953660cb..ce9b33e9 100644 --- a/table/field/match.ts +++ b/table/field/match.ts @@ -1,5 +1,5 @@ import type { Field, Schema } from "@dpkit/core" -import type { PolarsSchema } from "../schema/index.js" +import type { PolarsSchema } from "../schema/index.ts" export function matchField( index: number, diff --git a/table/field/parse.spec.ts b/table/field/parse.spec.ts index d8a8b894..ef2e24ef 100644 --- a/table/field/parse.spec.ts +++ b/table/field/parse.spec.ts @@ -1,7 +1,7 @@ import type { Schema } from "@dpkit/core" import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../table/index.js" +import { processTable } from "../table/index.ts" describe("parseField", () => { describe("missing values", () => { diff --git a/table/field/parse.ts b/table/field/parse.ts index 30b63ce9..6a9f8383 100644 --- a/table/field/parse.ts +++ b/table/field/parse.ts @@ -1,21 +1,21 @@ import type { Field, Schema } from "@dpkit/core" import { col, lit, when } from "nodejs-polars" import type { Expr } from "nodejs-polars" -import { parseArrayField } from "./types/array.js" -import { parseBooleanField } from "./types/boolean.js" -import { parseDateField } from "./types/date.js" -import { parseDatetimeField } from "./types/datetime.js" -import { parseDurationField } from "./types/duration.js" -import { parseGeojsonField } from "./types/geojson.js" -import { parseGeopointField } from "./types/geopoint.js" -import { parseIntegerField } from "./types/integer.js" -import { parseListField } from "./types/list.js" -import { parseNumberField } from "./types/number.js" -import { parseObjectField } from "./types/object.js" -import { parseStringField } from "./types/string.js" -import { parseTimeField } from "./types/time.js" -import { parseYearField } from "./types/year.js" -import { parseYearmonthField } from "./types/yearmonth.js" +import { parseArrayField } from "./types/array.ts" +import { parseBooleanField } from "./types/boolean.ts" +import { parseDateField } from "./types/date.ts" +import { parseDatetimeField } from "./types/datetime.ts" +import { parseDurationField } from "./types/duration.ts" +import { parseGeojsonField } from "./types/geojson.ts" +import { parseGeopointField } from "./types/geopoint.ts" +import { parseIntegerField } from "./types/integer.ts" +import { parseListField } from "./types/list.ts" +import { parseNumberField } from "./types/number.ts" +import { parseObjectField } from "./types/object.ts" +import { parseStringField } from "./types/string.ts" +import { parseTimeField } from "./types/time.ts" +import { parseYearField } from "./types/year.ts" +import { parseYearmonthField } from "./types/yearmonth.ts" const DEFAULT_MISSING_VALUES = [""] diff --git a/table/field/types/array.spec.ts b/table/field/types/array.spec.ts index 0591a4c6..d881f1b8 100644 --- a/table/field/types/array.spec.ts +++ b/table/field/types/array.spec.ts @@ -1,6 +1,6 @@ import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../../table/index.js" +import { processTable } from "../../table/index.ts" describe("parseArrayField", () => { it.each([ diff --git a/table/field/types/boolean.spec.ts b/table/field/types/boolean.spec.ts index c418f1e0..3618e98b 100644 --- a/table/field/types/boolean.spec.ts +++ b/table/field/types/boolean.spec.ts @@ -1,6 +1,6 @@ import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../../table/index.js" +import { processTable } from "../../table/index.ts" describe("parseBooleanField", () => { it.each([ diff --git a/table/field/types/date.spec.ts b/table/field/types/date.spec.ts index e273a3e7..5cf5beb5 100644 --- a/table/field/types/date.spec.ts +++ b/table/field/types/date.spec.ts @@ -1,21 +1,21 @@ import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../../table/index.js" +import { processTable } from "../../table/index.ts" describe("parseDateField", () => { it.each([ // Default format - ["2019-01-01", new Date(2019, 0, 1), {}], + ["2019-01-01", new Date(Date.UTC(2019, 0, 1)), {}], ["10th Jan 1969", null, {}], ["invalid", null, {}], ["", null, {}], // Custom format - ["21/11/2006", new Date(2006, 10, 21), { format: "%d/%m/%Y" }], + ["21/11/2006", new Date(Date.UTC(2006, 10, 21)), { format: "%d/%m/%Y" }], ["21/11/06 16:30", null, { format: "%d/%m/%y" }], ["invalid", null, { format: "%d/%m/%y" }], ["", null, { format: "%d/%m/%y" }], - ["2006/11/21", new Date(2006, 10, 21), { format: "%Y/%m/%d" }], + ["2006/11/21", new Date(Date.UTC(2006, 10, 21)), { format: "%Y/%m/%d" }], // Invalid format ["21/11/06", null, { format: "invalid" }], diff --git a/table/field/types/datetime.spec.ts b/table/field/types/datetime.spec.ts index 0a71f814..c1abbd7a 100644 --- a/table/field/types/datetime.spec.ts +++ b/table/field/types/datetime.spec.ts @@ -1,6 +1,6 @@ import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../../table/index.js" +import { processTable } from "../../table/index.ts" // TODO: Enable this test suite // Currently, it seems to have a weird datetime translation bug on the Polars side diff --git a/table/field/types/duration.spec.ts b/table/field/types/duration.spec.ts index f1a8c803..48a441e5 100644 --- a/table/field/types/duration.spec.ts +++ b/table/field/types/duration.spec.ts @@ -1,6 +1,6 @@ import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../../table/index.js" +import { processTable } from "../../table/index.ts" describe("parseDurationField", () => { it.each([["P23DT23H", "P23DT23H", {}]])( diff --git a/table/field/types/geojson.spec.ts b/table/field/types/geojson.spec.ts index 84f702a7..5b09578b 100644 --- a/table/field/types/geojson.spec.ts +++ b/table/field/types/geojson.spec.ts @@ -1,6 +1,6 @@ import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../../table/index.js" +import { processTable } from "../../table/index.ts" describe("parseGeojsonField", () => { it.each([ diff --git a/table/field/types/geopoint.spec.ts b/table/field/types/geopoint.spec.ts index 45ea00d4..fff80217 100644 --- a/table/field/types/geopoint.spec.ts +++ b/table/field/types/geopoint.spec.ts @@ -1,6 +1,6 @@ import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../../table/index.js" +import { processTable } from "../../table/index.ts" describe("parseGeopointField", () => { describe("default format", () => { diff --git a/table/field/types/integer.spec.ts b/table/field/types/integer.spec.ts index 3c776ed6..02fa74c4 100644 --- a/table/field/types/integer.spec.ts +++ b/table/field/types/integer.spec.ts @@ -1,6 +1,6 @@ import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../../table/index.js" +import { processTable } from "../../table/index.ts" describe("parseIntegerField", () => { it.each([ diff --git a/table/field/types/list.spec.ts b/table/field/types/list.spec.ts index 9387cc45..606452df 100644 --- a/table/field/types/list.spec.ts +++ b/table/field/types/list.spec.ts @@ -1,6 +1,6 @@ import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../../table/index.js" +import { processTable } from "../../table/index.ts" describe("parseListField", () => { describe("default settings (string items, comma delimiter)", () => { diff --git a/table/field/types/number.spec.ts b/table/field/types/number.spec.ts index 2b468b7c..bb375915 100644 --- a/table/field/types/number.spec.ts +++ b/table/field/types/number.spec.ts @@ -1,6 +1,6 @@ import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../../table/index.js" +import { processTable } from "../../table/index.ts" describe("parseNumberField", () => { it.each([ diff --git a/table/field/types/object.spec.ts b/table/field/types/object.spec.ts index afdea5d7..64259d9a 100644 --- a/table/field/types/object.spec.ts +++ b/table/field/types/object.spec.ts @@ -1,6 +1,6 @@ import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../../table/index.js" +import { processTable } from "../../table/index.ts" describe("parseObjectField", () => { it.each([ diff --git a/table/field/types/string.spec.ts b/table/field/types/string.spec.ts index 3fded186..3c5e6131 100644 --- a/table/field/types/string.spec.ts +++ b/table/field/types/string.spec.ts @@ -1,6 +1,6 @@ import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../../table/index.js" +import { processTable } from "../../table/index.ts" // TODO: Implement proper tests // TODO: Currently, it fails on to JS conversion from Polars diff --git a/table/field/types/time.spec.ts b/table/field/types/time.spec.ts index cd0c78c5..3de524c4 100644 --- a/table/field/types/time.spec.ts +++ b/table/field/types/time.spec.ts @@ -1,12 +1,13 @@ import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../../table/index.js" +import { processTable } from "../../table/index.ts" describe("parseTimeField", () => { it.each([ // Default format tests ["06:00:00", 6 * 60 * 60 * 10 ** 9, {}], - ["06:00:00Z", 6 * 60 * 60 * 10 ** 9, {}], + // #TODO: Clarify the behavior on the Standard level first + //["06:00:00Z", 6 * 60 * 60 * 10 ** 9, {}], ["09:00", null, {}], // Incomplete time ["3 am", null, {}], // Wrong format ["3.00", null, {}], // Wrong format diff --git a/table/field/types/year.spec.ts b/table/field/types/year.spec.ts index 07c3cb6f..a47c05e5 100644 --- a/table/field/types/year.spec.ts +++ b/table/field/types/year.spec.ts @@ -1,6 +1,6 @@ import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../../table/index.js" +import { processTable } from "../../table/index.ts" describe("parseYearField", () => { it.each([ diff --git a/table/field/types/yearmonth.spec.ts b/table/field/types/yearmonth.spec.ts index d10c234b..95f72aa4 100644 --- a/table/field/types/yearmonth.spec.ts +++ b/table/field/types/yearmonth.spec.ts @@ -1,6 +1,6 @@ import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "../../table/index.js" +import { processTable } from "../../table/index.ts" describe("parseYearmonthField", () => { it.each([ diff --git a/table/index.ts b/table/index.ts index c26a3102..d5e46f0e 100644 --- a/table/index.ts +++ b/table/index.ts @@ -1,5 +1,5 @@ -export * from "./error/index.js" -export * from "./field/index.js" -export * from "./schema/index.js" -export * from "./table/index.js" -export * from "./plugin.js" +export * from "./error/index.ts" +export * from "./field/index.ts" +export * from "./schema/index.ts" +export * from "./table/index.ts" +export * from "./plugin.ts" diff --git a/table/package.json b/table/package.json index 4a5e5bb6..53b98875 100644 --- a/table/package.json +++ b/table/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/table", "type": "module", - "main": "build/index.js", "version": "0.5.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,10 +20,10 @@ "table" ], "scripts": { - "build": "tsc --build" + "build": "tsc" }, "dependencies": { - "nodejs-polars": "^0.18.0", + "nodejs-polars": "^0.21.0", "@dpkit/core": "workspace:*" } } diff --git a/table/plugin.ts b/table/plugin.ts index 6962120b..b6b57735 100644 --- a/table/plugin.ts +++ b/table/plugin.ts @@ -1,8 +1,12 @@ import type { Dialect, Plugin, Resource } from "@dpkit/core" -import type { Table } from "./table/index.js" +import type { Table } from "./table/index.ts" export type InferDialectOptions = { sampleBytes?: number } -export type SaveTableOptions = { path: string; dialect?: Dialect } +export type SaveTableOptions = { + path: string + format?: string + dialect?: Dialect +} export interface TablePlugin extends Plugin { inferDialect?( diff --git a/table/row/checks/unique.spec.ts b/table/row/checks/unique.spec.ts index 35c5578c..34c91c6b 100644 --- a/table/row/checks/unique.spec.ts +++ b/table/row/checks/unique.spec.ts @@ -1,7 +1,7 @@ import type { Schema } from "@dpkit/core" import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { inspectTable } from "../../table/index.js" +import { inspectTable } from "../../table/index.ts" describe("inspectTable (row/unique)", () => { it("should not report errors when all rows are unique for primary key", async () => { diff --git a/table/row/checks/unique.ts b/table/row/checks/unique.ts index fdc706be..3ed1e21e 100644 --- a/table/row/checks/unique.ts +++ b/table/row/checks/unique.ts @@ -1,6 +1,6 @@ import type { Schema } from "@dpkit/core" import { col, concatList } from "nodejs-polars" -import type { Table } from "../../table/Table.js" +import type { Table } from "../../table/Table.ts" // TODO: fold is not available so we use a tricky way to eliminate list nulls // TODO: Using comma as separator might rarely clash with comma in field names diff --git a/table/row/index.ts b/table/row/index.ts index 908c3482..7a4e2c8b 100644 --- a/table/row/index.ts +++ b/table/row/index.ts @@ -1 +1 @@ -export { inspectRows } from "./inspect.js" +export { inspectRows } from "./inspect.ts" diff --git a/table/row/inspect.ts b/table/row/inspect.ts index 8b4a980e..097c6c49 100644 --- a/table/row/inspect.ts +++ b/table/row/inspect.ts @@ -1,7 +1,7 @@ import type { Schema } from "@dpkit/core" -import type { TableError } from "../error/Table.js" -import type { Table } from "../table/Table.js" -import { checkRowUnique } from "./checks/unique.js" +import type { TableError } from "../error/Table.ts" +import type { Table } from "../table/Table.ts" +import { checkRowUnique } from "./checks/unique.ts" export function inspectRows(schema: Schema, errorTable: Table) { const errors: TableError[] = [] diff --git a/table/schema/Schema.ts b/table/schema/Schema.ts index 3da30622..c4ae7f44 100644 --- a/table/schema/Schema.ts +++ b/table/schema/Schema.ts @@ -1,5 +1,5 @@ import type { DataType } from "nodejs-polars" -import type { PolarsField } from "../field/index.js" +import type { PolarsField } from "../field/index.ts" export interface PolarsSchema { fields: PolarsField[] diff --git a/table/schema/index.ts b/table/schema/index.ts index ec5f5ee5..9d6f0cd4 100644 --- a/table/schema/index.ts +++ b/table/schema/index.ts @@ -1,2 +1,2 @@ -export { type InferSchemaOptions, inferSchema } from "./infer.js" -export { type PolarsSchema, getPolarsSchema } from "./Schema.js" +export { type InferSchemaOptions, inferSchema } from "./infer.ts" +export { type PolarsSchema, getPolarsSchema } from "./Schema.ts" diff --git a/table/schema/infer.spec.ts b/table/schema/infer.spec.ts index 643a5c0b..a04ea61e 100644 --- a/table/schema/infer.spec.ts +++ b/table/schema/infer.spec.ts @@ -1,7 +1,7 @@ import { DataFrame, Series } from "nodejs-polars" import { DataType } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { inferSchema } from "./infer.js" +import { inferSchema } from "./infer.ts" describe("inferSchema", () => { it("should infer from native types", async () => { diff --git a/table/schema/infer.ts b/table/schema/infer.ts index 97b7c2d6..7354fcce 100644 --- a/table/schema/infer.ts +++ b/table/schema/infer.ts @@ -1,7 +1,7 @@ import type { Field, Schema } from "@dpkit/core" import { col } from "nodejs-polars" -import { getPolarsSchema } from "../schema/index.js" -import type { Table } from "../table/index.js" +import { getPolarsSchema } from "../schema/index.ts" +import type { Table } from "../table/index.ts" export type InferSchemaOptions = { sampleRows?: number diff --git a/table/table/index.ts b/table/table/index.ts index 6d218e5a..de48fdc4 100644 --- a/table/table/index.ts +++ b/table/table/index.ts @@ -1,3 +1,3 @@ -export { processTable } from "./process.js" -export { inspectTable } from "./inspect.js" -export type { Table } from "./Table.js" +export { processTable } from "./process.ts" +export { inspectTable } from "./inspect.ts" +export type { Table } from "./Table.ts" diff --git a/table/table/inspect.spec.ts b/table/table/inspect.spec.ts index 65b4d3fd..75888ff9 100644 --- a/table/table/inspect.spec.ts +++ b/table/table/inspect.spec.ts @@ -1,7 +1,7 @@ import type { Schema } from "@dpkit/core" import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { inspectTable } from "./inspect.js" +import { inspectTable } from "./inspect.ts" describe("inspectTable", () => { describe("fields validation with fieldsMatch='exact'", () => { diff --git a/table/table/inspect.ts b/table/table/inspect.ts index fde5a3b4..1e95570f 100644 --- a/table/table/inspect.ts +++ b/table/table/inspect.ts @@ -1,13 +1,13 @@ import type { Schema } from "@dpkit/core" import { col, lit } from "nodejs-polars" -import type { TableError } from "../error/index.js" -import { matchField } from "../field/index.js" -import { inspectField } from "../field/index.js" -import { inspectRows } from "../row/index.js" -import { getPolarsSchema } from "../schema/index.js" -import type { PolarsSchema } from "../schema/index.js" -import type { Table } from "./Table.js" -import { processFields } from "./process.js" +import type { TableError } from "../error/index.ts" +import { matchField } from "../field/index.ts" +import { inspectField } from "../field/index.ts" +import { inspectRows } from "../row/index.ts" +import { getPolarsSchema } from "../schema/index.ts" +import type { PolarsSchema } from "../schema/index.ts" +import type { Table } from "./Table.ts" +import { processFields } from "./process.ts" export async function inspectTable( table: Table, diff --git a/table/table/process.spec.ts b/table/table/process.spec.ts index d3b1b7d3..ea4eb244 100644 --- a/table/table/process.spec.ts +++ b/table/table/process.spec.ts @@ -1,7 +1,7 @@ import type { Schema } from "@dpkit/core" import { DataFrame } from "nodejs-polars" import { describe, expect, it } from "vitest" -import { processTable } from "./process.js" +import { processTable } from "./process.ts" describe("processTable", () => { it("should work without schema", async () => { diff --git a/table/table/process.ts b/table/table/process.ts index 13a29de1..2b085473 100644 --- a/table/table/process.ts +++ b/table/table/process.ts @@ -2,11 +2,11 @@ import type { Schema } from "@dpkit/core" import type { Expr } from "nodejs-polars" import { DataType } from "nodejs-polars" import { col, lit } from "nodejs-polars" -import { matchField } from "../field/index.js" -import { parseField } from "../field/index.js" -import type { PolarsSchema } from "../schema/index.js" -import { getPolarsSchema } from "../schema/index.js" -import type { Table } from "./Table.js" +import { matchField } from "../field/index.ts" +import { parseField } from "../field/index.ts" +import type { PolarsSchema } from "../schema/index.ts" +import { getPolarsSchema } from "../schema/index.ts" +import type { Table } from "./Table.ts" export async function processTable( table: Table, diff --git a/table/tsconfig.json b/table/tsconfig.json index 7be40230..3c43903c 100644 --- a/table/tsconfig.json +++ b/table/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/table/typedoc.json b/table/typedoc.json index fc33b815..f8e49f3a 100644 --- a/table/typedoc.json +++ b/table/typedoc.json @@ -1,5 +1,4 @@ { "entryPoints": ["index.ts"], - "projectDocuments": ["CHANGELOG.md", "OVERVIEW.md"], "skipErrorChecking": true } diff --git a/test/general/index.ts b/test/general/index.ts deleted file mode 100644 index 6ae78c0c..00000000 --- a/test/general/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { useRecording } from "./recording.js" diff --git a/test/index.ts b/test/index.ts index 0c3a1cc8..fee0754e 100644 --- a/test/index.ts +++ b/test/index.ts @@ -1 +1 @@ -export * from "./general/index.js" +export * from "./recording/index.ts" diff --git a/test/package.json b/test/package.json index 5d2705f1..c211a083 100644 --- a/test/package.json +++ b/test/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/test", "type": "module", - "main": "build/index.js", "version": "0.1.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,7 +20,7 @@ "test" ], "scripts": { - "build": "tsc --build" + "build": "tsc" }, "dependencies": { "@pollyjs/adapter-fetch": "^6.0.6", diff --git a/test/recording/index.ts b/test/recording/index.ts new file mode 100644 index 00000000..86c8b328 --- /dev/null +++ b/test/recording/index.ts @@ -0,0 +1 @@ +export { useRecording } from "./recording.ts" diff --git a/test/general/recording.ts b/test/recording/recording.ts similarity index 80% rename from test/general/recording.ts rename to test/recording/recording.ts index 5aadbb47..bc7360d9 100644 --- a/test/general/recording.ts +++ b/test/recording/recording.ts @@ -6,6 +6,8 @@ import { afterAll, beforeAll, beforeEach } from "vitest" // @ts-ignore Polly.register(FSPersister) +// It emits a deprecation warning, but at the moment there is not +// working alternative for the fetch adapter // @ts-ignore Polly.register(FetchAdapter) @@ -42,10 +44,15 @@ export function useRecording( beforeEach(context => { // Overwrite recording name on a per-test basis - polly.recordingName = options.recordingName ?? context.task.name + polly.recordingName = options.recordingName ?? getFullTaskName(context.task) }) afterAll(async () => { await polly.stop() }) } + +function getFullTaskName(item: any): string { + const suiteName = item.suite ? getFullTaskName(item.suite) : undefined + return [suiteName, item.name].filter(Boolean).join("-") +} diff --git a/test/tsconfig.json b/test/tsconfig.json index 7be40230..3c43903c 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/tsconfig.json b/tsconfig.json index 5fb99d7e..8b1e1a39 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,26 +1,32 @@ { "$schema": "https://json.schemastore.org/tsconfig", - "include": ["**/*.ts"], - "exclude": ["**/build/*", "**/docs/*"], + "include": ["${configDir}/**/*.ts", "${configDir}/**/*.tsx"], + "exclude": ["${configDir}/**/build/", "${configDir}/**/docs/"], + "compilerOptions": { - "strict": true, - "noEmit": true, "target": "ES2022", "module": "NodeNext", "moduleResolution": "NodeNext", - "lib": ["ESNext", "ESNext.Array"], + "outDir": "${configDir}/build", + + "lib": ["ESNext"], + "types": ["node"], + "jsx": "react", + + "strict": true, "isolatedModules": true, "esModuleInterop": true, "resolveJsonModule": true, - "noUnusedLocals": true, - "strictNullChecks": true, "erasableSyntaxOnly": true, + "noUncheckedIndexedAccess": true, "noUnusedParameters": true, "noImplicitReturns": true, - "noUncheckedIndexedAccess": true, - "noFallthroughCasesInSwitch": false, + "noUnusedLocals": true, "inlineSourceMap": true, "inlineSources": true, - "skipLibCheck": true + "skipLibCheck": true, + + "declaration": true, + "rewriteRelativeImportExtensions": true } } diff --git a/ui/package.json b/ui/package.json index 53264469..b8b42c87 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/ui", "type": "module", - "main": "build/index.js", "version": "0.2.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,6 +20,6 @@ "ui" ], "scripts": { - "build": "tsc --build" + "build": "tsc" } } diff --git a/ui/tsconfig.json b/ui/tsconfig.json index 7be40230..3c43903c 100644 --- a/ui/tsconfig.json +++ b/ui/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/vitest.config.ts b/vitest.config.ts index 53590018..573d75ec 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -11,6 +11,7 @@ export default defineConfig({ exclude: [...configDefaults.exclude, "**/build/**"], testTimeout: 60 * 1000, passWithNoTests: true, + silent: "passed-only", coverage: { enabled: true, reporter: ["html", "json"], diff --git a/zenodo/OVERVIEW.md b/zenodo/OVERVIEW.md deleted file mode 100644 index 650c9200..00000000 --- a/zenodo/OVERVIEW.md +++ /dev/null @@ -1,6 +0,0 @@ -# @dpkit/zenodo - -:::note -This overview is under development. -::: - diff --git a/zenodo/general/index.ts b/zenodo/general/index.ts deleted file mode 100644 index 0e36dceb..00000000 --- a/zenodo/general/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { makeZenodoApiRequest } from "./request.js" diff --git a/zenodo/index.ts b/zenodo/index.ts index c3c86163..ae6326f6 100644 --- a/zenodo/index.ts +++ b/zenodo/index.ts @@ -1,3 +1,3 @@ -export * from "./package/index.js" -export * from "./resource/index.js" -export * from "./plugin.js" +export * from "./package/index.ts" +export * from "./resource/index.ts" +export * from "./plugin.ts" diff --git a/zenodo/package.json b/zenodo/package.json index 3661efc8..d155e7b6 100644 --- a/zenodo/package.json +++ b/zenodo/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/zenodo", "type": "module", - "main": "build/index.js", "version": "0.6.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,7 +20,7 @@ "zenodo" ], "scripts": { - "build": "tsc --build" + "build": "tsc" }, "dependencies": { "@dpkit/core": "workspace:*", diff --git a/zenodo/package/Package.ts b/zenodo/package/Package.ts index e19f00b0..955dd23b 100644 --- a/zenodo/package/Package.ts +++ b/zenodo/package/Package.ts @@ -1,5 +1,5 @@ -import type { ZenodoResource } from "../resource/index.js" -import type { ZenodoCreator } from "./Creator.js" +import type { ZenodoResource } from "../resource/index.ts" +import type { ZenodoCreator } from "./Creator.ts" /** * Zenodo Deposit interface diff --git a/zenodo/package/fixtures/generated/load.spec.ts.snap b/zenodo/package/fixtures/generated/load.spec.ts.snap index 4d0347e4..1e3c5625 100644 --- a/zenodo/package/fixtures/generated/load.spec.ts.snap +++ b/zenodo/package/fixtures/generated/load.spec.ts.snap @@ -29,7 +29,7 @@ exports[`loadPackageFromZenodo > should load a package 1`] = ` "bytes": 272, "format": "csv", "hash": "md5:5ac1b92a57ec809c546ea90334c845c9", - "name": "openaq_measurements_pm10_japan_20250527_095520", + "name": "openaq-measurements-p-m10-japan-20250527-095520", "path": "https://zenodo.org/records/15525711/files/openaq_measurements_PM10_Japan_20250527_095520.csv", "zenodo:key": undefined, "zenodo:url": undefined, @@ -126,230 +126,228 @@ exports[`loadPackageFromZenodo > shoule merge datapackage.json if present 1`] = "profile": "tabular-data-resource", "schema": { "$schema": undefined, - "descriptor": { - "fields": [ - { - "description": "A unique identifier for the tag, provided by the data owner. If the data owner does not provide a tag ID, an internal Movebank tag identifier may sometimes be shown. Example: '2342'; Units: none; Entity described: tag", - "format": "default", - "name": "tag-id", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000181/2/", - "title": "tag ID", - "type": "string", - }, - { - "description": "An individual identifier for the animal, provided by the data owner. Values are unique within the study. If the data owner does not provide an Animal ID, an internal Movebank animal identifier is sometimes shown. Example: 'TUSC_CV5'; Units: none; Entity described: individual", - "format": "default", - "name": "animal-id", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000016/3/", - "title": "animal ID", - "type": "string", - }, - { - "description": "The scientific name of the taxon on which the tag was deployed, as defined by the Integrated Taxonomic Information System www.itis.gov. If the species name can not be provided, this should be the lowest level taxonomic rank that can be determined and that is used in the ITIS taxonomy. Additional information can be provided using the term 'taxon detail'. The values 'test' and 'calibration' identify events relevant to animal tracking studies that should not be associated with a taxon. Format: controlled list; Entity described: individual", - "format": "default", - "name": "animal-taxon", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000024/4/", - "title": "animal taxon", - "type": "string", - }, - { - "description": "The timestamp when the tag deployment started. Data records recorded before this day and time are not associated with the animal related to the deployment. Values are typically defined by the data owner, and in some cases are created automatically during data import. Example: '2008-08-30 18:00:00.000'; Format: yyyy-MM-dd HH:mm:ss.SSS; Units: UTC or GPS time; Entity described: deployment", - "format": "%Y-%m-%d %H:%M:%S.%f", - "name": "deploy-on-date", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000081/3/", - "title": "deploy on timestamp", - "type": "datetime", - }, - { - "description": "The timestamp when the tag deployment ended. Data records recorded after this day and time are not associated with the animal related to the deployment. Values are typically defined by the data owner, and in some cases are created automatically during data import. Further information can be provided in 'deployment end type' and 'deployment end comments'. Example: '2009-10-01 12:00:00.000'; Format: yyyy-MM-dd HH:mm:ss.SSS; Units: UTC or GPS time; Entity described: deployment", - "format": "%Y-%m-%d %H:%M:%S.%f", - "name": "deploy-off-date", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000077/4/", - "title": "deploy off timestamp", - "type": "datetime", - }, - { - "description": "A name or unique identifier for a project associated with the deployment, for example a monitoring program or another data platform. Best practice is to include the name of the related database or organization followed by the project identifier. Example: 'MOTUS145'; Units: none; Entity described: deployment", - "format": "default", - "name": "alt-project-id", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000244/2/", - "title": "alt project ID", - "type": "string", - }, - { - "description": "Additional information about the animal. Example: 'first to fledge from nest'; Units: none; Entity described: individual", - "format": "default", - "name": "animal-comments", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000012/3/", - "title": "animal comments", - "type": "string", - }, - { - "description": "The age class or life stage of the animal at the beginning of the deployment. Can be years or months of age or terms such as 'adult', 'subadult' and 'juvenile'. Best practice is to define units in the values if needed (e.g. '2 years'). Example: 'juvenile, adult'; Units: none; Entity described: deployment", - "format": "default", - "name": "animal-life-stage", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000018/3/", - "title": "animal life stage", - "type": "string", - }, - { - "description": "The mass of the animal, typically at the beginning of the deployment. Example: '500'; Units: grams; Entity described: deployment", - "format": "default", - "name": "animal-mass", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000019/2/", - "title": "animal mass", - "type": "number", - }, - { - "description": "An alternate identifier for the animal. Used as the display name for animals shown in the Animal Tracker App. Example: 'Ali'; Units: none; Entity described: individual", - "format": "default", - "name": "animal-nickname", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000020/2/", - "title": "animal nickname", - "type": "string", - }, - { - "description": "A number or color scheme for a band or ring attached to the animal. Color bands and other markings can be stored in 'animal marker ID'. Example: '26225'; Units: none; Entity described: individual", - "format": "default", - "name": "animal-ring-id", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000022/3/", - "title": "animal ring ID", - "type": "string", - }, - { - "description": "The sex of the animal. Allowed values are m = male; f = female; u = unknown. Format: controlled list; Entity described: individual", - "format": "default", - "name": "animal-sex", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000023/3/", - "title": "animal sex", - "type": "string", - }, - { - "description": "The way a tag is attached to an animal. Details can be provided in 'attachment comments'. Values are chosen from a controlled list: backpack-harness = The tag is attached to the animal using a backpack-style harness; collar = The tag is attached by a collar around the animal's neck; ear-tag = The tag is attached to the animal's ear; fin mount = The tag is attached to the animal's fin; glue = The tag is attached to the animal using glue; harness = The tag is attached to the animal using a harness; implant = The tag is placed under the skin of the animal; leg-band = The tag is attached as a leg band or ring; leg-loop-harness = The tag is attached to the animal using a leg-loop-style harness; none = No tag was attached, e.g., for observations using natural markings; other = The tag is attached using another method; subcutaneous-anchor = The tag is attached using one or more anchors attached underneath the animal's skin; suction-cup = The tag is attached using one or more suction cups; sutures = The tag is attached by one or more sutures; tape = The tag is attached to the animal using tape. Format: controlled list; Entity described: deployment", - "format": "default", - "name": "attachment-type", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000052/5/", - "title": "attachment type", - "type": "string", - }, - { - "description": "The geographic latitude of the location where the animal was released. Intended primarily for cases in which the animal release location has higher accuracy than that derived from sensor data. Example: '27.3516'; Units: decimal degrees, WGS84 reference system; Entity described: deployment", - "format": "default", - "name": "deploy-on-latitude", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000078/3/", - "title": "deploy on latitude", - "type": "number", - }, - { - "description": "The geographic longitude of the location where the animal was released. Intended primarily for cases in which the animal release location has higher accuracy than that derived from sensor data. Example: '-97.3321'; Units: decimal degrees, WGS84 reference system; Entity described: deployment", - "format": "default", - "name": "deploy-on-longitude", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000079/3/", - "title": "deploy on longitude", - "type": "number", - }, - { - "description": "A list of additional measurements taken during capture of the animal at the start of the deployment. Recommended best practice is to define units and use a key:value encoding schema for a data interchange format such as JSON. Example: "{tarsusLengthInMillimeters:17.3, wingChordInMillimeters:125}"; Units: not defined; Entity described: deployment", - "format": "default", - "name": "deploy-on-measurements", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000356/2/", - "title": "deploy on measurements", - "type": "string", - }, - { - "description": "Additional information about the tag deployment that is not described by other reference data terms. Example: 'body length 154 cm; condition good'; Units: none; Entity described: deployment", - "format": "default", - "name": "deployment-comments", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000082/2/", - "title": "deployment comments", - "type": "string", - }, - { - "description": "A categorical classification describing the end of the tag deployment on the animal. Best practice is to clarify how the 'deploy-off timestamp', if present, was chosen. Values are chosen from a controlled list: analysis-end = the end time represents the end of the period of interest; captured = The tag remained on the animal but the animal was captured or confined; dead = The deployment ended with the death of the animal that was carrying the tag; dead/fall-off = The tag stopped moving, and it is not possible to determine whether it is due to death of the animal or unscheduled tag detachment; equipment-failure = The tag stopped working; fall-off = The attachment of the tag to the animal failed, and it fell of accidentally; other = other; released = The tag remained on the animal but the animal was released from captivity or confinement; removal = The tag was purposefully removed from the animal; scheduled-detachment = The tag was programmed to detach from the animal; transmission-end = The tag stopped transmitting usable data; unknown = The cause of the end of data availability or transmission is unknown. Format: controlled list; Entity described: deployment", - "format": "default", - "name": "deployment-end-type", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000084/5/", - "title": "deployment end type", - "type": "string", - }, - { - "description": "A unique identifier for the deployment of a tag on animal, provided by the data owner. If the data owner does not provide a Deployment ID, an internal Movebank deployment identifier may sometimes be shown. Example: 'Jane_42818'; Units: none; Entity described: deployment", - "format": "default", - "name": "deployment-id", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000085/3/", - "title": "deployment ID", - "type": "string", - }, - { - "description": "Comments about the location accuracy. This can further describe values provided in 'location error text', 'location error numerical', 'vertical error numerical', 'lat lower', 'lat upper', 'long lower' and/or 'long upper'. The percentile uncertainty can be provided using 'location error percentile'. Example: '1 standard deviation errors, assuming normal distribution, provided by the GPS unit'; Units: none; Entity described: deployment", - "format": "default", - "name": "location-accuracy-comments", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000141/3/", - "title": "location accuracy comments", - "type": "string", - }, - { - "description": "The way in which the animal was manipulated during the deployment. Additional information can be provided using 'manipulation comments'. Changes in manipulation status during deployment can be identified using 'manipulation status'. Values are chosen from a controlled list: confined = The animal's movement was restricted to within a defined area; domesticated = The animal is domesticated, for example, is a house pet or part of a managed herd; manipulated-other = The animal was manipulated in some other way, such as a physiological manipulation; none = The animal received no treatment other than tag attachment and related measurements and sampling (if applicable); reintroduction = The animal has been reintroduced as part of wildlife conservation or management efforts; relocated = The animal was released from a site other than the one at which it was captured. Format: controlled list; Entity described: deployment", - "format": "default", - "name": "manipulation-type", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000155/6/", - "title": "manipulation type", - "type": "string", - }, - { - "description": "A location such as the deployment site, study site, or colony name. Example: 'Pickerel Island North'; Units: none; Entity described: deployment", - "format": "default", - "name": "study-site", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000175/3/", - "title": "study site", - "type": "string", - }, - { - "description": "The tag firmware and version used during the deployment. If needed, identify the relevant sensors on the tag. Units: none; Entity described: deployment", - "format": "default", - "name": "tag-firmware", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000380/1/", - "title": "tag firmware", - "type": "string", - }, - { - "description": "The company or person that produced the tag. Example: 'Holohil'; Units: none; Entity described: tag", - "format": "default", - "name": "tag-manufacturer-name", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000183/3/", - "title": "tag manufacturer name", - "type": "string", - }, - { - "description": "The mass of the tag. Can be used with 'tag mass total' to define the mass of the tag separately from that of the tag with additional hardware. Example: '24'; Units: grams; Entity described: tag", - "format": "default", - "name": "tag-mass", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000184/4/", - "title": "tag mass", - "type": "number", - }, - { - "description": "The way the data are received from the tag. Values are chosen from a controlled list: ISS = Data are transferred via the International Space Station; LPWAN = Data are transferred through a low-power wide-area network, such as LoRa or Sigfox; multiple = Data are acquired using multiple methods; none = Data are obtained without use of an animal-borne tag, such as by observing a unique marking; other-wireless = Data are transferred via another form of wireless data transfer, such as a VHF transmitter/receiver; phone-network = Data are transferred via a phone network, such as GSM or AMPS; satellite = Data are transferred via satellite; tag-retrieval = The tag must be physically retrieved in order to obtain the data; telemetry-network = Data are obtained through a radio or acoustic telemetry network; Wi-Fi/Bluetooth = Data are transferred via a local Wi-Fi or Bluetooth system. Format: controlled list; Entity described: deployment", - "format": "default", - "name": "tag-readout-method", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000188/4/", - "title": "tag readout method", - "type": "string", - }, - { - "description": "The serial number of the tag. Example: 'MN93-33243'; Units: none; Entity described: tag", - "format": "default", - "name": "tag-serial-no", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000189/3/", - "title": "tag serial no", - "type": "string", - }, - ], - "primaryKey": [ - "animal-id", - "tag-id", - ], - }, + "fields": [ + { + "description": "A unique identifier for the tag, provided by the data owner. If the data owner does not provide a tag ID, an internal Movebank tag identifier may sometimes be shown. Example: '2342'; Units: none; Entity described: tag", + "format": "default", + "name": "tag-id", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000181/2/", + "title": "tag ID", + "type": "string", + }, + { + "description": "An individual identifier for the animal, provided by the data owner. Values are unique within the study. If the data owner does not provide an Animal ID, an internal Movebank animal identifier is sometimes shown. Example: 'TUSC_CV5'; Units: none; Entity described: individual", + "format": "default", + "name": "animal-id", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000016/3/", + "title": "animal ID", + "type": "string", + }, + { + "description": "The scientific name of the taxon on which the tag was deployed, as defined by the Integrated Taxonomic Information System www.itis.gov. If the species name can not be provided, this should be the lowest level taxonomic rank that can be determined and that is used in the ITIS taxonomy. Additional information can be provided using the term 'taxon detail'. The values 'test' and 'calibration' identify events relevant to animal tracking studies that should not be associated with a taxon. Format: controlled list; Entity described: individual", + "format": "default", + "name": "animal-taxon", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000024/4/", + "title": "animal taxon", + "type": "string", + }, + { + "description": "The timestamp when the tag deployment started. Data records recorded before this day and time are not associated with the animal related to the deployment. Values are typically defined by the data owner, and in some cases are created automatically during data import. Example: '2008-08-30 18:00:00.000'; Format: yyyy-MM-dd HH:mm:ss.SSS; Units: UTC or GPS time; Entity described: deployment", + "format": "%Y-%m-%d %H:%M:%S.%f", + "name": "deploy-on-date", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000081/3/", + "title": "deploy on timestamp", + "type": "datetime", + }, + { + "description": "The timestamp when the tag deployment ended. Data records recorded after this day and time are not associated with the animal related to the deployment. Values are typically defined by the data owner, and in some cases are created automatically during data import. Further information can be provided in 'deployment end type' and 'deployment end comments'. Example: '2009-10-01 12:00:00.000'; Format: yyyy-MM-dd HH:mm:ss.SSS; Units: UTC or GPS time; Entity described: deployment", + "format": "%Y-%m-%d %H:%M:%S.%f", + "name": "deploy-off-date", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000077/4/", + "title": "deploy off timestamp", + "type": "datetime", + }, + { + "description": "A name or unique identifier for a project associated with the deployment, for example a monitoring program or another data platform. Best practice is to include the name of the related database or organization followed by the project identifier. Example: 'MOTUS145'; Units: none; Entity described: deployment", + "format": "default", + "name": "alt-project-id", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000244/2/", + "title": "alt project ID", + "type": "string", + }, + { + "description": "Additional information about the animal. Example: 'first to fledge from nest'; Units: none; Entity described: individual", + "format": "default", + "name": "animal-comments", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000012/3/", + "title": "animal comments", + "type": "string", + }, + { + "description": "The age class or life stage of the animal at the beginning of the deployment. Can be years or months of age or terms such as 'adult', 'subadult' and 'juvenile'. Best practice is to define units in the values if needed (e.g. '2 years'). Example: 'juvenile, adult'; Units: none; Entity described: deployment", + "format": "default", + "name": "animal-life-stage", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000018/3/", + "title": "animal life stage", + "type": "string", + }, + { + "description": "The mass of the animal, typically at the beginning of the deployment. Example: '500'; Units: grams; Entity described: deployment", + "format": "default", + "name": "animal-mass", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000019/2/", + "title": "animal mass", + "type": "number", + }, + { + "description": "An alternate identifier for the animal. Used as the display name for animals shown in the Animal Tracker App. Example: 'Ali'; Units: none; Entity described: individual", + "format": "default", + "name": "animal-nickname", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000020/2/", + "title": "animal nickname", + "type": "string", + }, + { + "description": "A number or color scheme for a band or ring attached to the animal. Color bands and other markings can be stored in 'animal marker ID'. Example: '26225'; Units: none; Entity described: individual", + "format": "default", + "name": "animal-ring-id", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000022/3/", + "title": "animal ring ID", + "type": "string", + }, + { + "description": "The sex of the animal. Allowed values are m = male; f = female; u = unknown. Format: controlled list; Entity described: individual", + "format": "default", + "name": "animal-sex", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000023/3/", + "title": "animal sex", + "type": "string", + }, + { + "description": "The way a tag is attached to an animal. Details can be provided in 'attachment comments'. Values are chosen from a controlled list: backpack-harness = The tag is attached to the animal using a backpack-style harness; collar = The tag is attached by a collar around the animal's neck; ear-tag = The tag is attached to the animal's ear; fin mount = The tag is attached to the animal's fin; glue = The tag is attached to the animal using glue; harness = The tag is attached to the animal using a harness; implant = The tag is placed under the skin of the animal; leg-band = The tag is attached as a leg band or ring; leg-loop-harness = The tag is attached to the animal using a leg-loop-style harness; none = No tag was attached, e.g., for observations using natural markings; other = The tag is attached using another method; subcutaneous-anchor = The tag is attached using one or more anchors attached underneath the animal's skin; suction-cup = The tag is attached using one or more suction cups; sutures = The tag is attached by one or more sutures; tape = The tag is attached to the animal using tape. Format: controlled list; Entity described: deployment", + "format": "default", + "name": "attachment-type", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000052/5/", + "title": "attachment type", + "type": "string", + }, + { + "description": "The geographic latitude of the location where the animal was released. Intended primarily for cases in which the animal release location has higher accuracy than that derived from sensor data. Example: '27.3516'; Units: decimal degrees, WGS84 reference system; Entity described: deployment", + "format": "default", + "name": "deploy-on-latitude", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000078/3/", + "title": "deploy on latitude", + "type": "number", + }, + { + "description": "The geographic longitude of the location where the animal was released. Intended primarily for cases in which the animal release location has higher accuracy than that derived from sensor data. Example: '-97.3321'; Units: decimal degrees, WGS84 reference system; Entity described: deployment", + "format": "default", + "name": "deploy-on-longitude", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000079/3/", + "title": "deploy on longitude", + "type": "number", + }, + { + "description": "A list of additional measurements taken during capture of the animal at the start of the deployment. Recommended best practice is to define units and use a key:value encoding schema for a data interchange format such as JSON. Example: "{tarsusLengthInMillimeters:17.3, wingChordInMillimeters:125}"; Units: not defined; Entity described: deployment", + "format": "default", + "name": "deploy-on-measurements", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000356/2/", + "title": "deploy on measurements", + "type": "string", + }, + { + "description": "Additional information about the tag deployment that is not described by other reference data terms. Example: 'body length 154 cm; condition good'; Units: none; Entity described: deployment", + "format": "default", + "name": "deployment-comments", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000082/2/", + "title": "deployment comments", + "type": "string", + }, + { + "description": "A categorical classification describing the end of the tag deployment on the animal. Best practice is to clarify how the 'deploy-off timestamp', if present, was chosen. Values are chosen from a controlled list: analysis-end = the end time represents the end of the period of interest; captured = The tag remained on the animal but the animal was captured or confined; dead = The deployment ended with the death of the animal that was carrying the tag; dead/fall-off = The tag stopped moving, and it is not possible to determine whether it is due to death of the animal or unscheduled tag detachment; equipment-failure = The tag stopped working; fall-off = The attachment of the tag to the animal failed, and it fell of accidentally; other = other; released = The tag remained on the animal but the animal was released from captivity or confinement; removal = The tag was purposefully removed from the animal; scheduled-detachment = The tag was programmed to detach from the animal; transmission-end = The tag stopped transmitting usable data; unknown = The cause of the end of data availability or transmission is unknown. Format: controlled list; Entity described: deployment", + "format": "default", + "name": "deployment-end-type", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000084/5/", + "title": "deployment end type", + "type": "string", + }, + { + "description": "A unique identifier for the deployment of a tag on animal, provided by the data owner. If the data owner does not provide a Deployment ID, an internal Movebank deployment identifier may sometimes be shown. Example: 'Jane_42818'; Units: none; Entity described: deployment", + "format": "default", + "name": "deployment-id", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000085/3/", + "title": "deployment ID", + "type": "string", + }, + { + "description": "Comments about the location accuracy. This can further describe values provided in 'location error text', 'location error numerical', 'vertical error numerical', 'lat lower', 'lat upper', 'long lower' and/or 'long upper'. The percentile uncertainty can be provided using 'location error percentile'. Example: '1 standard deviation errors, assuming normal distribution, provided by the GPS unit'; Units: none; Entity described: deployment", + "format": "default", + "name": "location-accuracy-comments", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000141/3/", + "title": "location accuracy comments", + "type": "string", + }, + { + "description": "The way in which the animal was manipulated during the deployment. Additional information can be provided using 'manipulation comments'. Changes in manipulation status during deployment can be identified using 'manipulation status'. Values are chosen from a controlled list: confined = The animal's movement was restricted to within a defined area; domesticated = The animal is domesticated, for example, is a house pet or part of a managed herd; manipulated-other = The animal was manipulated in some other way, such as a physiological manipulation; none = The animal received no treatment other than tag attachment and related measurements and sampling (if applicable); reintroduction = The animal has been reintroduced as part of wildlife conservation or management efforts; relocated = The animal was released from a site other than the one at which it was captured. Format: controlled list; Entity described: deployment", + "format": "default", + "name": "manipulation-type", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000155/6/", + "title": "manipulation type", + "type": "string", + }, + { + "description": "A location such as the deployment site, study site, or colony name. Example: 'Pickerel Island North'; Units: none; Entity described: deployment", + "format": "default", + "name": "study-site", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000175/3/", + "title": "study site", + "type": "string", + }, + { + "description": "The tag firmware and version used during the deployment. If needed, identify the relevant sensors on the tag. Units: none; Entity described: deployment", + "format": "default", + "name": "tag-firmware", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000380/1/", + "title": "tag firmware", + "type": "string", + }, + { + "description": "The company or person that produced the tag. Example: 'Holohil'; Units: none; Entity described: tag", + "format": "default", + "name": "tag-manufacturer-name", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000183/3/", + "title": "tag manufacturer name", + "type": "string", + }, + { + "description": "The mass of the tag. Can be used with 'tag mass total' to define the mass of the tag separately from that of the tag with additional hardware. Example: '24'; Units: grams; Entity described: tag", + "format": "default", + "name": "tag-mass", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000184/4/", + "title": "tag mass", + "type": "number", + }, + { + "description": "The way the data are received from the tag. Values are chosen from a controlled list: ISS = Data are transferred via the International Space Station; LPWAN = Data are transferred through a low-power wide-area network, such as LoRa or Sigfox; multiple = Data are acquired using multiple methods; none = Data are obtained without use of an animal-borne tag, such as by observing a unique marking; other-wireless = Data are transferred via another form of wireless data transfer, such as a VHF transmitter/receiver; phone-network = Data are transferred via a phone network, such as GSM or AMPS; satellite = Data are transferred via satellite; tag-retrieval = The tag must be physically retrieved in order to obtain the data; telemetry-network = Data are obtained through a radio or acoustic telemetry network; Wi-Fi/Bluetooth = Data are transferred via a local Wi-Fi or Bluetooth system. Format: controlled list; Entity described: deployment", + "format": "default", + "name": "tag-readout-method", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000188/4/", + "title": "tag readout method", + "type": "string", + }, + { + "description": "The serial number of the tag. Example: 'MN93-33243'; Units: none; Entity described: tag", + "format": "default", + "name": "tag-serial-no", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000189/3/", + "title": "tag serial no", + "type": "string", + }, + ], + "primaryKey": [ + "animal-id", + "tag-id", + ], }, "zenodo:key": undefined, "zenodo:url": undefined, @@ -367,202 +365,202 @@ exports[`loadPackageFromZenodo > shoule merge datapackage.json if present 1`] = "profile": "tabular-data-resource", "schema": { "$schema": undefined, - "descriptor": { - "fields": [ - { - "description": "An identifier for the set of values associated with each event, i.e. sensor measurement. A unique event ID is assigned to every time-location or other time-measurement record in Movebank. If multiple measurements are included within a single row of a data file, they will share an event ID. If users import the same sensor measurement to Movebank multiple times, a separate event ID will be assigned to each. Example: '14328243575'; Units: none; Entity described: event", - "format": "default", - "name": "event-id", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000103/3/", - "title": "event ID", - "type": "integer", - }, - { - "description": "Determines whether an event is visible on the Movebank map. Allowed values are TRUE or FALSE. Values are calculated automatically, with TRUE indicating the event has not been flagged as an outlier by 'algorithm marked outlier', 'import marked outlier' or 'manually marked outlier', or that the user has overridden the results of these outlier attributes using 'manually marked valid' = TRUE. Units: none; Entity described: event", - "format": "default", - "name": "visible", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000209/3/", - "title": "visible", - "type": "boolean", - }, - { - "description": "The date and time corresponding to a sensor measurement or an estimate derived from sensor measurements. Example: '2008-08-14 18:31:00.000'; Format: yyyy-MM-dd HH:mm:ss.SSS; Units: UTC or GPS time; Entity described: event", - "format": "%Y-%m-%d %H:%M:%S.%f", - "name": "timestamp", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000200/2/", - "title": "timestamp", - "type": "datetime", - }, - { - "description": "The geographic longitude of the location as estimated by the sensor. Positive values are east of the Greenwich Meridian, negative values are west of it. Example: '-121.1761111'; Units: decimal degrees, WGS84 reference system; Entity described: event", - "format": "default", - "name": "location-long", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000146/2/", - "title": "location long", - "type": "number", - }, - { - "description": "The geographic latitude of the location as estimated by the sensor. Example: '-41.0982423'; Units: decimal degrees, WGS84 reference system; Entity described: event", - "format": "default", - "name": "location-lat", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000145/4/", - "title": "location lat", - "type": "number", - }, - { - "description": "The barometric air or water pressure. Example: '32536.0'; Units: mbar (hPa); Entity described: event", - "format": "default", - "name": "bar:barometric-pressure", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000055/3/", - "title": "barometric pressure", - "type": "number", - }, - { - "description": "The temperature measured by the tag (different from ambient temperature or internal body temperature of the animal). Example: '32.1'; Units: degrees Celsius; Entity described: event", - "format": "default", - "name": "external-temperature", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000104/2/", - "title": "external temperature", - "type": "number", - }, - { - "description": "Dilution of precision provided by the GPS. Example: '1.8'; Units: unitless; Entity described: event", - "format": "default", - "name": "gps:dop", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000115/2/", - "title": "GPS DOP", - "type": "number", - }, - { - "description": "The number of GPS satellites used to estimate the location. Example: '8'; Units: count; Entity described: event", - "format": "default", - "name": "gps:satellite-count", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000120/3/", - "title": "GPS satellite count", - "type": "integer", - }, - { - "description": "The time required to obtain the GPS location fix. Example: '36'; Units: seconds; Entity described: event", - "format": "default", - "name": "gps-time-to-fix", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000121/3/", - "title": "GPS time to fix", - "type": "number", - }, - { - "description": "The estimated ground speed provided by the sensor or calculated between consecutive locations. Example: '7.22'; Units: m/s; Entity described: event", - "format": "default", - "name": "ground-speed", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000124/2/", - "title": "ground speed", - "type": "number", - }, - { - "description": "The direction in which the tag is moving, in decimal degrees clockwise from north, as provided by the sensor or calculated between consecutive locations. Values range from 0-360: 0 = north, 90 = east, 180 = south, 270 = west. Example: '315.88'; Units: degrees clockwise from north; Entity described: event", - "format": "default", - "name": "heading", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000129/2/", - "title": "heading", - "type": "number", - }, - { - "description": "The estimated height of the tag above mean sea level, typically estimated by the tag. If altitudes are calculated as height above an ellipsoid, use 'height above ellipsoid'. Example: '34'; Units: meters; Entity described: event", - "format": "default", - "name": "height-above-msl", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000131/3/", - "title": "height above mean sea level", - "type": "number", - }, - { - "description": "Identifies events as outliers. Outliers have the value TRUE. Typically used to import a record of outliers that were identified by the data provider or owner with automated methods outside of Movebank. Information about how outliers were defined can be provided in 'outlier comments'. Units: none; Entity described: event", - "format": "default", - "name": "import-marked-outlier", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000133/3/", - "title": "import marked outlier", - "type": "boolean", - }, - { - "description": "An estimate of the horizontal error of the location including only numbers. (If the error estimates include non-numerical characters such as '>' use 'location error text'.) These values can be described using 'location error percentile' and 'location accuracy comments'. Example: '50'; Units: meters; Entity described: event", - "format": "default", - "name": "location-error-numerical", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000142/3/", - "title": "location error numerical", - "type": "number", - }, - { - "description": "Identifies events flagged manually as outliers, typically using the Event Editor in Movebank, and may also include outliers identified using other methods. Outliers have the value TRUE. Information about how outliers were defined can be provided in 'outlier comments'. Units: none; Entity described: event", - "format": "default", - "name": "manually-marked-outlier", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000156/3/", - "title": "manually marked outlier", - "type": "boolean", - }, - { - "description": "An estimate of the vertical error of the location. These values can be described using 'location error percentile' and 'location accuracy comments'. Example: '12'; Units: meters; Entity described: event", - "format": "default", - "name": "vertical-error-numerical", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000208/3/", - "title": "vertical error numerical", - "type": "number", - }, - { - "description": "The type of sensor with which data were collected. All sensors are associated with a tag id, and tags can contain multiple sensor types. Each event record in Movebank is assigned one sensor type. If values from multiple sensors are reported in a single event, the primary sensor is used. Values are chosen from a controlled list: acceleration = The sensor collects acceleration data; accessory-measurements = The sensor collects accessory measurements, such as battery voltage; acoustic-telemetry = The sensor transmits an acoustic signal that is detected by receivers to determine location; argos-doppler-shift = The sensor location is estimated by Argos using Doppler shift; barometer = The sensor records air or water pressure; bird-ring = The animal is identified by a band or ring that has a unique identifier; gps = The sensor uses GPS to determine location; gyroscope = The sensor records angular velocity; heart-rate = The sensor records or is used to calculate heart rate; magnetometer = The sensor records the magnetic field; natural-mark = The animal is identified by a unique natural marking; orientation = Quaternion components describing the orientation of the tag are derived from accelerometer and gyroscope measurements; proximity = The sensor identifies proximity to other tags; radio-transmitter = The sensor transmits a radio signal that is detected by receivers to determine location; sigfox-geolocation = The sensor location is determined by Sigfox using the received signal strength indicator; solar-geolocator = The sensor collects light levels, which are used to determine position (for processed locations); solar-geolocator-raw = The sensor collects light levels, which are used to determine position (for raw light-level measurements); solar-geolocator-twilight = The sensor collects light levels, which are used to determine position (for twilights calculated from light-level measurements). Format: controlled list; Entity described: event", - "format": "default", - "name": "sensor-type", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000170/6/", - "title": "sensor type", - "type": "string", - }, - { - "description": "This attribute has been merged with 'animal taxon'. The scientific name of the species on which the tag was deployed, as defined by the Integrated Taxonomic Information System (ITIS, www.itis.gov). If the species name can not be provided, this should be the lowest level taxonomic rank that can be determined and that is used in the ITIS taxonomy. Additional information can be provided using the term 'taxon detail'. Format: controlled list; Entity described: individual", - "format": "default", - "name": "individual-taxon-canonical-name", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000135/5/", - "title": "individual taxon canonical name", - "type": "string", - }, - { - "description": "This attribute has been merged with 'tag ID'. An identifier for the tag, provided by the data owner. Values are unique within the study. If the data owner does not provide a tag ID, an internal Movebank tag identifier may sometimes be shown. Example: '2342'; Units: none; Entity described: tag", - "format": "default", - "name": "tag-local-identifier", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000182/5/", - "title": "tag local identifier", - "type": "string", - }, - { - "description": "This attribute has been merged with 'animal ID'. An individual identifier for the animal, provided by the data owner. Values are unique within the study. If the data owner does not provide an Animal ID, an internal Movebank animal identifier is sometimes shown. Example: '91876A, Gary'; Units: none; Entity described: individual", - "format": "default", - "name": "individual-local-identifier", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000134/4/", - "title": "individual local identifier", - "type": "string", - }, - { - "description": "The name of the study in Movebank. Example: 'Coyotes, Kays and Bogan, Albany NY'; Units: none; Entity described: study", - "format": "default", - "name": "study-name", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000173/3/", - "title": "study name", - "type": "string", - }, - ], - "foreignKeys": [ - { + "fields": [ + { + "description": "An identifier for the set of values associated with each event, i.e. sensor measurement. A unique event ID is assigned to every time-location or other time-measurement record in Movebank. If multiple measurements are included within a single row of a data file, they will share an event ID. If users import the same sensor measurement to Movebank multiple times, a separate event ID will be assigned to each. Example: '14328243575'; Units: none; Entity described: event", + "format": "default", + "name": "event-id", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000103/3/", + "title": "event ID", + "type": "integer", + }, + { + "description": "Determines whether an event is visible on the Movebank map. Allowed values are TRUE or FALSE. Values are calculated automatically, with TRUE indicating the event has not been flagged as an outlier by 'algorithm marked outlier', 'import marked outlier' or 'manually marked outlier', or that the user has overridden the results of these outlier attributes using 'manually marked valid' = TRUE. Units: none; Entity described: event", + "format": "default", + "name": "visible", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000209/3/", + "title": "visible", + "type": "boolean", + }, + { + "description": "The date and time corresponding to a sensor measurement or an estimate derived from sensor measurements. Example: '2008-08-14 18:31:00.000'; Format: yyyy-MM-dd HH:mm:ss.SSS; Units: UTC or GPS time; Entity described: event", + "format": "%Y-%m-%d %H:%M:%S.%f", + "name": "timestamp", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000200/2/", + "title": "timestamp", + "type": "datetime", + }, + { + "description": "The geographic longitude of the location as estimated by the sensor. Positive values are east of the Greenwich Meridian, negative values are west of it. Example: '-121.1761111'; Units: decimal degrees, WGS84 reference system; Entity described: event", + "format": "default", + "name": "location-long", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000146/2/", + "title": "location long", + "type": "number", + }, + { + "description": "The geographic latitude of the location as estimated by the sensor. Example: '-41.0982423'; Units: decimal degrees, WGS84 reference system; Entity described: event", + "format": "default", + "name": "location-lat", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000145/4/", + "title": "location lat", + "type": "number", + }, + { + "description": "The barometric air or water pressure. Example: '32536.0'; Units: mbar (hPa); Entity described: event", + "format": "default", + "name": "bar:barometric-pressure", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000055/3/", + "title": "barometric pressure", + "type": "number", + }, + { + "description": "The temperature measured by the tag (different from ambient temperature or internal body temperature of the animal). Example: '32.1'; Units: degrees Celsius; Entity described: event", + "format": "default", + "name": "external-temperature", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000104/2/", + "title": "external temperature", + "type": "number", + }, + { + "description": "Dilution of precision provided by the GPS. Example: '1.8'; Units: unitless; Entity described: event", + "format": "default", + "name": "gps:dop", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000115/2/", + "title": "GPS DOP", + "type": "number", + }, + { + "description": "The number of GPS satellites used to estimate the location. Example: '8'; Units: count; Entity described: event", + "format": "default", + "name": "gps:satellite-count", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000120/3/", + "title": "GPS satellite count", + "type": "integer", + }, + { + "description": "The time required to obtain the GPS location fix. Example: '36'; Units: seconds; Entity described: event", + "format": "default", + "name": "gps-time-to-fix", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000121/3/", + "title": "GPS time to fix", + "type": "number", + }, + { + "description": "The estimated ground speed provided by the sensor or calculated between consecutive locations. Example: '7.22'; Units: m/s; Entity described: event", + "format": "default", + "name": "ground-speed", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000124/2/", + "title": "ground speed", + "type": "number", + }, + { + "description": "The direction in which the tag is moving, in decimal degrees clockwise from north, as provided by the sensor or calculated between consecutive locations. Values range from 0-360: 0 = north, 90 = east, 180 = south, 270 = west. Example: '315.88'; Units: degrees clockwise from north; Entity described: event", + "format": "default", + "name": "heading", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000129/2/", + "title": "heading", + "type": "number", + }, + { + "description": "The estimated height of the tag above mean sea level, typically estimated by the tag. If altitudes are calculated as height above an ellipsoid, use 'height above ellipsoid'. Example: '34'; Units: meters; Entity described: event", + "format": "default", + "name": "height-above-msl", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000131/3/", + "title": "height above mean sea level", + "type": "number", + }, + { + "description": "Identifies events as outliers. Outliers have the value TRUE. Typically used to import a record of outliers that were identified by the data provider or owner with automated methods outside of Movebank. Information about how outliers were defined can be provided in 'outlier comments'. Units: none; Entity described: event", + "format": "default", + "name": "import-marked-outlier", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000133/3/", + "title": "import marked outlier", + "type": "boolean", + }, + { + "description": "An estimate of the horizontal error of the location including only numbers. (If the error estimates include non-numerical characters such as '>' use 'location error text'.) These values can be described using 'location error percentile' and 'location accuracy comments'. Example: '50'; Units: meters; Entity described: event", + "format": "default", + "name": "location-error-numerical", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000142/3/", + "title": "location error numerical", + "type": "number", + }, + { + "description": "Identifies events flagged manually as outliers, typically using the Event Editor in Movebank, and may also include outliers identified using other methods. Outliers have the value TRUE. Information about how outliers were defined can be provided in 'outlier comments'. Units: none; Entity described: event", + "format": "default", + "name": "manually-marked-outlier", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000156/3/", + "title": "manually marked outlier", + "type": "boolean", + }, + { + "description": "An estimate of the vertical error of the location. These values can be described using 'location error percentile' and 'location accuracy comments'. Example: '12'; Units: meters; Entity described: event", + "format": "default", + "name": "vertical-error-numerical", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000208/3/", + "title": "vertical error numerical", + "type": "number", + }, + { + "description": "The type of sensor with which data were collected. All sensors are associated with a tag id, and tags can contain multiple sensor types. Each event record in Movebank is assigned one sensor type. If values from multiple sensors are reported in a single event, the primary sensor is used. Values are chosen from a controlled list: acceleration = The sensor collects acceleration data; accessory-measurements = The sensor collects accessory measurements, such as battery voltage; acoustic-telemetry = The sensor transmits an acoustic signal that is detected by receivers to determine location; argos-doppler-shift = The sensor location is estimated by Argos using Doppler shift; barometer = The sensor records air or water pressure; bird-ring = The animal is identified by a band or ring that has a unique identifier; gps = The sensor uses GPS to determine location; gyroscope = The sensor records angular velocity; heart-rate = The sensor records or is used to calculate heart rate; magnetometer = The sensor records the magnetic field; natural-mark = The animal is identified by a unique natural marking; orientation = Quaternion components describing the orientation of the tag are derived from accelerometer and gyroscope measurements; proximity = The sensor identifies proximity to other tags; radio-transmitter = The sensor transmits a radio signal that is detected by receivers to determine location; sigfox-geolocation = The sensor location is determined by Sigfox using the received signal strength indicator; solar-geolocator = The sensor collects light levels, which are used to determine position (for processed locations); solar-geolocator-raw = The sensor collects light levels, which are used to determine position (for raw light-level measurements); solar-geolocator-twilight = The sensor collects light levels, which are used to determine position (for twilights calculated from light-level measurements). Format: controlled list; Entity described: event", + "format": "default", + "name": "sensor-type", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000170/6/", + "title": "sensor type", + "type": "string", + }, + { + "description": "This attribute has been merged with 'animal taxon'. The scientific name of the species on which the tag was deployed, as defined by the Integrated Taxonomic Information System (ITIS, www.itis.gov). If the species name can not be provided, this should be the lowest level taxonomic rank that can be determined and that is used in the ITIS taxonomy. Additional information can be provided using the term 'taxon detail'. Format: controlled list; Entity described: individual", + "format": "default", + "name": "individual-taxon-canonical-name", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000135/5/", + "title": "individual taxon canonical name", + "type": "string", + }, + { + "description": "This attribute has been merged with 'tag ID'. An identifier for the tag, provided by the data owner. Values are unique within the study. If the data owner does not provide a tag ID, an internal Movebank tag identifier may sometimes be shown. Example: '2342'; Units: none; Entity described: tag", + "format": "default", + "name": "tag-local-identifier", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000182/5/", + "title": "tag local identifier", + "type": "string", + }, + { + "description": "This attribute has been merged with 'animal ID'. An individual identifier for the animal, provided by the data owner. Values are unique within the study. If the data owner does not provide an Animal ID, an internal Movebank animal identifier is sometimes shown. Example: '91876A, Gary'; Units: none; Entity described: individual", + "format": "default", + "name": "individual-local-identifier", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000134/4/", + "title": "individual local identifier", + "type": "string", + }, + { + "description": "The name of the study in Movebank. Example: 'Coyotes, Kays and Bogan, Albany NY'; Units: none; Entity described: study", + "format": "default", + "name": "study-name", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000173/3/", + "title": "study name", + "type": "string", + }, + ], + "foreignKeys": [ + { + "fields": [ + "individual-local-identifier", + "tag-local-identifier", + ], + "reference": { "fields": [ - "individual-local-identifier", - "tag-local-identifier", + "animal-id", + "tag-id", ], - "reference": { - "fields": [ - "animal-id", - "tag-id", - ], - "resource": "reference-data", - }, + "resource": "reference-data", }, - ], - "primaryKey": "event-id", - }, + }, + ], + "primaryKey": [ + "event-id", + ], }, "zenodo:key": undefined, "zenodo:url": undefined, @@ -580,146 +578,146 @@ exports[`loadPackageFromZenodo > shoule merge datapackage.json if present 1`] = "profile": "tabular-data-resource", "schema": { "$schema": undefined, - "descriptor": { - "fields": [ - { - "description": "An identifier for the set of values associated with each event, i.e. sensor measurement. A unique event ID is assigned to every time-location or other time-measurement record in Movebank. If multiple measurements are included within a single row of a data file, they will share an event ID. If users import the same sensor measurement to Movebank multiple times, a separate event ID will be assigned to each. Example: '14328243575'; Units: none; Entity described: event", - "format": "default", - "name": "event-id", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000103/3/", - "title": "event ID", - "type": "integer", - }, - { - "description": "Determines whether an event is visible on the Movebank map. Allowed values are TRUE or FALSE. Values are calculated automatically, with TRUE indicating the event has not been flagged as an outlier by 'algorithm marked outlier', 'import marked outlier' or 'manually marked outlier', or that the user has overridden the results of these outlier attributes using 'manually marked valid' = TRUE. Units: none; Entity described: event", - "format": "default", - "name": "visible", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000209/3/", - "title": "visible", - "type": "boolean", - }, - { - "description": "The date and time corresponding to a sensor measurement or an estimate derived from sensor measurements. Example: '2008-08-14 18:31:00.000'; Format: yyyy-MM-dd HH:mm:ss.SSS; Units: UTC or GPS time; Entity described: event", - "format": "%Y-%m-%d %H:%M:%S.%f", - "name": "timestamp", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000200/2/", - "title": "timestamp", - "type": "datetime", - }, - { - "description": "Raw acceleration values provided by the tag for the X axis. Range and units may vary by provider, tag, and orientation of the sensor on the animal. Example: '0.556641'; Units: not defined; Entity described: event", - "format": "default", - "name": "acceleration-raw-x", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000002/2/", - "title": "acceleration raw x", - "type": "number", - }, - { - "description": "Raw acceleration values provided by the tag for the Y axis. Range and units may vary by provider, tag, and orientation of the sensor on the animal. Example: '0.09375'; Units: not defined; Entity described: event", - "format": "default", - "name": "acceleration-raw-y", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000003/2/", - "title": "acceleration raw y", - "type": "number", - }, - { - "description": "Raw acceleration values provided by the tag for the Z axis. Range and units may vary by provider, tag, and orientation of the sensor on the animal. Example: '-0.84375'; Units: not defined; Entity described: event", - "format": "default", - "name": "acceleration-raw-z", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000004/2/", - "title": "acceleration raw z", - "type": "number", - }, - { - "description": "The date and time when the sampling interval or burst began. Example: '2011-01-03 13:45:00.000'; Format: yyyy-MM-dd HH:mm:ss.SSS; Units: UTC or GPS time; Entity described: event", - "format": "%Y-%m-%d %H:%M:%S.%f", - "name": "start-timestamp", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000171/2/", - "title": "start timestamp", - "type": "datetime", - }, - { - "description": "Tilt provided by the accelerometer for the X axis. Example: '0'; Units: g forces (1 g = 9.8 m s^-2); Entity described: event", - "format": "default", - "name": "tilt-x", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000197/2/", - "title": "tilt x", - "type": "number", - }, - { - "description": "Tilt provided by the accelerometer for the Y axis. Example: '0'; Units: g forces (1 g = 9.8 m s^-2); Entity described: event", - "format": "default", - "name": "tilt-y", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000198/2/", - "title": "tilt y", - "type": "number", - }, - { - "description": "Tilt provided by the accelerometer for the Z axis. Example: '1'; Units: g forces (1 g = 9.8 m s^-2); Entity described: event", - "format": "default", - "name": "tilt-z", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000199/2/", - "title": "tilt z", - "type": "number", - }, - { - "description": "The type of sensor with which data were collected. All sensors are associated with a tag id, and tags can contain multiple sensor types. Each event record in Movebank is assigned one sensor type. If values from multiple sensors are reported in a single event, the primary sensor is used. Values are chosen from a controlled list: acceleration = The sensor collects acceleration data; accessory-measurements = The sensor collects accessory measurements, such as battery voltage; acoustic-telemetry = The sensor transmits an acoustic signal that is detected by receivers to determine location; argos-doppler-shift = The sensor location is estimated by Argos using Doppler shift; barometer = The sensor records air or water pressure; bird-ring = The animal is identified by a band or ring that has a unique identifier; gps = The sensor uses GPS to determine location; gyroscope = The sensor records angular velocity; heart-rate = The sensor records or is used to calculate heart rate; magnetometer = The sensor records the magnetic field; natural-mark = The animal is identified by a unique natural marking; orientation = Quaternion components describing the orientation of the tag are derived from accelerometer and gyroscope measurements; proximity = The sensor identifies proximity to other tags; radio-transmitter = The sensor transmits a radio signal that is detected by receivers to determine location; sigfox-geolocation = The sensor location is determined by Sigfox using the received signal strength indicator; solar-geolocator = The sensor collects light levels, which are used to determine position (for processed locations); solar-geolocator-raw = The sensor collects light levels, which are used to determine position (for raw light-level measurements); solar-geolocator-twilight = The sensor collects light levels, which are used to determine position (for twilights calculated from light-level measurements). Format: controlled list; Entity described: event", - "format": "default", - "name": "sensor-type", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000170/6/", - "title": "sensor type", - "type": "string", - }, - { - "description": "This attribute has been merged with 'animal taxon'. The scientific name of the species on which the tag was deployed, as defined by the Integrated Taxonomic Information System (ITIS, www.itis.gov). If the species name can not be provided, this should be the lowest level taxonomic rank that can be determined and that is used in the ITIS taxonomy. Additional information can be provided using the term 'taxon detail'. Format: controlled list; Entity described: individual", - "format": "default", - "name": "individual-taxon-canonical-name", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000135/5/", - "title": "individual taxon canonical name", - "type": "string", - }, - { - "description": "This attribute has been merged with 'tag ID'. An identifier for the tag, provided by the data owner. Values are unique within the study. If the data owner does not provide a tag ID, an internal Movebank tag identifier may sometimes be shown. Example: '2342'; Units: none; Entity described: tag", - "format": "default", - "name": "tag-local-identifier", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000182/5/", - "title": "tag local identifier", - "type": "string", - }, - { - "description": "This attribute has been merged with 'animal ID'. An individual identifier for the animal, provided by the data owner. Values are unique within the study. If the data owner does not provide an Animal ID, an internal Movebank animal identifier is sometimes shown. Example: '91876A, Gary'; Units: none; Entity described: individual", - "format": "default", - "name": "individual-local-identifier", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000134/4/", - "title": "individual local identifier", - "type": "string", - }, - { - "description": "The name of the study in Movebank. Example: 'Coyotes, Kays and Bogan, Albany NY'; Units: none; Entity described: study", - "format": "default", - "name": "study-name", - "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000173/3/", - "title": "study name", - "type": "string", - }, - ], - "foreignKeys": [ - { + "fields": [ + { + "description": "An identifier for the set of values associated with each event, i.e. sensor measurement. A unique event ID is assigned to every time-location or other time-measurement record in Movebank. If multiple measurements are included within a single row of a data file, they will share an event ID. If users import the same sensor measurement to Movebank multiple times, a separate event ID will be assigned to each. Example: '14328243575'; Units: none; Entity described: event", + "format": "default", + "name": "event-id", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000103/3/", + "title": "event ID", + "type": "integer", + }, + { + "description": "Determines whether an event is visible on the Movebank map. Allowed values are TRUE or FALSE. Values are calculated automatically, with TRUE indicating the event has not been flagged as an outlier by 'algorithm marked outlier', 'import marked outlier' or 'manually marked outlier', or that the user has overridden the results of these outlier attributes using 'manually marked valid' = TRUE. Units: none; Entity described: event", + "format": "default", + "name": "visible", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000209/3/", + "title": "visible", + "type": "boolean", + }, + { + "description": "The date and time corresponding to a sensor measurement or an estimate derived from sensor measurements. Example: '2008-08-14 18:31:00.000'; Format: yyyy-MM-dd HH:mm:ss.SSS; Units: UTC or GPS time; Entity described: event", + "format": "%Y-%m-%d %H:%M:%S.%f", + "name": "timestamp", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000200/2/", + "title": "timestamp", + "type": "datetime", + }, + { + "description": "Raw acceleration values provided by the tag for the X axis. Range and units may vary by provider, tag, and orientation of the sensor on the animal. Example: '0.556641'; Units: not defined; Entity described: event", + "format": "default", + "name": "acceleration-raw-x", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000002/2/", + "title": "acceleration raw x", + "type": "number", + }, + { + "description": "Raw acceleration values provided by the tag for the Y axis. Range and units may vary by provider, tag, and orientation of the sensor on the animal. Example: '0.09375'; Units: not defined; Entity described: event", + "format": "default", + "name": "acceleration-raw-y", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000003/2/", + "title": "acceleration raw y", + "type": "number", + }, + { + "description": "Raw acceleration values provided by the tag for the Z axis. Range and units may vary by provider, tag, and orientation of the sensor on the animal. Example: '-0.84375'; Units: not defined; Entity described: event", + "format": "default", + "name": "acceleration-raw-z", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000004/2/", + "title": "acceleration raw z", + "type": "number", + }, + { + "description": "The date and time when the sampling interval or burst began. Example: '2011-01-03 13:45:00.000'; Format: yyyy-MM-dd HH:mm:ss.SSS; Units: UTC or GPS time; Entity described: event", + "format": "%Y-%m-%d %H:%M:%S.%f", + "name": "start-timestamp", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000171/2/", + "title": "start timestamp", + "type": "datetime", + }, + { + "description": "Tilt provided by the accelerometer for the X axis. Example: '0'; Units: g forces (1 g = 9.8 m s^-2); Entity described: event", + "format": "default", + "name": "tilt-x", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000197/2/", + "title": "tilt x", + "type": "number", + }, + { + "description": "Tilt provided by the accelerometer for the Y axis. Example: '0'; Units: g forces (1 g = 9.8 m s^-2); Entity described: event", + "format": "default", + "name": "tilt-y", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000198/2/", + "title": "tilt y", + "type": "number", + }, + { + "description": "Tilt provided by the accelerometer for the Z axis. Example: '1'; Units: g forces (1 g = 9.8 m s^-2); Entity described: event", + "format": "default", + "name": "tilt-z", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000199/2/", + "title": "tilt z", + "type": "number", + }, + { + "description": "The type of sensor with which data were collected. All sensors are associated with a tag id, and tags can contain multiple sensor types. Each event record in Movebank is assigned one sensor type. If values from multiple sensors are reported in a single event, the primary sensor is used. Values are chosen from a controlled list: acceleration = The sensor collects acceleration data; accessory-measurements = The sensor collects accessory measurements, such as battery voltage; acoustic-telemetry = The sensor transmits an acoustic signal that is detected by receivers to determine location; argos-doppler-shift = The sensor location is estimated by Argos using Doppler shift; barometer = The sensor records air or water pressure; bird-ring = The animal is identified by a band or ring that has a unique identifier; gps = The sensor uses GPS to determine location; gyroscope = The sensor records angular velocity; heart-rate = The sensor records or is used to calculate heart rate; magnetometer = The sensor records the magnetic field; natural-mark = The animal is identified by a unique natural marking; orientation = Quaternion components describing the orientation of the tag are derived from accelerometer and gyroscope measurements; proximity = The sensor identifies proximity to other tags; radio-transmitter = The sensor transmits a radio signal that is detected by receivers to determine location; sigfox-geolocation = The sensor location is determined by Sigfox using the received signal strength indicator; solar-geolocator = The sensor collects light levels, which are used to determine position (for processed locations); solar-geolocator-raw = The sensor collects light levels, which are used to determine position (for raw light-level measurements); solar-geolocator-twilight = The sensor collects light levels, which are used to determine position (for twilights calculated from light-level measurements). Format: controlled list; Entity described: event", + "format": "default", + "name": "sensor-type", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000170/6/", + "title": "sensor type", + "type": "string", + }, + { + "description": "This attribute has been merged with 'animal taxon'. The scientific name of the species on which the tag was deployed, as defined by the Integrated Taxonomic Information System (ITIS, www.itis.gov). If the species name can not be provided, this should be the lowest level taxonomic rank that can be determined and that is used in the ITIS taxonomy. Additional information can be provided using the term 'taxon detail'. Format: controlled list; Entity described: individual", + "format": "default", + "name": "individual-taxon-canonical-name", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000135/5/", + "title": "individual taxon canonical name", + "type": "string", + }, + { + "description": "This attribute has been merged with 'tag ID'. An identifier for the tag, provided by the data owner. Values are unique within the study. If the data owner does not provide a tag ID, an internal Movebank tag identifier may sometimes be shown. Example: '2342'; Units: none; Entity described: tag", + "format": "default", + "name": "tag-local-identifier", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000182/5/", + "title": "tag local identifier", + "type": "string", + }, + { + "description": "This attribute has been merged with 'animal ID'. An individual identifier for the animal, provided by the data owner. Values are unique within the study. If the data owner does not provide an Animal ID, an internal Movebank animal identifier is sometimes shown. Example: '91876A, Gary'; Units: none; Entity described: individual", + "format": "default", + "name": "individual-local-identifier", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000134/4/", + "title": "individual local identifier", + "type": "string", + }, + { + "description": "The name of the study in Movebank. Example: 'Coyotes, Kays and Bogan, Albany NY'; Units: none; Entity described: study", + "format": "default", + "name": "study-name", + "skos:exactMatch": "http://vocab.nerc.ac.uk/collection/MVB/current/MVB000173/3/", + "title": "study name", + "type": "string", + }, + ], + "foreignKeys": [ + { + "fields": [ + "individual-local-identifier", + "tag-local-identifier", + ], + "reference": { "fields": [ - "individual-local-identifier", - "tag-local-identifier", + "animal-id", + "tag-id", ], - "reference": { - "fields": [ - "animal-id", - "tag-id", - ], - "resource": "reference-data", - }, + "resource": "reference-data", }, - ], - "primaryKey": "event-id", - }, + }, + ], + "primaryKey": [ + "event-id", + ], }, "zenodo:key": undefined, "zenodo:url": undefined, diff --git a/zenodo/package/fixtures/generated/should-load-a-package_2675098929/recording.har b/zenodo/package/fixtures/generated/loadPackageFromZenodo-should-load-a-package_3167400519/recording.har similarity index 91% rename from zenodo/package/fixtures/generated/should-load-a-package_2675098929/recording.har rename to zenodo/package/fixtures/generated/loadPackageFromZenodo-should-load-a-package_3167400519/recording.har index f8c4da0a..4f519237 100644 --- a/zenodo/package/fixtures/generated/should-load-a-package_2675098929/recording.har +++ b/zenodo/package/fixtures/generated/loadPackageFromZenodo-should-load-a-package_3167400519/recording.har @@ -1,6 +1,6 @@ { "log": { - "_recordingName": "should load a package", + "_recordingName": "loadPackageFromZenodo-should load a package", "creator": { "comment": "persister:fs", "name": "Polly.JS", @@ -26,7 +26,7 @@ "content": { "mimeType": "application/json", "size": 3794, - "text": "{\"created\": \"2025-05-27T10:20:07.936985+00:00\", \"modified\": \"2025-05-27T10:20:08.174083+00:00\", \"id\": 15525711, \"conceptrecid\": \"15525710\", \"doi\": \"10.5281/zenodo.15525711\", \"conceptdoi\": \"10.5281/zenodo.15525710\", \"doi_url\": \"https://doi.org/10.5281/zenodo.15525711\", \"metadata\": {\"title\": \"PM10 Concentration in Japan\", \"doi\": \"10.5281/zenodo.15525711\", \"publication_date\": \"2025-05-27\", \"description\": \"

A brief project to extract PM 10 concentration from Japan. Data set has been created using the OpenAQ data through a python script

\", \"access_right\": \"open\", \"creators\": [{\"name\": \"Sukhija, Vinay Jagdish\", \"affiliation\": null, \"orcid\": \"0000-0003-2155-6940\"}], \"keywords\": [\"PM10 concentrations\", \"Air Quality\", \"Japan\", \"OpenAQ\"], \"custom\": {\"code:programmingLanguage\": [{\"id\": \"python\", \"title\": {\"en\": \"Python\"}}]}, \"resource_type\": {\"title\": \"Dataset\", \"type\": \"dataset\"}, \"meeting\": {\"title\": \"Open Data and Open Science Conference\", \"dates\": \"27 May 2025\", \"place\": \"Padova\"}, \"license\": {\"id\": \"cc-by-4.0\"}, \"relations\": {\"version\": [{\"index\": 0, \"is_last\": true, \"parent\": {\"pid_type\": \"recid\", \"pid_value\": \"15525710\"}}]}}, \"title\": \"PM10 Concentration in Japan\", \"links\": {\"self\": \"https://zenodo.org/api/records/15525711\", \"self_html\": \"https://zenodo.org/records/15525711\", \"preview_html\": \"https://zenodo.org/records/15525711?preview=1\", \"doi\": \"https://doi.org/10.5281/zenodo.15525711\", \"self_doi\": \"https://doi.org/10.5281/zenodo.15525711\", \"self_doi_html\": \"https://zenodo.org/doi/10.5281/zenodo.15525711\", \"reserve_doi\": \"https://zenodo.org/api/records/15525711/draft/pids/doi\", \"parent\": \"https://zenodo.org/api/records/15525710\", \"parent_html\": \"https://zenodo.org/records/15525710\", \"parent_doi\": \"https://doi.org/10.5281/zenodo.15525710\", \"parent_doi_html\": \"https://zenodo.org/doi/10.5281/zenodo.15525710\", \"self_iiif_manifest\": \"https://zenodo.org/api/iiif/record:15525711/manifest\", \"self_iiif_sequence\": \"https://zenodo.org/api/iiif/record:15525711/sequence/default\", \"files\": \"https://zenodo.org/api/records/15525711/files\", \"media_files\": \"https://zenodo.org/api/records/15525711/media-files\", \"archive\": \"https://zenodo.org/api/records/15525711/files-archive\", \"archive_media\": \"https://zenodo.org/api/records/15525711/media-files-archive\", \"latest\": \"https://zenodo.org/api/records/15525711/versions/latest\", \"latest_html\": \"https://zenodo.org/records/15525711/latest\", \"versions\": \"https://zenodo.org/api/records/15525711/versions\", \"draft\": \"https://zenodo.org/api/records/15525711/draft\", \"access_links\": \"https://zenodo.org/api/records/15525711/access/links\", \"access_grants\": \"https://zenodo.org/api/records/15525711/access/grants\", \"access_users\": \"https://zenodo.org/api/records/15525711/access/users\", \"access_request\": \"https://zenodo.org/api/records/15525711/access/request\", \"access\": \"https://zenodo.org/api/records/15525711/access\", \"communities\": \"https://zenodo.org/api/records/15525711/communities\", \"communities-suggestions\": \"https://zenodo.org/api/records/15525711/communities-suggestions\", \"requests\": \"https://zenodo.org/api/records/15525711/requests\"}, \"updated\": \"2025-05-27T10:20:08.174083+00:00\", \"recid\": \"15525711\", \"revision\": 4, \"files\": [{\"id\": \"c50a6efe-4946-4054-a3bb-797a35da03d0\", \"key\": \"openaq_measurements_PM10_Japan_20250527_095520.csv\", \"size\": 272, \"checksum\": \"md5:5ac1b92a57ec809c546ea90334c845c9\", \"links\": {\"self\": \"https://zenodo.org/api/records/15525711/files/openaq_measurements_PM10_Japan_20250527_095520.csv/content\"}}], \"swh\": {}, \"owners\": [{\"id\": \"1328821\"}], \"status\": \"published\", \"stats\": {\"downloads\": 0, \"unique_downloads\": 0, \"views\": 0, \"unique_views\": 0, \"version_downloads\": 0, \"version_unique_downloads\": 0, \"version_unique_views\": 0, \"version_views\": 0}, \"state\": \"done\", \"submitted\": true}" + "text": "{\"created\": \"2025-05-27T10:20:07.936985+00:00\", \"modified\": \"2025-05-27T10:20:08.174083+00:00\", \"id\": 15525711, \"conceptrecid\": \"15525710\", \"doi\": \"10.5281/zenodo.15525711\", \"conceptdoi\": \"10.5281/zenodo.15525710\", \"doi_url\": \"https://doi.org/10.5281/zenodo.15525711\", \"metadata\": {\"title\": \"PM10 Concentration in Japan\", \"doi\": \"10.5281/zenodo.15525711\", \"publication_date\": \"2025-05-27\", \"description\": \"

A brief project to extract PM 10 concentration from Japan. Data set has been created using the OpenAQ data through a python script

\", \"access_right\": \"open\", \"creators\": [{\"name\": \"Sukhija, Vinay Jagdish\", \"affiliation\": null, \"orcid\": \"0000-0003-2155-6940\"}], \"keywords\": [\"PM10 concentrations\", \"Air Quality\", \"Japan\", \"OpenAQ\"], \"custom\": {\"code:programmingLanguage\": [{\"id\": \"python\", \"title\": {\"en\": \"Python\"}}]}, \"resource_type\": {\"title\": \"Dataset\", \"type\": \"dataset\"}, \"meeting\": {\"title\": \"Open Data and Open Science Conference\", \"dates\": \"27 May 2025\", \"place\": \"Padova\"}, \"license\": {\"id\": \"cc-by-4.0\"}, \"relations\": {\"version\": [{\"index\": 0, \"is_last\": true, \"parent\": {\"pid_type\": \"recid\", \"pid_value\": \"15525710\"}}]}}, \"title\": \"PM10 Concentration in Japan\", \"links\": {\"self\": \"https://zenodo.org/api/records/15525711\", \"self_html\": \"https://zenodo.org/records/15525711\", \"preview_html\": \"https://zenodo.org/records/15525711?preview=1\", \"doi\": \"https://doi.org/10.5281/zenodo.15525711\", \"self_doi\": \"https://doi.org/10.5281/zenodo.15525711\", \"self_doi_html\": \"https://zenodo.org/doi/10.5281/zenodo.15525711\", \"reserve_doi\": \"https://zenodo.org/api/records/15525711/draft/pids/doi\", \"parent\": \"https://zenodo.org/api/records/15525710\", \"parent_html\": \"https://zenodo.org/records/15525710\", \"parent_doi\": \"https://doi.org/10.5281/zenodo.15525710\", \"parent_doi_html\": \"https://zenodo.org/doi/10.5281/zenodo.15525710\", \"self_iiif_manifest\": \"https://zenodo.org/api/iiif/record:15525711/manifest\", \"self_iiif_sequence\": \"https://zenodo.org/api/iiif/record:15525711/sequence/default\", \"files\": \"https://zenodo.org/api/records/15525711/files\", \"media_files\": \"https://zenodo.org/api/records/15525711/media-files\", \"archive\": \"https://zenodo.org/api/records/15525711/files-archive\", \"archive_media\": \"https://zenodo.org/api/records/15525711/media-files-archive\", \"latest\": \"https://zenodo.org/api/records/15525711/versions/latest\", \"latest_html\": \"https://zenodo.org/records/15525711/latest\", \"versions\": \"https://zenodo.org/api/records/15525711/versions\", \"draft\": \"https://zenodo.org/api/records/15525711/draft\", \"access_links\": \"https://zenodo.org/api/records/15525711/access/links\", \"access_grants\": \"https://zenodo.org/api/records/15525711/access/grants\", \"access_users\": \"https://zenodo.org/api/records/15525711/access/users\", \"access_request\": \"https://zenodo.org/api/records/15525711/access/request\", \"access\": \"https://zenodo.org/api/records/15525711/access\", \"communities\": \"https://zenodo.org/api/records/15525711/communities\", \"communities-suggestions\": \"https://zenodo.org/api/records/15525711/communities-suggestions\", \"requests\": \"https://zenodo.org/api/records/15525711/requests\"}, \"updated\": \"2025-05-27T10:20:08.174083+00:00\", \"recid\": \"15525711\", \"revision\": 4, \"files\": [{\"id\": \"c50a6efe-4946-4054-a3bb-797a35da03d0\", \"key\": \"openaq_measurements_PM10_Japan_20250527_095520.csv\", \"size\": 272, \"checksum\": \"md5:5ac1b92a57ec809c546ea90334c845c9\", \"links\": {\"self\": \"https://zenodo.org/api/records/15525711/files/openaq_measurements_PM10_Japan_20250527_095520.csv/content\"}}], \"swh\": {}, \"owners\": [{\"id\": \"1328821\"}], \"status\": \"published\", \"stats\": {\"downloads\": 4, \"unique_downloads\": 4, \"views\": 6, \"unique_views\": 6, \"version_downloads\": 4, \"version_unique_downloads\": 4, \"version_unique_views\": 6, \"version_views\": 6}, \"state\": \"done\", \"submitted\": true}" }, "cookies": [ { @@ -35,7 +35,7 @@ "path": "/", "sameSite": "None", "secure": true, - "value": "1150a9296538db69f8d2c95afd8c3910" + "value": "ee05b1c4fc826a86b832f3008890c77d" } ], "headers": [ @@ -65,7 +65,7 @@ }, { "name": "date", - "value": "Tue, 27 May 2025 10:35:44 GMT" + "value": "Thu, 07 Aug 2025 07:49:25 GMT" }, { "name": "etag", @@ -85,7 +85,7 @@ }, { "name": "retry-after", - "value": "59" + "value": "60" }, { "name": "server", @@ -93,7 +93,7 @@ }, { "name": "set-cookie", - "value": "5569e5a730cade8ff2b54f1e815f3670=1150a9296538db69f8d2c95afd8c3910; path=/; HttpOnly; Secure; SameSite=None" + "value": "5569e5a730cade8ff2b54f1e815f3670=ee05b1c4fc826a86b832f3008890c77d; path=/; HttpOnly; Secure; SameSite=None" }, { "name": "strict-transport-security", @@ -125,11 +125,11 @@ }, { "name": "x-ratelimit-reset", - "value": "1748342204" + "value": "1754553026" }, { "name": "x-request-id", - "value": "0438503d83b8bf34f5ea707caee6734f" + "value": "14f848af2c654cb8534b2f735f0a5686" }, { "name": "x-xss-protection", @@ -142,8 +142,8 @@ "status": 200, "statusText": "OK" }, - "startedDateTime": "2025-05-27T10:35:42.687Z", - "time": 597, + "startedDateTime": "2025-08-07T07:49:25.328Z", + "time": 560, "timings": { "blocked": -1, "connect": -1, @@ -151,7 +151,7 @@ "receive": 0, "send": 0, "ssl": -1, - "wait": 597 + "wait": 560 } } ], diff --git a/zenodo/package/fixtures/generated/shoule-merge-datapackage-json-if-present_2284251141/recording.har b/zenodo/package/fixtures/generated/loadPackageFromZenodo-shoule-merge-datapackage-json-if-present_2160001855/recording.har similarity index 91% rename from zenodo/package/fixtures/generated/shoule-merge-datapackage-json-if-present_2284251141/recording.har rename to zenodo/package/fixtures/generated/loadPackageFromZenodo-shoule-merge-datapackage-json-if-present_2160001855/recording.har index a2d247db..a2386e7d 100644 --- a/zenodo/package/fixtures/generated/shoule-merge-datapackage-json-if-present_2284251141/recording.har +++ b/zenodo/package/fixtures/generated/loadPackageFromZenodo-shoule-merge-datapackage-json-if-present_2160001855/recording.har @@ -1,6 +1,6 @@ { "log": { - "_recordingName": "shoule merge datapackage.json if present", + "_recordingName": "loadPackageFromZenodo-shoule merge datapackage.json if present", "creator": { "comment": "persister:fs", "name": "Polly.JS", @@ -22,11 +22,11 @@ "url": "https://zenodo.org/api/records/10053903" }, "response": { - "bodySize": 10436, + "bodySize": 10502, "content": { "mimeType": "application/json", - "size": 10436, - "text": "{\"created\": \"2023-10-30T11:31:16.569518+00:00\", \"modified\": \"2025-05-15T09:13:47.716113+00:00\", \"id\": 10053903, \"conceptrecid\": \"5653310\", \"doi\": \"10.5281/zenodo.10053903\", \"conceptdoi\": \"10.5281/zenodo.5653310\", \"doi_url\": \"https://doi.org/10.5281/zenodo.10053903\", \"metadata\": {\"title\": \"O_ASSEN - Eurasian oystercatchers (Haematopus ostralegus, Haematopodidae) breeding in Assen (the Netherlands)\", \"doi\": \"10.5281/zenodo.10053903\", \"publication_date\": \"2023-10-30\", \"description\": \"

O_ASSEN - Eurasian oystercatchers (Haematopus ostralegus, Haematopodidae) breeding in Assen (the Netherlands) is a bird tracking dataset published by the Vogelwerkgroep Assen, Netherlands Institute of Ecology (NIOO-KNAW), Sovon, Radboud University, the University of Amsterdam and the Research Institute for Nature and Forest (INBO). It contains animal tracking data collected for the study O_ASSEN using trackers developed by the University of Amsterdam Bird Tracking System (UvA-BiTS, http://www.uva-bits.nl). The study was operational from 2018 to 2019. In total 6 individuals of Eurasian oystercatchers (Haematopus ostralegus) have been tagged as a breeding bird in the city of Assen (the Netherlands), mainly to study space use of oystercatchers breeding in urban areas. Data are uploaded from the UvA-BiTS database to Movebank and from there archived on Zenodo (see https://github.com/inbo/bird-tracking). No new data are expected.

\\n

See van der Kolk et al. (2022, https://doi.org/10.3897/zookeys.1123.90623) for a more detailed description of this dataset.

\\n

Files

\\n

Data in this package are exported from Movebank study 1605797471. Fields in the data follow the Movebank Attribute Dictionary and are described in datapackage.json. Files are structured as a Frictionless Data Package. You can access all data in R via https://zenodo.org/records/10053903/files/datapackage.json using frictionless.

\\n
    \\n
  • datapackage.json: technical description of the data files.
  • \\n
  • O_ASSEN-reference-data.csv: reference data about the animals, tags and deployments.
  • \\n
  • O_ASSEN-gps-yyyy.csv.gz: GPS data recorded by the tags, grouped by year.
  • \\n
  • O_ASSEN-acceleration-yyyy.csv.gz: acceleration data recorded by the tags, grouped by year.
  • \\n
\\n

Acknowledgements

\\n

These data were collected by Bert Dijkstra and Rinus Dillerop from Vogelwerkgroep Assen, in collaboration with the Netherlands Institute of Ecology (NIOO-KNAW), Sovon, Radboud University and the University of Amsterdam (UvA). Funding was provided by the Prins Bernard Cultuurfonds Drenthe, municipality of Assen, IJsvogelfonds (from Birdlife Netherlands and Nationale Postcodeloterij) and the Waterleiding Maatschappij Drenthe. The dataset was published with funding from Stichting NLBIF - Netherlands Biodiversity Information Facility.

\", \"access_right\": \"open\", \"creators\": [{\"name\": \"Dijkstra, Bert\", \"affiliation\": \"Vogelwerkgroep Assen\"}, {\"name\": \"Dillerop, Rinus\", \"affiliation\": \"Vogelwerkgroep Assen\"}, {\"name\": \"Oosterbeek, Kees\", \"affiliation\": \"Dutch Centre for Field Ornithology\"}, {\"name\": \"Bouten, Willem\", \"affiliation\": \"University of Amsterdam\", \"orcid\": \"0000-0002-5250-8872\"}, {\"name\": \"Desmet, Peter\", \"affiliation\": \"Research Institute for Nature and Forest\", \"orcid\": \"0000-0002-8442-8025\"}, {\"name\": \"van der Kolk, Henk-Jan\", \"affiliation\": \"Dutch Bryological and Lichenological Society\", \"orcid\": \"0000-0002-8023-379X\"}, {\"name\": \"Ens, Bruno J.\", \"affiliation\": \"Dutch Centre for Field Ornithology\", \"orcid\": \"0000-0002-4659-4807\"}], \"contributors\": [{\"name\": \"Desmet, Peter\", \"affiliation\": \"Research Institute for Nature and Forest\", \"type\": \"DataCurator\", \"orcid\": \"0000-0002-8442-8025\"}], \"keywords\": [\"animal movement\", \"animal tracking\", \"gps tracking\", \"accelerometer\", \"altitude\", \"temperature\", \"biologging\", \"birds\", \"UvA-BiTS\", \"Movebank\", \"frictionlessdata\"], \"related_identifiers\": [{\"identifier\": \"https://www.movebank.org/cms/webapp?gwt_fragment=page=studies,path=study1605797471\", \"relation\": \"isDerivedFrom\", \"resource_type\": \"dataset\", \"scheme\": \"url\"}, {\"identifier\": \"https://natuurtijdschriften.nl/pub/717840/DV2018032001001005.pdf\", \"relation\": \"isSourceOf\", \"resource_type\": \"publication-article\", \"scheme\": \"url\"}, {\"identifier\": \"https://natuurtijdschriften.nl/pub/1018631/DV2019032001001005.pdf\", \"relation\": \"isSourceOf\", \"resource_type\": \"publication-article\", \"scheme\": \"url\"}, {\"identifier\": \"https://www.gbif.org/dataset/226421f2-1d29-4950-901c-aba9d0e8f2bc\", \"relation\": \"isSourceOf\", \"resource_type\": \"dataset\", \"scheme\": \"url\"}, {\"identifier\": \"https://obis.org/dataset/550b4cc1-c40d-4070-a0cb-26e010eca9d4\", \"relation\": \"isSourceOf\", \"resource_type\": \"dataset\", \"scheme\": \"url\"}, {\"identifier\": \"10.3897/zookeys.1123.90623\", \"relation\": \"isDescribedBy\", \"resource_type\": \"publication-article\", \"scheme\": \"doi\"}, {\"identifier\": \"https://inbo.github.io/movepub/\", \"relation\": \"isCompiledBy\", \"resource_type\": \"software\", \"scheme\": \"url\"}], \"language\": \"eng\", \"resource_type\": {\"title\": \"Dataset\", \"type\": \"dataset\"}, \"license\": {\"id\": \"cc-zero\"}, \"grants\": [{\"code\": \"NLBIF\", \"internal_id\": \"0566bfb96::NLBIF\", \"funder\": {\"name\": \"Naturalis Biodiversity Center\"}, \"title\": \"Netherlands Biodiversity Information Facility\"}], \"communities\": [{\"id\": \"inbo\"}, {\"id\": \"netherlandsbiodiversityinformationfacility\"}, {\"id\": \"oscibio\"}], \"relations\": {\"version\": [{\"index\": 2, \"is_last\": true, \"parent\": {\"pid_type\": \"recid\", \"pid_value\": \"5653310\"}}]}, \"notes\": \"

This version adds alt-project-id to the reference-data and references the latest Movebank Attribute Dictionary.

\"}, \"title\": \"O_ASSEN - Eurasian oystercatchers (Haematopus ostralegus, Haematopodidae) breeding in Assen (the Netherlands)\", \"links\": {\"self\": \"https://zenodo.org/api/records/10053903\", \"self_html\": \"https://zenodo.org/records/10053903\", \"preview_html\": \"https://zenodo.org/records/10053903?preview=1\", \"doi\": \"https://doi.org/10.5281/zenodo.10053903\", \"self_doi\": \"https://doi.org/10.5281/zenodo.10053903\", \"self_doi_html\": \"https://zenodo.org/doi/10.5281/zenodo.10053903\", \"reserve_doi\": \"https://zenodo.org/api/records/10053903/draft/pids/doi\", \"parent\": \"https://zenodo.org/api/records/5653310\", \"parent_html\": \"https://zenodo.org/records/5653310\", \"parent_doi\": \"https://doi.org/10.5281/zenodo.5653310\", \"parent_doi_html\": \"https://zenodo.org/doi/10.5281/zenodo.5653310\", \"self_iiif_manifest\": \"https://zenodo.org/api/iiif/record:10053903/manifest\", \"self_iiif_sequence\": \"https://zenodo.org/api/iiif/record:10053903/sequence/default\", \"files\": \"https://zenodo.org/api/records/10053903/files\", \"media_files\": \"https://zenodo.org/api/records/10053903/media-files\", \"archive\": \"https://zenodo.org/api/records/10053903/files-archive\", \"archive_media\": \"https://zenodo.org/api/records/10053903/media-files-archive\", \"latest\": \"https://zenodo.org/api/records/10053903/versions/latest\", \"latest_html\": \"https://zenodo.org/records/10053903/latest\", \"versions\": \"https://zenodo.org/api/records/10053903/versions\", \"draft\": \"https://zenodo.org/api/records/10053903/draft\", \"access_links\": \"https://zenodo.org/api/records/10053903/access/links\", \"access_grants\": \"https://zenodo.org/api/records/10053903/access/grants\", \"access_users\": \"https://zenodo.org/api/records/10053903/access/users\", \"access_request\": \"https://zenodo.org/api/records/10053903/access/request\", \"access\": \"https://zenodo.org/api/records/10053903/access\", \"communities\": \"https://zenodo.org/api/records/10053903/communities\", \"communities-suggestions\": \"https://zenodo.org/api/records/10053903/communities-suggestions\", \"requests\": \"https://zenodo.org/api/records/10053903/requests\"}, \"updated\": \"2025-05-15T09:13:47.716113+00:00\", \"recid\": \"10053903\", \"revision\": 16, \"files\": [{\"id\": \"5ffb4935-0a78-4fd5-af2a-f0f5113ca7c0\", \"key\": \"datapackage.json\", \"size\": 42936, \"checksum\": \"md5:5ea86b7a222ac843e3833a2e50a2056b\", \"links\": {\"self\": \"https://zenodo.org/api/records/10053903/files/datapackage.json/content\"}}, {\"id\": \"f09bbed1-50e3-46b3-a1d9-10e8adeec337\", \"key\": \"O_ASSEN-acceleration-2018.csv.gz\", \"size\": 4067780, \"checksum\": \"md5:40b771d9bd53ee5cfae0266209364d9c\", \"links\": {\"self\": \"https://zenodo.org/api/records/10053903/files/O_ASSEN-acceleration-2018.csv.gz/content\"}}, {\"id\": \"73a7a2a5-cdfc-48a7-be65-641144ef9c38\", \"key\": \"O_ASSEN-acceleration-2019.csv.gz\", \"size\": 3696729, \"checksum\": \"md5:9d2cbbaece00ef8cf8b4fff87cf07079\", \"links\": {\"self\": \"https://zenodo.org/api/records/10053903/files/O_ASSEN-acceleration-2019.csv.gz/content\"}}, {\"id\": \"93e83695-a619-4f09-aa93-edb2fadcd586\", \"key\": \"O_ASSEN-gps-2018.csv.gz\", \"size\": 751448, \"checksum\": \"md5:f5e041ea66ebe8708a46fe57f383f549\", \"links\": {\"self\": \"https://zenodo.org/api/records/10053903/files/O_ASSEN-gps-2018.csv.gz/content\"}}, {\"id\": \"e64508be-1860-415f-bbbd-fc4353f33278\", \"key\": \"O_ASSEN-gps-2019.csv.gz\", \"size\": 263439, \"checksum\": \"md5:cec4550a769d4f053e92565b44d0409c\", \"links\": {\"self\": \"https://zenodo.org/api/records/10053903/files/O_ASSEN-gps-2019.csv.gz/content\"}}, {\"id\": \"05581f20-937c-4180-824c-c3068b641d34\", \"key\": \"O_ASSEN-reference-data.csv\", \"size\": 2082, \"checksum\": \"md5:5a5da155f404d5a3b4e50c350ad089d1\", \"links\": {\"self\": \"https://zenodo.org/api/records/10053903/files/O_ASSEN-reference-data.csv/content\"}}], \"swh\": {}, \"owners\": [{\"id\": \"6828\"}], \"status\": \"published\", \"stats\": {\"downloads\": 54743, \"unique_downloads\": 19482, \"views\": 1351, \"unique_views\": 1248, \"version_downloads\": 44749, \"version_unique_downloads\": 17507, \"version_unique_views\": 392, \"version_views\": 430}, \"state\": \"done\", \"submitted\": true}" + "size": 10502, + "text": "{\"created\": \"2023-10-30T11:31:16.569518+00:00\", \"modified\": \"2025-06-18T17:17:34.806869+00:00\", \"id\": 10053903, \"conceptrecid\": \"5653310\", \"doi\": \"10.5281/zenodo.10053903\", \"conceptdoi\": \"10.5281/zenodo.5653310\", \"doi_url\": \"https://doi.org/10.5281/zenodo.10053903\", \"metadata\": {\"title\": \"O_ASSEN - Eurasian oystercatchers (Haematopus ostralegus, Haematopodidae) breeding in Assen (the Netherlands)\", \"doi\": \"10.5281/zenodo.10053903\", \"publication_date\": \"2023-10-30\", \"description\": \"

O_ASSEN - Eurasian oystercatchers (Haematopus ostralegus, Haematopodidae) breeding in Assen (the Netherlands) is a bird tracking dataset published by the Vogelwerkgroep Assen, Netherlands Institute of Ecology (NIOO-KNAW), Sovon, Radboud University, the University of Amsterdam and the Research Institute for Nature and Forest (INBO). It contains animal tracking data collected for the study O_ASSEN using trackers developed by the University of Amsterdam Bird Tracking System (UvA-BiTS, http://www.uva-bits.nl). The study was operational from 2018 to 2019. In total 6 individuals of Eurasian oystercatchers (Haematopus ostralegus) have been tagged as a breeding bird in the city of Assen (the Netherlands), mainly to study space use of oystercatchers breeding in urban areas. Data are uploaded from the UvA-BiTS database to Movebank and from there archived on Zenodo (see https://github.com/inbo/bird-tracking). No new data are expected.

\\n

See van der Kolk et al. (2022, https://doi.org/10.3897/zookeys.1123.90623) for a more detailed description of this dataset.

\\n

Files

\\n

Data in this package are exported from Movebank study 1605797471. Fields in the data follow the Movebank Attribute Dictionary and are described in datapackage.json. Files are structured as a Frictionless Data Package. You can access all data in R via https://zenodo.org/records/10053903/files/datapackage.json using frictionless.

\\n
    \\n
  • datapackage.json: technical description of the data files.
  • \\n
  • O_ASSEN-reference-data.csv: reference data about the animals, tags and deployments.
  • \\n
  • O_ASSEN-gps-yyyy.csv.gz: GPS data recorded by the tags, grouped by year.
  • \\n
  • O_ASSEN-acceleration-yyyy.csv.gz: acceleration data recorded by the tags, grouped by year.
  • \\n
\\n

Acknowledgements

\\n

These data were collected by Bert Dijkstra and Rinus Dillerop from Vogelwerkgroep Assen, in collaboration with the Netherlands Institute of Ecology (NIOO-KNAW), Sovon, Radboud University and the University of Amsterdam (UvA). Funding was provided by the Prins Bernard Cultuurfonds Drenthe, municipality of Assen, IJsvogelfonds (from Birdlife Netherlands and Nationale Postcodeloterij) and the Waterleiding Maatschappij Drenthe. The dataset was published with funding from Stichting NLBIF - Netherlands Biodiversity Information Facility.

\", \"access_right\": \"open\", \"creators\": [{\"name\": \"Dijkstra, Bert\", \"affiliation\": \"Vogelwerkgroep Assen\"}, {\"name\": \"Dillerop, Rinus\", \"affiliation\": \"Vogelwerkgroep Assen\"}, {\"name\": \"Oosterbeek, Kees\", \"affiliation\": \"Dutch Centre for Field Ornithology\"}, {\"name\": \"Bouten, Willem\", \"affiliation\": \"University of Amsterdam\", \"orcid\": \"0000-0002-5250-8872\"}, {\"name\": \"Desmet, Peter\", \"affiliation\": \"Research Institute for Nature and Forest\", \"orcid\": \"0000-0002-8442-8025\"}, {\"name\": \"van der Kolk, Henk-Jan\", \"affiliation\": \"Dutch Bryological and Lichenological Society\", \"orcid\": \"0000-0002-8023-379X\"}, {\"name\": \"Ens, Bruno J.\", \"affiliation\": \"Dutch Centre for Field Ornithology\", \"orcid\": \"0000-0002-4659-4807\"}], \"contributors\": [{\"name\": \"Desmet, Peter\", \"affiliation\": \"Research Institute for Nature and Forest\", \"type\": \"DataCurator\", \"orcid\": \"0000-0002-8442-8025\"}], \"keywords\": [\"animal movement\", \"animal tracking\", \"gps tracking\", \"accelerometer\", \"altitude\", \"temperature\", \"biologging\", \"birds\", \"UvA-BiTS\", \"Movebank\", \"frictionlessdata\"], \"related_identifiers\": [{\"identifier\": \"https://www.movebank.org/cms/webapp?gwt_fragment=page=studies,path=study1605797471\", \"relation\": \"isDerivedFrom\", \"resource_type\": \"dataset\", \"scheme\": \"url\"}, {\"identifier\": \"https://natuurtijdschriften.nl/pub/717840/DV2018032001001005.pdf\", \"relation\": \"isSourceOf\", \"resource_type\": \"publication-article\", \"scheme\": \"url\"}, {\"identifier\": \"https://natuurtijdschriften.nl/pub/1018631/DV2019032001001005.pdf\", \"relation\": \"isSourceOf\", \"resource_type\": \"publication-article\", \"scheme\": \"url\"}, {\"identifier\": \"https://www.gbif.org/dataset/226421f2-1d29-4950-901c-aba9d0e8f2bc\", \"relation\": \"isSourceOf\", \"resource_type\": \"dataset\", \"scheme\": \"url\"}, {\"identifier\": \"https://obis.org/dataset/550b4cc1-c40d-4070-a0cb-26e010eca9d4\", \"relation\": \"isSourceOf\", \"resource_type\": \"dataset\", \"scheme\": \"url\"}, {\"identifier\": \"10.3897/zookeys.1123.90623\", \"relation\": \"isDescribedBy\", \"resource_type\": \"publication-article\", \"scheme\": \"doi\"}, {\"identifier\": \"https://inbo.github.io/movepub/\", \"relation\": \"isCompiledBy\", \"resource_type\": \"software\", \"scheme\": \"url\"}], \"language\": \"eng\", \"resource_type\": {\"title\": \"Dataset\", \"type\": \"dataset\"}, \"license\": {\"id\": \"cc-zero\"}, \"grants\": [{\"code\": \"NLBIF\", \"internal_id\": \"0566bfb96::NLBIF\", \"funder\": {\"name\": \"Naturalis Biodiversity Center\"}, \"title\": \"Netherlands Biodiversity Information Facility\"}], \"communities\": [{\"id\": \"inbo\"}, {\"id\": \"oscibio\"}, {\"id\": \"netherlandsbiodiversityinformationfacility\"}], \"relations\": {\"version\": [{\"index\": 2, \"is_last\": true, \"parent\": {\"pid_type\": \"recid\", \"pid_value\": \"5653310\"}}]}, \"notes\": \"

Changelog

\\n
    \\n
  • Add alt-project-id to the reference-data.
  • \\n
  • Reference the latest Movebank Attribute Dictionary.
  • \\n
\"}, \"title\": \"O_ASSEN - Eurasian oystercatchers (Haematopus ostralegus, Haematopodidae) breeding in Assen (the Netherlands)\", \"links\": {\"self\": \"https://zenodo.org/api/records/10053903\", \"self_html\": \"https://zenodo.org/records/10053903\", \"preview_html\": \"https://zenodo.org/records/10053903?preview=1\", \"doi\": \"https://doi.org/10.5281/zenodo.10053903\", \"self_doi\": \"https://doi.org/10.5281/zenodo.10053903\", \"self_doi_html\": \"https://zenodo.org/doi/10.5281/zenodo.10053903\", \"reserve_doi\": \"https://zenodo.org/api/records/10053903/draft/pids/doi\", \"parent\": \"https://zenodo.org/api/records/5653310\", \"parent_html\": \"https://zenodo.org/records/5653310\", \"parent_doi\": \"https://doi.org/10.5281/zenodo.5653310\", \"parent_doi_html\": \"https://zenodo.org/doi/10.5281/zenodo.5653310\", \"self_iiif_manifest\": \"https://zenodo.org/api/iiif/record:10053903/manifest\", \"self_iiif_sequence\": \"https://zenodo.org/api/iiif/record:10053903/sequence/default\", \"files\": \"https://zenodo.org/api/records/10053903/files\", \"media_files\": \"https://zenodo.org/api/records/10053903/media-files\", \"archive\": \"https://zenodo.org/api/records/10053903/files-archive\", \"archive_media\": \"https://zenodo.org/api/records/10053903/media-files-archive\", \"latest\": \"https://zenodo.org/api/records/10053903/versions/latest\", \"latest_html\": \"https://zenodo.org/records/10053903/latest\", \"versions\": \"https://zenodo.org/api/records/10053903/versions\", \"draft\": \"https://zenodo.org/api/records/10053903/draft\", \"access_links\": \"https://zenodo.org/api/records/10053903/access/links\", \"access_grants\": \"https://zenodo.org/api/records/10053903/access/grants\", \"access_users\": \"https://zenodo.org/api/records/10053903/access/users\", \"access_request\": \"https://zenodo.org/api/records/10053903/access/request\", \"access\": \"https://zenodo.org/api/records/10053903/access\", \"communities\": \"https://zenodo.org/api/records/10053903/communities\", \"communities-suggestions\": \"https://zenodo.org/api/records/10053903/communities-suggestions\", \"requests\": \"https://zenodo.org/api/records/10053903/requests\"}, \"updated\": \"2025-06-18T17:17:34.806869+00:00\", \"recid\": \"10053903\", \"revision\": 18, \"files\": [{\"id\": \"5ffb4935-0a78-4fd5-af2a-f0f5113ca7c0\", \"key\": \"datapackage.json\", \"size\": 42936, \"checksum\": \"md5:5ea86b7a222ac843e3833a2e50a2056b\", \"links\": {\"self\": \"https://zenodo.org/api/records/10053903/files/datapackage.json/content\"}}, {\"id\": \"f09bbed1-50e3-46b3-a1d9-10e8adeec337\", \"key\": \"O_ASSEN-acceleration-2018.csv.gz\", \"size\": 4067780, \"checksum\": \"md5:40b771d9bd53ee5cfae0266209364d9c\", \"links\": {\"self\": \"https://zenodo.org/api/records/10053903/files/O_ASSEN-acceleration-2018.csv.gz/content\"}}, {\"id\": \"73a7a2a5-cdfc-48a7-be65-641144ef9c38\", \"key\": \"O_ASSEN-acceleration-2019.csv.gz\", \"size\": 3696729, \"checksum\": \"md5:9d2cbbaece00ef8cf8b4fff87cf07079\", \"links\": {\"self\": \"https://zenodo.org/api/records/10053903/files/O_ASSEN-acceleration-2019.csv.gz/content\"}}, {\"id\": \"93e83695-a619-4f09-aa93-edb2fadcd586\", \"key\": \"O_ASSEN-gps-2018.csv.gz\", \"size\": 751448, \"checksum\": \"md5:f5e041ea66ebe8708a46fe57f383f549\", \"links\": {\"self\": \"https://zenodo.org/api/records/10053903/files/O_ASSEN-gps-2018.csv.gz/content\"}}, {\"id\": \"e64508be-1860-415f-bbbd-fc4353f33278\", \"key\": \"O_ASSEN-gps-2019.csv.gz\", \"size\": 263439, \"checksum\": \"md5:cec4550a769d4f053e92565b44d0409c\", \"links\": {\"self\": \"https://zenodo.org/api/records/10053903/files/O_ASSEN-gps-2019.csv.gz/content\"}}, {\"id\": \"05581f20-937c-4180-824c-c3068b641d34\", \"key\": \"O_ASSEN-reference-data.csv\", \"size\": 2082, \"checksum\": \"md5:5a5da155f404d5a3b4e50c350ad089d1\", \"links\": {\"self\": \"https://zenodo.org/api/records/10053903/files/O_ASSEN-reference-data.csv/content\"}}], \"swh\": {}, \"owners\": [{\"id\": \"6828\"}], \"status\": \"published\", \"stats\": {\"downloads\": 56783, \"unique_downloads\": 20314, \"views\": 1436, \"unique_views\": 1327, \"version_downloads\": 46734, \"version_unique_downloads\": 18284, \"version_unique_views\": 434, \"version_views\": 475}, \"state\": \"done\", \"submitted\": true}" }, "cookies": [ { @@ -35,7 +35,7 @@ "path": "/", "sameSite": "None", "secure": true, - "value": "fe8892fcd3384dc73cd2eb4e9b901329" + "value": "ee05b1c4fc826a86b832f3008890c77d" } ], "headers": [ @@ -65,11 +65,11 @@ }, { "name": "date", - "value": "Tue, 27 May 2025 07:50:50 GMT" + "value": "Thu, 07 Aug 2025 07:49:26 GMT" }, { "name": "etag", - "value": "W/\"16\"" + "value": "W/\"18\"" }, { "name": "link", @@ -85,7 +85,7 @@ }, { "name": "retry-after", - "value": "60" + "value": "59" }, { "name": "server", @@ -93,7 +93,7 @@ }, { "name": "set-cookie", - "value": "5569e5a730cade8ff2b54f1e815f3670=fe8892fcd3384dc73cd2eb4e9b901329; path=/; HttpOnly; Secure; SameSite=None" + "value": "5569e5a730cade8ff2b54f1e815f3670=ee05b1c4fc826a86b832f3008890c77d; path=/; HttpOnly; Secure; SameSite=None" }, { "name": "strict-transport-security", @@ -121,15 +121,15 @@ }, { "name": "x-ratelimit-remaining", - "value": "132" + "value": "131" }, { "name": "x-ratelimit-reset", - "value": "1748332311" + "value": "1754553026" }, { "name": "x-request-id", - "value": "8c371249a0b01a15e4baa71551bdeed2" + "value": "70ed876bc027711078c800c1e7030c13" }, { "name": "x-xss-protection", @@ -142,8 +142,8 @@ "status": 200, "statusText": "OK" }, - "startedDateTime": "2025-05-27T07:50:48.946Z", - "time": 848, + "startedDateTime": "2025-08-07T07:49:25.894Z", + "time": 426, "timings": { "blocked": -1, "connect": -1, @@ -151,7 +151,7 @@ "receive": 0, "send": 0, "ssl": -1, - "wait": 848 + "wait": 426 } }, { @@ -182,7 +182,7 @@ "path": "/", "sameSite": "None", "secure": true, - "value": "0acb936b975d164e9af26483a08df23e" + "value": "e26c51e5d1379a16d287881670fdf19c" } ], "headers": [ @@ -208,7 +208,7 @@ }, { "name": "date", - "value": "Tue, 27 May 2025 09:55:24 GMT" + "value": "Thu, 07 Aug 2025 07:49:26 GMT" }, { "name": "oc-checksum", @@ -220,7 +220,7 @@ }, { "name": "retry-after", - "value": "60" + "value": "59" }, { "name": "server", @@ -228,7 +228,7 @@ }, { "name": "set-cookie", - "value": "5569e5a730cade8ff2b54f1e815f3670=0acb936b975d164e9af26483a08df23e; path=/; HttpOnly; Secure; SameSite=None" + "value": "5569e5a730cade8ff2b54f1e815f3670=e26c51e5d1379a16d287881670fdf19c; path=/; HttpOnly; Secure; SameSite=None" }, { "name": "strict-transport-security", @@ -264,11 +264,11 @@ }, { "name": "x-ratelimit-remaining", - "value": "132" + "value": "130" }, { "name": "x-ratelimit-reset", - "value": "1748339785" + "value": "1754553026" }, { "name": "x-xss-protection", @@ -281,8 +281,8 @@ "status": 200, "statusText": "OK" }, - "startedDateTime": "2025-05-27T09:55:23.201Z", - "time": 1212, + "startedDateTime": "2025-08-07T07:49:26.324Z", + "time": 273, "timings": { "blocked": -1, "connect": -1, @@ -290,7 +290,7 @@ "receive": 0, "send": 0, "ssl": -1, - "wait": 1212 + "wait": 273 } } ], diff --git a/zenodo/package/index.ts b/zenodo/package/index.ts index 3ef3a5d1..8c9b2745 100644 --- a/zenodo/package/index.ts +++ b/zenodo/package/index.ts @@ -1,4 +1,4 @@ -export type { ZenodoPackage } from "./Package.js" -export type { ZenodoCreator } from "./Creator.js" -export { loadPackageFromZenodo } from "./load.js" -export { savePackageToZenodo } from "./save.js" +export type { ZenodoPackage } from "./Package.ts" +export type { ZenodoCreator } from "./Creator.ts" +export { loadPackageFromZenodo } from "./load.ts" +export { savePackageToZenodo } from "./save.ts" diff --git a/zenodo/package/load.spec.ts b/zenodo/package/load.spec.ts index 1b6f8420..2227e463 100644 --- a/zenodo/package/load.spec.ts +++ b/zenodo/package/load.spec.ts @@ -1,6 +1,6 @@ import { useRecording } from "@dpkit/test" import { describe, expect, it } from "vitest" -import { loadPackageFromZenodo } from "./load.js" +import { loadPackageFromZenodo } from "./load.ts" describe("loadPackageFromZenodo", () => { useRecording() diff --git a/zenodo/package/load.ts b/zenodo/package/load.ts index 1756176e..be9d5e32 100644 --- a/zenodo/package/load.ts +++ b/zenodo/package/load.ts @@ -1,7 +1,7 @@ import { mergePackages } from "@dpkit/core" -import { makeZenodoApiRequest } from "../general/index.js" -import type { ZenodoPackage } from "./Package.js" -import { normalizeZenodoPackage } from "./process/normalize.js" +import { makeZenodoApiRequest } from "../zenodo/index.ts" +import type { ZenodoPackage } from "./Package.ts" +import { normalizeZenodoPackage } from "./process/normalize.ts" /** * Load a package from a Zenodo deposit diff --git a/zenodo/package/process/denormalize.ts b/zenodo/package/process/denormalize.ts index 9c7a3138..c2770475 100644 --- a/zenodo/package/process/denormalize.ts +++ b/zenodo/package/process/denormalize.ts @@ -1,6 +1,6 @@ import type { Package } from "@dpkit/core" -import type { ZenodoCreator } from "../Creator.js" -import type { ZenodoPackage } from "../Package.js" +import type { ZenodoCreator } from "../Creator.ts" +import type { ZenodoPackage } from "../Package.ts" /** * Denormalizes a Frictionless Data Package to Zenodo Deposit metadata format diff --git a/zenodo/package/process/normalize.ts b/zenodo/package/process/normalize.ts index 267fbff0..813ee28d 100644 --- a/zenodo/package/process/normalize.ts +++ b/zenodo/package/process/normalize.ts @@ -1,6 +1,6 @@ import type { Contributor, License, Package } from "@dpkit/core" -import { normalizeZenodoResource } from "../../resource/index.js" -import type { ZenodoPackage } from "../Package.js" +import { normalizeZenodoResource } from "../../resource/index.ts" +import type { ZenodoPackage } from "../Package.ts" /** * Normalizes a Zenodo deposit to Frictionless Data package format diff --git a/zenodo/package/save.spec.ts b/zenodo/package/save.spec.ts index 51032e86..c81d7df6 100644 --- a/zenodo/package/save.spec.ts +++ b/zenodo/package/save.spec.ts @@ -1,7 +1,7 @@ import { loadPackageDescriptor } from "@dpkit/core" //import { useRecording } from "@dpkit/test" import { describe, expect, it } from "vitest" -import { savePackageToZenodo } from "./save.js" +import { savePackageToZenodo } from "./save.ts" describe("savePackageToZenodo", () => { //useRecording() diff --git a/zenodo/package/save.ts b/zenodo/package/save.ts index ba8efed1..c889f6b0 100644 --- a/zenodo/package/save.ts +++ b/zenodo/package/save.ts @@ -6,9 +6,9 @@ import { loadFileStream, saveResourceFiles, } from "@dpkit/file" -import { makeZenodoApiRequest } from "../general/index.js" -import type { ZenodoPackage } from "./Package.js" -import { denormalizeZenodoPackage } from "./process/denormalize.js" +import { makeZenodoApiRequest } from "../zenodo/index.ts" +import type { ZenodoPackage } from "./Package.ts" +import { denormalizeZenodoPackage } from "./process/denormalize.ts" /** * Save a package to Zenodo @@ -73,7 +73,7 @@ export async function savePackageToZenodo( for (const denormalizedPath of ["datapackage.json"]) { const upload = { name: denormalizedPath, - data: new Blob([stringifyDescriptor({ descriptor })]), + data: new Blob([stringifyDescriptor(descriptor)]), } await makeZenodoApiRequest({ diff --git a/zenodo/plugin.ts b/zenodo/plugin.ts index ef51e9d1..d02cee52 100644 --- a/zenodo/plugin.ts +++ b/zenodo/plugin.ts @@ -1,6 +1,6 @@ import type { Plugin } from "@dpkit/core" import { isRemotePath } from "@dpkit/core" -import { loadPackageFromZenodo } from "./package/load.js" +import { loadPackageFromZenodo } from "./package/load.ts" export class ZenodoPlugin implements Plugin { async loadPackage(source: string) { diff --git a/zenodo/resource/index.ts b/zenodo/resource/index.ts index 5d5851d7..9c1a6f5e 100644 --- a/zenodo/resource/index.ts +++ b/zenodo/resource/index.ts @@ -1,3 +1,3 @@ -export type { ZenodoResource } from "./Resource.js" -export { normalizeZenodoResource } from "./process/normalize.js" -export { denormalizeZenodoResource } from "./process/denormalize.js" +export type { ZenodoResource } from "./Resource.ts" +export { normalizeZenodoResource } from "./process/normalize.ts" +export { denormalizeZenodoResource } from "./process/denormalize.ts" diff --git a/zenodo/resource/process/denormalize.ts b/zenodo/resource/process/denormalize.ts index 6ef46165..ceac0d46 100644 --- a/zenodo/resource/process/denormalize.ts +++ b/zenodo/resource/process/denormalize.ts @@ -1,5 +1,5 @@ import type { Resource } from "@dpkit/core" -import type { ZenodoResource } from "../Resource.js" +import type { ZenodoResource } from "../Resource.ts" export function denormalizeZenodoResource(resource: Resource) { const zenodoResource: Partial = { diff --git a/zenodo/resource/process/normalize.ts b/zenodo/resource/process/normalize.ts index c08ed8ca..b5b57af6 100644 --- a/zenodo/resource/process/normalize.ts +++ b/zenodo/resource/process/normalize.ts @@ -1,5 +1,5 @@ import { getFormat, getName } from "@dpkit/core" -import type { ZenodoResource } from "../Resource.js" +import type { ZenodoResource } from "../Resource.ts" /** * Normalizes a Zenodo file to Frictionless Data resource format diff --git a/zenodo/tsconfig.json b/zenodo/tsconfig.json index 7be40230..3c43903c 100644 --- a/zenodo/tsconfig.json +++ b/zenodo/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/zenodo/typedoc.json b/zenodo/typedoc.json index fc33b815..f8e49f3a 100644 --- a/zenodo/typedoc.json +++ b/zenodo/typedoc.json @@ -1,5 +1,4 @@ { "entryPoints": ["index.ts"], - "projectDocuments": ["CHANGELOG.md", "OVERVIEW.md"], "skipErrorChecking": true } diff --git a/zenodo/zenodo/index.ts b/zenodo/zenodo/index.ts new file mode 100644 index 00000000..6887883b --- /dev/null +++ b/zenodo/zenodo/index.ts @@ -0,0 +1 @@ +export { makeZenodoApiRequest } from "./request.ts" diff --git a/zenodo/general/request.ts b/zenodo/zenodo/request.ts similarity index 100% rename from zenodo/general/request.ts rename to zenodo/zenodo/request.ts diff --git a/zip/OVERVIEW.md b/zip/OVERVIEW.md deleted file mode 100644 index 57f57cc9..00000000 --- a/zip/OVERVIEW.md +++ /dev/null @@ -1,6 +0,0 @@ -# @dpkit/zip - -:::note -This overview is under development. -::: - diff --git a/zip/index.ts b/zip/index.ts index af05c222..8e03d380 100644 --- a/zip/index.ts +++ b/zip/index.ts @@ -1,2 +1,2 @@ -export * from "./package/index.js" -export * from "./plugin.js" +export * from "./package/index.ts" +export * from "./plugin.ts" diff --git a/zip/package.json b/zip/package.json index 807bc760..4a15b41d 100644 --- a/zip/package.json +++ b/zip/package.json @@ -1,8 +1,8 @@ { "name": "@dpkit/zip", "type": "module", - "main": "build/index.js", "version": "0.6.0", + "exports": "./build/index.js", "license": "MIT", "author": "Evgeny Karev", "repository": "https://github.com/datisthq/dpkit", @@ -20,7 +20,7 @@ "zip" ], "scripts": { - "build": "tsc --build" + "build": "tsc" }, "dependencies": { "@dpkit/core": "workspace:*", diff --git a/zip/package/index.ts b/zip/package/index.ts index d66b41fc..33c3172e 100644 --- a/zip/package/index.ts +++ b/zip/package/index.ts @@ -1,2 +1,2 @@ -export { loadPackageFromZip } from "./load.js" -export { savePackageToZip } from "./save.js" +export { loadPackageFromZip } from "./load.ts" +export { savePackageToZip } from "./save.ts" diff --git a/zip/package/save.ts b/zip/package/save.ts index 03a75260..59f6e071 100644 --- a/zip/package/save.ts +++ b/zip/package/save.ts @@ -1,3 +1,4 @@ +import { Buffer } from "node:buffer" import { createWriteStream } from "node:fs" import { pipeline } from "node:stream/promises" import type { Descriptor, Package } from "@dpkit/core" @@ -47,7 +48,7 @@ export async function savePackageToZip( } zipfile.addBuffer( - Buffer.from(stringifyDescriptor({ descriptor })), + Buffer.from(stringifyDescriptor(descriptor)), "datapackage.json", ) diff --git a/zip/plugin.ts b/zip/plugin.ts index ac6e61d1..e575d8e4 100644 --- a/zip/plugin.ts +++ b/zip/plugin.ts @@ -1,5 +1,5 @@ import type { Package, Plugin } from "@dpkit/core" -import { loadPackageFromZip, savePackageToZip } from "./package/index.js" +import { loadPackageFromZip, savePackageToZip } from "./package/index.ts" export class ZipPlugin implements Plugin { async loadPackage(source: string) { diff --git a/zip/tsconfig.json b/zip/tsconfig.json index 7be40230..3c43903c 100644 --- a/zip/tsconfig.json +++ b/zip/tsconfig.json @@ -1,10 +1,3 @@ { - "extends": "../tsconfig.json", - "include": ["**/*.ts"], - "exclude": ["**/build/"], - "compilerOptions": { - "outDir": "build", - "noEmit": false, - "declaration": true - } + "extends": "../tsconfig.json" } diff --git a/zip/typedoc.json b/zip/typedoc.json index fc33b815..f8e49f3a 100644 --- a/zip/typedoc.json +++ b/zip/typedoc.json @@ -1,5 +1,4 @@ { "entryPoints": ["index.ts"], - "projectDocuments": ["CHANGELOG.md", "OVERVIEW.md"], "skipErrorChecking": true }