mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
refactor with extensive, experimental use of valibot for typecheck, vailidation and conversation
This commit is contained in:
parent
df28a5b4d1
commit
78351257ee
2
.gitignore
vendored
2
.gitignore
vendored
@ -12,7 +12,7 @@ messages.pot
|
||||
nbproject
|
||||
.metadata
|
||||
/out/*
|
||||
/.env
|
||||
.env
|
||||
package-lock.json
|
||||
/deployment/bare_metal/.env
|
||||
/deployment/bare_metal/nginx/sites-available/gradido.conf
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { DltTransaction } from '@entity/DltTransaction'
|
||||
import { TransactionLink } from '@entity/TransactionLink'
|
||||
import { DltTransaction, TransactionLink } from 'database'
|
||||
|
||||
import { DltTransactionType } from '@dltConnector/enum/DltTransactionType'
|
||||
import { TransactionType } from '@dltConnector/enum/TransactionType'
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
CONFIG_VERSION=$DLT_CONNECTOR_CONFIG_VERSION
|
||||
|
||||
JWT_SECRET=$JWT_SECRET
|
||||
|
||||
#IOTA
|
||||
IOTA_API_URL=$IOTA_API_URL
|
||||
IOTA_COMMUNITY_ALIAS=$IOTA_COMMUNITY_ALIAS
|
||||
IOTA_HOME_COMMUNITY_SEED=$IOTA_HOME_COMMUNITY_SEED
|
||||
|
||||
# DLT-Connector
|
||||
DLT_CONNECTOR_PORT=$DLT_CONNECTOR_PORT
|
||||
|
||||
# Gradido Node Server URL
|
||||
NODE_SERVER_URL=$NODE_SERVER_URL
|
||||
|
||||
# Gradido Blockchain
|
||||
GRADIDO_BLOCKCHAIN_CRYPTO_APP_SECRET=$GRADIDO_BLOCKCHAIN_CRYPTO_APP_SECRET
|
||||
GRADIDO_BLOCKCHAIN_SERVER_CRYPTO_KEY=$GRADIDO_BLOCKCHAIN_SERVER_CRYPTO_KEY
|
||||
|
||||
# Route to Backend
|
||||
BACKEND_SERVER_URL=http://localhost:4000
|
||||
@ -1,4 +0,0 @@
|
||||
node_modules
|
||||
**/*.min.js
|
||||
build
|
||||
coverage
|
||||
@ -1,207 +0,0 @@
|
||||
// eslint-disable-next-line import/no-commonjs, import/unambiguous
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['prettier', '@typescript-eslint', 'import', 'n', 'promise'],
|
||||
extends: [
|
||||
'standard',
|
||||
'eslint:recommended',
|
||||
'plugin:prettier/recommended',
|
||||
// 'plugin:import/recommended',
|
||||
// 'plugin:import/typescript',
|
||||
// 'plugin:security/recommended',
|
||||
'plugin:@eslint-community/eslint-comments/recommended',
|
||||
'plugin:dci-lint/recommended',
|
||||
],
|
||||
settings: {
|
||||
'import/parsers': {
|
||||
'@typescript-eslint/parser': ['.ts', '.tsx'],
|
||||
},
|
||||
'import/resolver': {
|
||||
typescript: {
|
||||
project: ['./tsconfig.json'],
|
||||
},
|
||||
node: true,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-console': 'error',
|
||||
camelcase: 'error',
|
||||
'no-debugger': 'error',
|
||||
'prettier/prettier': [
|
||||
'error',
|
||||
{
|
||||
htmlWhitespaceSensitivity: 'ignore',
|
||||
},
|
||||
],
|
||||
// 'dci-lint/literal-role-contracts': 'off'
|
||||
// import
|
||||
// 'import/export': 'error',
|
||||
// 'import/no-deprecated': 'error',
|
||||
// 'import/no-empty-named-blocks': 'error',
|
||||
// 'import/no-extraneous-dependencies': 'error',
|
||||
// 'import/no-mutable-exports': 'error',
|
||||
// 'import/no-unused-modules': 'error',
|
||||
// 'import/no-named-as-default': 'error',
|
||||
// 'import/no-named-as-default-member': 'error',
|
||||
// 'import/no-amd': 'error',
|
||||
// 'import/no-commonjs': 'error',
|
||||
// 'import/no-import-module-exports': 'error',
|
||||
// 'import/no-nodejs-modules': 'off',
|
||||
// 'import/unambiguous': 'error',
|
||||
// 'import/default': 'error',
|
||||
// 'import/named': 'error',
|
||||
// 'import/namespace': 'error',
|
||||
// 'import/no-absolute-path': 'error',
|
||||
// 'import/no-cycle': 'error',
|
||||
// 'import/no-dynamic-require': 'error',
|
||||
// 'import/no-internal-modules': 'off',
|
||||
// 'import/no-relative-packages': 'error',
|
||||
// 'import/no-relative-parent-imports': ['error', { ignore: ['@/*'] }],
|
||||
// 'import/no-self-import': 'error',
|
||||
// 'import/no-unresolved': 'error',
|
||||
// 'import/no-useless-path-segments': 'error',
|
||||
// 'import/no-webpack-loader-syntax': 'error',
|
||||
// 'import/consistent-type-specifier-style': 'error',
|
||||
// 'import/exports-last': 'off',
|
||||
// 'import/extensions': 'error',
|
||||
// 'import/first': 'error',
|
||||
// 'import/group-exports': 'off',
|
||||
// 'import/newline-after-import': 'error',
|
||||
// 'import/no-anonymous-default-export': 'error',
|
||||
// 'import/no-default-export': 'error',
|
||||
// 'import/no-duplicates': 'error',
|
||||
// 'import/no-named-default': 'error',
|
||||
// 'import/no-namespace': 'error',
|
||||
// 'import/no-unassigned-import': 'error',
|
||||
'import/order': [
|
||||
'error',
|
||||
{
|
||||
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
|
||||
'newlines-between': 'always',
|
||||
pathGroups: [
|
||||
{
|
||||
pattern: '@?*/**',
|
||||
group: 'external',
|
||||
position: 'after',
|
||||
},
|
||||
{
|
||||
pattern: '@/**',
|
||||
group: 'external',
|
||||
position: 'after',
|
||||
},
|
||||
],
|
||||
alphabetize: {
|
||||
order: 'asc' /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */,
|
||||
caseInsensitive: true /* ignore case. Options: [true, false] */,
|
||||
},
|
||||
distinctGroup: true,
|
||||
},
|
||||
],
|
||||
// 'import/prefer-default-export': 'off',
|
||||
// n
|
||||
'n/handle-callback-err': 'error',
|
||||
'n/no-callback-literal': 'error',
|
||||
'n/no-exports-assign': 'error',
|
||||
'n/no-extraneous-import': 'error',
|
||||
'n/no-extraneous-require': 'error',
|
||||
'n/no-hide-core-modules': 'error',
|
||||
'n/no-missing-import': 'off', // not compatible with typescript
|
||||
'n/no-missing-require': 'error',
|
||||
'n/no-new-require': 'error',
|
||||
'n/no-path-concat': 'error',
|
||||
'n/no-process-exit': 'error',
|
||||
'n/no-unpublished-bin': 'error',
|
||||
'n/no-unpublished-import': 'off', // TODO need to exclude seeds
|
||||
'n/no-unpublished-require': 'error',
|
||||
'n/no-unsupported-features': ['error', { ignores: ['modules'] }],
|
||||
'n/no-unsupported-features/es-builtins': 'error',
|
||||
'n/no-unsupported-features/es-syntax': 'error',
|
||||
'n/no-unsupported-features/node-builtins': 'error',
|
||||
'n/process-exit-as-throw': 'error',
|
||||
'n/shebang': 'error',
|
||||
'n/callback-return': 'error',
|
||||
'n/exports-style': 'error',
|
||||
'n/file-extension-in-import': 'off',
|
||||
'n/global-require': 'error',
|
||||
'n/no-mixed-requires': 'error',
|
||||
'n/no-process-env': 'error',
|
||||
'n/no-restricted-import': 'error',
|
||||
'n/no-restricted-require': 'error',
|
||||
'n/no-sync': 'error',
|
||||
'n/prefer-global/buffer': 'error',
|
||||
'n/prefer-global/console': 'error',
|
||||
'n/prefer-global/process': 'error',
|
||||
'n/prefer-global/text-decoder': 'error',
|
||||
'n/prefer-global/text-encoder': 'error',
|
||||
'n/prefer-global/url': 'error',
|
||||
'n/prefer-global/url-search-params': 'error',
|
||||
'n/prefer-promises/dns': 'error',
|
||||
'n/prefer-promises/fs': 'error',
|
||||
// promise
|
||||
// 'promise/catch-or-return': 'error',
|
||||
// 'promise/no-return-wrap': 'error',
|
||||
// 'promise/param-names': 'error',
|
||||
// 'promise/always-return': 'error',
|
||||
// 'promise/no-native': 'off',
|
||||
// 'promise/no-nesting': 'warn',
|
||||
// 'promise/no-promise-in-callback': 'warn',
|
||||
// 'promise/no-callback-in-promise': 'warn',
|
||||
// 'promise/avoid-new': 'warn',
|
||||
// 'promise/no-new-statics': 'error',
|
||||
// 'promise/no-return-in-finally': 'warn',
|
||||
// 'promise/valid-params': 'warn',
|
||||
// 'promise/prefer-await-to-callbacks': 'error',
|
||||
// 'promise/no-multiple-resolved': 'error',
|
||||
// eslint comments
|
||||
'@eslint-community/eslint-comments/disable-enable-pair': ['error', { allowWholeFile: true }],
|
||||
'@eslint-community/eslint-comments/no-restricted-disable': 'error',
|
||||
'@eslint-community/eslint-comments/no-use': 'off',
|
||||
'@eslint-community/eslint-comments/require-description': 'off',
|
||||
},
|
||||
overrides: [
|
||||
// only for ts files
|
||||
{
|
||||
files: ['*.ts', '*.tsx'],
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
// 'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
||||
// 'plugin:@typescript-eslint/strict',
|
||||
],
|
||||
rules: {
|
||||
// allow explicitly defined dangling promises
|
||||
// '@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }],
|
||||
'no-void': ['error', { allowAsStatement: true }],
|
||||
// ignore prefer-regexp-exec rule to allow string.match(regex)
|
||||
'@typescript-eslint/prefer-regexp-exec': 'off',
|
||||
// this should not run on ts files: https://github.com/import-js/eslint-plugin-import/issues/2215#issuecomment-911245486
|
||||
'import/unambiguous': 'off',
|
||||
// this is not compatible with typeorm, due to joined tables can be null, but are not defined as nullable
|
||||
'@typescript-eslint/no-unnecessary-condition': 'off',
|
||||
},
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: ['./tsconfig.json'],
|
||||
// this is to properly reference the referenced project database without requirement of compiling it
|
||||
// eslint-disable-next-line camelcase
|
||||
EXPERIMENTAL_useSourceOfProjectReferenceRedirect: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.test.ts'],
|
||||
plugins: ['jest'],
|
||||
rules: {
|
||||
'jest/no-disabled-tests': 'error',
|
||||
'jest/no-focused-tests': 'error',
|
||||
'jest/no-identical-title': 'error',
|
||||
'jest/prefer-to-have-length': 'error',
|
||||
'jest/valid-expect': 'error',
|
||||
'@typescript-eslint/unbound-method': 'off',
|
||||
'jest/unbound-method': 'error',
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
8
dlt-connector/.gitignore
vendored
8
dlt-connector/.gitignore
vendored
@ -1,8 +0,0 @@
|
||||
/node_modules/
|
||||
/.env
|
||||
/.env.bak
|
||||
/build/
|
||||
package-json.lock
|
||||
coverage
|
||||
# emacs
|
||||
*~
|
||||
@ -1 +0,0 @@
|
||||
v19.5.0
|
||||
@ -1,9 +0,0 @@
|
||||
module.exports = {
|
||||
semi: false,
|
||||
printWidth: 100,
|
||||
singleQuote: true,
|
||||
trailingComma: "all",
|
||||
tabWidth: 2,
|
||||
bracketSpacing: true,
|
||||
endOfLine: "auto",
|
||||
};
|
||||
@ -1 +0,0 @@
|
||||
declare module 'bip32-ed25519'
|
||||
@ -1,119 +0,0 @@
|
||||
##################################################################################
|
||||
# BASE ###########################################################################
|
||||
##################################################################################
|
||||
FROM node:19.5.0-alpine3.17 as base
|
||||
#FROM ubuntu:latest as base
|
||||
|
||||
# ENVs (available in production aswell, can be overwritten by commandline or env file)
|
||||
## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame
|
||||
ENV DOCKER_WORKDIR="/app"
|
||||
## We Cannot do `$(date -u +'%Y-%m-%dT%H:%M:%SZ')` here so we use unix timestamp=0
|
||||
ENV BUILD_DATE="1970-01-01T00:00:00.00Z"
|
||||
## We cannot do $(npm run version).${BUILD_NUMBER} here so we default to 0.0.0.0
|
||||
ENV BUILD_VERSION="0.0.0.0"
|
||||
## We cannot do `$(git rev-parse --short HEAD)` here so we default to 0000000
|
||||
ENV BUILD_COMMIT="0000000"
|
||||
## SET NODE_ENV
|
||||
ENV NODE_ENV="production"
|
||||
## App relevant Envs
|
||||
ENV PORT="6010"
|
||||
|
||||
# Labels
|
||||
LABEL org.label-schema.build-date="${BUILD_DATE}"
|
||||
LABEL org.label-schema.name="gradido:dlt-connector"
|
||||
LABEL org.label-schema.description="Gradido dlt-connector"
|
||||
LABEL org.label-schema.usage="https://github.com/gradido/gradido/blob/master/README.md"
|
||||
LABEL org.label-schema.url="https://gradido.net"
|
||||
LABEL org.label-schema.vcs-url="https://github.com/gradido/gradido/tree/master/dlt-connector"
|
||||
LABEL org.label-schema.vcs-ref="${BUILD_COMMIT}"
|
||||
LABEL org.label-schema.vendor="Gradido Community"
|
||||
LABEL org.label-schema.version="${BUILD_VERSION}"
|
||||
LABEL org.label-schema.schema-version="1.0"
|
||||
LABEL maintainer="support@gradido.net"
|
||||
|
||||
# Install Additional Software
|
||||
## install: @iota/client requirements
|
||||
# Install Build Tool for Rust for @iota/client
|
||||
RUN apk add --no-cache rust cargo python3 make g++
|
||||
|
||||
# Settings
|
||||
## Expose Container Port
|
||||
EXPOSE ${PORT}
|
||||
|
||||
## Workdir
|
||||
RUN mkdir -p ${DOCKER_WORKDIR}
|
||||
WORKDIR ${DOCKER_WORKDIR}
|
||||
|
||||
RUN mkdir -p /dlt-database
|
||||
|
||||
##################################################################################
|
||||
# DEVELOPMENT (Connected to the local environment, to reload on demand) ##########
|
||||
##################################################################################
|
||||
FROM base as development
|
||||
|
||||
# We don't need to copy or build anything since we gonna bind to the
|
||||
# local filesystem which will need a rebuild anyway
|
||||
|
||||
# Run command
|
||||
# (for development we need to execute yarn install since the
|
||||
# node_modules are on another volume and need updating)
|
||||
CMD /bin/sh -c "cd /dlt-database && yarn install && yarn build && cd /app && yarn install && yarn run dev"
|
||||
|
||||
##################################################################################
|
||||
# BUILD (Does contain all files and is therefore bloated) ########################
|
||||
##################################################################################
|
||||
FROM base as build
|
||||
|
||||
# Copy everything from dlt-connector
|
||||
COPY ./dlt-connector/ ./
|
||||
# Copy everything from dlt-database
|
||||
COPY ./dlt-database/ ../dlt-database/
|
||||
|
||||
# yarn install dlt-connector
|
||||
RUN yarn install --production=false --frozen-lockfile --non-interactive
|
||||
|
||||
# yarn install dlt-database
|
||||
RUN cd ../dlt-database && yarn install --production=false --frozen-lockfile --non-interactive
|
||||
|
||||
# yarn build
|
||||
RUN yarn run build
|
||||
|
||||
# yarn build dlt-database
|
||||
RUN cd ../dlt-database && yarn run build
|
||||
|
||||
##################################################################################
|
||||
# TEST ###########################################################################
|
||||
##################################################################################
|
||||
FROM build as test
|
||||
|
||||
# Run command
|
||||
CMD /bin/sh -c "yarn run start"
|
||||
|
||||
##################################################################################
|
||||
# PRODUCTION (Does contain only "binary"- and static-files to reduce image size) #
|
||||
##################################################################################
|
||||
FROM base as production
|
||||
|
||||
# remove iota build tools to have production docker image smaller
|
||||
RUN apk del rust cargo python3 make g++
|
||||
|
||||
# Copy "binary"-files from build image
|
||||
COPY --from=build ${DOCKER_WORKDIR}/build ./build
|
||||
COPY --from=build ${DOCKER_WORKDIR}/../dlt-database/build ../dlt-database/build
|
||||
# We also copy the node_modules express and serve-static for the run script
|
||||
COPY --from=build ${DOCKER_WORKDIR}/node_modules ./node_modules
|
||||
COPY --from=build ${DOCKER_WORKDIR}/../dlt-database/node_modules ../dlt-database/node_modules
|
||||
# Copy static files
|
||||
# COPY --from=build ${DOCKER_WORKDIR}/public ./public
|
||||
# Copy package.json for script definitions (lock file should not be needed)
|
||||
COPY --from=build ${DOCKER_WORKDIR}/package.json ./package.json
|
||||
# Copy tsconfig.json to provide alias path definitions
|
||||
COPY --from=build ${DOCKER_WORKDIR}/tsconfig.json ./tsconfig.json
|
||||
# Copy log4js-config.json to provide log configuration
|
||||
COPY --from=build ${DOCKER_WORKDIR}/log4js-config.json ./log4js-config.json
|
||||
|
||||
# Copy run scripts run/
|
||||
# COPY --from=build ${DOCKER_WORKDIR}/run ./run
|
||||
|
||||
# Run command
|
||||
CMD /bin/sh -c "yarn run start"
|
||||
1
dlt-connector/README.md
Normal file
1
dlt-connector/README.md
Normal file
@ -0,0 +1 @@
|
||||
# Elysia with Bun runtime
|
||||
577
dlt-connector/bun.lock
Normal file
577
dlt-connector/bun.lock
Normal file
@ -0,0 +1,577 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "dlt-connector",
|
||||
"dependencies": {
|
||||
"@iota/client": "^2.2.4",
|
||||
"gradido-blockchain-js": "git+https://github.com/gradido/gradido-blockchain-js#217d03b",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.0.0",
|
||||
"@elysiajs/trpc": "^1.1.0",
|
||||
"@elysiajs/websocket": "^0.2.8",
|
||||
"@trpc/server": "^11.4.3",
|
||||
"@types/bun": "^1.2.17",
|
||||
"dotenv": "^10.0.0",
|
||||
"elysia": "^1.3.5",
|
||||
"graphql-request": "^7.2.0",
|
||||
"jose": "^5.2.2",
|
||||
"jsonrpc-ts-client": "^0.2.3",
|
||||
"log4js": "^6.9.1",
|
||||
"typescript": "^5.8.3",
|
||||
"uuid": "^8.3.2",
|
||||
"valibot": "^1.1.0",
|
||||
"zod": "^3.25.61",
|
||||
},
|
||||
},
|
||||
},
|
||||
"trustedDependencies": [
|
||||
"@iota/client",
|
||||
],
|
||||
"packages": {
|
||||
"@biomejs/biome": ["@biomejs/biome@2.0.0", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.0.0", "@biomejs/cli-darwin-x64": "2.0.0", "@biomejs/cli-linux-arm64": "2.0.0", "@biomejs/cli-linux-arm64-musl": "2.0.0", "@biomejs/cli-linux-x64": "2.0.0", "@biomejs/cli-linux-x64-musl": "2.0.0", "@biomejs/cli-win32-arm64": "2.0.0", "@biomejs/cli-win32-x64": "2.0.0" }, "bin": { "biome": "bin/biome" } }, "sha512-BlUoXEOI/UQTDEj/pVfnkMo8SrZw3oOWBDrXYFT43V7HTkIUDkBRY53IC5Jx1QkZbaB+0ai1wJIfYwp9+qaJTQ=="],
|
||||
|
||||
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.0.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QvqWYtFFhhxdf8jMAdJzXW+Frc7X8XsnHQLY+TBM1fnT1TfeV/v9vsFI5L2J7GH6qN1+QEEJ19jHibCY2Ypplw=="],
|
||||
|
||||
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.0.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-5JFhls1EfmuIH4QGFPlNpxJQFC6ic3X1ltcoLN+eSRRIPr6H/lUS1ttuD0Fj7rPgPhZqopK/jfH8UVj/1hIsQw=="],
|
||||
|
||||
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.0.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-BAH4QVi06TzAbVchXdJPsL0Z/P87jOfes15rI+p3EX9/EGTfIjaQ9lBVlHunxcmoptaA5y1Hdb9UYojIhmnjIw=="],
|
||||
|
||||
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.0.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-Bxsz8ki8+b3PytMnS5SgrGV+mbAWwIxI3ydChb/d1rURlJTMdxTTq5LTebUnlsUWAX6OvJuFeiVq9Gjn1YbCyA=="],
|
||||
|
||||
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.0.0", "", { "os": "linux", "cpu": "x64" }, "sha512-09PcOGYTtkopWRm6mZ/B6Mr6UHdkniUgIG/jLBv+2J8Z61ezRE+xQmpi3yNgUrFIAU4lPA9atg7mhvE/5Bo7Wg=="],
|
||||
|
||||
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.0.0", "", { "os": "linux", "cpu": "x64" }, "sha512-tiQ0ABxMJb9I6GlfNp0ulrTiQSFacJRJO8245FFwE3ty3bfsfxlU/miblzDIi+qNrgGsLq5wIZcVYGp4c+HXZA=="],
|
||||
|
||||
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.0.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-vrTtuGu91xNTEQ5ZcMJBZuDlqr32DWU1r14UfePIGndF//s2WUAmer4FmgoPgruo76rprk37e8S2A2c0psXdxw=="],
|
||||
|
||||
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.0.0", "", { "os": "win32", "cpu": "x64" }, "sha512-2USVQ0hklNsph/KIR72ZdeptyXNnQ3JdzPn3NbjI4Sna34CnxeiYAaZcZzXPDl5PYNFBivV4xmvT3Z3rTmyDBg=="],
|
||||
|
||||
"@elysiajs/trpc": ["@elysiajs/trpc@1.1.0", "", { "peerDependencies": { "elysia": ">= 1.1.0" } }, "sha512-M8QWC+Wa5Z5MWY/+uMQuwZ+JoQkp4jOc1ra4SncFy1zSjFGin59LO1AT0pE+DRJaFV17gha9y7cB6Q7GnaJEAw=="],
|
||||
|
||||
"@elysiajs/websocket": ["@elysiajs/websocket@0.2.8", "", { "dependencies": { "nanoid": "^4.0.0", "raikiri": "^0.0.0-beta.3" }, "peerDependencies": { "elysia": ">= 0.2.2" } }, "sha512-K9KLmYL1SYuAV353GvmK0V9DG5w7XTOGsa1H1dGB5BUTzvBaMvnwNeqnJQ3cjf9V1c0EjQds0Ty4LfUFvV45jw=="],
|
||||
|
||||
"@graphql-typed-document-node/core": ["@graphql-typed-document-node/core@3.2.0", "", { "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ=="],
|
||||
|
||||
"@iota/client": ["@iota/client@2.2.4", "", { "dependencies": { "neon-cli": "^0.8", "prebuild-install": "^6.1.2" } }, "sha512-6zjtqJgkSgrMUFLbxr9k+zXGnEVw6gjTFn5emN2nKpR78+mwW4jUXuNcy/M194bK4sLHjj0T0L4pRWJ6XTGaew=="],
|
||||
|
||||
"@sinclair/typebox": ["@sinclair/typebox@0.34.37", "", {}, "sha512-2TRuQVgQYfy+EzHRTIvkhv2ADEouJ2xNS/Vq+W5EuuewBdOrvATvljZTxHWZSTYr2sTjTHpGvucaGAt67S2akw=="],
|
||||
|
||||
"@tokenizer/inflate": ["@tokenizer/inflate@0.2.7", "", { "dependencies": { "debug": "^4.4.0", "fflate": "^0.8.2", "token-types": "^6.0.0" } }, "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg=="],
|
||||
|
||||
"@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="],
|
||||
|
||||
"@trpc/server": ["@trpc/server@11.4.3", "", { "peerDependencies": { "typescript": ">=5.7.2" } }, "sha512-wnWq3wiLlMOlYkaIZz+qbuYA5udPTLS4GVVRyFkr6aT83xpdCHyVtURT+u4hSoIrOXQM9OPCNXSXsAujWZDdaw=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.2.17", "", { "dependencies": { "bun-types": "1.2.17" } }, "sha512-l/BYs/JYt+cXA/0+wUhulYJB6a6p//GTPiJ7nV+QHa8iiId4HZmnu/3J/SowP5g0rTiERY2kfGKXEK5Ehltx4Q=="],
|
||||
|
||||
"@types/node": ["@types/node@24.0.7", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-YIEUUr4yf8q8oQoXPpSlnvKNVKDQlPMWrmOcgzoduo7kvA2UF0/BwJ/eMKFTiTtkNL17I0M6Xe2tvwFU7be6iw=="],
|
||||
|
||||
"ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="],
|
||||
|
||||
"ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||
|
||||
"aproba": ["aproba@1.2.0", "", {}, "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="],
|
||||
|
||||
"are-we-there-yet": ["are-we-there-yet@1.1.7", "", { "dependencies": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" } }, "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g=="],
|
||||
|
||||
"array-back": ["array-back@3.1.0", "", {}, "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q=="],
|
||||
|
||||
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
|
||||
|
||||
"axios": ["axios@0.24.0", "", { "dependencies": { "follow-redirects": "^1.14.4" } }, "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA=="],
|
||||
|
||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
||||
|
||||
"bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
|
||||
|
||||
"bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
|
||||
|
||||
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
||||
|
||||
"buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
|
||||
|
||||
"builtins": ["builtins@1.0.3", "", {}, "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ=="],
|
||||
|
||||
"bun-types": ["bun-types@1.2.17", "", { "dependencies": { "@types/node": "*" } }, "sha512-ElC7ItwT3SCQwYZDYoAH+q6KT4Fxjl8DtZ6qDulUFBmXA8YB4xo+l54J9ZJN+k2pphfn9vk7kfubeSd5QfTVJQ=="],
|
||||
|
||||
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
||||
|
||||
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||
|
||||
"chardet": ["chardet@0.7.0", "", {}, "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="],
|
||||
|
||||
"chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
|
||||
|
||||
"cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="],
|
||||
|
||||
"cli-width": ["cli-width@3.0.0", "", {}, "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw=="],
|
||||
|
||||
"cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
|
||||
|
||||
"cmake-js": ["cmake-js@7.3.1", "", { "dependencies": { "axios": "^1.6.5", "debug": "^4", "fs-extra": "^11.2.0", "memory-stream": "^1.0.0", "node-api-headers": "^1.1.0", "npmlog": "^6.0.2", "rc": "^1.2.7", "semver": "^7.5.4", "tar": "^6.2.0", "url-join": "^4.0.1", "which": "^2.0.2", "yargs": "^17.7.2" }, "bin": { "cmake-js": "bin/cmake-js" } }, "sha512-aJtHDrTFl8qovjSSqXT9aC2jdGfmP8JQsPtjdLAXFfH1BF4/ImZ27Jx0R61TFg8Apc3pl6e2yBKMveAeRXx2Rw=="],
|
||||
|
||||
"code-point-at": ["code-point-at@1.1.0", "", {}, "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
||||
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
|
||||
"color-support": ["color-support@1.1.3", "", { "bin": { "color-support": "bin.js" } }, "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="],
|
||||
|
||||
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
||||
|
||||
"command-line-args": ["command-line-args@5.2.1", "", { "dependencies": { "array-back": "^3.1.0", "find-replace": "^3.0.0", "lodash.camelcase": "^4.3.0", "typical": "^4.0.0" } }, "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg=="],
|
||||
|
||||
"command-line-commands": ["command-line-commands@3.0.2", "", { "dependencies": { "array-back": "^4.0.1" } }, "sha512-ac6PdCtdR6q7S3HN+JiVLIWGHY30PRYIEl2qPo+FuEuzwAUk0UYyimrngrg7FvF/mCr4Jgoqv5ZnHZgads50rw=="],
|
||||
|
||||
"command-line-usage": ["command-line-usage@6.1.3", "", { "dependencies": { "array-back": "^4.0.2", "chalk": "^2.4.2", "table-layout": "^1.0.2", "typical": "^5.2.0" } }, "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw=="],
|
||||
|
||||
"commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
|
||||
|
||||
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||
|
||||
"console-control-strings": ["console-control-strings@1.1.0", "", {}, "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="],
|
||||
|
||||
"cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
|
||||
|
||||
"core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="],
|
||||
|
||||
"date-format": ["date-format@4.0.14", "", {}, "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg=="],
|
||||
|
||||
"debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
|
||||
|
||||
"decompress-response": ["decompress-response@4.2.1", "", { "dependencies": { "mimic-response": "^2.0.0" } }, "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw=="],
|
||||
|
||||
"deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="],
|
||||
|
||||
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
|
||||
|
||||
"delegates": ["delegates@1.0.0", "", {}, "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="],
|
||||
|
||||
"detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="],
|
||||
|
||||
"dotenv": ["dotenv@10.0.0", "", {}, "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q=="],
|
||||
|
||||
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||
|
||||
"elysia": ["elysia@1.3.5", "", { "dependencies": { "cookie": "^1.0.2", "exact-mirror": "0.1.2", "fast-decode-uri-component": "^1.0.1" }, "optionalDependencies": { "@sinclair/typebox": "^0.34.33", "openapi-types": "^12.1.3" }, "peerDependencies": { "file-type": ">= 20.0.0", "typescript": ">= 5.0.0" } }, "sha512-XVIKXlKFwUT7Sta8GY+wO5reD9I0rqAEtaz1Z71UgJb61csYt8Q3W9al8rtL5RgumuRR8e3DNdzlUN9GkC4KDw=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
|
||||
|
||||
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
||||
|
||||
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
||||
|
||||
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
|
||||
|
||||
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
|
||||
|
||||
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
|
||||
|
||||
"escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
||||
|
||||
"exact-mirror": ["exact-mirror@0.1.2", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-wFCPCDLmHbKGUb8TOi/IS7jLsgR8WVDGtDK3CzcB4Guf/weq7G+I+DkXiRSZfbemBFOxOINKpraM6ml78vo8Zw=="],
|
||||
|
||||
"execspawn": ["execspawn@1.0.1", "", { "dependencies": { "util-extend": "^1.0.1" } }, "sha512-s2k06Jy9i8CUkYe0+DxRlvtkZoOkwwfhB+Xxo5HGUtrISVW2m98jO2tr67DGRFxZwkjQqloA3v/tNtjhBRBieg=="],
|
||||
|
||||
"expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="],
|
||||
|
||||
"external-editor": ["external-editor@3.1.0", "", { "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", "tmp": "^0.0.33" } }, "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew=="],
|
||||
|
||||
"fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="],
|
||||
|
||||
"fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="],
|
||||
|
||||
"figures": ["figures@3.2.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5" } }, "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg=="],
|
||||
|
||||
"file-type": ["file-type@21.0.0", "", { "dependencies": { "@tokenizer/inflate": "^0.2.7", "strtok3": "^10.2.2", "token-types": "^6.0.0", "uint8array-extras": "^1.4.0" } }, "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg=="],
|
||||
|
||||
"file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="],
|
||||
|
||||
"find-replace": ["find-replace@3.0.0", "", { "dependencies": { "array-back": "^3.0.1" } }, "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ=="],
|
||||
|
||||
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
|
||||
|
||||
"follow-redirects": ["follow-redirects@1.15.9", "", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="],
|
||||
|
||||
"form-data": ["form-data@4.0.3", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA=="],
|
||||
|
||||
"fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="],
|
||||
|
||||
"fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="],
|
||||
|
||||
"fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="],
|
||||
|
||||
"fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="],
|
||||
|
||||
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||
|
||||
"gauge": ["gauge@2.7.4", "", { "dependencies": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", "has-unicode": "^2.0.0", "object-assign": "^4.1.0", "signal-exit": "^3.0.0", "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wide-align": "^1.1.0" } }, "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg=="],
|
||||
|
||||
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
|
||||
|
||||
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
|
||||
|
||||
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
|
||||
|
||||
"git-config": ["git-config@0.0.7", "", { "dependencies": { "iniparser": "~1.0.5" } }, "sha512-LidZlYZXWzVjS+M3TEwhtYBaYwLeOZrXci1tBgqp/vDdZTBMl02atvwb6G35L64ibscYoPnxfbwwUS+VZAISLA=="],
|
||||
|
||||
"github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="],
|
||||
|
||||
"glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||
|
||||
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
||||
|
||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||
|
||||
"gradido-blockchain-js": ["gradido-blockchain-js@github:gradido/gradido-blockchain-js#217d03b", { "dependencies": { "bindings": "^1.5.0", "nan": "^2.20.0", "node-addon-api": "^7.1.1", "node-gyp-build": "^4.8.1", "prebuildify": "git+https://github.com/einhornimmond/prebuildify#cmake_js" } }, "gradido-gradido-blockchain-js-217d03b"],
|
||||
|
||||
"graphql": ["graphql@16.11.0", "", {}, "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw=="],
|
||||
|
||||
"graphql-request": ["graphql-request@7.2.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.2.0" }, "peerDependencies": { "graphql": "14 - 16" } }, "sha512-0GR7eQHBFYz372u9lxS16cOtEekFlZYB2qOyq8wDvzRmdRSJ0mgUVX1tzNcIzk3G+4NY+mGtSz411wZdeDF/+A=="],
|
||||
|
||||
"handlebars": ["handlebars@4.7.8", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ=="],
|
||||
|
||||
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
||||
|
||||
"has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
|
||||
|
||||
"has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
|
||||
|
||||
"has-unicode": ["has-unicode@2.0.1", "", {}, "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="],
|
||||
|
||||
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||
|
||||
"iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="],
|
||||
|
||||
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
||||
|
||||
"inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="],
|
||||
|
||||
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||
|
||||
"ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
|
||||
|
||||
"iniparser": ["iniparser@1.0.5", "", {}, "sha512-i40MWqgTU6h/70NtMsDVVDLjDYWwcIR1yIEVDPfxZIJno9z9L4s83p/V7vAu2i48Vj0gpByrkGFub7ko9XvPrw=="],
|
||||
|
||||
"inquirer": ["inquirer@7.3.3", "", { "dependencies": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-width": "^3.0.0", "external-editor": "^3.0.3", "figures": "^3.0.0", "lodash": "^4.17.19", "mute-stream": "0.0.8", "run-async": "^2.4.0", "rxjs": "^6.6.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6" } }, "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA=="],
|
||||
|
||||
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
||||
|
||||
"isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="],
|
||||
|
||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"jose": ["jose@5.10.0", "", {}, "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg=="],
|
||||
|
||||
"jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="],
|
||||
|
||||
"jsonrpc-ts-client": ["jsonrpc-ts-client@0.2.3", "", { "dependencies": { "axios": "^0.24.0", "debug": "^4.3.3" } }, "sha512-9uYpKrZKN3/3+9MYA/0vdhl9/esn59u6I9Qj6ohczxKwJ+e7DD4prf3i2nSdAl0Wlw5gBHZOL3wajSa1uiE16g=="],
|
||||
|
||||
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
|
||||
|
||||
"lodash.camelcase": ["lodash.camelcase@4.3.0", "", {}, "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="],
|
||||
|
||||
"log4js": ["log4js@6.9.1", "", { "dependencies": { "date-format": "^4.0.14", "debug": "^4.3.4", "flatted": "^3.2.7", "rfdc": "^1.3.0", "streamroller": "^3.1.5" } }, "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g=="],
|
||||
|
||||
"make-promises-safe": ["make-promises-safe@5.1.0", "", {}, "sha512-AfdZ49rtyhQR/6cqVKGoH7y4ql7XkS5HJI1lZm0/5N6CQosy1eYbBJ/qbhkKHzo17UH7M918Bysf6XB9f3kS1g=="],
|
||||
|
||||
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
||||
|
||||
"memory-stream": ["memory-stream@1.0.0", "", { "dependencies": { "readable-stream": "^3.4.0" } }, "sha512-Wm13VcsPIMdG96dzILfij09PvuS3APtcKNh7M28FsCA/w6+1mjR7hhPmfFNoilX9xU7wTdhsH5lJAm6XNzdtww=="],
|
||||
|
||||
"mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
||||
|
||||
"mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||
|
||||
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
||||
|
||||
"mimic-response": ["mimic-response@2.1.0", "", {}, "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA=="],
|
||||
|
||||
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
||||
|
||||
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||
|
||||
"minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="],
|
||||
|
||||
"minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="],
|
||||
|
||||
"mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
|
||||
|
||||
"mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"mute-stream": ["mute-stream@0.0.8", "", {}, "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="],
|
||||
|
||||
"nan": ["nan@2.22.2", "", {}, "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ=="],
|
||||
|
||||
"nanoid": ["nanoid@4.0.2", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw=="],
|
||||
|
||||
"napi-build-utils": ["napi-build-utils@1.0.2", "", {}, "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="],
|
||||
|
||||
"neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="],
|
||||
|
||||
"neon-cli": ["neon-cli@0.8.3", "", { "dependencies": { "chalk": "^4.1.0", "command-line-args": "^5.1.1", "command-line-commands": "^3.0.1", "command-line-usage": "^6.1.0", "git-config": "0.0.7", "handlebars": "^4.7.6", "inquirer": "^7.3.3", "make-promises-safe": "^5.1.0", "rimraf": "^3.0.2", "semver": "^7.3.2", "toml": "^3.0.0", "ts-typed-json": "^0.3.2", "validate-npm-package-license": "^3.0.4", "validate-npm-package-name": "^3.0.0" }, "bin": { "neon": "bin/cli.js" } }, "sha512-I44MB8PD0AEyFr/b5icR4sX1tsjdkb2T2uWEStG4Uf5C/jzalZPn7eazbQrW6KDyXNd8bc+LVuOr1v6CGTa1KQ=="],
|
||||
|
||||
"node-abi": ["node-abi@2.30.1", "", { "dependencies": { "semver": "^5.4.1" } }, "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w=="],
|
||||
|
||||
"node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
|
||||
|
||||
"node-api-headers": ["node-api-headers@1.5.0", "", {}, "sha512-Yi/FgnN8IU/Cd6KeLxyHkylBUvDTsSScT0Tna2zTrz8klmc8qF2ppj6Q1LHsmOueJWhigQwR4cO2p0XBGW5IaQ=="],
|
||||
|
||||
"node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="],
|
||||
|
||||
"npm-path": ["npm-path@2.0.4", "", { "dependencies": { "which": "^1.2.10" }, "bin": { "npm-path": "bin/npm-path" } }, "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw=="],
|
||||
|
||||
"npm-run-path": ["npm-run-path@3.1.0", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg=="],
|
||||
|
||||
"npm-which": ["npm-which@3.0.1", "", { "dependencies": { "commander": "^2.9.0", "npm-path": "^2.0.2", "which": "^1.2.10" }, "bin": { "npm-which": "bin/npm-which.js" } }, "sha512-CM8vMpeFQ7MAPin0U3wzDhSGV0hMHNwHU0wjo402IVizPDrs45jSfSuoC+wThevY88LQti8VvaAnqYAeVy3I1A=="],
|
||||
|
||||
"npmlog": ["npmlog@4.1.2", "", { "dependencies": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", "gauge": "~2.7.3", "set-blocking": "~2.0.0" } }, "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg=="],
|
||||
|
||||
"number-is-nan": ["number-is-nan@1.0.1", "", {}, "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ=="],
|
||||
|
||||
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
||||
|
||||
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
||||
|
||||
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
|
||||
|
||||
"openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
|
||||
|
||||
"os-tmpdir": ["os-tmpdir@1.0.2", "", {}, "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="],
|
||||
|
||||
"path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="],
|
||||
|
||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||
|
||||
"prebuild-install": ["prebuild-install@6.1.4", "", { "dependencies": { "detect-libc": "^1.0.3", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^1.0.1", "node-abi": "^2.21.0", "npmlog": "^4.0.1", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^3.0.3", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ=="],
|
||||
|
||||
"prebuildify": ["prebuildify@github:einhornimmond/prebuildify#91f4e76", { "dependencies": { "cmake-js": "^7.2.1", "execspawn": "^1.0.1", "minimist": "^1.2.5", "mkdirp-classic": "^0.5.3", "node-abi": "^3.3.0", "npm-run-path": "^3.1.0", "npm-which": "^3.0.1", "pump": "^3.0.0", "tar-fs": "^2.1.0" }, "bin": { "prebuildify": "./bin.js" } }, "einhornimmond-prebuildify-91f4e76"],
|
||||
|
||||
"process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="],
|
||||
|
||||
"proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
|
||||
|
||||
"pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
|
||||
|
||||
"raikiri": ["raikiri@0.0.0-beta.8", "", {}, "sha512-cH/yfvkiGkN8IBB2MkRHikpPurTnd2sMkQ/xtGpXrp3O76P4ppcWPb+86mJaBDzKaclLnSX+9NnT79D7ifH4/w=="],
|
||||
|
||||
"rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="],
|
||||
|
||||
"readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
|
||||
|
||||
"reduce-flatten": ["reduce-flatten@2.0.0", "", {}, "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w=="],
|
||||
|
||||
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
|
||||
|
||||
"restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="],
|
||||
|
||||
"rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
|
||||
|
||||
"rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
|
||||
|
||||
"run-async": ["run-async@2.4.1", "", {}, "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ=="],
|
||||
|
||||
"rxjs": ["rxjs@6.6.7", "", { "dependencies": { "tslib": "^1.9.0" } }, "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ=="],
|
||||
|
||||
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
|
||||
|
||||
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||
|
||||
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
||||
|
||||
"set-blocking": ["set-blocking@2.0.0", "", {}, "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="],
|
||||
|
||||
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
||||
|
||||
"simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="],
|
||||
|
||||
"simple-get": ["simple-get@3.1.1", "", { "dependencies": { "decompress-response": "^4.2.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA=="],
|
||||
|
||||
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"spdx-correct": ["spdx-correct@3.2.0", "", { "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA=="],
|
||||
|
||||
"spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="],
|
||||
|
||||
"spdx-expression-parse": ["spdx-expression-parse@3.0.1", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q=="],
|
||||
|
||||
"spdx-license-ids": ["spdx-license-ids@3.0.21", "", {}, "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg=="],
|
||||
|
||||
"streamroller": ["streamroller@3.1.5", "", { "dependencies": { "date-format": "^4.0.14", "debug": "^4.3.4", "fs-extra": "^8.1.0" } }, "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw=="],
|
||||
|
||||
"string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
|
||||
|
||||
"strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
|
||||
|
||||
"strtok3": ["strtok3@10.3.1", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-3JWEZM6mfix/GCJBBUrkA8p2Id2pBkyTkVCJKto55w080QBKZ+8R171fGrbiSp+yMO/u6F8/yUh7K4V9K+YCnw=="],
|
||||
|
||||
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
||||
|
||||
"table-layout": ["table-layout@1.0.2", "", { "dependencies": { "array-back": "^4.0.1", "deep-extend": "~0.6.0", "typical": "^5.2.0", "wordwrapjs": "^4.0.0" } }, "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A=="],
|
||||
|
||||
"tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="],
|
||||
|
||||
"tar-fs": ["tar-fs@2.1.3", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg=="],
|
||||
|
||||
"tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="],
|
||||
|
||||
"through": ["through@2.3.8", "", {}, "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="],
|
||||
|
||||
"tmp": ["tmp@0.0.33", "", { "dependencies": { "os-tmpdir": "~1.0.2" } }, "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw=="],
|
||||
|
||||
"token-types": ["token-types@6.0.3", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-IKJ6EzuPPWtKtEIEPpIdXv9j5j2LGJEYk0CKY2efgKoYKLBiZdh6iQkLVBow/CB3phyWAWCyk+bZeaimJn6uRQ=="],
|
||||
|
||||
"toml": ["toml@3.0.0", "", {}, "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="],
|
||||
|
||||
"ts-typed-json": ["ts-typed-json@0.3.2", "", {}, "sha512-Tdu3BWzaer7R5RvBIJcg9r8HrTZgpJmsX+1meXMJzYypbkj8NK2oJN0yvm4Dp/Iv6tzFa/L5jKRmEVTga6K3nA=="],
|
||||
|
||||
"tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="],
|
||||
|
||||
"tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="],
|
||||
|
||||
"type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
|
||||
|
||||
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||
|
||||
"typical": ["typical@4.0.0", "", {}, "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw=="],
|
||||
|
||||
"uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="],
|
||||
|
||||
"uint8array-extras": ["uint8array-extras@1.4.0", "", {}, "sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ=="],
|
||||
|
||||
"undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||
|
||||
"universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="],
|
||||
|
||||
"url-join": ["url-join@4.0.1", "", {}, "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA=="],
|
||||
|
||||
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
||||
|
||||
"util-extend": ["util-extend@1.0.3", "", {}, "sha512-mLs5zAK+ctllYBj+iAQvlDCwoxU/WDOUaJkcFudeiAX6OajC6BKXJUa9a+tbtkC11dz2Ufb7h0lyvIOVn4LADA=="],
|
||||
|
||||
"uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="],
|
||||
|
||||
"valibot": ["valibot@1.1.0", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-Nk8lX30Qhu+9txPYTwM0cFlWLdPFsFr6LblzqIySfbZph9+BFsAHsNvHOymEviUepeIW6KFHzpX8TKhbptBXXw=="],
|
||||
|
||||
"validate-npm-package-license": ["validate-npm-package-license@3.0.4", "", { "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew=="],
|
||||
|
||||
"validate-npm-package-name": ["validate-npm-package-name@3.0.0", "", { "dependencies": { "builtins": "^1.0.3" } }, "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw=="],
|
||||
|
||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
|
||||
"wide-align": ["wide-align@1.1.5", "", { "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } }, "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg=="],
|
||||
|
||||
"wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="],
|
||||
|
||||
"wordwrapjs": ["wordwrapjs@4.0.1", "", { "dependencies": { "reduce-flatten": "^2.0.0", "typical": "^5.2.0" } }, "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA=="],
|
||||
|
||||
"wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||
|
||||
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||
|
||||
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
|
||||
|
||||
"yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||
|
||||
"yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
|
||||
|
||||
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
|
||||
|
||||
"zod": ["zod@3.25.67", "", {}, "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw=="],
|
||||
|
||||
"bl/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
||||
|
||||
"cmake-js/axios": ["axios@1.10.0", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw=="],
|
||||
|
||||
"cmake-js/fs-extra": ["fs-extra@11.3.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew=="],
|
||||
|
||||
"cmake-js/npmlog": ["npmlog@6.0.2", "", { "dependencies": { "are-we-there-yet": "^3.0.0", "console-control-strings": "^1.1.0", "gauge": "^4.0.3", "set-blocking": "^2.0.0" } }, "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg=="],
|
||||
|
||||
"command-line-commands/array-back": ["array-back@4.0.2", "", {}, "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg=="],
|
||||
|
||||
"command-line-usage/array-back": ["array-back@4.0.2", "", {}, "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg=="],
|
||||
|
||||
"command-line-usage/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
||||
|
||||
"command-line-usage/typical": ["typical@5.2.0", "", {}, "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg=="],
|
||||
|
||||
"fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"gauge/string-width": ["string-width@1.0.2", "", { "dependencies": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" } }, "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw=="],
|
||||
|
||||
"gauge/strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg=="],
|
||||
|
||||
"memory-stream/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
||||
|
||||
"minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"node-abi/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
|
||||
|
||||
"npm-path/which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="],
|
||||
|
||||
"npm-which/which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="],
|
||||
|
||||
"prebuildify/node-abi": ["node-abi@3.75.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg=="],
|
||||
|
||||
"readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
||||
|
||||
"string_decoder/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
||||
|
||||
"table-layout/array-back": ["array-back@4.0.2", "", {}, "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg=="],
|
||||
|
||||
"table-layout/typical": ["typical@5.2.0", "", {}, "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg=="],
|
||||
|
||||
"tar/chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="],
|
||||
|
||||
"tar-stream/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
||||
|
||||
"wordwrapjs/typical": ["typical@5.2.0", "", {}, "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg=="],
|
||||
|
||||
"bl/readable-stream/string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
|
||||
|
||||
"cmake-js/fs-extra/jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="],
|
||||
|
||||
"cmake-js/fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
|
||||
|
||||
"cmake-js/npmlog/are-we-there-yet": ["are-we-there-yet@3.0.1", "", { "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" } }, "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg=="],
|
||||
|
||||
"cmake-js/npmlog/gauge": ["gauge@4.0.4", "", { "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.3", "console-control-strings": "^1.1.0", "has-unicode": "^2.0.1", "signal-exit": "^3.0.7", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "wide-align": "^1.1.5" } }, "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg=="],
|
||||
|
||||
"command-line-usage/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
|
||||
|
||||
"command-line-usage/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
|
||||
|
||||
"gauge/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@1.0.0", "", { "dependencies": { "number-is-nan": "^1.0.0" } }, "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw=="],
|
||||
|
||||
"gauge/strip-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="],
|
||||
|
||||
"memory-stream/readable-stream/string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
|
||||
|
||||
"tar-stream/readable-stream/string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
|
||||
|
||||
"cmake-js/npmlog/are-we-there-yet/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
||||
|
||||
"command-line-usage/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||
|
||||
"command-line-usage/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
||||
|
||||
"cmake-js/npmlog/are-we-there-yet/readable-stream/string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
|
||||
|
||||
"command-line-usage/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
|
||||
module.exports = {
|
||||
verbose: true,
|
||||
preset: 'ts-jest',
|
||||
collectCoverage: true,
|
||||
collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**', '!src/seeds/**', '!build/**'],
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
lines: 72,
|
||||
},
|
||||
},
|
||||
setupFiles: ['<rootDir>/test/testSetup.ts'],
|
||||
setupFilesAfterEnv: [],
|
||||
modulePathIgnorePatterns: ['<rootDir>/build/'],
|
||||
moduleNameMapper: {
|
||||
'@/(.*)': '<rootDir>/src/$1',
|
||||
'@arg/(.*)': '<rootDir>/src/graphql/arg/$1',
|
||||
'@controller/(.*)': '<rootDir>/src/controller/$1',
|
||||
'@enum/(.*)': '<rootDir>/src/graphql/enum/$1',
|
||||
'@model/(.*)': '<rootDir>/src/graphql/model/$1',
|
||||
'@resolver/(.*)': '<rootDir>/src/graphql/resolver/$1',
|
||||
'@input/(.*)': '<rootDir>/src/graphql/input/$1',
|
||||
'@proto/(.*)': '<rootDir>/src/proto/$1',
|
||||
'@test/(.*)': '<rootDir>/test/$1',
|
||||
'@client/(.*)': '<rootDir>/src/client/$1',
|
||||
'@validator/(.*)': '<rootDir>/src/graphql/validator/$1',
|
||||
},
|
||||
}
|
||||
/*
|
||||
@arg/*": ["src/graphql/arg/*"],
|
||||
"@enum/*": ["src/graphql/enum/*"],
|
||||
"@input/*": ["src/graphql/input/*"],
|
||||
"@resolver/*": ["src/graphql/resolver/*"],
|
||||
"@scalar/*": ["src/graphql/scalar/*"],
|
||||
"@test/*": ["test/*"],
|
||||
"@proto/*" : ["src/proto/*"],
|
||||
*/
|
||||
@ -8,7 +8,7 @@
|
||||
"pattern": "yyyy-MM-dd",
|
||||
"layout":
|
||||
{
|
||||
"type": "pattern", "pattern": "%d{ISO8601} %p %c [%X{user}] [%f : %l] - %m"
|
||||
"type": "pattern", "pattern": "%d{ISO8601} %p %c [%X{url}] [%f : %l] - %m"
|
||||
},
|
||||
"compress": true,
|
||||
"keepFileExt" : true,
|
||||
@ -22,7 +22,7 @@
|
||||
"pattern": "yyyy-MM-dd",
|
||||
"layout":
|
||||
{
|
||||
"type": "pattern", "pattern": "%d{ISO8601} %p %c [%X{user}] [%f : %l] - %m"
|
||||
"type": "pattern", "pattern": "%d{ISO8601} %p %c [%X{url}] [%f : %l] - %m"
|
||||
},
|
||||
"compress": true,
|
||||
"keepFileExt" : true,
|
||||
@ -40,7 +40,7 @@
|
||||
"type": "stdout",
|
||||
"layout":
|
||||
{
|
||||
"type": "pattern", "pattern": "%d{ISO8601} %p %c [%X{user}] [%f : %l] - %m"
|
||||
"type": "pattern", "pattern": "%d{ISO8601} %p %c [%X{url}] [%f : %l] - %m"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -1,73 +1,42 @@
|
||||
{
|
||||
"name": "gradido-dlt-connector",
|
||||
"version": "2.6.0",
|
||||
"description": "Gradido DLT-Connector",
|
||||
"main": "src/index.ts",
|
||||
"repository": "https://github.com/gradido/gradido/",
|
||||
"author": "Dario Rekowski",
|
||||
"license": "Apache-2.0",
|
||||
"private": false,
|
||||
"name": "dlt-connector",
|
||||
"version": "1.0.50",
|
||||
"scripts": {
|
||||
"build": "tsc --build",
|
||||
"clean": "tsc --build --clean",
|
||||
"start": "cross-env TZ=UTC TS_NODE_BASEURL=./build node -r tsconfig-paths/register build/src/index.js",
|
||||
"dev": "cross-env TZ=UTC nodemon -w src --ext ts --exec ts-node -r dotenv/config -r tsconfig-paths/register src/index.ts",
|
||||
"lint": "eslint --max-warnings=0 --ext .js,.ts .",
|
||||
"test": "cross-env TZ=UTC NODE_ENV=development jest --forceExit --detectOpenHandles"
|
||||
"start": "bun run src/index.ts",
|
||||
"build": "bun build src/index.ts --outdir=build --target=bun --external=gradido-blockchain-js --external=@iota/client",
|
||||
"dev": "bun run --watch src/index.ts",
|
||||
"test": "bun test",
|
||||
"test:debug": "bun test --inspect-brk",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"lint": "biome check --error-on-warnings .",
|
||||
"lint:fix": "biome check --error-on-warnings . --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/server": "^4.7.5",
|
||||
"@apollo/utils.fetcher": "^3.0.0",
|
||||
"@iota/client": "^2.2.4",
|
||||
"body-parser": "^1.20.2",
|
||||
"class-validator": "^0.14.0",
|
||||
"cors": "^2.8.5",
|
||||
"cross-env": "^7.0.3",
|
||||
"dotenv": "10.0.0",
|
||||
"express": "4.17.1",
|
||||
"express-slow-down": "^2.0.1",
|
||||
"gradido-blockchain-js": "git+https://github.com/gradido/gradido-blockchain-js#1c75576",
|
||||
"graphql": "^16.7.1",
|
||||
"graphql-request": "^6.1.0",
|
||||
"graphql-scalars": "^1.22.2",
|
||||
"helmet": "^7.1.0",
|
||||
"jose": "^5.2.2",
|
||||
"jsonrpc-ts-client": "^0.2.3",
|
||||
"log4js": "^6.7.1",
|
||||
"nodemon": "^2.0.20",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"tsconfig-paths": "^4.1.2",
|
||||
"type-graphql": "^2.0.0-beta.2",
|
||||
"uuid": "^9.0.1"
|
||||
"gradido-blockchain-js": "git+https://github.com/gradido/gradido-blockchain-js#217d03b",
|
||||
"@iota/client": "^2.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint-community/eslint-plugin-eslint-comments": "^3.2.1",
|
||||
"@graphql-tools/mock": "^9.0.0",
|
||||
"@types/cors": "^2.8.13",
|
||||
"@types/jest": "^27.0.2",
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/sodium-native": "^2.3.5",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.57.1",
|
||||
"@typescript-eslint/parser": "^5.57.1",
|
||||
"eslint": "^8.37.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-config-standard": "^17.0.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.4",
|
||||
"eslint-plugin-dci-lint": "^0.3.0",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-jest": "^27.2.1",
|
||||
"eslint-plugin-n": "^15.7.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-security": "^1.7.1",
|
||||
"jest": "^27.2.4",
|
||||
"prettier": "^2.8.7",
|
||||
"ts-jest": "^27.0.5",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.9.4"
|
||||
"@biomejs/biome": "2.0.0",
|
||||
"@elysiajs/trpc": "^1.1.0",
|
||||
"@elysiajs/websocket": "^0.2.8",
|
||||
"@trpc/server": "^11.4.3",
|
||||
"@types/bun": "^1.2.17",
|
||||
"dotenv": "^10.0.0",
|
||||
"elysia": "^1.3.5",
|
||||
"graphql-request": "^7.2.0",
|
||||
"jose": "^5.2.2",
|
||||
"jsonrpc-ts-client": "^0.2.3",
|
||||
"log4js": "^6.9.1",
|
||||
"typescript": "^5.8.3",
|
||||
"uuid": "^8.3.2",
|
||||
"valibot": "^1.1.0",
|
||||
"zod": "^3.25.61"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
"node": ">=18"
|
||||
},
|
||||
"module": "src/index.js",
|
||||
"trustedDependencies": [
|
||||
"@iota/client"
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,98 +0,0 @@
|
||||
# -----------------------------------------------
|
||||
# !!! THIS FILE WAS GENERATED BY TYPE-GRAPHQL !!!
|
||||
# !!! DO NOT MODIFY THIS FILE BY YOURSELF !!!
|
||||
# -----------------------------------------------
|
||||
|
||||
type Community {
|
||||
confirmedAt: String!
|
||||
createdAt: String!
|
||||
foreign: Boolean!
|
||||
id: Int!
|
||||
iotaTopic: String!
|
||||
rootPublicKeyHex: String!
|
||||
}
|
||||
|
||||
input CommunityDraft {
|
||||
createdAt: String!
|
||||
foreign: Boolean!
|
||||
uuid: String!
|
||||
}
|
||||
|
||||
"""The `Decimal` scalar type to represent currency values"""
|
||||
scalar Decimal
|
||||
|
||||
"""Type of the transaction"""
|
||||
enum InputTransactionType {
|
||||
CREATION
|
||||
RECEIVE
|
||||
SEND
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
addCommunity(data: CommunityDraft!): TransactionResult!
|
||||
sendTransaction(data: TransactionDraft!): TransactionResult!
|
||||
}
|
||||
|
||||
type Query {
|
||||
communities(confirmed: Boolean, foreign: Boolean, uuid: String): [Community!]!
|
||||
community(confirmed: Boolean, foreign: Boolean, uuid: String): Community!
|
||||
isCommunityExist(confirmed: Boolean, foreign: Boolean, uuid: String): Boolean!
|
||||
}
|
||||
|
||||
input TransactionDraft {
|
||||
amount: Decimal!
|
||||
backendTransactionId: Int!
|
||||
createdAt: String!
|
||||
recipientUser: UserIdentifier!
|
||||
senderUser: UserIdentifier!
|
||||
targetDate: String
|
||||
type: InputTransactionType!
|
||||
}
|
||||
|
||||
type TransactionError {
|
||||
message: String!
|
||||
name: String!
|
||||
type: TransactionErrorType!
|
||||
}
|
||||
|
||||
"""Transaction Error Type"""
|
||||
enum TransactionErrorType {
|
||||
ALREADY_EXIST
|
||||
DB_ERROR
|
||||
INVALID_SIGNATURE
|
||||
LOGIC_ERROR
|
||||
MISSING_PARAMETER
|
||||
NOT_FOUND
|
||||
NOT_IMPLEMENTED_YET
|
||||
PROTO_DECODE_ERROR
|
||||
PROTO_ENCODE_ERROR
|
||||
}
|
||||
|
||||
type TransactionRecipe {
|
||||
createdAt: String!
|
||||
id: Int!
|
||||
topic: String!
|
||||
type: TransactionType!
|
||||
}
|
||||
|
||||
type TransactionResult {
|
||||
error: TransactionError
|
||||
recipe: TransactionRecipe
|
||||
succeed: Boolean!
|
||||
}
|
||||
|
||||
"""Type of the transaction"""
|
||||
enum TransactionType {
|
||||
COMMUNITY_ROOT
|
||||
GRADIDO_CREATION
|
||||
GRADIDO_DEFERRED_TRANSFER
|
||||
GRADIDO_TRANSFER
|
||||
GROUP_FRIENDS_UPDATE
|
||||
REGISTER_ADDRESS
|
||||
}
|
||||
|
||||
input UserIdentifier {
|
||||
accountNr: Int = 1
|
||||
communityUuid: String
|
||||
uuid: String!
|
||||
}
|
||||
@ -1,7 +1,8 @@
|
||||
import { KeyPairEd25519 } from 'gradido-blockchain-js'
|
||||
|
||||
import { KeyPairIdentifier } from '@/data/KeyPairIdentifier'
|
||||
import { logger } from '@/logging/logger'
|
||||
import { KeyPairIdentifier } from './data/KeyPairIdentifier.logic'
|
||||
import { getLogger, Logger } from 'log4js'
|
||||
import { LOG4JS_BASE_CATEGORY } from './config/const'
|
||||
|
||||
// Source: https://refactoring.guru/design-patterns/singleton/typescript/example
|
||||
// and ../federation/client/FederationClientFactory.ts
|
||||
@ -9,19 +10,19 @@ import { logger } from '@/logging/logger'
|
||||
* A Singleton class defines the `getInstance` method that lets clients access
|
||||
* the unique singleton instance.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
||||
export class KeyPairCacheManager {
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
private static instance: KeyPairCacheManager
|
||||
private cache: Map<string, KeyPairEd25519> = new Map<string, KeyPairEd25519>()
|
||||
private homeCommunityUUID: string
|
||||
private homeCommunityUUID: string | undefined
|
||||
private logger: Logger
|
||||
|
||||
/**
|
||||
* The Singleton's constructor should always be private to prevent direct
|
||||
* construction calls with the `new` operator.
|
||||
*/
|
||||
// eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
|
||||
private constructor() {}
|
||||
private constructor() {
|
||||
this.logger = getLogger(`${LOG4JS_BASE_CATEGORY}.client.KeyPairCacheManager`)
|
||||
}
|
||||
|
||||
/**
|
||||
* The static method that controls the access to the singleton instance.
|
||||
@ -41,22 +42,34 @@ export class KeyPairCacheManager {
|
||||
}
|
||||
|
||||
public getHomeCommunityUUID(): string {
|
||||
if (!this.homeCommunityUUID) {
|
||||
throw new Error('home community uuid is not set')
|
||||
}
|
||||
return this.homeCommunityUUID
|
||||
}
|
||||
|
||||
public findKeyPair(input: KeyPairIdentifier): KeyPairEd25519 | undefined {
|
||||
return this.cache.get(input.getKey())
|
||||
public findKeyPair(input: string): KeyPairEd25519 | undefined {
|
||||
return this.cache.get(input)
|
||||
}
|
||||
|
||||
public addKeyPair(input: KeyPairIdentifier, keyPair: KeyPairEd25519): void {
|
||||
const key = input.getKey()
|
||||
if (this.cache.has(key)) {
|
||||
logger.warn('key already exist, cannot add', {
|
||||
key,
|
||||
public addKeyPair(input: string, keyPair: KeyPairEd25519): void {
|
||||
if (this.cache.has(input)) {
|
||||
this.logger.warn('key already exist, cannot add', {
|
||||
key: input,
|
||||
publicKey: keyPair.getPublicKey()?.convertToHex(),
|
||||
})
|
||||
return
|
||||
}
|
||||
this.cache.set(key, keyPair)
|
||||
this.cache.set(input, keyPair)
|
||||
}
|
||||
|
||||
public async getKeyPair(input: string, createKeyPair: () => Promise<KeyPairEd25519>): Promise<KeyPairEd25519> {
|
||||
const keyPair = this.cache.get(input)
|
||||
if (!keyPair) {
|
||||
const keyPair = await createKeyPair()
|
||||
this.cache.set(input, keyPair)
|
||||
return keyPair
|
||||
}
|
||||
return keyPair
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,11 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import { gql, GraphQLClient } from 'graphql-request'
|
||||
import { SignJWT } from 'jose'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
import { CommunityDraft } from '@/graphql/input/CommunityDraft'
|
||||
import { logger } from '@/logging/logger'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { CONFIG } from '../config'
|
||||
import { communitySchema, type Community } from '../schemas/rpcParameter.schema'
|
||||
import { getLogger, Logger } from 'log4js'
|
||||
import { LOG4JS_BASE_CATEGORY } from '../config/const'
|
||||
import * as v from 'valibot'
|
||||
|
||||
const homeCommunity = gql`
|
||||
query {
|
||||
@ -17,30 +16,36 @@ const homeCommunity = gql`
|
||||
}
|
||||
}
|
||||
`
|
||||
interface Community {
|
||||
homeCommunity: {
|
||||
uuid: string
|
||||
foreign: boolean
|
||||
creationDate: string
|
||||
}
|
||||
}
|
||||
|
||||
// Source: https://refactoring.guru/design-patterns/singleton/typescript/example
|
||||
// and ../federation/client/FederationClientFactory.ts
|
||||
/**
|
||||
* A Singleton class defines the `getInstance` method that lets clients access
|
||||
* the unique singleton instance.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
||||
export class BackendClient {
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
private static instance: BackendClient
|
||||
client: GraphQLClient
|
||||
logger: Logger
|
||||
|
||||
/**
|
||||
* The Singleton's constructor should always be private to prevent direct
|
||||
* construction calls with the `new` operator.
|
||||
*/
|
||||
// eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
|
||||
private constructor() {}
|
||||
private constructor() {
|
||||
this.logger = getLogger(`${LOG4JS_BASE_CATEGORY}.client.BackendClient`)
|
||||
this.logger.addContext('url', CONFIG.BACKEND_SERVER_URL)
|
||||
this.client = new GraphQLClient(CONFIG.BACKEND_SERVER_URL, {
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
method: 'GET',
|
||||
jsonSerializer: {
|
||||
parse: JSON.parse,
|
||||
stringify: JSON.stringify,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* The static method that controls the access to the singleton instance.
|
||||
@ -51,44 +56,29 @@ export class BackendClient {
|
||||
public static getInstance(): BackendClient | undefined {
|
||||
if (!BackendClient.instance) {
|
||||
BackendClient.instance = new BackendClient()
|
||||
}
|
||||
if (!BackendClient.instance.client) {
|
||||
try {
|
||||
BackendClient.instance.client = new GraphQLClient(CONFIG.BACKEND_SERVER_URL, {
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
method: 'GET',
|
||||
jsonSerializer: {
|
||||
parse: JSON.parse,
|
||||
stringify: JSON.stringify,
|
||||
},
|
||||
})
|
||||
} catch (e) {
|
||||
logger.error("couldn't connect to backend: ", e)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return BackendClient.instance
|
||||
}
|
||||
|
||||
public async getHomeCommunityDraft(): Promise<CommunityDraft> {
|
||||
logger.info('check home community on backend')
|
||||
const { data, errors } = await this.client.rawRequest<Community>(
|
||||
public async getHomeCommunityDraft(): Promise<Community> {
|
||||
this.logger.info('check home community on backend')
|
||||
const { data, errors } = await this.client.rawRequest<{ homeCommunity: Community }>(
|
||||
homeCommunity,
|
||||
{},
|
||||
{
|
||||
authorization: 'Bearer ' + (await this.createJWTToken()),
|
||||
},
|
||||
{}, // empty variables
|
||||
await this.getRequestHeader(),
|
||||
)
|
||||
if (errors) {
|
||||
throw new LogError('error getting home community from backend', errors)
|
||||
throw errors[0]
|
||||
}
|
||||
return v.parse(communitySchema, data.homeCommunity)
|
||||
}
|
||||
|
||||
private async getRequestHeader(): Promise<{
|
||||
authorization: string
|
||||
}> {
|
||||
return {
|
||||
authorization: 'Bearer ' + (await this.createJWTToken()),
|
||||
}
|
||||
const communityDraft = new CommunityDraft()
|
||||
communityDraft.uuid = data.homeCommunity.uuid
|
||||
communityDraft.foreign = data.homeCommunity.foreign
|
||||
communityDraft.createdAt = data.homeCommunity.creationDate
|
||||
return communityDraft
|
||||
}
|
||||
|
||||
private async createJWTToken(): Promise<string> {
|
||||
|
||||
@ -1,156 +0,0 @@
|
||||
/* eslint-disable camelcase */
|
||||
import { AddressType, ConfirmedTransaction, MemoryBlock, stringToAddressType } from 'gradido-blockchain-js'
|
||||
import JsonRpcClient from 'jsonrpc-ts-client'
|
||||
import { JsonRpcEitherResponse } from 'jsonrpc-ts-client/dist/types/utils/jsonrpc'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
import { logger } from '@/logging/logger'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { confirmedTransactionFromBase64 } from '@/utils/typeConverter'
|
||||
|
||||
const client = new JsonRpcClient({
|
||||
url: CONFIG.NODE_SERVER_URL,
|
||||
})
|
||||
/*
|
||||
enum JsonRPCErrorCodes {
|
||||
NONE = 0,
|
||||
GRADIDO_NODE_ERROR = -10000,
|
||||
UNKNOWN_GROUP = -10001,
|
||||
NOT_IMPLEMENTED = -10002,
|
||||
TRANSACTION_NOT_FOUND = -10003,
|
||||
// default errors from json rpc standard: https://www.jsonrpc.org/specification
|
||||
// -32700 Parse error Invalid JSON was received by the server.
|
||||
PARSE_ERROR = -32700,
|
||||
// -32600 Invalid Request The JSON sent is not a valid Request object.
|
||||
INVALID_REQUEST = -32600,
|
||||
// -32601 Method not found The method does not exist / is not available.
|
||||
METHODE_NOT_FOUND = -32601,
|
||||
// -32602 Invalid params Invalid method parameter(s).
|
||||
INVALID_PARAMS = -32602,
|
||||
// -32603 Internal error Internal JSON - RPC error.
|
||||
INTERNAL_ERROR = -32603,
|
||||
// -32000 to -32099 Server error Reserved for implementation-defined server-errors.
|
||||
}
|
||||
*/
|
||||
|
||||
interface ConfirmedTransactionList {
|
||||
transactions: string[]
|
||||
timeUsed: string
|
||||
}
|
||||
|
||||
interface ConfirmedTransactionResponse {
|
||||
transaction: string
|
||||
timeUsed: string
|
||||
}
|
||||
|
||||
interface AddressTypeResult {
|
||||
addressType: string
|
||||
}
|
||||
|
||||
function resolveResponse<T, R>(response: JsonRpcEitherResponse<T>, onSuccess: (result: T) => R): R {
|
||||
if (response.isSuccess()) {
|
||||
return onSuccess(response.result)
|
||||
} else if (response.isError()) {
|
||||
throw new LogError('error by json rpc request to gradido node server', response.error)
|
||||
}
|
||||
throw new LogError('no success and no error', response)
|
||||
}
|
||||
|
||||
async function getTransactions(
|
||||
fromTransactionId: number,
|
||||
maxResultCount: number,
|
||||
iotaTopic: string,
|
||||
): Promise<ConfirmedTransaction[]> {
|
||||
const parameter = {
|
||||
format: 'base64',
|
||||
fromTransactionId,
|
||||
maxResultCount,
|
||||
communityId: iotaTopic,
|
||||
}
|
||||
logger.info('call getTransactions on Node Server via jsonrpc 2.0 with ', parameter)
|
||||
const response = await client.exec<ConfirmedTransactionList>('getTransactions', parameter) // sends payload {jsonrpc: '2.0', params: ...}
|
||||
return resolveResponse(response, (result: ConfirmedTransactionList) => {
|
||||
logger.debug('GradidoNode used time', result.timeUsed)
|
||||
return result.transactions.map((transactionBase64) =>
|
||||
confirmedTransactionFromBase64(transactionBase64),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
async function getTransaction(
|
||||
transactionId: number | Buffer,
|
||||
iotaTopic: string,
|
||||
): Promise<ConfirmedTransaction | undefined> {
|
||||
logger.info('call gettransaction on Node Server via jsonrpc 2.0')
|
||||
const response = await client.exec<ConfirmedTransactionResponse>('gettransaction', {
|
||||
format: 'base64',
|
||||
communityId: iotaTopic,
|
||||
transactionId: typeof transactionId === 'number' ? transactionId : undefined,
|
||||
iotaMessageId: transactionId instanceof Buffer ? transactionId.toString('hex') : undefined,
|
||||
})
|
||||
return resolveResponse(response, (result: ConfirmedTransactionResponse) => {
|
||||
logger.debug('GradidoNode used time', result.timeUsed)
|
||||
return result.transaction && result.transaction !== ''
|
||||
? confirmedTransactionFromBase64(result.transaction)
|
||||
: undefined
|
||||
})
|
||||
}
|
||||
|
||||
async function getLastTransaction(iotaTopic: string): Promise<ConfirmedTransaction | undefined> {
|
||||
logger.info('call getlasttransaction on Node Server via jsonrpc 2.0')
|
||||
const response = await client.exec<ConfirmedTransactionResponse>('getlasttransaction', {
|
||||
format: 'base64',
|
||||
communityId: iotaTopic,
|
||||
})
|
||||
return resolveResponse(response, (result: ConfirmedTransactionResponse) => {
|
||||
logger.debug('GradidoNode used time', result.timeUsed)
|
||||
return result.transaction && result.transaction !== ''
|
||||
? confirmedTransactionFromBase64(result.transaction)
|
||||
: undefined
|
||||
})
|
||||
}
|
||||
|
||||
async function getAddressType(pubkey: Buffer, iotaTopic: string): Promise<AddressType | undefined> {
|
||||
logger.info('call getaddresstype on Node Server via jsonrpc 2.0')
|
||||
const response = await client.exec<AddressTypeResult>('getaddresstype', {
|
||||
pubkey: pubkey.toString('hex'),
|
||||
communityId: iotaTopic,
|
||||
})
|
||||
return resolveResponse(response, (result: AddressTypeResult) =>
|
||||
stringToAddressType(result.addressType),
|
||||
)
|
||||
}
|
||||
|
||||
async function getTransactionsForAccount(
|
||||
pubkey: MemoryBlock,
|
||||
iotaTopic: string,
|
||||
maxResultCount = 0,
|
||||
firstTransactionNr = 1,
|
||||
): Promise<ConfirmedTransaction[] | undefined> {
|
||||
const parameter = {
|
||||
pubkey: pubkey.convertToHex(),
|
||||
format: 'base64',
|
||||
firstTransactionNr,
|
||||
maxResultCount,
|
||||
communityId: iotaTopic,
|
||||
}
|
||||
logger.info('call listtransactionsforaddress on Node Server via jsonrpc 2.0', parameter)
|
||||
const response = await client.exec<ConfirmedTransactionList>(
|
||||
'listtransactionsforaddress',
|
||||
parameter,
|
||||
)
|
||||
return resolveResponse(response, (result: ConfirmedTransactionList) => {
|
||||
logger.debug('GradidoNode used time', result.timeUsed)
|
||||
return result.transactions.map((transactionBase64) =>
|
||||
confirmedTransactionFromBase64(transactionBase64),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
export {
|
||||
getTransaction,
|
||||
getLastTransaction,
|
||||
getTransactions,
|
||||
getAddressType,
|
||||
getTransactionsForAccount,
|
||||
}
|
||||
33
dlt-connector/src/client/GradidoNode/input.schema.ts
Normal file
33
dlt-connector/src/client/GradidoNode/input.schema.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import * as v from 'valibot'
|
||||
import { uuid4ToTopicSchema } from '../../schemas/typeConverter.schema'
|
||||
|
||||
export enum TransactionFormatType {
|
||||
BASE64 = 'base64',
|
||||
JSON = 'json',
|
||||
}
|
||||
|
||||
export const transactionFormatTypeSchema = v.nullish(
|
||||
v.enum(TransactionFormatType),
|
||||
TransactionFormatType.BASE64
|
||||
)
|
||||
|
||||
export type TransactionFormatTypeInput = v.InferInput<typeof transactionFormatTypeSchema>
|
||||
|
||||
export const getTransactionsInputSchema = v.object({
|
||||
format: transactionFormatTypeSchema,
|
||||
// default value is 1, from first transactions
|
||||
fromTransactionId: v.undefinedable(v.pipe(v.number(), v.minValue(1, 'expect number >= 1')), 1),
|
||||
// default value is 100, max 100 transactions
|
||||
maxResultCount: v.undefinedable(v.pipe(v.number(), v.minValue(1, 'expect number >= 1')), 100),
|
||||
communityId: uuid4ToTopicSchema,
|
||||
})
|
||||
|
||||
export type GetTransactionsInputType = v.InferInput<typeof getTransactionsInputSchema>
|
||||
|
||||
export const getTransactionInputSchema = v.object({
|
||||
transactionIdentifier: v.object({
|
||||
iotaTopic: uuid4ToTopicSchema,
|
||||
transactionNr: v.number(),
|
||||
iotaMessageId: v.string(),
|
||||
}),
|
||||
})
|
||||
174
dlt-connector/src/client/GradidoNode/jsonrpc.api.ts
Normal file
174
dlt-connector/src/client/GradidoNode/jsonrpc.api.ts
Normal file
@ -0,0 +1,174 @@
|
||||
/* eslint-disable camelcase */
|
||||
import { AddressType, ConfirmedTransaction, MemoryBlock, stringToAddressType } from 'gradido-blockchain-js'
|
||||
import JsonRpcClient from 'jsonrpc-ts-client'
|
||||
import { JsonRpcEitherResponse } from 'jsonrpc-ts-client/dist/types/utils/jsonrpc'
|
||||
|
||||
import { CONFIG } from '../../config'
|
||||
import { getLogger } from 'log4js'
|
||||
import { LOG4JS_BASE_CATEGORY } from '../../config/const'
|
||||
import * as v from 'valibot'
|
||||
import { confirmedTransactionFromBase64Schema } from '../../schemas/typeConverter.schema'
|
||||
import { isPortOpenRetry } from '../../utils/network'
|
||||
import { TransactionIdentifierInput, transactionIdentifierSchema } from '../../schemas/transaction.schema'
|
||||
import { GradidoNodeErrorCodes } from '../../enum/GradidoNodeErrorCodes'
|
||||
import { GetTransactionsInputType, TransactionFormatTypeInput, getTransactionsInputSchema, transactionFormatTypeSchema } from './input.schema'
|
||||
|
||||
const logger = getLogger(`${LOG4JS_BASE_CATEGORY}.client.GradidoNode`)
|
||||
|
||||
const client = new JsonRpcClient({
|
||||
url: CONFIG.NODE_SERVER_URL,
|
||||
})
|
||||
|
||||
|
||||
interface ConfirmedTransactionList {
|
||||
transactions: string[]
|
||||
timeUsed: string
|
||||
}
|
||||
|
||||
interface ConfirmedTransactionResponse {
|
||||
transaction: string
|
||||
timeUsed: string
|
||||
}
|
||||
|
||||
interface AddressTypeResult {
|
||||
addressType: string
|
||||
}
|
||||
|
||||
interface FindUserResponse {
|
||||
pubkey: string
|
||||
timeUsed: string
|
||||
}
|
||||
|
||||
export class GradidoNodeRequestError<T> extends Error {
|
||||
private response?: JsonRpcEitherResponse<T>
|
||||
constructor(message: string, response?: JsonRpcEitherResponse<T>) {
|
||||
super(message)
|
||||
this.name = 'GradidoNodeRequestError'
|
||||
this.response = response
|
||||
}
|
||||
getResponse(): JsonRpcEitherResponse<T> | undefined {
|
||||
return this.response
|
||||
}
|
||||
}
|
||||
|
||||
function resolveResponse<T, R>(response: JsonRpcEitherResponse<T>, onSuccess: (result: T) => R): R {
|
||||
if (response.isSuccess()) {
|
||||
return onSuccess(response.result)
|
||||
} else if (response.isError()) {
|
||||
throw new GradidoNodeRequestError(response.error.message, response)
|
||||
}
|
||||
throw new GradidoNodeRequestError('no success and no error')
|
||||
}
|
||||
|
||||
async function getTransactions(input: GetTransactionsInputType): Promise<ConfirmedTransaction[]> {
|
||||
const parameter = v.parse(getTransactionsInputSchema, input)
|
||||
logger.debug('call getTransactions with ', parameter)
|
||||
await isPortOpenRetry(CONFIG.NODE_SERVER_URL)
|
||||
const response = await client.exec<ConfirmedTransactionList>('getTransactions', parameter)
|
||||
return resolveResponse(response, (result: ConfirmedTransactionList) => {
|
||||
logger.info(`call getTransactions, used ${result.timeUsed}`)
|
||||
return result.transactions.map((transactionBase64) =>
|
||||
v.parse(confirmedTransactionFromBase64Schema, transactionBase64),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
async function getTransaction(
|
||||
transactionIdentifier: TransactionIdentifierInput,
|
||||
format: TransactionFormatTypeInput
|
||||
)
|
||||
: Promise<ConfirmedTransaction | undefined> {
|
||||
const parameter = {
|
||||
...v.parse(transactionIdentifierSchema, transactionIdentifier),
|
||||
format: v.parse(transactionFormatTypeSchema, format),
|
||||
}
|
||||
logger.debug('call gettransaction with ', parameter)
|
||||
await isPortOpenRetry(CONFIG.NODE_SERVER_URL)
|
||||
const response = await client.exec<ConfirmedTransactionResponse>('gettransaction', parameter)
|
||||
return resolveResponse(response, (result: ConfirmedTransactionResponse) => {
|
||||
logger.info(`call gettransaction, used ${result.timeUsed}`)
|
||||
return result.transaction && result.transaction !== ''
|
||||
? v.parse(confirmedTransactionFromBase64Schema, result.transaction)
|
||||
: undefined
|
||||
})
|
||||
}
|
||||
|
||||
async function getLastTransaction(iotaTopic: string): Promise<ConfirmedTransaction | undefined> {
|
||||
const parameter = {
|
||||
format: 'base64',
|
||||
communityId: iotaTopic,
|
||||
}
|
||||
logger.debug('call getlasttransaction with ', parameter)
|
||||
await isPortOpenRetry(CONFIG.NODE_SERVER_URL)
|
||||
const response = await client.exec<ConfirmedTransactionResponse>('getlasttransaction', parameter)
|
||||
return resolveResponse(response, (result: ConfirmedTransactionResponse) => {
|
||||
logger.info(`call getlasttransaction, used ${result.timeUsed}`)
|
||||
return result.transaction && result.transaction !== ''
|
||||
? v.parse(confirmedTransactionFromBase64Schema, result.transaction)
|
||||
: undefined
|
||||
})
|
||||
}
|
||||
|
||||
async function getAddressType(pubkey: Buffer, iotaTopic: string): Promise<AddressType | undefined> {
|
||||
const parameter = {
|
||||
pubkey: pubkey.toString('hex'),
|
||||
communityId: iotaTopic,
|
||||
}
|
||||
logger.debug('call getaddresstype with ', parameter)
|
||||
await isPortOpenRetry(CONFIG.NODE_SERVER_URL)
|
||||
const response = await client.exec<AddressTypeResult>('getaddresstype', parameter)
|
||||
return resolveResponse(response, (result: AddressTypeResult) => {
|
||||
logger.info(`call getaddresstype`)
|
||||
return stringToAddressType(result.addressType)
|
||||
})
|
||||
}
|
||||
|
||||
async function findUserByNameHash(nameHash: MemoryBlock, iotaTopic: string): Promise<MemoryBlock | undefined> {
|
||||
const parameter = {
|
||||
nameHash: nameHash.convertToHex(),
|
||||
communityId: iotaTopic,
|
||||
}
|
||||
logger.debug('call findUserByNameHash with ', parameter)
|
||||
await isPortOpenRetry(CONFIG.NODE_SERVER_URL)
|
||||
const response = await client.exec<FindUserResponse>('findUserByNameHash', parameter)
|
||||
if (response.isError() && response.error.code === GradidoNodeErrorCodes.JSON_RPC_ERROR_ADDRESS_NOT_FOUND) {
|
||||
return undefined
|
||||
}
|
||||
return resolveResponse(response, (result: FindUserResponse) => {
|
||||
logger.info(`call findUserByNameHash, used ${result.timeUsed}`)
|
||||
return result.pubkey && result.pubkey !== '' ? MemoryBlock.fromHex(result.pubkey) : undefined
|
||||
})
|
||||
}
|
||||
|
||||
async function getTransactionsForAccount(
|
||||
pubkey: MemoryBlock,
|
||||
iotaTopic: string,
|
||||
maxResultCount = 0,
|
||||
firstTransactionNr = 1,
|
||||
): Promise<ConfirmedTransaction[] | undefined> {
|
||||
const parameter = {
|
||||
pubkey: pubkey.convertToHex(),
|
||||
format: 'base64',
|
||||
firstTransactionNr,
|
||||
maxResultCount,
|
||||
communityId: iotaTopic,
|
||||
}
|
||||
logger.debug('call listtransactionsforaddress with ', parameter)
|
||||
await isPortOpenRetry(CONFIG.NODE_SERVER_URL)
|
||||
const response = await client.exec<ConfirmedTransactionList>('listtransactionsforaddress', parameter)
|
||||
return resolveResponse(response, (result: ConfirmedTransactionList) => {
|
||||
logger.info(`call listtransactionsforaddress, used ${result.timeUsed}`)
|
||||
return result.transactions.map((transactionBase64) =>
|
||||
v.parse(confirmedTransactionFromBase64Schema, transactionBase64),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
export {
|
||||
getTransaction,
|
||||
getLastTransaction,
|
||||
getTransactions,
|
||||
getAddressType,
|
||||
getTransactionsForAccount,
|
||||
findUserByNameHash,
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
|
||||
import { sendMessage, receiveMessage } from '@/client/IotaClient'
|
||||
|
||||
jest.mock('@iota/client', () => {
|
||||
const mockMessageSender = jest.fn().mockImplementation(() => {
|
||||
return {
|
||||
index: jest.fn().mockReturnThis(),
|
||||
data: jest.fn().mockReturnThis(),
|
||||
submit: jest
|
||||
.fn()
|
||||
.mockReturnValue('5498130bc3918e1a7143969ce05805502417e3e1bd596d3c44d6a0adeea22710'),
|
||||
}
|
||||
})
|
||||
const mockMessageFinder = jest.fn().mockImplementation(() => {
|
||||
return {
|
||||
data: jest.fn().mockReturnValue({
|
||||
message: {
|
||||
networkId: '1454675179895816119',
|
||||
parentMessageIds: [
|
||||
'5f30efecca59fdfef7c103e85ef691b2b1dc474e9eae9056888a6d58605083e7',
|
||||
'77cef2fb405daedcd7469e009bb87a6d9a4840e618cdb599cd21a30a9fec88dc',
|
||||
'7d2cfb39f40585ba568a29ad7e85c1478b2584496eb736d4001ac344f6a6cacf',
|
||||
'c66da602874220dfa26925f6be540d37c0084d37cd04726fcc5be9d80b36f850',
|
||||
],
|
||||
payload: {
|
||||
type: 2,
|
||||
index: '4752414449444f3a205465737448656c6c6f57656c7431',
|
||||
data: '48656c6c6f20576f726c64202d20546875204a756e20303820323032332031343a35393a343520474d542b3030303020284b6f6f7264696e69657274652057656c747a65697429',
|
||||
},
|
||||
nonce: '13835058055282465157',
|
||||
},
|
||||
messageId: '5498130bc3918e1a7143969ce05805502417e3e1bd596d3c44d6a0adeea22710',
|
||||
}),
|
||||
}
|
||||
})
|
||||
|
||||
const mockClient = {
|
||||
message: mockMessageSender,
|
||||
getMessage: mockMessageFinder,
|
||||
}
|
||||
const mockClientBuilder = {
|
||||
node: jest.fn().mockReturnThis(),
|
||||
build: jest.fn(() => mockClient),
|
||||
}
|
||||
return {
|
||||
ClientBuilder: jest.fn(() => mockClientBuilder),
|
||||
}
|
||||
})
|
||||
|
||||
describe('Iota Tests', () => {
|
||||
it('test mocked sendDataMessage', async () => {
|
||||
const result = await sendMessage('Test Message', 'topic')
|
||||
expect(result).toBe('5498130bc3918e1a7143969ce05805502417e3e1bd596d3c44d6a0adeea22710')
|
||||
})
|
||||
|
||||
it('should mock getMessage', async () => {
|
||||
const result = await receiveMessage(
|
||||
'5498130bc3918e1a7143969ce05805502417e3e1bd596d3c44d6a0adeea22710',
|
||||
)
|
||||
expect(result).toMatchObject({
|
||||
message: {
|
||||
payload: {
|
||||
data: '48656c6c6f20576f726c64202d20546875204a756e20303820323032332031343a35393a343520474d542b3030303020284b6f6f7264696e69657274652057656c747a65697429',
|
||||
index: '4752414449444f3a205465737448656c6c6f57656c7431',
|
||||
},
|
||||
},
|
||||
messageId: '5498130bc3918e1a7143969ce05805502417e3e1bd596d3c44d6a0adeea22710',
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -1,53 +0,0 @@
|
||||
import { ClientBuilder } from '@iota/client'
|
||||
import { MessageWrapper } from '@iota/client/lib/types'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
const client = new ClientBuilder().node(CONFIG.IOTA_API_URL).build()
|
||||
|
||||
/**
|
||||
* send data message onto iota tangle
|
||||
* @param {string | Uint8Array} message - the message as utf based string, will be converted to hex automatically from @iota/client
|
||||
* @param {string | Uint8Array} topic - the iota topic to which the message will be sended
|
||||
* @return {Promise<MessageWrapper>} the iota message typed
|
||||
*/
|
||||
function sendMessage(
|
||||
message: string | Uint8Array,
|
||||
topic: string | Uint8Array,
|
||||
): Promise<MessageWrapper> {
|
||||
return client.message().index(topic).data(message).submit()
|
||||
}
|
||||
|
||||
/**
|
||||
* receive message for known message id from iota tangle
|
||||
* @param {string} messageId - as hex string
|
||||
* @return {Promise<MessageWrapper>} the iota message typed
|
||||
*/
|
||||
function receiveMessage(messageId: string): Promise<MessageWrapper> {
|
||||
return client.getMessage().data(messageId)
|
||||
}
|
||||
|
||||
export { sendMessage, receiveMessage }
|
||||
|
||||
/**
|
||||
* example for message:
|
||||
```json
|
||||
{
|
||||
message: {
|
||||
networkId: '1454675179895816119',
|
||||
parentMessageIds: [
|
||||
'5f30efecca59fdfef7c103e85ef691b2b1dc474e9eae9056888a6d58605083e7',
|
||||
'77cef2fb405daedcd7469e009bb87a6d9a4840e618cdb599cd21a30a9fec88dc',
|
||||
'7d2cfb39f40585ba568a29ad7e85c1478b2584496eb736d4001ac344f6a6cacf',
|
||||
'c66da602874220dfa26925f6be540d37c0084d37cd04726fcc5be9d80b36f850'
|
||||
],
|
||||
payload: {
|
||||
type: 2,
|
||||
index: '4752414449444f3a205465737448656c6c6f57656c7431',
|
||||
data: '48656c6c6f20576f726c64202d20546875204a756e20303820323032332031343a35393a343520474d542b3030303020284b6f6f7264696e69657274652057656c747a65697429'
|
||||
},
|
||||
nonce: '13835058055282465157'
|
||||
},
|
||||
messageId: '5498130bc3918e1a7143969ce05805502417e3e1bd596d3c44d6a0adeea22710'
|
||||
}
|
||||
```
|
||||
*/
|
||||
1
dlt-connector/src/config/const.ts
Normal file
1
dlt-connector/src/config/const.ts
Normal file
@ -0,0 +1 @@
|
||||
export const LOG4JS_BASE_CATEGORY = 'dlt'
|
||||
@ -2,65 +2,48 @@
|
||||
import dotenv from 'dotenv'
|
||||
dotenv.config()
|
||||
|
||||
const constants = {
|
||||
const logging = {
|
||||
LOG4JS_CONFIG: 'log4js-config.json',
|
||||
// default log level on production should be info
|
||||
LOG_LEVEL: process.env.LOG_LEVEL ?? 'info',
|
||||
CONFIG_VERSION: {
|
||||
DEFAULT: 'DEFAULT',
|
||||
EXPECTED: 'v7.2024-09-24',
|
||||
CURRENT: '',
|
||||
},
|
||||
}
|
||||
|
||||
const server = {
|
||||
PRODUCTION: process.env.NODE_ENV === 'production' ?? false,
|
||||
JWT_SECRET: process.env.JWT_SECRET ?? 'secret123',
|
||||
}
|
||||
|
||||
const iota = {
|
||||
IOTA_API_URL: process.env.IOTA_API_URL ?? 'https://chrysalis-nodes.iota.org',
|
||||
IOTA_COMMUNITY_ALIAS: process.env.IOTA_COMMUNITY_ALIAS ?? 'GRADIDO: TestHelloWelt2',
|
||||
IOTA_HOME_COMMUNITY_SEED: process.env.IOTA_HOME_COMMUNITY_SEED ?? null,
|
||||
}
|
||||
|
||||
const dltConnector = {
|
||||
PRODUCTION: process.env.NODE_ENV === 'production',
|
||||
DLT_CONNECTOR_PORT: process.env.DLT_CONNECTOR_PORT ?? 6010,
|
||||
}
|
||||
|
||||
const nodeServer = {
|
||||
NODE_SERVER_URL: process.env.NODE_SERVER_URL ?? 'http://localhost:8340',
|
||||
}
|
||||
|
||||
const gradidoBlockchain = {
|
||||
const secrets = {
|
||||
JWT_SECRET: process.env.JWT_SECRET ?? 'secret123',
|
||||
GRADIDO_BLOCKCHAIN_CRYPTO_APP_SECRET:
|
||||
process.env.GRADIDO_BLOCKCHAIN_CRYPTO_APP_SECRET ?? 'invalid',
|
||||
GRADIDO_BLOCKCHAIN_SERVER_CRYPTO_KEY:
|
||||
process.env.GRADIDO_BLOCKCHAIN_SERVER_CRYPTO_KEY ?? 'invalid',
|
||||
}
|
||||
|
||||
const backendServer = {
|
||||
BACKEND_SERVER_URL: process.env.BACKEND_SERVER_URL ?? 'http://backend:4000',
|
||||
const iota = {
|
||||
IOTA_HOME_COMMUNITY_SEED: process.env.IOTA_HOME_COMMUNITY_SEED ?? null,
|
||||
}
|
||||
|
||||
// Check config version
|
||||
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION ?? constants.CONFIG_VERSION.DEFAULT
|
||||
if (
|
||||
![constants.CONFIG_VERSION.EXPECTED, constants.CONFIG_VERSION.DEFAULT].includes(
|
||||
constants.CONFIG_VERSION.CURRENT,
|
||||
)
|
||||
) {
|
||||
throw new Error(
|
||||
`Fatal: Config Version incorrect - expected "${constants.CONFIG_VERSION.EXPECTED}" or "${constants.CONFIG_VERSION.DEFAULT}", but found "${constants.CONFIG_VERSION.CURRENT}"`,
|
||||
)
|
||||
const apis = {
|
||||
CONNECT_TIMEOUT_MS: process.env.CONNECT_TIMEOUT_MS
|
||||
? Number.parseInt(process.env.CONNECT_TIMEOUT_MS)
|
||||
: 1000,
|
||||
CONNECT_RETRY_COUNT: process.env.CONNECT_RETRY_COUNT
|
||||
? Number.parseInt(process.env.CONNECT_RETRY_COUNT)
|
||||
: 15,
|
||||
CONNECT_RETRY_DELAY_MS: process.env.CONNECT_RETRY_DELAY_MS
|
||||
? Number.parseInt(process.env.CONNECT_RETRY_DELAY_MS)
|
||||
: 500,
|
||||
IOTA_API_URL: process.env.IOTA_API_URL ?? 'https://chrysalis-nodes.iota.org',
|
||||
NODE_SERVER_URL: process.env.NODE_SERVER_URL ?? 'http://127.0.0.1:8340',
|
||||
BACKEND_SERVER_URL: process.env.BACKEND_SERVER_URL ?? 'http://127.0.0.1:4000',
|
||||
}
|
||||
|
||||
export const CONFIG = {
|
||||
...constants,
|
||||
...logging,
|
||||
...server,
|
||||
...secrets,
|
||||
...iota,
|
||||
...dltConnector,
|
||||
...nodeServer,
|
||||
...gradidoBlockchain,
|
||||
...backendServer,
|
||||
...apis,
|
||||
}
|
||||
|
||||
97
dlt-connector/src/data/KeyPairIdentifier.logic.ts
Normal file
97
dlt-connector/src/data/KeyPairIdentifier.logic.ts
Normal file
@ -0,0 +1,97 @@
|
||||
import { MemoryBlock } from 'gradido-blockchain-js'
|
||||
import { IdentifierAccount, IdentifierAccountInput, identifierAccountSchema } from '../schemas/account.schema'
|
||||
import { ParameterError } from '../errors'
|
||||
import * as v from 'valibot'
|
||||
|
||||
export class KeyPairIdentifierLogic {
|
||||
public identifier: IdentifierAccount
|
||||
public constructor(identifier: IdentifierAccountInput) {
|
||||
// check if data structure is like expected and fill in defaults
|
||||
this.identifier = v.parse(identifierAccountSchema, identifier)
|
||||
}
|
||||
|
||||
isCommunityKeyPair(): boolean {
|
||||
return !this.identifier.seed && !this.identifier.account
|
||||
}
|
||||
|
||||
isSeedKeyPair(): boolean {
|
||||
return this.identifier.seed !== undefined
|
||||
}
|
||||
|
||||
isUserKeyPair(): boolean {
|
||||
return (
|
||||
this.identifier.seed === undefined &&
|
||||
this.identifier.account != undefined &&
|
||||
this.identifier.account.accountNr === 0
|
||||
)
|
||||
}
|
||||
|
||||
isAccountKeyPair(): boolean {
|
||||
return (
|
||||
this.identifier.seed === undefined &&
|
||||
this.identifier.account != undefined &&
|
||||
this.identifier.account.accountNr > 0
|
||||
)
|
||||
}
|
||||
|
||||
getSeed(): string {
|
||||
if (!this.identifier.seed) {
|
||||
throw new Error('get seed called on non seed key pair identifier, please check first with isSeedKeyPair()')
|
||||
}
|
||||
return this.identifier.seed.seed
|
||||
}
|
||||
|
||||
getCommunityUuid(): string {
|
||||
return this.identifier.communityUuid
|
||||
}
|
||||
|
||||
getUserUuid(): string {
|
||||
if (!this.identifier.account) {
|
||||
throw new Error(
|
||||
'get user uuid called on non user key pair identifier, please check first with isUserKeyPair() or isAccountKeyPair()'
|
||||
)
|
||||
}
|
||||
return this.identifier.account.userUuid
|
||||
}
|
||||
|
||||
getAccountNr(): number {
|
||||
if (!this.identifier.account?.accountNr) {
|
||||
throw new Error(
|
||||
'get account nr called on non account key pair identifier, please check first with isAccountKeyPair()'
|
||||
)
|
||||
}
|
||||
return this.identifier.account.accountNr
|
||||
}
|
||||
|
||||
getSeedKey(): string { return this.getSeed() }
|
||||
getCommunityKey(): string { return this.getCommunityUuid() }
|
||||
getCommunityUserKey(): string {
|
||||
return this.createCommunityUserHash()
|
||||
}
|
||||
getCommunityUserAccountKey(): string {
|
||||
return this.createCommunityUserHash() + this.getAccountNr().toString()
|
||||
}
|
||||
|
||||
getKey(): string {
|
||||
if (this.isSeedKeyPair()) {
|
||||
return this.getSeedKey()
|
||||
} else if (this.isCommunityKeyPair()) {
|
||||
return this.getCommunityKey()
|
||||
} else if (this.isUserKeyPair()) {
|
||||
return this.getCommunityUserKey()
|
||||
} else if (this.isAccountKeyPair()) {
|
||||
return this.getCommunityUserAccountKey()
|
||||
}
|
||||
throw new ParameterError('KeyPairIdentifier: unhandled input type')
|
||||
}
|
||||
|
||||
private createCommunityUserHash(): string {
|
||||
if (!this.identifier.account?.userUuid || !this.identifier.communityUuid) {
|
||||
throw new ParameterError('userUuid and/or communityUuid is undefined')
|
||||
}
|
||||
const resultHexString =
|
||||
this.identifier.communityUuid.replace(/-/g, '')
|
||||
+ this.identifier.account.userUuid.replace(/-/g, '')
|
||||
return MemoryBlock.fromHex(resultHexString).calculateHash().convertToHex()
|
||||
}
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
import { UserIdentifier } from '@/graphql/input/UserIdentifier'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { uuid4sToMemoryBlock } from '@/utils/typeConverter'
|
||||
|
||||
export class KeyPairIdentifier {
|
||||
// used for community key pair if it is only parameter or for user key pair
|
||||
communityUuid?: string
|
||||
// if set calculate key pair from seed, ignore all other parameter
|
||||
seed?: string
|
||||
// used for user key pair and account key pair, need also communityUuid
|
||||
userUuid?: string
|
||||
// used for account key pair, need also userUuid
|
||||
accountNr?: number
|
||||
|
||||
public constructor(input: UserIdentifier | string | undefined = undefined) {
|
||||
if (input instanceof UserIdentifier) {
|
||||
if (input.seed !== undefined) {
|
||||
this.seed = input.seed.seed
|
||||
} else {
|
||||
this.communityUuid = input.communityUuid
|
||||
this.userUuid = input.communityUser?.uuid
|
||||
this.accountNr = input.communityUser?.accountNr
|
||||
}
|
||||
} else if (typeof input === 'string') {
|
||||
this.communityUuid = input
|
||||
}
|
||||
}
|
||||
|
||||
isCommunityKeyPair(): boolean {
|
||||
return this.communityUuid !== undefined && this.userUuid === undefined
|
||||
}
|
||||
|
||||
isSeedKeyPair(): boolean {
|
||||
return this.seed !== undefined
|
||||
}
|
||||
|
||||
isUserKeyPair(): boolean {
|
||||
return (
|
||||
this.communityUuid !== undefined &&
|
||||
this.userUuid !== undefined &&
|
||||
this.accountNr === undefined
|
||||
)
|
||||
}
|
||||
|
||||
isAccountKeyPair(): boolean {
|
||||
return (
|
||||
this.communityUuid !== undefined &&
|
||||
this.userUuid !== undefined &&
|
||||
this.accountNr !== undefined
|
||||
)
|
||||
}
|
||||
|
||||
getKey(): string {
|
||||
if (this.seed && this.isSeedKeyPair()) {
|
||||
return this.seed
|
||||
} else if (this.communityUuid && this.isCommunityKeyPair()) {
|
||||
return this.communityUuid
|
||||
}
|
||||
if (this.userUuid && this.communityUuid) {
|
||||
const communityUserHash = uuid4sToMemoryBlock([this.userUuid, this.communityUuid])
|
||||
.calculateHash()
|
||||
.convertToHex()
|
||||
if (this.isUserKeyPair()) {
|
||||
return communityUserHash
|
||||
}
|
||||
if (this.accountNr && this.isAccountKeyPair()) {
|
||||
return communityUserHash + this.accountNr.toString()
|
||||
}
|
||||
}
|
||||
throw new LogError('KeyPairIdentifier: unhandled input type', this)
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,3 @@
|
||||
import { registerEnumType } from 'type-graphql'
|
||||
|
||||
/**
|
||||
* enum for graphql
|
||||
* describe input account type in UserAccountDraft
|
||||
@ -14,8 +12,3 @@ export enum AccountType {
|
||||
SUBACCOUNT = 'SUBACCOUNT', // no creations allowed
|
||||
CRYPTO_ACCOUNT = 'CRYPTO_ACCOUNT', // user control his keys, no creations
|
||||
}
|
||||
|
||||
registerEnumType(AccountType, {
|
||||
name: 'AccountType', // this one is mandatory
|
||||
description: 'Type of account', // this one is optional
|
||||
})
|
||||
19
dlt-connector/src/enum/AddressType.ts
Normal file
19
dlt-connector/src/enum/AddressType.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import {
|
||||
AddressType_COMMUNITY_AUF,
|
||||
AddressType_COMMUNITY_GMW,
|
||||
AddressType_COMMUNITY_HUMAN,
|
||||
AddressType_COMMUNITY_PROJECT,
|
||||
AddressType_CRYPTO_ACCOUNT,
|
||||
AddressType_NONE,
|
||||
AddressType_SUBACCOUNT,
|
||||
} from 'gradido-blockchain-js'
|
||||
|
||||
export enum AddressType {
|
||||
COMMUNITY_AUF = AddressType_COMMUNITY_AUF,
|
||||
COMMUNITY_GMW = AddressType_COMMUNITY_GMW,
|
||||
COMMUNITY_HUMAN = AddressType_COMMUNITY_HUMAN,
|
||||
COMMUNITY_PROJECT = AddressType_COMMUNITY_PROJECT,
|
||||
CRYPTO_ACCOUNT = AddressType_CRYPTO_ACCOUNT,
|
||||
NONE = AddressType_NONE,
|
||||
SUBACCOUNT = AddressType_SUBACCOUNT,
|
||||
}
|
||||
20
dlt-connector/src/enum/GradidoNodeErrorCodes.ts
Normal file
20
dlt-connector/src/enum/GradidoNodeErrorCodes.ts
Normal file
@ -0,0 +1,20 @@
|
||||
export enum GradidoNodeErrorCodes {
|
||||
NONE = 0,
|
||||
GRADIDO_NODE_ERROR = -10000,
|
||||
UNKNOWN_GROUP = -10001,
|
||||
NOT_IMPLEMENTED = -10002,
|
||||
TRANSACTION_NOT_FOUND = -10003,
|
||||
JSON_RPC_ERROR_ADDRESS_NOT_FOUND = -10004,
|
||||
// default errors from json rpc standard: https://www.jsonrpc.org/specification
|
||||
// -32700 Parse error Invalid JSON was received by the server.
|
||||
PARSE_ERROR = -32700,
|
||||
// -32600 Invalid Request The JSON sent is not a valid Request object.
|
||||
INVALID_REQUEST = -32600,
|
||||
// -32601 Method not found The method does not exist / is not available.
|
||||
METHODE_NOT_FOUND = -32601,
|
||||
// -32602 Invalid params Invalid method parameter(s).
|
||||
INVALID_PARAMS = -32602,
|
||||
// -32603 Internal error Internal JSON - RPC error.
|
||||
INTERNAL_ERROR = -32603,
|
||||
// -32000 to -32099 Server error Reserved for implementation-defined server-errors.
|
||||
}
|
||||
@ -1,5 +1,3 @@
|
||||
import { registerEnumType } from 'type-graphql'
|
||||
|
||||
// enum for graphql but with int because it is the same in backend
|
||||
// for transaction type from backend
|
||||
export enum InputTransactionType {
|
||||
@ -11,8 +9,3 @@ export enum InputTransactionType {
|
||||
GRADIDO_REDEEM_DEFERRED_TRANSFER = 'GRADIDO_REDEEM_DEFERRED_TRANSFER',
|
||||
COMMUNITY_ROOT = 'COMMUNITY_ROOT',
|
||||
}
|
||||
|
||||
registerEnumType(InputTransactionType, {
|
||||
name: 'InputTransactionType', // this one is mandatory
|
||||
description: 'Type of the transaction', // this one is optional
|
||||
})
|
||||
@ -1,5 +1,3 @@
|
||||
import { registerEnumType } from 'type-graphql'
|
||||
|
||||
// enum for graphql
|
||||
// error groups for resolver answers
|
||||
export enum TransactionErrorType {
|
||||
@ -15,8 +13,3 @@ export enum TransactionErrorType {
|
||||
NOT_FOUND = 'Not found',
|
||||
VALIDATION_ERROR = 'Validation Error',
|
||||
}
|
||||
|
||||
registerEnumType(TransactionErrorType, {
|
||||
name: 'TransactionErrorType',
|
||||
description: 'Transaction Error Type',
|
||||
})
|
||||
43
dlt-connector/src/errors.ts
Normal file
43
dlt-connector/src/errors.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { TransactionIdentifier } from './schemas/transaction.schema'
|
||||
import { IdentifierAccount } from './schemas/account.schema'
|
||||
|
||||
export class GradidoNodeError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message)
|
||||
this.name = 'GradidoNodeError'
|
||||
}
|
||||
}
|
||||
|
||||
export class GradidoNodeMissingTransactionError extends GradidoNodeError {
|
||||
public transactionIdentifier?: TransactionIdentifier
|
||||
constructor(message: string, transactionIdentifier?: TransactionIdentifier) {
|
||||
super(message)
|
||||
this.name = 'GradidoNodeMissingTransactionError'
|
||||
this.transactionIdentifier = transactionIdentifier
|
||||
}
|
||||
}
|
||||
|
||||
export class GradidoNodeMissingUserError extends GradidoNodeError {
|
||||
public userIdentifier?: IdentifierAccount
|
||||
constructor(message: string, userIdentifier?: IdentifierAccount) {
|
||||
super(message)
|
||||
this.name = 'GradidoNodeMissingUserError'
|
||||
this.userIdentifier = userIdentifier
|
||||
}
|
||||
}
|
||||
|
||||
export class GradidoNodeInvalidTransactionError extends GradidoNodeError {
|
||||
public transactionIdentifier?: TransactionIdentifier
|
||||
constructor(message: string, transactionIdentifier?: TransactionIdentifier) {
|
||||
super(message)
|
||||
this.name = 'GradidoNodeInvalidTransactionError'
|
||||
this.transactionIdentifier = transactionIdentifier
|
||||
}
|
||||
}
|
||||
|
||||
export class ParameterError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message)
|
||||
this.name = 'ParameterError'
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
// https://www.npmjs.com/package/@apollo/protobufjs
|
||||
|
||||
import { IsBoolean, IsUUID } from 'class-validator'
|
||||
import { ArgsType, Field } from 'type-graphql'
|
||||
|
||||
@ArgsType()
|
||||
export class CommunityArg {
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsUUID('4')
|
||||
uuid?: string
|
||||
|
||||
@Field(() => Boolean, { nullable: true })
|
||||
@IsBoolean()
|
||||
foreign?: boolean
|
||||
|
||||
@Field(() => Boolean, { nullable: true })
|
||||
@IsBoolean()
|
||||
confirmed?: boolean
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
export const MEMO_MAX_CHARS = 255
|
||||
export const MEMO_MIN_CHARS = 5
|
||||
@ -1,20 +0,0 @@
|
||||
// https://www.npmjs.com/package/@apollo/protobufjs
|
||||
|
||||
import { isValidDateString } from '@validator/DateString'
|
||||
import { IsBoolean, IsUUID } from 'class-validator'
|
||||
import { Field, InputType } from 'type-graphql'
|
||||
|
||||
@InputType()
|
||||
export class CommunityDraft {
|
||||
@Field(() => String)
|
||||
@IsUUID('4')
|
||||
uuid: string
|
||||
|
||||
@Field(() => Boolean)
|
||||
@IsBoolean()
|
||||
foreign: boolean
|
||||
|
||||
@Field(() => String)
|
||||
@isValidDateString()
|
||||
createdAt: string
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
// https://www.npmjs.com/package/@apollo/protobufjs
|
||||
|
||||
import { IsPositive, IsUUID } from 'class-validator'
|
||||
import { Field, Int, InputType } from 'type-graphql'
|
||||
|
||||
@InputType()
|
||||
export class CommunityUser {
|
||||
@Field(() => String)
|
||||
@IsUUID('4')
|
||||
uuid: string
|
||||
|
||||
@Field(() => Int, { defaultValue: 1, nullable: true })
|
||||
@IsPositive()
|
||||
accountNr?: number
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
// https://www.npmjs.com/package/@apollo/protobufjs
|
||||
|
||||
import { IsString } from 'class-validator'
|
||||
import { Field, InputType } from 'type-graphql'
|
||||
|
||||
@InputType()
|
||||
export class IdentifierSeed {
|
||||
@Field(() => String)
|
||||
@IsString()
|
||||
seed: string
|
||||
|
||||
constructor(seed: string) {
|
||||
this.seed = seed
|
||||
}
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
// https://www.npmjs.com/package/@apollo/protobufjs
|
||||
import { InputTransactionType } from '@enum/InputTransactionType'
|
||||
import { isValidDateString, isValidNumberString } from '@validator/DateString'
|
||||
import { IsEnum, IsObject, IsPositive, MaxLength, MinLength, ValidateNested } from 'class-validator'
|
||||
import { InputType, Field } from 'type-graphql'
|
||||
|
||||
import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from '@/graphql//const'
|
||||
import { AccountType } from '@/graphql/enum/AccountType'
|
||||
|
||||
import { UserIdentifier } from './UserIdentifier'
|
||||
|
||||
@InputType()
|
||||
export class TransactionDraft {
|
||||
@Field(() => UserIdentifier)
|
||||
@IsObject()
|
||||
@ValidateNested()
|
||||
user: UserIdentifier
|
||||
|
||||
// not used for simply register address
|
||||
@Field(() => UserIdentifier, { nullable: true })
|
||||
@IsObject()
|
||||
@ValidateNested()
|
||||
linkedUser?: UserIdentifier
|
||||
|
||||
// not used for register address
|
||||
@Field(() => String, { nullable: true })
|
||||
@isValidNumberString()
|
||||
amount?: string
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@MaxLength(MEMO_MAX_CHARS)
|
||||
@MinLength(MEMO_MIN_CHARS)
|
||||
memo?: string
|
||||
|
||||
@Field(() => InputTransactionType)
|
||||
@IsEnum(InputTransactionType)
|
||||
type: InputTransactionType
|
||||
|
||||
@Field(() => String)
|
||||
@isValidDateString()
|
||||
createdAt: string
|
||||
|
||||
// only for creation transactions
|
||||
@Field(() => String, { nullable: true })
|
||||
@isValidDateString()
|
||||
targetDate?: string
|
||||
|
||||
// only for deferred transaction
|
||||
// duration in seconds
|
||||
@Field(() => Number, { nullable: true })
|
||||
@IsPositive()
|
||||
timeoutDuration?: number
|
||||
|
||||
// only for register address
|
||||
@Field(() => AccountType, { nullable: true })
|
||||
@IsEnum(AccountType)
|
||||
accountType?: AccountType
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
// https://www.npmjs.com/package/@apollo/protobufjs
|
||||
|
||||
import { IsObject, IsUUID, ValidateNested } from 'class-validator'
|
||||
import { Field, InputType } from 'type-graphql'
|
||||
|
||||
import { CommunityUser } from './CommunityUser'
|
||||
import { IdentifierSeed } from './IdentifierSeed'
|
||||
|
||||
@InputType()
|
||||
export class UserIdentifier {
|
||||
@Field(() => String)
|
||||
@IsUUID('4')
|
||||
communityUuid: string
|
||||
|
||||
@Field(() => CommunityUser, { nullable: true })
|
||||
@IsObject()
|
||||
@ValidateNested()
|
||||
communityUser?: CommunityUser
|
||||
|
||||
@Field(() => IdentifierSeed, { nullable: true })
|
||||
@IsObject()
|
||||
@ValidateNested()
|
||||
seed?: IdentifierSeed
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
import { ObjectType, Field } from 'type-graphql'
|
||||
|
||||
import { TransactionErrorType } from '../enum/TransactionErrorType'
|
||||
|
||||
@ObjectType()
|
||||
export class TransactionError implements Error {
|
||||
constructor(type: TransactionErrorType, message: string) {
|
||||
this.type = type
|
||||
this.message = message
|
||||
this.name = type.toString()
|
||||
}
|
||||
|
||||
@Field(() => TransactionErrorType)
|
||||
type: TransactionErrorType
|
||||
|
||||
@Field(() => String)
|
||||
message: string
|
||||
|
||||
@Field(() => String)
|
||||
name: string
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
import { GradidoTransaction, MemoryBlock, transactionTypeToString } from 'gradido-blockchain-js'
|
||||
import { Field, ObjectType } from 'type-graphql'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
@ObjectType()
|
||||
export class TransactionRecipe {
|
||||
public constructor(transaction: GradidoTransaction, messageId: MemoryBlock) {
|
||||
const body = transaction.getTransactionBody()
|
||||
if (!body) {
|
||||
throw new LogError('invalid gradido transaction, cannot geht valid TransactionBody')
|
||||
}
|
||||
|
||||
this.createdAt = body.getCreatedAt().getDate().toString()
|
||||
this.type = transactionTypeToString(body?.getTransactionType())
|
||||
this.messageIdHex = messageId.convertToHex()
|
||||
}
|
||||
|
||||
@Field(() => String)
|
||||
createdAt: string
|
||||
|
||||
@Field(() => String)
|
||||
type: string
|
||||
|
||||
@Field(() => String)
|
||||
messageIdHex: string
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
import { ObjectType, Field } from 'type-graphql'
|
||||
|
||||
import { TransactionError } from './TransactionError'
|
||||
import { TransactionRecipe } from './TransactionRecipe'
|
||||
|
||||
@ObjectType()
|
||||
export class TransactionResult {
|
||||
constructor(content?: TransactionError | TransactionRecipe) {
|
||||
this.succeed = true
|
||||
if (content instanceof TransactionError) {
|
||||
this.error = content
|
||||
this.succeed = false
|
||||
} else if (content instanceof TransactionRecipe) {
|
||||
this.recipe = content
|
||||
}
|
||||
}
|
||||
|
||||
// the error if one happened
|
||||
@Field(() => TransactionError, { nullable: true })
|
||||
error?: TransactionError
|
||||
|
||||
// if no error happened, the message id of the iota transaction
|
||||
@Field(() => TransactionRecipe, { nullable: true })
|
||||
recipe?: TransactionRecipe
|
||||
|
||||
@Field(() => Boolean)
|
||||
succeed: boolean
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
/* eslint-disable camelcase */
|
||||
import { AddressType_NONE } from 'gradido-blockchain-js'
|
||||
import { Arg, Query, Resolver } from 'type-graphql'
|
||||
|
||||
import { getAddressType } from '@/client/GradidoNode'
|
||||
import { KeyPairIdentifier } from '@/data/KeyPairIdentifier'
|
||||
import { KeyPairCalculation } from '@/interactions/keyPairCalculation/KeyPairCalculation.context'
|
||||
import { logger } from '@/logging/logger'
|
||||
import { uuid4ToHash } from '@/utils/typeConverter'
|
||||
|
||||
import { TransactionErrorType } from '../enum/TransactionErrorType'
|
||||
import { UserIdentifier } from '../input/UserIdentifier'
|
||||
import { TransactionError } from '../model/TransactionError'
|
||||
import { TransactionResult } from '../model/TransactionResult'
|
||||
|
||||
@Resolver()
|
||||
export class AccountResolver {
|
||||
@Query(() => Boolean)
|
||||
async isAccountExist(@Arg('data') userIdentifier: UserIdentifier): Promise<boolean> {
|
||||
const accountKeyPair = await KeyPairCalculation(new KeyPairIdentifier(userIdentifier))
|
||||
const publicKey = accountKeyPair.getPublicKey()
|
||||
if (!publicKey) {
|
||||
throw new TransactionResult(
|
||||
new TransactionError(TransactionErrorType.NOT_FOUND, 'cannot get user public key'),
|
||||
)
|
||||
}
|
||||
|
||||
// ask gradido node server for account type, if type !== NONE account exist
|
||||
const addressType = await getAddressType(
|
||||
publicKey.data(),
|
||||
uuid4ToHash(userIdentifier.communityUuid).convertToHex(),
|
||||
)
|
||||
logger.info('isAccountExist', userIdentifier)
|
||||
return addressType !== AddressType_NONE
|
||||
}
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
import { Resolver, Arg, Mutation } from 'type-graphql'
|
||||
|
||||
import { SendToIotaContext } from '@/interactions/sendToIota/SendToIota.context'
|
||||
|
||||
import { TransactionDraft } from '../input/TransactionDraft'
|
||||
import { TransactionError } from '../model/TransactionError'
|
||||
import { TransactionResult } from '../model/TransactionResult'
|
||||
|
||||
@Resolver()
|
||||
export class TransactionResolver {
|
||||
@Mutation(() => TransactionResult)
|
||||
async sendTransaction(
|
||||
@Arg('data')
|
||||
transactionDraft: TransactionDraft,
|
||||
): Promise<TransactionResult> {
|
||||
try {
|
||||
return await SendToIotaContext(transactionDraft)
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (error: any) {
|
||||
if (error instanceof TransactionError) {
|
||||
return new TransactionResult(error)
|
||||
} else {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
import { GraphQLSchema } from 'graphql'
|
||||
import { buildSchema } from 'type-graphql'
|
||||
|
||||
import { AccountResolver } from './resolver/AccountsResolver'
|
||||
import { TransactionResolver } from './resolver/TransactionsResolver'
|
||||
|
||||
export const schema = async (): Promise<GraphQLSchema> => {
|
||||
return buildSchema({
|
||||
resolvers: [TransactionResolver, AccountResolver],
|
||||
validate: {
|
||||
validationError: { target: false },
|
||||
skipMissingProperties: true,
|
||||
skipNullProperties: true,
|
||||
skipUndefinedProperties: false,
|
||||
forbidUnknownValues: true,
|
||||
stopAtFirstError: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
import { registerDecorator, ValidationOptions } from 'class-validator'
|
||||
|
||||
export function isValidDateString(validationOptions?: ValidationOptions) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
return function (object: Object, propertyName: string) {
|
||||
registerDecorator({
|
||||
name: 'isValidDateString',
|
||||
target: object.constructor,
|
||||
propertyName,
|
||||
options: validationOptions,
|
||||
validator: {
|
||||
validate(value: string): boolean {
|
||||
return !isNaN(Date.parse(value))
|
||||
},
|
||||
defaultMessage(): string {
|
||||
return `${propertyName} must be a valid date string`
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function isValidNumberString(validationOptions?: ValidationOptions) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
return function (object: Object, propertyName: string) {
|
||||
registerDecorator({
|
||||
name: 'isValidNumberString',
|
||||
target: object.constructor,
|
||||
propertyName,
|
||||
options: validationOptions,
|
||||
validator: {
|
||||
validate(value: string): boolean {
|
||||
return !isNaN(parseFloat(value))
|
||||
},
|
||||
defaultMessage(): string {
|
||||
return `${propertyName} must be a valid number string`
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,45 +1,22 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { Elysia } from 'elysia'
|
||||
import { CONFIG } from './config'
|
||||
import { loadCryptoKeys, MemoryBlock } from 'gradido-blockchain-js'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
|
||||
import { getLogger, configure } from 'log4js'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { isPortOpenRetry } from './utils/network'
|
||||
import { BackendClient } from './client/BackendClient'
|
||||
import { getTransaction } from './client/GradidoNode'
|
||||
import { CommunityDraft } from './graphql/input/CommunityDraft'
|
||||
import { SendToIotaContext } from './interactions/sendToIota/SendToIota.context'
|
||||
import { logger } from './logging/logger'
|
||||
import { KeyPairCacheManager } from './manager/KeyPairCacheManager'
|
||||
import createServer from './server/createServer'
|
||||
import { LogError } from './server/LogError'
|
||||
import { uuid4ToHash } from './utils/typeConverter'
|
||||
|
||||
async function waitForServer(
|
||||
backend: BackendClient,
|
||||
retryIntervalMs: number,
|
||||
maxRetries: number,
|
||||
): Promise<CommunityDraft> {
|
||||
let retries = 0
|
||||
while (retries < maxRetries) {
|
||||
logger.info(`Attempt ${retries + 1} for connecting to backend`)
|
||||
|
||||
try {
|
||||
// Make a HEAD request to the server
|
||||
return await backend.getHomeCommunityDraft()
|
||||
} catch (error) {
|
||||
logger.info('Server is not reachable: ', error)
|
||||
}
|
||||
|
||||
// Server is not reachable, wait and retry
|
||||
await new Promise((resolve) => setTimeout(resolve, retryIntervalMs))
|
||||
retries++
|
||||
}
|
||||
|
||||
throw new LogError('Max retries exceeded. Server did not become reachable.')
|
||||
}
|
||||
import { KeyPairCacheManager } from './KeyPairCacheManager'
|
||||
import { communityUuidToTopicSchema } from './schemas/rpcParameter.schema'
|
||||
import { parse } from 'valibot'
|
||||
import { getTransaction } from './client/GradidoNode/jsonrpc.api'
|
||||
|
||||
async function main() {
|
||||
// configure log4js
|
||||
// TODO: replace late by loader from config-schema
|
||||
const options = JSON.parse(readFileSync(CONFIG.LOG4JS_CONFIG, 'utf-8'))
|
||||
configure(options)
|
||||
const logger = getLogger('dlt')
|
||||
// TODO: replace with schema validation
|
||||
if (CONFIG.IOTA_HOME_COMMUNITY_SEED) {
|
||||
try {
|
||||
const seed = MemoryBlock.fromHex(CONFIG.IOTA_HOME_COMMUNITY_SEED)
|
||||
@ -47,62 +24,50 @@ async function main() {
|
||||
throw new Error('seed need to be greater than 32 Bytes')
|
||||
}
|
||||
} catch (error) {
|
||||
throw new LogError(
|
||||
logger.error(
|
||||
'IOTA_HOME_COMMUNITY_SEED must be a valid hex string, at least 64 characters long',
|
||||
error,
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// load crypto keys for gradido blockchain lib
|
||||
loadCryptoKeys(
|
||||
MemoryBlock.fromHex(CONFIG.GRADIDO_BLOCKCHAIN_CRYPTO_APP_SECRET),
|
||||
MemoryBlock.fromHex(CONFIG.GRADIDO_BLOCKCHAIN_SERVER_CRYPTO_KEY),
|
||||
)
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`DLT_CONNECTOR_PORT=${CONFIG.DLT_CONNECTOR_PORT}`)
|
||||
const { app } = await createServer()
|
||||
|
||||
// ask backend for home community if we haven't one
|
||||
const backend = BackendClient.getInstance()
|
||||
if (!backend) {
|
||||
throw new LogError('cannot create backend client')
|
||||
throw new Error('cannot create backend client')
|
||||
}
|
||||
// wait for backend server to be ready
|
||||
await waitForServer(backend, 2500, 10)
|
||||
|
||||
const communityDraft = await backend.getHomeCommunityDraft()
|
||||
KeyPairCacheManager.getInstance().setHomeCommunityUUID(communityDraft.uuid)
|
||||
logger.info('home community topic: %s', uuid4ToHash(communityDraft.uuid).convertToHex())
|
||||
// wait for backend server
|
||||
await isPortOpenRetry(CONFIG.BACKEND_SERVER_URL)
|
||||
const homeCommunity = await backend.getHomeCommunityDraft()
|
||||
KeyPairCacheManager.getInstance().setHomeCommunityUUID(homeCommunity.uuid)
|
||||
logger.info('home community topic: %s', parse(communityUuidToTopicSchema, homeCommunity.uuid))
|
||||
logger.info('gradido node server: %s', CONFIG.NODE_SERVER_URL)
|
||||
// ask gradido node if community blockchain was created
|
||||
try {
|
||||
const firstTransaction = await getTransaction(
|
||||
1,
|
||||
uuid4ToHash(communityDraft.uuid).convertToHex(),
|
||||
)
|
||||
if (!firstTransaction) {
|
||||
const topic = parse(communityUuidToTopicSchema, homeCommunity.uuid)
|
||||
if (!await getTransaction(1, topic)) {
|
||||
// if not exist, create community root transaction
|
||||
await SendToIotaContext(communityDraft)
|
||||
await SendToIotaContext(homeCommunity)
|
||||
}
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('error requesting gradido node: ', e)
|
||||
// if not exist, create community root transaction
|
||||
await SendToIotaContext(communityDraft)
|
||||
logger.error('error requesting gradido node: ', e)
|
||||
}
|
||||
app.listen(CONFIG.DLT_CONNECTOR_PORT, () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Server is running at http://localhost:${CONFIG.DLT_CONNECTOR_PORT}`)
|
||||
})
|
||||
|
||||
process.on('exit', () => {
|
||||
// Add shutdown logic here.
|
||||
})
|
||||
|
||||
const app = new Elysia()
|
||||
.get('/', () => "Hello Elysia")
|
||||
.listen(CONFIG.DLT_CONNECTOR_PORT, () => {
|
||||
logger.info(`Server is running at http://localhost:${CONFIG.DLT_CONNECTOR_PORT}`)
|
||||
})
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
// eslint-disable-next-line no-console
|
||||
// biome-ignore lint/suspicious/noConsole: maybe logger isn't initialized here
|
||||
console.error(e)
|
||||
// eslint-disable-next-line n/no-process-exit
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
import { KeyPairEd25519 } from 'gradido-blockchain-js'
|
||||
import { communityUuidToTopicSchema } from '../../schemas/rpcParameter.schema'
|
||||
import * as v from 'valibot'
|
||||
|
||||
export abstract class AbstractRemoteKeyPairRole {
|
||||
protected topic: string
|
||||
public constructor(communityUuid: string) {
|
||||
this.topic = v.parse(communityUuidToTopicSchema, communityUuid)
|
||||
}
|
||||
public abstract retrieveKeyPair(): Promise<KeyPairEd25519>
|
||||
}
|
||||
|
||||
@ -1,30 +1,43 @@
|
||||
import { KeyPairEd25519 } from 'gradido-blockchain-js'
|
||||
|
||||
import { getTransaction } from '@/client/GradidoNode'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { uuid4ToHash } from '@/utils/typeConverter'
|
||||
import { getTransaction } from '../../client/GradidoNode/jsonrpc.api'
|
||||
|
||||
import { AbstractRemoteKeyPairRole } from './AbstractRemoteKeyPair.role'
|
||||
import { GradidoNodeInvalidTransactionError, GradidoNodeMissingTransactionError } from '../../errors'
|
||||
|
||||
export class ForeignCommunityKeyPairRole extends AbstractRemoteKeyPairRole {
|
||||
public constructor(private communityUuid: string) {
|
||||
super()
|
||||
public constructor(communityUuid: string) {
|
||||
super(communityUuid)
|
||||
}
|
||||
|
||||
public async retrieveKeyPair(): Promise<KeyPairEd25519> {
|
||||
const firstTransaction = await getTransaction(1, uuid4ToHash(this.communityUuid).convertToHex())
|
||||
const transactionIdentifier = {
|
||||
transactionNr: 1,
|
||||
iotaTopic: this.topic,
|
||||
}
|
||||
const firstTransaction = await getTransaction(transactionIdentifier)
|
||||
if (!firstTransaction) {
|
||||
throw new LogError(
|
||||
"GradidoNode Server don't know this community with uuid " + this.communityUuid,
|
||||
)
|
||||
throw new GradidoNodeMissingTransactionError('Cannot find transaction', transactionIdentifier)
|
||||
}
|
||||
const transactionBody = firstTransaction.getGradidoTransaction()?.getTransactionBody()
|
||||
if (!transactionBody || !transactionBody.isCommunityRoot()) {
|
||||
throw new LogError('get invalid confirmed transaction from gradido node')
|
||||
if (!transactionBody) {
|
||||
throw new GradidoNodeInvalidTransactionError(
|
||||
'Invalid transaction, body is missing',
|
||||
transactionIdentifier
|
||||
)
|
||||
}
|
||||
if (!transactionBody.isCommunityRoot()) {
|
||||
throw new GradidoNodeInvalidTransactionError(
|
||||
'Invalid transaction, community root type expected',
|
||||
transactionIdentifier
|
||||
)
|
||||
}
|
||||
const communityRoot = transactionBody.getCommunityRoot()
|
||||
if (!communityRoot) {
|
||||
throw new LogError('invalid confirmed transaction')
|
||||
throw new GradidoNodeInvalidTransactionError(
|
||||
'Invalid transaction, community root is missing',
|
||||
transactionIdentifier
|
||||
)
|
||||
}
|
||||
return new KeyPairEd25519(communityRoot.getPublicKey())
|
||||
}
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
import { KeyPairEd25519, MemoryBlock } from 'gradido-blockchain-js'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
import { CONFIG } from '../../config'
|
||||
import { ParameterError } from '../../errors'
|
||||
import { AbstractKeyPairRole } from './AbstractKeyPair.role'
|
||||
|
||||
export class HomeCommunityKeyPairRole extends AbstractKeyPairRole {
|
||||
public generateKeyPair(): KeyPairEd25519 {
|
||||
// TODO: prevent this check with valibot test on config
|
||||
if (!CONFIG.IOTA_HOME_COMMUNITY_SEED) {
|
||||
throw new LogError(
|
||||
throw new Error(
|
||||
'IOTA_HOME_COMMUNITY_SEED is missing either in config or as environment variable',
|
||||
)
|
||||
}
|
||||
const seed = MemoryBlock.fromHex(CONFIG.IOTA_HOME_COMMUNITY_SEED)
|
||||
const keyPair = KeyPairEd25519.create(seed)
|
||||
if (!keyPair) {
|
||||
throw new LogError("couldn't create keyPair from IOTA_HOME_COMMUNITY_SEED")
|
||||
throw new ParameterError("couldn't create keyPair from IOTA_HOME_COMMUNITY_SEED")
|
||||
}
|
||||
return keyPair
|
||||
}
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
import { KeyPairEd25519 } from 'gradido-blockchain-js'
|
||||
|
||||
import { KeyPairIdentifier } from '@/data/KeyPairIdentifier'
|
||||
import { UserIdentifier } from '@/graphql/input/UserIdentifier'
|
||||
import { KeyPairCacheManager } from '@/manager/KeyPairCacheManager'
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
import { KeyPairIdentifierLogic } from '../../data/KeyPairIdentifier.logic'
|
||||
import { KeyPairCacheManager } from '../../KeyPairCacheManager'
|
||||
import { AccountKeyPairRole } from './AccountKeyPair.role'
|
||||
import { ForeignCommunityKeyPairRole } from './ForeignCommunityKeyPair.role'
|
||||
import { HomeCommunityKeyPairRole } from './HomeCommunityKeyPair.role'
|
||||
@ -16,61 +13,46 @@ import { UserKeyPairRole } from './UserKeyPair.role'
|
||||
* @DCI-Context
|
||||
* Context for calculating key pair for signing transactions
|
||||
*/
|
||||
export async function KeyPairCalculation(input: KeyPairIdentifier): Promise<KeyPairEd25519> {
|
||||
export async function KeyPairCalculation(input: KeyPairIdentifierLogic): Promise<KeyPairEd25519> {
|
||||
const cache = KeyPairCacheManager.getInstance()
|
||||
|
||||
// Try cache lookup first
|
||||
let keyPair = cache.findKeyPair(input)
|
||||
if (keyPair) {
|
||||
return keyPair
|
||||
}
|
||||
|
||||
const retrieveKeyPair = async (input: KeyPairIdentifier): Promise<KeyPairEd25519> => {
|
||||
if (input.isSeedKeyPair() && input.seed) {
|
||||
return new LinkedTransactionKeyPairRole(input.seed).generateKeyPair()
|
||||
}
|
||||
if (!input.communityUuid) {
|
||||
throw new LogError('missing community id')
|
||||
return await cache.getKeyPair(input.getKey(), async () => {
|
||||
if (input.isSeedKeyPair()) {
|
||||
return new LinkedTransactionKeyPairRole(input.getSeed()).generateKeyPair()
|
||||
}
|
||||
// If input does not belong to the home community, handle as remote key pair
|
||||
if (cache.getHomeCommunityUUID() !== input.communityUuid) {
|
||||
if (cache.getHomeCommunityUUID() !== input.getCommunityUuid()) {
|
||||
const role =
|
||||
input instanceof UserIdentifier
|
||||
? new RemoteAccountKeyPairRole(input)
|
||||
: new ForeignCommunityKeyPairRole(input.communityUuid)
|
||||
input.isAccountKeyPair()
|
||||
? new RemoteAccountKeyPairRole(input.identifier)
|
||||
: new ForeignCommunityKeyPairRole(input.getCommunityUuid())
|
||||
return await role.retrieveKeyPair()
|
||||
}
|
||||
|
||||
let communityKeyPair = cache.findKeyPair(input)
|
||||
const communityKeyPair = await cache.getKeyPair(input.getCommunityKey(), async () => {
|
||||
return new HomeCommunityKeyPairRole().generateKeyPair()
|
||||
})
|
||||
if (!communityKeyPair) {
|
||||
communityKeyPair = new HomeCommunityKeyPairRole().generateKeyPair()
|
||||
throw new Error("couldn't generate community key pair")
|
||||
}
|
||||
if (input.isCommunityKeyPair()) {
|
||||
return communityKeyPair
|
||||
}
|
||||
const userKeyPairIdentifier = new KeyPairIdentifier()
|
||||
userKeyPairIdentifier.communityUuid = input.communityUuid
|
||||
userKeyPairIdentifier.userUuid = input.userUuid
|
||||
|
||||
let userKeyPair = cache.findKeyPair(userKeyPairIdentifier)
|
||||
if (!userKeyPair && userKeyPairIdentifier.userUuid) {
|
||||
userKeyPair = new UserKeyPairRole(
|
||||
userKeyPairIdentifier.userUuid,
|
||||
const userKeyPair = await cache.getKeyPair(input.getCommunityUserKey(), async () => {
|
||||
return new UserKeyPairRole(
|
||||
input.getUserUuid(),
|
||||
communityKeyPair,
|
||||
).generateKeyPair()
|
||||
}
|
||||
})
|
||||
if (!userKeyPair) {
|
||||
throw new LogError("couldn't generate user key pair")
|
||||
throw new Error("couldn't generate user key pair")
|
||||
}
|
||||
if (input.isUserKeyPair()) {
|
||||
return userKeyPair
|
||||
}
|
||||
|
||||
const accountNr = input.accountNr ?? 1
|
||||
return new AccountKeyPairRole(accountNr, userKeyPair).generateKeyPair()
|
||||
}
|
||||
|
||||
keyPair = await retrieveKeyPair(input)
|
||||
cache.addKeyPair(input, keyPair)
|
||||
return keyPair
|
||||
const accountNr = input.getAccountNr()
|
||||
const accountKeyPair = new AccountKeyPairRole(accountNr, userKeyPair).generateKeyPair()
|
||||
if (input.isAccountKeyPair()) {
|
||||
return accountKeyPair
|
||||
}
|
||||
throw new Error("couldn't generate account key pair, unexpected type")
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { KeyPairEd25519, MemoryBlock } from 'gradido-blockchain-js'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
import { AbstractKeyPairRole } from './AbstractKeyPair.role'
|
||||
import { ParameterError } from '../../errors'
|
||||
|
||||
export class LinkedTransactionKeyPairRole extends AbstractKeyPairRole {
|
||||
public constructor(private seed: string) {
|
||||
@ -15,7 +14,7 @@ export class LinkedTransactionKeyPairRole extends AbstractKeyPairRole {
|
||||
const hash = new MemoryBlock(this.seed).calculateHash()
|
||||
const keyPair = KeyPairEd25519.create(hash)
|
||||
if (!keyPair) {
|
||||
throw new LogError('error creating Ed25519 KeyPair from seed', this.seed)
|
||||
throw new ParameterError(`error creating Ed25519 KeyPair from seed: ${this.seed.substring(0, 5)}...`)
|
||||
}
|
||||
return keyPair
|
||||
}
|
||||
|
||||
@ -1,39 +1,29 @@
|
||||
import { KeyPairEd25519 } from 'gradido-blockchain-js'
|
||||
|
||||
import { getTransactions } from '@/client/GradidoNode'
|
||||
import { UserIdentifier } from '@/graphql/input/UserIdentifier'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { uuid4ToHash } from '@/utils/typeConverter'
|
||||
|
||||
import { findUserByNameHash } from '../../client/GradidoNode/jsonrpc.api'
|
||||
import { IdentifierAccount } from '../../schemas/account.schema'
|
||||
import { GradidoNodeMissingUserError, ParameterError } from '../../errors'
|
||||
import { AbstractRemoteKeyPairRole } from './AbstractRemoteKeyPair.role'
|
||||
import { uuid4ToHashSchema } from '../../schemas/typeConverter.schema'
|
||||
import * as v from 'valibot'
|
||||
|
||||
export class RemoteAccountKeyPairRole extends AbstractRemoteKeyPairRole {
|
||||
public constructor(private user: UserIdentifier) {
|
||||
super()
|
||||
public constructor(private identifier: IdentifierAccount) {
|
||||
super(identifier.communityUuid)
|
||||
}
|
||||
|
||||
public async retrieveKeyPair(): Promise<KeyPairEd25519> {
|
||||
if (!this.user.communityUser) {
|
||||
throw new LogError('missing community user')
|
||||
if (!this.identifier.account) {
|
||||
throw new ParameterError('missing account')
|
||||
}
|
||||
|
||||
const nameHash = uuid4ToHash(this.user.communityUser.uuid)
|
||||
const confirmedTransactions = await getTransactions(
|
||||
0,
|
||||
30,
|
||||
uuid4ToHash(this.user.communityUuid).convertToHex(),
|
||||
const accountPublicKey = await findUserByNameHash(
|
||||
v.parse(uuid4ToHashSchema, this.identifier.account.userUuid),
|
||||
this.topic,
|
||||
)
|
||||
for (let i = 0; i < confirmedTransactions.length; i++) {
|
||||
const transactionBody = confirmedTransactions[i].getGradidoTransaction()?.getTransactionBody()
|
||||
if (transactionBody && transactionBody.isRegisterAddress()) {
|
||||
const registerAddress = transactionBody.getRegisterAddress()
|
||||
if (registerAddress && registerAddress.getNameHash()?.equal(nameHash)) {
|
||||
return new KeyPairEd25519(registerAddress.getAccountPublicKey())
|
||||
}
|
||||
}
|
||||
if (accountPublicKey) {
|
||||
return new KeyPairEd25519(accountPublicKey)
|
||||
}
|
||||
throw new LogError(
|
||||
'cannot find remote user in first 30 transaction from remote blockchain, please wait for better recover implementation',
|
||||
)
|
||||
throw new GradidoNodeMissingUserError('cannot find remote user', this.identifier)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import { KeyPairEd25519 } from 'gradido-blockchain-js'
|
||||
|
||||
import { hardenDerivationIndex } from '@/utils/derivationHelper'
|
||||
import { uuid4ToBuffer } from '@/utils/typeConverter'
|
||||
|
||||
import { hardenDerivationIndex } from '../../utils/derivationHelper'
|
||||
import { AbstractKeyPairRole } from './AbstractKeyPair.role'
|
||||
|
||||
export class UserKeyPairRole extends AbstractKeyPairRole {
|
||||
@ -14,7 +12,7 @@ export class UserKeyPairRole extends AbstractKeyPairRole {
|
||||
// example gradido id: 03857ac1-9cc2-483e-8a91-e5b10f5b8d16 =>
|
||||
// wholeHex: '03857ac19cc2483e8a91e5b10f5b8d16']
|
||||
|
||||
const wholeHex = uuid4ToBuffer(this.userUuid)
|
||||
const wholeHex = Buffer.from(this.userUuid.replace(/-/g, ''), 'hex')
|
||||
const parts = []
|
||||
for (let i = 0; i < 4; i++) {
|
||||
parts[i] = hardenDerivationIndex(wholeHex.subarray(i * 4, (i + 1) * 4).readUInt32BE())
|
||||
|
||||
@ -1,34 +1,37 @@
|
||||
import { GradidoTransactionBuilder } from 'gradido-blockchain-js'
|
||||
|
||||
import { KeyPairIdentifier } from '@/data/KeyPairIdentifier'
|
||||
import { CommunityDraft } from '@/graphql/input/CommunityDraft'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { KeyPairIdentifierLogic } from '../../data/KeyPairIdentifier.logic'
|
||||
import {
|
||||
AUF_ACCOUNT_DERIVATION_INDEX,
|
||||
GMW_ACCOUNT_DERIVATION_INDEX,
|
||||
hardenDerivationIndex,
|
||||
} from '@/utils/derivationHelper'
|
||||
} from '../../utils/derivationHelper'
|
||||
|
||||
import { KeyPairCalculation } from '../keyPairCalculation/KeyPairCalculation.context'
|
||||
|
||||
import { AbstractTransactionRole } from './AbstractTransaction.role'
|
||||
import { Community, CommunityInput, communitySchema } from '../../schemas/rpcParameter.schema'
|
||||
import * as v from 'valibot'
|
||||
|
||||
export class CommunityRootTransactionRole extends AbstractTransactionRole {
|
||||
constructor(private self: CommunityDraft) {
|
||||
private com: Community
|
||||
constructor(input: CommunityInput) {
|
||||
super()
|
||||
this.com = v.parse(communitySchema, input)
|
||||
}
|
||||
|
||||
getSenderCommunityUuid(): string {
|
||||
return this.self.uuid
|
||||
return this.com.uuid
|
||||
}
|
||||
|
||||
getRecipientCommunityUuid(): string {
|
||||
throw new LogError('cannot be used as cross group transaction')
|
||||
throw new Error('cannot be used as cross group transaction')
|
||||
}
|
||||
|
||||
public async getGradidoTransactionBuilder(): Promise<GradidoTransactionBuilder> {
|
||||
const builder = new GradidoTransactionBuilder()
|
||||
const communityKeyPair = await KeyPairCalculation(new KeyPairIdentifier(this.self.uuid))
|
||||
const communityKeyPair = await KeyPairCalculation(
|
||||
new KeyPairIdentifierLogic({ communityUuid: this.com.uuid }))
|
||||
const gmwKeyPair = communityKeyPair.deriveChild(
|
||||
hardenDerivationIndex(GMW_ACCOUNT_DERIVATION_INDEX),
|
||||
)
|
||||
@ -36,7 +39,7 @@ export class CommunityRootTransactionRole extends AbstractTransactionRole {
|
||||
hardenDerivationIndex(AUF_ACCOUNT_DERIVATION_INDEX),
|
||||
)
|
||||
builder
|
||||
.setCreatedAt(new Date(this.self.createdAt))
|
||||
.setCreatedAt(this.com.createdAt)
|
||||
.setCommunityRoot(
|
||||
communityKeyPair.getPublicKey(),
|
||||
gmwKeyPair.getPublicKey(),
|
||||
|
||||
@ -2,72 +2,80 @@ import {
|
||||
AuthenticatedEncryption,
|
||||
EncryptedMemo,
|
||||
GradidoTransactionBuilder,
|
||||
GradidoUnit,
|
||||
TransferAmount,
|
||||
} from 'gradido-blockchain-js'
|
||||
|
||||
import { KeyPairIdentifier } from '@/data/KeyPairIdentifier'
|
||||
import { TransactionErrorType } from '@/graphql/enum/TransactionErrorType'
|
||||
import { TransactionDraft } from '@/graphql/input/TransactionDraft'
|
||||
import { TransactionError } from '@/graphql/model/TransactionError'
|
||||
import { KeyPairCacheManager } from '@/manager/KeyPairCacheManager'
|
||||
import { KeyPairIdentifierLogic } from '../../data/KeyPairIdentifier.logic'
|
||||
import { CreationTransactionInput, creationTransactionSchema, CreationTransaction } from '../../schemas/transaction.schema'
|
||||
import { KeyPairCacheManager } from '../../KeyPairCacheManager'
|
||||
import { TRPCError } from '@trpc/server'
|
||||
|
||||
import { KeyPairCalculation } from '../keyPairCalculation/KeyPairCalculation.context'
|
||||
|
||||
import * as v from 'valibot'
|
||||
import { AbstractTransactionRole } from './AbstractTransaction.role'
|
||||
import { Uuidv4, uuidv4Schema } from '../../schemas/typeConverter.schema'
|
||||
|
||||
export class CreationTransactionRole extends AbstractTransactionRole {
|
||||
constructor(private self: TransactionDraft) {
|
||||
private tx: CreationTransaction
|
||||
private homeCommunityUuid: Uuidv4
|
||||
constructor(input: CreationTransactionInput) {
|
||||
super()
|
||||
this.tx = v.parse(creationTransactionSchema, input)
|
||||
this.homeCommunityUuid = v.parse(
|
||||
uuidv4Schema,
|
||||
KeyPairCacheManager.getInstance().getHomeCommunityUUID()
|
||||
)
|
||||
if (
|
||||
this.homeCommunityUuid !== this.tx.user.communityUuid ||
|
||||
this.homeCommunityUuid !== this.tx.linkedUser.communityUuid
|
||||
) {
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'creation: both recipient and signer must belong to home community',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
getSenderCommunityUuid(): string {
|
||||
return this.self.user.communityUuid
|
||||
return this.tx.user.communityUuid
|
||||
}
|
||||
|
||||
getRecipientCommunityUuid(): string {
|
||||
throw new TransactionError(
|
||||
TransactionErrorType.LOGIC_ERROR,
|
||||
'creation: cannot be used as cross group transaction',
|
||||
)
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'creation: cannot be used as cross group transaction',
|
||||
})
|
||||
}
|
||||
|
||||
public async getGradidoTransactionBuilder(): Promise<GradidoTransactionBuilder> {
|
||||
if (!this.self.targetDate) {
|
||||
throw new TransactionError(
|
||||
TransactionErrorType.MISSING_PARAMETER,
|
||||
'creation: target date missing',
|
||||
)
|
||||
}
|
||||
if (!this.self.linkedUser) {
|
||||
throw new TransactionError(
|
||||
TransactionErrorType.MISSING_PARAMETER,
|
||||
'creation: linked user missing',
|
||||
)
|
||||
}
|
||||
if (!this.self.amount) {
|
||||
throw new TransactionError(TransactionErrorType.MISSING_PARAMETER, 'creation: amount missing')
|
||||
}
|
||||
if (!this.self.memo) {
|
||||
throw new TransactionError(TransactionErrorType.MISSING_PARAMETER, 'creation: memo missing')
|
||||
}
|
||||
|
||||
const builder = new GradidoTransactionBuilder()
|
||||
const recipientKeyPair = await KeyPairCalculation(new KeyPairIdentifier(this.self.user))
|
||||
const signerKeyPair = await KeyPairCalculation(new KeyPairIdentifier(this.self.linkedUser))
|
||||
const homeCommunityKeyPair = await KeyPairCalculation(
|
||||
new KeyPairIdentifier(KeyPairCacheManager.getInstance().getHomeCommunityUUID()),
|
||||
// Recipient: user (account owner)
|
||||
const recipientKeyPair = await KeyPairCalculation(
|
||||
new KeyPairIdentifierLogic(this.tx.user)
|
||||
)
|
||||
|
||||
// Signer: linkedUser (admin/moderator)
|
||||
const signerKeyPair = await KeyPairCalculation(
|
||||
new KeyPairIdentifierLogic(this.tx.linkedUser)
|
||||
)
|
||||
const homeCommunityKeyPair = await KeyPairCalculation(
|
||||
new KeyPairIdentifierLogic({
|
||||
communityUuid: this.homeCommunityUuid
|
||||
}),
|
||||
)
|
||||
// Memo: encrypted, home community and recipient can decrypt it
|
||||
builder
|
||||
.setCreatedAt(new Date(this.self.createdAt))
|
||||
.addMemo(new EncryptedMemo(this.self.memo, new AuthenticatedEncryption(homeCommunityKeyPair)))
|
||||
.setCreatedAt(this.tx.createdAt)
|
||||
.addMemo(new EncryptedMemo(
|
||||
this.tx.memo,
|
||||
new AuthenticatedEncryption(homeCommunityKeyPair),
|
||||
new AuthenticatedEncryption(recipientKeyPair),
|
||||
))
|
||||
.setTransactionCreation(
|
||||
new TransferAmount(
|
||||
recipientKeyPair.getPublicKey(),
|
||||
GradidoUnit.fromString(this.self.amount),
|
||||
this.tx.amount,
|
||||
),
|
||||
new Date(this.self.targetDate),
|
||||
this.tx.targetDate,
|
||||
)
|
||||
.sign(signerKeyPair)
|
||||
return builder
|
||||
|
||||
@ -1,72 +1,57 @@
|
||||
import {
|
||||
AuthenticatedEncryption,
|
||||
DurationSeconds,
|
||||
EncryptedMemo,
|
||||
GradidoTransactionBuilder,
|
||||
GradidoTransfer,
|
||||
GradidoUnit,
|
||||
TransferAmount,
|
||||
} from 'gradido-blockchain-js'
|
||||
|
||||
import { KeyPairIdentifier } from '@/data/KeyPairIdentifier'
|
||||
import { TransactionErrorType } from '@/graphql/enum/TransactionErrorType'
|
||||
import { TransactionDraft } from '@/graphql/input/TransactionDraft'
|
||||
import { TransactionError } from '@/graphql/model/TransactionError'
|
||||
|
||||
import { KeyPairIdentifierLogic } from '../../data/KeyPairIdentifier.logic'
|
||||
import { KeyPairCalculation } from '../keyPairCalculation/KeyPairCalculation.context'
|
||||
|
||||
import { AbstractTransactionRole } from './AbstractTransaction.role'
|
||||
import { DeferredTransferTransactionInput, deferredTransferTransactionSchema, DeferredTransferTransaction } from '../../schemas/transaction.schema'
|
||||
import * as v from 'valibot'
|
||||
import { TRPCError } from '@trpc/server'
|
||||
import { identifierSeedSchema, IdentifierSeed } from '../../schemas/account.schema'
|
||||
|
||||
export class DeferredTransferTransactionRole extends AbstractTransactionRole {
|
||||
constructor(protected self: TransactionDraft) {
|
||||
private tx: DeferredTransferTransaction
|
||||
private seed: IdentifierSeed
|
||||
constructor(protected input: DeferredTransferTransactionInput) {
|
||||
super()
|
||||
this.tx = v.parse(deferredTransferTransactionSchema, input)
|
||||
this.seed = v.parse(identifierSeedSchema, input.linkedUser.seed)
|
||||
}
|
||||
|
||||
getSenderCommunityUuid(): string {
|
||||
return this.self.user.communityUuid
|
||||
return this.tx.user.communityUuid
|
||||
}
|
||||
|
||||
getRecipientCommunityUuid(): string {
|
||||
throw new TransactionError(
|
||||
TransactionErrorType.LOGIC_ERROR,
|
||||
'deferred transfer: cannot be used as cross group transaction',
|
||||
)
|
||||
throw new TRPCError({
|
||||
code: 'NOT_IMPLEMENTED',
|
||||
message: 'deferred transfer: cannot be used as cross group transaction yet',
|
||||
})
|
||||
}
|
||||
|
||||
public async getGradidoTransactionBuilder(): Promise<GradidoTransactionBuilder> {
|
||||
if (!this.self.linkedUser || !this.self.linkedUser.seed) {
|
||||
throw new TransactionError(
|
||||
TransactionErrorType.MISSING_PARAMETER,
|
||||
'deferred transfer: missing linked user or not a seed',
|
||||
)
|
||||
}
|
||||
if (!this.self.amount) {
|
||||
throw new TransactionError(
|
||||
TransactionErrorType.MISSING_PARAMETER,
|
||||
'deferred transfer: amount missing',
|
||||
)
|
||||
}
|
||||
if (!this.self.memo) {
|
||||
throw new TransactionError(
|
||||
TransactionErrorType.MISSING_PARAMETER,
|
||||
'deferred transfer: memo missing',
|
||||
)
|
||||
}
|
||||
if (!this.self.timeoutDuration) {
|
||||
throw new TransactionError(
|
||||
TransactionErrorType.MISSING_PARAMETER,
|
||||
'deferred transfer: timeout duration missing',
|
||||
)
|
||||
}
|
||||
const builder = new GradidoTransactionBuilder()
|
||||
const senderKeyPair = await KeyPairCalculation(new KeyPairIdentifier(this.self.user))
|
||||
const recipientKeyPair = await KeyPairCalculation(new KeyPairIdentifier(this.self.linkedUser))
|
||||
const senderKeyPair = await KeyPairCalculation(
|
||||
new KeyPairIdentifierLogic(this.tx.user)
|
||||
)
|
||||
const recipientKeyPair = await KeyPairCalculation(
|
||||
new KeyPairIdentifierLogic({
|
||||
communityUuid: this.tx.linkedUser.communityUuid,
|
||||
seed: this.seed,
|
||||
})
|
||||
)
|
||||
|
||||
builder
|
||||
.setCreatedAt(new Date(this.self.createdAt))
|
||||
.setCreatedAt(this.tx.createdAt)
|
||||
.addMemo(
|
||||
new EncryptedMemo(
|
||||
this.self.memo,
|
||||
this.tx.memo,
|
||||
new AuthenticatedEncryption(senderKeyPair),
|
||||
new AuthenticatedEncryption(recipientKeyPair),
|
||||
),
|
||||
@ -75,13 +60,13 @@ export class DeferredTransferTransactionRole extends AbstractTransactionRole {
|
||||
new GradidoTransfer(
|
||||
new TransferAmount(
|
||||
senderKeyPair.getPublicKey(),
|
||||
GradidoUnit.fromString(this.self.amount).calculateCompoundInterest(
|
||||
this.self.timeoutDuration,
|
||||
this.tx.amount.calculateCompoundInterest(
|
||||
this.tx.timeoutDuration.getSeconds(),
|
||||
),
|
||||
),
|
||||
recipientKeyPair.getPublicKey(),
|
||||
),
|
||||
new DurationSeconds(this.self.timeoutDuration),
|
||||
this.tx.timeoutDuration,
|
||||
)
|
||||
.sign(senderKeyPair)
|
||||
return builder
|
||||
|
||||
@ -1,60 +1,69 @@
|
||||
/* eslint-disable camelcase */
|
||||
import { GradidoTransactionBuilder } from 'gradido-blockchain-js'
|
||||
|
||||
import { KeyPairIdentifier } from '@/data/KeyPairIdentifier'
|
||||
import { TransactionErrorType } from '@/graphql/enum/TransactionErrorType'
|
||||
import { TransactionDraft } from '@/graphql/input/TransactionDraft'
|
||||
import { TransactionError } from '@/graphql/model/TransactionError'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { accountTypeToAddressType, uuid4ToHash } from '@/utils/typeConverter'
|
||||
import { KeyPairIdentifierLogic } from '../../data/KeyPairIdentifier.logic'
|
||||
|
||||
import { KeyPairCalculation } from '../keyPairCalculation/KeyPairCalculation.context'
|
||||
|
||||
import { AbstractTransactionRole } from './AbstractTransaction.role'
|
||||
import { RegisterAddressTransactionInput, registerAddressTransactionSchema, RegisterAddressTransaction } from '../../schemas/transaction.schema'
|
||||
import { IdentifierAccount, IdentifierCommunityAccount, identifierCommunityAccountSchema } from '../../schemas/account.schema'
|
||||
import * as v from 'valibot'
|
||||
import { TRPCError } from '@trpc/server'
|
||||
import { uuid4ToHashSchema } from '../../schemas/typeConverter.schema'
|
||||
|
||||
export class RegisterAddressTransactionRole extends AbstractTransactionRole {
|
||||
constructor(private self: TransactionDraft) {
|
||||
private tx: RegisterAddressTransaction
|
||||
private account: IdentifierCommunityAccount
|
||||
constructor(input: RegisterAddressTransactionInput) {
|
||||
super()
|
||||
this.tx = v.parse(registerAddressTransactionSchema, input)
|
||||
this.account = v.parse(identifierCommunityAccountSchema, input.user.account)
|
||||
}
|
||||
|
||||
getSenderCommunityUuid(): string {
|
||||
return this.self.user.communityUuid
|
||||
return this.tx.user.communityUuid
|
||||
}
|
||||
|
||||
getRecipientCommunityUuid(): string {
|
||||
throw new LogError('cannot yet be used as cross group transaction')
|
||||
throw new TRPCError({
|
||||
code: 'NOT_IMPLEMENTED',
|
||||
message: 'register address: cannot be used as cross group transaction yet',
|
||||
})
|
||||
}
|
||||
|
||||
public async getGradidoTransactionBuilder(): Promise<GradidoTransactionBuilder> {
|
||||
if (!this.self.accountType) {
|
||||
throw new TransactionError(
|
||||
TransactionErrorType.MISSING_PARAMETER,
|
||||
'register address: account type missing',
|
||||
)
|
||||
}
|
||||
|
||||
if (!this.self.user.communityUser) {
|
||||
throw new TransactionError(
|
||||
TransactionErrorType.MISSING_PARAMETER,
|
||||
"register address: user isn't a community user",
|
||||
)
|
||||
}
|
||||
|
||||
const builder = new GradidoTransactionBuilder()
|
||||
const communityKeyPair = await KeyPairCalculation(
|
||||
new KeyPairIdentifier(this.self.user.communityUuid),
|
||||
new KeyPairIdentifierLogic({ communityUuid: this.tx.user.communityUuid }),
|
||||
)
|
||||
const keyPairIdentifer = new KeyPairIdentifier(this.self.user)
|
||||
const accountKeyPair = await KeyPairCalculation(keyPairIdentifer)
|
||||
// unsetting accountNr change identifier from account key pair to user key pair
|
||||
keyPairIdentifer.accountNr = undefined
|
||||
const userKeyPair = await KeyPairCalculation(keyPairIdentifer)
|
||||
const userKeyPairIdentifier: IdentifierAccount = {
|
||||
communityUuid: this.tx.user.communityUuid,
|
||||
account: {
|
||||
userUuid: this.account.userUuid,
|
||||
accountNr: 0,
|
||||
},
|
||||
}
|
||||
const accountKeyPairIdentifier: IdentifierAccount = {
|
||||
communityUuid: this.tx.user.communityUuid,
|
||||
account: {
|
||||
userUuid: this.account.userUuid,
|
||||
accountNr: this.account.accountNr,
|
||||
},
|
||||
}
|
||||
const userKeyPair = await KeyPairCalculation(
|
||||
new KeyPairIdentifierLogic(userKeyPairIdentifier)
|
||||
)
|
||||
const accountKeyPair = await KeyPairCalculation(
|
||||
new KeyPairIdentifierLogic(accountKeyPairIdentifier)
|
||||
)
|
||||
|
||||
builder
|
||||
.setCreatedAt(new Date(this.self.createdAt))
|
||||
.setCreatedAt(this.tx.createdAt)
|
||||
.setRegisterAddress(
|
||||
userKeyPair.getPublicKey(),
|
||||
accountTypeToAddressType(this.self.accountType),
|
||||
uuid4ToHash(this.self.user.communityUser.uuid),
|
||||
this.tx.accountType,
|
||||
v.parse(uuid4ToHashSchema, this.account.userUuid),
|
||||
accountKeyPair.getPublicKey(),
|
||||
)
|
||||
.sign(communityKeyPair)
|
||||
|
||||
@ -2,76 +2,62 @@ import {
|
||||
AuthenticatedEncryption,
|
||||
EncryptedMemo,
|
||||
GradidoTransactionBuilder,
|
||||
GradidoUnit,
|
||||
TransferAmount,
|
||||
} from 'gradido-blockchain-js'
|
||||
|
||||
import { KeyPairIdentifier } from '@/data/KeyPairIdentifier'
|
||||
import { TransactionErrorType } from '@/graphql/enum/TransactionErrorType'
|
||||
import { TransactionDraft } from '@/graphql/input/TransactionDraft'
|
||||
import { UserIdentifier } from '@/graphql/input/UserIdentifier'
|
||||
import { TransactionError } from '@/graphql/model/TransactionError'
|
||||
import { uuid4ToHash } from '@/utils/typeConverter'
|
||||
|
||||
import { KeyPairIdentifierLogic } from '../../data/KeyPairIdentifier.logic'
|
||||
import { KeyPairCalculation } from '../keyPairCalculation/KeyPairCalculation.context'
|
||||
|
||||
import { AbstractTransactionRole } from './AbstractTransaction.role'
|
||||
import { TransferTransactionInput, transferTransactionSchema, TransferTransaction } from '../../schemas/transaction.schema'
|
||||
import * as v from 'valibot'
|
||||
import { uuid4ToTopicSchema } from '../../schemas/typeConverter.schema'
|
||||
|
||||
export class TransferTransactionRole extends AbstractTransactionRole {
|
||||
private linkedUser: UserIdentifier
|
||||
constructor(private self: TransactionDraft) {
|
||||
private tx: TransferTransaction
|
||||
constructor(input: TransferTransactionInput) {
|
||||
super()
|
||||
if (!this.self.linkedUser) {
|
||||
throw new TransactionError(
|
||||
TransactionErrorType.MISSING_PARAMETER,
|
||||
'transfer: linked user missing',
|
||||
)
|
||||
}
|
||||
this.linkedUser = this.self.linkedUser
|
||||
this.tx = v.parse(transferTransactionSchema, input)
|
||||
}
|
||||
|
||||
getSenderCommunityUuid(): string {
|
||||
return this.self.user.communityUuid
|
||||
return this.tx.user.communityUuid
|
||||
}
|
||||
|
||||
getRecipientCommunityUuid(): string {
|
||||
return this.linkedUser.communityUuid
|
||||
return this.tx.linkedUser.communityUuid
|
||||
}
|
||||
|
||||
public async getGradidoTransactionBuilder(): Promise<GradidoTransactionBuilder> {
|
||||
if (!this.self.amount) {
|
||||
throw new TransactionError(TransactionErrorType.MISSING_PARAMETER, 'transfer: amount missing')
|
||||
}
|
||||
if (!this.self.memo) {
|
||||
throw new TransactionError(
|
||||
TransactionErrorType.MISSING_PARAMETER,
|
||||
'deferred transfer: memo missing',
|
||||
)
|
||||
}
|
||||
const builder = new GradidoTransactionBuilder()
|
||||
const senderKeyPair = await KeyPairCalculation(new KeyPairIdentifier(this.self.user))
|
||||
const recipientKeyPair = await KeyPairCalculation(new KeyPairIdentifier(this.linkedUser))
|
||||
// sender + signer
|
||||
const senderKeyPair = await KeyPairCalculation(
|
||||
new KeyPairIdentifierLogic(this.tx.user)
|
||||
)
|
||||
// recipient
|
||||
const recipientKeyPair = await KeyPairCalculation(
|
||||
new KeyPairIdentifierLogic(this.tx.linkedUser)
|
||||
)
|
||||
|
||||
builder
|
||||
.setCreatedAt(new Date(this.self.createdAt))
|
||||
.setCreatedAt(new Date(this.tx.createdAt))
|
||||
.addMemo(
|
||||
new EncryptedMemo(
|
||||
this.self.memo,
|
||||
this.tx.memo,
|
||||
new AuthenticatedEncryption(senderKeyPair),
|
||||
new AuthenticatedEncryption(recipientKeyPair),
|
||||
),
|
||||
)
|
||||
.setTransactionTransfer(
|
||||
new TransferAmount(senderKeyPair.getPublicKey(), GradidoUnit.fromString(this.self.amount)),
|
||||
new TransferAmount(senderKeyPair.getPublicKey(), this.tx.amount),
|
||||
recipientKeyPair.getPublicKey(),
|
||||
)
|
||||
const senderCommunity = this.self.user.communityUuid
|
||||
const recipientCommunity = this.linkedUser.communityUuid
|
||||
const senderCommunity = this.tx.user.communityUuid
|
||||
const recipientCommunity = this.tx.linkedUser.communityUuid
|
||||
if (senderCommunity !== recipientCommunity) {
|
||||
// we have a cross group transaction
|
||||
builder
|
||||
.setSenderCommunity(uuid4ToHash(senderCommunity).convertToHex())
|
||||
.setRecipientCommunity(uuid4ToHash(recipientCommunity).convertToHex())
|
||||
.setSenderCommunity(v.parse(uuid4ToTopicSchema, senderCommunity))
|
||||
.setRecipientCommunity(v.parse(uuid4ToTopicSchema, recipientCommunity))
|
||||
}
|
||||
builder.sign(senderKeyPair)
|
||||
return builder
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
import util from 'util'
|
||||
|
||||
import { Timestamp, TimestampSeconds } from 'gradido-blockchain-js'
|
||||
|
||||
export abstract class AbstractLoggingView {
|
||||
protected bufferStringFormat: BufferEncoding = 'hex'
|
||||
|
||||
// This function gets called automatically when JSON.stringify() is called on this class instance
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public abstract toJSON(): any
|
||||
public toString(): string {
|
||||
return JSON.stringify(this.toJSON(), null, 2)
|
||||
}
|
||||
|
||||
// called form console.log or log4js logging functions
|
||||
[util.inspect.custom](): string {
|
||||
return this.toString()
|
||||
}
|
||||
|
||||
protected dateToString(date: Date | undefined | null): string | undefined {
|
||||
if (date) {
|
||||
return date.toISOString()
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
protected timestampSecondsToDateString(timestamp: TimestampSeconds): string | undefined {
|
||||
if (timestamp && timestamp.getSeconds()) {
|
||||
return timestamp.getDate().toISOString()
|
||||
}
|
||||
}
|
||||
|
||||
protected timestampToDateString(timestamp: Timestamp): string | undefined {
|
||||
if (timestamp && (timestamp.getSeconds() || timestamp.getNanos())) {
|
||||
return timestamp.getDate().toISOString()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
import { CommunityUser } from '@/graphql/input/CommunityUser'
|
||||
|
||||
import { AbstractLoggingView } from './AbstractLogging.view'
|
||||
|
||||
export class CommunityUserLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: CommunityUser) {
|
||||
super()
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public toJSON(): any {
|
||||
return {
|
||||
uuid: this.self.uuid,
|
||||
accountNr: this.self.accountNr,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
import { IdentifierSeed } from '@/graphql/input/IdentifierSeed'
|
||||
|
||||
import { AbstractLoggingView } from './AbstractLogging.view'
|
||||
|
||||
export class IdentifierSeedLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: IdentifierSeed) {
|
||||
super()
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public toJSON(): any {
|
||||
return {
|
||||
seed: this.self.seed,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
import { InputTransactionType } from '@/graphql/enum/InputTransactionType'
|
||||
import { TransactionDraft } from '@/graphql/input/TransactionDraft'
|
||||
import { UserIdentifier } from '@/graphql/input/UserIdentifier'
|
||||
import { getEnumValue } from '@/utils/typeConverter'
|
||||
|
||||
import { AbstractLoggingView } from './AbstractLogging.view'
|
||||
import { UserIdentifierLoggingView } from './UserIdentifierLogging.view'
|
||||
|
||||
export class TransactionDraftLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: TransactionDraft) {
|
||||
super()
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public toJSON(): any {
|
||||
return {
|
||||
user: new UserIdentifierLoggingView(this.self.user).toJSON(),
|
||||
linkedUser:
|
||||
this.self.linkedUser instanceof UserIdentifier
|
||||
? new UserIdentifierLoggingView(this.self.linkedUser).toJSON()
|
||||
: 'seed',
|
||||
amount: Number(this.self.amount),
|
||||
type: getEnumValue(InputTransactionType, this.self.type),
|
||||
createdAt: this.self.createdAt,
|
||||
targetDate: this.self.targetDate,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
import { UserIdentifier } from '@/graphql/input/UserIdentifier'
|
||||
|
||||
import { AbstractLoggingView } from './AbstractLogging.view'
|
||||
import { CommunityUserLoggingView } from './CommunityUserLogging.view'
|
||||
import { IdentifierSeedLoggingView } from './IdentifierSeedLogging.view'
|
||||
|
||||
export class UserIdentifierLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: UserIdentifier) {
|
||||
super()
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public toJSON(): any {
|
||||
return {
|
||||
communityUuid: this.self.communityUuid,
|
||||
communityUser: this.self.communityUser
|
||||
? new CommunityUserLoggingView(this.self.communityUser).toJSON()
|
||||
: undefined,
|
||||
seed: this.self.seed ? new IdentifierSeedLoggingView(this.self.seed).toJSON() : undefined,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
import { readFileSync } from 'fs'
|
||||
|
||||
import log4js from 'log4js'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
|
||||
const options = JSON.parse(readFileSync(CONFIG.LOG4JS_CONFIG, 'utf-8'))
|
||||
|
||||
log4js.configure(options)
|
||||
|
||||
const logger = log4js.getLogger('dlt')
|
||||
|
||||
export { logger }
|
||||
40
dlt-connector/src/schemas/account.schema.ts
Normal file
40
dlt-connector/src/schemas/account.schema.ts
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
import * as v from 'valibot'
|
||||
import { uuidv4Schema } from './typeConverter.schema'
|
||||
|
||||
// use code from transaction links
|
||||
export const identifierSeedSchema = v.object({
|
||||
seed: v.pipe(
|
||||
v.string('expect string type'),
|
||||
v.length(24, 'expect seed length 24')
|
||||
)
|
||||
})
|
||||
|
||||
export type IdentifierSeed = v.InferOutput<typeof identifierSeedSchema>
|
||||
|
||||
// identifier for gradido community accounts, inside a community
|
||||
export const identifierCommunityAccountSchema = v.object({
|
||||
userUuid: uuidv4Schema,
|
||||
accountNr: v.nullish(v.number('expect number type'), 0),
|
||||
})
|
||||
|
||||
export type IdentifierCommunityAccount = v.InferOutput<typeof identifierCommunityAccountSchema>
|
||||
|
||||
// identifier for gradido account, including the community uuid
|
||||
export const identifierAccountSchema = v.pipe(
|
||||
v.object({
|
||||
communityUuid: uuidv4Schema,
|
||||
account: v.nullish(identifierCommunityAccountSchema, undefined),
|
||||
seed: v.nullish(identifierSeedSchema, undefined),
|
||||
}),
|
||||
v.custom((value: any) => {
|
||||
const setFieldsCount = Number(value.seed !== undefined) + Number(value.account !== undefined)
|
||||
if (setFieldsCount !== 1) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 'expect seed or account')
|
||||
)
|
||||
|
||||
export type IdentifierAccountInput = v.InferInput<typeof identifierAccountSchema>
|
||||
export type IdentifierAccount = v.InferOutput<typeof identifierAccountSchema>
|
||||
21
dlt-connector/src/schemas/rpcParameter.schema.test.ts
Normal file
21
dlt-connector/src/schemas/rpcParameter.schema.test.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { communitySchema } from './rpcParameter.schema'
|
||||
import { uuidv4Schema } from './typeGuard.schema'
|
||||
import * as v from 'valibot'
|
||||
// only for IDE, bun don't need this to work
|
||||
import { describe, expect, it } from 'bun:test'
|
||||
|
||||
describe('rpcParameter.schema', () => {
|
||||
it('community', () => {
|
||||
expect(v.parse(communitySchema, {
|
||||
uuid: '4f28e081-5c39-4dde-b6a4-3bde71de8d65',
|
||||
foreign: false,
|
||||
createdAt: '2021-01-01',
|
||||
})).toEqual(
|
||||
{
|
||||
uuid: v.parse(uuidv4Schema, '4f28e081-5c39-4dde-b6a4-3bde71de8d65'),
|
||||
foreign: false,
|
||||
createdAt: new Date('2021-01-01'),
|
||||
},
|
||||
)
|
||||
})
|
||||
})
|
||||
19
dlt-connector/src/schemas/rpcParameter.schema.ts
Normal file
19
dlt-connector/src/schemas/rpcParameter.schema.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import * as v from 'valibot'
|
||||
import { uuidv4Schema } from './typeGuard.schema'
|
||||
import { dateSchema } from './typeConverter.schema'
|
||||
|
||||
/**
|
||||
* Schema Definitions for rpc call parameter, when dlt-connector is called from backend
|
||||
*/
|
||||
|
||||
/**
|
||||
* Schema for community, for creating new CommunityRoot Transaction on gradido blockchain
|
||||
*/
|
||||
export const communitySchema = v.object({
|
||||
uuid: uuidv4Schema,
|
||||
foreign: v.boolean('expect boolean type'),
|
||||
createdAt: dateSchema,
|
||||
})
|
||||
|
||||
export type CommunityInput = v.InferInput<typeof communitySchema>
|
||||
export type Community = v.InferOutput<typeof communitySchema>
|
||||
207
dlt-connector/src/schemas/transaction.schema.test.ts
Normal file
207
dlt-connector/src/schemas/transaction.schema.test.ts
Normal file
@ -0,0 +1,207 @@
|
||||
import { describe, it, expect } from 'bun:test'
|
||||
import { transactionIdentifierSchema, transactionSchema, TransactionInput, memoSchema } from './transaction.schema'
|
||||
import { InputTransactionType } from '../enum/InputTransactionType'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import * as v from 'valibot'
|
||||
import { GradidoUnit, DurationSeconds } from 'gradido-blockchain-js'
|
||||
import { randomBytes } from 'crypto'
|
||||
|
||||
const transactionLinkCode = (date: Date): string => {
|
||||
const time = date.getTime().toString(16)
|
||||
return (
|
||||
randomBytes(12)
|
||||
.toString('hex')
|
||||
.substring(0, 24 - time.length) + time
|
||||
)
|
||||
}
|
||||
|
||||
describe('transaction schemas', () => {
|
||||
|
||||
describe('transactionIdentifierSchema ', () => {
|
||||
it('valid, transaction identified by transactionNr and topic', () => {
|
||||
expect(v.parse(transactionIdentifierSchema, {
|
||||
transactionNr: 1,
|
||||
iotaTopic: 'c00b210fc0a189df054eb9dafb584c527e9aeb537a62a35d44667f54529c73f5'
|
||||
})).toEqual({
|
||||
transactionNr: 1,
|
||||
iotaMessageId: undefined,
|
||||
iotaTopic: 'c00b210fc0a189df054eb9dafb584c527e9aeb537a62a35d44667f54529c73f5'
|
||||
})
|
||||
})
|
||||
it('valid, transaction identified by iotaMessageId and topic', () => {
|
||||
expect(v.parse(transactionIdentifierSchema, {
|
||||
iotaMessageId: '1b33a3cf7eb5dde04ed7ae571db1763006811ff6b7bb35b3d1c780de153af9dd',
|
||||
iotaTopic: 'c00b210fc0a189df054eb9dafb584c527e9aeb537a62a35d44667f54529c73f5'
|
||||
})).toEqual({
|
||||
transactionNr: 0,
|
||||
iotaMessageId: '1b33a3cf7eb5dde04ed7ae571db1763006811ff6b7bb35b3d1c780de153af9dd',
|
||||
iotaTopic: 'c00b210fc0a189df054eb9dafb584c527e9aeb537a62a35d44667f54529c73f5'
|
||||
})
|
||||
})
|
||||
it('invalid, missing topic', () => {
|
||||
expect(() => v.parse(transactionIdentifierSchema, {
|
||||
transactionNr: 1,
|
||||
iotaMessageId: '1b33a3cf7eb5dde04ed7ae571db1763006811ff6b7bb35b3d1c780de153af9dd',
|
||||
})).toThrowError(new Error('Invalid key: Expected "iotaTopic" but received undefined'))
|
||||
})
|
||||
it('invalid, transactionNr and iotaMessageId set', () => {
|
||||
expect(() => v.parse(transactionIdentifierSchema, {
|
||||
transactionNr: 1,
|
||||
iotaMessageId: '1b33a3cf7eb5dde04ed7ae571db1763006811ff6b7bb35b3d1c780de153af9dd',
|
||||
iotaTopic: 'c00b210fc0a189df054eb9dafb584c527e9aeb537a62a35d44667f54529c73f5'
|
||||
})).toThrowError(new Error('expect transactionNr or iotaMessageId not both'))
|
||||
})
|
||||
})
|
||||
|
||||
describe('transactionSchema', () => {
|
||||
it('valid, register new user address', () => {
|
||||
const registerAddress: TransactionInput = {
|
||||
user: {
|
||||
communityUuid: uuidv4(),
|
||||
account: {
|
||||
userUuid: uuidv4(),
|
||||
}
|
||||
},
|
||||
type: InputTransactionType.REGISTER_ADDRESS,
|
||||
createdAt: '2022-01-01T00:00:00.000Z',
|
||||
}
|
||||
expect(v.parse(transactionSchema, registerAddress)).toEqual({
|
||||
user: {
|
||||
communityUuid: registerAddress.user.communityUuid,
|
||||
account: {
|
||||
userUuid: registerAddress.user.account!.userUuid,
|
||||
accountNr: 1,
|
||||
}
|
||||
},
|
||||
type: registerAddress.type,
|
||||
createdAt: new Date(registerAddress.createdAt),
|
||||
})
|
||||
})
|
||||
it('valid, gradido transfer', () => {
|
||||
const communityUuid = uuidv4()
|
||||
const gradidoTransfer: TransactionInput = {
|
||||
user: {
|
||||
communityUuid,
|
||||
account: {
|
||||
userUuid: uuidv4(),
|
||||
}
|
||||
},
|
||||
linkedUser: {
|
||||
communityUuid,
|
||||
account: {
|
||||
userUuid: uuidv4(),
|
||||
}
|
||||
},
|
||||
amount: '100',
|
||||
memo: 'TestMemo',
|
||||
type: InputTransactionType.GRADIDO_TRANSFER,
|
||||
createdAt: '2022-01-01T00:00:00.000Z',
|
||||
}
|
||||
expect(v.parse(transactionSchema, gradidoTransfer)).toEqual({
|
||||
user: {
|
||||
communityUuid,
|
||||
account: {
|
||||
userUuid: gradidoTransfer.user.account!.userUuid,
|
||||
accountNr: 1,
|
||||
}
|
||||
},
|
||||
linkedUser: {
|
||||
communityUuid,
|
||||
account: {
|
||||
userUuid: gradidoTransfer.linkedUser!.account!.userUuid,
|
||||
accountNr: 1,
|
||||
}
|
||||
},
|
||||
amount: GradidoUnit.fromString(gradidoTransfer.amount!),
|
||||
memo: gradidoTransfer.memo,
|
||||
type: gradidoTransfer.type,
|
||||
createdAt: new Date(gradidoTransfer.createdAt),
|
||||
})
|
||||
})
|
||||
|
||||
it('valid, gradido creation', () => {
|
||||
const communityUuid = uuidv4()
|
||||
const gradidoCreation: TransactionInput = {
|
||||
user: {
|
||||
communityUuid,
|
||||
account: {
|
||||
userUuid: uuidv4(),
|
||||
}
|
||||
},
|
||||
linkedUser: {
|
||||
communityUuid,
|
||||
account: {
|
||||
userUuid: uuidv4(),
|
||||
}
|
||||
},
|
||||
amount: '1000',
|
||||
memo: 'For your help',
|
||||
type: InputTransactionType.GRADIDO_CREATION,
|
||||
createdAt: '2022-01-01T00:00:00.000Z',
|
||||
targetDate: '2021-11-01T10:00'
|
||||
}
|
||||
expect(v.parse(transactionSchema, gradidoCreation)).toEqual({
|
||||
user: {
|
||||
communityUuid,
|
||||
account: {
|
||||
userUuid: gradidoCreation.user.account!.userUuid,
|
||||
accountNr: 1,
|
||||
}
|
||||
},
|
||||
linkedUser: {
|
||||
communityUuid,
|
||||
account: {
|
||||
userUuid: gradidoCreation.linkedUser!.account!.userUuid,
|
||||
accountNr: 1,
|
||||
}
|
||||
},
|
||||
amount: GradidoUnit.fromString(gradidoCreation.amount!),
|
||||
memo: gradidoCreation.memo,
|
||||
type: gradidoCreation.type,
|
||||
createdAt: new Date(gradidoCreation.createdAt),
|
||||
targetDate: new Date(gradidoCreation.targetDate!),
|
||||
})
|
||||
})
|
||||
it('valid, gradido transaction link / deferred transfer', () => {
|
||||
const gradidoTransactionLink: TransactionInput = {
|
||||
user: {
|
||||
communityUuid: uuidv4(),
|
||||
account: {
|
||||
userUuid: uuidv4(),
|
||||
}
|
||||
},
|
||||
linkedUser: {
|
||||
communityUuid: uuidv4(),
|
||||
seed: {
|
||||
seed: transactionLinkCode(new Date()),
|
||||
}
|
||||
},
|
||||
amount: '100',
|
||||
memo: 'use link wisely',
|
||||
type: InputTransactionType.GRADIDO_DEFERRED_TRANSFER,
|
||||
createdAt: '2022-01-01T00:00:00.000Z',
|
||||
timeoutDuration: 60*60*24*30,
|
||||
}
|
||||
expect(v.parse(transactionSchema, gradidoTransactionLink)).toEqual({
|
||||
user: {
|
||||
communityUuid: gradidoTransactionLink.user.communityUuid,
|
||||
account: {
|
||||
userUuid: gradidoTransactionLink.user.account!.userUuid,
|
||||
accountNr: 1,
|
||||
}
|
||||
},
|
||||
linkedUser: {
|
||||
communityUuid: gradidoTransactionLink.linkedUser!.communityUuid,
|
||||
seed: {
|
||||
seed: gradidoTransactionLink.linkedUser!.seed!.seed,
|
||||
}
|
||||
},
|
||||
amount: GradidoUnit.fromString(gradidoTransactionLink.amount!),
|
||||
memo: gradidoTransactionLink.memo,
|
||||
type: gradidoTransactionLink.type,
|
||||
createdAt: new Date(gradidoTransactionLink.createdAt),
|
||||
timeoutDuration: new DurationSeconds(gradidoTransactionLink.timeoutDuration!),
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
87
dlt-connector/src/schemas/transaction.schema.ts
Normal file
87
dlt-connector/src/schemas/transaction.schema.ts
Normal file
@ -0,0 +1,87 @@
|
||||
import * as v from 'valibot'
|
||||
import { dateFromStringSchema } from './typeConverter.schema'
|
||||
import { identifierAccountSchema } from './account.schema'
|
||||
import { InputTransactionType } from '../enum/InputTransactionType'
|
||||
import { accountTypeToAddressTypeSchema } from './typeConverter.schema'
|
||||
|
||||
// allow TransactionIdentifier to only contain either transactionNr or iotaMessageId
|
||||
export const transactionIdentifierSchema = v.pipe(
|
||||
v.object({
|
||||
transactionNr: v.nullish(
|
||||
v.pipe(v.number('expect number type'), v.minValue(0, 'expect number >= 0')),
|
||||
0
|
||||
),
|
||||
iotaMessageId: v.nullish(iotaMessageIdSchema, undefined),
|
||||
communityId: uuid4ToTopicSchema,
|
||||
}),
|
||||
v.custom((value: any) => {
|
||||
const setFieldsCount = Number(value.transactionNr !== 0) + Number(value.iotaMessageId !== undefined)
|
||||
if (setFieldsCount !== 1) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 'expect transactionNr or iotaMessageId not both')
|
||||
)
|
||||
export type TransactionIdentifierInput = v.InferInput<typeof transactionIdentifierSchema>
|
||||
export type TransactionIdentifier = v.InferOutput<typeof transactionIdentifierSchema>
|
||||
|
||||
export const transactionSchema = v.object({
|
||||
user: identifierAccountSchema,
|
||||
linkedUser: v.nullish(identifierAccountSchema, undefined),
|
||||
amount: v.nullish(amountToGradidoUnitSchema, undefined),
|
||||
memo: v.nullish(memoSchema, undefined),
|
||||
type: v.enum(InputTransactionType),
|
||||
createdAt: dateFromStringSchema,
|
||||
targetDate: v.nullish(dateFromStringSchema, undefined),
|
||||
timeoutDuration: v.nullish(timeoutDurationSchema, undefined),
|
||||
accountType: v.nullish(accountTypeToAddressTypeSchema, undefined),
|
||||
})
|
||||
|
||||
export type TransactionInput = v.InferInput<typeof transactionSchema>
|
||||
export type Transaction = v.InferOutput<typeof transactionSchema>
|
||||
|
||||
export const creationTransactionSchema = v.object({
|
||||
user: identifierAccountSchema,
|
||||
linkedUser: identifierAccountSchema,
|
||||
amount: amountToGradidoUnitSchema,
|
||||
memo: memoSchema,
|
||||
createdAt: dateFromStringSchema,
|
||||
targetDate: dateFromStringSchema,
|
||||
})
|
||||
|
||||
export type CreationTransactionInput = v.InferInput<typeof creationTransactionSchema>
|
||||
export type CreationTransaction = v.InferOutput<typeof creationTransactionSchema>
|
||||
|
||||
export const transferTransactionSchema = v.object({
|
||||
user: identifierAccountSchema,
|
||||
linkedUser: identifierAccountSchema,
|
||||
amount: amountToGradidoUnitSchema,
|
||||
memo: memoSchema,
|
||||
createdAt: dateFromStringSchema,
|
||||
})
|
||||
|
||||
export type TransferTransactionInput = v.InferInput<typeof transferTransactionSchema>
|
||||
export type TransferTransaction = v.InferOutput<typeof transferTransactionSchema>
|
||||
|
||||
// linked user is later needed for move account transaction
|
||||
export const registerAddressTransactionSchema = v.object({
|
||||
user: identifierAccountSchema,
|
||||
createdAt: dateFromStringSchema,
|
||||
accountType: accountTypeToAddressTypeSchema,
|
||||
})
|
||||
|
||||
export type RegisterAddressTransactionInput = v.InferInput<typeof registerAddressTransactionSchema>
|
||||
export type RegisterAddressTransaction = v.InferOutput<typeof registerAddressTransactionSchema>
|
||||
|
||||
|
||||
export const deferredTransferTransactionSchema = v.object({
|
||||
user: identifierAccountSchema,
|
||||
linkedUser: identifierAccountSchema,
|
||||
amount: amountToGradidoUnitSchema,
|
||||
memo: memoSchema,
|
||||
createdAt: dateFromStringSchema,
|
||||
timeoutDuration: timeoutDurationSchema,
|
||||
})
|
||||
|
||||
export type DeferredTransferTransactionInput = v.InferInput<typeof deferredTransferTransactionSchema>
|
||||
export type DeferredTransferTransaction = v.InferOutput<typeof deferredTransferTransactionSchema>
|
||||
51
dlt-connector/src/schemas/typeConverter.schema.test.ts
Normal file
51
dlt-connector/src/schemas/typeConverter.schema.test.ts
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
import { accountTypeSchema, addressTypeSchema, confirmedTransactionFromBase64Schema } from './typeConverter.schema'
|
||||
import * as v from 'valibot'
|
||||
// only for IDE, bun don't need this to work
|
||||
import { describe, expect, it } from 'bun:test'
|
||||
import { dateSchema } from './typeConverter.schema'
|
||||
import { AddressType_COMMUNITY_AUF } from 'gradido-blockchain-js'
|
||||
import { AccountType } from '../enum/AccountType'
|
||||
|
||||
describe('basic.schema', () => {
|
||||
|
||||
describe('date', () => {
|
||||
it('from string', () => {
|
||||
const date = v.parse(dateSchema, '2021-01-01:10:10')
|
||||
expect(date.toISOString()).toBe('2021-01-01T10:10:00.000Z')
|
||||
})
|
||||
it('from Date', () => {
|
||||
const date = v.parse(dateSchema, new Date('2021-01-01'))
|
||||
expect(date.toISOString()).toBe('2021-01-01T00:00:00.000Z')
|
||||
})
|
||||
it('invalid date', () => {
|
||||
expect(() => v.parse(dateSchema, 'invalid date')).toThrow(new Error('invalid date'))
|
||||
})
|
||||
})
|
||||
|
||||
describe('AddressType and AccountType', () => {
|
||||
it('AddressType from AddressType', () => {
|
||||
const addressType = v.parse(addressTypeSchema, AddressType_COMMUNITY_AUF)
|
||||
expect(addressType).toBe(AddressType_COMMUNITY_AUF)
|
||||
})
|
||||
it('AddressType from AccountType', () => {
|
||||
const accountType = v.parse(addressTypeSchema, AccountType.COMMUNITY_AUF)
|
||||
expect(accountType).toBe(AddressType_COMMUNITY_AUF)
|
||||
})
|
||||
it('AccountType from AccountType', () => {
|
||||
const accountType = v.parse(accountTypeSchema, AccountType.COMMUNITY_AUF)
|
||||
expect(accountType).toBe(AccountType.COMMUNITY_AUF)
|
||||
})
|
||||
it('AccountType from AddressType', () => {
|
||||
const accountType = v.parse(accountTypeSchema, AddressType_COMMUNITY_AUF)
|
||||
expect(accountType).toBe(AccountType.COMMUNITY_AUF)
|
||||
})
|
||||
})
|
||||
|
||||
it('confirmedTransactionFromBase64Schema', () => {
|
||||
const confirmedTransaction = v.parse(confirmedTransactionFromBase64Schema, 'CAcSAgoAGgYIwvK5/wUiAzMuNCogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')
|
||||
expect(confirmedTransaction.getId()).toBe(7)
|
||||
expect(confirmedTransaction.getConfirmedAt().getSeconds()).toBe(1609464130)
|
||||
expect(confirmedTransaction.getVersionNumber()).toBe('3.4')
|
||||
})
|
||||
})
|
||||
125
dlt-connector/src/schemas/typeConverter.schema.ts
Normal file
125
dlt-connector/src/schemas/typeConverter.schema.ts
Normal file
@ -0,0 +1,125 @@
|
||||
import {
|
||||
AddressType as AddressType,
|
||||
AddressType_COMMUNITY_AUF,
|
||||
AddressType_COMMUNITY_GMW,
|
||||
AddressType_COMMUNITY_HUMAN,
|
||||
AddressType_COMMUNITY_PROJECT,
|
||||
AddressType_CRYPTO_ACCOUNT,
|
||||
AddressType_NONE,
|
||||
AddressType_SUBACCOUNT,
|
||||
ConfirmedTransaction,
|
||||
DeserializeType_CONFIRMED_TRANSACTION,
|
||||
InteractionDeserialize,
|
||||
MemoryBlock,
|
||||
} from 'gradido-blockchain-js'
|
||||
import { AccountType } from '../enum/AccountType'
|
||||
// import { AddressType as AddressTypeWrapper } from '../enum/AddressType'
|
||||
import * as v from 'valibot'
|
||||
|
||||
/**
|
||||
* dateSchema for creating a date from string or Date object
|
||||
*/
|
||||
export const dateSchema = v.pipe(
|
||||
v.union([
|
||||
v.string('expect valid date string'),
|
||||
v.instance(Date, 'expect Date object')
|
||||
]),
|
||||
v.transform<string | Date, Date>((input) => {
|
||||
let date: Date
|
||||
if (input instanceof Date) {
|
||||
date = input
|
||||
} else {
|
||||
date = new Date(input)
|
||||
}
|
||||
if (isNaN(date.getTime())) {
|
||||
throw new Error('invalid date')
|
||||
}
|
||||
return date
|
||||
})
|
||||
)
|
||||
|
||||
/**
|
||||
* AddressType is defined in gradido-blockchain C++ Code
|
||||
* AccountType is the enum defined in TypeScript but with the same options
|
||||
* addressTypeSchema and accountTypeSchema are for easy handling and conversion between both
|
||||
*/
|
||||
|
||||
const accountToAddressMap: Record<AccountType, AddressType> = {
|
||||
[AccountType.COMMUNITY_AUF]: AddressType_COMMUNITY_AUF,
|
||||
[AccountType.COMMUNITY_GMW]: AddressType_COMMUNITY_GMW,
|
||||
[AccountType.COMMUNITY_HUMAN]: AddressType_COMMUNITY_HUMAN,
|
||||
[AccountType.COMMUNITY_PROJECT]: AddressType_COMMUNITY_PROJECT,
|
||||
[AccountType.CRYPTO_ACCOUNT]: AddressType_CRYPTO_ACCOUNT,
|
||||
[AccountType.SUBACCOUNT]: AddressType_SUBACCOUNT,
|
||||
[AccountType.NONE]: AddressType_NONE,
|
||||
}
|
||||
|
||||
const addressToAccountMap: Record<AddressType, AccountType> = Object.entries(accountToAddressMap).reduce((acc, [accKey, addrVal]) => {
|
||||
acc[addrVal] = String(accKey) as AccountType
|
||||
return acc;
|
||||
}, {} as Record<AddressType, AccountType>)
|
||||
|
||||
function isAddressType(val: unknown): val is AddressType {
|
||||
return typeof val === 'number' && Object.keys(addressToAccountMap).includes(val.toString())
|
||||
}
|
||||
|
||||
function isAccountType(val: unknown): val is AccountType {
|
||||
return Object.values(AccountType).includes(val as AccountType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schema for address type, can also convert from account type (if used with v.parse)
|
||||
*/
|
||||
export const addressTypeSchema = v.pipe(
|
||||
v.union([
|
||||
v.enum(AccountType, 'expect account type'),
|
||||
v.custom<AddressType>((val): val is AddressType => isAddressType(val), 'expect AddressType'),
|
||||
]),
|
||||
v.transform<AccountType | AddressType, AddressType>((value) => {
|
||||
if (isAddressType(value)) {
|
||||
return value;
|
||||
}
|
||||
return accountToAddressMap[value as AccountType] ?? AddressType_NONE
|
||||
}),
|
||||
)
|
||||
|
||||
/**
|
||||
* Schema for account type, can also convert from address type (if used with v.parse)
|
||||
*/
|
||||
export const accountTypeSchema = v.pipe(
|
||||
v.union([
|
||||
v.custom<AddressType>(isAddressType, 'expect AddressType'),
|
||||
v.enum(AccountType, 'expect AccountType'),
|
||||
]),
|
||||
v.transform<AddressType | AccountType, AccountType>((value) => {
|
||||
if (isAccountType(value)) {
|
||||
return value;
|
||||
}
|
||||
return addressToAccountMap[value as AddressType] ?? AccountType.NONE;
|
||||
}),
|
||||
)
|
||||
|
||||
const confirmedTransactionFromBase64 = (base64: string): ConfirmedTransaction => {
|
||||
const deserializer = new InteractionDeserialize(
|
||||
MemoryBlock.fromBase64(base64),
|
||||
DeserializeType_CONFIRMED_TRANSACTION,
|
||||
)
|
||||
deserializer.run()
|
||||
const confirmedTransaction = deserializer.getConfirmedTransaction()
|
||||
if (!confirmedTransaction) {
|
||||
throw new Error("invalid data, couldn't deserialize")
|
||||
}
|
||||
return confirmedTransaction
|
||||
}
|
||||
|
||||
export const confirmedTransactionFromBase64Schema = v.pipe(
|
||||
v.pipe(
|
||||
v.string('expect confirmed Transaction base64 as string type'),
|
||||
v.base64('expect to be valid base64')
|
||||
),
|
||||
v.transform<string, ConfirmedTransaction>(
|
||||
(base64: string) => confirmedTransactionFromBase64(base64),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
67
dlt-connector/src/schemas/typeGuard.schema.test.ts
Normal file
67
dlt-connector/src/schemas/typeGuard.schema.test.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import { describe, it, expect } from 'bun:test'
|
||||
import { uuidv4Schema, topicIndexSchema, uuid4HashSchema, memoSchema } from './typeGuard.schema'
|
||||
import * as v from 'valibot'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { MemoryBlock } from 'gradido-blockchain-js'
|
||||
|
||||
describe('typeGuard.schema', () => {
|
||||
describe('Uuidv4', () => {
|
||||
const uuidv4String = uuidv4()
|
||||
const uuidv4Hash = MemoryBlock.fromHex(uuidv4String.replace(/-/g, '')).calculateHash()
|
||||
|
||||
it('from string to uuidv4', () => {
|
||||
const uuidv4Value = v.parse(uuidv4Schema, uuidv4String)
|
||||
expect(uuidv4Value.toString()).toBe(uuidv4String)
|
||||
})
|
||||
|
||||
it('from uuidv4 to hash', () => {
|
||||
const uuidv4Value = v.parse(uuidv4Schema, uuidv4String)
|
||||
const uuidv4HashParsed = v.parse(uuid4HashSchema, uuidv4Value)
|
||||
expect(uuidv4HashParsed.copyAsString()).toBe(uuidv4Hash.copyAsString())
|
||||
})
|
||||
|
||||
it('from uuidv4 string to hash', () => {
|
||||
const uuidv4HashParsed = v.parse(uuid4HashSchema, uuidv4String)
|
||||
expect(uuidv4HashParsed.copyAsString()).toBe(uuidv4Hash.copyAsString())
|
||||
})
|
||||
|
||||
it('from uuidv4 hash to topicIndex (hash in hex format', () => {
|
||||
const uuidv4HashParsed = v.parse(uuid4HashSchema, uuidv4String)
|
||||
const topicIndex = v.parse(topicIndexSchema, uuidv4HashParsed)
|
||||
expect(topicIndex.toString()).toBe(uuidv4Hash.convertToHex())
|
||||
})
|
||||
|
||||
it('from uuidv4 to topicIndex (hash in hex format)', () => {
|
||||
const uuidv4Value = v.parse(uuidv4Schema, uuidv4String)
|
||||
const topicIndex = v.parse(topicIndexSchema, uuidv4Value)
|
||||
expect(topicIndex.toString()).toBe(uuidv4Hash.convertToHex())
|
||||
})
|
||||
|
||||
it('from uuidv4 string to topicIndex (hash in hex format)', () => {
|
||||
const topicIndex = v.parse(topicIndexSchema, uuidv4String)
|
||||
expect(topicIndex.toString()).toBe(uuidv4Hash.convertToHex())
|
||||
})
|
||||
})
|
||||
describe('Basic Type Schemas for transactions', () => {
|
||||
describe('Memo', () => {
|
||||
it('min length', () => {
|
||||
const memoValue = 'memo1'
|
||||
const memoValueParsed = v.parse(memoSchema, memoValue)
|
||||
expect(memoValueParsed.toString()).toBe(memoValue)
|
||||
})
|
||||
it('max length', () => {
|
||||
const memoValue = 's'.repeat(255)
|
||||
const memoValueParsed = v.parse(memoSchema, memoValue)
|
||||
expect(memoValueParsed.toString()).toBe(memoValue)
|
||||
})
|
||||
it('to short', () => {
|
||||
const memoValue = 'memo'
|
||||
expect(() => v.parse(memoSchema, memoValue)).toThrow(new Error('expect string length >= 5'))
|
||||
})
|
||||
it('to long', () => {
|
||||
const memoValue = 's'.repeat(256)
|
||||
expect(() => v.parse(memoSchema, memoValue)).toThrow(new Error('expect string length <= 255'))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
146
dlt-connector/src/schemas/typeGuard.schema.ts
Normal file
146
dlt-connector/src/schemas/typeGuard.schema.ts
Normal file
@ -0,0 +1,146 @@
|
||||
/**
|
||||
* # TypeGuards
|
||||
* Expand TypeScript Default Types with custom type which a based on a default type (or class)
|
||||
* Use valibot, so we can describe the type and validate it easy at runtime
|
||||
* After transpiling TypeScript unique symbol are gone
|
||||
* Infos at opaque type in typescript: https://evertpot.com/opaque-ts-types/
|
||||
*
|
||||
* declare const validAmount: unique symbol
|
||||
* export type Amount = number & { [validAmount]: true };
|
||||
* Can be compared with using `typedef int Amount;` in C/C++
|
||||
* Example:
|
||||
* To create a instance of Amount:
|
||||
* `const amount: Amount = v.parse(amountSchema, 1.21)`
|
||||
* must be called and ensure the value is valid
|
||||
* If it isn't valid, v.parse will throw an error
|
||||
*/
|
||||
|
||||
import { validate, version } from 'uuid'
|
||||
import * as v from 'valibot'
|
||||
import { MemoryBlock, DurationSeconds, GradidoUnit } from 'gradido-blockchain-js'
|
||||
|
||||
/**
|
||||
* type guard for uuid v4
|
||||
* create with `v.parse(uuidv4Schema, 'uuid')`
|
||||
* uuidv4 is used for communityUuid and userUuid
|
||||
*/
|
||||
declare const validUuidv4: unique symbol
|
||||
export type Uuidv4 = string & { [validUuidv4]: true };
|
||||
|
||||
export const uuidv4Schema = v.custom<Uuidv4>((value) =>
|
||||
(typeof value === 'string' && validate(value) && version(value) === 4),
|
||||
'uuid v4 expected'
|
||||
)
|
||||
|
||||
/**
|
||||
* type guard for uuid v4 hash
|
||||
* const uuidv4Value: Uuidv4 = v.parse(uuidv4Schema, 'uuid')
|
||||
* create with `v.parse(uuidv4HashSchema, uuidv4Value)`
|
||||
* uuidv4Hash is uuidv4 value hashed with BLAKE2b as Binary Type MemoryBlock from gradido-blockchain similar to Node.js Buffer Type,
|
||||
* used for iota topic
|
||||
*/
|
||||
declare const validUuidv4Hash: unique symbol
|
||||
export type Uuidv4Hash = MemoryBlock & { [validUuidv4Hash]: true };
|
||||
|
||||
export const uuid4HashSchema = v.pipe(
|
||||
uuidv4Schema,
|
||||
v.transform<Uuidv4, Uuidv4Hash>(
|
||||
(input: Uuidv4) => MemoryBlock.fromHex(input.replace(/-/g, '')).calculateHash() as Uuidv4Hash,
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* type guard for topic index
|
||||
* const uuidv4Value: Uuidv4 = v.parse(uuidv4Schema, 'uuid')
|
||||
* const uuidv4Hash: Uuidv4Hash = v.parse(uuid4HashSchema, uuidv4Value)
|
||||
* create with `v.parse(topicIndexSchema, uuidv4Hash)`
|
||||
* topicIndex is uuidv4Hash value converted to hex string used for iota topic
|
||||
* The beauty of valibot allow also parse a uuidv4 string directly to topicIndex
|
||||
* const topic: TopicIndex = v.parse(topicIndexSchema, 'uuid')
|
||||
*/
|
||||
declare const validTopicIndex: unique symbol
|
||||
export type TopicIndex = string & { [validTopicIndex]: true };
|
||||
|
||||
export const topicIndexSchema = v.pipe(
|
||||
v.union([uuidv4Schema, v.custom((val): val is Uuidv4Hash => val instanceof MemoryBlock)]),
|
||||
v.transform<any, TopicIndex>((input) => {
|
||||
const hash = typeof input === 'string'
|
||||
? MemoryBlock.fromHex(input.replace(/-/g, '')).calculateHash()
|
||||
: input;
|
||||
return hash.convertToHex() as TopicIndex;
|
||||
})
|
||||
)
|
||||
|
||||
/**
|
||||
* type guard for memo
|
||||
* create with `v.parse(memoSchema, 'memo')`
|
||||
* memo string inside bounds [5, 255]
|
||||
*/
|
||||
export const MEMO_MIN_CHARS = 5
|
||||
export const MEMO_MAX_CHARS = 255
|
||||
|
||||
declare const validMemo: unique symbol
|
||||
export type Memo = string & { [validMemo]: true };
|
||||
|
||||
export const memoSchema = v.pipe(
|
||||
v.string('expect string type'),
|
||||
v.maxLength(MEMO_MAX_CHARS, `expect string length <= ${MEMO_MAX_CHARS}`),
|
||||
v.minLength(MEMO_MIN_CHARS, `expect string length >= ${MEMO_MIN_CHARS}`),
|
||||
v.transform<string, Memo>(
|
||||
(input: string) => input as Memo,
|
||||
),
|
||||
)
|
||||
|
||||
/**
|
||||
* type guard for timeout duration
|
||||
* create with `v.parse(timeoutDurationSchema, 123)`
|
||||
* timeout duration is a number in seconds inside bounds
|
||||
* [1 hour, 3 months]
|
||||
* for Transaction Links / Deferred Transactions
|
||||
* seconds starting from createdAt Date in which the transaction link can be redeemed
|
||||
*/
|
||||
const LINKED_TRANSACTION_TIMEOUT_DURATION_MIN = 60*60
|
||||
const LINKED_TRANSACTION_TIMEOUT_DURATION_MAX = 60*60*24*31*3
|
||||
|
||||
declare const validTimeoutDuration: unique symbol
|
||||
export type TimeoutDuration = DurationSeconds & { [validTimeoutDuration]: true };
|
||||
|
||||
export const timeoutDurationSchema = v.pipe(
|
||||
v.number('expect number type'),
|
||||
v.minValue(LINKED_TRANSACTION_TIMEOUT_DURATION_MIN, 'expect number >= 1 hour'),
|
||||
v.maxValue(LINKED_TRANSACTION_TIMEOUT_DURATION_MAX, 'expect number <= 3 months'),
|
||||
v.transform<number, TimeoutDuration>(
|
||||
(input: number) => new DurationSeconds(input) as TimeoutDuration,
|
||||
),
|
||||
)
|
||||
|
||||
/**
|
||||
* type guard for amount
|
||||
* create with `v.parse(amountSchema, '123')`
|
||||
* amount is a string representing a positive decimal number, compatible with decimal.js
|
||||
*/
|
||||
declare const validAmount: unique symbol
|
||||
export type Amount = string & { [validAmount]: true };
|
||||
|
||||
export const amountSchema = v.pipe(
|
||||
v.string('expect string type'),
|
||||
v.regex(/^[0-9]+(\.[0-9]+)?$/, 'expect positive number'),
|
||||
v.transform<string, Amount>(
|
||||
(input: string) => input as Amount,
|
||||
),
|
||||
)
|
||||
|
||||
/**
|
||||
* type guard for gradido amount
|
||||
* create with `v.parse(gradidoAmountSchema, '123')`
|
||||
* gradido amount is a string representing a positive decimal number, compatible with decimal.js
|
||||
*/
|
||||
declare const validGradidoAmount: unique symbol
|
||||
export type GradidoAmount = GradidoUnit & { [validGradidoAmount]: true };
|
||||
|
||||
export const gradidoAmountSchema = v.pipe(
|
||||
amountSchema,
|
||||
v.transform<Amount, GradidoAmount>(
|
||||
(input: Amount) => GradidoUnit.fromString(input) as GradidoAmount,
|
||||
),
|
||||
)
|
||||
@ -1,27 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import { logger } from '@test/testSetup'
|
||||
|
||||
import { LogError } from './LogError'
|
||||
|
||||
describe('LogError', () => {
|
||||
it('logs an Error when created', () => {
|
||||
/* eslint-disable-next-line no-new */
|
||||
new LogError('new LogError')
|
||||
expect(logger.error).toBeCalledWith('new LogError')
|
||||
})
|
||||
|
||||
it('logs an Error including additional data when created', () => {
|
||||
/* eslint-disable-next-line no-new */
|
||||
new LogError('new LogError', { some: 'data' })
|
||||
expect(logger.error).toBeCalledWith('new LogError', { some: 'data' })
|
||||
})
|
||||
|
||||
it('does not contain additional data in Error object when thrown', () => {
|
||||
try {
|
||||
throw new LogError('new LogError', { someWeirdValue123: 'arbitraryData456' })
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
} catch (e: any) {
|
||||
expect(e.stack).not.toMatch(/(someWeirdValue123|arbitraryData456)/i)
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -1,10 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
import { logger } from '@/logging/logger'
|
||||
|
||||
export class LogError extends Error {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
constructor(msg: string, ...details: any[]) {
|
||||
super(msg)
|
||||
logger.error(msg, ...details)
|
||||
}
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
import corsLib from 'cors'
|
||||
|
||||
const corsOptions = {
|
||||
origin: '*',
|
||||
exposedHeaders: ['token'],
|
||||
}
|
||||
|
||||
export const cors = corsLib(corsOptions)
|
||||
@ -1,79 +0,0 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { ApolloServer } from '@apollo/server'
|
||||
import { expressMiddleware } from '@apollo/server/express4'
|
||||
import bodyParser from 'body-parser'
|
||||
import cors from 'cors'
|
||||
import express, { Express } from 'express'
|
||||
// graphql
|
||||
import { slowDown } from 'express-slow-down'
|
||||
import helmet from 'helmet'
|
||||
import { Logger } from 'log4js'
|
||||
|
||||
import { schema } from '@/graphql/schema'
|
||||
import { logger as dltLogger } from '@/logging/logger'
|
||||
|
||||
type ServerDef = { apollo: ApolloServer; app: Express }
|
||||
|
||||
interface MyContext {
|
||||
token?: string
|
||||
}
|
||||
|
||||
const createServer = async (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// context: any = serverContext,
|
||||
logger: Logger = dltLogger,
|
||||
// localization: i18n.I18n = i18n,
|
||||
): Promise<ServerDef> => {
|
||||
logger.addContext('user', 'unknown')
|
||||
logger.debug('createServer...')
|
||||
|
||||
// Express Server
|
||||
const app = express()
|
||||
|
||||
// Apollo Server
|
||||
const apollo = new ApolloServer<MyContext>({
|
||||
schema: await schema(),
|
||||
introspection: true,
|
||||
// context,
|
||||
// plugins
|
||||
logger,
|
||||
})
|
||||
// Helmet helps secure Express apps by setting HTTP response headers.
|
||||
app.use(helmet())
|
||||
|
||||
// rate limiter/ slow down to many requests
|
||||
const limiter = slowDown({
|
||||
windowMs: 1000, // 1 second
|
||||
delayAfter: 10, // Allow 10 requests per 1 second.
|
||||
delayMs: (hits) => hits * 50, // Add 100 ms of delay to every request after the 10th one.
|
||||
/**
|
||||
* So:
|
||||
*
|
||||
* - requests 1-10 are not delayed.
|
||||
* - request 11 is delayed by 550ms
|
||||
* - request 12 is delayed by 600ms
|
||||
* - request 13 is delayed by 650ms
|
||||
*
|
||||
* and so on. After 1 seconds, the delay is reset to 0.
|
||||
*/
|
||||
})
|
||||
app.use(limiter)
|
||||
// because of nginx proxy, needed for limiter
|
||||
app.set('trust proxy', 1)
|
||||
|
||||
await apollo.start()
|
||||
app.use(
|
||||
'/',
|
||||
cors<cors.CorsRequest>(),
|
||||
bodyParser.json(),
|
||||
expressMiddleware(apollo, {
|
||||
context: async ({ req }) => ({ token: req.headers.token }),
|
||||
}),
|
||||
)
|
||||
logger.debug('createServer...successful')
|
||||
|
||||
return { apollo, app }
|
||||
}
|
||||
|
||||
export default createServer
|
||||
@ -1,6 +1,6 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { hardenDerivationIndex, HARDENED_KEY_BITMASK } from './derivationHelper'
|
||||
// only for IDE, bun don't need this to work
|
||||
import { describe, expect, it } from 'bun:test'
|
||||
|
||||
describe('utils', () => {
|
||||
it('test bitmask for hardened keys', () => {
|
||||
|
||||
51
dlt-connector/src/utils/network.ts
Normal file
51
dlt-connector/src/utils/network.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import net from 'node:net'
|
||||
import { getLogger } from 'log4js'
|
||||
import { LOG4JS_BASE_CATEGORY } from '../config/const'
|
||||
import { CONFIG } from '../config'
|
||||
|
||||
export async function isPortOpen(
|
||||
url: string,
|
||||
timeoutMs: number = CONFIG.CONNECT_TIMEOUT_MS,
|
||||
): Promise<boolean> {
|
||||
return new Promise((resolve) => {
|
||||
const socket = new net.Socket()
|
||||
const { hostname, port } = new URL(url)
|
||||
|
||||
// auto-destroy socket after timeout
|
||||
const timer = setTimeout(() => {
|
||||
socket.destroy()
|
||||
resolve(false)
|
||||
}, timeoutMs)
|
||||
|
||||
socket.connect(Number(port), hostname, () => {
|
||||
// connection successful
|
||||
clearTimeout(timer)
|
||||
socket.end()
|
||||
resolve(true)
|
||||
})
|
||||
|
||||
socket.on('error', (err: any) => {
|
||||
clearTimeout(timer)
|
||||
socket.destroy()
|
||||
const logger = getLogger(`${LOG4JS_BASE_CATEGORY}.network.isPortOpen`)
|
||||
logger.addContext('url', url)
|
||||
logger.error(`${err.message}: ${err.code}`)
|
||||
resolve(false)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const wait = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
|
||||
|
||||
export async function isPortOpenRetry(
|
||||
url: string,
|
||||
timeoutMs: number = CONFIG.CONNECT_TIMEOUT_MS,
|
||||
delayMs: number = CONFIG.CONNECT_RETRY_DELAY_MS,
|
||||
retries: number = CONFIG.CONNECT_RETRY_COUNT,
|
||||
): Promise<boolean> {
|
||||
for (let i = 0; i < retries; i++) {
|
||||
if (await isPortOpen(url, timeoutMs)) return true
|
||||
await wait(delayMs)
|
||||
}
|
||||
throw new Error(`${url} port is not open after ${retries} retries`)
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { base64ToBuffer, uuid4ToHash, uuid4ToBuffer } from './typeConverter'
|
||||
|
||||
describe('utils/typeConverter', () => {
|
||||
it('uuid4ToBuffer', () => {
|
||||
expect(uuid4ToBuffer('4f28e081-5c39-4dde-b6a4-3bde71de8d65')).toStrictEqual(
|
||||
Buffer.from('4f28e0815c394ddeb6a43bde71de8d65', 'hex'),
|
||||
)
|
||||
})
|
||||
|
||||
it('iotaTopicFromCommunityUUID', () => {
|
||||
expect(uuid4ToHash('4f28e081-5c39-4dde-b6a4-3bde71de8d65')).toBe(
|
||||
'3138b3590311fdf0a823e173caa9487b7d275c23fab07106b4b1364cb038affd',
|
||||
)
|
||||
})
|
||||
|
||||
it('base64ToBuffer', () => {
|
||||
expect(base64ToBuffer('MTizWQMR/fCoI+FzyqlIe30nXCP6sHEGtLE2TLA4r/0=')).toStrictEqual(
|
||||
Buffer.from('3138b3590311fdf0a823e173caa9487b7d275c23fab07106b4b1364cb038affd', 'hex'),
|
||||
)
|
||||
})
|
||||
})
|
||||
@ -1,120 +0,0 @@
|
||||
/* eslint-disable camelcase */
|
||||
import {
|
||||
AddressType,
|
||||
AddressType_COMMUNITY_AUF,
|
||||
AddressType_COMMUNITY_GMW,
|
||||
AddressType_COMMUNITY_HUMAN,
|
||||
AddressType_COMMUNITY_PROJECT,
|
||||
AddressType_CRYPTO_ACCOUNT,
|
||||
AddressType_NONE,
|
||||
AddressType_SUBACCOUNT,
|
||||
ConfirmedTransaction,
|
||||
DeserializeType_CONFIRMED_TRANSACTION,
|
||||
InteractionDeserialize,
|
||||
MemoryBlock,
|
||||
} from 'gradido-blockchain-js'
|
||||
|
||||
import { AccountType } from '@/graphql/enum/AccountType'
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
export const uuid4ToBuffer = (uuid: string): Buffer => {
|
||||
// Remove dashes from the UUIDv4 string
|
||||
const cleanedUUID = uuid.replace(/-/g, '')
|
||||
|
||||
// Create a Buffer object from the hexadecimal values
|
||||
const buffer = Buffer.from(cleanedUUID, 'hex')
|
||||
|
||||
return buffer
|
||||
}
|
||||
|
||||
export const uuid4ToMemoryBlock = (uuid: string): MemoryBlock => {
|
||||
// Remove dashes from the UUIDv4 string
|
||||
return MemoryBlock.fromHex(uuid.replace(/-/g, ''))
|
||||
}
|
||||
|
||||
export const uuid4sToMemoryBlock = (uuid: string[]): MemoryBlock => {
|
||||
let resultHexString = ''
|
||||
for (let i = 0; i < uuid.length; i++) {
|
||||
resultHexString += uuid[i].replace(/-/g, '')
|
||||
}
|
||||
return MemoryBlock.fromHex(resultHexString)
|
||||
}
|
||||
|
||||
export const uuid4ToHash = (communityUUID: string): MemoryBlock => {
|
||||
return uuid4ToMemoryBlock(communityUUID).calculateHash()
|
||||
}
|
||||
|
||||
export const base64ToBuffer = (base64: string): Buffer => {
|
||||
return Buffer.from(base64, 'base64')
|
||||
}
|
||||
|
||||
export const communityUuidToTopic = (communityUUID: string): string => {
|
||||
return uuid4ToHash(communityUUID).convertToHex()
|
||||
}
|
||||
|
||||
export function getEnumValue<T extends Record<string, unknown>>(
|
||||
enumType: T,
|
||||
value: number | string,
|
||||
): T[keyof T] | undefined {
|
||||
if (typeof value === 'number' && typeof enumType === 'object') {
|
||||
return enumType[value as keyof T] as T[keyof T]
|
||||
} else if (typeof value === 'string') {
|
||||
for (const key in enumType) {
|
||||
if (enumType[key as keyof T] === value) {
|
||||
return enumType[key as keyof T] as T[keyof T]
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
export const accountTypeToAddressType = (type: AccountType): AddressType => {
|
||||
switch (type) {
|
||||
case AccountType.COMMUNITY_AUF:
|
||||
return AddressType_COMMUNITY_AUF
|
||||
case AccountType.COMMUNITY_GMW:
|
||||
return AddressType_COMMUNITY_GMW
|
||||
case AccountType.COMMUNITY_HUMAN:
|
||||
return AddressType_COMMUNITY_HUMAN
|
||||
case AccountType.COMMUNITY_PROJECT:
|
||||
return AddressType_COMMUNITY_PROJECT
|
||||
case AccountType.CRYPTO_ACCOUNT:
|
||||
return AddressType_CRYPTO_ACCOUNT
|
||||
case AccountType.SUBACCOUNT:
|
||||
return AddressType_SUBACCOUNT
|
||||
default:
|
||||
return AddressType_NONE
|
||||
}
|
||||
}
|
||||
|
||||
export const addressTypeToAccountType = (type: AddressType): AccountType => {
|
||||
switch (type) {
|
||||
case AddressType_COMMUNITY_AUF:
|
||||
return AccountType.COMMUNITY_AUF
|
||||
case AddressType_COMMUNITY_GMW:
|
||||
return AccountType.COMMUNITY_GMW
|
||||
case AddressType_COMMUNITY_HUMAN:
|
||||
return AccountType.COMMUNITY_HUMAN
|
||||
case AddressType_COMMUNITY_PROJECT:
|
||||
return AccountType.COMMUNITY_PROJECT
|
||||
case AddressType_CRYPTO_ACCOUNT:
|
||||
return AccountType.CRYPTO_ACCOUNT
|
||||
case AddressType_SUBACCOUNT:
|
||||
return AccountType.SUBACCOUNT
|
||||
default:
|
||||
return AccountType.NONE
|
||||
}
|
||||
}
|
||||
|
||||
export const confirmedTransactionFromBase64 = (base64: string): ConfirmedTransaction => {
|
||||
const deserializer = new InteractionDeserialize(
|
||||
MemoryBlock.fromBase64(base64),
|
||||
DeserializeType_CONFIRMED_TRANSACTION,
|
||||
)
|
||||
deserializer.run()
|
||||
const confirmedTransaction = deserializer.getConfirmedTransaction()
|
||||
if (!confirmedTransaction) {
|
||||
throw new LogError("invalid data, couldn't deserialize")
|
||||
}
|
||||
return confirmedTransaction
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
import { ApolloServer } from '@apollo/server'
|
||||
import { addMocksToSchema } from '@graphql-tools/mock'
|
||||
|
||||
import { schema } from '@/graphql/schema'
|
||||
|
||||
let apolloTestServer: ApolloServer
|
||||
|
||||
export async function createApolloTestServer() {
|
||||
if (apolloTestServer === undefined) {
|
||||
apolloTestServer = new ApolloServer({
|
||||
// addMocksToSchema accepts a schema instance and provides
|
||||
// mocked data for each field in the schema
|
||||
schema: addMocksToSchema({
|
||||
schema: await schema(),
|
||||
preserveResolvers: true,
|
||||
}),
|
||||
})
|
||||
}
|
||||
return apolloTestServer
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
import { logger } from '@/logging/logger'
|
||||
|
||||
jest.setTimeout(1000000)
|
||||
|
||||
jest.mock('@/logging/logger', () => {
|
||||
const originalModule = jest.requireActual('@/logging/logger')
|
||||
return {
|
||||
__esModule: true,
|
||||
...originalModule,
|
||||
logger: {
|
||||
addContext: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
info: jest.fn(),
|
||||
error: jest.fn(),
|
||||
fatal: jest.fn(),
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
export { logger }
|
||||
@ -1,88 +1,104 @@
|
||||
{
|
||||
"include": ["src/**/*", "types/**/*"],
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
||||
// "lib": [], /* Specify library files to be included in the compilation. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
"outDir": "./build", /* Redirect output structure to the directory. */
|
||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
/* Projects */
|
||||
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
"strictPropertyInitialization": false, /* Enable strict checking of property initialization in classes. */
|
||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
/* Language and Environment */
|
||||
"target": "ES2021", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||
|
||||
/* Additional Checks */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
"baseUrl": ".", /* Base directory to resolve non-absolute module names. */
|
||||
"paths": { /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
"@/*": ["src/*"],
|
||||
"@arg/*": ["src/graphql/arg/*"],
|
||||
"@enum/*": ["src/graphql/enum/*"],
|
||||
"@input/*": ["src/graphql/input/*"],
|
||||
"@model/*": ["src/graphql/model/*"],
|
||||
"@resolver/*": ["src/graphql/resolver/*"],
|
||||
"@test/*": ["test/*"],
|
||||
"@proto/*" : ["src/proto/*"],
|
||||
"@validator/*" : ["src/graphql/validator/*"],
|
||||
},
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
"typeRoots": ["node_modules/@types", "@types"], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
/* Modules */
|
||||
"module": "ES2022", /* Specify what module code is generated. */
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||
"types": ["bun-types"], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
/* JavaScript Support */
|
||||
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||
|
||||
/* Experimental Options */
|
||||
"experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
"emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
/* Emit */
|
||||
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||
// "outDir": "./", /* Specify an output folder for all emitted files. */
|
||||
// "removeComments": true, /* Disable emitting comments. */
|
||||
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
||||
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||
|
||||
/* Advanced Options */
|
||||
"skipLibCheck": true, /* Skip type checking of declaration files. */
|
||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
// add 'prepend' if you want to include the referenced project in your output file
|
||||
// "prepend": true
|
||||
}
|
||||
]
|
||||
/* Interop Constraints */
|
||||
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
|
||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
||||
|
||||
/* Type Checking */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
}
|
||||
}
|
||||
|
||||
2
dlt-connector/types/global.d.ts
vendored
Normal file
2
dlt-connector/types/global.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
// types/global.d.ts
|
||||
/// <reference types="bun-types" /
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user