diff --git a/.github/workflows/pull_request.workflow.yml b/.github/workflows/pull_request.workflow.yml index d393e3c9..aa8eda50 100644 --- a/.github/workflows/pull_request.workflow.yml +++ b/.github/workflows/pull_request.workflow.yml @@ -7,9 +7,9 @@ jobs: name: Lint runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -19,9 +19,9 @@ jobs: ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- - - uses: actions/setup-node@v1.4.4 + - uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 18 - uses: ./.github/actions/es-lint build: @@ -29,9 +29,9 @@ jobs: runs-on: ubuntu-22.04 needs: [lint] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -41,9 +41,9 @@ jobs: ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- - - uses: actions/setup-node@v1.4.4 + - uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 18 - uses: ./.github/actions/build - name: Store build archive as artifact uses: actions/upload-artifact@v2 @@ -59,9 +59,9 @@ jobs: matrix: test-set: [stdout, cucumber] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules NODE_ENV: test @@ -72,9 +72,9 @@ jobs: ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- - - uses: actions/setup-node@v1.4.4 + - uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 18 - name: Recover previously built Kourou uses: actions/download-artifact@v2 with: diff --git a/.github/workflows/push_dev.workflow.yml b/.github/workflows/push_dev.workflow.yml index 896b32b4..3ec56539 100644 --- a/.github/workflows/push_dev.workflow.yml +++ b/.github/workflows/push_dev.workflow.yml @@ -10,9 +10,9 @@ jobs: name: Lint runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -22,9 +22,9 @@ jobs: ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- - - uses: actions/setup-node@v1.4.4 + - uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 18 - uses: ./.github/actions/es-lint build: @@ -32,9 +32,9 @@ jobs: runs-on: ubuntu-22.04 needs: [lint] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -44,9 +44,9 @@ jobs: ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- - - uses: actions/setup-node@v1.4.4 + - uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 18 - uses: ./.github/actions/build - name: Store build archive as artifact uses: actions/upload-artifact@v2 @@ -62,9 +62,9 @@ jobs: matrix: test-set: [stdout, cucumber] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules NODE_ENV: test @@ -75,9 +75,9 @@ jobs: ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- - - uses: actions/setup-node@v1.4.4 + - uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 18 - name: Recover previously built Kourou uses: actions/download-artifact@v2 with: diff --git a/.github/workflows/push_master.workflow.yml b/.github/workflows/push_master.workflow.yml index e4aeb525..55d09170 100644 --- a/.github/workflows/push_master.workflow.yml +++ b/.github/workflows/push_master.workflow.yml @@ -10,9 +10,9 @@ jobs: name: Lint runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -22,9 +22,9 @@ jobs: ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- - - uses: actions/setup-node@v1.4.4 + - uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 18 - uses: ./.github/actions/es-lint build: @@ -32,9 +32,9 @@ jobs: runs-on: ubuntu-22.04 needs: [lint] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -44,9 +44,9 @@ jobs: ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- - - uses: actions/setup-node@v1.4.4 + - uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 18 - uses: ./.github/actions/build - name: Store build archive as artifact uses: actions/upload-artifact@v2 @@ -62,9 +62,9 @@ jobs: matrix: test-set: [stdout, cucumber] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules NODE_ENV: test @@ -75,9 +75,9 @@ jobs: ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- - - uses: actions/setup-node@v1.4.4 + - uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 18 - name: Recover previously built Kourou uses: actions/download-artifact@v2 with: @@ -95,10 +95,10 @@ jobs: runs-on: ubuntu-22.04 needs: [functional-test] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions/setup-node@v1 with: - node-version: 14 + node-version: 18 registry-url: "https://registry.npmjs.org" - run: npm install - run: npm run build diff --git a/README.md b/README.md index 3006ee67..6ca97495 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ The CLI that helps you manage your Kuzzle instances. + [![oclif](https://img.shields.io/badge/cli-oclif-brightgreen.svg)](https://oclif.io) [![Version](https://img.shields.io/npm/v/kourou.svg)](https://npmjs.org/package/kourou) [![Downloads/week](https://img.shields.io/npm/dw/kourou.svg)](https://npmjs.org/package/kourou) @@ -26,7 +27,7 @@ $ npm install -g kourou $ kourou COMMAND running command... $ kourou (-v|--version|version) -kourou/0.25.0 linux-x64 node-v16.15.0 +kourou/0.27.1 darwin-arm64 node-v18.17.1 $ kourou --help [COMMAND] USAGE $ kourou COMMAND @@ -164,6 +165,9 @@ All other arguments and options will be passed as-is to the `sdk:query` method. * [`kourou paas:init PROJECT`](#kourou-paasinit-project) * [`kourou paas:login`](#kourou-paaslogin) * [`kourou paas:logs ENVIRONMENT APPLICATION`](#kourou-paaslogs-environment-application) +* [`kourou paas:snapshots:cat ENVIRONMENT APPLICATIONID`](#kourou-paassnapshotscat-environment-applicationid) +* [`kourou paas:snapshots:dump ENVIRONMENT APPLICATIONID`](#kourou-paassnapshotsdump-environment-applicationid) +* [`kourou paas:snapshots:restore ENVIRONMENT APPLICATIONID SNAPSHOTID`](#kourou-paassnapshotsrestore-environment-applicationid-snapshotid) * [`kourou profile:export`](#kourou-profileexport) * [`kourou profile:import PATH`](#kourou-profileimport-path) * [`kourou realtime:subscribe INDEX COLLECTION [FILTERS]`](#kourou-realtimesubscribe-index-collection-filters) @@ -208,7 +212,7 @@ EXAMPLE kourou api-key:check eyJhbG...QxfQrc ``` -_See code: [src/commands/api-key/check.ts](src/commands/api-key/check.ts)_ +_See code: [lib/commands/api-key/check.js](lib/commands/api-key/check.js)_ ## `kourou api-key:create USER` @@ -236,7 +240,7 @@ OPTIONS --username=username [default: anonymous] Kuzzle username (local strategy) ``` -_See code: [src/commands/api-key/create.ts](src/commands/api-key/create.ts)_ +_See code: [lib/commands/api-key/create.js](lib/commands/api-key/create.js)_ ## `kourou api-key:delete USER ID` @@ -265,7 +269,7 @@ EXAMPLE kourou vault:delete sigfox-gateway 1k-BF3EBjsXdvA2PR8x ``` -_See code: [src/commands/api-key/delete.ts](src/commands/api-key/delete.ts)_ +_See code: [lib/commands/api-key/delete.js](lib/commands/api-key/delete.js)_ ## `kourou api-key:search USER` @@ -291,7 +295,7 @@ OPTIONS --username=username [default: anonymous] Kuzzle username (local strategy) ``` -_See code: [src/commands/api-key/search.ts](src/commands/api-key/search.ts)_ +_See code: [lib/commands/api-key/search.js](lib/commands/api-key/search.js)_ ## `kourou app:debug-proxy` @@ -329,7 +333,7 @@ OPTIONS --username=username [default: anonymous] Kuzzle username (local strategy) ``` -_See code: [src/commands/app/debug-proxy.ts](src/commands/app/debug-proxy.ts)_ +_See code: [lib/commands/app/debug-proxy.js](lib/commands/app/debug-proxy.js)_ ## `kourou app:doctor` @@ -352,7 +356,7 @@ OPTIONS --username=username [default: anonymous] Kuzzle username (local strategy) ``` -_See code: [src/commands/app/doctor.ts](src/commands/app/doctor.ts)_ +_See code: [lib/commands/app/doctor.js](lib/commands/app/doctor.js)_ ## `kourou app:scaffold DESTINATION` @@ -366,13 +370,11 @@ ARGUMENTS DESTINATION Directory to scaffold the app OPTIONS - --flavor=flavor [default: generic] Template flavor ("generic", "iot-platform", "iot-console", "iot-platform"). - Those can be found here: https://github.com/kuzzleio/project-templates - + --flavor=flavor [default: generic] Template flavor ("generic", "iot"). --help show CLI help ``` -_See code: [src/commands/app/scaffold.ts](src/commands/app/scaffold.ts)_ +_See code: [lib/commands/app/scaffold.js](lib/commands/app/scaffold.js)_ ## `kourou app:start-services` @@ -387,7 +389,7 @@ OPTIONS --help show CLI help ``` -_See code: [src/commands/app/start-services.ts](src/commands/app/start-services.ts)_ +_See code: [lib/commands/app/start-services.js](lib/commands/app/start-services.js)_ ## `kourou autocomplete [SHELL]` @@ -437,7 +439,7 @@ OPTIONS --username=username [default: anonymous] Kuzzle username (local strategy) ``` -_See code: [src/commands/collection/create.ts](src/commands/collection/create.ts)_ +_See code: [lib/commands/collection/create.js](lib/commands/collection/create.js)_ ## `kourou collection:export INDEX COLLECTION` @@ -507,6 +509,9 @@ OPTIONS --ssl Use SSL to connect to Kuzzle + --type=type + [default: all] Type of the export: all, mappings, data + --username=username [default: anonymous] Kuzzle username (local strategy) @@ -515,7 +520,7 @@ EXAMPLES kourou collection:export nyc-open-data yellow-taxi --query '{ term: { city: "Saigon" } }' ``` -_See code: [src/commands/collection/export.ts](src/commands/collection/export.ts)_ +_See code: [lib/commands/collection/export.js](lib/commands/collection/export.js)_ ## `kourou collection:import PATH` @@ -544,7 +549,7 @@ OPTIONS --username=username [default: anonymous] Kuzzle username (local strategy) ``` -_See code: [src/commands/collection/import.ts](src/commands/collection/import.ts)_ +_See code: [lib/commands/collection/import.js](lib/commands/collection/import.js)_ ## `kourou collection:migrate SCRIPT PATH` @@ -573,7 +578,7 @@ OPTIONS --username=username [default: anonymous] Kuzzle username (local strategy) ``` -_See code: [src/commands/collection/migrate.ts](src/commands/collection/migrate.ts)_ +_See code: [lib/commands/collection/migrate.js](lib/commands/collection/migrate.js)_ ## `kourou config:diff FIRST SECOND` @@ -595,7 +600,7 @@ EXAMPLE kourou config:diff config/local/kuzzlerc config/production/kuzzlerc ``` -_See code: [src/commands/config/diff.ts](src/commands/config/diff.ts)_ +_See code: [lib/commands/config/diff.js](lib/commands/config/diff.js)_ ## `kourou document:search INDEX COLLECTION [QUERY]` @@ -633,7 +638,7 @@ EXAMPLES kourou document:search iot sensors --editor ``` -_See code: [src/commands/document/search.ts](src/commands/document/search.ts)_ +_See code: [lib/commands/document/search.js](lib/commands/document/search.js)_ ## `kourou es:aliases:cat` @@ -649,7 +654,7 @@ OPTIONS --help show CLI help ``` -_See code: [src/commands/es/aliases/cat.ts](src/commands/es/aliases/cat.ts)_ +_See code: [lib/commands/es/aliases/cat.js](lib/commands/es/aliases/cat.js)_ ## `kourou es:indices:cat` @@ -665,7 +670,7 @@ OPTIONS --help show CLI help ``` -_See code: [src/commands/es/indices/cat.ts](src/commands/es/indices/cat.ts)_ +_See code: [lib/commands/es/indices/cat.js](lib/commands/es/indices/cat.js)_ ## `kourou es:indices:get INDEX ID` @@ -684,7 +689,7 @@ OPTIONS --help show CLI help ``` -_See code: [src/commands/es/indices/get.ts](src/commands/es/indices/get.ts)_ +_See code: [lib/commands/es/indices/get.js](lib/commands/es/indices/get.js)_ ## `kourou es:indices:insert INDEX` @@ -704,7 +709,7 @@ OPTIONS --id=id Document ID ``` -_See code: [src/commands/es/indices/insert.ts](src/commands/es/indices/insert.ts)_ +_See code: [lib/commands/es/indices/insert.js](lib/commands/es/indices/insert.js)_ ## `kourou es:migrate` @@ -726,12 +731,12 @@ OPTIONS --src=src (required) Migration source provider EXAMPLES - kourou es:migrate --src http://elasticsearch:9200 --dest ./my-backup --batch-size 2000 --pattern + kourou es:migrate --src http://elasticsearch:9200 --dest ./my-backup --batch-size 2000 --pattern '&myindexes.collection-*' kourou es:migrate --src ./my-backup --dest http://elasticsearch:9200 --reset --batch-size 2000 --no-interactive ``` -_See code: [src/commands/es/migrate.ts](src/commands/es/migrate.ts)_ +_See code: [lib/commands/es/migrate.js](lib/commands/es/migrate.js)_ ## `kourou es:snapshot:create REPOSITORY NAME` @@ -750,7 +755,7 @@ OPTIONS --help show CLI help ``` -_See code: [src/commands/es/snapshot/create.ts](src/commands/es/snapshot/create.ts)_ +_See code: [lib/commands/es/snapshot/create.js](lib/commands/es/snapshot/create.js)_ ## `kourou es:snapshot:create-repository REPOSITORY LOCATION` @@ -770,7 +775,7 @@ OPTIONS --help show CLI help ``` -_See code: [src/commands/es/snapshot/create-repository.ts](src/commands/es/snapshot/create-repository.ts)_ +_See code: [lib/commands/es/snapshot/create-repository.js](lib/commands/es/snapshot/create-repository.js)_ ## `kourou es:snapshot:list REPOSITORY` @@ -788,7 +793,7 @@ OPTIONS --help show CLI help ``` -_See code: [src/commands/es/snapshot/list.ts](src/commands/es/snapshot/list.ts)_ +_See code: [lib/commands/es/snapshot/list.js](lib/commands/es/snapshot/list.js)_ ## `kourou file:decrypt FILE` @@ -811,7 +816,7 @@ EXAMPLES kourou file:decrypt books/cryptonomicon.txt.enc -o books/cryptonomicon.txt --vault-key ``` -_See code: [src/commands/file/decrypt.ts](src/commands/file/decrypt.ts)_ +_See code: [lib/commands/file/decrypt.js](lib/commands/file/decrypt.js)_ ## `kourou file:encrypt FILE` @@ -834,7 +839,7 @@ EXAMPLES kourou file:encrypt books/cryptonomicon.txt -o books/cryptonomicon.txt.enc --vault-key ``` -_See code: [src/commands/file/encrypt.ts](src/commands/file/encrypt.ts)_ +_See code: [lib/commands/file/encrypt.js](lib/commands/file/encrypt.js)_ ## `kourou file:test FILE` @@ -854,7 +859,7 @@ EXAMPLE kourou file:test books/cryptonomicon.txt.enc --vault-key ``` -_See code: [src/commands/file/test.ts](src/commands/file/test.ts)_ +_See code: [lib/commands/file/test.js](lib/commands/file/test.js)_ ## `kourou help [COMMAND]` @@ -898,7 +903,7 @@ OPTIONS --username=username [default: anonymous] Kuzzle username (local strategy) ``` -_See code: [src/commands/import.ts](src/commands/import.ts)_ +_See code: [lib/commands/import.js](lib/commands/import.js)_ ## `kourou index:export INDEX` @@ -939,6 +944,8 @@ OPTIONS --ssl Use SSL to connect to Kuzzle + --type=type [default: all] Type of the export: all, mappings, data + --username=username [default: anonymous] Kuzzle username (local strategy) EXAMPLES @@ -946,7 +953,7 @@ EXAMPLES kourou index:export nyc-open-data --query '{"range":{"_kuzzle_info.createdAt":{"gt":1632935638866}}}' ``` -_See code: [src/commands/index/export.ts](src/commands/index/export.ts)_ +_See code: [lib/commands/index/export.js](lib/commands/index/export.js)_ ## `kourou index:import PATH` @@ -978,7 +985,7 @@ EXAMPLES kourou index:import ./dump/iot-data --index iot-data-production --no-mappings ``` -_See code: [src/commands/index/import.ts](src/commands/index/import.ts)_ +_See code: [lib/commands/index/import.js](lib/commands/index/import.js)_ ## `kourou instance:kill` @@ -993,7 +1000,7 @@ OPTIONS -i, --instance=instance Kuzzle instance name [ex: stack-0] ``` -_See code: [src/commands/instance/kill.ts](src/commands/instance/kill.ts)_ +_See code: [lib/commands/instance/kill.js](lib/commands/instance/kill.js)_ ## `kourou instance:list` @@ -1004,7 +1011,7 @@ USAGE $ kourou instance:list ``` -_See code: [src/commands/instance/list.ts](src/commands/instance/list.ts)_ +_See code: [lib/commands/instance/list.js](lib/commands/instance/list.js)_ ## `kourou instance:logs` @@ -1019,7 +1026,7 @@ OPTIONS -i, --instance=instance Kuzzle instance name ``` -_See code: [src/commands/instance/logs.ts](src/commands/instance/logs.ts)_ +_See code: [lib/commands/instance/logs.js](lib/commands/instance/logs.js)_ ## `kourou instance:spawn` @@ -1035,7 +1042,7 @@ OPTIONS --help show CLI help ``` -_See code: [src/commands/instance/spawn.ts](src/commands/instance/spawn.ts)_ +_See code: [lib/commands/instance/spawn.js](lib/commands/instance/spawn.js)_ ## `kourou paas:deploy ENVIRONMENT APPLICATIONID IMAGE` @@ -1056,7 +1063,7 @@ OPTIONS --token=token Authentication token ``` -_See code: [src/commands/paas/deploy.ts](src/commands/paas/deploy.ts)_ +_See code: [lib/commands/paas/deploy.js](lib/commands/paas/deploy.js)_ ## `kourou paas:elasticsearch:dump ENVIRONMENT APPLICATIONID DUMPDIRECTORY` @@ -1094,7 +1101,7 @@ OPTIONS --help show CLI help ``` -_See code: [src/commands/paas/init.ts](src/commands/paas/init.ts)_ +_See code: [lib/commands/paas/init.js](lib/commands/paas/init.js)_ ## `kourou paas:login` @@ -1111,7 +1118,7 @@ OPTIONS --username=username PaaS username ``` -_See code: [src/commands/paas/login.ts](src/commands/paas/login.ts)_ +_See code: [lib/commands/paas/login.js](lib/commands/paas/login.js)_ ## `kourou paas:logs ENVIRONMENT APPLICATION` @@ -1136,7 +1143,77 @@ OPTIONS --until=until Display logs until a specific absolute (e.g. 2022/12/02 09:41) or relative (e.g. a minute ago) time ``` -_See code: [src/commands/paas/logs.ts](src/commands/paas/logs.ts)_ +_See code: [lib/commands/paas/logs.js](lib/commands/paas/logs.js)_ + +## `kourou paas:snapshots:cat ENVIRONMENT APPLICATIONID` + +List all snapshots for a given kuzzle application in a environment + +``` +USAGE + $ kourou paas:snapshots:cat ENVIRONMENT APPLICATIONID + +ARGUMENTS + ENVIRONMENT Project environment name + APPLICATIONID Application Identifier + +OPTIONS + --help show CLI help + --project=project Current PaaS project + --token=token Authentication token + +EXAMPLE + kourou paas:snapshots:cat --project paas-project-myproject api main +``` + +_See code: [lib/commands/paas/snapshots/cat.js](lib/commands/paas/snapshots/cat.js)_ + +## `kourou paas:snapshots:dump ENVIRONMENT APPLICATIONID` + +Create a new snapshot of the current application state + +``` +USAGE + $ kourou paas:snapshots:dump ENVIRONMENT APPLICATIONID + +ARGUMENTS + ENVIRONMENT Project environment name + APPLICATIONID Application Identifier + +OPTIONS + --help show CLI help + --project=project Current PaaS project + --token=token Authentication token + +EXAMPLE + kourou paas:snapshots:dump --project paas-project-myproject api main +``` + +_See code: [lib/commands/paas/snapshots/dump.js](lib/commands/paas/snapshots/dump.js)_ + +## `kourou paas:snapshots:restore ENVIRONMENT APPLICATIONID SNAPSHOTID` + +Restore a snapshot of the current application state + +``` +USAGE + $ kourou paas:snapshots:restore ENVIRONMENT APPLICATIONID SNAPSHOTID + +ARGUMENTS + ENVIRONMENT Project environment name + APPLICATIONID Application Identifier + SNAPSHOTID Snapshot Identifier + +OPTIONS + --help show CLI help + --project=project Current PaaS project + --token=token Authentication token + +EXAMPLE + kourou paas:snapshots:restore --project paas-project-myproject api main snapshot-id +``` + +_See code: [lib/commands/paas/snapshots/restore.js](lib/commands/paas/snapshots/restore.js)_ ## `kourou profile:export` @@ -1159,7 +1236,7 @@ OPTIONS --username=username [default: anonymous] Kuzzle username (local strategy) ``` -_See code: [src/commands/profile/export.ts](src/commands/profile/export.ts)_ +_See code: [lib/commands/profile/export.js](lib/commands/profile/export.js)_ ## `kourou profile:import PATH` @@ -1184,7 +1261,7 @@ OPTIONS --username=username [default: anonymous] Kuzzle username (local strategy) ``` -_See code: [src/commands/profile/import.ts](src/commands/profile/import.ts)_ +_See code: [lib/commands/profile/import.js](lib/commands/profile/import.js)_ ## `kourou realtime:subscribe INDEX COLLECTION [FILTERS]` @@ -1236,7 +1313,7 @@ EXAMPLES kourou realtime:subscribe iot-data sensors --display result._source.temperature ``` -_See code: [src/commands/realtime/subscribe.ts](src/commands/realtime/subscribe.ts)_ +_See code: [lib/commands/realtime/subscribe.js](lib/commands/realtime/subscribe.js)_ ## `kourou redis:list-keys [MATCH]` @@ -1268,7 +1345,7 @@ EXAMPLES kourou redis:list-keys "counters/*" --remove ``` -_See code: [src/commands/redis/list-keys.ts](src/commands/redis/list-keys.ts)_ +_See code: [lib/commands/redis/list-keys.js](lib/commands/redis/list-keys.js)_ ## `kourou role:export` @@ -1291,7 +1368,7 @@ OPTIONS --username=username [default: anonymous] Kuzzle username (local strategy) ``` -_See code: [src/commands/role/export.ts](src/commands/role/export.ts)_ +_See code: [lib/commands/role/export.js](lib/commands/role/export.js)_ ## `kourou role:import PATH` @@ -1317,7 +1394,7 @@ OPTIONS --username=username [default: anonymous] Kuzzle username (local strategy) ``` -_See code: [src/commands/role/import.ts](src/commands/role/import.ts)_ +_See code: [lib/commands/role/import.js](lib/commands/role/import.js)_ ## `kourou sdk:execute [CODE]` @@ -1375,7 +1452,7 @@ DESCRIPTION - kourou sdk:execute 'return await sdk.server.now()' --editor ``` -_See code: [src/commands/sdk/execute.ts](src/commands/sdk/execute.ts)_ +_See code: [lib/commands/sdk/execute.js](lib/commands/sdk/execute.js)_ ## `kourou sdk:query CONTROLLER:ACTION` @@ -1476,7 +1553,7 @@ DESCRIPTION - kourou admin:loadMappings < mappings.json ``` -_See code: [src/commands/sdk/query.ts](src/commands/sdk/query.ts)_ +_See code: [lib/commands/sdk/query.js](lib/commands/sdk/query.js)_ ## `kourou user:export` @@ -1509,7 +1586,7 @@ DESCRIPTION You can either: - Manually re-create credentials for your users - - Use the "mustChangePasswordIfSetByAdmin" option Kuzzle password policies (see + - Use the "mustChangePasswordIfSetByAdmin" option Kuzzle password policies (see https://github.com/kuzzleio/kuzzle-plugin-auth-passport-local/#optional-properties) - Use the "--generate-credentials" flag to auto-generate credentials for your users @@ -1528,7 +1605,7 @@ DESCRIPTION - kourou user:export --generate-credentials --generated-username content.email ``` -_See code: [src/commands/user/export.ts](src/commands/user/export.ts)_ +_See code: [lib/commands/user/export.js](lib/commands/user/export.js)_ ## `kourou user:export-mappings` @@ -1551,7 +1628,7 @@ OPTIONS --username=username [default: anonymous] Kuzzle username (local strategy) ``` -_See code: [src/commands/user/export-mappings.ts](src/commands/user/export-mappings.ts)_ +_See code: [lib/commands/user/export-mappings.js](lib/commands/user/export-mappings.js)_ ## `kourou user:import PATH` @@ -1576,7 +1653,7 @@ OPTIONS --username=username [default: anonymous] Kuzzle username (local strategy) ``` -_See code: [src/commands/user/import.ts](src/commands/user/import.ts)_ +_See code: [lib/commands/user/import.js](lib/commands/user/import.js)_ ## `kourou user:import-mappings PATH` @@ -1601,7 +1678,7 @@ OPTIONS --username=username [default: anonymous] Kuzzle username (local strategy) ``` -_See code: [src/commands/user/import-mappings.ts](src/commands/user/import-mappings.ts)_ +_See code: [lib/commands/user/import-mappings.js](lib/commands/user/import-mappings.js)_ ## `kourou vault:add SECRETS-FILE KEY VALUE` @@ -1632,7 +1709,7 @@ EXAMPLE kourou vault:add config/secrets.enc.json aws.s3.keyId b61e267676660c314b006b06 --vault-key ``` -_See code: [src/commands/vault/add.ts](src/commands/vault/add.ts)_ +_See code: [lib/commands/vault/add.js](lib/commands/vault/add.js)_ ## `kourou vault:decrypt FILE` @@ -1662,7 +1739,7 @@ EXAMPLES kourou vault:decrypt config/secrets.enc.json -o config/secrets.json --vault-key ``` -_See code: [src/commands/vault/decrypt.ts](src/commands/vault/decrypt.ts)_ +_See code: [lib/commands/vault/decrypt.js](lib/commands/vault/decrypt.js)_ ## `kourou vault:encrypt FILE` @@ -1703,7 +1780,7 @@ EXAMPLES kourou vault:encrypt config/secrets.json -o config/secrets_prod.enc.json --vault-key ``` -_See code: [src/commands/vault/encrypt.ts](src/commands/vault/encrypt.ts)_ +_See code: [lib/commands/vault/encrypt.js](lib/commands/vault/encrypt.js)_ ## `kourou vault:show SECRETS-FILE [KEY]` @@ -1734,7 +1811,7 @@ EXAMPLES kourou vault:show config/secrets.enc.json aws.s3.secretKey --vault-key ``` -_See code: [src/commands/vault/show.ts](src/commands/vault/show.ts)_ +_See code: [lib/commands/vault/show.js](lib/commands/vault/show.js)_ ## `kourou vault:test SECRETS-FILE` @@ -1759,7 +1836,7 @@ EXAMPLE kourou vault:test config/secrets.enc.json --vault-key ``` -_See code: [src/commands/vault/test.ts](src/commands/vault/test.ts)_ +_See code: [lib/commands/vault/test.js](lib/commands/vault/test.js)_ # Where does this weird name come from? diff --git a/features/Sdk.feature b/features/Sdk.feature index 89074c04..1d8eb9af 100644 --- a/features/Sdk.feature +++ b/features/Sdk.feature @@ -1,7 +1,5 @@ Feature: SDK commands - # sdk:query ================================================================== - @mappings Scenario: Send a query to Kuzzle Given an existing collection "nyc-open-data":"yellow-taxi" @@ -21,8 +19,6 @@ Feature: SDK commands Then I should match stdout with: | "_id": "gordon" | - # sdk:execute ================================================================ - @mappings Scenario: Execute code in the SDK context Given an existing collection "nyc-open-data":"yellow-taxi" @@ -30,3 +26,11 @@ Feature: SDK commands | arg | return await sdk.document.create("nyc-open-data", "yellow-taxi", {}, "document-adrien"); | Then The document "document-adrien" should exist And I should match stdout with "document-adrien" + + @mappings + Scenario: Execute Typescript code in the SDK context + Given an existing collection "nyc-open-data":"yellow-taxi" + When I run the command "sdk:execute" with: + | arg | const index: string = "nyc-open-data"; const collection: string = "yellow-taxi"; const id: string = "document-ricky"; return await sdk.document.create(index, collection, {}, id); | + Then The document "document-ricky" should exist + And I should match stdout with "document-ricky" diff --git a/features/run-kuzzle-stack.sh b/features/run-kuzzle-stack.sh index cf35ec9f..b0cb41ff 100755 --- a/features/run-kuzzle-stack.sh +++ b/features/run-kuzzle-stack.sh @@ -7,7 +7,7 @@ mkdir -p /tmp/snapshots chmod 777 -R /tmp/snapshots # Launch the kuzzle stack -docker-compose -f features/docker/docker-compose.yml up -d +docker compose -f features/docker/docker-compose.yml up -d echo "[$(date --rfc-3339 seconds)] - Starting Kuzzle..." while ! curl -f -s -o /dev/null http://localhost:7512 diff --git a/package-lock.json b/package-lock.json index 241ee7ad..5ce0359d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "kourou", - "version": "0.25.0", + "version": "0.27.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "kourou", - "version": "0.25.0", + "version": "0.27.1", "license": "Apache-2.0", "dependencies": { "@elastic/elasticsearch": "^7.12.0", @@ -27,10 +27,12 @@ "ndjson": "^2.0.0", "node-emoji": "^1.10.0", "node-fetch": "^2.6.7", + "production": "^0.0.2", "strip-json-comments": "^3.1.1", "tar": "^6.1.11", "tmp": "^0.2.1", "tslib": "^2.3.1", + "typescript": "4.4.*", "ws": "^8.8.0" }, "bin": { @@ -64,8 +66,7 @@ "prettier-eslint": "^12.0.0", "should": "^13.2.3", "source-map-support": "^0.5.19", - "ts-node": "10.9.*", - "typescript": "4.4.*" + "ts-node": "10.9.*" }, "engines": { "node": ">=10.0.0" @@ -1602,6 +1603,11 @@ "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "node_modules/acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -1898,6 +1904,11 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2100,6 +2111,36 @@ "node": "*" } }, + "node_modules/cheerio": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.10.3.tgz", + "integrity": "sha512-z18iEDVDRpNeLPCGDmDRlex8iLpYxV5KyQz3JHGpzdVX1tSRvtBfwWELW65Ae/FIOGO/YKxKERhz/0n5RI0m7A==", + "dependencies": { + "cheerio-select": "*", + "entities": "0.x", + "htmlparser2": "2.x", + "underscore": "*" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/chokidar": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", @@ -2484,6 +2525,32 @@ "node": ">= 8" } }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/cucumber": { "version": "6.0.7", "resolved": "https://registry.npmjs.org/cucumber/-/cucumber-6.0.7.tgz", @@ -2702,6 +2769,68 @@ "node": ">=6.0.0" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/duration": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz", @@ -2766,6 +2895,11 @@ "node": ">=8.6" } }, + "node_modules/entities": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-0.5.0.tgz", + "integrity": "sha512-T5XQtlzuW+PfeSsGp3uryfYQof820zYbnUnUDEkwUVIAfgYeixIN16c4jh8gs0SqJUTGLU0XD6QsvjEPbmdwzQ==" + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -3811,6 +3945,37 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/htmlparser2": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-2.6.0.tgz", + "integrity": "sha512-oR9aps3hDZdU0whPlDjz4HdafpcZclpjrUOwPqDldr+WDubEnVerBNP8I0Wy0VIZO5Mxq/4yALDOYZTWf5Jtog==", + "dependencies": { + "domelementtype": "1", + "domhandler": "2.0", + "domutils": "1.0" + } + }, + "node_modules/htmlparser2/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "node_modules/htmlparser2/node_modules/domhandler": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.0.3.tgz", + "integrity": "sha512-D8+qeCUo6LpYvBZsmXWunDJ9zOD8mVg6EwZIdgxmnT+xGWRsReF/TwsZ5EzlIJDipxlE6qJh1dXt9oeplGN3Bg==", + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/htmlparser2/node_modules/domutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.0.1.tgz", + "integrity": "sha512-EtnpDnVNvVaRBHmc5PV2lGHlgic4IjrYgS1f3U/M7CjihJIKfsJFvwj6JfAjr7f7wNDcloq3rOb08xAiL622gA==", + "dependencies": { + "domelementtype": "1" + } + }, "node_modules/http-call": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/http-call/-/http-call-5.3.0.tgz", @@ -4369,6 +4534,11 @@ "kuzzle-sdk": "^7.0.0" } }, + "node_modules/keypress": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz", + "integrity": "sha512-x0yf9PL/nx9Nw9oLL8ZVErFAk85/lslwEP7Vz7s5SI1ODXZIgit3C5qyWjw4DxOuO/3Hb4866SQh28a1V1d+WA==" + }, "node_modules/knuth-shuffle-seeded": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/knuth-shuffle-seeded/-/knuth-shuffle-seeded-1.0.6.tgz", @@ -5513,6 +5683,17 @@ "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", "dev": true }, + "node_modules/nopt": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.1.2.tgz", + "integrity": "sha512-x8vXm7BZ2jE1Txrxh/hO74HTuYZQEbo8edoRcANgdZ4+PCV+pbjd/xdummkmjjC7LU5EjPzlu8zEq/oxWylnKA==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, "node_modules/normalize-package-data": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", @@ -5558,6 +5739,17 @@ "node": ">=4" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -6403,6 +6595,28 @@ "node": ">=8" } }, + "node_modules/production": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/production/-/production-0.0.2.tgz", + "integrity": "sha512-5w7rjO1yaPVymK2zA3BGlIFhQMJdu6UufXR1KxUh+1lWGorjcGMzs9kOTHadReT1f8+EHfSFefgZVyDYSz7tOQ==", + "dependencies": { + "cheerio": "0.10.3", + "commander": "1.1.1", + "request": "2.12.0", + "yuglify": "*" + } + }, + "node_modules/production/node_modules/commander": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-1.1.1.tgz", + "integrity": "sha512-71Rod2AhcH3JhkBikVpNd0pA+fWsmAaVoti6OR38T76chA7vE3pSerS0Jor4wDw+tOueD2zLVvFOw5H0Rcj7rA==", + "dependencies": { + "keypress": "0.1.x" + }, + "engines": { + "node": ">= 0.6.x" + } + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -6689,6 +6903,66 @@ "node": ">=0.10" } }, + "node_modules/request": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.12.0.tgz", + "integrity": "sha512-GcOI9NyUw2lRke4kdbrjQFxu+cLugShENHvcb9QCSLLc/yH3lP7I/7RESxVbYS+AxC/r9rwzks52MRHVoZdb5w==", + "bundleDependencies": [ + "form-data", + "mime" + ], + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "engines": [ + "node >= 0.3.6" + ], + "dependencies": { + "form-data": "~0.0.3", + "mime": "~1.2.7" + } + }, + "node_modules/request/node_modules/form-data": { + "version": "0.0.3", + "inBundle": true, + "dependencies": { + "async": "~0.1.9", + "combined-stream": "0.0.3", + "mime": "~1.2.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/request/node_modules/form-data/node_modules/async": { + "version": "0.1.9", + "inBundle": true, + "engines": { + "node": "*" + } + }, + "node_modules/request/node_modules/form-data/node_modules/combined-stream": { + "version": "0.0.3", + "inBundle": true, + "dependencies": { + "delayed-stream": "0.0.5" + }, + "engines": { + "node": "*" + } + }, + "node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream": { + "version": "0.0.5", + "inBundle": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/request/node_modules/mime": { + "version": "1.2.7", + "inBundle": true, + "engines": { + "node": "*" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -7662,7 +7936,6 @@ "version": "4.4.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", - "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7671,6 +7944,22 @@ "node": ">=4.2.0" } }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -8110,6 +8399,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ycssmin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ycssmin/-/ycssmin-1.0.1.tgz", + "integrity": "sha512-nSBxAfGA/RlALXyqijYUnIjMXNXWxYHrQJSYwNqypeULl44J8Z/eN5larw7ZEdYLeUHBgPyilve6hqQtWVVs9g==", + "bin": { + "ycssmin": "bin/cssmin" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", @@ -8130,6 +8427,19 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/yuglify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yuglify/-/yuglify-2.0.0.tgz", + "integrity": "sha512-H5bf7+JO9htUtORqDGYiFAeZjrAQXVU7l2ZX1EYDQFJENjex2pSixhmE6SMSnntzHMeraQhcIXPFdA3YF9ssMA==", + "dependencies": { + "nopt": "~2.1.1", + "uglify-js": "^3.1.4", + "ycssmin": "~1.0.1" + }, + "bin": { + "yuglify": "bin/yuglify" + } } }, "dependencies": { @@ -9351,6 +9661,11 @@ "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -9569,6 +9884,11 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -9703,6 +10023,30 @@ "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", "dev": true }, + "cheerio": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.10.3.tgz", + "integrity": "sha512-z18iEDVDRpNeLPCGDmDRlex8iLpYxV5KyQz3JHGpzdVX1tSRvtBfwWELW65Ae/FIOGO/YKxKERhz/0n5RI0m7A==", + "requires": { + "cheerio-select": "*", + "entities": "0.x", + "htmlparser2": "2.x", + "underscore": "*" + } + }, + "cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "requires": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + } + }, "chokidar": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", @@ -9999,6 +10343,23 @@ "which": "^2.0.1" } }, + "css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + }, "cucumber": { "version": "6.0.7", "resolved": "https://registry.npmjs.org/cucumber/-/cucumber-6.0.7.tgz", @@ -10172,6 +10533,46 @@ "esutils": "^2.0.2" } }, + "dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "dependencies": { + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" + } + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "requires": { + "domelementtype": "^2.3.0" + } + }, + "domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "requires": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + } + }, "duration": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz", @@ -10224,6 +10625,11 @@ "ansi-colors": "^4.1.1" } }, + "entities": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-0.5.0.tgz", + "integrity": "sha512-T5XQtlzuW+PfeSsGp3uryfYQof820zYbnUnUDEkwUVIAfgYeixIN16c4jh8gs0SqJUTGLU0XD6QsvjEPbmdwzQ==" + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -11018,6 +11424,39 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "htmlparser2": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-2.6.0.tgz", + "integrity": "sha512-oR9aps3hDZdU0whPlDjz4HdafpcZclpjrUOwPqDldr+WDubEnVerBNP8I0Wy0VIZO5Mxq/4yALDOYZTWf5Jtog==", + "requires": { + "domelementtype": "1", + "domhandler": "2.0", + "domutils": "1.0" + }, + "dependencies": { + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domhandler": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.0.3.tgz", + "integrity": "sha512-D8+qeCUo6LpYvBZsmXWunDJ9zOD8mVg6EwZIdgxmnT+xGWRsReF/TwsZ5EzlIJDipxlE6qJh1dXt9oeplGN3Bg==", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.0.1.tgz", + "integrity": "sha512-EtnpDnVNvVaRBHmc5PV2lGHlgic4IjrYgS1f3U/M7CjihJIKfsJFvwj6JfAjr7f7wNDcloq3rOb08xAiL622gA==", + "requires": { + "domelementtype": "1" + } + } + } + }, "http-call": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/http-call/-/http-call-5.3.0.tgz", @@ -11432,6 +11871,11 @@ "getmac": "^5.20.0" } }, + "keypress": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz", + "integrity": "sha512-x0yf9PL/nx9Nw9oLL8ZVErFAk85/lslwEP7Vz7s5SI1ODXZIgit3C5qyWjw4DxOuO/3Hb4866SQh28a1V1d+WA==" + }, "knuth-shuffle-seeded": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/knuth-shuffle-seeded/-/knuth-shuffle-seeded-1.0.6.tgz", @@ -12307,6 +12751,14 @@ "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", "dev": true }, + "nopt": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.1.2.tgz", + "integrity": "sha512-x8vXm7BZ2jE1Txrxh/hO74HTuYZQEbo8edoRcANgdZ4+PCV+pbjd/xdummkmjjC7LU5EjPzlu8zEq/oxWylnKA==", + "requires": { + "abbrev": "1" + } + }, "normalize-package-data": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", @@ -12342,6 +12794,14 @@ } } }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "requires": { + "boolbase": "^1.0.0" + } + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -12949,6 +13409,27 @@ "fromentries": "^1.2.0" } }, + "production": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/production/-/production-0.0.2.tgz", + "integrity": "sha512-5w7rjO1yaPVymK2zA3BGlIFhQMJdu6UufXR1KxUh+1lWGorjcGMzs9kOTHadReT1f8+EHfSFefgZVyDYSz7tOQ==", + "requires": { + "cheerio": "0.10.3", + "commander": "1.1.1", + "request": "2.12.0", + "yuglify": "*" + }, + "dependencies": { + "commander": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-1.1.1.tgz", + "integrity": "sha512-71Rod2AhcH3JhkBikVpNd0pA+fWsmAaVoti6OR38T76chA7vE3pSerS0Jor4wDw+tOueD2zLVvFOw5H0Rcj7rA==", + "requires": { + "keypress": "0.1.x" + } + } + } + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -13169,6 +13650,49 @@ "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", "dev": true }, + "request": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.12.0.tgz", + "integrity": "sha512-GcOI9NyUw2lRke4kdbrjQFxu+cLugShENHvcb9QCSLLc/yH3lP7I/7RESxVbYS+AxC/r9rwzks52MRHVoZdb5w==", + "requires": { + "form-data": "~0.0.3", + "mime": "~1.2.7" + }, + "dependencies": { + "form-data": { + "version": "0.0.3", + "bundled": true, + "requires": { + "async": "~0.1.9", + "combined-stream": "0.0.3", + "mime": "~1.2.2" + }, + "dependencies": { + "async": { + "version": "0.1.9", + "bundled": true + }, + "combined-stream": { + "version": "0.0.3", + "bundled": true, + "requires": { + "delayed-stream": "0.0.5" + }, + "dependencies": { + "delayed-stream": { + "version": "0.0.5", + "bundled": true + } + } + } + } + }, + "mime": { + "version": "1.2.7", + "bundled": true + } + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -13926,8 +14450,17 @@ "typescript": { "version": "4.4.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", - "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", - "dev": true + "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==" + }, + "uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==" + }, + "underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" }, "undici-types": { "version": "5.26.5", @@ -14260,6 +14793,11 @@ } } }, + "ycssmin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ycssmin/-/ycssmin-1.0.1.tgz", + "integrity": "sha512-nSBxAfGA/RlALXyqijYUnIjMXNXWxYHrQJSYwNqypeULl44J8Z/eN5larw7ZEdYLeUHBgPyilve6hqQtWVVs9g==" + }, "yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", @@ -14271,6 +14809,16 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true + }, + "yuglify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yuglify/-/yuglify-2.0.0.tgz", + "integrity": "sha512-H5bf7+JO9htUtORqDGYiFAeZjrAQXVU7l2ZX1EYDQFJENjex2pSixhmE6SMSnntzHMeraQhcIXPFdA3YF9ssMA==", + "requires": { + "nopt": "~2.1.1", + "uglify-js": "^3.1.4", + "ycssmin": "~1.0.1" + } } } } diff --git a/package.json b/package.json index b77a093b..ce1b2e17 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "kourou", "description": "The CLI that helps you manage your Kuzzle instances", - "version": "0.25.0", + "version": "0.27.1", "author": "The Kuzzle Team ", "bin": { "kourou": "./bin/run" @@ -37,11 +37,13 @@ "ndjson": "^2.0.0", "node-emoji": "^1.10.0", "node-fetch": "^2.6.7", + "production": "^0.0.2", "strip-json-comments": "^3.1.1", "tar": "^6.1.11", "tmp": "^0.2.1", "tslib": "^2.3.1", - "ws": "^8.8.0" + "ws": "^8.8.0", + "typescript": "4.4.*" }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", @@ -71,8 +73,7 @@ "prettier-eslint": "^12.0.0", "should": "^13.2.3", "source-map-support": "^0.5.19", - "ts-node": "10.9.*", - "typescript": "4.4.*" + "ts-node": "10.9.*" }, "engines": { "node": ">=10.0.0" diff --git a/src/commands/app/doctor.ts b/src/commands/app/doctor.ts index 757b817a..372f87d0 100644 --- a/src/commands/app/doctor.ts +++ b/src/commands/app/doctor.ts @@ -5,6 +5,7 @@ import { kuzzleFlags } from "../../support/kuzzle"; import { Client } from "@elastic/elasticsearch"; import { execute } from "../../support/execute"; import _ from "lodash"; +import { checkPrerequisites } from "../../support/docker/checkPrerequisites"; export default class AppDoctor extends Kommand { static description = "Analyze a Kuzzle application"; @@ -50,7 +51,7 @@ export default class AppDoctor extends Kommand { const suggestions = []; const [nodeVersion, adminExists, anonymous] = await Promise.all([ - this.sdk.query({ controller: "debug", action: "nodeVersion", }), + this.sdk.query({ controller: "debug", action: "nodeVersion", }), this.sdk.server.adminExists({}), this.sdk.security.getRole("anonymous") ]); @@ -67,8 +68,7 @@ export default class AppDoctor extends Kommand { } else { this.logKo("No admin user exists"); suggestions.push( - `Create an admin user ${ - anonymousNotRestricted ? "and restrict anonymous role " : "" + `Create an admin user ${anonymousNotRestricted ? "and restrict anonymous role " : "" }with kourou security:createFirstAdmin '{ credentials: { @@ -216,20 +216,13 @@ export default class AppDoctor extends Kommand { } this.log("Docker checks"); - try { - const docov = await execute("docker-compose", "-v"); - const matches = docov.stdout.match(/[^0-9.]*([0-9.]*).*/); - if (matches === null || matches.length === 0) { - this.logKo("Docker Version cannot be found"); - } else { - this.logOk(`Docker Compose Version: ${matches[1]}`); - } - } catch (error: any) { - this.logKo("Docker Compose cannot be found"); - suggestions.push("Install Docker Compose with 'npm run install:docker'"); + const result = await checkPrerequisites(this); + + if (!result) { + suggestions.push("Install Docker and the Compose plugin"); } - this.log(`----------------- DoKtor finish his job ! -----------------`); + this.log(`----------------- DoKtor finished its job ! -----------------`); this.log(`He suggest you to check the following points:`); for (const suggestion of suggestions) { this.logInfo(" => " + suggestion); diff --git a/src/commands/app/scaffold.ts b/src/commands/app/scaffold.ts index 21786773..48a03791 100644 --- a/src/commands/app/scaffold.ts +++ b/src/commands/app/scaffold.ts @@ -6,6 +6,7 @@ import { Kommand } from "../../common"; import { execute } from "../../support/execute"; export default class AppScaffold extends Kommand { + public templatesDir = "/tmp/kuzzle-templates"; static initSdk = false; static description = "Scaffolds a new Kuzzle application"; @@ -14,8 +15,7 @@ export default class AppScaffold extends Kommand { help: flags.help(), flavor: flags.string({ default: "generic", - description: `Template flavor ("generic", "iot-backend", "iot-console"). - Those can be found here: https://github.com/kuzzleio/project-templates`, + description: `Template flavor ("generic", "iot").`, }), }; @@ -33,40 +33,89 @@ export default class AppScaffold extends Kommand { const tasks = new Listr([ { - title: "Creating and rendering application files", - task: async () => this.cloneTemplate(flavor, destination), + title: "Checking destination", + task: async () => this.checkDestination(destination), }, + { + title: "Prepare temporary folder", + task: async () => this.prepareTemplate(), + }, + { + title: "Cloning template repository", + task: async () => this.cloneTemplate(flavor) + }, { + title: "Copying template files", + task: async () => this.copyTemplate(destination) + }, + { + title: "Cleaning up", + task: async () => this.cleanup() + } ]); await tasks.run(); this.log(""); - this.logOk( - `Scaffolding complete! Use ${chalk.blue.bold( - `cd ${destination} && npm run docker npm install` - )} install dependencies and then ${chalk.blue.bold( - `npm run docker:dev` - )} to run your application!` - ); + this.logOk(`Scaffolding complete!`); + this.logOk(`Use ${chalk.blue.bold( + `cd ${destination} && docker compose up -d` + )} to start your Kuzzle stack.`); + } + + getRepo(flavor: string) { + console.log(flavor); + switch (flavor) { + case "generic": + return "template-kuzzle-project"; + case "iot": + return "template-kiotp-project"; + default: + return "template-kuzzle-project"; + } } - async cloneTemplate(flavor: string, destination: string) { - const templatesDir = "/tmp/project-templates"; + async checkDestination(destination: string) { + let process: any; - await execute("rm", "-rf", templatesDir); + try { + process = await execute("test", "-d", destination) + } catch (error: any) { + if (error.result.exitCode === 1) { + // Destination directory does not exist + return; + } + } + + if (process.exitCode === 0) { + throw new Error( + `Destination directory ${destination} already exists.` + ); + } + } + + async prepareTemplate() { + await execute("rm", "-rf", this.templatesDir); + } + + async cloneTemplate(flavor: string) { + const repo = this.getRepo(flavor); await execute( "git", "clone", "--depth=1", - "https://github.com/kuzzleio/project-templates", + `https://github.com/kuzzleio/${repo}`, "--branch", - flavor, + "master", "--single-branch", - templatesDir + this.templatesDir ); + } - await execute("cp", "-r", `${templatesDir}/${flavor}`, `${destination}/`); + async copyTemplate(destination: string) { + await execute("cp", "-r", `${this.templatesDir}/`, `${destination}/`); + } - await execute("rm", "-rf", templatesDir); + async cleanup() { + await execute("rm", "-rf", this.templatesDir); } } diff --git a/src/commands/app/start-services.ts b/src/commands/app/start-services.ts index 9e3117e9..f20be36d 100644 --- a/src/commands/app/start-services.ts +++ b/src/commands/app/start-services.ts @@ -3,13 +3,12 @@ import path from "path"; import { flags } from "@oclif/command"; import chalk from "chalk"; -import Listr from "listr"; + import emoji from "node-emoji"; import { Kommand } from "../../common"; import { execute } from "../../support/execute"; - -const MIN_DOCO_VERSION = "1.12.0"; +import { checkPrerequisites } from "../../support/docker/checkPrerequisites"; const kuzzleServicesFile = ` version: '3' @@ -48,7 +47,7 @@ export default class AppStartServices extends Kommand { const docoFilename = path.join(this.kourouDir, "kuzzle-services.yml"); const successfullCheck = this.flags.check - ? await this.checkPrerequisites() + ? await checkPrerequisites(this) : true; if (this.flags.check && successfullCheck) { @@ -64,22 +63,22 @@ export default class AppStartServices extends Kommand { } this.log( - chalk.grey(`\nWriting docker-compose file to ${docoFilename}...\n`) + chalk.grey(`\nWriting the Docker Compose file to ${docoFilename}...\n`) ); writeFileSync(docoFilename, kuzzleServicesFile); // clean up - await execute("docker-compose", "-f", docoFilename, "down"); + await execute("docker", "compose", "-f", docoFilename, "down"); try { - await execute("docker-compose", "-f", docoFilename, "up", "-d"); + await execute("docker", "compose", "-f", docoFilename, "up", "-d"); this.logOk( "Elasticsearch and Redis are booting in the background right now." ); this.log(chalk.grey("\nTo watch the logs, run")); - this.log(chalk.blue.bold(` docker-compose -f ${docoFilename} logs -f\n`)); + this.log(chalk.blue.bold(` docker compose -f ${docoFilename} logs -f\n`)); this.log(` Elasticsearch port: ${chalk.bold("9200")}`); this.log(` Redis port: ${chalk.bold("6379")}`); } catch (error: any) { @@ -88,58 +87,7 @@ export default class AppStartServices extends Kommand { chalk.grey("If you want to investigate the problem, try running") ); - this.log(chalk.grey(` docker-compose -f ${docoFilename} up\n`)); - } - } - - public async checkPrerequisites(): Promise { - this.log(chalk.grey("Checking prerequisites...")); - - const checks: Listr = new Listr([ - { - title: `docker-compose exists and the version is at least ${MIN_DOCO_VERSION}`, - task: async () => { - try { - const docov = await execute("docker-compose", "-v"); - const matches = docov.stdout.match(/[^0-9.]*([0-9.]*).*/); - if (matches === null) { - throw new Error( - "Unable to read docker-compose verson. This is weird." - ); - } - const docoVersion = matches.length > 0 ? matches[1] : null; - - if (docoVersion === null) { - throw new Error( - "Unable to read docker-compose version. This is weird." - ); - } - try { - if (docoVersion < MIN_DOCO_VERSION) { - throw new Error( - `The detected version of docker-compose (${docoVersion}) is not recent enough (${MIN_DOCO_VERSION})` - ); - } - } catch (error: any) { - throw new Error(error); - } - } catch (error: any) { - throw new Error( - "No docker-compose found. Are you sure docker-compose is installed?" - ); - } - }, - }, - ]); - - try { - await checks.run(); - - return true; - } catch (error: any) { - this.logKo(error.message); - - return false; + this.log(chalk.grey(` docker compose -f ${docoFilename} up\n`)); } } } diff --git a/src/commands/collection/export.ts b/src/commands/collection/export.ts index 6667d6bf..62661123 100644 --- a/src/commands/collection/export.ts +++ b/src/commands/collection/export.ts @@ -52,6 +52,10 @@ exportable fields in the mapping will be exported.`, expressed in ms format, e.g. '2s', '1m', '3h'.`, default: "20s", }), + type: flags.string({ + description: "Type of the export: all, mappings, data", + default: "all", + }), ...kuzzleFlags, protocol: flags.string({ description: "Kuzzle protocol (http or websocket)", @@ -99,30 +103,35 @@ expressed in ms format, e.g. '2s', '1m', '3h'.`, ); this.logInfo( - `Dumping ${count} of ${countAll} documents from collection "${this.args.index}:${this.args.collection}" in ${exportPath} ...` + `Dumping collection "${this.args.index}:${this.args.collection}" in ${exportPath} ...` ); fs.mkdirSync(exportPath, { recursive: true }); - await dumpCollectionMappings( - this.sdk, - this.args.index, - this.args.collection, - exportPath, - this.flags.format - ); - - await dumpCollectionData( - this.sdk, - this.args.index, - this.args.collection, - Number(this.flags["batch-size"]), - exportPath, - query, - this.flags.format, - fields, - this.flags.scrollTTL - ); + if (this.flags.type === "all" || this.flags.type === "mappings") { + this.logInfo(`Dumping collection mappings ...`); + await dumpCollectionMappings( + this.sdk, + this.args.index, + this.args.collection, + exportPath, + this.flags.format + ); + } + if (this.flags.type === "all" || this.flags.type === "data") { + this.logInfo(`Dumping collection ${count} of ${countAll} documents ...`); + await dumpCollectionData( + this.sdk, + this.args.index, + this.args.collection, + Number(this.flags["batch-size"]), + exportPath, + query, + this.flags.format, + fields, + this.flags.scrollTTL + ); + } this.logOk(`Collection ${this.args.index}:${this.args.collection} dumped`); } diff --git a/src/commands/index/export.ts b/src/commands/index/export.ts index d1368791..f44f7bc4 100644 --- a/src/commands/index/export.ts +++ b/src/commands/index/export.ts @@ -44,6 +44,10 @@ expressed in ms format, e.g. '2s', '1m', '3h'.`, description: "Kuzzle protocol (http or websocket)", default: "ws", }), + type: flags.string({ + description: "Type of the export: all, mappings, data", + default: "all", + }), }; static args = [{ name: "index", description: "Index name", required: true }]; @@ -70,7 +74,12 @@ expressed in ms format, e.g. '2s', '1m', '3h'.`, for (const collection of collections) { try { - if (collection.type !== "realtime") { + if (collection.type === "realtime") { + continue; + } + + if (this.flags.type === "all" || this.flags.type === "mappings") { + this.logInfo(`Dumping collection "${collection.name}" mappings ...`); await dumpCollectionMappings( this.sdk, this.args.index, @@ -78,7 +87,10 @@ expressed in ms format, e.g. '2s', '1m', '3h'.`, exportPath, this.flags.format ); + } + if (this.flags.type === "all" || this.flags.type === "data") { + this.logInfo(`Dumping collection "${collection.name}" documents ...`); await dumpCollectionData( this.sdk, this.args.index, @@ -87,11 +99,11 @@ expressed in ms format, e.g. '2s', '1m', '3h'.`, exportPath, query, this.flags.format, - this.flags.scrollTTL, + this.flags.scrollTTL ); - - cli.action.stop(); } + + cli.action.stop(); } catch (error: any) { this.logKo( `Error when exporting collection "${collection.name}": ${error}` diff --git a/src/commands/instance/kill.ts b/src/commands/instance/kill.ts index fc9800e0..506d4895 100644 --- a/src/commands/instance/kill.ts +++ b/src/commands/instance/kill.ts @@ -80,7 +80,8 @@ export class InstanceLogs extends Kommand { stdout: true, } ); - const instanceKill: ChildProcess = spawn("docker-compose", [ + const instanceKill: ChildProcess = spawn("docker", [ + "compose", "-f", docoFilename, "-p", diff --git a/src/commands/instance/spawn.ts b/src/commands/instance/spawn.ts index c9556fea..69b4cde7 100644 --- a/src/commands/instance/spawn.ts +++ b/src/commands/instance/spawn.ts @@ -11,9 +11,10 @@ import emoji from "node-emoji"; import { Kommand } from "../../common"; import { execute } from "../../support/execute"; +import { checkPrerequisites } from "../../support/docker/checkPrerequisites"; const MIN_MAX_MAP_COUNT = 262144; -const MIN_DOCO_VERSION = "1.12.0"; +const MIN_DOCO_VERSION = "2.0.0"; const kuzzleStackV1 = (increment: number): string => ` version: '3' @@ -112,7 +113,7 @@ export default class InstanceSpawn extends Kommand { ); const successfullCheck = this.flags.check - ? await this.checkPrerequisites() + ? await checkPrerequisites(this) : true; if (this.flags.check && successfullCheck) { @@ -127,7 +128,7 @@ export default class InstanceSpawn extends Kommand { ); } - this.log(chalk.grey(`\nWriting docker-compose file to ${docoFilename}...`)); + this.log(chalk.grey(`\nWriting docker compose file to ${docoFilename}...`)); writeFileSync( docoFilename, this.generateDocoFile(this.flags.version, portIndex) @@ -135,7 +136,8 @@ export default class InstanceSpawn extends Kommand { // clean up await execute( - "docker-compose", + "docker", + "compose", "-f", docoFilename, "-p", @@ -143,7 +145,8 @@ export default class InstanceSpawn extends Kommand { "down" ); - const doco: ChildProcess = spawn("docker-compose", [ + const doco: ChildProcess = spawn("docker", [ + "compose", "-f", docoFilename, "-p", @@ -153,8 +156,7 @@ export default class InstanceSpawn extends Kommand { ]); cli.action.start( - ` ${emoji.get("rocket")} Kuzzle version ${ - this.flags.version + ` ${emoji.get("rocket")} Kuzzle version ${this.flags.version } is launching`, undefined, { @@ -173,7 +175,7 @@ export default class InstanceSpawn extends Kommand { this.log(chalk.grey("To watch the logs, run")); this.log( chalk.grey( - ` docker-compose -f ${docoFilename} -p stack-${portIndex} logs -f\n` + ` docker compose -f ${docoFilename} -p stack-${portIndex} logs -f\n` ) ); this.log(` Kuzzle port: ${7512 + portIndex}`); @@ -183,7 +185,7 @@ export default class InstanceSpawn extends Kommand { } else { cli.action.stop( chalk.red( - ` Something went wrong: docker-compose exited with ${docoCode}` + ` Something went wrong: docker compose exited with ${docoCode}` ) ); this.log( @@ -191,89 +193,14 @@ export default class InstanceSpawn extends Kommand { ); this.log( chalk.grey( - ` docker-compose -f ${docoFilename} -p stack-${portIndex} up\n` + ` docker compose -f ${docoFilename} -p stack-${portIndex} up\n` ) ); - throw new Error("docker-compose exited witn non-zero status"); + throw new Error("docker compose exited with a non-zero status"); } }); } - public async checkPrerequisites(): Promise { - this.log(chalk.grey("Checking prerequisites...")); - const checks: Listr = new Listr([ - { - title: `docker-compose exists and the version is at least ${MIN_DOCO_VERSION}`, - task: async () => { - try { - const docov = await execute("docker-compose", "-v"); - const matches = docov.stdout.match(/[^0-9.]*([0-9.]*).*/); - if (matches === null) { - throw new Error( - "Unable to read docker-compose verson. This is weird." - ); - } - const docoVersion = matches.length > 0 ? matches[1] : null; - - if (docoVersion === null) { - throw new Error( - "Unable to read docker-compose version. This is weird." - ); - } - try { - if (docoVersion < MIN_DOCO_VERSION) { - throw new Error( - `The detected version of docker-compose (${docoVersion}) is not recent enough (${MIN_DOCO_VERSION})` - ); - } - } catch (error: any) { - throw new Error(error); - } - } catch (error: any) { - throw new Error( - "No docker-compose found. Are you sure docker-compose is installed?" - ); - } - }, - }, - { - title: `vm.max_map_count is greater than ${MIN_MAX_MAP_COUNT}`, - task: async () => { - try { - const sysctl = await execute( - "/sbin/sysctl", - "-n", - "vm.max_map_count" - ); - - if (sysctl.exitCode !== 0) { - throw new Error("Something went wrong checking vm.max_map_count"); - } - - const value: number = parseInt(sysctl.stdout, 10); - if (value < MIN_MAX_MAP_COUNT) { - throw new Error( - `vm.max_map_count must be at least ${MIN_MAX_MAP_COUNT} (found ${value})` - ); - } - } catch (error: any) { - throw new Error( - `Something went wrong checking vm.max_map_count: ${error.message}` - ); - } - }, - }, - ]); - - try { - await checks.run(); - return true; - } catch (error: any) { - this.logKo(error.message); - return false; - } - } - private generateDocoFile(kuzzleMajor: string, portIndex: number): string { if (kuzzleMajor === "1") { return kuzzleStackV1(portIndex); diff --git a/src/commands/paas/logs.ts b/src/commands/paas/logs.ts index f4ec363a..65d8da7e 100644 --- a/src/commands/paas/logs.ts +++ b/src/commands/paas/logs.ts @@ -55,10 +55,12 @@ class PaasLogs extends PaasKommand { description: "Name of the pod to show logs from", }), since: flags.string({ - description: "Display logs from a specific absolute (e.g. 2022/12/02 09:41) or relative (e.g. a minute ago) time", + description: + "Display logs from a specific absolute (e.g. 2022/12/02 09:41) or relative (e.g. a minute ago) time", }), until: flags.string({ - description: "Display logs until a specific absolute (e.g. 2022/12/02 09:41) or relative (e.g. a minute ago) time", + description: + "Display logs until a specific absolute (e.g. 2022/12/02 09:41) or relative (e.g. a minute ago) time", }), }; @@ -78,7 +80,15 @@ class PaasLogs extends PaasKommand { /** * Allowed colors for pod names. */ - private readonly allColors = [chalk.red, chalk.green, chalk.yellow, chalk.blue, chalk.magenta, chalk.cyan, chalk.gray]; + private readonly allColors = [ + chalk.red, + chalk.green, + chalk.yellow, + chalk.blue, + chalk.magenta, + chalk.cyan, + chalk.gray, + ]; /** * Available colors for pod names. @@ -105,8 +115,12 @@ class PaasLogs extends PaasKommand { const separator = "\t"; // Parse the time arguments - const since = this.flags.since ? chrono.parseDate(this.flags.since).toISOString() : undefined; - const until = this.flags.until ? chrono.parseDate(this.flags.until).toISOString() : undefined; + const since = this.flags.since + ? chrono.parseDate(this.flags.since).toISOString() + : undefined; + const until = this.flags.until + ? chrono.parseDate(this.flags.until).toISOString() + : undefined; // Perform the streamed request const incomingMessage = await this.paas.queryHttpStream({ @@ -122,6 +136,31 @@ class PaasLogs extends PaasKommand { until, }); + // Don't continue if an error occurred + if (incomingMessage.statusCode !== 200) { + return new Promise((_, reject) => { + // Collect the whole response body + let responseBody = ""; + + incomingMessage.on("data", (buffer) => { + responseBody += buffer.toString(); + }); + + incomingMessage.on("end", () => { + let response; + + try { + response = JSON.parse(responseBody); + } catch (error: any) { + reject(new Error("An error occurred while parsing the error response body from Kuzzle")); + return; + } + + reject(response.error); + }); + }); + } + // Read the response line by line const lineStream = readline.createInterface({ input: incomingMessage, @@ -134,10 +173,8 @@ class PaasLogs extends PaasKommand { try { const data: PaasLogData = JSON.parse(line); - // Exclude logs that are empty or that are not from a pod if (!data.content || !data.podName) { - this.logKo(line); continue; } @@ -145,12 +182,14 @@ class PaasLogs extends PaasKommand { const podColor = this.getPodColor(data.podName); // Display the log - const timestamp = this.flags.timestamp ? `[${new Date(data.timeStamp).toLocaleString()}] ` : ""; + const timestamp = this.flags.timestamp + ? `[${new Date(data.timeStamp).toLocaleString()}] ` + : ""; const name = podColor(`${data.podName}${separator}`); this.log(`${timestamp}${name}| ${data.content}`); } catch (error) { - this.logKo(`Unable to parse the following line: ${line}`); + this.logKo(`Error while parsing log: ${error} (Received: "${line}")`); } } } diff --git a/src/commands/paas/snapshots/cat.ts b/src/commands/paas/snapshots/cat.ts index defcf45f..decada66 100644 --- a/src/commands/paas/snapshots/cat.ts +++ b/src/commands/paas/snapshots/cat.ts @@ -30,6 +30,8 @@ class PaasSnapshotsCat extends PaasKommand { } ]; + static examples = ["kourou paas:snapshots:cat --project paas-project-myproject api main"]; + async runSafe() { const apiKey = await this.getCredentials(); diff --git a/src/commands/paas/snapshots/dump.ts b/src/commands/paas/snapshots/dump.ts index 50bdf540..738866c2 100644 --- a/src/commands/paas/snapshots/dump.ts +++ b/src/commands/paas/snapshots/dump.ts @@ -4,7 +4,7 @@ import { PaasKommand } from "../../../support/PaasKommand"; class PaasSnapshotsDump extends PaasKommand { public static description = - "List all snapshots for a given kuzzle application in a environment"; + "Create a new snapshot of the current application state"; public static flags = { help: flags.help(), @@ -30,6 +30,8 @@ class PaasSnapshotsDump extends PaasKommand { } ]; + static examples = ["kourou paas:snapshots:dump --project paas-project-myproject api main"]; + async runSafe() { const apiKey = await this.getCredentials(); diff --git a/src/commands/paas/snapshots/restore.ts b/src/commands/paas/snapshots/restore.ts index 0a396030..f52f0405 100644 --- a/src/commands/paas/snapshots/restore.ts +++ b/src/commands/paas/snapshots/restore.ts @@ -4,7 +4,7 @@ import { PaasKommand } from "../../../support/PaasKommand"; class PaasSnapshotsRestore extends PaasKommand { public static description = - "List all snapshots for a given kuzzle application in a environment"; + "Restore a snapshot of the current application state"; public static flags = { help: flags.help(), @@ -35,6 +35,8 @@ class PaasSnapshotsRestore extends PaasKommand { } ]; + static examples = ["kourou paas:snapshots:restore --project paas-project-myproject api main snapshot-id"]; + async runSafe() { const apiKey = await this.getCredentials(); diff --git a/src/commands/sdk/execute.ts b/src/commands/sdk/execute.ts index 2b77fced..1597c286 100644 --- a/src/commands/sdk/execute.ts +++ b/src/commands/sdk/execute.ts @@ -4,6 +4,8 @@ import { isEmpty } from "lodash"; import { Editor } from "../../support/editor"; import { Kommand } from "../../common"; import { kuzzleFlags } from "../../support/kuzzle"; +import ts from "typescript"; +import vm from 'node:vm' class SdkExecute extends Kommand { public static description = ` @@ -71,12 +73,31 @@ Other async beforeConnect() { this.code = this.stdin || this.args.code || "// paste your code here"; - + try { + vm.runInContext(this.code, vm.createContext({})); + } catch (e: any) { + if (e.name === "SyntaxError") { + const result = ts.transpileModule(this.code, { compilerOptions: { module: ts.ModuleKind.CommonJS } }); + this.code = result.outputText; + } + } if (this.haveSubscription) { this.sdkOptions.protocol = "ws"; } } + getVariables() { + return (this.flags.var || []) + .map((nameValue: string) => { + const [name, value] = nameValue.split("="); + + return ` let ${name} = ${value};`; + }) + .join("\n"); + + + } + async runSafe() { if (isEmpty(this.code)) { throw new Error("No code provided."); @@ -84,18 +105,12 @@ Other let userError: Error | null = null; - const variables = (this.flags.var || []) - .map((nameValue: string) => { - const [name, value] = nameValue.split("="); - return ` let ${name} = ${value};`; - }) - .join("\n"); this.code = ` (async () => { try { -${variables} +${this.getVariables()} ${this.code} } catch (error) { @@ -137,7 +152,7 @@ ${variables} this.logInfo("Keep alive for realtime notifications ..."); // eslint-disable-next-line @typescript-eslint/no-empty-function - await new Promise(() => {}); + await new Promise(() => { }); } } diff --git a/src/support/docker/checkPrerequisites.ts b/src/support/docker/checkPrerequisites.ts new file mode 100644 index 00000000..50a097a3 --- /dev/null +++ b/src/support/docker/checkPrerequisites.ts @@ -0,0 +1,44 @@ +import Listr from "listr"; + +import { execute } from "../execute"; +import { Kommand } from "../../common"; + + +const MIN_DOCO_VERSION = "2.0.0"; + +export async function checkPrerequisites(ctx: Kommand): Promise { + const checks: Listr = new Listr([ + { + title: `docker compose exists and the version is at least ${MIN_DOCO_VERSION}`, + task: async () => { + const docov = await execute("docker", "compose", "version"); + const matches = docov.stdout.match(/[^0-9.]*([0-9.]*).*/); + const docoVersion = matches ? matches[1] : null; + ctx.logInfo(`Found Docker Compose version: ${docoVersion}`); + + if (!docoVersion) { + throw new Error( + "Unable to read the version of Docker Compose. Are you sure Docker and the Compose plugin are installed?" + ); + } + + + if (docoVersion < MIN_DOCO_VERSION) { + throw new Error( + `Your version of Docker Compose (${docoVersion}) is below the required version (${MIN_DOCO_VERSION}).` + ); + } + }, + }, + ]); + + try { + await checks.run(); + + return true; + } catch (error: any) { + ctx.logKo(error.message); + + return false; + } +} \ No newline at end of file diff --git a/src/support/dump-collection.ts b/src/support/dump-collection.ts index 667183fa..0aa06570 100644 --- a/src/support/dump-collection.ts +++ b/src/support/dump-collection.ts @@ -83,14 +83,14 @@ abstract class AbstractDumper { * @returns void */ // eslint-disable-next-line @typescript-eslint/no-empty-function - public async setup() { } + public async setup() {} /** * One-shot call before iterating over the data. Can be * used to write the header of the dumped output. */ // eslint-disable-next-line @typescript-eslint/no-empty-function - public async writeHeader() { } + public async writeHeader() {} /** * You can put here the logic to write into the dump. @@ -111,7 +111,7 @@ abstract class AbstractDumper { abstract onResult(document: { _id: string; _source: any }): Promise; // eslint-disable-next-line @typescript-eslint/no-empty-function - public async tearDown() { } + public async tearDown() {} /** * The loop that iterates over the documents of the collection and @@ -120,6 +120,7 @@ abstract class AbstractDumper { * @returns a promise resolving when the dump is finished. */ async dump() { + fs.mkdirSync(this.collectionDir, { recursive: true }); this.filename = path.join( this.collectionDir, `documents.${this.fileExtension}` diff --git a/src/support/execute.ts b/src/support/execute.ts index 19f84c3c..1a1c14c2 100644 --- a/src/support/execute.ts +++ b/src/support/execute.ts @@ -47,10 +47,7 @@ export function execute(...args: any[]): ProcessExecutor { let stdout = ""; let stderr = ""; - // eslint-disable-next-line process.stdout.on("data", (data) => (stdout += data.toString())); - - // eslint-disable-next-line process.stderr.on("data", (data) => (stderr += data.toString())); const executor: any = new Promise((resolve, reject) => { diff --git a/src/support/kuzzle.ts b/src/support/kuzzle.ts index 7f6614d9..1553f004 100644 --- a/src/support/kuzzle.ts +++ b/src/support/kuzzle.ts @@ -114,7 +114,8 @@ export class KuzzleSDK { this.sdk.on("networkError", (error: any) => logger.logKo(error.message)); logger.logInfo( - `Connecting to ${this.protocol}${this.ssl ? "s" : ""}://${this.host}:${this.port + `Connecting to ${this.protocol}${this.ssl ? "s" : ""}://${this.host}:${ + this.port } ...` ); @@ -207,11 +208,15 @@ export class KuzzleSDK { public queryHttpStream(request: JSONObject): Promise { // Ensure the protocol is HTTP if (this.protocol !== "http") { - throw new TypeError("HTTP streaming is only available with the HTTP protocol"); + throw new TypeError( + "HTTP streaming is only available with the HTTP protocol" + ); } // Construct the URL - const url = `${this.ssl ? "https" : "http"}://${this.host}:${this.port}/_query`; + const url = `${this.ssl ? "https" : "http"}://${this.host}:${ + this.port + }/_query`; // Construct the request const body = JSON.stringify(request); @@ -219,7 +224,10 @@ export class KuzzleSDK { const options = { method: "POST", headers: { - "Authorization": `Bearer ${this.sdk.jwt}`, + Accept: "application/json", + "Accept-Encoding": "identity", + Authorization: `Bearer ${this.sdk.jwt}`, + Connection: "keep-alive", "Content-Length": Buffer.byteLength(body), "Content-Type": "application/json", }, @@ -230,7 +238,7 @@ export class KuzzleSDK { const httpModule = this.ssl ? https : http; const req = httpModule.request(url, options, (res) => { resolve(res); - }) + }); req.on("error", reject); diff --git a/src/support/restore-collection.ts b/src/support/restore-collection.ts index d18bdc56..42d4ac22 100644 --- a/src/support/restore-collection.ts +++ b/src/support/restore-collection.ts @@ -1,25 +1,22 @@ -import fs from "fs"; +import fs, { write } from "fs"; import chalk from "chalk"; import ndjson from "ndjson"; import { JSONObject } from "kuzzle-sdk"; function handleError(log: any, dumpFile: string, error: any) { - if (error.status === 206) { + if (error.errors) { const errorFile = `${dumpFile .split(".") .slice(0, -1) .join(".")}-errors.jsonl`; const writeStream = fs.createWriteStream(errorFile, { flags: "a" }); - const serialize = ndjson.stringify().pipe(writeStream); - - serialize.on("data", (line: string) => writeStream.write(line)); for (const partialError of error.errors) { - serialize.write(partialError); + writeStream.write(JSON.stringify(partialError) + '\n'); } - serialize.end(); + writeStream.end(); log( chalk.red(`[X] Error importing ${dumpFile}. See errors in ${errorFile}`) @@ -44,6 +41,7 @@ export async function restoreCollectionData( action: "mWrite", index: "", collection: "", + strict: true, body: { documents: [{}], }, @@ -110,8 +108,8 @@ export async function restoreCollectionData( sdk .query(mWriteRequest) - .then(() => { - total += mWriteRequest.body.documents.length; + .then((response: JSONObject) => { + total += response.result.successes.length; process.stdout.write(` ${total} documents imported`); process.stdout.write("\r"); diff --git a/test/commands/app/scaffold.test.ts b/test/commands/app/scaffold.test.ts index cda9bc62..a7bd112c 100644 --- a/test/commands/app/scaffold.test.ts +++ b/test/commands/app/scaffold.test.ts @@ -5,7 +5,7 @@ import should from "should"; import { kourou } from "../../support"; describe("app:scaffold", () => { - it("creates desired files and install packages", () => { + it("should create generic flavor if not specified", () => { execSync("rm -rf blackmesa/"); kourou("app:scaffold blackmesa"); @@ -13,10 +13,44 @@ describe("app:scaffold", () => { should(fs.existsSync("./blackmesa/.eslintignore")).be.eql(true); should(fs.existsSync("./blackmesa/.eslintrc.json")).be.eql(true); should(fs.existsSync("./blackmesa/.gitignore")).be.eql(true); - should(fs.existsSync("./blackmesa/.mocharc.json")).be.eql(true); + should(fs.existsSync("./blackmesa/Dockerfile")).be.eql(true); + should(fs.existsSync("./blackmesa/docker-compose.yml")).be.eql(true); should(fs.existsSync("./blackmesa/app.ts")).be.eql(true); should(fs.existsSync("./blackmesa/package.json")).be.eql(true); should(fs.existsSync("./blackmesa/README.md")).be.eql(true); should(fs.existsSync("./blackmesa/tsconfig.json")).be.eql(true); + should(fs.existsSync("./blackmesa/jest.config.ts")).be.eql(true); + }).timeout("60s"); + + it("should create generic flavor when specified", () => { + execSync("rm -rf blackmesa/"); + + kourou("app:scaffold blackmesa --flavor generic"); + + should(fs.existsSync("./blackmesa/.eslintignore")).be.eql(true); + should(fs.existsSync("./blackmesa/.eslintrc.json")).be.eql(true); + should(fs.existsSync("./blackmesa/.gitignore")).be.eql(true); + should(fs.existsSync("./blackmesa/Dockerfile")).be.eql(true); + should(fs.existsSync("./blackmesa/docker-compose.yml")).be.eql(true); + should(fs.existsSync("./blackmesa/app.ts")).be.eql(true); + should(fs.existsSync("./blackmesa/package.json")).be.eql(true); + should(fs.existsSync("./blackmesa/README.md")).be.eql(true); + should(fs.existsSync("./blackmesa/tsconfig.json")).be.eql(true); + should(fs.existsSync("./blackmesa/jest.config.ts")).be.eql(true); + }).timeout("60s"); + + it("should create iot flavor when specified", () => { + execSync("rm -rf blackmesa/"); + + kourou("app:scaffold blackmesa --flavor iot"); + + should(fs.existsSync("./blackmesa/tsconfig.node.json")).be.eql(true); + should(fs.existsSync("./blackmesa/tsconfig.web.json")).be.eql(true); + should(fs.existsSync("./blackmesa/.gitignore")).be.eql(true); + should(fs.existsSync("./blackmesa/docker-compose.yml")).be.eql(true); + should(fs.existsSync("./blackmesa/package.json")).be.eql(true); + should(fs.existsSync("./blackmesa/README.md")).be.eql(true); + should(fs.existsSync("./blackmesa/turbo.json")).be.eql(true); + should(fs.existsSync("./blackmesa/start.sh")).be.eql(true); }).timeout("60s"); }); diff --git a/test/support.ts b/test/support.ts index d1aebd29..21b9709a 100644 --- a/test/support.ts +++ b/test/support.ts @@ -9,7 +9,7 @@ export function kourou(command: string) { } catch (error: any) { console.log(error); console.log("STDOUT: ", error.stdout.toString()); - console.log("STDOUT: ", error.stderr.toString()); + console.log("STDERR: ", error.stderr.toString()); throw error; } }