@nzz/q-cli 1.10.2 → 2.0.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/dist/index.js +79 -0
  2. package/dist/interfaces.js +1 -0
  3. package/dist/newCustomCode.js +106 -0
  4. package/dist/updateItem.js +191 -0
  5. package/dist/utils.js +11 -0
  6. package/package.json +27 -36
  7. package/.nvmrc +0 -1
  8. package/.travis.yml +0 -17
  9. package/.vscode/launch.json +0 -36
  10. package/.vscode/settings.json +0 -5
  11. package/LICENSE +0 -21
  12. package/README.md +0 -360
  13. package/bin/commands/bootstrap.js +0 -68
  14. package/bin/commands/qItem/configStore.js +0 -144
  15. package/bin/commands/qItem/copyItem/copyItem.js +0 -103
  16. package/bin/commands/qItem/copyItem/copySchema.json +0 -37
  17. package/bin/commands/qItem/createCustomCodeItem/createCustomCodeItem.js +0 -70
  18. package/bin/commands/qItem/createCustomCodeItem/schema.json +0 -41
  19. package/bin/commands/qItem/helpers.js +0 -102
  20. package/bin/commands/qItem/itemService.js +0 -310
  21. package/bin/commands/qItem/resourcesService.js +0 -148
  22. package/bin/commands/qItem/schemaService.js +0 -65
  23. package/bin/commands/qItem/updateItem/updateItem.js +0 -64
  24. package/bin/commands/server.js +0 -80
  25. package/bin/q.js +0 -213
  26. package/dev-server/config/default.js +0 -51
  27. package/dev-server/public/favicon.ico +0 -0
  28. package/dev-server/public/style.css +0 -64
  29. package/dev-server/routes/dev-view.js +0 -52
  30. package/dev-server/routes/file.js +0 -10
  31. package/dev-server/routes/rendering-info.js +0 -130
  32. package/dev-server/routes/routes.js +0 -6
  33. package/dev-server/routes/tool-default.js +0 -108
  34. package/dev-server/server-plugins.js +0 -1
  35. package/dev-server/server.js +0 -18
  36. package/dev-server/views/index.html +0 -184
  37. package/skeletons/custom-code-skeleton/.nvmrc +0 -1
  38. package/skeletons/custom-code-skeleton/.vscode/settings.json +0 -5
  39. package/skeletons/custom-code-skeleton/README.md +0 -26
  40. package/skeletons/custom-code-skeleton/index.d.ts +0 -3
  41. package/skeletons/custom-code-skeleton/package-lock.json +0 -7355
  42. package/skeletons/custom-code-skeleton/package.json +0 -46
  43. package/skeletons/custom-code-skeleton/q.config.json +0 -60
  44. package/skeletons/custom-code-skeleton/rollup.config.js +0 -185
  45. package/skeletons/custom-code-skeleton/src/App.scss +0 -5
  46. package/skeletons/custom-code-skeleton/src/App.svelte +0 -7
  47. package/skeletons/custom-code-skeleton/src/enums.ts +0 -0
  48. package/skeletons/custom-code-skeleton/src/interfaces.ts +0 -0
  49. package/skeletons/custom-code-skeleton/src/main-prod.ts +0 -4
  50. package/skeletons/custom-code-skeleton/src/main.scss +0 -1
  51. package/skeletons/custom-code-skeleton/src/main.ts +0 -18
  52. package/skeletons/custom-code-skeleton/tsconfig.json +0 -16
  53. package/skeletons/et-utils-package-skeleton/.nvmrc +0 -1
  54. package/skeletons/et-utils-package-skeleton/README.md +0 -12
  55. package/skeletons/et-utils-package-skeleton/jest.config.ts +0 -17
  56. package/skeletons/et-utils-package-skeleton/package-lock.json +0 -3969
  57. package/skeletons/et-utils-package-skeleton/package.json +0 -40
  58. package/skeletons/et-utils-package-skeleton/scripts/package-fixup.sh +0 -13
  59. package/skeletons/et-utils-package-skeleton/src/Service.ts +0 -8
  60. package/skeletons/et-utils-package-skeleton/src/index.ts +0 -4
  61. package/skeletons/et-utils-package-skeleton/test/Service.spec.ts +0 -10
  62. package/skeletons/et-utils-package-skeleton/test/tsconfig.json +0 -8
  63. package/skeletons/et-utils-package-skeleton/tsconfig-base.json +0 -10
  64. package/skeletons/et-utils-package-skeleton/tsconfig-cjs.json +0 -8
  65. package/skeletons/et-utils-package-skeleton/tsconfig.json +0 -8
  66. package/skeletons/server-skeleton/.nvmrc +0 -1
  67. package/skeletons/server-skeleton/Dockerfile +0 -19
  68. package/skeletons/server-skeleton/auth/routes.js +0 -85
  69. package/skeletons/server-skeleton/auth/strategyOptions.js +0 -28
  70. package/skeletons/server-skeleton/config/base.js +0 -45
  71. package/skeletons/server-skeleton/config/db.js +0 -6
  72. package/skeletons/server-skeleton/config/editor.js +0 -105
  73. package/skeletons/server-skeleton/config/rendering-info.js +0 -70
  74. package/skeletons/server-skeleton/config/screenshot.js +0 -80
  75. package/skeletons/server-skeleton/config/targets.js +0 -31
  76. package/skeletons/server-skeleton/config/tools.js +0 -65
  77. package/skeletons/server-skeleton/files/favicon.png +0 -0
  78. package/skeletons/server-skeleton/files/system.js +0 -3612
  79. package/skeletons/server-skeleton/index.js +0 -106
  80. package/skeletons/server-skeleton/package-lock.json +0 -1825
  81. package/skeletons/server-skeleton/package.json +0 -29
  82. package/skeletons/tool-skeleton/.dockerignore +0 -1
  83. package/skeletons/tool-skeleton/.nvmrc +0 -1
  84. package/skeletons/tool-skeleton/.travis.yml +0 -26
  85. package/skeletons/tool-skeleton/.vscode/settings.json +0 -5
  86. package/skeletons/tool-skeleton/Dockerfile +0 -19
  87. package/skeletons/tool-skeleton/LICENSE +0 -20
  88. package/skeletons/tool-skeleton/README.md +0 -104
  89. package/skeletons/tool-skeleton/index.js +0 -32
  90. package/skeletons/tool-skeleton/package-lock.json +0 -10108
  91. package/skeletons/tool-skeleton/package.json +0 -45
  92. package/skeletons/tool-skeleton/resources/display-options-schema.json +0 -11
  93. package/skeletons/tool-skeleton/resources/fixtures/data/basic.json +0 -4
  94. package/skeletons/tool-skeleton/resources/locales/de/translation.json +0 -1
  95. package/skeletons/tool-skeleton/resources/locales/en/translation.json +0 -1
  96. package/skeletons/tool-skeleton/resources/locales/fr/translation.json +0 -1
  97. package/skeletons/tool-skeleton/resources/schema.json +0 -16
  98. package/skeletons/tool-skeleton/rollup.config.js +0 -75
  99. package/skeletons/tool-skeleton/routes/fixtures/data.js +0 -15
  100. package/skeletons/tool-skeleton/routes/health.js +0 -10
  101. package/skeletons/tool-skeleton/routes/locales.js +0 -21
  102. package/skeletons/tool-skeleton/routes/rendering-info/web.js +0 -97
  103. package/skeletons/tool-skeleton/routes/routes.js +0 -8
  104. package/skeletons/tool-skeleton/routes/schema.js +0 -19
  105. package/skeletons/tool-skeleton/routes/script.js +0 -17
  106. package/skeletons/tool-skeleton/routes/stylesheet.js +0 -17
  107. package/skeletons/tool-skeleton/sass.config.js +0 -66
  108. package/skeletons/tool-skeleton/scripts_src/default.js +0 -3
  109. package/skeletons/tool-skeleton/styles_src/_variables.scss +0 -1
  110. package/skeletons/tool-skeleton/styles_src/main.scss +0 -2
  111. package/skeletons/tool-skeleton/test/e2e-tests.js +0 -162
  112. package/skeletons/tool-skeleton/views/dynamic/YourTool.scss +0 -5
  113. package/skeletons/tool-skeleton/views/dynamic/YourTool.svelte +0 -19
  114. package/skeletons/tool-skeleton/views/static/App.scss +0 -5
  115. package/skeletons/tool-skeleton/views/static/App.svelte +0 -21
  116. package/skeletons/tool-skeleton/views/static/components/Footer.svelte +0 -31
  117. package/skeletons/tool-skeleton/views/static/components/Header.svelte +0 -7
  118. package/skeletons/toolv2-skeleton/.husky/pre-commit +0 -6
  119. package/skeletons/toolv2-skeleton/.nvmrc +0 -1
  120. package/skeletons/toolv2-skeleton/.prettierrc.cjs +0 -15
  121. package/skeletons/toolv2-skeleton/.travis.yml +0 -30
  122. package/skeletons/toolv2-skeleton/.vscode/settings.json +0 -6
  123. package/skeletons/toolv2-skeleton/Dockerfile +0 -19
  124. package/skeletons/toolv2-skeleton/LICENSE +0 -21
  125. package/skeletons/toolv2-skeleton/README.md +0 -99
  126. package/skeletons/toolv2-skeleton/dev.js +0 -7
  127. package/skeletons/toolv2-skeleton/index.js +0 -39
  128. package/skeletons/toolv2-skeleton/jest.config.ts +0 -39
  129. package/skeletons/toolv2-skeleton/nodemon.json +0 -4
  130. package/skeletons/toolv2-skeleton/package-lock.json +0 -21382
  131. package/skeletons/toolv2-skeleton/package.json +0 -80
  132. package/skeletons/toolv2-skeleton/resources/display-options-schema.json +0 -11
  133. package/skeletons/toolv2-skeleton/resources/locales/de/translation.json +0 -8
  134. package/skeletons/toolv2-skeleton/resources/locales/en/translation.json +0 -10
  135. package/skeletons/toolv2-skeleton/resources/locales/fr/translation.json +0 -10
  136. package/skeletons/toolv2-skeleton/resources/schema.json +0 -66
  137. package/skeletons/toolv2-skeleton/rollup.config.js +0 -48
  138. package/skeletons/toolv2-skeleton/scripts/postinstall.sh +0 -5
  139. package/skeletons/toolv2-skeleton/src/.eslintrc.cjs +0 -52
  140. package/skeletons/toolv2-skeleton/src/components/Main.spec.ts +0 -15
  141. package/skeletons/toolv2-skeleton/src/components/Main.svelte +0 -32
  142. package/skeletons/toolv2-skeleton/src/enums.ts +0 -11
  143. package/skeletons/toolv2-skeleton/src/helpers/fixture-generators.ts +0 -38
  144. package/skeletons/toolv2-skeleton/src/helpers/toolRuntimeConfig.ts +0 -15
  145. package/skeletons/toolv2-skeleton/src/interfaces.ts +0 -82
  146. package/skeletons/toolv2-skeleton/src/modules.d.ts +0 -8
  147. package/skeletons/toolv2-skeleton/src/routes/dynamic-schemas/exampleDynamicSchema.ts +0 -49
  148. package/skeletons/toolv2-skeleton/src/routes/dynamic-schemas/index.ts +0 -5
  149. package/skeletons/toolv2-skeleton/src/routes/health.ts +0 -14
  150. package/skeletons/toolv2-skeleton/src/routes/locales.ts +0 -31
  151. package/skeletons/toolv2-skeleton/src/routes/notifications/exampleNotification.ts +0 -46
  152. package/skeletons/toolv2-skeleton/src/routes/option-availability.ts +0 -27
  153. package/skeletons/toolv2-skeleton/src/routes/rendering-info/web.ts +0 -150
  154. package/skeletons/toolv2-skeleton/src/routes/routes.ts +0 -21
  155. package/skeletons/toolv2-skeleton/src/routes/schema.ts +0 -21
  156. package/skeletons/toolv2-skeleton/src/routes/stylesheet.ts +0 -31
  157. package/skeletons/toolv2-skeleton/src/styles/main.scss +0 -6
  158. package/skeletons/toolv2-skeleton/svelte.config.cjs +0 -6
  159. package/skeletons/toolv2-skeleton/tasks/compileStyleFiles.cjs +0 -101
  160. package/skeletons/toolv2-skeleton/tests/e2e-tests.spec.ts +0 -158
  161. package/skeletons/toolv2-skeleton/tests/helpers.ts +0 -21
  162. package/skeletons/toolv2-skeleton/tsconfig.json +0 -48
  163. /package/{bin/commands/qItem/updateItem → dist/assets}/updateSchema.json +0 -0
