├── .eslintrc.js ├── .github └── workflows │ ├── check-version.yaml │ ├── publish.yaml │ ├── release-rc.yaml │ ├── release.yaml │ └── test.yaml ├── .gitignore ├── .licensee.json ├── .npmignore ├── .prettierignore ├── .prettierrc.js ├── CHANGELOG.md ├── LICENSE ├── README.md ├── assets ├── license_header.txt └── nitric-logo.svg ├── jest.config.ts ├── licenseconfig.json ├── package.json ├── scripts └── check-nitric-version.ts ├── src ├── api │ ├── batch │ │ └── v1 │ │ │ ├── batch.ts │ │ │ ├── index.ts │ │ │ ├── job.test.ts │ │ │ └── job.ts │ ├── errors │ │ ├── index.test.ts │ │ ├── index.ts │ │ └── provider-error.ts │ ├── index.ts │ ├── keyvalue │ │ ├── index.ts │ │ └── v1 │ │ │ ├── index.ts │ │ │ ├── keyvalue.test.ts │ │ │ ├── keyvalue.ts │ │ │ └── store.ts │ ├── queues │ │ ├── index.ts │ │ └── v1 │ │ │ ├── index.ts │ │ │ ├── queues.test.ts │ │ │ └── queues.ts │ ├── secrets │ │ ├── index.ts │ │ └── v1 │ │ │ ├── index.ts │ │ │ ├── secret.test.ts │ │ │ └── secrets.ts │ ├── storage │ │ ├── index.ts │ │ └── v1 │ │ │ ├── index.ts │ │ │ ├── storage.test.ts │ │ │ └── storage.ts │ ├── topics │ │ ├── index.ts │ │ └── v1 │ │ │ ├── index.ts │ │ │ ├── topics.test.ts │ │ │ └── topics.ts │ └── websocket │ │ ├── index.ts │ │ └── v1 │ │ ├── index.ts │ │ └── websocket.ts ├── constants.ts ├── context │ ├── base.ts │ ├── bucket.ts │ ├── http.ts │ ├── index.ts │ ├── interval.ts │ ├── job.ts │ ├── message.ts │ └── websocket.ts ├── gen │ └── nitric │ │ └── proto │ │ ├── apis │ │ └── v1 │ │ │ ├── apis_grpc_pb.d.ts │ │ │ ├── apis_grpc_pb.js │ │ │ ├── apis_pb.d.ts │ │ │ └── apis_pb.js │ │ ├── batch │ │ └── v1 │ │ │ ├── batch_grpc_pb.d.ts │ │ │ ├── batch_grpc_pb.js │ │ │ ├── batch_pb.d.ts │ │ │ └── batch_pb.js │ │ ├── deployments │ │ └── v1 │ │ │ ├── deployments_grpc_pb.d.ts │ │ │ ├── deployments_grpc_pb.js │ │ │ ├── deployments_pb.d.ts │ │ │ └── deployments_pb.js │ │ ├── http │ │ └── v1 │ │ │ ├── http_grpc_pb.d.ts │ │ │ ├── http_grpc_pb.js │ │ │ ├── http_pb.d.ts │ │ │ └── http_pb.js │ │ ├── keyvalue │ │ └── v1 │ │ │ ├── keyvalue_grpc_pb.d.ts │ │ │ ├── keyvalue_grpc_pb.js │ │ │ ├── keyvalue_pb.d.ts │ │ │ └── keyvalue_pb.js │ │ ├── kvstore │ │ └── v1 │ │ │ ├── kvstore_grpc_pb.d.ts │ │ │ ├── kvstore_grpc_pb.js │ │ │ ├── kvstore_pb.d.ts │ │ │ └── kvstore_pb.js │ │ ├── queues │ │ └── v1 │ │ │ ├── queues_grpc_pb.d.ts │ │ │ ├── queues_grpc_pb.js │ │ │ ├── queues_pb.d.ts │ │ │ └── queues_pb.js │ │ ├── resources │ │ └── v1 │ │ │ ├── resources_grpc_pb.d.ts │ │ │ ├── resources_grpc_pb.js │ │ │ ├── resources_pb.d.ts │ │ │ └── resources_pb.js │ │ ├── schedules │ │ └── v1 │ │ │ ├── schedules_grpc_pb.d.ts │ │ │ ├── schedules_grpc_pb.js │ │ │ ├── schedules_pb.d.ts │ │ │ └── schedules_pb.js │ │ ├── secrets │ │ └── v1 │ │ │ ├── secrets_grpc_pb.d.ts │ │ │ ├── secrets_grpc_pb.js │ │ │ ├── secrets_pb.d.ts │ │ │ └── secrets_pb.js │ │ ├── sql │ │ └── v1 │ │ │ ├── sql_grpc_pb.d.ts │ │ │ ├── sql_grpc_pb.js │ │ │ ├── sql_pb.d.ts │ │ │ └── sql_pb.js │ │ ├── storage │ │ └── v1 │ │ │ ├── storage_grpc_pb.d.ts │ │ │ ├── storage_grpc_pb.js │ │ │ ├── storage_pb.d.ts │ │ │ └── storage_pb.js │ │ ├── topics │ │ └── v1 │ │ │ ├── topics_grpc_pb.d.ts │ │ │ ├── topics_grpc_pb.js │ │ │ ├── topics_pb.d.ts │ │ │ └── topics_pb.js │ │ └── websockets │ │ └── v1 │ │ ├── websockets_grpc_pb.d.ts │ │ ├── websockets_grpc_pb.js │ │ ├── websockets_pb.d.ts │ │ └── websockets_pb.js ├── handlers │ ├── handler.test.ts │ ├── handler.ts │ ├── index.ts │ └── json.ts ├── index.ts ├── lifecycle │ ├── index.ts │ └── lifecycle.ts ├── resources │ ├── api.test.ts │ ├── api.ts │ ├── batch.test.ts │ ├── batch.ts │ ├── bucket.test.ts │ ├── bucket.ts │ ├── client.ts │ ├── common.test.ts │ ├── common.ts │ ├── http.test.ts │ ├── http.ts │ ├── index.ts │ ├── keyvalue.test.ts │ ├── keyvalue.ts │ ├── oidc.ts │ ├── queue.test.ts │ ├── queue.ts │ ├── schedule.test.ts │ ├── schedule.ts │ ├── secret.test.ts │ ├── secret.ts │ ├── sql.ts │ ├── topic.test.ts │ ├── topic.ts │ ├── websocket.test.ts │ └── websocket.ts └── types.ts ├── tsconfig.json └── yarn.lock /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | ignorePatterns: ['src/gen/**/*.ts', 'src/**/*.test.ts'], 4 | env: { 5 | node: true, 6 | }, 7 | plugins: ['jsdoc'], 8 | extends: [ 9 | 'plugin:@typescript-eslint/eslint-recommended', 10 | 'plugin:@typescript-eslint/recommended', 11 | 'plugin:jsdoc/recommended-typescript-error', 12 | ], 13 | rules: { 14 | '@typescript-eslint/explicit-function-return-type': 'off', 15 | '@typescript-eslint/ban-ts-ignore': 'off', 16 | '@typescript-eslint/no-explicit-any': 'off', 17 | 'jsdoc/tag-lines': 'off', // not documented on jsdoc plugin site, unsure how to correct. 18 | '@typescript-eslint/no-unused-vars': [ 19 | 'error', 20 | { args: 'all', argsIgnorePattern: '^_' }, 21 | ], 22 | 'no-warning-comments': [ 23 | 'error', 24 | { 25 | terms: ['todo', 'fixme'], 26 | location: 'anywhere', 27 | }, 28 | ], 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /.github/workflows/check-version.yaml: -------------------------------------------------------------------------------- 1 | name: Check Nitric Version 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v2 14 | - name: Cache Yarn Cache 15 | uses: actions/cache@v4 16 | with: 17 | path: 'node_modules' 18 | key: ${{ runner.os }}-modules-${{ hashFiles('yarn.lock') }} 19 | - name: Install modules 20 | run: yarn --frozen-lockfile 21 | - name: Check nitric version 22 | run: yarn check-nitric 23 | -------------------------------------------------------------------------------- /.github/workflows/publish.yaml: -------------------------------------------------------------------------------- 1 | name: Publish to NPM on Github Release 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | publish: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v2 14 | with: 15 | token: ${{ secrets.NITRIC_BOT_TOKEN }} 16 | 17 | - name: Cache Dependencies 18 | uses: actions/cache@v4 19 | with: 20 | path: 'node_modules' 21 | key: ${{ runner.os }}-modules-${{ hashFiles('yarn.lock') }} 22 | 23 | - name: Use Node 20 24 | uses: actions/setup-node@v1 25 | with: 26 | node-version: 20 27 | registry-url: 'https://registry.npmjs.org' 28 | always-auth: true 29 | 30 | - name: Git Identity 31 | run: | 32 | git config --global user.name 'nitric-bot[bot]' 33 | git config --global user.email 'maintainers@nitric.io' 34 | 35 | - name: Set Version 36 | # Tag will already be created by release flow 37 | run: npm version --no-git-tag-version ${{ github.event.release.tag_name }} 38 | 39 | - name: Install Dependencies 40 | run: yarn install --frozen-lockfile 41 | 42 | - name: Build 43 | run: yarn build 44 | 45 | - name: Publish latest to NPM 46 | if: '!github.event.release.prerelease' 47 | run: npm publish --access public 48 | env: 49 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 50 | 51 | - name: Publish latest RC to NPM 52 | if: 'github.event.release.prerelease' 53 | run: npm publish --access public --tag rc-latest 54 | env: 55 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 56 | -------------------------------------------------------------------------------- /.github/workflows/release-rc.yaml: -------------------------------------------------------------------------------- 1 | name: Release Candidate 2 | on: 3 | push: 4 | branches: 5 | - develop 6 | 7 | jobs: 8 | # Bump the membrane version 9 | version_bump: 10 | name: Bump Version and Create Release 11 | runs-on: ubuntu-latest 12 | outputs: 13 | version_id: ${{ steps.tag_version.outputs.new_tag }} 14 | upload_url: ${{ steps.create_release.outputs.upload_url }} 15 | steps: 16 | - uses: actions/checkout@v2 17 | with: 18 | fetch-depth: 0 19 | - name: Bump version and push tag 20 | id: tag_version 21 | uses: mathieudutour/github-tag-action@v5.5 22 | with: 23 | # Don't commit tag 24 | # this will be done as part of the release 25 | dry_run: true 26 | github_token: ${{ secrets.GITHUB_TOKEN }} 27 | release_branches: main,develop 28 | 29 | - name: Calculate RC number 30 | id: vars 31 | run: echo "::set-output name=rc_num::$(git rev-list --merges --count origin/develop...origin/main)" 32 | 33 | - name: Create a GitHub release 34 | id: create_release 35 | uses: actions/create-release@v1 36 | env: 37 | # Use NITRIC_BOT_TOKEN here to 38 | # trigger release 'published' workflows 39 | GITHUB_TOKEN: ${{ secrets.NITRIC_BOT_TOKEN }} 40 | with: 41 | prerelease: true 42 | tag_name: ${{ steps.tag_version.outputs.new_tag }}-rc.${{ steps.vars.outputs.rc_num }} 43 | release_name: Release ${{ steps.tag_version.outputs.new_tag }}-rc.${{ steps.vars.outputs.rc_num }} 44 | body: ${{ steps.tag_version.outputs.changelog }}-rc.${{ steps.vars.outputs.rc_num }} -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Production Release 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | # Bump the membrane version 8 | version_bump: 9 | name: Bump Version and Create Release 10 | runs-on: ubuntu-latest 11 | outputs: 12 | version_id: ${{ steps.tag_version.outputs.new_tag }} 13 | upload_url: ${{ steps.create_release.outputs.upload_url }} 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Bump version and push tag 17 | id: tag_version 18 | uses: mathieudutour/github-tag-action@v5.5 19 | with: 20 | # Use GITHUB_TOKEN here to prevent further workflows 21 | # generated on 'tag' action 22 | github_token: ${{ secrets.GITHUB_TOKEN }} 23 | - name: Create a GitHub release 24 | id: create_release 25 | uses: actions/create-release@v1 26 | env: 27 | # Use NITRIC_BOT_TOKEN here to 28 | # trigger release 'published' workflows 29 | GITHUB_TOKEN: ${{ secrets.NITRIC_BOT_TOKEN }} 30 | with: 31 | tag_name: ${{ steps.tag_version.outputs.new_tag }} 32 | release_name: Release ${{ steps.tag_version.outputs.new_tag }} 33 | body: ${{ steps.tag_version.outputs.changelog }} -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v2 15 | - name: Cache Yarn Cache 16 | uses: actions/cache@v4 17 | with: 18 | path: 'node_modules' 19 | key: ${{ runner.os }}-modules-${{ hashFiles('yarn.lock') }} 20 | - name: Install modules 21 | run: yarn --frozen-lockfile 22 | - name: License Header Check 23 | run: yarn license:header:check 24 | - name: OSS License Whitelist Check 25 | run: yarn license:check 26 | - name: Check sources 27 | run: | 28 | yarn gen:proto 29 | git add . 30 | git diff --cached --quiet 31 | - name: Check Formatting 32 | run: yarn prettier:check 33 | - name: Linting 34 | run: yarn lint 35 | - name: Build 36 | run: yarn build 37 | - name: Run tests 38 | run: yarn test:coverage 39 | - name: Upload coverage 40 | uses: codecov/codecov-action@v5 41 | with: 42 | token: ${{ secrets.CODECOV_TOKEN }} 43 | gcov_ignore: './src/gen' 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore tmp directory 2 | tmp/ 3 | 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | 12 | # Diagnostic reports (https://nodejs.org/api/report.html) 13 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 14 | 15 | # Runtime data 16 | pids 17 | *.pid 18 | *.seed 19 | *.pid.lock 20 | 21 | # Directory for instrumented libs generated by jscoverage/JSCover 22 | lib-cov 23 | 24 | # Coverage directory used by tools like istanbul 25 | coverage 26 | *.lcov 27 | 28 | # nyc test coverage 29 | .nyc_output 30 | 31 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 32 | .grunt 33 | 34 | # Bower dependency directory (https://bower.io/) 35 | bower_components 36 | 37 | # node-waf configuration 38 | .lock-wscript 39 | 40 | # Compiled binary addons (https://nodejs.org/api/addons.html) 41 | build/Release 42 | 43 | # Dependency directories 44 | node_modules/ 45 | jspm_packages/ 46 | 47 | # TypeScript v1 declaration files 48 | typings/ 49 | 50 | # TypeScript cache 51 | *.tsbuildinfo 52 | 53 | # Optional npm cache directory 54 | .npm 55 | 56 | # Optional eslint cache 57 | .eslintcache 58 | 59 | # Optional REPL history 60 | .node_repl_history 61 | 62 | # Output of 'npm pack' 63 | *.tgz 64 | 65 | # Yarn Integrity file 66 | .yarn-integrity 67 | 68 | # dotenv environment variables file 69 | .env 70 | .env.test 71 | 72 | # parcel-bundler cache (https://parceljs.org/) 73 | .cache 74 | 75 | # next.js build output 76 | .next 77 | 78 | # nuxt.js build output 79 | .nuxt 80 | 81 | # vuepress build output 82 | .vuepress/dist 83 | 84 | # Serverless directories 85 | .serverless/ 86 | 87 | # FuseBox cache 88 | .fusebox/ 89 | 90 | # DynamoDB Local files 91 | .dynamodb/ 92 | 93 | lib/ 94 | 95 | contracts/ 96 | 97 | nitric/** -------------------------------------------------------------------------------- /.licensee.json: -------------------------------------------------------------------------------- 1 | { 2 | "licenses": { 3 | "spdx": [ 4 | "MIT", 5 | "BSD-3-Clause", 6 | "Apache-2.0", 7 | "ISC", 8 | "0BSD" 9 | ] 10 | } 11 | } -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | contracts/ 3 | .git/ 4 | .github/ 5 | .gitmodules 6 | tests/ 7 | coverage/ 8 | node_modules/ 9 | docs/ 10 | jest.config.json 11 | tsconfig.json 12 | yarn.lock 13 | README.md -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/src/gen 2 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | semi: true, 3 | trailingComma: 'es5', 4 | singleQuote: true, 5 | printWidth: 80, 6 | tabWidth: 2, 7 | useTabs: false, 8 | }; 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Nitric Logo 4 | 5 |

6 | 7 |

8 | Build Nitric applications with Node.js 9 |

10 | 11 |

12 | 13 | codecov 14 | 15 | 16 | Version 17 | 18 | 19 | Downloads/week 20 | 21 | Discord 22 |

23 | 24 | The NodeJS SDK supports the use of the Nitric framework with NodeJS 12+. For more information, check out the main [Nitric repo](https://github.com/nitrictech/nitric). 25 | 26 | Nitric SDKs provide an infrastructure-as-code style that lets you define resources in code. You can also write the functions that support the logic behind APIs, subscribers and schedules. 27 | 28 | You can request the type of access you need to resources such as publishing for topics, without dealing directly with IAM or policy documents. 29 | 30 | - Reference Documentation: https://nitric.io/docs/reference/nodejs 31 | - Guides: https://nitric.io/docs/guides/nodejs 32 | 33 | ## Usage 34 | 35 | ### Starting a new project 36 | 37 | Install the [Nitric CLI](https://nitric.io/docs/getting-started/installation), then generate your project: 38 | 39 | TypeScript: 40 | 41 | ```bash 42 | nitric new hello-world ts-starter 43 | ``` 44 | 45 | JavaScript: 46 | 47 | ```bash 48 | nitric new hello-world js-starter 49 | ``` 50 | 51 | ### Add to an existing project 52 | 53 | First of all, you need to install the library: 54 | 55 | ```bash 56 | npm install @nitric/sdk 57 | ``` 58 | 59 | Then you're able to import the library and create cloud resources: 60 | 61 | ```typescript 62 | import { api, bucket } from '@nitric/sdk'; 63 | 64 | const publicApi = api('public'); 65 | const uploads = bucket('uploads').allow('write'); 66 | 67 | publicApi.get('/upload', async (ctx) => { 68 | const photo = uploads.file('images/photo.png'); 69 | 70 | const url = await photo.getUploadUrl({ 71 | expiry: 300, 72 | }); 73 | 74 | return ctx.res.json({ url }); 75 | }); 76 | ``` 77 | 78 | ## Learn more 79 | 80 | Learn more by checking out the [Nitric documentation](https://nitric.io/docs). 81 | 82 | ## Get in touch: 83 | 84 | - Join us on [Discord](https://nitric.io/chat) 85 | 86 | - Ask questions in [GitHub discussions](https://github.com/nitrictech/nitric/discussions) 87 | 88 | - Find us on [Twitter](https://twitter.com/nitric_io) 89 | 90 | - Send us an [email](mailto:maintainers@nitric.io) 91 | -------------------------------------------------------------------------------- /assets/license_header.txt: -------------------------------------------------------------------------------- 1 | Copyright 2021, Nitric Technologies Pty Ltd. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /assets/nitric-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | import { pathsToModuleNameMapper } from 'ts-jest'; 2 | import { compilerOptions } from './tsconfig.json'; 3 | 4 | module.exports = { 5 | preset: 'ts-jest', 6 | testEnvironment: 'node', 7 | // Ignore the auto generated code for code coverage 8 | roots: [''], 9 | coveragePathIgnorePatterns: ['src/gen/'], 10 | modulePaths: [compilerOptions.baseUrl], 11 | moduleNameMapper: pathsToModuleNameMapper( 12 | compilerOptions.paths /*, { prefix: '/' } */ 13 | ), 14 | }; 15 | -------------------------------------------------------------------------------- /licenseconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignoreFile": ".gitignore", 3 | "ignore": [ 4 | "README", 5 | "**/*.svg", 6 | ".*", 7 | "**/*.config.*", 8 | "**/.gitignore", 9 | "lib/**/*", 10 | "contracts/**/*", 11 | ".yarn/", 12 | ".github/", 13 | "**/*.md", 14 | "*.lock", 15 | "*.html", 16 | "**/.eslintignore", 17 | "makefile", 18 | "./src/gen/**/*", 19 | "codecov.yml" 20 | ], 21 | "license": "./assets/license_header.txt", 22 | "licenseFormats": { 23 | "js|ts": { 24 | "eachLine": { 25 | "prepend": "// " 26 | } 27 | }, 28 | "dotfile|^Dockerfile": { 29 | "eachLine": { 30 | "prepend": "# " 31 | } 32 | } 33 | }, 34 | "trailingWhitespace": "TRIM" 35 | } 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nitric/sdk", 3 | "description": "Nitric NodeJS client sdk", 4 | "nitric": "v1.14.0", 5 | "author": "Nitric ", 6 | "repository": "https://github.com/nitrictech/node-sdk", 7 | "main": "lib/index.js", 8 | "types": "lib/index.d.ts", 9 | "scripts": { 10 | "bump": "standard-version", 11 | "build": "tsup src/index.ts --dts --outDir lib", 12 | "test": "jest", 13 | "check-nitric": "ts-node ./scripts/check-nitric-version.ts", 14 | "test:coverage": "jest --coverage", 15 | "prettier:check": "prettier --check src", 16 | "prettier:fix": "prettier --write src", 17 | "lint": "eslint \"src/**/*.ts\"", 18 | "lint:fix": "yarn lint --fix", 19 | "license:header:remove": "license-check-and-add remove -f ./licenseconfig.json", 20 | "license:header:add": "license-check-and-add add -f ./licenseconfig.json", 21 | "license:header:check": "license-check-and-add check -f ./licenseconfig.json", 22 | "license:check": "licensee --production", 23 | "download:contracts": "curl -L https://github.com/nitrictech/nitric/releases/download/${npm_package_nitric}/proto.tgz -o nitric.tgz && tar xvzf nitric.tgz && rm nitric.tgz", 24 | "download:contracts:local": "rm -r ./nitric && mkdir ./nitric && cp -r $NITRIC_CORE_HOME/nitric/proto ./nitric", 25 | "gen:proto": "yarn run download:contracts && yarn run gen:sources", 26 | "gen:sources": "mkdir -p ./src/gen && grpc_tools_node_protoc --ts_out=service=grpc-node,mode=grpc-js:./src/gen --js_out=import_style=commonjs,binary:./src/gen --grpc_out=grpc_js:./src/gen -I ./ ./nitric/proto/**/*/*.proto" 27 | }, 28 | "contributors": [ 29 | "Jye Cusch ", 30 | "Tim Holm ", 31 | "David Moore " 32 | ], 33 | "dependencies": { 34 | "@grpc/grpc-js": "1.10.0", 35 | "@nitric/grpc-error-status": "^0.0.2", 36 | "google-protobuf": "3.14.0", 37 | "portfinder": "^1.0.32", 38 | "tslib": "^2.1.0" 39 | }, 40 | "license": "Apache-2.0", 41 | "lint-staged": { 42 | "src/**/*.{ts}": "yarn lint:fix" 43 | }, 44 | "husky": { 45 | "hooks": { 46 | "pre-commit": "lint-staged" 47 | } 48 | }, 49 | "devDependencies": { 50 | "@types/google-protobuf": "^3.15.6", 51 | "@types/jest": "^29.5.12", 52 | "@types/node": "^20.11.17", 53 | "@typescript-eslint/eslint-plugin": "^4.22.0", 54 | "@typescript-eslint/parser": "^4.22.0", 55 | "eslint": "^7.24.0", 56 | "eslint-plugin-jsdoc": "^46.9.1", 57 | "glob-run": "^0.1.7", 58 | "grpc-tools": "^1.11.3", 59 | "husky": "^6.0.0", 60 | "jest": "^29.0.10", 61 | "license-check-and-add": "^4.0.2", 62 | "licensee": "^8.2.0", 63 | "lint-staged": "^10.5.4", 64 | "prettier": "^2.2.1", 65 | "standard-version": "^9.0.0", 66 | "ts-jest": "^29.1.5", 67 | "ts-node": "^10.9.1", 68 | "ts-protoc-gen": "^0.15.0", 69 | "tsconfig-paths": "^4.2.0", 70 | "tsup": "^6.5.0", 71 | "typescript": "^4.4" 72 | }, 73 | "license-check-config": { 74 | "src": [ 75 | "src/**/*.ts", 76 | "!./node_modules/**/*" 77 | ], 78 | "path": "assets/license_header.txt", 79 | "blocking": true, 80 | "logInfo": false, 81 | "logError": true 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /scripts/check-nitric-version.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { nitric } from "../package.json" 15 | 16 | if (nitric.includes("-rc")) { 17 | throw new Error("nitric must be set to a production version!"); 18 | } -------------------------------------------------------------------------------- /src/api/batch/v1/batch.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { SERVICE_BIND } from '@nitric/sdk/constants'; 15 | import { BatchClient } from '@nitric/sdk/gen/nitric/proto/batch/v1/batch_grpc_pb'; 16 | import * as grpc from '@grpc/grpc-js'; 17 | 18 | let batchClient: BatchClient; 19 | 20 | export const getBatchClient = (): BatchClient => { 21 | if (!batchClient) { 22 | batchClient = new BatchClient( 23 | SERVICE_BIND, 24 | grpc.ChannelCredentials.createInsecure() 25 | ); 26 | } 27 | return batchClient; 28 | }; 29 | -------------------------------------------------------------------------------- /src/api/batch/v1/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './job'; 15 | -------------------------------------------------------------------------------- /src/api/batch/v1/job.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { Job } from './job'; 15 | import { UnimplementedError } from '../../errors'; 16 | import { status } from '@grpc/grpc-js'; 17 | import { getBatchClient } from './batch'; 18 | import { JobSubmitResponse } from '@nitric/sdk/gen/nitric/proto/batch/v1/batch_pb'; 19 | import { BatchClient } from '@nitric/sdk/gen/nitric/proto/batch/v1/batch_grpc_pb'; 20 | 21 | describe('Job Client Tests', () => { 22 | describe('Given the grpc client returns an unimplemented error status', () => { 23 | const MOCK_ERROR = { 24 | code: status.UNIMPLEMENTED, 25 | message: 'UNIMPLEMENTED', 26 | }; 27 | let submitMock; 28 | beforeAll(() => { 29 | submitMock = jest 30 | .spyOn(BatchClient.prototype, 'submitJob') 31 | .mockImplementation((request, callback: any) => { 32 | callback(MOCK_ERROR, null); 33 | return null as any; 34 | }); 35 | }); 36 | afterAll(() => { 37 | jest.resetAllMocks(); 38 | }); 39 | test('Then submit call should return an UnimplementedError', async () => { 40 | const job = new Job('test', getBatchClient()); 41 | await expect( 42 | job.submit({ 43 | test: 'test', 44 | }) 45 | ).rejects.toBeInstanceOf(UnimplementedError); 46 | }); 47 | test('The Grpc client for Job.submit should have been called exactly once', () => { 48 | expect(submitMock).toHaveBeenCalledTimes(1); 49 | }); 50 | }); 51 | describe('Given the grpc returns successfully', () => { 52 | let submitMock; 53 | beforeAll(() => { 54 | submitMock = jest 55 | .spyOn(BatchClient.prototype, 'submitJob') 56 | .mockImplementation((request, callback: any) => { 57 | const response = new JobSubmitResponse(); 58 | callback(null, response); 59 | return null as any; 60 | }); 61 | }); 62 | afterAll(() => { 63 | jest.resetAllMocks(); 64 | }); 65 | test('Then Eventing.submit should resolve with the provided id', async () => { 66 | const client = new Job('test', getBatchClient()); 67 | await expect( 68 | client.submit({ message: 'Test Payload' }) 69 | ).resolves.toBeUndefined(); 70 | }); 71 | test('The Grpc client for Eventing.submit should have been called exactly once', () => { 72 | expect(submitMock).toHaveBeenCalledTimes(1); 73 | }); 74 | }); 75 | }); 76 | -------------------------------------------------------------------------------- /src/api/batch/v1/job.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { BatchClient } from '@nitric/proto/batch/v1/batch_grpc_pb'; 15 | import { JobData, JobSubmitRequest } from '@nitric/proto/batch/v1/batch_pb'; 16 | import { Struct } from 'google-protobuf/google/protobuf/struct_pb'; 17 | import { fromGrpcError } from '../../errors'; 18 | 19 | export class Job = Record> { 20 | private name: string; 21 | private client: BatchClient; 22 | 23 | constructor(name: string, client: BatchClient) { 24 | this.name = name; 25 | this.client = client; 26 | } 27 | 28 | /** 29 | * Submit a job to the batch service 30 | * 31 | * @example 32 | * ```typescript 33 | * const analyse = job('analyse').allow('submit'); 34 | * 35 | * await analyse.submit({ 36 | * data: 'some data', 37 | * }); 38 | * ``` 39 | * 40 | * @param data - Data to submit to the job 41 | * @returns Promise that resolves when the job has been submitted 42 | */ 43 | async submit(data: T): Promise { 44 | const request = new JobSubmitRequest(); 45 | const jobData = new JobData(); 46 | 47 | jobData.setStruct(Struct.fromJavaScript(data)); 48 | request.setJobName(this.name); 49 | request.setData(jobData); 50 | 51 | return new Promise((resolve, reject) => { 52 | this.client.submitJob(request, (error, _response) => { 53 | if (error) { 54 | reject(fromGrpcError(error)); 55 | } else { 56 | resolve(); 57 | } 58 | }); 59 | }); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/api/errors/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { status, ServiceError } from '@grpc/grpc-js'; 16 | import { 17 | AbortedError, 18 | AlreadyExistsError, 19 | CancelledError, 20 | DataLossError, 21 | DeadlineExceededError, 22 | FailedPreconditionError, 23 | InternalError, 24 | InvalidArgumentError, 25 | NotFoundError, 26 | OutOfRangeError, 27 | PermissionDeniedError, 28 | ResourceExhaustedError, 29 | UnauthenticatedError, 30 | UnavailableError, 31 | UnimplementedError, 32 | UnknownError, 33 | } from './provider-error'; 34 | 35 | // Accept all codes except Status OK 36 | type codes = Exclude; 37 | 38 | const STATUS_CODE_MAP: Record Error> = { 39 | [status.CANCELLED]: CancelledError, 40 | [status.UNKNOWN]: UnknownError, 41 | [status.INVALID_ARGUMENT]: InvalidArgumentError, 42 | [status.DEADLINE_EXCEEDED]: DeadlineExceededError, 43 | [status.NOT_FOUND]: NotFoundError, 44 | [status.ALREADY_EXISTS]: AlreadyExistsError, 45 | [status.PERMISSION_DENIED]: PermissionDeniedError, 46 | [status.RESOURCE_EXHAUSTED]: ResourceExhaustedError, 47 | [status.FAILED_PRECONDITION]: FailedPreconditionError, 48 | [status.ABORTED]: AbortedError, 49 | [status.OUT_OF_RANGE]: OutOfRangeError, 50 | [status.UNIMPLEMENTED]: UnimplementedError, 51 | [status.INTERNAL]: InternalError, 52 | [status.UNAVAILABLE]: UnavailableError, 53 | [status.DATA_LOSS]: DataLossError, 54 | [status.UNAUTHENTICATED]: UnauthenticatedError, 55 | }; 56 | 57 | /** 58 | * Translates gRPC service errors to Nitric API errors. 59 | * 60 | * @param error the original gRPC service error 61 | * @returns Nitric API error that maps to the provided service error code 62 | */ 63 | export const fromGrpcError = (error: ServiceError): Error => { 64 | const construct = STATUS_CODE_MAP[error.code]; 65 | 66 | if (construct) { 67 | return new construct(error); 68 | } 69 | 70 | return new UnknownError(error); 71 | }; 72 | 73 | // Re-export errors 74 | export { 75 | CancelledError, 76 | UnknownError, 77 | InvalidArgumentError, 78 | DeadlineExceededError, 79 | NotFoundError, 80 | AlreadyExistsError, 81 | PermissionDeniedError, 82 | ResourceExhaustedError, 83 | FailedPreconditionError, 84 | AbortedError, 85 | OutOfRangeError, 86 | UnimplementedError, 87 | InternalError, 88 | UnavailableError, 89 | DataLossError, 90 | UnauthenticatedError, 91 | }; 92 | -------------------------------------------------------------------------------- /src/api/errors/provider-error.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { ServiceError } from '@grpc/grpc-js'; 16 | import { parse } from '@nitric/grpc-error-status'; 17 | import { Struct } from 'google-protobuf/google/protobuf/struct_pb'; 18 | 19 | /** 20 | * Nitric Provider Error 21 | * 22 | * Generic error for Nitric Provider errors 23 | */ 24 | export class NitricProviderError extends Error { 25 | constructor(grpcError: ServiceError) { 26 | const errorStatus = parse(grpcError); 27 | 28 | let errorDetails: Struct | undefined = undefined; 29 | 30 | if (errorStatus) { 31 | const allDetails = errorStatus.parseDetails(Struct); 32 | 33 | if (allDetails.length > 0) { 34 | errorDetails = allDetails[0]; 35 | } 36 | } 37 | 38 | let details = grpcError.details; 39 | try { 40 | details = JSON.stringify(errorDetails?.toJavaScript()); 41 | } catch (e) { 42 | // Ignore 43 | console.debug( 44 | 'provider returned error details in a format other than Struct. Unable to parse details' 45 | ); 46 | } 47 | 48 | const message = `${grpcError.message} 49 | Nitric Provider Error: ${grpcError.name} 50 | Code: ${grpcError.code} 51 | Message: ${grpcError.message} 52 | Details: ${details}`; 53 | super(message); 54 | } 55 | } 56 | 57 | /** 58 | * NotFoundError 59 | * 60 | * Requested resource was not found 61 | */ 62 | export class NotFoundError extends NitricProviderError {} 63 | 64 | /** 65 | * PermissionDeniedError 66 | * 67 | * The client is authenticated but does not have permission to 68 | * perform the requested operation 69 | */ 70 | export class PermissionDeniedError extends NitricProviderError {} 71 | 72 | /** 73 | * AbortedError 74 | * 75 | * The operation was aborted 76 | */ 77 | export class AbortedError extends NitricProviderError {} 78 | 79 | /** 80 | * AlreadyExistsError 81 | * 82 | * Client attempted to illegally create an entity that already exists 83 | */ 84 | export class AlreadyExistsError extends NitricProviderError {} 85 | 86 | /** 87 | * CancelledError 88 | * 89 | * Operation was cancelled (typically occurs client side) 90 | */ 91 | export class CancelledError extends NitricProviderError {} 92 | 93 | /** 94 | * DataLossError 95 | * 96 | * Unrecoverable data loss or corruption 97 | */ 98 | export class DataLossError extends NitricProviderError {} 99 | 100 | /** 101 | * DeadlineExceededError 102 | * 103 | * Specified deadline was exceeded before the operation could complete 104 | */ 105 | export class DeadlineExceededError extends NitricProviderError {} 106 | 107 | /** 108 | * FailedPreconditionError 109 | * 110 | * Operation was rejected due to the system being not being 111 | * in a state required for the requested operation. 112 | */ 113 | export class FailedPreconditionError extends NitricProviderError {} 114 | 115 | /** 116 | * InternalError 117 | * 118 | * Some invariant error has incurred internally 119 | */ 120 | export class InternalError extends NitricProviderError {} 121 | 122 | /** 123 | * InvalidArgumentError 124 | * 125 | * Invalid argument was provided by the client 126 | */ 127 | export class InvalidArgumentError extends NitricProviderError {} 128 | 129 | /** 130 | * OutOfRangeError 131 | * 132 | * The operation was attempted outside of valid range 133 | * e.g. seeking past the end of a file or array, or specifying invalid offsets 134 | */ 135 | export class OutOfRangeError extends NitricProviderError {} 136 | 137 | /** 138 | * ResourceExhaustedError 139 | * 140 | * The requested user resource has been exhausted. 141 | * Examples include API quotas being exceeded or disk space running out 142 | */ 143 | export class ResourceExhaustedError extends NitricProviderError {} 144 | 145 | /** 146 | * UnauthenticatedError 147 | * 148 | * The request does not have or has invalid credentials 149 | */ 150 | export class UnauthenticatedError extends NitricProviderError {} 151 | 152 | /** 153 | * UnavailableError 154 | * 155 | * The request operation is currently unavailable 156 | */ 157 | export class UnavailableError extends NitricProviderError {} 158 | 159 | /** 160 | * UnimplementedError 161 | * 162 | * The requested operation was not implemented for the service provider. 163 | */ 164 | export class UnimplementedError extends NitricProviderError {} 165 | 166 | /** 167 | * UnknownError 168 | * 169 | * Not enough information received to determine discrete error type 170 | */ 171 | export class UnknownError extends NitricProviderError {} 172 | -------------------------------------------------------------------------------- /src/api/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './topics'; 15 | export * from './queues'; 16 | export * from './keyvalue'; 17 | export * from './storage'; 18 | export * from './secrets'; 19 | -------------------------------------------------------------------------------- /src/api/keyvalue/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './v1'; 15 | -------------------------------------------------------------------------------- /src/api/keyvalue/v1/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './keyvalue'; 15 | export { ValueStructure } from './store'; 16 | -------------------------------------------------------------------------------- /src/api/keyvalue/v1/keyvalue.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { keyvalue } from './keyvalue'; 15 | 16 | describe('KeyValue Client Tests', () => { 17 | describe('Given a new store', () => { 18 | test('Then store should contain correct store reference', () => { 19 | const store = keyvalue().store('customers'); 20 | 21 | expect(store.name).toEqual('customers'); 22 | }); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /src/api/keyvalue/v1/keyvalue.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { SERVICE_BIND } from '../../../constants'; 15 | import { KvStoreClient } from '@nitric/proto/kvstore/v1/kvstore_grpc_pb'; 16 | import * as grpc from '@grpc/grpc-js'; 17 | import { StoreRef, ValueStructure } from './store'; 18 | 19 | /** 20 | * KeyValue 21 | * 22 | * Provides a KeyValue API client. 23 | * Used to create references to key/value stores. 24 | */ 25 | export class KeyValue { 26 | private kvClient: KvStoreClient; 27 | 28 | constructor() { 29 | this.kvClient = new KvStoreClient( 30 | SERVICE_BIND, 31 | grpc.ChannelCredentials.createInsecure() 32 | ); 33 | } 34 | 35 | /** 36 | * Gets a store instance that refers to the store at the specified path. 37 | * 38 | * @param name The name of the store (required) 39 | * @returns The Store instance 40 | */ 41 | public store(name: string): StoreRef { 42 | return new StoreRef(this.kvClient, name); 43 | } 44 | } 45 | 46 | // KeyValue client singleton 47 | let KEY_VALUE = undefined; 48 | 49 | export const keyvalue = (): KeyValue => { 50 | if (!KEY_VALUE) { 51 | KEY_VALUE = new KeyValue(); 52 | } 53 | 54 | return KEY_VALUE; 55 | }; 56 | -------------------------------------------------------------------------------- /src/api/queues/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './v1'; 15 | -------------------------------------------------------------------------------- /src/api/queues/v1/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './queues'; 15 | -------------------------------------------------------------------------------- /src/api/secrets/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './v1'; 15 | -------------------------------------------------------------------------------- /src/api/secrets/v1/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './secrets'; 15 | -------------------------------------------------------------------------------- /src/api/storage/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './v1'; 15 | -------------------------------------------------------------------------------- /src/api/storage/v1/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './storage'; 15 | -------------------------------------------------------------------------------- /src/api/topics/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './v1'; 15 | -------------------------------------------------------------------------------- /src/api/topics/v1/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './topics'; 15 | -------------------------------------------------------------------------------- /src/api/topics/v1/topics.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { Eventing, Topic } from './topics'; 15 | import { TopicPublishResponse } from '@nitric/proto/topics/v1/topics_pb'; 16 | import { TopicsClient as GrpcTopicServiceClient } from '@nitric/proto/topics/v1/topics_grpc_pb'; 17 | import { UnimplementedError } from '../../errors'; 18 | import { TopicsClient } from '@nitric/sdk/gen/nitric/proto/topics/v1/topics_grpc_pb'; 19 | import { status } from '@grpc/grpc-js'; 20 | 21 | describe('Event Client Tests', () => { 22 | describe('Given the grpc client returns an unimplemented error status', () => { 23 | const MOCK_ERROR = { 24 | code: status.UNIMPLEMENTED, 25 | message: 'UNIMPLEMENTED', 26 | }; 27 | let publishMock; 28 | beforeAll(() => { 29 | publishMock = jest 30 | .spyOn(TopicsClient.prototype, 'publish') 31 | .mockImplementation((request, callback: any) => { 32 | callback(MOCK_ERROR, null); 33 | return null as any; 34 | }); 35 | }); 36 | afterAll(() => { 37 | jest.resetAllMocks(); 38 | }); 39 | test('Then publish call should return an UnimplementedError', async () => { 40 | const topic = new Eventing().topic('test'); 41 | await expect( 42 | topic.publish({ 43 | id: 'test', 44 | payloadType: 'Test Payload', 45 | payload: { 46 | test: 'test', 47 | }, 48 | }) 49 | ).rejects.toBeInstanceOf(UnimplementedError); 50 | }); 51 | test('The Grpc client for Eventing.publish should have been called exactly once', () => { 52 | expect(publishMock).toBeCalledTimes(1); 53 | }); 54 | }); 55 | describe('Given the grpc returns successfully', () => { 56 | let publishMock; 57 | beforeAll(() => { 58 | publishMock = jest 59 | .spyOn(TopicsClient.prototype, 'publish') 60 | .mockImplementation((request, callback: any) => { 61 | const response = new TopicPublishResponse(); 62 | callback(null, response); 63 | return null as any; 64 | }); 65 | }); 66 | afterAll(() => { 67 | jest.resetAllMocks(); 68 | }); 69 | test('Then Eventing.publish should resolve with the provided id', async () => { 70 | const client = new Eventing(); 71 | await expect( 72 | client.topic('test').publish({ message: 'Test Payload' }) 73 | ).resolves.toBeUndefined(); 74 | }); 75 | test('The Grpc client for Eventing.publish should have been called exactly once', () => { 76 | expect(publishMock).toBeCalledTimes(1); 77 | }); 78 | }); 79 | }); 80 | -------------------------------------------------------------------------------- /src/api/websocket/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | -------------------------------------------------------------------------------- /src/api/websocket/v1/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './websocket'; 15 | -------------------------------------------------------------------------------- /src/api/websocket/v1/websocket.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { SERVICE_BIND } from '../../../constants'; 15 | import { WebsocketClient } from '@nitric/proto/websockets/v1/websockets_grpc_pb'; 16 | import { 17 | WebsocketSendRequest, 18 | WebsocketCloseConnectionRequest, 19 | } from '@nitric/proto/websockets/v1/websockets_pb'; 20 | import * as grpc from '@grpc/grpc-js'; 21 | import { fromGrpcError } from '../../errors'; 22 | 23 | /** 24 | * Nitric websocket client, facilitates sending messages to connections on this websocket. 25 | */ 26 | export class Websocket { 27 | client: WebsocketClient; 28 | 29 | constructor() { 30 | this.client = new WebsocketClient( 31 | SERVICE_BIND, 32 | grpc.ChannelCredentials.createInsecure() 33 | ); 34 | } 35 | 36 | async send( 37 | socket: string, 38 | connectionId: string, 39 | message: string | Uint8Array | Record 40 | ): Promise { 41 | let payload: Uint8Array; 42 | 43 | // handle all message types 44 | if (typeof message === 'string') { 45 | payload = new TextEncoder().encode(message); 46 | } else if (message instanceof Uint8Array) { 47 | payload = message; 48 | } else { 49 | payload = new TextEncoder().encode(JSON.stringify(message)); 50 | } 51 | 52 | const sendRequest = new WebsocketSendRequest(); 53 | 54 | sendRequest.setSocketName(socket); 55 | sendRequest.setConnectionId(connectionId); 56 | sendRequest.setData(payload); 57 | 58 | return new Promise((res, rej) => { 59 | this.client.sendMessage(sendRequest, (error, _data) => { 60 | if (error) { 61 | rej(fromGrpcError(error)); 62 | } 63 | 64 | res(); 65 | }); 66 | }); 67 | } 68 | 69 | async close(socket: string, connectionId: string): Promise { 70 | const closeRequest = new WebsocketCloseConnectionRequest(); 71 | 72 | closeRequest.setSocketName(socket); 73 | closeRequest.setConnectionId(connectionId); 74 | 75 | return new Promise((res, rej) => { 76 | this.client.closeConnection(closeRequest, (error) => { 77 | if (error) { 78 | rej(fromGrpcError(error)); 79 | } 80 | 81 | res(); 82 | }); 83 | }); 84 | } 85 | } 86 | 87 | // Websocket client singleton 88 | let WEBSOCKET = undefined; 89 | 90 | /** 91 | * Websocket API client. 92 | * 93 | * @returns a Websocket API client. 94 | */ 95 | export const websocket = (): Websocket => { 96 | if (!WEBSOCKET) { 97 | WEBSOCKET = new Websocket(); 98 | } 99 | 100 | return WEBSOCKET; 101 | }; 102 | -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export const SERVICE_BIND = process.env.SERVICE_ADDRESS || '127.0.0.1:50051'; 15 | export const NITRIC_DEBUG = process.env.NITRIC_DEBUG === 'true' || false; 16 | -------------------------------------------------------------------------------- /src/context/base.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export type JSONTypes = Record | Array | string; 15 | 16 | export abstract class AbstractRequest< 17 | JSONT extends JSONTypes = Record 18 | > { 19 | readonly data: string | Uint8Array; 20 | // readonly traceContext: api.Context; 21 | 22 | protected constructor(data: string | Uint8Array) { 23 | this.data = data; 24 | //this.traceContext = traceContext; 25 | } 26 | 27 | /** 28 | * Return the request payload as a string. 29 | * If the request was a byte array it will converted using UTF-8 text decoding. 30 | * 31 | * @returns the request payload as a string 32 | */ 33 | text(): string { 34 | const stringPayload = 35 | typeof this.data === 'string' 36 | ? this.data 37 | : new TextDecoder('utf-8').decode(this.data); 38 | 39 | return stringPayload; 40 | } 41 | 42 | /** 43 | * Deserialize the request payload from JSON 44 | * 45 | * @returns JSON parsed request body 46 | */ 47 | json(): JSONT { 48 | // attempt to deserialize as a JSON object 49 | const textBody = this.text(); 50 | return textBody ? JSON.parse(textBody) : undefined; 51 | } 52 | } 53 | 54 | export abstract class BaseContext< 55 | Req extends AbstractRequest = AbstractRequest, 56 | Resp extends Record = any 57 | > { 58 | protected request: Req; 59 | protected response: Resp; 60 | 61 | /** 62 | * Return the request object from this context. 63 | * 64 | * @returns the request object. 65 | */ 66 | get req(): Req { 67 | return this.request; 68 | } 69 | 70 | /** 71 | * Return the response object from this context. 72 | * 73 | * @returns the response object. 74 | */ 75 | get res(): Resp { 76 | return this.response; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/context/bucket.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { 15 | BlobEventRequest as BlobEventRequestPb, 16 | BlobEventResponse as BlobEventResponsePb, 17 | BlobEventType as BlobEventTypePb, 18 | } from '@nitric/proto/storage/v1/storage_pb'; 19 | import { AbstractRequest, BaseContext } from './base'; 20 | import type { Bucket, File } from '../api/storage'; 21 | 22 | export class BlobEventContext extends BaseContext< 23 | BlobEventRequest, 24 | BucketNotificationResponse 25 | > { 26 | public get bucketNotification(): BlobEventContext { 27 | return this; 28 | } 29 | 30 | static fromRequest( 31 | request: BlobEventRequestPb, 32 | bucket: Bucket 33 | ): BlobEventContext { 34 | const ctx = new BlobEventContext(); 35 | const blobEvent = request.getBlobEvent(); 36 | 37 | ctx.request = new BlobEventRequest( 38 | blobEvent.getKey(), 39 | blobEvent.getType(), 40 | bucket 41 | ); 42 | 43 | ctx.response = { 44 | success: true, 45 | }; 46 | 47 | return ctx; 48 | } 49 | 50 | static toResponse(ctx: BlobEventContext): BlobEventResponsePb { 51 | const blobEventRespsonse = new BlobEventResponsePb(); 52 | blobEventRespsonse.setSuccess(ctx.res.success); 53 | return blobEventRespsonse; 54 | } 55 | } 56 | 57 | export class BucketEventContext extends BaseContext< 58 | BucketEventRequest, 59 | BucketNotificationResponse 60 | > { 61 | public get bucketNotification(): BucketEventContext { 62 | return this; 63 | } 64 | 65 | static fromRequest(request: BlobEventRequestPb): BucketEventContext { 66 | const ctx = new BucketEventContext(); 67 | const blobEvent = request.getBlobEvent(); 68 | 69 | ctx.request = new BucketEventRequest( 70 | blobEvent.getKey(), 71 | blobEvent.getType() 72 | ); 73 | 74 | ctx.response = { 75 | success: true, 76 | }; 77 | 78 | return ctx; 79 | } 80 | 81 | static toResponse(ctx: BucketEventContext): BlobEventResponsePb { 82 | const blobEventRespsonse = new BlobEventResponsePb(); 83 | blobEventRespsonse.setSuccess(ctx.res.success); 84 | return blobEventRespsonse; 85 | } 86 | } 87 | 88 | export enum BlobEventType { 89 | Created, 90 | Deleted, 91 | } 92 | 93 | export class BucketEventRequest extends AbstractRequest { 94 | public readonly key: string; 95 | public readonly eventType: BlobEventType; 96 | 97 | constructor(key: string, notificationType: number) { 98 | super(''); 99 | 100 | // Get reference to the bucket 101 | this.key = key; 102 | this.eventType = this.eventTypeToNotificationType(notificationType); 103 | } 104 | 105 | private eventTypeToNotificationType = (eventType: number): BlobEventType => { 106 | switch (eventType) { 107 | case BlobEventTypePb.CREATED: 108 | return BlobEventType.Created; 109 | case BlobEventTypePb.DELETED: 110 | return BlobEventType.Deleted; 111 | default: 112 | throw new Error(`event type unsupported: ${eventType}`); 113 | } 114 | }; 115 | } 116 | 117 | export class BlobEventRequest extends BucketEventRequest { 118 | public readonly file: File | undefined; 119 | 120 | constructor(key: string, notificationType: number, bucket: Bucket) { 121 | super(key, notificationType); 122 | 123 | this.file = bucket.file(key); 124 | } 125 | } 126 | 127 | export interface BucketNotificationResponse { 128 | success: boolean; 129 | } 130 | -------------------------------------------------------------------------------- /src/context/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './base'; 15 | export * from './bucket'; 16 | export * from './http'; 17 | export * from './interval'; 18 | export * from './message'; 19 | export * from './websocket'; 20 | export * from './job'; 21 | -------------------------------------------------------------------------------- /src/context/interval.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { 15 | IntervalRequest as IntervalRequestPb, 16 | IntervalResponse as IntervalResponsePb, 17 | } from '@nitric/proto/schedules/v1/schedules_pb'; 18 | import { AbstractRequest, BaseContext } from './base'; 19 | 20 | export interface IntervalResponse { 21 | success: boolean; 22 | } 23 | 24 | export class IntervalRequest extends AbstractRequest { 25 | public readonly schedule: string; 26 | 27 | constructor( 28 | schedule: string 29 | // traceContext: api.Context 30 | ) { 31 | super(''); 32 | this.schedule = schedule; 33 | } 34 | } 35 | 36 | export class IntervalContext extends BaseContext< 37 | IntervalRequest, 38 | IntervalResponse 39 | > { 40 | public get event(): IntervalContext { 41 | return this; 42 | } 43 | 44 | static fromRequest(messageRequest: IntervalRequestPb): IntervalContext { 45 | const schedule = messageRequest.getScheduleName(); 46 | const ctx = new IntervalContext(); 47 | 48 | ctx.request = new IntervalRequest(schedule); 49 | 50 | ctx.response = { 51 | success: true, 52 | }; 53 | 54 | return ctx; 55 | } 56 | 57 | static toResponse(_: IntervalContext): IntervalResponsePb { 58 | const intervalResponse = new IntervalResponsePb(); 59 | 60 | return intervalResponse; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/context/job.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { 15 | JobRequest as JobRequestPb, 16 | JobResponse as JobResponsePb, 17 | } from '../gen/nitric/proto/batch/v1/batch_pb'; 18 | import { AbstractRequest, BaseContext } from './base'; 19 | 20 | export interface JobResponse { 21 | success: boolean; 22 | } 23 | 24 | export class JobRequest extends AbstractRequest { 25 | public readonly jobName: string; 26 | 27 | constructor(data: string | Uint8Array, jobName: string) { 28 | super(data); 29 | this.jobName = jobName; 30 | } 31 | } 32 | 33 | export class JobContext extends BaseContext { 34 | public get job(): JobContext { 35 | return this; 36 | } 37 | 38 | static fromJobRequest(jobRequest: JobRequestPb): JobContext { 39 | const ctx = new JobContext(); 40 | const jobName = jobRequest.getJobName(); 41 | 42 | const data = jobRequest.getData().getStruct().toJavaScript(); 43 | 44 | ctx.request = new JobRequest(JSON.stringify(data), jobName); 45 | 46 | ctx.response = { 47 | success: true, 48 | }; 49 | 50 | return ctx; 51 | } 52 | 53 | static toJobResponse(ctx: JobContext): JobResponsePb { 54 | const evtCtx = ctx.job; 55 | const jobResponse = new JobResponsePb(); 56 | jobResponse.setSuccess(evtCtx.res.success); 57 | 58 | return jobResponse; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/context/message.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { 15 | MessageRequest as MessageRequestPb, 16 | MessageResponse as MessageResponsePb, 17 | } from '@nitric/proto/topics/v1/topics_pb'; 18 | 19 | import { AbstractRequest, BaseContext } from './base'; 20 | 21 | export interface MessageResponse { 22 | success: boolean; 23 | } 24 | 25 | export class MessageRequest extends AbstractRequest { 26 | public readonly topic: string; 27 | 28 | constructor( 29 | data: string | Uint8Array, 30 | topic: string 31 | // traceContext: api.Context 32 | ) { 33 | super(data); 34 | this.topic = topic; 35 | } 36 | } 37 | 38 | export class MessageContext extends BaseContext< 39 | MessageRequest, 40 | MessageResponse 41 | > { 42 | public get message(): MessageContext { 43 | return this; 44 | } 45 | 46 | static fromMessageRequest( 47 | messageRequest: MessageRequestPb 48 | ): MessageContext { 49 | const topic = messageRequest.getTopicName(); 50 | const ctx = new MessageContext(); 51 | 52 | const data = messageRequest.getMessage().getStructPayload().toJavaScript(); 53 | 54 | ctx.request = new MessageRequest(JSON.stringify(data), topic); 55 | 56 | ctx.response = { 57 | success: true, 58 | }; 59 | 60 | return ctx; 61 | } 62 | 63 | static toMessageResponse(ctx: MessageContext): MessageResponsePb { 64 | const evtCtx = ctx.message; 65 | const messageResponse = new MessageResponsePb(); 66 | messageResponse.setSuccess(evtCtx.res.success); 67 | 68 | return messageResponse; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/context/websocket.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { 15 | WebsocketConnectionResponse, 16 | WebsocketEventRequest as WebsocketEventRequestPb, 17 | WebsocketEventResponse as WebsocketEventResponsePb, 18 | WebsocketEventType, 19 | } from '@nitric/proto/websockets/v1/websockets_pb'; 20 | import { AbstractRequest, BaseContext } from './base'; 21 | 22 | export class WebsocketNotificationContext extends BaseContext< 23 | WebsocketNotificationRequest, 24 | WebsocketNotificationResponse 25 | > { 26 | public get websocket(): WebsocketNotificationContext { 27 | return this; 28 | } 29 | 30 | static fromRequest( 31 | request: WebsocketEventRequestPb 32 | ): WebsocketNotificationContext { 33 | const ctx = new WebsocketNotificationContext(); 34 | const connection = request.getConnection(); 35 | const query = connection 36 | ? ( 37 | connection 38 | .getQueryParamsMap() 39 | // getEntryList claims to return [string, faas.HeaderValue][], but really returns [string, string[][]][] 40 | // we force the type to match the real return type. 41 | .getEntryList() as unknown as [string, string[][]][] 42 | ).reduce( 43 | (acc, [key, [val]]) => ({ 44 | ...acc, 45 | [key]: val.map((v) => decodeURIComponent(v)), 46 | }), 47 | {} as Record 48 | ) 49 | : {}; 50 | 51 | const message = request.getMessage(); 52 | 53 | ctx.request = new WebsocketNotificationRequest( 54 | message ? message.getBody() : '', 55 | request.getSocketName(), 56 | request.getWebsocketEventCase(), 57 | request.getConnectionId(), 58 | query 59 | ); 60 | 61 | ctx.response = { 62 | success: true, 63 | }; 64 | 65 | return ctx; 66 | } 67 | 68 | static toResponse( 69 | ctx: WebsocketNotificationContext 70 | ): WebsocketEventResponsePb { 71 | const notifyCtx = ctx.websocket; 72 | const eventResponse = new WebsocketEventResponsePb(); 73 | const connectionResponse = new WebsocketConnectionResponse(); 74 | connectionResponse.setReject(!notifyCtx.res.success); 75 | 76 | eventResponse.setConnectionResponse(connectionResponse); 77 | return eventResponse; 78 | } 79 | } 80 | 81 | export enum WebsocketNotificationType { 82 | Connected, 83 | Disconnected, 84 | Message, 85 | } 86 | 87 | export type WebsocketEventType = 'connect' | 'disconnect' | 'message'; 88 | 89 | export class WebsocketNotificationRequest extends AbstractRequest { 90 | public readonly socket: string; 91 | public readonly eventType: WebsocketEventType; 92 | public readonly connectionId: string; 93 | public readonly query: Record; 94 | 95 | constructor( 96 | data: string | Uint8Array, 97 | socket: string, 98 | eventType: number, 99 | connectionId: string, 100 | query: Record 101 | ) { 102 | super(data); 103 | 104 | this.socket = socket; 105 | this.eventType = this.eventCaseToType(eventType); 106 | this.connectionId = connectionId; 107 | this.query = query; 108 | } 109 | 110 | private eventCaseToType = (eventType: number) => { 111 | switch (eventType) { 112 | case WebsocketEventRequestPb.WebsocketEventCase.CONNECTION: 113 | return 'connect'; 114 | case WebsocketEventRequestPb.WebsocketEventCase.DISCONNECTION: 115 | return 'disconnect'; 116 | case WebsocketEventRequestPb.WebsocketEventCase.MESSAGE: 117 | return 'message'; 118 | default: 119 | throw new Error(`event type unsupported: ${eventType}`); 120 | } 121 | }; 122 | } 123 | 124 | export interface WebsocketNotificationResponse { 125 | success: boolean; 126 | } 127 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/apis/v1/apis_grpc_pb.d.ts: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | // package: nitric.proto.apis.v1 4 | // file: nitric/proto/apis/v1/apis.proto 5 | 6 | import * as nitric_proto_apis_v1_apis_pb from "../../../../nitric/proto/apis/v1/apis_pb"; 7 | import * as grpc from "@grpc/grpc-js"; 8 | 9 | interface IApiService extends grpc.ServiceDefinition { 10 | serve: grpc.MethodDefinition; 11 | apiDetails: grpc.MethodDefinition; 12 | } 13 | 14 | export const ApiService: IApiService; 15 | 16 | export interface IApiServer extends grpc.UntypedServiceImplementation { 17 | serve: grpc.handleBidiStreamingCall; 18 | apiDetails: grpc.handleUnaryCall; 19 | } 20 | 21 | export class ApiClient extends grpc.Client { 22 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 23 | serve(metadataOrOptions?: grpc.Metadata | grpc.CallOptions | null): grpc.ClientDuplexStream; 24 | serve(metadata?: grpc.Metadata | null, options?: grpc.CallOptions | null): grpc.ClientDuplexStream; 25 | apiDetails(argument: nitric_proto_apis_v1_apis_pb.ApiDetailsRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 26 | apiDetails(argument: nitric_proto_apis_v1_apis_pb.ApiDetailsRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 27 | apiDetails(argument: nitric_proto_apis_v1_apis_pb.ApiDetailsRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 28 | } 29 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/apis/v1/apis_grpc_pb.js: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | 'use strict'; 4 | var grpc = require('@grpc/grpc-js'); 5 | var nitric_proto_apis_v1_apis_pb = require('../../../../nitric/proto/apis/v1/apis_pb.js'); 6 | 7 | function serialize_nitric_proto_apis_v1_ApiDetailsRequest(arg) { 8 | if (!(arg instanceof nitric_proto_apis_v1_apis_pb.ApiDetailsRequest)) { 9 | throw new Error('Expected argument of type nitric.proto.apis.v1.ApiDetailsRequest'); 10 | } 11 | return Buffer.from(arg.serializeBinary()); 12 | } 13 | 14 | function deserialize_nitric_proto_apis_v1_ApiDetailsRequest(buffer_arg) { 15 | return nitric_proto_apis_v1_apis_pb.ApiDetailsRequest.deserializeBinary(new Uint8Array(buffer_arg)); 16 | } 17 | 18 | function serialize_nitric_proto_apis_v1_ApiDetailsResponse(arg) { 19 | if (!(arg instanceof nitric_proto_apis_v1_apis_pb.ApiDetailsResponse)) { 20 | throw new Error('Expected argument of type nitric.proto.apis.v1.ApiDetailsResponse'); 21 | } 22 | return Buffer.from(arg.serializeBinary()); 23 | } 24 | 25 | function deserialize_nitric_proto_apis_v1_ApiDetailsResponse(buffer_arg) { 26 | return nitric_proto_apis_v1_apis_pb.ApiDetailsResponse.deserializeBinary(new Uint8Array(buffer_arg)); 27 | } 28 | 29 | function serialize_nitric_proto_apis_v1_ClientMessage(arg) { 30 | if (!(arg instanceof nitric_proto_apis_v1_apis_pb.ClientMessage)) { 31 | throw new Error('Expected argument of type nitric.proto.apis.v1.ClientMessage'); 32 | } 33 | return Buffer.from(arg.serializeBinary()); 34 | } 35 | 36 | function deserialize_nitric_proto_apis_v1_ClientMessage(buffer_arg) { 37 | return nitric_proto_apis_v1_apis_pb.ClientMessage.deserializeBinary(new Uint8Array(buffer_arg)); 38 | } 39 | 40 | function serialize_nitric_proto_apis_v1_ServerMessage(arg) { 41 | if (!(arg instanceof nitric_proto_apis_v1_apis_pb.ServerMessage)) { 42 | throw new Error('Expected argument of type nitric.proto.apis.v1.ServerMessage'); 43 | } 44 | return Buffer.from(arg.serializeBinary()); 45 | } 46 | 47 | function deserialize_nitric_proto_apis_v1_ServerMessage(buffer_arg) { 48 | return nitric_proto_apis_v1_apis_pb.ServerMessage.deserializeBinary(new Uint8Array(buffer_arg)); 49 | } 50 | 51 | 52 | // Service for API routing and handlers 53 | var ApiService = exports.ApiService = { 54 | // Serve a route on an API 55 | serve: { 56 | path: '/nitric.proto.apis.v1.Api/Serve', 57 | requestStream: true, 58 | responseStream: true, 59 | requestType: nitric_proto_apis_v1_apis_pb.ClientMessage, 60 | responseType: nitric_proto_apis_v1_apis_pb.ServerMessage, 61 | requestSerialize: serialize_nitric_proto_apis_v1_ClientMessage, 62 | requestDeserialize: deserialize_nitric_proto_apis_v1_ClientMessage, 63 | responseSerialize: serialize_nitric_proto_apis_v1_ServerMessage, 64 | responseDeserialize: deserialize_nitric_proto_apis_v1_ServerMessage, 65 | }, 66 | // Retrieve details about an API 67 | apiDetails: { 68 | path: '/nitric.proto.apis.v1.Api/ApiDetails', 69 | requestStream: false, 70 | responseStream: false, 71 | requestType: nitric_proto_apis_v1_apis_pb.ApiDetailsRequest, 72 | responseType: nitric_proto_apis_v1_apis_pb.ApiDetailsResponse, 73 | requestSerialize: serialize_nitric_proto_apis_v1_ApiDetailsRequest, 74 | requestDeserialize: deserialize_nitric_proto_apis_v1_ApiDetailsRequest, 75 | responseSerialize: serialize_nitric_proto_apis_v1_ApiDetailsResponse, 76 | responseDeserialize: deserialize_nitric_proto_apis_v1_ApiDetailsResponse, 77 | }, 78 | }; 79 | 80 | exports.ApiClient = grpc.makeGenericClientConstructor(ApiService); 81 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/batch/v1/batch_grpc_pb.d.ts: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | // package: nitric.proto.batch.v1 4 | // file: nitric/proto/batch/v1/batch.proto 5 | 6 | import * as nitric_proto_batch_v1_batch_pb from "../../../../nitric/proto/batch/v1/batch_pb"; 7 | import * as grpc from "@grpc/grpc-js"; 8 | 9 | interface IJobService extends grpc.ServiceDefinition { 10 | handleJob: grpc.MethodDefinition; 11 | } 12 | 13 | export const JobService: IJobService; 14 | 15 | export interface IJobServer extends grpc.UntypedServiceImplementation { 16 | handleJob: grpc.handleBidiStreamingCall; 17 | } 18 | 19 | export class JobClient extends grpc.Client { 20 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 21 | handleJob(metadataOrOptions?: grpc.Metadata | grpc.CallOptions | null): grpc.ClientDuplexStream; 22 | handleJob(metadata?: grpc.Metadata | null, options?: grpc.CallOptions | null): grpc.ClientDuplexStream; 23 | } 24 | 25 | interface IBatchService extends grpc.ServiceDefinition { 26 | submitJob: grpc.MethodDefinition; 27 | } 28 | 29 | export const BatchService: IBatchService; 30 | 31 | export interface IBatchServer extends grpc.UntypedServiceImplementation { 32 | submitJob: grpc.handleUnaryCall; 33 | } 34 | 35 | export class BatchClient extends grpc.Client { 36 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 37 | submitJob(argument: nitric_proto_batch_v1_batch_pb.JobSubmitRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 38 | submitJob(argument: nitric_proto_batch_v1_batch_pb.JobSubmitRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 39 | submitJob(argument: nitric_proto_batch_v1_batch_pb.JobSubmitRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 40 | } 41 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/batch/v1/batch_grpc_pb.js: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | 'use strict'; 4 | var grpc = require('@grpc/grpc-js'); 5 | var nitric_proto_batch_v1_batch_pb = require('../../../../nitric/proto/batch/v1/batch_pb.js'); 6 | var google_protobuf_struct_pb = require('google-protobuf/google/protobuf/struct_pb.js'); 7 | 8 | function serialize_nitric_proto_batch_v1_ClientMessage(arg) { 9 | if (!(arg instanceof nitric_proto_batch_v1_batch_pb.ClientMessage)) { 10 | throw new Error('Expected argument of type nitric.proto.batch.v1.ClientMessage'); 11 | } 12 | return Buffer.from(arg.serializeBinary()); 13 | } 14 | 15 | function deserialize_nitric_proto_batch_v1_ClientMessage(buffer_arg) { 16 | return nitric_proto_batch_v1_batch_pb.ClientMessage.deserializeBinary(new Uint8Array(buffer_arg)); 17 | } 18 | 19 | function serialize_nitric_proto_batch_v1_JobSubmitRequest(arg) { 20 | if (!(arg instanceof nitric_proto_batch_v1_batch_pb.JobSubmitRequest)) { 21 | throw new Error('Expected argument of type nitric.proto.batch.v1.JobSubmitRequest'); 22 | } 23 | return Buffer.from(arg.serializeBinary()); 24 | } 25 | 26 | function deserialize_nitric_proto_batch_v1_JobSubmitRequest(buffer_arg) { 27 | return nitric_proto_batch_v1_batch_pb.JobSubmitRequest.deserializeBinary(new Uint8Array(buffer_arg)); 28 | } 29 | 30 | function serialize_nitric_proto_batch_v1_JobSubmitResponse(arg) { 31 | if (!(arg instanceof nitric_proto_batch_v1_batch_pb.JobSubmitResponse)) { 32 | throw new Error('Expected argument of type nitric.proto.batch.v1.JobSubmitResponse'); 33 | } 34 | return Buffer.from(arg.serializeBinary()); 35 | } 36 | 37 | function deserialize_nitric_proto_batch_v1_JobSubmitResponse(buffer_arg) { 38 | return nitric_proto_batch_v1_batch_pb.JobSubmitResponse.deserializeBinary(new Uint8Array(buffer_arg)); 39 | } 40 | 41 | function serialize_nitric_proto_batch_v1_ServerMessage(arg) { 42 | if (!(arg instanceof nitric_proto_batch_v1_batch_pb.ServerMessage)) { 43 | throw new Error('Expected argument of type nitric.proto.batch.v1.ServerMessage'); 44 | } 45 | return Buffer.from(arg.serializeBinary()); 46 | } 47 | 48 | function deserialize_nitric_proto_batch_v1_ServerMessage(buffer_arg) { 49 | return nitric_proto_batch_v1_batch_pb.ServerMessage.deserializeBinary(new Uint8Array(buffer_arg)); 50 | } 51 | 52 | 53 | // Service for processing jobs 54 | var JobService = exports.JobService = { 55 | handleJob: { 56 | path: '/nitric.proto.batch.v1.Job/HandleJob', 57 | requestStream: true, 58 | responseStream: true, 59 | requestType: nitric_proto_batch_v1_batch_pb.ClientMessage, 60 | responseType: nitric_proto_batch_v1_batch_pb.ServerMessage, 61 | requestSerialize: serialize_nitric_proto_batch_v1_ClientMessage, 62 | requestDeserialize: deserialize_nitric_proto_batch_v1_ClientMessage, 63 | responseSerialize: serialize_nitric_proto_batch_v1_ServerMessage, 64 | responseDeserialize: deserialize_nitric_proto_batch_v1_ServerMessage, 65 | }, 66 | }; 67 | 68 | exports.JobClient = grpc.makeGenericClientConstructor(JobService); 69 | // Service for submitting jobs to be processed 70 | var BatchService = exports.BatchService = { 71 | submitJob: { 72 | path: '/nitric.proto.batch.v1.Batch/SubmitJob', 73 | requestStream: false, 74 | responseStream: false, 75 | requestType: nitric_proto_batch_v1_batch_pb.JobSubmitRequest, 76 | responseType: nitric_proto_batch_v1_batch_pb.JobSubmitResponse, 77 | requestSerialize: serialize_nitric_proto_batch_v1_JobSubmitRequest, 78 | requestDeserialize: deserialize_nitric_proto_batch_v1_JobSubmitRequest, 79 | responseSerialize: serialize_nitric_proto_batch_v1_JobSubmitResponse, 80 | responseDeserialize: deserialize_nitric_proto_batch_v1_JobSubmitResponse, 81 | }, 82 | }; 83 | 84 | exports.BatchClient = grpc.makeGenericClientConstructor(BatchService); 85 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/deployments/v1/deployments_grpc_pb.d.ts: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | // package: nitric.proto.deployments.v1 4 | // file: nitric/proto/deployments/v1/deployments.proto 5 | 6 | import * as nitric_proto_deployments_v1_deployments_pb from "../../../../nitric/proto/deployments/v1/deployments_pb"; 7 | import * as grpc from "@grpc/grpc-js"; 8 | 9 | interface IDeploymentService extends grpc.ServiceDefinition { 10 | up: grpc.MethodDefinition; 11 | down: grpc.MethodDefinition; 12 | } 13 | 14 | export const DeploymentService: IDeploymentService; 15 | 16 | export interface IDeploymentServer extends grpc.UntypedServiceImplementation { 17 | up: grpc.handleServerStreamingCall; 18 | down: grpc.handleServerStreamingCall; 19 | } 20 | 21 | export class DeploymentClient extends grpc.Client { 22 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 23 | up(argument: nitric_proto_deployments_v1_deployments_pb.DeploymentUpRequest, metadataOrOptions?: grpc.Metadata | grpc.CallOptions | null): grpc.ClientReadableStream; 24 | up(argument: nitric_proto_deployments_v1_deployments_pb.DeploymentUpRequest, metadata?: grpc.Metadata | null, options?: grpc.CallOptions | null): grpc.ClientReadableStream; 25 | down(argument: nitric_proto_deployments_v1_deployments_pb.DeploymentDownRequest, metadataOrOptions?: grpc.Metadata | grpc.CallOptions | null): grpc.ClientReadableStream; 26 | down(argument: nitric_proto_deployments_v1_deployments_pb.DeploymentDownRequest, metadata?: grpc.Metadata | null, options?: grpc.CallOptions | null): grpc.ClientReadableStream; 27 | } 28 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/deployments/v1/deployments_grpc_pb.js: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | 'use strict'; 4 | var grpc = require('@grpc/grpc-js'); 5 | var nitric_proto_deployments_v1_deployments_pb = require('../../../../nitric/proto/deployments/v1/deployments_pb.js'); 6 | var google_protobuf_struct_pb = require('google-protobuf/google/protobuf/struct_pb.js'); 7 | var nitric_proto_batch_v1_batch_pb = require('../../../../nitric/proto/batch/v1/batch_pb.js'); 8 | var nitric_proto_resources_v1_resources_pb = require('../../../../nitric/proto/resources/v1/resources_pb.js'); 9 | var nitric_proto_storage_v1_storage_pb = require('../../../../nitric/proto/storage/v1/storage_pb.js'); 10 | 11 | function serialize_nitric_proto_deployments_v1_DeploymentDownEvent(arg) { 12 | if (!(arg instanceof nitric_proto_deployments_v1_deployments_pb.DeploymentDownEvent)) { 13 | throw new Error('Expected argument of type nitric.proto.deployments.v1.DeploymentDownEvent'); 14 | } 15 | return Buffer.from(arg.serializeBinary()); 16 | } 17 | 18 | function deserialize_nitric_proto_deployments_v1_DeploymentDownEvent(buffer_arg) { 19 | return nitric_proto_deployments_v1_deployments_pb.DeploymentDownEvent.deserializeBinary(new Uint8Array(buffer_arg)); 20 | } 21 | 22 | function serialize_nitric_proto_deployments_v1_DeploymentDownRequest(arg) { 23 | if (!(arg instanceof nitric_proto_deployments_v1_deployments_pb.DeploymentDownRequest)) { 24 | throw new Error('Expected argument of type nitric.proto.deployments.v1.DeploymentDownRequest'); 25 | } 26 | return Buffer.from(arg.serializeBinary()); 27 | } 28 | 29 | function deserialize_nitric_proto_deployments_v1_DeploymentDownRequest(buffer_arg) { 30 | return nitric_proto_deployments_v1_deployments_pb.DeploymentDownRequest.deserializeBinary(new Uint8Array(buffer_arg)); 31 | } 32 | 33 | function serialize_nitric_proto_deployments_v1_DeploymentUpEvent(arg) { 34 | if (!(arg instanceof nitric_proto_deployments_v1_deployments_pb.DeploymentUpEvent)) { 35 | throw new Error('Expected argument of type nitric.proto.deployments.v1.DeploymentUpEvent'); 36 | } 37 | return Buffer.from(arg.serializeBinary()); 38 | } 39 | 40 | function deserialize_nitric_proto_deployments_v1_DeploymentUpEvent(buffer_arg) { 41 | return nitric_proto_deployments_v1_deployments_pb.DeploymentUpEvent.deserializeBinary(new Uint8Array(buffer_arg)); 42 | } 43 | 44 | function serialize_nitric_proto_deployments_v1_DeploymentUpRequest(arg) { 45 | if (!(arg instanceof nitric_proto_deployments_v1_deployments_pb.DeploymentUpRequest)) { 46 | throw new Error('Expected argument of type nitric.proto.deployments.v1.DeploymentUpRequest'); 47 | } 48 | return Buffer.from(arg.serializeBinary()); 49 | } 50 | 51 | function deserialize_nitric_proto_deployments_v1_DeploymentUpRequest(buffer_arg) { 52 | return nitric_proto_deployments_v1_deployments_pb.DeploymentUpRequest.deserializeBinary(new Uint8Array(buffer_arg)); 53 | } 54 | 55 | 56 | // The Nitric Deloyment Service contract 57 | var DeploymentService = exports.DeploymentService = { 58 | // Begins a new deployment 59 | // Server will stream updates back to the connected client 60 | // on the status of the deployment 61 | up: { 62 | path: '/nitric.proto.deployments.v1.Deployment/Up', 63 | requestStream: false, 64 | responseStream: true, 65 | requestType: nitric_proto_deployments_v1_deployments_pb.DeploymentUpRequest, 66 | responseType: nitric_proto_deployments_v1_deployments_pb.DeploymentUpEvent, 67 | requestSerialize: serialize_nitric_proto_deployments_v1_DeploymentUpRequest, 68 | requestDeserialize: deserialize_nitric_proto_deployments_v1_DeploymentUpRequest, 69 | responseSerialize: serialize_nitric_proto_deployments_v1_DeploymentUpEvent, 70 | responseDeserialize: deserialize_nitric_proto_deployments_v1_DeploymentUpEvent, 71 | }, 72 | // Tears down an existing deployment 73 | // Server will stream updates back to the connected client 74 | // on the status of the teardown 75 | down: { 76 | path: '/nitric.proto.deployments.v1.Deployment/Down', 77 | requestStream: false, 78 | responseStream: true, 79 | requestType: nitric_proto_deployments_v1_deployments_pb.DeploymentDownRequest, 80 | responseType: nitric_proto_deployments_v1_deployments_pb.DeploymentDownEvent, 81 | requestSerialize: serialize_nitric_proto_deployments_v1_DeploymentDownRequest, 82 | requestDeserialize: deserialize_nitric_proto_deployments_v1_DeploymentDownRequest, 83 | responseSerialize: serialize_nitric_proto_deployments_v1_DeploymentDownEvent, 84 | responseDeserialize: deserialize_nitric_proto_deployments_v1_DeploymentDownEvent, 85 | }, 86 | }; 87 | 88 | exports.DeploymentClient = grpc.makeGenericClientConstructor(DeploymentService); 89 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/http/v1/http_grpc_pb.d.ts: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | // package: nitric.proto.http.v1 4 | // file: nitric/proto/http/v1/http.proto 5 | 6 | import * as nitric_proto_http_v1_http_pb from "../../../../nitric/proto/http/v1/http_pb"; 7 | import * as grpc from "@grpc/grpc-js"; 8 | 9 | interface IHttpService extends grpc.ServiceDefinition { 10 | proxy: grpc.MethodDefinition; 11 | } 12 | 13 | export const HttpService: IHttpService; 14 | 15 | export interface IHttpServer extends grpc.UntypedServiceImplementation { 16 | proxy: grpc.handleBidiStreamingCall; 17 | } 18 | 19 | export class HttpClient extends grpc.Client { 20 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 21 | proxy(metadataOrOptions?: grpc.Metadata | grpc.CallOptions | null): grpc.ClientDuplexStream; 22 | proxy(metadata?: grpc.Metadata | null, options?: grpc.CallOptions | null): grpc.ClientDuplexStream; 23 | } 24 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/http/v1/http_grpc_pb.js: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | 'use strict'; 4 | var grpc = require('@grpc/grpc-js'); 5 | var nitric_proto_http_v1_http_pb = require('../../../../nitric/proto/http/v1/http_pb.js'); 6 | 7 | function serialize_nitric_proto_http_v1_ClientMessage(arg) { 8 | if (!(arg instanceof nitric_proto_http_v1_http_pb.ClientMessage)) { 9 | throw new Error('Expected argument of type nitric.proto.http.v1.ClientMessage'); 10 | } 11 | return Buffer.from(arg.serializeBinary()); 12 | } 13 | 14 | function deserialize_nitric_proto_http_v1_ClientMessage(buffer_arg) { 15 | return nitric_proto_http_v1_http_pb.ClientMessage.deserializeBinary(new Uint8Array(buffer_arg)); 16 | } 17 | 18 | function serialize_nitric_proto_http_v1_ServerMessage(arg) { 19 | if (!(arg instanceof nitric_proto_http_v1_http_pb.ServerMessage)) { 20 | throw new Error('Expected argument of type nitric.proto.http.v1.ServerMessage'); 21 | } 22 | return Buffer.from(arg.serializeBinary()); 23 | } 24 | 25 | function deserialize_nitric_proto_http_v1_ServerMessage(buffer_arg) { 26 | return nitric_proto_http_v1_http_pb.ServerMessage.deserializeBinary(new Uint8Array(buffer_arg)); 27 | } 28 | 29 | 30 | // Service for proxying HTTP requests 31 | var HttpService = exports.HttpService = { 32 | // Proxy an HTTP server 33 | proxy: { 34 | path: '/nitric.proto.http.v1.Http/Proxy', 35 | requestStream: true, 36 | responseStream: true, 37 | requestType: nitric_proto_http_v1_http_pb.ClientMessage, 38 | responseType: nitric_proto_http_v1_http_pb.ServerMessage, 39 | requestSerialize: serialize_nitric_proto_http_v1_ClientMessage, 40 | requestDeserialize: deserialize_nitric_proto_http_v1_ClientMessage, 41 | responseSerialize: serialize_nitric_proto_http_v1_ServerMessage, 42 | responseDeserialize: deserialize_nitric_proto_http_v1_ServerMessage, 43 | }, 44 | }; 45 | 46 | exports.HttpClient = grpc.makeGenericClientConstructor(HttpService); 47 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/http/v1/http_pb.d.ts: -------------------------------------------------------------------------------- 1 | // package: nitric.proto.http.v1 2 | // file: nitric/proto/http/v1/http.proto 3 | 4 | import * as jspb from "google-protobuf"; 5 | 6 | export class ClientMessage extends jspb.Message { 7 | hasRequest(): boolean; 8 | clearRequest(): void; 9 | getRequest(): HttpProxyRequest | undefined; 10 | setRequest(value?: HttpProxyRequest): void; 11 | 12 | serializeBinary(): Uint8Array; 13 | toObject(includeInstance?: boolean): ClientMessage.AsObject; 14 | static toObject(includeInstance: boolean, msg: ClientMessage): ClientMessage.AsObject; 15 | static extensions: {[key: number]: jspb.ExtensionFieldInfo}; 16 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; 17 | static serializeBinaryToWriter(message: ClientMessage, writer: jspb.BinaryWriter): void; 18 | static deserializeBinary(bytes: Uint8Array): ClientMessage; 19 | static deserializeBinaryFromReader(message: ClientMessage, reader: jspb.BinaryReader): ClientMessage; 20 | } 21 | 22 | export namespace ClientMessage { 23 | export type AsObject = { 24 | request?: HttpProxyRequest.AsObject, 25 | } 26 | } 27 | 28 | export class ServerMessage extends jspb.Message { 29 | serializeBinary(): Uint8Array; 30 | toObject(includeInstance?: boolean): ServerMessage.AsObject; 31 | static toObject(includeInstance: boolean, msg: ServerMessage): ServerMessage.AsObject; 32 | static extensions: {[key: number]: jspb.ExtensionFieldInfo}; 33 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; 34 | static serializeBinaryToWriter(message: ServerMessage, writer: jspb.BinaryWriter): void; 35 | static deserializeBinary(bytes: Uint8Array): ServerMessage; 36 | static deserializeBinaryFromReader(message: ServerMessage, reader: jspb.BinaryReader): ServerMessage; 37 | } 38 | 39 | export namespace ServerMessage { 40 | export type AsObject = { 41 | } 42 | } 43 | 44 | export class HttpProxyRequest extends jspb.Message { 45 | getHost(): string; 46 | setHost(value: string): void; 47 | 48 | serializeBinary(): Uint8Array; 49 | toObject(includeInstance?: boolean): HttpProxyRequest.AsObject; 50 | static toObject(includeInstance: boolean, msg: HttpProxyRequest): HttpProxyRequest.AsObject; 51 | static extensions: {[key: number]: jspb.ExtensionFieldInfo}; 52 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; 53 | static serializeBinaryToWriter(message: HttpProxyRequest, writer: jspb.BinaryWriter): void; 54 | static deserializeBinary(bytes: Uint8Array): HttpProxyRequest; 55 | static deserializeBinaryFromReader(message: HttpProxyRequest, reader: jspb.BinaryReader): HttpProxyRequest; 56 | } 57 | 58 | export namespace HttpProxyRequest { 59 | export type AsObject = { 60 | host: string, 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/keyvalue/v1/keyvalue_grpc_pb.d.ts: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | // package: nitric.proto.KeyValue.v1 4 | // file: nitric/proto/keyvalue/v1/keyvalue.proto 5 | 6 | import * as nitric_proto_keyvalue_v1_keyvalue_pb from "../../../../nitric/proto/keyvalue/v1/keyvalue_pb"; 7 | import * as grpc from "@grpc/grpc-js"; 8 | 9 | interface IKeyValueService extends grpc.ServiceDefinition { 10 | get: grpc.MethodDefinition; 11 | set: grpc.MethodDefinition; 12 | delete: grpc.MethodDefinition; 13 | } 14 | 15 | export const KeyValueService: IKeyValueService; 16 | 17 | export interface IKeyValueServer extends grpc.UntypedServiceImplementation { 18 | get: grpc.handleUnaryCall; 19 | set: grpc.handleUnaryCall; 20 | delete: grpc.handleUnaryCall; 21 | } 22 | 23 | export class KeyValueClient extends grpc.Client { 24 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 25 | get(argument: nitric_proto_keyvalue_v1_keyvalue_pb.KeyValueGetRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 26 | get(argument: nitric_proto_keyvalue_v1_keyvalue_pb.KeyValueGetRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 27 | get(argument: nitric_proto_keyvalue_v1_keyvalue_pb.KeyValueGetRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 28 | set(argument: nitric_proto_keyvalue_v1_keyvalue_pb.KeyValueSetRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 29 | set(argument: nitric_proto_keyvalue_v1_keyvalue_pb.KeyValueSetRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 30 | set(argument: nitric_proto_keyvalue_v1_keyvalue_pb.KeyValueSetRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 31 | delete(argument: nitric_proto_keyvalue_v1_keyvalue_pb.KeyValueDeleteRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 32 | delete(argument: nitric_proto_keyvalue_v1_keyvalue_pb.KeyValueDeleteRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 33 | delete(argument: nitric_proto_keyvalue_v1_keyvalue_pb.KeyValueDeleteRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 34 | } 35 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/kvstore/v1/kvstore_grpc_pb.d.ts: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | // package: nitric.proto.kvstore.v1 4 | // file: nitric/proto/kvstore/v1/kvstore.proto 5 | 6 | import * as nitric_proto_kvstore_v1_kvstore_pb from "../../../../nitric/proto/kvstore/v1/kvstore_pb"; 7 | import * as grpc from "@grpc/grpc-js"; 8 | 9 | interface IKvStoreService extends grpc.ServiceDefinition { 10 | getValue: grpc.MethodDefinition; 11 | setValue: grpc.MethodDefinition; 12 | deleteKey: grpc.MethodDefinition; 13 | scanKeys: grpc.MethodDefinition; 14 | } 15 | 16 | export const KvStoreService: IKvStoreService; 17 | 18 | export interface IKvStoreServer extends grpc.UntypedServiceImplementation { 19 | getValue: grpc.handleUnaryCall; 20 | setValue: grpc.handleUnaryCall; 21 | deleteKey: grpc.handleUnaryCall; 22 | scanKeys: grpc.handleServerStreamingCall; 23 | } 24 | 25 | export class KvStoreClient extends grpc.Client { 26 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 27 | getValue(argument: nitric_proto_kvstore_v1_kvstore_pb.KvStoreGetValueRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 28 | getValue(argument: nitric_proto_kvstore_v1_kvstore_pb.KvStoreGetValueRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 29 | getValue(argument: nitric_proto_kvstore_v1_kvstore_pb.KvStoreGetValueRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 30 | setValue(argument: nitric_proto_kvstore_v1_kvstore_pb.KvStoreSetValueRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 31 | setValue(argument: nitric_proto_kvstore_v1_kvstore_pb.KvStoreSetValueRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 32 | setValue(argument: nitric_proto_kvstore_v1_kvstore_pb.KvStoreSetValueRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 33 | deleteKey(argument: nitric_proto_kvstore_v1_kvstore_pb.KvStoreDeleteKeyRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 34 | deleteKey(argument: nitric_proto_kvstore_v1_kvstore_pb.KvStoreDeleteKeyRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 35 | deleteKey(argument: nitric_proto_kvstore_v1_kvstore_pb.KvStoreDeleteKeyRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 36 | scanKeys(argument: nitric_proto_kvstore_v1_kvstore_pb.KvStoreScanKeysRequest, metadataOrOptions?: grpc.Metadata | grpc.CallOptions | null): grpc.ClientReadableStream; 37 | scanKeys(argument: nitric_proto_kvstore_v1_kvstore_pb.KvStoreScanKeysRequest, metadata?: grpc.Metadata | null, options?: grpc.CallOptions | null): grpc.ClientReadableStream; 38 | } 39 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/queues/v1/queues_grpc_pb.d.ts: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | // package: nitric.proto.queues.v1 4 | // file: nitric/proto/queues/v1/queues.proto 5 | 6 | import * as nitric_proto_queues_v1_queues_pb from "../../../../nitric/proto/queues/v1/queues_pb"; 7 | import * as grpc from "@grpc/grpc-js"; 8 | 9 | interface IQueuesService extends grpc.ServiceDefinition { 10 | enqueue: grpc.MethodDefinition; 11 | dequeue: grpc.MethodDefinition; 12 | complete: grpc.MethodDefinition; 13 | } 14 | 15 | export const QueuesService: IQueuesService; 16 | 17 | export interface IQueuesServer extends grpc.UntypedServiceImplementation { 18 | enqueue: grpc.handleUnaryCall; 19 | dequeue: grpc.handleUnaryCall; 20 | complete: grpc.handleUnaryCall; 21 | } 22 | 23 | export class QueuesClient extends grpc.Client { 24 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 25 | enqueue(argument: nitric_proto_queues_v1_queues_pb.QueueEnqueueRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 26 | enqueue(argument: nitric_proto_queues_v1_queues_pb.QueueEnqueueRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 27 | enqueue(argument: nitric_proto_queues_v1_queues_pb.QueueEnqueueRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 28 | dequeue(argument: nitric_proto_queues_v1_queues_pb.QueueDequeueRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 29 | dequeue(argument: nitric_proto_queues_v1_queues_pb.QueueDequeueRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 30 | dequeue(argument: nitric_proto_queues_v1_queues_pb.QueueDequeueRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 31 | complete(argument: nitric_proto_queues_v1_queues_pb.QueueCompleteRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 32 | complete(argument: nitric_proto_queues_v1_queues_pb.QueueCompleteRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 33 | complete(argument: nitric_proto_queues_v1_queues_pb.QueueCompleteRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 34 | } 35 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/resources/v1/resources_grpc_pb.d.ts: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | // package: nitric.proto.resources.v1 4 | // file: nitric/proto/resources/v1/resources.proto 5 | 6 | import * as nitric_proto_resources_v1_resources_pb from "../../../../nitric/proto/resources/v1/resources_pb"; 7 | import * as grpc from "@grpc/grpc-js"; 8 | 9 | interface IResourcesService extends grpc.ServiceDefinition { 10 | declare: grpc.MethodDefinition; 11 | } 12 | 13 | export const ResourcesService: IResourcesService; 14 | 15 | export interface IResourcesServer extends grpc.UntypedServiceImplementation { 16 | declare: grpc.handleUnaryCall; 17 | } 18 | 19 | export class ResourcesClient extends grpc.Client { 20 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 21 | declare(argument: nitric_proto_resources_v1_resources_pb.ResourceDeclareRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 22 | declare(argument: nitric_proto_resources_v1_resources_pb.ResourceDeclareRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 23 | declare(argument: nitric_proto_resources_v1_resources_pb.ResourceDeclareRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 24 | } 25 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/resources/v1/resources_grpc_pb.js: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | 'use strict'; 4 | var grpc = require('@grpc/grpc-js'); 5 | var nitric_proto_resources_v1_resources_pb = require('../../../../nitric/proto/resources/v1/resources_pb.js'); 6 | 7 | function serialize_nitric_proto_resources_v1_ResourceDeclareRequest(arg) { 8 | if (!(arg instanceof nitric_proto_resources_v1_resources_pb.ResourceDeclareRequest)) { 9 | throw new Error('Expected argument of type nitric.proto.resources.v1.ResourceDeclareRequest'); 10 | } 11 | return Buffer.from(arg.serializeBinary()); 12 | } 13 | 14 | function deserialize_nitric_proto_resources_v1_ResourceDeclareRequest(buffer_arg) { 15 | return nitric_proto_resources_v1_resources_pb.ResourceDeclareRequest.deserializeBinary(new Uint8Array(buffer_arg)); 16 | } 17 | 18 | function serialize_nitric_proto_resources_v1_ResourceDeclareResponse(arg) { 19 | if (!(arg instanceof nitric_proto_resources_v1_resources_pb.ResourceDeclareResponse)) { 20 | throw new Error('Expected argument of type nitric.proto.resources.v1.ResourceDeclareResponse'); 21 | } 22 | return Buffer.from(arg.serializeBinary()); 23 | } 24 | 25 | function deserialize_nitric_proto_resources_v1_ResourceDeclareResponse(buffer_arg) { 26 | return nitric_proto_resources_v1_resources_pb.ResourceDeclareResponse.deserializeBinary(new Uint8Array(buffer_arg)); 27 | } 28 | 29 | 30 | // Nitric Resource Service 31 | // The service definition exists to allow a nitric application to declare peripheral dependencies 32 | var ResourcesService = exports.ResourcesService = { 33 | // Declare a resource for the nitric application 34 | // At Deploy time this will create resources as part of the nitric stacks dependency graph 35 | // At runtime 36 | declare: { 37 | path: '/nitric.proto.resources.v1.Resources/Declare', 38 | requestStream: false, 39 | responseStream: false, 40 | requestType: nitric_proto_resources_v1_resources_pb.ResourceDeclareRequest, 41 | responseType: nitric_proto_resources_v1_resources_pb.ResourceDeclareResponse, 42 | requestSerialize: serialize_nitric_proto_resources_v1_ResourceDeclareRequest, 43 | requestDeserialize: deserialize_nitric_proto_resources_v1_ResourceDeclareRequest, 44 | responseSerialize: serialize_nitric_proto_resources_v1_ResourceDeclareResponse, 45 | responseDeserialize: deserialize_nitric_proto_resources_v1_ResourceDeclareResponse, 46 | }, 47 | }; 48 | 49 | exports.ResourcesClient = grpc.makeGenericClientConstructor(ResourcesService); 50 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/schedules/v1/schedules_grpc_pb.d.ts: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | // package: nitric.proto.schedules.v1 4 | // file: nitric/proto/schedules/v1/schedules.proto 5 | 6 | import * as nitric_proto_schedules_v1_schedules_pb from "../../../../nitric/proto/schedules/v1/schedules_pb"; 7 | import * as grpc from "@grpc/grpc-js"; 8 | 9 | interface ISchedulesService extends grpc.ServiceDefinition { 10 | schedule: grpc.MethodDefinition; 11 | } 12 | 13 | export const SchedulesService: ISchedulesService; 14 | 15 | export interface ISchedulesServer extends grpc.UntypedServiceImplementation { 16 | schedule: grpc.handleBidiStreamingCall; 17 | } 18 | 19 | export class SchedulesClient extends grpc.Client { 20 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 21 | schedule(metadataOrOptions?: grpc.Metadata | grpc.CallOptions | null): grpc.ClientDuplexStream; 22 | schedule(metadata?: grpc.Metadata | null, options?: grpc.CallOptions | null): grpc.ClientDuplexStream; 23 | } 24 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/schedules/v1/schedules_grpc_pb.js: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | 'use strict'; 4 | var grpc = require('@grpc/grpc-js'); 5 | var nitric_proto_schedules_v1_schedules_pb = require('../../../../nitric/proto/schedules/v1/schedules_pb.js'); 6 | 7 | function serialize_nitric_proto_schedules_v1_ClientMessage(arg) { 8 | if (!(arg instanceof nitric_proto_schedules_v1_schedules_pb.ClientMessage)) { 9 | throw new Error('Expected argument of type nitric.proto.schedules.v1.ClientMessage'); 10 | } 11 | return Buffer.from(arg.serializeBinary()); 12 | } 13 | 14 | function deserialize_nitric_proto_schedules_v1_ClientMessage(buffer_arg) { 15 | return nitric_proto_schedules_v1_schedules_pb.ClientMessage.deserializeBinary(new Uint8Array(buffer_arg)); 16 | } 17 | 18 | function serialize_nitric_proto_schedules_v1_ServerMessage(arg) { 19 | if (!(arg instanceof nitric_proto_schedules_v1_schedules_pb.ServerMessage)) { 20 | throw new Error('Expected argument of type nitric.proto.schedules.v1.ServerMessage'); 21 | } 22 | return Buffer.from(arg.serializeBinary()); 23 | } 24 | 25 | function deserialize_nitric_proto_schedules_v1_ServerMessage(buffer_arg) { 26 | return nitric_proto_schedules_v1_schedules_pb.ServerMessage.deserializeBinary(new Uint8Array(buffer_arg)); 27 | } 28 | 29 | 30 | // Service for scheduling callbacks on a cadence 31 | var SchedulesService = exports.SchedulesService = { 32 | schedule: { 33 | path: '/nitric.proto.schedules.v1.Schedules/Schedule', 34 | requestStream: true, 35 | responseStream: true, 36 | requestType: nitric_proto_schedules_v1_schedules_pb.ClientMessage, 37 | responseType: nitric_proto_schedules_v1_schedules_pb.ServerMessage, 38 | requestSerialize: serialize_nitric_proto_schedules_v1_ClientMessage, 39 | requestDeserialize: deserialize_nitric_proto_schedules_v1_ClientMessage, 40 | responseSerialize: serialize_nitric_proto_schedules_v1_ServerMessage, 41 | responseDeserialize: deserialize_nitric_proto_schedules_v1_ServerMessage, 42 | }, 43 | }; 44 | 45 | exports.SchedulesClient = grpc.makeGenericClientConstructor(SchedulesService); 46 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/secrets/v1/secrets_grpc_pb.d.ts: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | // package: nitric.proto.secrets.v1 4 | // file: nitric/proto/secrets/v1/secrets.proto 5 | 6 | import * as nitric_proto_secrets_v1_secrets_pb from "../../../../nitric/proto/secrets/v1/secrets_pb"; 7 | import * as grpc from "@grpc/grpc-js"; 8 | 9 | interface ISecretManagerService extends grpc.ServiceDefinition { 10 | put: grpc.MethodDefinition; 11 | access: grpc.MethodDefinition; 12 | } 13 | 14 | export const SecretManagerService: ISecretManagerService; 15 | 16 | export interface ISecretManagerServer extends grpc.UntypedServiceImplementation { 17 | put: grpc.handleUnaryCall; 18 | access: grpc.handleUnaryCall; 19 | } 20 | 21 | export class SecretManagerClient extends grpc.Client { 22 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 23 | put(argument: nitric_proto_secrets_v1_secrets_pb.SecretPutRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 24 | put(argument: nitric_proto_secrets_v1_secrets_pb.SecretPutRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 25 | put(argument: nitric_proto_secrets_v1_secrets_pb.SecretPutRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 26 | access(argument: nitric_proto_secrets_v1_secrets_pb.SecretAccessRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 27 | access(argument: nitric_proto_secrets_v1_secrets_pb.SecretAccessRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 28 | access(argument: nitric_proto_secrets_v1_secrets_pb.SecretAccessRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 29 | } 30 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/secrets/v1/secrets_grpc_pb.js: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | 'use strict'; 4 | var grpc = require('@grpc/grpc-js'); 5 | var nitric_proto_secrets_v1_secrets_pb = require('../../../../nitric/proto/secrets/v1/secrets_pb.js'); 6 | 7 | function serialize_nitric_proto_secrets_v1_SecretAccessRequest(arg) { 8 | if (!(arg instanceof nitric_proto_secrets_v1_secrets_pb.SecretAccessRequest)) { 9 | throw new Error('Expected argument of type nitric.proto.secrets.v1.SecretAccessRequest'); 10 | } 11 | return Buffer.from(arg.serializeBinary()); 12 | } 13 | 14 | function deserialize_nitric_proto_secrets_v1_SecretAccessRequest(buffer_arg) { 15 | return nitric_proto_secrets_v1_secrets_pb.SecretAccessRequest.deserializeBinary(new Uint8Array(buffer_arg)); 16 | } 17 | 18 | function serialize_nitric_proto_secrets_v1_SecretAccessResponse(arg) { 19 | if (!(arg instanceof nitric_proto_secrets_v1_secrets_pb.SecretAccessResponse)) { 20 | throw new Error('Expected argument of type nitric.proto.secrets.v1.SecretAccessResponse'); 21 | } 22 | return Buffer.from(arg.serializeBinary()); 23 | } 24 | 25 | function deserialize_nitric_proto_secrets_v1_SecretAccessResponse(buffer_arg) { 26 | return nitric_proto_secrets_v1_secrets_pb.SecretAccessResponse.deserializeBinary(new Uint8Array(buffer_arg)); 27 | } 28 | 29 | function serialize_nitric_proto_secrets_v1_SecretPutRequest(arg) { 30 | if (!(arg instanceof nitric_proto_secrets_v1_secrets_pb.SecretPutRequest)) { 31 | throw new Error('Expected argument of type nitric.proto.secrets.v1.SecretPutRequest'); 32 | } 33 | return Buffer.from(arg.serializeBinary()); 34 | } 35 | 36 | function deserialize_nitric_proto_secrets_v1_SecretPutRequest(buffer_arg) { 37 | return nitric_proto_secrets_v1_secrets_pb.SecretPutRequest.deserializeBinary(new Uint8Array(buffer_arg)); 38 | } 39 | 40 | function serialize_nitric_proto_secrets_v1_SecretPutResponse(arg) { 41 | if (!(arg instanceof nitric_proto_secrets_v1_secrets_pb.SecretPutResponse)) { 42 | throw new Error('Expected argument of type nitric.proto.secrets.v1.SecretPutResponse'); 43 | } 44 | return Buffer.from(arg.serializeBinary()); 45 | } 46 | 47 | function deserialize_nitric_proto_secrets_v1_SecretPutResponse(buffer_arg) { 48 | return nitric_proto_secrets_v1_secrets_pb.SecretPutResponse.deserializeBinary(new Uint8Array(buffer_arg)); 49 | } 50 | 51 | 52 | // The Nitric Secret Service 53 | var SecretManagerService = exports.SecretManagerService = { 54 | // Updates a secret, creating a new one if it doesn't already exist 55 | put: { 56 | path: '/nitric.proto.secrets.v1.SecretManager/Put', 57 | requestStream: false, 58 | responseStream: false, 59 | requestType: nitric_proto_secrets_v1_secrets_pb.SecretPutRequest, 60 | responseType: nitric_proto_secrets_v1_secrets_pb.SecretPutResponse, 61 | requestSerialize: serialize_nitric_proto_secrets_v1_SecretPutRequest, 62 | requestDeserialize: deserialize_nitric_proto_secrets_v1_SecretPutRequest, 63 | responseSerialize: serialize_nitric_proto_secrets_v1_SecretPutResponse, 64 | responseDeserialize: deserialize_nitric_proto_secrets_v1_SecretPutResponse, 65 | }, 66 | // Gets a secret from a Secret Store 67 | access: { 68 | path: '/nitric.proto.secrets.v1.SecretManager/Access', 69 | requestStream: false, 70 | responseStream: false, 71 | requestType: nitric_proto_secrets_v1_secrets_pb.SecretAccessRequest, 72 | responseType: nitric_proto_secrets_v1_secrets_pb.SecretAccessResponse, 73 | requestSerialize: serialize_nitric_proto_secrets_v1_SecretAccessRequest, 74 | requestDeserialize: deserialize_nitric_proto_secrets_v1_SecretAccessRequest, 75 | responseSerialize: serialize_nitric_proto_secrets_v1_SecretAccessResponse, 76 | responseDeserialize: deserialize_nitric_proto_secrets_v1_SecretAccessResponse, 77 | }, 78 | }; 79 | 80 | exports.SecretManagerClient = grpc.makeGenericClientConstructor(SecretManagerService); 81 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/sql/v1/sql_grpc_pb.d.ts: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | // package: nitric.proto.sql.v1 4 | // file: nitric/proto/sql/v1/sql.proto 5 | 6 | import * as nitric_proto_sql_v1_sql_pb from "../../../../nitric/proto/sql/v1/sql_pb"; 7 | import * as grpc from "@grpc/grpc-js"; 8 | 9 | interface ISqlService extends grpc.ServiceDefinition { 10 | connectionString: grpc.MethodDefinition; 11 | } 12 | 13 | export const SqlService: ISqlService; 14 | 15 | export interface ISqlServer extends grpc.UntypedServiceImplementation { 16 | connectionString: grpc.handleUnaryCall; 17 | } 18 | 19 | export class SqlClient extends grpc.Client { 20 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 21 | connectionString(argument: nitric_proto_sql_v1_sql_pb.SqlConnectionStringRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 22 | connectionString(argument: nitric_proto_sql_v1_sql_pb.SqlConnectionStringRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 23 | connectionString(argument: nitric_proto_sql_v1_sql_pb.SqlConnectionStringRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 24 | } 25 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/sql/v1/sql_grpc_pb.js: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | 'use strict'; 4 | var grpc = require('@grpc/grpc-js'); 5 | var nitric_proto_sql_v1_sql_pb = require('../../../../nitric/proto/sql/v1/sql_pb.js'); 6 | 7 | function serialize_nitric_proto_sql_v1_SqlConnectionStringRequest(arg) { 8 | if (!(arg instanceof nitric_proto_sql_v1_sql_pb.SqlConnectionStringRequest)) { 9 | throw new Error('Expected argument of type nitric.proto.sql.v1.SqlConnectionStringRequest'); 10 | } 11 | return Buffer.from(arg.serializeBinary()); 12 | } 13 | 14 | function deserialize_nitric_proto_sql_v1_SqlConnectionStringRequest(buffer_arg) { 15 | return nitric_proto_sql_v1_sql_pb.SqlConnectionStringRequest.deserializeBinary(new Uint8Array(buffer_arg)); 16 | } 17 | 18 | function serialize_nitric_proto_sql_v1_SqlConnectionStringResponse(arg) { 19 | if (!(arg instanceof nitric_proto_sql_v1_sql_pb.SqlConnectionStringResponse)) { 20 | throw new Error('Expected argument of type nitric.proto.sql.v1.SqlConnectionStringResponse'); 21 | } 22 | return Buffer.from(arg.serializeBinary()); 23 | } 24 | 25 | function deserialize_nitric_proto_sql_v1_SqlConnectionStringResponse(buffer_arg) { 26 | return nitric_proto_sql_v1_sql_pb.SqlConnectionStringResponse.deserializeBinary(new Uint8Array(buffer_arg)); 27 | } 28 | 29 | 30 | // The Nitric Secret Service 31 | var SqlService = exports.SqlService = { 32 | // Retrieve the connection string for a given database 33 | connectionString: { 34 | path: '/nitric.proto.sql.v1.Sql/ConnectionString', 35 | requestStream: false, 36 | responseStream: false, 37 | requestType: nitric_proto_sql_v1_sql_pb.SqlConnectionStringRequest, 38 | responseType: nitric_proto_sql_v1_sql_pb.SqlConnectionStringResponse, 39 | requestSerialize: serialize_nitric_proto_sql_v1_SqlConnectionStringRequest, 40 | requestDeserialize: deserialize_nitric_proto_sql_v1_SqlConnectionStringRequest, 41 | responseSerialize: serialize_nitric_proto_sql_v1_SqlConnectionStringResponse, 42 | responseDeserialize: deserialize_nitric_proto_sql_v1_SqlConnectionStringResponse, 43 | }, 44 | }; 45 | 46 | exports.SqlClient = grpc.makeGenericClientConstructor(SqlService); 47 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/sql/v1/sql_pb.d.ts: -------------------------------------------------------------------------------- 1 | // package: nitric.proto.sql.v1 2 | // file: nitric/proto/sql/v1/sql.proto 3 | 4 | import * as jspb from "google-protobuf"; 5 | 6 | export class SqlConnectionStringRequest extends jspb.Message { 7 | getDatabaseName(): string; 8 | setDatabaseName(value: string): void; 9 | 10 | serializeBinary(): Uint8Array; 11 | toObject(includeInstance?: boolean): SqlConnectionStringRequest.AsObject; 12 | static toObject(includeInstance: boolean, msg: SqlConnectionStringRequest): SqlConnectionStringRequest.AsObject; 13 | static extensions: {[key: number]: jspb.ExtensionFieldInfo}; 14 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; 15 | static serializeBinaryToWriter(message: SqlConnectionStringRequest, writer: jspb.BinaryWriter): void; 16 | static deserializeBinary(bytes: Uint8Array): SqlConnectionStringRequest; 17 | static deserializeBinaryFromReader(message: SqlConnectionStringRequest, reader: jspb.BinaryReader): SqlConnectionStringRequest; 18 | } 19 | 20 | export namespace SqlConnectionStringRequest { 21 | export type AsObject = { 22 | databaseName: string, 23 | } 24 | } 25 | 26 | export class SqlConnectionStringResponse extends jspb.Message { 27 | getConnectionString(): string; 28 | setConnectionString(value: string): void; 29 | 30 | serializeBinary(): Uint8Array; 31 | toObject(includeInstance?: boolean): SqlConnectionStringResponse.AsObject; 32 | static toObject(includeInstance: boolean, msg: SqlConnectionStringResponse): SqlConnectionStringResponse.AsObject; 33 | static extensions: {[key: number]: jspb.ExtensionFieldInfo}; 34 | static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; 35 | static serializeBinaryToWriter(message: SqlConnectionStringResponse, writer: jspb.BinaryWriter): void; 36 | static deserializeBinary(bytes: Uint8Array): SqlConnectionStringResponse; 37 | static deserializeBinaryFromReader(message: SqlConnectionStringResponse, reader: jspb.BinaryReader): SqlConnectionStringResponse; 38 | } 39 | 40 | export namespace SqlConnectionStringResponse { 41 | export type AsObject = { 42 | connectionString: string, 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/topics/v1/topics_grpc_pb.d.ts: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | // package: nitric.proto.topics.v1 4 | // file: nitric/proto/topics/v1/topics.proto 5 | 6 | import * as nitric_proto_topics_v1_topics_pb from "../../../../nitric/proto/topics/v1/topics_pb"; 7 | import * as grpc from "@grpc/grpc-js"; 8 | 9 | interface ITopicsService extends grpc.ServiceDefinition { 10 | publish: grpc.MethodDefinition; 11 | } 12 | 13 | export const TopicsService: ITopicsService; 14 | 15 | export interface ITopicsServer extends grpc.UntypedServiceImplementation { 16 | publish: grpc.handleUnaryCall; 17 | } 18 | 19 | export class TopicsClient extends grpc.Client { 20 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 21 | publish(argument: nitric_proto_topics_v1_topics_pb.TopicPublishRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 22 | publish(argument: nitric_proto_topics_v1_topics_pb.TopicPublishRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 23 | publish(argument: nitric_proto_topics_v1_topics_pb.TopicPublishRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 24 | } 25 | 26 | interface ISubscriberService extends grpc.ServiceDefinition { 27 | subscribe: grpc.MethodDefinition; 28 | } 29 | 30 | export const SubscriberService: ISubscriberService; 31 | 32 | export interface ISubscriberServer extends grpc.UntypedServiceImplementation { 33 | subscribe: grpc.handleBidiStreamingCall; 34 | } 35 | 36 | export class SubscriberClient extends grpc.Client { 37 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 38 | subscribe(metadataOrOptions?: grpc.Metadata | grpc.CallOptions | null): grpc.ClientDuplexStream; 39 | subscribe(metadata?: grpc.Metadata | null, options?: grpc.CallOptions | null): grpc.ClientDuplexStream; 40 | } 41 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/topics/v1/topics_grpc_pb.js: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | 'use strict'; 4 | var grpc = require('@grpc/grpc-js'); 5 | var nitric_proto_topics_v1_topics_pb = require('../../../../nitric/proto/topics/v1/topics_pb.js'); 6 | var google_protobuf_duration_pb = require('google-protobuf/google/protobuf/duration_pb.js'); 7 | var google_protobuf_struct_pb = require('google-protobuf/google/protobuf/struct_pb.js'); 8 | 9 | function serialize_nitric_proto_topics_v1_ClientMessage(arg) { 10 | if (!(arg instanceof nitric_proto_topics_v1_topics_pb.ClientMessage)) { 11 | throw new Error('Expected argument of type nitric.proto.topics.v1.ClientMessage'); 12 | } 13 | return Buffer.from(arg.serializeBinary()); 14 | } 15 | 16 | function deserialize_nitric_proto_topics_v1_ClientMessage(buffer_arg) { 17 | return nitric_proto_topics_v1_topics_pb.ClientMessage.deserializeBinary(new Uint8Array(buffer_arg)); 18 | } 19 | 20 | function serialize_nitric_proto_topics_v1_ServerMessage(arg) { 21 | if (!(arg instanceof nitric_proto_topics_v1_topics_pb.ServerMessage)) { 22 | throw new Error('Expected argument of type nitric.proto.topics.v1.ServerMessage'); 23 | } 24 | return Buffer.from(arg.serializeBinary()); 25 | } 26 | 27 | function deserialize_nitric_proto_topics_v1_ServerMessage(buffer_arg) { 28 | return nitric_proto_topics_v1_topics_pb.ServerMessage.deserializeBinary(new Uint8Array(buffer_arg)); 29 | } 30 | 31 | function serialize_nitric_proto_topics_v1_TopicPublishRequest(arg) { 32 | if (!(arg instanceof nitric_proto_topics_v1_topics_pb.TopicPublishRequest)) { 33 | throw new Error('Expected argument of type nitric.proto.topics.v1.TopicPublishRequest'); 34 | } 35 | return Buffer.from(arg.serializeBinary()); 36 | } 37 | 38 | function deserialize_nitric_proto_topics_v1_TopicPublishRequest(buffer_arg) { 39 | return nitric_proto_topics_v1_topics_pb.TopicPublishRequest.deserializeBinary(new Uint8Array(buffer_arg)); 40 | } 41 | 42 | function serialize_nitric_proto_topics_v1_TopicPublishResponse(arg) { 43 | if (!(arg instanceof nitric_proto_topics_v1_topics_pb.TopicPublishResponse)) { 44 | throw new Error('Expected argument of type nitric.proto.topics.v1.TopicPublishResponse'); 45 | } 46 | return Buffer.from(arg.serializeBinary()); 47 | } 48 | 49 | function deserialize_nitric_proto_topics_v1_TopicPublishResponse(buffer_arg) { 50 | return nitric_proto_topics_v1_topics_pb.TopicPublishResponse.deserializeBinary(new Uint8Array(buffer_arg)); 51 | } 52 | 53 | 54 | // Service for publishing asynchronous messages 55 | var TopicsService = exports.TopicsService = { 56 | // Publishes a message to a given topic 57 | publish: { 58 | path: '/nitric.proto.topics.v1.Topics/Publish', 59 | requestStream: false, 60 | responseStream: false, 61 | requestType: nitric_proto_topics_v1_topics_pb.TopicPublishRequest, 62 | responseType: nitric_proto_topics_v1_topics_pb.TopicPublishResponse, 63 | requestSerialize: serialize_nitric_proto_topics_v1_TopicPublishRequest, 64 | requestDeserialize: deserialize_nitric_proto_topics_v1_TopicPublishRequest, 65 | responseSerialize: serialize_nitric_proto_topics_v1_TopicPublishResponse, 66 | responseDeserialize: deserialize_nitric_proto_topics_v1_TopicPublishResponse, 67 | }, 68 | }; 69 | 70 | exports.TopicsClient = grpc.makeGenericClientConstructor(TopicsService); 71 | // Service for subscribing to asynchronous messages 72 | var SubscriberService = exports.SubscriberService = { 73 | // Subscribe to a topic and handle incoming messages 74 | subscribe: { 75 | path: '/nitric.proto.topics.v1.Subscriber/Subscribe', 76 | requestStream: true, 77 | responseStream: true, 78 | requestType: nitric_proto_topics_v1_topics_pb.ClientMessage, 79 | responseType: nitric_proto_topics_v1_topics_pb.ServerMessage, 80 | requestSerialize: serialize_nitric_proto_topics_v1_ClientMessage, 81 | requestDeserialize: deserialize_nitric_proto_topics_v1_ClientMessage, 82 | responseSerialize: serialize_nitric_proto_topics_v1_ServerMessage, 83 | responseDeserialize: deserialize_nitric_proto_topics_v1_ServerMessage, 84 | }, 85 | }; 86 | 87 | exports.SubscriberClient = grpc.makeGenericClientConstructor(SubscriberService); 88 | -------------------------------------------------------------------------------- /src/gen/nitric/proto/websockets/v1/websockets_grpc_pb.d.ts: -------------------------------------------------------------------------------- 1 | // GENERATED CODE -- DO NOT EDIT! 2 | 3 | // package: nitric.proto.websockets.v1 4 | // file: nitric/proto/websockets/v1/websockets.proto 5 | 6 | import * as nitric_proto_websockets_v1_websockets_pb from "../../../../nitric/proto/websockets/v1/websockets_pb"; 7 | import * as grpc from "@grpc/grpc-js"; 8 | 9 | interface IWebsocketService extends grpc.ServiceDefinition { 10 | sendMessage: grpc.MethodDefinition; 11 | closeConnection: grpc.MethodDefinition; 12 | socketDetails: grpc.MethodDefinition; 13 | } 14 | 15 | export const WebsocketService: IWebsocketService; 16 | 17 | export interface IWebsocketServer extends grpc.UntypedServiceImplementation { 18 | sendMessage: grpc.handleUnaryCall; 19 | closeConnection: grpc.handleUnaryCall; 20 | socketDetails: grpc.handleUnaryCall; 21 | } 22 | 23 | export class WebsocketClient extends grpc.Client { 24 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 25 | sendMessage(argument: nitric_proto_websockets_v1_websockets_pb.WebsocketSendRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 26 | sendMessage(argument: nitric_proto_websockets_v1_websockets_pb.WebsocketSendRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 27 | sendMessage(argument: nitric_proto_websockets_v1_websockets_pb.WebsocketSendRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 28 | closeConnection(argument: nitric_proto_websockets_v1_websockets_pb.WebsocketCloseConnectionRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 29 | closeConnection(argument: nitric_proto_websockets_v1_websockets_pb.WebsocketCloseConnectionRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 30 | closeConnection(argument: nitric_proto_websockets_v1_websockets_pb.WebsocketCloseConnectionRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 31 | socketDetails(argument: nitric_proto_websockets_v1_websockets_pb.WebsocketDetailsRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; 32 | socketDetails(argument: nitric_proto_websockets_v1_websockets_pb.WebsocketDetailsRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 33 | socketDetails(argument: nitric_proto_websockets_v1_websockets_pb.WebsocketDetailsRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; 34 | } 35 | 36 | interface IWebsocketHandlerService extends grpc.ServiceDefinition { 37 | handleEvents: grpc.MethodDefinition; 38 | } 39 | 40 | export const WebsocketHandlerService: IWebsocketHandlerService; 41 | 42 | export interface IWebsocketHandlerServer extends grpc.UntypedServiceImplementation { 43 | handleEvents: grpc.handleBidiStreamingCall; 44 | } 45 | 46 | export class WebsocketHandlerClient extends grpc.Client { 47 | constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); 48 | handleEvents(metadataOrOptions?: grpc.Metadata | grpc.CallOptions | null): grpc.ClientDuplexStream; 49 | handleEvents(metadata?: grpc.Metadata | null, options?: grpc.CallOptions | null): grpc.ClientDuplexStream; 50 | } 51 | -------------------------------------------------------------------------------- /src/handlers/handler.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { BaseContext, JSONTypes } from '../context/base'; 16 | import { BlobEventContext, BucketEventContext } from '../context/bucket'; 17 | import { HttpContext } from '../context/http'; 18 | import { IntervalContext } from '../context/interval'; 19 | import { JobContext } from '../context/job'; 20 | import { MessageContext } from '../context/message'; 21 | import { WebsocketNotificationContext } from '../context/websocket'; 22 | 23 | export type GenericHandler = (ctx: Ctx) => Promise | Ctx; 24 | 25 | export type TriggerHandler = GenericHandler; 26 | export type HttpHandler = GenericHandler; 27 | 28 | export type GenericMiddleware = ( 29 | ctx: Ctx, 30 | next?: GenericHandler 31 | ) => Promise | Ctx | void; 32 | 33 | export type TriggerMiddleware = GenericMiddleware; 34 | export type HttpMiddleware = GenericMiddleware; 35 | export type WebsocketMiddleware> = 36 | GenericMiddleware>; 37 | export type MessageMiddleware< 38 | T extends Record = Record 39 | > = GenericMiddleware>; 40 | export type ScheduleMiddleware = GenericMiddleware; 41 | export type BucketNotificationMiddleware = 42 | GenericMiddleware; 43 | export type FileNotificationMiddleware = GenericMiddleware; 44 | export type JobMiddleware = GenericMiddleware; 45 | /** 46 | * createHandler 47 | * 48 | * Used to compose multiple handler functions into a single function that calls each of the provided handlers in order. 49 | * 50 | * The handlers are passed to each other via the 'next' argument. 51 | * 52 | * @param handlers one or more handler functions to be chained together into a single root function. 53 | * @returns - A root function composed of a chain of user provided functions 54 | */ 55 | export const createHandler = ( 56 | ...handlers: GenericMiddleware[] 57 | ): GenericMiddleware => { 58 | const reversedHandlers = handlers.slice().reverse(); 59 | 60 | return async (ctx: Ctx, finalNext: GenericHandler = (ctx) => ctx) => { 61 | if (handlers.length < 1) { 62 | throw new Error( 63 | 'at least one handler or middleware function must be provided' 64 | ); 65 | } 66 | if (handlers.some((handler) => typeof handler !== 'function')) { 67 | throw new Error('all handlers and middleware must be functions'); 68 | } 69 | 70 | // Chain the provided handlers together, passing each as 'next' to the following handler in the chain. 71 | 72 | const composedHandler = reversedHandlers.reduce( 73 | (next: GenericHandler, h: GenericMiddleware) => { 74 | const nextNext: GenericHandler = async (ctx) => { 75 | // Actual function written by user that calls next and returns context 76 | return (await h(ctx, next)) || ctx; 77 | }; 78 | return nextNext; 79 | }, 80 | finalNext 81 | ); 82 | 83 | // Call the root user function from this function 84 | return await composedHandler(ctx); 85 | }; 86 | }; 87 | -------------------------------------------------------------------------------- /src/handlers/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './handler'; 15 | export * from './json'; 16 | -------------------------------------------------------------------------------- /src/handlers/json.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { HttpContext } from '../context/http'; 16 | import type { HttpMiddleware } from './handler'; 17 | 18 | const decodeData = (data: string | Uint8Array): string => { 19 | if (typeof data !== 'string') { 20 | return new TextDecoder('utf-8').decode(data); 21 | } 22 | return data; 23 | }; 24 | 25 | /** 26 | * HttpMiddleware that takes a ctx.req containing raw data (string | Uint8Array) and parses it as JSON into ctx.body 27 | * 28 | * @returns a middleware decorator 29 | */ 30 | export const json = (): HttpMiddleware => (ctx: HttpContext, next) => { 31 | (ctx.req as any).body = JSON.parse(decodeData(ctx.req.data)); 32 | return next(ctx); 33 | }; 34 | 35 | /** 36 | * Helper method to encode to JSON string for JSON http responses. 37 | * 38 | * @param ctx HttpContext 39 | * @returns HttpContext with body property set with an encoded JSON string and json headers set. 40 | */ 41 | export const jsonResponse = 42 | (ctx: HttpContext) => 43 | (data: string | number | boolean | Record): HttpContext => { 44 | ctx.res.body = new TextEncoder().encode(JSON.stringify(data)); 45 | ctx.res.headers['Content-Type'] = ['application/json']; 46 | 47 | return ctx; 48 | }; 49 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './api'; 15 | export * from './resources'; 16 | export * from './types'; 17 | export * from './context'; 18 | export * from './handlers'; 19 | export { Lifecycle } from './lifecycle'; 20 | -------------------------------------------------------------------------------- /src/lifecycle/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | export * from './lifecycle'; 16 | -------------------------------------------------------------------------------- /src/lifecycle/lifecycle.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // The environment variable key that will be used to determine the current Nitric lifecycle/executing environment 16 | const NITRIC_ENVIRONMENT = 'NITRIC_ENVIRONMENT'; 17 | 18 | // Possible nitric execution environments 19 | export enum LifecycleStage { 20 | // Local development run (using nitric run/start) 21 | LocalRun = 'run', 22 | // Local development requirements building/collection (using nitric up) 23 | Build = 'build', 24 | // When the code is running in a deployed environment 25 | Cloud = 'cloud', 26 | } 27 | 28 | const getCurrentLifecycle = (): LifecycleStage => { 29 | const lifecycle = process.env[NITRIC_ENVIRONMENT]; 30 | if ( 31 | !lifecycle || 32 | !Object.values(LifecycleStage).includes(lifecycle as LifecycleStage) 33 | ) { 34 | throw new Error( 35 | `Unable to determine the current Nitric lifecycle, please ensure the ${NITRIC_ENVIRONMENT} environment variable is set` 36 | ); 37 | } 38 | return lifecycle as LifecycleStage; 39 | }; 40 | 41 | // Check if the current environment is one of the provided stages 42 | const isInLifecycle = (stage: LifecycleStage[]) => { 43 | const currentStage = getCurrentLifecycle(); 44 | return stage.includes(currentStage); 45 | }; 46 | 47 | // If the current environment is one of the provided stages, execute the provided callback 48 | const whenInLifecycles = ( 49 | stage: LifecycleStage[], 50 | callback: Lifecycle 51 | ): T | undefined => { 52 | if (isInLifecycle(stage)) { 53 | return callback(); 54 | } 55 | }; 56 | 57 | const whenRunning = (callback: Lifecycle) => 58 | whenInLifecycles([LifecycleStage.LocalRun, LifecycleStage.Cloud], callback); 59 | 60 | const whenCollecting = (callback: Lifecycle) => 61 | whenInLifecycles([LifecycleStage.Build], callback); 62 | 63 | const isRunning = () => 64 | isInLifecycle([LifecycleStage.LocalRun, LifecycleStage.Cloud]); 65 | 66 | const isCollecting = () => isInLifecycle([LifecycleStage.Build]); 67 | 68 | type Lifecycle = () => T; 69 | 70 | export const Lifecycle = { 71 | // Check if the current environment is one of the provided stages 72 | is: isInLifecycle, 73 | // Check if the current lifecycle is collecting application requirements 74 | isCollecting, 75 | // Check if the current lifecycle is running the app 76 | isRunning, 77 | // If the current environment is one of the provided stages, execute the provided callback 78 | when: whenInLifecycles, 79 | // If the current environment is collecting application requirements 80 | whenCollecting, 81 | // If the current environment is a cloud environment, execute the provided callback 82 | whenRunning, 83 | }; 84 | -------------------------------------------------------------------------------- /src/resources/api.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { api, Method } from '.'; 15 | import { ResourcesClient } from '@nitric/proto/resources/v1/resources_grpc_pb'; 16 | import { ApiDetailsResponse } from '../gen/nitric/proto/apis/v1/apis_pb'; 17 | import { ApiClient } from '../gen/nitric/proto/apis/v1/apis_grpc_pb'; 18 | import { status } from '@grpc/grpc-js'; 19 | 20 | describe('Api', () => { 21 | const MOCK_ERROR = { 22 | code: status.UNIMPLEMENTED, 23 | message: 'UNIMPLEMENTED', 24 | }; 25 | 26 | let declareSpy; 27 | let startSpy; 28 | let mockFn; 29 | beforeAll(() => { 30 | jest.spyOn(console, 'error').mockImplementation(() => {}); 31 | declareSpy = jest 32 | .spyOn(ResourcesClient.prototype, 'declare') 33 | .mockImplementationOnce((request, callback: any) => { 34 | callback(MOCK_ERROR, null); 35 | 36 | return null as any; 37 | }); 38 | startSpy = jest 39 | .spyOn(Method.prototype as any, 'start') 40 | .mockReturnValue(Promise.resolve()); 41 | mockFn = jest.fn(); 42 | }); 43 | 44 | afterAll(() => { 45 | jest.restoreAllMocks(); 46 | }); 47 | 48 | describe('when create a new route', () => { 49 | afterAll(() => { 50 | jest.resetAllMocks(); 51 | }); 52 | 53 | const route = api('main').route('/newroute/'); 54 | 55 | describe('when registering a catch all handler', () => { 56 | beforeAll(async () => { 57 | await route.all(mockFn); 58 | }); 59 | 60 | it('should call Method::start()', () => { 61 | expect(startSpy).toBeCalledTimes(1); 62 | }); 63 | }); 64 | }); 65 | 66 | // individual method handlers 67 | ['get', 'post', 'delete', 'patch', 'put', 'options'].forEach((method) => { 68 | describe(`when creating a new ${method} handler`, () => { 69 | beforeAll(async () => { 70 | await api('main1', { 71 | path: 'v1', 72 | })[method]('/test/', mockFn, { 73 | security: { 74 | test: [], 75 | }, 76 | }); 77 | }); 78 | 79 | afterAll(() => { 80 | jest.resetAllMocks(); 81 | }); 82 | 83 | it('should call FaasClient::start()', () => { 84 | expect(startSpy).toBeCalledTimes(1); 85 | }); 86 | }); 87 | }); 88 | 89 | describe('when getting the url', () => { 90 | describe('when api details are returned', () => { 91 | let a; 92 | let detailsSpy; 93 | 94 | beforeAll(async () => { 95 | // mock the details api 96 | detailsSpy = jest 97 | .spyOn(ApiClient.prototype, 'apiDetails') 98 | .mockImplementationOnce((request, callback: any) => { 99 | const resp = new ApiDetailsResponse(); 100 | resp.setUrl('http://localhost:9001/test'); 101 | 102 | callback(null, resp); 103 | 104 | return null as any; 105 | }); 106 | 107 | a = await api('main'); 108 | }); 109 | 110 | afterAll(() => { 111 | jest.resetAllMocks(); 112 | }); 113 | 114 | it('should return the url', async () => { 115 | await expect(a.url()).resolves.toBe('http://localhost:9001/test'); 116 | }); 117 | }); 118 | }); 119 | }); 120 | -------------------------------------------------------------------------------- /src/resources/bucket.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { ResourcesClient } from '@nitric/proto/resources/v1/resources_grpc_pb'; 16 | import { UnimplementedError } from '../api/errors'; 17 | import { bucket } from '.'; 18 | import { 19 | BucketResource, 20 | ResourceDeclareResponse, 21 | } from '@nitric/proto/resources/v1/resources_pb'; 22 | import { Resource } from './common'; 23 | import { Bucket } from '..'; 24 | import { Metadata, status } from '@grpc/grpc-js'; 25 | 26 | // What we need to test about buckets 27 | // 1. register with the name 28 | // 2. cache is used if name is used twice 29 | // 3. read policy can be declared 30 | // 4. write policy can be declared 31 | 32 | describe('Registering bucket resources', () => { 33 | describe('Given the server is unimplemented', () => { 34 | describe('When a bucket is registered', () => { 35 | const MOCK_ERROR = { 36 | code: status.UNIMPLEMENTED, 37 | message: 'UNIMPLEMENTED', 38 | }; 39 | 40 | const validName = 'my-bucket'; 41 | let declareSpy; 42 | 43 | beforeAll(() => { 44 | jest.spyOn(console, 'error').mockImplementation(() => {}); 45 | declareSpy = jest 46 | .spyOn(ResourcesClient.prototype, 'declare') 47 | .mockImplementationOnce((request, callback: any) => { 48 | callback(MOCK_ERROR, null); 49 | 50 | return null as any; 51 | }); 52 | }); 53 | 54 | afterAll(() => { 55 | jest.restoreAllMocks(); 56 | }); 57 | 58 | it('Should throw the error', async () => { 59 | await expect( 60 | bucket(validName)['registerPromise'] 61 | ).rejects.toBeInstanceOf(UnimplementedError); 62 | }); 63 | 64 | it('Should call the resource server', () => { 65 | expect(declareSpy).toBeCalledTimes(1); 66 | }); 67 | }); 68 | }); 69 | 70 | describe('Given the server is available', () => { 71 | describe('When registering a new bucket', () => { 72 | const validName = 'my-bucket2'; 73 | let otherSpy; 74 | 75 | beforeAll(() => { 76 | otherSpy = jest 77 | .spyOn(ResourcesClient.prototype, 'declare') 78 | .mockImplementationOnce((request, callback: any) => { 79 | const response = new ResourceDeclareResponse(); 80 | callback(null, response); 81 | return null as any; 82 | }); 83 | }); 84 | 85 | afterAll(() => { 86 | jest.resetAllMocks(); 87 | }); 88 | 89 | it('Should succeed', async () => { 90 | await expect( 91 | bucket(validName)['registerPromise'] 92 | ).resolves.not.toBeNull(); 93 | }); 94 | 95 | it('Should call the resource server', () => { 96 | expect(otherSpy).toBeCalledTimes(1); 97 | }); 98 | }); 99 | 100 | describe('Given a bucket is already registered', () => { 101 | const bucketName = 'already-exists'; 102 | let bucketResource; 103 | let existsSpy; 104 | 105 | beforeEach(() => { 106 | // ensure a success is returned and calls can be counted. 107 | existsSpy = jest 108 | .spyOn(ResourcesClient.prototype, 'declare') 109 | .mockImplementation((request, callback: any) => { 110 | const response = new ResourceDeclareResponse(); 111 | callback(null, response); 112 | return null as any; 113 | }); 114 | 115 | // register the bucket for the first time 116 | bucketResource = bucket(bucketName); 117 | }); 118 | 119 | afterEach(() => { 120 | jest.resetAllMocks(); 121 | }); 122 | 123 | describe('When registering a bucket with the same name', () => { 124 | let secondBucket; 125 | 126 | beforeEach(() => { 127 | // make sure the initial registration isn't counted for these tests. 128 | existsSpy.mockClear(); 129 | secondBucket = bucket(bucketName); 130 | }); 131 | 132 | it('Should not call the server again', () => { 133 | expect(existsSpy).not.toBeCalled(); 134 | }); 135 | 136 | it('Should return the same resource object', () => { 137 | expect(bucketResource === secondBucket).toEqual(true); 138 | }); 139 | }); 140 | 141 | describe('When declaring usage', () => { 142 | it('Should return a bucket reference', () => { 143 | const ref = bucketResource.for('reading'); 144 | expect(ref).toBeInstanceOf(Bucket); 145 | }); 146 | }); 147 | }); 148 | }); 149 | }); 150 | -------------------------------------------------------------------------------- /src/resources/client.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { ResourcesClient } from '@nitric/proto/resources/v1/resources_grpc_pb'; 15 | import { SERVICE_BIND } from '../constants'; 16 | import * as grpc from '@grpc/grpc-js'; 17 | 18 | const resourceClient = new ResourcesClient( 19 | SERVICE_BIND, 20 | grpc.ChannelCredentials.createInsecure() 21 | ); 22 | 23 | export default resourceClient; 24 | -------------------------------------------------------------------------------- /src/resources/common.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { Resource, make } from './common'; 15 | 16 | const MOCK_RESOURCE = 0; 17 | const MOCK_DETAILS = {}; 18 | 19 | class MockResource extends Resource { 20 | register = jest.fn().mockReturnValue(Promise.resolve()); 21 | permsToActions = jest.fn(); 22 | unwrapDetails = jest.fn(() => MOCK_DETAILS); 23 | resourceType = jest.fn(() => MOCK_RESOURCE) as any; 24 | } 25 | 26 | describe('common', () => { 27 | describe('when calling make', () => { 28 | const res = make(MockResource); 29 | 30 | it('should create a constructor for the new resource', () => { 31 | expect(typeof res).toBe('function'); 32 | }); 33 | 34 | describe('when calling the function returned by make', () => { 35 | const test = res('test'); 36 | it('should return a new instance of MockResource', () => { 37 | expect(test instanceof MockResource).toBe(true); 38 | }); 39 | }); 40 | 41 | describe('when creating two resources with the same name', () => { 42 | const test1 = res('same'); 43 | const test2 = res('same'); 44 | 45 | it('should return the same instance of those resource', () => { 46 | expect(test1).toStrictEqual(test2); 47 | }); 48 | }); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /src/resources/common.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { 15 | ResourceIdentifier as ProtoResource, 16 | ResourceType, 17 | PolicyResource, 18 | ResourceDeclareRequest, 19 | ActionMap, 20 | ResourceTypeMap, 21 | } from '@nitric/proto/resources/v1/resources_pb'; 22 | import resourceClient from './client'; 23 | import { Duration } from 'google-protobuf/google/protobuf/duration_pb'; 24 | import type { ClientDuplexStream } from '@grpc/grpc-js'; 25 | import { fromGrpcError } from '../api/errors'; 26 | 27 | export type ActionsList = ActionMap[keyof ActionMap][]; 28 | 29 | export abstract class Resource { 30 | /** 31 | * Unique name for the resource by type within the stack. 32 | * 33 | * This name can be used in all future references, it will be resolved automatically at runtime. 34 | */ 35 | public readonly name: string; 36 | /** 37 | * Used to resolve the given resource for policy creation 38 | */ 39 | private _registerPromise: Promise; 40 | 41 | constructor(name: string) { 42 | this.name = name; 43 | } 44 | 45 | protected get registerPromise(): Promise { 46 | return this._registerPromise; 47 | } 48 | 49 | protected set registerPromise(promise: Promise) { 50 | this._registerPromise = promise; 51 | } 52 | 53 | protected abstract resourceType(): ResourceTypeMap[keyof ResourceTypeMap]; 54 | 55 | protected abstract register(): Promise; 56 | } 57 | 58 | export abstract class SecureResource

extends Resource { 59 | protected abstract permsToActions(...perms: P[]): ActionsList; 60 | 61 | protected registerPolicy(...perms: P[]): void { 62 | const req = new ResourceDeclareRequest(); 63 | const policyResource = new ProtoResource(); 64 | policyResource.setType(ResourceType.POLICY); 65 | 66 | // Send an unnamed function as the principle. This is interpreted to mean the currently running function, making the request. 67 | const policy = new PolicyResource(); 68 | const defaultPrincipal = new ProtoResource(); 69 | defaultPrincipal.setType(ResourceType.SERVICE); 70 | policy.setPrincipalsList([defaultPrincipal]); 71 | 72 | // Convert the permissions to an action set. 73 | const actions = this.permsToActions(...perms); 74 | policy.setActionsList(actions); 75 | 76 | req.setId(policyResource); 77 | req.setPolicy(policy); 78 | 79 | this.registerPromise.then((resource) => { 80 | policy.setResourcesList([resource]); 81 | 82 | resourceClient.declare(req, (error) => { 83 | if (error) { 84 | throw fromGrpcError(error); 85 | } 86 | }); 87 | }); 88 | } 89 | } 90 | 91 | // This singleton helps avoid duplicate references to bucket('name') 92 | // will return the same bucket resource 93 | const cache: Record> = {}; 94 | 95 | export type newer = (name: string, ...args: any[]) => T; 96 | 97 | /** 98 | * Provides a new resource instance. 99 | * 100 | * @param T the type of resource to construct 101 | * @returns the resource 102 | */ 103 | export const make = ( 104 | T: new (name: string, ...args: any[]) => T 105 | ): newer => { 106 | const typename = T.name; 107 | return (name: string, ...args: any[]) => { 108 | if (!cache[typename]) { 109 | cache[typename] = {}; 110 | } 111 | if (!cache[typename][name]) { 112 | cache[typename][name] = new T(name, ...args); 113 | 114 | const prom = cache[typename][name]['register'](); 115 | 116 | cache[typename][name]['registerPromise'] = prom; 117 | 118 | prom.catch((err) => { 119 | console.error(err); 120 | }); 121 | } 122 | return cache[typename][name] as T; 123 | }; 124 | }; 125 | 126 | export const toDuration = (seconds: number): Duration => { 127 | const duration = new Duration(); 128 | duration.setSeconds(seconds); 129 | 130 | return duration; 131 | }; 132 | 133 | export const startStreamHandler = async ( 134 | handler: () => Promise> 135 | ): Promise => { 136 | const stream = await handler(); 137 | 138 | // Block until the stream has closed... 139 | await new Promise((res) => { 140 | // The server has determined this stream must close 141 | stream.on('end', () => { 142 | console.log('Membrane has terminated the trigger stream'); 143 | res(); 144 | }); 145 | }); 146 | }; 147 | -------------------------------------------------------------------------------- /src/resources/http.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { HttpWorkerOptions, http } from '.'; 15 | import { HttpClient } from '../gen/nitric/proto/http/v1/http_grpc_pb'; 16 | 17 | jest.mock('portfinder', () => { 18 | const originalModule = jest.requireActual('portfinder'); 19 | 20 | return { 21 | __esmodule: true, 22 | ...originalModule, 23 | getPort: (callback: (err, port) => void) => { 24 | callback('', 1234); 25 | }, 26 | }; 27 | }); 28 | 29 | describe.skip('HTTP Proxy', () => { 30 | const httpProxySpy = jest 31 | .spyOn(HttpClient.prototype, 'proxy') 32 | .mockReturnValue({} as any); 33 | 34 | const mockApp = { 35 | listen: () => { 36 | return { 37 | on: () => {}, 38 | } as any; 39 | }, 40 | }; 41 | 42 | afterAll(() => { 43 | jest.clearAllMocks(); 44 | }); 45 | 46 | describe.skip('when creating a new http proxy with an app', () => { 47 | let error = undefined; 48 | afterAll(() => { 49 | jest.resetAllMocks(); 50 | }); 51 | 52 | beforeAll(() => { 53 | try { 54 | http(mockApp); 55 | } catch (err) { 56 | error = err; 57 | } 58 | }); 59 | 60 | it('should not return an error', () => { 61 | expect(error).toBe(undefined); 62 | }); 63 | }); 64 | 65 | describe.skip(`when creating a new http proxy with an app and callback`, () => { 66 | const fakeCallback = () => {}; 67 | 68 | afterAll(() => { 69 | jest.resetAllMocks(); 70 | }); 71 | 72 | beforeAll(async () => { 73 | http(mockApp, fakeCallback); 74 | }); 75 | 76 | it('should call HttpClient::proxy()', () => { 77 | expect(httpProxySpy).toBeCalledTimes(1); 78 | }); 79 | }); 80 | 81 | describe.skip(`when creating a new http proxy with a bootstrap function`, () => { 82 | const fakeFunc = () => { 83 | return { 84 | on: () => {}, 85 | } as any; 86 | }; 87 | const fakeCallback = () => {}; 88 | 89 | afterAll(() => { 90 | jest.resetAllMocks(); 91 | }); 92 | 93 | beforeAll(async () => { 94 | http(fakeFunc, fakeCallback); 95 | }); 96 | 97 | it('should call HttpClient::proxy()', () => { 98 | expect(httpProxySpy).toBeCalledTimes(1); 99 | }); 100 | }); 101 | }); 102 | -------------------------------------------------------------------------------- /src/resources/http.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import portfinder from 'portfinder'; 16 | import { HttpClient } from '@nitric/proto/http/v1/http_grpc_pb'; 17 | import { SERVICE_BIND } from '../constants'; 18 | import * as grpc from '@grpc/grpc-js'; 19 | import { ClientMessage, HttpProxyRequest } from '@nitric/proto/http/v1/http_pb'; 20 | 21 | interface ServerType { 22 | on: ( 23 | eventType: 'close', 24 | callback: () => void, 25 | options?: Record 26 | ) => void; 27 | close?: () => void; 28 | } 29 | 30 | type ListenerFunction = 31 | | ((port: number, callback?: () => void) => ServerType | Promise) 32 | | ((port: number) => ServerType | Promise); 33 | 34 | interface NodeApplication { 35 | listen: ListenerFunction; 36 | } 37 | 38 | // eslint-disable-next-line 39 | const NO_OP = () => {}; 40 | 41 | export class HttpWorkerOptions { 42 | public readonly app: NodeApplication; 43 | public readonly port: number; 44 | public readonly callback: () => void; 45 | 46 | constructor( 47 | app: NodeApplication, 48 | port: number, 49 | callback: () => void = NO_OP 50 | ) { 51 | this.app = app; 52 | this.port = port; 53 | this.callback = callback; 54 | } 55 | } 56 | 57 | const createWorker = async ( 58 | app: NodeApplication, 59 | port: number, 60 | callback?: () => void 61 | ) => { 62 | const httpClient = new HttpClient( 63 | SERVICE_BIND, 64 | grpc.ChannelCredentials.createInsecure() 65 | ); 66 | 67 | const httpProxyRequest = new HttpProxyRequest(); 68 | httpProxyRequest.setHost(`localhost:${port}`); 69 | 70 | const httpProxyStream = httpClient.proxy(); 71 | 72 | httpProxyStream.on('data', NO_OP); 73 | 74 | httpProxyStream.on('error', (err) => { 75 | console.error('An error occurred:', err); 76 | }); 77 | 78 | const clientMessage = new ClientMessage(); 79 | clientMessage.setRequest(httpProxyRequest); 80 | httpProxyStream.write(clientMessage); 81 | // Start Node application that HTTP proxy sits on 82 | if (process.env.NITRIC_ENVIRONMENT !== 'build') { 83 | const srv = await app.listen(port, callback); 84 | 85 | srv.on('close', () => { 86 | httpProxyStream.cancel(); 87 | }); 88 | 89 | httpProxyStream.on('end', () => { 90 | if (typeof srv.close === 'function') { 91 | srv.close(); 92 | } else { 93 | process.exit(1); // Close the Node.js application with a non-zero exit code 94 | } 95 | }); 96 | } 97 | }; 98 | 99 | /** 100 | * Register an HTTP Proxy to the provided application. 101 | * 102 | * @param app the http application to run behind the proxy 103 | * @param callback an optional callback to run after the proxy has started 104 | */ 105 | export const http = ( 106 | app: NodeApplication | ListenerFunction, 107 | callback?: () => void 108 | ): void => { 109 | const unknownApp = app as any; 110 | 111 | const nodeApp = 112 | !!unknownApp.listen && typeof unknownApp.listen === 'function' 113 | ? (app as NodeApplication) 114 | : { listen: app as ListenerFunction }; 115 | 116 | const port = Number.parseInt(process.env.NITRIC_HTTP_PROXY_PORT); 117 | 118 | if (!port || Number.isNaN(port)) { 119 | // If port isn't set and the nitric environment is not run or cloud 120 | console.log('NITRIC_HTTP_PROXY_PORT not set. Finding open port...'); 121 | portfinder.getPort((err, port) => { 122 | if (err) { 123 | throw new Error( 124 | 'Unable to find open port. Try setting the env var `NITRIC_HTTP_PROXY_PORT`' 125 | ); 126 | } 127 | 128 | createWorker(nodeApp, port, callback); 129 | }); 130 | 131 | return; 132 | } 133 | 134 | createWorker(nodeApp, port, callback); 135 | }; 136 | -------------------------------------------------------------------------------- /src/resources/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export * from './api'; 15 | export * from './topic'; 16 | export * from './queue'; 17 | export * from './keyvalue'; 18 | export * from './bucket'; 19 | export * from './schedule'; 20 | export * from './secret'; 21 | export * from './sql'; 22 | export * from './http'; 23 | export * from './websocket'; 24 | export * from './batch'; 25 | export { oidcRule } from './oidc'; 26 | -------------------------------------------------------------------------------- /src/resources/keyvalue.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { status, ServiceError, Metadata } from '@grpc/grpc-js'; 16 | import { ResourcesClient } from '@nitric/proto/resources/v1/resources_grpc_pb'; 17 | import { UnimplementedError } from '../api/errors'; 18 | import { kv } from '.'; 19 | import { ResourceDeclareResponse } from '@nitric/proto/resources/v1/resources_pb'; 20 | import { StoreRef } from '../api/keyvalue/v1/store'; 21 | 22 | describe('Registering key/value store resources', () => { 23 | describe('Given declare returns an error from the resource server', () => { 24 | const MOCK_ERROR = { 25 | code: status.UNIMPLEMENTED, 26 | message: 'UNIMPLEMENTED', 27 | }; 28 | 29 | const validName = 'my-store'; 30 | let declareSpy; 31 | 32 | beforeAll(() => { 33 | jest.spyOn(console, 'error').mockImplementation(() => {}); 34 | declareSpy = jest 35 | .spyOn(ResourcesClient.prototype, 'declare') 36 | .mockImplementationOnce((request, callback: any) => { 37 | callback(MOCK_ERROR, null); 38 | 1; 39 | return null as any; 40 | }); 41 | }); 42 | 43 | afterAll(() => { 44 | jest.restoreAllMocks(); 45 | }); 46 | 47 | it('Should throw the error', async () => { 48 | await expect(kv(validName)['registerPromise']).rejects.toBeInstanceOf( 49 | UnimplementedError 50 | ); 51 | }); 52 | 53 | it('Should call the resource server', () => { 54 | expect(declareSpy).toBeCalledTimes(1); 55 | }); 56 | }); 57 | 58 | describe('Given declare succeeds on the resource server', () => { 59 | describe('When the service succeeds', () => { 60 | const validName = 'my-store2'; 61 | let otherSpy; 62 | 63 | beforeAll(() => { 64 | otherSpy = jest 65 | .spyOn(ResourcesClient.prototype, 'declare') 66 | .mockImplementationOnce((request, callback: any) => { 67 | const response = new ResourceDeclareResponse(); 68 | callback(null, response); 69 | return null as any; 70 | }); 71 | }); 72 | 73 | afterAll(() => { 74 | jest.resetAllMocks(); 75 | }); 76 | 77 | it('Should succeed', async () => { 78 | await expect(kv(validName)['registerPromise']).resolves.not.toBeNull(); 79 | }); 80 | 81 | it('Should call the resource server', () => { 82 | expect(otherSpy).toBeCalledTimes(1); 83 | }); 84 | }); 85 | }); 86 | 87 | describe('Given a store is already registered', () => { 88 | const storeName = 'already-exists'; 89 | let store; 90 | let existsSpy; 91 | 92 | beforeEach(() => { 93 | // ensure a success is returned and calls can be counted. 94 | existsSpy = jest 95 | .spyOn(ResourcesClient.prototype, 'declare') 96 | .mockImplementation((request, callback: any) => { 97 | const response = new ResourceDeclareResponse(); 98 | callback(null, response); 99 | return null as any; 100 | }); 101 | 102 | // register the resource for the first time 103 | store = kv(storeName); 104 | }); 105 | 106 | afterEach(() => { 107 | jest.resetAllMocks(); 108 | }); 109 | 110 | describe('When registering a store with the same name', () => { 111 | let secondStore; 112 | 113 | beforeEach(() => { 114 | // make sure the initial registration isn't counted for these tests. 115 | existsSpy.mockClear(); 116 | secondStore = kv(storeName); 117 | }); 118 | 119 | it('Should not call the server again', () => { 120 | expect(existsSpy).not.toBeCalled(); 121 | }); 122 | 123 | it('Should return the same resource object', () => { 124 | expect(store === secondStore).toEqual(true); 125 | }); 126 | }); 127 | 128 | describe('When declaring usage', () => { 129 | it('Should return a store reference', () => { 130 | const ref = store.for('getting'); 131 | expect(ref).toBeInstanceOf(StoreRef); 132 | }); 133 | }); 134 | }); 135 | }); 136 | -------------------------------------------------------------------------------- /src/resources/oidc.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { 15 | ResourceIdentifier, 16 | ResourceDeclareRequest, 17 | ResourceDeclareResponse, 18 | ResourceType, 19 | ResourceTypeMap, 20 | ApiSecurityDefinitionResource, 21 | ApiOpenIdConnectionDefinition, 22 | } from '@nitric/proto/resources/v1/resources_pb'; 23 | import resourceClient from './client'; 24 | import { make, newer, Resource } from './common'; 25 | import { fromGrpcError } from '../api/errors'; 26 | 27 | /** 28 | * Cloud storage bucket resource for large file storage. 29 | */ 30 | export class OidcSecurityDefinition extends Resource { 31 | private apiName: string; 32 | private issuer: string; 33 | private ruleName: string; 34 | private audiences: string[]; 35 | 36 | constructor(name: string, apiName: string, options: UnscopedOicdOptions) { 37 | super(name); 38 | this.apiName = apiName; 39 | this.issuer = options.issuer; 40 | this.audiences = options.audiences; 41 | this.ruleName = options.name; 42 | } 43 | 44 | protected resourceType(): ResourceTypeMap[keyof ResourceTypeMap] { 45 | return ResourceType.APISECURITYDEFINITION; 46 | } 47 | 48 | /** 49 | * Register this bucket as a required resource for the calling function/container. 50 | * 51 | * @returns a promise that resolves when the registration is complete 52 | */ 53 | protected async register(): Promise { 54 | const req = new ResourceDeclareRequest(); 55 | const resource = new ResourceIdentifier(); 56 | resource.setName(this.ruleName); 57 | resource.setType(ResourceType.APISECURITYDEFINITION); 58 | 59 | const securityDefinition = new ApiSecurityDefinitionResource(); 60 | const oidcDefinition = new ApiOpenIdConnectionDefinition(); 61 | 62 | oidcDefinition.setAudiencesList(this.audiences); 63 | oidcDefinition.setIssuer(this.issuer); 64 | 65 | securityDefinition.setApiName(this.apiName); 66 | securityDefinition.setOidc(oidcDefinition); 67 | 68 | req.setId(resource); 69 | req.setApiSecurityDefinition(securityDefinition); 70 | 71 | return new Promise((resolve, reject) => { 72 | resourceClient.declare(req, (error, _: ResourceDeclareResponse) => { 73 | if (error) { 74 | reject(fromGrpcError(error)); 75 | } else { 76 | resolve(resource); 77 | } 78 | }); 79 | }); 80 | } 81 | } 82 | 83 | export interface OidcOptions { 84 | name: string; 85 | issuer: string; 86 | audiences: string[]; 87 | scopes: string[]; 88 | } 89 | 90 | export type UnscopedOicdOptions = Omit; 91 | 92 | export type SecurityOption = (...scopes: string[]) => OidcOptions; 93 | 94 | /** 95 | * Constructs a new OpenID Connect (OIDC) security definition, which can be applied to APIs and their routes. 96 | * 97 | * This rule can be applied with various scopes, which are used to restrict access to the API. 98 | * @param options - The options for the OIDC security definition. 99 | * 100 | * @param options.name - The name of the OIDC security definition. 101 | * @param options.issuer - The OIDC issuer URL. 102 | * @param options.audiences - The OIDC audiences. 103 | * @returns SecurityOption 104 | */ 105 | export const oidcRule = ({ 106 | name, 107 | issuer, 108 | audiences, 109 | }: UnscopedOicdOptions): SecurityOption => { 110 | return (...scopes: string[]): OidcOptions => { 111 | return { 112 | name, 113 | issuer, 114 | audiences, 115 | scopes, 116 | }; 117 | }; 118 | }; 119 | 120 | const baseMaker = make(OidcSecurityDefinition); 121 | 122 | /** 123 | * 124 | * @param apiName - The name of the API to attach the OIDC security definition to. 125 | * @param options - The options for the OIDC security definition. 126 | * 127 | * @returns factory function for creating a new OIDC security definition 128 | */ 129 | export const attachOidc: newer = ( 130 | apiName: string, 131 | options: UnscopedOicdOptions 132 | ) => { 133 | return baseMaker(`${options.name}-${apiName}`, apiName, options); 134 | }; 135 | -------------------------------------------------------------------------------- /src/resources/queue.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { ResourcesClient } from '@nitric/proto/resources/v1/resources_grpc_pb'; 16 | import { UnimplementedError } from '../api/errors'; 17 | import { Queue } from '../api'; 18 | import { queue, QueueResource } from '.'; 19 | import { ResourceDeclareResponse } from '@nitric/proto/resources/v1/resources_pb'; 20 | import { status } from '@grpc/grpc-js'; 21 | 22 | describe('Registering queue resources', () => { 23 | describe('Given declare returns an error from the resource server', () => { 24 | const MOCK_ERROR = { 25 | code: status.UNIMPLEMENTED, 26 | message: 'UNIMPLEMENTED', 27 | }; 28 | 29 | const validName = 'my-queue'; 30 | let declareSpy; 31 | 32 | beforeAll(() => { 33 | jest.spyOn(console, 'error').mockImplementation(() => {}); 34 | declareSpy = jest 35 | .spyOn(ResourcesClient.prototype, 'declare') 36 | .mockImplementationOnce((request, callback: any) => { 37 | callback(MOCK_ERROR, null); 38 | 39 | return null as any; 40 | }); 41 | }); 42 | 43 | afterAll(() => { 44 | jest.restoreAllMocks(); 45 | }); 46 | 47 | it('Should throw the error', async () => { 48 | await expect(queue(validName)['registerPromise']).rejects.toBeInstanceOf( 49 | UnimplementedError 50 | ); 51 | }); 52 | 53 | it('Should call the resource server', () => { 54 | expect(declareSpy).toBeCalledTimes(1); 55 | }); 56 | }); 57 | 58 | describe('Given declare succeeds on the resource server', () => { 59 | describe('When the service succeeds', () => { 60 | const validName = 'my-queue2'; 61 | let otherSpy; 62 | 63 | beforeAll(() => { 64 | otherSpy = jest 65 | .spyOn(ResourcesClient.prototype, 'declare') 66 | .mockImplementationOnce((request, callback: any) => { 67 | const response = new ResourceDeclareResponse(); 68 | callback(null, response); 69 | return null as any; 70 | }); 71 | }); 72 | 73 | afterAll(() => { 74 | jest.resetAllMocks(); 75 | }); 76 | 77 | it('Should succeed', async () => { 78 | await expect( 79 | queue(validName)['registerPromise'] 80 | ).resolves.not.toBeNull(); 81 | }); 82 | 83 | it('Should call the resource server', () => { 84 | expect(otherSpy).toBeCalledTimes(1); 85 | }); 86 | }); 87 | }); 88 | 89 | describe('Given a topic is already registered', () => { 90 | const queueName = 'already-exists'; 91 | let queueResource: QueueResource; 92 | let existsSpy; 93 | 94 | beforeEach(() => { 95 | // ensure a success is returned and calls can be counted. 96 | existsSpy = jest 97 | .spyOn(ResourcesClient.prototype, 'declare') 98 | .mockImplementation((request, callback: any) => { 99 | const response = new ResourceDeclareResponse(); 100 | callback(null, response); 101 | return null as any; 102 | }); 103 | 104 | // register the resource for the first time 105 | queueResource = queue(queueName); 106 | }); 107 | 108 | afterEach(() => { 109 | jest.resetAllMocks(); 110 | }); 111 | 112 | describe('When registering a queue with the same name', () => { 113 | let secondTopic; 114 | 115 | beforeEach(() => { 116 | // make sure the initial registration isn't counted for these tests. 117 | existsSpy.mockClear(); 118 | secondTopic = queue(queueName); 119 | }); 120 | 121 | it('Should not call the server again', () => { 122 | expect(existsSpy).not.toBeCalled(); 123 | }); 124 | 125 | it('Should return the same resource object', () => { 126 | expect(queueResource === secondTopic).toEqual(true); 127 | }); 128 | }); 129 | 130 | describe('When declaring usage', () => { 131 | it('Should return a topic reference', () => { 132 | const ref = queueResource.for('dequeue'); 133 | expect(ref).toBeInstanceOf(Queue); 134 | }); 135 | }); 136 | }); 137 | }); 138 | -------------------------------------------------------------------------------- /src/resources/queue.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { Queue, queues } from '@nitric/sdk/api/queues'; 15 | import { 16 | ResourceIdentifier, 17 | ResourceDeclareRequest, 18 | ResourceDeclareResponse, 19 | ResourceType, 20 | Action, 21 | QueueResource as NitricQueueResource, 22 | ResourceTypeMap, 23 | } from '@nitric/proto/resources/v1/resources_pb'; 24 | import resourceClient from './client'; 25 | import { fromGrpcError } from '../api/errors'; 26 | import { ActionsList, make, SecureResource } from './common'; 27 | 28 | export type QueuePermission = 'enqueue' | 'dequeue'; 29 | 30 | const everything: QueuePermission[] = ['enqueue', 'dequeue']; 31 | 32 | /** 33 | * Queue resource for async messaging 34 | */ 35 | export class QueueResource< 36 | T extends Record = Record 37 | > extends SecureResource { 38 | /** 39 | * Register this queue as a required resource for the calling service/container. 40 | * 41 | * @returns a promise that resolves when the registration is complete 42 | */ 43 | protected async register(): Promise { 44 | const req = new ResourceDeclareRequest(); 45 | const resource = new ResourceIdentifier(); 46 | resource.setName(this.name); 47 | resource.setType(ResourceType.QUEUE); 48 | req.setId(resource); 49 | req.setQueue(new NitricQueueResource()); 50 | 51 | return new Promise((resolve, reject) => { 52 | resourceClient.declare(req, (error) => { 53 | if (error) { 54 | reject(fromGrpcError(error)); 55 | } else { 56 | resolve(resource); 57 | } 58 | }); 59 | }); 60 | } 61 | 62 | protected permsToActions(...perms: QueuePermission[]): ActionsList { 63 | const actions: ActionsList = perms.reduce((actions, p) => { 64 | switch (p) { 65 | case 'enqueue': 66 | return [...actions, Action.QUEUEENQUEUE]; 67 | case 'dequeue': 68 | return [...actions, Action.QUEUEDEQUEUE]; 69 | default: 70 | throw new Error( 71 | `unknown permission ${p}, supported permissions are ${everything.join( 72 | ', ' 73 | )}` 74 | ); 75 | } 76 | }, []); 77 | 78 | return actions; 79 | } 80 | 81 | protected resourceType(): ResourceTypeMap[keyof ResourceTypeMap] { 82 | return ResourceType.QUEUE; 83 | } 84 | 85 | protected unwrapDetails(_: ResourceDeclareResponse): never { 86 | throw new Error('details unimplemented for queue'); 87 | } 88 | 89 | /** 90 | * Return a queue reference and registers the permissions required by the currently scoped function for this resource. 91 | * 92 | * e.g. const taskQueue = resources.queue('work').for('enqueue') 93 | * 94 | * @deprecated use allow instead 95 | * @param perm - the access that the currently scoped function is requesting to this resource. 96 | * @param perms - the access that the currently scoped function is requesting to this resource. 97 | * @returns a useable queue. 98 | */ 99 | public for(perm: QueuePermission, ...perms: QueuePermission[]): Queue { 100 | console.warn("The 'for' method is deprecated, please use 'allow' instead"); 101 | 102 | this.registerPolicy(perm, ...perms); 103 | 104 | return queues().queue(this.name); 105 | } 106 | 107 | public allow(perm: QueuePermission, ...perms: QueuePermission[]): Queue { 108 | this.registerPolicy(perm, ...perms); 109 | 110 | return queues().queue(this.name); 111 | } 112 | } 113 | 114 | // export const queue = make(QueueResource) as < 115 | // T extends Record = Record 116 | // >( 117 | // name: string 118 | // ) => QueueResource; 119 | 120 | /** 121 | * Create a reference to a named queue in this project. 122 | * 123 | * If the queue hasn't been referenced before this is a request for a new resource. Otherwise, the existing queue with the same name will be used. 124 | * 125 | * @param name the name of the queue. 126 | * @returns a reference to the queue. 127 | */ 128 | export function queue = Record>( 129 | name: string 130 | ): QueueResource { 131 | return make>(QueueResource)(name); 132 | } 133 | -------------------------------------------------------------------------------- /src/resources/schedule.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { schedule, Frequency, Rate, Cron, Schedule } from '.'; 15 | 16 | describe('Rate Schedules', () => { 17 | const startSpy = jest 18 | .spyOn(Rate.prototype as any, 'start') 19 | .mockResolvedValue(undefined as never); 20 | const mockFn = jest.fn(); 21 | 22 | afterAll(() => { 23 | jest.clearAllMocks(); 24 | }); 25 | 26 | describe('when creating a new schedule with an invalid rate', () => { 27 | let error = undefined; 28 | afterAll(() => { 29 | jest.resetAllMocks(); 30 | }); 31 | 32 | // beforeAll(async () => { 33 | // try { 34 | // await schedule('main').every('fleventy days', mockFn); 35 | // } catch (err) { 36 | // error = err; 37 | // } 38 | // }); 39 | 40 | it('should return an error', async () => { 41 | await expect(async () => { 42 | await schedule('main').every('fleventy days', mockFn); 43 | }).rejects.toThrowError( 44 | 'invalid rate expression, expression must begin with a number' 45 | ); 46 | // expect(error).not.toBe(undefined); 47 | }); 48 | }); 49 | 50 | describe('when creating a new schedule with an invalid frequency', () => { 51 | let error = undefined; 52 | afterAll(() => { 53 | jest.resetAllMocks(); 54 | }); 55 | 56 | beforeAll(async () => { 57 | try { 58 | await schedule('main').every('70 smidgets', mockFn); 59 | } catch (e) { 60 | error = e; 61 | } 62 | }); 63 | 64 | it('should throw an error', () => { 65 | expect(error).not.toBe(undefined); 66 | }); 67 | }); 68 | 69 | ['day', 'hour', 'minute'].forEach((rate: Frequency) => { 70 | describe(`when creating a new schedule with rate ${rate}`, () => { 71 | afterAll(() => { 72 | jest.resetAllMocks(); 73 | }); 74 | 75 | beforeAll(async () => { 76 | await schedule('main').every(rate, mockFn); 77 | }); 78 | 79 | it('should call Rate start()', () => { 80 | expect(startSpy).toBeCalledTimes(1); 81 | }); 82 | }); 83 | }); 84 | }); 85 | 86 | describe('Cron Schedules', () => { 87 | const cronSpy = jest 88 | .spyOn(Cron.prototype as any, 'start') 89 | .mockResolvedValue(undefined as never); 90 | const mockFn = jest.fn(); 91 | 92 | afterAll(() => { 93 | jest.clearAllMocks(); 94 | }); 95 | 96 | describe('when creating a new schedule with cron expression', () => { 97 | let error = undefined; 98 | afterAll(() => { 99 | jest.resetAllMocks(); 100 | }); 101 | 102 | beforeAll(async () => { 103 | try { 104 | await schedule('main').cron('0 10 * * *', mockFn); 105 | } catch (err) { 106 | error = err; 107 | } 108 | }); 109 | 110 | it('should call Cron start()', () => { 111 | expect(cronSpy).toBeCalledTimes(1); 112 | }); 113 | 114 | it('should not return an error', () => { 115 | expect(error).toBe(undefined); 116 | }); 117 | }); 118 | }); 119 | -------------------------------------------------------------------------------- /src/resources/secret.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { ResourcesClient } from '@nitric/proto/resources/v1/resources_grpc_pb'; 16 | import { UnimplementedError } from '../api/errors'; 17 | import { secret } from '.'; 18 | import { ResourceDeclareResponse } from '@nitric/proto/resources/v1/resources_pb'; 19 | import { Secret } from '..'; 20 | import { status } from '@grpc/grpc-js'; 21 | 22 | describe('Registering secret resources', () => { 23 | describe('Given the server is unimplemented', () => { 24 | describe('When a secret is registered', () => { 25 | const MOCK_ERROR = { 26 | code: status.UNIMPLEMENTED, 27 | message: 'UNIMPLEMENTED', 28 | }; 29 | 30 | const validName = 'my-secret'; 31 | let declareSpy; 32 | 33 | beforeAll(() => { 34 | jest.spyOn(console, 'error').mockImplementation(() => {}); 35 | declareSpy = jest 36 | .spyOn(ResourcesClient.prototype, 'declare') 37 | .mockImplementationOnce((request, callback: any) => { 38 | callback(MOCK_ERROR, null); 39 | 40 | return null as any; 41 | }); 42 | }); 43 | 44 | afterAll(() => { 45 | jest.restoreAllMocks(); 46 | }); 47 | 48 | it('Should throw the error', async () => { 49 | await expect( 50 | secret(validName)['registerPromise'] 51 | ).rejects.toBeInstanceOf(UnimplementedError); 52 | }); 53 | 54 | it('Should call the resource server', () => { 55 | expect(declareSpy).toBeCalledTimes(1); 56 | }); 57 | }); 58 | }); 59 | 60 | describe('Given the server is available', () => { 61 | describe('When registeringa new secret', () => { 62 | const validName = 'my-secret2'; 63 | let otherSpy; 64 | 65 | beforeAll(() => { 66 | otherSpy = jest 67 | .spyOn(ResourcesClient.prototype, 'declare') 68 | .mockImplementationOnce((request, callback: any) => { 69 | const response = new ResourceDeclareResponse(); 70 | callback(null, response); 71 | return null as any; 72 | }); 73 | }); 74 | 75 | afterAll(() => { 76 | jest.resetAllMocks(); 77 | }); 78 | 79 | it('Should succeed', async () => { 80 | await expect( 81 | secret(validName)['registerPromise'] 82 | ).resolves.not.toBeNull(); 83 | }); 84 | 85 | it('Should call the resource server', () => { 86 | expect(otherSpy).toBeCalledTimes(1); 87 | }); 88 | }); 89 | }); 90 | 91 | describe('Given a secret is already registered', () => { 92 | const secretName = 'already-exists'; 93 | let secretResource; 94 | let existsSpy; 95 | 96 | beforeEach(() => { 97 | // ensure a success is returned and calls can be counted 98 | existsSpy = jest 99 | .spyOn(ResourcesClient.prototype, 'declare') 100 | .mockImplementation((request, callback: any) => { 101 | const response = new ResourceDeclareResponse(); 102 | callback(null, response); 103 | return null as any; 104 | }); 105 | 106 | secretResource = secret(secretName); 107 | }); 108 | 109 | afterAll(() => { 110 | jest.resetAllMocks(); 111 | }); 112 | 113 | describe('When registering a secret with the same name', () => { 114 | let secondSecret; 115 | 116 | beforeEach(() => { 117 | existsSpy.mockClear(); 118 | secondSecret = secret(secretName); 119 | }); 120 | 121 | it('Should not call the server again', () => { 122 | expect(existsSpy).not.toBeCalled(); 123 | }); 124 | 125 | it('Should return the same resource object', () => { 126 | expect(secretResource === secondSecret).toEqual(true); 127 | }); 128 | }); 129 | 130 | describe('When declaring usage', () => { 131 | it('Should return a secret reference', () => { 132 | const ref = secretResource.for('accessing'); 133 | expect(ref).toBeInstanceOf(Secret); 134 | }); 135 | }); 136 | }); 137 | }); 138 | -------------------------------------------------------------------------------- /src/resources/secret.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { 15 | Action, 16 | ResourceIdentifier, 17 | ResourceType, 18 | ResourceDeclareRequest, 19 | ResourceDeclareResponse, 20 | ResourceTypeMap, 21 | SecretResource as NitricSecretResource, 22 | } from '@nitric/proto/resources/v1/resources_pb'; 23 | import resourceClient from './client'; 24 | import { secrets, Secret } from '../api/secrets'; 25 | import { ActionsList, make, SecureResource } from './common'; 26 | import { fromGrpcError } from '../api/errors'; 27 | 28 | type SecretPermission = 'put' | 'access'; 29 | 30 | type SecretPermissionLegacy = 'putting' | 'accessing'; 31 | 32 | const everything: SecretPermission[] = ['put', 'access']; 33 | 34 | /** 35 | * Cloud secret resource for secret storage 36 | */ 37 | export class SecretResource extends SecureResource { 38 | protected async register(): Promise { 39 | const req = new ResourceDeclareRequest(); 40 | const resource = new ResourceIdentifier(); 41 | resource.setName(this.name); 42 | resource.setType(ResourceType.SECRET); 43 | 44 | req.setSecret(new NitricSecretResource()); 45 | req.setId(resource); 46 | 47 | return new Promise((resolve, reject) => { 48 | resourceClient.declare( 49 | req, 50 | (error, _response: ResourceDeclareResponse) => { 51 | if (error) { 52 | reject(fromGrpcError(error)); 53 | } else { 54 | resolve(resource); 55 | } 56 | } 57 | ); 58 | }); 59 | } 60 | 61 | protected permsToActions(...perms: SecretPermission[]): ActionsList { 62 | return perms.reduce((actions, perm) => { 63 | switch (perm) { 64 | case 'put': 65 | return [...actions, Action.SECRETPUT]; 66 | case 'access': 67 | return [...actions, Action.SECRETACCESS]; 68 | default: 69 | throw new Error( 70 | `unknown secret permission ${perm}, supported permissions are ${everything.join( 71 | ', ' 72 | )}` 73 | ); 74 | } 75 | }, []); 76 | } 77 | 78 | protected resourceType(): ResourceTypeMap[keyof ResourceTypeMap] { 79 | return ResourceType.SECRET; 80 | } 81 | 82 | public for( 83 | perm: SecretPermissionLegacy, 84 | ...perms: SecretPermissionLegacy[] 85 | ): Secret { 86 | console.warn("The 'for' method is deprecated, please use 'allow' instead"); 87 | 88 | const allPerms = [perm, ...perms].map((p) => { 89 | switch (p) { 90 | case 'putting': 91 | return 'put'; 92 | case 'accessing': 93 | return 'access'; 94 | default: 95 | throw new Error( 96 | `unknown secret permission ${p}, supported permissions are ${everything.join( 97 | ', ' 98 | )}` 99 | ); 100 | } 101 | }); 102 | 103 | this.registerPolicy(...allPerms); 104 | 105 | return secrets().secret(this.name); 106 | } 107 | 108 | public allow(perm: SecretPermission, ...perms: SecretPermission[]): Secret { 109 | this.registerPolicy(perm, ...perms); 110 | 111 | return secrets().secret(this.name); 112 | } 113 | } 114 | 115 | /** 116 | * Create a reference to a named secret in this project. 117 | * 118 | * If the secret hasn't been referenced before this is a request for a new resource. Otherwise, the existing secret with the same name will be used. 119 | * 120 | * @param name the name of the secret. 121 | * @returns a reference to the secret. 122 | */ 123 | export const secret: (name: string) => SecretResource = make(SecretResource); 124 | -------------------------------------------------------------------------------- /src/resources/sql.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import { 15 | ResourceIdentifier, 16 | ResourceDeclareRequest, 17 | ResourceType, 18 | ResourceTypeMap, 19 | SqlDatabaseResource, 20 | SqlDatabaseMigrations, 21 | } from '@nitric/proto/resources/v1/resources_pb'; 22 | import { SqlConnectionStringRequest } from '@nitric/proto/sql/v1/sql_pb'; 23 | import resourceClient from './client'; 24 | import { make, Resource as Base } from './common'; 25 | import { SqlClient } from '../gen/nitric/proto/sql/v1/sql_grpc_pb'; 26 | import { SERVICE_BIND } from '../constants'; 27 | import * as grpc from '@grpc/grpc-js'; 28 | import { fromGrpcError } from '../api/errors'; 29 | 30 | interface SQLDatabaseOptions { 31 | /** 32 | * Location of migrations for the SQL Database 33 | * This can be specified as either a local file path or a docker file relative to the nitric project root. 34 | * e.g. "file://migrations/main-database" or "dockerfile://path/to/migration.dockerfile" 35 | */ 36 | migrations: string; 37 | } 38 | /** 39 | * Register a SQL resource to the provided application. 40 | */ 41 | export class SQLDatabaseResource extends Base { 42 | private readonly sqlClient: SqlClient; 43 | private readonly options?: SQLDatabaseOptions; 44 | 45 | constructor(name: string, options?: SQLDatabaseOptions) { 46 | super(name); 47 | this.options = options; 48 | this.sqlClient = new SqlClient( 49 | SERVICE_BIND, 50 | grpc.ChannelCredentials.createInsecure() 51 | ); 52 | } 53 | 54 | /** 55 | * Register this SQL as a required resource for the calling function/container. 56 | * 57 | * @returns a promise that resolves when the registration is complete 58 | */ 59 | protected async register(): Promise { 60 | const req = new ResourceDeclareRequest(); 61 | const resource = new ResourceIdentifier(); 62 | resource.setName(this.name); 63 | resource.setType(ResourceType.SQLDATABASE); 64 | req.setId(resource); 65 | 66 | const sqlConfig = new SqlDatabaseResource(); 67 | 68 | if (this.options) { 69 | const sqlMigrations = new SqlDatabaseMigrations(); 70 | sqlMigrations.setMigrationsPath(this.options.migrations); 71 | 72 | sqlConfig.setMigrations(sqlMigrations); 73 | } 74 | 75 | req.setSqlDatabase(sqlConfig); 76 | 77 | const res = await new Promise((resolve, reject) => { 78 | resourceClient.declare(req, (error, _: ResourceDeclareRequest) => { 79 | if (error) { 80 | reject(fromGrpcError(error)); 81 | } else { 82 | resolve(resource); 83 | } 84 | }); 85 | }); 86 | 87 | return res; 88 | } 89 | 90 | /** 91 | * Retrieves the connection string of this SQL Database at runtime. 92 | * 93 | * @returns Promise that returns the connection string of this SQL Database 94 | */ 95 | async connectionString(): Promise { 96 | const request = new SqlConnectionStringRequest(); 97 | request.setDatabaseName(this.name); 98 | 99 | const connectionString = await new Promise((resolve, reject) => { 100 | this.sqlClient.connectionString(request, (error, data) => { 101 | if (error) { 102 | reject(fromGrpcError(error)); 103 | } else { 104 | resolve(data.getConnectionString()); 105 | } 106 | }); 107 | }); 108 | 109 | return connectionString; 110 | } 111 | 112 | protected resourceType(): ResourceTypeMap[keyof ResourceTypeMap] { 113 | return ResourceType.SQLDATABASE; 114 | } 115 | } 116 | 117 | const maker = make(SQLDatabaseResource); 118 | 119 | /** 120 | * Register a SQL Database Resource. If the SQL Database has already been registered, the existing SQL will be returned. 121 | * 122 | * The returned SQL Database object can be used to register handlers for SQL events. 123 | * e.g. const connectionString = db.connectionString() 124 | * 125 | * @param name the name of the SQL Database 126 | * @param options the options for the SQL Database 127 | * @returns a SQL resource 128 | */ 129 | export const sql = ( 130 | name: string, 131 | options?: SQLDatabaseOptions 132 | ): SQLDatabaseResource => maker(name, options); 133 | -------------------------------------------------------------------------------- /src/resources/websocket.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { ResourcesClient } from '@nitric/proto/resources/v1/resources_grpc_pb'; 16 | import { UnimplementedError } from '../api/errors'; 17 | import { websocket } from '.'; 18 | import { ResourceDeclareResponse } from '@nitric/proto/resources/v1/resources_pb'; 19 | import { Metadata, status } from '@grpc/grpc-js'; 20 | 21 | describe('Registering websocket resources', () => { 22 | describe('Given declare returns an error from the resource server', () => { 23 | const MOCK_ERROR = { 24 | code: status.UNIMPLEMENTED, 25 | message: 'UNIMPLEMENTED', 26 | }; 27 | 28 | const validName = 'my-websocket'; 29 | let declareSpy; 30 | 31 | beforeAll(() => { 32 | jest.spyOn(console, 'error').mockImplementation(() => {}); 33 | declareSpy = jest 34 | .spyOn(ResourcesClient.prototype, 'declare') 35 | .mockImplementationOnce((request, callback: any) => { 36 | callback(MOCK_ERROR, null); 37 | 38 | return null as any; 39 | }); 40 | }); 41 | 42 | afterAll(() => { 43 | jest.restoreAllMocks(); 44 | }); 45 | 46 | it('Should throw the error', async () => { 47 | await expect( 48 | websocket(validName)['registerPromise'] 49 | ).rejects.toBeInstanceOf(UnimplementedError); 50 | }); 51 | 52 | it('Should call the resource server', () => { 53 | expect(declareSpy).toBeCalledTimes(1); 54 | }); 55 | }); 56 | 57 | describe('Given declare succeeds on the resource server', () => { 58 | describe('When the service succeeds', () => { 59 | const validName = 'my-websocket2'; 60 | let otherSpy; 61 | 62 | beforeAll(() => { 63 | otherSpy = jest 64 | .spyOn(ResourcesClient.prototype, 'declare') 65 | .mockImplementation((request, callback: any) => { 66 | const response = new ResourceDeclareResponse(); 67 | callback(null, response); 68 | return null as any; 69 | }); 70 | }); 71 | 72 | afterAll(() => { 73 | jest.resetAllMocks(); 74 | }); 75 | 76 | it('Should succeed', async () => { 77 | await expect( 78 | websocket(validName)['registerPromise'] 79 | ).resolves.not.toBeNull(); 80 | }); 81 | 82 | it('Should call the resource server twice', () => { 83 | expect(otherSpy).toBeCalledTimes(2); 84 | }); 85 | }); 86 | }); 87 | 88 | describe('Given a topic is already registered', () => { 89 | const websocketName = 'already-exists'; 90 | let websocketResource; 91 | let existsSpy; 92 | 93 | beforeEach(() => { 94 | // ensure a success is returned and calls can be counted. 95 | existsSpy = jest 96 | .spyOn(ResourcesClient.prototype, 'declare') 97 | .mockImplementation((request, callback: any) => { 98 | const response = new ResourceDeclareResponse(); 99 | callback(null, response); 100 | return null as any; 101 | }); 102 | 103 | // register the resource for the first time 104 | websocketResource = websocket(websocketName); 105 | }); 106 | 107 | afterEach(() => { 108 | jest.resetAllMocks(); 109 | }); 110 | 111 | describe('When registering a topic with the same name', () => { 112 | let secondWebsocket; 113 | 114 | beforeEach(() => { 115 | // make sure the initial registration isn't counted for these tests. 116 | existsSpy.mockClear(); 117 | secondWebsocket = websocket(websocketName); 118 | }); 119 | 120 | it('Should not call the server again', () => { 121 | expect(existsSpy).not.toBeCalled(); 122 | }); 123 | 124 | it('Should return the same resource object', () => { 125 | expect(websocketResource === secondWebsocket).toEqual(true); 126 | }); 127 | }); 128 | }); 129 | }); 130 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021, Nitric Technologies Pty Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export type WhereQueryOperator = 15 | | '<' 16 | | '<=' 17 | | '==' 18 | | '!=' 19 | | '>=' 20 | | '>' 21 | | 'startsWith'; 22 | 23 | export type WhereValueExpression = string | number | boolean; 24 | 25 | export type HttpMethod = 26 | | 'GET' 27 | | 'POST' 28 | | 'PATCH' 29 | | 'PUT' 30 | | 'DELETE' 31 | | 'OPTIONS'; 32 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "declaration": true, 5 | "module": "commonjs", 6 | "target": "es6", 7 | "outDir": "lib", 8 | "allowJs": true, 9 | "types": ["node", "jest"], 10 | "resolveJsonModule": true, 11 | "importHelpers": true, 12 | "baseUrl": ".", 13 | "paths": { 14 | "@nitric/sdk": ["src"], 15 | "@nitric/sdk/*": ["src/*"], 16 | "@nitric/proto/*": ["src/gen/nitric/proto/*"] 17 | } 18 | }, 19 | "include": ["src/**/*", "examples/**/*"] 20 | } 21 | --------------------------------------------------------------------------------