@servicetitan/startup 38.1.0 → 38.2.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 (66) hide show
  1. package/dist/cli/commands/build.d.ts.map +1 -1
  2. package/dist/cli/commands/build.js +10 -1
  3. package/dist/cli/commands/build.js.map +1 -1
  4. package/dist/cli/commands/command.d.ts +4 -0
  5. package/dist/cli/commands/command.d.ts.map +1 -1
  6. package/dist/cli/commands/command.js +39 -0
  7. package/dist/cli/commands/command.js.map +1 -1
  8. package/dist/cli/commands/init.d.ts.map +1 -1
  9. package/dist/cli/commands/init.js +0 -1
  10. package/dist/cli/commands/init.js.map +1 -1
  11. package/dist/cli/commands/install.d.ts.map +1 -1
  12. package/dist/cli/commands/install.js +1 -17
  13. package/dist/cli/commands/install.js.map +1 -1
  14. package/dist/cli/commands/registry/command-registry.d.ts +0 -16
  15. package/dist/cli/commands/registry/command-registry.d.ts.map +1 -1
  16. package/dist/cli/commands/registry/install.d.ts +0 -16
  17. package/dist/cli/commands/registry/install.d.ts.map +1 -1
  18. package/dist/cli/commands/registry/install.js +1 -17
  19. package/dist/cli/commands/registry/install.js.map +1 -1
  20. package/dist/cli/commands/start.d.ts.map +1 -1
  21. package/dist/cli/commands/start.js +9 -1
  22. package/dist/cli/commands/start.js.map +1 -1
  23. package/dist/cli/utils/cli-git.d.ts +7 -0
  24. package/dist/cli/utils/cli-git.d.ts.map +1 -1
  25. package/dist/cli/utils/cli-git.js +30 -0
  26. package/dist/cli/utils/cli-git.js.map +1 -1
  27. package/dist/cli/utils/cli-os.d.ts +6 -1
  28. package/dist/cli/utils/cli-os.d.ts.map +1 -1
  29. package/dist/cli/utils/cli-os.js +22 -0
  30. package/dist/cli/utils/cli-os.js.map +1 -1
  31. package/dist/telemetry/index.d.ts +3 -0
  32. package/dist/telemetry/index.d.ts.map +1 -0
  33. package/dist/telemetry/index.js +21 -0
  34. package/dist/telemetry/index.js.map +1 -0
  35. package/dist/telemetry/telemetry.d.ts +15 -0
  36. package/dist/telemetry/telemetry.d.ts.map +1 -0
  37. package/dist/telemetry/telemetry.js +176 -0
  38. package/dist/telemetry/telemetry.js.map +1 -0
  39. package/dist/vite/config/create-filtering-logger.d.ts.map +1 -1
  40. package/dist/vite/config/create-filtering-logger.js +6 -2
  41. package/dist/vite/config/create-filtering-logger.js.map +1 -1
  42. package/dist/webpack/configs/optimization-config.js +13 -8
  43. package/dist/webpack/configs/optimization-config.js.map +1 -1
  44. package/package.json +17 -14
  45. package/src/cli/commands/__tests__/build.test.ts +49 -2
  46. package/src/cli/commands/__tests__/command.test.ts +112 -0
  47. package/src/cli/commands/__tests__/init.test.ts +1 -1
  48. package/src/cli/commands/__tests__/install.test.ts +5 -72
  49. package/src/cli/commands/__tests__/start.test.ts +43 -2
  50. package/src/cli/commands/build.ts +9 -1
  51. package/src/cli/commands/command.ts +50 -0
  52. package/src/cli/commands/init.ts +0 -1
  53. package/src/cli/commands/install.ts +5 -21
  54. package/src/cli/commands/registry/install.ts +1 -6
  55. package/src/cli/commands/start.ts +8 -1
  56. package/src/cli/utils/__tests__/cli-git.test.ts +54 -3
  57. package/src/cli/utils/__tests__/cli-os.test.ts +98 -2
  58. package/src/cli/utils/cli-git.ts +27 -1
  59. package/src/cli/utils/cli-os.ts +30 -0
  60. package/src/telemetry/__tests__/telemetry.test.ts +326 -0
  61. package/src/telemetry/index.ts +2 -0
  62. package/src/telemetry/telemetry.ts +134 -0
  63. package/src/vite/config/__tests__/create-filtering-logger.test.ts +3 -2
  64. package/src/vite/config/create-filtering-logger.ts +8 -2
  65. package/src/webpack/__tests__/create-webpack-config-shared-dependencies.test.ts +27 -1
  66. package/src/webpack/configs/optimization-config.ts +19 -8
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get Telemetry () {
13
+ return _telemetry.Telemetry;
14
+ },
15
+ get telemetry () {
16
+ return _telemetry.telemetry;
17
+ }
18
+ });
19
+ const _telemetry = require("./telemetry");
20
+
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/telemetry/index.ts"],"sourcesContent":["export { Telemetry, telemetry } from './telemetry';\nexport type { AttributeValue, Attributes } from './telemetry';\n"],"names":["Telemetry","telemetry"],"mappings":";;;;;;;;;;;QAASA;eAAAA,oBAAS;;QAAEC;eAAAA,oBAAS;;;2BAAQ"}
@@ -0,0 +1,15 @@
1
+ export type AttributeValue = string | number | boolean | undefined;
2
+ export type Attributes = Record<string, AttributeValue | Record<string, AttributeValue>>;
3
+ export declare class Telemetry {
4
+ private initPromise?;
5
+ private readonly pendingRequests;
6
+ info(name: string, attributes?: Attributes): void;
7
+ warn(name: string, attributes?: Attributes): void;
8
+ error(name: string, error: unknown, attributes?: Attributes): void;
9
+ flush(): Promise<void>;
10
+ private init;
11
+ private event;
12
+ private send;
13
+ }
14
+ export declare const telemetry: Telemetry;
15
+ //# sourceMappingURL=telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/telemetry/telemetry.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AACnE,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;AA4DzF,qBAAa,SAAS;IAClB,OAAO,CAAC,WAAW,CAAC,CAA+B;IACnD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA+B;IAE/D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,GAAE,UAAe,GAAG,IAAI;IAIrD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,GAAE,UAAe,GAAG,IAAI;IAIrD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,GAAE,UAAe,GAAG,IAAI;IAIhE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,KAAK;IAMb,OAAO,CAAC,IAAI;CAwBf;AAED,eAAO,MAAM,SAAS,WAAkB,CAAC"}
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get Telemetry () {
13
+ return Telemetry;
14
+ },
15
+ get telemetry () {
16
+ return telemetry;
17
+ }
18
+ });
19
+ const _install = require("@servicetitan/install");
20
+ const _os = /*#__PURE__*/ _interop_require_default(require("os"));
21
+ const _cligit = require("../cli/utils/cli-git");
22
+ const _core = require("../core");
23
+ function _define_property(obj, key, value) {
24
+ if (key in obj) {
25
+ Object.defineProperty(obj, key, {
26
+ value: value,
27
+ enumerable: true,
28
+ configurable: true,
29
+ writable: true
30
+ });
31
+ } else obj[key] = value;
32
+ return obj;
33
+ }
34
+ function _interop_require_default(obj) {
35
+ return obj && obj.__esModule ? obj : {
36
+ default: obj
37
+ };
38
+ }
39
+ const DDSOURCE = 'frontend-platform';
40
+ const SERVICE = 'startup';
41
+ const SITE = 'datadoghq.com';
42
+ const REQUEST_TIMEOUT_MS = 2000;
43
+ function toError(error) {
44
+ if (error instanceof Error) {
45
+ return {
46
+ message: error.message,
47
+ kind: error.name,
48
+ stack: error.stack
49
+ };
50
+ }
51
+ if (typeof error === 'string') {
52
+ return {
53
+ message: error
54
+ };
55
+ }
56
+ try {
57
+ return {
58
+ message: JSON.stringify(error)
59
+ };
60
+ } catch (unused) {
61
+ return {
62
+ message: 'unserializable error value'
63
+ };
64
+ }
65
+ }
66
+ function getClientToken() {
67
+ if (process.env.DATADOG_CLIENT_TOKEN) {
68
+ return process.env.DATADOG_CLIENT_TOKEN;
69
+ }
70
+ try {
71
+ const secrets = require('@servicetitan/secrets');
72
+ return secrets.datadogStartupClientToken;
73
+ } catch (unused) {
74
+ return undefined;
75
+ }
76
+ }
77
+ async function getBaseContext() {
78
+ var _process_env_AI_AGENT;
79
+ const git = await (0, _cligit.gitGetContext)();
80
+ return {
81
+ service: SERVICE,
82
+ repo: git.repo,
83
+ branch: git.branch,
84
+ startupVersion: (0, _core.getStartupVersion)(),
85
+ ci: (0, _install.isCI)(),
86
+ agent: Boolean((_process_env_AI_AGENT = process.env.AI_AGENT) !== null && _process_env_AI_AGENT !== void 0 ? _process_env_AI_AGENT : process.env.CURSOR_AGENT),
87
+ hostname: _os.default.hostname(),
88
+ os: process.platform,
89
+ node: process.versions.node,
90
+ usr: {
91
+ email: git.userEmail,
92
+ name: git.userName
93
+ }
94
+ };
95
+ }
96
+ async function resolveContext() {
97
+ const clientToken = getClientToken();
98
+ if (!clientToken) {
99
+ return undefined;
100
+ }
101
+ const baseAttributes = await getBaseContext().catch(()=>({}));
102
+ return {
103
+ clientToken,
104
+ baseAttributes
105
+ };
106
+ }
107
+ class Telemetry {
108
+ info(name, attributes = {}) {
109
+ this.event(name, 'info', attributes);
110
+ }
111
+ warn(name, attributes = {}) {
112
+ this.event(name, 'warn', attributes);
113
+ }
114
+ error(name, error, attributes = {}) {
115
+ this.event(name, 'error', {
116
+ ...attributes,
117
+ error: toError(error)
118
+ });
119
+ }
120
+ async flush() {
121
+ /*
122
+ * Promise.all, not allSettled: pending requests never reject, and swallowing
123
+ * here would leave failures asymmetric on whether flush ran (a race).
124
+ */ await Promise.all([
125
+ ...this.pendingRequests
126
+ ]);
127
+ }
128
+ init() {
129
+ var _this_initPromise;
130
+ (_this_initPromise = this.initPromise) !== null && _this_initPromise !== void 0 ? _this_initPromise : this.initPromise = resolveContext();
131
+ return this.initPromise;
132
+ }
133
+ event(name, status, attributes) {
134
+ try {
135
+ this.send({
136
+ message: name,
137
+ status,
138
+ date: Date.now(),
139
+ ...attributes
140
+ });
141
+ } catch (unused) {} // eslint-disable-line no-empty
142
+ }
143
+ send(event) {
144
+ const request = this.init().then((context)=>{
145
+ if (!context) {
146
+ return;
147
+ }
148
+ const { clientToken, baseAttributes } = context;
149
+ const controller = new AbortController();
150
+ const timer = setTimeout(()=>controller.abort(), REQUEST_TIMEOUT_MS);
151
+ timer.unref();
152
+ const url = `https://browser-intake-${SITE}/api/v2/logs` + `?dd-api-key=${encodeURIComponent(clientToken)}&ddsource=${DDSOURCE}`;
153
+ return fetch(url, {
154
+ method: 'POST',
155
+ headers: {
156
+ 'Content-Type': 'application/json'
157
+ },
158
+ body: JSON.stringify([
159
+ {
160
+ ...baseAttributes,
161
+ ...event
162
+ }
163
+ ]),
164
+ signal: controller.signal
165
+ }).finally(()=>clearTimeout(timer));
166
+ }).catch(()=>{}).finally(()=>this.pendingRequests.delete(request));
167
+ this.pendingRequests.add(request);
168
+ }
169
+ constructor(){
170
+ _define_property(this, "initPromise", void 0);
171
+ _define_property(this, "pendingRequests", new Set());
172
+ }
173
+ }
174
+ const telemetry = new Telemetry();
175
+
176
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/telemetry/telemetry.ts"],"sourcesContent":["import { isCI } from '@servicetitan/install';\nimport os from 'os';\nimport { gitGetContext } from '../cli/utils/cli-git';\nimport { getStartupVersion } from '../core';\n\nconst DDSOURCE = 'frontend-platform';\nconst SERVICE = 'startup';\nconst SITE = 'datadoghq.com';\nconst REQUEST_TIMEOUT_MS = 2000;\n\ntype Status = 'info' | 'warn' | 'error';\nexport type AttributeValue = string | number | boolean | undefined;\nexport type Attributes = Record<string, AttributeValue | Record<string, AttributeValue>>;\n\ninterface Context {\n clientToken: string;\n baseAttributes: Attributes;\n}\n\nfunction toError(error: unknown): { message: string; kind?: string; stack?: string } {\n if (error instanceof Error) {\n return { message: error.message, kind: error.name, stack: error.stack };\n }\n if (typeof error === 'string') {\n return { message: error };\n }\n try {\n return { message: JSON.stringify(error) };\n } catch {\n return { message: 'unserializable error value' };\n }\n}\n\nfunction getClientToken(): string | undefined {\n if (process.env.DATADOG_CLIENT_TOKEN) {\n return process.env.DATADOG_CLIENT_TOKEN;\n }\n try {\n const secrets = require('@servicetitan/secrets') as {\n datadogStartupClientToken?: string;\n };\n return secrets.datadogStartupClientToken;\n } catch {\n return undefined;\n }\n}\n\nasync function getBaseContext(): Promise<Attributes> {\n const git = await gitGetContext();\n return {\n service: SERVICE,\n repo: git.repo,\n branch: git.branch,\n startupVersion: getStartupVersion(),\n ci: isCI(),\n agent: Boolean(process.env.AI_AGENT ?? process.env.CURSOR_AGENT),\n hostname: os.hostname(),\n os: process.platform,\n node: process.versions.node,\n usr: { email: git.userEmail, name: git.userName },\n };\n}\n\nasync function resolveContext(): Promise<Context | undefined> {\n const clientToken = getClientToken();\n if (!clientToken) {\n return undefined;\n }\n const baseAttributes = await getBaseContext().catch(() => ({}));\n return { clientToken, baseAttributes };\n}\n\nexport class Telemetry {\n private initPromise?: Promise<Context | undefined>;\n private readonly pendingRequests = new Set<Promise<unknown>>();\n\n info(name: string, attributes: Attributes = {}): void {\n this.event(name, 'info', attributes);\n }\n\n warn(name: string, attributes: Attributes = {}): void {\n this.event(name, 'warn', attributes);\n }\n\n error(name: string, error: unknown, attributes: Attributes = {}): void {\n this.event(name, 'error', { ...attributes, error: toError(error) });\n }\n\n async flush(): Promise<void> {\n /*\n * Promise.all, not allSettled: pending requests never reject, and swallowing\n * here would leave failures asymmetric on whether flush ran (a race).\n */\n await Promise.all([...this.pendingRequests]);\n }\n\n private init(): Promise<Context | undefined> {\n this.initPromise ??= resolveContext();\n return this.initPromise;\n }\n\n private event(name: string, status: Status, attributes: Attributes): void {\n try {\n this.send({ message: name, status, date: Date.now(), ...attributes });\n } catch {} // eslint-disable-line no-empty\n }\n\n private send(event: Attributes): void {\n const request = this.init()\n .then(context => {\n if (!context) {\n return;\n }\n const { clientToken, baseAttributes } = context;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n timer.unref();\n const url =\n `https://browser-intake-${SITE}/api/v2/logs` +\n `?dd-api-key=${encodeURIComponent(clientToken)}&ddsource=${DDSOURCE}`;\n return fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify([{ ...baseAttributes, ...event }]),\n signal: controller.signal,\n }).finally(() => clearTimeout(timer));\n })\n .catch(() => {})\n .finally(() => this.pendingRequests.delete(request));\n this.pendingRequests.add(request);\n }\n}\n\nexport const telemetry = new Telemetry();\n"],"names":["Telemetry","telemetry","DDSOURCE","SERVICE","SITE","REQUEST_TIMEOUT_MS","toError","error","Error","message","kind","name","stack","JSON","stringify","getClientToken","process","env","DATADOG_CLIENT_TOKEN","secrets","require","datadogStartupClientToken","undefined","getBaseContext","git","gitGetContext","service","repo","branch","startupVersion","getStartupVersion","ci","isCI","agent","Boolean","AI_AGENT","CURSOR_AGENT","hostname","os","platform","node","versions","usr","email","userEmail","userName","resolveContext","clientToken","baseAttributes","catch","info","attributes","event","warn","flush","Promise","all","pendingRequests","init","initPromise","status","send","date","Date","now","request","then","context","controller","AbortController","timer","setTimeout","abort","unref","url","encodeURIComponent","fetch","method","headers","body","signal","finally","clearTimeout","delete","add","Set"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"create-filtering-logger.d.ts","sourceRoot":"","sources":["../../../src/vite/config/create-filtering-logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AA0BjD,wBAAgB,qBAAqB,IAAI,MAAM,CAkB9C"}
1
+ {"version":3,"file":"create-filtering-logger.d.ts","sourceRoot":"","sources":["../../../src/vite/config/create-filtering-logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AAgCjD,wBAAgB,qBAAqB,IAAI,MAAM,CAkB9C"}
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "createFilteringLogger", {
9
9
  }
10
10
  });
11
11
  const _vite = require("vite");
12
+ const _ignoremodulesplugin = require("../plugins/ignore-modules-plugin");
12
13
  /*
13
14
  * Expected warnings when a host's HTML references the shared-bundle assets created by
14
15
  * separate "exposed dependencies" build. Matched on ./shared/ so a genuinely missing
@@ -20,9 +21,12 @@ const _vite = require("vite");
20
21
  /*
21
22
  * Expected when code feature-detects an optional peer dependency (e.g. `Package.Export
22
23
  * === undefined`) and ignoreModulesPlugin has substituted an empty module for it. Matched
23
- * on the plugin's IGNORE_EMPTY marker so a genuinely undefined export elsewhere still warns.
24
+ * on the plugin's EMPTY_PREFIX marker so a genuinely undefined export elsewhere still warns.
25
+ * Rolldown renders the marker's leading NUL control character as the visible characters "\"
26
+ * and "0" when it prints a warning, so match that instead of the raw NUL, doubled here
27
+ * because the backslash is also a regex metacharacter.
24
28
  */ const IGNORED_MODULE_WARNINGS = [
25
- /Import `\w+` will always be undefined because there is no matching export in '\\0IGNORE_EMPTY:[^']+'/
29
+ new RegExp(`Import \`\\w+\` will always be undefined because there is no matching export in '${_ignoremodulesplugin.EMPTY_PREFIX.replace('\0', '\\\\0')}[^']+'`)
26
30
  ];
