aimeat 3.2.0 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/.env.example +58 -1
- package/dist/build-stamp.json +4 -4
- package/dist/locales/en.json +41 -1
- package/dist/locales/es.json +41 -1
- package/dist/locales/fi.json +43 -3
- package/dist/public/changelog.json +12 -0
- package/dist/public/css/views/chat.css +388 -0
- package/dist/public/js/services/chat.js +190 -0
- package/dist/public/js/services/speech-reader.js +26 -0
- package/dist/public/lib/VENDORED.md +1 -0
- package/dist/public/lib/duckdb-wasm@1.32.0/duckdb-browser-eh.worker.js +14 -0
- package/dist/public/lib/duckdb-wasm@1.32.0/duckdb-browser.js +23 -0
- package/dist/public/lib/duckdb-wasm@1.32.0/duckdb-eh.wasm +0 -0
- package/dist/public/lib/duckdb-wasm@1.32.0/extensions/v1.4.3/wasm_eh/parquet.duckdb_extension.wasm +0 -0
- package/dist/public/lib/vendored-assets.json +19 -0
- package/dist/public/llms-full-template.txt +2706 -0
- package/dist/public/llms-index-template.txt +60 -0
- package/dist/public/robots.node.txt +64 -23
- package/dist/public/spa.html +8 -1
- package/dist/public/views/chat/parts.js +257 -0
- package/dist/public/views/chat.js +327 -0
- package/dist/public/views/landing.js +24 -1
- package/dist/public/views/profile/agents/scope-model.js +320 -315
- package/dist/scripts/audit-mcp-schemas.js +50 -0
- package/dist/scripts/audit-mcp-schemas.js.map +1 -1
- package/dist/scripts/build-sdk-libs.d.ts.map +1 -1
- package/dist/scripts/build-sdk-libs.js +1 -0
- package/dist/scripts/build-sdk-libs.js.map +1 -1
- package/dist/scripts/check-ai-disclosure.d.ts +1 -1
- package/dist/scripts/check-ai-disclosure.d.ts.map +1 -1
- package/dist/scripts/check-ai-disclosure.js +30 -3
- package/dist/scripts/check-ai-disclosure.js.map +1 -1
- package/dist/scripts/check-denial-coverage.d.ts +29 -0
- package/dist/scripts/check-denial-coverage.d.ts.map +1 -0
- package/dist/scripts/check-denial-coverage.js +237 -0
- package/dist/scripts/check-denial-coverage.js.map +1 -0
- package/dist/scripts/check-ext-entrypoints.js +14 -2
- package/dist/scripts/check-ext-entrypoints.js.map +1 -1
- package/dist/scripts/check-outbound-fetch.d.ts.map +1 -1
- package/dist/scripts/check-outbound-fetch.js +16 -2
- package/dist/scripts/check-outbound-fetch.js.map +1 -1
- package/dist/scripts/check-sse-parity.js +14 -0
- package/dist/scripts/check-sse-parity.js.map +1 -1
- package/dist/scripts/indexnow.js +9 -7
- package/dist/scripts/indexnow.js.map +1 -1
- package/dist/src/auth/ai-gate.d.ts +25 -0
- package/dist/src/auth/ai-gate.d.ts.map +1 -0
- package/dist/src/auth/ai-gate.js +21 -0
- package/dist/src/auth/ai-gate.js.map +1 -0
- package/dist/src/auth/middleware.d.ts +7 -0
- package/dist/src/auth/middleware.d.ts.map +1 -1
- package/dist/src/auth/middleware.js +15 -21
- package/dist/src/auth/middleware.js.map +1 -1
- package/dist/src/cli/connect/mcp/tools/agent-tasks.d.ts +4 -0
- package/dist/src/cli/connect/mcp/tools/agent-tasks.d.ts.map +1 -1
- package/dist/src/cli/connect/mcp/tools/agent-tasks.js +11 -1
- package/dist/src/cli/connect/mcp/tools/agent-tasks.js.map +1 -1
- package/dist/src/cli/connect/mcp/tools/apps.d.ts.map +1 -1
- package/dist/src/cli/connect/mcp/tools/apps.js +88 -0
- package/dist/src/cli/connect/mcp/tools/apps.js.map +1 -1
- package/dist/src/cli/connect/mcp/tools/core.d.ts +7 -0
- package/dist/src/cli/connect/mcp/tools/core.d.ts.map +1 -1
- package/dist/src/cli/connect/mcp/tools/core.js +83 -4
- package/dist/src/cli/connect/mcp/tools/core.js.map +1 -1
- package/dist/src/cli/connect/onboarding-prompt.js +1 -1
- package/dist/src/cli/connect/skill-bundle.js +1 -1
- package/dist/src/cli/connect/tool-call-defs-agent.d.ts.map +1 -1
- package/dist/src/cli/connect/tool-call-defs-agent.js +38 -9
- package/dist/src/cli/connect/tool-call-defs-agent.js.map +1 -1
- package/dist/src/cli/connect/tool-call-defs-app-draft-edit.d.ts +21 -0
- package/dist/src/cli/connect/tool-call-defs-app-draft-edit.d.ts.map +1 -0
- package/dist/src/cli/connect/tool-call-defs-app-draft-edit.js +137 -0
- package/dist/src/cli/connect/tool-call-defs-app-draft-edit.js.map +1 -0
- package/dist/src/cli/connect/tool-call-defs-apps.d.ts.map +1 -1
- package/dist/src/cli/connect/tool-call-defs-apps.js +114 -25
- package/dist/src/cli/connect/tool-call-defs-apps.js.map +1 -1
- package/dist/src/cli/connect/tool-call-defs-core.d.ts +1 -0
- package/dist/src/cli/connect/tool-call-defs-core.d.ts.map +1 -1
- package/dist/src/cli/connect/tool-call-defs-core.js +179 -26
- package/dist/src/cli/connect/tool-call-defs-core.js.map +1 -1
- package/dist/src/cli/connect/tool-call-defs-organism.d.ts.map +1 -1
- package/dist/src/cli/connect/tool-call-defs-organism.js +20 -3
- package/dist/src/cli/connect/tool-call-defs-organism.js.map +1 -1
- package/dist/src/cli/connect/tool-call.d.ts.map +1 -1
- package/dist/src/cli/connect/tool-call.js +52 -1
- package/dist/src/cli/connect/tool-call.js.map +1 -1
- package/dist/src/config-types-ai.d.ts +76 -0
- package/dist/src/config-types-ai.d.ts.map +1 -0
- package/dist/src/config-types-ai.js +15 -0
- package/dist/src/config-types-ai.js.map +1 -0
- package/dist/src/config-types.d.ts +11 -2
- package/dist/src/config-types.d.ts.map +1 -1
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +25 -4
- package/dist/src/config.js.map +1 -1
- package/dist/src/data/builtin-skills.d.ts.map +1 -1
- package/dist/src/data/builtin-skills.js +3 -2
- package/dist/src/data/builtin-skills.js.map +1 -1
- package/dist/src/data/digital-signage-package.js +1 -1
- package/dist/src/data/library-packs/sdk.d.ts.map +1 -1
- package/dist/src/data/library-packs/sdk.js +76 -0
- package/dist/src/data/library-packs/sdk.js.map +1 -1
- package/dist/src/data/library-packs/vendored.d.ts.map +1 -1
- package/dist/src/data/library-packs/vendored.js +81 -0
- package/dist/src/data/library-packs/vendored.js.map +1 -1
- package/dist/src/data/library-packs.d.ts +2 -2
- package/dist/src/data/library-packs.js +2 -2
- package/dist/src/data/public-pages.d.ts +13 -0
- package/dist/src/data/public-pages.d.ts.map +1 -1
- package/dist/src/data/public-pages.js +153 -113
- package/dist/src/data/public-pages.js.map +1 -1
- package/dist/src/generated/api-types.d.ts +1808 -36
- package/dist/src/generated/api-types.d.ts.map +1 -1
- package/dist/src/index-start.d.ts.map +1 -1
- package/dist/src/index-start.js +3 -0
- package/dist/src/index-start.js.map +1 -1
- package/dist/src/mcp/agent-tasks.d.ts.map +1 -1
- package/dist/src/mcp/agent-tasks.js +5 -0
- package/dist/src/mcp/agent-tasks.js.map +1 -1
- package/dist/src/mcp/ai-image.d.ts +22 -0
- package/dist/src/mcp/ai-image.d.ts.map +1 -0
- package/dist/src/mcp/ai-image.js +60 -0
- package/dist/src/mcp/ai-image.js.map +1 -0
- package/dist/src/mcp/annotations.d.ts +5 -0
- package/dist/src/mcp/annotations.d.ts.map +1 -1
- package/dist/src/mcp/annotations.js +18 -0
- package/dist/src/mcp/annotations.js.map +1 -1
- package/dist/src/mcp/apps-draft-edit.d.ts +28 -0
- package/dist/src/mcp/apps-draft-edit.d.ts.map +1 -0
- package/dist/src/mcp/apps-draft-edit.js +164 -0
- package/dist/src/mcp/apps-draft-edit.js.map +1 -0
- package/dist/src/mcp/apps-screenshot.d.ts +26 -0
- package/dist/src/mcp/apps-screenshot.d.ts.map +1 -0
- package/dist/src/mcp/apps-screenshot.js +39 -0
- package/dist/src/mcp/apps-screenshot.js.map +1 -0
- package/dist/src/mcp/catalog/definitions/discovery-work-boards.d.ts +1 -0
- package/dist/src/mcp/catalog/definitions/discovery-work-boards.d.ts.map +1 -1
- package/dist/src/mcp/catalog/definitions/discovery-work-boards.js +40 -0
- package/dist/src/mcp/catalog/definitions/discovery-work-boards.js.map +1 -1
- package/dist/src/mcp/catalog/definitions/organisms-workspaces-apps.d.ts +3 -0
- package/dist/src/mcp/catalog/definitions/organisms-workspaces-apps.d.ts.map +1 -1
- package/dist/src/mcp/catalog/definitions/organisms-workspaces-apps.js +74 -0
- package/dist/src/mcp/catalog/definitions/organisms-workspaces-apps.js.map +1 -1
- package/dist/src/mcp/catalog/definitions/schedules-tasks-memory.d.ts.map +1 -1
- package/dist/src/mcp/catalog/definitions/schedules-tasks-memory.js +1 -0
- package/dist/src/mcp/catalog/definitions/schedules-tasks-memory.js.map +1 -1
- package/dist/src/mcp/catalog/scopes.d.ts.map +1 -1
- package/dist/src/mcp/catalog/scopes.js +19 -1
- package/dist/src/mcp/catalog/scopes.js.map +1 -1
- package/dist/src/mcp/catalog/surfaces.d.ts.map +1 -1
- package/dist/src/mcp/catalog/surfaces.js +18 -4
- package/dist/src/mcp/catalog/surfaces.js.map +1 -1
- package/dist/src/mcp/core-datapackage.d.ts +32 -0
- package/dist/src/mcp/core-datapackage.d.ts.map +1 -0
- package/dist/src/mcp/core-datapackage.js +188 -0
- package/dist/src/mcp/core-datapackage.js.map +1 -0
- package/dist/src/mcp/core-storage.d.ts +7 -3
- package/dist/src/mcp/core-storage.d.ts.map +1 -1
- package/dist/src/mcp/core-storage.js +27 -4
- package/dist/src/mcp/core-storage.js.map +1 -1
- package/dist/src/mcp/core.d.ts.map +1 -1
- package/dist/src/mcp/core.js +3 -0
- package/dist/src/mcp/core.js.map +1 -1
- package/dist/src/mcp/extensions.d.ts.map +1 -1
- package/dist/src/mcp/extensions.js +11 -1
- package/dist/src/mcp/extensions.js.map +1 -1
- package/dist/src/mcp/index.d.ts +9 -0
- package/dist/src/mcp/index.d.ts.map +1 -1
- package/dist/src/mcp/index.js +34 -0
- package/dist/src/mcp/index.js.map +1 -1
- package/dist/src/models/agent-task-schemas.d.ts.map +1 -1
- package/dist/src/models/agent-task-schemas.js +12 -1
- package/dist/src/models/agent-task-schemas.js.map +1 -1
- package/dist/src/models/workflow-schemas.d.ts +178 -1
- package/dist/src/models/workflow-schemas.d.ts.map +1 -1
- package/dist/src/models/workflow-schemas.js +75 -0
- package/dist/src/models/workflow-schemas.js.map +1 -1
- package/dist/src/routes/admin-extensions.d.ts +4 -0
- package/dist/src/routes/admin-extensions.d.ts.map +1 -1
- package/dist/src/routes/admin-extensions.js +135 -142
- package/dist/src/routes/admin-extensions.js.map +1 -1
- package/dist/src/routes/agent-conventions.d.ts.map +1 -1
- package/dist/src/routes/agent-conventions.js +4 -2
- package/dist/src/routes/agent-conventions.js.map +1 -1
- package/dist/src/routes/agent-docs.d.ts +4 -4
- package/dist/src/routes/agent-docs.js +145 -145
- package/dist/src/routes/agent-docs.js.map +1 -1
- package/dist/src/routes/agent-messages.d.ts +6 -0
- package/dist/src/routes/agent-messages.d.ts.map +1 -1
- package/dist/src/routes/agent-messages.js +23 -1
- package/dist/src/routes/agent-messages.js.map +1 -1
- package/dist/src/routes/agent-tasks/create-read.d.ts.map +1 -1
- package/dist/src/routes/agent-tasks/create-read.js +8 -1
- package/dist/src/routes/agent-tasks/create-read.js.map +1 -1
- package/dist/src/routes/agent-tasks/lifecycle.d.ts +4 -1
- package/dist/src/routes/agent-tasks/lifecycle.d.ts.map +1 -1
- package/dist/src/routes/agent-tasks/lifecycle.js +80 -2
- package/dist/src/routes/agent-tasks/lifecycle.js.map +1 -1
- package/dist/src/routes/ai.d.ts +5 -0
- package/dist/src/routes/ai.d.ts.map +1 -1
- package/dist/src/routes/ai.js +55 -16
- package/dist/src/routes/ai.js.map +1 -1
- package/dist/src/routes/app-grants.d.ts.map +1 -1
- package/dist/src/routes/app-grants.js +5 -0
- package/dist/src/routes/app-grants.js.map +1 -1
- package/dist/src/routes/apps/drafts.d.ts +6 -0
- package/dist/src/routes/apps/drafts.d.ts.map +1 -1
- package/dist/src/routes/apps/drafts.js +133 -1
- package/dist/src/routes/apps/drafts.js.map +1 -1
- package/dist/src/routes/apps/read.d.ts.map +1 -1
- package/dist/src/routes/apps/read.js +38 -1
- package/dist/src/routes/apps/read.js.map +1 -1
- package/dist/src/routes/auth-otk.d.ts +28 -0
- package/dist/src/routes/auth-otk.d.ts.map +1 -0
- package/dist/src/routes/auth-otk.js +190 -0
- package/dist/src/routes/auth-otk.js.map +1 -0
- package/dist/src/routes/auth.d.ts +17 -0
- package/dist/src/routes/auth.d.ts.map +1 -1
- package/dist/src/routes/auth.js +44 -153
- package/dist/src/routes/auth.js.map +1 -1
- package/dist/src/routes/bootstrap.d.ts +6 -0
- package/dist/src/routes/bootstrap.d.ts.map +1 -1
- package/dist/src/routes/bootstrap.js +47 -20
- package/dist/src/routes/bootstrap.js.map +1 -1
- package/dist/src/routes/chat.d.ts +23 -0
- package/dist/src/routes/chat.d.ts.map +1 -0
- package/dist/src/routes/chat.js +165 -0
- package/dist/src/routes/chat.js.map +1 -0
- package/dist/src/routes/commerce.js +4 -4
- package/dist/src/routes/commerce.js.map +1 -1
- package/dist/src/routes/datapackages.d.ts +35 -0
- package/dist/src/routes/datapackages.d.ts.map +1 -0
- package/dist/src/routes/datapackages.js +217 -0
- package/dist/src/routes/datapackages.js.map +1 -0
- package/dist/src/routes/disputes.d.ts +8 -0
- package/dist/src/routes/disputes.d.ts.map +1 -1
- package/dist/src/routes/disputes.js +52 -1
- package/dist/src/routes/disputes.js.map +1 -1
- package/dist/src/routes/ecosystem-apps-advisories.d.ts +16 -0
- package/dist/src/routes/ecosystem-apps-advisories.d.ts.map +1 -0
- package/dist/src/routes/ecosystem-apps-advisories.js +104 -0
- package/dist/src/routes/ecosystem-apps-advisories.js.map +1 -0
- package/dist/src/routes/ecosystem-apps.d.ts +6 -0
- package/dist/src/routes/ecosystem-apps.d.ts.map +1 -1
- package/dist/src/routes/ecosystem-apps.js +31 -99
- package/dist/src/routes/ecosystem-apps.js.map +1 -1
- package/dist/src/routes/extensions/actions.d.ts.map +1 -1
- package/dist/src/routes/extensions/actions.js +29 -1
- package/dist/src/routes/extensions/actions.js.map +1 -1
- package/dist/src/routes/federation-sync/routing.d.ts.map +1 -1
- package/dist/src/routes/federation-sync/routing.js +12 -3
- package/dist/src/routes/federation-sync/routing.js.map +1 -1
- package/dist/src/routes/glossary.js +1 -1
- package/dist/src/routes/glossary.js.map +1 -1
- package/dist/src/routes/home/track.d.ts +5 -1
- package/dist/src/routes/home/track.d.ts.map +1 -1
- package/dist/src/routes/home/track.js +20 -6
- package/dist/src/routes/home/track.js.map +1 -1
- package/dist/src/routes/instances/install.d.ts +3 -0
- package/dist/src/routes/instances/install.d.ts.map +1 -1
- package/dist/src/routes/instances/install.js +17 -24
- package/dist/src/routes/instances/install.js.map +1 -1
- package/dist/src/routes/libs.js +1 -1
- package/dist/src/routes/libs.js.map +1 -1
- package/dist/src/routes/llm-proxy.d.ts +34 -0
- package/dist/src/routes/llm-proxy.d.ts.map +1 -0
- package/dist/src/routes/llm-proxy.js +258 -0
- package/dist/src/routes/llm-proxy.js.map +1 -0
- package/dist/src/routes/markdown-mirrors.js +1 -1
- package/dist/src/routes/markdown-mirrors.js.map +1 -1
- package/dist/src/routes/odata.d.ts +36 -0
- package/dist/src/routes/odata.d.ts.map +1 -0
- package/dist/src/routes/odata.js +143 -0
- package/dist/src/routes/odata.js.map +1 -0
- package/dist/src/routes/openrouter.d.ts +4 -0
- package/dist/src/routes/openrouter.d.ts.map +1 -1
- package/dist/src/routes/openrouter.js +10 -1
- package/dist/src/routes/openrouter.js.map +1 -1
- package/dist/src/routes/organisms/gates.d.ts.map +1 -1
- package/dist/src/routes/organisms/gates.js +9 -2
- package/dist/src/routes/organisms/gates.js.map +1 -1
- package/dist/src/routes/portal.d.ts +1 -0
- package/dist/src/routes/portal.d.ts.map +1 -1
- package/dist/src/routes/portal.js +13 -0
- package/dist/src/routes/portal.js.map +1 -1
- package/dist/src/routes/schedules.d.ts +4 -0
- package/dist/src/routes/schedules.d.ts.map +1 -1
- package/dist/src/routes/schedules.js +9 -1
- package/dist/src/routes/schedules.js.map +1 -1
- package/dist/src/routes/storage-files.d.ts +23 -0
- package/dist/src/routes/storage-files.d.ts.map +1 -1
- package/dist/src/routes/storage-files.js +103 -82
- package/dist/src/routes/storage-files.js.map +1 -1
- package/dist/src/routes/workflows.d.ts.map +1 -1
- package/dist/src/routes/workflows.js +9 -1
- package/dist/src/routes/workflows.js.map +1 -1
- package/dist/src/server-bootstrap/routes-loader.d.ts +2 -0
- package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
- package/dist/src/server-bootstrap/routes-loader.js +22 -2
- package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
- package/dist/src/server-bootstrap/service-init.d.ts.map +1 -1
- package/dist/src/server-bootstrap/service-init.js +12 -7
- package/dist/src/server-bootstrap/service-init.js.map +1 -1
- package/dist/src/server-bootstrap/static-files.d.ts.map +1 -1
- package/dist/src/server-bootstrap/static-files.js +44 -10
- package/dist/src/server-bootstrap/static-files.js.map +1 -1
- package/dist/src/services/ai-allowance.d.ts +82 -0
- package/dist/src/services/ai-allowance.d.ts.map +1 -0
- package/dist/src/services/ai-allowance.js +117 -0
- package/dist/src/services/ai-allowance.js.map +1 -0
- package/dist/src/services/ai-completion.d.ts +102 -0
- package/dist/src/services/ai-completion.d.ts.map +1 -1
- package/dist/src/services/ai-completion.js +131 -67
- package/dist/src/services/ai-completion.js.map +1 -1
- package/dist/src/services/ai-image.d.ts +70 -0
- package/dist/src/services/ai-image.d.ts.map +1 -0
- package/dist/src/services/ai-image.js +104 -0
- package/dist/src/services/ai-image.js.map +1 -0
- package/dist/src/services/ai-model-defaults.d.ts +45 -0
- package/dist/src/services/ai-model-defaults.d.ts.map +1 -0
- package/dist/src/services/ai-model-defaults.js +42 -0
- package/dist/src/services/ai-model-defaults.js.map +1 -0
- package/dist/src/services/ai-tool-setup.d.ts +5 -1
- package/dist/src/services/ai-tool-setup.d.ts.map +1 -1
- package/dist/src/services/ai-tool-setup.js +36 -0
- package/dist/src/services/ai-tool-setup.js.map +1 -1
- package/dist/src/services/ai-transcription.d.ts +5 -0
- package/dist/src/services/ai-transcription.d.ts.map +1 -1
- package/dist/src/services/ai-transcription.js +5 -2
- package/dist/src/services/ai-transcription.js.map +1 -1
- package/dist/src/services/app-agent-surfaces.js +4 -4
- package/dist/src/services/app-agent-surfaces.js.map +1 -1
- package/dist/src/services/app-draft-edit.d.ts +144 -0
- package/dist/src/services/app-draft-edit.d.ts.map +1 -0
- package/dist/src/services/app-draft-edit.js +203 -0
- package/dist/src/services/app-draft-edit.js.map +1 -0
- package/dist/src/services/auth-md.js +2 -2
- package/dist/src/services/auth-md.js.map +1 -1
- package/dist/src/services/board-write.d.ts +11 -3
- package/dist/src/services/board-write.d.ts.map +1 -1
- package/dist/src/services/board-write.js +24 -3
- package/dist/src/services/board-write.js.map +1 -1
- package/dist/src/services/chat-agent.d.ts +36 -0
- package/dist/src/services/chat-agent.d.ts.map +1 -0
- package/dist/src/services/chat-agent.js +123 -0
- package/dist/src/services/chat-agent.js.map +1 -0
- package/dist/src/services/chat-session.d.ts +58 -0
- package/dist/src/services/chat-session.d.ts.map +1 -0
- package/dist/src/services/chat-session.js +151 -0
- package/dist/src/services/chat-session.js.map +1 -0
- package/dist/src/services/chat-threads.d.ts +61 -0
- package/dist/src/services/chat-threads.d.ts.map +1 -0
- package/dist/src/services/chat-threads.js +137 -0
- package/dist/src/services/chat-threads.js.map +1 -0
- package/dist/src/services/config-schema.d.ts.map +1 -1
- package/dist/src/services/config-schema.js +2 -1
- package/dist/src/services/config-schema.js.map +1 -1
- package/dist/src/services/datapackage/contract.d.ts +198 -0
- package/dist/src/services/datapackage/contract.d.ts.map +1 -0
- package/dist/src/services/datapackage/contract.js +140 -0
- package/dist/src/services/datapackage/contract.js.map +1 -0
- package/dist/src/services/datapackage/ext-capability.d.ts +85 -0
- package/dist/src/services/datapackage/ext-capability.d.ts.map +1 -0
- package/dist/src/services/datapackage/ext-capability.js +72 -0
- package/dist/src/services/datapackage/ext-capability.js.map +1 -0
- package/dist/src/services/datapackage/odata.d.ts +92 -0
- package/dist/src/services/datapackage/odata.d.ts.map +1 -0
- package/dist/src/services/datapackage/odata.js +256 -0
- package/dist/src/services/datapackage/odata.js.map +1 -0
- package/dist/src/services/datapackage/odps.d.ts +24 -0
- package/dist/src/services/datapackage/odps.d.ts.map +1 -0
- package/dist/src/services/datapackage/odps.js +183 -0
- package/dist/src/services/datapackage/odps.js.map +1 -0
- package/dist/src/services/datapackage/store.d.ts +143 -0
- package/dist/src/services/datapackage/store.d.ts.map +1 -0
- package/dist/src/services/datapackage/store.js +533 -0
- package/dist/src/services/datapackage/store.js.map +1 -0
- package/dist/src/services/datapackage/table.d.ts +67 -0
- package/dist/src/services/datapackage/table.d.ts.map +1 -0
- package/dist/src/services/datapackage/table.js +0 -0
- package/dist/src/services/datapackage/table.js.map +1 -0
- package/dist/src/services/extension-ctx.d.ts +1 -0
- package/dist/src/services/extension-ctx.d.ts.map +1 -1
- package/dist/src/services/extension-ctx.js +31 -6
- package/dist/src/services/extension-ctx.js.map +1 -1
- package/dist/src/services/extension-files.d.ts +20 -0
- package/dist/src/services/extension-files.d.ts.map +1 -1
- package/dist/src/services/extension-files.js +9 -2
- package/dist/src/services/extension-files.js.map +1 -1
- package/dist/src/services/extension-lifecycle.d.ts +3 -0
- package/dist/src/services/extension-lifecycle.d.ts.map +1 -1
- package/dist/src/services/extension-lifecycle.js +2 -26
- package/dist/src/services/extension-lifecycle.js.map +1 -1
- package/dist/src/services/extension-runtime.d.ts +28 -2
- package/dist/src/services/extension-runtime.d.ts.map +1 -1
- package/dist/src/services/extension-runtime.js +22 -0
- package/dist/src/services/extension-runtime.js.map +1 -1
- package/dist/src/services/extension-schedules.d.ts +90 -0
- package/dist/src/services/extension-schedules.d.ts.map +1 -0
- package/dist/src/services/extension-schedules.js +123 -0
- package/dist/src/services/extension-schedules.js.map +1 -0
- package/dist/src/services/extension-system-run.d.ts +91 -0
- package/dist/src/services/extension-system-run.d.ts.map +1 -0
- package/dist/src/services/extension-system-run.js +100 -0
- package/dist/src/services/extension-system-run.js.map +1 -0
- package/dist/src/services/extension-upsert.d.ts +2 -0
- package/dist/src/services/extension-upsert.d.ts.map +1 -1
- package/dist/src/services/extension-upsert.js +6 -24
- package/dist/src/services/extension-upsert.js.map +1 -1
- package/dist/src/services/goose-acp.d.ts +84 -0
- package/dist/src/services/goose-acp.d.ts.map +1 -0
- package/dist/src/services/goose-acp.js +304 -0
- package/dist/src/services/goose-acp.js.map +1 -0
- package/dist/src/services/markdown-negotiation.js +1 -1
- package/dist/src/services/markdown-negotiation.js.map +1 -1
- package/dist/src/services/openrouter.d.ts +43 -1
- package/dist/src/services/openrouter.d.ts.map +1 -1
- package/dist/src/services/openrouter.js +98 -1
- package/dist/src/services/openrouter.js.map +1 -1
- package/dist/src/services/prompt-defaults/tiers-core.js +4 -4
- package/dist/src/services/scheduler-extension-job.d.ts +29 -6
- package/dist/src/services/scheduler-extension-job.d.ts.map +1 -1
- package/dist/src/services/scheduler-extension-job.js +29 -75
- package/dist/src/services/scheduler-extension-job.js.map +1 -1
- package/dist/src/services/scope-vocabulary-migration.d.ts +34 -1
- package/dist/src/services/scope-vocabulary-migration.d.ts.map +1 -1
- package/dist/src/services/scope-vocabulary-migration.js +60 -0
- package/dist/src/services/scope-vocabulary-migration.js.map +1 -1
- package/dist/src/services/screenshot-capture.d.ts +40 -1
- package/dist/src/services/screenshot-capture.d.ts.map +1 -1
- package/dist/src/services/screenshot-capture.js +142 -60
- package/dist/src/services/screenshot-capture.js.map +1 -1
- package/dist/src/services/skill-bundle/generator.js +1 -1
- package/dist/src/services/skill-bundle/generic-adapter.js +1 -1
- package/dist/src/services/skill-bundle/hermes-adapter.js +1 -1
- package/dist/src/services/storage-file-write.d.ts +36 -1
- package/dist/src/services/storage-file-write.d.ts.map +1 -1
- package/dist/src/services/storage-file-write.js +49 -3
- package/dist/src/services/storage-file-write.js.map +1 -1
- package/dist/src/services/task-outcome.d.ts +53 -0
- package/dist/src/services/task-outcome.d.ts.map +1 -0
- package/dist/src/services/task-outcome.js +28 -0
- package/dist/src/services/task-outcome.js.map +1 -0
- package/dist/src/services/workflow/engine-human.d.ts +15 -0
- package/dist/src/services/workflow/engine-human.d.ts.map +1 -1
- package/dist/src/services/workflow/engine-human.js +10 -1
- package/dist/src/services/workflow/engine-human.js.map +1 -1
- package/dist/src/services/workflow/engine-steps.d.ts +48 -3
- package/dist/src/services/workflow/engine-steps.d.ts.map +1 -1
- package/dist/src/services/workflow/engine-steps.js +361 -0
- package/dist/src/services/workflow/engine-steps.js.map +1 -1
- package/dist/src/services/workflow/engine.d.ts +1 -0
- package/dist/src/services/workflow/engine.d.ts.map +1 -1
- package/dist/src/services/workflow/engine.js +2 -1
- package/dist/src/services/workflow/engine.js.map +1 -1
- package/dist/src/services/workflow/store.d.ts.map +1 -1
- package/dist/src/services/workflow/store.js +60 -4
- package/dist/src/services/workflow/store.js.map +1 -1
- package/dist/src/services/write-guards.d.ts +27 -1
- package/dist/src/services/write-guards.d.ts.map +1 -1
- package/dist/src/services/write-guards.js +39 -9
- package/dist/src/services/write-guards.js.map +1 -1
- package/dist/src/storage/providers/postgres-kysely/db-types.d.ts +1 -0
- package/dist/src/storage/providers/postgres-kysely/db-types.d.ts.map +1 -1
- package/dist/src/storage/providers/postgres-kysely/methods/app-grants.d.ts +1 -0
- package/dist/src/storage/providers/postgres-kysely/methods/app-grants.d.ts.map +1 -1
- package/dist/src/storage/providers/postgres-kysely/methods/app-grants.js +3 -0
- package/dist/src/storage/providers/postgres-kysely/methods/app-grants.js.map +1 -1
- package/dist/src/storage/providers/postgres-kysely/methods/files.d.ts +2 -0
- package/dist/src/storage/providers/postgres-kysely/methods/files.d.ts.map +1 -1
- package/dist/src/storage/providers/postgres-kysely/methods/files.js +34 -2
- package/dist/src/storage/providers/postgres-kysely/methods/files.js.map +1 -1
- package/dist/src/storage/providers/postgres-kysely/methods/wallet.d.ts.map +1 -1
- package/dist/src/storage/providers/postgres-kysely/methods/wallet.js +23 -4
- package/dist/src/storage/providers/postgres-kysely/methods/wallet.js.map +1 -1
- package/dist/src/storage/providers/postgres-kysely/migrations/0039_storage_file_utf8_verified.sql +19 -0
- package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/index.js +2 -1
- package/dist/src/storage/providers/sqlite/index.js.map +1 -1
- package/dist/src/storage/providers/sqlite/methods/apps.d.ts +1 -0
- package/dist/src/storage/providers/sqlite/methods/apps.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/methods/apps.js +33 -28
- package/dist/src/storage/providers/sqlite/methods/apps.js.map +1 -1
- package/dist/src/storage/providers/sqlite/methods/identity-nodes.d.ts +1 -12
- package/dist/src/storage/providers/sqlite/methods/identity-nodes.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/methods/identity-nodes.js +28 -135
- package/dist/src/storage/providers/sqlite/methods/identity-nodes.js.map +1 -1
- package/dist/src/storage/providers/sqlite/methods/storage-files.d.ts +38 -0
- package/dist/src/storage/providers/sqlite/methods/storage-files.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/methods/storage-files.js +109 -0
- package/dist/src/storage/providers/sqlite/methods/storage-files.js.map +1 -0
- package/dist/src/storage/providers/sqlite/methods/work.d.ts +5 -0
- package/dist/src/storage/providers/sqlite/methods/work.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/methods/work.js +34 -22
- package/dist/src/storage/providers/sqlite/methods/work.js.map +1 -1
- package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/schema.js +134 -130
- package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
- package/dist/src/storage/repositories/app-grant.repository.d.ts +11 -0
- package/dist/src/storage/repositories/app-grant.repository.d.ts.map +1 -1
- package/dist/src/storage/repositories/file.repository.d.ts +13 -0
- package/dist/src/storage/repositories/file.repository.d.ts.map +1 -1
- package/dist/src/storage/types/commerce.d.ts +6 -0
- package/dist/src/storage/types/commerce.d.ts.map +1 -1
- package/dist/src/utils/agent-footer.d.ts.map +1 -1
- package/dist/src/utils/agent-footer.js +1 -0
- package/dist/src/utils/agent-footer.js.map +1 -1
- package/dist/src/utils/app-content-type.d.ts +57 -3
- package/dist/src/utils/app-content-type.d.ts.map +1 -1
- package/dist/src/utils/app-content-type.js +81 -12
- package/dist/src/utils/app-content-type.js.map +1 -1
- package/dist/src/utils/env-config/sections-features.d.ts.map +1 -1
- package/dist/src/utils/env-config/sections-features.js +9 -3
- package/dist/src/utils/env-config/sections-features.js.map +1 -1
- package/dist/src/utils/file-download-headers.d.ts +5 -3
- package/dist/src/utils/file-download-headers.d.ts.map +1 -1
- package/dist/src/utils/file-download-headers.js +18 -5
- package/dist/src/utils/file-download-headers.js.map +1 -1
- package/dist/src/utils/http-range.d.ts +151 -0
- package/dist/src/utils/http-range.d.ts.map +1 -0
- package/dist/src/utils/http-range.js +190 -0
- package/dist/src/utils/http-range.js.map +1 -0
- package/dist/src/utils/page-head.d.ts +5 -0
- package/dist/src/utils/page-head.d.ts.map +1 -1
- package/dist/src/utils/page-head.js +10 -1
- package/dist/src/utils/page-head.js.map +1 -1
- package/dist/src/utils/reserved-keys.d.ts +4 -1
- package/dist/src/utils/reserved-keys.d.ts.map +1 -1
- package/dist/src/utils/reserved-keys.js +4 -1
- package/dist/src/utils/reserved-keys.js.map +1 -1
- package/dist/static/sdk-libs/datapackage/index.js +336 -0
- package/dist/static/sdk-libs/dist/aimeat-datapackage.js +305 -0
- package/package.json +10 -2
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file datapackage/index.js
|
|
3
|
+
* @description The aimeat-datapackage library — AIMEAT.datapackage. Build, check, publish and read
|
|
4
|
+
* a Frictionless Data Package with AIMEAT provenance, without an app parsing CSV, inferring a
|
|
5
|
+
* type, computing a hash or assembling a provenance block itself.
|
|
6
|
+
*
|
|
7
|
+
* IT IS A CLIENT, NOT A SECOND IMPLEMENTATION, and that is the whole design. A package's identity
|
|
8
|
+
* is a content hash: two pieces of code that compute it differently produce two identities for the
|
|
9
|
+
* same bytes, and every consumer pinned to a hash breaks silently. This node has already paid for
|
|
10
|
+
* that shape once, which is why `ctx.hash` is published as source (EXT_HASH_REFERENCE_JS) rather
|
|
11
|
+
* than described. So the inference, the quality gate, the canonical CSV and the hash all happen on
|
|
12
|
+
* the server, in services/datapackage/, and this library carries the rows there and brings the
|
|
13
|
+
* answer back. An app, an extension and an agent therefore cannot disagree about what a package is.
|
|
14
|
+
*
|
|
15
|
+
* WHAT AN APP STILL GETS LOCALLY: the shape of the work. `create()` gives a small builder so a
|
|
16
|
+
* page can accumulate resources and provenance as the user fills a form, `validate()` shows the
|
|
17
|
+
* row and the column before anything is stored, and `publish()` is one call at the end.
|
|
18
|
+
*
|
|
19
|
+
* THE ADDRESS IS NOT THIS LIBRARY. Every answer carries `descriptorUrl` — a permanent, auth-free,
|
|
20
|
+
* range-readable /v1/pub URL. That is what you give to DuckDB, pandas, frictionless-py, Excel or a
|
|
21
|
+
* person. Reading a package back through here is a convenience for a UI, not the road.
|
|
22
|
+
* @structure makeSession/authFetch · DataPackageBuilder (create) · publish/validate/inferSchema ·
|
|
23
|
+
* list/open/rows/exportAs · attach('datapackage', …)
|
|
24
|
+
* @usage
|
|
25
|
+
* <script src="/v1/libs/aimeat-auth.js"></script>
|
|
26
|
+
* <script src="/v1/libs/aimeat-datapackage.js"></script>
|
|
27
|
+
* const pkg = AIMEAT.datapackage.create({ name: 'laake-weekly' });
|
|
28
|
+
* pkg.addResource('rows', rows); // schema inferred unless you declare one
|
|
29
|
+
* const check = await pkg.validate(); // { ok, issues:[{row, field, message}], schemas }
|
|
30
|
+
* pkg.changes('Added the sentiment column');
|
|
31
|
+
* const out = await pkg.publish(); // { packageId, contentHash, descriptorUrl }
|
|
32
|
+
* @version-history
|
|
33
|
+
* v1.0.0 — 2026-08-15 — Initial (TARGET-063 vaihe 1, B1).
|
|
34
|
+
* v1.1.0 — 2026-08-15 — Three session.fetch contract errors fixed against a real browser (see call()),
|
|
35
|
+
* and parseTable() added so an app does not rebuild paste handling.
|
|
36
|
+
* v1.2.0 — 2026-08-16 — versions(): a package's history, each entry with the explanation it was
|
|
37
|
+
* published with, so an app can show a chain rather than a hash.
|
|
38
|
+
*/
|
|
39
|
+
import { makeSession } from '../_core/session.js';
|
|
40
|
+
const { authFetch } = makeSession('aimeat-datapackage.js');
|
|
41
|
+
import { attach } from '../_core/namespace.js';
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Unwrap the node envelope and turn a refusal into a thrown Error carrying `.code` and `.issues`.
|
|
45
|
+
*
|
|
46
|
+
* THREE THINGS ABOUT `session.fetch` THAT THIS FUNCTION GOT WRONG ON THE FIRST PASS, all of them
|
|
47
|
+
* invisible to a server-side test and all three caught the moment a real browser loaded the page:
|
|
48
|
+
* - it returns the PARSED envelope, not a `Response`. Calling `.json()` on it throws, and a
|
|
49
|
+
* swallowed throw here made every call answer `null`.
|
|
50
|
+
* - it does NOT throw on an error status — it hands back the envelope so a caller can look. So
|
|
51
|
+
* the refusal has to be read here, from `ok`/`error`, or a 422 reads as success.
|
|
52
|
+
* - it sets `Content-Type: application/json` itself. Passing our own duplicates the header and
|
|
53
|
+
* the body arrives empty at the route.
|
|
54
|
+
*/
|
|
55
|
+
async function call(path, opts) {
|
|
56
|
+
const body = await authFetch(path, opts);
|
|
57
|
+
if (!body || body.ok === false || body.error) {
|
|
58
|
+
const err = (body && body.error) || { code: 'REQUEST_FAILED', message: 'The request did not answer.' };
|
|
59
|
+
/** @type {Error & { code?: string, issues?: any[] }} */
|
|
60
|
+
const e = new Error(err.message || 'Request failed');
|
|
61
|
+
e.code = err.code;
|
|
62
|
+
// The quality gate's coordinates, so a page can point at the cell rather than say "invalid".
|
|
63
|
+
e.issues = (err.details && err.details.issues) || [];
|
|
64
|
+
throw e;
|
|
65
|
+
}
|
|
66
|
+
return body.data !== undefined ? body.data : body;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* A package under construction. Holds nothing but what you put in it — no rows are sent anywhere
|
|
71
|
+
* until you call validate() or publish().
|
|
72
|
+
*/
|
|
73
|
+
class DataPackageBuilder {
|
|
74
|
+
constructor(meta) {
|
|
75
|
+
this._meta = meta || {};
|
|
76
|
+
this._resources = [];
|
|
77
|
+
this._changes = '';
|
|
78
|
+
this._provenance = {};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Add one tabular resource.
|
|
83
|
+
*
|
|
84
|
+
* `opts.schema` omitted means INFER, and inference is a PROPOSAL: the published descriptor records
|
|
85
|
+
* `schemaSource: 'inferred'`, so a consumer can see that nobody confirmed the types. Call
|
|
86
|
+
* inferSchema() first, show the result to the person publishing, and pass the corrected schema
|
|
87
|
+
* here to publish as `declared`.
|
|
88
|
+
*/
|
|
89
|
+
addResource(name, rows, opts) {
|
|
90
|
+
const o = opts || {};
|
|
91
|
+
this._resources.push({
|
|
92
|
+
name,
|
|
93
|
+
rows: rows || [],
|
|
94
|
+
...(o.schema ? { schema: o.schema } : {}),
|
|
95
|
+
...(o.title ? { title: o.title } : {}),
|
|
96
|
+
...(o.description ? { description: o.description } : {}),
|
|
97
|
+
});
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** REQUIRED before publish: what moved against the previous version and why. */
|
|
102
|
+
changes(text) { this._changes = String(text || ''); return this; }
|
|
103
|
+
|
|
104
|
+
/** Origin, legal basis and licence. The owner is responsible for what they publish; this is where
|
|
105
|
+
* they say where it came from and on what terms. */
|
|
106
|
+
provenance(block) { this._provenance = Object.assign({}, this._provenance, block || {}); return this; }
|
|
107
|
+
|
|
108
|
+
/** How many old versions to keep, by count or by months. */
|
|
109
|
+
retention(policy) { this._retentionPolicy = policy; return this; }
|
|
110
|
+
|
|
111
|
+
/** What the producer was asked for — the window, the keywords. Travels in the descriptor. */
|
|
112
|
+
parameters(params) { this._parameters = params; return this; }
|
|
113
|
+
|
|
114
|
+
/** Run the quality gate WITHOUT publishing. Answers `{ ok, issues, schemas }`; `issues` name the
|
|
115
|
+
* resource, the row and the field, which is what lets a page highlight the cell. */
|
|
116
|
+
validate() {
|
|
117
|
+
return call('/v1/datapackages/validate', {
|
|
118
|
+
method: 'POST',
|
|
119
|
+
body: JSON.stringify({ resources: this._resources }),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Publish one version. THROWS when the gate refuses, with `.code === 'QUALITY_GATE'` and `.issues`
|
|
125
|
+
* carrying the coordinates — nothing was written, and the package stands on its previous version.
|
|
126
|
+
*
|
|
127
|
+
* `unchanged: true` in the answer means these exact bytes were already published: the address
|
|
128
|
+
* already holds them, and no new version was created. Say "no change" rather than "updated".
|
|
129
|
+
*/
|
|
130
|
+
publish() {
|
|
131
|
+
return call('/v1/datapackages', {
|
|
132
|
+
method: 'POST',
|
|
133
|
+
body: JSON.stringify(Object.assign({}, this._meta, {
|
|
134
|
+
changes: this._changes,
|
|
135
|
+
resources: this._resources,
|
|
136
|
+
provenance: this._provenance,
|
|
137
|
+
...(this._parameters ? { parameters: this._parameters } : {}),
|
|
138
|
+
...(this._retentionPolicy ? { retentionPolicy: this._retentionPolicy } : {}),
|
|
139
|
+
})),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Drop a leading byte-order mark. A spreadsheet export usually carries one, and left in place it
|
|
145
|
+
* becomes part of the FIRST COLUMN'S NAME — so the header a person sees and the key the rows carry
|
|
146
|
+
* quietly stop matching. Written as a code point: a raw BOM in source is invisible. */
|
|
147
|
+
const stripBom = (s) => (s.charCodeAt(0) === 0xFEFF ? s.slice(1) : s);
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Turn a pasted table into rows: CSV, TSV, semicolon-separated, or a JSON array of objects.
|
|
151
|
+
*
|
|
152
|
+
* THIS IS INPUT HANDLING, NOT THE CANONICAL READER, and the distinction is the whole reason it can
|
|
153
|
+
* live in the browser. It is deliberately lenient — it sniffs the delimiter, tolerates a BOM, CRLF
|
|
154
|
+
* and a ragged last line — because it is reading whatever a person pasted out of a spreadsheet. The
|
|
155
|
+
* canonical CSV reader is on the server and is deliberately exact, because it reads bytes this node
|
|
156
|
+
* itself wrote and hashed. Two parsers with two jobs; only one of them decides what a package IS.
|
|
157
|
+
*
|
|
158
|
+
* It lives here rather than in each app because otherwise every app rebuilds it, which is the exact
|
|
159
|
+
* duplication this library exists to prevent.
|
|
160
|
+
*/
|
|
161
|
+
function parseTable(text) {
|
|
162
|
+
const raw = stripBom(String(text || '')).trim();
|
|
163
|
+
if (!raw) return [];
|
|
164
|
+
if (raw[0] === '[' || raw[0] === '{') {
|
|
165
|
+
const parsed = JSON.parse(raw);
|
|
166
|
+
const rows = Array.isArray(parsed) ? parsed : [parsed];
|
|
167
|
+
if (!rows.every(r => r && typeof r === 'object' && !Array.isArray(r))) {
|
|
168
|
+
throw new Error('A JSON table must be an array of objects, one per row.');
|
|
169
|
+
}
|
|
170
|
+
return rows;
|
|
171
|
+
}
|
|
172
|
+
// Sniff the delimiter from the HEADER line only: a comma inside a quoted value further down
|
|
173
|
+
// must not outvote the separator the file actually uses.
|
|
174
|
+
const head = raw.split(/\r?\n/)[0];
|
|
175
|
+
/** @type {Array<{ ch: string, n: number }>} */
|
|
176
|
+
const counts = [{ ch: ',', n: 0 }, { ch: ';', n: 0 }, { ch: '\t', n: 0 }];
|
|
177
|
+
let q = false;
|
|
178
|
+
for (const ch of head) {
|
|
179
|
+
if (ch === '"') q = !q;
|
|
180
|
+
else if (!q) for (const c of counts) if (ch === c.ch) c.n++;
|
|
181
|
+
}
|
|
182
|
+
counts.sort((a, b) => b.n - a.n);
|
|
183
|
+
const delim = counts[0].n > 0 ? counts[0].ch : ',';
|
|
184
|
+
|
|
185
|
+
const records = [];
|
|
186
|
+
let field = '';
|
|
187
|
+
let record = [];
|
|
188
|
+
let inQuotes = false;
|
|
189
|
+
for (let i = 0; i < raw.length; i++) {
|
|
190
|
+
const ch = raw[i];
|
|
191
|
+
if (inQuotes) {
|
|
192
|
+
if (ch === '"') { if (raw[i + 1] === '"') { field += '"'; i++; } else inQuotes = false; }
|
|
193
|
+
else field += ch;
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (ch === '"') { inQuotes = true; continue; }
|
|
197
|
+
if (ch === delim) { record.push(field); field = ''; continue; }
|
|
198
|
+
if (ch === '\n' || ch === '\r') {
|
|
199
|
+
if (ch === '\r' && raw[i + 1] === '\n') i++;
|
|
200
|
+
record.push(field); field = ''; records.push(record); record = [];
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
field += ch;
|
|
204
|
+
}
|
|
205
|
+
if (field !== '' || record.length) { record.push(field); records.push(record); }
|
|
206
|
+
if (!records.length) return [];
|
|
207
|
+
|
|
208
|
+
const header = records[0].map((h, i) => (h.trim() || `column_${i + 1}`));
|
|
209
|
+
return records.slice(1)
|
|
210
|
+
.filter(r => r.length > 1 || (r[0] ?? '') !== '')
|
|
211
|
+
.map(r => {
|
|
212
|
+
const row = {};
|
|
213
|
+
// Values stay STRINGS here. Typing them is the server's job — a browser that eagerly turned
|
|
214
|
+
// "001000" into a number would destroy exactly the identifier the type inference protects.
|
|
215
|
+
for (let c = 0; c < header.length; c++) row[header[c]] = (r[c] ?? '') === '' ? null : r[c];
|
|
216
|
+
return row;
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const datapackage = {
|
|
221
|
+
/** Start a package. `meta` is `{ name, title?, description? }`; the name is an address segment. */
|
|
222
|
+
create(meta) { return new DataPackageBuilder(meta); },
|
|
223
|
+
|
|
224
|
+
/** CSV / TSV / semicolon / JSON text → rows. See parseTable above for why it is lenient. */
|
|
225
|
+
parseTable(text) { return parseTable(text); },
|
|
226
|
+
|
|
227
|
+
/** The type proposal for a set of rows, without publishing anything. Show it to the publisher. */
|
|
228
|
+
inferSchema(rows) {
|
|
229
|
+
return call('/v1/datapackages/validate', {
|
|
230
|
+
method: 'POST',
|
|
231
|
+
body: JSON.stringify({ resources: [{ name: 'preview', rows: rows || [] }] }),
|
|
232
|
+
}).then(d => d.schemas.preview);
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
/** One-shot publish for a caller that has everything already. Same refusal behaviour as the builder. */
|
|
236
|
+
publish(input) {
|
|
237
|
+
return call('/v1/datapackages', {
|
|
238
|
+
method: 'POST', body: JSON.stringify(input || {}),
|
|
239
|
+
});
|
|
240
|
+
},
|
|
241
|
+
|
|
242
|
+
/** The caller's own packages, newest version each, with `lastError` when the last run failed. */
|
|
243
|
+
list() { return call('/v1/datapackages', { method: 'GET' }); },
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Every version of one package, newest first: `{ contentHash, at, current, changes, rowCount,
|
|
247
|
+
* bytes, descriptorUrl, supersedes }`.
|
|
248
|
+
*
|
|
249
|
+
* `changes` is why this is worth showing rather than a list of hashes — it is the sentence the
|
|
250
|
+
* producer had to write to publish at all. Pin any of them by passing
|
|
251
|
+
* `pkg:owner/name@<contentHash>` to open() or rows().
|
|
252
|
+
*/
|
|
253
|
+
versions(ref) {
|
|
254
|
+
const p = parseRef(ref);
|
|
255
|
+
if (!p) return Promise.reject(new Error('versions() needs a reference like "pkg:owner/name"'));
|
|
256
|
+
return call('/v1/datapackages/' + encodeURIComponent(p.owner) + '/' + encodeURIComponent(p.name) + '/versions',
|
|
257
|
+
{ method: 'GET' });
|
|
258
|
+
},
|
|
259
|
+
|
|
260
|
+
/** A descriptor. `ref` is `pkg:owner/name`, optionally `@sha256:…` to pin a version. */
|
|
261
|
+
open(ref) {
|
|
262
|
+
const p = parseRef(ref);
|
|
263
|
+
if (!p) return Promise.reject(new Error('open() needs a reference like "pkg:owner/name" or "pkg:owner/name@sha256:…"'));
|
|
264
|
+
const q = p.version ? ('?version=' + encodeURIComponent(p.version)) : '';
|
|
265
|
+
return call('/v1/datapackages/' + encodeURIComponent(p.owner) + '/' + encodeURIComponent(p.name) + q, { method: 'GET' });
|
|
266
|
+
},
|
|
267
|
+
|
|
268
|
+
/** A window of rows, for a preview table. For the whole thing use the CSV address — it is
|
|
269
|
+
* permanent, needs no session and answers byte ranges. */
|
|
270
|
+
rows(ref, resource, opts) {
|
|
271
|
+
const p = parseRef(ref);
|
|
272
|
+
if (!p) return Promise.reject(new Error('rows() needs a reference like "pkg:owner/name"'));
|
|
273
|
+
const o = opts || {};
|
|
274
|
+
const qs = [];
|
|
275
|
+
if (p.version) qs.push('version=' + encodeURIComponent(p.version));
|
|
276
|
+
if (o.offset != null) qs.push('offset=' + encodeURIComponent(o.offset));
|
|
277
|
+
if (o.limit != null) qs.push('limit=' + encodeURIComponent(o.limit));
|
|
278
|
+
if (o.select && o.select.length) qs.push('select=' + encodeURIComponent(o.select.join(',')));
|
|
279
|
+
const q = qs.length ? ('?' + qs.join('&')) : '';
|
|
280
|
+
return call('/v1/datapackages/' + encodeURIComponent(p.owner) + '/' + encodeURIComponent(p.name)
|
|
281
|
+
+ '/rows/' + encodeURIComponent(resource) + q, { method: 'GET' });
|
|
282
|
+
},
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* The permanent, session-free address of one resource's CSV — what you hand to DuckDB, pandas,
|
|
286
|
+
* Google Sheets IMPORTDATA or a person with a download button.
|
|
287
|
+
*
|
|
288
|
+
* Derived from the descriptor rather than assembled from parts, because the descriptor's
|
|
289
|
+
* `resources[].path` is the authority on where a resource lives and a hand-built URL would be a
|
|
290
|
+
* second opinion about it.
|
|
291
|
+
*/
|
|
292
|
+
urlFor(descriptorResponse, resource) {
|
|
293
|
+
const d = descriptorResponse && (descriptorResponse.descriptor || descriptorResponse);
|
|
294
|
+
if (!d || !d.resources) return null;
|
|
295
|
+
const r = d.resources.find(x => x.name === resource);
|
|
296
|
+
const base = descriptorResponse && descriptorResponse.descriptor_url;
|
|
297
|
+
if (!r || !base) return null;
|
|
298
|
+
return base.replace(/datapackage\.json$/, '') + r.path.split('/').map(encodeURIComponent).join('/');
|
|
299
|
+
},
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Turn a resource into a file the person can keep. CSV is handed over as its permanent URL — no
|
|
303
|
+
* download, no copy, the address IS the file. JSON is derived in the browser from a row read.
|
|
304
|
+
*
|
|
305
|
+
* There is no XLSX here yet, and it is left out rather than half-done: a spreadsheet writer is a
|
|
306
|
+
* vendored dependency this node does not carry, and emitting a CSV named .xlsx would be exactly
|
|
307
|
+
* the covering fallback this whole format exists to avoid.
|
|
308
|
+
*/
|
|
309
|
+
async exportAs(ref, resource, format) {
|
|
310
|
+
const fmt = String(format || 'csv').toLowerCase();
|
|
311
|
+
const opened = await this.open(ref);
|
|
312
|
+
if (fmt === 'csv') return { url: this.urlFor(opened, resource), format: 'csv' };
|
|
313
|
+
if (fmt === 'json') {
|
|
314
|
+
const all = [];
|
|
315
|
+
let offset = 0;
|
|
316
|
+
for (;;) {
|
|
317
|
+
const page = await this.rows(ref, resource, { offset, limit: 5000 });
|
|
318
|
+
all.push.apply(all, page.rows);
|
|
319
|
+
offset += page.rows.length;
|
|
320
|
+
if (offset >= page.total || page.rows.length === 0) break;
|
|
321
|
+
}
|
|
322
|
+
const blob = new Blob([JSON.stringify(all, null, 2)], { type: 'application/json' });
|
|
323
|
+
return { url: URL.createObjectURL(blob), format: 'json', rows: all.length };
|
|
324
|
+
}
|
|
325
|
+
throw new Error('exportAs supports "csv" (the permanent URL) and "json". '
|
|
326
|
+
+ 'XLSX needs a spreadsheet writer this node does not vendor yet, and a CSV named .xlsx would be a lie.');
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
/** `pkg:owner/name` or `pkg:owner/name@sha256:…`. */
|
|
331
|
+
function parseRef(ref) {
|
|
332
|
+
const m = /^pkg:([^/@]+)\/([^@]+)(?:@(sha256:[a-f0-9]{64}))?$/.exec(String(ref || '').trim());
|
|
333
|
+
return m ? { owner: m[1], name: m[2], version: m[3] || null } : null;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
attach('datapackage', datapackage);
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
// GENERATED FILE — do not edit directly. Source: src/static/sdk-libs/datapackage/ (+ _core/).
|
|
2
|
+
// Rebuild: pnpm build:sdk · Served at /v1/libs/aimeat-datapackage.js (with a per-node config prelude).
|
|
3
|
+
"use strict";
|
|
4
|
+
(() => {
|
|
5
|
+
// src/static/sdk-libs/_core/session.js
|
|
6
|
+
function getSession(libLabel) {
|
|
7
|
+
const auth = window.AIMEAT && window.AIMEAT.auth;
|
|
8
|
+
if (!auth) {
|
|
9
|
+
throw new Error("AIMEAT.auth is required. Include aimeat-auth.js before " + (libLabel || "this library"));
|
|
10
|
+
}
|
|
11
|
+
const s = auth.getSession();
|
|
12
|
+
if (!s) throw new Error("Not logged in. Call AIMEAT.auth.login() first.");
|
|
13
|
+
return s;
|
|
14
|
+
}
|
|
15
|
+
function authFetch(path, opts, libLabel) {
|
|
16
|
+
return getSession(libLabel).fetch(path, opts);
|
|
17
|
+
}
|
|
18
|
+
function makeSession(libLabel) {
|
|
19
|
+
return {
|
|
20
|
+
getSession: () => getSession(libLabel),
|
|
21
|
+
authFetch: (path, opts) => authFetch(path, opts, libLabel)
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/static/sdk-libs/_core/namespace.js
|
|
26
|
+
function namespace() {
|
|
27
|
+
if (!window.AIMEAT) window.AIMEAT = {};
|
|
28
|
+
return window.AIMEAT;
|
|
29
|
+
}
|
|
30
|
+
function attach(key, value) {
|
|
31
|
+
const ns = namespace();
|
|
32
|
+
ns[key] = value;
|
|
33
|
+
return ns;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/static/sdk-libs/datapackage/index.js
|
|
37
|
+
var { authFetch: authFetch2 } = makeSession("aimeat-datapackage.js");
|
|
38
|
+
async function call(path, opts) {
|
|
39
|
+
const body = await authFetch2(path, opts);
|
|
40
|
+
if (!body || body.ok === false || body.error) {
|
|
41
|
+
const err = body && body.error || { code: "REQUEST_FAILED", message: "The request did not answer." };
|
|
42
|
+
const e = new Error(err.message || "Request failed");
|
|
43
|
+
e.code = err.code;
|
|
44
|
+
e.issues = err.details && err.details.issues || [];
|
|
45
|
+
throw e;
|
|
46
|
+
}
|
|
47
|
+
return body.data !== void 0 ? body.data : body;
|
|
48
|
+
}
|
|
49
|
+
var DataPackageBuilder = class {
|
|
50
|
+
constructor(meta) {
|
|
51
|
+
this._meta = meta || {};
|
|
52
|
+
this._resources = [];
|
|
53
|
+
this._changes = "";
|
|
54
|
+
this._provenance = {};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Add one tabular resource.
|
|
58
|
+
*
|
|
59
|
+
* `opts.schema` omitted means INFER, and inference is a PROPOSAL: the published descriptor records
|
|
60
|
+
* `schemaSource: 'inferred'`, so a consumer can see that nobody confirmed the types. Call
|
|
61
|
+
* inferSchema() first, show the result to the person publishing, and pass the corrected schema
|
|
62
|
+
* here to publish as `declared`.
|
|
63
|
+
*/
|
|
64
|
+
addResource(name, rows, opts) {
|
|
65
|
+
const o = opts || {};
|
|
66
|
+
this._resources.push({
|
|
67
|
+
name,
|
|
68
|
+
rows: rows || [],
|
|
69
|
+
...o.schema ? { schema: o.schema } : {},
|
|
70
|
+
...o.title ? { title: o.title } : {},
|
|
71
|
+
...o.description ? { description: o.description } : {}
|
|
72
|
+
});
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
/** REQUIRED before publish: what moved against the previous version and why. */
|
|
76
|
+
changes(text) {
|
|
77
|
+
this._changes = String(text || "");
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
/** Origin, legal basis and licence. The owner is responsible for what they publish; this is where
|
|
81
|
+
* they say where it came from and on what terms. */
|
|
82
|
+
provenance(block) {
|
|
83
|
+
this._provenance = Object.assign({}, this._provenance, block || {});
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
/** How many old versions to keep, by count or by months. */
|
|
87
|
+
retention(policy) {
|
|
88
|
+
this._retentionPolicy = policy;
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
91
|
+
/** What the producer was asked for — the window, the keywords. Travels in the descriptor. */
|
|
92
|
+
parameters(params) {
|
|
93
|
+
this._parameters = params;
|
|
94
|
+
return this;
|
|
95
|
+
}
|
|
96
|
+
/** Run the quality gate WITHOUT publishing. Answers `{ ok, issues, schemas }`; `issues` name the
|
|
97
|
+
* resource, the row and the field, which is what lets a page highlight the cell. */
|
|
98
|
+
validate() {
|
|
99
|
+
return call("/v1/datapackages/validate", {
|
|
100
|
+
method: "POST",
|
|
101
|
+
body: JSON.stringify({ resources: this._resources })
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Publish one version. THROWS when the gate refuses, with `.code === 'QUALITY_GATE'` and `.issues`
|
|
106
|
+
* carrying the coordinates — nothing was written, and the package stands on its previous version.
|
|
107
|
+
*
|
|
108
|
+
* `unchanged: true` in the answer means these exact bytes were already published: the address
|
|
109
|
+
* already holds them, and no new version was created. Say "no change" rather than "updated".
|
|
110
|
+
*/
|
|
111
|
+
publish() {
|
|
112
|
+
return call("/v1/datapackages", {
|
|
113
|
+
method: "POST",
|
|
114
|
+
body: JSON.stringify(Object.assign({}, this._meta, {
|
|
115
|
+
changes: this._changes,
|
|
116
|
+
resources: this._resources,
|
|
117
|
+
provenance: this._provenance,
|
|
118
|
+
...this._parameters ? { parameters: this._parameters } : {},
|
|
119
|
+
...this._retentionPolicy ? { retentionPolicy: this._retentionPolicy } : {}
|
|
120
|
+
}))
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
var stripBom = (s) => s.charCodeAt(0) === 65279 ? s.slice(1) : s;
|
|
125
|
+
function parseTable(text) {
|
|
126
|
+
const raw = stripBom(String(text || "")).trim();
|
|
127
|
+
if (!raw) return [];
|
|
128
|
+
if (raw[0] === "[" || raw[0] === "{") {
|
|
129
|
+
const parsed = JSON.parse(raw);
|
|
130
|
+
const rows = Array.isArray(parsed) ? parsed : [parsed];
|
|
131
|
+
if (!rows.every((r) => r && typeof r === "object" && !Array.isArray(r))) {
|
|
132
|
+
throw new Error("A JSON table must be an array of objects, one per row.");
|
|
133
|
+
}
|
|
134
|
+
return rows;
|
|
135
|
+
}
|
|
136
|
+
const head = raw.split(/\r?\n/)[0];
|
|
137
|
+
const counts = [{ ch: ",", n: 0 }, { ch: ";", n: 0 }, { ch: " ", n: 0 }];
|
|
138
|
+
let q = false;
|
|
139
|
+
for (const ch of head) {
|
|
140
|
+
if (ch === '"') q = !q;
|
|
141
|
+
else if (!q) {
|
|
142
|
+
for (const c of counts) if (ch === c.ch) c.n++;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
counts.sort((a, b) => b.n - a.n);
|
|
146
|
+
const delim = counts[0].n > 0 ? counts[0].ch : ",";
|
|
147
|
+
const records = [];
|
|
148
|
+
let field = "";
|
|
149
|
+
let record = [];
|
|
150
|
+
let inQuotes = false;
|
|
151
|
+
for (let i = 0; i < raw.length; i++) {
|
|
152
|
+
const ch = raw[i];
|
|
153
|
+
if (inQuotes) {
|
|
154
|
+
if (ch === '"') {
|
|
155
|
+
if (raw[i + 1] === '"') {
|
|
156
|
+
field += '"';
|
|
157
|
+
i++;
|
|
158
|
+
} else inQuotes = false;
|
|
159
|
+
} else field += ch;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (ch === '"') {
|
|
163
|
+
inQuotes = true;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (ch === delim) {
|
|
167
|
+
record.push(field);
|
|
168
|
+
field = "";
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (ch === "\n" || ch === "\r") {
|
|
172
|
+
if (ch === "\r" && raw[i + 1] === "\n") i++;
|
|
173
|
+
record.push(field);
|
|
174
|
+
field = "";
|
|
175
|
+
records.push(record);
|
|
176
|
+
record = [];
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
field += ch;
|
|
180
|
+
}
|
|
181
|
+
if (field !== "" || record.length) {
|
|
182
|
+
record.push(field);
|
|
183
|
+
records.push(record);
|
|
184
|
+
}
|
|
185
|
+
if (!records.length) return [];
|
|
186
|
+
const header = records[0].map((h, i) => h.trim() || `column_${i + 1}`);
|
|
187
|
+
return records.slice(1).filter((r) => r.length > 1 || (r[0] ?? "") !== "").map((r) => {
|
|
188
|
+
const row = {};
|
|
189
|
+
for (let c = 0; c < header.length; c++) row[header[c]] = (r[c] ?? "") === "" ? null : r[c];
|
|
190
|
+
return row;
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
var datapackage = {
|
|
194
|
+
/** Start a package. `meta` is `{ name, title?, description? }`; the name is an address segment. */
|
|
195
|
+
create(meta) {
|
|
196
|
+
return new DataPackageBuilder(meta);
|
|
197
|
+
},
|
|
198
|
+
/** CSV / TSV / semicolon / JSON text → rows. See parseTable above for why it is lenient. */
|
|
199
|
+
parseTable(text) {
|
|
200
|
+
return parseTable(text);
|
|
201
|
+
},
|
|
202
|
+
/** The type proposal for a set of rows, without publishing anything. Show it to the publisher. */
|
|
203
|
+
inferSchema(rows) {
|
|
204
|
+
return call("/v1/datapackages/validate", {
|
|
205
|
+
method: "POST",
|
|
206
|
+
body: JSON.stringify({ resources: [{ name: "preview", rows: rows || [] }] })
|
|
207
|
+
}).then((d) => d.schemas.preview);
|
|
208
|
+
},
|
|
209
|
+
/** One-shot publish for a caller that has everything already. Same refusal behaviour as the builder. */
|
|
210
|
+
publish(input) {
|
|
211
|
+
return call("/v1/datapackages", {
|
|
212
|
+
method: "POST",
|
|
213
|
+
body: JSON.stringify(input || {})
|
|
214
|
+
});
|
|
215
|
+
},
|
|
216
|
+
/** The caller's own packages, newest version each, with `lastError` when the last run failed. */
|
|
217
|
+
list() {
|
|
218
|
+
return call("/v1/datapackages", { method: "GET" });
|
|
219
|
+
},
|
|
220
|
+
/**
|
|
221
|
+
* Every version of one package, newest first: `{ contentHash, at, current, changes, rowCount,
|
|
222
|
+
* bytes, descriptorUrl, supersedes }`.
|
|
223
|
+
*
|
|
224
|
+
* `changes` is why this is worth showing rather than a list of hashes — it is the sentence the
|
|
225
|
+
* producer had to write to publish at all. Pin any of them by passing
|
|
226
|
+
* `pkg:owner/name@<contentHash>` to open() or rows().
|
|
227
|
+
*/
|
|
228
|
+
versions(ref) {
|
|
229
|
+
const p = parseRef(ref);
|
|
230
|
+
if (!p) return Promise.reject(new Error('versions() needs a reference like "pkg:owner/name"'));
|
|
231
|
+
return call(
|
|
232
|
+
"/v1/datapackages/" + encodeURIComponent(p.owner) + "/" + encodeURIComponent(p.name) + "/versions",
|
|
233
|
+
{ method: "GET" }
|
|
234
|
+
);
|
|
235
|
+
},
|
|
236
|
+
/** A descriptor. `ref` is `pkg:owner/name`, optionally `@sha256:…` to pin a version. */
|
|
237
|
+
open(ref) {
|
|
238
|
+
const p = parseRef(ref);
|
|
239
|
+
if (!p) return Promise.reject(new Error('open() needs a reference like "pkg:owner/name" or "pkg:owner/name@sha256:…"'));
|
|
240
|
+
const q = p.version ? "?version=" + encodeURIComponent(p.version) : "";
|
|
241
|
+
return call("/v1/datapackages/" + encodeURIComponent(p.owner) + "/" + encodeURIComponent(p.name) + q, { method: "GET" });
|
|
242
|
+
},
|
|
243
|
+
/** A window of rows, for a preview table. For the whole thing use the CSV address — it is
|
|
244
|
+
* permanent, needs no session and answers byte ranges. */
|
|
245
|
+
rows(ref, resource, opts) {
|
|
246
|
+
const p = parseRef(ref);
|
|
247
|
+
if (!p) return Promise.reject(new Error('rows() needs a reference like "pkg:owner/name"'));
|
|
248
|
+
const o = opts || {};
|
|
249
|
+
const qs = [];
|
|
250
|
+
if (p.version) qs.push("version=" + encodeURIComponent(p.version));
|
|
251
|
+
if (o.offset != null) qs.push("offset=" + encodeURIComponent(o.offset));
|
|
252
|
+
if (o.limit != null) qs.push("limit=" + encodeURIComponent(o.limit));
|
|
253
|
+
if (o.select && o.select.length) qs.push("select=" + encodeURIComponent(o.select.join(",")));
|
|
254
|
+
const q = qs.length ? "?" + qs.join("&") : "";
|
|
255
|
+
return call("/v1/datapackages/" + encodeURIComponent(p.owner) + "/" + encodeURIComponent(p.name) + "/rows/" + encodeURIComponent(resource) + q, { method: "GET" });
|
|
256
|
+
},
|
|
257
|
+
/**
|
|
258
|
+
* The permanent, session-free address of one resource's CSV — what you hand to DuckDB, pandas,
|
|
259
|
+
* Google Sheets IMPORTDATA or a person with a download button.
|
|
260
|
+
*
|
|
261
|
+
* Derived from the descriptor rather than assembled from parts, because the descriptor's
|
|
262
|
+
* `resources[].path` is the authority on where a resource lives and a hand-built URL would be a
|
|
263
|
+
* second opinion about it.
|
|
264
|
+
*/
|
|
265
|
+
urlFor(descriptorResponse, resource) {
|
|
266
|
+
const d = descriptorResponse && (descriptorResponse.descriptor || descriptorResponse);
|
|
267
|
+
if (!d || !d.resources) return null;
|
|
268
|
+
const r = d.resources.find((x) => x.name === resource);
|
|
269
|
+
const base = descriptorResponse && descriptorResponse.descriptor_url;
|
|
270
|
+
if (!r || !base) return null;
|
|
271
|
+
return base.replace(/datapackage\.json$/, "") + r.path.split("/").map(encodeURIComponent).join("/");
|
|
272
|
+
},
|
|
273
|
+
/**
|
|
274
|
+
* Turn a resource into a file the person can keep. CSV is handed over as its permanent URL — no
|
|
275
|
+
* download, no copy, the address IS the file. JSON is derived in the browser from a row read.
|
|
276
|
+
*
|
|
277
|
+
* There is no XLSX here yet, and it is left out rather than half-done: a spreadsheet writer is a
|
|
278
|
+
* vendored dependency this node does not carry, and emitting a CSV named .xlsx would be exactly
|
|
279
|
+
* the covering fallback this whole format exists to avoid.
|
|
280
|
+
*/
|
|
281
|
+
async exportAs(ref, resource, format) {
|
|
282
|
+
const fmt = String(format || "csv").toLowerCase();
|
|
283
|
+
const opened = await this.open(ref);
|
|
284
|
+
if (fmt === "csv") return { url: this.urlFor(opened, resource), format: "csv" };
|
|
285
|
+
if (fmt === "json") {
|
|
286
|
+
const all = [];
|
|
287
|
+
let offset = 0;
|
|
288
|
+
for (; ; ) {
|
|
289
|
+
const page = await this.rows(ref, resource, { offset, limit: 5e3 });
|
|
290
|
+
all.push.apply(all, page.rows);
|
|
291
|
+
offset += page.rows.length;
|
|
292
|
+
if (offset >= page.total || page.rows.length === 0) break;
|
|
293
|
+
}
|
|
294
|
+
const blob = new Blob([JSON.stringify(all, null, 2)], { type: "application/json" });
|
|
295
|
+
return { url: URL.createObjectURL(blob), format: "json", rows: all.length };
|
|
296
|
+
}
|
|
297
|
+
throw new Error('exportAs supports "csv" (the permanent URL) and "json". XLSX needs a spreadsheet writer this node does not vendor yet, and a CSV named .xlsx would be a lie.');
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
function parseRef(ref) {
|
|
301
|
+
const m = /^pkg:([^/@]+)\/([^@]+)(?:@(sha256:[a-f0-9]{64}))?$/.exec(String(ref || "").trim());
|
|
302
|
+
return m ? { owner: m[1], name: m[2], version: m[3] || null } : null;
|
|
303
|
+
}
|
|
304
|
+
attach("datapackage", datapackage);
|
|
305
|
+
})();
|