@digital-science-dsl/dimensions-analytics-mcp 0.5.3
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/CHANGELOG.md +61 -0
- package/README.md +152 -0
- package/bin/dimensions-analytics-mcp-http.js +2 -0
- package/bin/dimensions-analytics-mcp.js +2 -0
- package/dist/client/auth/config-loaders.d.ts +22 -0
- package/dist/client/auth/config-loaders.d.ts.map +1 -0
- package/dist/client/auth/config-loaders.js +68 -0
- package/dist/client/auth/config-loaders.js.map +1 -0
- package/dist/client/auth/decorators/index.d.ts +7 -0
- package/dist/client/auth/decorators/index.d.ts.map +1 -0
- package/dist/client/auth/decorators/index.js +6 -0
- package/dist/client/auth/decorators/index.js.map +1 -0
- package/dist/client/auth/decorators/with-caching.d.ts +81 -0
- package/dist/client/auth/decorators/with-caching.d.ts.map +1 -0
- package/dist/client/auth/decorators/with-caching.js +168 -0
- package/dist/client/auth/decorators/with-caching.js.map +1 -0
- package/dist/client/auth/factory.d.ts +13 -0
- package/dist/client/auth/factory.d.ts.map +1 -0
- package/dist/client/auth/factory.js +29 -0
- package/dist/client/auth/factory.js.map +1 -0
- package/dist/client/auth/index.d.ts +7 -0
- package/dist/client/auth/index.d.ts.map +1 -0
- package/dist/client/auth/index.js +6 -0
- package/dist/client/auth/index.js.map +1 -0
- package/dist/client/auth/jwt-utils.d.ts +17 -0
- package/dist/client/auth/jwt-utils.d.ts.map +1 -0
- package/dist/client/auth/jwt-utils.js +33 -0
- package/dist/client/auth/jwt-utils.js.map +1 -0
- package/dist/client/auth/node.d.ts +16 -0
- package/dist/client/auth/node.d.ts.map +1 -0
- package/dist/client/auth/node.js +15 -0
- package/dist/client/auth/node.js.map +1 -0
- package/dist/client/auth/providers/index.d.ts +2 -0
- package/dist/client/auth/providers/index.d.ts.map +1 -0
- package/dist/client/auth/providers/index.js +2 -0
- package/dist/client/auth/providers/index.js.map +1 -0
- package/dist/client/auth/providers/jwt-auth-provider.d.ts +70 -0
- package/dist/client/auth/providers/jwt-auth-provider.d.ts.map +1 -0
- package/dist/client/auth/providers/jwt-auth-provider.js +134 -0
- package/dist/client/auth/providers/jwt-auth-provider.js.map +1 -0
- package/dist/client/auth/schemas.d.ts +19 -0
- package/dist/client/auth/schemas.d.ts.map +1 -0
- package/dist/client/auth/schemas.js +23 -0
- package/dist/client/auth/schemas.js.map +1 -0
- package/dist/client/auth/types.d.ts +25 -0
- package/dist/client/auth/types.d.ts.map +1 -0
- package/dist/client/auth/types.js +9 -0
- package/dist/client/auth/types.js.map +1 -0
- package/dist/client/command.d.ts +44 -0
- package/dist/client/command.d.ts.map +1 -0
- package/dist/client/command.js +23 -0
- package/dist/client/command.js.map +1 -0
- package/dist/client/config/index.d.ts +11 -0
- package/dist/client/config/index.d.ts.map +1 -0
- package/dist/client/config/index.js +8 -0
- package/dist/client/config/index.js.map +1 -0
- package/dist/client/config/loader.d.ts +27 -0
- package/dist/client/config/loader.d.ts.map +1 -0
- package/dist/client/config/loader.js +128 -0
- package/dist/client/config/loader.js.map +1 -0
- package/dist/client/config/node.d.ts +18 -0
- package/dist/client/config/node.d.ts.map +1 -0
- package/dist/client/config/node.js +17 -0
- package/dist/client/config/node.js.map +1 -0
- package/dist/client/config/schemas.d.ts +23 -0
- package/dist/client/config/schemas.d.ts.map +1 -0
- package/dist/client/config/schemas.js +24 -0
- package/dist/client/config/schemas.js.map +1 -0
- package/dist/client/config/types.d.ts +37 -0
- package/dist/client/config/types.d.ts.map +1 -0
- package/dist/client/config/types.js +6 -0
- package/dist/client/config/types.js.map +1 -0
- package/dist/client/config/unified-loader.d.ts +41 -0
- package/dist/client/config/unified-loader.d.ts.map +1 -0
- package/dist/client/config/unified-loader.js +86 -0
- package/dist/client/config/unified-loader.js.map +1 -0
- package/dist/client/config.d.ts +43 -0
- package/dist/client/config.d.ts.map +1 -0
- package/dist/client/config.js +56 -0
- package/dist/client/config.js.map +1 -0
- package/dist/client/deployment-config.d.ts +36 -0
- package/dist/client/deployment-config.d.ts.map +1 -0
- package/dist/client/deployment-config.js +79 -0
- package/dist/client/deployment-config.js.map +1 -0
- package/dist/client/errors.d.ts +180 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +253 -0
- package/dist/client/errors.js.map +1 -0
- package/dist/client/http-client.d.ts +215 -0
- package/dist/client/http-client.d.ts.map +1 -0
- package/dist/client/http-client.js +419 -0
- package/dist/client/http-client.js.map +1 -0
- package/dist/client/index.d.ts +28 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +18 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/internal-dsl-client.d.ts +30 -0
- package/dist/client/internal-dsl-client.d.ts.map +1 -0
- package/dist/client/internal-dsl-client.js +101 -0
- package/dist/client/internal-dsl-client.js.map +1 -0
- package/dist/client/rate-limiter.d.ts +79 -0
- package/dist/client/rate-limiter.d.ts.map +1 -0
- package/dist/client/rate-limiter.js +118 -0
- package/dist/client/rate-limiter.js.map +1 -0
- package/dist/client/resolve-api-key-user.d.ts +24 -0
- package/dist/client/resolve-api-key-user.d.ts.map +1 -0
- package/dist/client/resolve-api-key-user.js +80 -0
- package/dist/client/resolve-api-key-user.js.map +1 -0
- package/dist/client/types.d.ts +44 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +10 -0
- package/dist/client/types.js.map +1 -0
- package/dist/dsl/client.d.ts +330 -0
- package/dist/dsl/client.d.ts.map +1 -0
- package/dist/dsl/client.js +433 -0
- package/dist/dsl/client.js.map +1 -0
- package/dist/dsl/commands/apply-filters.d.ts +15 -0
- package/dist/dsl/commands/apply-filters.d.ts.map +1 -0
- package/dist/dsl/commands/apply-filters.js +29 -0
- package/dist/dsl/commands/apply-filters.js.map +1 -0
- package/dist/dsl/commands/facet/index.d.ts +6 -0
- package/dist/dsl/commands/facet/index.d.ts.map +1 -0
- package/dist/dsl/commands/facet/index.js +6 -0
- package/dist/dsl/commands/facet/index.js.map +1 -0
- package/dist/dsl/commands/facet/schemas.d.ts +71 -0
- package/dist/dsl/commands/facet/schemas.d.ts.map +1 -0
- package/dist/dsl/commands/facet/schemas.js +84 -0
- package/dist/dsl/commands/facet/schemas.js.map +1 -0
- package/dist/dsl/commands/functions/ClassifyCommand.d.ts +96 -0
- package/dist/dsl/commands/functions/ClassifyCommand.d.ts.map +1 -0
- package/dist/dsl/commands/functions/ClassifyCommand.js +95 -0
- package/dist/dsl/commands/functions/ClassifyCommand.js.map +1 -0
- package/dist/dsl/commands/functions/ExtractAffiliationsCommand.d.ts +86 -0
- package/dist/dsl/commands/functions/ExtractAffiliationsCommand.d.ts.map +1 -0
- package/dist/dsl/commands/functions/ExtractAffiliationsCommand.js +131 -0
- package/dist/dsl/commands/functions/ExtractAffiliationsCommand.js.map +1 -0
- package/dist/dsl/commands/functions/ExtractConceptsCommand.d.ts +73 -0
- package/dist/dsl/commands/functions/ExtractConceptsCommand.d.ts.map +1 -0
- package/dist/dsl/commands/functions/ExtractConceptsCommand.js +110 -0
- package/dist/dsl/commands/functions/ExtractConceptsCommand.js.map +1 -0
- package/dist/dsl/commands/functions/ExtractGrantsCommand.d.ts +66 -0
- package/dist/dsl/commands/functions/ExtractGrantsCommand.d.ts.map +1 -0
- package/dist/dsl/commands/functions/ExtractGrantsCommand.js +87 -0
- package/dist/dsl/commands/functions/ExtractGrantsCommand.js.map +1 -0
- package/dist/dsl/commands/functions/index.d.ts +10 -0
- package/dist/dsl/commands/functions/index.d.ts.map +1 -0
- package/dist/dsl/commands/functions/index.js +10 -0
- package/dist/dsl/commands/functions/index.js.map +1 -0
- package/dist/dsl/commands/index.d.ts +8 -0
- package/dist/dsl/commands/index.d.ts.map +1 -0
- package/dist/dsl/commands/index.js +7 -0
- package/dist/dsl/commands/index.js.map +1 -0
- package/dist/dsl/commands/validate-input.d.ts +18 -0
- package/dist/dsl/commands/validate-input.d.ts.map +1 -0
- package/dist/dsl/commands/validate-input.js +27 -0
- package/dist/dsl/commands/validate-input.js.map +1 -0
- package/dist/dsl/create-client.d.ts +32 -0
- package/dist/dsl/create-client.d.ts.map +1 -0
- package/dist/dsl/create-client.js +58 -0
- package/dist/dsl/create-client.js.map +1 -0
- package/dist/dsl/fluent-query-builder.d.ts +439 -0
- package/dist/dsl/fluent-query-builder.d.ts.map +1 -0
- package/dist/dsl/fluent-query-builder.js +534 -0
- package/dist/dsl/fluent-query-builder.js.map +1 -0
- package/dist/dsl/index.d.ts +32 -0
- package/dist/dsl/index.d.ts.map +1 -0
- package/dist/dsl/index.js +31 -0
- package/dist/dsl/index.js.map +1 -0
- package/dist/dsl/pagination.d.ts +82 -0
- package/dist/dsl/pagination.d.ts.map +1 -0
- package/dist/dsl/pagination.js +135 -0
- package/dist/dsl/pagination.js.map +1 -0
- package/dist/dsl/query-builder.d.ts +456 -0
- package/dist/dsl/query-builder.d.ts.map +1 -0
- package/dist/dsl/query-builder.js +994 -0
- package/dist/dsl/query-builder.js.map +1 -0
- package/dist/dsl/response-parser.d.ts +111 -0
- package/dist/dsl/response-parser.d.ts.map +1 -0
- package/dist/dsl/response-parser.js +210 -0
- package/dist/dsl/response-parser.js.map +1 -0
- package/dist/dsl/schema/cache.d.ts +52 -0
- package/dist/dsl/schema/cache.d.ts.map +1 -0
- package/dist/dsl/schema/cache.js +97 -0
- package/dist/dsl/schema/cache.js.map +1 -0
- package/dist/dsl/schema/extract.d.ts +18 -0
- package/dist/dsl/schema/extract.d.ts.map +1 -0
- package/dist/dsl/schema/extract.js +41 -0
- package/dist/dsl/schema/extract.js.map +1 -0
- package/dist/dsl/schema/index.d.ts +13 -0
- package/dist/dsl/schema/index.d.ts.map +1 -0
- package/dist/dsl/schema/index.js +12 -0
- package/dist/dsl/schema/index.js.map +1 -0
- package/dist/dsl/schema/load.d.ts +41 -0
- package/dist/dsl/schema/load.d.ts.map +1 -0
- package/dist/dsl/schema/load.js +119 -0
- package/dist/dsl/schema/load.js.map +1 -0
- package/dist/dsl/schema/store.d.ts +137 -0
- package/dist/dsl/schema/store.d.ts.map +1 -0
- package/dist/dsl/schema/store.js +204 -0
- package/dist/dsl/schema/store.js.map +1 -0
- package/dist/dsl/schema/structured-entities.d.ts +21 -0
- package/dist/dsl/schema/structured-entities.d.ts.map +1 -0
- package/dist/dsl/schema/structured-entities.js +39 -0
- package/dist/dsl/schema/structured-entities.js.map +1 -0
- package/dist/dsl/schema/summary.d.ts +51 -0
- package/dist/dsl/schema/summary.d.ts.map +1 -0
- package/dist/dsl/schema/summary.js +61 -0
- package/dist/dsl/schema/summary.js.map +1 -0
- package/dist/dsl/schema/types.d.ts +36 -0
- package/dist/dsl/schema/types.d.ts.map +1 -0
- package/dist/dsl/schema/types.js +6 -0
- package/dist/dsl/schema/types.js.map +1 -0
- package/dist/dsl/schema/validation.d.ts +21 -0
- package/dist/dsl/schema/validation.d.ts.map +1 -0
- package/dist/dsl/schema/validation.js +44 -0
- package/dist/dsl/schema/validation.js.map +1 -0
- package/dist/dsl/types/buckets.d.ts +18 -0
- package/dist/dsl/types/buckets.d.ts.map +1 -0
- package/dist/dsl/types/buckets.js +6 -0
- package/dist/dsl/types/buckets.js.map +1 -0
- package/dist/dsl/types/common.d.ts +91 -0
- package/dist/dsl/types/common.d.ts.map +1 -0
- package/dist/dsl/types/common.js +6 -0
- package/dist/dsl/types/common.js.map +1 -0
- package/dist/dsl/types/entities.d.ts +35 -0
- package/dist/dsl/types/entities.d.ts.map +1 -0
- package/dist/dsl/types/entities.js +11 -0
- package/dist/dsl/types/entities.js.map +1 -0
- package/dist/dsl/types/index.d.ts +12 -0
- package/dist/dsl/types/index.d.ts.map +1 -0
- package/dist/dsl/types/index.js +7 -0
- package/dist/dsl/types/index.js.map +1 -0
- package/dist/dsl/types/return-clauses.d.ts +107 -0
- package/dist/dsl/types/return-clauses.d.ts.map +1 -0
- package/dist/dsl/types/return-clauses.js +22 -0
- package/dist/dsl/types/return-clauses.js.map +1 -0
- package/dist/dsl/types/special-functions.d.ts +175 -0
- package/dist/dsl/types/special-functions.d.ts.map +1 -0
- package/dist/dsl/types/special-functions.js +25 -0
- package/dist/dsl/types/special-functions.js.map +1 -0
- package/dist/dsl/types/vocabulary.d.ts +21 -0
- package/dist/dsl/types/vocabulary.d.ts.map +1 -0
- package/dist/dsl/types/vocabulary.js +44 -0
- package/dist/dsl/types/vocabulary.js.map +1 -0
- package/dist/dsl/usage-policy.d.ts +87 -0
- package/dist/dsl/usage-policy.d.ts.map +1 -0
- package/dist/dsl/usage-policy.js +133 -0
- package/dist/dsl/usage-policy.js.map +1 -0
- package/dist/dsl/utils/escape.d.ts +24 -0
- package/dist/dsl/utils/escape.d.ts.map +1 -0
- package/dist/dsl/utils/escape.js +124 -0
- package/dist/dsl/utils/escape.js.map +1 -0
- package/dist/dsl/utils/sanitize.d.ts +13 -0
- package/dist/dsl/utils/sanitize.d.ts.map +1 -0
- package/dist/dsl/utils/sanitize.js +19 -0
- package/dist/dsl/utils/sanitize.js.map +1 -0
- package/dist/dsl/utils/string-utils.d.ts +35 -0
- package/dist/dsl/utils/string-utils.d.ts.map +1 -0
- package/dist/dsl/utils/string-utils.js +145 -0
- package/dist/dsl/utils/string-utils.js.map +1 -0
- package/dist/dsl/utils/validate-field-name.d.ts +11 -0
- package/dist/dsl/utils/validate-field-name.d.ts.map +1 -0
- package/dist/dsl/utils/validate-field-name.js +18 -0
- package/dist/dsl/utils/validate-field-name.js.map +1 -0
- package/dist/examples/dsl-examples.d.ts +11 -0
- package/dist/examples/dsl-examples.d.ts.map +1 -0
- package/dist/examples/dsl-examples.js +49 -0
- package/dist/examples/dsl-examples.js.map +1 -0
- package/dist/examples/usage-scenarios.d.ts +22 -0
- package/dist/examples/usage-scenarios.d.ts.map +1 -0
- package/dist/examples/usage-scenarios.js +173 -0
- package/dist/examples/usage-scenarios.js.map +1 -0
- package/dist/funder-org-names.d.ts +12 -0
- package/dist/funder-org-names.d.ts.map +1 -0
- package/dist/funder-org-names.js +30 -0
- package/dist/funder-org-names.js.map +1 -0
- package/dist/http-main.d.ts +7 -0
- package/dist/http-main.d.ts.map +1 -0
- package/dist/http-main.js +36 -0
- package/dist/http-main.js.map +1 -0
- package/dist/http.d.ts +29 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +173 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/kwq/build-query.d.ts +26 -0
- package/dist/kwq/build-query.d.ts.map +1 -0
- package/dist/kwq/build-query.js +37 -0
- package/dist/kwq/build-query.js.map +1 -0
- package/dist/kwq/concept-groups.d.ts +49 -0
- package/dist/kwq/concept-groups.d.ts.map +1 -0
- package/dist/kwq/concept-groups.js +55 -0
- package/dist/kwq/concept-groups.js.map +1 -0
- package/dist/kwq/dsl-assembler.d.ts +28 -0
- package/dist/kwq/dsl-assembler.d.ts.map +1 -0
- package/dist/kwq/dsl-assembler.js +124 -0
- package/dist/kwq/dsl-assembler.js.map +1 -0
- package/dist/kwq/ensemble.d.ts +38 -0
- package/dist/kwq/ensemble.d.ts.map +1 -0
- package/dist/kwq/ensemble.js +107 -0
- package/dist/kwq/ensemble.js.map +1 -0
- package/dist/kwq/index.d.ts +16 -0
- package/dist/kwq/index.d.ts.map +1 -0
- package/dist/kwq/index.js +14 -0
- package/dist/kwq/index.js.map +1 -0
- package/dist/kwq/types.d.ts +120 -0
- package/dist/kwq/types.d.ts.map +1 -0
- package/dist/kwq/types.js +11 -0
- package/dist/kwq/types.js.map +1 -0
- package/dist/lambda.d.ts +10 -0
- package/dist/lambda.d.ts.map +1 -0
- package/dist/lambda.js +4 -0
- package/dist/lambda.js.map +1 -0
- package/dist/main.d.ts +8 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +33 -0
- package/dist/main.js.map +1 -0
- package/dist/mcp/batch-fetch.d.ts +89 -0
- package/dist/mcp/batch-fetch.d.ts.map +1 -0
- package/dist/mcp/batch-fetch.js +178 -0
- package/dist/mcp/batch-fetch.js.map +1 -0
- package/dist/mcp/examples/dsl-examples.d.ts +21 -0
- package/dist/mcp/examples/dsl-examples.d.ts.map +1 -0
- package/dist/mcp/examples/dsl-examples.js +61 -0
- package/dist/mcp/examples/dsl-examples.js.map +1 -0
- package/dist/mcp/examples/usage-scenarios.d.ts +20 -0
- package/dist/mcp/examples/usage-scenarios.d.ts.map +1 -0
- package/dist/mcp/examples/usage-scenarios.js +169 -0
- package/dist/mcp/examples/usage-scenarios.js.map +1 -0
- package/dist/mcp/export-format.d.ts +43 -0
- package/dist/mcp/export-format.d.ts.map +1 -0
- package/dist/mcp/export-format.js +92 -0
- package/dist/mcp/export-format.js.map +1 -0
- package/dist/mcp/funder-org-names.d.ts +12 -0
- package/dist/mcp/funder-org-names.d.ts.map +1 -0
- package/dist/mcp/funder-org-names.js +30 -0
- package/dist/mcp/funder-org-names.js.map +1 -0
- package/dist/mcp/http-server.d.ts +20 -0
- package/dist/mcp/http-server.d.ts.map +1 -0
- package/dist/mcp/http-server.js +118 -0
- package/dist/mcp/http-server.js.map +1 -0
- package/dist/mcp/middleware/field-aliases.d.ts +97 -0
- package/dist/mcp/middleware/field-aliases.d.ts.map +1 -0
- package/dist/mcp/middleware/field-aliases.js +208 -0
- package/dist/mcp/middleware/field-aliases.js.map +1 -0
- package/dist/mcp/resources/schema.d.ts +13 -0
- package/dist/mcp/resources/schema.d.ts.map +1 -0
- package/dist/mcp/resources/schema.js +262 -0
- package/dist/mcp/resources/schema.js.map +1 -0
- package/dist/mcp/schema/context.d.ts +10 -0
- package/dist/mcp/schema/context.d.ts.map +1 -0
- package/dist/mcp/schema/context.js +6 -0
- package/dist/mcp/schema/context.js.map +1 -0
- package/dist/mcp/schema/index.d.ts +8 -0
- package/dist/mcp/schema/index.d.ts.map +1 -0
- package/dist/mcp/schema/index.js +6 -0
- package/dist/mcp/schema/index.js.map +1 -0
- package/dist/mcp/server.d.ts +56 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +168 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/shared-schema.d.ts +13 -0
- package/dist/mcp/shared-schema.d.ts.map +1 -0
- package/dist/mcp/shared-schema.js +28 -0
- package/dist/mcp/shared-schema.js.map +1 -0
- package/dist/mcp/tools/analytics-filters.d.ts +18 -0
- package/dist/mcp/tools/analytics-filters.d.ts.map +1 -0
- package/dist/mcp/tools/analytics-filters.js +35 -0
- package/dist/mcp/tools/analytics-filters.js.map +1 -0
- package/dist/mcp/tools/analytics.d.ts +16 -0
- package/dist/mcp/tools/analytics.d.ts.map +1 -0
- package/dist/mcp/tools/analytics.js +381 -0
- package/dist/mcp/tools/analytics.js.map +1 -0
- package/dist/mcp/tools/concept-profile.d.ts +14 -0
- package/dist/mcp/tools/concept-profile.d.ts.map +1 -0
- package/dist/mcp/tools/concept-profile.js +130 -0
- package/dist/mcp/tools/concept-profile.js.map +1 -0
- package/dist/mcp/tools/dataset-profile.d.ts +15 -0
- package/dist/mcp/tools/dataset-profile.d.ts.map +1 -0
- package/dist/mcp/tools/dataset-profile.js +194 -0
- package/dist/mcp/tools/dataset-profile.js.map +1 -0
- package/dist/mcp/tools/fetch-search-pages.d.ts +15 -0
- package/dist/mcp/tools/fetch-search-pages.d.ts.map +1 -0
- package/dist/mcp/tools/fetch-search-pages.js +237 -0
- package/dist/mcp/tools/fetch-search-pages.js.map +1 -0
- package/dist/mcp/tools/functions.d.ts +14 -0
- package/dist/mcp/tools/functions.d.ts.map +1 -0
- package/dist/mcp/tools/functions.js +87 -0
- package/dist/mcp/tools/functions.js.map +1 -0
- package/dist/mcp/tools/impact-chain.d.ts +15 -0
- package/dist/mcp/tools/impact-chain.d.ts.map +1 -0
- package/dist/mcp/tools/impact-chain.js +96 -0
- package/dist/mcp/tools/impact-chain.js.map +1 -0
- package/dist/mcp/tools/kwq.d.ts +19 -0
- package/dist/mcp/tools/kwq.d.ts.map +1 -0
- package/dist/mcp/tools/kwq.js +156 -0
- package/dist/mcp/tools/kwq.js.map +1 -0
- package/dist/mcp/tools/lookup.d.ts +14 -0
- package/dist/mcp/tools/lookup.d.ts.map +1 -0
- package/dist/mcp/tools/lookup.js +146 -0
- package/dist/mcp/tools/lookup.js.map +1 -0
- package/dist/mcp/tools/policy-profile.d.ts +15 -0
- package/dist/mcp/tools/policy-profile.d.ts.map +1 -0
- package/dist/mcp/tools/policy-profile.js +174 -0
- package/dist/mcp/tools/policy-profile.js.map +1 -0
- package/dist/mcp/tools/profile.d.ts +14 -0
- package/dist/mcp/tools/profile.d.ts.map +1 -0
- package/dist/mcp/tools/profile.js +349 -0
- package/dist/mcp/tools/profile.js.map +1 -0
- package/dist/mcp/tools/query.d.ts +16 -0
- package/dist/mcp/tools/query.d.ts.map +1 -0
- package/dist/mcp/tools/query.js +75 -0
- package/dist/mcp/tools/query.js.map +1 -0
- package/dist/mcp/tools/schema.d.ts +23 -0
- package/dist/mcp/tools/schema.d.ts.map +1 -0
- package/dist/mcp/tools/schema.js +124 -0
- package/dist/mcp/tools/schema.js.map +1 -0
- package/dist/mcp/tools/search-entity-metadata.d.ts +18 -0
- package/dist/mcp/tools/search-entity-metadata.d.ts.map +1 -0
- package/dist/mcp/tools/search-entity-metadata.js +221 -0
- package/dist/mcp/tools/search-entity-metadata.js.map +1 -0
- package/dist/mcp/tools/search-input.d.ts +58 -0
- package/dist/mcp/tools/search-input.d.ts.map +1 -0
- package/dist/mcp/tools/search-input.js +76 -0
- package/dist/mcp/tools/search-input.js.map +1 -0
- package/dist/mcp/tools/search.d.ts +24 -0
- package/dist/mcp/tools/search.d.ts.map +1 -0
- package/dist/mcp/tools/search.js +115 -0
- package/dist/mcp/tools/search.js.map +1 -0
- package/dist/mcp/utils.d.ts +82 -0
- package/dist/mcp/utils.d.ts.map +1 -0
- package/dist/mcp/utils.js +126 -0
- package/dist/mcp/utils.js.map +1 -0
- package/dist/middleware/field-aliases.d.ts +97 -0
- package/dist/middleware/field-aliases.d.ts.map +1 -0
- package/dist/middleware/field-aliases.js +208 -0
- package/dist/middleware/field-aliases.js.map +1 -0
- package/dist/resources/schema.d.ts +13 -0
- package/dist/resources/schema.d.ts.map +1 -0
- package/dist/resources/schema.js +204 -0
- package/dist/resources/schema.js.map +1 -0
- package/dist/schema/context.d.ts +10 -0
- package/dist/schema/context.d.ts.map +1 -0
- package/dist/schema/context.js +6 -0
- package/dist/schema/context.js.map +1 -0
- package/dist/schema/index.d.ts +9 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +6 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/load.d.ts +43 -0
- package/dist/schema/load.d.ts.map +1 -0
- package/dist/schema/load.js +139 -0
- package/dist/schema/load.js.map +1 -0
- package/dist/schema/store.d.ts +112 -0
- package/dist/schema/store.d.ts.map +1 -0
- package/dist/schema/store.js +173 -0
- package/dist/schema/store.js.map +1 -0
- package/dist/schema/structured-entities.d.ts +21 -0
- package/dist/schema/structured-entities.d.ts.map +1 -0
- package/dist/schema/structured-entities.js +39 -0
- package/dist/schema/structured-entities.js.map +1 -0
- package/dist/schema/types.d.ts +36 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +6 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/server.d.ts +57 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +144 -0
- package/dist/server.js.map +1 -0
- package/dist/telemetry.d.ts +172 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +233 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/tools/analytics-filters.d.ts +18 -0
- package/dist/tools/analytics-filters.d.ts.map +1 -0
- package/dist/tools/analytics-filters.js +35 -0
- package/dist/tools/analytics-filters.js.map +1 -0
- package/dist/tools/analytics.d.ts +16 -0
- package/dist/tools/analytics.d.ts.map +1 -0
- package/dist/tools/analytics.js +381 -0
- package/dist/tools/analytics.js.map +1 -0
- package/dist/tools/concept-profile.d.ts +14 -0
- package/dist/tools/concept-profile.d.ts.map +1 -0
- package/dist/tools/concept-profile.js +130 -0
- package/dist/tools/concept-profile.js.map +1 -0
- package/dist/tools/dataset-profile.d.ts +15 -0
- package/dist/tools/dataset-profile.d.ts.map +1 -0
- package/dist/tools/dataset-profile.js +194 -0
- package/dist/tools/dataset-profile.js.map +1 -0
- package/dist/tools/functions.d.ts +14 -0
- package/dist/tools/functions.d.ts.map +1 -0
- package/dist/tools/functions.js +294 -0
- package/dist/tools/functions.js.map +1 -0
- package/dist/tools/impact-chain.d.ts +15 -0
- package/dist/tools/impact-chain.d.ts.map +1 -0
- package/dist/tools/impact-chain.js +96 -0
- package/dist/tools/impact-chain.js.map +1 -0
- package/dist/tools/kwq.d.ts +19 -0
- package/dist/tools/kwq.d.ts.map +1 -0
- package/dist/tools/kwq.js +156 -0
- package/dist/tools/kwq.js.map +1 -0
- package/dist/tools/lookup.d.ts +14 -0
- package/dist/tools/lookup.d.ts.map +1 -0
- package/dist/tools/lookup.js +213 -0
- package/dist/tools/lookup.js.map +1 -0
- package/dist/tools/policy-profile.d.ts +15 -0
- package/dist/tools/policy-profile.d.ts.map +1 -0
- package/dist/tools/policy-profile.js +174 -0
- package/dist/tools/policy-profile.js.map +1 -0
- package/dist/tools/profile.d.ts +14 -0
- package/dist/tools/profile.d.ts.map +1 -0
- package/dist/tools/profile.js +349 -0
- package/dist/tools/profile.js.map +1 -0
- package/dist/tools/query.d.ts +16 -0
- package/dist/tools/query.d.ts.map +1 -0
- package/dist/tools/query.js +53 -0
- package/dist/tools/query.js.map +1 -0
- package/dist/tools/schema.d.ts +23 -0
- package/dist/tools/schema.d.ts.map +1 -0
- package/dist/tools/schema.js +124 -0
- package/dist/tools/schema.js.map +1 -0
- package/dist/tools/search-entity-metadata.d.ts +18 -0
- package/dist/tools/search-entity-metadata.d.ts.map +1 -0
- package/dist/tools/search-entity-metadata.js +221 -0
- package/dist/tools/search-entity-metadata.js.map +1 -0
- package/dist/tools/search.d.ts +23 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +110 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/solr-fields.d.ts +39 -0
- package/dist/tools/solr-fields.d.ts.map +1 -0
- package/dist/tools/solr-fields.js +40 -0
- package/dist/tools/solr-fields.js.map +1 -0
- package/dist/utils.d.ts +70 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +104 -0
- package/dist/utils.js.map +1 -0
- package/package.json +41 -0
- package/src/client/auth/config-loaders.ts +81 -0
- package/src/client/auth/decorators/index.ts +7 -0
- package/src/client/auth/decorators/with-caching.ts +237 -0
- package/src/client/auth/factory.ts +34 -0
- package/src/client/auth/index.ts +6 -0
- package/src/client/auth/jwt-utils.ts +36 -0
- package/src/client/auth/node.ts +16 -0
- package/src/client/auth/providers/index.ts +1 -0
- package/src/client/auth/providers/jwt-auth-provider.ts +153 -0
- package/src/client/auth/schemas.ts +25 -0
- package/src/client/auth/types.ts +30 -0
- package/src/client/command.ts +54 -0
- package/src/client/config/index.ts +15 -0
- package/src/client/config/loader.ts +155 -0
- package/src/client/config/node.ts +22 -0
- package/src/client/config/schemas.ts +28 -0
- package/src/client/config/types.ts +39 -0
- package/src/client/config/unified-loader.ts +118 -0
- package/src/client/config.ts +69 -0
- package/src/client/deployment-config.ts +98 -0
- package/src/client/errors.ts +295 -0
- package/src/client/http-client.ts +577 -0
- package/src/client/index.ts +68 -0
- package/src/client/internal-dsl-client.ts +128 -0
- package/src/client/rate-limiter.ts +139 -0
- package/src/client/resolve-api-key-user.ts +99 -0
- package/src/client/types.ts +44 -0
- package/src/dsl/client.ts +538 -0
- package/src/dsl/commands/apply-filters.ts +35 -0
- package/src/dsl/commands/facet/index.ts +12 -0
- package/src/dsl/commands/facet/schemas.ts +101 -0
- package/src/dsl/commands/functions/ClassifyCommand.ts +129 -0
- package/src/dsl/commands/functions/ExtractAffiliationsCommand.ts +163 -0
- package/src/dsl/commands/functions/ExtractConceptsCommand.ts +141 -0
- package/src/dsl/commands/functions/ExtractGrantsCommand.ts +112 -0
- package/src/dsl/commands/functions/index.ts +31 -0
- package/src/dsl/commands/index.ts +29 -0
- package/src/dsl/commands/validate-input.ts +29 -0
- package/src/dsl/create-client.ts +80 -0
- package/src/dsl/fluent-query-builder.ts +684 -0
- package/src/dsl/index.ts +206 -0
- package/src/dsl/pagination.ts +202 -0
- package/src/dsl/query-builder.ts +1120 -0
- package/src/dsl/response-parser.ts +299 -0
- package/src/dsl/schema/cache.ts +124 -0
- package/src/dsl/schema/extract.ts +44 -0
- package/src/dsl/schema/index.ts +50 -0
- package/src/dsl/schema/load.ts +160 -0
- package/src/dsl/schema/store.ts +253 -0
- package/src/dsl/schema/structured-entities.ts +44 -0
- package/src/dsl/schema/summary.ts +94 -0
- package/src/dsl/schema/types.ts +40 -0
- package/src/dsl/schema/validation.ts +56 -0
- package/src/dsl/types/buckets.ts +22 -0
- package/src/dsl/types/common.ts +99 -0
- package/src/dsl/types/entities.ts +43 -0
- package/src/dsl/types/index.ts +63 -0
- package/src/dsl/types/return-clauses.ts +147 -0
- package/src/dsl/types/special-functions.ts +220 -0
- package/src/dsl/types/vocabulary.ts +82 -0
- package/src/dsl/usage-policy.ts +219 -0
- package/src/dsl/utils/escape.ts +123 -0
- package/src/dsl/utils/sanitize.ts +21 -0
- package/src/dsl/utils/string-utils.ts +147 -0
- package/src/dsl/utils/validate-field-name.ts +19 -0
- package/src/http-main.ts +41 -0
- package/src/index.ts +14 -0
- package/src/main.ts +40 -0
- package/src/mcp/batch-fetch.ts +255 -0
- package/src/mcp/examples/dsl-examples.ts +66 -0
- package/src/mcp/examples/usage-scenarios.ts +185 -0
- package/src/mcp/export-format.ts +113 -0
- package/src/mcp/funder-org-names.ts +30 -0
- package/src/mcp/http-server.ts +148 -0
- package/src/mcp/middleware/field-aliases.ts +274 -0
- package/src/mcp/resources/schema.ts +364 -0
- package/src/mcp/schema/context.ts +11 -0
- package/src/mcp/schema/index.ts +38 -0
- package/src/mcp/server.ts +247 -0
- package/src/mcp/shared-schema.ts +34 -0
- package/src/mcp/tools/analytics-filters.ts +46 -0
- package/src/mcp/tools/analytics.ts +453 -0
- package/src/mcp/tools/fetch-search-pages.ts +329 -0
- package/src/mcp/tools/functions.ts +105 -0
- package/src/mcp/tools/lookup.ts +182 -0
- package/src/mcp/tools/query.ts +91 -0
- package/src/mcp/tools/schema.ts +147 -0
- package/src/mcp/tools/search-entity-metadata.ts +253 -0
- package/src/mcp/tools/search-input.ts +87 -0
- package/src/mcp/tools/search.ts +168 -0
- package/src/mcp/utils.ts +199 -0
- package/test/client/auth/config-loaders.test.ts +92 -0
- package/test/client/auth/decorators/with-caching.test.ts +482 -0
- package/test/client/auth/factory.test.ts +68 -0
- package/test/client/auth/providers/jwt-auth-provider.test.ts +398 -0
- package/test/client/auth/types.test.ts +18 -0
- package/test/client/command.test.ts +163 -0
- package/test/client/config/loader.test.ts +377 -0
- package/test/client/config/unified-loader.test.ts +136 -0
- package/test/client/deployment-config.test.ts +69 -0
- package/test/client/errors/index.test.ts +408 -0
- package/test/client/helpers/mock-fetch.ts +42 -0
- package/test/client/http-client.test.ts +1148 -0
- package/test/client/integration/auth-providers.integration.test.ts +186 -0
- package/test/client/internal-dsl-client.test.ts +76 -0
- package/test/client/rate-limiter.test.ts +204 -0
- package/test/client/resolve-api-key-user.test.ts +87 -0
- package/test/dsl/client.special-functions.test.ts +387 -0
- package/test/dsl/client.test.ts +457 -0
- package/test/dsl/commands/apply-filters.test.ts +147 -0
- package/test/dsl/commands/functions/ClassifyCommand.test.ts +170 -0
- package/test/dsl/commands/functions/ExtractAffiliationsCommand.test.ts +306 -0
- package/test/dsl/commands/functions/ExtractConceptsCommand.test.ts +136 -0
- package/test/dsl/commands/functions/ExtractGrantsCommand.test.ts +202 -0
- package/test/dsl/commands/search/filters.test.ts +42 -0
- package/test/dsl/fluent-query-builder.test.ts +865 -0
- package/test/dsl/integration/client.integration.test.ts +294 -0
- package/test/dsl/integration/facet-api.integration.test.ts +276 -0
- package/test/dsl/integration/field-existence.integration.test.ts +148 -0
- package/test/dsl/integration/fluent-api-docs-examples.integration.test.ts +988 -0
- package/test/dsl/integration/fluent-api.integration.test.ts +615 -0
- package/test/dsl/integration/search-helpers.ts +27 -0
- package/test/dsl/integration/special-functions.integration.test.ts +224 -0
- package/test/dsl/integration/test-config.ts +52 -0
- package/test/dsl/pagination.test.ts +86 -0
- package/test/dsl/query-builder.test.ts +1775 -0
- package/test/dsl/response-parser.test.ts +520 -0
- package/test/dsl/schema/cache.test.ts +53 -0
- package/test/dsl/schema/load.test.ts +165 -0
- package/test/dsl/schema/summary.test.ts +61 -0
- package/test/dsl/schema/validation.test.ts +46 -0
- package/test/dsl/time-series.test.ts +135 -0
- package/test/dsl/unnest.test.ts +151 -0
- package/test/dsl/usage-policy.test.ts +100 -0
- package/test/dsl/utils/escape.property.test.ts +109 -0
- package/test/dsl/utils/escape.test.ts +140 -0
- package/test/dsl/utils/validate-field-name.property.test.ts +99 -0
- package/test/dsl/utils/validate-field-name.test.ts +55 -0
- package/test/examples/dsl-examples.test.ts +29 -0
- package/test/examples/usage-scenarios.test.ts +90 -0
- package/test/fixtures/describe-schema.json +4000 -0
- package/test/funder-org-names.test.ts +20 -0
- package/test/helpers/schema-fixture.ts +18 -0
- package/test/helpers/tool-test-harness.ts +114 -0
- package/test/integration/assertions.ts +263 -0
- package/test/integration/env.ts +108 -0
- package/test/integration/harness.ts +307 -0
- package/test/integration/hosted-client.ts +56 -0
- package/test/integration/hosted-mocks.ts +81 -0
- package/test/integration/hosted-run.ts +86 -0
- package/test/integration/hosted.e2e.test.ts +101 -0
- package/test/integration/reporter.ts +100 -0
- package/test/integration/run.ts +74 -0
- package/test/integration/suites/analytics.integration.ts +72 -0
- package/test/integration/suites/functions.integration.ts +37 -0
- package/test/integration/suites/hosted-smoke.integration.ts +38 -0
- package/test/integration/suites/index.ts +22 -0
- package/test/integration/suites/lookup.integration.ts +57 -0
- package/test/integration/suites/query.integration.ts +49 -0
- package/test/integration/suites/resources.integration.ts +68 -0
- package/test/integration/suites/search.integration.ts +80 -0
- package/test/integration/types.ts +92 -0
- package/test/integration/verify-usage-scenarios.ts +162 -0
- package/test/mcp/export-format.test.ts +67 -0
- package/test/mcp/http-server.test.ts +80 -0
- package/test/middleware/field-aliases.test.ts +287 -0
- package/test/resources/schema.test.ts +28 -0
- package/test/schema/describe-contract.test.ts +24 -0
- package/test/schema/store.test.ts +45 -0
- package/test/server.test.ts +170 -0
- package/test/tools/analytics-filters.test.ts +35 -0
- package/test/tools/analytics.test.ts +419 -0
- package/test/tools/fetch-search-pages.test.ts +200 -0
- package/test/tools/functions.test.ts +153 -0
- package/test/tools/lookup.test.ts +296 -0
- package/test/tools/query.test.ts +100 -0
- package/test/tools/schema.test.ts +37 -0
- package/test/tools/search.test.ts +415 -0
- package/test/utils.test.ts +45 -0
- package/tsconfig.json +9 -0
- package/tsconfig.tsbuildinfo +1 -0
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@digital-science-dsl/dimensions-analytics-mcp",
|
|
3
|
+
"version": "0.5.3",
|
|
4
|
+
"description": "Dimensions Analytics MCP server for Dimensions DSL querying",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"dimensions-analytics-mcp": "bin/dimensions-analytics-mcp.js",
|
|
10
|
+
"dimensions-analytics-mcp-http": "bin/dimensions-analytics-mcp-http.js"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@modelcontextprotocol/sdk": "^1.27.0",
|
|
20
|
+
"zod": "4.3.6"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/express": "^5.0.0",
|
|
24
|
+
"fast-check": "^4.6.0",
|
|
25
|
+
"typescript": "^5.9.3"
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"registry": "https://registry.npmjs.org",
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/digital-science/dimensions-analytics-mcp.git",
|
|
34
|
+
"directory": "apps/mcp"
|
|
35
|
+
},
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsc && node -e \"const fs=require('fs');for (const f of ['dist/main.js','dist/http-main.js','bin/dimensions-analytics-mcp.js','bin/dimensions-analytics-mcp-http.js']) { if (!fs.existsSync(f)) continue; const c=fs.readFileSync(f,'utf8'); if (!c.startsWith('#!')) fs.writeFileSync(f,'#!/usr/bin/env node\\n'+c); }\" && chmod +x dist/main.js dist/http-main.js bin/dimensions-analytics-mcp.js bin/dimensions-analytics-mcp-http.js",
|
|
39
|
+
"typecheck": "tsc --noEmit"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loaders for JWT AuthConfig.
|
|
3
|
+
* @module client/auth/config-loaders
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { readFileSync } from "node:fs";
|
|
7
|
+
import { ValidationError } from "../errors.js";
|
|
8
|
+
import { JwtAuthConfigSchema } from "./schemas.js";
|
|
9
|
+
import type { AuthConfig, JwtAuthConfig } from "./types.js";
|
|
10
|
+
|
|
11
|
+
/** Options for loading config from environment variables. */
|
|
12
|
+
export interface FromEnvOptions {
|
|
13
|
+
/** Env prefix (default `DIMENSIONS` → `DIMENSIONS_API_KEY`) */
|
|
14
|
+
prefix?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Load JWT auth config from environment variables.
|
|
19
|
+
* @param type - Must be `"jwt"`
|
|
20
|
+
* @param options - Optional env prefix
|
|
21
|
+
* @returns Validated JwtAuthConfig
|
|
22
|
+
*/
|
|
23
|
+
export function fromEnv(type: "jwt", options?: FromEnvOptions): JwtAuthConfig {
|
|
24
|
+
if (type !== "jwt") {
|
|
25
|
+
throw new ValidationError("Only JWT auth is supported");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const envPrefix = options?.prefix ?? "DIMENSIONS";
|
|
29
|
+
const apiKey = process.env[`${envPrefix}_API_KEY`];
|
|
30
|
+
if (!apiKey) {
|
|
31
|
+
throw new ValidationError(`Missing required environment variable: ${envPrefix}_API_KEY`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const authUrl = process.env[`${envPrefix}_AUTH_URL`];
|
|
35
|
+
const tokenCacheDuration = process.env[`${envPrefix}_TOKEN_CACHE_DURATION`];
|
|
36
|
+
const timeout = process.env[`${envPrefix}_TIMEOUT`];
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
type: "jwt",
|
|
40
|
+
apiKey,
|
|
41
|
+
...(authUrl && { authUrl }),
|
|
42
|
+
...(tokenCacheDuration && {
|
|
43
|
+
tokenCacheDuration: Number.parseInt(tokenCacheDuration, 10),
|
|
44
|
+
}),
|
|
45
|
+
...(timeout && { timeout: Number.parseInt(timeout, 10) }),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Load JWT auth config from a JSON file. */
|
|
50
|
+
export function fromPath(filePath: string): AuthConfig {
|
|
51
|
+
let fileContent: string;
|
|
52
|
+
try {
|
|
53
|
+
fileContent = readFileSync(filePath, "utf-8");
|
|
54
|
+
} catch (error) {
|
|
55
|
+
throw new ValidationError(`Failed to read config file: ${filePath}`, {
|
|
56
|
+
cause: error instanceof Error ? error.message : String(error),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let parsed: unknown;
|
|
61
|
+
try {
|
|
62
|
+
parsed = JSON.parse(fileContent);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
throw new ValidationError(`Invalid JSON in config file: ${filePath}`, {
|
|
65
|
+
cause: error instanceof Error ? error.message : String(error),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return fromObject(parsed);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Validate and return JWT auth config from an object. */
|
|
73
|
+
export function fromObject(obj: unknown): AuthConfig {
|
|
74
|
+
const parseResult = JwtAuthConfigSchema.safeParse(obj);
|
|
75
|
+
if (!parseResult.success) {
|
|
76
|
+
throw new ValidationError(`Invalid auth configuration: ${parseResult.error.message}`, {
|
|
77
|
+
issues: parseResult.error.issues,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return parseResult.data;
|
|
81
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Caching decorator for AuthProvider.
|
|
3
|
+
* @module core/auth/decorators/with-caching
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { AuthConfig, AuthProvider } from "../types.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Configuration options for the caching decorator.
|
|
10
|
+
*/
|
|
11
|
+
export interface CachingOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Cache duration in milliseconds.
|
|
14
|
+
* Headers will be refreshed after this time.
|
|
15
|
+
* @default 3600000 (1 hour)
|
|
16
|
+
*/
|
|
17
|
+
cacheDurationMs?: number;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Buffer before expiry to trigger refresh, as a decimal (0-1).
|
|
21
|
+
* E.g., 0.1 means refresh when 90% of TTL has passed.
|
|
22
|
+
* @default 0.1
|
|
23
|
+
*/
|
|
24
|
+
expiryBuffer?: number;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Initial backoff delay in milliseconds after a failed fetch.
|
|
28
|
+
* Grows exponentially on consecutive failures up to {@link failureBackoffMaxMs}.
|
|
29
|
+
* @default 1000
|
|
30
|
+
*/
|
|
31
|
+
failureBackoffMs?: number;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Maximum backoff delay in milliseconds. Caps exponential growth.
|
|
35
|
+
* @default 60000
|
|
36
|
+
*/
|
|
37
|
+
failureBackoffMaxMs?: number;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Multiplication factor applied to the base delay on each consecutive failure.
|
|
41
|
+
* Set to 1 for flat (non-exponential) backoff.
|
|
42
|
+
* @default 2
|
|
43
|
+
*/
|
|
44
|
+
failureBackoffFactor?: number;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Jitter as a fraction of the computed delay (0–1), e.g. 0.1 = ±10%.
|
|
48
|
+
* Prevents thundering herd by spreading retry times across clients.
|
|
49
|
+
* Set to 0 for deterministic delays (useful in tests).
|
|
50
|
+
* @default 0.1
|
|
51
|
+
*/
|
|
52
|
+
failureBackoffJitter?: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Default cache duration: 1 hour */
|
|
56
|
+
const DEFAULT_CACHE_DURATION_MS = 3600000;
|
|
57
|
+
|
|
58
|
+
/** Default expiry buffer: 10% */
|
|
59
|
+
const DEFAULT_EXPIRY_BUFFER = 0.1;
|
|
60
|
+
|
|
61
|
+
/** Default failure backoff: 1 second */
|
|
62
|
+
const DEFAULT_FAILURE_BACKOFF_MS = 1000;
|
|
63
|
+
|
|
64
|
+
/** Default max backoff delay: 60 seconds */
|
|
65
|
+
const DEFAULT_FAILURE_BACKOFF_MAX_MS = 60_000;
|
|
66
|
+
|
|
67
|
+
/** Default backoff multiplication factor */
|
|
68
|
+
const DEFAULT_FAILURE_BACKOFF_FACTOR = 2;
|
|
69
|
+
|
|
70
|
+
/** Default jitter fraction: ±10% */
|
|
71
|
+
const DEFAULT_FAILURE_BACKOFF_JITTER = 0.1;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Wraps an AuthProvider with caching behavior.
|
|
75
|
+
*
|
|
76
|
+
* Features:
|
|
77
|
+
* - Caches getHeaders() results with configurable TTL
|
|
78
|
+
* - Deduplicates concurrent calls (reuses in-flight promise)
|
|
79
|
+
* - Calls underlying provider's getHeaders() when cache expires
|
|
80
|
+
* - Propagates errors (no stale fallback)
|
|
81
|
+
* - Implements exponential backoff with jitter after failures to prevent thundering herd
|
|
82
|
+
*
|
|
83
|
+
* @param provider - The AuthProvider to wrap
|
|
84
|
+
* @param options - Caching configuration
|
|
85
|
+
* @returns A new AuthProvider with caching behavior
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* const baseProvider = new JwtAuthProvider(config);
|
|
90
|
+
* const cachedProvider = withCaching(baseProvider, {
|
|
91
|
+
* cacheDurationMs: 3600000, // 1 hour
|
|
92
|
+
* expiryBuffer: 0.1, // Refresh at 90% of TTL
|
|
93
|
+
* failureBackoffMs: 1000, // Initial backoff: 1s
|
|
94
|
+
* failureBackoffMaxMs: 60000, // Cap at 60s
|
|
95
|
+
* failureBackoffFactor: 2, // Double each failure: 1s, 2s, 4s, 8s...
|
|
96
|
+
* failureBackoffJitter: 0.1, // ±10% jitter
|
|
97
|
+
* });
|
|
98
|
+
*
|
|
99
|
+
* // First call fetches headers
|
|
100
|
+
* const headers1 = await cachedProvider.getHeaders();
|
|
101
|
+
*
|
|
102
|
+
* // Subsequent calls return cached value
|
|
103
|
+
* const headers2 = await cachedProvider.getHeaders();
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export function withCaching(provider: AuthProvider, options?: CachingOptions): AuthProvider {
|
|
107
|
+
const cacheDurationMs = options?.cacheDurationMs ?? DEFAULT_CACHE_DURATION_MS;
|
|
108
|
+
const expiryBuffer = options?.expiryBuffer ?? DEFAULT_EXPIRY_BUFFER;
|
|
109
|
+
const failureBackoffMs = options?.failureBackoffMs ?? DEFAULT_FAILURE_BACKOFF_MS;
|
|
110
|
+
const failureBackoffMaxMs = options?.failureBackoffMaxMs ?? DEFAULT_FAILURE_BACKOFF_MAX_MS;
|
|
111
|
+
const failureBackoffFactor = options?.failureBackoffFactor ?? DEFAULT_FAILURE_BACKOFF_FACTOR;
|
|
112
|
+
const failureBackoffJitter = options?.failureBackoffJitter ?? DEFAULT_FAILURE_BACKOFF_JITTER;
|
|
113
|
+
|
|
114
|
+
let cachedHeaders: Record<string, string> | null = null;
|
|
115
|
+
let cacheExpiry = 0;
|
|
116
|
+
let refreshPromise: Promise<Record<string, string>> | null = null;
|
|
117
|
+
let failureCount = 0;
|
|
118
|
+
let backoffDeadline = 0;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Calculate the effective expiry time with buffer.
|
|
122
|
+
* @param durationMs - Full cache duration
|
|
123
|
+
* @returns Expiry timestamp with buffer applied
|
|
124
|
+
*/
|
|
125
|
+
const calculateExpiry = (durationMs: number): number => {
|
|
126
|
+
// Buffer is at least 1 minute, but never more than 90% of duration
|
|
127
|
+
const bufferMs = Math.min(Math.max(durationMs * expiryBuffer, 60000), durationMs * 0.9);
|
|
128
|
+
return Date.now() + durationMs - bufferMs;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Calculates the backoff delay for a given consecutive failure count.
|
|
133
|
+
* Uses exponential backoff with multiplicative jitter.
|
|
134
|
+
* @param count - Number of consecutive failures (must be >= 1)
|
|
135
|
+
* @returns Delay in milliseconds
|
|
136
|
+
*/
|
|
137
|
+
const calculateBackoffDelay = (count: number): number => {
|
|
138
|
+
const base = Math.min(
|
|
139
|
+
failureBackoffMs * failureBackoffFactor ** (count - 1),
|
|
140
|
+
failureBackoffMaxMs,
|
|
141
|
+
);
|
|
142
|
+
const jittered = base * (1 + (Math.random() - 0.5) * 2 * failureBackoffJitter);
|
|
143
|
+
return Math.max(0, jittered);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Check if we're in a backoff period after a failure.
|
|
148
|
+
* @returns True if still in backoff period
|
|
149
|
+
*/
|
|
150
|
+
const isInBackoffPeriod = (): boolean => {
|
|
151
|
+
if (backoffDeadline === 0) return false;
|
|
152
|
+
return Date.now() < backoffDeadline;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Fetch fresh headers from the underlying provider.
|
|
157
|
+
*
|
|
158
|
+
* Calls getHeaders() directly rather than refresh() + getHeaders().
|
|
159
|
+
* The provider's getHeaders() is self-sufficient (fetches a token when
|
|
160
|
+
* needed), so an explicit refresh() is unnecessary and creates a race
|
|
161
|
+
* window where invalidate() between the two calls triggers a redundant
|
|
162
|
+
* token fetch.
|
|
163
|
+
*
|
|
164
|
+
* @returns Fresh headers
|
|
165
|
+
*/
|
|
166
|
+
const fetchHeaders = async (): Promise<Record<string, string>> => {
|
|
167
|
+
try {
|
|
168
|
+
const headers = await provider.getHeaders();
|
|
169
|
+
cachedHeaders = headers;
|
|
170
|
+
cacheExpiry = calculateExpiry(cacheDurationMs);
|
|
171
|
+
failureCount = 0;
|
|
172
|
+
backoffDeadline = 0;
|
|
173
|
+
return headers;
|
|
174
|
+
} catch (error) {
|
|
175
|
+
failureCount += 1;
|
|
176
|
+
backoffDeadline = Date.now() + calculateBackoffDelay(failureCount);
|
|
177
|
+
throw error;
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const wrapper = {
|
|
182
|
+
get type(): AuthConfig["type"] {
|
|
183
|
+
return provider.type;
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
async initialize(): Promise<void> {
|
|
187
|
+
await provider.initialize();
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
async getHeaders(): Promise<Record<string, string>> {
|
|
191
|
+
// Return cached headers if valid
|
|
192
|
+
if (cachedHeaders && Date.now() < cacheExpiry) {
|
|
193
|
+
return cachedHeaders;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// If already refreshing, wait for that promise
|
|
197
|
+
if (refreshPromise) {
|
|
198
|
+
return refreshPromise;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Check backoff period - if in backoff, rethrow if no cache
|
|
202
|
+
if (isInBackoffPeriod()) {
|
|
203
|
+
if (cachedHeaders) {
|
|
204
|
+
// Return stale cache during backoff rather than failing
|
|
205
|
+
return cachedHeaders;
|
|
206
|
+
}
|
|
207
|
+
// No cache available and in backoff - we must try anyway
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Fetch new headers
|
|
211
|
+
refreshPromise = fetchHeaders();
|
|
212
|
+
try {
|
|
213
|
+
return await refreshPromise;
|
|
214
|
+
} finally {
|
|
215
|
+
refreshPromise = null;
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
async refresh(): Promise<void> {
|
|
220
|
+
cachedHeaders = null;
|
|
221
|
+
cacheExpiry = 0;
|
|
222
|
+
failureCount = 0;
|
|
223
|
+
backoffDeadline = 0;
|
|
224
|
+
await provider.refresh();
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
invalidate(): void {
|
|
228
|
+
cachedHeaders = null;
|
|
229
|
+
cacheExpiry = 0;
|
|
230
|
+
failureCount = 0;
|
|
231
|
+
backoffDeadline = 0;
|
|
232
|
+
provider.invalidate();
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
return wrapper;
|
|
237
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory function for creating JWT AuthProvider instances.
|
|
3
|
+
* @module client/auth/factory
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ValidationError } from "../errors.js";
|
|
7
|
+
import { withCaching } from "./decorators/index.js";
|
|
8
|
+
import { JwtAuthProvider } from "./providers/jwt-auth-provider.js";
|
|
9
|
+
import { JwtAuthConfigSchema } from "./schemas.js";
|
|
10
|
+
import type { AuthProvider, JwtAuthConfig } from "./types.js";
|
|
11
|
+
|
|
12
|
+
/** Default token cache duration for JWT: 1 hour */
|
|
13
|
+
const DEFAULT_TOKEN_CACHE_DURATION_MS = 3600000;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates a JWT AuthProvider with token caching.
|
|
17
|
+
* @param config - JWT authentication configuration
|
|
18
|
+
* @returns Configured AuthProvider instance
|
|
19
|
+
* @throws {ValidationError} If the configuration is invalid
|
|
20
|
+
*/
|
|
21
|
+
export function createAuthProvider(config: JwtAuthConfig): AuthProvider {
|
|
22
|
+
const parseResult = JwtAuthConfigSchema.safeParse(config);
|
|
23
|
+
if (!parseResult.success) {
|
|
24
|
+
throw new ValidationError(`Invalid auth configuration: ${parseResult.error.message}`, {
|
|
25
|
+
issues: parseResult.error.issues,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const validConfig = parseResult.data;
|
|
30
|
+
const jwtProvider = new JwtAuthProvider(validConfig);
|
|
31
|
+
const cacheDurationMs =
|
|
32
|
+
(validConfig.tokenCacheDuration ?? 3600) * 1000 || DEFAULT_TOKEN_CACHE_DURATION_MS;
|
|
33
|
+
return withCaching(jwtProvider, { cacheDurationMs });
|
|
34
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { fromEnv, fromObject, fromPath } from "./config-loaders.js";
|
|
2
|
+
export { createAuthProvider } from "./factory.js";
|
|
3
|
+
export { JwtAuthProvider } from "./providers/jwt-auth-provider.js";
|
|
4
|
+
export { AuthResponseSchema, JwtAuthConfigSchema } from "./schemas.js";
|
|
5
|
+
export type { AuthConfig, AuthProvider, JwtAuthConfig } from "./types.js";
|
|
6
|
+
export { isJwtAuthConfig } from "./types.js";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT structure validation for Dimensions auth responses.
|
|
3
|
+
* @module client/auth/jwt-utils
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { AuthenticationError } from "../errors.js";
|
|
7
|
+
|
|
8
|
+
const JWT_SEGMENT = /^[A-Za-z0-9_-]+$/;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Validates a JWT has three base64url segments.
|
|
12
|
+
* @param token - Raw token from auth response
|
|
13
|
+
* @returns The token string
|
|
14
|
+
* @throws {AuthenticationError} When structure is invalid
|
|
15
|
+
*/
|
|
16
|
+
export function validateJwtStructure(token: unknown): string {
|
|
17
|
+
if (typeof token !== "string") {
|
|
18
|
+
throw new AuthenticationError("Invalid token: expected string");
|
|
19
|
+
}
|
|
20
|
+
const parts = token.split(".");
|
|
21
|
+
if (parts.length !== 3 || parts.some((part) => !part || !JWT_SEGMENT.test(part))) {
|
|
22
|
+
throw new AuthenticationError("Invalid JWT structure");
|
|
23
|
+
}
|
|
24
|
+
return token;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Decodes the JWT payload (middle segment) without signature verification.
|
|
29
|
+
* Use only for tokens returned by a trusted auth.json endpoint.
|
|
30
|
+
*/
|
|
31
|
+
export function decodeJwtPayload(token: string): Record<string, unknown> {
|
|
32
|
+
const validated = validateJwtStructure(token);
|
|
33
|
+
const payloadSegment = validated.split(".")[1];
|
|
34
|
+
const json = Buffer.from(payloadSegment, "base64url").toString("utf8");
|
|
35
|
+
return JSON.parse(json) as Record<string, unknown>;
|
|
36
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js-only auth config loaders.
|
|
3
|
+
*
|
|
4
|
+
* These utilities read credentials from the filesystem and environment variables.
|
|
5
|
+
* They depend on `node:fs` and must not be imported in browser/edge contexts.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { fromEnv, fromPath } from "./node.js";
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* @module core/auth/node
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export type { FromEnvOptions } from "./config-loaders.js";
|
|
16
|
+
export { fromEnv, fromObject, fromPath } from "./config-loaders.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { JwtAuthProvider } from "./jwt-auth-provider.js";
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT authentication provider for Dimensions API.
|
|
3
|
+
* @module core/auth/providers/jwt-auth-provider
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { AuthenticationError, NetworkError, sanitizeErrorMessage } from "../../errors.js";
|
|
7
|
+
import { validateJwtStructure } from "../jwt-utils.js";
|
|
8
|
+
import { AuthResponseSchema } from "../schemas.js";
|
|
9
|
+
import type { AuthProvider, JwtAuthConfig } from "../types.js";
|
|
10
|
+
|
|
11
|
+
/** Default auth endpoint URL */
|
|
12
|
+
const DEFAULT_AUTH_URL = "https://app.dimensions.ai/api/auth.json";
|
|
13
|
+
|
|
14
|
+
/** Default request timeout in milliseconds */
|
|
15
|
+
const DEFAULT_TIMEOUT = 30000;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Authentication provider using JWT tokens from Dimensions API.
|
|
19
|
+
* Exchanges an API key for a short-lived JWT token.
|
|
20
|
+
*
|
|
21
|
+
* Note: This provider does NOT cache tokens internally. Use the withCaching()
|
|
22
|
+
* decorator if caching is needed.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* import { JwtAuthProvider } from "../../index.js";
|
|
27
|
+
* import { withCaching } from "../../index.js";
|
|
28
|
+
*
|
|
29
|
+
* const provider = new JwtAuthProvider({
|
|
30
|
+
* type: 'jwt',
|
|
31
|
+
* apiKey: 'your-api-key'
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* // Wrap with caching for production use
|
|
35
|
+
* const cachedProvider = withCaching(provider, {
|
|
36
|
+
* cacheDurationMs: 3600000 // 1 hour
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* const headers = await cachedProvider.getHeaders();
|
|
40
|
+
* // { Authorization: 'JWT eyJ...' }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export class JwtAuthProvider implements AuthProvider {
|
|
44
|
+
readonly type = "jwt" as const;
|
|
45
|
+
|
|
46
|
+
private readonly apiKey: string;
|
|
47
|
+
private readonly authUrl: string;
|
|
48
|
+
private readonly timeout: number;
|
|
49
|
+
|
|
50
|
+
private currentToken: string | null = null;
|
|
51
|
+
private initialized = false;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Creates a new JwtAuthProvider.
|
|
55
|
+
* @param config - JWT auth configuration
|
|
56
|
+
*/
|
|
57
|
+
constructor(config: JwtAuthConfig) {
|
|
58
|
+
this.apiKey = config.apiKey;
|
|
59
|
+
this.authUrl = config.authUrl ?? DEFAULT_AUTH_URL;
|
|
60
|
+
this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Initialize the provider by fetching an initial token.
|
|
65
|
+
* Called automatically on first getHeaders() if not called explicitly.
|
|
66
|
+
*/
|
|
67
|
+
async initialize(): Promise<void> {
|
|
68
|
+
if (this.initialized) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
await this.fetchToken();
|
|
72
|
+
this.initialized = true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get the Authorization header with JWT token.
|
|
77
|
+
* Fetches a new token if not initialized.
|
|
78
|
+
* @returns Headers object with Authorization header
|
|
79
|
+
*/
|
|
80
|
+
async getHeaders(): Promise<Record<string, string>> {
|
|
81
|
+
if (!this.currentToken) {
|
|
82
|
+
await this.fetchToken();
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
Authorization: `JWT ${this.currentToken}`,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Force refresh of the JWT token by fetching a new one.
|
|
91
|
+
*/
|
|
92
|
+
async refresh(): Promise<void> {
|
|
93
|
+
await this.fetchToken();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Invalidate the current token, forcing a refresh on next getHeaders().
|
|
98
|
+
*/
|
|
99
|
+
invalidate(): void {
|
|
100
|
+
this.currentToken = null;
|
|
101
|
+
this.initialized = false;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Fetches a new JWT token from the auth endpoint.
|
|
106
|
+
* @throws {AuthenticationError} If authentication fails
|
|
107
|
+
* @throws {NetworkError} If a network error occurs
|
|
108
|
+
*/
|
|
109
|
+
private async fetchToken(): Promise<void> {
|
|
110
|
+
const controller = new AbortController();
|
|
111
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
const response = await fetch(this.authUrl, {
|
|
115
|
+
method: "POST",
|
|
116
|
+
headers: {
|
|
117
|
+
"Content-Type": "application/json",
|
|
118
|
+
},
|
|
119
|
+
body: JSON.stringify({ key: this.apiKey }),
|
|
120
|
+
signal: controller.signal,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
if (!response.ok) {
|
|
124
|
+
throw new AuthenticationError(
|
|
125
|
+
`Authentication failed: ${response.status} ${response.statusText}`,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const rawData: unknown = await response.json();
|
|
130
|
+
const parseResult = AuthResponseSchema.safeParse(rawData);
|
|
131
|
+
|
|
132
|
+
if (!parseResult.success) {
|
|
133
|
+
throw new AuthenticationError(
|
|
134
|
+
`Invalid authentication response: ${parseResult.error.message}`,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Schema guarantees at least one non-empty token field
|
|
139
|
+
const rawToken = parseResult.data.token || parseResult.data.access_token;
|
|
140
|
+
this.currentToken = validateJwtStructure(rawToken);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
if (error instanceof AuthenticationError) {
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
146
|
+
throw new NetworkError("Authentication request timeout");
|
|
147
|
+
}
|
|
148
|
+
throw new NetworkError(`Authentication failed: ${sanitizeErrorMessage(error)}`);
|
|
149
|
+
} finally {
|
|
150
|
+
clearTimeout(timeoutId);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod schemas for JWT authentication configuration.
|
|
3
|
+
* @module client/auth/schemas
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
|
|
8
|
+
/** Zod schema for JWT auth configuration. */
|
|
9
|
+
export const JwtAuthConfigSchema = z.object({
|
|
10
|
+
type: z.literal("jwt"),
|
|
11
|
+
apiKey: z.string().min(1, "API key is required"),
|
|
12
|
+
authUrl: z.string().url().optional(),
|
|
13
|
+
tokenCacheDuration: z.number().positive().optional(),
|
|
14
|
+
timeout: z.number().positive().optional(),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
/** Zod schema for authentication API response. */
|
|
18
|
+
export const AuthResponseSchema = z
|
|
19
|
+
.object({
|
|
20
|
+
token: z.string().min(1, "token must be a non-empty string").optional(),
|
|
21
|
+
access_token: z.string().min(1, "access_token must be a non-empty string").optional(),
|
|
22
|
+
})
|
|
23
|
+
.refine((data) => data.token || data.access_token, {
|
|
24
|
+
message: "Either 'token' or 'access_token' field is required with a non-empty value",
|
|
25
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication provider types for Dimensions API key → JWT exchange.
|
|
3
|
+
* @module client/auth/types
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** Base interface for authentication providers. */
|
|
7
|
+
export interface AuthProvider {
|
|
8
|
+
readonly type: AuthConfig["type"];
|
|
9
|
+
initialize(): Promise<void>;
|
|
10
|
+
getHeaders(): Promise<Record<string, string>>;
|
|
11
|
+
refresh(): Promise<void>;
|
|
12
|
+
invalidate(): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** JWT auth configuration (Dimensions API key). */
|
|
16
|
+
export type AuthConfig = JwtAuthConfig;
|
|
17
|
+
|
|
18
|
+
/** Configuration for JWT-based authentication with Dimensions API. */
|
|
19
|
+
export interface JwtAuthConfig {
|
|
20
|
+
readonly type: "jwt";
|
|
21
|
+
readonly apiKey: string;
|
|
22
|
+
readonly authUrl?: string;
|
|
23
|
+
readonly tokenCacheDuration?: number;
|
|
24
|
+
readonly timeout?: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Type guard for JWT auth configuration. */
|
|
28
|
+
export function isJwtAuthConfig(config: AuthConfig): config is JwtAuthConfig {
|
|
29
|
+
return config.type === "jwt";
|
|
30
|
+
}
|