@servicetitan/startup 34.3.0 → 35.0.0

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 (59) hide show
  1. package/dist/cli/commands/get-command.d.ts.map +1 -1
  2. package/dist/cli/commands/get-command.js +2 -0
  3. package/dist/cli/commands/get-command.js.map +1 -1
  4. package/dist/cli/commands/mfe-package-publish.d.ts +10 -0
  5. package/dist/cli/commands/mfe-package-publish.d.ts.map +1 -1
  6. package/dist/cli/commands/mfe-package-publish.js +12 -0
  7. package/dist/cli/commands/mfe-package-publish.js.map +1 -1
  8. package/dist/cli/commands/mfe-package-rollback.d.ts +10 -1
  9. package/dist/cli/commands/mfe-package-rollback.d.ts.map +1 -1
  10. package/dist/cli/commands/mfe-package-rollback.js +15 -3
  11. package/dist/cli/commands/mfe-package-rollback.js.map +1 -1
  12. package/dist/cli/commands/mfe-publish.d.ts.map +1 -1
  13. package/dist/cli/commands/mfe-publish.js +10 -4
  14. package/dist/cli/commands/mfe-publish.js.map +1 -1
  15. package/dist/cli/commands/mfe-purge-cache.d.ts +57 -0
  16. package/dist/cli/commands/mfe-purge-cache.d.ts.map +1 -0
  17. package/dist/cli/commands/mfe-purge-cache.js +101 -0
  18. package/dist/cli/commands/mfe-purge-cache.js.map +1 -0
  19. package/dist/cli/commands/{utils.d.ts → utils/build-rollback-tag.d.ts} +1 -2
  20. package/dist/cli/commands/utils/build-rollback-tag.d.ts.map +1 -0
  21. package/dist/cli/commands/{utils.js → utils/build-rollback-tag.js} +1 -5
  22. package/dist/cli/commands/utils/build-rollback-tag.js.map +1 -0
  23. package/dist/cli/commands/utils/constants.d.ts +2 -0
  24. package/dist/cli/commands/utils/constants.d.ts.map +1 -0
  25. package/dist/cli/commands/utils/constants.js +13 -0
  26. package/dist/cli/commands/utils/constants.js.map +1 -0
  27. package/dist/cli/commands/utils/index.d.ts +4 -0
  28. package/dist/cli/commands/utils/index.d.ts.map +1 -0
  29. package/dist/cli/commands/utils/index.js +22 -0
  30. package/dist/cli/commands/utils/index.js.map +1 -0
  31. package/dist/cli/commands/utils/purge-cache.d.ts +6 -0
  32. package/dist/cli/commands/utils/purge-cache.d.ts.map +1 -0
  33. package/dist/cli/commands/utils/purge-cache.js +21 -0
  34. package/dist/cli/commands/utils/purge-cache.js.map +1 -0
  35. package/dist/cli/utils/cli-os.js +1 -1
  36. package/dist/cli/utils/cli-os.js.map +1 -1
  37. package/dist/utils/get-configuration.d.ts +1 -0
  38. package/dist/utils/get-configuration.d.ts.map +1 -1
  39. package/dist/utils/get-configuration.js +1 -0
  40. package/dist/utils/get-configuration.js.map +1 -1
  41. package/package.json +15 -15
  42. package/src/cli/commands/__tests__/mfe-package-publish.test.ts +27 -1
  43. package/src/cli/commands/__tests__/mfe-package-rollback.test.ts +31 -0
  44. package/src/cli/commands/__tests__/mfe-publish.test.ts +4 -2
  45. package/src/cli/commands/__tests__/mfe-purge-cache.test.ts +141 -0
  46. package/src/cli/commands/get-command.ts +2 -0
  47. package/src/cli/commands/mfe-package-publish.ts +11 -1
  48. package/src/cli/commands/mfe-package-rollback.ts +15 -5
  49. package/src/cli/commands/mfe-publish.ts +14 -3
  50. package/src/cli/commands/mfe-purge-cache.ts +75 -0
  51. package/src/cli/commands/utils/__tests__/purge-cache.test.ts +40 -0
  52. package/src/cli/commands/{utils.ts → utils/build-rollback-tag.ts} +0 -1
  53. package/src/cli/commands/utils/constants.ts +1 -0
  54. package/src/cli/commands/utils/index.ts +3 -0
  55. package/src/cli/commands/utils/purge-cache.ts +13 -0
  56. package/src/cli/utils/cli-os.ts +1 -1
  57. package/src/utils/get-configuration.ts +1 -0
  58. package/dist/cli/commands/utils.d.ts.map +0 -1
  59. package/dist/cli/commands/utils.js.map +0 -1