27
31
  const SUPPRESSED_WARNINGS = [
28
32
  ...SHARED_ASSET_WARNINGS,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/vite/config/create-filtering-logger.ts"],"sourcesContent":["import { createLogger, type Logger } from 'vite';\n\n/*\n * Expected warnings when a host's HTML references the shared-bundle assets created by\n * separate \"exposed dependencies\" build. Matched on ./shared/ so a genuinely missing\n * app asset still warns.\n */\nconst SHARED_ASSET_WARNINGS = [\n /<script src=\"\\.\\/shared\\/[^\"]+\"> in \"[^\"]*\" can't be bundled without type=\"module\"/,\n /\\.\\/shared\\/\\S+ doesn't exist at build time/,\n];\n\n/*\n * Expected when code feature-detects an optional peer dependency (e.g. `Package.Export\n * === undefined`) and ignoreModulesPlugin has substituted an empty module for it. Matched\n * on the plugin's IGNORE_EMPTY marker so a genuinely undefined export elsewhere still warns.\n */\nconst IGNORED_MODULE_WARNINGS = [\n /Import `\\w+` will always be undefined because there is no matching export in '\\\\0IGNORE_EMPTY:[^']+'/,\n];\n\nconst SUPPRESSED_WARNINGS = [...SHARED_ASSET_WARNINGS, ...IGNORED_MODULE_WARNINGS];\n\n/*\n * Wraps Vite's logger to drop expected warnings. Everything else passes through.\n */\nexport function createFilteringLogger(): Logger {\n const logger = createLogger();\n const { warn, warnOnce } = logger;\n const isSuppressed = (message: string) =>\n SUPPRESSED_WARNINGS.some(pattern => pattern.test(message));\n\n logger.warn = (message, options) => {\n if (!isSuppressed(message)) {\n warn.call(logger, message, options);\n }\n };\n logger.warnOnce = (message, options) => {\n if (!isSuppressed(message)) {\n warnOnce.call(logger, message, options);\n }\n };\n\n return logger;\n}\n"],"names":["createFilteringLogger","SHARED_ASSET_WARNINGS","IGNORED_MODULE_WARNINGS","SUPPRESSED_WARNINGS","logger","createLogger","warn","warnOnce","isSuppressed","message","some","pattern","test","options","call"],"mappings":";;;;+BA0BgBA;;;eAAAA;;;sBA1B0B;AAE1C;;;;CAIC,GACD,MAAMC,wBAAwB;IAC1B;IACA;CACH;AAED;;;;CAIC,GACD,MAAMC,0BAA0B;IAC5B;CACH;AAED,MAAMC,sBAAsB;OAAIF;OAA0BC;CAAwB;AAK3E,SAASF;IACZ,MAAMI,SAASC,IAAAA,kBAAY;IAC3B,MAAM,EAAEC,IAAI,EAAEC,QAAQ,EAAE,GAAGH;IAC3B,MAAMI,eAAe,CAACC,UAClBN,oBAAoBO,IAAI,CAACC,CAAAA,UAAWA,QAAQC,IAAI,CAACH;IAErDL,OAAOE,IAAI,GAAG,CAACG,SAASI;QACpB,IAAI,CAACL,aAAaC,UAAU;YACxBH,KAAKQ,IAAI,CAACV,QAAQK,SAASI;QAC/B;IACJ;IACAT,OAAOG,QAAQ,GAAG,CAACE,SAASI;QACxB,IAAI,CAACL,aAAaC,UAAU;YACxBF,SAASO,IAAI,CAACV,QAAQK,SAASI;QACnC;IACJ;IAEA,OAAOT;AACX"}