package/dist/index.js ADDED
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env node
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ import { Command } from 'commander';
12
+ import updateItem from './updateItem.js';
13
+ import newCustomCode from './newCustomCode.js';
14
+ import packageJson from '../package.json' with { type: 'json' };
15
+ const program = new Command();
16
+ // Get the version from the package.json file
17
+ const version = packageJson.version;
18
+ function main() {
19
+ return __awaiter(this, void 0, void 0, function* () {
20
+ program.version(version).description('Q Toolbox cli');
21
+ program
22
+ .command('new-custom-code')
23
+ .option('-d, --dir [path]', 'the base directory to bootstrap the new custom code project in')
24
+ .description('bootstrap a new custom code project')
25
+ .action((command) => {
26
+ newCustomCode(command.dir);
27
+ });
28
+ program
29
+ .command('new-et-utils-package')
30
+ .option('-d, --dir [path]', 'the base directory to bootstrap the new tool in, defaults to the tools name')
31
+ .description('bootstrap a new ed-tech utility package')
32
+ .action(() => __awaiter(this, void 0, void 0, function* () {
33
+ // const name = program.args[1];
34
+ // const author = program.args[2] || 'TODO: Set package author name';
35
+ // const description = program.args[3] || 'TODO: Write a package description';
36
+ // if (!name) {
37
+ // console.error(errorColor('no package name given'));
38
+ // process.exit(1);
39
+ // }
40
+ // const baseDir = program.dir || name;
41
+ // const textReplacements = [
42
+ // { regex: new RegExp('<package-name>', 'g'), replaceWith: name },
43
+ // { regex: new RegExp('<author-name>', 'g'), replaceWith: author },
44
+ // {
45
+ // regex: new RegExp('<package-description>', 'g'),
46
+ // replaceWith: description,
47
+ // },
48
+ // ];
49
+ // await bootstrap('et-utils-package', baseDir, textReplacements);
50
+ }));
51
+ program
52
+ .command('update-item')
53
+ .description('update q item')
54
+ .option('-c, --config [path]', 'set config path which defines the q items to be updated. defaults to ./q.config.json', `${process.cwd()}/q.config.json`)
55
+ .option('-e, --environment [env]', 'set environment which should be updated, defaults to update all items of all environments defined in config')
56
+ .action((command) => __awaiter(this, void 0, void 0, function* () {
57
+ yield updateItem(command);
58
+ }));
59
+ program
60
+ .command('copy-item')
61
+ .description('copies an existing q item')
62
+ .option('-c, --config [path]', 'set config path which defines the q items to be copied. defaults to ./q.config.json', `${process.cwd()}/q.config.json`)
63
+ .option('-e, --environment [env]', 'set environment where the existing q item is found, defaults to copy all items of all environments defined in config')
64
+ .action((command) => __awaiter(this, void 0, void 0, function* () {
65
+ // await copyItem(command);
66
+ }));
67
+ program
68
+ .command('create-custom-code-item')
69
+ .description('creates a new q custom code item in the db and adds it to the q config file')
70
+ .option('-c, --config [path]', 'set config path to q.config.json. defaults to ./q.config.json', `${process.cwd()}/q.config.json`)
71
+ .option('-e, --environment [env]', 'set environment where the new q custom code item should be created in')
72
+ .option('-t, --title [title]', 'set title of the new q custom code item')
73
+ .action((command) => __awaiter(this, void 0, void 0, function* () {
74
+ // await createCustomCodeItem(command);
75
+ }));
76
+ yield program.parseAsync(process.argv);
77
+ });
78
+ }
79
+ main();
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,106 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { execSync } from 'child_process';
4
+ import { logError, logSuccess } from './utils.js';
5
+ export default function newCustomCode(dir) {
6
+ if (!dir) {
7
+ logError('No custom-code project name/directory given');
8
+ process.exit(1);
9
+ }
10
+ if (fs.existsSync(dir)) {
11
+ logError(`Directory ${dir} already exists`);
12
+ process.exit(1);
13
+ }
14
+ const skeletonDir = 'skeletons';
15
+ const skeletonCustomCodeDir = path.join(skeletonDir, 'custom-code-project');
16
+ try {
17
+ // Create the target directory
18
+ fs.mkdirSync(dir);
19
+ // Change to the target directory
20
+ process.chdir(dir);
21
+ // Initialize git repository to pull the skeletons/custom-code-project content into a separate directory
22
+ console.log('Initializing git repository...');
23
+ execSync('git init');
24
+ execSync('git remote add origin https://github.com/nzzdev/Q.git');
25
+ // Enable sparse checkout and pull the content from remote
26
+ console.log(`Sparse checkout ${skeletonCustomCodeDir}...`);
27
+ execSync('git sparse-checkout init --cone');
28
+ execSync(`git sparse-checkout set ${skeletonCustomCodeDir}`);
29
+ console.log('Pulling content from remote...');
30
+ execSync('git pull origin edtech-965-cli-porting');
31
+ // Remove all files, except the skeletons directory
32
+ console.log('Cleaning up...');
33
+ const cwdFiles = fs.readdirSync(process.cwd());
34
+ for (const file of cwdFiles) {
35
+ if (file === skeletonDir)
36
+ continue; // Skip the skeletons directory
37
+ const filePath = path.join(process.cwd(), file);
38
+ if (fs.statSync(filePath).isDirectory()) {
39
+ fs.rmSync(filePath, { recursive: true, force: true });
40
+ }
41
+ else {
42
+ fs.unlinkSync(filePath);
43
+ }
44
+ }
45
+ // Copy the skeletons/custom-code-project content to the root
46
+ const cwdSkeletonCustomCodeDir = path.join(process.cwd(), skeletonCustomCodeDir);
47
+ const skeletonFiles = fs.readdirSync(cwdSkeletonCustomCodeDir);
48
+ for (const file of skeletonFiles) {
49
+ const srcFilePath = path.join(cwdSkeletonCustomCodeDir, file);
50
+ const targetFilePath = path.join(process.cwd(), file);
51
+ if (fs.statSync(srcFilePath).isDirectory()) {
52
+ fs.cpSync(srcFilePath, targetFilePath, { recursive: true });
53
+ }
54
+ else {
55
+ fs.copyFileSync(srcFilePath, targetFilePath);
56
+ }
57
+ }
58
+ // Remove the now empty skeletons directory
59
+ fs.rmSync(path.join(process.cwd(), skeletonDir), { recursive: true, force: true });
60
+ // Update the package.json and q.config.json files with the custom code project name
61
+ const customCodeProjectName = path.basename(dir);
62
+ updateJsonValue(path.join(process.cwd(), 'package.json'), 'name', customCodeProjectName);
63
+ updateJsonValue(path.join(process.cwd(), 'q.config.json'), 'items.0.item.trackingComponent.componentInfo.componentName', customCodeProjectName);
64
+ logSuccess(`Successfully created new custom code project '${dir}'`);
65
+ }
66
+ catch (error) {
67
+ logError(error.message);
68
+ process.exit(1);
69
+ }
70
+ }
71
+ /**
72
+ * Reads a JSON file, updates a specific value, and writes the changes back to the file
73
+ * @param filePath - Path to the JSON file
74
+ * @param keyPath - Path to the key to update (use dot notation for nested objects, e.g., 'parent.child')
75
+ * @param newValue - New value to set
76
+ * @returns boolean indicating success
77
+ */
78
+ function updateJsonValue(filePath, keyPath, newValue) {
79
+ try {
80
+ // Read the JSON file
81
+ const jsonContent = JSON.parse(fs.readFileSync(filePath, 'utf8'));
82
+ // Split the key path into parts for nested objects
83
+ const keys = keyPath.split('.');
84
+ let current = jsonContent;
85
+ // Navigate to the parent of the target property
86
+ for (let i = 0; i < keys.length - 1; i++) {
87
+ if (!(keys[i] in current)) {
88
+ throw new Error(`Key path ${keyPath} not found in JSON file`);
89
+ }
90
+ current = current[keys[i]];
91
+ }
92
+ // Update the value
93
+ const lastKey = keys[keys.length - 1];
94
+ if (!(lastKey in current)) {
95
+ throw new Error(`Key ${lastKey} not found in JSON file`);
96
+ }
97
+ current[lastKey] = newValue;
98
+ // Write the updated JSON back to the file
99
+ fs.writeFileSync(filePath, JSON.stringify(jsonContent, null, 2));
100
+ return true;
101
+ }
102
+ catch (error) {
103
+ logError('Error updating JSON file:' + error.message);
104
+ return false;
105
+ }
106
+ }
@@ -0,0 +1,191 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import Ajv from 'ajv';
11
+ import { readFileSync, existsSync, createReadStream } from 'fs';
12
+ import { resolve } from 'path';
13
+ import { read } from '@1password/op-js';
14
+ import FormData from 'form-data';
15
+ import fetch from 'node-fetch'; // Use node-fetch instead of native fetch, because native fetch seems to have issues with FormData/uploading files
16
+ import { logError, logSuccess } from './utils.js';
17
+ import updateSchemaJson from './assets/updateSchema.json' with { type: 'json' };
18
+ function readSecret(reference) {
19
+ try {
20
+ return read.parse(reference);
21
+ }
22
+ catch (error) {
23
+ logError(`Error occurred while reading the secret: ${error.message}`);
24
+ process.exit(1);
25
+ }
26
+ }
27
+ function validateConfig(metaSchema, qConfig) {
28
+ const ajv = new Ajv({ allErrors: true });
29
+ let isValid = true;
30
+ let errorsText = '';
31
+ try {
32
+ isValid = ajv.validate(metaSchema, qConfig);
33
+ errorsText = ajv.errorsText();
34
+ }
35
+ catch (error) {
36
+ isValid = false;
37
+ errorsText = `Error occurred while validating the config file: ${error.message}`;
38
+ }
39
+ return {
40
+ isValid,
41
+ errorsText,
42
+ };
43
+ }
44
+ // Use type predicate to check response type
45
+ function isAuthError(data) {
46
+ return 'error' in data;
47
+ }
48
+ function updateItem(qDoc, qServerUrl, accessToken) {
49
+ return __awaiter(this, void 0, void 0, function* () {
50
+ let data;
51
+ try {
52
+ const response = yield fetch(`${qServerUrl}/item`, {
53
+ method: 'POST',
54
+ body: JSON.stringify(qDoc),
55
+ headers: {
56
+ 'user-agent': 'Q Command-line Tool',
57
+ Authorization: `Bearer ${accessToken}`,
58
+ 'Content-Type': 'application/json',
59
+ },
60
+ });
61
+ data = (yield response.json());
62
+ }
63
+ catch (error) {
64
+ if (error instanceof TypeError && error.message.includes('fetch failed')) {
65
+ logError('Network request failed: Unable to connect to the server. Please check your internet connection and server status.');
66
+ }
67
+ else {
68
+ logError(`Failed to update item: ${error instanceof Error ? error.message : String(error)}`);
69
+ }
70
+ return false;
71
+ }
72
+ if (isAuthError(data)) {
73
+ logError(`Authentication error: ${data.error}`);
74
+ return false;
75
+ }
76
+ if (!data.success) {
77
+ logError(`Error occurred while updating item: ${data.msg}`);
78
+ return false;
79
+ }
80
+ return true;
81
+ });
82
+ }
83
+ function uploadFile(path, qServerUrl, accessToken) {
84
+ return __awaiter(this, void 0, void 0, function* () {
85
+ const localFilePath = resolve(path);
86
+ // Check if the file exists
87
+ if (!existsSync(localFilePath)) {
88
+ logError(`File not found: ${localFilePath}`);
89
+ return undefined;
90
+ }
91
+ try {
92
+ const form = new FormData();
93
+ // Read the file
94
+ const fileStream = createReadStream(localFilePath);
95
+ // Append the file to the form
96
+ form.append('file', fileStream);
97
+ // Upload the file to the server
98
+ const response = yield fetch(`${qServerUrl}/file`, {
99
+ method: 'POST',
100
+ body: form,
101
+ headers: Object.assign(Object.assign({}, form.getHeaders()), { 'user-agent': 'Q Command-line Tool', Authorization: `Bearer ${accessToken}` }),
102
+ });
103
+ const data = (yield response.json());
104
+ if (!data.apiResponseStatus.success) {
105
+ logError(`Failed to upload file: ${data.apiResponseStatus.msg}`);
106
+ return undefined;
107
+ }
108
+ logSuccess(`Successfully uploaded file: ${localFilePath}`);
109
+ return data.fileInfo;
110
+ }
111
+ catch (error) {
112
+ logError(`Error uploading file: ${error instanceof Error ? error.message : String(error)}`);
113
+ }
114
+ });
115
+ }
116
+ /**
117
+ * Recursively processes a document structure, looking for 'path' properties
118
+ * and processing them with the processResource function.
119
+ *
120
+ * @param item The object or value to process
121
+ * @param processResource Function to handle path properties
122
+ * @returns The processed item
123
+ */
124
+ function processPathProperties(item, processResource) {
125
+ return __awaiter(this, void 0, void 0, function* () {
126
+ // Base case: if item is null or not an object, return it unchanged
127
+ if (item === null || typeof item !== 'object') {
128
+ return item;
129
+ }
130
+ // Handle arrays
131
+ if (Array.isArray(item)) {
132
+ return yield Promise.all(item.map((element) => __awaiter(this, void 0, void 0, function* () { return yield processPathProperties(element, processResource); })));
133
+ }
134
+ // Check if this object has a 'path' property (using Object.prototype.hasOwnProperty.call to avoid prototype pollution)
135
+ if (Object.prototype.hasOwnProperty.call(item, 'path') && typeof item.path === 'string') {
136
+ return yield processResource(item.path);
137
+ }
138
+ // Process each property recursively
139
+ const result = Object.assign({}, item);
140
+ for (const key of Object.keys(item)) {
141
+ result[key] = yield processPathProperties(item[key], processResource);
142
+ }
143
+ return result;
144
+ });
145
+ }
146
+ export default function (command) {
147
+ return __awaiter(this, void 0, void 0, function* () {
148
+ const qConfigPath = resolve(command.config);
149
+ if (!existsSync(qConfigPath)) {
150
+ logError(`Couldn't find config file: '${qConfigPath}'.\nCreate a config file in the current directory or pass the path to the config file with the option -c <path>`);
151
+ return;
152
+ }
153
+ const qConfig = JSON.parse(readFileSync(qConfigPath, 'utf-8'));
154
+ const validationResult = validateConfig(updateSchemaJson, qConfig); // Validate the config file against the schema
155
+ if (!validationResult.isValid) {
156
+ logError(`A problem occurred while validating the config file: ${validationResult.errorsText}`);
157
+ process.exit(1);
158
+ }
159
+ // Get the Q server URL and access token from the environment variables or 1Password
160
+ const envUpperCase = command.environment.toUpperCase();
161
+ const envLowerCase = command.environment.toLowerCase();
162
+ const qServerUrl = process.env[`Q_${envUpperCase}_SERVER`]
163
+ ? process.env[`Q_${envUpperCase}_SERVER`]
164
+ : readSecret(`op://Q CLI/qv2-${envLowerCase}/Q_SERVER_BASE_URL`);
165
+ const accessToken = process.env[`Q_${envUpperCase}_ACCESSTOKEN`]
166
+ ? process.env[`Q_${envUpperCase}_ACCESSTOKEN`]
167
+ : readSecret(`op://Q CLI/qv2-${envLowerCase}/CLI_AUTH_TOKEN`);
168
+ console.log(`Updating items on server ${qServerUrl}...`);
169
+ for (const item of qConfig.items) {
170
+ for (const environment of item.environments) {
171
+ // Skip if the environment is not the one we want to update
172
+ if (command.environment !== environment.name)
173
+ continue;
174
+ console.log(`Updating item ${environment.id} on ${environment.name} environment...`);
175
+ let qDoc = structuredClone(item.item);
176
+ qDoc._id = environment.id;
177
+ // Process the 'path' properties and upload files
178
+ qDoc = yield processPathProperties(qDoc, (path) => __awaiter(this, void 0, void 0, function* () {
179
+ const formattedPath = path.replace('{id}', environment.id);
180
+ console.log(`Processing resource at path: ${formattedPath}`);
181
+ return yield uploadFile(formattedPath, qServerUrl, accessToken);
182
+ }));
183
+ // Update the item on the Q server
184
+ const result = yield updateItem(qDoc, qServerUrl, accessToken);
185
+ if (result) {
186
+ logSuccess(`Successfully updated item with id ${environment.id} on ${environment.name} environment`);
187
+ }
188
+ }
189
+ }
190
+ });
191
+ }
package/dist/utils.js ADDED
@@ -0,0 +1,11 @@
1
+ const colors = {
2
+ green: '\x1b[32m',
3
+ reset: '\x1b[0m',
4
+ red: '\x1b[31m',
5
+ };
6
+ export function logError(message) {
7
+ console.error(`${colors.red}${message}${colors.reset}`);
8
+ }
9
+ export function logSuccess(message) {
10
+ console.log(`${colors.green}${message}${colors.reset}`);
11
+ }
package/package.json CHANGED
@@ -1,47 +1,38 @@
1
1
  {
2
2
  "name": "@nzz/q-cli",
3
- "version": "1.10.2",
4
- "prettier": "@nzz/et-utils-config-prettier",
5
- "description": "Cli tool to setup new Q tools, new Q server implementations and start Q dev server to test developing Q tools",
6
- "main": "index.js",
7
- "scripts": {
8
- "test": "echo \"Error: no test specified\" && exit 1"
9
- },
10
- "repository": {
11
- "type": "git",
12
- "url": "git+https://github.com/nzzdev/Q-cli.git"
13
- },
3
+ "version": "2.0.0-beta.7",
4
+ "description": "",
5
+ "main": "./src/index.ts",
6
+ "type": "module",
14
7
  "bin": {
15
- "Q": "bin/q.js"
8
+ "q": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc && npm run copy-assets",
15
+ "copy-assets": "cp -R src/assets dist/",
16
+ "update-item": "tsx ./src/index.ts update-item -e local -c ./tests/q.config.json",
17
+ "new-custom-code": "tsx ./src/index.ts new-custom-code -d my-custom-code-project",
18
+ "eslint": "TIMING=1 eslint --ext .svelte,.ts --config .eslintrc.cjs .",
19
+ "lint:all": "run-s -c tscheck lint svelte-check",
20
+ "tscheck": "tsc --noEmit"
16
21
  },
17
22
  "author": "",
18
23
  "license": "MIT",
19
- "bugs": {
20
- "url": "https://github.com/nzzdev/Q-cli/issues"
21
- },
22
- "homepage": "https://github.com/nzzdev/Q-cli#readme",
23
24
  "dependencies": {
24
- "@hapi/boom": "^9.1.1",
25
- "@hapi/hapi": "^20.3.0",
26
- "@hapi/inert": "^6.0.3",
27
- "@hapi/mimos": "^5.0.0",
28
- "@hapi/vision": "^6.1.0",
29
- "@hapi/wreck": "^17.1.0",
30
- "ajv": "^6.12.6",
31
- "chalk": "^4.1.1",
32
- "commander": "^5.1.0",
33
- "configstore": "^5.0.1",
34
- "deepmerge": "^4.3.1",
35
- "form-data": "^3.0.0",
36
- "fs-extra": "^9.0.1",
37
- "image-size": "^0.8.3",
38
- "joi": "^17.9.1",
39
- "node-fetch": "^2.6.9",
40
- "nunjucks": "^3.2.2",
41
- "promptly": "^3.2.0",
42
- "replace-in-file": "^3.4.4"
25
+ "@1password/op-js": "^0.1.13",
26
+ "ajv": "^8.17.1",
27
+ "commander": "^13.1.0",
28
+ "form-data": "^4.0.2",
29
+ "node-fetch": "^3.3.2"
43
30
  },
44
31
  "devDependencies": {
45
- "@nzz/et-utils-config-prettier": "^1.0.6"
32
+ "@repo/types-db": "workspace:^",
33
+ "@repo/types-files": "workspace:^",
34
+ "delivery-server": "workspace:*",
35
+ "typescript": "^5.2.2",
36
+ "vitest": "^0.34.6"
46
37
  }
47
38
  }
