@raisenow/tamaro-cli 1.6.0-beta.0 → 1.6.0-dev.2
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 +3 -11
- package/dist/{chunk-MCUAYEGK.js → chunk-FI7KZAG6.js} +86 -20
- package/dist/cli.js +475 -343
- package/dist/webpack.config.js +1 -1
- package/package.json +9 -2
package/README.md
CHANGED
|
@@ -249,7 +249,6 @@ the CloudFront cache. Always asks for confirmation unless `-y` is passed.
|
|
|
249
249
|
- `--tag <tag>` – Tag which should be undeployed (default: "latest")
|
|
250
250
|
- `--all` – Undeploy all tags
|
|
251
251
|
- `--dryrun` – Displays the operations that would be performed without actually running them
|
|
252
|
-
- `-y, --yes` – Skip confirmation prompt
|
|
253
252
|
|
|
254
253
|
### Undeploy the "latest" tag
|
|
255
254
|
|
|
@@ -274,13 +273,12 @@ npx -y @raisenow/tamaro-cli undeploy --all
|
|
|
274
273
|
|
|
275
274
|
## `undeploy-email-config`
|
|
276
275
|
|
|
277
|
-
Undeploy a widget's email configuration from AWS S3.
|
|
276
|
+
Undeploy a widget's email configuration from AWS S3.
|
|
278
277
|
|
|
279
278
|
### Options
|
|
280
279
|
|
|
281
280
|
- `--bucket <bucket>` – AWS bucket for email configs
|
|
282
281
|
- `--dryrun` – Displays the operations that would be performed without actually running them
|
|
283
|
-
- `-y, --yes` – Skip confirmation prompt
|
|
284
282
|
|
|
285
283
|
### Example
|
|
286
284
|
|
|
@@ -291,14 +289,11 @@ npx -y @raisenow/tamaro-cli undeploy-email-config
|
|
|
291
289
|
|
|
292
290
|
## `archive`
|
|
293
291
|
|
|
294
|
-
Archive a customer configuration. This moves the configuration folder into the `_archived` folder
|
|
295
|
-
from S3, and undeploys the email configuration from both stage and prod. Archived widgets cannot be archived again.
|
|
296
|
-
Always asks for confirmation unless `-y` is passed.
|
|
292
|
+
Archive a customer configuration. This moves the configuration folder into the `_archived` folder.
|
|
297
293
|
|
|
298
294
|
### Options
|
|
299
295
|
|
|
300
296
|
- `--dryrun` – Displays the operations that would be performed without actually running them
|
|
301
|
-
- `-y, --yes` – Skip confirmation prompt
|
|
302
297
|
|
|
303
298
|
### Example
|
|
304
299
|
|
|
@@ -309,14 +304,11 @@ npx -y @raisenow/tamaro-cli archive
|
|
|
309
304
|
|
|
310
305
|
## `unarchive`
|
|
311
306
|
|
|
312
|
-
Unarchive a previously archived customer configuration. This moves the configuration out of the `_archived` folder
|
|
313
|
-
builds the bundle, deploys it to the "latest" tag, and deploys the email configuration. Only archived widgets can be
|
|
314
|
-
unarchived. Always asks for confirmation unless `-y` is passed.
|
|
307
|
+
Unarchive a previously archived customer configuration. This moves the configuration out of the `_archived` folder.
|
|
315
308
|
|
|
316
309
|
### Options
|
|
317
310
|
|
|
318
311
|
- `--dryrun` – Displays the operations that would be performed without actually running them
|
|
319
|
-
- `-y, --yes` – Skip confirmation prompt
|
|
320
312
|
|
|
321
313
|
### Example
|
|
322
314
|
|
|
@@ -34,6 +34,7 @@ var logDataTable = (data) => {
|
|
|
34
34
|
|
|
35
35
|
// src/lib/command.ts
|
|
36
36
|
import { execaCommandSync } from "execa";
|
|
37
|
+
import prompts from "prompts";
|
|
37
38
|
var halt = (message) => {
|
|
38
39
|
logError(message);
|
|
39
40
|
process.exit(1);
|
|
@@ -44,17 +45,27 @@ var prepareCommand = (cmd) => {
|
|
|
44
45
|
var runCommandSync = (cmd, options) => {
|
|
45
46
|
return execaCommandSync(prepareCommand(cmd), options);
|
|
46
47
|
};
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
var promptConfirmation = async (message, skipConfirmation) => {
|
|
49
|
+
if (skipConfirmation) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const { confirmed } = await prompts(
|
|
53
|
+
[
|
|
54
|
+
{
|
|
55
|
+
type: "confirm",
|
|
56
|
+
name: "confirmed",
|
|
57
|
+
message,
|
|
58
|
+
initial: false
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
{
|
|
62
|
+
onCancel: () => halt()
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
if (!confirmed) {
|
|
66
|
+
halt("Operation cancelled.");
|
|
67
|
+
}
|
|
68
|
+
};
|
|
58
69
|
|
|
59
70
|
// src/lib/resolve.ts
|
|
60
71
|
import { existsSync, realpathSync } from "fs";
|
|
@@ -63,6 +74,7 @@ import { basename, dirname, join, relative, resolve } from "path";
|
|
|
63
74
|
import chalk2 from "chalk";
|
|
64
75
|
import stripIndent2 from "strip-indent";
|
|
65
76
|
import { getIfUtils } from "webpack-config-utils";
|
|
77
|
+
import { z } from "zod";
|
|
66
78
|
var require2 = createRequire(import.meta.url);
|
|
67
79
|
var moduleFileExtensions = ["ts", "tsx", "js", "jsx"];
|
|
68
80
|
var extensions = moduleFileExtensions.map((v) => `.${v}`);
|
|
@@ -128,6 +140,7 @@ var getPaths = (ifCore) => {
|
|
|
128
140
|
appTsConfig: resolveApp("tsconfig.json"),
|
|
129
141
|
appHtml: resolveApp("*.html"),
|
|
130
142
|
appEnv: resolveApp(".env*"),
|
|
143
|
+
configYml: resolveApp("config.yml"),
|
|
131
144
|
appTailwindConfig: void 0
|
|
132
145
|
}
|
|
133
146
|
);
|
|
@@ -174,6 +187,55 @@ var getIfCoreFns = ({
|
|
|
174
187
|
);
|
|
175
188
|
process.exit(1);
|
|
176
189
|
};
|
|
190
|
+
var resolveAccountUuidFromConfig = (rawConfig, field) => {
|
|
191
|
+
const epmsConfig = z.object({
|
|
192
|
+
[field]: z.object()
|
|
193
|
+
}).safeParse(rawConfig);
|
|
194
|
+
if (!epmsConfig.success) {
|
|
195
|
+
return void 0;
|
|
196
|
+
}
|
|
197
|
+
const simple = z.object({
|
|
198
|
+
[field]: z.object({
|
|
199
|
+
account_uuid: z.uuid()
|
|
200
|
+
})
|
|
201
|
+
}).safeParse(rawConfig);
|
|
202
|
+
if (simple.success) {
|
|
203
|
+
return simple.data[field].account_uuid;
|
|
204
|
+
}
|
|
205
|
+
const accountMapping = z.object({
|
|
206
|
+
[field]: z.object({
|
|
207
|
+
account_mapping: z.uuid()
|
|
208
|
+
})
|
|
209
|
+
}).safeParse(rawConfig);
|
|
210
|
+
if (accountMapping.success) {
|
|
211
|
+
return accountMapping.data[field].account_mapping;
|
|
212
|
+
}
|
|
213
|
+
halt(
|
|
214
|
+
stripIndent2(
|
|
215
|
+
`Could not extract EPMS account UUID(s) from config.yml. Please ensure that the "${field}" field is correctly formatted. Expected formats:
|
|
216
|
+
1. ${field}:
|
|
217
|
+
account_uuid: <UUID>
|
|
218
|
+
|
|
219
|
+
2. ${field}:
|
|
220
|
+
account_mapping: <UUID>
|
|
221
|
+
`
|
|
222
|
+
)
|
|
223
|
+
);
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
// src/lib/constants.ts
|
|
227
|
+
import envPaths from "env-paths";
|
|
228
|
+
var DEFAULT_TAG = "latest";
|
|
229
|
+
var DEFAULT_PORT = 1234;
|
|
230
|
+
var AWS_S3_BUCKET_TAMARO = "tamaro.raisenow.com";
|
|
231
|
+
var AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE = "rnw-stage-email-service";
|
|
232
|
+
var AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD = "rnw-email-service";
|
|
233
|
+
var EPMS_API_BASE_URL_STAGE = "https://api.stage.mesos.raisenow.net";
|
|
234
|
+
var CORE_CONFIG_NAME = "tamaro-core";
|
|
235
|
+
var AWS_CLOUDFRONT_DISTRIBUTION_ID = "EHJ1OM458YQ0I";
|
|
236
|
+
var HTTPS_CRT_FILE = "localhost.crt";
|
|
237
|
+
var HTTPS_KEY_FILE = "localhost.key";
|
|
238
|
+
var CACHE_DIR = envPaths("tamaro-cli", { suffix: "" }).cache;
|
|
177
239
|
|
|
178
240
|
// src/lib/env.ts
|
|
179
241
|
import { createRequire as createRequire2 } from "module";
|
|
@@ -308,15 +370,7 @@ export {
|
|
|
308
370
|
logDataTable,
|
|
309
371
|
halt,
|
|
310
372
|
runCommandSync,
|
|
311
|
-
|
|
312
|
-
DEFAULT_PORT,
|
|
313
|
-
AWS_S3_BUCKET_TAMARO,
|
|
314
|
-
AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE,
|
|
315
|
-
AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD,
|
|
316
|
-
CORE_CONFIG_NAME,
|
|
317
|
-
AWS_CLOUDFRONT_DISTRIBUTION_ID,
|
|
318
|
-
HTTPS_CRT_FILE,
|
|
319
|
-
HTTPS_KEY_FILE,
|
|
373
|
+
promptConfirmation,
|
|
320
374
|
extensions,
|
|
321
375
|
resolveApp,
|
|
322
376
|
resolveOwn,
|
|
@@ -326,6 +380,18 @@ export {
|
|
|
326
380
|
getPaths,
|
|
327
381
|
getRelativePaths,
|
|
328
382
|
getIfCoreFns,
|
|
383
|
+
resolveAccountUuidFromConfig,
|
|
384
|
+
DEFAULT_TAG,
|
|
385
|
+
DEFAULT_PORT,
|
|
386
|
+
AWS_S3_BUCKET_TAMARO,
|
|
387
|
+
AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE,
|
|
388
|
+
AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD,
|
|
389
|
+
EPMS_API_BASE_URL_STAGE,
|
|
390
|
+
CORE_CONFIG_NAME,
|
|
391
|
+
AWS_CLOUDFRONT_DISTRIBUTION_ID,
|
|
392
|
+
HTTPS_CRT_FILE,
|
|
393
|
+
HTTPS_KEY_FILE,
|
|
394
|
+
CACHE_DIR,
|
|
329
395
|
getEnvVars,
|
|
330
396
|
assertEnvValid,
|
|
331
397
|
applyEnv
|
package/dist/cli.js
CHANGED
|
@@ -4,9 +4,11 @@ import {
|
|
|
4
4
|
AWS_S3_BUCKET_TAMARO,
|
|
5
5
|
AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD,
|
|
6
6
|
AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE,
|
|
7
|
+
CACHE_DIR,
|
|
7
8
|
CORE_CONFIG_NAME,
|
|
8
9
|
DEFAULT_PORT,
|
|
9
10
|
DEFAULT_TAG,
|
|
11
|
+
EPMS_API_BASE_URL_STAGE,
|
|
10
12
|
HTTPS_CRT_FILE,
|
|
11
13
|
HTTPS_KEY_FILE,
|
|
12
14
|
applyEnv,
|
|
@@ -20,10 +22,12 @@ import {
|
|
|
20
22
|
logError,
|
|
21
23
|
logSuccess,
|
|
22
24
|
logTitle,
|
|
25
|
+
promptConfirmation,
|
|
26
|
+
resolveAccountUuidFromConfig,
|
|
23
27
|
resolveBin,
|
|
24
28
|
resolveOwn,
|
|
25
29
|
runCommandSync
|
|
26
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-FI7KZAG6.js";
|
|
27
31
|
|
|
28
32
|
// src/cli.ts
|
|
29
33
|
import { createCommand } from "commander";
|
|
@@ -31,7 +35,6 @@ import { createCommand } from "commander";
|
|
|
31
35
|
// src/commands/archive.ts
|
|
32
36
|
import { existsSync, mkdirSync, renameSync } from "fs";
|
|
33
37
|
import { basename, dirname, resolve } from "path";
|
|
34
|
-
import chalk from "chalk";
|
|
35
38
|
|
|
36
39
|
// src/lib/aws.ts
|
|
37
40
|
import { execaCommandSync } from "execa";
|
|
@@ -113,35 +116,6 @@ var promptProfile = async () => {
|
|
|
113
116
|
);
|
|
114
117
|
return profile;
|
|
115
118
|
};
|
|
116
|
-
var promptConfirmation = async (message, skipConfirmation) => {
|
|
117
|
-
if (skipConfirmation) {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
const { confirmed } = await prompts(
|
|
121
|
-
[
|
|
122
|
-
{
|
|
123
|
-
type: "confirm",
|
|
124
|
-
name: "confirmed",
|
|
125
|
-
message,
|
|
126
|
-
initial: false
|
|
127
|
-
}
|
|
128
|
-
],
|
|
129
|
-
{
|
|
130
|
-
onCancel: () => halt()
|
|
131
|
-
}
|
|
132
|
-
);
|
|
133
|
-
if (!confirmed) {
|
|
134
|
-
halt("Operation cancelled.");
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
var assertTagValid = (tag) => {
|
|
138
|
-
const regex = /^[a-zA-Z0-9-_.]+$/;
|
|
139
|
-
if (!regex.test(tag)) {
|
|
140
|
-
halt(
|
|
141
|
-
`Flag "--tag" has forbidden format. Allowed format: ${regex.toString()}.`
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
119
|
|
|
146
120
|
// src/lib/notifier.ts
|
|
147
121
|
import notifier from "node-notifier";
|
|
@@ -156,186 +130,10 @@ var notify = (args) => {
|
|
|
156
130
|
});
|
|
157
131
|
};
|
|
158
132
|
|
|
159
|
-
// src/commands/undeploy.ts
|
|
160
|
-
var undeploy = async (options) => {
|
|
161
|
-
const { ifCore } = getIfCoreFns();
|
|
162
|
-
const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid());
|
|
163
|
-
if (!options.profile && !options.ci) {
|
|
164
|
-
assertProfilesPresent();
|
|
165
|
-
options.profile = await promptProfile();
|
|
166
|
-
}
|
|
167
|
-
assertOptionsValid(options);
|
|
168
|
-
awsAuthenticate(options);
|
|
169
|
-
const flags = prepareFlags(options);
|
|
170
|
-
const { tag, all, dryrun } = options;
|
|
171
|
-
const dryRunFlag = dryrun ? `--dryrun` : "";
|
|
172
|
-
const deployUrl = all ? `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/` : `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/`;
|
|
173
|
-
const description = all ? `all tags of "${configName}"` : `tag "${tag}" of "${configName}"`;
|
|
174
|
-
if (dryRunFlag) {
|
|
175
|
-
logTitle("\u{1F9EA} DRY RUN MODE - No actual changes will be made \u{1F9EA}");
|
|
176
|
-
}
|
|
177
|
-
await promptConfirmation(
|
|
178
|
-
`Are you sure you want to undeploy ${description}?`,
|
|
179
|
-
options.yes
|
|
180
|
-
);
|
|
181
|
-
const cmd = `
|
|
182
|
-
aws s3 rm ${deployUrl}
|
|
183
|
-
--recursive
|
|
184
|
-
${flags}
|
|
185
|
-
${dryRunFlag}
|
|
186
|
-
`;
|
|
187
|
-
logTitle(`Undeploying ${description} from AWS S3 \u2026`);
|
|
188
|
-
logCommand(cmd);
|
|
189
|
-
try {
|
|
190
|
-
runCommandSync(cmd, { stdout: "inherit" });
|
|
191
|
-
} catch (error) {
|
|
192
|
-
halt(error.stderr);
|
|
193
|
-
}
|
|
194
|
-
if (!dryRunFlag) {
|
|
195
|
-
const invalidationPath = all ? `/${configName}/*` : `/${configName}/${tag}/*`;
|
|
196
|
-
const cmdInvalidateCache = `
|
|
197
|
-
aws cloudfront create-invalidation
|
|
198
|
-
--distribution-id ${AWS_CLOUDFRONT_DISTRIBUTION_ID}
|
|
199
|
-
--paths ${invalidationPath}
|
|
200
|
-
${flags}
|
|
201
|
-
`;
|
|
202
|
-
logTitle("\nInvalidating edge cache \u2026");
|
|
203
|
-
logCommand(cmdInvalidateCache);
|
|
204
|
-
try {
|
|
205
|
-
runCommandSync(cmdInvalidateCache);
|
|
206
|
-
} catch (error) {
|
|
207
|
-
halt(error.stderr);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
logTitle(`
|
|
211
|
-
${description} has been undeployed.`);
|
|
212
|
-
logDataTable({ "Removed URL:": deployUrl });
|
|
213
|
-
process.on("exit", () => {
|
|
214
|
-
notify({
|
|
215
|
-
title: "undeploy",
|
|
216
|
-
message: `${description} has been undeployed.`
|
|
217
|
-
});
|
|
218
|
-
});
|
|
219
|
-
};
|
|
220
|
-
var assertOptionsValid = (options) => {
|
|
221
|
-
const { profile, tag, all } = options;
|
|
222
|
-
const { ifCore } = getIfCoreFns();
|
|
223
|
-
if (ifCore() && all) {
|
|
224
|
-
halt('Flag "--all" must not be used in Tamaro Core context.');
|
|
225
|
-
}
|
|
226
|
-
if (ifCore() && tag === DEFAULT_TAG) {
|
|
227
|
-
halt("You cannot undeploy the default tag for Tamaro Core.");
|
|
228
|
-
}
|
|
229
|
-
if (profile) {
|
|
230
|
-
assertProfileValid(profile);
|
|
231
|
-
}
|
|
232
|
-
if (all && tag) {
|
|
233
|
-
halt('Flags "--tag" and "--all" must not be used together.');
|
|
234
|
-
}
|
|
235
|
-
if (!all && tag) {
|
|
236
|
-
assertTagValid(tag);
|
|
237
|
-
}
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
// src/commands/undeploy-email-config.ts
|
|
241
|
-
import prompts2 from "prompts";
|
|
242
|
-
var undeployEmailConfig = async (options) => {
|
|
243
|
-
const { ifCore } = getIfCoreFns();
|
|
244
|
-
assertIsNotCore(ifCore);
|
|
245
|
-
if (!options.profile && !options.ci) {
|
|
246
|
-
assertProfilesPresent();
|
|
247
|
-
options.profile = await promptProfile();
|
|
248
|
-
}
|
|
249
|
-
if (!options.bucket) {
|
|
250
|
-
options.bucket = options.ci ? AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD : await promptBucketTamaroEmailConfig();
|
|
251
|
-
}
|
|
252
|
-
assertOptionsValid2(options);
|
|
253
|
-
awsAuthenticate(options);
|
|
254
|
-
const flags = prepareFlags(options);
|
|
255
|
-
const dryRunFlag = options.dryrun ? `--dryrun` : "";
|
|
256
|
-
const configName = getWidgetUuid();
|
|
257
|
-
const deployUrl = `s3://${options.bucket}/${configName}/`;
|
|
258
|
-
await promptConfirmation(
|
|
259
|
-
`Are you sure you want to undeploy the email configuration for "${configName}" from "${options.bucket}"?`,
|
|
260
|
-
options.yes
|
|
261
|
-
);
|
|
262
|
-
if (dryRunFlag) {
|
|
263
|
-
logTitle("\u{1F9EA} DRY RUN MODE - No actual changes will be made \u{1F9EA}");
|
|
264
|
-
}
|
|
265
|
-
const cmd = `
|
|
266
|
-
aws s3 rm ${deployUrl}
|
|
267
|
-
--recursive
|
|
268
|
-
${flags}
|
|
269
|
-
${dryRunFlag}
|
|
270
|
-
`;
|
|
271
|
-
logTitle(
|
|
272
|
-
`Undeploying email configuration for "${configName}" from AWS S3 \u2026`
|
|
273
|
-
);
|
|
274
|
-
logCommand(cmd);
|
|
275
|
-
try {
|
|
276
|
-
runCommandSync(cmd, { stdout: "inherit" });
|
|
277
|
-
} catch (error) {
|
|
278
|
-
halt(error.stderr);
|
|
279
|
-
}
|
|
280
|
-
logTitle(
|
|
281
|
-
`Email configuration for "${configName}" has been undeployed from "${options.bucket}".`
|
|
282
|
-
);
|
|
283
|
-
logDataTable({ "Removed URL:": deployUrl });
|
|
284
|
-
process.on("exit", () => {
|
|
285
|
-
notify({
|
|
286
|
-
title: "undeploy-email-config",
|
|
287
|
-
message: `Email configuration for "${configName}" has been undeployed.`
|
|
288
|
-
});
|
|
289
|
-
});
|
|
290
|
-
};
|
|
291
|
-
var assertOptionsValid2 = (options) => {
|
|
292
|
-
const { profile, bucket } = options;
|
|
293
|
-
if (profile) {
|
|
294
|
-
assertProfileValid(profile);
|
|
295
|
-
}
|
|
296
|
-
if (bucket) {
|
|
297
|
-
assertBucketValid(bucket);
|
|
298
|
-
}
|
|
299
|
-
};
|
|
300
|
-
var assertIsNotCore = (ifCore) => {
|
|
301
|
-
if (ifCore()) {
|
|
302
|
-
halt("You cannot undeploy widget email configuration for Tamaro Core.");
|
|
303
|
-
}
|
|
304
|
-
};
|
|
305
|
-
var assertBucketValid = (bucket) => {
|
|
306
|
-
const buckets = [
|
|
307
|
-
AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE,
|
|
308
|
-
AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD
|
|
309
|
-
];
|
|
310
|
-
if (!buckets.includes(bucket)) {
|
|
311
|
-
halt("Invalid bucket name.");
|
|
312
|
-
}
|
|
313
|
-
};
|
|
314
|
-
var promptBucketTamaroEmailConfig = async () => {
|
|
315
|
-
const buckets = [
|
|
316
|
-
{ title: "stage", value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE },
|
|
317
|
-
{ title: "prod", value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD }
|
|
318
|
-
];
|
|
319
|
-
const { bucket } = await prompts2(
|
|
320
|
-
[
|
|
321
|
-
{
|
|
322
|
-
type: "select",
|
|
323
|
-
name: "bucket",
|
|
324
|
-
message: "Select environment",
|
|
325
|
-
choices: buckets
|
|
326
|
-
}
|
|
327
|
-
],
|
|
328
|
-
{
|
|
329
|
-
onCancel: () => halt()
|
|
330
|
-
}
|
|
331
|
-
);
|
|
332
|
-
return bucket;
|
|
333
|
-
};
|
|
334
|
-
|
|
335
133
|
// src/commands/archive.ts
|
|
336
|
-
var archive =
|
|
134
|
+
var archive = (options) => {
|
|
337
135
|
const { ifCore } = getIfCoreFns();
|
|
338
|
-
|
|
136
|
+
assertIsNotCore(ifCore);
|
|
339
137
|
assertIsNotArchived();
|
|
340
138
|
const configName = getWidgetUuid();
|
|
341
139
|
const cwd = process.cwd();
|
|
@@ -343,56 +141,20 @@ var archive = async (options) => {
|
|
|
343
141
|
const archiveDir = resolve(parentDir, "_archived");
|
|
344
142
|
const archiveTarget = resolve(archiveDir, configName);
|
|
345
143
|
assertArchiveTargetDoesNotExist(archiveTarget);
|
|
346
|
-
|
|
347
|
-
assertProfilesPresent();
|
|
348
|
-
options.profile = await promptProfile();
|
|
349
|
-
}
|
|
350
|
-
assertOptionsValid3(options);
|
|
144
|
+
assertOptionsValid(options);
|
|
351
145
|
if (options.dryrun) {
|
|
352
146
|
logTitle("\u{1F9EA} DRY RUN MODE - No actual changes will be made \u{1F9EA}");
|
|
353
147
|
}
|
|
354
|
-
await promptConfirmation(
|
|
355
|
-
`Are you sure you want to archive "${configName}"? This will ${chalk.red(`undeploy all tags and email configurations of "${configName}"`)}.`,
|
|
356
|
-
options.yes
|
|
357
|
-
);
|
|
358
|
-
logTitle(`
|
|
359
|
-
Undeploying all tags for "${configName}" \u2026`);
|
|
360
|
-
await undeploy({
|
|
361
|
-
all: true,
|
|
362
|
-
yes: true,
|
|
363
|
-
profile: options.profile,
|
|
364
|
-
ci: options.ci,
|
|
365
|
-
dryrun: options.dryrun
|
|
366
|
-
});
|
|
367
|
-
logSuccess(`
|
|
368
|
-
\u2705 Undeployed all tags for "${configName}" \u2026`);
|
|
369
|
-
logTitle(`
|
|
370
|
-
Undeploying email configuration for "${configName}" \u2026`);
|
|
371
|
-
await undeployEmailConfig({
|
|
372
|
-
yes: true,
|
|
373
|
-
profile: options.profile,
|
|
374
|
-
ci: options.ci,
|
|
375
|
-
dryrun: options.dryrun,
|
|
376
|
-
bucket: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD
|
|
377
|
-
});
|
|
378
|
-
logSuccess(`
|
|
379
|
-
\u2705 Undeployed email configuration for "${configName}" \u2026`);
|
|
380
|
-
logTitle(`
|
|
381
|
-
Archiving "${configName}" \u2026`);
|
|
382
148
|
if (!options.dryrun) {
|
|
383
149
|
if (!existsSync(archiveDir)) {
|
|
384
150
|
mkdirSync(archiveDir, { recursive: true });
|
|
385
151
|
}
|
|
386
152
|
renameSync(cwd, archiveTarget);
|
|
387
|
-
logSuccess(`\u2705 Moved to ${archiveTarget}`);
|
|
388
153
|
} else {
|
|
389
154
|
logTitle(`Would move ${cwd} \u2192 ${archiveTarget}`);
|
|
390
155
|
}
|
|
391
156
|
logSuccess(`
|
|
392
|
-
|
|
393
|
-
logDataTable({
|
|
394
|
-
"Archived to:": archiveTarget
|
|
395
|
-
});
|
|
157
|
+
\u2705 "${configName}" has been archived and moved to ${archiveTarget}`);
|
|
396
158
|
process.on("exit", () => {
|
|
397
159
|
notify({
|
|
398
160
|
title: "archive",
|
|
@@ -400,13 +162,13 @@ Archiving "${configName}" \u2026`);
|
|
|
400
162
|
});
|
|
401
163
|
});
|
|
402
164
|
};
|
|
403
|
-
var
|
|
165
|
+
var assertOptionsValid = (options) => {
|
|
404
166
|
const { profile } = options;
|
|
405
167
|
if (profile) {
|
|
406
168
|
assertProfileValid(profile);
|
|
407
169
|
}
|
|
408
170
|
};
|
|
409
|
-
var
|
|
171
|
+
var assertIsNotCore = (ifCore) => {
|
|
410
172
|
if (ifCore()) {
|
|
411
173
|
halt("You cannot archive Tamaro Core.");
|
|
412
174
|
}
|
|
@@ -575,7 +337,7 @@ var build = async (options) => {
|
|
|
575
337
|
assertProfilesPresent();
|
|
576
338
|
options.profile = await promptProfile();
|
|
577
339
|
}
|
|
578
|
-
|
|
340
|
+
assertOptionsValid2(options);
|
|
579
341
|
await validate();
|
|
580
342
|
const flags = prepareFlags2(options);
|
|
581
343
|
const { ifCore } = getIfCoreFns();
|
|
@@ -607,7 +369,7 @@ Bundle for "${configName}" customer configuration is done.`);
|
|
|
607
369
|
});
|
|
608
370
|
});
|
|
609
371
|
};
|
|
610
|
-
var
|
|
372
|
+
var assertOptionsValid2 = (options) => {
|
|
611
373
|
const { localCore, https, deploy: deploy2, env, profile } = options;
|
|
612
374
|
const { ifCore } = getIfCoreFns();
|
|
613
375
|
if (ifCore() && localCore) {
|
|
@@ -645,6 +407,18 @@ var prepareFlags2 = (options) => {
|
|
|
645
407
|
// src/commands/deploy.ts
|
|
646
408
|
import { existsSync as existsSync3 } from "fs";
|
|
647
409
|
import stripIndent4 from "strip-indent";
|
|
410
|
+
|
|
411
|
+
// src/lib/validators/assertTagValid.ts
|
|
412
|
+
var assertTagValid = (tag) => {
|
|
413
|
+
const regex = /^[a-zA-Z0-9-_.]+$/;
|
|
414
|
+
if (!regex.test(tag)) {
|
|
415
|
+
halt(
|
|
416
|
+
`Flag "--tag" has forbidden format. Allowed format: ${regex.toString()}.`
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
// src/commands/deploy.ts
|
|
648
422
|
var deploy = async (options) => {
|
|
649
423
|
const { ifCore } = getIfCoreFns();
|
|
650
424
|
const paths = getPaths(ifCore);
|
|
@@ -653,7 +427,7 @@ var deploy = async (options) => {
|
|
|
653
427
|
assertProfilesPresent();
|
|
654
428
|
options.profile = await promptProfile();
|
|
655
429
|
}
|
|
656
|
-
|
|
430
|
+
assertOptionsValid3(options);
|
|
657
431
|
await validate();
|
|
658
432
|
awsAuthenticate(options);
|
|
659
433
|
const flags = prepareFlags(options);
|
|
@@ -727,7 +501,7 @@ Bundle for "${configName}" is deployed with tag "${tag}".`);
|
|
|
727
501
|
});
|
|
728
502
|
});
|
|
729
503
|
};
|
|
730
|
-
var
|
|
504
|
+
var assertOptionsValid3 = (options) => {
|
|
731
505
|
const { profile, tag } = options;
|
|
732
506
|
if (profile) {
|
|
733
507
|
assertProfileValid(profile);
|
|
@@ -747,21 +521,21 @@ var assertDistPathExists = (distPath) => {
|
|
|
747
521
|
|
|
748
522
|
// src/commands/deploy-email-config.ts
|
|
749
523
|
import { existsSync as existsSync4 } from "fs";
|
|
750
|
-
import
|
|
524
|
+
import prompts2 from "prompts";
|
|
751
525
|
var deployEmailConfig = async (options) => {
|
|
752
526
|
const { ifCore } = getIfCoreFns();
|
|
753
527
|
const paths = getPaths(ifCore);
|
|
754
528
|
const emailConfigPath = `${paths.app}/email-config`;
|
|
755
|
-
|
|
529
|
+
assertIsNotCore2();
|
|
756
530
|
assertEmailConfigPathExists(emailConfigPath);
|
|
757
531
|
if (!options.profile && !options.ci) {
|
|
758
532
|
assertProfilesPresent();
|
|
759
533
|
options.profile = await promptProfile();
|
|
760
534
|
}
|
|
761
535
|
if (!options.bucket) {
|
|
762
|
-
options.bucket = options.ci ? AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD : await
|
|
536
|
+
options.bucket = options.ci ? AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD : await promptBucketTamaroEmailConfig();
|
|
763
537
|
}
|
|
764
|
-
|
|
538
|
+
assertOptionsValid4(options);
|
|
765
539
|
await validate();
|
|
766
540
|
awsAuthenticate(options);
|
|
767
541
|
const flags = prepareFlags(options);
|
|
@@ -798,13 +572,13 @@ var deployEmailConfig = async (options) => {
|
|
|
798
572
|
});
|
|
799
573
|
});
|
|
800
574
|
};
|
|
801
|
-
var
|
|
575
|
+
var assertOptionsValid4 = (options) => {
|
|
802
576
|
const { profile, bucket } = options;
|
|
803
577
|
if (profile) {
|
|
804
578
|
assertProfileValid(profile);
|
|
805
579
|
}
|
|
806
580
|
if (bucket) {
|
|
807
|
-
|
|
581
|
+
assertBucketValid(bucket);
|
|
808
582
|
}
|
|
809
583
|
};
|
|
810
584
|
var assertEmailConfigPathExists = (distPath) => {
|
|
@@ -812,13 +586,13 @@ var assertEmailConfigPathExists = (distPath) => {
|
|
|
812
586
|
halt("Email config folder does not exists. Nothing to deploy.");
|
|
813
587
|
}
|
|
814
588
|
};
|
|
815
|
-
var
|
|
589
|
+
var assertIsNotCore2 = () => {
|
|
816
590
|
const { ifCore } = getIfCoreFns();
|
|
817
591
|
if (ifCore()) {
|
|
818
592
|
halt("You cannot deploy widget email configuration for Tamaro Core.");
|
|
819
593
|
}
|
|
820
594
|
};
|
|
821
|
-
var
|
|
595
|
+
var assertBucketValid = (bucket) => {
|
|
822
596
|
const buckets = [
|
|
823
597
|
AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE,
|
|
824
598
|
AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD
|
|
@@ -827,12 +601,12 @@ var assertBucketValid2 = (bucket) => {
|
|
|
827
601
|
halt("Invalid bucket name.");
|
|
828
602
|
}
|
|
829
603
|
};
|
|
830
|
-
var
|
|
604
|
+
var promptBucketTamaroEmailConfig = async () => {
|
|
831
605
|
const buckets = [
|
|
832
606
|
{ title: "stage", value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE },
|
|
833
607
|
{ title: "prod", value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD }
|
|
834
608
|
];
|
|
835
|
-
const { bucket } = await
|
|
609
|
+
const { bucket } = await prompts2(
|
|
836
610
|
[
|
|
837
611
|
{
|
|
838
612
|
type: "select",
|
|
@@ -853,7 +627,7 @@ import { getPortPromise } from "portfinder";
|
|
|
853
627
|
var dev = async (options) => {
|
|
854
628
|
const { env } = options;
|
|
855
629
|
applyEnv(env);
|
|
856
|
-
|
|
630
|
+
assertOptionsValid5(options);
|
|
857
631
|
const flags = await prepareFlags3(options);
|
|
858
632
|
const { ifCore } = getIfCoreFns();
|
|
859
633
|
const title = ifCore(
|
|
@@ -871,7 +645,7 @@ var dev = async (options) => {
|
|
|
871
645
|
logCommand(cmd);
|
|
872
646
|
runCommandSync(cmd, { stdio: "inherit" });
|
|
873
647
|
};
|
|
874
|
-
var
|
|
648
|
+
var assertOptionsValid5 = (options) => {
|
|
875
649
|
const { localCore, https, port, env } = options;
|
|
876
650
|
const { ifCore } = getIfCoreFns();
|
|
877
651
|
if (ifCore() && localCore) {
|
|
@@ -908,7 +682,7 @@ var listDeployed = async (options) => {
|
|
|
908
682
|
assertProfilesPresent();
|
|
909
683
|
options.profile = await promptProfile();
|
|
910
684
|
}
|
|
911
|
-
|
|
685
|
+
assertOptionsValid6(options);
|
|
912
686
|
awsAuthenticate(options);
|
|
913
687
|
const flags = prepareFlags(options);
|
|
914
688
|
const { config } = options;
|
|
@@ -942,7 +716,7 @@ var listDeployed = async (options) => {
|
|
|
942
716
|
console.log(`${text}
|
|
943
717
|
`);
|
|
944
718
|
};
|
|
945
|
-
var
|
|
719
|
+
var assertOptionsValid6 = (options) => {
|
|
946
720
|
const { config, profile } = options;
|
|
947
721
|
assertConfigValid(config);
|
|
948
722
|
if (profile) {
|
|
@@ -969,7 +743,7 @@ var parseTags = (lines) => {
|
|
|
969
743
|
import { resolve as resolve3 } from "path";
|
|
970
744
|
import { getPortPromise as getPortPromise2 } from "portfinder";
|
|
971
745
|
var serve = async (options) => {
|
|
972
|
-
|
|
746
|
+
assertOptionsValid7(options);
|
|
973
747
|
const flags = await prepareFlags4(options);
|
|
974
748
|
const { ifCore } = getIfCoreFns();
|
|
975
749
|
const paths = getPaths(ifCore);
|
|
@@ -982,7 +756,7 @@ var serve = async (options) => {
|
|
|
982
756
|
logCommand(cmd);
|
|
983
757
|
runCommandSync(cmd, { stdio: "inherit" });
|
|
984
758
|
};
|
|
985
|
-
var
|
|
759
|
+
var assertOptionsValid7 = (options) => {
|
|
986
760
|
const { port, https } = options;
|
|
987
761
|
if (isNaN(Number(port))) {
|
|
988
762
|
halt('Flag "--port" should be a number.');
|
|
@@ -1010,9 +784,9 @@ var prepareFlags4 = async (options) => {
|
|
|
1010
784
|
// src/commands/unarchive.ts
|
|
1011
785
|
import { existsSync as existsSync5, renameSync as renameSync2 } from "fs";
|
|
1012
786
|
import { basename as basename2, dirname as dirname2, resolve as resolve4 } from "path";
|
|
1013
|
-
var unarchive =
|
|
787
|
+
var unarchive = (options) => {
|
|
1014
788
|
const { ifCore } = getIfCoreFns({ allowArchived: true });
|
|
1015
|
-
|
|
789
|
+
assertIsNotCore3(ifCore);
|
|
1016
790
|
assertIsArchived();
|
|
1017
791
|
const configName = getWidgetUuid();
|
|
1018
792
|
const cwd = process.cwd();
|
|
@@ -1020,77 +794,25 @@ var unarchive = async (options) => {
|
|
|
1020
794
|
const configsDir = dirname2(archivedDir);
|
|
1021
795
|
const restoreTarget = resolve4(configsDir, configName);
|
|
1022
796
|
assertRestoreTargetDoesNotExist(restoreTarget);
|
|
1023
|
-
|
|
1024
|
-
assertProfilesPresent();
|
|
1025
|
-
options.profile = await promptProfile();
|
|
1026
|
-
}
|
|
1027
|
-
assertOptionsValid10(options);
|
|
1028
|
-
await promptConfirmation(
|
|
1029
|
-
`Are you sure you want to unarchive "${configName}"? This will restore, build, and deploy the configuration.`,
|
|
1030
|
-
options.yes
|
|
1031
|
-
);
|
|
797
|
+
assertOptionsValid8(options);
|
|
1032
798
|
if (options.dryrun) {
|
|
1033
799
|
logTitle("\u{1F9EA} DRY RUN MODE - No actual changes will be made \u{1F9EA}");
|
|
1034
800
|
}
|
|
1035
|
-
logTitle(`
|
|
1036
|
-
Unarchiving "${configName}" \u2026`);
|
|
1037
801
|
if (!options.dryrun) {
|
|
1038
802
|
renameSync2(cwd, restoreTarget);
|
|
1039
803
|
process.chdir(restoreTarget);
|
|
1040
|
-
logTitle(`Moved to ${restoreTarget}`);
|
|
1041
804
|
} else {
|
|
1042
805
|
logTitle(`Would move ${cwd} \u2192 ${restoreTarget}`);
|
|
1043
806
|
}
|
|
1044
|
-
|
|
1045
|
-
logTitle(`
|
|
1046
|
-
Building "${configName}" \u2026`);
|
|
1047
|
-
await build({
|
|
1048
|
-
localCore: false,
|
|
1049
|
-
analyze: false,
|
|
1050
|
-
https: false,
|
|
1051
|
-
serve: false,
|
|
1052
|
-
deploy: false,
|
|
1053
|
-
nolint: false,
|
|
1054
|
-
tag: DEFAULT_TAG,
|
|
1055
|
-
profile: options.profile,
|
|
1056
|
-
ci: options.ci,
|
|
1057
|
-
dryrun: options.dryrun
|
|
1058
|
-
});
|
|
1059
|
-
logSuccess(`
|
|
1060
|
-
\u2705 Built "${configName}" \u2026`);
|
|
1061
|
-
logTitle(`
|
|
1062
|
-
Deploying "${configName}" to tag "${DEFAULT_TAG}" \u2026`);
|
|
1063
|
-
await deploy({
|
|
1064
|
-
tag: DEFAULT_TAG,
|
|
1065
|
-
profile: options.profile,
|
|
1066
|
-
ci: options.ci,
|
|
1067
|
-
dryrun: options.dryrun
|
|
1068
|
-
});
|
|
1069
|
-
logSuccess(`
|
|
1070
|
-
\u2705 Deployed "${configName}" to tag "${DEFAULT_TAG}" \u2026`);
|
|
1071
|
-
logTitle(`
|
|
1072
|
-
Deploying email configuration for "${configName}" \u2026`);
|
|
1073
|
-
await deployEmailConfig({
|
|
1074
|
-
profile: options.profile,
|
|
1075
|
-
ci: options.ci,
|
|
1076
|
-
dryrun: options.dryrun,
|
|
1077
|
-
bucket: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD
|
|
1078
|
-
});
|
|
1079
|
-
logSuccess(`
|
|
1080
|
-
\u2705 Deployed email configuration for "${configName}" \u2026`);
|
|
1081
|
-
} else {
|
|
1082
|
-
logTitle('Would build, deploy to "latest", and deploy email configuration.');
|
|
1083
|
-
}
|
|
1084
|
-
logSuccess(`
|
|
1085
|
-
\u2705 "${configName}" has been unarchived and deployed.`);
|
|
807
|
+
logTitle(`\u2705 "${configName}" has been unarchived and moved to ${restoreTarget}`);
|
|
1086
808
|
process.on("exit", () => {
|
|
1087
809
|
notify({
|
|
1088
810
|
title: "unarchive",
|
|
1089
|
-
message: `"${configName}" has been unarchived
|
|
811
|
+
message: `"${configName}" has been unarchived.`
|
|
1090
812
|
});
|
|
1091
813
|
});
|
|
1092
814
|
};
|
|
1093
|
-
var
|
|
815
|
+
var assertOptionsValid8 = (options) => {
|
|
1094
816
|
const { profile } = options;
|
|
1095
817
|
if (profile) {
|
|
1096
818
|
assertProfileValid(profile);
|
|
@@ -1104,7 +826,7 @@ var assertIsArchived = () => {
|
|
|
1104
826
|
);
|
|
1105
827
|
}
|
|
1106
828
|
};
|
|
1107
|
-
var
|
|
829
|
+
var assertIsNotCore3 = (ifCore) => {
|
|
1108
830
|
if (ifCore()) {
|
|
1109
831
|
halt("You cannot unarchive Tamaro Core.");
|
|
1110
832
|
}
|
|
@@ -1117,10 +839,410 @@ var assertRestoreTargetDoesNotExist = (restoreTarget) => {
|
|
|
1117
839
|
}
|
|
1118
840
|
};
|
|
1119
841
|
|
|
842
|
+
// src/commands/undeploy.ts
|
|
843
|
+
var undeploy = async (options) => {
|
|
844
|
+
const { ifCore } = getIfCoreFns();
|
|
845
|
+
const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid());
|
|
846
|
+
if (!options.profile && !options.ci) {
|
|
847
|
+
assertProfilesPresent();
|
|
848
|
+
options.profile = await promptProfile();
|
|
849
|
+
}
|
|
850
|
+
assertOptionsValid9(options);
|
|
851
|
+
awsAuthenticate(options);
|
|
852
|
+
const flags = prepareFlags(options);
|
|
853
|
+
const { tag, all, dryrun } = options;
|
|
854
|
+
const dryRunFlag = dryrun ? `--dryrun` : "";
|
|
855
|
+
const deployUrl = all ? `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/` : `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/`;
|
|
856
|
+
const description = all ? `all tags of "${configName}"` : `tag "${tag}" of "${configName}"`;
|
|
857
|
+
if (dryRunFlag) {
|
|
858
|
+
logTitle("\u{1F9EA} DRY RUN MODE - No actual changes will be made \u{1F9EA}");
|
|
859
|
+
}
|
|
860
|
+
await promptConfirmation(
|
|
861
|
+
`Are you sure you want to undeploy ${description}?`,
|
|
862
|
+
options.ci
|
|
863
|
+
);
|
|
864
|
+
const cmd = `
|
|
865
|
+
aws s3 rm ${deployUrl}
|
|
866
|
+
--recursive
|
|
867
|
+
${flags}
|
|
868
|
+
${dryRunFlag}
|
|
869
|
+
`;
|
|
870
|
+
logTitle(`Undeploying ${description} from AWS S3 \u2026`);
|
|
871
|
+
logCommand(cmd);
|
|
872
|
+
try {
|
|
873
|
+
runCommandSync(cmd, { stdout: "inherit" });
|
|
874
|
+
} catch (error) {
|
|
875
|
+
halt(error.stderr);
|
|
876
|
+
}
|
|
877
|
+
if (!dryRunFlag) {
|
|
878
|
+
const invalidationPath = all ? `/${configName}/*` : `/${configName}/${tag}/*`;
|
|
879
|
+
const cmdInvalidateCache = `
|
|
880
|
+
aws cloudfront create-invalidation
|
|
881
|
+
--distribution-id ${AWS_CLOUDFRONT_DISTRIBUTION_ID}
|
|
882
|
+
--paths ${invalidationPath}
|
|
883
|
+
${flags}
|
|
884
|
+
`;
|
|
885
|
+
logTitle("\nInvalidating edge cache \u2026");
|
|
886
|
+
logCommand(cmdInvalidateCache);
|
|
887
|
+
try {
|
|
888
|
+
runCommandSync(cmdInvalidateCache);
|
|
889
|
+
} catch (error) {
|
|
890
|
+
halt(error.stderr);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
logTitle(`
|
|
894
|
+
${description} has been undeployed.`);
|
|
895
|
+
logDataTable({ "Removed URL:": deployUrl });
|
|
896
|
+
process.on("exit", () => {
|
|
897
|
+
notify({
|
|
898
|
+
title: "undeploy",
|
|
899
|
+
message: `${description} has been undeployed.`
|
|
900
|
+
});
|
|
901
|
+
});
|
|
902
|
+
};
|
|
903
|
+
var assertOptionsValid9 = (options) => {
|
|
904
|
+
const { profile, tag, all } = options;
|
|
905
|
+
const { ifCore } = getIfCoreFns();
|
|
906
|
+
if (ifCore() && all) {
|
|
907
|
+
halt('Flag "--all" must not be used in Tamaro Core context.');
|
|
908
|
+
}
|
|
909
|
+
if (ifCore() && tag === DEFAULT_TAG) {
|
|
910
|
+
halt("You cannot undeploy the default tag for Tamaro Core.");
|
|
911
|
+
}
|
|
912
|
+
if (profile) {
|
|
913
|
+
assertProfileValid(profile);
|
|
914
|
+
}
|
|
915
|
+
if (all && tag) {
|
|
916
|
+
halt('Flags "--tag" and "--all" must not be used together.');
|
|
917
|
+
}
|
|
918
|
+
if (!all && tag) {
|
|
919
|
+
assertTagValid(tag);
|
|
920
|
+
}
|
|
921
|
+
};
|
|
922
|
+
|
|
923
|
+
// src/commands/undeploy-email-config.ts
|
|
924
|
+
import prompts3 from "prompts";
|
|
925
|
+
var undeployEmailConfig = async (options) => {
|
|
926
|
+
const { ifCore } = getIfCoreFns();
|
|
927
|
+
assertIsNotCore4(ifCore);
|
|
928
|
+
if (!options.profile && !options.ci) {
|
|
929
|
+
assertProfilesPresent();
|
|
930
|
+
options.profile = await promptProfile();
|
|
931
|
+
}
|
|
932
|
+
if (!options.bucket) {
|
|
933
|
+
options.bucket = options.ci ? AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD : await promptBucketTamaroEmailConfig2();
|
|
934
|
+
}
|
|
935
|
+
assertOptionsValid10(options);
|
|
936
|
+
awsAuthenticate(options);
|
|
937
|
+
const flags = prepareFlags(options);
|
|
938
|
+
const dryRunFlag = options.dryrun ? `--dryrun` : "";
|
|
939
|
+
const configName = getWidgetUuid();
|
|
940
|
+
const deployUrl = `s3://${options.bucket}/${configName}/`;
|
|
941
|
+
await promptConfirmation(
|
|
942
|
+
`Are you sure you want to undeploy the email configuration for "${configName}" from "${options.bucket}"?`,
|
|
943
|
+
options.ci
|
|
944
|
+
);
|
|
945
|
+
if (dryRunFlag) {
|
|
946
|
+
logTitle("\u{1F9EA} DRY RUN MODE - No actual changes will be made \u{1F9EA}");
|
|
947
|
+
}
|
|
948
|
+
const cmd = `
|
|
949
|
+
aws s3 rm ${deployUrl}
|
|
950
|
+
--recursive
|
|
951
|
+
${flags}
|
|
952
|
+
${dryRunFlag}
|
|
953
|
+
`;
|
|
954
|
+
logTitle(`Undeploying email configuration for "${configName}" from AWS S3 \u2026`);
|
|
955
|
+
logCommand(cmd);
|
|
956
|
+
try {
|
|
957
|
+
runCommandSync(cmd, { stdout: "inherit" });
|
|
958
|
+
} catch (error) {
|
|
959
|
+
halt(error.stderr);
|
|
960
|
+
}
|
|
961
|
+
logTitle(
|
|
962
|
+
`Email configuration for "${configName}" has been undeployed from "${options.bucket}".`
|
|
963
|
+
);
|
|
964
|
+
logDataTable({ "Removed URL:": deployUrl });
|
|
965
|
+
process.on("exit", () => {
|
|
966
|
+
notify({
|
|
967
|
+
title: "undeploy-email-config",
|
|
968
|
+
message: `Email configuration for "${configName}" has been undeployed.`
|
|
969
|
+
});
|
|
970
|
+
});
|
|
971
|
+
};
|
|
972
|
+
var assertOptionsValid10 = (options) => {
|
|
973
|
+
const { profile, bucket } = options;
|
|
974
|
+
if (profile) {
|
|
975
|
+
assertProfileValid(profile);
|
|
976
|
+
}
|
|
977
|
+
if (bucket) {
|
|
978
|
+
assertBucketValid2(bucket);
|
|
979
|
+
}
|
|
980
|
+
};
|
|
981
|
+
var assertIsNotCore4 = (ifCore) => {
|
|
982
|
+
if (ifCore()) {
|
|
983
|
+
halt("You cannot undeploy widget email configuration for Tamaro Core.");
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
var assertBucketValid2 = (bucket) => {
|
|
987
|
+
const buckets = [
|
|
988
|
+
AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE,
|
|
989
|
+
AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD
|
|
990
|
+
];
|
|
991
|
+
if (!buckets.includes(bucket)) {
|
|
992
|
+
halt("Invalid bucket name.");
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
var promptBucketTamaroEmailConfig2 = async () => {
|
|
996
|
+
const buckets = [
|
|
997
|
+
{ title: "stage", value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE },
|
|
998
|
+
{ title: "prod", value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD }
|
|
999
|
+
];
|
|
1000
|
+
const { bucket } = await prompts3(
|
|
1001
|
+
[
|
|
1002
|
+
{
|
|
1003
|
+
type: "select",
|
|
1004
|
+
name: "bucket",
|
|
1005
|
+
message: "Select environment",
|
|
1006
|
+
choices: buckets
|
|
1007
|
+
}
|
|
1008
|
+
],
|
|
1009
|
+
{
|
|
1010
|
+
onCancel: () => halt()
|
|
1011
|
+
}
|
|
1012
|
+
);
|
|
1013
|
+
return bucket;
|
|
1014
|
+
};
|
|
1015
|
+
|
|
1016
|
+
// src/commands/update-epms.ts
|
|
1017
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
1018
|
+
import yaml2 from "js-yaml";
|
|
1019
|
+
|
|
1020
|
+
// src/lib/epms/assert.ts
|
|
1021
|
+
import { existsSync as existsSync6, readFileSync } from "fs";
|
|
1022
|
+
import yaml from "js-yaml";
|
|
1023
|
+
import stripIndent5 from "strip-indent";
|
|
1024
|
+
var assertEpmsCredentials = (configPath) => {
|
|
1025
|
+
if (!existsSync6(configPath)) {
|
|
1026
|
+
throw new Error(`Config file not found at path: ${configPath}`);
|
|
1027
|
+
}
|
|
1028
|
+
try {
|
|
1029
|
+
const configContent = yaml.load(readFileSync(configPath, "utf8"));
|
|
1030
|
+
assertEpmsCredentialsPresentStage(configContent);
|
|
1031
|
+
assertEpmsCredentialsPresentProd(configContent);
|
|
1032
|
+
} catch (e) {
|
|
1033
|
+
throw new Error(
|
|
1034
|
+
`Error parsing config file at path: ${configPath}. Details: ${e}`
|
|
1035
|
+
);
|
|
1036
|
+
}
|
|
1037
|
+
};
|
|
1038
|
+
var assertEpmsCredentialsPresentStage = (rawConfig) => {
|
|
1039
|
+
const accountsUuidsStage = resolveAccountUuidFromConfig(
|
|
1040
|
+
rawConfig,
|
|
1041
|
+
"epms_stage"
|
|
1042
|
+
);
|
|
1043
|
+
if (!accountsUuidsStage) {
|
|
1044
|
+
return;
|
|
1045
|
+
}
|
|
1046
|
+
if (!process.env.EPMS_CLIENT_ID_STAGE || !process.env.EPMS_CLIENT_SECRET_STAGE) {
|
|
1047
|
+
halt(
|
|
1048
|
+
stripIndent5(
|
|
1049
|
+
`EPMS credentials for stage environment are missing.
|
|
1050
|
+
- Please set EPMS_CLIENT_ID_STAGE and EPMS_CLIENT_SECRET_STAGE in your environment variables.
|
|
1051
|
+
- Alternatively, remove the "epms_stage" fields from your config.yml
|
|
1052
|
+
`
|
|
1053
|
+
)
|
|
1054
|
+
);
|
|
1055
|
+
}
|
|
1056
|
+
};
|
|
1057
|
+
var assertEpmsCredentialsPresentProd = (rawConfig) => {
|
|
1058
|
+
const accountsUuidsProd = resolveAccountUuidFromConfig(rawConfig, "epms");
|
|
1059
|
+
if (!accountsUuidsProd) {
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1062
|
+
if (!process.env.EPMS_CLIENT_ID || !process.env.EPMS_CLIENT_SECRET) {
|
|
1063
|
+
halt(
|
|
1064
|
+
stripIndent5(
|
|
1065
|
+
`EPMS credentials for prod environment are missing.
|
|
1066
|
+
- Please set EPMS_CLIENT_ID and EPMS_CLIENT_SECRET in your environment variables.
|
|
1067
|
+
- Alternatively, remove the "epms" fields from your config.yml
|
|
1068
|
+
`
|
|
1069
|
+
)
|
|
1070
|
+
);
|
|
1071
|
+
}
|
|
1072
|
+
};
|
|
1073
|
+
|
|
1074
|
+
// src/lib/epms/auth.ts
|
|
1075
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
1076
|
+
import { dirname as dirname3, join } from "path";
|
|
1077
|
+
import ky from "ky";
|
|
1078
|
+
var DEFAULT_TIMEOUT = 1e4;
|
|
1079
|
+
function getCacheFilePath() {
|
|
1080
|
+
return join(CACHE_DIR, "token.json");
|
|
1081
|
+
}
|
|
1082
|
+
function readCachedToken() {
|
|
1083
|
+
try {
|
|
1084
|
+
const filePath = getCacheFilePath();
|
|
1085
|
+
if (!existsSync7(filePath)) {
|
|
1086
|
+
return void 0;
|
|
1087
|
+
}
|
|
1088
|
+
const data = JSON.parse(readFileSync2(filePath, "utf-8"));
|
|
1089
|
+
if (typeof data.token === "string" && typeof data.expirationTime === "number") {
|
|
1090
|
+
return data;
|
|
1091
|
+
}
|
|
1092
|
+
} catch {
|
|
1093
|
+
}
|
|
1094
|
+
return void 0;
|
|
1095
|
+
}
|
|
1096
|
+
function writeCachedToken(cached) {
|
|
1097
|
+
try {
|
|
1098
|
+
const filePath = getCacheFilePath();
|
|
1099
|
+
mkdirSync2(dirname3(filePath), { recursive: true });
|
|
1100
|
+
writeFileSync(filePath, JSON.stringify(cached), { mode: 384 });
|
|
1101
|
+
} catch {
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
var createAuthorizer = (baseUrl, clientId, clientSecret) => {
|
|
1105
|
+
const apiUnauthorized = ky.extend({
|
|
1106
|
+
headers: {
|
|
1107
|
+
"Access-Control-Allow-Origin": "*"
|
|
1108
|
+
},
|
|
1109
|
+
prefixUrl: baseUrl,
|
|
1110
|
+
timeout: DEFAULT_TIMEOUT
|
|
1111
|
+
});
|
|
1112
|
+
let expirationTime = void 0;
|
|
1113
|
+
let token = void 0;
|
|
1114
|
+
const cached = readCachedToken();
|
|
1115
|
+
if (cached) {
|
|
1116
|
+
token = cached.token;
|
|
1117
|
+
expirationTime = cached.expirationTime;
|
|
1118
|
+
}
|
|
1119
|
+
const authorize = async () => {
|
|
1120
|
+
const isExpired = (expirationTime ?? 0) - Date.now() < 5 * 60 * 1e3;
|
|
1121
|
+
if (token && !isExpired) {
|
|
1122
|
+
return token;
|
|
1123
|
+
}
|
|
1124
|
+
const data = await apiUnauthorized.post("oauth2/token", {
|
|
1125
|
+
json: {
|
|
1126
|
+
client_id: clientId,
|
|
1127
|
+
client_secret: clientSecret,
|
|
1128
|
+
grant_type: "client_credentials"
|
|
1129
|
+
}
|
|
1130
|
+
}).json();
|
|
1131
|
+
token = `${data.token_type} ${data.access_token}`;
|
|
1132
|
+
expirationTime = Date.now() + data.expires_in * 1e3;
|
|
1133
|
+
writeCachedToken({ token, expirationTime });
|
|
1134
|
+
return token;
|
|
1135
|
+
};
|
|
1136
|
+
return apiUnauthorized.extend({
|
|
1137
|
+
hooks: {
|
|
1138
|
+
beforeRequest: [
|
|
1139
|
+
async (request) => {
|
|
1140
|
+
request.headers.set("Authorization", await authorize());
|
|
1141
|
+
}
|
|
1142
|
+
]
|
|
1143
|
+
}
|
|
1144
|
+
});
|
|
1145
|
+
};
|
|
1146
|
+
|
|
1147
|
+
// src/lib/epms/client.ts
|
|
1148
|
+
var EpmsClient = class {
|
|
1149
|
+
#epmsClient;
|
|
1150
|
+
constructor(baseUrl, clientId, clientSecret) {
|
|
1151
|
+
this.#epmsClient = createAuthorizer(baseUrl, clientId, clientSecret);
|
|
1152
|
+
}
|
|
1153
|
+
async getOrganisationIdByAccountUuid(accountUuid) {
|
|
1154
|
+
const query = {
|
|
1155
|
+
query: {
|
|
1156
|
+
$and: [
|
|
1157
|
+
{ $term: { object_uuid: accountUuid } },
|
|
1158
|
+
{ $term: { object: "account" } }
|
|
1159
|
+
]
|
|
1160
|
+
},
|
|
1161
|
+
size: 1,
|
|
1162
|
+
from: 0
|
|
1163
|
+
};
|
|
1164
|
+
const response = await this.#epmsClient.post("search/events", {
|
|
1165
|
+
json: query
|
|
1166
|
+
}).json();
|
|
1167
|
+
if (response.hits.length === 0) {
|
|
1168
|
+
throw new Error(`No events found for account UUID: ${accountUuid}`);
|
|
1169
|
+
}
|
|
1170
|
+
const organisationId = response.hits[0].organisation_uuid;
|
|
1171
|
+
if (!organisationId) {
|
|
1172
|
+
throw new Error(
|
|
1173
|
+
`Organisation UUID not found for account UUID: ${accountUuid}`
|
|
1174
|
+
);
|
|
1175
|
+
}
|
|
1176
|
+
return organisationId;
|
|
1177
|
+
}
|
|
1178
|
+
async updateTamaro(configName, tag, json) {
|
|
1179
|
+
return this.#epmsClient.put(`products/tamaro/${configName}/tags/${tag}`, {
|
|
1180
|
+
json
|
|
1181
|
+
}).json();
|
|
1182
|
+
}
|
|
1183
|
+
};
|
|
1184
|
+
|
|
1185
|
+
// src/commands/update-epms.ts
|
|
1186
|
+
var updateEpms = async (options) => {
|
|
1187
|
+
const { ifCore } = getIfCoreFns();
|
|
1188
|
+
assertIsNotCore5(ifCore);
|
|
1189
|
+
const paths = getPaths(ifCore);
|
|
1190
|
+
const { tag, dryrun } = options;
|
|
1191
|
+
const dryRunFlag = dryrun ? `--dryrun` : "";
|
|
1192
|
+
const configName = getWidgetUuid();
|
|
1193
|
+
if (!("configYml" in paths)) {
|
|
1194
|
+
halt("Fatal error, this should never happen");
|
|
1195
|
+
throw new Error();
|
|
1196
|
+
}
|
|
1197
|
+
if (dryRunFlag) {
|
|
1198
|
+
logTitle("\u{1F9EA} DRY RUN MODE - No actual changes will be made \u{1F9EA}");
|
|
1199
|
+
}
|
|
1200
|
+
assertTagValid(tag);
|
|
1201
|
+
assertEpmsCredentials(paths.configYml);
|
|
1202
|
+
const configContent = yaml2.load(readFileSync3(paths.configYml, "utf8"));
|
|
1203
|
+
const accountUuidStage = resolveAccountUuidFromConfig(
|
|
1204
|
+
configContent,
|
|
1205
|
+
"epms_stage"
|
|
1206
|
+
);
|
|
1207
|
+
if (dryrun) {
|
|
1208
|
+
logTitle(
|
|
1209
|
+
`[DRY RUN] Would update EPMS for "${configName}" with tag "${tag}"`
|
|
1210
|
+
);
|
|
1211
|
+
} else {
|
|
1212
|
+
if (accountUuidStage) {
|
|
1213
|
+
const epmsClient = new EpmsClient(
|
|
1214
|
+
EPMS_API_BASE_URL_STAGE,
|
|
1215
|
+
process.env.EPMS_CLIENT_ID_STAGE,
|
|
1216
|
+
process.env.EPMS_CLIENT_SECRET_STAGE
|
|
1217
|
+
);
|
|
1218
|
+
const organisationUuid = await epmsClient.getOrganisationIdByAccountUuid(accountUuidStage);
|
|
1219
|
+
logTitle("Updating EPMS with the following details:");
|
|
1220
|
+
const body = {
|
|
1221
|
+
account_uuid: accountUuidStage,
|
|
1222
|
+
organisation_uuid: organisationUuid,
|
|
1223
|
+
configured_version: tag,
|
|
1224
|
+
read_only: false
|
|
1225
|
+
};
|
|
1226
|
+
logDataTable({
|
|
1227
|
+
name: configName,
|
|
1228
|
+
tag,
|
|
1229
|
+
...body
|
|
1230
|
+
});
|
|
1231
|
+
await epmsClient.updateTamaro(configName, tag, body);
|
|
1232
|
+
logSuccess("\u2705 EPMS Stage is updated.");
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
};
|
|
1236
|
+
var assertIsNotCore5 = (ifCore) => {
|
|
1237
|
+
if (ifCore()) {
|
|
1238
|
+
halt("You cannot update EPMS in the context of Tamaro Core.");
|
|
1239
|
+
}
|
|
1240
|
+
};
|
|
1241
|
+
|
|
1120
1242
|
// package.json
|
|
1121
1243
|
var package_default = {
|
|
1122
1244
|
name: "@raisenow/tamaro-cli",
|
|
1123
|
-
version: "1.6.0-
|
|
1245
|
+
version: "1.6.0-dev.2",
|
|
1124
1246
|
author: {
|
|
1125
1247
|
name: "RaiseNow",
|
|
1126
1248
|
email: "development@raisenow.com"
|
|
@@ -1183,6 +1305,7 @@ var package_default = {
|
|
|
1183
1305
|
"css-loader": "^7.1.3",
|
|
1184
1306
|
"css-minimizer-webpack-plugin": "^7.0.4",
|
|
1185
1307
|
dotenv: "^17.2.3",
|
|
1308
|
+
"env-paths": "^4.0.0",
|
|
1186
1309
|
"escape-string-regexp": "^5.0.0",
|
|
1187
1310
|
eslint: "^8.57.1",
|
|
1188
1311
|
"eslint-config-prettier": "^10.1.8",
|
|
@@ -1202,7 +1325,9 @@ var package_default = {
|
|
|
1202
1325
|
"handlebars-helpers": "^0.10.0",
|
|
1203
1326
|
"html-loader": "^5.1.0",
|
|
1204
1327
|
"html-webpack-plugin": "^5.6.6",
|
|
1328
|
+
"js-yaml": "^4.1.1",
|
|
1205
1329
|
"json-loader": "^0.5.7",
|
|
1330
|
+
ky: "^1.14.3",
|
|
1206
1331
|
lodash: "^4.17.23",
|
|
1207
1332
|
"mini-css-extract-plugin": "^2.10.0",
|
|
1208
1333
|
"node-notifier": "^10.0.1",
|
|
@@ -1230,7 +1355,11 @@ var package_default = {
|
|
|
1230
1355
|
"webpack-cli": "^6.0.1",
|
|
1231
1356
|
"webpack-config-utils": "^2.3.1",
|
|
1232
1357
|
"webpack-dev-server": "^5.2.3",
|
|
1233
|
-
"yaml-loader": "^0.9.0"
|
|
1358
|
+
"yaml-loader": "^0.9.0",
|
|
1359
|
+
zod: "^4.3.6"
|
|
1360
|
+
},
|
|
1361
|
+
devDependencies: {
|
|
1362
|
+
"@types/js-yaml": "^4.0.9"
|
|
1234
1363
|
}
|
|
1235
1364
|
};
|
|
1236
1365
|
|
|
@@ -1319,41 +1448,44 @@ cli.command("deploy-email-config").description("Deploy a widget's email configur
|
|
|
1319
1448
|
});
|
|
1320
1449
|
cli.command("undeploy").description(
|
|
1321
1450
|
"Undeploy a Tamaro Core or customer configuration bundle from AWS S3"
|
|
1322
|
-
).option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option(
|
|
1323
|
-
"--tag <tag>",
|
|
1324
|
-
"Tag which should be undeployed",
|
|
1325
|
-
DEFAULT_TAG
|
|
1326
|
-
).option("--all", "Undeploy all tags", false).option(
|
|
1451
|
+
).option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--tag <tag>", "Tag which should be undeployed", DEFAULT_TAG).option("--all", "Undeploy all tags", false).option(
|
|
1327
1452
|
"--dryrun",
|
|
1328
1453
|
"Displays the operations that would be performed without actually running them",
|
|
1329
1454
|
false
|
|
1330
|
-
).
|
|
1455
|
+
).action(async (options) => {
|
|
1331
1456
|
await undeploy(options);
|
|
1332
1457
|
});
|
|
1333
1458
|
cli.command("undeploy-email-config").description("Undeploy a widget's email configuration from AWS S3").option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option("--bucket <bucket>", "AWS bucket for email configs").option(
|
|
1334
1459
|
"--dryrun",
|
|
1335
1460
|
"Displays the operations that would be performed without actually running them",
|
|
1336
1461
|
false
|
|
1337
|
-
).
|
|
1462
|
+
).action(async (options) => {
|
|
1338
1463
|
await undeployEmailConfig(options);
|
|
1339
1464
|
});
|
|
1340
1465
|
cli.command("archive").description(
|
|
1341
|
-
"Archive a customer configuration
|
|
1466
|
+
"Archive a customer configuration by moving it to the _archived folder"
|
|
1342
1467
|
).option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option(
|
|
1343
1468
|
"--dryrun",
|
|
1344
1469
|
"Displays the operations that would be performed without actually running them",
|
|
1345
1470
|
false
|
|
1346
|
-
).
|
|
1347
|
-
|
|
1471
|
+
).action((options) => {
|
|
1472
|
+
archive(options);
|
|
1348
1473
|
});
|
|
1349
1474
|
cli.command("unarchive").description(
|
|
1350
|
-
"Unarchive a customer configuration
|
|
1475
|
+
"Unarchive a customer configuration by restoring it from the _archived folder"
|
|
1351
1476
|
).option("--profile <profile>", "AWS profile").option("--ci", "CI environment", false).option(
|
|
1352
1477
|
"--dryrun",
|
|
1353
1478
|
"Displays the operations that would be performed without actually running them",
|
|
1354
1479
|
false
|
|
1355
|
-
).
|
|
1356
|
-
|
|
1480
|
+
).action((options) => {
|
|
1481
|
+
unarchive(options);
|
|
1482
|
+
});
|
|
1483
|
+
cli.command("update-epms").description("Update EPMS with the currently configured widget version.").option("--tag <tag>", "Tag which should be used for the update", DEFAULT_TAG).option(
|
|
1484
|
+
"--dryrun",
|
|
1485
|
+
"Displays the operations that would be performed without actually running them",
|
|
1486
|
+
false
|
|
1487
|
+
).action(async (options) => {
|
|
1488
|
+
await updateEpms(options);
|
|
1357
1489
|
});
|
|
1358
1490
|
cli.command("validate").description(
|
|
1359
1491
|
"Validate the current Tamaro configuration to avoid common errors"
|
package/dist/webpack.config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raisenow/tamaro-cli",
|
|
3
|
-
"version": "1.6.0-
|
|
3
|
+
"version": "1.6.0-dev.2",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "RaiseNow",
|
|
6
6
|
"email": "development@raisenow.com"
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"css-loader": "^7.1.3",
|
|
49
49
|
"css-minimizer-webpack-plugin": "^7.0.4",
|
|
50
50
|
"dotenv": "^17.2.3",
|
|
51
|
+
"env-paths": "^4.0.0",
|
|
51
52
|
"escape-string-regexp": "^5.0.0",
|
|
52
53
|
"eslint": "^8.57.1",
|
|
53
54
|
"eslint-config-prettier": "^10.1.8",
|
|
@@ -67,7 +68,9 @@
|
|
|
67
68
|
"handlebars-helpers": "^0.10.0",
|
|
68
69
|
"html-loader": "^5.1.0",
|
|
69
70
|
"html-webpack-plugin": "^5.6.6",
|
|
71
|
+
"js-yaml": "^4.1.1",
|
|
70
72
|
"json-loader": "^0.5.7",
|
|
73
|
+
"ky": "^1.14.3",
|
|
71
74
|
"lodash": "^4.17.23",
|
|
72
75
|
"mini-css-extract-plugin": "^2.10.0",
|
|
73
76
|
"node-notifier": "^10.0.1",
|
|
@@ -95,7 +98,11 @@
|
|
|
95
98
|
"webpack-cli": "^6.0.1",
|
|
96
99
|
"webpack-config-utils": "^2.3.1",
|
|
97
100
|
"webpack-dev-server": "^5.2.3",
|
|
98
|
-
"yaml-loader": "^0.9.0"
|
|
101
|
+
"yaml-loader": "^0.9.0",
|
|
102
|
+
"zod": "^4.3.6"
|
|
103
|
+
},
|
|
104
|
+
"devDependencies": {
|
|
105
|
+
"@types/js-yaml": "^4.0.9"
|
|
99
106
|
},
|
|
100
107
|
"scripts": {
|
|
101
108
|
"typecheck": "tsc --noEmit",
|