@@ -22,7 +22,7 @@ import {
22
22
  runCommand,
23
23
  } from '../utils';
24
24
  import { Command, CommandOptions } from './types';
25
- import { buildRollbackTag, DEFAULT_MFE_REGISTRY } from './utils';
25
+ import { DEFAULT_MFE_REGISTRY, buildRollbackTag, purgeCache } from './utils';
26
26
 
27
27
  export const mfePackagePublishOptions = {
28
28
  branch: {
@@ -59,6 +59,11 @@ export const mfePackagePublishOptions = {
59
59
  description: 'Upload source maps to Datadog?',
60
60
  defaultDescription: 'true',
61
61
  },
62
+ purgeCache: {
63
+ boolean: true,
64
+ description: 'Purge unpkg cache after publishing?',
65
+ defaultDescription: 'true',
66
+ },
62
67
  } satisfies CommandOptions;
63
68
 
64
69
  interface PublishData {
@@ -100,6 +105,11 @@ export class MFEPackagePublish extends Command<typeof mfePackagePublishOptions>
100
105
 
101
106
  await this.maybePublishPackage(packageJson, data);
102
107
 
108
+ const { dry, tag } = data;
109
+ if (this.args.purgeCache !== false && !dry) {
110
+ purgeCache({ packageName: packageJson.name, tag });
111
+ }
112
+
103
113
  if (data.uploadSourcemaps) {
104
114
  this.uploadSourcemaps(data);
105
115
  }
@@ -1,7 +1,7 @@
1
1
  import { log, logErrors, readJson } from '../../utils';
2
2
  import { DRY_RUN_PREFIX, npmTagVersion, npmView } from '../utils';
3
3
  import { Command, CommandOptions } from './types';
4
- import { buildRollbackTag, DEFAULT_MFE_REGISTRY } from './utils';
4
+ import { DEFAULT_MFE_REGISTRY, buildRollbackTag, purgeCache } from './utils';
5
5
 
6
6
  export const mfePackageRollbackOptions = {
7
7
  dry: {
@@ -18,6 +18,11 @@ export const mfePackageRollbackOptions = {
18
18
  description: 'The tag to rollback to its previous version',
19
19
  required: true,
20
20
  },
21
+ purgeCache: {
22
+ boolean: true,
23
+ description: 'Purge unpkg cache after rolling back?',
24
+ defaultDescription: 'true',
25
+ },
21
26
  } satisfies CommandOptions;
22
27
 
23
28
  interface PackageJson {
@@ -25,8 +30,6 @@ interface PackageJson {
25
30
  }
26
31
 
27
32
  export class MFEPackageRollback extends Command<typeof mfePackageRollbackOptions> {
28
- static readonly description = 'Rollback a package to a previous tagged version';
29
-
30
33
  static readonly options = mfePackageRollbackOptions;
31
34
 
32
35
  private get dryRunPrefix() {
@@ -35,11 +38,16 @@ export class MFEPackageRollback extends Command<typeof mfePackageRollbackOptions
35
38
 
36
39
  @logErrors
37
40
  async execute() {
38
- if (this.args.dry) {
41
+ const { dry, tag } = this.args;
42
+ if (dry) {
39
43
  log.warning('DRY-RUN MODE ENABLED, WILL NOT PERFORM ROLLBACK');
40
44
  }
41
45
 
42
- await this.handleRollback();
46
+ const packageName = await this.handleRollback();
47
+
48
+ if (packageName && this.args.purgeCache !== false && !dry) {
49
+ purgeCache({ packageName, tag });
50
+ }
43
51
  }
44
52
 
45
53
  private async handleRollback() {
@@ -96,5 +104,7 @@ export class MFEPackageRollback extends Command<typeof mfePackageRollbackOptions
96
104
  tag,
97
105
  });
98
106
  }
107
+
108
+ return packageName;
99
109
  }
100
110
  }
@@ -111,17 +111,28 @@ export class MFEPublish extends Command<MFEPublishOptions> {
111
111
  }
112
112
 
113
113
  getPublishOptions() {
114
- const { build, branch, dry, force, registry, tag, uploadSourcemaps, trackHistory } =
115
- this.args;
114
+ const {
115
+ build,
116
+ branch,
117
+ dry,
118
+ force,
119
+ purgeCache,
120
+ registry,
121
+ tag,
122
+ uploadSourcemaps,
123
+ trackHistory,
124
+ } = this.args;
116
125
  return [
117
126
  ...[branch && `--branch ${branch}`],
118
127
  ...[build && `--build ${build}`],
119
128
  ...[dry && '--dry'],
120
129
  ...[force && '--force'],
130
+ ...[purgeCache === true && '--purge-cache'],
131
+ ...[purgeCache === false && '--no-purge-cache'],
121
132
  ...[registry && `--registry ${registry}`],
133
+ ...[typeof tag === 'string' && `--tag ${tag}`],
122
134
  ...[trackHistory === true && '--track-history'],
123
135
  ...[trackHistory === false && '--no-track-history'],
124
- ...[typeof tag === 'string' && `--tag ${tag}`],
125
136
  ...[uploadSourcemaps === true && `--upload-sourcemaps`],
126
137
  ...[uploadSourcemaps === false && `--no-upload-sourcemaps`],
127
138
  ].filter(item => !!item) as string[];
@@ -0,0 +1,75 @@
1
+ import { log, logErrors } from '../../utils';
2
+ import { Command, CommandOptions } from './types';
3
+
4
+ const mfePurgeCacheOptions = {
5
+ host: {
6
+ string: true,
7
+ description: 'Host URL to send purge requests to',
8
+ demandOption: true,
9
+ },
10
+ packageName: {
11
+ string: true,
12
+ description: 'Package name to purge',
13
+ demandOption: true,
14
+ },
15
+ tag: {
16
+ string: true,
17
+ description: 'Package tag to purge',
18
+ demandOption: true,
19
+ },
20
+ token: {
21
+ string: true,
22
+ description: 'X-Purge-Token header value',
23
+ defaultDescription: 'process.env.UNPKG_PURGE_TOKEN',
24
+ },
25
+ } satisfies CommandOptions;
26
+
27
+ export type PurgeResponse = {
28
+ pod: string;
29
+ status: number;
30
+ cache: string | null;
31
+ location: string | null;
32
+ }[];
33
+
34
+ export class MFEPurgeCache extends Command<typeof mfePurgeCacheOptions> {
35
+ static readonly options = mfePurgeCacheOptions;
36
+
37
+ @logErrors
38
+ async execute() {
39
+ const { host: rawHost, packageName, tag } = this.args;
40
+ const host = rawHost.replace(/\/$/, '');
41
+ const token = this.args.token ?? process.env.UNPKG_PURGE_TOKEN;
42
+ const packageNameAndTag = `${packageName}@${tag}`;
43
+ const path = `${packageNameAndTag}/dist/metadata.json`;
44
+
45
+ log.info(`Purging cache for ${packageNameAndTag}`);
46
+
47
+ if (!token) {
48
+ log.warning('Token is not defined, skipping purge');
49
+ return;
50
+ }
51
+
52
+ const response = await fetch(`${host}/_purge/${path}`, {
53
+ method: 'POST',
54
+ headers: { 'X-Purge-Token': token },
55
+ });
56
+
57
+ if (!response.ok) {
58
+ throw new Error(`Purge request failed: ${response.status} ${response.statusText}`);
59
+ }
60
+
61
+ const responseJson = await response.json();
62
+ /* istanbul ignore next: debug only */
63
+ log.debug('mfe-purge-cache', () => JSON.stringify(responseJson, null, 2));
64
+
65
+ log.info(`Cache purged: ${path} -> ${this.getLocation(responseJson)}`);
66
+ }
67
+
68
+ private getLocation(responseJson: PurgeResponse) {
69
+ let location: string | null = null;
70
+ if (Array.isArray(responseJson)) {
71
+ location = responseJson[0]?.location?.replace(/^\//, '') ?? null;
72
+ }
73
+ return location;
74
+ }
75
+ }
@@ -0,0 +1,40 @@
1
+ import { runCommandOutput } from '../../../utils';
2
+ import { purgeCache } from '../purge-cache';
3
+
4
+ jest.mock('../../../utils', () => ({
5
+ ...jest.requireActual('../../../utils'),
6
+ runCommandOutput: jest.fn(),
7
+ }));
8
+
9
+ describe(purgeCache.name, () => {
10
+ let args: Parameters<typeof purgeCache>[0];
11
+ const packageName = '@servicetitan/foo';
12
+ const tag = 'prod';
13
+
14
+ beforeEach(() => {
15
+ jest.clearAllMocks();
16
+ args = { packageName, tag };
17
+ });
18
+
19
+ const subject = () => purgeCache(args);
20
+
21
+ test('runs mfe-purge-cache with host "https://unpkg.servicetitan.com", package name and tag', () => {
22
+ subject();
23
+
24
+ expect(runCommandOutput).toHaveBeenCalledWith(
25
+ `npx startup mfe-purge-cache --host https://unpkg.servicetitan.com --package-name ${packageName} --tag ${tag}`
26
+ );
27
+ });
28
+
29
+ describe('when registry is "https://verdaccio.st.dev"', () => {
30
+ beforeEach(() => (args.registry = 'https://verdaccio.st.dev'));
31
+
32
+ test('runs mfe-purge-cache with host "https://unpkg.st.dev"', () => {
33
+ subject();
34
+
35
+ expect(runCommandOutput).toHaveBeenCalledWith(
36
+ expect.stringContaining(`--host https://unpkg.st.dev`)
37
+ );
38
+ });
39
+ });
40
+ });
@@ -1,4 +1,3 @@
1
- export const DEFAULT_MFE_REGISTRY = 'https://verdaccio.servicetitan.com';
2
1
  export const ROLLBACK_TAG_SUFFIX = '-rollback-1';
3
2
 
4
3
  export function buildRollbackTag(tag: string): string {
@@ -0,0 +1 @@
1
+ export const DEFAULT_MFE_REGISTRY = 'https://verdaccio.servicetitan.com';
@@ -0,0 +1,3 @@
1
+ export * from './build-rollback-tag';
2
+ export * from './constants';
3
+ export * from './purge-cache';
@@ -0,0 +1,13 @@
1
+ import { runCommandOutput } from '../../utils';
2
+
3
+ const DEV_MFE_REGISTRY = 'https://verdaccio.st.dev';
4
+ const DEFAULT_UNPKG_HOST = 'https://unpkg.servicetitan.com';
5
+ const DEV_UNPKG_HOST = 'https://unpkg.st.dev';
6
+
7
+ export function purgeCache(options: { packageName: string; registry?: string; tag: string }) {
8
+ const { packageName, registry, tag } = options;
9
+ const host = registry === DEV_MFE_REGISTRY ? DEV_UNPKG_HOST : DEFAULT_UNPKG_HOST;
10
+ runCommandOutput(
11
+ `npx startup mfe-purge-cache --host ${host} --package-name ${packageName} --tag ${tag}`
12
+ );
13
+ }
@@ -74,7 +74,7 @@ export function runCommandOutput(
74
74
  const result = execSync(fullCommand, execSyncOptions).toString();
75
75
 
76
76
  if (!quiet) {
77
- log.info('command finished', result);
77
+ log.info('command finished', result.trim());
78
78
  }
79
79
 
80
80
  return result;
@@ -76,6 +76,7 @@ export enum CommandName {
76
76
  'mfe-package-publish' = 'mfe-package-publish',
77
77
  'mfe-package-rollback' = 'mfe-package-rollback',
78
78
  'mfe-publish' = 'mfe-publish',
79
+ 'mfe-purge-cache' = 'mfe-purge-cache',
79
80
  'prepare-package' = 'prepare-package',
80
81
  'review' = 'review',
81
82
  'start' = 'start',
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,uCAAuC,CAAC;AACzE,eAAO,MAAM,mBAAmB,gBAAgB,CAAC;AAEjD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/cli/commands/utils.ts"],"sourcesContent":["export const DEFAULT_MFE_REGISTRY = 'https://verdaccio.servicetitan.com';\nexport const ROLLBACK_TAG_SUFFIX = '-rollback-1';\n\nexport function buildRollbackTag(tag: string): string {\n return `${tag}${ROLLBACK_TAG_SUFFIX}`;\n}\n"],"names":["DEFAULT_MFE_REGISTRY","ROLLBACK_TAG_SUFFIX","buildRollbackTag","tag"],"mappings":";;;;;;;;;;;QAAaA;eAAAA;;QACAC;eAAAA;;QAEGC;eAAAA;;;AAHT,MAAMF,uBAAuB;AAC7B,MAAMC,sBAAsB;AAE5B,SAASC,iBAAiBC,GAAW;IACxC,OAAO,GAAGA,MAAMF,qBAAqB;AACzC"}