1
+ {"version":3,"sources":["../../../src/vite/config/create-filtering-logger.ts"],"sourcesContent":["import { createLogger, type Logger } from 'vite';\nimport { EMPTY_PREFIX } from '../plugins/ignore-modules-plugin';\n\n/*\n * Expected warnings when a host's HTML references the shared-bundle assets created by\n * separate \"exposed dependencies\" build. Matched on ./shared/ so a genuinely missing\n * app asset still warns.\n */\nconst SHARED_ASSET_WARNINGS = [\n /<script src=\"\\.\\/shared\\/[^\"]+\"> in \"[^\"]*\" can't be bundled without type=\"module\"/,\n /\\.\\/shared\\/\\S+ doesn't exist at build time/,\n];\n\n/*\n * Expected when code feature-detects an optional peer dependency (e.g. `Package.Export\n * === undefined`) and ignoreModulesPlugin has substituted an empty module for it. Matched\n * on the plugin's EMPTY_PREFIX marker so a genuinely undefined export elsewhere still warns.\n * Rolldown renders the marker's leading NUL control character as the visible characters \"\\\"\n * and \"0\" when it prints a warning, so match that instead of the raw NUL, doubled here\n * because the backslash is also a regex metacharacter.\n */\nconst IGNORED_MODULE_WARNINGS = [\n new RegExp(\n `Import \\`\\\\w+\\` will always be undefined because there is no matching export in '${EMPTY_PREFIX.replace('\\0', '\\\\\\\\0')}[^']+'`\n ),\n];\n\nconst SUPPRESSED_WARNINGS = [...SHARED_ASSET_WARNINGS, ...IGNORED_MODULE_WARNINGS];\n\n/*\n * Wraps Vite's logger to drop expected warnings. Everything else passes through.\n */\nexport function createFilteringLogger(): Logger {\n const logger = createLogger();\n const { warn, warnOnce } = logger;\n const isSuppressed = (message: string) =>\n SUPPRESSED_WARNINGS.some(pattern => pattern.test(message));\n\n logger.warn = (message, options) => {\n if (!isSuppressed(message)) {\n warn.call(logger, message, options);\n }\n };\n logger.warnOnce = (message, options) => {\n if (!isSuppressed(message)) {\n warnOnce.call(logger, message, options);\n }\n };\n\n return logger;\n}\n"],"names":["createFilteringLogger","SHARED_ASSET_WARNINGS","IGNORED_MODULE_WARNINGS","RegExp","EMPTY_PREFIX","replace","SUPPRESSED_WARNINGS","logger","createLogger","warn","warnOnce","isSuppressed","message","some","pattern","test","options","call"],"mappings":";;;;+BAgCgBA;;;eAAAA;;;sBAhC0B;qCACb;AAE7B;;;;CAIC,GACD,MAAMC,wBAAwB;IAC1B;IACA;CACH;AAED;;;;;;;CAOC,GACD,MAAMC,0BAA0B;IAC5B,IAAIC,OACA,CAAC,iFAAiF,EAAEC,iCAAY,CAACC,OAAO,CAAC,MAAM,SAAS,MAAM,CAAC;CAEtI;AAED,MAAMC,sBAAsB;OAAIL;OAA0BC;CAAwB;AAK3E,SAASF;IACZ,MAAMO,SAASC,IAAAA,kBAAY;IAC3B,MAAM,EAAEC,IAAI,EAAEC,QAAQ,EAAE,GAAGH;IAC3B,MAAMI,eAAe,CAACC,UAClBN,oBAAoBO,IAAI,CAACC,CAAAA,UAAWA,QAAQC,IAAI,CAACH;IAErDL,OAAOE,IAAI,GAAG,CAACG,SAASI;QACpB,IAAI,CAACL,aAAaC,UAAU;YACxBH,KAAKQ,IAAI,CAACV,QAAQK,SAASI;QAC/B;IACJ;IACAT,OAAOG,QAAQ,GAAG,CAACE,SAASI;QACxB,IAAI,CAACL,aAAaC,UAAU;YACxBF,SAASO,IAAI,CAACV,QAAQK,SAASI;QACnC;IACJ;IAEA,OAAOT;AACX"}
@@ -42,12 +42,13 @@ function optimizationConfig(context, _) {
42
42
  };