package/.nvmrc DELETED
@@ -1 +0,0 @@
1
- 14
package/.travis.yml DELETED
@@ -1,17 +0,0 @@
1
- dist: trusty
2
- sudo: true
3
- language: node_js
4
- node_js:
5
- - "14"
6
- cache:
7
- directories:
8
- - node_modules
9
- install:
10
- - cd ./skeletons/tool-skeleton
11
- - npm install
12
- script:
13
- - npm run build
14
- - npm run test
15
- notfications:
16
- slack:
17
- secure: cpd8v7VZ14SE1//jmd6mP+Gndo+htGzleW3E6RdnsEgz1ttAJLvIkx9HxtN2ppwwhQJTv3g4rZUGU2vXyyneRQAMak80tWK8zrhdShg0Yry47M1R24LZsPiwOUCaMLD8O26irSlWgAuwno1LUReiJLnssRDGj0CSW3o+ISp11G9Q338u9PzULhjFnD3lT4pv4u7RAPbTB6MLVjWe7eRxyXATn92HQCtKH5YdVjItbDS/HEZwZOHV+lwrQNu/w/wBqHoEDX4XCJnQdzTdUZdlXmSz/5AS10IlDw05U9P9YEO9toOMWQJunDaslpIhl7kuSkqYrWzb0X+wLVNyLVfA0vf8wQG31WHs5T+Ul2P/O9zm4NzgTCT2khfQaynUpE2Zh9p1asnUSYGN75M+GPYKOkHHdj6KKmZ2APsuggC42vyI7FrsOy0Af9wnaoKxsBfaM/XNxx0hoblRQaQ4RaUaNQ4cF1WwUg6ZOlfewjpFnDLmC+XJS8t6PSlIKgHdTsaJB9wA4xlYPU4JFGMVYGd15tRpGDz9mgQbIkKhAFsFF6PiuemTHSO17Zpij7WKFVZuyAcs6NLZieXNIUwjKrfEzaUV03mPuw2dlxIlzm2TbZrKE97SzNIND2XJ2HTfmIoJ/jL3OKwc3WdE76ypoUl9E5sqg7zRrU+wgZMBM1U4ytY=
@@ -1,36 +0,0 @@
1
- {
2
- // Use IntelliSense to learn about possible attributes.
3
- // Hover to view descriptions of existing attributes.
4
- // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
- "version": "0.2.0",
6
- "configurations": [
7
- {
8
- "type": "node",
9
- "request": "launch",
10
- "name": "Debug server command",
11
- "program": "${workspaceFolder}/bin/q.js",
12
- "args": ["server"]
13
- },
14
- {
15
- "type": "node",
16
- "request": "launch",
17
- "name": "Debug new-server command",
18
- "program": "${workspaceFolder}/bin/q.js",
19
- "args": ["new-server", "test-server"]
20
- },
21
- {
22
- "type": "node",
23
- "request": "launch",
24
- "name": "Debug new-tool command",
25
- "program": "${workspaceFolder}/bin/q.js",
26
- "args": ["new-tool", "test-tool"]
27
- },
28
- {
29
- "type": "node",
30
- "request": "launch",
31
- "name": "Debug update-item command",
32
- "program": "${workspaceFolder}/bin/q.js",
33
- "args": ["update-item"]
34
- }
35
- ]
36
- }
@@ -1,5 +0,0 @@
1
- {
2
- "[svelte]": {
3
- "editor.defaultFormatter": "svelte.svelte-vscode"
4
- }
5
- }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) NZZ Management AG
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.