@nzz/q-cli 2.0.0-beta.7 → 2.0.6
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.
- package/README.md +69 -0
- package/dist/createCustomCodeItem.js +74 -0
- package/dist/enums.js +7 -0
- package/dist/index.js +7 -36
- package/dist/newCustomCode.js +3 -2
- package/dist/updateItem.js +57 -64
- package/dist/utils.js +77 -0
- package/package.json +5 -3
package/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Q cli
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
```bash
|
6
|
+
npm install -g @nzz/q-cli
|
7
|
+
```
|
8
|
+
|
9
|
+
Some commands require certain environment variables. If you do not provide them, q cli tries to get them from your local 1Password installation. Make sure, that you have [1Password](https://1password.com/downloads/mac) installed.
|
10
|
+
|
11
|
+
## Development
|
12
|
+
|
13
|
+
```bash
|
14
|
+
pnpm i
|
15
|
+
```
|
16
|
+
|
17
|
+
There is a test script for each command in the `package.json`.
|
18
|
+
|
19
|
+
## GitHub Actions
|
20
|
+
|
21
|
+
To use the q cli in GitHub Actions there are special access tokens provided. You can find them in 1Password (vault: Q CLI). Editorial Tech manages those access tokens.
|
22
|
+
|
23
|
+
You will need to set the secrets in your GitHub repository under: `Settings > Secrets & variables > Actions > New repository secret`
|
24
|
+
|
25
|
+
Example:
|
26
|
+
|
27
|
+
```
|
28
|
+
- name: Run Q cli
|
29
|
+
run: Q update-item
|
30
|
+
env:
|
31
|
+
Q_STAGING_SERVER: ${{ secrets.Q_STAGING_SERVER }}
|
32
|
+
Q_STAGING_ACCESSTOKEN: ${{ secrets.Q_STAGING_ACCESSTOKEN }}
|
33
|
+
Q_PRODUCTION_SERVER: ${{ secrets.Q_PRODUCTION_SERVER }}
|
34
|
+
Q_PRODUCTION_ACCESSTOKEN: ${{ secrets.Q_PRODUCTION_ACCESSTOKEN }}
|
35
|
+
```
|
36
|
+
|
37
|
+
## Functionality
|
38
|
+
|
39
|
+
### Creating a new custom code project
|
40
|
+
|
41
|
+
Creates a new custom code project.
|
42
|
+
|
43
|
+
```bash
|
44
|
+
Q new-custom-code -d my-custom-code-project
|
45
|
+
```
|
46
|
+
|
47
|
+
### Creating a new custom code item
|
48
|
+
|
49
|
+
Creates a new custom code item on the specified environment and adds the id of the newly created item to the specified `q.config.json`.
|
50
|
+
|
51
|
+
`q.config.json`: By default q cli will look for the config file in the current directory, if no path is specified.
|
52
|
+
|
53
|
+
This command requires the environment variables `Q_[ENVIRONMENT]_SERVER` and `Q_[ENVIRONMENT]_ACCESSTOKEN`.
|
54
|
+
|
55
|
+
```bash
|
56
|
+
Q create-custom-code-item -e local -c ./tests/q.config.json -t 'TEST CUSTOM CODE ITEM'
|
57
|
+
```
|
58
|
+
|
59
|
+
### Updating existing Q items
|
60
|
+
|
61
|
+
Reads the specified `q.config.json` and updates all q items there.
|
62
|
+
|
63
|
+
`q.config.json`: By default q cli will look for the config file in the current directory, if no path is specified.
|
64
|
+
|
65
|
+
This command requires the environment variables `Q_[ENVIRONMENT]_SERVER` and `Q_[ENVIRONMENT]_ACCESSTOKEN`.
|
66
|
+
|
67
|
+
```bash
|
68
|
+
Q update-item -e local -c ./tests/q.config.json
|
69
|
+
```
|
@@ -0,0 +1,74 @@
|
|
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 { logSuccess, logError, updateItem, getAccessToken, getQServerUrl } from './utils.js';
|
11
|
+
import { readFileSync, existsSync, writeFileSync } from 'fs';
|
12
|
+
import { resolve } from 'path';
|
13
|
+
export default function (command) {
|
14
|
+
return __awaiter(this, void 0, void 0, function* () {
|
15
|
+
const qConfigPath = resolve(command.config);
|
16
|
+
if (!existsSync(qConfigPath)) {
|
17
|
+
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>`);
|
18
|
+
process.exit(1);
|
19
|
+
}
|
20
|
+
if (!command.environment) {
|
21
|
+
logError('Environment is required');
|
22
|
+
process.exit(1);
|
23
|
+
}
|
24
|
+
// Get the Q server URL and access token from the environment variables or 1Password
|
25
|
+
const qServerUrl = getQServerUrl(command.environment);
|
26
|
+
const accessToken = getAccessToken(command.environment);
|
27
|
+
const newCustomCodeDoc = {
|
28
|
+
acronym: 'Visuals',
|
29
|
+
assetGroups: [],
|
30
|
+
createdDate: '', // Will be set when saved
|
31
|
+
createdBy: 'editorial-tech@nzz.ch',
|
32
|
+
data: [],
|
33
|
+
// @ts-ignore
|
34
|
+
department: 'Visuals',
|
35
|
+
files: [],
|
36
|
+
options: {
|
37
|
+
previewDisabled: true,
|
38
|
+
},
|
39
|
+
// @ts-ignore
|
40
|
+
publication: 'nzz',
|
41
|
+
sophieModules: [],
|
42
|
+
title: command.title,
|
43
|
+
// @ts-ignore
|
44
|
+
tool: 'custom_code',
|
45
|
+
updatedDate: '', // Will be set when saved
|
46
|
+
updatedBy: 'editorial-tech@nzz.ch',
|
47
|
+
};
|
48
|
+
// Create the item on the Q server
|
49
|
+
const result = yield updateItem(newCustomCodeDoc, qServerUrl, accessToken);
|
50
|
+
if (!result.success) {
|
51
|
+
logError(result.msg);
|
52
|
+
process.exit(1);
|
53
|
+
}
|
54
|
+
const newCustomCodeDocId = result.id;
|
55
|
+
// Update the config file with the new item
|
56
|
+
const qConfig = JSON.parse(readFileSync(qConfigPath, 'utf-8'));
|
57
|
+
if (!qConfig.items) {
|
58
|
+
qConfig.items = [];
|
59
|
+
}
|
60
|
+
if (qConfig.items.length === 0) {
|
61
|
+
qConfig.items.push({
|
62
|
+
environments: [],
|
63
|
+
item: {}, // User needs to add the item later
|
64
|
+
});
|
65
|
+
}
|
66
|
+
const firstItem = qConfig.items[0];
|
67
|
+
firstItem.environments.push({
|
68
|
+
id: newCustomCodeDocId,
|
69
|
+
name: command.environment,
|
70
|
+
});
|
71
|
+
writeFileSync(qConfigPath, JSON.stringify(qConfig, null, 2));
|
72
|
+
logSuccess(`Successfully created item with id ${newCustomCodeDocId} on ${command.environment} environment`);
|
73
|
+
});
|
74
|
+
}
|
package/dist/enums.js
ADDED
package/dist/index.js
CHANGED
@@ -9,9 +9,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
9
9
|
});
|
10
10
|
};
|
11
11
|
import { Command } from 'commander';
|
12
|
+
import packageJson from '../package.json' with { type: 'json' };
|
12
13
|
import updateItem from './updateItem.js';
|
13
14
|
import newCustomCode from './newCustomCode.js';
|
14
|
-
import
|
15
|
+
import createCustomCodeItem from './createCustomCodeItem.js';
|
15
16
|
const program = new Command();
|
16
17
|
// Get the version from the package.json file
|
17
18
|
const version = packageJson.version;
|
@@ -20,34 +21,12 @@ function main() {
|
|
20
21
|
program.version(version).description('Q Toolbox cli');
|
21
22
|
program
|
22
23
|
.command('new-custom-code')
|
23
|
-
.
|
24
|
+
.argument('<path>', 'the base directory to bootstrap the new custom code project in')
|
24
25
|
.description('bootstrap a new custom code project')
|
25
|
-
.action((
|
26
|
-
|
26
|
+
.action(() => {
|
27
|
+
const dir = program.args[1];
|
28
|
+
newCustomCode({ dir });
|
27
29
|
});
|
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
30
|
program
|
52
31
|
.command('update-item')
|
53
32
|
.description('update q item')
|
@@ -56,14 +35,6 @@ function main() {
|
|
56
35
|
.action((command) => __awaiter(this, void 0, void 0, function* () {
|
57
36
|
yield updateItem(command);
|
58
37
|
}));
|
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
38
|
program
|
68
39
|
.command('create-custom-code-item')
|
69
40
|
.description('creates a new q custom code item in the db and adds it to the q config file')
|
@@ -71,7 +42,7 @@ function main() {
|
|
71
42
|
.option('-e, --environment [env]', 'set environment where the new q custom code item should be created in')
|
72
43
|
.option('-t, --title [title]', 'set title of the new q custom code item')
|
73
44
|
.action((command) => __awaiter(this, void 0, void 0, function* () {
|
74
|
-
|
45
|
+
yield createCustomCodeItem(command);
|
75
46
|
}));
|
76
47
|
yield program.parseAsync(process.argv);
|
77
48
|
});
|
package/dist/newCustomCode.js
CHANGED
@@ -2,7 +2,8 @@ import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
3
3
|
import { execSync } from 'child_process';
|
4
4
|
import { logError, logSuccess } from './utils.js';
|
5
|
-
export default function
|
5
|
+
export default function (command) {
|
6
|
+
const { dir } = command;
|
6
7
|
if (!dir) {
|
7
8
|
logError('No custom-code project name/directory given');
|
8
9
|
process.exit(1);
|
@@ -27,7 +28,7 @@ export default function newCustomCode(dir) {
|
|
27
28
|
execSync('git sparse-checkout init --cone');
|
28
29
|
execSync(`git sparse-checkout set ${skeletonCustomCodeDir}`);
|
29
30
|
console.log('Pulling content from remote...');
|
30
|
-
execSync('git pull origin
|
31
|
+
execSync('git pull origin main');
|
31
32
|
// Remove all files, except the skeletons directory
|
32
33
|
console.log('Cleaning up...');
|
33
34
|
const cwdFiles = fs.readdirSync(process.cwd());
|
package/dist/updateItem.js
CHANGED
@@ -10,19 +10,42 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
10
10
|
import Ajv from 'ajv';
|
11
11
|
import { readFileSync, existsSync, createReadStream } from 'fs';
|
12
12
|
import { resolve } from 'path';
|
13
|
-
import { read } from '@1password/op-js';
|
14
13
|
import FormData from 'form-data';
|
15
14
|
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';
|
15
|
+
import { getAccessToken, getQServerUrl, logError, logSuccess, updateItem } from './utils.js';
|
17
16
|
import updateSchemaJson from './assets/updateSchema.json' with { type: 'json' };
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
import { Environment } from './enums.js';
|
18
|
+
const envCredentials = {
|
19
|
+
[Environment.LOCAL]: {
|
20
|
+
qServerUrl: '',
|
21
|
+
accessToken: '',
|
22
|
+
},
|
23
|
+
[Environment.TEST]: {
|
24
|
+
qServerUrl: '',
|
25
|
+
accessToken: '',
|
26
|
+
},
|
27
|
+
[Environment.STAGING]: {
|
28
|
+
qServerUrl: '',
|
29
|
+
accessToken: '',
|
30
|
+
},
|
31
|
+
[Environment.PRODUCTION]: {
|
32
|
+
qServerUrl: '',
|
33
|
+
accessToken: '',
|
34
|
+
},
|
35
|
+
};
|
36
|
+
/**
|
37
|
+
* Get the Q server URL and access token from the environment variables or 1Password
|
38
|
+
* @param environment The environment to get the credentials for
|
39
|
+
* @returns The Q server URL and access token
|
40
|
+
*/
|
41
|
+
function getEnvCredentials(environment) {
|
42
|
+
if (envCredentials[environment].qServerUrl === '' || envCredentials[environment].accessToken === '') {
|
43
|
+
envCredentials[environment] = {
|
44
|
+
qServerUrl: getQServerUrl(environment),
|
45
|
+
accessToken: getAccessToken(environment),
|
46
|
+
};
|
25
47
|
}
|
48
|
+
return envCredentials[environment];
|
26
49
|
}
|
27
50
|
function validateConfig(metaSchema, qConfig) {
|
28
51
|
const ajv = new Ajv({ allErrors: true });
|
@@ -41,45 +64,6 @@ function validateConfig(metaSchema, qConfig) {
|
|
41
64
|
errorsText,
|
42
65
|
};
|
43
66
|
}
|
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
67
|
function uploadFile(path, qServerUrl, accessToken) {
|
84
68
|
return __awaiter(this, void 0, void 0, function* () {
|
85
69
|
const localFilePath = resolve(path);
|
@@ -156,22 +140,27 @@ export default function (command) {
|
|
156
140
|
logError(`A problem occurred while validating the config file: ${validationResult.errorsText}`);
|
157
141
|
process.exit(1);
|
158
142
|
}
|
159
|
-
|
160
|
-
|
161
|
-
|
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}...`);
|
143
|
+
let qServerUrl;
|
144
|
+
let accessToken;
|
145
|
+
let environmentToUpdate;
|
169
146
|
for (const item of qConfig.items) {
|
170
147
|
for (const environment of item.environments) {
|
171
|
-
//
|
172
|
-
if (command.environment
|
173
|
-
|
174
|
-
|
148
|
+
// If the environment is specified, use that environment
|
149
|
+
if (command.environment) {
|
150
|
+
// Skip if the environment is not the one we want to update
|
151
|
+
if (command.environment !== environment.name)
|
152
|
+
continue;
|
153
|
+
environmentToUpdate = command.environment;
|
154
|
+
}
|
155
|
+
else {
|
156
|
+
// Otherwise, use the environment from the config
|
157
|
+
environmentToUpdate = environment.name;
|
158
|
+
}
|
159
|
+
// Get the credentials for the current environment
|
160
|
+
const credentials = getEnvCredentials(environmentToUpdate);
|
161
|
+
qServerUrl = credentials.qServerUrl;
|
162
|
+
accessToken = credentials.accessToken;
|
163
|
+
console.log(`Updating item ${environment.id} on ${environmentToUpdate} environment (${qServerUrl})...`);
|
175
164
|
let qDoc = structuredClone(item.item);
|
176
165
|
qDoc._id = environment.id;
|
177
166
|
// Process the 'path' properties and upload files
|
@@ -182,8 +171,12 @@ export default function (command) {
|
|
182
171
|
}));
|
183
172
|
// Update the item on the Q server
|
184
173
|
const result = yield updateItem(qDoc, qServerUrl, accessToken);
|
185
|
-
if (result) {
|
186
|
-
logSuccess(`Successfully updated item with id ${environment.id} on ${
|
174
|
+
if (result.success) {
|
175
|
+
logSuccess(`Successfully updated item with id ${environment.id} on ${environmentToUpdate} environment`);
|
176
|
+
}
|
177
|
+
else {
|
178
|
+
logError(result.msg);
|
179
|
+
process.exit(1);
|
187
180
|
}
|
188
181
|
}
|
189
182
|
}
|
package/dist/utils.js
CHANGED
@@ -1,11 +1,88 @@
|
|
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 { read } from '@1password/op-js';
|
11
|
+
import fetch from 'node-fetch';
|
1
12
|
const colors = {
|
2
13
|
green: '\x1b[32m',
|
3
14
|
reset: '\x1b[0m',
|
4
15
|
red: '\x1b[31m',
|
5
16
|
};
|
17
|
+
export function getAccessToken(env) {
|
18
|
+
return process.env[`Q_${env.toUpperCase()}_ACCESSTOKEN`]
|
19
|
+
? process.env[`Q_${env.toUpperCase()}_ACCESSTOKEN`]
|
20
|
+
: readSecret(`op://Q CLI/qv2-${env.toLowerCase()}/CLI_AUTH_TOKEN`);
|
21
|
+
}
|
22
|
+
export function getQServerUrl(env) {
|
23
|
+
return process.env[`Q_${env.toUpperCase()}_SERVER`]
|
24
|
+
? process.env[`Q_${env.toUpperCase()}_SERVER`]
|
25
|
+
: readSecret(`op://Q CLI/qv2-${env.toLowerCase()}/Q_SERVER_BASE_URL`);
|
26
|
+
}
|
6
27
|
export function logError(message) {
|
7
28
|
console.error(`${colors.red}${message}${colors.reset}`);
|
8
29
|
}
|
9
30
|
export function logSuccess(message) {
|
10
31
|
console.log(`${colors.green}${message}${colors.reset}`);
|
11
32
|
}
|
33
|
+
export function updateItem(qDoc, qServerUrl, accessToken) {
|
34
|
+
return __awaiter(this, void 0, void 0, function* () {
|
35
|
+
const retVal = {
|
36
|
+
id: undefined,
|
37
|
+
msg: '',
|
38
|
+
success: false,
|
39
|
+
};
|
40
|
+
let data;
|
41
|
+
try {
|
42
|
+
const response = yield fetch(`${qServerUrl}/item`, {
|
43
|
+
method: 'POST',
|
44
|
+
body: JSON.stringify(qDoc),
|
45
|
+
headers: {
|
46
|
+
'user-agent': 'Q Command-line Tool',
|
47
|
+
Authorization: `Bearer ${accessToken}`,
|
48
|
+
'Content-Type': 'application/json',
|
49
|
+
},
|
50
|
+
});
|
51
|
+
data = (yield response.json());
|
52
|
+
}
|
53
|
+
catch (error) {
|
54
|
+
if (error instanceof TypeError && error.message.includes('fetch failed')) {
|
55
|
+
retVal.msg =
|
56
|
+
'Network request failed: Unable to connect to the server. Please check your internet connection and server status.';
|
57
|
+
}
|
58
|
+
else {
|
59
|
+
retVal.msg = `Failed to update item: ${error instanceof Error ? error.message : String(error)}`;
|
60
|
+
}
|
61
|
+
return retVal;
|
62
|
+
}
|
63
|
+
if (isAuthError(data)) {
|
64
|
+
retVal.msg = `Authentication error: ${data.error}`;
|
65
|
+
return retVal;
|
66
|
+
}
|
67
|
+
if (!data.success) {
|
68
|
+
retVal.msg = `Error occurred while updating item: ${data.msg}`;
|
69
|
+
return retVal;
|
70
|
+
}
|
71
|
+
retVal.success = true;
|
72
|
+
retVal.id = data.id; // If the item was created, we get the id from the response
|
73
|
+
return retVal;
|
74
|
+
});
|
75
|
+
}
|
76
|
+
// Use type predicate to check response type
|
77
|
+
function isAuthError(data) {
|
78
|
+
return 'error' in data;
|
79
|
+
}
|
80
|
+
function readSecret(reference) {
|
81
|
+
try {
|
82
|
+
return read.parse(reference);
|
83
|
+
}
|
84
|
+
catch (error) {
|
85
|
+
logError(`Error occurred while reading the secret: ${error.message}`);
|
86
|
+
process.exit(1);
|
87
|
+
}
|
88
|
+
}
|
package/package.json
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
{
|
2
2
|
"name": "@nzz/q-cli",
|
3
|
-
"version": "2.0.
|
3
|
+
"version": "2.0.6",
|
4
4
|
"description": "",
|
5
|
-
"main": "./src/index.ts",
|
6
5
|
"type": "module",
|
6
|
+
"main": "./src/index.ts",
|
7
7
|
"bin": {
|
8
|
-
"
|
8
|
+
"Q": "./dist/index.js"
|
9
9
|
},
|
10
10
|
"files": [
|
11
11
|
"dist"
|
@@ -13,6 +13,7 @@
|
|
13
13
|
"scripts": {
|
14
14
|
"build": "tsc && npm run copy-assets",
|
15
15
|
"copy-assets": "cp -R src/assets dist/",
|
16
|
+
"create-custom-code-item": "tsx ./src/index.ts create-custom-code-item -e local -c ./tests/q.config.json -t 'TEST CUSTOM CODE ITEM'",
|
16
17
|
"update-item": "tsx ./src/index.ts update-item -e local -c ./tests/q.config.json",
|
17
18
|
"new-custom-code": "tsx ./src/index.ts new-custom-code -d my-custom-code-project",
|
18
19
|
"eslint": "TIMING=1 eslint --ext .svelte,.ts --config .eslintrc.cjs .",
|
@@ -29,6 +30,7 @@
|
|
29
30
|
"node-fetch": "^3.3.2"
|
30
31
|
},
|
31
32
|
"devDependencies": {
|
33
|
+
"@repo/types-custom-code": "workspace:^",
|
32
34
|
"@repo/types-db": "workspace:^",
|
33
35
|
"@repo/types-files": "workspace:^",
|
34
36
|
"delivery-server": "workspace:*",
|