43
43
  }
44
44
  function hostConfig(optimization, context) {
45
- const { isProduction } = context.build;
46
- const { isWebComponent } = context.package;
45
+ const { isProduction, emitExposedDependencies } = context.build;
46
+ const { isWebComponent, sharedDependencies } = context.package;
47
47
  if (isWebComponent || !isProduction) {
48
48
  return;
49
49
  }
50
- Object.assign(optimization.splitChunks.cacheGroups, vendorGroups());
50
+ const excludeDesignSystem = emitExposedDependencies && !!sharedDependencies['@servicetitan/design-system'];
51
+ Object.assign(optimization.splitChunks.cacheGroups, vendorGroups(excludeDesignSystem));
51
52
  }
52
53
  function minimizeConfig(optimization, context) {
53
54
  var _ref, _ref1;
@@ -125,27 +126,31 @@ function webComponentConfig(optimization, context) {
125
126
  }
126
127
  });
127
128
  }
128
- function vendorGroups() {
129
+ function vendorGroups(excludeDesignSystem = false) {
130
+ /*
131
+ * The design-system entry already gets its own chunk; excluding it here keeps
132
+ * its CSS from being absorbed into a vendor chunk.
133
+ */ const chunks = excludeDesignSystem ? (chunk)=>chunk.name !== 'design-system' : 'all';
129
134
  return {
130
135
  'servicetitan': {
131
136
  name: 'servicetitan',
132
137
  test: _core.CHUNK_PATTERNS.servicetitan,
133
- chunks: 'all'
138
+ chunks
134
139
  },
135
140
  'vendor-core': {
136
141
  name: 'vendor-core',
137
142
  test: _core.CHUNK_PATTERNS['vendor-core'],
138
- chunks: 'all'
143
+ chunks
139
144
  },
140
145
  'kendo': {
141
146
  name: 'kendo',
142
147
  test: _core.CHUNK_PATTERNS.kendo,
143
- chunks: 'all'
148
+ chunks
144
149
  },
145
150
  'vendor': {
146
151
  name: 'vendor',
147
152
  test: _core.CHUNK_PATTERNS.vendor,
148
- chunks: 'all',
153
+ chunks,
149
154
  priority: -5
150
155
  }
151
156
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/webpack/configs/optimization-config.ts"],"sourcesContent":["import CssMinimizerWebpackPlugin from 'css-minimizer-webpack-plugin';\nimport MinimizerPlugin from 'minimizer-webpack-plugin';\nimport { Configuration } from 'webpack';\nimport { CHUNK_PATTERNS } from '../../core';\nimport { Overrides, WebpackBuildContext } from '../types';\n\ntype Config = Configuration['optimization'];\ntype ConfigWithCacheGroups = Config & { splitChunks: { cacheGroups: Record<string, any> } };\ntype Result = Pick<Configuration, 'optimization'>;\n\nexport function optimizationConfig(context: WebpackBuildContext, _: Overrides): Result {\n const { headless, isProduction, emitExposedDependencies } = context.build;\n\n const optimization: ConfigWithCacheGroups = {\n chunkIds: isProduction ? 'deterministic' : 'named',\n moduleIds: 'size',\n mangleExports: 'size',\n splitChunks: { cacheGroups: {} },\n };\n\n if (emitExposedDependencies) {\n optimization.runtimeChunk = false;\n } else if (!headless && isProduction) {\n optimization.runtimeChunk = 'single';\n }\n\n [hostConfig, minimizeConfig, sharedDependenciesConfig, webComponentConfig].forEach(handler =>\n handler(optimization, context)\n );\n\n return { optimization };\n}\n\nfunction hostConfig(optimization: ConfigWithCacheGroups, context: WebpackBuildContext) {\n const { isProduction } = context.build;\n const { isWebComponent } = context.package;\n if (isWebComponent || !isProduction) {\n return;\n }\n\n Object.assign(optimization.splitChunks.cacheGroups, vendorGroups());\n}\n\nfunction minimizeConfig(optimization: ConfigWithCacheGroups, context: WebpackBuildContext) {\n const { isProduction } = context.build;\n const { isWebComponent } = context.package;\n const { codeCoverage } = context.options;\n const { minify } = context.bundlerConfig;\n if (!isProduction) {\n return;\n }\n\n const minifyJs = minify?.js ?? true;\n const minifyCss = minify?.css ?? true;\n optimization.minimize = !codeCoverage && (!!minifyJs || !!minifyCss);\n if (!optimization.minimize) {\n return;\n }\n\n /*\n * MFE source maps are available to Datadog, so compress and mangle are OK.\n * Disable for hosts until their source maps are uploaded too.\n */\n const minimizerOptions = {\n compress: !!isWebComponent,\n mangle: !!isWebComponent,\n ...(typeof minifyJs === 'object' ? minifyJs : {}),\n };\n\n const cssMinimizerPluginOptions = {\n ...(typeof minifyCss === 'object' ? minifyCss : {}),\n };\n\n optimization.minimizer = [\n ...(minifyJs ? [new MinimizerPlugin({ minimizerOptions })] : []),\n ...(minifyCss ? [new CssMinimizerWebpackPlugin(cssMinimizerPluginOptions)] : []),\n ];\n}\n\nfunction sharedDependenciesConfig(\n optimization: ConfigWithCacheGroups,\n context: WebpackBuildContext\n) {\n const { emitExposedDependencies } = context.build;\n if (!emitExposedDependencies) {\n return;\n }\n\n Object.assign(optimization.splitChunks.cacheGroups, {\n anvil2: {\n test: /@servicetitan[\\\\/]anvil2[\\\\/].*\\.css$/,\n name: 'anvil2',\n chunks: 'all',\n enforce: true,\n // Must outrank vendor groups so anvil2 CSS lands in separate chunk\n priority: 10,\n },\n });\n}\n\nfunction webComponentConfig(optimization: ConfigWithCacheGroups, context: WebpackBuildContext) {\n const { headless, isProduction } = context.build;\n const { isWebComponent } = context.package;\n if (!isWebComponent) {\n return;\n }\n\n const groups = vendorGroups();\n const styles = { name: 'main', type: 'css/mini-extract', chunks: 'all', enforce: true };\n\n Object.assign(optimization.splitChunks.cacheGroups, {\n ...(headless ? {} : { styles }),\n // assets-manifest-plugin requires servicetitan to order CSS correctly (headless has no CSS)\n ...(isProduction ? groups : headless ? {} : { servicetitan: groups.servicetitan }),\n });\n}\n\nfunction vendorGroups() {\n return {\n 'servicetitan': {\n name: 'servicetitan',\n test: CHUNK_PATTERNS.servicetitan,\n chunks: 'all',\n },\n 'vendor-core': {\n name: 'vendor-core',\n test: CHUNK_PATTERNS['vendor-core'],\n chunks: 'all',\n },\n 'kendo': {\n name: 'kendo',\n test: CHUNK_PATTERNS.kendo,\n chunks: 'all',\n },\n 'vendor': {\n name: 'vendor',\n test: CHUNK_PATTERNS.vendor,\n chunks: 'all',\n priority: -5,\n },\n };\n}\n"],"names":["optimizationConfig","context","_","headless","isProduction","emitExposedDependencies","build","optimization","chunkIds","moduleIds","mangleExports","splitChunks","cacheGroups","runtimeChunk","hostConfig","minimizeConfig","sharedDependenciesConfig","webComponentConfig","forEach","handler","isWebComponent","package","Object","assign","vendorGroups","codeCoverage","options","minify","bundlerConfig","minifyJs","js","minifyCss","css","minimize","minimizerOptions","compress","mangle","cssMinimizerPluginOptions","minimizer","MinimizerPlugin","CssMinimizerWebpackPlugin","anvil2","test","name","chunks","enforce","priority","groups","styles","type","servicetitan","CHUNK_PATTERNS","kendo","vendor"],"mappings":";;;;+BAUgBA;;;eAAAA;;;kFAVsB;+EACV;sBAEG;;;;;;AAOxB,SAASA,mBAAmBC,OAA4B,EAAEC,CAAY;IACzE,MAAM,EAAEC,QAAQ,EAAEC,YAAY,EAAEC,uBAAuB,EAAE,GAAGJ,QAAQK,KAAK;IAEzE,MAAMC,eAAsC;QACxCC,UAAUJ,eAAe,kBAAkB;QAC3CK,WAAW;QACXC,eAAe;QACfC,aAAa;YAAEC,aAAa,CAAC;QAAE;IACnC;IAEA,IAAIP,yBAAyB;QACzBE,aAAaM,YAAY,GAAG;IAChC,OAAO,IAAI,CAACV,YAAYC,cAAc;QAClCG,aAAaM,YAAY,GAAG;IAChC;IAEA;QAACC;QAAYC;QAAgBC;QAA0BC;KAAmB,CAACC,OAAO,CAACC,CAAAA,UAC/EA,QAAQZ,cAAcN;IAG1B,OAAO;QAAEM;IAAa;AAC1B;AAEA,SAASO,WAAWP,YAAmC,EAAEN,OAA4B;IACjF,MAAM,EAAEG,YAAY,EAAE,GAAGH,QAAQK,KAAK;IACtC,MAAM,EAAEc,cAAc,EAAE,GAAGnB,QAAQoB,OAAO;IAC1C,IAAID,kBAAkB,CAAChB,cAAc;QACjC;IACJ;IAEAkB,OAAOC,MAAM,CAAChB,aAAaI,WAAW,CAACC,WAAW,EAAEY;AACxD;AAEA,SAAST,eAAeR,YAAmC,EAAEN,OAA4B;;IACrF,MAAM,EAAEG,YAAY,EAAE,GAAGH,QAAQK,KAAK;IACtC,MAAM,EAAEc,cAAc,EAAE,GAAGnB,QAAQoB,OAAO;IAC1C,MAAM,EAAEI,YAAY,EAAE,GAAGxB,QAAQyB,OAAO;IACxC,MAAM,EAAEC,MAAM,EAAE,GAAG1B,QAAQ2B,aAAa;IACxC,IAAI,CAACxB,cAAc;QACf;IACJ;IAEA,MAAMyB,mBAAWF,mBAAAA,6BAAAA,OAAQG,EAAE,uCAAI;IAC/B,MAAMC,qBAAYJ,mBAAAA,6BAAAA,OAAQK,GAAG,yCAAI;IACjCzB,aAAa0B,QAAQ,GAAG,CAACR,gBAAiB,CAAA,CAAC,CAACI,YAAY,CAAC,CAACE,SAAQ;IAClE,IAAI,CAACxB,aAAa0B,QAAQ,EAAE;QACxB;IACJ;IAEA;;;KAGC,GACD,MAAMC,mBAAmB;QACrBC,UAAU,CAAC,CAACf;QACZgB,QAAQ,CAAC,CAAChB;QACV,GAAI,OAAOS,aAAa,WAAWA,WAAW,CAAC,CAAC;IACpD;IAEA,MAAMQ,4BAA4B;QAC9B,GAAI,OAAON,cAAc,WAAWA,YAAY,CAAC,CAAC;IACtD;IAEAxB,aAAa+B,SAAS,GAAG;WACjBT,WAAW;YAAC,IAAIU,+BAAe,CAAC;gBAAEL;YAAiB;SAAG,GAAG,EAAE;WAC3DH,YAAY;YAAC,IAAIS,kCAAyB,CAACH;SAA2B,GAAG,EAAE;KAClF;AACL;AAEA,SAASrB,yBACLT,YAAmC,EACnCN,OAA4B;IAE5B,MAAM,EAAEI,uBAAuB,EAAE,GAAGJ,QAAQK,KAAK;IACjD,IAAI,CAACD,yBAAyB;QAC1B;IACJ;IAEAiB,OAAOC,MAAM,CAAChB,aAAaI,WAAW,CAACC,WAAW,EAAE;QAChD6B,QAAQ;YACJC,MAAM;YACNC,MAAM;YACNC,QAAQ;YACRC,SAAS;YACT,mEAAmE;YACnEC,UAAU;QACd;IACJ;AACJ;AAEA,SAAS7B,mBAAmBV,YAAmC,EAAEN,OAA4B;IACzF,MAAM,EAAEE,QAAQ,EAAEC,YAAY,EAAE,GAAGH,QAAQK,KAAK;IAChD,MAAM,EAAEc,cAAc,EAAE,GAAGnB,QAAQoB,OAAO;IAC1C,IAAI,CAACD,gBAAgB;QACjB;IACJ;IAEA,MAAM2B,SAASvB;IACf,MAAMwB,SAAS;QAAEL,MAAM;QAAQM,MAAM;QAAoBL,QAAQ;QAAOC,SAAS;IAAK;IAEtFvB,OAAOC,MAAM,CAAChB,aAAaI,WAAW,CAACC,WAAW,EAAE;QAChD,GAAIT,WAAW,CAAC,IAAI;YAAE6C;QAAO,CAAC;QAC9B,4FAA4F;QAC5F,GAAI5C,eAAe2C,SAAS5C,WAAW,CAAC,IAAI;YAAE+C,cAAcH,OAAOG,YAAY;QAAC,CAAC;IACrF;AACJ;AAEA,SAAS1B;IACL,OAAO;QACH,gBAAgB;YACZmB,MAAM;YACND,MAAMS,oBAAc,CAACD,YAAY;YACjCN,QAAQ;QACZ;QACA,eAAe;YACXD,MAAM;YACND,MAAMS,oBAAc,CAAC,cAAc;YACnCP,QAAQ;QACZ;QACA,SAAS;YACLD,MAAM;YACND,MAAMS,oBAAc,CAACC,KAAK;YAC1BR,QAAQ;QACZ;QACA,UAAU;YACND,MAAM;YACND,MAAMS,oBAAc,CAACE,MAAM;YAC3BT,QAAQ;YACRE,UAAU,CAAC;QACf;IACJ;AACJ"}
1
+ {"version":3,"sources":["../../../src/webpack/configs/optimization-config.ts"],"sourcesContent":["import CssMinimizerWebpackPlugin from 'css-minimizer-webpack-plugin';\nimport MinimizerPlugin from 'minimizer-webpack-plugin';\nimport { Configuration } from 'webpack';\nimport { CHUNK_PATTERNS } from '../../core';\nimport { Overrides, WebpackBuildContext } from '../types';\n\ntype Config = Configuration['optimization'];\ntype ConfigWithCacheGroups = Config & { splitChunks: { cacheGroups: Record<string, any> } };\ntype Result = Pick<Configuration, 'optimization'>;\n\nexport function optimizationConfig(context: WebpackBuildContext, _: Overrides): Result {\n const { headless, isProduction, emitExposedDependencies } = context.build;\n\n const optimization: ConfigWithCacheGroups = {\n chunkIds: isProduction ? 'deterministic' : 'named',\n moduleIds: 'size',\n mangleExports: 'size',\n splitChunks: { cacheGroups: {} },\n };\n\n if (emitExposedDependencies) {\n optimization.runtimeChunk = false;\n } else if (!headless && isProduction) {\n optimization.runtimeChunk = 'single';\n }\n\n [hostConfig, minimizeConfig, sharedDependenciesConfig, webComponentConfig].forEach(handler =>\n handler(optimization, context)\n );\n\n return { optimization };\n}\n\nfunction hostConfig(optimization: ConfigWithCacheGroups, context: WebpackBuildContext) {\n const { isProduction, emitExposedDependencies } = context.build;\n const { isWebComponent, sharedDependencies } = context.package;\n if (isWebComponent || !isProduction) {\n return;\n }\n\n const excludeDesignSystem =\n emitExposedDependencies && !!sharedDependencies['@servicetitan/design-system'];\n\n Object.assign(optimization.splitChunks.cacheGroups, vendorGroups(excludeDesignSystem));\n}\n\nfunction minimizeConfig(optimization: ConfigWithCacheGroups, context: WebpackBuildContext) {\n const { isProduction } = context.build;\n const { isWebComponent } = context.package;\n const { codeCoverage } = context.options;\n const { minify } = context.bundlerConfig;\n if (!isProduction) {\n return;\n }\n\n const minifyJs = minify?.js ?? true;\n const minifyCss = minify?.css ?? true;\n optimization.minimize = !codeCoverage && (!!minifyJs || !!minifyCss);\n if (!optimization.minimize) {\n return;\n }\n\n /*\n * MFE source maps are available to Datadog, so compress and mangle are OK.\n * Disable for hosts until their source maps are uploaded too.\n */\n const minimizerOptions = {\n compress: !!isWebComponent,\n mangle: !!isWebComponent,\n ...(typeof minifyJs === 'object' ? minifyJs : {}),\n };\n\n const cssMinimizerPluginOptions = {\n ...(typeof minifyCss === 'object' ? minifyCss : {}),\n };\n\n optimization.minimizer = [\n ...(minifyJs ? [new MinimizerPlugin({ minimizerOptions })] : []),\n ...(minifyCss ? [new CssMinimizerWebpackPlugin(cssMinimizerPluginOptions)] : []),\n ];\n}\n\nfunction sharedDependenciesConfig(\n optimization: ConfigWithCacheGroups,\n context: WebpackBuildContext\n) {\n const { emitExposedDependencies } = context.build;\n if (!emitExposedDependencies) {\n return;\n }\n\n Object.assign(optimization.splitChunks.cacheGroups, {\n anvil2: {\n test: /@servicetitan[\\\\/]anvil2[\\\\/].*\\.css$/,\n name: 'anvil2',\n chunks: 'all',\n enforce: true,\n // Must outrank vendor groups so anvil2 CSS lands in separate chunk\n priority: 10,\n },\n });\n}\n\nfunction webComponentConfig(optimization: ConfigWithCacheGroups, context: WebpackBuildContext) {\n const { headless, isProduction } = context.build;\n const { isWebComponent } = context.package;\n if (!isWebComponent) {\n return;\n }\n\n const groups = vendorGroups();\n const styles = { name: 'main', type: 'css/mini-extract', chunks: 'all', enforce: true };\n\n Object.assign(optimization.splitChunks.cacheGroups, {\n ...(headless ? {} : { styles }),\n // assets-manifest-plugin requires servicetitan to order CSS correctly (headless has no CSS)\n ...(isProduction ? groups : headless ? {} : { servicetitan: groups.servicetitan }),\n });\n}\n\nfunction vendorGroups(excludeDesignSystem = false): Record<string, any> {\n /*\n * The design-system entry already gets its own chunk; excluding it here keeps\n * its CSS from being absorbed into a vendor chunk.\n */\n const chunks: any = excludeDesignSystem\n ? (chunk: { name?: string }) => chunk.name !== 'design-system'\n : 'all';\n\n return {\n 'servicetitan': {\n name: 'servicetitan',\n test: CHUNK_PATTERNS.servicetitan,\n chunks,\n },\n 'vendor-core': {\n name: 'vendor-core',\n test: CHUNK_PATTERNS['vendor-core'],\n chunks,\n },\n 'kendo': {\n name: 'kendo',\n test: CHUNK_PATTERNS.kendo,\n chunks,\n },\n 'vendor': {\n name: 'vendor',\n test: CHUNK_PATTERNS.vendor,\n chunks,\n priority: -5,\n },\n };\n}\n"],"names":["optimizationConfig","context","_","headless","isProduction","emitExposedDependencies","build","optimization","chunkIds","moduleIds","mangleExports","splitChunks","cacheGroups","runtimeChunk","hostConfig","minimizeConfig","sharedDependenciesConfig","webComponentConfig","forEach","handler","isWebComponent","sharedDependencies","package","excludeDesignSystem","Object","assign","vendorGroups","codeCoverage","options","minify","bundlerConfig","minifyJs","js","minifyCss","css","minimize","minimizerOptions","compress","mangle","cssMinimizerPluginOptions","minimizer","MinimizerPlugin","CssMinimizerWebpackPlugin","anvil2","test","name","chunks","enforce","priority","groups","styles","type","servicetitan","chunk","CHUNK_PATTERNS","kendo","vendor"],"mappings":";;;;+BAUgBA;;;eAAAA;;;kFAVsB;+EACV;sBAEG;;;;;;AAOxB,SAASA,mBAAmBC,OAA4B,EAAEC,CAAY;IACzE,MAAM,EAAEC,QAAQ,EAAEC,YAAY,EAAEC,uBAAuB,EAAE,GAAGJ,QAAQK,KAAK;IAEzE,MAAMC,eAAsC;QACxCC,UAAUJ,eAAe,kBAAkB;QAC3CK,WAAW;QACXC,eAAe;QACfC,aAAa;YAAEC,aAAa,CAAC;QAAE;IACnC;IAEA,IAAIP,yBAAyB;QACzBE,aAAaM,YAAY,GAAG;IAChC,OAAO,IAAI,CAACV,YAAYC,cAAc;QAClCG,aAAaM,YAAY,GAAG;IAChC;IAEA;QAACC;QAAYC;QAAgBC;QAA0BC;KAAmB,CAACC,OAAO,CAACC,CAAAA,UAC/EA,QAAQZ,cAAcN;IAG1B,OAAO;QAAEM;IAAa;AAC1B;AAEA,SAASO,WAAWP,YAAmC,EAAEN,OAA4B;IACjF,MAAM,EAAEG,YAAY,EAAEC,uBAAuB,EAAE,GAAGJ,QAAQK,KAAK;IAC/D,MAAM,EAAEc,cAAc,EAAEC,kBAAkB,EAAE,GAAGpB,QAAQqB,OAAO;IAC9D,IAAIF,kBAAkB,CAAChB,cAAc;QACjC;IACJ;IAEA,MAAMmB,sBACFlB,2BAA2B,CAAC,CAACgB,kBAAkB,CAAC,8BAA8B;IAElFG,OAAOC,MAAM,CAAClB,aAAaI,WAAW,CAACC,WAAW,EAAEc,aAAaH;AACrE;AAEA,SAASR,eAAeR,YAAmC,EAAEN,OAA4B;;IACrF,MAAM,EAAEG,YAAY,EAAE,GAAGH,QAAQK,KAAK;IACtC,MAAM,EAAEc,cAAc,EAAE,GAAGnB,QAAQqB,OAAO;IAC1C,MAAM,EAAEK,YAAY,EAAE,GAAG1B,QAAQ2B,OAAO;IACxC,MAAM,EAAEC,MAAM,EAAE,GAAG5B,QAAQ6B,aAAa;IACxC,IAAI,CAAC1B,cAAc;QACf;IACJ;IAEA,MAAM2B,mBAAWF,mBAAAA,6BAAAA,OAAQG,EAAE,uCAAI;IAC/B,MAAMC,qBAAYJ,mBAAAA,6BAAAA,OAAQK,GAAG,yCAAI;IACjC3B,aAAa4B,QAAQ,GAAG,CAACR,gBAAiB,CAAA,CAAC,CAACI,YAAY,CAAC,CAACE,SAAQ;IAClE,IAAI,CAAC1B,aAAa4B,QAAQ,EAAE;QACxB;IACJ;IAEA;;;KAGC,GACD,MAAMC,mBAAmB;QACrBC,UAAU,CAAC,CAACjB;QACZkB,QAAQ,CAAC,CAAClB;QACV,GAAI,OAAOW,aAAa,WAAWA,WAAW,CAAC,CAAC;IACpD;IAEA,MAAMQ,4BAA4B;QAC9B,GAAI,OAAON,cAAc,WAAWA,YAAY,CAAC,CAAC;IACtD;IAEA1B,aAAaiC,SAAS,GAAG;WACjBT,WAAW;YAAC,IAAIU,+BAAe,CAAC;gBAAEL;YAAiB;SAAG,GAAG,EAAE;WAC3DH,YAAY;YAAC,IAAIS,kCAAyB,CAACH;SAA2B,GAAG,EAAE;KAClF;AACL;AAEA,SAASvB,yBACLT,YAAmC,EACnCN,OAA4B;IAE5B,MAAM,EAAEI,uBAAuB,EAAE,GAAGJ,QAAQK,KAAK;IACjD,IAAI,CAACD,yBAAyB;QAC1B;IACJ;IAEAmB,OAAOC,MAAM,CAAClB,aAAaI,WAAW,CAACC,WAAW,EAAE;QAChD+B,QAAQ;YACJC,MAAM;YACNC,MAAM;YACNC,QAAQ;YACRC,SAAS;YACT,mEAAmE;YACnEC,UAAU;QACd;IACJ;AACJ;AAEA,SAAS/B,mBAAmBV,YAAmC,EAAEN,OAA4B;IACzF,MAAM,EAAEE,QAAQ,EAAEC,YAAY,EAAE,GAAGH,QAAQK,KAAK;IAChD,MAAM,EAAEc,cAAc,EAAE,GAAGnB,QAAQqB,OAAO;IAC1C,IAAI,CAACF,gBAAgB;QACjB;IACJ;IAEA,MAAM6B,SAASvB;IACf,MAAMwB,SAAS;QAAEL,MAAM;QAAQM,MAAM;QAAoBL,QAAQ;QAAOC,SAAS;IAAK;IAEtFvB,OAAOC,MAAM,CAAClB,aAAaI,WAAW,CAACC,WAAW,EAAE;QAChD,GAAIT,WAAW,CAAC,IAAI;YAAE+C;QAAO,CAAC;QAC9B,4FAA4F;QAC5F,GAAI9C,eAAe6C,SAAS9C,WAAW,CAAC,IAAI;YAAEiD,cAAcH,OAAOG,YAAY;QAAC,CAAC;IACrF;AACJ;AAEA,SAAS1B,aAAaH,sBAAsB,KAAK;IAC7C;;;KAGC,GACD,MAAMuB,SAAcvB,sBACd,CAAC8B,QAA6BA,MAAMR,IAAI,KAAK,kBAC7C;IAEN,OAAO;QACH,gBAAgB;YACZA,MAAM;YACND,MAAMU,oBAAc,CAACF,YAAY;YACjCN;QACJ;QACA,eAAe;YACXD,MAAM;YACND,MAAMU,oBAAc,CAAC,cAAc;YACnCR;QACJ;QACA,SAAS;YACLD,MAAM;YACND,MAAMU,oBAAc,CAACC,KAAK;YAC1BT;QACJ;QACA,UAAU;YACND,MAAM;YACND,MAAMU,oBAAc,CAACE,MAAM;YAC3BV;YACAE,UAAU,CAAC;QACf;IACJ;AACJ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/startup",
3
- "version": "38.1.0",
3
+ "version": "38.2.0",
4
4
  "description": "CLI to create multi-package Lerna projects with TypeScript and React",
5
5
  "homepage": "https://docs.st.dev/docs/frontend/uikit/startup",
6
6
  "repository": {
@@ -103,10 +103,10 @@
103
103
  "@jest/core": "~30.4.2",
104
104
  "@jest/types": "~30.4.1",
105
105
  "@jsdevtools/coverage-istanbul-loader": "^3.0.5",
106
- "@servicetitan/eslint-config": "38.1.0",
107
- "@servicetitan/install": "38.1.0",
108
- "@servicetitan/startup-utils": "38.1.0",
109
- "@servicetitan/stylelint-config": "38.1.0",
106
+ "@servicetitan/eslint-config": "38.2.0",
107
+ "@servicetitan/install": "38.2.0",
108
+ "@servicetitan/startup-utils": "38.2.0",
109
+ "@servicetitan/stylelint-config": "38.2.0",
110
110
  "@svgr/webpack": "^8.1.0",
111
111
  "@swc/cli": "^0.8.1",
112
112
  "@swc/core": "1.15.46",
@@ -125,22 +125,22 @@
125
125
  "eta": "^4.6.0",
126
126
  "execa": "~5.1.1",
127
127
  "glob": "~13.0.6",
128
- "html-webpack-plugin": "~5.6.7",
128
+ "html-webpack-plugin": "~5.6.8",
129
129
  "html-webpack-tags-plugin": "^3.0.2",
130
130
  "identity-obj-proxy": "~3.0.0",
131
131
  "jest": "~30.4.2",
132
132
  "jest-circus": "~30.4.2",
133
133
  "jest-environment-jsdom": "~30.4.1",
134
134
  "jest-fetch-mock": "~4.2.0",
135
- "js-yaml": "~5.2.1",
135
+ "js-yaml": "~5.2.2",
136
136
  "json5": "^2.2.3",
137
137
  "lerna": "~9.0.7",
138
- "less": "~4.6.7",
138
+ "less": "~4.8.1",
139
139
  "less-loader": "~13.0.0",
140
140
  "less-plugin-npm-import": "~2.1.0",
141
141
  "lodash.kebabcase": "^4.1.1",
142
142
  "lodash.memoize": "^4.1.2",
143
- "magic-string": "^0.30.21",
143
+ "magic-string": "^1.1.0",
144
144
  "memfs": "~4.64.0",
145
145
  "mini-css-extract-plugin": "~2.10.2",
146
146
  "minimizer-webpack-plugin": "^5.6.1",
@@ -149,9 +149,9 @@
149
149
  "patch-package": "^8.0.1",
150
150
  "portfinder": "~1.0.38",
151
151
  "postcss": "~8.5.16",
152
- "prettier": "~3.9.5",
152
+ "prettier": "~3.9.6",
153
153
  "react-refresh": "^0.18.0",
154
- "sass": "~1.101.0",
154
+ "sass": "~1.102.0",
155
155
  "sass-loader": "~17.0.0",
156
156
  "semver": "~7.8.5",
157
157
  "source-map-js": "^1.2.1",
@@ -160,7 +160,7 @@
160
160
  "stylelint": "~17.14.1",
161
161
  "swc-loader": "^0.2.7",
162
162
  "terminal-link": "^5.0.0",
163
- "ts-jest": "29.4.11",
163
+ "ts-jest": "29.4.12",
164
164
  "ts-node": "~10.9.2",
165
165
  "typed-css-modules": "~0.9.1",
166
166
  "typescript": "6.0.3",
@@ -179,7 +179,7 @@
179
179
  "webpack-virtual-modules": "~0.6.2",
180
180
  "worker-loader": "~3.0.8",
181
181
  "xhr-mock": "~2.5.1",
182
- "yargs": "~18.0.0"
182
+ "yargs": "~18.1.0"
183
183
  },
184
184
  "peerDependencies": {
185
185
  "cypress": ">=15.0.0",
@@ -193,6 +193,9 @@
193
193
  "optional": true
194
194
  }
195
195
  },
196
+ "optionalDependencies": {
197
+ "@servicetitan/secrets": "^3.2.0"
198
+ },
196
199
  "DEVELOPER_NOTES": {},
197
200
  "publishConfig": {
198
201
  "access": "public"
@@ -200,5 +203,5 @@
200
203
  "cli": {
201
204
  "webpack": false
202
205
  },
203
- "gitHead": "e8c601a26ad49ca0d6b0b84a9f530f3242d53c7f"
206
+ "gitHead": "fd8cf00982a529371e44d76a0ca455dbbb42bae5"
204
207
  }
@@ -2,9 +2,11 @@
2
2
  * @jest-environment node
3
3
  */
4
4
  import { createPackage } from '../../../__mocks__';
5
- import { Package, PackageType, getConfiguration, getPackages, log } from '../../../utils';
6
- import { compile, lernaExec, typeCheck } from '../../utils';
5
+ import { Attributes } from '../../../telemetry';
6
+ import { getConfiguration, getPackages, log, Package, PackageType } from '../../../utils';
7
+ import { compile, lernaExec, ProcessTree, typeCheck } from '../../utils';
7
8
  import { Build } from '../build';
9
+ import { Command } from '../command';
8
10
  import { kendoUILicense } from '../kendo-ui-license';
9
11
  import { entry } from '../registry/build';
10
12
 
@@ -25,15 +27,25 @@ jest.mock('../kendo-ui-license', () => ({
25
27
  }));
26
28
 
27
29
  describe(`[startup] ${Build.name}`, () => {
30
+ const commandProto = Command.prototype as unknown as {
31
+ recordStart: (command: string, attributes?: Attributes) => void;
32
+ recordEnd: (error?: unknown) => Promise<void>;
33
+ };
34
+
28
35
  let args: ConstructorParameters<typeof Build>[0];
29
36
  let packages: Package[];
37
+ let recordStart: jest.SpyInstance;
38
+ let recordEnd: jest.SpyInstance;
30
39
 
31
40
  beforeEach(() => {
32
41
  args = {};
33
42
  packages = [];
43
+ jest.restoreAllMocks();
34
44
  jest.clearAllMocks();
35
45
  jest.mocked(getConfiguration).mockReturnValue({});
36
46
  jest.mocked(getPackages).mockImplementation(() => packages);
47
+ recordStart = jest.spyOn(commandProto, 'recordStart').mockImplementation(() => {});
48
+ recordEnd = jest.spyOn(commandProto, 'recordEnd').mockResolvedValue(undefined);
37
49
  });
38
50
 
39
51
  const subject = async () => new Build(args).execute();
@@ -240,6 +252,41 @@ describe(`[startup] ${Build.name}`, () => {
240
252
  });
241
253
  });
242
254
 
255
+ describe('telemetry', () => {
256
+ beforeEach(() => packages.push(createPackage({ type: PackageType.TSC })));
257
+
258
+ test('records the command start', async () => {
259
+ await subject();
260
+
261
+ expect(recordStart).toHaveBeenCalledWith('build', { bundler: expect.any(String) });
262
+ });
263
+
264
+ test('records the command completion', async () => {
265
+ await subject();
266
+
267
+ expect(recordEnd).toHaveBeenCalledWith();
268
+ });
269
+
270
+ describe('when the build fails', () => {
271
+ const error = new Error('bundle failed');
272
+
273
+ beforeEach(() => {
274
+ jest.spyOn(log, 'error').mockImplementation(jest.fn());
275
+ jest.spyOn(ProcessTree.prototype, 'run').mockRejectedValue(error);
276
+ });
277
+
278
+ test('records the failure', async () => {
279
+ await subject().catch(() => {});
280
+
281
+ expect(recordEnd).toHaveBeenCalledWith(error);
282
+ });
283
+
284
+ test('propagates the error', async () => {
285
+ await expect(subject()).rejects.toBe(error);
286
+ });
287
+ });
288
+ });
289
+
243
290
  describe('with "scope"', () => {
244
291
  beforeEach(() => (args.scope = ['foo']));
245
292