From 9020e1411e3c77ea892f4f4f52b283bce0bd8e8e Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Thu, 31 Oct 2024 17:33:43 -0700 Subject: [PATCH 01/17] initial commit --- reactions/sdk/javascript/.dockerignore | 1 + reactions/sdk/javascript/.gitignore | 2 + reactions/sdk/javascript/api-extractor.json | 454 +++ .../javascript/examples/simple/.dockerignore | 1 + .../sdk/javascript/examples/simple/.gitignore | 2 + .../sdk/javascript/examples/simple/Dockerfile | 16 + .../javascript/examples/simple/Reaction.yaml | 8 + .../examples/simple/ReactionProvider.yaml | 7 + .../examples/simple/package-lock.json | 51 + .../javascript/examples/simple/package.json | 16 + .../javascript/examples/simple/src/index.ts | 25 + .../javascript/examples/simple/tsconfig.json | 11 + reactions/sdk/javascript/package-lock.json | 2445 +++++++++++++++++ reactions/sdk/javascript/package.json | 27 + reactions/sdk/javascript/src/index.ts | 71 + .../src/types/BootstrapCompletedSignal.d.ts | 15 + .../src/types/BootstrapStartedSignal.d.ts | 15 + .../sdk/javascript/src/types/ChangeEvent.d.ts | 54 + .../javascript/src/types/ControlEvent.d.ts | 26 + .../javascript/src/types/ControlSignal.d.ts | 10 + .../javascript/src/types/DeletedSignal.d.ts | 15 + .../sdk/javascript/src/types/ResultEvent.d.ts | 17 + .../javascript/src/types/RunningSignal.d.ts | 15 + .../javascript/src/types/StoppedSignal.d.ts | 15 + .../javascript/src/types/UpdatePayload.d.ts | 24 + .../sdk/javascript/src/types/Versions.d.ts | 8 + reactions/sdk/javascript/tsconfig.json | 15 + typespec/.gitignore | 9 + typespec/notes.md | 2 + typespec/package-lock.json | 1538 +++++++++++ typespec/package.json | 26 + typespec/query-output/.gitignore | 1 + typespec/query-output/main.tsp | 83 + typespec/query-output/tspconfig.yaml | 23 + 34 files changed, 5048 insertions(+) create mode 100644 reactions/sdk/javascript/.dockerignore create mode 100644 reactions/sdk/javascript/.gitignore create mode 100644 reactions/sdk/javascript/api-extractor.json create mode 100644 reactions/sdk/javascript/examples/simple/.dockerignore create mode 100644 reactions/sdk/javascript/examples/simple/.gitignore create mode 100644 reactions/sdk/javascript/examples/simple/Dockerfile create mode 100644 reactions/sdk/javascript/examples/simple/Reaction.yaml create mode 100644 reactions/sdk/javascript/examples/simple/ReactionProvider.yaml create mode 100644 reactions/sdk/javascript/examples/simple/package-lock.json create mode 100644 reactions/sdk/javascript/examples/simple/package.json create mode 100644 reactions/sdk/javascript/examples/simple/src/index.ts create mode 100644 reactions/sdk/javascript/examples/simple/tsconfig.json create mode 100644 reactions/sdk/javascript/package-lock.json create mode 100644 reactions/sdk/javascript/package.json create mode 100644 reactions/sdk/javascript/src/index.ts create mode 100644 reactions/sdk/javascript/src/types/BootstrapCompletedSignal.d.ts create mode 100644 reactions/sdk/javascript/src/types/BootstrapStartedSignal.d.ts create mode 100644 reactions/sdk/javascript/src/types/ChangeEvent.d.ts create mode 100644 reactions/sdk/javascript/src/types/ControlEvent.d.ts create mode 100644 reactions/sdk/javascript/src/types/ControlSignal.d.ts create mode 100644 reactions/sdk/javascript/src/types/DeletedSignal.d.ts create mode 100644 reactions/sdk/javascript/src/types/ResultEvent.d.ts create mode 100644 reactions/sdk/javascript/src/types/RunningSignal.d.ts create mode 100644 reactions/sdk/javascript/src/types/StoppedSignal.d.ts create mode 100644 reactions/sdk/javascript/src/types/UpdatePayload.d.ts create mode 100644 reactions/sdk/javascript/src/types/Versions.d.ts create mode 100644 reactions/sdk/javascript/tsconfig.json create mode 100644 typespec/.gitignore create mode 100644 typespec/notes.md create mode 100644 typespec/package-lock.json create mode 100644 typespec/package.json create mode 100644 typespec/query-output/.gitignore create mode 100644 typespec/query-output/main.tsp create mode 100644 typespec/query-output/tspconfig.yaml diff --git a/reactions/sdk/javascript/.dockerignore b/reactions/sdk/javascript/.dockerignore new file mode 100644 index 00000000..b512c09d --- /dev/null +++ b/reactions/sdk/javascript/.dockerignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/reactions/sdk/javascript/.gitignore b/reactions/sdk/javascript/.gitignore new file mode 100644 index 00000000..76add878 --- /dev/null +++ b/reactions/sdk/javascript/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/reactions/sdk/javascript/api-extractor.json b/reactions/sdk/javascript/api-extractor.json new file mode 100644 index 00000000..4e1f7be9 --- /dev/null +++ b/reactions/sdk/javascript/api-extractor.json @@ -0,0 +1,454 @@ +/** + * Config file for API Extractor. For more info, please visit: https://api-extractor.com + */ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + + /** + * Optionally specifies another JSON config file that this file extends from. This provides a way for + * standard settings to be shared across multiple projects. + * + * If the path starts with "./" or "../", the path is resolved relative to the folder of the file that contains + * the "extends" field. Otherwise, the first path segment is interpreted as an NPM package name, and will be + * resolved using NodeJS require(). + * + * SUPPORTED TOKENS: none + * DEFAULT VALUE: "" + */ + // "extends": "./shared/api-extractor-base.json" + // "extends": "my-package/include/api-extractor-base.json" + + /** + * Determines the "" token that can be used with other config file settings. The project folder + * typically contains the tsconfig.json and package.json config files, but the path is user-defined. + * + * The path is resolved relative to the folder of the config file that contains the setting. + * + * The default value for "projectFolder" is the token "", which means the folder is determined by traversing + * parent folders, starting from the folder containing api-extractor.json, and stopping at the first folder + * that contains a tsconfig.json file. If a tsconfig.json file cannot be found in this way, then an error + * will be reported. + * + * SUPPORTED TOKENS: + * DEFAULT VALUE: "" + */ + // "projectFolder": "..", + + /** + * (REQUIRED) Specifies the .d.ts file to be used as the starting point for analysis. API Extractor + * analyzes the symbols exported by this module. + * + * The file extension must be ".d.ts" and not ".ts". + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * SUPPORTED TOKENS: , , + */ + "mainEntryPointFilePath": "/lib/index.d.ts", + + /** + * A list of NPM package names whose exports should be treated as part of this package. + * + * For example, suppose that Webpack is used to generate a distributed bundle for the project "library1", + * and another NPM package "library2" is embedded in this bundle. Some types from library2 may become part + * of the exported API for library1, but by default API Extractor would generate a .d.ts rollup that explicitly + * imports library2. To avoid this, we might specify: + * + * "bundledPackages": [ "library2" ], + * + * This would direct API Extractor to embed those types directly in the .d.ts rollup, as if they had been + * local files for library1. + * + * The "bundledPackages" elements may specify glob patterns using minimatch syntax. To ensure deterministic + * output, globs are expanded by matching explicitly declared top-level dependencies only. For example, + * the pattern below will NOT match "@my-company/example" unless it appears in a field such as "dependencies" + * or "devDependencies" of the project's package.json file: + * + * "bundledPackages": [ "@my-company/*" ], + */ + "bundledPackages": [], + + /** + * Specifies what type of newlines API Extractor should use when writing output files. By default, the output files + * will be written with Windows-style newlines. To use POSIX-style newlines, specify "lf" instead. + * To use the OS's default newline kind, specify "os". + * + * DEFAULT VALUE: "crlf" + */ + // "newlineKind": "crlf", + + /** + * Specifies how API Extractor sorts members of an enum when generating the .api.json file. By default, the output + * files will be sorted alphabetically, which is "by-name". To keep the ordering in the source code, specify + * "preserve". + * + * DEFAULT VALUE: "by-name" + */ + // "enumMemberOrder": "by-name", + + /** + * Set to true when invoking API Extractor's test harness. When `testMode` is true, the `toolVersion` field in the + * .api.json file is assigned an empty string to prevent spurious diffs in output files tracked for tests. + * + * DEFAULT VALUE: "false" + */ + // "testMode": false, + + /** + * Determines how the TypeScript compiler engine will be invoked by API Extractor. + */ + "compiler": { + /** + * Specifies the path to the tsconfig.json file to be used by API Extractor when analyzing the project. + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * Note: This setting will be ignored if "overrideTsconfig" is used. + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "/tsconfig.json" + */ + // "tsconfigFilePath": "/tsconfig.json", + /** + * Provides a compiler configuration that will be used instead of reading the tsconfig.json file from disk. + * The object must conform to the TypeScript tsconfig schema: + * + * http://json.schemastore.org/tsconfig + * + * If omitted, then the tsconfig.json file will be read from the "projectFolder". + * + * DEFAULT VALUE: no overrideTsconfig section + */ + // "overrideTsconfig": { + // . . . + // } + /** + * This option causes the compiler to be invoked with the --skipLibCheck option. This option is not recommended + * and may cause API Extractor to produce incomplete or incorrect declarations, but it may be required when + * dependencies contain declarations that are incompatible with the TypeScript engine that API Extractor uses + * for its analysis. Where possible, the underlying issue should be fixed rather than relying on skipLibCheck. + * + * DEFAULT VALUE: false + */ + // "skipLibCheck": true, + }, + + /** + * Configures how the API report file (*.api.md) will be generated. + */ + "apiReport": { + /** + * (REQUIRED) Whether to generate an API report. + */ + "enabled": true + + /** + * The base filename for the API report files, to be combined with "reportFolder" or "reportTempFolder" + * to produce the full file path. The "reportFileName" should not include any path separators such as + * "\" or "/". The "reportFileName" should not include a file extension, since API Extractor will automatically + * append an appropriate file extension such as ".api.md". If the "reportVariants" setting is used, then the + * file extension includes the variant name, for example "my-report.public.api.md" or "my-report.beta.api.md". + * The "complete" variant always uses the simple extension "my-report.api.md". + * + * Previous versions of API Extractor required "reportFileName" to include the ".api.md" extension explicitly; + * for backwards compatibility, that is still accepted but will be discarded before applying the above rules. + * + * SUPPORTED TOKENS: , + * DEFAULT VALUE: "" + */ + // "reportFileName": "", + + /** + * To support different approval requirements for different API levels, multiple "variants" of the API report can + * be generated. The "reportVariants" setting specifies a list of variants to be generated. If omitted, + * by default only the "complete" variant will be generated, which includes all @internal, @alpha, @beta, + * and @public items. Other possible variants are "alpha" (@alpha + @beta + @public), "beta" (@beta + @public), + * and "public" (@public only). + * + * DEFAULT VALUE: [ "complete" ] + */ + // "reportVariants": ["public", "beta"], + + /** + * Specifies the folder where the API report file is written. The file name portion is determined by + * the "reportFileName" setting. + * + * The API report file is normally tracked by Git. Changes to it can be used to trigger a branch policy, + * e.g. for an API review. + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "/etc/" + */ + // "reportFolder": "/etc/", + + /** + * Specifies the folder where the temporary report file is written. The file name portion is determined by + * the "reportFileName" setting. + * + * After the temporary file is written to disk, it is compared with the file in the "reportFolder". + * If they are different, a production build will fail. + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "/temp/" + */ + // "reportTempFolder": "/temp/", + + /** + * Whether "forgotten exports" should be included in the API report file. Forgotten exports are declarations + * flagged with `ae-forgotten-export` warnings. See https://api-extractor.com/pages/messages/ae-forgotten-export/ to + * learn more. + * + * DEFAULT VALUE: "false" + */ + // "includeForgottenExports": false + }, + + /** + * Configures how the doc model file (*.api.json) will be generated. + */ + "docModel": { + /** + * (REQUIRED) Whether to generate a doc model file. + */ + "enabled": true + + /** + * The output path for the doc model file. The file extension should be ".api.json". + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "/temp/.api.json" + */ + // "apiJsonFilePath": "/temp/.api.json", + + /** + * Whether "forgotten exports" should be included in the doc model file. Forgotten exports are declarations + * flagged with `ae-forgotten-export` warnings. See https://api-extractor.com/pages/messages/ae-forgotten-export/ to + * learn more. + * + * DEFAULT VALUE: "false" + */ + // "includeForgottenExports": false, + + /** + * The base URL where the project's source code can be viewed on a website such as GitHub or + * Azure DevOps. This URL path corresponds to the `` path on disk. + * + * This URL is concatenated with the file paths serialized to the doc model to produce URL file paths to individual API items. + * For example, if the `projectFolderUrl` is "https://github.com/microsoft/rushstack/tree/main/apps/api-extractor" and an API + * item's file path is "api/ExtractorConfig.ts", the full URL file path would be + * "https://github.com/microsoft/rushstack/tree/main/apps/api-extractor/api/ExtractorConfig.js". + * + * This setting can be omitted if you don't need source code links in your API documentation reference. + * + * SUPPORTED TOKENS: none + * DEFAULT VALUE: "" + */ + // "projectFolderUrl": "http://github.com/path/to/your/projectFolder" + }, + + /** + * Configures how the .d.ts rollup file will be generated. + */ + "dtsRollup": { + /** + * (REQUIRED) Whether to generate the .d.ts rollup file. + */ + "enabled": true + + /** + * Specifies the output path for a .d.ts rollup file to be generated without any trimming. + * This file will include all declarations that are exported by the main entry point. + * + * If the path is an empty string, then this file will not be written. + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "/dist/.d.ts" + */ + // "untrimmedFilePath": "/dist/.d.ts", + + /** + * Specifies the output path for a .d.ts rollup file to be generated with trimming for an "alpha" release. + * This file will include only declarations that are marked as "@public", "@beta", or "@alpha". + * + * If the path is an empty string, then this file will not be written. + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "" + */ + // "alphaTrimmedFilePath": "/dist/-alpha.d.ts", + + /** + * Specifies the output path for a .d.ts rollup file to be generated with trimming for a "beta" release. + * This file will include only declarations that are marked as "@public" or "@beta". + * + * If the path is an empty string, then this file will not be written. + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "" + */ + // "betaTrimmedFilePath": "/dist/-beta.d.ts", + + /** + * Specifies the output path for a .d.ts rollup file to be generated with trimming for a "public" release. + * This file will include only declarations that are marked as "@public". + * + * If the path is an empty string, then this file will not be written. + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "" + */ + // "publicTrimmedFilePath": "/dist/-public.d.ts", + + /** + * When a declaration is trimmed, by default it will be replaced by a code comment such as + * "Excluded from this release type: exampleMember". Set "omitTrimmingComments" to true to remove the + * declaration completely. + * + * DEFAULT VALUE: false + */ + // "omitTrimmingComments": true + }, + + /** + * Configures how the tsdoc-metadata.json file will be generated. + */ + "tsdocMetadata": { + /** + * Whether to generate the tsdoc-metadata.json file. + * + * DEFAULT VALUE: true + */ + // "enabled": true, + /** + * Specifies where the TSDoc metadata file should be written. + * + * The path is resolved relative to the folder of the config file that contains the setting; to change this, + * prepend a folder token such as "". + * + * The default value is "", which causes the path to be automatically inferred from the "tsdocMetadata", + * "typings" or "main" fields of the project's package.json. If none of these fields are set, the lookup + * falls back to "tsdoc-metadata.json" in the package folder. + * + * SUPPORTED TOKENS: , , + * DEFAULT VALUE: "" + */ + // "tsdocMetadataFilePath": "/dist/tsdoc-metadata.json" + }, + + /** + * Configures how API Extractor reports error and warning messages produced during analysis. + * + * There are three sources of messages: compiler messages, API Extractor messages, and TSDoc messages. + */ + "messages": { + /** + * Configures handling of diagnostic messages reported by the TypeScript compiler engine while analyzing + * the input .d.ts files. + * + * TypeScript message identifiers start with "TS" followed by an integer. For example: "TS2551" + * + * DEFAULT VALUE: A single "default" entry with logLevel=warning. + */ + "compilerMessageReporting": { + /** + * Configures the default routing for messages that don't match an explicit rule in this table. + */ + "default": { + /** + * Specifies whether the message should be written to the the tool's output log. Note that + * the "addToApiReportFile" property may supersede this option. + * + * Possible values: "error", "warning", "none" + * + * Errors cause the build to fail and return a nonzero exit code. Warnings cause a production build fail + * and return a nonzero exit code. For a non-production build (e.g. when "api-extractor run" includes + * the "--local" option), the warning is displayed but the build will not fail. + * + * DEFAULT VALUE: "warning" + */ + "logLevel": "warning" + + /** + * When addToApiReportFile is true: If API Extractor is configured to write an API report file (.api.md), + * then the message will be written inside that file; otherwise, the message is instead logged according to + * the "logLevel" option. + * + * DEFAULT VALUE: false + */ + // "addToApiReportFile": false + } + + // "TS2551": { + // "logLevel": "warning", + // "addToApiReportFile": true + // }, + // + // . . . + }, + + /** + * Configures handling of messages reported by API Extractor during its analysis. + * + * API Extractor message identifiers start with "ae-". For example: "ae-extra-release-tag" + * + * DEFAULT VALUE: See api-extractor-defaults.json for the complete table of extractorMessageReporting mappings + */ + "extractorMessageReporting": { + "default": { + "logLevel": "warning" + // "addToApiReportFile": false + } + + // "ae-extra-release-tag": { + // "logLevel": "warning", + // "addToApiReportFile": true + // }, + // + // . . . + }, + + /** + * Configures handling of messages reported by the TSDoc parser when analyzing code comments. + * + * TSDoc message identifiers start with "tsdoc-". For example: "tsdoc-link-tag-unescaped-text" + * + * DEFAULT VALUE: A single "default" entry with logLevel=warning. + */ + "tsdocMessageReporting": { + "default": { + "logLevel": "warning" + // "addToApiReportFile": false + } + + // "tsdoc-link-tag-unescaped-text": { + // "logLevel": "warning", + // "addToApiReportFile": true + // }, + // + // . . . + } + } +} diff --git a/reactions/sdk/javascript/examples/simple/.dockerignore b/reactions/sdk/javascript/examples/simple/.dockerignore new file mode 100644 index 00000000..b512c09d --- /dev/null +++ b/reactions/sdk/javascript/examples/simple/.dockerignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/simple/.gitignore b/reactions/sdk/javascript/examples/simple/.gitignore new file mode 100644 index 00000000..76add878 --- /dev/null +++ b/reactions/sdk/javascript/examples/simple/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/simple/Dockerfile b/reactions/sdk/javascript/examples/simple/Dockerfile new file mode 100644 index 00000000..357e7d89 --- /dev/null +++ b/reactions/sdk/javascript/examples/simple/Dockerfile @@ -0,0 +1,16 @@ +FROM node:20 + +WORKDIR /usr/src/app + +COPY . . + +RUN npm install -g typescript +RUN npm install +RUN npm run build + +WORKDIR /usr/src/app/examples/simple + +RUN npm install +RUN npm run build + +CMD ["npm", "start"] \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/simple/Reaction.yaml b/reactions/sdk/javascript/examples/simple/Reaction.yaml new file mode 100644 index 00000000..84619734 --- /dev/null +++ b/reactions/sdk/javascript/examples/simple/Reaction.yaml @@ -0,0 +1,8 @@ +kind: Reaction +apiVersion: v1 +name: test-simple +spec: + kind: Simple + queries: + freezer2: + query2: \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/simple/ReactionProvider.yaml b/reactions/sdk/javascript/examples/simple/ReactionProvider.yaml new file mode 100644 index 00000000..20cd1909 --- /dev/null +++ b/reactions/sdk/javascript/examples/simple/ReactionProvider.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ReactionProvider +name: Simple +spec: + services: + simple: + image: reaction-simple diff --git a/reactions/sdk/javascript/examples/simple/package-lock.json b/reactions/sdk/javascript/examples/simple/package-lock.json new file mode 100644 index 00000000..348c6ef9 --- /dev/null +++ b/reactions/sdk/javascript/examples/simple/package-lock.json @@ -0,0 +1,51 @@ +{ + "name": "example-reaction", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "example-reaction", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@drasi/reaction-sdk": "file:../../" + } + }, + "..": { + "name": "@drasi/reaction-sdk", + "version": "1.0.0", + "extraneous": true, + "license": "ISC", + "dependencies": { + "@dapr/dapr": "^3.4.1", + "tslib": "^2.8.0" + }, + "devDependencies": { + "@microsoft/api-extractor": "^7.47.11", + "@types/node": "^22.8.6", + "json-schema-to-typescript": "^15.0.2", + "typescript": "^5.6.3" + } + }, + "../..": { + "name": "@drasi/reaction-sdk", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@dapr/dapr": "^3.4.1", + "tslib": "^2.8.0" + }, + "devDependencies": { + "@microsoft/api-extractor": "^7.47.11", + "@types/node": "^22.8.6", + "json-schema-to-typescript": "^15.0.2", + "typescript": "^5.6.3" + } + }, + "node_modules/@drasi/reaction-sdk": { + "resolved": "../..", + "link": true + } + } +} diff --git a/reactions/sdk/javascript/examples/simple/package.json b/reactions/sdk/javascript/examples/simple/package.json new file mode 100644 index 00000000..0174ef1a --- /dev/null +++ b/reactions/sdk/javascript/examples/simple/package.json @@ -0,0 +1,16 @@ +{ + "name": "example-reaction", + "version": "1.0.0", + "main": "dist/index.js", + "scripts": { + "build": "tsc", + "start": "node dist/index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "Apache-2.0", + "description": "", + "dependencies": { + "@drasi/reaction-sdk": "file:../../" + } +} diff --git a/reactions/sdk/javascript/examples/simple/src/index.ts b/reactions/sdk/javascript/examples/simple/src/index.ts new file mode 100644 index 00000000..1edcd86c --- /dev/null +++ b/reactions/sdk/javascript/examples/simple/src/index.ts @@ -0,0 +1,25 @@ +import {DrasiReaction, ChangeEvent} from '@drasi/reaction-sdk'; + +async function main() { + + let myReaction = new DrasiReaction((event: ChangeEvent) => { + + console.log(`Received change sequence: ${event.sequence} for query ${event.queryId}`); + + for (let added of event.addedResults) { + console.log(`Added result: ${JSON.stringify(added)}`); + } + + for (let deleted of event.deletedResults) { + console.log(`Removed result: ${JSON.stringify(deleted)}`); + } + + for (let updated of event.updatedResults) { + console.log(`Updated result - before: ${JSON.stringify(updated.before)}, after: ${JSON.stringify(updated.after)}`); + } + }); + + await myReaction.start(); +} + +main().catch(console.error); \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/simple/tsconfig.json b/reactions/sdk/javascript/examples/simple/tsconfig.json new file mode 100644 index 00000000..645f823c --- /dev/null +++ b/reactions/sdk/javascript/examples/simple/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "commonjs", + "outDir": "./dist", + "esModuleInterop": true, + "sourceMap": true + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "**/*.test.ts"] + } \ No newline at end of file diff --git a/reactions/sdk/javascript/package-lock.json b/reactions/sdk/javascript/package-lock.json new file mode 100644 index 00000000..155c7903 --- /dev/null +++ b/reactions/sdk/javascript/package-lock.json @@ -0,0 +1,2445 @@ +{ + "name": "drasi-reaction-sdk", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "drasi-reaction-sdk", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@dapr/dapr": "^3.4.1", + "tslib": "^2.8.0" + }, + "devDependencies": { + "@microsoft/api-extractor": "^7.47.11", + "@types/node": "^22.8.6", + "json-schema-to-typescript": "^15.0.2", + "typescript": "^5.6.3" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "11.7.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.2.tgz", + "integrity": "sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.15", + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/philsturgeon" + } + }, + "node_modules/@dapr/dapr": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@dapr/dapr/-/dapr-3.4.1.tgz", + "integrity": "sha512-Ev9/Pqzo2ftiDU3gYOCiOJR/UZ5fZk+y+hFcn133mBkYvbU9cTU9S+/46kH2YVJCg6+62m/rG7LQ1o2s5gX76Q==", + "license": "ISC", + "dependencies": { + "@grpc/grpc-js": "^1.9.3", + "@js-temporal/polyfill": "^0.3.0", + "@microsoft/durabletask-js": "^0.1.0-alpha.2", + "@types/google-protobuf": "^3.15.5", + "@types/node-fetch": "^2.6.2", + "body-parser": "^1.19.0", + "express": "^4.18.2", + "google-protobuf": "^3.18.0", + "http-terminator": "^3.2.0", + "node-fetch": "^2.6.7" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.2.tgz", + "integrity": "sha512-bgxdZmgTrJZX50OjyVwz3+mNEnCTNkh3cIqGPWVNeW9jX6bn1ZkU80uPd+67/ZpIJIjRQ9qaHCjhavyoWYxumg==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@js-temporal/polyfill": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@js-temporal/polyfill/-/polyfill-0.3.0.tgz", + "integrity": "sha512-cxxxis19j0WvK3+kUwKrXeXaDBaWxLeRfKqlVz7g50Cly6UgGs2p3wovH9zjtZ4TtjYHDR4De/880+aalduDZQ==", + "license": "ISC", + "dependencies": { + "big-integer": "^1.6.51", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@microsoft/api-extractor": { + "version": "7.47.11", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.47.11.tgz", + "integrity": "sha512-lrudfbPub5wzBhymfFtgZKuBvXxoSIAdrvS2UbHjoMT2TjIEddq6Z13pcve7A03BAouw0x8sW8G4txdgfiSwpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@microsoft/api-extractor-model": "7.29.8", + "@microsoft/tsdoc": "~0.15.0", + "@microsoft/tsdoc-config": "~0.17.0", + "@rushstack/node-core-library": "5.9.0", + "@rushstack/rig-package": "0.5.3", + "@rushstack/terminal": "0.14.2", + "@rushstack/ts-command-line": "4.23.0", + "lodash": "~4.17.15", + "minimatch": "~3.0.3", + "resolve": "~1.22.1", + "semver": "~7.5.4", + "source-map": "~0.6.1", + "typescript": "5.4.2" + }, + "bin": { + "api-extractor": "bin/api-extractor" + } + }, + "node_modules/@microsoft/api-extractor-model": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.29.8.tgz", + "integrity": "sha512-t3Z/xcO6TRbMcnKGVMs4uMzv/gd5j0NhMiJIGjD4cJMeFJ1Hf8wnLSx37vxlRlL0GWlGJhnFgxvnaL6JlS+73g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@microsoft/tsdoc": "~0.15.0", + "@microsoft/tsdoc-config": "~0.17.0", + "@rushstack/node-core-library": "5.9.0" + } + }, + "node_modules/@microsoft/api-extractor/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@microsoft/api-extractor/node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@microsoft/api-extractor/node_modules/typescript": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/@microsoft/durabletask-js": { + "version": "0.1.0-alpha.2", + "resolved": "https://registry.npmjs.org/@microsoft/durabletask-js/-/durabletask-js-0.1.0-alpha.2.tgz", + "integrity": "sha512-EiUgOyT05JQ9/M/InjTKdXs5Y1XxdXRczb6nizceJglXr8S/myxMnQHDV1QRASxroFCoTyKiDHU6uAq4Cpe/LQ==", + "license": "MIT", + "dependencies": { + "@grpc/grpc-js": "^1.8.14", + "google-protobuf": "^3.21.2" + } + }, + "node_modules/@microsoft/tsdoc": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz", + "integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@microsoft/tsdoc-config": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.17.0.tgz", + "integrity": "sha512-v/EYRXnCAIHxOHW+Plb6OWuUoMotxTN0GLatnpOb1xq0KuTNw/WI3pamJx/UbsoJP5k9MCw1QxvvhPcF9pH3Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@microsoft/tsdoc": "0.15.0", + "ajv": "~8.12.0", + "jju": "~1.4.0", + "resolve": "~1.22.2" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, + "node_modules/@rushstack/node-core-library": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.9.0.tgz", + "integrity": "sha512-MMsshEWkTbXqxqFxD4gcIUWQOCeBChlGczdZbHfqmNZQFLHB3yWxDFSMHFUdu2/OB9NUk7Awn5qRL+rws4HQNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "~8.13.0", + "ajv-draft-04": "~1.0.0", + "ajv-formats": "~3.0.1", + "fs-extra": "~7.0.1", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.22.1", + "semver": "~7.5.4" + }, + "peerDependencies": { + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@rushstack/node-core-library/node_modules/ajv": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", + "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@rushstack/rig-package": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.5.3.tgz", + "integrity": "sha512-olzSSjYrvCNxUFZowevC3uz8gvKr3WTpHQ7BkpjtRpA3wK+T0ybep/SRUMfr195gBzJm5gaXw0ZMgjIyHqJUow==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "~1.22.1", + "strip-json-comments": "~3.1.1" + } + }, + "node_modules/@rushstack/terminal": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.14.2.tgz", + "integrity": "sha512-2fC1wqu1VCExKC0/L+0noVcFQEXEnoBOtCIex1TOjBzEDWcw8KzJjjj7aTP6mLxepG0XIyn9OufeFb6SFsa+sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rushstack/node-core-library": "5.9.0", + "supports-color": "~8.1.1" + }, + "peerDependencies": { + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@rushstack/ts-command-line": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.23.0.tgz", + "integrity": "sha512-jYREBtsxduPV6ptNq8jOKp9+yx0ld1Tb/Tkdnlj8gTjazl1sF3DwX2VbluyYrNd0meWIL0bNeer7WDf5tKFjaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rushstack/terminal": "0.14.2", + "@types/argparse": "1.0.38", + "argparse": "~1.0.9", + "string-argv": "~0.3.1" + } + }, + "node_modules/@rushstack/ts-command-line/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@types/argparse": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", + "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/google-protobuf": { + "version": "3.15.12", + "resolved": "https://registry.npmjs.org/@types/google-protobuf/-/google-protobuf-3.15.12.tgz", + "integrity": "sha512-40um9QqwHjRS92qnOaDpL7RmDK15NuZYo9HihiJRbYkMQZlWnuH8AdvbMy8/o6lgLmKbDUKa+OALCltHdbOTpQ==", + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.13.tgz", + "integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.6.tgz", + "integrity": "sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-printf": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", + "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "license": "BSD-3-Clause", + "dependencies": { + "boolean": "^3.1.4" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/google-protobuf": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.4.tgz", + "integrity": "sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==", + "license": "(BSD-3-Clause AND Apache-2.0)" + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-terminator": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/http-terminator/-/http-terminator-3.2.0.tgz", + "integrity": "sha512-JLjck1EzPaWjsmIf8bziM3p9fgR1Y3JoUKAkyYEbZmFrIvJM6I8vVJfBGWlEtV9IWOvzNnaTtjuwZeBY2kwB4g==", + "license": "BSD-3-Clause", + "dependencies": { + "delay": "^5.0.0", + "p-wait-for": "^3.2.0", + "roarr": "^7.0.4", + "type-fest": "^2.3.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-to-typescript": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-15.0.2.tgz", + "integrity": "sha512-+cRBw+bBJ3k783mZroDIgz1pLNPB4hvj6nnbHTWwEVl0dkW8qdZ+M9jWhBb+Y0FAdHvNsXACga3lewGO8lktrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^11.5.5", + "@types/json-schema": "^7.0.15", + "@types/lodash": "^4.17.7", + "glob": "^10.3.12", + "is-glob": "^4.0.3", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "minimist": "^1.2.8", + "prettier": "^3.2.5" + }, + "bin": { + "json2ts": "dist/src/cli.js" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "license": "Apache-2.0" + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "license": "MIT", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-wait-for": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-wait-for/-/p-wait-for-3.2.0.tgz", + "integrity": "sha512-wpgERjNkLrBiFmkMEjuZJEWKKDrNfHCKA1OhyN1wg1FrLkULbviEy6py1AyJUgZ72YWFbZ38FIpnqvVqAlDUwA==", + "license": "MIT", + "dependencies": { + "p-timeout": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "license": "MIT" + }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/protobufjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/roarr": { + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-7.21.1.tgz", + "integrity": "sha512-3niqt5bXFY1InKU8HKWqqYTYjtrBaxBMnXELXCXUYgtNYGUtZM5rB46HIC430AyacL95iEniGf7RgqsesykLmQ==", + "license": "BSD-3-Clause", + "dependencies": { + "fast-printf": "^1.6.9", + "safe-stable-stringify": "^2.4.3", + "semver-compare": "^1.0.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "license": "MIT" + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/reactions/sdk/javascript/package.json b/reactions/sdk/javascript/package.json new file mode 100644 index 00000000..59ecbc0c --- /dev/null +++ b/reactions/sdk/javascript/package.json @@ -0,0 +1,27 @@ +{ + "name": "@drasi/reaction-sdk", + "version": "1.0.0", + "description": "Reaction SDK for Project Drasi", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*" + ], + "scripts": { + "generate-types": "tsp compile ../../../typespec/query-output && json2ts -i ../../../typespec/query-output/_generated/@typespec/json-schema/ -o src/types/ --cwd ../../../typespec/query-output/_generated/@typespec/json-schema", + "build": "tsc && mkdir -p ./dist/types && cp ./src/types/* ./dist/types/", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "Apache-2.0", + "devDependencies": { + "@microsoft/api-extractor": "^7.47.11", + "@types/node": "^22.8.6", + "json-schema-to-typescript": "^15.0.2", + "typescript": "^5.6.3" + }, + "dependencies": { + "@dapr/dapr": "^3.4.1", + "tslib": "^2.8.0" + } +} diff --git a/reactions/sdk/javascript/src/index.ts b/reactions/sdk/javascript/src/index.ts new file mode 100644 index 00000000..cb3d3fac --- /dev/null +++ b/reactions/sdk/javascript/src/index.ts @@ -0,0 +1,71 @@ +import { DaprServer } from "@dapr/dapr"; +import { ChangeEvent } from "./types/ChangeEvent"; +import { ControlEvent } from "./types/ControlEvent"; +import { readdirSync, readFileSync } from "fs"; + +export type OnChangeEvent = (event: ChangeEvent, queryConfig?: TQueryConfig) => void; +export type OnControlEvent = (event: ControlEvent, queryConfig?: TQueryConfig) => void; +export { ChangeEvent } from "./types/ChangeEvent"; +export { ControlEvent } from "./types/ControlEvent"; + +export type ReactionOptions = { + onControlEvent?: OnControlEvent; + parseQueryConfig?: (queryId: string, config: string) => TQueryConfig; +} + +export class DrasiReaction { + private onChangeEvent: OnChangeEvent; + private onControlEvent: OnControlEvent | undefined; + private daprServer: DaprServer; + private pubSubName: string = process.env["PUBSUB"] ?? "drasi-pubsub"; + private configDirectory: string = process.env["QueryConfigPath"] ?? "/etc/queries"; + private queryConfig: Map = new Map(); + private parseQueryConfig: (queryId: string, config: string) => TQueryConfig | undefined; + + constructor(onChangeEvent: OnChangeEvent, options?: ReactionOptions) { + this.onChangeEvent = onChangeEvent; + this.onControlEvent = options?.onControlEvent; + this.parseQueryConfig = options?.parseQueryConfig; + this.daprServer = new DaprServer({ + serverPort: '80' + }); + } + + public async start() { + let queryIds = readdirSync(this.configDirectory); + for (let queryId of queryIds) { + console.log(`Subscribing to query ${queryId}`); + this.daprServer.pubsub.subscribe(this.pubSubName, `${queryId}-results`, this.onMessage.bind(this)); + if (this.parseQueryConfig) { + let cfgStr = readFileSync(`${this.configDirectory}/${queryId}`, 'utf-8'); + let cfg = this.parseQueryConfig(queryId, cfgStr); + this.queryConfig.set(queryId, cfg); + } + } + await this.daprServer.start(); + } + + public async stop() { + await this.daprServer.stop(); + } + + async onMessage(data: any) { + console.log(`Received ${data?.kind} sequence: ${data?.sequence} for query ${data?.queryId}`); + let queryConfig = this.queryConfig.get(data.queryId); + switch (data.kind) { + case "change": + this.onChangeEvent(data, queryConfig); + break; + case "control": + if (!this.onControlEvent) { + console.log("Received control event but no handler is registered"); + return; + } + this.onControlEvent(data, queryConfig); + break; + default: + console.log("Unknown message kind: " + data.kind); + } + } + +} \ No newline at end of file diff --git a/reactions/sdk/javascript/src/types/BootstrapCompletedSignal.d.ts b/reactions/sdk/javascript/src/types/BootstrapCompletedSignal.d.ts new file mode 100644 index 00000000..70f0246b --- /dev/null +++ b/reactions/sdk/javascript/src/types/BootstrapCompletedSignal.d.ts @@ -0,0 +1,15 @@ +/* eslint-disable */ +/** + * This file was automatically generated by json-schema-to-typescript. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run json-schema-to-typescript to regenerate this file. + */ + +export type BootstrapCompletedSignal = ControlSignal & { + kind: "bootstrapCompleted"; + [k: string]: unknown; +}; + +export interface ControlSignal { + [k: string]: unknown; +} diff --git a/reactions/sdk/javascript/src/types/BootstrapStartedSignal.d.ts b/reactions/sdk/javascript/src/types/BootstrapStartedSignal.d.ts new file mode 100644 index 00000000..7eb71b62 --- /dev/null +++ b/reactions/sdk/javascript/src/types/BootstrapStartedSignal.d.ts @@ -0,0 +1,15 @@ +/* eslint-disable */ +/** + * This file was automatically generated by json-schema-to-typescript. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run json-schema-to-typescript to regenerate this file. + */ + +export type BootstrapStartedSignal = ControlSignal & { + kind: "bootstrapStarted"; + [k: string]: unknown; +}; + +export interface ControlSignal { + [k: string]: unknown; +} diff --git a/reactions/sdk/javascript/src/types/ChangeEvent.d.ts b/reactions/sdk/javascript/src/types/ChangeEvent.d.ts new file mode 100644 index 00000000..44be6ec4 --- /dev/null +++ b/reactions/sdk/javascript/src/types/ChangeEvent.d.ts @@ -0,0 +1,54 @@ +/* eslint-disable */ +/** + * This file was automatically generated by json-schema-to-typescript. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run json-schema-to-typescript to regenerate this file. + */ + +export type ChangeEvent = ResultEvent & { + kind: "change"; + /** + * The results that were added + */ + addedResults: RecordUnknown1[]; + /** + * The results that were updated + */ + updatedResults: UpdatePayload[]; + /** + * The results that were deleted + */ + deletedResults: RecordUnknown1[]; + [k: string]: unknown; +}; + +export interface ResultEvent { + queryId: string; + sequence: string; + sourceTimeMs: string; + metadata?: RecordUnknown; + [k: string]: unknown; +} +export interface RecordUnknown { + [k: string]: unknown; +} +export interface RecordUnknown1 { + [k: string]: unknown; +} +export interface UpdatePayload { + before: RecordUnknown2; + after: RecordUnknown3; + [k: string]: unknown; +} +/** + * The result before the change + */ +export interface RecordUnknown2 { + [k: string]: unknown; +} +/** + * The result after the change + */ +export interface RecordUnknown3 { + [k: string]: unknown; +} diff --git a/reactions/sdk/javascript/src/types/ControlEvent.d.ts b/reactions/sdk/javascript/src/types/ControlEvent.d.ts new file mode 100644 index 00000000..bfab648d --- /dev/null +++ b/reactions/sdk/javascript/src/types/ControlEvent.d.ts @@ -0,0 +1,26 @@ +/* eslint-disable */ +/** + * This file was automatically generated by json-schema-to-typescript. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run json-schema-to-typescript to regenerate this file. + */ + +export type ControlEvent = ResultEvent & { + kind: "control"; + controlSignal: ControlSignal; + [k: string]: unknown; +}; + +export interface ResultEvent { + queryId: string; + sequence: string; + sourceTimeMs: string; + metadata?: RecordUnknown; + [k: string]: unknown; +} +export interface RecordUnknown { + [k: string]: unknown; +} +export interface ControlSignal { + [k: string]: unknown; +} diff --git a/reactions/sdk/javascript/src/types/ControlSignal.d.ts b/reactions/sdk/javascript/src/types/ControlSignal.d.ts new file mode 100644 index 00000000..76b6115f --- /dev/null +++ b/reactions/sdk/javascript/src/types/ControlSignal.d.ts @@ -0,0 +1,10 @@ +/* eslint-disable */ +/** + * This file was automatically generated by json-schema-to-typescript. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run json-schema-to-typescript to regenerate this file. + */ + +export interface ControlSignal { + [k: string]: unknown; +} diff --git a/reactions/sdk/javascript/src/types/DeletedSignal.d.ts b/reactions/sdk/javascript/src/types/DeletedSignal.d.ts new file mode 100644 index 00000000..124fa465 --- /dev/null +++ b/reactions/sdk/javascript/src/types/DeletedSignal.d.ts @@ -0,0 +1,15 @@ +/* eslint-disable */ +/** + * This file was automatically generated by json-schema-to-typescript. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run json-schema-to-typescript to regenerate this file. + */ + +export type DeletedSignal = ControlSignal & { + kind: "deleted"; + [k: string]: unknown; +}; + +export interface ControlSignal { + [k: string]: unknown; +} diff --git a/reactions/sdk/javascript/src/types/ResultEvent.d.ts b/reactions/sdk/javascript/src/types/ResultEvent.d.ts new file mode 100644 index 00000000..edb6c9c7 --- /dev/null +++ b/reactions/sdk/javascript/src/types/ResultEvent.d.ts @@ -0,0 +1,17 @@ +/* eslint-disable */ +/** + * This file was automatically generated by json-schema-to-typescript. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run json-schema-to-typescript to regenerate this file. + */ + +export interface ResultEvent { + queryId: string; + sequence: string; + sourceTimeMs: string; + metadata?: RecordUnknown; + [k: string]: unknown; +} +export interface RecordUnknown { + [k: string]: unknown; +} diff --git a/reactions/sdk/javascript/src/types/RunningSignal.d.ts b/reactions/sdk/javascript/src/types/RunningSignal.d.ts new file mode 100644 index 00000000..324cb1db --- /dev/null +++ b/reactions/sdk/javascript/src/types/RunningSignal.d.ts @@ -0,0 +1,15 @@ +/* eslint-disable */ +/** + * This file was automatically generated by json-schema-to-typescript. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run json-schema-to-typescript to regenerate this file. + */ + +export type RunningSignal = ControlSignal & { + kind: "running"; + [k: string]: unknown; +}; + +export interface ControlSignal { + [k: string]: unknown; +} diff --git a/reactions/sdk/javascript/src/types/StoppedSignal.d.ts b/reactions/sdk/javascript/src/types/StoppedSignal.d.ts new file mode 100644 index 00000000..0280f646 --- /dev/null +++ b/reactions/sdk/javascript/src/types/StoppedSignal.d.ts @@ -0,0 +1,15 @@ +/* eslint-disable */ +/** + * This file was automatically generated by json-schema-to-typescript. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run json-schema-to-typescript to regenerate this file. + */ + +export type StoppedSignal = ControlSignal & { + kind: "stopped"; + [k: string]: unknown; +}; + +export interface ControlSignal { + [k: string]: unknown; +} diff --git a/reactions/sdk/javascript/src/types/UpdatePayload.d.ts b/reactions/sdk/javascript/src/types/UpdatePayload.d.ts new file mode 100644 index 00000000..cb7d0612 --- /dev/null +++ b/reactions/sdk/javascript/src/types/UpdatePayload.d.ts @@ -0,0 +1,24 @@ +/* eslint-disable */ +/** + * This file was automatically generated by json-schema-to-typescript. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run json-schema-to-typescript to regenerate this file. + */ + +export interface UpdatePayload { + before: RecordUnknown; + after: RecordUnknown1; + [k: string]: unknown; +} +/** + * The result before the change + */ +export interface RecordUnknown { + [k: string]: unknown; +} +/** + * The result after the change + */ +export interface RecordUnknown1 { + [k: string]: unknown; +} diff --git a/reactions/sdk/javascript/src/types/Versions.d.ts b/reactions/sdk/javascript/src/types/Versions.d.ts new file mode 100644 index 00000000..4214667e --- /dev/null +++ b/reactions/sdk/javascript/src/types/Versions.d.ts @@ -0,0 +1,8 @@ +/* eslint-disable */ +/** + * This file was automatically generated by json-schema-to-typescript. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run json-schema-to-typescript to regenerate this file. + */ + +export type Versions = "v1"; diff --git a/reactions/sdk/javascript/tsconfig.json b/reactions/sdk/javascript/tsconfig.json new file mode 100644 index 00000000..1074b6c6 --- /dev/null +++ b/reactions/sdk/javascript/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "es2020", + "declaration": true, + "emitDeclarationOnly": false, + "module": "commonjs", + "outDir": "./dist", + "esModuleInterop": true, + //"skipLibCheck": true, + //"isolatedModules": true, + "sourceMap": true + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "**/*.test.ts"] + } \ No newline at end of file diff --git a/typespec/.gitignore b/typespec/.gitignore new file mode 100644 index 00000000..0fe4f7a0 --- /dev/null +++ b/typespec/.gitignore @@ -0,0 +1,9 @@ +# MacOS +.DS_Store + +# Default TypeSpec output +tsp-output/ +dist/ + +# Dependency directories +node_modules/ \ No newline at end of file diff --git a/typespec/notes.md b/typespec/notes.md new file mode 100644 index 00000000..9337b558 --- /dev/null +++ b/typespec/notes.md @@ -0,0 +1,2 @@ +json2ts -i ./reaction/_generated/@typespec/json-schema -o types/ --cwd ./reaction/_generated/@typespec/json-schema -- +declareExternallyReferenced false diff --git a/typespec/package-lock.json b/typespec/package-lock.json new file mode 100644 index 00000000..cd5b3ff3 --- /dev/null +++ b/typespec/package-lock.json @@ -0,0 +1,1538 @@ +{ + "name": "drasi", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "drasi", + "version": "0.1.0", + "license": "Apache-2.0", + "dependencies": { + "@azure-tools/typespec-ts": "^0.33.0", + "@typespec/json-schema": "^0.61.0", + "@typespec/openapi3": "^0.61.0" + }, + "devDependencies": { + "@typespec/compiler": "latest" + }, + "peerDependencies": { + "@azure-tools/typespec-autorest": "latest", + "@azure-tools/typespec-azure-core": "latest", + "@azure-tools/typespec-azure-resource-manager": "latest", + "@azure-tools/typespec-providerhub": "latest", + "@typespec/compiler": "latest", + "@typespec/http": "latest", + "@typespec/openapi": "latest", + "@typespec/rest": "latest", + "@typespec/versioning": "^0.61.0" + } + }, + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", + "license": "MIT" + }, + "node_modules/@azure-tools/rlc-common": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@azure-tools/rlc-common/-/rlc-common-0.33.0.tgz", + "integrity": "sha512-x0+URxuvtFAA8GtlNTqr/R2/hnShfT0HISBYr8q8mWP2l8bxaCZm/EdyBYkZ98G9vJHlkKO70mVOK9zUOvFIvw==", + "license": "ISC", + "dependencies": { + "handlebars": "^4.7.7", + "lodash": "^4.17.21", + "ts-morph": "^23.0.0" + } + }, + "node_modules/@azure-tools/typespec-autorest": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-autorest/-/typespec-autorest-0.47.0.tgz", + "integrity": "sha512-uYkk8mnzekSMhJKU3RS0cXvKPH0vbkonthYoPe7/vxZ7tWv4xJLSglV2v3m3QElFgvNebNVoBOEWSY8Kz/ip2Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@azure-tools/typespec-azure-core": "~0.47.0", + "@azure-tools/typespec-azure-resource-manager": "~0.47.0", + "@azure-tools/typespec-client-generator-core": "~0.47.0", + "@typespec/compiler": "~0.61.0", + "@typespec/http": "~0.61.0", + "@typespec/openapi": "~0.61.0", + "@typespec/rest": "~0.61.0", + "@typespec/versioning": "~0.61.0" + } + }, + "node_modules/@azure-tools/typespec-azure-core": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-azure-core/-/typespec-azure-core-0.47.0.tgz", + "integrity": "sha512-RcBC5+dE1BVXTrUkkKULTImGxzM/ea3P3IL2kr9pk7r1uqF7D4CGqEKHFTg5L6QUtqc1f+zgTgQTNn6t4gI92w==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@typespec/compiler": "~0.61.0", + "@typespec/http": "~0.61.0", + "@typespec/rest": "~0.61.0" + } + }, + "node_modules/@azure-tools/typespec-azure-resource-manager": { + "version": "0.47.1", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-azure-resource-manager/-/typespec-azure-resource-manager-0.47.1.tgz", + "integrity": "sha512-ZTrnHwPsc6aMVu6QghF7tPcKPVkt/ErHiEGP+vPXtb9iQh8YKMkkAl6jpvfnqMUqa1h3JkvOBCZM9w5FA84a6Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "change-case": "~5.4.4", + "pluralize": "^8.0.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@azure-tools/typespec-azure-core": "~0.47.0", + "@typespec/compiler": "~0.61.0", + "@typespec/http": "~0.61.0", + "@typespec/openapi": "~0.61.0", + "@typespec/rest": "~0.61.0", + "@typespec/versioning": "~0.61.0" + } + }, + "node_modules/@azure-tools/typespec-client-generator-core": { + "version": "0.47.3", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-client-generator-core/-/typespec-client-generator-core-0.47.3.tgz", + "integrity": "sha512-13knZRDFBlVTw61vbhAnvQzttnqPRwHK0+YI/3QbYRN77j/Kv3zXFPeCcromz31exg3Y/Q8qD24mJ1Oikab2mA==", + "license": "MIT", + "peer": true, + "dependencies": { + "change-case": "~5.4.4", + "pluralize": "^8.0.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@azure-tools/typespec-azure-core": "~0.47.0", + "@typespec/compiler": "~0.61.0", + "@typespec/http": "~0.61.0", + "@typespec/openapi": "~0.61.0", + "@typespec/rest": "~0.61.0", + "@typespec/versioning": "~0.61.0" + } + }, + "node_modules/@azure-tools/typespec-providerhub": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-providerhub/-/typespec-providerhub-0.47.0.tgz", + "integrity": "sha512-528VwSeoF0W6p5DS+wTQePeqJI/5H4KoP3tZe1rB5PI4ykLyV3IDrAsASMov3ULPXjkjC0AZp41S+M4q4PZe+Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure-tools/typespec-ts": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-ts/-/typespec-ts-0.33.0.tgz", + "integrity": "sha512-q81iMQtQSpj//krqXQUG/eselh2cpOTqlLkC0z+5Vr1MhLCGNATUu906NnPRoYuT3gfEkA2uHL30AkDDZH8/+Q==", + "license": "MIT", + "dependencies": { + "@azure-tools/rlc-common": "^0.33.0", + "fs-extra": "^11.1.0", + "lodash": "^4.17.21", + "prettier": "^3.1.0", + "ts-morph": "^23.0.0", + "tslib": "^2.3.1" + }, + "peerDependencies": { + "@azure-tools/typespec-azure-core": ">=0.45.0 <1.0.0", + "@azure-tools/typespec-client-generator-core": ">=0.45.4 <1.0.0", + "@typespec/compiler": ">=0.59.0 <1.0.0", + "@typespec/http": ">=0.59.0 <1.0.0", + "@typespec/rest": ">=0.59.0 <1.0.0", + "@typespec/versioning": ">=0.59.0 <1.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz", + "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@humanwhocodes/momoa": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@humanwhocodes/momoa/-/momoa-2.0.4.tgz", + "integrity": "sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "license": "MIT" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@readme/better-ajv-errors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@readme/better-ajv-errors/-/better-ajv-errors-1.6.0.tgz", + "integrity": "sha512-9gO9rld84Jgu13kcbKRU+WHseNhaVt76wYMeRDGsUGYxwJtI3RmEJ9LY9dZCYQGI8eUZLuxb5qDja0nqklpFjQ==", + "license": "Apache-2.0", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "@babel/runtime": "^7.21.0", + "@humanwhocodes/momoa": "^2.0.3", + "chalk": "^4.1.2", + "json-to-ast": "^2.0.3", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "ajv": "4.11.8 - 8" + } + }, + "node_modules/@readme/better-ajv-errors/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@readme/better-ajv-errors/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@readme/better-ajv-errors/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@readme/better-ajv-errors/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/@readme/better-ajv-errors/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@readme/better-ajv-errors/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@readme/json-schema-ref-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@readme/json-schema-ref-parser/-/json-schema-ref-parser-1.2.0.tgz", + "integrity": "sha512-Bt3QVovFSua4QmHa65EHUmh2xS0XJ3rgTEUPH998f4OW4VVJke3BuS16f+kM0ZLOGdvIrzrPRqwihuv5BAjtrA==", + "license": "MIT", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + } + }, + "node_modules/@readme/openapi-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@readme/openapi-parser/-/openapi-parser-2.6.0.tgz", + "integrity": "sha512-pyFJXezWj9WI1O+gdp95CoxfY+i+Uq3kKk4zXIFuRAZi9YnHpHOpjumWWr67wkmRTw19Hskh9spyY0Iyikf3fA==", + "license": "MIT", + "dependencies": { + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "@readme/better-ajv-errors": "^1.6.0", + "@readme/json-schema-ref-parser": "^1.2.0", + "@readme/openapi-schemas": "^3.1.0", + "ajv": "^8.12.0", + "ajv-draft-04": "^1.0.0", + "call-me-maybe": "^1.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@readme/openapi-schemas": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@readme/openapi-schemas/-/openapi-schemas-3.1.0.tgz", + "integrity": "sha512-9FC/6ho8uFa8fV50+FPy/ngWN53jaUu4GRXlAjcxIRrzhltJnpKkBG2Tp0IDraFJeWrOpk84RJ9EMEEYzaI1Bw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ts-morph/common": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.24.0.tgz", + "integrity": "sha512-c1xMmNHWpNselmpIqursHeOHHBTIsJLbB+NuovbTTRCNiTLEr/U9dbJ8qy0jd/O2x5pc3seWuOUN5R2IoOTp8A==", + "license": "MIT", + "dependencies": { + "fast-glob": "^3.3.2", + "minimatch": "^9.0.4", + "mkdirp": "^3.0.1", + "path-browserify": "^1.0.1" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@typespec/compiler": { + "version": "0.61.2", + "resolved": "https://registry.npmjs.org/@typespec/compiler/-/compiler-0.61.2.tgz", + "integrity": "sha512-6QxYJd09VWssd/BvY+8eBxTVv085s1UNK63FdPrgT2lgI+j8VMMcpNR9m5l1zWlgGDM7sniA/Or8VCdVA6jerg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "~7.24.7", + "ajv": "~8.17.1", + "change-case": "~5.4.4", + "globby": "~14.0.2", + "mustache": "~4.2.0", + "picocolors": "~1.1.0", + "prettier": "~3.3.3", + "prompts": "~2.4.2", + "semver": "^7.6.3", + "temporal-polyfill": "^0.2.5", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.12", + "yaml": "~2.5.1", + "yargs": "~17.7.2" + }, + "bin": { + "tsp": "cmd/tsp.js", + "tsp-server": "cmd/tsp-server.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@typespec/http": { + "version": "0.61.0", + "resolved": "https://registry.npmjs.org/@typespec/http/-/http-0.61.0.tgz", + "integrity": "sha512-7+AYHkzkc+p652GY9BcEbXY4OZa1fTr03MVmZeafvmbQbXfyzUU9eJld13M3v6NaUWqXWZ7nBNMISyKiXp/kSw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@typespec/compiler": "~0.61.0", + "@typespec/streams": "~0.61.0" + }, + "peerDependenciesMeta": { + "@typespec/streams": { + "optional": true + } + } + }, + "node_modules/@typespec/json-schema": { + "version": "0.61.0", + "resolved": "https://registry.npmjs.org/@typespec/json-schema/-/json-schema-0.61.0.tgz", + "integrity": "sha512-BoId8WRo4iLFJUbXIRX26OdHWaUqJIFYmRUvDnlUJmYtcKbMRMkfYajJM3L+b7AdXjLbHwh4ACjwIuZVU90N/Q==", + "license": "MIT", + "dependencies": { + "yaml": "~2.5.1" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@typespec/compiler": "~0.61.0" + } + }, + "node_modules/@typespec/openapi": { + "version": "0.61.0", + "resolved": "https://registry.npmjs.org/@typespec/openapi/-/openapi-0.61.0.tgz", + "integrity": "sha512-3AF319Ae4yGVOscsCLQeedXUJJcL/NdGOR2/e/nFiL/AOVdgLfIRnpR0Ad9Zj9XAESh1fq9XSu4Mi7N1k4V7rw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@typespec/compiler": "~0.61.0", + "@typespec/http": "~0.61.0" + } + }, + "node_modules/@typespec/openapi3": { + "version": "0.61.0", + "resolved": "https://registry.npmjs.org/@typespec/openapi3/-/openapi3-0.61.0.tgz", + "integrity": "sha512-ALLsTkK1UiJBzvygV1Zk/yZaym+lOWroGeEUhQNXYShsq+/GLZkK0rl8sd76Gigq+TVXKMOEwUUvgfws/LMUJw==", + "license": "MIT", + "dependencies": { + "@readme/openapi-parser": "~2.6.0", + "yaml": "~2.5.1" + }, + "bin": { + "tsp-openapi3": "cmd/tsp-openapi3.js" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@typespec/compiler": "~0.61.0", + "@typespec/http": "~0.61.0", + "@typespec/openapi": "~0.61.0", + "@typespec/versioning": "~0.61.0" + } + }, + "node_modules/@typespec/rest": { + "version": "0.61.0", + "resolved": "https://registry.npmjs.org/@typespec/rest/-/rest-0.61.0.tgz", + "integrity": "sha512-L9Oyor+l42p6S8GE+UvaZTi+dcu6WubGZKmaBRpX8mCZGsa69EgIK8DQoyxrfMcxAO4I5U0sfkzCKwCVFtRr9g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@typespec/compiler": "~0.61.0", + "@typespec/http": "~0.61.0" + } + }, + "node_modules/@typespec/versioning": { + "version": "0.61.0", + "resolved": "https://registry.npmjs.org/@typespec/versioning/-/versioning-0.61.0.tgz", + "integrity": "sha512-PIIug6eg3zc7E+BBHyNHHQD+OBq3FU465nhKrLEp35iVji/sYFuPc1ywnELDuwJVRWm6nvqNL1vtnc+4lEk+oA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@typespec/compiler": "~0.61.0" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "license": "MIT", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "license": "MIT" + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/change-case": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/code-block-writer": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", + "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==", + "license": "MIT" + }, + "node_modules/code-error-fragment": { + "version": "0.0.230", + "resolved": "https://registry.npmjs.org/code-error-fragment/-/code-error-fragment-0.0.230.tgz", + "integrity": "sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globby": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "license": "MIT" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/json-to-ast": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json-to-ast/-/json-to-ast-2.1.0.tgz", + "integrity": "sha512-W9Lq347r8tA1DfMvAGn9QNcgYm4Wm7Yc+k8e6vezpMnRT+NHbtlxgNBXRVjXe9YM6eTn6+p/MKOlV/aABJcSnQ==", + "license": "MIT", + "dependencies": { + "code-error-fragment": "0.0.230", + "grapheme-splitter": "^1.0.4" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "license": "MIT", + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "license": "MIT", + "peer": true + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/temporal-polyfill": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/temporal-polyfill/-/temporal-polyfill-0.2.5.tgz", + "integrity": "sha512-ye47xp8Cb0nDguAhrrDS1JT1SzwEV9e26sSsrWzVu+yPZ7LzceEcH0i2gci9jWfOfSCCgM3Qv5nOYShVUUFUXA==", + "license": "MIT", + "dependencies": { + "temporal-spec": "^0.2.4" + } + }, + "node_modules/temporal-spec": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/temporal-spec/-/temporal-spec-0.2.4.tgz", + "integrity": "sha512-lDMFv4nKQrSjlkHKAlHVqKrBG4DyFfa9F74cmBZ3Iy3ed8yvWnlWSIdi4IKfSqwmazAohBNwiN64qGx4y5Q3IQ==", + "license": "ISC" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-morph": { + "version": "23.0.0", + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-23.0.0.tgz", + "integrity": "sha512-FcvFx7a9E8TUe6T3ShihXJLiJOiqyafzFKUO4aqIHDUCIvADdGNShcbc2W5PMr3LerXRv7mafvFZ9lRENxJmug==", + "license": "MIT", + "dependencies": { + "@ts-morph/common": "~0.24.0", + "code-block-writer": "^13.0.1" + } + }, + "node_modules/tslib": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", + "license": "0BSD" + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "license": "MIT", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/typespec/package.json b/typespec/package.json new file mode 100644 index 00000000..950afbfb --- /dev/null +++ b/typespec/package.json @@ -0,0 +1,26 @@ +{ + "name": "drasi", + "version": "0.1.0", + "type": "module", + "peerDependencies": { + "@azure-tools/typespec-autorest": "latest", + "@azure-tools/typespec-azure-core": "latest", + "@azure-tools/typespec-azure-resource-manager": "latest", + "@azure-tools/typespec-providerhub": "latest", + "@typespec/compiler": "latest", + "@typespec/http": "latest", + "@typespec/openapi": "latest", + "@typespec/rest": "latest", + "@typespec/versioning": "^0.61.0" + }, + "devDependencies": { + "@typespec/compiler": "latest" + }, + "private": true, + "license": "Apache-2.0", + "dependencies": { + "@azure-tools/typespec-ts": "^0.33.0", + "@typespec/json-schema": "^0.61.0", + "@typespec/openapi3": "^0.61.0" + } +} diff --git a/typespec/query-output/.gitignore b/typespec/query-output/.gitignore new file mode 100644 index 00000000..94f0f0d9 --- /dev/null +++ b/typespec/query-output/.gitignore @@ -0,0 +1 @@ +_generated \ No newline at end of file diff --git a/typespec/query-output/main.tsp b/typespec/query-output/main.tsp new file mode 100644 index 00000000..16800f13 --- /dev/null +++ b/typespec/query-output/main.tsp @@ -0,0 +1,83 @@ +import "@typespec/json-schema"; +import "@typespec/versioning"; + +using TypeSpec.JsonSchema; +using TypeSpec.Versioning; + +@jsonSchema +@versioned(Drasi.QueryOutput.Versions) +namespace Drasi.QueryOutput; + +@extension("title", "Versions") +enum Versions { + v1, + } + +@discriminator("kind") +@extension("title", "ResultEvent") +model ResultEvent { + queryId: string; + sequence: int64; + sourceTimeMs: int64; + metadata?: Record +} + +@extension("title", "ChangeEvent") +model ChangeEvent extends ResultEvent { + kind: "change"; + + @doc("The results that were added") + addedResults: Record[]; + + @doc("The results that were updated") + updatedResults: UpdatePayload[]; + + @doc("The results that were deleted") + deletedResults: Record[]; +} + +@extension("title", "UpdatePayload") +model UpdatePayload { + @doc("The result before the change") + before: Record; + + @doc("The result after the change") + after: Record; +} + +@extension("title", "ControlEvent") +model ControlEvent extends ResultEvent { + kind: "control"; + controlSignal: ControlSignal; +} + +@discriminator("kind") +@extension("title", "ControlSignal") +model ControlSignal { +} + +@extension("title", "BootstrapStartedSignal") +model BootstrapStartedSignal extends ControlSignal { + kind: "bootstrapStarted"; +} + +@extension("title", "BootstrapCompletedSignal") +model BootstrapCompletedSignal extends ControlSignal { + kind: "bootstrapCompleted"; +} + +@extension("title", "RunningSignal") +model RunningSignal extends ControlSignal { + kind: "running"; +} + +@extension("title", "StoppedSignal") +model StoppedSignal extends ControlSignal { + kind: "stopped"; +} + +@extension("title", "DeletedSignal") +model DeletedSignal extends ControlSignal { + kind: "deleted"; +} + diff --git a/typespec/query-output/tspconfig.yaml b/typespec/query-output/tspconfig.yaml new file mode 100644 index 00000000..498150b8 --- /dev/null +++ b/typespec/query-output/tspconfig.yaml @@ -0,0 +1,23 @@ +# extends: ../tspconfig.yaml # Extend another config file +# emit: # Emitter name +# - ": +# "": "" +# environment-variables: # Environment variables which can be used to interpolate emitter options +# : +# default: "" +# parameters: # Parameters which can be used to interpolate emitter options +# : +# default: "" +# trace: # Trace areas to enable tracing +# - "" +# warn-as-error: true # Treat warnings as errors + +emit: + - "@typespec/json-schema" +options: + "@typespec/json-schema": + file-type: "yaml" + +output-dir: "{project-root}/_generated" # Configure the base output directory for all emitters \ No newline at end of file From 52659d26466d1a03dae8baaa44bf7bfbf9faa2fb Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Thu, 31 Oct 2024 20:20:38 -0700 Subject: [PATCH 02/17] advanced example --- .../examples/advanced/.dockerignore | 1 + .../javascript/examples/advanced/.gitignore | 2 + .../javascript/examples/advanced/Dockerfile | 16 ++++++ .../examples/advanced/Reaction.yaml | 10 ++++ .../examples/advanced/ReactionProvider.yaml | 7 +++ .../examples/advanced/package-lock.json | 51 +++++++++++++++++++ .../javascript/examples/advanced/package.json | 16 ++++++ .../javascript/examples/advanced/src/index.ts | 41 +++++++++++++++ .../examples/advanced/tsconfig.json | 11 ++++ .../javascript/examples/simple/src/index.ts | 4 +- reactions/sdk/javascript/package-lock.json | 21 ++++++-- reactions/sdk/javascript/package.json | 3 +- reactions/sdk/javascript/src/index.ts | 26 ++++++++-- 13 files changed, 197 insertions(+), 12 deletions(-) create mode 100644 reactions/sdk/javascript/examples/advanced/.dockerignore create mode 100644 reactions/sdk/javascript/examples/advanced/.gitignore create mode 100644 reactions/sdk/javascript/examples/advanced/Dockerfile create mode 100644 reactions/sdk/javascript/examples/advanced/Reaction.yaml create mode 100644 reactions/sdk/javascript/examples/advanced/ReactionProvider.yaml create mode 100644 reactions/sdk/javascript/examples/advanced/package-lock.json create mode 100644 reactions/sdk/javascript/examples/advanced/package.json create mode 100644 reactions/sdk/javascript/examples/advanced/src/index.ts create mode 100644 reactions/sdk/javascript/examples/advanced/tsconfig.json diff --git a/reactions/sdk/javascript/examples/advanced/.dockerignore b/reactions/sdk/javascript/examples/advanced/.dockerignore new file mode 100644 index 00000000..b512c09d --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced/.dockerignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/advanced/.gitignore b/reactions/sdk/javascript/examples/advanced/.gitignore new file mode 100644 index 00000000..76add878 --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/advanced/Dockerfile b/reactions/sdk/javascript/examples/advanced/Dockerfile new file mode 100644 index 00000000..e908e509 --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced/Dockerfile @@ -0,0 +1,16 @@ +FROM node:20 + +WORKDIR /usr/src/app + +COPY . . + +RUN npm install -g typescript +RUN npm install +RUN npm run build + +WORKDIR /usr/src/app/examples/advanced + +RUN npm install +RUN npm run build + +CMD ["npm", "start"] \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/advanced/Reaction.yaml b/reactions/sdk/javascript/examples/advanced/Reaction.yaml new file mode 100644 index 00000000..712b9c97 --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced/Reaction.yaml @@ -0,0 +1,10 @@ +kind: Reaction +apiVersion: v1 +name: test-advanced +spec: + kind: Advanced + queries: + query1: | + greeting: "Hello, World!" + query2: | + greeting: "Howdy!" diff --git a/reactions/sdk/javascript/examples/advanced/ReactionProvider.yaml b/reactions/sdk/javascript/examples/advanced/ReactionProvider.yaml new file mode 100644 index 00000000..44b88868 --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced/ReactionProvider.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ReactionProvider +name: Advanced +spec: + services: + simple: + image: reaction-advanced diff --git a/reactions/sdk/javascript/examples/advanced/package-lock.json b/reactions/sdk/javascript/examples/advanced/package-lock.json new file mode 100644 index 00000000..348c6ef9 --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced/package-lock.json @@ -0,0 +1,51 @@ +{ + "name": "example-reaction", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "example-reaction", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@drasi/reaction-sdk": "file:../../" + } + }, + "..": { + "name": "@drasi/reaction-sdk", + "version": "1.0.0", + "extraneous": true, + "license": "ISC", + "dependencies": { + "@dapr/dapr": "^3.4.1", + "tslib": "^2.8.0" + }, + "devDependencies": { + "@microsoft/api-extractor": "^7.47.11", + "@types/node": "^22.8.6", + "json-schema-to-typescript": "^15.0.2", + "typescript": "^5.6.3" + } + }, + "../..": { + "name": "@drasi/reaction-sdk", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@dapr/dapr": "^3.4.1", + "tslib": "^2.8.0" + }, + "devDependencies": { + "@microsoft/api-extractor": "^7.47.11", + "@types/node": "^22.8.6", + "json-schema-to-typescript": "^15.0.2", + "typescript": "^5.6.3" + } + }, + "node_modules/@drasi/reaction-sdk": { + "resolved": "../..", + "link": true + } + } +} diff --git a/reactions/sdk/javascript/examples/advanced/package.json b/reactions/sdk/javascript/examples/advanced/package.json new file mode 100644 index 00000000..0174ef1a --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced/package.json @@ -0,0 +1,16 @@ +{ + "name": "example-reaction", + "version": "1.0.0", + "main": "dist/index.js", + "scripts": { + "build": "tsc", + "start": "node dist/index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "Apache-2.0", + "description": "", + "dependencies": { + "@drasi/reaction-sdk": "file:../../" + } +} diff --git a/reactions/sdk/javascript/examples/advanced/src/index.ts b/reactions/sdk/javascript/examples/advanced/src/index.ts new file mode 100644 index 00000000..95bcf0b5 --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced/src/index.ts @@ -0,0 +1,41 @@ +import { DrasiReaction, ChangeEvent,parseYaml, ControlEvent, getConfigValue } from '@drasi/reaction-sdk'; + +const myConnectionString = getConfigValue("MyConnectionString", ""); + +async function main() { + console.log(`Starting Drasi reaction with connection string: ${myConnectionString}`); + + let myReaction = new DrasiReaction(onChangeEvent, { + parseQueryConfig: parseYaml, + onControlEvent: onControlEvent + }); + + await myReaction.start(); +} + +class MyQueryConfig { + greeting: string = "Default greeting"; +} + +async function onChangeEvent(event: ChangeEvent, queryConfig?: MyQueryConfig): Promise { + console.log(queryConfig.greeting); + console.log(`Received change sequence: ${event.sequence} for query ${event.queryId}`); + + for (let added of event.addedResults) { + console.log(`Added result: ${JSON.stringify(added)}`); + } + + for (let deleted of event.deletedResults) { + console.log(`Removed result: ${JSON.stringify(deleted)}`); + } + + for (let updated of event.updatedResults) { + console.log(`Updated result - before: ${JSON.stringify(updated.before)}, after: ${JSON.stringify(updated.after)}`); + } +} + +async function onControlEvent(event: ControlEvent, queryConfig?: MyQueryConfig): Promise { + console.log(`Received control signal: ${JSON.stringify(event.controlSignal)} for query ${event.queryId}`); +} + +main().catch(console.error); \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/advanced/tsconfig.json b/reactions/sdk/javascript/examples/advanced/tsconfig.json new file mode 100644 index 00000000..645f823c --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "commonjs", + "outDir": "./dist", + "esModuleInterop": true, + "sourceMap": true + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "**/*.test.ts"] + } \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/simple/src/index.ts b/reactions/sdk/javascript/examples/simple/src/index.ts index 1edcd86c..2785f04a 100644 --- a/reactions/sdk/javascript/examples/simple/src/index.ts +++ b/reactions/sdk/javascript/examples/simple/src/index.ts @@ -1,8 +1,8 @@ -import {DrasiReaction, ChangeEvent} from '@drasi/reaction-sdk'; +import { DrasiReaction, ChangeEvent } from '@drasi/reaction-sdk'; async function main() { - let myReaction = new DrasiReaction((event: ChangeEvent) => { + let myReaction = new DrasiReaction(async (event: ChangeEvent) => { console.log(`Received change sequence: ${event.sequence} for query ${event.queryId}`); diff --git a/reactions/sdk/javascript/package-lock.json b/reactions/sdk/javascript/package-lock.json index 155c7903..3de43020 100644 --- a/reactions/sdk/javascript/package-lock.json +++ b/reactions/sdk/javascript/package-lock.json @@ -1,16 +1,17 @@ { - "name": "drasi-reaction-sdk", + "name": "@drasi/reaction-sdk", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "drasi-reaction-sdk", + "name": "@drasi/reaction-sdk", "version": "1.0.0", - "license": "ISC", + "license": "Apache-2.0", "dependencies": { "@dapr/dapr": "^3.4.1", - "tslib": "^2.8.0" + "tslib": "^2.8.0", + "yaml": "^2.6.0" }, "devDependencies": { "@microsoft/api-extractor": "^7.47.11", @@ -2414,6 +2415,18 @@ "dev": true, "license": "ISC" }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/reactions/sdk/javascript/package.json b/reactions/sdk/javascript/package.json index 59ecbc0c..3f13d1ef 100644 --- a/reactions/sdk/javascript/package.json +++ b/reactions/sdk/javascript/package.json @@ -22,6 +22,7 @@ }, "dependencies": { "@dapr/dapr": "^3.4.1", - "tslib": "^2.8.0" + "tslib": "^2.8.0", + "yaml": "^2.6.0" } } diff --git a/reactions/sdk/javascript/src/index.ts b/reactions/sdk/javascript/src/index.ts index cb3d3fac..38778b0e 100644 --- a/reactions/sdk/javascript/src/index.ts +++ b/reactions/sdk/javascript/src/index.ts @@ -2,11 +2,16 @@ import { DaprServer } from "@dapr/dapr"; import { ChangeEvent } from "./types/ChangeEvent"; import { ControlEvent } from "./types/ControlEvent"; import { readdirSync, readFileSync } from "fs"; +import YAML from 'yaml' -export type OnChangeEvent = (event: ChangeEvent, queryConfig?: TQueryConfig) => void; -export type OnControlEvent = (event: ControlEvent, queryConfig?: TQueryConfig) => void; +export type OnChangeEvent = (event: ChangeEvent, queryConfig?: TQueryConfig) => Promise; +export type OnControlEvent = (event: ControlEvent, queryConfig?: TQueryConfig) => Promise; export { ChangeEvent } from "./types/ChangeEvent"; export { ControlEvent } from "./types/ControlEvent"; +export { RunningSignal } from "./types/RunningSignal"; +export { BootstrapStartedSignal } from "./types/BootstrapStartedSignal"; +export { BootstrapCompletedSignal } from "./types/BootstrapCompletedSignal"; +export { StoppedSignal } from "./types/StoppedSignal"; export type ReactionOptions = { onControlEvent?: OnControlEvent; @@ -35,7 +40,7 @@ export class DrasiReaction { let queryIds = readdirSync(this.configDirectory); for (let queryId of queryIds) { console.log(`Subscribing to query ${queryId}`); - this.daprServer.pubsub.subscribe(this.pubSubName, `${queryId}-results`, this.onMessage.bind(this)); + await this.daprServer.pubsub.subscribe(this.pubSubName, `${queryId}-results`, this.onMessage.bind(this)); if (this.parseQueryConfig) { let cfgStr = readFileSync(`${this.configDirectory}/${queryId}`, 'utf-8'); let cfg = this.parseQueryConfig(queryId, cfgStr); @@ -54,18 +59,29 @@ export class DrasiReaction { let queryConfig = this.queryConfig.get(data.queryId); switch (data.kind) { case "change": - this.onChangeEvent(data, queryConfig); + await this.onChangeEvent(data, queryConfig); break; case "control": if (!this.onControlEvent) { console.log("Received control event but no handler is registered"); return; } - this.onControlEvent(data, queryConfig); + await this.onControlEvent(data, queryConfig); break; default: console.log("Unknown message kind: " + data.kind); } } +} + +export function getConfigValue(key: string, defaultValue: string): string { + return process.env[key] ?? defaultValue; +} + +export function parseJson(queryId: string, config: string): any { + return JSON.parse(config); +} +export function parseYaml(queryId: string, config: string): any { + return YAML.parse(config); } \ No newline at end of file From 9966071dd2f9ee8accc3d2a09faafc24a8e47142 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 1 Nov 2024 13:01:19 -0700 Subject: [PATCH 03/17] inline docs --- reactions/sdk/javascript/.npmignore | 5 + reactions/sdk/javascript/README.md | 84 + reactions/sdk/javascript/api-extractor.json | 454 ------ .../{advanced => advanced-ts}/.dockerignore | 0 .../{advanced => advanced-ts}/.gitignore | 0 .../{simple => advanced-ts}/Dockerfile | 7 +- .../examples/advanced-ts/package-lock.json | 1413 +++++++++++++++++ .../{advanced => advanced-ts}/package.json | 2 +- .../advanced-ts/reaction-provider.yaml | 14 + .../reaction.yaml} | 2 + .../{advanced => advanced-ts}/src/index.ts | 28 +- .../{advanced => advanced-ts}/tsconfig.json | 0 .../examples/advanced/ReactionProvider.yaml | 7 - .../examples/advanced/package-lock.json | 51 - .../{simple => simple-ts}/.dockerignore | 0 .../examples/{simple => simple-ts}/.gitignore | 0 .../{advanced => simple-ts}/Dockerfile | 7 +- .../examples/simple-ts/package-lock.json | 1413 +++++++++++++++++ .../{simple => simple-ts}/package.json | 2 +- .../reaction-provider.yaml} | 0 .../Reaction.yaml => simple-ts/reaction.yaml} | 0 .../examples/simple-ts/src/index.ts | 20 + .../{simple => simple-ts}/tsconfig.json | 0 .../examples/simple/package-lock.json | 51 - .../javascript/examples/simple/src/index.ts | 25 - reactions/sdk/javascript/package.json | 12 +- reactions/sdk/javascript/src/index.ts | 91 +- reactions/sdk/javascript/src/options.ts | 59 + .../src/types/BootstrapCompletedSignal.d.ts | 3 + .../src/types/BootstrapStartedSignal.d.ts | 3 + .../sdk/javascript/src/types/ChangeEvent.d.ts | 25 +- .../javascript/src/types/ControlEvent.d.ts | 12 + .../javascript/src/types/DeletedSignal.d.ts | 3 + .../sdk/javascript/src/types/ResultEvent.d.ts | 9 + .../javascript/src/types/RunningSignal.d.ts | 3 + .../javascript/src/types/StoppedSignal.d.ts | 3 + .../javascript/src/types/UpdatePayload.d.ts | 7 +- reactions/sdk/javascript/src/utils.ts | 59 + typespec/query-output/main.tsp | 25 +- 39 files changed, 3240 insertions(+), 659 deletions(-) create mode 100644 reactions/sdk/javascript/.npmignore create mode 100644 reactions/sdk/javascript/README.md delete mode 100644 reactions/sdk/javascript/api-extractor.json rename reactions/sdk/javascript/examples/{advanced => advanced-ts}/.dockerignore (100%) rename reactions/sdk/javascript/examples/{advanced => advanced-ts}/.gitignore (100%) rename reactions/sdk/javascript/examples/{simple => advanced-ts}/Dockerfile (57%) create mode 100644 reactions/sdk/javascript/examples/advanced-ts/package-lock.json rename reactions/sdk/javascript/examples/{advanced => advanced-ts}/package.json (88%) create mode 100644 reactions/sdk/javascript/examples/advanced-ts/reaction-provider.yaml rename reactions/sdk/javascript/examples/{advanced/Reaction.yaml => advanced-ts/reaction.yaml} (72%) rename reactions/sdk/javascript/examples/{advanced => advanced-ts}/src/index.ts (59%) rename reactions/sdk/javascript/examples/{advanced => advanced-ts}/tsconfig.json (100%) delete mode 100644 reactions/sdk/javascript/examples/advanced/ReactionProvider.yaml delete mode 100644 reactions/sdk/javascript/examples/advanced/package-lock.json rename reactions/sdk/javascript/examples/{simple => simple-ts}/.dockerignore (100%) rename reactions/sdk/javascript/examples/{simple => simple-ts}/.gitignore (100%) rename reactions/sdk/javascript/examples/{advanced => simple-ts}/Dockerfile (57%) create mode 100644 reactions/sdk/javascript/examples/simple-ts/package-lock.json rename reactions/sdk/javascript/examples/{simple => simple-ts}/package.json (88%) rename reactions/sdk/javascript/examples/{simple/ReactionProvider.yaml => simple-ts/reaction-provider.yaml} (100%) rename reactions/sdk/javascript/examples/{simple/Reaction.yaml => simple-ts/reaction.yaml} (100%) create mode 100644 reactions/sdk/javascript/examples/simple-ts/src/index.ts rename reactions/sdk/javascript/examples/{simple => simple-ts}/tsconfig.json (100%) delete mode 100644 reactions/sdk/javascript/examples/simple/package-lock.json delete mode 100644 reactions/sdk/javascript/examples/simple/src/index.ts create mode 100644 reactions/sdk/javascript/src/options.ts create mode 100644 reactions/sdk/javascript/src/utils.ts diff --git a/reactions/sdk/javascript/.npmignore b/reactions/sdk/javascript/.npmignore new file mode 100644 index 00000000..44a58d24 --- /dev/null +++ b/reactions/sdk/javascript/.npmignore @@ -0,0 +1,5 @@ +examples/ +test/ +node_modules/ +.DS_Store +.env diff --git a/reactions/sdk/javascript/README.md b/reactions/sdk/javascript/README.md new file mode 100644 index 00000000..af4c4cc9 --- /dev/null +++ b/reactions/sdk/javascript/README.md @@ -0,0 +1,84 @@ +# Reaction SDK for Drasi + +This library provides the building blocks and infrastructure to implement a [Drasi](https://drasi.io/) Reaction in Node.js + +## Getting started + +### Install the package + +``` +npm install --save @drasi/reaction-sdk +``` + +### Basic example + +The following example simply breaks down and logs the various parts of the incoming change event from a [Continuous Query](https://drasi.io/concepts/continuous-queries/). + +```typescript +import { DrasiReaction, ChangeEvent } from '@drasi/reaction-sdk'; + +let myReaction = new DrasiReaction(async (event: ChangeEvent) => { + + console.log(`Received change sequence: ${event.sequence} for query ${event.queryId}`); + + for (let added of event.addedResults) { + console.log(`Added result: ${JSON.stringify(added)}`); + } + + for (let deleted of event.deletedResults) { + console.log(`Removed result: ${JSON.stringify(deleted)}`); + } + + for (let updated of event.updatedResults) { + console.log(`Updated result - before: ${JSON.stringify(updated.before)}, after: ${JSON.stringify(updated.after)}`); + } +}); + +myReaction.start(); +``` + +### A more advanced example + +The following example illustrates + - Retrieving a configuration value from the Reaction manifest + - Defining a custom per query configuration object + - Parsing the per query configuration object from Yaml + - Process change events form thw query + - Process control events (start, stop, etc.) from the query + + +```typescript +import { DrasiReaction, ChangeEvent,parseYaml, ControlEvent, getConfigValue } from '@drasi/reaction-sdk'; + +// Retrieve the connection string from the Reaction configuration +const myConnectionString = getConfigValue("MyConnectionString"); + +// Define a custom per query configuration object +class MyQueryConfig { + greeting: string = "Default greeting"; +} + +// Define the function that will be called when a change event is received +async function onChangeEvent(event: ChangeEvent, queryConfig?: MyQueryConfig): Promise { + // We can access the per query config here + console.log(queryConfig.greeting); + + // do something with the result set diff +} + +// Define the function that will be called when a control event is received +async function onControlEvent(event: ControlEvent, queryConfig?: MyQueryConfig): Promise { + console.log(`Received control signal: ${JSON.stringify(event.controlSignal)} for query ${event.queryId}`); +} + +console.log(`Starting Drasi reaction with connection string: ${myConnectionString}`); + +// Configure the Reaction with the onChangeEvent and onControlEvent functions +let myReaction = new DrasiReaction(onChangeEvent, { + parseQueryConfig: parseYaml, // Parse the per query configuration from Yaml + onControlEvent: onControlEvent +}); + +// Start the Reaction +myReaction.start(); +``` \ No newline at end of file diff --git a/reactions/sdk/javascript/api-extractor.json b/reactions/sdk/javascript/api-extractor.json deleted file mode 100644 index 4e1f7be9..00000000 --- a/reactions/sdk/javascript/api-extractor.json +++ /dev/null @@ -1,454 +0,0 @@ -/** - * Config file for API Extractor. For more info, please visit: https://api-extractor.com - */ -{ - "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", - - /** - * Optionally specifies another JSON config file that this file extends from. This provides a way for - * standard settings to be shared across multiple projects. - * - * If the path starts with "./" or "../", the path is resolved relative to the folder of the file that contains - * the "extends" field. Otherwise, the first path segment is interpreted as an NPM package name, and will be - * resolved using NodeJS require(). - * - * SUPPORTED TOKENS: none - * DEFAULT VALUE: "" - */ - // "extends": "./shared/api-extractor-base.json" - // "extends": "my-package/include/api-extractor-base.json" - - /** - * Determines the "" token that can be used with other config file settings. The project folder - * typically contains the tsconfig.json and package.json config files, but the path is user-defined. - * - * The path is resolved relative to the folder of the config file that contains the setting. - * - * The default value for "projectFolder" is the token "", which means the folder is determined by traversing - * parent folders, starting from the folder containing api-extractor.json, and stopping at the first folder - * that contains a tsconfig.json file. If a tsconfig.json file cannot be found in this way, then an error - * will be reported. - * - * SUPPORTED TOKENS: - * DEFAULT VALUE: "" - */ - // "projectFolder": "..", - - /** - * (REQUIRED) Specifies the .d.ts file to be used as the starting point for analysis. API Extractor - * analyzes the symbols exported by this module. - * - * The file extension must be ".d.ts" and not ".ts". - * - * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as "". - * - * SUPPORTED TOKENS: , , - */ - "mainEntryPointFilePath": "/lib/index.d.ts", - - /** - * A list of NPM package names whose exports should be treated as part of this package. - * - * For example, suppose that Webpack is used to generate a distributed bundle for the project "library1", - * and another NPM package "library2" is embedded in this bundle. Some types from library2 may become part - * of the exported API for library1, but by default API Extractor would generate a .d.ts rollup that explicitly - * imports library2. To avoid this, we might specify: - * - * "bundledPackages": [ "library2" ], - * - * This would direct API Extractor to embed those types directly in the .d.ts rollup, as if they had been - * local files for library1. - * - * The "bundledPackages" elements may specify glob patterns using minimatch syntax. To ensure deterministic - * output, globs are expanded by matching explicitly declared top-level dependencies only. For example, - * the pattern below will NOT match "@my-company/example" unless it appears in a field such as "dependencies" - * or "devDependencies" of the project's package.json file: - * - * "bundledPackages": [ "@my-company/*" ], - */ - "bundledPackages": [], - - /** - * Specifies what type of newlines API Extractor should use when writing output files. By default, the output files - * will be written with Windows-style newlines. To use POSIX-style newlines, specify "lf" instead. - * To use the OS's default newline kind, specify "os". - * - * DEFAULT VALUE: "crlf" - */ - // "newlineKind": "crlf", - - /** - * Specifies how API Extractor sorts members of an enum when generating the .api.json file. By default, the output - * files will be sorted alphabetically, which is "by-name". To keep the ordering in the source code, specify - * "preserve". - * - * DEFAULT VALUE: "by-name" - */ - // "enumMemberOrder": "by-name", - - /** - * Set to true when invoking API Extractor's test harness. When `testMode` is true, the `toolVersion` field in the - * .api.json file is assigned an empty string to prevent spurious diffs in output files tracked for tests. - * - * DEFAULT VALUE: "false" - */ - // "testMode": false, - - /** - * Determines how the TypeScript compiler engine will be invoked by API Extractor. - */ - "compiler": { - /** - * Specifies the path to the tsconfig.json file to be used by API Extractor when analyzing the project. - * - * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as "". - * - * Note: This setting will be ignored if "overrideTsconfig" is used. - * - * SUPPORTED TOKENS: , , - * DEFAULT VALUE: "/tsconfig.json" - */ - // "tsconfigFilePath": "/tsconfig.json", - /** - * Provides a compiler configuration that will be used instead of reading the tsconfig.json file from disk. - * The object must conform to the TypeScript tsconfig schema: - * - * http://json.schemastore.org/tsconfig - * - * If omitted, then the tsconfig.json file will be read from the "projectFolder". - * - * DEFAULT VALUE: no overrideTsconfig section - */ - // "overrideTsconfig": { - // . . . - // } - /** - * This option causes the compiler to be invoked with the --skipLibCheck option. This option is not recommended - * and may cause API Extractor to produce incomplete or incorrect declarations, but it may be required when - * dependencies contain declarations that are incompatible with the TypeScript engine that API Extractor uses - * for its analysis. Where possible, the underlying issue should be fixed rather than relying on skipLibCheck. - * - * DEFAULT VALUE: false - */ - // "skipLibCheck": true, - }, - - /** - * Configures how the API report file (*.api.md) will be generated. - */ - "apiReport": { - /** - * (REQUIRED) Whether to generate an API report. - */ - "enabled": true - - /** - * The base filename for the API report files, to be combined with "reportFolder" or "reportTempFolder" - * to produce the full file path. The "reportFileName" should not include any path separators such as - * "\" or "/". The "reportFileName" should not include a file extension, since API Extractor will automatically - * append an appropriate file extension such as ".api.md". If the "reportVariants" setting is used, then the - * file extension includes the variant name, for example "my-report.public.api.md" or "my-report.beta.api.md". - * The "complete" variant always uses the simple extension "my-report.api.md". - * - * Previous versions of API Extractor required "reportFileName" to include the ".api.md" extension explicitly; - * for backwards compatibility, that is still accepted but will be discarded before applying the above rules. - * - * SUPPORTED TOKENS: , - * DEFAULT VALUE: "" - */ - // "reportFileName": "", - - /** - * To support different approval requirements for different API levels, multiple "variants" of the API report can - * be generated. The "reportVariants" setting specifies a list of variants to be generated. If omitted, - * by default only the "complete" variant will be generated, which includes all @internal, @alpha, @beta, - * and @public items. Other possible variants are "alpha" (@alpha + @beta + @public), "beta" (@beta + @public), - * and "public" (@public only). - * - * DEFAULT VALUE: [ "complete" ] - */ - // "reportVariants": ["public", "beta"], - - /** - * Specifies the folder where the API report file is written. The file name portion is determined by - * the "reportFileName" setting. - * - * The API report file is normally tracked by Git. Changes to it can be used to trigger a branch policy, - * e.g. for an API review. - * - * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as "". - * - * SUPPORTED TOKENS: , , - * DEFAULT VALUE: "/etc/" - */ - // "reportFolder": "/etc/", - - /** - * Specifies the folder where the temporary report file is written. The file name portion is determined by - * the "reportFileName" setting. - * - * After the temporary file is written to disk, it is compared with the file in the "reportFolder". - * If they are different, a production build will fail. - * - * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as "". - * - * SUPPORTED TOKENS: , , - * DEFAULT VALUE: "/temp/" - */ - // "reportTempFolder": "/temp/", - - /** - * Whether "forgotten exports" should be included in the API report file. Forgotten exports are declarations - * flagged with `ae-forgotten-export` warnings. See https://api-extractor.com/pages/messages/ae-forgotten-export/ to - * learn more. - * - * DEFAULT VALUE: "false" - */ - // "includeForgottenExports": false - }, - - /** - * Configures how the doc model file (*.api.json) will be generated. - */ - "docModel": { - /** - * (REQUIRED) Whether to generate a doc model file. - */ - "enabled": true - - /** - * The output path for the doc model file. The file extension should be ".api.json". - * - * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as "". - * - * SUPPORTED TOKENS: , , - * DEFAULT VALUE: "/temp/.api.json" - */ - // "apiJsonFilePath": "/temp/.api.json", - - /** - * Whether "forgotten exports" should be included in the doc model file. Forgotten exports are declarations - * flagged with `ae-forgotten-export` warnings. See https://api-extractor.com/pages/messages/ae-forgotten-export/ to - * learn more. - * - * DEFAULT VALUE: "false" - */ - // "includeForgottenExports": false, - - /** - * The base URL where the project's source code can be viewed on a website such as GitHub or - * Azure DevOps. This URL path corresponds to the `` path on disk. - * - * This URL is concatenated with the file paths serialized to the doc model to produce URL file paths to individual API items. - * For example, if the `projectFolderUrl` is "https://github.com/microsoft/rushstack/tree/main/apps/api-extractor" and an API - * item's file path is "api/ExtractorConfig.ts", the full URL file path would be - * "https://github.com/microsoft/rushstack/tree/main/apps/api-extractor/api/ExtractorConfig.js". - * - * This setting can be omitted if you don't need source code links in your API documentation reference. - * - * SUPPORTED TOKENS: none - * DEFAULT VALUE: "" - */ - // "projectFolderUrl": "http://github.com/path/to/your/projectFolder" - }, - - /** - * Configures how the .d.ts rollup file will be generated. - */ - "dtsRollup": { - /** - * (REQUIRED) Whether to generate the .d.ts rollup file. - */ - "enabled": true - - /** - * Specifies the output path for a .d.ts rollup file to be generated without any trimming. - * This file will include all declarations that are exported by the main entry point. - * - * If the path is an empty string, then this file will not be written. - * - * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as "". - * - * SUPPORTED TOKENS: , , - * DEFAULT VALUE: "/dist/.d.ts" - */ - // "untrimmedFilePath": "/dist/.d.ts", - - /** - * Specifies the output path for a .d.ts rollup file to be generated with trimming for an "alpha" release. - * This file will include only declarations that are marked as "@public", "@beta", or "@alpha". - * - * If the path is an empty string, then this file will not be written. - * - * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as "". - * - * SUPPORTED TOKENS: , , - * DEFAULT VALUE: "" - */ - // "alphaTrimmedFilePath": "/dist/-alpha.d.ts", - - /** - * Specifies the output path for a .d.ts rollup file to be generated with trimming for a "beta" release. - * This file will include only declarations that are marked as "@public" or "@beta". - * - * If the path is an empty string, then this file will not be written. - * - * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as "". - * - * SUPPORTED TOKENS: , , - * DEFAULT VALUE: "" - */ - // "betaTrimmedFilePath": "/dist/-beta.d.ts", - - /** - * Specifies the output path for a .d.ts rollup file to be generated with trimming for a "public" release. - * This file will include only declarations that are marked as "@public". - * - * If the path is an empty string, then this file will not be written. - * - * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as "". - * - * SUPPORTED TOKENS: , , - * DEFAULT VALUE: "" - */ - // "publicTrimmedFilePath": "/dist/-public.d.ts", - - /** - * When a declaration is trimmed, by default it will be replaced by a code comment such as - * "Excluded from this release type: exampleMember". Set "omitTrimmingComments" to true to remove the - * declaration completely. - * - * DEFAULT VALUE: false - */ - // "omitTrimmingComments": true - }, - - /** - * Configures how the tsdoc-metadata.json file will be generated. - */ - "tsdocMetadata": { - /** - * Whether to generate the tsdoc-metadata.json file. - * - * DEFAULT VALUE: true - */ - // "enabled": true, - /** - * Specifies where the TSDoc metadata file should be written. - * - * The path is resolved relative to the folder of the config file that contains the setting; to change this, - * prepend a folder token such as "". - * - * The default value is "", which causes the path to be automatically inferred from the "tsdocMetadata", - * "typings" or "main" fields of the project's package.json. If none of these fields are set, the lookup - * falls back to "tsdoc-metadata.json" in the package folder. - * - * SUPPORTED TOKENS: , , - * DEFAULT VALUE: "" - */ - // "tsdocMetadataFilePath": "/dist/tsdoc-metadata.json" - }, - - /** - * Configures how API Extractor reports error and warning messages produced during analysis. - * - * There are three sources of messages: compiler messages, API Extractor messages, and TSDoc messages. - */ - "messages": { - /** - * Configures handling of diagnostic messages reported by the TypeScript compiler engine while analyzing - * the input .d.ts files. - * - * TypeScript message identifiers start with "TS" followed by an integer. For example: "TS2551" - * - * DEFAULT VALUE: A single "default" entry with logLevel=warning. - */ - "compilerMessageReporting": { - /** - * Configures the default routing for messages that don't match an explicit rule in this table. - */ - "default": { - /** - * Specifies whether the message should be written to the the tool's output log. Note that - * the "addToApiReportFile" property may supersede this option. - * - * Possible values: "error", "warning", "none" - * - * Errors cause the build to fail and return a nonzero exit code. Warnings cause a production build fail - * and return a nonzero exit code. For a non-production build (e.g. when "api-extractor run" includes - * the "--local" option), the warning is displayed but the build will not fail. - * - * DEFAULT VALUE: "warning" - */ - "logLevel": "warning" - - /** - * When addToApiReportFile is true: If API Extractor is configured to write an API report file (.api.md), - * then the message will be written inside that file; otherwise, the message is instead logged according to - * the "logLevel" option. - * - * DEFAULT VALUE: false - */ - // "addToApiReportFile": false - } - - // "TS2551": { - // "logLevel": "warning", - // "addToApiReportFile": true - // }, - // - // . . . - }, - - /** - * Configures handling of messages reported by API Extractor during its analysis. - * - * API Extractor message identifiers start with "ae-". For example: "ae-extra-release-tag" - * - * DEFAULT VALUE: See api-extractor-defaults.json for the complete table of extractorMessageReporting mappings - */ - "extractorMessageReporting": { - "default": { - "logLevel": "warning" - // "addToApiReportFile": false - } - - // "ae-extra-release-tag": { - // "logLevel": "warning", - // "addToApiReportFile": true - // }, - // - // . . . - }, - - /** - * Configures handling of messages reported by the TSDoc parser when analyzing code comments. - * - * TSDoc message identifiers start with "tsdoc-". For example: "tsdoc-link-tag-unescaped-text" - * - * DEFAULT VALUE: A single "default" entry with logLevel=warning. - */ - "tsdocMessageReporting": { - "default": { - "logLevel": "warning" - // "addToApiReportFile": false - } - - // "tsdoc-link-tag-unescaped-text": { - // "logLevel": "warning", - // "addToApiReportFile": true - // }, - // - // . . . - } - } -} diff --git a/reactions/sdk/javascript/examples/advanced/.dockerignore b/reactions/sdk/javascript/examples/advanced-ts/.dockerignore similarity index 100% rename from reactions/sdk/javascript/examples/advanced/.dockerignore rename to reactions/sdk/javascript/examples/advanced-ts/.dockerignore diff --git a/reactions/sdk/javascript/examples/advanced/.gitignore b/reactions/sdk/javascript/examples/advanced-ts/.gitignore similarity index 100% rename from reactions/sdk/javascript/examples/advanced/.gitignore rename to reactions/sdk/javascript/examples/advanced-ts/.gitignore diff --git a/reactions/sdk/javascript/examples/simple/Dockerfile b/reactions/sdk/javascript/examples/advanced-ts/Dockerfile similarity index 57% rename from reactions/sdk/javascript/examples/simple/Dockerfile rename to reactions/sdk/javascript/examples/advanced-ts/Dockerfile index 357e7d89..d67fb134 100644 --- a/reactions/sdk/javascript/examples/simple/Dockerfile +++ b/reactions/sdk/javascript/examples/advanced-ts/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20 +FROM node:20-alpine WORKDIR /usr/src/app @@ -8,9 +8,4 @@ RUN npm install -g typescript RUN npm install RUN npm run build -WORKDIR /usr/src/app/examples/simple - -RUN npm install -RUN npm run build - CMD ["npm", "start"] \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/advanced-ts/package-lock.json b/reactions/sdk/javascript/examples/advanced-ts/package-lock.json new file mode 100644 index 00000000..9a0bdf06 --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced-ts/package-lock.json @@ -0,0 +1,1413 @@ +{ + "name": "example-reaction", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "example-reaction", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@drasi/reaction-sdk": "0.1.0-alpha" + } + }, + "node_modules/@dapr/dapr": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@dapr/dapr/-/dapr-3.4.1.tgz", + "integrity": "sha512-Ev9/Pqzo2ftiDU3gYOCiOJR/UZ5fZk+y+hFcn133mBkYvbU9cTU9S+/46kH2YVJCg6+62m/rG7LQ1o2s5gX76Q==", + "license": "ISC", + "dependencies": { + "@grpc/grpc-js": "^1.9.3", + "@js-temporal/polyfill": "^0.3.0", + "@microsoft/durabletask-js": "^0.1.0-alpha.2", + "@types/google-protobuf": "^3.15.5", + "@types/node-fetch": "^2.6.2", + "body-parser": "^1.19.0", + "express": "^4.18.2", + "google-protobuf": "^3.18.0", + "http-terminator": "^3.2.0", + "node-fetch": "^2.6.7" + } + }, + "node_modules/@drasi/reaction-sdk": { + "version": "0.1.0-alpha", + "resolved": "https://registry.npmjs.org/@drasi/reaction-sdk/-/reaction-sdk-0.1.0-alpha.tgz", + "integrity": "sha512-ecnOOHtVHlpHLt/NdQw4FR5W6CCIHtCu2vf7ZoWJz30Op+P6oQ36MQ8M3Gi1jzBFp4Zd/pM6sxi/Whh1OULFaA==", + "license": "Apache-2.0", + "dependencies": { + "@dapr/dapr": "^3.4.1", + "tslib": "^2.8.0", + "yaml": "^2.6.0" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.2.tgz", + "integrity": "sha512-bgxdZmgTrJZX50OjyVwz3+mNEnCTNkh3cIqGPWVNeW9jX6bn1ZkU80uPd+67/ZpIJIjRQ9qaHCjhavyoWYxumg==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@js-temporal/polyfill": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@js-temporal/polyfill/-/polyfill-0.3.0.tgz", + "integrity": "sha512-cxxxis19j0WvK3+kUwKrXeXaDBaWxLeRfKqlVz7g50Cly6UgGs2p3wovH9zjtZ4TtjYHDR4De/880+aalduDZQ==", + "license": "ISC", + "dependencies": { + "big-integer": "^1.6.51", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@microsoft/durabletask-js": { + "version": "0.1.0-alpha.2", + "resolved": "https://registry.npmjs.org/@microsoft/durabletask-js/-/durabletask-js-0.1.0-alpha.2.tgz", + "integrity": "sha512-EiUgOyT05JQ9/M/InjTKdXs5Y1XxdXRczb6nizceJglXr8S/myxMnQHDV1QRASxroFCoTyKiDHU6uAq4Cpe/LQ==", + "license": "MIT", + "dependencies": { + "@grpc/grpc-js": "^1.8.14", + "google-protobuf": "^3.21.2" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, + "node_modules/@types/google-protobuf": { + "version": "3.15.12", + "resolved": "https://registry.npmjs.org/@types/google-protobuf/-/google-protobuf-3.15.12.tgz", + "integrity": "sha512-40um9QqwHjRS92qnOaDpL7RmDK15NuZYo9HihiJRbYkMQZlWnuH8AdvbMy8/o6lgLmKbDUKa+OALCltHdbOTpQ==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.6.tgz", + "integrity": "sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fast-printf": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", + "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "license": "BSD-3-Clause", + "dependencies": { + "boolean": "^3.1.4" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/google-protobuf": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.4.tgz", + "integrity": "sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==", + "license": "(BSD-3-Clause AND Apache-2.0)" + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-terminator": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/http-terminator/-/http-terminator-3.2.0.tgz", + "integrity": "sha512-JLjck1EzPaWjsmIf8bziM3p9fgR1Y3JoUKAkyYEbZmFrIvJM6I8vVJfBGWlEtV9IWOvzNnaTtjuwZeBY2kwB4g==", + "license": "BSD-3-Clause", + "dependencies": { + "delay": "^5.0.0", + "p-wait-for": "^3.2.0", + "roarr": "^7.0.4", + "type-fest": "^2.3.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "license": "Apache-2.0" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "license": "MIT", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-wait-for": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-wait-for/-/p-wait-for-3.2.0.tgz", + "integrity": "sha512-wpgERjNkLrBiFmkMEjuZJEWKKDrNfHCKA1OhyN1wg1FrLkULbviEy6py1AyJUgZ72YWFbZ38FIpnqvVqAlDUwA==", + "license": "MIT", + "dependencies": { + "p-timeout": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "license": "MIT" + }, + "node_modules/protobufjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/roarr": { + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-7.21.1.tgz", + "integrity": "sha512-3niqt5bXFY1InKU8HKWqqYTYjtrBaxBMnXELXCXUYgtNYGUtZM5rB46HIC430AyacL95iEniGf7RgqsesykLmQ==", + "license": "BSD-3-Clause", + "dependencies": { + "fast-printf": "^1.6.9", + "safe-stable-stringify": "^2.4.3", + "semver-compare": "^1.0.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/reactions/sdk/javascript/examples/advanced/package.json b/reactions/sdk/javascript/examples/advanced-ts/package.json similarity index 88% rename from reactions/sdk/javascript/examples/advanced/package.json rename to reactions/sdk/javascript/examples/advanced-ts/package.json index 0174ef1a..14dda5f0 100644 --- a/reactions/sdk/javascript/examples/advanced/package.json +++ b/reactions/sdk/javascript/examples/advanced-ts/package.json @@ -11,6 +11,6 @@ "license": "Apache-2.0", "description": "", "dependencies": { - "@drasi/reaction-sdk": "file:../../" + "@drasi/reaction-sdk": "0.1.0-alpha" } } diff --git a/reactions/sdk/javascript/examples/advanced-ts/reaction-provider.yaml b/reactions/sdk/javascript/examples/advanced-ts/reaction-provider.yaml new file mode 100644 index 00000000..97e7424f --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced-ts/reaction-provider.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ReactionProvider +name: Advanced +spec: + services: + reaction: + image: reaction-advanced + config_schema: + type: object + properties: + MyConnectionString: + type: string + required: + - MyConnectionString diff --git a/reactions/sdk/javascript/examples/advanced/Reaction.yaml b/reactions/sdk/javascript/examples/advanced-ts/reaction.yaml similarity index 72% rename from reactions/sdk/javascript/examples/advanced/Reaction.yaml rename to reactions/sdk/javascript/examples/advanced-ts/reaction.yaml index 712b9c97..6a8e34cc 100644 --- a/reactions/sdk/javascript/examples/advanced/Reaction.yaml +++ b/reactions/sdk/javascript/examples/advanced-ts/reaction.yaml @@ -3,6 +3,8 @@ apiVersion: v1 name: test-advanced spec: kind: Advanced + properties: + MyConnectionString: "some connection string" queries: query1: | greeting: "Hello, World!" diff --git a/reactions/sdk/javascript/examples/advanced/src/index.ts b/reactions/sdk/javascript/examples/advanced-ts/src/index.ts similarity index 59% rename from reactions/sdk/javascript/examples/advanced/src/index.ts rename to reactions/sdk/javascript/examples/advanced-ts/src/index.ts index 95bcf0b5..c139d987 100644 --- a/reactions/sdk/javascript/examples/advanced/src/index.ts +++ b/reactions/sdk/javascript/examples/advanced-ts/src/index.ts @@ -1,22 +1,14 @@ import { DrasiReaction, ChangeEvent,parseYaml, ControlEvent, getConfigValue } from '@drasi/reaction-sdk'; -const myConnectionString = getConfigValue("MyConnectionString", ""); - -async function main() { - console.log(`Starting Drasi reaction with connection string: ${myConnectionString}`); - - let myReaction = new DrasiReaction(onChangeEvent, { - parseQueryConfig: parseYaml, - onControlEvent: onControlEvent - }); - - await myReaction.start(); -} +// Retrieve the connection string from the Reaction configuration +const myConnectionString = getConfigValue("MyConnectionString"); +// Define a custom per query configuration object class MyQueryConfig { greeting: string = "Default greeting"; } +// Define the function that will be called when a change event is received async function onChangeEvent(event: ChangeEvent, queryConfig?: MyQueryConfig): Promise { console.log(queryConfig.greeting); console.log(`Received change sequence: ${event.sequence} for query ${event.queryId}`); @@ -34,8 +26,18 @@ async function onChangeEvent(event: ChangeEvent, queryConfig?: MyQueryConfig): P } } +// Define the function that will be called when a control event is received async function onControlEvent(event: ControlEvent, queryConfig?: MyQueryConfig): Promise { console.log(`Received control signal: ${JSON.stringify(event.controlSignal)} for query ${event.queryId}`); } -main().catch(console.error); \ No newline at end of file +console.log(`Starting Drasi reaction with connection string: ${myConnectionString}`); + +// Configure the Reaction with the onChangeEvent and onControlEvent functions +let myReaction = new DrasiReaction(onChangeEvent, { + parseQueryConfig: parseYaml, // Parse the per query configuration from Yaml + onControlEvent: onControlEvent +}); + +// Start the Reaction +myReaction.start(); diff --git a/reactions/sdk/javascript/examples/advanced/tsconfig.json b/reactions/sdk/javascript/examples/advanced-ts/tsconfig.json similarity index 100% rename from reactions/sdk/javascript/examples/advanced/tsconfig.json rename to reactions/sdk/javascript/examples/advanced-ts/tsconfig.json diff --git a/reactions/sdk/javascript/examples/advanced/ReactionProvider.yaml b/reactions/sdk/javascript/examples/advanced/ReactionProvider.yaml deleted file mode 100644 index 44b88868..00000000 --- a/reactions/sdk/javascript/examples/advanced/ReactionProvider.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: ReactionProvider -name: Advanced -spec: - services: - simple: - image: reaction-advanced diff --git a/reactions/sdk/javascript/examples/advanced/package-lock.json b/reactions/sdk/javascript/examples/advanced/package-lock.json deleted file mode 100644 index 348c6ef9..00000000 --- a/reactions/sdk/javascript/examples/advanced/package-lock.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "example-reaction", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "example-reaction", - "version": "1.0.0", - "license": "Apache-2.0", - "dependencies": { - "@drasi/reaction-sdk": "file:../../" - } - }, - "..": { - "name": "@drasi/reaction-sdk", - "version": "1.0.0", - "extraneous": true, - "license": "ISC", - "dependencies": { - "@dapr/dapr": "^3.4.1", - "tslib": "^2.8.0" - }, - "devDependencies": { - "@microsoft/api-extractor": "^7.47.11", - "@types/node": "^22.8.6", - "json-schema-to-typescript": "^15.0.2", - "typescript": "^5.6.3" - } - }, - "../..": { - "name": "@drasi/reaction-sdk", - "version": "1.0.0", - "license": "Apache-2.0", - "dependencies": { - "@dapr/dapr": "^3.4.1", - "tslib": "^2.8.0" - }, - "devDependencies": { - "@microsoft/api-extractor": "^7.47.11", - "@types/node": "^22.8.6", - "json-schema-to-typescript": "^15.0.2", - "typescript": "^5.6.3" - } - }, - "node_modules/@drasi/reaction-sdk": { - "resolved": "../..", - "link": true - } - } -} diff --git a/reactions/sdk/javascript/examples/simple/.dockerignore b/reactions/sdk/javascript/examples/simple-ts/.dockerignore similarity index 100% rename from reactions/sdk/javascript/examples/simple/.dockerignore rename to reactions/sdk/javascript/examples/simple-ts/.dockerignore diff --git a/reactions/sdk/javascript/examples/simple/.gitignore b/reactions/sdk/javascript/examples/simple-ts/.gitignore similarity index 100% rename from reactions/sdk/javascript/examples/simple/.gitignore rename to reactions/sdk/javascript/examples/simple-ts/.gitignore diff --git a/reactions/sdk/javascript/examples/advanced/Dockerfile b/reactions/sdk/javascript/examples/simple-ts/Dockerfile similarity index 57% rename from reactions/sdk/javascript/examples/advanced/Dockerfile rename to reactions/sdk/javascript/examples/simple-ts/Dockerfile index e908e509..d67fb134 100644 --- a/reactions/sdk/javascript/examples/advanced/Dockerfile +++ b/reactions/sdk/javascript/examples/simple-ts/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20 +FROM node:20-alpine WORKDIR /usr/src/app @@ -8,9 +8,4 @@ RUN npm install -g typescript RUN npm install RUN npm run build -WORKDIR /usr/src/app/examples/advanced - -RUN npm install -RUN npm run build - CMD ["npm", "start"] \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/simple-ts/package-lock.json b/reactions/sdk/javascript/examples/simple-ts/package-lock.json new file mode 100644 index 00000000..9a0bdf06 --- /dev/null +++ b/reactions/sdk/javascript/examples/simple-ts/package-lock.json @@ -0,0 +1,1413 @@ +{ + "name": "example-reaction", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "example-reaction", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@drasi/reaction-sdk": "0.1.0-alpha" + } + }, + "node_modules/@dapr/dapr": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@dapr/dapr/-/dapr-3.4.1.tgz", + "integrity": "sha512-Ev9/Pqzo2ftiDU3gYOCiOJR/UZ5fZk+y+hFcn133mBkYvbU9cTU9S+/46kH2YVJCg6+62m/rG7LQ1o2s5gX76Q==", + "license": "ISC", + "dependencies": { + "@grpc/grpc-js": "^1.9.3", + "@js-temporal/polyfill": "^0.3.0", + "@microsoft/durabletask-js": "^0.1.0-alpha.2", + "@types/google-protobuf": "^3.15.5", + "@types/node-fetch": "^2.6.2", + "body-parser": "^1.19.0", + "express": "^4.18.2", + "google-protobuf": "^3.18.0", + "http-terminator": "^3.2.0", + "node-fetch": "^2.6.7" + } + }, + "node_modules/@drasi/reaction-sdk": { + "version": "0.1.0-alpha", + "resolved": "https://registry.npmjs.org/@drasi/reaction-sdk/-/reaction-sdk-0.1.0-alpha.tgz", + "integrity": "sha512-ecnOOHtVHlpHLt/NdQw4FR5W6CCIHtCu2vf7ZoWJz30Op+P6oQ36MQ8M3Gi1jzBFp4Zd/pM6sxi/Whh1OULFaA==", + "license": "Apache-2.0", + "dependencies": { + "@dapr/dapr": "^3.4.1", + "tslib": "^2.8.0", + "yaml": "^2.6.0" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.2.tgz", + "integrity": "sha512-bgxdZmgTrJZX50OjyVwz3+mNEnCTNkh3cIqGPWVNeW9jX6bn1ZkU80uPd+67/ZpIJIjRQ9qaHCjhavyoWYxumg==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@js-temporal/polyfill": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@js-temporal/polyfill/-/polyfill-0.3.0.tgz", + "integrity": "sha512-cxxxis19j0WvK3+kUwKrXeXaDBaWxLeRfKqlVz7g50Cly6UgGs2p3wovH9zjtZ4TtjYHDR4De/880+aalduDZQ==", + "license": "ISC", + "dependencies": { + "big-integer": "^1.6.51", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@microsoft/durabletask-js": { + "version": "0.1.0-alpha.2", + "resolved": "https://registry.npmjs.org/@microsoft/durabletask-js/-/durabletask-js-0.1.0-alpha.2.tgz", + "integrity": "sha512-EiUgOyT05JQ9/M/InjTKdXs5Y1XxdXRczb6nizceJglXr8S/myxMnQHDV1QRASxroFCoTyKiDHU6uAq4Cpe/LQ==", + "license": "MIT", + "dependencies": { + "@grpc/grpc-js": "^1.8.14", + "google-protobuf": "^3.21.2" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, + "node_modules/@types/google-protobuf": { + "version": "3.15.12", + "resolved": "https://registry.npmjs.org/@types/google-protobuf/-/google-protobuf-3.15.12.tgz", + "integrity": "sha512-40um9QqwHjRS92qnOaDpL7RmDK15NuZYo9HihiJRbYkMQZlWnuH8AdvbMy8/o6lgLmKbDUKa+OALCltHdbOTpQ==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.6.tgz", + "integrity": "sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fast-printf": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", + "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "license": "BSD-3-Clause", + "dependencies": { + "boolean": "^3.1.4" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/google-protobuf": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.4.tgz", + "integrity": "sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==", + "license": "(BSD-3-Clause AND Apache-2.0)" + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-terminator": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/http-terminator/-/http-terminator-3.2.0.tgz", + "integrity": "sha512-JLjck1EzPaWjsmIf8bziM3p9fgR1Y3JoUKAkyYEbZmFrIvJM6I8vVJfBGWlEtV9IWOvzNnaTtjuwZeBY2kwB4g==", + "license": "BSD-3-Clause", + "dependencies": { + "delay": "^5.0.0", + "p-wait-for": "^3.2.0", + "roarr": "^7.0.4", + "type-fest": "^2.3.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "license": "Apache-2.0" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "license": "MIT", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-wait-for": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-wait-for/-/p-wait-for-3.2.0.tgz", + "integrity": "sha512-wpgERjNkLrBiFmkMEjuZJEWKKDrNfHCKA1OhyN1wg1FrLkULbviEy6py1AyJUgZ72YWFbZ38FIpnqvVqAlDUwA==", + "license": "MIT", + "dependencies": { + "p-timeout": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "license": "MIT" + }, + "node_modules/protobufjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/roarr": { + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-7.21.1.tgz", + "integrity": "sha512-3niqt5bXFY1InKU8HKWqqYTYjtrBaxBMnXELXCXUYgtNYGUtZM5rB46HIC430AyacL95iEniGf7RgqsesykLmQ==", + "license": "BSD-3-Clause", + "dependencies": { + "fast-printf": "^1.6.9", + "safe-stable-stringify": "^2.4.3", + "semver-compare": "^1.0.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/reactions/sdk/javascript/examples/simple/package.json b/reactions/sdk/javascript/examples/simple-ts/package.json similarity index 88% rename from reactions/sdk/javascript/examples/simple/package.json rename to reactions/sdk/javascript/examples/simple-ts/package.json index 0174ef1a..14dda5f0 100644 --- a/reactions/sdk/javascript/examples/simple/package.json +++ b/reactions/sdk/javascript/examples/simple-ts/package.json @@ -11,6 +11,6 @@ "license": "Apache-2.0", "description": "", "dependencies": { - "@drasi/reaction-sdk": "file:../../" + "@drasi/reaction-sdk": "0.1.0-alpha" } } diff --git a/reactions/sdk/javascript/examples/simple/ReactionProvider.yaml b/reactions/sdk/javascript/examples/simple-ts/reaction-provider.yaml similarity index 100% rename from reactions/sdk/javascript/examples/simple/ReactionProvider.yaml rename to reactions/sdk/javascript/examples/simple-ts/reaction-provider.yaml diff --git a/reactions/sdk/javascript/examples/simple/Reaction.yaml b/reactions/sdk/javascript/examples/simple-ts/reaction.yaml similarity index 100% rename from reactions/sdk/javascript/examples/simple/Reaction.yaml rename to reactions/sdk/javascript/examples/simple-ts/reaction.yaml diff --git a/reactions/sdk/javascript/examples/simple-ts/src/index.ts b/reactions/sdk/javascript/examples/simple-ts/src/index.ts new file mode 100644 index 00000000..be9222b7 --- /dev/null +++ b/reactions/sdk/javascript/examples/simple-ts/src/index.ts @@ -0,0 +1,20 @@ +import { DrasiReaction, ChangeEvent } from '@drasi/reaction-sdk'; + +let myReaction = new DrasiReaction(async (event: ChangeEvent) => { + + console.log(`Received change sequence: ${event.sequence} for query ${event.queryId}`); + + for (let added of event.addedResults) { + console.log(`Added result: ${JSON.stringify(added)}`); + } + + for (let deleted of event.deletedResults) { + console.log(`Removed result: ${JSON.stringify(deleted)}`); + } + + for (let updated of event.updatedResults) { + console.log(`Updated result - before: ${JSON.stringify(updated.before)}, after: ${JSON.stringify(updated.after)}`); + } +}); + +myReaction.start(); \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/simple/tsconfig.json b/reactions/sdk/javascript/examples/simple-ts/tsconfig.json similarity index 100% rename from reactions/sdk/javascript/examples/simple/tsconfig.json rename to reactions/sdk/javascript/examples/simple-ts/tsconfig.json diff --git a/reactions/sdk/javascript/examples/simple/package-lock.json b/reactions/sdk/javascript/examples/simple/package-lock.json deleted file mode 100644 index 348c6ef9..00000000 --- a/reactions/sdk/javascript/examples/simple/package-lock.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "example-reaction", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "example-reaction", - "version": "1.0.0", - "license": "Apache-2.0", - "dependencies": { - "@drasi/reaction-sdk": "file:../../" - } - }, - "..": { - "name": "@drasi/reaction-sdk", - "version": "1.0.0", - "extraneous": true, - "license": "ISC", - "dependencies": { - "@dapr/dapr": "^3.4.1", - "tslib": "^2.8.0" - }, - "devDependencies": { - "@microsoft/api-extractor": "^7.47.11", - "@types/node": "^22.8.6", - "json-schema-to-typescript": "^15.0.2", - "typescript": "^5.6.3" - } - }, - "../..": { - "name": "@drasi/reaction-sdk", - "version": "1.0.0", - "license": "Apache-2.0", - "dependencies": { - "@dapr/dapr": "^3.4.1", - "tslib": "^2.8.0" - }, - "devDependencies": { - "@microsoft/api-extractor": "^7.47.11", - "@types/node": "^22.8.6", - "json-schema-to-typescript": "^15.0.2", - "typescript": "^5.6.3" - } - }, - "node_modules/@drasi/reaction-sdk": { - "resolved": "../..", - "link": true - } - } -} diff --git a/reactions/sdk/javascript/examples/simple/src/index.ts b/reactions/sdk/javascript/examples/simple/src/index.ts deleted file mode 100644 index 2785f04a..00000000 --- a/reactions/sdk/javascript/examples/simple/src/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { DrasiReaction, ChangeEvent } from '@drasi/reaction-sdk'; - -async function main() { - - let myReaction = new DrasiReaction(async (event: ChangeEvent) => { - - console.log(`Received change sequence: ${event.sequence} for query ${event.queryId}`); - - for (let added of event.addedResults) { - console.log(`Added result: ${JSON.stringify(added)}`); - } - - for (let deleted of event.deletedResults) { - console.log(`Removed result: ${JSON.stringify(deleted)}`); - } - - for (let updated of event.updatedResults) { - console.log(`Updated result - before: ${JSON.stringify(updated.before)}, after: ${JSON.stringify(updated.after)}`); - } - }); - - await myReaction.start(); -} - -main().catch(console.error); \ No newline at end of file diff --git a/reactions/sdk/javascript/package.json b/reactions/sdk/javascript/package.json index 3f13d1ef..ec28d4bd 100644 --- a/reactions/sdk/javascript/package.json +++ b/reactions/sdk/javascript/package.json @@ -1,6 +1,6 @@ { "name": "@drasi/reaction-sdk", - "version": "1.0.0", + "version": "0.1.0-alpha", "description": "Reaction SDK for Project Drasi", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -12,8 +12,16 @@ "build": "tsc && mkdir -p ./dist/types && cp ./src/types/* ./dist/types/", "test": "echo \"Error: no test specified\" && exit 1" }, - "author": "", + "author": "The Drasi Authors", "license": "Apache-2.0", + "homepage": "https://drasi.io", + "repository": { + "type": "git", + "url": "https://github.com/drasi-project/drasi-platform" + }, + "publishConfig": { + "access": "public" + }, "devDependencies": { "@microsoft/api-extractor": "^7.47.11", "@types/node": "^22.8.6", diff --git a/reactions/sdk/javascript/src/index.ts b/reactions/sdk/javascript/src/index.ts index 38778b0e..6de9688b 100644 --- a/reactions/sdk/javascript/src/index.ts +++ b/reactions/sdk/javascript/src/index.ts @@ -1,11 +1,11 @@ import { DaprServer } from "@dapr/dapr"; import { ChangeEvent } from "./types/ChangeEvent"; import { ControlEvent } from "./types/ControlEvent"; -import { readdirSync, readFileSync } from "fs"; -import YAML from 'yaml' +import { readdirSync, readFileSync, writeFileSync } from "fs"; +import { ReactionOptions } from "./options"; -export type OnChangeEvent = (event: ChangeEvent, queryConfig?: TQueryConfig) => Promise; -export type OnControlEvent = (event: ControlEvent, queryConfig?: TQueryConfig) => Promise; +export { ReactionOptions } from "./options"; +export { getConfigValue, parseJson, parseYaml } from "./utils"; export { ChangeEvent } from "./types/ChangeEvent"; export { ControlEvent } from "./types/ControlEvent"; export { RunningSignal } from "./types/RunningSignal"; @@ -13,20 +13,51 @@ export { BootstrapStartedSignal } from "./types/BootstrapStartedSignal"; export { BootstrapCompletedSignal } from "./types/BootstrapCompletedSignal"; export { StoppedSignal } from "./types/StoppedSignal"; -export type ReactionOptions = { - onControlEvent?: OnControlEvent; - parseQueryConfig?: (queryId: string, config: string) => TQueryConfig; -} +/** + * The function signature that is called when a change event is received. + * + * @param event The change event from the query + * @param queryConfig The configuration object for the query + */ +export type OnChangeEvent = (event: ChangeEvent, queryConfig?: TQueryConfig) => Promise; + +/** + * The function signature that is called when a control event is received. + * + * @param event The control event from the query + * @param queryConfig The configuration object for the query + */ +export type OnControlEvent = (event: ControlEvent, queryConfig?: TQueryConfig) => Promise; + +/** + * A class that encapsulates all the functionality for a Drasi Reaction. + * + * @template TQueryConfig The type of the query configuration object. This is defined per query in the Reaction manifest. + * + * @example + * ```typescript + * let myReaction = new DrasiReaction(async (event: ChangeEvent) => { + * // Handle the event that describes the changes to the query results + * }); + * myReaction.start(); + * ``` + * +*/ export class DrasiReaction { private onChangeEvent: OnChangeEvent; private onControlEvent: OnControlEvent | undefined; private daprServer: DaprServer; - private pubSubName: string = process.env["PUBSUB"] ?? "drasi-pubsub"; + private pubSubName: string = process.env["PubsubName"] ?? "drasi-pubsub"; private configDirectory: string = process.env["QueryConfigPath"] ?? "/etc/queries"; private queryConfig: Map = new Map(); private parseQueryConfig: (queryId: string, config: string) => TQueryConfig | undefined; + /** + * + * @param onChangeEvent {OnChangeEvent} The function that is called when a change event is received. + * @param options {ReactionOptions} The options for the Reaction. + */ constructor(onChangeEvent: OnChangeEvent, options?: ReactionOptions) { this.onChangeEvent = onChangeEvent; this.onControlEvent = options?.onControlEvent; @@ -36,18 +67,30 @@ export class DrasiReaction { }); } + /** + * Starts the Drasi Reaction. + */ public async start() { - let queryIds = readdirSync(this.configDirectory); - for (let queryId of queryIds) { - console.log(`Subscribing to query ${queryId}`); - await this.daprServer.pubsub.subscribe(this.pubSubName, `${queryId}-results`, this.onMessage.bind(this)); - if (this.parseQueryConfig) { - let cfgStr = readFileSync(`${this.configDirectory}/${queryId}`, 'utf-8'); - let cfg = this.parseQueryConfig(queryId, cfgStr); - this.queryConfig.set(queryId, cfg); + try { + let queryIds = readdirSync(this.configDirectory); + for (let queryId of queryIds) { + if (!queryId || queryId.startsWith('.')) + continue; + console.log(`Subscribing to query ${queryId}`); + await this.daprServer.pubsub.subscribe(this.pubSubName, `${queryId}-results`, this.onMessage.bind(this)); + if (this.parseQueryConfig) { + let cfgStr = readFileSync(`${this.configDirectory}/${queryId}`, 'utf-8'); + let cfg = this.parseQueryConfig(queryId, cfgStr); + this.queryConfig.set(queryId, cfg); + } } + await this.daprServer.start(); + } + catch (err) { + console.error(err); + writeFileSync("/dev/termination-log", err.message); + process.exit(1); } - await this.daprServer.start(); } public async stop() { @@ -73,15 +116,3 @@ export class DrasiReaction { } } } - -export function getConfigValue(key: string, defaultValue: string): string { - return process.env[key] ?? defaultValue; -} - -export function parseJson(queryId: string, config: string): any { - return JSON.parse(config); -} - -export function parseYaml(queryId: string, config: string): any { - return YAML.parse(config); -} \ No newline at end of file diff --git a/reactions/sdk/javascript/src/options.ts b/reactions/sdk/javascript/src/options.ts new file mode 100644 index 00000000..dc2a7e0d --- /dev/null +++ b/reactions/sdk/javascript/src/options.ts @@ -0,0 +1,59 @@ +import { OnControlEvent } from "."; + + +export type ReactionOptions = { + + /** + * The function that is called when a control event (query started, stopped, etc.) is received. + * + * @param event The control event + * @param queryConfig The configuration object for the query + */ + onControlEvent?: OnControlEvent; + + /** + * The function to parse the per query configuration. + * + * @param queryId The ID of the query + * @param config The configuration string from the query specific configuration. + * + * @example + * ```yaml + * kind: Reaction + * apiVersion: v1 + * name: my-reaction + * spec: + * kind: MyReaction + * queries: + * query1: | + * greeting: "Hello, World!" # This YAML configuration will be parsed into a MyQueryConfig object + * query2: | + * greeting: "Howdy!" + * ``` + * @returns The parsed configuration object + * + * @example + * ```json + * { + * "greeting": "Hello, World!" + * } + * ``` + * + * If your configuration is in JSON format, you can use the built-in JSON parser: + * @example + * ```typescript + * let myReaction = new DrasiReaction(onChangeEvent, { + * parseQueryConfig: parseJson, + * }); + ``` + + * If your configuration is in YAML format, you can use the built-in YAML parser: + * @example + * ```typescript + * let myReaction = new DrasiReaction(onChangeEvent, { + * parseQueryConfig: parseYaml, + * }); + * ``` + */ + parseQueryConfig?: (queryId: string, config: string) => TQueryConfig; +}; diff --git a/reactions/sdk/javascript/src/types/BootstrapCompletedSignal.d.ts b/reactions/sdk/javascript/src/types/BootstrapCompletedSignal.d.ts index 70f0246b..06f6ff67 100644 --- a/reactions/sdk/javascript/src/types/BootstrapCompletedSignal.d.ts +++ b/reactions/sdk/javascript/src/types/BootstrapCompletedSignal.d.ts @@ -5,6 +5,9 @@ * and run json-schema-to-typescript to regenerate this file. */ +/** + * A signal that indicates that the query has completed bootstrapping + */ export type BootstrapCompletedSignal = ControlSignal & { kind: "bootstrapCompleted"; [k: string]: unknown; diff --git a/reactions/sdk/javascript/src/types/BootstrapStartedSignal.d.ts b/reactions/sdk/javascript/src/types/BootstrapStartedSignal.d.ts index 7eb71b62..6726ac93 100644 --- a/reactions/sdk/javascript/src/types/BootstrapStartedSignal.d.ts +++ b/reactions/sdk/javascript/src/types/BootstrapStartedSignal.d.ts @@ -5,6 +5,9 @@ * and run json-schema-to-typescript to regenerate this file. */ +/** + * A signal that indicates that the query is starting to bootstrap + */ export type BootstrapStartedSignal = ControlSignal & { kind: "bootstrapStarted"; [k: string]: unknown; diff --git a/reactions/sdk/javascript/src/types/ChangeEvent.d.ts b/reactions/sdk/javascript/src/types/ChangeEvent.d.ts index 44be6ec4..ab823719 100644 --- a/reactions/sdk/javascript/src/types/ChangeEvent.d.ts +++ b/reactions/sdk/javascript/src/types/ChangeEvent.d.ts @@ -5,26 +5,38 @@ * and run json-schema-to-typescript to regenerate this file. */ +/** + * An event that represents a changes in the result set + */ export type ChangeEvent = ResultEvent & { kind: "change"; /** - * The results that were added + * The results that were added to the result set as a consequence of the change */ addedResults: RecordUnknown1[]; /** - * The results that were updated + * The results that were updated on the result set as a consequence of the change */ updatedResults: UpdatePayload[]; /** - * The results that were deleted + * The results that were deleted from the result set as a consequence of the change */ deletedResults: RecordUnknown1[]; [k: string]: unknown; }; export interface ResultEvent { + /** + * The ID of the query that the event originated from + */ queryId: string; + /** + * The sequence number of the event + */ sequence: string; + /** + * The time at which the source change was recorded + */ sourceTimeMs: string; metadata?: RecordUnknown; [k: string]: unknown; @@ -35,19 +47,22 @@ export interface RecordUnknown { export interface RecordUnknown1 { [k: string]: unknown; } +/** + * A payload that represents the before and after snapshots of a result + */ export interface UpdatePayload { before: RecordUnknown2; after: RecordUnknown3; [k: string]: unknown; } /** - * The result before the change + * The snapshot of the result before the change */ export interface RecordUnknown2 { [k: string]: unknown; } /** - * The result after the change + * The snapshot of the result after the change */ export interface RecordUnknown3 { [k: string]: unknown; diff --git a/reactions/sdk/javascript/src/types/ControlEvent.d.ts b/reactions/sdk/javascript/src/types/ControlEvent.d.ts index bfab648d..18539905 100644 --- a/reactions/sdk/javascript/src/types/ControlEvent.d.ts +++ b/reactions/sdk/javascript/src/types/ControlEvent.d.ts @@ -5,6 +5,9 @@ * and run json-schema-to-typescript to regenerate this file. */ +/** + * An event that represents a control signal from the query, such are start, stop, etc. + */ export type ControlEvent = ResultEvent & { kind: "control"; controlSignal: ControlSignal; @@ -12,8 +15,17 @@ export type ControlEvent = ResultEvent & { }; export interface ResultEvent { + /** + * The ID of the query that the event originated from + */ queryId: string; + /** + * The sequence number of the event + */ sequence: string; + /** + * The time at which the source change was recorded + */ sourceTimeMs: string; metadata?: RecordUnknown; [k: string]: unknown; diff --git a/reactions/sdk/javascript/src/types/DeletedSignal.d.ts b/reactions/sdk/javascript/src/types/DeletedSignal.d.ts index 124fa465..28237833 100644 --- a/reactions/sdk/javascript/src/types/DeletedSignal.d.ts +++ b/reactions/sdk/javascript/src/types/DeletedSignal.d.ts @@ -5,6 +5,9 @@ * and run json-schema-to-typescript to regenerate this file. */ +/** + * A signal that indicates that the query has been deleted + */ export type DeletedSignal = ControlSignal & { kind: "deleted"; [k: string]: unknown; diff --git a/reactions/sdk/javascript/src/types/ResultEvent.d.ts b/reactions/sdk/javascript/src/types/ResultEvent.d.ts index edb6c9c7..ee99bc4a 100644 --- a/reactions/sdk/javascript/src/types/ResultEvent.d.ts +++ b/reactions/sdk/javascript/src/types/ResultEvent.d.ts @@ -6,8 +6,17 @@ */ export interface ResultEvent { + /** + * The ID of the query that the event originated from + */ queryId: string; + /** + * The sequence number of the event + */ sequence: string; + /** + * The time at which the source change was recorded + */ sourceTimeMs: string; metadata?: RecordUnknown; [k: string]: unknown; diff --git a/reactions/sdk/javascript/src/types/RunningSignal.d.ts b/reactions/sdk/javascript/src/types/RunningSignal.d.ts index 324cb1db..64b64162 100644 --- a/reactions/sdk/javascript/src/types/RunningSignal.d.ts +++ b/reactions/sdk/javascript/src/types/RunningSignal.d.ts @@ -5,6 +5,9 @@ * and run json-schema-to-typescript to regenerate this file. */ +/** + * A signal that indicates that the query has entered the running state + */ export type RunningSignal = ControlSignal & { kind: "running"; [k: string]: unknown; diff --git a/reactions/sdk/javascript/src/types/StoppedSignal.d.ts b/reactions/sdk/javascript/src/types/StoppedSignal.d.ts index 0280f646..75f27aad 100644 --- a/reactions/sdk/javascript/src/types/StoppedSignal.d.ts +++ b/reactions/sdk/javascript/src/types/StoppedSignal.d.ts @@ -5,6 +5,9 @@ * and run json-schema-to-typescript to regenerate this file. */ +/** + * A signal that indicates that the query has stopped + */ export type StoppedSignal = ControlSignal & { kind: "stopped"; [k: string]: unknown; diff --git a/reactions/sdk/javascript/src/types/UpdatePayload.d.ts b/reactions/sdk/javascript/src/types/UpdatePayload.d.ts index cb7d0612..ed0edb3f 100644 --- a/reactions/sdk/javascript/src/types/UpdatePayload.d.ts +++ b/reactions/sdk/javascript/src/types/UpdatePayload.d.ts @@ -5,19 +5,22 @@ * and run json-schema-to-typescript to regenerate this file. */ +/** + * A payload that represents the before and after snapshots of a result + */ export interface UpdatePayload { before: RecordUnknown; after: RecordUnknown1; [k: string]: unknown; } /** - * The result before the change + * The snapshot of the result before the change */ export interface RecordUnknown { [k: string]: unknown; } /** - * The result after the change + * The snapshot of the result after the change */ export interface RecordUnknown1 { [k: string]: unknown; diff --git a/reactions/sdk/javascript/src/utils.ts b/reactions/sdk/javascript/src/utils.ts new file mode 100644 index 00000000..a2beaabd --- /dev/null +++ b/reactions/sdk/javascript/src/utils.ts @@ -0,0 +1,59 @@ +import YAML from 'yaml' + +/** + * Retrieves a configuration value for the Reaction. + * + * @param key The configuration key to retrieve + * @param defaultValue The default value to return if the key is not found + * @returns The configuration value or the default value if the key is not found + * + * @example + * ```typescript + * const connectionString = getConfigValue("MyConnectionString"); + * ``` + * The above code will retrieve the value of the MyConnectionString configuration key, as defined in the reaction manifest: + * ```yaml + * kind: Reaction + * apiVersion: v1 + * name: test + * spec: + * kind: MyReaction + * properties: + * MyConnectionString: "some connection string" + * queries: + * query1: + * ``` + * + */ +export function getConfigValue(key: string, defaultValue?: string): string | undefined { + return process.env[key] ?? defaultValue; +} + + +/** + * Parses a JSON configuration string into an object. + * + * @example + * ```typescript + * let myReaction = new DrasiReaction(onChangeEvent, { + * parseQueryConfig: parseJson, + * }); + * ``` + */ +export function parseJson(queryId: string, config: string): any { + return JSON.parse(config); +} + +/** + * Parses a YAML configuration string into an object. + * + * @example + * ```typescript + * let myReaction = new DrasiReaction(onChangeEvent, { + * parseQueryConfig: parseYaml, + * }); + * ``` + */ +export function parseYaml(queryId: string, config: string): any { + return YAML.parse(config); +} \ No newline at end of file diff --git a/typespec/query-output/main.tsp b/typespec/query-output/main.tsp index 16800f13..6df547f0 100644 --- a/typespec/query-output/main.tsp +++ b/typespec/query-output/main.tsp @@ -16,36 +16,46 @@ enum Versions { @discriminator("kind") @extension("title", "ResultEvent") model ResultEvent { + + @doc("The ID of the query that the event originated from") queryId: string; + + @doc("The sequence number of the event") sequence: int64; + + @doc("The time at which the source change was recorded") sourceTimeMs: int64; + metadata?: Record } @extension("title", "ChangeEvent") +@doc("An event that represents a changes in the result set") model ChangeEvent extends ResultEvent { kind: "change"; - @doc("The results that were added") + @doc("The results that were added to the result set as a consequence of the change") addedResults: Record[]; - @doc("The results that were updated") + @doc("The results that were updated on the result set as a consequence of the change") updatedResults: UpdatePayload[]; - @doc("The results that were deleted") + @doc("The results that were deleted from the result set as a consequence of the change") deletedResults: Record[]; } @extension("title", "UpdatePayload") +@doc("A payload that represents the before and after snapshots of a result") model UpdatePayload { - @doc("The result before the change") + @doc("The snapshot of the result before the change") before: Record; - @doc("The result after the change") + @doc("The snapshot of the result after the change") after: Record; } @extension("title", "ControlEvent") +@doc("An event that represents a control signal from the query, such are start, stop, etc.") model ControlEvent extends ResultEvent { kind: "control"; controlSignal: ControlSignal; @@ -57,26 +67,31 @@ model ControlSignal { } @extension("title", "BootstrapStartedSignal") +@doc("A signal that indicates that the query is starting to bootstrap") model BootstrapStartedSignal extends ControlSignal { kind: "bootstrapStarted"; } @extension("title", "BootstrapCompletedSignal") +@doc("A signal that indicates that the query has completed bootstrapping") model BootstrapCompletedSignal extends ControlSignal { kind: "bootstrapCompleted"; } @extension("title", "RunningSignal") +@doc("A signal that indicates that the query has entered the running state") model RunningSignal extends ControlSignal { kind: "running"; } @extension("title", "StoppedSignal") +@doc("A signal that indicates that the query has stopped") model StoppedSignal extends ControlSignal { kind: "stopped"; } @extension("title", "DeletedSignal") +@doc("A signal that indicates that the query has been deleted") model DeletedSignal extends ControlSignal { kind: "deleted"; } From fb0af942a7d85a5dd07edff83092bdd22adba442 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 1 Nov 2024 13:30:14 -0700 Subject: [PATCH 04/17] js examples --- reactions/sdk/javascript/README.md | 2 +- .../examples/advanced-js/.dockerignore | 1 + .../examples/advanced-js/.gitignore | 2 + .../examples/advanced-js/Dockerfile | 9 + .../javascript/examples/advanced-js/index.js | 46 + .../examples/advanced-js/package-lock.json | 1413 +++++++++++++++++ .../examples/advanced-js/package.json | 16 + .../advanced-js/reaction-provider.yaml | 7 + .../examples/advanced-js/reaction.yaml | 8 + .../examples/advanced-ts/src/index.ts | 4 +- .../examples/simple-js/.dockerignore | 1 + .../javascript/examples/simple-js/.gitignore | 2 + .../javascript/examples/simple-js/Dockerfile | 9 + .../javascript/examples/simple-js/index.js | 20 + .../examples/simple-js/package-lock.json | 1413 +++++++++++++++++ .../examples/simple-js/package.json | 16 + .../examples/simple-js/reaction-provider.yaml | 7 + .../examples/simple-js/reaction.yaml | 8 + 18 files changed, 2981 insertions(+), 3 deletions(-) create mode 100644 reactions/sdk/javascript/examples/advanced-js/.dockerignore create mode 100644 reactions/sdk/javascript/examples/advanced-js/.gitignore create mode 100644 reactions/sdk/javascript/examples/advanced-js/Dockerfile create mode 100644 reactions/sdk/javascript/examples/advanced-js/index.js create mode 100644 reactions/sdk/javascript/examples/advanced-js/package-lock.json create mode 100644 reactions/sdk/javascript/examples/advanced-js/package.json create mode 100644 reactions/sdk/javascript/examples/advanced-js/reaction-provider.yaml create mode 100644 reactions/sdk/javascript/examples/advanced-js/reaction.yaml create mode 100644 reactions/sdk/javascript/examples/simple-js/.dockerignore create mode 100644 reactions/sdk/javascript/examples/simple-js/.gitignore create mode 100644 reactions/sdk/javascript/examples/simple-js/Dockerfile create mode 100644 reactions/sdk/javascript/examples/simple-js/index.js create mode 100644 reactions/sdk/javascript/examples/simple-js/package-lock.json create mode 100644 reactions/sdk/javascript/examples/simple-js/package.json create mode 100644 reactions/sdk/javascript/examples/simple-js/reaction-provider.yaml create mode 100644 reactions/sdk/javascript/examples/simple-js/reaction.yaml diff --git a/reactions/sdk/javascript/README.md b/reactions/sdk/javascript/README.md index af4c4cc9..f0f2d9d0 100644 --- a/reactions/sdk/javascript/README.md +++ b/reactions/sdk/javascript/README.md @@ -74,7 +74,7 @@ async function onControlEvent(event: ControlEvent, queryConfig?: MyQueryConfig): console.log(`Starting Drasi reaction with connection string: ${myConnectionString}`); // Configure the Reaction with the onChangeEvent and onControlEvent functions -let myReaction = new DrasiReaction(onChangeEvent, { +let myReaction = new DrasiReaction(onChangeEvent, { parseQueryConfig: parseYaml, // Parse the per query configuration from Yaml onControlEvent: onControlEvent }); diff --git a/reactions/sdk/javascript/examples/advanced-js/.dockerignore b/reactions/sdk/javascript/examples/advanced-js/.dockerignore new file mode 100644 index 00000000..b512c09d --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced-js/.dockerignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/advanced-js/.gitignore b/reactions/sdk/javascript/examples/advanced-js/.gitignore new file mode 100644 index 00000000..76add878 --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced-js/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/advanced-js/Dockerfile b/reactions/sdk/javascript/examples/advanced-js/Dockerfile new file mode 100644 index 00000000..d1eb1632 --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced-js/Dockerfile @@ -0,0 +1,9 @@ +FROM node:20-alpine + +WORKDIR /usr/src/app + +COPY . . + +RUN npm install + +CMD ["npm", "start"] \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/advanced-js/index.js b/reactions/sdk/javascript/examples/advanced-js/index.js new file mode 100644 index 00000000..4a7af420 --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced-js/index.js @@ -0,0 +1,46 @@ +import { DrasiReaction, parseYaml, getConfigValue } from '@drasi/reaction-sdk'; + +// Retrieve the connection string from the Reaction configuration +const myConnectionString = getConfigValue("MyConnectionString"); + +// Define a custom per query configuration object +class MyQueryConfig { + greeting = "Default greeting"; +} + +// Define the function that will be called when a change event is received +/** + * @param {{ greeting: MyQueryConfig; }} queryConfig + */ +async function onChangeEvent(event, queryConfig) { + console.log(queryConfig.greeting); + console.log(`Received change sequence: ${event.sequence} for query ${event.queryId}`); + + for (let added of event.addedResults) { + console.log(`Added result: ${JSON.stringify(added)}`); + } + + for (let deleted of event.deletedResults) { + console.log(`Removed result: ${JSON.stringify(deleted)}`); + } + + for (let updated of event.updatedResults) { + console.log(`Updated result - before: ${JSON.stringify(updated.before)}, after: ${JSON.stringify(updated.after)}`); + } +} + +// Define the function that will be called when a control event is received +async function onControlEvent(event, queryConfig) { + console.log(`Received control signal: ${JSON.stringify(event.controlSignal)} for query ${event.queryId}`); +} + +console.log(`Starting Drasi reaction with connection string: ${myConnectionString}`); + +// Configure the Reaction with the onChangeEvent and onControlEvent functions +let myReaction = new DrasiReaction(onChangeEvent, { + parseQueryConfig: parseYaml, // Parse the per query configuration from Yaml + onControlEvent: onControlEvent +}); + +// Start the Reaction +myReaction.start(); diff --git a/reactions/sdk/javascript/examples/advanced-js/package-lock.json b/reactions/sdk/javascript/examples/advanced-js/package-lock.json new file mode 100644 index 00000000..9a0bdf06 --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced-js/package-lock.json @@ -0,0 +1,1413 @@ +{ + "name": "example-reaction", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "example-reaction", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@drasi/reaction-sdk": "0.1.0-alpha" + } + }, + "node_modules/@dapr/dapr": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@dapr/dapr/-/dapr-3.4.1.tgz", + "integrity": "sha512-Ev9/Pqzo2ftiDU3gYOCiOJR/UZ5fZk+y+hFcn133mBkYvbU9cTU9S+/46kH2YVJCg6+62m/rG7LQ1o2s5gX76Q==", + "license": "ISC", + "dependencies": { + "@grpc/grpc-js": "^1.9.3", + "@js-temporal/polyfill": "^0.3.0", + "@microsoft/durabletask-js": "^0.1.0-alpha.2", + "@types/google-protobuf": "^3.15.5", + "@types/node-fetch": "^2.6.2", + "body-parser": "^1.19.0", + "express": "^4.18.2", + "google-protobuf": "^3.18.0", + "http-terminator": "^3.2.0", + "node-fetch": "^2.6.7" + } + }, + "node_modules/@drasi/reaction-sdk": { + "version": "0.1.0-alpha", + "resolved": "https://registry.npmjs.org/@drasi/reaction-sdk/-/reaction-sdk-0.1.0-alpha.tgz", + "integrity": "sha512-ecnOOHtVHlpHLt/NdQw4FR5W6CCIHtCu2vf7ZoWJz30Op+P6oQ36MQ8M3Gi1jzBFp4Zd/pM6sxi/Whh1OULFaA==", + "license": "Apache-2.0", + "dependencies": { + "@dapr/dapr": "^3.4.1", + "tslib": "^2.8.0", + "yaml": "^2.6.0" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.2.tgz", + "integrity": "sha512-bgxdZmgTrJZX50OjyVwz3+mNEnCTNkh3cIqGPWVNeW9jX6bn1ZkU80uPd+67/ZpIJIjRQ9qaHCjhavyoWYxumg==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@js-temporal/polyfill": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@js-temporal/polyfill/-/polyfill-0.3.0.tgz", + "integrity": "sha512-cxxxis19j0WvK3+kUwKrXeXaDBaWxLeRfKqlVz7g50Cly6UgGs2p3wovH9zjtZ4TtjYHDR4De/880+aalduDZQ==", + "license": "ISC", + "dependencies": { + "big-integer": "^1.6.51", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@microsoft/durabletask-js": { + "version": "0.1.0-alpha.2", + "resolved": "https://registry.npmjs.org/@microsoft/durabletask-js/-/durabletask-js-0.1.0-alpha.2.tgz", + "integrity": "sha512-EiUgOyT05JQ9/M/InjTKdXs5Y1XxdXRczb6nizceJglXr8S/myxMnQHDV1QRASxroFCoTyKiDHU6uAq4Cpe/LQ==", + "license": "MIT", + "dependencies": { + "@grpc/grpc-js": "^1.8.14", + "google-protobuf": "^3.21.2" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, + "node_modules/@types/google-protobuf": { + "version": "3.15.12", + "resolved": "https://registry.npmjs.org/@types/google-protobuf/-/google-protobuf-3.15.12.tgz", + "integrity": "sha512-40um9QqwHjRS92qnOaDpL7RmDK15NuZYo9HihiJRbYkMQZlWnuH8AdvbMy8/o6lgLmKbDUKa+OALCltHdbOTpQ==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.6.tgz", + "integrity": "sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fast-printf": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", + "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "license": "BSD-3-Clause", + "dependencies": { + "boolean": "^3.1.4" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/google-protobuf": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.4.tgz", + "integrity": "sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==", + "license": "(BSD-3-Clause AND Apache-2.0)" + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-terminator": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/http-terminator/-/http-terminator-3.2.0.tgz", + "integrity": "sha512-JLjck1EzPaWjsmIf8bziM3p9fgR1Y3JoUKAkyYEbZmFrIvJM6I8vVJfBGWlEtV9IWOvzNnaTtjuwZeBY2kwB4g==", + "license": "BSD-3-Clause", + "dependencies": { + "delay": "^5.0.0", + "p-wait-for": "^3.2.0", + "roarr": "^7.0.4", + "type-fest": "^2.3.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "license": "Apache-2.0" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "license": "MIT", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-wait-for": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-wait-for/-/p-wait-for-3.2.0.tgz", + "integrity": "sha512-wpgERjNkLrBiFmkMEjuZJEWKKDrNfHCKA1OhyN1wg1FrLkULbviEy6py1AyJUgZ72YWFbZ38FIpnqvVqAlDUwA==", + "license": "MIT", + "dependencies": { + "p-timeout": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "license": "MIT" + }, + "node_modules/protobufjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/roarr": { + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-7.21.1.tgz", + "integrity": "sha512-3niqt5bXFY1InKU8HKWqqYTYjtrBaxBMnXELXCXUYgtNYGUtZM5rB46HIC430AyacL95iEniGf7RgqsesykLmQ==", + "license": "BSD-3-Clause", + "dependencies": { + "fast-printf": "^1.6.9", + "safe-stable-stringify": "^2.4.3", + "semver-compare": "^1.0.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/reactions/sdk/javascript/examples/advanced-js/package.json b/reactions/sdk/javascript/examples/advanced-js/package.json new file mode 100644 index 00000000..caf5b9d5 --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced-js/package.json @@ -0,0 +1,16 @@ +{ + "name": "example-reaction", + "version": "1.0.0", + "type": "module", + "main": "index.js", + "scripts": { + "start": "node index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "Apache-2.0", + "description": "", + "dependencies": { + "@drasi/reaction-sdk": "0.1.0-alpha" + } +} diff --git a/reactions/sdk/javascript/examples/advanced-js/reaction-provider.yaml b/reactions/sdk/javascript/examples/advanced-js/reaction-provider.yaml new file mode 100644 index 00000000..20cd1909 --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced-js/reaction-provider.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ReactionProvider +name: Simple +spec: + services: + simple: + image: reaction-simple diff --git a/reactions/sdk/javascript/examples/advanced-js/reaction.yaml b/reactions/sdk/javascript/examples/advanced-js/reaction.yaml new file mode 100644 index 00000000..84619734 --- /dev/null +++ b/reactions/sdk/javascript/examples/advanced-js/reaction.yaml @@ -0,0 +1,8 @@ +kind: Reaction +apiVersion: v1 +name: test-simple +spec: + kind: Simple + queries: + freezer2: + query2: \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/advanced-ts/src/index.ts b/reactions/sdk/javascript/examples/advanced-ts/src/index.ts index c139d987..cea5a031 100644 --- a/reactions/sdk/javascript/examples/advanced-ts/src/index.ts +++ b/reactions/sdk/javascript/examples/advanced-ts/src/index.ts @@ -1,4 +1,4 @@ -import { DrasiReaction, ChangeEvent,parseYaml, ControlEvent, getConfigValue } from '@drasi/reaction-sdk'; +import { DrasiReaction, ChangeEvent, parseYaml, ControlEvent, getConfigValue } from '@drasi/reaction-sdk'; // Retrieve the connection string from the Reaction configuration const myConnectionString = getConfigValue("MyConnectionString"); @@ -34,7 +34,7 @@ async function onControlEvent(event: ControlEvent, queryConfig?: MyQueryConfig): console.log(`Starting Drasi reaction with connection string: ${myConnectionString}`); // Configure the Reaction with the onChangeEvent and onControlEvent functions -let myReaction = new DrasiReaction(onChangeEvent, { +let myReaction = new DrasiReaction(onChangeEvent, { parseQueryConfig: parseYaml, // Parse the per query configuration from Yaml onControlEvent: onControlEvent }); diff --git a/reactions/sdk/javascript/examples/simple-js/.dockerignore b/reactions/sdk/javascript/examples/simple-js/.dockerignore new file mode 100644 index 00000000..b512c09d --- /dev/null +++ b/reactions/sdk/javascript/examples/simple-js/.dockerignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/simple-js/.gitignore b/reactions/sdk/javascript/examples/simple-js/.gitignore new file mode 100644 index 00000000..76add878 --- /dev/null +++ b/reactions/sdk/javascript/examples/simple-js/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/simple-js/Dockerfile b/reactions/sdk/javascript/examples/simple-js/Dockerfile new file mode 100644 index 00000000..d1eb1632 --- /dev/null +++ b/reactions/sdk/javascript/examples/simple-js/Dockerfile @@ -0,0 +1,9 @@ +FROM node:20-alpine + +WORKDIR /usr/src/app + +COPY . . + +RUN npm install + +CMD ["npm", "start"] \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/simple-js/index.js b/reactions/sdk/javascript/examples/simple-js/index.js new file mode 100644 index 00000000..86b6e73a --- /dev/null +++ b/reactions/sdk/javascript/examples/simple-js/index.js @@ -0,0 +1,20 @@ +import { DrasiReaction } from '@drasi/reaction-sdk'; + +let myReaction = new DrasiReaction(async (event) => { + + console.log(`Received change sequence: ${event.sequence} for query ${event.queryId}`); + + for (let added of event.addedResults) { + console.log(`Added result: ${JSON.stringify(added)}`); + } + + for (let deleted of event.deletedResults) { + console.log(`Removed result: ${JSON.stringify(deleted)}`); + } + + for (let updated of event.updatedResults) { + console.log(`Updated result - before: ${JSON.stringify(updated.before)}, after: ${JSON.stringify(updated.after)}`); + } +}); + +myReaction.start(); \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/simple-js/package-lock.json b/reactions/sdk/javascript/examples/simple-js/package-lock.json new file mode 100644 index 00000000..9a0bdf06 --- /dev/null +++ b/reactions/sdk/javascript/examples/simple-js/package-lock.json @@ -0,0 +1,1413 @@ +{ + "name": "example-reaction", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "example-reaction", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@drasi/reaction-sdk": "0.1.0-alpha" + } + }, + "node_modules/@dapr/dapr": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@dapr/dapr/-/dapr-3.4.1.tgz", + "integrity": "sha512-Ev9/Pqzo2ftiDU3gYOCiOJR/UZ5fZk+y+hFcn133mBkYvbU9cTU9S+/46kH2YVJCg6+62m/rG7LQ1o2s5gX76Q==", + "license": "ISC", + "dependencies": { + "@grpc/grpc-js": "^1.9.3", + "@js-temporal/polyfill": "^0.3.0", + "@microsoft/durabletask-js": "^0.1.0-alpha.2", + "@types/google-protobuf": "^3.15.5", + "@types/node-fetch": "^2.6.2", + "body-parser": "^1.19.0", + "express": "^4.18.2", + "google-protobuf": "^3.18.0", + "http-terminator": "^3.2.0", + "node-fetch": "^2.6.7" + } + }, + "node_modules/@drasi/reaction-sdk": { + "version": "0.1.0-alpha", + "resolved": "https://registry.npmjs.org/@drasi/reaction-sdk/-/reaction-sdk-0.1.0-alpha.tgz", + "integrity": "sha512-ecnOOHtVHlpHLt/NdQw4FR5W6CCIHtCu2vf7ZoWJz30Op+P6oQ36MQ8M3Gi1jzBFp4Zd/pM6sxi/Whh1OULFaA==", + "license": "Apache-2.0", + "dependencies": { + "@dapr/dapr": "^3.4.1", + "tslib": "^2.8.0", + "yaml": "^2.6.0" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.2.tgz", + "integrity": "sha512-bgxdZmgTrJZX50OjyVwz3+mNEnCTNkh3cIqGPWVNeW9jX6bn1ZkU80uPd+67/ZpIJIjRQ9qaHCjhavyoWYxumg==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@js-temporal/polyfill": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@js-temporal/polyfill/-/polyfill-0.3.0.tgz", + "integrity": "sha512-cxxxis19j0WvK3+kUwKrXeXaDBaWxLeRfKqlVz7g50Cly6UgGs2p3wovH9zjtZ4TtjYHDR4De/880+aalduDZQ==", + "license": "ISC", + "dependencies": { + "big-integer": "^1.6.51", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@microsoft/durabletask-js": { + "version": "0.1.0-alpha.2", + "resolved": "https://registry.npmjs.org/@microsoft/durabletask-js/-/durabletask-js-0.1.0-alpha.2.tgz", + "integrity": "sha512-EiUgOyT05JQ9/M/InjTKdXs5Y1XxdXRczb6nizceJglXr8S/myxMnQHDV1QRASxroFCoTyKiDHU6uAq4Cpe/LQ==", + "license": "MIT", + "dependencies": { + "@grpc/grpc-js": "^1.8.14", + "google-protobuf": "^3.21.2" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, + "node_modules/@types/google-protobuf": { + "version": "3.15.12", + "resolved": "https://registry.npmjs.org/@types/google-protobuf/-/google-protobuf-3.15.12.tgz", + "integrity": "sha512-40um9QqwHjRS92qnOaDpL7RmDK15NuZYo9HihiJRbYkMQZlWnuH8AdvbMy8/o6lgLmKbDUKa+OALCltHdbOTpQ==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.6.tgz", + "integrity": "sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fast-printf": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", + "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "license": "BSD-3-Clause", + "dependencies": { + "boolean": "^3.1.4" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/google-protobuf": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.4.tgz", + "integrity": "sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==", + "license": "(BSD-3-Clause AND Apache-2.0)" + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-terminator": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/http-terminator/-/http-terminator-3.2.0.tgz", + "integrity": "sha512-JLjck1EzPaWjsmIf8bziM3p9fgR1Y3JoUKAkyYEbZmFrIvJM6I8vVJfBGWlEtV9IWOvzNnaTtjuwZeBY2kwB4g==", + "license": "BSD-3-Clause", + "dependencies": { + "delay": "^5.0.0", + "p-wait-for": "^3.2.0", + "roarr": "^7.0.4", + "type-fest": "^2.3.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "license": "Apache-2.0" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "license": "MIT", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-wait-for": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-wait-for/-/p-wait-for-3.2.0.tgz", + "integrity": "sha512-wpgERjNkLrBiFmkMEjuZJEWKKDrNfHCKA1OhyN1wg1FrLkULbviEy6py1AyJUgZ72YWFbZ38FIpnqvVqAlDUwA==", + "license": "MIT", + "dependencies": { + "p-timeout": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "license": "MIT" + }, + "node_modules/protobufjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/roarr": { + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-7.21.1.tgz", + "integrity": "sha512-3niqt5bXFY1InKU8HKWqqYTYjtrBaxBMnXELXCXUYgtNYGUtZM5rB46HIC430AyacL95iEniGf7RgqsesykLmQ==", + "license": "BSD-3-Clause", + "dependencies": { + "fast-printf": "^1.6.9", + "safe-stable-stringify": "^2.4.3", + "semver-compare": "^1.0.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/reactions/sdk/javascript/examples/simple-js/package.json b/reactions/sdk/javascript/examples/simple-js/package.json new file mode 100644 index 00000000..caf5b9d5 --- /dev/null +++ b/reactions/sdk/javascript/examples/simple-js/package.json @@ -0,0 +1,16 @@ +{ + "name": "example-reaction", + "version": "1.0.0", + "type": "module", + "main": "index.js", + "scripts": { + "start": "node index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "Apache-2.0", + "description": "", + "dependencies": { + "@drasi/reaction-sdk": "0.1.0-alpha" + } +} diff --git a/reactions/sdk/javascript/examples/simple-js/reaction-provider.yaml b/reactions/sdk/javascript/examples/simple-js/reaction-provider.yaml new file mode 100644 index 00000000..20cd1909 --- /dev/null +++ b/reactions/sdk/javascript/examples/simple-js/reaction-provider.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ReactionProvider +name: Simple +spec: + services: + simple: + image: reaction-simple diff --git a/reactions/sdk/javascript/examples/simple-js/reaction.yaml b/reactions/sdk/javascript/examples/simple-js/reaction.yaml new file mode 100644 index 00000000..84619734 --- /dev/null +++ b/reactions/sdk/javascript/examples/simple-js/reaction.yaml @@ -0,0 +1,8 @@ +kind: Reaction +apiVersion: v1 +name: test-simple +spec: + kind: Simple + queries: + freezer2: + query2: \ No newline at end of file From 8b013bd145f9ad3dd6966eb6bec158b8d4e9fea6 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 1 Nov 2024 13:34:19 -0700 Subject: [PATCH 05/17] rename --- .../examples/{advanced-js => 01-simple-js}/.dockerignore | 0 .../javascript/examples/{advanced-js => 01-simple-js}/.gitignore | 0 .../javascript/examples/{advanced-js => 01-simple-js}/Dockerfile | 0 .../sdk/javascript/examples/{simple-js => 01-simple-js}/index.js | 0 .../examples/{advanced-js => 01-simple-js}/package-lock.json | 0 .../examples/{advanced-js => 01-simple-js}/package.json | 0 .../examples/{advanced-js => 01-simple-js}/reaction-provider.yaml | 0 .../examples/{advanced-js => 01-simple-js}/reaction.yaml | 0 .../examples/{advanced-ts => 01-simple-ts}/.dockerignore | 0 .../javascript/examples/{advanced-ts => 01-simple-ts}/.gitignore | 0 .../javascript/examples/{advanced-ts => 01-simple-ts}/Dockerfile | 0 .../examples/{advanced-ts => 01-simple-ts}/package-lock.json | 0 .../examples/{advanced-ts => 01-simple-ts}/package.json | 0 .../examples/{simple-js => 01-simple-ts}/reaction-provider.yaml | 0 .../javascript/examples/{simple-js => 01-simple-ts}/reaction.yaml | 0 .../javascript/examples/{simple-ts => 01-simple-ts}/src/index.ts | 0 .../examples/{advanced-ts => 01-simple-ts}/tsconfig.json | 0 .../examples/{simple-js => 02-advanced-js}/.dockerignore | 0 .../javascript/examples/{simple-js => 02-advanced-js}/.gitignore | 0 .../javascript/examples/{simple-js => 02-advanced-js}/Dockerfile | 0 .../javascript/examples/{advanced-js => 02-advanced-js}/index.js | 0 .../examples/{simple-js => 02-advanced-js}/package-lock.json | 0 .../examples/{simple-js => 02-advanced-js}/package.json | 0 .../examples/{simple-ts => 02-advanced-js}/reaction-provider.yaml | 0 .../examples/{simple-ts => 02-advanced-js}/reaction.yaml | 0 .../examples/{simple-ts => 02-advanced-ts}/.dockerignore | 0 .../javascript/examples/{simple-ts => 02-advanced-ts}/.gitignore | 0 .../javascript/examples/{simple-ts => 02-advanced-ts}/Dockerfile | 0 .../examples/{simple-ts => 02-advanced-ts}/package-lock.json | 0 .../examples/{simple-ts => 02-advanced-ts}/package.json | 0 .../{advanced-ts => 02-advanced-ts}/reaction-provider.yaml | 0 .../examples/{advanced-ts => 02-advanced-ts}/reaction.yaml | 0 .../examples/{advanced-ts => 02-advanced-ts}/src/index.ts | 0 .../examples/{simple-ts => 02-advanced-ts}/tsconfig.json | 0 34 files changed, 0 insertions(+), 0 deletions(-) rename reactions/sdk/javascript/examples/{advanced-js => 01-simple-js}/.dockerignore (100%) rename reactions/sdk/javascript/examples/{advanced-js => 01-simple-js}/.gitignore (100%) rename reactions/sdk/javascript/examples/{advanced-js => 01-simple-js}/Dockerfile (100%) rename reactions/sdk/javascript/examples/{simple-js => 01-simple-js}/index.js (100%) rename reactions/sdk/javascript/examples/{advanced-js => 01-simple-js}/package-lock.json (100%) rename reactions/sdk/javascript/examples/{advanced-js => 01-simple-js}/package.json (100%) rename reactions/sdk/javascript/examples/{advanced-js => 01-simple-js}/reaction-provider.yaml (100%) rename reactions/sdk/javascript/examples/{advanced-js => 01-simple-js}/reaction.yaml (100%) rename reactions/sdk/javascript/examples/{advanced-ts => 01-simple-ts}/.dockerignore (100%) rename reactions/sdk/javascript/examples/{advanced-ts => 01-simple-ts}/.gitignore (100%) rename reactions/sdk/javascript/examples/{advanced-ts => 01-simple-ts}/Dockerfile (100%) rename reactions/sdk/javascript/examples/{advanced-ts => 01-simple-ts}/package-lock.json (100%) rename reactions/sdk/javascript/examples/{advanced-ts => 01-simple-ts}/package.json (100%) rename reactions/sdk/javascript/examples/{simple-js => 01-simple-ts}/reaction-provider.yaml (100%) rename reactions/sdk/javascript/examples/{simple-js => 01-simple-ts}/reaction.yaml (100%) rename reactions/sdk/javascript/examples/{simple-ts => 01-simple-ts}/src/index.ts (100%) rename reactions/sdk/javascript/examples/{advanced-ts => 01-simple-ts}/tsconfig.json (100%) rename reactions/sdk/javascript/examples/{simple-js => 02-advanced-js}/.dockerignore (100%) rename reactions/sdk/javascript/examples/{simple-js => 02-advanced-js}/.gitignore (100%) rename reactions/sdk/javascript/examples/{simple-js => 02-advanced-js}/Dockerfile (100%) rename reactions/sdk/javascript/examples/{advanced-js => 02-advanced-js}/index.js (100%) rename reactions/sdk/javascript/examples/{simple-js => 02-advanced-js}/package-lock.json (100%) rename reactions/sdk/javascript/examples/{simple-js => 02-advanced-js}/package.json (100%) rename reactions/sdk/javascript/examples/{simple-ts => 02-advanced-js}/reaction-provider.yaml (100%) rename reactions/sdk/javascript/examples/{simple-ts => 02-advanced-js}/reaction.yaml (100%) rename reactions/sdk/javascript/examples/{simple-ts => 02-advanced-ts}/.dockerignore (100%) rename reactions/sdk/javascript/examples/{simple-ts => 02-advanced-ts}/.gitignore (100%) rename reactions/sdk/javascript/examples/{simple-ts => 02-advanced-ts}/Dockerfile (100%) rename reactions/sdk/javascript/examples/{simple-ts => 02-advanced-ts}/package-lock.json (100%) rename reactions/sdk/javascript/examples/{simple-ts => 02-advanced-ts}/package.json (100%) rename reactions/sdk/javascript/examples/{advanced-ts => 02-advanced-ts}/reaction-provider.yaml (100%) rename reactions/sdk/javascript/examples/{advanced-ts => 02-advanced-ts}/reaction.yaml (100%) rename reactions/sdk/javascript/examples/{advanced-ts => 02-advanced-ts}/src/index.ts (100%) rename reactions/sdk/javascript/examples/{simple-ts => 02-advanced-ts}/tsconfig.json (100%) diff --git a/reactions/sdk/javascript/examples/advanced-js/.dockerignore b/reactions/sdk/javascript/examples/01-simple-js/.dockerignore similarity index 100% rename from reactions/sdk/javascript/examples/advanced-js/.dockerignore rename to reactions/sdk/javascript/examples/01-simple-js/.dockerignore diff --git a/reactions/sdk/javascript/examples/advanced-js/.gitignore b/reactions/sdk/javascript/examples/01-simple-js/.gitignore similarity index 100% rename from reactions/sdk/javascript/examples/advanced-js/.gitignore rename to reactions/sdk/javascript/examples/01-simple-js/.gitignore diff --git a/reactions/sdk/javascript/examples/advanced-js/Dockerfile b/reactions/sdk/javascript/examples/01-simple-js/Dockerfile similarity index 100% rename from reactions/sdk/javascript/examples/advanced-js/Dockerfile rename to reactions/sdk/javascript/examples/01-simple-js/Dockerfile diff --git a/reactions/sdk/javascript/examples/simple-js/index.js b/reactions/sdk/javascript/examples/01-simple-js/index.js similarity index 100% rename from reactions/sdk/javascript/examples/simple-js/index.js rename to reactions/sdk/javascript/examples/01-simple-js/index.js diff --git a/reactions/sdk/javascript/examples/advanced-js/package-lock.json b/reactions/sdk/javascript/examples/01-simple-js/package-lock.json similarity index 100% rename from reactions/sdk/javascript/examples/advanced-js/package-lock.json rename to reactions/sdk/javascript/examples/01-simple-js/package-lock.json diff --git a/reactions/sdk/javascript/examples/advanced-js/package.json b/reactions/sdk/javascript/examples/01-simple-js/package.json similarity index 100% rename from reactions/sdk/javascript/examples/advanced-js/package.json rename to reactions/sdk/javascript/examples/01-simple-js/package.json diff --git a/reactions/sdk/javascript/examples/advanced-js/reaction-provider.yaml b/reactions/sdk/javascript/examples/01-simple-js/reaction-provider.yaml similarity index 100% rename from reactions/sdk/javascript/examples/advanced-js/reaction-provider.yaml rename to reactions/sdk/javascript/examples/01-simple-js/reaction-provider.yaml diff --git a/reactions/sdk/javascript/examples/advanced-js/reaction.yaml b/reactions/sdk/javascript/examples/01-simple-js/reaction.yaml similarity index 100% rename from reactions/sdk/javascript/examples/advanced-js/reaction.yaml rename to reactions/sdk/javascript/examples/01-simple-js/reaction.yaml diff --git a/reactions/sdk/javascript/examples/advanced-ts/.dockerignore b/reactions/sdk/javascript/examples/01-simple-ts/.dockerignore similarity index 100% rename from reactions/sdk/javascript/examples/advanced-ts/.dockerignore rename to reactions/sdk/javascript/examples/01-simple-ts/.dockerignore diff --git a/reactions/sdk/javascript/examples/advanced-ts/.gitignore b/reactions/sdk/javascript/examples/01-simple-ts/.gitignore similarity index 100% rename from reactions/sdk/javascript/examples/advanced-ts/.gitignore rename to reactions/sdk/javascript/examples/01-simple-ts/.gitignore diff --git a/reactions/sdk/javascript/examples/advanced-ts/Dockerfile b/reactions/sdk/javascript/examples/01-simple-ts/Dockerfile similarity index 100% rename from reactions/sdk/javascript/examples/advanced-ts/Dockerfile rename to reactions/sdk/javascript/examples/01-simple-ts/Dockerfile diff --git a/reactions/sdk/javascript/examples/advanced-ts/package-lock.json b/reactions/sdk/javascript/examples/01-simple-ts/package-lock.json similarity index 100% rename from reactions/sdk/javascript/examples/advanced-ts/package-lock.json rename to reactions/sdk/javascript/examples/01-simple-ts/package-lock.json diff --git a/reactions/sdk/javascript/examples/advanced-ts/package.json b/reactions/sdk/javascript/examples/01-simple-ts/package.json similarity index 100% rename from reactions/sdk/javascript/examples/advanced-ts/package.json rename to reactions/sdk/javascript/examples/01-simple-ts/package.json diff --git a/reactions/sdk/javascript/examples/simple-js/reaction-provider.yaml b/reactions/sdk/javascript/examples/01-simple-ts/reaction-provider.yaml similarity index 100% rename from reactions/sdk/javascript/examples/simple-js/reaction-provider.yaml rename to reactions/sdk/javascript/examples/01-simple-ts/reaction-provider.yaml diff --git a/reactions/sdk/javascript/examples/simple-js/reaction.yaml b/reactions/sdk/javascript/examples/01-simple-ts/reaction.yaml similarity index 100% rename from reactions/sdk/javascript/examples/simple-js/reaction.yaml rename to reactions/sdk/javascript/examples/01-simple-ts/reaction.yaml diff --git a/reactions/sdk/javascript/examples/simple-ts/src/index.ts b/reactions/sdk/javascript/examples/01-simple-ts/src/index.ts similarity index 100% rename from reactions/sdk/javascript/examples/simple-ts/src/index.ts rename to reactions/sdk/javascript/examples/01-simple-ts/src/index.ts diff --git a/reactions/sdk/javascript/examples/advanced-ts/tsconfig.json b/reactions/sdk/javascript/examples/01-simple-ts/tsconfig.json similarity index 100% rename from reactions/sdk/javascript/examples/advanced-ts/tsconfig.json rename to reactions/sdk/javascript/examples/01-simple-ts/tsconfig.json diff --git a/reactions/sdk/javascript/examples/simple-js/.dockerignore b/reactions/sdk/javascript/examples/02-advanced-js/.dockerignore similarity index 100% rename from reactions/sdk/javascript/examples/simple-js/.dockerignore rename to reactions/sdk/javascript/examples/02-advanced-js/.dockerignore diff --git a/reactions/sdk/javascript/examples/simple-js/.gitignore b/reactions/sdk/javascript/examples/02-advanced-js/.gitignore similarity index 100% rename from reactions/sdk/javascript/examples/simple-js/.gitignore rename to reactions/sdk/javascript/examples/02-advanced-js/.gitignore diff --git a/reactions/sdk/javascript/examples/simple-js/Dockerfile b/reactions/sdk/javascript/examples/02-advanced-js/Dockerfile similarity index 100% rename from reactions/sdk/javascript/examples/simple-js/Dockerfile rename to reactions/sdk/javascript/examples/02-advanced-js/Dockerfile diff --git a/reactions/sdk/javascript/examples/advanced-js/index.js b/reactions/sdk/javascript/examples/02-advanced-js/index.js similarity index 100% rename from reactions/sdk/javascript/examples/advanced-js/index.js rename to reactions/sdk/javascript/examples/02-advanced-js/index.js diff --git a/reactions/sdk/javascript/examples/simple-js/package-lock.json b/reactions/sdk/javascript/examples/02-advanced-js/package-lock.json similarity index 100% rename from reactions/sdk/javascript/examples/simple-js/package-lock.json rename to reactions/sdk/javascript/examples/02-advanced-js/package-lock.json diff --git a/reactions/sdk/javascript/examples/simple-js/package.json b/reactions/sdk/javascript/examples/02-advanced-js/package.json similarity index 100% rename from reactions/sdk/javascript/examples/simple-js/package.json rename to reactions/sdk/javascript/examples/02-advanced-js/package.json diff --git a/reactions/sdk/javascript/examples/simple-ts/reaction-provider.yaml b/reactions/sdk/javascript/examples/02-advanced-js/reaction-provider.yaml similarity index 100% rename from reactions/sdk/javascript/examples/simple-ts/reaction-provider.yaml rename to reactions/sdk/javascript/examples/02-advanced-js/reaction-provider.yaml diff --git a/reactions/sdk/javascript/examples/simple-ts/reaction.yaml b/reactions/sdk/javascript/examples/02-advanced-js/reaction.yaml similarity index 100% rename from reactions/sdk/javascript/examples/simple-ts/reaction.yaml rename to reactions/sdk/javascript/examples/02-advanced-js/reaction.yaml diff --git a/reactions/sdk/javascript/examples/simple-ts/.dockerignore b/reactions/sdk/javascript/examples/02-advanced-ts/.dockerignore similarity index 100% rename from reactions/sdk/javascript/examples/simple-ts/.dockerignore rename to reactions/sdk/javascript/examples/02-advanced-ts/.dockerignore diff --git a/reactions/sdk/javascript/examples/simple-ts/.gitignore b/reactions/sdk/javascript/examples/02-advanced-ts/.gitignore similarity index 100% rename from reactions/sdk/javascript/examples/simple-ts/.gitignore rename to reactions/sdk/javascript/examples/02-advanced-ts/.gitignore diff --git a/reactions/sdk/javascript/examples/simple-ts/Dockerfile b/reactions/sdk/javascript/examples/02-advanced-ts/Dockerfile similarity index 100% rename from reactions/sdk/javascript/examples/simple-ts/Dockerfile rename to reactions/sdk/javascript/examples/02-advanced-ts/Dockerfile diff --git a/reactions/sdk/javascript/examples/simple-ts/package-lock.json b/reactions/sdk/javascript/examples/02-advanced-ts/package-lock.json similarity index 100% rename from reactions/sdk/javascript/examples/simple-ts/package-lock.json rename to reactions/sdk/javascript/examples/02-advanced-ts/package-lock.json diff --git a/reactions/sdk/javascript/examples/simple-ts/package.json b/reactions/sdk/javascript/examples/02-advanced-ts/package.json similarity index 100% rename from reactions/sdk/javascript/examples/simple-ts/package.json rename to reactions/sdk/javascript/examples/02-advanced-ts/package.json diff --git a/reactions/sdk/javascript/examples/advanced-ts/reaction-provider.yaml b/reactions/sdk/javascript/examples/02-advanced-ts/reaction-provider.yaml similarity index 100% rename from reactions/sdk/javascript/examples/advanced-ts/reaction-provider.yaml rename to reactions/sdk/javascript/examples/02-advanced-ts/reaction-provider.yaml diff --git a/reactions/sdk/javascript/examples/advanced-ts/reaction.yaml b/reactions/sdk/javascript/examples/02-advanced-ts/reaction.yaml similarity index 100% rename from reactions/sdk/javascript/examples/advanced-ts/reaction.yaml rename to reactions/sdk/javascript/examples/02-advanced-ts/reaction.yaml diff --git a/reactions/sdk/javascript/examples/advanced-ts/src/index.ts b/reactions/sdk/javascript/examples/02-advanced-ts/src/index.ts similarity index 100% rename from reactions/sdk/javascript/examples/advanced-ts/src/index.ts rename to reactions/sdk/javascript/examples/02-advanced-ts/src/index.ts diff --git a/reactions/sdk/javascript/examples/simple-ts/tsconfig.json b/reactions/sdk/javascript/examples/02-advanced-ts/tsconfig.json similarity index 100% rename from reactions/sdk/javascript/examples/simple-ts/tsconfig.json rename to reactions/sdk/javascript/examples/02-advanced-ts/tsconfig.json From ff4d1a56afccb6efdd082d2bc45a38a15c2abad8 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 1 Nov 2024 14:50:47 -0700 Subject: [PATCH 06/17] external images --- .../src/spec_builder/mod.rs | 440 +++++++++--------- .../src/spec_builder/query_container.rs | 3 + .../src/spec_builder/reaction.rs | 1 + .../src/spec_builder/source.rs | 6 +- .../mgmt_api/src/api/v1/mappings/providers.rs | 3 + .../mgmt_api/src/api/v1/models/providers.rs | 2 + .../mgmt_api/src/domain/mappings.rs | 1 + control-planes/mgmt_api/src/domain/models.rs | 2 + .../resource_services/extensible/mod.rs | 2 + .../resource_provider_api/src/models.rs | 29 +- .../01-simple-js/reaction-provider.yaml | 3 +- .../examples/01-simple-js/reaction.yaml | 2 +- .../01-simple-ts/reaction-provider.yaml | 3 +- .../examples/01-simple-ts/reaction.yaml | 2 +- .../02-advanced-js/reaction-provider.yaml | 14 +- .../examples/02-advanced-js/reaction.yaml | 12 +- .../02-advanced-ts/reaction-provider.yaml | 1 + 17 files changed, 282 insertions(+), 244 deletions(-) diff --git a/control-planes/kubernetes_provider/src/spec_builder/mod.rs b/control-planes/kubernetes_provider/src/spec_builder/mod.rs index 2608343e..8450434b 100644 --- a/control-planes/kubernetes_provider/src/spec_builder/mod.rs +++ b/control-planes/kubernetes_provider/src/spec_builder/mod.rs @@ -12,221 +12,225 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::collections::BTreeMap; - -use k8s_openapi::{ - api::{ - apps::v1::DeploymentSpec, - core::v1::{ - Container, ContainerPort, EnvVar, EnvVarSource, PodSpec, PodTemplateSpec, - ResourceRequirements, SecretKeySelector, - }, - }, - apimachinery::pkg::apis::meta::v1::LabelSelector, -}; -use kube::core::ObjectMeta; -use resource_provider_api::models::{ConfigValue, ResourceRequest}; -use serde_json::json; - -use super::models::{KubernetesSpec, RuntimeConfig}; -pub mod query_container; -pub mod reaction; -pub mod source; - -pub trait SpecBuilder { - fn build( - &self, - source: ResourceRequest, - runtime_config: &RuntimeConfig, - instance_id: &str, - ) -> Vec; -} - -#[allow(clippy::too_many_arguments)] -pub fn build_deployment_spec( - runtime_config: &RuntimeConfig, - resource_type: &str, - resource_id: &str, - service_name: &str, - image: &str, - replicas: i32, - app_port: Option, - env_vars: BTreeMap, - endpoints: Option>, - config_volumes: Option>, - // claim => mount path - persistent_volumes: Option>, - app_protocol: Option, -) -> DeploymentSpec { - let app_id = format!("{}-{}", resource_id, service_name); - - let mut env = map_env_vars(env_vars); - let mut ports = Vec::new(); - let mut volume_mounts = Vec::new(); - let mut volumes = Vec::new(); - let mut pod_annotations = BTreeMap::new(); - pod_annotations.insert("dapr.io/enabled".to_string(), "true".to_string()); - pod_annotations.insert("dapr.io/app-id".to_string(), app_id.clone()); - pod_annotations.insert( - "dapr.io/config".to_string(), - runtime_config.dapr_config.clone(), - ); - pod_annotations.insert( - "dapr.io/sidecar-image".to_string(), - runtime_config.dapr_sidecar.clone(), - ); - - if let Some(port) = app_port { - pod_annotations.insert("dapr.io/app-port".to_string(), port.to_string()); - } - - if let Some(protocol) = app_protocol { - pod_annotations.insert("dapr.io/app-protocol".to_string(), protocol); - } - let mut labels = BTreeMap::new(); - labels.insert("drasi/type".to_string(), resource_type.to_string()); - labels.insert("drasi/resource".to_string(), resource_id.to_string()); - labels.insert("drasi/service".to_string(), service_name.to_string()); - - if let Some(endpoints) = endpoints { - for (name, port) in endpoints { - ports.push(ContainerPort { - name: Some(name), - container_port: port, - ..Default::default() - }); - } - } - - if let Some(persistent_volumes) = persistent_volumes { - for (name, path) in persistent_volumes { - volume_mounts.push(k8s_openapi::api::core::v1::VolumeMount { - name: name.clone(), - mount_path: path.clone(), - ..Default::default() - }); - volumes.push(k8s_openapi::api::core::v1::Volume { - name: name.clone(), - persistent_volume_claim: Some( - k8s_openapi::api::core::v1::PersistentVolumeClaimVolumeSource { - claim_name: name.clone(), - ..Default::default() - }, - ), - ..Default::default() - }); - } - } - - if let Some(config_volumes) = config_volumes { - for (name, path) in config_volumes { - volume_mounts.push(k8s_openapi::api::core::v1::VolumeMount { - name: name.clone(), - read_only: Some(true), - mount_path: path.clone(), - ..Default::default() - }); - volumes.push(k8s_openapi::api::core::v1::Volume { - name: name.clone(), - config_map: Some(k8s_openapi::api::core::v1::ConfigMapVolumeSource { - name: Some(name.clone()), - ..Default::default() - }), - ..Default::default() - }); - } - } - - env.sort_by_key(|e| e.name.clone()); - - DeploymentSpec { - replicas: Some(replicas), - selector: LabelSelector { - match_labels: Some(labels.clone()), - ..Default::default() - }, - template: PodTemplateSpec { - metadata: Some(ObjectMeta { - labels: Some(labels.clone()), - annotations: Some(pod_annotations), - ..Default::default() - }), - spec: Some(PodSpec { - containers: vec![Container { - name: service_name.to_string(), - image: Some(format!( - "{}{}:{}", - runtime_config.image_prefix, image, runtime_config.image_tag - )), - image_pull_policy: Some(runtime_config.image_pull_policy.clone()), - termination_message_policy: Some("FallbackToLogsOnError".to_string()), - env: Some(env), - resources: Some(get_default_resource_requirements(image)), - ports: Some(ports), - volume_mounts: Some(volume_mounts), - ..Default::default() - }], - volumes: Some(volumes), - ..Default::default() - }), - }, - ..Default::default() - } -} - -fn map_env_vars(env_vars: BTreeMap) -> Vec { - let mut env: Vec = vec![]; - - for (k, v) in env_vars.iter() { - env.push(EnvVar { - name: k.to_string(), - value: match v { - ConfigValue::Inline { value } => Some(value.clone()), - _ => None, - }, - value_from: match v { - ConfigValue::Secret { name, key } => Some(EnvVarSource { - secret_key_ref: Some(SecretKeySelector { - key: key.clone(), - name: Some(name.clone()), - optional: None, - }), - config_map_key_ref: None, - field_ref: None, - resource_field_ref: None, - }), - _ => None, - }, - }); - } - env -} - -fn get_default_resource_requirements(image: &str) -> ResourceRequirements { - let result: ResourceRequirements = match image { - "query-container-query-host" => serde_json::from_value(json!({ - "limits": { - "cpu": "250m", - "memory": "4Gi" - }, - "requests": { - "cpu": "250m", - "memory": "512Mi" - }, - })) - .unwrap(), - _ => serde_json::from_value(json!({ - "limits": { - "cpu": "200m", - "memory": "512Mi" - }, - "requests": { - "cpu": "50m", - "memory": "128Mi" - }, - })) - .unwrap(), - }; - - result -} +use std::collections::BTreeMap; + +use k8s_openapi::{ + api::{ + apps::v1::DeploymentSpec, + core::v1::{ + Container, ContainerPort, EnvVar, EnvVarSource, PodSpec, PodTemplateSpec, + ResourceRequirements, SecretKeySelector, + }, + }, + apimachinery::pkg::apis::meta::v1::LabelSelector, +}; +use kube::core::ObjectMeta; +use resource_provider_api::models::{ConfigValue, ResourceRequest}; +use serde_json::json; + +use super::models::{KubernetesSpec, RuntimeConfig}; +pub mod query_container; +pub mod reaction; +pub mod source; + +pub trait SpecBuilder { + fn build( + &self, + source: ResourceRequest, + runtime_config: &RuntimeConfig, + instance_id: &str, + ) -> Vec; +} + +#[allow(clippy::too_many_arguments)] +pub fn build_deployment_spec( + runtime_config: &RuntimeConfig, + resource_type: &str, + resource_id: &str, + service_name: &str, + image: &str, + external_image: bool, + replicas: i32, + app_port: Option, + env_vars: BTreeMap, + endpoints: Option>, + config_volumes: Option>, + // claim => mount path + persistent_volumes: Option>, + app_protocol: Option, +) -> DeploymentSpec { + let app_id = format!("{}-{}", resource_id, service_name); + + let mut env = map_env_vars(env_vars); + let mut ports = Vec::new(); + let mut volume_mounts = Vec::new(); + let mut volumes = Vec::new(); + let mut pod_annotations = BTreeMap::new(); + pod_annotations.insert("dapr.io/enabled".to_string(), "true".to_string()); + pod_annotations.insert("dapr.io/app-id".to_string(), app_id.clone()); + pod_annotations.insert( + "dapr.io/config".to_string(), + runtime_config.dapr_config.clone(), + ); + pod_annotations.insert( + "dapr.io/sidecar-image".to_string(), + runtime_config.dapr_sidecar.clone(), + ); + + if let Some(port) = app_port { + pod_annotations.insert("dapr.io/app-port".to_string(), port.to_string()); + } + + if let Some(protocol) = app_protocol { + pod_annotations.insert("dapr.io/app-protocol".to_string(), protocol); + } + let mut labels = BTreeMap::new(); + labels.insert("drasi/type".to_string(), resource_type.to_string()); + labels.insert("drasi/resource".to_string(), resource_id.to_string()); + labels.insert("drasi/service".to_string(), service_name.to_string()); + + if let Some(endpoints) = endpoints { + for (name, port) in endpoints { + ports.push(ContainerPort { + name: Some(name), + container_port: port, + ..Default::default() + }); + } + } + + if let Some(persistent_volumes) = persistent_volumes { + for (name, path) in persistent_volumes { + volume_mounts.push(k8s_openapi::api::core::v1::VolumeMount { + name: name.clone(), + mount_path: path.clone(), + ..Default::default() + }); + volumes.push(k8s_openapi::api::core::v1::Volume { + name: name.clone(), + persistent_volume_claim: Some( + k8s_openapi::api::core::v1::PersistentVolumeClaimVolumeSource { + claim_name: name.clone(), + ..Default::default() + }, + ), + ..Default::default() + }); + } + } + + if let Some(config_volumes) = config_volumes { + for (name, path) in config_volumes { + volume_mounts.push(k8s_openapi::api::core::v1::VolumeMount { + name: name.clone(), + read_only: Some(true), + mount_path: path.clone(), + ..Default::default() + }); + volumes.push(k8s_openapi::api::core::v1::Volume { + name: name.clone(), + config_map: Some(k8s_openapi::api::core::v1::ConfigMapVolumeSource { + name: Some(name.clone()), + ..Default::default() + }), + ..Default::default() + }); + } + } + + env.sort_by_key(|e| e.name.clone()); + + DeploymentSpec { + replicas: Some(replicas), + selector: LabelSelector { + match_labels: Some(labels.clone()), + ..Default::default() + }, + template: PodTemplateSpec { + metadata: Some(ObjectMeta { + labels: Some(labels.clone()), + annotations: Some(pod_annotations), + ..Default::default() + }), + spec: Some(PodSpec { + containers: vec![Container { + name: service_name.to_string(), + image: match external_image { + true => Some(image.to_string()), + false => Some(format!( + "{}{}:{}", + runtime_config.image_prefix, image, runtime_config.image_tag + )), + }, + image_pull_policy: Some(runtime_config.image_pull_policy.clone()), + termination_message_policy: Some("FallbackToLogsOnError".to_string()), + env: Some(env), + resources: Some(get_default_resource_requirements(image)), + ports: Some(ports), + volume_mounts: Some(volume_mounts), + ..Default::default() + }], + volumes: Some(volumes), + ..Default::default() + }), + }, + ..Default::default() + } +} + +fn map_env_vars(env_vars: BTreeMap) -> Vec { + let mut env: Vec = vec![]; + + for (k, v) in env_vars.iter() { + env.push(EnvVar { + name: k.to_string(), + value: match v { + ConfigValue::Inline { value } => Some(value.clone()), + _ => None, + }, + value_from: match v { + ConfigValue::Secret { name, key } => Some(EnvVarSource { + secret_key_ref: Some(SecretKeySelector { + key: key.clone(), + name: Some(name.clone()), + optional: None, + }), + config_map_key_ref: None, + field_ref: None, + resource_field_ref: None, + }), + _ => None, + }, + }); + } + env +} + +fn get_default_resource_requirements(image: &str) -> ResourceRequirements { + let result: ResourceRequirements = match image { + "query-container-query-host" => serde_json::from_value(json!({ + "limits": { + "cpu": "250m", + "memory": "4Gi" + }, + "requests": { + "cpu": "250m", + "memory": "512Mi" + }, + })) + .unwrap(), + _ => serde_json::from_value(json!({ + "limits": { + "cpu": "200m", + "memory": "512Mi" + }, + "requests": { + "cpu": "50m", + "memory": "128Mi" + }, + })) + .unwrap(), + }; + + result +} diff --git a/control-planes/kubernetes_provider/src/spec_builder/query_container.rs b/control-planes/kubernetes_provider/src/spec_builder/query_container.rs index 70a7e210..d2d49b4a 100644 --- a/control-planes/kubernetes_provider/src/spec_builder/query_container.rs +++ b/control-planes/kubernetes_provider/src/spec_builder/query_container.rs @@ -58,6 +58,7 @@ impl SpecBuilder for QueryContainerSpecBuilder { &source.id, "publish-api", "query-container-publish-api", + false, 1, Some(4000), hashmap![ @@ -209,6 +210,7 @@ impl SpecBuilder for QueryContainerSpecBuilder { &source.id, "query-host", "query-container-query-host", + false, source.spec.query_host_count as i32, Some(3000), env.clone(), @@ -233,6 +235,7 @@ impl SpecBuilder for QueryContainerSpecBuilder { &source.id, "view-svc", "query-container-view-svc", + false, 1, Some(8080), hashmap![ diff --git a/control-planes/kubernetes_provider/src/spec_builder/reaction.rs b/control-planes/kubernetes_provider/src/spec_builder/reaction.rs index 16e4da62..9f1ec5e2 100644 --- a/control-planes/kubernetes_provider/src/spec_builder/reaction.rs +++ b/control-planes/kubernetes_provider/src/spec_builder/reaction.rs @@ -147,6 +147,7 @@ impl SpecBuilder for ReactionSpecBuilder { &source.id, "reaction", image.as_str(), + service_spec.external_image.unwrap_or(false), replica.parse::().unwrap(), Some(app_port.unwrap_or(80)), env.clone(), diff --git a/control-planes/kubernetes_provider/src/spec_builder/source.rs b/control-planes/kubernetes_provider/src/spec_builder/source.rs index 5f5f3837..02368d73 100644 --- a/control-planes/kubernetes_provider/src/spec_builder/source.rs +++ b/control-planes/kubernetes_provider/src/spec_builder/source.rs @@ -21,7 +21,7 @@ use k8s_openapi::{ apimachinery::pkg::util::intstr::IntOrString, }; use resource_provider_api::models::{ConfigValue, EndpointSetting, ResourceRequest, SourceSpec}; -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; macro_rules! hashmap { ($( $key: expr => $val: expr ),*) => {{ @@ -51,6 +51,7 @@ impl SpecBuilder for SourceSpecBuilder { &source.id, "change-router", "source-change-router", + false, 1, Some(3000), hashmap![ @@ -78,6 +79,7 @@ impl SpecBuilder for SourceSpecBuilder { &source.id, "change-dispatcher", "source-change-dispatcher", + false, 1, Some(3000), hashmap![ @@ -105,6 +107,7 @@ impl SpecBuilder for SourceSpecBuilder { &source.id, "query-api", "source-query-api", + false, 1, Some(4001), hashmap![ @@ -214,6 +217,7 @@ impl SpecBuilder for SourceSpecBuilder { &source.id, &service_name, service_spec.image.as_str(), + service_spec.external_image.unwrap_or(false), replica, app_port, env_var_map.clone(), diff --git a/control-planes/mgmt_api/src/api/v1/mappings/providers.rs b/control-planes/mgmt_api/src/api/v1/mappings/providers.rs index 1b0753f3..fafacb9f 100644 --- a/control-planes/mgmt_api/src/api/v1/mappings/providers.rs +++ b/control-planes/mgmt_api/src/api/v1/mappings/providers.rs @@ -50,6 +50,7 @@ impl From for ServiceConfig { ServiceConfig { replica: None, image: None, + external_image: None, deprovision_handler: None, endpoints: service .endpoints @@ -152,6 +153,7 @@ impl From for ProviderService { fn from(provider_service: ProviderServiceDto) -> Self { ProviderService { image: provider_service.image, + external_image: provider_service.external_image, dapr: provider_service.dapr, endpoints: provider_service .endpoints @@ -166,6 +168,7 @@ impl From for ProviderServiceDto { fn from(provider_service: ProviderService) -> Self { ProviderServiceDto { image: provider_service.image, + external_image: provider_service.external_image, dapr: provider_service.dapr, endpoints: provider_service .endpoints diff --git a/control-planes/mgmt_api/src/api/v1/models/providers.rs b/control-planes/mgmt_api/src/api/v1/models/providers.rs index 6f32c762..ee6a6eda 100644 --- a/control-planes/mgmt_api/src/api/v1/models/providers.rs +++ b/control-planes/mgmt_api/src/api/v1/models/providers.rs @@ -28,6 +28,8 @@ pub struct ProviderSpecDto { #[derive(Serialize, Deserialize, Debug)] pub struct ProviderServiceDto { pub image: String, + #[serde(rename = "externalImage")] + pub external_image: Option, pub dapr: Option>, pub endpoints: Option>, pub config_schema: Option, diff --git a/control-planes/mgmt_api/src/domain/mappings.rs b/control-planes/mgmt_api/src/domain/mappings.rs index a65792e7..21412542 100644 --- a/control-planes/mgmt_api/src/domain/mappings.rs +++ b/control-planes/mgmt_api/src/domain/mappings.rs @@ -169,6 +169,7 @@ impl From for resource_provider_api::models::Service { resource_provider_api::models::Service { replica: service.replica, image: service.image.unwrap(), + external_image: service.external_image, endpoints: service .endpoints .map(|endpoints| endpoints.into_iter().map(|(k, v)| (k, v.into())).collect()), diff --git a/control-planes/mgmt_api/src/domain/models.rs b/control-planes/mgmt_api/src/domain/models.rs index fdf05228..c536db92 100644 --- a/control-planes/mgmt_api/src/domain/models.rs +++ b/control-planes/mgmt_api/src/domain/models.rs @@ -224,6 +224,7 @@ pub struct ReactionProviderMarker; #[serde(rename_all = "camelCase")] pub struct ProviderService { pub image: String, + pub external_image: Option, pub dapr: Option>, pub endpoints: Option>, pub config_schema: Option, @@ -241,6 +242,7 @@ pub struct ServiceEndpoint { pub struct ServiceConfig { pub replica: Option, pub image: Option, + pub external_image: Option, pub dapr: Option>, pub endpoints: Option>, pub properties: Option>, diff --git a/control-planes/mgmt_api/src/domain/resource_services/extensible/mod.rs b/control-planes/mgmt_api/src/domain/resource_services/extensible/mod.rs index 756952c2..83cf49d5 100644 --- a/control-planes/mgmt_api/src/domain/resource_services/extensible/mod.rs +++ b/control-planes/mgmt_api/src/domain/resource_services/extensible/mod.rs @@ -390,6 +390,7 @@ fn merge_spec( _ => ServiceConfig { replica: None, image: None, + external_image: None, endpoints: None, dapr: None, properties: None, @@ -535,6 +536,7 @@ fn merge_spec( let new_service = ServiceConfig { replica: None, image: Some(service_config.image.clone()), + external_image: service_config.external_image, endpoints, dapr, properties: service_properties, diff --git a/control-planes/resource_provider_api/src/models.rs b/control-planes/resource_provider_api/src/models.rs index 719785cb..862dc8bf 100644 --- a/control-planes/resource_provider_api/src/models.rs +++ b/control-planes/resource_provider_api/src/models.rs @@ -1,17 +1,17 @@ -// Copyright 2024 The Drasi Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use std::collections::{BTreeMap, HashMap}; use std::fmt; use std::marker::PhantomData; @@ -174,6 +174,7 @@ pub enum DefaultValue { pub struct Service { pub replica: Option, pub image: String, + pub external_image: Option, pub endpoints: Option>, pub dapr: Option>, pub properties: Option>, diff --git a/reactions/sdk/javascript/examples/01-simple-js/reaction-provider.yaml b/reactions/sdk/javascript/examples/01-simple-js/reaction-provider.yaml index 20cd1909..9d12c464 100644 --- a/reactions/sdk/javascript/examples/01-simple-js/reaction-provider.yaml +++ b/reactions/sdk/javascript/examples/01-simple-js/reaction-provider.yaml @@ -3,5 +3,6 @@ kind: ReactionProvider name: Simple spec: services: - simple: + reaction: image: reaction-simple + externalImage: true diff --git a/reactions/sdk/javascript/examples/01-simple-js/reaction.yaml b/reactions/sdk/javascript/examples/01-simple-js/reaction.yaml index 84619734..c59d0ad8 100644 --- a/reactions/sdk/javascript/examples/01-simple-js/reaction.yaml +++ b/reactions/sdk/javascript/examples/01-simple-js/reaction.yaml @@ -4,5 +4,5 @@ name: test-simple spec: kind: Simple queries: - freezer2: + query1: query2: \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/01-simple-ts/reaction-provider.yaml b/reactions/sdk/javascript/examples/01-simple-ts/reaction-provider.yaml index 20cd1909..9d12c464 100644 --- a/reactions/sdk/javascript/examples/01-simple-ts/reaction-provider.yaml +++ b/reactions/sdk/javascript/examples/01-simple-ts/reaction-provider.yaml @@ -3,5 +3,6 @@ kind: ReactionProvider name: Simple spec: services: - simple: + reaction: image: reaction-simple + externalImage: true diff --git a/reactions/sdk/javascript/examples/01-simple-ts/reaction.yaml b/reactions/sdk/javascript/examples/01-simple-ts/reaction.yaml index 84619734..c59d0ad8 100644 --- a/reactions/sdk/javascript/examples/01-simple-ts/reaction.yaml +++ b/reactions/sdk/javascript/examples/01-simple-ts/reaction.yaml @@ -4,5 +4,5 @@ name: test-simple spec: kind: Simple queries: - freezer2: + query1: query2: \ No newline at end of file diff --git a/reactions/sdk/javascript/examples/02-advanced-js/reaction-provider.yaml b/reactions/sdk/javascript/examples/02-advanced-js/reaction-provider.yaml index 20cd1909..c77529a7 100644 --- a/reactions/sdk/javascript/examples/02-advanced-js/reaction-provider.yaml +++ b/reactions/sdk/javascript/examples/02-advanced-js/reaction-provider.yaml @@ -1,7 +1,15 @@ apiVersion: v1 kind: ReactionProvider -name: Simple +name: Advanced spec: services: - simple: - image: reaction-simple + reaction: + image: reaction-advanced + externalImage: true + config_schema: + type: object + properties: + MyConnectionString: + type: string + required: + - MyConnectionString diff --git a/reactions/sdk/javascript/examples/02-advanced-js/reaction.yaml b/reactions/sdk/javascript/examples/02-advanced-js/reaction.yaml index 84619734..6a8e34cc 100644 --- a/reactions/sdk/javascript/examples/02-advanced-js/reaction.yaml +++ b/reactions/sdk/javascript/examples/02-advanced-js/reaction.yaml @@ -1,8 +1,12 @@ kind: Reaction apiVersion: v1 -name: test-simple +name: test-advanced spec: - kind: Simple + kind: Advanced + properties: + MyConnectionString: "some connection string" queries: - freezer2: - query2: \ No newline at end of file + query1: | + greeting: "Hello, World!" + query2: | + greeting: "Howdy!" diff --git a/reactions/sdk/javascript/examples/02-advanced-ts/reaction-provider.yaml b/reactions/sdk/javascript/examples/02-advanced-ts/reaction-provider.yaml index 97e7424f..c77529a7 100644 --- a/reactions/sdk/javascript/examples/02-advanced-ts/reaction-provider.yaml +++ b/reactions/sdk/javascript/examples/02-advanced-ts/reaction-provider.yaml @@ -5,6 +5,7 @@ spec: services: reaction: image: reaction-advanced + externalImage: true config_schema: type: object properties: From e22bc89bb06a27d5c3c98a9cca6331ec3f8c930b Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 1 Nov 2024 17:36:49 -0700 Subject: [PATCH 07/17] wip --- .../sdk/dotnet/drasi-reaction-sdk/.gitignore | 2 + .../sdk/dotnet/drasi-reaction-sdk/Makefile | 4 + .../sdk/dotnet/drasi-reaction-sdk/Models.g.cs | 760 ++++++++++++++++++ .../sdk/dotnet/drasi-reaction-sdk/Reaction.cs | 6 + .../drasi-reaction-sdk.csproj | 14 + .../drasi-reaction-sdk/drasi-reaction-sdk.sln | 25 + typespec/notes.md | 7 + typespec/query-output/main.tsp | 4 +- typespec/query-output/tspconfig.yaml | 1 + 9 files changed, 822 insertions(+), 1 deletion(-) create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/.gitignore create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Makefile create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Models.g.cs create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.csproj create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.sln diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/.gitignore b/reactions/sdk/dotnet/drasi-reaction-sdk/.gitignore new file mode 100644 index 00000000..8d4a6c08 --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/.gitignore @@ -0,0 +1,2 @@ +bin +obj \ No newline at end of file diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Makefile b/reactions/sdk/dotnet/drasi-reaction-sdk/Makefile new file mode 100644 index 00000000..9b91e3a2 --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Makefile @@ -0,0 +1,4 @@ +.PHONY: generate-types + +generate-types: + quicktype --src-lang schema -l cs -o Models.g.cs ../../../../typespec/query-output/_generated/@typespec/json-schema/*.yaml --framework SystemTextJson --namespace Drasi.Reaction.SDK.Models \ No newline at end of file diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Models.g.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Models.g.cs new file mode 100644 index 00000000..7e8afc02 --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Models.g.cs @@ -0,0 +1,760 @@ +// +// +// To parse this JSON data, add NuGet 'System.Text.Json' then do one of these: +// +// using Drasi.Reaction.SDK.Models; +// +// var bootstrapCompletedSignal = BootstrapCompletedSignal.FromJson(jsonString); +// var bootstrapStartedSignal = BootstrapStartedSignal.FromJson(jsonString); +// var changeEvent = ChangeEvent.FromJson(jsonString); +// var controlEvent = ControlEvent.FromJson(jsonString); +// var controlSignal = ControlSignal.FromJson(jsonString); +// var deletedSignal = DeletedSignal.FromJson(jsonString); +// var resultEvent = ResultEvent.FromJson(jsonString); +// var runningSignal = RunningSignal.FromJson(jsonString); +// var stoppedSignal = StoppedSignal.FromJson(jsonString); +// var updatePayload = UpdatePayload.FromJson(jsonString); +// var versions = Versions.FromJson(jsonString); +#nullable enable +#pragma warning disable CS8618 +#pragma warning disable CS8601 +#pragma warning disable CS8603 + +namespace Drasi.Reaction.SDK.Models +{ + using System; + using System.Collections.Generic; + + using System.Text.Json; + using System.Text.Json.Serialization; + using System.Globalization; + + /// + /// A signal that indicates that the query has completed bootstrapping + /// + public partial class BootstrapCompletedSignal + { + [JsonPropertyName("kind")] + public BootstrapCompletedSignalKind Kind { get; set; } + } + + /// + /// A signal that indicates that the query is starting to bootstrap + /// + public partial class BootstrapStartedSignal + { + [JsonPropertyName("kind")] + public BootstrapStartedSignalKind Kind { get; set; } + } + + /// + /// An event that represents a changes in the result set + /// + public partial class ChangeEvent + { + /// + /// The results that were added to the result set as a consequence of the change + /// + [JsonPropertyName("addedResults")] + public Dictionary[] AddedResults { get; set; } + + /// + /// The results that were deleted from the result set as a consequence of the change + /// + [JsonPropertyName("deletedResults")] + public Dictionary[] DeletedResults { get; set; } + + [JsonPropertyName("kind")] + public ChangeEventKind Kind { get; set; } + + /// + /// The results that were updated on the result set as a consequence of the change + /// + [JsonPropertyName("updatedResults")] + public UpdatedResultElement[] UpdatedResults { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("metadata")] + public Dictionary Metadata { get; set; } + + /// + /// The ID of the query that the event originated from + /// + [JsonPropertyName("queryId")] + public string QueryId { get; set; } + + /// + /// The sequence number of the event + /// + [JsonPropertyName("sequence")] + public long Sequence { get; set; } + + /// + /// The time at which the source change was recorded + /// + [JsonPropertyName("sourceTimeMs")] + public long SourceTimeMs { get; set; } + } + + /// + /// A payload that represents the before and after snapshots of a result + /// + public partial class UpdatedResultElement + { + /// + /// The snapshot of the result after the change + /// + [JsonPropertyName("after")] + public Dictionary After { get; set; } + + /// + /// The snapshot of the result before the change + /// + [JsonPropertyName("before")] + public Dictionary Before { get; set; } + } + + /// + /// An event that represents a control signal from the query, such are start, stop, etc. + /// + public partial class ControlEvent + { + [JsonPropertyName("controlSignal")] + public ControlSignalClass ControlSignal { get; set; } + + [JsonPropertyName("kind")] + public ControlEventKind Kind { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("metadata")] + public Dictionary Metadata { get; set; } + + /// + /// The ID of the query that the event originated from + /// + [JsonPropertyName("queryId")] + public string QueryId { get; set; } + + /// + /// The sequence number of the event + /// + [JsonPropertyName("sequence")] + public long Sequence { get; set; } + + /// + /// The time at which the source change was recorded + /// + [JsonPropertyName("sourceTimeMs")] + public long SourceTimeMs { get; set; } + } + + public partial class ControlSignalClass + { + [JsonPropertyName("kind")] + public ControlSignalKind Kind { get; set; } + } + + public partial class ControlSignal + { + [JsonPropertyName("kind")] + public ControlSignalKind Kind { get; set; } + } + + /// + /// A signal that indicates that the query has been deleted + /// + public partial class DeletedSignal + { + [JsonPropertyName("kind")] + public DeletedSignalKind Kind { get; set; } + } + + public partial class ResultEvent + { + [JsonPropertyName("kind")] + public ResultEventKind Kind { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("metadata")] + public Dictionary Metadata { get; set; } + + /// + /// The ID of the query that the event originated from + /// + [JsonPropertyName("queryId")] + public string QueryId { get; set; } + + /// + /// The sequence number of the event + /// + [JsonPropertyName("sequence")] + public long Sequence { get; set; } + + /// + /// The time at which the source change was recorded + /// + [JsonPropertyName("sourceTimeMs")] + public long SourceTimeMs { get; set; } + } + + /// + /// A signal that indicates that the query has entered the running state + /// + public partial class RunningSignal + { + [JsonPropertyName("kind")] + public RunningSignalKind Kind { get; set; } + } + + /// + /// A signal that indicates that the query has stopped + /// + public partial class StoppedSignal + { + [JsonPropertyName("kind")] + public StoppedSignalKind Kind { get; set; } + } + + /// + /// A payload that represents the before and after snapshots of a result + /// + public partial class UpdatePayload + { + /// + /// The snapshot of the result after the change + /// + [JsonPropertyName("after")] + public Dictionary After { get; set; } + + /// + /// The snapshot of the result before the change + /// + [JsonPropertyName("before")] + public Dictionary Before { get; set; } + } + + public enum BootstrapCompletedSignalKind { BootstrapCompleted }; + + public enum BootstrapStartedSignalKind { BootstrapStarted }; + + public enum ChangeEventKind { Change }; + + public enum ControlSignalKind { BootstrapCompleted, BootstrapStarted, Deleted, Running, Stopped }; + + public enum ControlEventKind { Control }; + + public enum DeletedSignalKind { Deleted }; + + public enum ResultEventKind { Change, Control }; + + public enum RunningSignalKind { Running }; + + public enum StoppedSignalKind { Stopped }; + + public enum VersionsEnum { V1 }; + + public partial class BootstrapCompletedSignal + { + public static BootstrapCompletedSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + } + + public partial class BootstrapStartedSignal + { + public static BootstrapStartedSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + } + + public partial class ChangeEvent + { + public static ChangeEvent FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + } + + public partial class ControlEvent + { + public static ControlEvent FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + } + + public partial class ControlSignal + { + public static ControlSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + } + + public partial class DeletedSignal + { + public static DeletedSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + } + + public partial class ResultEvent + { + public static ResultEvent FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + } + + public partial class RunningSignal + { + public static RunningSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + } + + public partial class StoppedSignal + { + public static StoppedSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + } + + public partial class UpdatePayload + { + public static UpdatePayload FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + } + + public class Versions + { + public static VersionsEnum FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + } + + public static class Serialize + { + public static string ToJson(this BootstrapCompletedSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); + public static string ToJson(this BootstrapStartedSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); + public static string ToJson(this ChangeEvent self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); + public static string ToJson(this ControlEvent self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); + public static string ToJson(this ControlSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); + public static string ToJson(this DeletedSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); + public static string ToJson(this ResultEvent self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); + public static string ToJson(this RunningSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); + public static string ToJson(this StoppedSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); + public static string ToJson(this UpdatePayload self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); + public static string ToJson(this VersionsEnum self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); + } + + internal static class Converter + { + public static readonly JsonSerializerOptions Settings = new(JsonSerializerDefaults.General) + { + Converters = + { + BootstrapCompletedSignalKindConverter.Singleton, + BootstrapStartedSignalKindConverter.Singleton, + ChangeEventKindConverter.Singleton, + ControlSignalKindConverter.Singleton, + ControlEventKindConverter.Singleton, + DeletedSignalKindConverter.Singleton, + ResultEventKindConverter.Singleton, + RunningSignalKindConverter.Singleton, + StoppedSignalKindConverter.Singleton, + VersionsEnumConverter.Singleton, + new DateOnlyConverter(), + new TimeOnlyConverter(), + IsoDateTimeOffsetConverter.Singleton + }, + }; + } + + internal class BootstrapCompletedSignalKindConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(BootstrapCompletedSignalKind); + + public override BootstrapCompletedSignalKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + if (value == "bootstrapCompleted") + { + return BootstrapCompletedSignalKind.BootstrapCompleted; + } + throw new Exception("Cannot unmarshal type BootstrapCompletedSignalKind"); + } + + public override void Write(Utf8JsonWriter writer, BootstrapCompletedSignalKind value, JsonSerializerOptions options) + { + if (value == BootstrapCompletedSignalKind.BootstrapCompleted) + { + JsonSerializer.Serialize(writer, "bootstrapCompleted", options); + return; + } + throw new Exception("Cannot marshal type BootstrapCompletedSignalKind"); + } + + public static readonly BootstrapCompletedSignalKindConverter Singleton = new BootstrapCompletedSignalKindConverter(); + } + + internal class BootstrapStartedSignalKindConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(BootstrapStartedSignalKind); + + public override BootstrapStartedSignalKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + if (value == "bootstrapStarted") + { + return BootstrapStartedSignalKind.BootstrapStarted; + } + throw new Exception("Cannot unmarshal type BootstrapStartedSignalKind"); + } + + public override void Write(Utf8JsonWriter writer, BootstrapStartedSignalKind value, JsonSerializerOptions options) + { + if (value == BootstrapStartedSignalKind.BootstrapStarted) + { + JsonSerializer.Serialize(writer, "bootstrapStarted", options); + return; + } + throw new Exception("Cannot marshal type BootstrapStartedSignalKind"); + } + + public static readonly BootstrapStartedSignalKindConverter Singleton = new BootstrapStartedSignalKindConverter(); + } + + internal class ChangeEventKindConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(ChangeEventKind); + + public override ChangeEventKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + if (value == "change") + { + return ChangeEventKind.Change; + } + throw new Exception("Cannot unmarshal type ChangeEventKind"); + } + + public override void Write(Utf8JsonWriter writer, ChangeEventKind value, JsonSerializerOptions options) + { + if (value == ChangeEventKind.Change) + { + JsonSerializer.Serialize(writer, "change", options); + return; + } + throw new Exception("Cannot marshal type ChangeEventKind"); + } + + public static readonly ChangeEventKindConverter Singleton = new ChangeEventKindConverter(); + } + + internal class ControlSignalKindConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(ControlSignalKind); + + public override ControlSignalKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + switch (value) + { + case "bootstrapCompleted": + return ControlSignalKind.BootstrapCompleted; + case "bootstrapStarted": + return ControlSignalKind.BootstrapStarted; + case "deleted": + return ControlSignalKind.Deleted; + case "running": + return ControlSignalKind.Running; + case "stopped": + return ControlSignalKind.Stopped; + } + throw new Exception("Cannot unmarshal type ControlSignalKind"); + } + + public override void Write(Utf8JsonWriter writer, ControlSignalKind value, JsonSerializerOptions options) + { + switch (value) + { + case ControlSignalKind.BootstrapCompleted: + JsonSerializer.Serialize(writer, "bootstrapCompleted", options); + return; + case ControlSignalKind.BootstrapStarted: + JsonSerializer.Serialize(writer, "bootstrapStarted", options); + return; + case ControlSignalKind.Deleted: + JsonSerializer.Serialize(writer, "deleted", options); + return; + case ControlSignalKind.Running: + JsonSerializer.Serialize(writer, "running", options); + return; + case ControlSignalKind.Stopped: + JsonSerializer.Serialize(writer, "stopped", options); + return; + } + throw new Exception("Cannot marshal type ControlSignalKind"); + } + + public static readonly ControlSignalKindConverter Singleton = new ControlSignalKindConverter(); + } + + internal class ControlEventKindConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(ControlEventKind); + + public override ControlEventKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + if (value == "control") + { + return ControlEventKind.Control; + } + throw new Exception("Cannot unmarshal type ControlEventKind"); + } + + public override void Write(Utf8JsonWriter writer, ControlEventKind value, JsonSerializerOptions options) + { + if (value == ControlEventKind.Control) + { + JsonSerializer.Serialize(writer, "control", options); + return; + } + throw new Exception("Cannot marshal type ControlEventKind"); + } + + public static readonly ControlEventKindConverter Singleton = new ControlEventKindConverter(); + } + + internal class DeletedSignalKindConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(DeletedSignalKind); + + public override DeletedSignalKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + if (value == "deleted") + { + return DeletedSignalKind.Deleted; + } + throw new Exception("Cannot unmarshal type DeletedSignalKind"); + } + + public override void Write(Utf8JsonWriter writer, DeletedSignalKind value, JsonSerializerOptions options) + { + if (value == DeletedSignalKind.Deleted) + { + JsonSerializer.Serialize(writer, "deleted", options); + return; + } + throw new Exception("Cannot marshal type DeletedSignalKind"); + } + + public static readonly DeletedSignalKindConverter Singleton = new DeletedSignalKindConverter(); + } + + internal class ResultEventKindConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(ResultEventKind); + + public override ResultEventKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + switch (value) + { + case "change": + return ResultEventKind.Change; + case "control": + return ResultEventKind.Control; + } + throw new Exception("Cannot unmarshal type ResultEventKind"); + } + + public override void Write(Utf8JsonWriter writer, ResultEventKind value, JsonSerializerOptions options) + { + switch (value) + { + case ResultEventKind.Change: + JsonSerializer.Serialize(writer, "change", options); + return; + case ResultEventKind.Control: + JsonSerializer.Serialize(writer, "control", options); + return; + } + throw new Exception("Cannot marshal type ResultEventKind"); + } + + public static readonly ResultEventKindConverter Singleton = new ResultEventKindConverter(); + } + + internal class RunningSignalKindConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(RunningSignalKind); + + public override RunningSignalKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + if (value == "running") + { + return RunningSignalKind.Running; + } + throw new Exception("Cannot unmarshal type RunningSignalKind"); + } + + public override void Write(Utf8JsonWriter writer, RunningSignalKind value, JsonSerializerOptions options) + { + if (value == RunningSignalKind.Running) + { + JsonSerializer.Serialize(writer, "running", options); + return; + } + throw new Exception("Cannot marshal type RunningSignalKind"); + } + + public static readonly RunningSignalKindConverter Singleton = new RunningSignalKindConverter(); + } + + internal class StoppedSignalKindConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(StoppedSignalKind); + + public override StoppedSignalKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + if (value == "stopped") + { + return StoppedSignalKind.Stopped; + } + throw new Exception("Cannot unmarshal type StoppedSignalKind"); + } + + public override void Write(Utf8JsonWriter writer, StoppedSignalKind value, JsonSerializerOptions options) + { + if (value == StoppedSignalKind.Stopped) + { + JsonSerializer.Serialize(writer, "stopped", options); + return; + } + throw new Exception("Cannot marshal type StoppedSignalKind"); + } + + public static readonly StoppedSignalKindConverter Singleton = new StoppedSignalKindConverter(); + } + + internal class VersionsEnumConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(VersionsEnum); + + public override VersionsEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + if (value == "v1") + { + return VersionsEnum.V1; + } + throw new Exception("Cannot unmarshal type VersionsEnum"); + } + + public override void Write(Utf8JsonWriter writer, VersionsEnum value, JsonSerializerOptions options) + { + if (value == VersionsEnum.V1) + { + JsonSerializer.Serialize(writer, "v1", options); + return; + } + throw new Exception("Cannot marshal type VersionsEnum"); + } + + public static readonly VersionsEnumConverter Singleton = new VersionsEnumConverter(); + } + + public class DateOnlyConverter : JsonConverter + { + private readonly string serializationFormat; + public DateOnlyConverter() : this(null) { } + + public DateOnlyConverter(string? serializationFormat) + { + this.serializationFormat = serializationFormat ?? "yyyy-MM-dd"; + } + + public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + return DateOnly.Parse(value!); + } + + public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options) + => writer.WriteStringValue(value.ToString(serializationFormat)); + } + + public class TimeOnlyConverter : JsonConverter + { + private readonly string serializationFormat; + + public TimeOnlyConverter() : this(null) { } + + public TimeOnlyConverter(string? serializationFormat) + { + this.serializationFormat = serializationFormat ?? "HH:mm:ss.fff"; + } + + public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + return TimeOnly.Parse(value!); + } + + public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options) + => writer.WriteStringValue(value.ToString(serializationFormat)); + } + + internal class IsoDateTimeOffsetConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(DateTimeOffset); + + private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; + + private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind; + private string? _dateTimeFormat; + private CultureInfo? _culture; + + public DateTimeStyles DateTimeStyles + { + get => _dateTimeStyles; + set => _dateTimeStyles = value; + } + + public string? DateTimeFormat + { + get => _dateTimeFormat ?? string.Empty; + set => _dateTimeFormat = (string.IsNullOrEmpty(value)) ? null : value; + } + + public CultureInfo Culture + { + get => _culture ?? CultureInfo.CurrentCulture; + set => _culture = value; + } + + public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) + { + string text; + + + if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal + || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) + { + value = value.ToUniversalTime(); + } + + text = value.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture); + + writer.WriteStringValue(text); + } + + public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + string? dateText = reader.GetString(); + + if (string.IsNullOrEmpty(dateText) == false) + { + if (!string.IsNullOrEmpty(_dateTimeFormat)) + { + return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles); + } + else + { + return DateTimeOffset.Parse(dateText, Culture, _dateTimeStyles); + } + } + else + { + return default(DateTimeOffset); + } + } + + + public static readonly IsoDateTimeOffsetConverter Singleton = new IsoDateTimeOffsetConverter(); + } +} +#pragma warning restore CS8618 +#pragma warning restore CS8601 +#pragma warning restore CS8603 diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs new file mode 100644 index 00000000..3d277bd4 --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs @@ -0,0 +1,6 @@ +namespace Drasi.Reaction.SDK; + +public class Reaction +{ + +} diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.csproj b/reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.csproj new file mode 100644 index 00000000..56607968 --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + Drasi.Reaction.SDK + enable + enable + + + + + + + diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.sln b/reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.sln new file mode 100644 index 00000000..d96bd4d6 --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.002.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "drasi-reaction-sdk", "drasi-reaction-sdk.csproj", "{E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D9F15981-EA51-4A5A-B943-5691552B8081} + EndGlobalSection +EndGlobal diff --git a/typespec/notes.md b/typespec/notes.md index 9337b558..c63fe5a3 100644 --- a/typespec/notes.md +++ b/typespec/notes.md @@ -1,2 +1,9 @@ json2ts -i ./reaction/_generated/@typespec/json-schema -o types/ --cwd ./reaction/_generated/@typespec/json-schema -- declareExternallyReferenced false + + +dotnet tool install -g NJsonSchema.CodeGeneration.CSharp + +quicktype --src-lang schema -l typescript -o output.ts ./query-output/_generated/@typespec/json-schema/*.yaml + +quicktype --src-lang schema -l cs -o output.cs ./query-output/_generated/@typespec/json-schema/*.yaml --framework SystemTextJson --namespace Drasi.Reaction.SDK.Models diff --git a/typespec/query-output/main.tsp b/typespec/query-output/main.tsp index 6df547f0..fec4c48c 100644 --- a/typespec/query-output/main.tsp +++ b/typespec/query-output/main.tsp @@ -16,6 +16,7 @@ enum Versions { @discriminator("kind") @extension("title", "ResultEvent") model ResultEvent { + kind: "change" | "control"; @doc("The ID of the query that the event originated from") queryId: string; @@ -25,7 +26,7 @@ model ResultEvent { @doc("The time at which the source change was recorded") sourceTimeMs: int64; - + metadata?: Record } @@ -64,6 +65,7 @@ model ControlEvent extends ResultEvent { @discriminator("kind") @extension("title", "ControlSignal") model ControlSignal { + kind: "bootstrapStarted" | "bootstrapCompleted" | "running" | "stopped" | "deleted"; } @extension("title", "BootstrapStartedSignal") diff --git a/typespec/query-output/tspconfig.yaml b/typespec/query-output/tspconfig.yaml index 498150b8..a76dcc14 100644 --- a/typespec/query-output/tspconfig.yaml +++ b/typespec/query-output/tspconfig.yaml @@ -19,5 +19,6 @@ emit: options: "@typespec/json-schema": file-type: "yaml" + int64-strategy: "number" output-dir: "{project-root}/_generated" # Configure the base output directory for all emitters \ No newline at end of file From 2fb83d385a2762bf78e6e0e7115ad7185e66163f Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 1 Nov 2024 20:53:26 -0700 Subject: [PATCH 08/17] dotnet reaction sdk --- .../sdk/dotnet/drasi-reaction-sdk/.gitignore | 6 +- .../sdk/dotnet/drasi-reaction-sdk/Reaction.cs | 71 ++++++++++++++++++- .../drasi-reaction-sdk/ReactionBuilder.cs | 62 ++++++++++++++++ .../Services/DefaultControlEventHandler.cs | 17 +++++ .../Services/IChangeEventHandler.cs | 14 ++++ .../Services/IConfigDeserializer.cs | 7 ++ .../Services/IControlEventHandler.cs | 14 ++++ .../Services/IQueryConfigService.cs | 9 +++ .../Services/JsonConfigDeserializer.cs | 20 ++++++ .../Services/NullConfigDeserializer.cs | 17 +++++ .../Services/QueryConfigService.cs | 23 ++++++ .../Services/YamlConfigDeserializer.cs | 56 +++++++++++++++ 12 files changed, 313 insertions(+), 3 deletions(-) create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/ReactionBuilder.cs create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Services/DefaultControlEventHandler.cs create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Services/IChangeEventHandler.cs create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Services/IConfigDeserializer.cs create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Services/IControlEventHandler.cs create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Services/IQueryConfigService.cs create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Services/JsonConfigDeserializer.cs create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Services/NullConfigDeserializer.cs create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Services/QueryConfigService.cs create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Services/YamlConfigDeserializer.cs diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/.gitignore b/reactions/sdk/dotnet/drasi-reaction-sdk/.gitignore index 8d4a6c08..1049fdc8 100644 --- a/reactions/sdk/dotnet/drasi-reaction-sdk/.gitignore +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/.gitignore @@ -1,2 +1,6 @@ bin -obj \ No newline at end of file +obj +CopilotIndices +DesignTimeBuild +FileContentIndex +v17 \ No newline at end of file diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs index 3d277bd4..168258f7 100644 --- a/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs @@ -1,6 +1,73 @@ -namespace Drasi.Reaction.SDK; +using Drasi.Reaction.SDK.Models; +using Drasi.Reaction.SDK.Services; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System.Text.Json; -public class Reaction +namespace Drasi.Reaction.SDK; + +public class Reaction : IHost + where TQueryConfig : class { + private readonly WebApplication _app; + private readonly Dictionary _queriesConfig; + + public IServiceProvider Services => _app.Services; + + internal Reaction(IQueryConfigService queryConfigService, WebApplication app) + { + _app = app; + _queriesConfig = []; + var pubsubName = Environment.GetEnvironmentVariable("PubsubName") ?? "drasi-pubsub"; + + var handler = app.MapPost("event", this.ProcessEvent); + + foreach (var name in queryConfigService.GetQueryNames()) + { + var config = queryConfigService.GetQueryConfig(name); + _queriesConfig.Add(name, config); + handler.WithTopic(pubsubName, name + "-results"); + }; + } + public async Task StartAsync(CancellationToken cancellationToken = default) + { + await _app.RunAsync("http://0.0.0.0:80"); + } + + public async Task StopAsync(CancellationToken cancellationToken = default) + { + await _app.StopAsync(cancellationToken); + } + + public void Dispose() + { + + } + + private async Task ProcessEvent(HttpContext context, IChangeEventHandler changeHandler, IControlEventHandler controlEventHandler) + { + var data = await JsonDocument.ParseAsync(context.Request.Body); + var evt = data.RootElement; + switch (evt.GetProperty("kind").GetString()) + { + case "change": + var changeEvt = evt.Deserialize(); + var queryCfg = _queriesConfig.GetValueOrDefault(changeEvt.QueryId, null); + changeHandler.HandleChange(changeEvt, queryCfg); + break; + case "control": + var controlEvt = evt.Deserialize(); + var queryCfg2 = _queriesConfig.GetValueOrDefault(controlEvt.QueryId, null); + controlEventHandler.HandleControlSignal(controlEvt, queryCfg2); + break; + default: + break; + } + + context.Response.StatusCode = 200; + } } + diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/ReactionBuilder.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/ReactionBuilder.cs new file mode 100644 index 00000000..cc2b7fb1 --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/ReactionBuilder.cs @@ -0,0 +1,62 @@ +using System; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Drasi.Reaction.SDK.Services; + +namespace Drasi.Reaction.SDK +{ + public class ReactionBuilder + { + private readonly WebApplicationBuilder _webappBuilder; + + public IServiceCollection Services => _webappBuilder.Services; + + public ReactionBuilder() + { + _webappBuilder = WebApplication.CreateBuilder(); + _webappBuilder.Services.AddDaprClient(); + _webappBuilder.Services.AddControllers(); + _webappBuilder.Services.AddSingleton(); + _webappBuilder.Services.AddSingleton(); + _webappBuilder.Services.AddSingleton(); + } + + public void UseChangeEventHandler() where TChangeEventHandler : class, IChangeEventHandler + { + _webappBuilder.Services.AddSingleton(); + } + + public void UseControlEventHandler() where TControlEventHandler : class, IControlEventHandler + { + _webappBuilder.Services.AddSingleton(); + } + + public void UseJsonQueryConfig() + { + _webappBuilder.Services.AddSingleton(); + } + + public void UseYamlQueryConfig() + { + _webappBuilder.Services.AddSingleton(); + } + + public Reaction Build() where TQueryConfig : class + { + var hasChangeHandler = _webappBuilder.Services.Any(x => x.ServiceType == typeof(IChangeEventHandler)); + if (!hasChangeHandler) + { + throw new InvalidOperationException("No change event handler registered"); + } + + var app = _webappBuilder.Build(); + app.UseRouting(); + app.UseCloudEvents(); + app.MapSubscribeHandler(); + + var queryConfigSvc = app.Services.GetRequiredService(); + + return new Reaction(queryConfigSvc, app); + } + } +} diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/DefaultControlEventHandler.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/DefaultControlEventHandler.cs new file mode 100644 index 00000000..9e79e15a --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/DefaultControlEventHandler.cs @@ -0,0 +1,17 @@ +using Drasi.Reaction.SDK.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Drasi.Reaction.SDK.Services +{ + internal class DefaultControlEventHandler : IControlEventHandler + { + public void HandleControlSignal(ControlEvent evt, TQueryConfig? queryConfig) where TQueryConfig : class + { + } + + } +} diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IChangeEventHandler.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IChangeEventHandler.cs new file mode 100644 index 00000000..4e8a5628 --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IChangeEventHandler.cs @@ -0,0 +1,14 @@ +using Drasi.Reaction.SDK.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Drasi.Reaction.SDK.Services +{ + public interface IChangeEventHandler + { + void HandleChange(ChangeEvent evt, TQueryConfig? queryConfig) where TQueryConfig : class; + } +} diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IConfigDeserializer.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IConfigDeserializer.cs new file mode 100644 index 00000000..91ed585e --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IConfigDeserializer.cs @@ -0,0 +1,7 @@ +namespace Drasi.Reaction.SDK.Services +{ + public interface IConfigDeserializer + { + T? Deserialize(string data) where T : class; + } +} \ No newline at end of file diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IControlEventHandler.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IControlEventHandler.cs new file mode 100644 index 00000000..319378cf --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IControlEventHandler.cs @@ -0,0 +1,14 @@ +using Drasi.Reaction.SDK.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Drasi.Reaction.SDK.Services +{ + public interface IControlEventHandler + { + void HandleControlSignal(ControlEvent evt, TQueryConfig? queryConfig) where TQueryConfig : class; + } +} diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IQueryConfigService.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IQueryConfigService.cs new file mode 100644 index 00000000..5de040b7 --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IQueryConfigService.cs @@ -0,0 +1,9 @@ + +namespace Drasi.Reaction.SDK.Services +{ + public interface IQueryConfigService + { + T? GetQueryConfig(string queryName) where T : class; + List GetQueryNames(); + } +} \ No newline at end of file diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/JsonConfigDeserializer.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/JsonConfigDeserializer.cs new file mode 100644 index 00000000..a8578691 --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/JsonConfigDeserializer.cs @@ -0,0 +1,20 @@ +using System; +using System.Text.Json; + +namespace Drasi.Reaction.SDK.Services +{ + public class JsonConfigDeserializer : IConfigDeserializer + { + public JsonConfigDeserializer() + { + } + + public T? Deserialize(string data) where T : class + { + var jsonDoc = JsonDocument.Parse(data); + var result = jsonDoc.Deserialize(); + + return result; + } + } +} diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/NullConfigDeserializer.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/NullConfigDeserializer.cs new file mode 100644 index 00000000..392880eb --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/NullConfigDeserializer.cs @@ -0,0 +1,17 @@ +using System; +using System.Text.Json; + +namespace Drasi.Reaction.SDK.Services +{ + public class NullConfigDeserializer : IConfigDeserializer + { + public NullConfigDeserializer() + { + } + + public T? Deserialize(string data) where T : class + { + return null; + } + } +} diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/QueryConfigService.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/QueryConfigService.cs new file mode 100644 index 00000000..3e9f2418 --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/QueryConfigService.cs @@ -0,0 +1,23 @@ +using System; + +namespace Drasi.Reaction.SDK.Services +{ + internal class QueryConfigService(IConfigDeserializer configDeserializer) : IQueryConfigService + { + private readonly string _configDirectory = Environment.GetEnvironmentVariable("QueryConfigPath") ?? "/etc/queries"; + private readonly IConfigDeserializer _configDeserializer = configDeserializer; + + public List GetQueryNames() + { + return Directory.GetFiles(_configDirectory) + .Select(x => Path.GetFileName(x)) + .ToList(); + } + + public T? GetQueryConfig(string queryName) where T : class + { + var data = File.ReadAllText($"{_configDirectory}/{queryName}"); + return _configDeserializer.Deserialize(data); + } + } +} diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/YamlConfigDeserializer.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/YamlConfigDeserializer.cs new file mode 100644 index 00000000..34313273 --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/YamlConfigDeserializer.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using YamlDotNet.Serialization; +using YamlDotNet.Core.Events; +using System.IO; +using System.Text.Json; + +namespace Drasi.Reaction.SDK.Services +{ + public class YamlConfigDeserializer : IConfigDeserializer + { + private readonly IDeserializer _yamlDeserializer; + private readonly ISerializer _yamlJsonSerializer; + + public YamlConfigDeserializer() + { + _yamlDeserializer = new DeserializerBuilder() + .WithNodeTypeResolver(new InferTypeFromValue()) + .Build(); + + _yamlJsonSerializer = new SerializerBuilder() + .JsonCompatible() + .Build(); + } + + public T? Deserialize(string data) where T : class + { + var yamlObject = _yamlDeserializer.Deserialize(data); + var specJson = _yamlJsonSerializer.Serialize(yamlObject); + var result = JsonSerializer.Deserialize(specJson); + + return result; + } + } + + internal class InferTypeFromValue : INodeTypeResolver + { + public bool Resolve(NodeEvent nodeEvent, ref Type currentType) + { + var scalar = nodeEvent as Scalar; + if (scalar != null) + { + int value; + if (int.TryParse(scalar.Value, out value)) + { + currentType = typeof(int); + return true; + } + } + return false; + } + } +} From 8e7f3b8eedf500a10e5ea68726081e53ba140ad9 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 2 Nov 2024 16:33:56 -0700 Subject: [PATCH 09/17] wip --- reactions/sdk/dotnet/.dockerignore | 30 +++++++++++++ reactions/sdk/dotnet/.gitignore | 1 + reactions/sdk/dotnet/drasi-reaction-sdk.sln | 43 +++++++++++++++++++ .../drasi-reaction-sdk/IChangeEventHandler.cs | 14 ++++++ .../IControlEventHandler.cs | 14 ++++++ .../sdk/dotnet/drasi-reaction-sdk/Reaction.cs | 11 ++--- .../drasi-reaction-sdk/ReactionBuilder.cs | 33 ++++++++++---- .../Services/DefaultControlEventHandler.cs | 9 +++- .../Services/IChangeEventHandler.cs | 14 ------ .../Services/IControlEventHandler.cs | 14 ------ .../Services/InlineChangeEventHandler.cs | 24 +++++++++++ .../drasi-reaction-sdk.csproj | 4 +- .../drasi-reaction-sdk/drasi-reaction-sdk.sln | 25 ----------- .../examples/advanced-reaction/.gitignore | 6 +++ .../examples/advanced-reaction/Dockerfile | 29 +++++++++++++ .../examples/advanced-reaction/Program.cs | 26 +++++++++++ .../Properties/launchSettings.json | 39 +++++++++++++++++ .../advanced-reaction.csproj | 16 +++++++ .../advanced-reaction.csproj.user | 6 +++ .../appsettings.Development.json | 8 ++++ .../advanced-reaction/appsettings.json | 9 ++++ .../examples/simple-reaction/.gitignore | 6 +++ .../examples/simple-reaction/Dockerfile | 29 +++++++++++++ .../examples/simple-reaction/Program.cs | 13 ++++++ .../Properties/launchSettings.json | 39 +++++++++++++++++ .../appsettings.Development.json | 8 ++++ .../examples/simple-reaction/appsettings.json | 9 ++++ .../simple-reaction/simple-reaction.csproj | 20 +++++++++ .../simple-reaction.csproj.user | 6 +++ 29 files changed, 436 insertions(+), 69 deletions(-) create mode 100644 reactions/sdk/dotnet/.dockerignore create mode 100644 reactions/sdk/dotnet/.gitignore create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk.sln create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/IChangeEventHandler.cs create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/IControlEventHandler.cs delete mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Services/IChangeEventHandler.cs delete mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Services/IControlEventHandler.cs create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Services/InlineChangeEventHandler.cs delete mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.sln create mode 100644 reactions/sdk/dotnet/examples/advanced-reaction/.gitignore create mode 100644 reactions/sdk/dotnet/examples/advanced-reaction/Dockerfile create mode 100644 reactions/sdk/dotnet/examples/advanced-reaction/Program.cs create mode 100644 reactions/sdk/dotnet/examples/advanced-reaction/Properties/launchSettings.json create mode 100644 reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj create mode 100644 reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj.user create mode 100644 reactions/sdk/dotnet/examples/advanced-reaction/appsettings.Development.json create mode 100644 reactions/sdk/dotnet/examples/advanced-reaction/appsettings.json create mode 100644 reactions/sdk/dotnet/examples/simple-reaction/.gitignore create mode 100644 reactions/sdk/dotnet/examples/simple-reaction/Dockerfile create mode 100644 reactions/sdk/dotnet/examples/simple-reaction/Program.cs create mode 100644 reactions/sdk/dotnet/examples/simple-reaction/Properties/launchSettings.json create mode 100644 reactions/sdk/dotnet/examples/simple-reaction/appsettings.Development.json create mode 100644 reactions/sdk/dotnet/examples/simple-reaction/appsettings.json create mode 100644 reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj create mode 100644 reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj.user diff --git a/reactions/sdk/dotnet/.dockerignore b/reactions/sdk/dotnet/.dockerignore new file mode 100644 index 00000000..4d72b4f9 --- /dev/null +++ b/reactions/sdk/dotnet/.dockerignore @@ -0,0 +1,30 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md +!**/.gitignore +!.git/HEAD +!.git/config +!.git/packed-refs +!.git/refs/heads/** \ No newline at end of file diff --git a/reactions/sdk/dotnet/.gitignore b/reactions/sdk/dotnet/.gitignore new file mode 100644 index 00000000..0a343817 --- /dev/null +++ b/reactions/sdk/dotnet/.gitignore @@ -0,0 +1 @@ +.vs \ No newline at end of file diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk.sln b/reactions/sdk/dotnet/drasi-reaction-sdk.sln new file mode 100644 index 00000000..63b1a5fd --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.002.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "drasi-reaction-sdk", "drasi-reaction-sdk\drasi-reaction-sdk.csproj", "{E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{561184F7-D4CC-4392-934F-C725FE595D4C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "simple-reaction", "examples\simple-reaction\simple-reaction.csproj", "{AF6F510D-FCBD-4F18-8D1F-F1ED0261A979}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "advanced-reaction", "examples\advanced-reaction\advanced-reaction.csproj", "{FA13C8A9-8513-4985-897F-F728C79C4DAC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}.Release|Any CPU.Build.0 = Release|Any CPU + {AF6F510D-FCBD-4F18-8D1F-F1ED0261A979}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AF6F510D-FCBD-4F18-8D1F-F1ED0261A979}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AF6F510D-FCBD-4F18-8D1F-F1ED0261A979}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AF6F510D-FCBD-4F18-8D1F-F1ED0261A979}.Release|Any CPU.Build.0 = Release|Any CPU + {FA13C8A9-8513-4985-897F-F728C79C4DAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FA13C8A9-8513-4985-897F-F728C79C4DAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FA13C8A9-8513-4985-897F-F728C79C4DAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FA13C8A9-8513-4985-897F-F728C79C4DAC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {AF6F510D-FCBD-4F18-8D1F-F1ED0261A979} = {561184F7-D4CC-4392-934F-C725FE595D4C} + {FA13C8A9-8513-4985-897F-F728C79C4DAC} = {561184F7-D4CC-4392-934F-C725FE595D4C} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D9F15981-EA51-4A5A-B943-5691552B8081} + EndGlobalSection +EndGlobal diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/IChangeEventHandler.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/IChangeEventHandler.cs new file mode 100644 index 00000000..3f8a75b9 --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/IChangeEventHandler.cs @@ -0,0 +1,14 @@ +using Drasi.Reaction.SDK.Models; +using System; + +namespace Drasi.Reaction.SDK +{ + public interface IChangeEventHandler : IChangeEventHandler + { + } + + public interface IChangeEventHandler where TQueryConfig : class + { + Task HandleChange(ChangeEvent evt, TQueryConfig? queryConfig); + } +} diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/IControlEventHandler.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/IControlEventHandler.cs new file mode 100644 index 00000000..1a852738 --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/IControlEventHandler.cs @@ -0,0 +1,14 @@ +using Drasi.Reaction.SDK.Models; +using System; + +namespace Drasi.Reaction.SDK +{ + public interface IControlEventHandler : IControlEventHandler + { + } + + public interface IControlEventHandler where TQueryConfig : class + { + Task HandleControlSignal(ControlEvent evt, TQueryConfig? queryConfig); + } +} diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs index 168258f7..ec2c0f9c 100644 --- a/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs @@ -2,7 +2,7 @@ using Drasi.Reaction.SDK.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using System.Text.Json; @@ -15,10 +15,11 @@ public class Reaction : IHost private readonly Dictionary _queriesConfig; public IServiceProvider Services => _app.Services; + public IConfiguration Configuration => _app.Configuration; internal Reaction(IQueryConfigService queryConfigService, WebApplication app) { - _app = app; + _app = app; _queriesConfig = []; var pubsubName = Environment.GetEnvironmentVariable("PubsubName") ?? "drasi-pubsub"; @@ -47,7 +48,7 @@ public void Dispose() } - private async Task ProcessEvent(HttpContext context, IChangeEventHandler changeHandler, IControlEventHandler controlEventHandler) + private async Task ProcessEvent(HttpContext context, IChangeEventHandler changeHandler, IControlEventHandler controlEventHandler) { var data = await JsonDocument.ParseAsync(context.Request.Body); var evt = data.RootElement; @@ -56,12 +57,12 @@ private async Task ProcessEvent(HttpContext context, IChangeEventHandler changeH case "change": var changeEvt = evt.Deserialize(); var queryCfg = _queriesConfig.GetValueOrDefault(changeEvt.QueryId, null); - changeHandler.HandleChange(changeEvt, queryCfg); + await changeHandler.HandleChange(changeEvt, queryCfg); break; case "control": var controlEvt = evt.Deserialize(); var queryCfg2 = _queriesConfig.GetValueOrDefault(controlEvt.QueryId, null); - controlEventHandler.HandleControlSignal(controlEvt, queryCfg2); + await controlEventHandler.HandleControlSignal(controlEvt, queryCfg2); break; default: break; diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/ReactionBuilder.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/ReactionBuilder.cs index cc2b7fb1..6281c8c9 100644 --- a/reactions/sdk/dotnet/drasi-reaction-sdk/ReactionBuilder.cs +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/ReactionBuilder.cs @@ -2,15 +2,24 @@ using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Drasi.Reaction.SDK.Services; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using Drasi.Reaction.SDK.Models; namespace Drasi.Reaction.SDK { - public class ReactionBuilder + public class ReactionBuilder : ReactionBuilder + { + } + + public class ReactionBuilder where TQueryConfig : class { private readonly WebApplicationBuilder _webappBuilder; public IServiceCollection Services => _webappBuilder.Services; + public IConfiguration Configuration => _webappBuilder.Configuration; + public ReactionBuilder() { _webappBuilder = WebApplication.CreateBuilder(); @@ -18,17 +27,24 @@ public ReactionBuilder() _webappBuilder.Services.AddControllers(); _webappBuilder.Services.AddSingleton(); _webappBuilder.Services.AddSingleton(); - _webappBuilder.Services.AddSingleton(); + _webappBuilder.Services.AddScoped, DefaultControlEventHandler>(); + _webappBuilder.Configuration.AddEnvironmentVariables(); + _webappBuilder.Logging.AddConsole(); } - public void UseChangeEventHandler() where TChangeEventHandler : class, IChangeEventHandler + public void UseChangeEventHandler() where TChangeEventHandler : class, IChangeEventHandler { - _webappBuilder.Services.AddSingleton(); + _webappBuilder.Services.AddScoped, TChangeEventHandler>(); } - public void UseControlEventHandler() where TControlEventHandler : class, IControlEventHandler + public void UseChangeEventHandler(Func handler) { - _webappBuilder.Services.AddSingleton(); + _webappBuilder.Services.AddScoped>((sp) => new InlineChangeEventHandler(handler)); + } + + public void UseControlEventHandler() where TControlEventHandler : class, IControlEventHandler + { + _webappBuilder.Services.AddScoped, TControlEventHandler>(); } public void UseJsonQueryConfig() @@ -41,9 +57,9 @@ public void UseYamlQueryConfig() _webappBuilder.Services.AddSingleton(); } - public Reaction Build() where TQueryConfig : class + public Reaction Build() { - var hasChangeHandler = _webappBuilder.Services.Any(x => x.ServiceType == typeof(IChangeEventHandler)); + var hasChangeHandler = _webappBuilder.Services.Any(x => x.ServiceType == typeof(IChangeEventHandler)); if (!hasChangeHandler) { throw new InvalidOperationException("No change event handler registered"); @@ -58,5 +74,6 @@ public Reaction Build() where TQueryConfig : class return new Reaction(queryConfigSvc, app); } + } } diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/DefaultControlEventHandler.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/DefaultControlEventHandler.cs index 9e79e15a..835dec57 100644 --- a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/DefaultControlEventHandler.cs +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/DefaultControlEventHandler.cs @@ -1,4 +1,5 @@ using Drasi.Reaction.SDK.Models; +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; @@ -7,10 +8,14 @@ namespace Drasi.Reaction.SDK.Services { - internal class DefaultControlEventHandler : IControlEventHandler + internal class DefaultControlEventHandler(ILogger> logger) : IControlEventHandler where T : class { - public void HandleControlSignal(ControlEvent evt, TQueryConfig? queryConfig) where TQueryConfig : class + private readonly ILogger> _logger = logger; + + public Task HandleControlSignal(ControlEvent evt, T? queryConfig) { + _logger.LogInformation("Received control signal: {ControlEvent}", evt?.ControlSignal?.Kind); + return Task.CompletedTask; } } diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IChangeEventHandler.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IChangeEventHandler.cs deleted file mode 100644 index 4e8a5628..00000000 --- a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IChangeEventHandler.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Drasi.Reaction.SDK.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Drasi.Reaction.SDK.Services -{ - public interface IChangeEventHandler - { - void HandleChange(ChangeEvent evt, TQueryConfig? queryConfig) where TQueryConfig : class; - } -} diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IControlEventHandler.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IControlEventHandler.cs deleted file mode 100644 index 319378cf..00000000 --- a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IControlEventHandler.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Drasi.Reaction.SDK.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Drasi.Reaction.SDK.Services -{ - public interface IControlEventHandler - { - void HandleControlSignal(ControlEvent evt, TQueryConfig? queryConfig) where TQueryConfig : class; - } -} diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/InlineChangeEventHandler.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/InlineChangeEventHandler.cs new file mode 100644 index 00000000..0861ddcf --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/InlineChangeEventHandler.cs @@ -0,0 +1,24 @@ +using Drasi.Reaction.SDK.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Drasi.Reaction.SDK.Services +{ + internal class InlineChangeEventHandler : IChangeEventHandler where T : class + { + private readonly Func _handler; + + public InlineChangeEventHandler(Func handler) + { + _handler = handler; + } + + public Task HandleChange(ChangeEvent evt, T? queryConfig) + { + return _handler(evt, queryConfig as T); + } + } +} diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.csproj b/reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.csproj index 56607968..02b91985 100644 --- a/reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.csproj +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.csproj @@ -8,7 +8,9 @@ - + + + diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.sln b/reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.sln deleted file mode 100644 index d96bd4d6..00000000 --- a/reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.5.002.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "drasi-reaction-sdk", "drasi-reaction-sdk.csproj", "{E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {D9F15981-EA51-4A5A-B943-5691552B8081} - EndGlobalSection -EndGlobal diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/.gitignore b/reactions/sdk/dotnet/examples/advanced-reaction/.gitignore new file mode 100644 index 00000000..1049fdc8 --- /dev/null +++ b/reactions/sdk/dotnet/examples/advanced-reaction/.gitignore @@ -0,0 +1,6 @@ +bin +obj +CopilotIndices +DesignTimeBuild +FileContentIndex +v17 \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/Dockerfile b/reactions/sdk/dotnet/examples/advanced-reaction/Dockerfile new file mode 100644 index 00000000..05913e65 --- /dev/null +++ b/reactions/sdk/dotnet/examples/advanced-reaction/Dockerfile @@ -0,0 +1,29 @@ +# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. + +# This stage is used when running from VS in fast mode (Default for Debug configuration) +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER app +WORKDIR /app +EXPOSE 8080 + + +# This stage is used to build the service project +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["examples/advanced-reaction/advanced-reaction.csproj", "examples/advanced-reaction/"] +RUN dotnet restore "./examples/advanced-reaction/advanced-reaction.csproj" +COPY . . +WORKDIR "/src/examples/advanced-reaction" +RUN dotnet build "./advanced-reaction.csproj" -c $BUILD_CONFIGURATION -o /app/build + +# This stage is used to publish the service project to be copied to the final stage +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./advanced-reaction.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration) +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "advanced-reaction.dll"] \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/Program.cs b/reactions/sdk/dotnet/examples/advanced-reaction/Program.cs new file mode 100644 index 00000000..b016e55a --- /dev/null +++ b/reactions/sdk/dotnet/examples/advanced-reaction/Program.cs @@ -0,0 +1,26 @@ + +using Drasi.Reaction.SDK; +using Drasi.Reaction.SDK.Models; + +var builder = new ReactionBuilder(); +builder.UseChangeEventHandler(); + +var reaction = builder.Build(); + +await reaction.StartAsync(); + + +class MyChangeHandler : IChangeEventHandler +{ + private readonly ILogger _logger; + + public MyChangeHandler(ILogger logger) + { + _logger = logger; + } + + public async Task HandleChange(ChangeEvent evt, object? queryConfig) + { + _logger.LogInformation($"Received change event: {evt}"); + } +} \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/Properties/launchSettings.json b/reactions/sdk/dotnet/examples/advanced-reaction/Properties/launchSettings.json new file mode 100644 index 00000000..3292538e --- /dev/null +++ b/reactions/sdk/dotnet/examples/advanced-reaction/Properties/launchSettings.json @@ -0,0 +1,39 @@ +{ + "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5163" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Container (Dockerfile)": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}", + "environmentVariables": { + "ASPNETCORE_HTTP_PORTS": "8080" + }, + "publishAllPorts": true, + "useSSL": false + } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:15167", + "sslPort": 0 + } + } +} \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj b/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj new file mode 100644 index 00000000..7bfbfeda --- /dev/null +++ b/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + enable + advanced_reaction + Linux + ..\.. + + + + + + + diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj.user b/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj.user new file mode 100644 index 00000000..4f592401 --- /dev/null +++ b/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj.user @@ -0,0 +1,6 @@ + + + + Container (Dockerfile) + + \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/appsettings.Development.json b/reactions/sdk/dotnet/examples/advanced-reaction/appsettings.Development.json new file mode 100644 index 00000000..ff66ba6b --- /dev/null +++ b/reactions/sdk/dotnet/examples/advanced-reaction/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/appsettings.json b/reactions/sdk/dotnet/examples/advanced-reaction/appsettings.json new file mode 100644 index 00000000..4d566948 --- /dev/null +++ b/reactions/sdk/dotnet/examples/advanced-reaction/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/reactions/sdk/dotnet/examples/simple-reaction/.gitignore b/reactions/sdk/dotnet/examples/simple-reaction/.gitignore new file mode 100644 index 00000000..1049fdc8 --- /dev/null +++ b/reactions/sdk/dotnet/examples/simple-reaction/.gitignore @@ -0,0 +1,6 @@ +bin +obj +CopilotIndices +DesignTimeBuild +FileContentIndex +v17 \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/simple-reaction/Dockerfile b/reactions/sdk/dotnet/examples/simple-reaction/Dockerfile new file mode 100644 index 00000000..81916b5b --- /dev/null +++ b/reactions/sdk/dotnet/examples/simple-reaction/Dockerfile @@ -0,0 +1,29 @@ +# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. + +# This stage is used when running from VS in fast mode (Default for Debug configuration) +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER app +WORKDIR /app +EXPOSE 8080 + + +# This stage is used to build the service project +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["examples/simple-reaction/simple-reaction.csproj", "examples/simple-reaction/"] +RUN dotnet restore "./examples/simple-reaction/simple-reaction.csproj" +COPY . . +WORKDIR "/src/examples/simple-reaction" +RUN dotnet build "./simple-reaction.csproj" -c $BUILD_CONFIGURATION -o /app/build + +# This stage is used to publish the service project to be copied to the final stage +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./simple-reaction.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration) +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "simple-reaction.dll"] \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/simple-reaction/Program.cs b/reactions/sdk/dotnet/examples/simple-reaction/Program.cs new file mode 100644 index 00000000..624744cd --- /dev/null +++ b/reactions/sdk/dotnet/examples/simple-reaction/Program.cs @@ -0,0 +1,13 @@ + + +using Drasi.Reaction.SDK; + +var builder = new ReactionBuilder(); +builder.UseChangeEventHandler(async (evt, queryConfig) => +{ + Console.WriteLine($"Received change event: {evt}"); +}); + +var reaction = builder.Build(); + +await reaction.StartAsync(); \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/simple-reaction/Properties/launchSettings.json b/reactions/sdk/dotnet/examples/simple-reaction/Properties/launchSettings.json new file mode 100644 index 00000000..3e35de47 --- /dev/null +++ b/reactions/sdk/dotnet/examples/simple-reaction/Properties/launchSettings.json @@ -0,0 +1,39 @@ +{ + "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5106" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Container (Dockerfile)": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}", + "environmentVariables": { + "ASPNETCORE_HTTP_PORTS": "8080" + }, + "publishAllPorts": true, + "useSSL": false + } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:18595", + "sslPort": 0 + } + } +} \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/simple-reaction/appsettings.Development.json b/reactions/sdk/dotnet/examples/simple-reaction/appsettings.Development.json new file mode 100644 index 00000000..ff66ba6b --- /dev/null +++ b/reactions/sdk/dotnet/examples/simple-reaction/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/reactions/sdk/dotnet/examples/simple-reaction/appsettings.json b/reactions/sdk/dotnet/examples/simple-reaction/appsettings.json new file mode 100644 index 00000000..4d566948 --- /dev/null +++ b/reactions/sdk/dotnet/examples/simple-reaction/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj b/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj new file mode 100644 index 00000000..47703c3c --- /dev/null +++ b/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj @@ -0,0 +1,20 @@ + + + + net8.0 + enable + enable + simple_reaction + Linux + ..\.. + + + + + + + + + + + diff --git a/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj.user b/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj.user new file mode 100644 index 00000000..4f592401 --- /dev/null +++ b/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj.user @@ -0,0 +1,6 @@ + + + + Container (Dockerfile) + + \ No newline at end of file From c1d36f532ceba47c6eba8baabdbb295ba66a8035 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 2 Nov 2024 20:22:39 -0700 Subject: [PATCH 10/17] examples --- .../sdk/dotnet/drasi-reaction-sdk/Models.cs | 12 ++++++ .../sdk/dotnet/drasi-reaction-sdk/Reaction.cs | 4 +- .../Services/DefaultControlEventHandler.cs | 4 -- .../examples/advanced-reaction/Dockerfile | 27 +++---------- .../examples/advanced-reaction/Program.cs | 37 +++++++++++++++--- .../Properties/launchSettings.json | 39 ------------------- .../advanced-reaction.csproj | 12 +++--- .../advanced-reaction.csproj.user | 6 --- .../appsettings.Development.json | 8 ---- .../advanced-reaction/appsettings.json | 9 ----- .../advanced-reaction/reaction-provider.yaml | 15 +++++++ .../examples/advanced-reaction/reaction.yaml | 12 ++++++ .../examples/simple-reaction/Dockerfile | 27 +++---------- .../examples/simple-reaction/Program.cs | 18 ++++++--- .../Properties/launchSettings.json | 39 ------------------- .../appsettings.Development.json | 8 ---- .../examples/simple-reaction/appsettings.json | 9 ----- .../simple-reaction/reaction-provider.yaml | 8 ++++ .../examples/simple-reaction/reaction.yaml | 8 ++++ .../simple-reaction/simple-reaction.csproj | 13 ++----- .../simple-reaction.csproj.user | 6 --- 21 files changed, 122 insertions(+), 199 deletions(-) create mode 100644 reactions/sdk/dotnet/drasi-reaction-sdk/Models.cs delete mode 100644 reactions/sdk/dotnet/examples/advanced-reaction/Properties/launchSettings.json delete mode 100644 reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj.user delete mode 100644 reactions/sdk/dotnet/examples/advanced-reaction/appsettings.Development.json delete mode 100644 reactions/sdk/dotnet/examples/advanced-reaction/appsettings.json create mode 100644 reactions/sdk/dotnet/examples/advanced-reaction/reaction-provider.yaml create mode 100644 reactions/sdk/dotnet/examples/advanced-reaction/reaction.yaml delete mode 100644 reactions/sdk/dotnet/examples/simple-reaction/Properties/launchSettings.json delete mode 100644 reactions/sdk/dotnet/examples/simple-reaction/appsettings.Development.json delete mode 100644 reactions/sdk/dotnet/examples/simple-reaction/appsettings.json create mode 100644 reactions/sdk/dotnet/examples/simple-reaction/reaction-provider.yaml create mode 100644 reactions/sdk/dotnet/examples/simple-reaction/reaction.yaml delete mode 100644 reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj.user diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Models.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Models.cs new file mode 100644 index 00000000..83737a02 --- /dev/null +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Models.cs @@ -0,0 +1,12 @@ +using System.Text.Json; + +namespace Drasi.Reaction.SDK.Models +{ + public static class ModelOptions + { + public static JsonSerializerOptions JsonOptions => Converter.Settings; + } +} + + + diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs index ec2c0f9c..4bbaf1ba 100644 --- a/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs @@ -55,12 +55,12 @@ private async Task ProcessEvent(HttpContext context, IChangeEventHandler(); + var changeEvt = evt.Deserialize(ModelOptions.JsonOptions); var queryCfg = _queriesConfig.GetValueOrDefault(changeEvt.QueryId, null); await changeHandler.HandleChange(changeEvt, queryCfg); break; case "control": - var controlEvt = evt.Deserialize(); + var controlEvt = evt.Deserialize(ModelOptions.JsonOptions); var queryCfg2 = _queriesConfig.GetValueOrDefault(controlEvt.QueryId, null); await controlEventHandler.HandleControlSignal(controlEvt, queryCfg2); break; diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/DefaultControlEventHandler.cs b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/DefaultControlEventHandler.cs index 835dec57..abb49eae 100644 --- a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/DefaultControlEventHandler.cs +++ b/reactions/sdk/dotnet/drasi-reaction-sdk/Services/DefaultControlEventHandler.cs @@ -1,10 +1,6 @@ using Drasi.Reaction.SDK.Models; using Microsoft.Extensions.Logging; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Drasi.Reaction.SDK.Services { diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/Dockerfile b/reactions/sdk/dotnet/examples/advanced-reaction/Dockerfile index 05913e65..4b3debbc 100644 --- a/reactions/sdk/dotnet/examples/advanced-reaction/Dockerfile +++ b/reactions/sdk/dotnet/examples/advanced-reaction/Dockerfile @@ -1,29 +1,12 @@ -# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. - -# This stage is used when running from VS in fast mode (Default for Debug configuration) -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base -USER app -WORKDIR /app -EXPOSE 8080 - - -# This stage is used to build the service project -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:8.0-cbl-mariner2.0 AS build ARG BUILD_CONFIGURATION=Release WORKDIR /src -COPY ["examples/advanced-reaction/advanced-reaction.csproj", "examples/advanced-reaction/"] -RUN dotnet restore "./examples/advanced-reaction/advanced-reaction.csproj" COPY . . +RUN dotnet restore "./examples/advanced-reaction/advanced-reaction.csproj" WORKDIR "/src/examples/advanced-reaction" RUN dotnet build "./advanced-reaction.csproj" -c $BUILD_CONFIGURATION -o /app/build -# This stage is used to publish the service project to be copied to the final stage -FROM build AS publish -ARG BUILD_CONFIGURATION=Release -RUN dotnet publish "./advanced-reaction.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false - -# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration) -FROM base AS final +FROM mcr.microsoft.com/dotnet/aspnet:8.0-cbl-mariner2.0 AS final WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "advanced-reaction.dll"] \ No newline at end of file +COPY --from=build /app/build . +ENTRYPOINT ["/app/advanced-reaction"] \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/Program.cs b/reactions/sdk/dotnet/examples/advanced-reaction/Program.cs index b016e55a..e90e4323 100644 --- a/reactions/sdk/dotnet/examples/advanced-reaction/Program.cs +++ b/reactions/sdk/dotnet/examples/advanced-reaction/Program.cs @@ -1,16 +1,27 @@ - +using System.Text.Json.Serialization; using Drasi.Reaction.SDK; using Drasi.Reaction.SDK.Models; +using Microsoft.Extensions.Logging; -var builder = new ReactionBuilder(); +var builder = new ReactionBuilder(); builder.UseChangeEventHandler(); +builder.UseControlEventHandler(); +builder.UseYamlQueryConfig(); var reaction = builder.Build(); +var myConnectionString = reaction.Configuration["MyConnectionString"]; +Console.WriteLine("MyConnectionString: " + myConnectionString); + await reaction.StartAsync(); +class MyQueryConfig +{ + [JsonPropertyName("greeting")] + public string? Greeting { get; set; } +} -class MyChangeHandler : IChangeEventHandler +class MyChangeHandler : IChangeEventHandler { private readonly ILogger _logger; @@ -19,8 +30,24 @@ public MyChangeHandler(ILogger logger) _logger = logger; } - public async Task HandleChange(ChangeEvent evt, object? queryConfig) + public async Task HandleChange(ChangeEvent evt, MyQueryConfig? queryConfig) + { + _logger.LogInformation($"Received change event from query {evt.QueryId} sequence {evt.Sequence}. Query greeting is {queryConfig?.Greeting}"); + _logger.LogInformation($"Full event: {evt.ToJson()}"); + } +} + +class MyControlSignalHandler : IControlEventHandler +{ + private readonly ILogger _logger; + + public MyControlSignalHandler(ILogger logger) + { + _logger = logger; + } + + public async Task HandleControlSignal(ControlEvent evt, MyQueryConfig? queryConfig) { - _logger.LogInformation($"Received change event: {evt}"); + _logger.LogWarning($"Received control signal: {evt.ControlSignal?.Kind} for query {evt.QueryId}. Query greeting is {queryConfig?.Greeting}"); } } \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/Properties/launchSettings.json b/reactions/sdk/dotnet/examples/advanced-reaction/Properties/launchSettings.json deleted file mode 100644 index 3292538e..00000000 --- a/reactions/sdk/dotnet/examples/advanced-reaction/Properties/launchSettings.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "profiles": { - "http": { - "commandName": "Project", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "dotnetRunMessages": true, - "applicationUrl": "http://localhost:5163" - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "Container (Dockerfile)": { - "commandName": "Docker", - "launchBrowser": true, - "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}", - "environmentVariables": { - "ASPNETCORE_HTTP_PORTS": "8080" - }, - "publishAllPorts": true, - "useSSL": false - } - }, - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:15167", - "sslPort": 0 - } - } -} \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj b/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj index 7bfbfeda..dda34e8a 100644 --- a/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj +++ b/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj @@ -1,16 +1,16 @@ - + + Exe net8.0 - enable - enable advanced_reaction - Linux - ..\.. + enable + enable - + + diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj.user b/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj.user deleted file mode 100644 index 4f592401..00000000 --- a/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj.user +++ /dev/null @@ -1,6 +0,0 @@ - - - - Container (Dockerfile) - - \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/appsettings.Development.json b/reactions/sdk/dotnet/examples/advanced-reaction/appsettings.Development.json deleted file mode 100644 index ff66ba6b..00000000 --- a/reactions/sdk/dotnet/examples/advanced-reaction/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/appsettings.json b/reactions/sdk/dotnet/examples/advanced-reaction/appsettings.json deleted file mode 100644 index 4d566948..00000000 --- a/reactions/sdk/dotnet/examples/advanced-reaction/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" -} diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/reaction-provider.yaml b/reactions/sdk/dotnet/examples/advanced-reaction/reaction-provider.yaml new file mode 100644 index 00000000..c77529a7 --- /dev/null +++ b/reactions/sdk/dotnet/examples/advanced-reaction/reaction-provider.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: ReactionProvider +name: Advanced +spec: + services: + reaction: + image: reaction-advanced + externalImage: true + config_schema: + type: object + properties: + MyConnectionString: + type: string + required: + - MyConnectionString diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/reaction.yaml b/reactions/sdk/dotnet/examples/advanced-reaction/reaction.yaml new file mode 100644 index 00000000..6a8e34cc --- /dev/null +++ b/reactions/sdk/dotnet/examples/advanced-reaction/reaction.yaml @@ -0,0 +1,12 @@ +kind: Reaction +apiVersion: v1 +name: test-advanced +spec: + kind: Advanced + properties: + MyConnectionString: "some connection string" + queries: + query1: | + greeting: "Hello, World!" + query2: | + greeting: "Howdy!" diff --git a/reactions/sdk/dotnet/examples/simple-reaction/Dockerfile b/reactions/sdk/dotnet/examples/simple-reaction/Dockerfile index 81916b5b..dc9f5cc3 100644 --- a/reactions/sdk/dotnet/examples/simple-reaction/Dockerfile +++ b/reactions/sdk/dotnet/examples/simple-reaction/Dockerfile @@ -1,29 +1,12 @@ -# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. - -# This stage is used when running from VS in fast mode (Default for Debug configuration) -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base -USER app -WORKDIR /app -EXPOSE 8080 - - -# This stage is used to build the service project -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:8.0-cbl-mariner2.0 AS build ARG BUILD_CONFIGURATION=Release WORKDIR /src -COPY ["examples/simple-reaction/simple-reaction.csproj", "examples/simple-reaction/"] -RUN dotnet restore "./examples/simple-reaction/simple-reaction.csproj" COPY . . +RUN dotnet restore "./examples/simple-reaction/simple-reaction.csproj" WORKDIR "/src/examples/simple-reaction" RUN dotnet build "./simple-reaction.csproj" -c $BUILD_CONFIGURATION -o /app/build -# This stage is used to publish the service project to be copied to the final stage -FROM build AS publish -ARG BUILD_CONFIGURATION=Release -RUN dotnet publish "./simple-reaction.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false - -# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration) -FROM base AS final +FROM mcr.microsoft.com/dotnet/aspnet:8.0-cbl-mariner2.0 AS final WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "simple-reaction.dll"] \ No newline at end of file +COPY --from=build /app/build . +ENTRYPOINT ["/app/simple-reaction"] \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/simple-reaction/Program.cs b/reactions/sdk/dotnet/examples/simple-reaction/Program.cs index 624744cd..cdc0a21a 100644 --- a/reactions/sdk/dotnet/examples/simple-reaction/Program.cs +++ b/reactions/sdk/dotnet/examples/simple-reaction/Program.cs @@ -1,13 +1,21 @@ - - -using Drasi.Reaction.SDK; +using Drasi.Reaction.SDK; var builder = new ReactionBuilder(); + builder.UseChangeEventHandler(async (evt, queryConfig) => { - Console.WriteLine($"Received change event: {evt}"); + Console.WriteLine($"Received change event from query {evt.QueryId} sequence {evt.Sequence}"); + + foreach (var item in evt.AddedResults) + Console.WriteLine($"Added result: {item}"); + + foreach (var item in evt.UpdatedResults) + Console.WriteLine($"Updated result, before {item.Before}, after {item.After}"); + + foreach (var item in evt.DeletedResults) + Console.WriteLine($"Deleted result: {item}"); + }); var reaction = builder.Build(); - await reaction.StartAsync(); \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/simple-reaction/Properties/launchSettings.json b/reactions/sdk/dotnet/examples/simple-reaction/Properties/launchSettings.json deleted file mode 100644 index 3e35de47..00000000 --- a/reactions/sdk/dotnet/examples/simple-reaction/Properties/launchSettings.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "profiles": { - "http": { - "commandName": "Project", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "dotnetRunMessages": true, - "applicationUrl": "http://localhost:5106" - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "Container (Dockerfile)": { - "commandName": "Docker", - "launchBrowser": true, - "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}", - "environmentVariables": { - "ASPNETCORE_HTTP_PORTS": "8080" - }, - "publishAllPorts": true, - "useSSL": false - } - }, - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:18595", - "sslPort": 0 - } - } -} \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/simple-reaction/appsettings.Development.json b/reactions/sdk/dotnet/examples/simple-reaction/appsettings.Development.json deleted file mode 100644 index ff66ba6b..00000000 --- a/reactions/sdk/dotnet/examples/simple-reaction/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/reactions/sdk/dotnet/examples/simple-reaction/appsettings.json b/reactions/sdk/dotnet/examples/simple-reaction/appsettings.json deleted file mode 100644 index 4d566948..00000000 --- a/reactions/sdk/dotnet/examples/simple-reaction/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" -} diff --git a/reactions/sdk/dotnet/examples/simple-reaction/reaction-provider.yaml b/reactions/sdk/dotnet/examples/simple-reaction/reaction-provider.yaml new file mode 100644 index 00000000..9d12c464 --- /dev/null +++ b/reactions/sdk/dotnet/examples/simple-reaction/reaction-provider.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ReactionProvider +name: Simple +spec: + services: + reaction: + image: reaction-simple + externalImage: true diff --git a/reactions/sdk/dotnet/examples/simple-reaction/reaction.yaml b/reactions/sdk/dotnet/examples/simple-reaction/reaction.yaml new file mode 100644 index 00000000..c59d0ad8 --- /dev/null +++ b/reactions/sdk/dotnet/examples/simple-reaction/reaction.yaml @@ -0,0 +1,8 @@ +kind: Reaction +apiVersion: v1 +name: test-simple +spec: + kind: Simple + queries: + query1: + query2: \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj b/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj index 47703c3c..2caa7e02 100644 --- a/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj +++ b/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj @@ -1,18 +1,13 @@ - + + Exe net8.0 - enable - enable simple_reaction - Linux - ..\.. + enable + enable - - - - diff --git a/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj.user b/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj.user deleted file mode 100644 index 4f592401..00000000 --- a/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj.user +++ /dev/null @@ -1,6 +0,0 @@ - - - - Container (Dockerfile) - - \ No newline at end of file From e915e1961eeac38cb82341136c5bb2230789102a Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Mon, 4 Nov 2024 14:12:36 -0800 Subject: [PATCH 11/17] wip --- .../Drasi.Reaction.SDK.Tests.csproj | 27 ++++++++++++++ .../Drasi.Reaction.SDK.Tests/UnitTest1.cs | 16 ++++++++ .../.gitignore | 0 .../Drasi.Reaction.SDK.csproj} | 0 .../IChangeEventHandler.cs | 0 .../IControlEventHandler.cs | 0 .../Makefile | 0 .../Models.cs | 0 .../Models.g.cs | 0 .../Reaction.cs | 8 +++- .../ReactionBuilder.cs | 37 ++++++++++++++++--- .../Services/DefaultControlEventHandler.cs | 0 .../Services/IConfigDeserializer.cs | 0 .../Services/IQueryConfigService.cs | 0 .../Services/InlineChangeEventHandler.cs | 0 .../Services/JsonConfigDeserializer.cs | 0 .../Services/NullConfigDeserializer.cs | 0 .../Services/QueryConfigService.cs | 0 .../Services/YamlConfigDeserializer.cs | 0 reactions/sdk/dotnet/drasi-reaction-sdk.sln | 8 +++- .../advanced-reaction.csproj | 2 +- .../simple-reaction/simple-reaction.csproj | 2 +- .../src/types/BootstrapCompletedSignal.d.ts | 1 + .../src/types/BootstrapStartedSignal.d.ts | 1 + .../sdk/javascript/src/types/ChangeEvent.d.ts | 5 ++- .../javascript/src/types/ControlEvent.d.ts | 6 ++- .../javascript/src/types/ControlSignal.d.ts | 1 + .../javascript/src/types/DeletedSignal.d.ts | 1 + .../sdk/javascript/src/types/ResultEvent.d.ts | 5 ++- .../javascript/src/types/RunningSignal.d.ts | 1 + .../javascript/src/types/StoppedSignal.d.ts | 1 + 31 files changed, 106 insertions(+), 16 deletions(-) create mode 100644 reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Drasi.Reaction.SDK.Tests.csproj create mode 100644 reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/UnitTest1.cs rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/.gitignore (100%) rename reactions/sdk/dotnet/{drasi-reaction-sdk/drasi-reaction-sdk.csproj => Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj} (100%) rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/IChangeEventHandler.cs (100%) rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/IControlEventHandler.cs (100%) rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/Makefile (100%) rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/Models.cs (100%) rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/Models.g.cs (100%) rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/Reaction.cs (85%) rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/ReactionBuilder.cs (62%) rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/Services/DefaultControlEventHandler.cs (100%) rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/Services/IConfigDeserializer.cs (100%) rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/Services/IQueryConfigService.cs (100%) rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/Services/InlineChangeEventHandler.cs (100%) rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/Services/JsonConfigDeserializer.cs (100%) rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/Services/NullConfigDeserializer.cs (100%) rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/Services/QueryConfigService.cs (100%) rename reactions/sdk/dotnet/{drasi-reaction-sdk => Drasi.Reaction.SDK}/Services/YamlConfigDeserializer.cs (100%) diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Drasi.Reaction.SDK.Tests.csproj b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Drasi.Reaction.SDK.Tests.csproj new file mode 100644 index 00000000..a526a21a --- /dev/null +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Drasi.Reaction.SDK.Tests.csproj @@ -0,0 +1,27 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + + + diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/UnitTest1.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/UnitTest1.cs new file mode 100644 index 00000000..10194e9f --- /dev/null +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/UnitTest1.cs @@ -0,0 +1,16 @@ +namespace Drasi.Reaction.SDK.Tests; + +using Drasi.Reaction.SDK; + +public class UnitTest1 +{ + [Fact] + public async void Test1() + { + + var reaction = new ReactionBuilder() + .UseJsonQueryConfig() + .UseChangeEventHandler((evt, config) => Task.CompletedTask) + .Build(); + } +} \ No newline at end of file diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/.gitignore b/reactions/sdk/dotnet/Drasi.Reaction.SDK/.gitignore similarity index 100% rename from reactions/sdk/dotnet/drasi-reaction-sdk/.gitignore rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/.gitignore diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.csproj b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj similarity index 100% rename from reactions/sdk/dotnet/drasi-reaction-sdk/drasi-reaction-sdk.csproj rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/IChangeEventHandler.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/IChangeEventHandler.cs similarity index 100% rename from reactions/sdk/dotnet/drasi-reaction-sdk/IChangeEventHandler.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/IChangeEventHandler.cs diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/IControlEventHandler.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/IControlEventHandler.cs similarity index 100% rename from reactions/sdk/dotnet/drasi-reaction-sdk/IControlEventHandler.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/IControlEventHandler.cs diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Makefile b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Makefile similarity index 100% rename from reactions/sdk/dotnet/drasi-reaction-sdk/Makefile rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Makefile diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Models.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models.cs similarity index 100% rename from reactions/sdk/dotnet/drasi-reaction-sdk/Models.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Models.cs diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Models.g.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models.g.cs similarity index 100% rename from reactions/sdk/dotnet/drasi-reaction-sdk/Models.g.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Models.g.cs diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs similarity index 85% rename from reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs index 4bbaf1ba..f16d6386 100644 --- a/reactions/sdk/dotnet/drasi-reaction-sdk/Reaction.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs @@ -3,7 +3,9 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using System.Text.Json; namespace Drasi.Reaction.SDK; @@ -17,6 +19,8 @@ public class Reaction : IHost public IServiceProvider Services => _app.Services; public IConfiguration Configuration => _app.Configuration; + public ILogger> Logger => _app.Services.GetRequiredService>>(); + internal Reaction(IQueryConfigService queryConfigService, WebApplication app) { _app = app; @@ -35,11 +39,13 @@ internal Reaction(IQueryConfigService queryConfigService, WebApplication app) public async Task StartAsync(CancellationToken cancellationToken = default) { - await _app.RunAsync("http://0.0.0.0:80"); + Logger.LogInformation("Starting reaction"); + await _app.RunAsync("http://127.0.0.1:80"); } public async Task StopAsync(CancellationToken cancellationToken = default) { + Logger.LogInformation("Stopping reaction"); await _app.StopAsync(cancellationToken); } diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/ReactionBuilder.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/ReactionBuilder.cs similarity index 62% rename from reactions/sdk/dotnet/drasi-reaction-sdk/ReactionBuilder.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/ReactionBuilder.cs index 6281c8c9..192cde7f 100644 --- a/reactions/sdk/dotnet/drasi-reaction-sdk/ReactionBuilder.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/ReactionBuilder.cs @@ -32,33 +32,58 @@ public ReactionBuilder() _webappBuilder.Logging.AddConsole(); } - public void UseChangeEventHandler() where TChangeEventHandler : class, IChangeEventHandler + public ReactionBuilder UseChangeEventHandler() where TChangeEventHandler : class, IChangeEventHandler { _webappBuilder.Services.AddScoped, TChangeEventHandler>(); + return this; } - public void UseChangeEventHandler(Func handler) + public ReactionBuilder UseChangeEventHandler(Func handler) { _webappBuilder.Services.AddScoped>((sp) => new InlineChangeEventHandler(handler)); + return this; } - public void UseControlEventHandler() where TControlEventHandler : class, IControlEventHandler + public ReactionBuilder UseControlEventHandler() where TControlEventHandler : class, IControlEventHandler { _webappBuilder.Services.AddScoped, TControlEventHandler>(); + return this; } - public void UseJsonQueryConfig() + public ReactionBuilder UseJsonQueryConfig() { _webappBuilder.Services.AddSingleton(); + return this; } - - public void UseYamlQueryConfig() + + public ReactionBuilder UseYamlQueryConfig() { _webappBuilder.Services.AddSingleton(); + return this; } + public ReactionBuilder ConfigureServices(Action configureServices) + { + configureServices(_webappBuilder.Services); + return this; + } + public Reaction Build() { + AppDomain.CurrentDomain.UnhandledException += (sender, args) => + { + var message = args.ExceptionObject is Exception exception ? exception.Message : "Unknown error occurred"; + + try + { + File.WriteAllText("/dev/termination-log", message); + } + catch (Exception logException) + { + Console.Error.WriteLine($"Failed to write to /dev/termination-log: {logException}"); + } + }; + var hasChangeHandler = _webappBuilder.Services.Any(x => x.ServiceType == typeof(IChangeEventHandler)); if (!hasChangeHandler) { diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/DefaultControlEventHandler.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/DefaultControlEventHandler.cs similarity index 100% rename from reactions/sdk/dotnet/drasi-reaction-sdk/Services/DefaultControlEventHandler.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/DefaultControlEventHandler.cs diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IConfigDeserializer.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IConfigDeserializer.cs similarity index 100% rename from reactions/sdk/dotnet/drasi-reaction-sdk/Services/IConfigDeserializer.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IConfigDeserializer.cs diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/IQueryConfigService.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IQueryConfigService.cs similarity index 100% rename from reactions/sdk/dotnet/drasi-reaction-sdk/Services/IQueryConfigService.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IQueryConfigService.cs diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/InlineChangeEventHandler.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/InlineChangeEventHandler.cs similarity index 100% rename from reactions/sdk/dotnet/drasi-reaction-sdk/Services/InlineChangeEventHandler.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/InlineChangeEventHandler.cs diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/JsonConfigDeserializer.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/JsonConfigDeserializer.cs similarity index 100% rename from reactions/sdk/dotnet/drasi-reaction-sdk/Services/JsonConfigDeserializer.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/JsonConfigDeserializer.cs diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/NullConfigDeserializer.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/NullConfigDeserializer.cs similarity index 100% rename from reactions/sdk/dotnet/drasi-reaction-sdk/Services/NullConfigDeserializer.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/NullConfigDeserializer.cs diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/QueryConfigService.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/QueryConfigService.cs similarity index 100% rename from reactions/sdk/dotnet/drasi-reaction-sdk/Services/QueryConfigService.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/QueryConfigService.cs diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk/Services/YamlConfigDeserializer.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/YamlConfigDeserializer.cs similarity index 100% rename from reactions/sdk/dotnet/drasi-reaction-sdk/Services/YamlConfigDeserializer.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/YamlConfigDeserializer.cs diff --git a/reactions/sdk/dotnet/drasi-reaction-sdk.sln b/reactions/sdk/dotnet/drasi-reaction-sdk.sln index 63b1a5fd..a16b13b9 100644 --- a/reactions/sdk/dotnet/drasi-reaction-sdk.sln +++ b/reactions/sdk/dotnet/drasi-reaction-sdk.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.002.0 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "drasi-reaction-sdk", "drasi-reaction-sdk\drasi-reaction-sdk.csproj", "{E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Drasi.Reaction.SDK", "Drasi.Reaction.SDK\Drasi.Reaction.SDK.csproj", "{E63E1B5E-61C8-4A5B-B7E0-5E3859C8E6B2}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{561184F7-D4CC-4392-934F-C725FE595D4C}" EndProject @@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "simple-reaction", "examples EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "advanced-reaction", "examples\advanced-reaction\advanced-reaction.csproj", "{FA13C8A9-8513-4985-897F-F728C79C4DAC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Drasi.Reaction.SDK.Tests", "Drasi.Reaction.SDK.Tests\Drasi.Reaction.SDK.Tests.csproj", "{69BF4350-D8F9-4FEB-8DCC-3E4AC1F8322B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -29,6 +31,10 @@ Global {FA13C8A9-8513-4985-897F-F728C79C4DAC}.Debug|Any CPU.Build.0 = Debug|Any CPU {FA13C8A9-8513-4985-897F-F728C79C4DAC}.Release|Any CPU.ActiveCfg = Release|Any CPU {FA13C8A9-8513-4985-897F-F728C79C4DAC}.Release|Any CPU.Build.0 = Release|Any CPU + {69BF4350-D8F9-4FEB-8DCC-3E4AC1F8322B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {69BF4350-D8F9-4FEB-8DCC-3E4AC1F8322B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {69BF4350-D8F9-4FEB-8DCC-3E4AC1F8322B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {69BF4350-D8F9-4FEB-8DCC-3E4AC1F8322B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj b/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj index dda34e8a..91195cd4 100644 --- a/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj +++ b/reactions/sdk/dotnet/examples/advanced-reaction/advanced-reaction.csproj @@ -9,7 +9,7 @@ - + diff --git a/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj b/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj index 2caa7e02..c21cb303 100644 --- a/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj +++ b/reactions/sdk/dotnet/examples/simple-reaction/simple-reaction.csproj @@ -9,7 +9,7 @@ - + diff --git a/reactions/sdk/javascript/src/types/BootstrapCompletedSignal.d.ts b/reactions/sdk/javascript/src/types/BootstrapCompletedSignal.d.ts index 06f6ff67..5fd5038f 100644 --- a/reactions/sdk/javascript/src/types/BootstrapCompletedSignal.d.ts +++ b/reactions/sdk/javascript/src/types/BootstrapCompletedSignal.d.ts @@ -14,5 +14,6 @@ export type BootstrapCompletedSignal = ControlSignal & { }; export interface ControlSignal { + kind: "bootstrapStarted" | "bootstrapCompleted" | "running" | "stopped" | "deleted"; [k: string]: unknown; } diff --git a/reactions/sdk/javascript/src/types/BootstrapStartedSignal.d.ts b/reactions/sdk/javascript/src/types/BootstrapStartedSignal.d.ts index 6726ac93..56e48f49 100644 --- a/reactions/sdk/javascript/src/types/BootstrapStartedSignal.d.ts +++ b/reactions/sdk/javascript/src/types/BootstrapStartedSignal.d.ts @@ -14,5 +14,6 @@ export type BootstrapStartedSignal = ControlSignal & { }; export interface ControlSignal { + kind: "bootstrapStarted" | "bootstrapCompleted" | "running" | "stopped" | "deleted"; [k: string]: unknown; } diff --git a/reactions/sdk/javascript/src/types/ChangeEvent.d.ts b/reactions/sdk/javascript/src/types/ChangeEvent.d.ts index ab823719..c48b44ee 100644 --- a/reactions/sdk/javascript/src/types/ChangeEvent.d.ts +++ b/reactions/sdk/javascript/src/types/ChangeEvent.d.ts @@ -26,6 +26,7 @@ export type ChangeEvent = ResultEvent & { }; export interface ResultEvent { + kind: "change" | "control"; /** * The ID of the query that the event originated from */ @@ -33,11 +34,11 @@ export interface ResultEvent { /** * The sequence number of the event */ - sequence: string; + sequence: number; /** * The time at which the source change was recorded */ - sourceTimeMs: string; + sourceTimeMs: number; metadata?: RecordUnknown; [k: string]: unknown; } diff --git a/reactions/sdk/javascript/src/types/ControlEvent.d.ts b/reactions/sdk/javascript/src/types/ControlEvent.d.ts index 18539905..0685d779 100644 --- a/reactions/sdk/javascript/src/types/ControlEvent.d.ts +++ b/reactions/sdk/javascript/src/types/ControlEvent.d.ts @@ -15,6 +15,7 @@ export type ControlEvent = ResultEvent & { }; export interface ResultEvent { + kind: "change" | "control"; /** * The ID of the query that the event originated from */ @@ -22,11 +23,11 @@ export interface ResultEvent { /** * The sequence number of the event */ - sequence: string; + sequence: number; /** * The time at which the source change was recorded */ - sourceTimeMs: string; + sourceTimeMs: number; metadata?: RecordUnknown; [k: string]: unknown; } @@ -34,5 +35,6 @@ export interface RecordUnknown { [k: string]: unknown; } export interface ControlSignal { + kind: "bootstrapStarted" | "bootstrapCompleted" | "running" | "stopped" | "deleted"; [k: string]: unknown; } diff --git a/reactions/sdk/javascript/src/types/ControlSignal.d.ts b/reactions/sdk/javascript/src/types/ControlSignal.d.ts index 76b6115f..ce091d6d 100644 --- a/reactions/sdk/javascript/src/types/ControlSignal.d.ts +++ b/reactions/sdk/javascript/src/types/ControlSignal.d.ts @@ -6,5 +6,6 @@ */ export interface ControlSignal { + kind: "bootstrapStarted" | "bootstrapCompleted" | "running" | "stopped" | "deleted"; [k: string]: unknown; } diff --git a/reactions/sdk/javascript/src/types/DeletedSignal.d.ts b/reactions/sdk/javascript/src/types/DeletedSignal.d.ts index 28237833..08633e36 100644 --- a/reactions/sdk/javascript/src/types/DeletedSignal.d.ts +++ b/reactions/sdk/javascript/src/types/DeletedSignal.d.ts @@ -14,5 +14,6 @@ export type DeletedSignal = ControlSignal & { }; export interface ControlSignal { + kind: "bootstrapStarted" | "bootstrapCompleted" | "running" | "stopped" | "deleted"; [k: string]: unknown; } diff --git a/reactions/sdk/javascript/src/types/ResultEvent.d.ts b/reactions/sdk/javascript/src/types/ResultEvent.d.ts index ee99bc4a..eaf1b7b7 100644 --- a/reactions/sdk/javascript/src/types/ResultEvent.d.ts +++ b/reactions/sdk/javascript/src/types/ResultEvent.d.ts @@ -6,6 +6,7 @@ */ export interface ResultEvent { + kind: "change" | "control"; /** * The ID of the query that the event originated from */ @@ -13,11 +14,11 @@ export interface ResultEvent { /** * The sequence number of the event */ - sequence: string; + sequence: number; /** * The time at which the source change was recorded */ - sourceTimeMs: string; + sourceTimeMs: number; metadata?: RecordUnknown; [k: string]: unknown; } diff --git a/reactions/sdk/javascript/src/types/RunningSignal.d.ts b/reactions/sdk/javascript/src/types/RunningSignal.d.ts index 64b64162..7c01224e 100644 --- a/reactions/sdk/javascript/src/types/RunningSignal.d.ts +++ b/reactions/sdk/javascript/src/types/RunningSignal.d.ts @@ -14,5 +14,6 @@ export type RunningSignal = ControlSignal & { }; export interface ControlSignal { + kind: "bootstrapStarted" | "bootstrapCompleted" | "running" | "stopped" | "deleted"; [k: string]: unknown; } diff --git a/reactions/sdk/javascript/src/types/StoppedSignal.d.ts b/reactions/sdk/javascript/src/types/StoppedSignal.d.ts index 75f27aad..8fb5cb6b 100644 --- a/reactions/sdk/javascript/src/types/StoppedSignal.d.ts +++ b/reactions/sdk/javascript/src/types/StoppedSignal.d.ts @@ -14,5 +14,6 @@ export type StoppedSignal = ControlSignal & { }; export interface ControlSignal { + kind: "bootstrapStarted" | "bootstrapCompleted" | "running" | "stopped" | "deleted"; [k: string]: unknown; } From 7273e0dd3e55eaa26725f9f26ab611c51d311fc3 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Mon, 4 Nov 2024 16:51:46 -0800 Subject: [PATCH 12/17] wip --- .../Drasi.Reaction.SDK.Tests.csproj | 1 + .../Drasi.Reaction.SDK.Tests/Fixture.cs | 51 ++++++++ .../Drasi.Reaction.SDK.Tests/ReactionTests.cs | 39 ++++++ .../Drasi.Reaction.SDK.Tests/UnitTest1.cs | 16 --- .../Drasi.Reaction.SDK.csproj | 1 + .../sdk/dotnet/Drasi.Reaction.SDK/Makefile | 2 +- .../{Models.g.cs => Models.generated.cs} | 0 .../sdk/dotnet/Drasi.Reaction.SDK/README.md | 122 ++++++++++++++++++ .../sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs | 4 +- .../Drasi.Reaction.SDK/ReactionBuilder.cs | 8 +- .../Services/QueryConfigService.cs | 7 +- .../examples/advanced-reaction/Program.cs | 46 +++++-- 12 files changed, 264 insertions(+), 33 deletions(-) create mode 100644 reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Fixture.cs create mode 100644 reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/ReactionTests.cs delete mode 100644 reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/UnitTest1.cs rename reactions/sdk/dotnet/Drasi.Reaction.SDK/{Models.g.cs => Models.generated.cs} (100%) create mode 100644 reactions/sdk/dotnet/Drasi.Reaction.SDK/README.md diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Drasi.Reaction.SDK.Tests.csproj b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Drasi.Reaction.SDK.Tests.csproj index a526a21a..4e611e5a 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Drasi.Reaction.SDK.Tests.csproj +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Drasi.Reaction.SDK.Tests.csproj @@ -11,6 +11,7 @@ + diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Fixture.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Fixture.cs new file mode 100644 index 00000000..124c3e06 --- /dev/null +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Fixture.cs @@ -0,0 +1,51 @@ +using Drasi.Reaction.SDK.Models; +using System; +using System.Threading.Channels; + +namespace Drasi.Reaction.SDK.Tests +{ + public class Fixture : IDisposable + where TQueryConfig : class + { + public string QueryDirectory { get; private set; } + public Channel ChangeEventChannel { get; private set; } + + public Reaction Reaction { get; private set; } + + public HttpClient Client { get; private set; } + + public Fixture() + { + QueryDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(QueryDirectory); + ChangeEventChannel = Channel.CreateUnbounded(); + + Reaction = new ReactionBuilder() + .UseChangeEventHandler(async (evt, config) => + { + await ChangeEventChannel.Writer.WriteAsync(evt); + }) + .Configure(x => x["QueryConfigPath"] = QueryDirectory) + .Build(); + + _ = Reaction.StartAsync(); + + Client = new HttpClient(); + Client.BaseAddress = new Uri("http://localhost:80"); + } + + public void ClearChannels() + { + while (ChangeEventChannel.Reader.Count > 0) + { + ChangeEventChannel.Reader.TryRead(out _); + } + } + + public void Dispose() + { + Directory.Delete(QueryDirectory, true); + _ = Reaction.StopAsync(); + } + } +} diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/ReactionTests.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/ReactionTests.cs new file mode 100644 index 00000000..50b973e3 --- /dev/null +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/ReactionTests.cs @@ -0,0 +1,39 @@ +namespace Drasi.Reaction.SDK.Tests; + +using Drasi.Reaction.SDK; +using Drasi.Reaction.SDK.Models; +using Microsoft.AspNetCore.TestHost; +using System.Net.Http.Json; +using System.Threading.Channels; + +public class ReactionTests : IClassFixture> +{ + + private readonly Fixture _fixture; + + public ReactionTests(Fixture fixture) + { + _fixture = fixture; + _fixture.ClearChannels(); + } + + [Fact] + public async void ChangeEventsAreHandled() + { + var myEvt = new ChangeEvent() + { + Sequence = 1, + QueryId = "query1", + AddedResults = [], + UpdatedResults = [], + DeletedResults = [] + }; + + await _fixture.Client.PostAsJsonAsync("event", myEvt, ModelOptions.JsonOptions); + + Assert.True(await _fixture.ChangeEventChannel.Reader.WaitToReadAsync(new CancellationTokenSource(TimeSpan.FromSeconds(5)).Token)); + var result = await _fixture.ChangeEventChannel.Reader.ReadAsync(); + Assert.Equal(myEvt.QueryId, result.QueryId); + Assert.Equal(myEvt.Sequence, result.Sequence); + } +} \ No newline at end of file diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/UnitTest1.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/UnitTest1.cs deleted file mode 100644 index 10194e9f..00000000 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/UnitTest1.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Drasi.Reaction.SDK.Tests; - -using Drasi.Reaction.SDK; - -public class UnitTest1 -{ - [Fact] - public async void Test1() - { - - var reaction = new ReactionBuilder() - .UseJsonQueryConfig() - .UseChangeEventHandler((evt, config) => Task.CompletedTask) - .Build(); - } -} \ No newline at end of file diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj index 02b91985..ecefbda7 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj @@ -8,6 +8,7 @@ + diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Makefile b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Makefile index 9b91e3a2..7510858b 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Makefile +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Makefile @@ -1,4 +1,4 @@ .PHONY: generate-types generate-types: - quicktype --src-lang schema -l cs -o Models.g.cs ../../../../typespec/query-output/_generated/@typespec/json-schema/*.yaml --framework SystemTextJson --namespace Drasi.Reaction.SDK.Models \ No newline at end of file + quicktype --src-lang schema -l cs -o Models.generated.cs ../../../../typespec/query-output/_generated/@typespec/json-schema/*.yaml --framework SystemTextJson --namespace Drasi.Reaction.SDK.Models \ No newline at end of file diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models.g.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models.generated.cs similarity index 100% rename from reactions/sdk/dotnet/Drasi.Reaction.SDK/Models.g.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Models.generated.cs diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/README.md b/reactions/sdk/dotnet/Drasi.Reaction.SDK/README.md new file mode 100644 index 00000000..9c24cd6a --- /dev/null +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/README.md @@ -0,0 +1,122 @@ +# Reaction SDK for Drasi + +This library provides the building blocks and infrastructure to implement a [Drasi](https://drasi.io/) Reaction in .NET + +## Getting started + +### Install the package + +``` +dotnet add package Drasi.Reaction.SDK +``` + +### Basic example + +The following example simply breaks down and logs the various parts of the incoming change event from a [Continuous Query](https://drasi.io/concepts/continuous-queries/). + +```csharp +var builder = new ReactionBuilder(); + +builder.UseChangeEventHandler(async (evt, queryConfig) => +{ + Console.WriteLine($"Received change event from query {evt.QueryId} sequence {evt.Sequence}"); + + foreach (var item in evt.AddedResults) + Console.WriteLine($"Added result: {item}"); + + foreach (var item in evt.UpdatedResults) + Console.WriteLine($"Updated result, before {item.Before}, after {item.After}"); + + foreach (var item in evt.DeletedResults) + Console.WriteLine($"Deleted result: {item}"); + +}); + +var reaction = builder.Build(); +await reaction.StartAsync(); +``` + +### A more advanced example + +The following example illustrates + - Retrieving a configuration value from the Reaction manifest + - Defining a custom per query configuration object + - Parsing the per query configuration object from Yaml + - Process change events form thw query + - Process control events (start, stop, etc.) from the query + + +```csharp +var reaction = new ReactionBuilder() + .UseChangeEventHandler() // Use your custom change handler + .UseControlEventHandler() // Use your custom control signal handler + .UseYamlQueryConfig() // Parse the per query configuration from Yaml + .ConfigureServices((services) => // Register your own services + { + services.AddSingleton(); + }) + .Build(); + +// Start the reaction +await reaction.StartAsync(); + +// Define a custom per query configuration object +class MyQueryConfig +{ + [JsonPropertyName("greeting")] + public string? Greeting { get; set; } +} + +// Your own internal service +class MyService +{ + private readonly string _connectionString; + + public MyService(IConfiguration configuration) + { + // Retrieve the connection string from the Reaction configuration + _connectionString = configuration["MyConnectionString"]; + } + + public void DoSomething() + { + Console.WriteLine("Doing something"); + } +} + +// Define a custom change handler, that uses your service +class MyChangeHandler : IChangeEventHandler +{ + private readonly MyService _service; + private readonly ILogger _logger; + + public MyChangeHandler(MyService service, ILogger logger) + { + _service = service; + _logger = logger; + } + + public async Task HandleChange(ChangeEvent evt, MyQueryConfig? queryConfig) + { + _logger.LogInformation($"Received change event from query {evt.QueryId} sequence {evt.Sequence}. Query greeting is {queryConfig?.Greeting}"); + _logger.LogInformation($"Full event: {evt.ToJson()}"); + _service.DoSomething(); + } +} + +// Define a custom control signal handler +class MyControlSignalHandler : IControlEventHandler +{ + private readonly ILogger _logger; + + public MyControlSignalHandler(ILogger logger) + { + _logger = logger; + } + + public async Task HandleControlSignal(ControlEvent evt, MyQueryConfig? queryConfig) + { + _logger.LogWarning($"Received control signal: {evt.ControlSignal?.Kind} for query {evt.QueryId}. Query greeting is {queryConfig?.Greeting}"); + } +} +``` \ No newline at end of file diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs index f16d6386..e65959ad 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs @@ -38,9 +38,9 @@ internal Reaction(IQueryConfigService queryConfigService, WebApplication app) } public async Task StartAsync(CancellationToken cancellationToken = default) - { + { Logger.LogInformation("Starting reaction"); - await _app.RunAsync("http://127.0.0.1:80"); + await _app.RunAsync($"http://127.0.0.1:{Configuration["APP_PORT"] ?? "80"}"); } public async Task StopAsync(CancellationToken cancellationToken = default) diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/ReactionBuilder.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/ReactionBuilder.cs index 192cde7f..b6199da1 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/ReactionBuilder.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/ReactionBuilder.cs @@ -66,7 +66,13 @@ public ReactionBuilder ConfigureServices(Action Configure(Action configure) + { + configure(_webappBuilder.Configuration); + return this; + } public Reaction Build() { diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/QueryConfigService.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/QueryConfigService.cs index 3e9f2418..94bd698a 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/QueryConfigService.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/QueryConfigService.cs @@ -1,10 +1,11 @@ -using System; +using Microsoft.Extensions.Configuration; +using System; namespace Drasi.Reaction.SDK.Services { - internal class QueryConfigService(IConfigDeserializer configDeserializer) : IQueryConfigService + internal class QueryConfigService(IConfigDeserializer configDeserializer, IConfiguration appConfig) : IQueryConfigService { - private readonly string _configDirectory = Environment.GetEnvironmentVariable("QueryConfigPath") ?? "/etc/queries"; + private readonly string _configDirectory = appConfig["QueryConfigPath"] ?? "/etc/queries"; private readonly IConfigDeserializer _configDeserializer = configDeserializer; public List GetQueryNames() diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/Program.cs b/reactions/sdk/dotnet/examples/advanced-reaction/Program.cs index e90e4323..a934df2d 100644 --- a/reactions/sdk/dotnet/examples/advanced-reaction/Program.cs +++ b/reactions/sdk/dotnet/examples/advanced-reaction/Program.cs @@ -1,32 +1,56 @@ using System.Text.Json.Serialization; using Drasi.Reaction.SDK; using Drasi.Reaction.SDK.Models; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -var builder = new ReactionBuilder(); -builder.UseChangeEventHandler(); -builder.UseControlEventHandler(); -builder.UseYamlQueryConfig(); - -var reaction = builder.Build(); - -var myConnectionString = reaction.Configuration["MyConnectionString"]; -Console.WriteLine("MyConnectionString: " + myConnectionString); +var reaction = new ReactionBuilder() + .UseChangeEventHandler() // Use your custom change handler + .UseControlEventHandler() // Use your custom control signal handler + .UseYamlQueryConfig() // Parse the per query configuration from Yaml + .ConfigureServices((services) => // Register your own services + { + services.AddSingleton(); + }) + .Build(); +// Start the reaction await reaction.StartAsync(); +// Define a custom per query configuration object class MyQueryConfig { [JsonPropertyName("greeting")] public string? Greeting { get; set; } } +// Your own internal service +class MyService +{ + private readonly string _connectionString; + + public MyService(IConfiguration configuration) + { + // Retrieve the connection string from the Reaction configuration + _connectionString = configuration["MyConnectionString"]; + } + + public void DoSomething() + { + Console.WriteLine("Doing something"); + } +} + +// Define a custom change handler, that uses your service class MyChangeHandler : IChangeEventHandler { + private readonly MyService _service; private readonly ILogger _logger; - public MyChangeHandler(ILogger logger) + public MyChangeHandler(MyService service, ILogger logger) { + _service = service; _logger = logger; } @@ -34,9 +58,11 @@ public async Task HandleChange(ChangeEvent evt, MyQueryConfig? queryConfig) { _logger.LogInformation($"Received change event from query {evt.QueryId} sequence {evt.Sequence}. Query greeting is {queryConfig?.Greeting}"); _logger.LogInformation($"Full event: {evt.ToJson()}"); + _service.DoSomething(); } } +// Define a custom control signal handler class MyControlSignalHandler : IControlEventHandler { private readonly ILogger _logger; From f0e0d0d3a4220176392c26a30c8860df2114e249 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 5 Nov 2024 11:34:52 -0800 Subject: [PATCH 13/17] packaging --- .../Drasi.Reaction.SDK.csproj | 16 +++++++++++++++- .../sdk/dotnet/Drasi.Reaction.SDK/drasi.png | Bin 0 -> 11789 bytes 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 reactions/sdk/dotnet/Drasi.Reaction.SDK/drasi.png diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj index ecefbda7..d3cd6069 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj @@ -5,10 +5,24 @@ Drasi.Reaction.SDK enable enable + + Drasi.Reaction.SDK + The Drasi authors + Reaction SDK for Drasi + https://drasi.io + Apache-2.0 + git + https://github.com/drasi-project/drasi-platform.git + 0.1.0 + drasi.png + 0.1.0-alpha + README.md - + + + diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/drasi.png b/reactions/sdk/dotnet/Drasi.Reaction.SDK/drasi.png new file mode 100644 index 0000000000000000000000000000000000000000..e284ea5eaf7138934250e2a699aa61086d946888 GIT binary patch literal 11789 zcmeHtdpy+X`~KTmvN4%uHWrOS2Zwe`YRObH+9a_$u%d~gl#8)lc$n@GBquGM=465TFG9z zHaxYbWlez2hGU&i+HLPQ2FfTl&dKoArLqoATUjJqD08pu`>2{Z<_i`&4ydpbt>!C; zH`b}xFP*$CB#rl2|JQX^bm`0!Cl)eazLg35Yi!t6X{`A(>2Bt$_fMJxfil?o`1rXY z{Gn9i9p$kp4YpA;meDAR$2OLwsGpTNcrf*}GDWeNbWHg6022>l|9kmAH2&kpf0^>1 z6#VamaqaJJ^9KW}FJ*U76oYwMx$bNt-{uM@q}k-8)YMv)5+MOI!Y&v{uDZ=PTcsvT znbVii^gWH3kAI4P{+rwUUD+`*l<{g~+0lx4zGb)OJ*Tdv6lFIxj%svZkJgx+EDWf& znuCQ{la|riyhmvL+utufTMY83-LRqAYau0K0GjnPEp`WHN_C1% z`h4Ult7J!c-y-MEs+Pp@Bjw+~5pM1QChH3u&L>A6j`j6632MHk{M-fG4h{)Nm)MFo zf8BkbK&!qvOW9mrsahHq>=B_(@szbW8Q;k@8GF25#5{D;^{4OgFvG(lj=FVGZ_I09 zg>I<~Wrt#VYiRLsmD48TSZoRBjBOUDv7()Jn3$E_FA& zELcYsN0aaESz-%(ToEu{*F`6J#_|39cXcKwFB8C4W8L;4L#*3G(5N+_%ard}IP5&_ zm7kUjFBI`@f9uRn1qn!eMDxS%D(2Sk^$IUnRq!qSyjymXRr|4O^0ED$k)@U-M&_`c zb=2^x)72LtLpk#uh|dY}iA>Rt{{(6sSkblX%dw8!3AQEdca+b)6~MmwO7q@I!L~Pc zYI2ln3Z7NQcM9THWGl%~2P=s`vv=NozCNHq|!! zw6Z9r(`JP~*;Ey)>SyBJq=4$Hh3@jy0jA@r37+2KjnQcxEt!kv!d}Nih~^frFu^JQ zyA6VE4yS4;-r`9dDj-CCEKsY1Y+k&|ST^YRDSmjZ$+V;vip4?aqE_%JI=n88I4VyP zI+UJuoh+EYXc>*SuGdyP5>TBQ-lIsJS!pcW=VF%GYN~q_(Q`3_mCikEv00__w3p7Z zA~rgs`X~Rm!LY##i~mjw(PbKr{cXQUgawQJZICC2ti$A}TSzC{-|vtL(uR zx?9bLd-`-4#vx#}b*EiB$(RgpxO*B&x~3)b#4fmd2U)24;O{ULfn%zT0ieR;MpIeQ z8#r6umczG1tT%%`L<4vQ4YB-46TQ+#q9OJt5Rgk7BB->d`opcJ6G`JdlO8p#_oyz< zs414e5Qc@=$x-!djAhNeN2=3nEZ@M+JY)q|#bbqZ(Ths3SwzQ9XFL~9XqY&RMy1)} z^#x{`Hrc^zkzC`I?hBX1x=`y+14utZhoQW_nrkz%1-J8Oc+=Y%1RDA^+ z$Y>vj?Gy{9vjT09X(Ych!q6sPd{`ZM=ml7Ob|zh>ZC7cvO<0I$sWK}Ov21?H!McY? zVmBdJZ2{lV`YQ*H97GQ1?sJsq#Vq2F7o?DEx&iHxnwKi>wXO!-7pvdEwkO+uzAg zx(v* zS}ypPR|)B4F``gO*lkF zTfbQ73tL_@L3twRTuW5UJ-XMduUvE=bz|@LX#JL63{F^P%ZO&4R(4F^pEIt2YFK~w ziVv-SaN6_DmPn*EAnZGG-pux)8qNk(zuUB%Cand&p`+2qIy4_guZhTczKX45YO_c& z<15tA&_`|$H{A{kCiGFmExaqJfS0D z>b!n5teJZv)Tlc0&G6=?NDJ*yNG%kMI}NK{iyOV3cOo=$LE+1-4W}4Gqp8d+yJPboK(H#H`Ywv2=mmLwik(`}_RH?OHEDsX zs%}2I)}?umv<2nQVgg&QA5D|tp1ZRl`XEZJyqv z)(~oUl`SnJVE;GCkMCZog(qhpB98|zB5j+|F4p-6oo4jELgC|xTW%LiM4q7kMYl4hlK9UW>zZQ zZx=DAq`3aH9^xHAV%s#wTC^NE0FL7L+Dm%0^balV(!k3yz9jW5t{ms2xGqfM3pv7Q z&+iFiecd9|d5_)?(Q^;2StA@26zm-kSUulMACsG9Um1heA=FMTgVN?uXhQm2kPe0X zcP?R5E!v0x6B6)HWPUdKO84xE(2h!_o#S87w4y6EUkhVOw7{=o==!?;rW|e5D(;uy zuTF8iGZHY;)MkMqcQUkRSGJOiR#VxZyJ}5NhDdKJaR>2G2@eHxn#$C&eKz-gq^bp) z4t3{IrI*jb`nR%24g9onIzxw&TCSqU5YbUhn6~2?_uR3^)Ul2t002pS1xd@_i-O9Z z6ywQef89NP(LMFjN0RQrMl{;tk)a{O4aM=o&vm0;ms(|$R(Pc}UXAAu4Pdh`Wh*rt z!;a?6ab4Obm84t4y(`2t5t#eK$p<=r2-bYv=&=tP za28e7s5qWF2ST&i?0dp)m~vGM#kvnUAP4(Rfl~cgpFwh1+8 zv|%oRmghnu+s+mbQC=ZPcp)mmx(iw4G=WHx0(Ac3f}OuX;^X%kjGXS7;ddM76`YSI zTBCDsR;ihL-^&|0cOulxK%z$`lO6_zhg*ZaVk^E$I}fqI^R35|TA-iy$FSSt^ap?3 zDC(6QuNlmzDbf0U1lvegO{>`kQOJkP=dN~(;L#cYVclG` z-n9O=B&o+f2xPK6nGFUfpG74&*ej{Kb_jjPaV#9JLWXn;8}*yYW}~AaC=lRzu0#PzX2l%Wq@`Cn+&Z{1t;RAWLXn|?aw>9k;{a2*RTBj)%6 zlatOl^Lf+3;O5(t6K_@Dz0%&fDYM8u^*qi{g*Z~9%_PlxK*wOMOo4k|c?trDmSutj zg6*r+L~qagY1te}i%x7z0#IJaqiphiyPl(xF9PrdO{&~fHVY>quZ83!RJQ`O(iS@D zl)!6tjsJ_Bu|Xb-Vv7?OWCtUzUibjUqO12i_g5eOGI#82y7|EJ?WLkYb{`JA+Kh0)0+ z@Sdc0*UpAyq_)s1y8!1TQiU9~s|yzgyT^Lhf4M>`ZPg=UbB)i(eTELsY7A4d=>bm; z3`T*ofCdK`G55MI32Tomk9vi0yexE%po*))3a0&o>IN|T<+Gh*i`~&^1)@l|d^!xN z;z-&y9Zs+o-OJmhHP$MpcgNx8!CqT5uPE?9&q|DF7$esw3j7DzpJ@Icfoso3KVB

%@Z44u=;_KycIT=1|JFYQ`n+nM$445sA$!wvpy9b565twx(CUuTP}U)hXDd>5gf zF&6>KFtHYWdvBE*%e9h~8WUOl-F`FLJn2})rd9&KBHn1*+9hM#*-j>XAEA7Q*s^&j zs>Cg9YH=Hrd1#Nf%0?r4)JnJUGk0uy&IfoP9NpMb`sJ8#?THxaiQjK<*g7lpVk2=& z!T_P|Px(t;_-V|!s4C8SCT*N$HKnQFVz|m)ff%TgrFY24b;lA)VqRZXlr(yK+PV8i}Z(8P(_7X>?+2-KqzX>p>p zMcGOWT9f#ffqmN_?41&&?DsRaz2lk?lLB8J%-w`lqFfB{_8;nTqNkSe1yh^Ev|vf5 zuU@9~O9_sSyv52KZrr09xrEzShp6Vj_xrk>*gaah(Y+y)X~xT7=9a8?=Ebpc9b(P{ zd8Q+j#jwmZ;V7}>EgZJS+Dox^U4!A01b>NWu5@O_v(MO3E_zYQs&O#p3<)*fW>v+; zzqlN&tokb+mb)g5G#XA34Jg!R^}Y4`L!N2A4KAws%+vMrh~S+xkuI@TF*5aiuE{hH z$H1?sq6U2_{+?fWn9sz^XxWpeYL|_GLXL-@O+FI?)D=9h;l6ExX6O}pF;nA2Gc4o# z^@WXF{9-h;=3?&z)W|b8E&BHk*2vkP(z16Qo;s%3{~OxYB-}Loj%sKgR2-{41e*I) z2dXJ}wlpu3H(YKkn zA29z0xcmtd=9XqpVy=lE zt)S&{3nJlFwEM=8xjge)5-r$RJ?eXG(L=UK_Lmq~2H%*Nf#nzorksTt`lX#Wj_feaY}LO$ z2X3fikGs3WBED`CyUi8+6;mDQIa@t8Xfmx0T^^&5Oj-rjeDrp8iYMw8kW~~d*I91Z7iAAl@OqJjE$!P_#xo+pL;$_)i z?Db{y@FlT47aS8^{bO@V$?lBj=BXuZyD%dU7fQCE>Z^@nu^`sN{Mi&)8h1HBu^`BM zUzGB$et>x4hzax1nc=rKtnKhqTexO4snY+>Z*bEZ;cviANW#HFM(c?>i|WZ|n%ljG zw8e#xsN#DL%g7=?jwg4U{ zqh>Mq)d3pE&5}JHv*`S0F=oji{Kl5?za#{tbcz+!f@pj64-IVEN7XB1U-crG>ZsB}cXF)t2l3AW*9oZiyh5(k~5xJ4pg+f0NHl4$dT0i$Ku#%L9D~Z z{C)9IyjQrv64hctr>|O>XOnn>s%5S(J2aUhF&^iqmht(r(zaf)!W?xzrGZ?WUbwos zhTv_r4@A*`VbgaY*BiwmR*t*N~W!EAG%hwOu24^*~jZDMk1?n=hne?co zKWKV^#bh5^zh_INzu_vp3$b3lZqTBCRo>2&cS!N$)k>KfT2@D}!RLU*@qtd8$8?w1`3&S`A|zU5RtMJm_yv!Pj*o1O{7-+$HPq|9Cq zEU2Fbv^iYIWBr4_59ugay%WTKP?}liMi`JOa`&y8f^Fs(#|m6Xw#feS0HP+c1K{%) z9F&|AuKrQ7&*U1mlL9tV1d`Qc6x z4BKx1AvboEvgnazl8oxIY@d0iH#@Se(txR70&JznWGfl7W(+X&G9gQZWM@$Nmg74P zrHEvqipz6ySizMs8^`BbE2-9Xe5{Wdx)yOFbtDQ;=7-5No+mt%FS-_{@)M0u(FuBB zDJ9ni%=S;GM`fl(?s;(Vq0R3pEO~Aay1SEA4!@s(38dE8fj5)_0;+g#r)mbnXI}2l z7)jWN8;9@QBB+L`Fg_O_du9mNY$na9XaU#>4J5;hvkHq~Ld^TCs8RDeD`%70*leNeKTtuu*Dl|UAYf5+4Z zNLET03FOvKlHti*#b-dtB?`mY7+we9DP7zNH%Z>c`WS8u76$K^Bhx%f2Z9Y)Qji1rpg;dIF)&xlf{v;j`y_i1Ik&|wB`g;4sgn|znz zo`s9sfl0C|=*3+{{$~+q^?>w9M(B}vq~>|0mbJw~hIq>`ys|jfs+=?AV~VAjEer${857rVvwY7}DA%_&9T=CAg-wxMA_js)=E2q=Ahbo6%ANL52~+v9FNvnjmBd0Czl_Ydg_> zQHOy@CLy5(g zuD%~hG0?p4neZU6S~`VvuaqbV?tKaS^DmO-w2FLAP(^oIf8&)#1+k;e!)Eu$n?HtB zMSN@N@C%`VL~2)cAW$T0XucgsTYG%!`3PZcAzfrHeA1 zi6~PRcWi0ldFV7gAJ!Q&5!aH{Yms>s1C3p82<7~6n$$f9VN&?iwor~*fbp(tLL%X_ zF)rnkpf22-q(hjtjIoZA*&$HCk6 z3wO}*S<#u0OiJykm10oVq*G-j{Js0%ohQzF;j4DDcTW==8BFQoa)4Za^nD9_+hVbB z%DezNvDroLwDNAB13vSBp=jD9PMe`uqu~{VGhYTf{`uE(Cw*DU@8>}V>#M#(#->c0 z&|sVt@ns*#o!6G2WTWT$2}w`oLY~ee!Gg*@=>U}rex298XOD4| zYDP|Sf}su>Dj&a{*!XD3Cx-+u0hwxAq&?j2!Petf;IG^Sr}-V5HWd|&7cwT^LC!Mk zrHx%x(}9aEDjuzSq^FJ;I4MY1Znoe|Aw!QT`4(Q=?@wg@wd9HP4}!1;RH*`73W2+| z3#w!(5rxX+{zO<$rm84&avM}8KqTLy>w2$OIS_Pne|9`@rARQ^fvUqQOReD9wFGOD z#OB>;G+uV?(GF<=Sgp^*l%9dNvBW_9@FTaW74K6IarI77)Soyf;}35$ZoU5Z_Y431 zGVs6ON&fdk(EpEr7AqBwE!KpPP>iR6*LF?Wik|}~kY59vXDU;ah))#9fC$Zh5C7kQ Z$e*2kxy?+{` Date: Thu, 7 Nov 2024 13:10:17 -0800 Subject: [PATCH 14/17] error handling --- .../Drasi.Reaction.SDK.csproj | 4 +-- .../sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs | 13 ++++++++ .../Drasi.Reaction.SDK/ReactionBuilder.cs | 32 +++++++++++-------- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj index d3cd6069..e6df9970 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj @@ -13,9 +13,9 @@ Apache-2.0 git https://github.com/drasi-project/drasi-platform.git - 0.1.0 + 0.1.1 drasi.png - 0.1.0-alpha + 0.1.1-alpha README.md diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs index e65959ad..9c7239c3 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs @@ -76,5 +76,18 @@ private async Task ProcessEvent(HttpContext context, IChangeEventHandler Configure(Action con public Reaction Build() { - AppDomain.CurrentDomain.UnhandledException += (sender, args) => - { - var message = args.ExceptionObject is Exception exception ? exception.Message : "Unknown error occurred"; - - try - { - File.WriteAllText("/dev/termination-log", message); - } - catch (Exception logException) - { - Console.Error.WriteLine($"Failed to write to /dev/termination-log: {logException}"); - } - }; - var hasChangeHandler = _webappBuilder.Services.Any(x => x.ServiceType == typeof(IChangeEventHandler)); if (!hasChangeHandler) { @@ -106,5 +92,23 @@ public Reaction Build() return new Reaction(queryConfigSvc, app); } + static ReactionBuilder() + { + AppDomain.CurrentDomain.UnhandledException += (sender, args) => + { + var message = args.ExceptionObject is Exception exception ? exception.Message : "Unknown error occurred"; + + try + { + File.WriteAllText("/dev/termination-log", message); + } + catch (Exception logException) + { + Console.Error.WriteLine($"Failed to write to /dev/termination-log: {logException}"); + } + }; + } + } + } From ae5acf14a4949ad8d55e61b4f5c2f0ac171f7209 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 8 Nov 2024 15:33:58 -0800 Subject: [PATCH 15/17] wip --- .../Drasi.Reaction.SDK.Tests/Fixture.cs | 30 +- .../Drasi.Reaction.SDK.Tests/ReactionTests.cs | 2 +- .../Drasi.Reaction.SDK.csproj | 4 +- .../Drasi.Reaction.SDK/IChangeEventHandler.cs | 2 +- .../IControlEventHandler.cs | 2 +- .../sdk/dotnet/Drasi.Reaction.SDK/Makefile | 4 - .../{ => Models/QueryOutput}/Models.cs | 2 +- .../QueryOutput}/Models.generated.cs | 48 +-- .../Models/ViewService/Models.cs | 12 + .../Models/ViewService/Models.generated.cs | 239 +++++++++++ .../sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs | 2 +- .../Drasi.Reaction.SDK/ReactionBuilder.cs | 3 +- .../Services/DefaultControlEventHandler.cs | 2 +- .../Services/IResultViewClient.cs | 9 + .../Services/InlineChangeEventHandler.cs | 6 +- .../Services/ResultViewClient.cs | 57 +++ reactions/sdk/dotnet/Makefile | 18 + .../examples/advanced-reaction/Program.cs | 2 +- typespec/package-lock.json | 389 +++++++++++++++++- typespec/package.json | 7 +- typespec/view-svc/.gitignore | 1 + typespec/view-svc/main.tsp | 33 ++ typespec/view-svc/tspconfig.yaml | 8 + 23 files changed, 833 insertions(+), 49 deletions(-) delete mode 100644 reactions/sdk/dotnet/Drasi.Reaction.SDK/Makefile rename reactions/sdk/dotnet/Drasi.Reaction.SDK/{ => Models/QueryOutput}/Models.cs (77%) rename reactions/sdk/dotnet/Drasi.Reaction.SDK/{ => Models/QueryOutput}/Models.generated.cs (95%) create mode 100644 reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/ViewService/Models.cs create mode 100644 reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/ViewService/Models.generated.cs create mode 100644 reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IResultViewClient.cs create mode 100644 reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/ResultViewClient.cs create mode 100644 reactions/sdk/dotnet/Makefile create mode 100644 typespec/view-svc/.gitignore create mode 100644 typespec/view-svc/main.tsp create mode 100644 typespec/view-svc/tspconfig.yaml diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Fixture.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Fixture.cs index 124c3e06..3a8d9b67 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Fixture.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Fixture.cs @@ -1,5 +1,7 @@ -using Drasi.Reaction.SDK.Models; +using Drasi.Reaction.SDK.Models.QueryOutput; using System; +using System.Net; +using System.Net.Sockets; using System.Threading.Channels; namespace Drasi.Reaction.SDK.Tests @@ -19,19 +21,24 @@ public Fixture() QueryDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Directory.CreateDirectory(QueryDirectory); ChangeEventChannel = Channel.CreateUnbounded(); + var port = GetAvailablePort(); Reaction = new ReactionBuilder() .UseChangeEventHandler(async (evt, config) => { await ChangeEventChannel.Writer.WriteAsync(evt); }) - .Configure(x => x["QueryConfigPath"] = QueryDirectory) + .Configure(cfg => + { + cfg["QueryConfigPath"] = QueryDirectory; + cfg["APP_PORT"] = port.ToString(); + }) .Build(); _ = Reaction.StartAsync(); Client = new HttpClient(); - Client.BaseAddress = new Uri("http://localhost:80"); + Client.BaseAddress = new Uri("http://localhost:" + port); } public void ClearChannels() @@ -47,5 +54,20 @@ public void Dispose() Directory.Delete(QueryDirectory, true); _ = Reaction.StopAsync(); } - } + + public static int GetAvailablePort() + { + // Create a TcpListener on port 0 (let OS select an available port) + TcpListener listener = new(IPAddress.Loopback, 0); + listener.Start(); + + // Retrieve the assigned port number + int port = ((IPEndPoint)listener.LocalEndpoint).Port; + + // Stop the listener immediately to free up the port + listener.Stop(); + + return port; + } + } } diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/ReactionTests.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/ReactionTests.cs index 50b973e3..a4928317 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/ReactionTests.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/ReactionTests.cs @@ -1,7 +1,7 @@ namespace Drasi.Reaction.SDK.Tests; using Drasi.Reaction.SDK; -using Drasi.Reaction.SDK.Models; +using Drasi.Reaction.SDK.Models.QueryOutput; using Microsoft.AspNetCore.TestHost; using System.Net.Http.Json; using System.Threading.Channels; diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj index e6df9970..6da94898 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj @@ -13,9 +13,9 @@ Apache-2.0 git https://github.com/drasi-project/drasi-platform.git - 0.1.1 + 0.1.2 drasi.png - 0.1.1-alpha + 0.1.2-alpha README.md diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/IChangeEventHandler.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/IChangeEventHandler.cs index 3f8a75b9..1971f4e9 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/IChangeEventHandler.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/IChangeEventHandler.cs @@ -1,4 +1,4 @@ -using Drasi.Reaction.SDK.Models; +using Drasi.Reaction.SDK.Models.QueryOutput; using System; namespace Drasi.Reaction.SDK diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/IControlEventHandler.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/IControlEventHandler.cs index 1a852738..e878f675 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/IControlEventHandler.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/IControlEventHandler.cs @@ -1,4 +1,4 @@ -using Drasi.Reaction.SDK.Models; +using Drasi.Reaction.SDK.Models.QueryOutput; using System; namespace Drasi.Reaction.SDK diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Makefile b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Makefile deleted file mode 100644 index 7510858b..00000000 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -.PHONY: generate-types - -generate-types: - quicktype --src-lang schema -l cs -o Models.generated.cs ../../../../typespec/query-output/_generated/@typespec/json-schema/*.yaml --framework SystemTextJson --namespace Drasi.Reaction.SDK.Models \ No newline at end of file diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/QueryOutput/Models.cs similarity index 77% rename from reactions/sdk/dotnet/Drasi.Reaction.SDK/Models.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/QueryOutput/Models.cs index 83737a02..7a9f6dd9 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/QueryOutput/Models.cs @@ -1,6 +1,6 @@ using System.Text.Json; -namespace Drasi.Reaction.SDK.Models +namespace Drasi.Reaction.SDK.Models.QueryOutput { public static class ModelOptions { diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models.generated.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/QueryOutput/Models.generated.cs similarity index 95% rename from reactions/sdk/dotnet/Drasi.Reaction.SDK/Models.generated.cs rename to reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/QueryOutput/Models.generated.cs index 7e8afc02..731f3348 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models.generated.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/QueryOutput/Models.generated.cs @@ -2,7 +2,7 @@ // // To parse this JSON data, add NuGet 'System.Text.Json' then do one of these: // -// using Drasi.Reaction.SDK.Models; +// using Drasi.Reaction.SDK.Models.QueryOutput; // // var bootstrapCompletedSignal = BootstrapCompletedSignal.FromJson(jsonString); // var bootstrapStartedSignal = BootstrapStartedSignal.FromJson(jsonString); @@ -20,7 +20,7 @@ #pragma warning disable CS8601 #pragma warning disable CS8603 -namespace Drasi.Reaction.SDK.Models +namespace Drasi.Reaction.SDK.Models.QueryOutput { using System; using System.Collections.Generic; @@ -255,72 +255,72 @@ public enum VersionsEnum { V1 }; public partial class BootstrapCompletedSignal { - public static BootstrapCompletedSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + public static BootstrapCompletedSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); } public partial class BootstrapStartedSignal { - public static BootstrapStartedSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + public static BootstrapStartedSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); } public partial class ChangeEvent { - public static ChangeEvent FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + public static ChangeEvent FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); } public partial class ControlEvent { - public static ControlEvent FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + public static ControlEvent FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); } public partial class ControlSignal { - public static ControlSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + public static ControlSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); } public partial class DeletedSignal { - public static DeletedSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + public static DeletedSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); } public partial class ResultEvent { - public static ResultEvent FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + public static ResultEvent FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); } public partial class RunningSignal { - public static RunningSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + public static RunningSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); } public partial class StoppedSignal { - public static StoppedSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + public static StoppedSignal FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); } public partial class UpdatePayload { - public static UpdatePayload FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + public static UpdatePayload FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); } public class Versions { - public static VersionsEnum FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.Converter.Settings); + public static VersionsEnum FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); } public static class Serialize { - public static string ToJson(this BootstrapCompletedSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); - public static string ToJson(this BootstrapStartedSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); - public static string ToJson(this ChangeEvent self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); - public static string ToJson(this ControlEvent self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); - public static string ToJson(this ControlSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); - public static string ToJson(this DeletedSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); - public static string ToJson(this ResultEvent self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); - public static string ToJson(this RunningSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); - public static string ToJson(this StoppedSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); - public static string ToJson(this UpdatePayload self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); - public static string ToJson(this VersionsEnum self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.Converter.Settings); + public static string ToJson(this BootstrapCompletedSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); + public static string ToJson(this BootstrapStartedSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); + public static string ToJson(this ChangeEvent self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); + public static string ToJson(this ControlEvent self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); + public static string ToJson(this ControlSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); + public static string ToJson(this DeletedSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); + public static string ToJson(this ResultEvent self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); + public static string ToJson(this RunningSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); + public static string ToJson(this StoppedSignal self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); + public static string ToJson(this UpdatePayload self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); + public static string ToJson(this VersionsEnum self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.QueryOutput.Converter.Settings); } internal static class Converter diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/ViewService/Models.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/ViewService/Models.cs new file mode 100644 index 00000000..aaecb658 --- /dev/null +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/ViewService/Models.cs @@ -0,0 +1,12 @@ +using System.Text.Json; + +namespace Drasi.Reaction.SDK.Models.ViewService +{ + public static class ModelOptions + { + public static JsonSerializerOptions JsonOptions => Converter.Settings; + } +} + + + diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/ViewService/Models.generated.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/ViewService/Models.generated.cs new file mode 100644 index 00000000..382f453d --- /dev/null +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/ViewService/Models.generated.cs @@ -0,0 +1,239 @@ +// +// +// To parse this JSON data, add NuGet 'System.Text.Json' then do one of these: +// +// using Drasi.Reaction.SDK.Models.ViewService; +// +// var data = Data.FromJson(jsonString); +// var header = Header.FromJson(jsonString); +// var headerItem = HeaderItem.FromJson(jsonString); +// var viewItem = ViewItem.FromJson(jsonString); +#nullable enable +#pragma warning disable CS8618 +#pragma warning disable CS8601 +#pragma warning disable CS8603 + +namespace Drasi.Reaction.SDK.Models.ViewService +{ + using System; + using System.Collections.Generic; + + using System.Text.Json; + using System.Text.Json.Serialization; + using System.Globalization; + + public partial class Data + { + [JsonPropertyName("data")] + public Dictionary DataData { get; set; } + } + + public partial class Header + { + [JsonPropertyName("header")] + public HeaderClass HeaderHeader { get; set; } + } + + public partial class HeaderClass + { + ///

+ /// The sequence number of the event + /// + [JsonPropertyName("sequence")] + public long Sequence { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("state")] + public string State { get; set; } + + /// + /// The time at which the source change was recorded + /// + [JsonPropertyName("timestamp")] + public long Timestamp { get; set; } + } + + public partial class HeaderItem + { + /// + /// The sequence number of the event + /// + [JsonPropertyName("sequence")] + public long Sequence { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("state")] + public string State { get; set; } + + /// + /// The time at which the source change was recorded + /// + [JsonPropertyName("timestamp")] + public long Timestamp { get; set; } + } + + public partial class ViewItem + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("header")] + public HeaderClass Header { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("data")] + public Dictionary Data { get; set; } + } + + public partial class Data + { + public static Data FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.ViewService.Converter.Settings); + } + + public partial class Header + { + public static Header FromJson(string json) => JsonSerializer.Deserialize
(json, Drasi.Reaction.SDK.Models.ViewService.Converter.Settings); + } + + public partial class HeaderItem + { + public static HeaderItem FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.ViewService.Converter.Settings); + } + + public partial class ViewItem + { + public static ViewItem FromJson(string json) => JsonSerializer.Deserialize(json, Drasi.Reaction.SDK.Models.ViewService.Converter.Settings); + } + + public static class Serialize + { + public static string ToJson(this Data self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.ViewService.Converter.Settings); + public static string ToJson(this Header self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.ViewService.Converter.Settings); + public static string ToJson(this HeaderItem self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.ViewService.Converter.Settings); + public static string ToJson(this ViewItem self) => JsonSerializer.Serialize(self, Drasi.Reaction.SDK.Models.ViewService.Converter.Settings); + } + + internal static class Converter + { + public static readonly JsonSerializerOptions Settings = new(JsonSerializerDefaults.General) + { + Converters = + { + new DateOnlyConverter(), + new TimeOnlyConverter(), + IsoDateTimeOffsetConverter.Singleton + }, + }; + } + + public class DateOnlyConverter : JsonConverter + { + private readonly string serializationFormat; + public DateOnlyConverter() : this(null) { } + + public DateOnlyConverter(string? serializationFormat) + { + this.serializationFormat = serializationFormat ?? "yyyy-MM-dd"; + } + + public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + return DateOnly.Parse(value!); + } + + public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options) + => writer.WriteStringValue(value.ToString(serializationFormat)); + } + + public class TimeOnlyConverter : JsonConverter + { + private readonly string serializationFormat; + + public TimeOnlyConverter() : this(null) { } + + public TimeOnlyConverter(string? serializationFormat) + { + this.serializationFormat = serializationFormat ?? "HH:mm:ss.fff"; + } + + public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + return TimeOnly.Parse(value!); + } + + public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options) + => writer.WriteStringValue(value.ToString(serializationFormat)); + } + + internal class IsoDateTimeOffsetConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(DateTimeOffset); + + private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; + + private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind; + private string? _dateTimeFormat; + private CultureInfo? _culture; + + public DateTimeStyles DateTimeStyles + { + get => _dateTimeStyles; + set => _dateTimeStyles = value; + } + + public string? DateTimeFormat + { + get => _dateTimeFormat ?? string.Empty; + set => _dateTimeFormat = (string.IsNullOrEmpty(value)) ? null : value; + } + + public CultureInfo Culture + { + get => _culture ?? CultureInfo.CurrentCulture; + set => _culture = value; + } + + public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) + { + string text; + + + if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal + || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) + { + value = value.ToUniversalTime(); + } + + text = value.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture); + + writer.WriteStringValue(text); + } + + public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + string? dateText = reader.GetString(); + + if (string.IsNullOrEmpty(dateText) == false) + { + if (!string.IsNullOrEmpty(_dateTimeFormat)) + { + return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles); + } + else + { + return DateTimeOffset.Parse(dateText, Culture, _dateTimeStyles); + } + } + else + { + return default(DateTimeOffset); + } + } + + + public static readonly IsoDateTimeOffsetConverter Singleton = new IsoDateTimeOffsetConverter(); + } +} +#pragma warning restore CS8618 +#pragma warning restore CS8601 +#pragma warning restore CS8603 diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs index 9c7239c3..7f22d939 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Reaction.cs @@ -1,4 +1,4 @@ -using Drasi.Reaction.SDK.Models; +using Drasi.Reaction.SDK.Models.QueryOutput; using Drasi.Reaction.SDK.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/ReactionBuilder.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/ReactionBuilder.cs index 345c1b53..76bac9ba 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/ReactionBuilder.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/ReactionBuilder.cs @@ -4,7 +4,7 @@ using Drasi.Reaction.SDK.Services; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; -using Drasi.Reaction.SDK.Models; +using Drasi.Reaction.SDK.Models.QueryOutput; namespace Drasi.Reaction.SDK { @@ -27,6 +27,7 @@ public ReactionBuilder() _webappBuilder.Services.AddControllers(); _webappBuilder.Services.AddSingleton(); _webappBuilder.Services.AddSingleton(); + _webappBuilder.Services.AddSingleton(); _webappBuilder.Services.AddScoped, DefaultControlEventHandler>(); _webappBuilder.Configuration.AddEnvironmentVariables(); _webappBuilder.Logging.AddConsole(); diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/DefaultControlEventHandler.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/DefaultControlEventHandler.cs index abb49eae..ae25a92c 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/DefaultControlEventHandler.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/DefaultControlEventHandler.cs @@ -1,4 +1,4 @@ -using Drasi.Reaction.SDK.Models; +using Drasi.Reaction.SDK.Models.QueryOutput; using Microsoft.Extensions.Logging; using System; diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IResultViewClient.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IResultViewClient.cs new file mode 100644 index 00000000..89bcd26b --- /dev/null +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IResultViewClient.cs @@ -0,0 +1,9 @@ +using System; +using Drasi.Reaction.SDK.Models.ViewService; + +namespace Drasi.Reaction.SDK.Services; + +public interface IResultViewClient +{ + IAsyncEnumerable GetCurrentResult(string queryContainerId, string queryId, CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/InlineChangeEventHandler.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/InlineChangeEventHandler.cs index 0861ddcf..f3d9d754 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/InlineChangeEventHandler.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/InlineChangeEventHandler.cs @@ -1,9 +1,5 @@ -using Drasi.Reaction.SDK.Models; +using Drasi.Reaction.SDK.Models.QueryOutput; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Drasi.Reaction.SDK.Services { diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/ResultViewClient.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/ResultViewClient.cs new file mode 100644 index 00000000..ebc2681e --- /dev/null +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/ResultViewClient.cs @@ -0,0 +1,57 @@ +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text.Json; +using System.Runtime.CompilerServices; +using Drasi.Reaction.SDK.Models.ViewService; + +namespace Drasi.Reaction.SDK.Services; + +public class ResultViewClient : IResultViewClient +{ + private readonly HttpClient _httpClient; + + public ResultViewClient() + { + _httpClient = new HttpClient(); + } + + public async IAsyncEnumerable GetCurrentResult(string queryContainerId, string queryId, [EnumeratorCancellation]CancellationToken cancellationToken = default) + { + Stream? stream = null; + try + { + stream = await _httpClient.GetStreamAsync($"http://{queryContainerId}-view-svc/{queryId}", cancellationToken); + } + catch (HttpRequestException ex) + { + Console.WriteLine("Error getting current result: " + ex.Message); + yield break; + } + + if (stream == null) + { + yield break; + } + + + await foreach (var item in JsonSerializer.DeserializeAsyncEnumerable(stream, ModelOptions.JsonOptions, cancellationToken)) + { + if (item != null) + { + yield return item; + } + } + } +} diff --git a/reactions/sdk/dotnet/Makefile b/reactions/sdk/dotnet/Makefile new file mode 100644 index 00000000..0ef657c7 --- /dev/null +++ b/reactions/sdk/dotnet/Makefile @@ -0,0 +1,18 @@ +.PHONY: generate-types install-dependencies test package + +install-dependencies: + dotnet restore + npm install --prefix ../../../typespec + +generate-types: + npm run clean --prefix ../../../typespec + npm run build ./view-svc --prefix ../../../typespec + npm run build ./query-output --prefix ../../../typespec + quicktype --src-lang schema -l cs -o Drasi.Reaction.SDK/Models/QueryOutput/Models.generated.cs ../../../typespec/query-output/_generated/@typespec/json-schema/*.yaml --framework SystemTextJson --namespace Drasi.Reaction.SDK.Models.QueryOutput + quicktype --src-lang schema -l cs -o Drasi.Reaction.SDK/Models/ViewService/Models.generated.cs ../../../typespec/view-svc/_generated/@typespec/json-schema/*.yaml --framework SystemTextJson --namespace Drasi.Reaction.SDK.Models.ViewService + +test: + dotnet test + +package: + dotnet pack Drasi.Reaction.SDK/Drasi.Reaction.SDK.csproj -c Release \ No newline at end of file diff --git a/reactions/sdk/dotnet/examples/advanced-reaction/Program.cs b/reactions/sdk/dotnet/examples/advanced-reaction/Program.cs index a934df2d..5d52002e 100644 --- a/reactions/sdk/dotnet/examples/advanced-reaction/Program.cs +++ b/reactions/sdk/dotnet/examples/advanced-reaction/Program.cs @@ -1,6 +1,6 @@ using System.Text.Json.Serialization; using Drasi.Reaction.SDK; -using Drasi.Reaction.SDK.Models; +using Drasi.Reaction.SDK.Models.QueryOutput; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/typespec/package-lock.json b/typespec/package-lock.json index cd5b3ff3..2c0d0907 100644 --- a/typespec/package-lock.json +++ b/typespec/package-lock.json @@ -14,7 +14,8 @@ "@typespec/openapi3": "^0.61.0" }, "devDependencies": { - "@typespec/compiler": "latest" + "@typespec/compiler": "latest", + "rimraf": "^6.0.1" }, "peerDependencies": { "@azure-tools/typespec-autorest": "latest", @@ -214,6 +215,102 @@ "node": ">=10.10.0" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@jsdevtools/ono": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", @@ -699,6 +796,26 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "license": "MIT" }, + "node_modules/cross-spawn": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz", + "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -772,6 +889,22 @@ "node": ">=8" } }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/fs-extra": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", @@ -795,6 +928,29 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/glob": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -807,6 +963,21 @@ "node": ">= 6" } }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/globby": { "version": "14.0.2", "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", @@ -917,6 +1088,27 @@ "node": ">=0.12.0" } }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -999,6 +1191,15 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, + "node_modules/lru-cache": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", + "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", + "dev": true, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -1045,6 +1246,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", @@ -1082,12 +1292,43 @@ "license": "MIT", "peer": true }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", "license": "MIT" }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/path-type": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", @@ -1210,6 +1451,25 @@ "node": ">=0.10.0" } }, + "node_modules/rimraf": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", + "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", + "dev": true, + "dependencies": { + "glob": "^11.0.0", + "package-json-from-dist": "^1.0.0" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -1245,6 +1505,39 @@ "node": ">=10" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -1286,6 +1579,21 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -1298,6 +1606,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -1430,6 +1751,21 @@ "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", "license": "MIT" }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -1453,6 +1789,57 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", diff --git a/typespec/package.json b/typespec/package.json index 950afbfb..b0f664b3 100644 --- a/typespec/package.json +++ b/typespec/package.json @@ -2,6 +2,10 @@ "name": "drasi", "version": "0.1.0", "type": "module", + "scripts": { + "clean": "rimraf **/_generated/@typespec", + "build": "tsp compile" + }, "peerDependencies": { "@azure-tools/typespec-autorest": "latest", "@azure-tools/typespec-azure-core": "latest", @@ -14,7 +18,8 @@ "@typespec/versioning": "^0.61.0" }, "devDependencies": { - "@typespec/compiler": "latest" + "@typespec/compiler": "latest", + "rimraf": "^6.0.1" }, "private": true, "license": "Apache-2.0", diff --git a/typespec/view-svc/.gitignore b/typespec/view-svc/.gitignore new file mode 100644 index 00000000..94f0f0d9 --- /dev/null +++ b/typespec/view-svc/.gitignore @@ -0,0 +1 @@ +_generated \ No newline at end of file diff --git a/typespec/view-svc/main.tsp b/typespec/view-svc/main.tsp new file mode 100644 index 00000000..56b3706b --- /dev/null +++ b/typespec/view-svc/main.tsp @@ -0,0 +1,33 @@ +import "@typespec/json-schema"; + +using TypeSpec.JsonSchema; + +@jsonSchema +namespace Drasi.View; + +@extension("title", "ViewItem") +union ViewItem { + header: Header; + data: Data; +} + +@extension("title", "Header") +model Header { + header: HeaderItem; +} + +@extension("title", "Data") +model Data { + data: Record; +} + +@extension("title", "HeaderItem") +model HeaderItem { + @doc("The sequence number of the event") + sequence: int64; + + @doc("The time at which the source change was recorded") + timestamp: int64; + + state?: string; +} diff --git a/typespec/view-svc/tspconfig.yaml b/typespec/view-svc/tspconfig.yaml new file mode 100644 index 00000000..92f2cf81 --- /dev/null +++ b/typespec/view-svc/tspconfig.yaml @@ -0,0 +1,8 @@ +emit: + - "@typespec/json-schema" +options: + "@typespec/json-schema": + file-type: "yaml" + int64-strategy: "number" + +output-dir: "{project-root}/_generated" \ No newline at end of file From dfad36aa6516feb9f44178941502ff258298d264 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 8 Nov 2024 15:40:07 -0800 Subject: [PATCH 16/17] license headers --- .../dotnet/Drasi.Reaction.SDK.Tests/Fixture.cs | 16 +++++++++++++++- .../Drasi.Reaction.SDK.Tests/ReactionTests.cs | 14 ++++++++++++++ .../Drasi.Reaction.SDK/IChangeEventHandler.cs | 16 +++++++++++++++- .../Drasi.Reaction.SDK/IControlEventHandler.cs | 16 +++++++++++++++- .../Models/QueryOutput/Models.cs | 14 ++++++++++++++ .../Models/ViewService/Models.cs | 17 ++++++++++++++--- .../Drasi.Reaction.SDK/ReactionBuilder.cs | 16 +++++++++++++++- .../Services/DefaultControlEventHandler.cs | 16 +++++++++++++++- .../Services/IConfigDeserializer.cs | 16 +++++++++++++++- .../Services/IQueryConfigService.cs | 15 ++++++++++++++- .../Services/IResultViewClient.cs | 14 ++++++++++++++ .../Services/InlineChangeEventHandler.cs | 16 +++++++++++++++- .../Services/JsonConfigDeserializer.cs | 16 +++++++++++++++- .../Services/NullConfigDeserializer.cs | 16 +++++++++++++++- .../Services/QueryConfigService.cs | 16 +++++++++++++++- .../Services/YamlConfigDeserializer.cs | 16 +++++++++++++++- 16 files changed, 235 insertions(+), 15 deletions(-) diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Fixture.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Fixture.cs index 3a8d9b67..811c1357 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Fixture.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/Fixture.cs @@ -1,4 +1,18 @@ -using Drasi.Reaction.SDK.Models.QueryOutput; +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Drasi.Reaction.SDK.Models.QueryOutput; using System; using System.Net; using System.Net.Sockets; diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/ReactionTests.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/ReactionTests.cs index a4928317..d3aac81f 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/ReactionTests.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK.Tests/ReactionTests.cs @@ -1,3 +1,17 @@ +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + namespace Drasi.Reaction.SDK.Tests; using Drasi.Reaction.SDK; diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/IChangeEventHandler.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/IChangeEventHandler.cs index 1971f4e9..fbb7508d 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/IChangeEventHandler.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/IChangeEventHandler.cs @@ -1,4 +1,18 @@ -using Drasi.Reaction.SDK.Models.QueryOutput; +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Drasi.Reaction.SDK.Models.QueryOutput; using System; namespace Drasi.Reaction.SDK diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/IControlEventHandler.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/IControlEventHandler.cs index e878f675..a5cc8817 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/IControlEventHandler.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/IControlEventHandler.cs @@ -1,4 +1,18 @@ -using Drasi.Reaction.SDK.Models.QueryOutput; +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Drasi.Reaction.SDK.Models.QueryOutput; using System; namespace Drasi.Reaction.SDK diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/QueryOutput/Models.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/QueryOutput/Models.cs index 7a9f6dd9..05390086 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/QueryOutput/Models.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/QueryOutput/Models.cs @@ -1,3 +1,17 @@ +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + using System.Text.Json; namespace Drasi.Reaction.SDK.Models.QueryOutput diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/ViewService/Models.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/ViewService/Models.cs index aaecb658..7035efa6 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/ViewService/Models.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Models/ViewService/Models.cs @@ -1,3 +1,17 @@ +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + using System.Text.Json; namespace Drasi.Reaction.SDK.Models.ViewService @@ -7,6 +21,3 @@ public static class ModelOptions public static JsonSerializerOptions JsonOptions => Converter.Settings; } } - - - diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/ReactionBuilder.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/ReactionBuilder.cs index 76bac9ba..a753b881 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/ReactionBuilder.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/ReactionBuilder.cs @@ -1,4 +1,18 @@ -using System; +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Drasi.Reaction.SDK.Services; diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/DefaultControlEventHandler.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/DefaultControlEventHandler.cs index ae25a92c..0d05989c 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/DefaultControlEventHandler.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/DefaultControlEventHandler.cs @@ -1,4 +1,18 @@ -using Drasi.Reaction.SDK.Models.QueryOutput; +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Drasi.Reaction.SDK.Models.QueryOutput; using Microsoft.Extensions.Logging; using System; diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IConfigDeserializer.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IConfigDeserializer.cs index 91ed585e..bf9f3ab9 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IConfigDeserializer.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IConfigDeserializer.cs @@ -1,4 +1,18 @@ -namespace Drasi.Reaction.SDK.Services +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Drasi.Reaction.SDK.Services { public interface IConfigDeserializer { diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IQueryConfigService.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IQueryConfigService.cs index 5de040b7..c20daca8 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IQueryConfigService.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IQueryConfigService.cs @@ -1,4 +1,17 @@ - +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + namespace Drasi.Reaction.SDK.Services { public interface IQueryConfigService diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IResultViewClient.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IResultViewClient.cs index 89bcd26b..9de7d225 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IResultViewClient.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/IResultViewClient.cs @@ -1,3 +1,17 @@ +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + using System; using Drasi.Reaction.SDK.Models.ViewService; diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/InlineChangeEventHandler.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/InlineChangeEventHandler.cs index f3d9d754..a508f199 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/InlineChangeEventHandler.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/InlineChangeEventHandler.cs @@ -1,4 +1,18 @@ -using Drasi.Reaction.SDK.Models.QueryOutput; +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Drasi.Reaction.SDK.Models.QueryOutput; using System; namespace Drasi.Reaction.SDK.Services diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/JsonConfigDeserializer.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/JsonConfigDeserializer.cs index a8578691..9622c271 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/JsonConfigDeserializer.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/JsonConfigDeserializer.cs @@ -1,4 +1,18 @@ -using System; +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; using System.Text.Json; namespace Drasi.Reaction.SDK.Services diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/NullConfigDeserializer.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/NullConfigDeserializer.cs index 392880eb..1af27135 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/NullConfigDeserializer.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/NullConfigDeserializer.cs @@ -1,4 +1,18 @@ -using System; +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; using System.Text.Json; namespace Drasi.Reaction.SDK.Services diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/QueryConfigService.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/QueryConfigService.cs index 94bd698a..78f5c17c 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/QueryConfigService.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/QueryConfigService.cs @@ -1,4 +1,18 @@ -using Microsoft.Extensions.Configuration; +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Microsoft.Extensions.Configuration; using System; namespace Drasi.Reaction.SDK.Services diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/YamlConfigDeserializer.cs b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/YamlConfigDeserializer.cs index 34313273..05051cee 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/YamlConfigDeserializer.cs +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/Services/YamlConfigDeserializer.cs @@ -1,4 +1,18 @@ -using System; +// Copyright 2024 The Drasi Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; using System.Collections.Generic; using System.Linq; using System.Text; From 5ceb11dcda61f93726ad993ff474fe6da49ebdad Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 13 Nov 2024 08:31:31 -0800 Subject: [PATCH 17/17] Update README.md typo --- reactions/sdk/dotnet/Drasi.Reaction.SDK/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reactions/sdk/dotnet/Drasi.Reaction.SDK/README.md b/reactions/sdk/dotnet/Drasi.Reaction.SDK/README.md index 9c24cd6a..e2e7a9c5 100644 --- a/reactions/sdk/dotnet/Drasi.Reaction.SDK/README.md +++ b/reactions/sdk/dotnet/Drasi.Reaction.SDK/README.md @@ -42,7 +42,7 @@ The following example illustrates - Retrieving a configuration value from the Reaction manifest - Defining a custom per query configuration object - Parsing the per query configuration object from Yaml - - Process change events form thw query + - Process change events from the query - Process control events (start, stop, etc.) from the query @@ -119,4 +119,4 @@ class MyControlSignalHandler : IControlEventHandler _logger.LogWarning($"Received control signal: {evt.ControlSignal?.Kind} for query {evt.QueryId}. Query greeting is {queryConfig?.Greeting}"); } } -``` \ No newline at end of file +```