@servicetitan/startup 32.0.1 → 32.1.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 (72) hide show
  1. package/dist/cli/commands/review/rules/index.d.ts.map +1 -1
  2. package/dist/cli/commands/review/rules/index.js +10 -2
  3. package/dist/cli/commands/review/rules/index.js.map +1 -1
  4. package/dist/cli/commands/review/rules/no-deprecated-content-base.d.ts +13 -0
  5. package/dist/cli/commands/review/rules/no-deprecated-content-base.d.ts.map +1 -0
  6. package/dist/cli/commands/review/rules/no-deprecated-content-base.js +71 -0
  7. package/dist/cli/commands/review/rules/no-deprecated-content-base.js.map +1 -0
  8. package/dist/cli/commands/review/rules/no-direct-peer-dependencies.d.ts +15 -0
  9. package/dist/cli/commands/review/rules/no-direct-peer-dependencies.d.ts.map +1 -0
  10. package/dist/cli/commands/review/rules/no-direct-peer-dependencies.js +75 -0
  11. package/dist/cli/commands/review/rules/no-direct-peer-dependencies.js.map +1 -0
  12. package/dist/cli/commands/review/rules/no-typescript-entry-point.d.ts +2 -2
  13. package/dist/cli/commands/review/rules/no-typescript-entry-point.d.ts.map +1 -1
  14. package/dist/cli/commands/review/rules/no-typescript-entry-point.js +58 -45
  15. package/dist/cli/commands/review/rules/no-typescript-entry-point.js.map +1 -1
  16. package/dist/cli/commands/review/rules/prefer-open-ended-peer-dependencies.d.ts +20 -0
  17. package/dist/cli/commands/review/rules/prefer-open-ended-peer-dependencies.d.ts.map +1 -0
  18. package/dist/cli/commands/review/rules/prefer-open-ended-peer-dependencies.js +145 -0
  19. package/dist/cli/commands/review/rules/prefer-open-ended-peer-dependencies.js.map +1 -0
  20. package/dist/cli/commands/review/rules/require-compatible-launch-darkly-sdk.d.ts +22 -0
  21. package/dist/cli/commands/review/rules/require-compatible-launch-darkly-sdk.d.ts.map +1 -0
  22. package/dist/cli/commands/review/rules/require-compatible-launch-darkly-sdk.js +189 -0
  23. package/dist/cli/commands/review/rules/require-compatible-launch-darkly-sdk.js.map +1 -0
  24. package/dist/cli/commands/review/rules/require-explicit-side-effects.d.ts +2 -1
  25. package/dist/cli/commands/review/rules/require-explicit-side-effects.d.ts.map +1 -1
  26. package/dist/cli/commands/review/rules/require-explicit-side-effects.js +24 -11
  27. package/dist/cli/commands/review/rules/require-explicit-side-effects.js.map +1 -1
  28. package/dist/cli/commands/review/rules/require-one-collection-version.d.ts.map +1 -1
  29. package/dist/cli/commands/review/rules/require-one-collection-version.js +1 -1
  30. package/dist/cli/commands/review/rules/require-one-collection-version.js.map +1 -1
  31. package/dist/cli/commands/review/rules/require-project-version-in-root-node-modules.d.ts.map +1 -1
  32. package/dist/cli/commands/review/rules/require-project-version-in-root-node-modules.js +5 -7
  33. package/dist/cli/commands/review/rules/require-project-version-in-root-node-modules.js.map +1 -1
  34. package/dist/cli/commands/review/rules/require-servicetitan-scope.d.ts +2 -1
  35. package/dist/cli/commands/review/rules/require-servicetitan-scope.d.ts.map +1 -1
  36. package/dist/cli/commands/review/rules/require-servicetitan-scope.js +24 -11
  37. package/dist/cli/commands/review/rules/require-servicetitan-scope.js.map +1 -1
  38. package/dist/cli/commands/review/types.d.ts +4 -1
  39. package/dist/cli/commands/review/types.d.ts.map +1 -1
  40. package/dist/cli/commands/review/types.js.map +1 -1
  41. package/dist/cli/commands/review/utils/check-packages.d.ts +7 -0
  42. package/dist/cli/commands/review/utils/check-packages.d.ts.map +1 -0
  43. package/dist/cli/commands/review/utils/check-packages.js +30 -0
  44. package/dist/cli/commands/review/utils/check-packages.js.map +1 -0
  45. package/dist/cli/commands/review/utils/index.d.ts +1 -0
  46. package/dist/cli/commands/review/utils/index.d.ts.map +1 -1
  47. package/dist/cli/commands/review/utils/index.js +1 -0
  48. package/dist/cli/commands/review/utils/index.js.map +1 -1
  49. package/dist/cli/utils/cli-git.d.ts.map +1 -1
  50. package/dist/cli/utils/cli-git.js +11 -8
  51. package/dist/cli/utils/cli-git.js.map +1 -1
  52. package/package.json +4 -4
  53. package/src/cli/commands/review/rules/__mocks__/mock-config.ts +8 -2
  54. package/src/cli/commands/review/rules/__tests__/no-deprecated-content-base.test.ts +123 -0
  55. package/src/cli/commands/review/rules/__tests__/no-direct-peer-dependencies.test.ts +130 -0
  56. package/src/cli/commands/review/rules/__tests__/prefer-open-ended-peer-dependencies.test.ts +121 -0
  57. package/src/cli/commands/review/rules/__tests__/require-compatible-launch-darkly-sdk.test.ts +256 -0
  58. package/src/cli/commands/review/rules/index.ts +10 -2
  59. package/src/cli/commands/review/rules/no-deprecated-content-base.ts +50 -0
  60. package/src/cli/commands/review/rules/no-direct-peer-dependencies.ts +58 -0
  61. package/src/cli/commands/review/rules/no-typescript-entry-point.ts +5 -8
  62. package/src/cli/commands/review/rules/prefer-open-ended-peer-dependencies.ts +89 -0
  63. package/src/cli/commands/review/rules/require-compatible-launch-darkly-sdk.ts +141 -0
  64. package/src/cli/commands/review/rules/require-explicit-side-effects.ts +14 -14
  65. package/src/cli/commands/review/rules/require-one-collection-version.ts +1 -3
  66. package/src/cli/commands/review/rules/require-project-version-in-root-node-modules.ts +5 -9
  67. package/src/cli/commands/review/rules/require-servicetitan-scope.ts +14 -14
  68. package/src/cli/commands/review/types.ts +16 -2
  69. package/src/cli/commands/review/utils/check-packages.ts +19 -0
  70. package/src/cli/commands/review/utils/index.ts +1 -0
  71. package/src/cli/utils/__tests__/cli-git.test.ts +20 -18
  72. package/src/cli/utils/cli-git.ts +8 -7
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "checkPackages", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return checkPackages;
9
+ }
10
+ });
11
+ const _applyfilter = require("./apply-filter");
12
+ function checkPackages({ id }, { config, packages }, fn) {
13
+ var _config_rules;
14
+ const ruleConfig = id ? (_config_rules = config.rules) === null || _config_rules === void 0 ? void 0 : _config_rules[id] : undefined;
15
+ return (0, _applyfilter.applyFilter)(ruleConfig, packages, ({ name })=>name).reduce((result, pkg)=>{
16
+ const error = fn(pkg);
17
+ if (Array.isArray(error)) {
18
+ return [
19
+ ...result,
20
+ ...error
21
+ ];
22
+ }
23
+ return error ? [
24
+ ...result,
25
+ error
26
+ ] : result;
27
+ }, []);
28
+ }
29
+
30
+ //# sourceMappingURL=check-packages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/cli/commands/review/utils/check-packages.ts"],"sourcesContent":["import { Package, PackageError, Project } from '../types';\nimport { applyFilter } from './apply-filter';\n\ntype CheckFn<T> = (pkg: Package) => PackageError<T>[] | PackageError<T> | undefined;\n\nexport function checkPackages<T>(\n { id }: { id?: string },\n { config, packages }: Project,\n fn: CheckFn<T>\n) {\n const ruleConfig = id ? config.rules?.[id] : undefined;\n return applyFilter(ruleConfig, packages, ({ name }) => name).reduce((result, pkg) => {\n const error = fn(pkg);\n if (Array.isArray(error)) {\n return [...result, ...error];\n }\n return error ? [...result, error] : result;\n }, []);\n}\n"],"names":["checkPackages","id","config","packages","fn","ruleConfig","rules","undefined","applyFilter","name","reduce","result","pkg","error","Array","isArray"],"mappings":";;;;+BAKgBA;;;eAAAA;;;6BAJY;AAIrB,SAASA,cACZ,EAAEC,EAAE,EAAmB,EACvB,EAAEC,MAAM,EAAEC,QAAQ,EAAW,EAC7BC,EAAc;QAEUF;IAAxB,MAAMG,aAAaJ,MAAKC,gBAAAA,OAAOI,KAAK,cAAZJ,oCAAAA,aAAc,CAACD,GAAG,GAAGM;IAC7C,OAAOC,IAAAA,wBAAW,EAACH,YAAYF,UAAU,CAAC,EAAEM,IAAI,EAAE,GAAKA,MAAMC,MAAM,CAAC,CAACC,QAAQC;QACzE,MAAMC,QAAQT,GAAGQ;QACjB,IAAIE,MAAMC,OAAO,CAACF,QAAQ;YACtB,OAAO;mBAAIF;mBAAWE;aAAM;QAChC;QACA,OAAOA,QAAQ;eAAIF;YAAQE;SAAM,GAAGF;IACxC,GAAG,EAAE;AACT"}
@@ -1,4 +1,5 @@
1
1
  export * from './apply-filter';
2
+ export * from './check-packages';
2
3
  export * from './collate-dependencies';
3
4
  export * from './compare-version';
4
5
  export * from './format-depends-on';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/review/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/review/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC"}
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
5
  _export_star(require("./apply-filter"), exports);
6
+ _export_star(require("./check-packages"), exports);
6
7
  _export_star(require("./collate-dependencies"), exports);
7
8
  _export_star(require("./compare-version"), exports);
8
9
  _export_star(require("./format-depends-on"), exports);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/cli/commands/review/utils/index.ts"],"sourcesContent":["export * from './apply-filter';\nexport * from './collate-dependencies';\nexport * from './compare-version';\nexport * from './format-depends-on';\nexport * from './format-location';\nexport * from './get-key';\nexport * from './get-max-version';\nexport * from './indent';\nexport * from './is-library';\nexport * from './name-to-location';\nexport * from './pluralize';\nexport * from './set-version';\nexport * from './summarize';\n"],"names":[],"mappings":";;;;qBAAc;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA"}
1
+ {"version":3,"sources":["../../../../../src/cli/commands/review/utils/index.ts"],"sourcesContent":["export * from './apply-filter';\nexport * from './check-packages';\nexport * from './collate-dependencies';\nexport * from './compare-version';\nexport * from './format-depends-on';\nexport * from './format-location';\nexport * from './get-key';\nexport * from './get-max-version';\nexport * from './indent';\nexport * from './is-library';\nexport * from './name-to-location';\nexport * from './pluralize';\nexport * from './set-version';\nexport * from './summarize';\n"],"names":[],"mappings":";;;;qBAAc;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA"}
@@ -1 +1 @@
1
- {"version":3,"file":"cli-git.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/cli-git.ts"],"names":[],"mappings":"AAIA,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,UAAU,IAAI;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,IAAI,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,oBAkBxE;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAsB,EAAE,IAAI,EAAE,EAAE,IAAI,WASpE"}
1
+ {"version":3,"file":"cli-git.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/cli-git.ts"],"names":[],"mappings":"AAIA,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,UAAU,IAAI;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,IAAI,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,oBAsBxE;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAsB,EAAE,IAAI,EAAE,EAAE,IAAI,WASpE"}
@@ -43,7 +43,12 @@ async function gitCloneRepo(params) {
43
43
  _utils.log.debug('git:clone-repo', `running ${command}`);
44
44
  // eslint-disable-next-line no-await-in-loop
45
45
  await (0, _clios.runCommand)(command, {
46
- quiet: true
46
+ quiet: true,
47
+ // eslint-disable-next-line @typescript-eslint/naming-convention
48
+ env: {
49
+ ...process.env,
50
+ GIT_TERMINAL_PROMPT: '0'
51
+ }
47
52
  });
48
53
  return true;
49
54
  } catch (e) {
@@ -70,14 +75,12 @@ function gitIsReachable({ owner = 'servicetitan', name }) {
70
75
  function getGitUrls({ owner, name }) {
71
76
  const webUrl = `https://github.com/${owner}/${name}.git`;
72
77
  const sshUrl = `git@github.com:${owner}/${name}.git`;
73
- const urls = [
74
- webUrl,
75
- sshUrl
78
+ return (0, _isci.isCI)() && !!process.env.GITHUB_TOKEN ? [
79
+ webUrl.replace('github.com', `oauth2:${process.env.GITHUB_TOKEN}@github.com`)
80
+ ] : [
81
+ sshUrl,
82
+ webUrl
76
83
  ];
77
- if ((0, _isci.isCI)() && !!process.env.GITHUB_TOKEN) {
78
- urls.unshift(webUrl.replace('github.com', `oauth2:${process.env.GITHUB_TOKEN}@github.com`));
79
- }
80
- return urls;
81
84
  }
82
85
 
83
86
  //# sourceMappingURL=cli-git.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/utils/cli-git.ts"],"sourcesContent":["import { log } from '../../utils';\nimport { runCommand, runCommandOutput } from './cli-os';\nimport { isCI } from './is-ci';\n\nexport function gitGetBranch(): string {\n return runCommandOutput('git rev-parse --abbrev-ref HEAD').trim();\n}\n\nexport function gitGetCommitHash(): string {\n return runCommandOutput('git rev-parse --short HEAD').trim();\n}\n\ninterface Repo {\n owner?: string;\n name: string;\n}\n\nexport async function gitCloneRepo(params: Repo & { destination: string }) {\n const { destination, name, owner = 'servicetitan' } = params;\n const gitUrls = getGitUrls({ owner, name });\n\n for (const url of gitUrls) {\n try {\n const command = `git clone -q ${url} ${destination}`;\n log.debug('git:clone-repo', `running ${command}`);\n\n // eslint-disable-next-line no-await-in-loop\n await runCommand(command, { quiet: true });\n return true;\n } catch {\n // ignore error\n }\n }\n\n return false;\n}\n\nexport function gitIsReachable({ owner = 'servicetitan', name }: Repo) {\n return getGitUrls({ owner, name }).some(url => {\n try {\n runCommandOutput(`git ls-remote -qt ${url}`, { quiet: true });\n return true;\n } catch {\n return false;\n }\n });\n}\n\nfunction getGitUrls({ owner, name }: Repo) {\n const webUrl = `https://github.com/${owner}/${name}.git`;\n const sshUrl = `git@github.com:${owner}/${name}.git`;\n\n const urls = [webUrl, sshUrl];\n if (isCI() && !!process.env.GITHUB_TOKEN) {\n urls.unshift(webUrl.replace('github.com', `oauth2:${process.env.GITHUB_TOKEN}@github.com`));\n }\n\n return urls;\n}\n"],"names":["gitCloneRepo","gitGetBranch","gitGetCommitHash","gitIsReachable","runCommandOutput","trim","params","destination","name","owner","gitUrls","getGitUrls","url","command","log","debug","runCommand","quiet","some","webUrl","sshUrl","urls","isCI","process","env","GITHUB_TOKEN","unshift","replace"],"mappings":";;;;;;;;;;;QAiBsBA;eAAAA;;QAbNC;eAAAA;;QAIAC;eAAAA;;QA6BAC;eAAAA;;;uBArCI;uBACyB;sBACxB;AAEd,SAASF;IACZ,OAAOG,IAAAA,uBAAgB,EAAC,mCAAmCC,IAAI;AACnE;AAEO,SAASH;IACZ,OAAOE,IAAAA,uBAAgB,EAAC,8BAA8BC,IAAI;AAC9D;AAOO,eAAeL,aAAaM,MAAsC;IACrE,MAAM,EAAEC,WAAW,EAAEC,IAAI,EAAEC,QAAQ,cAAc,EAAE,GAAGH;IACtD,MAAMI,UAAUC,WAAW;QAAEF;QAAOD;IAAK;IAEzC,KAAK,MAAMI,OAAOF,QAAS;QACvB,IAAI;YACA,MAAMG,UAAU,CAAC,aAAa,EAAED,IAAI,CAAC,EAAEL,aAAa;YACpDO,UAAG,CAACC,KAAK,CAAC,kBAAkB,CAAC,QAAQ,EAAEF,SAAS;YAEhD,4CAA4C;YAC5C,MAAMG,IAAAA,iBAAU,EAACH,SAAS;gBAAEI,OAAO;YAAK;YACxC,OAAO;QACX,EAAE,UAAM;QACJ,eAAe;QACnB;IACJ;IAEA,OAAO;AACX;AAEO,SAASd,eAAe,EAAEM,QAAQ,cAAc,EAAED,IAAI,EAAQ;IACjE,OAAOG,WAAW;QAAEF;QAAOD;IAAK,GAAGU,IAAI,CAACN,CAAAA;QACpC,IAAI;YACAR,IAAAA,uBAAgB,EAAC,CAAC,kBAAkB,EAAEQ,KAAK,EAAE;gBAAEK,OAAO;YAAK;YAC3D,OAAO;QACX,EAAE,UAAM;YACJ,OAAO;QACX;IACJ;AACJ;AAEA,SAASN,WAAW,EAAEF,KAAK,EAAED,IAAI,EAAQ;IACrC,MAAMW,SAAS,CAAC,mBAAmB,EAAEV,MAAM,CAAC,EAAED,KAAK,IAAI,CAAC;IACxD,MAAMY,SAAS,CAAC,eAAe,EAAEX,MAAM,CAAC,EAAED,KAAK,IAAI,CAAC;IAEpD,MAAMa,OAAO;QAACF;QAAQC;KAAO;IAC7B,IAAIE,IAAAA,UAAI,OAAM,CAAC,CAACC,QAAQC,GAAG,CAACC,YAAY,EAAE;QACtCJ,KAAKK,OAAO,CAACP,OAAOQ,OAAO,CAAC,cAAc,CAAC,OAAO,EAAEJ,QAAQC,GAAG,CAACC,YAAY,CAAC,WAAW,CAAC;IAC7F;IAEA,OAAOJ;AACX"}
1
+ {"version":3,"sources":["../../../src/cli/utils/cli-git.ts"],"sourcesContent":["import { log } from '../../utils';\nimport { runCommand, runCommandOutput } from './cli-os';\nimport { isCI } from './is-ci';\n\nexport function gitGetBranch(): string {\n return runCommandOutput('git rev-parse --abbrev-ref HEAD').trim();\n}\n\nexport function gitGetCommitHash(): string {\n return runCommandOutput('git rev-parse --short HEAD').trim();\n}\n\ninterface Repo {\n owner?: string;\n name: string;\n}\n\nexport async function gitCloneRepo(params: Repo & { destination: string }) {\n const { destination, name, owner = 'servicetitan' } = params;\n const gitUrls = getGitUrls({ owner, name });\n\n for (const url of gitUrls) {\n try {\n const command = `git clone -q ${url} ${destination}`;\n log.debug('git:clone-repo', `running ${command}`);\n\n // eslint-disable-next-line no-await-in-loop\n await runCommand(command, {\n quiet: true,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },\n });\n return true;\n } catch {\n // ignore error\n }\n }\n\n return false;\n}\n\nexport function gitIsReachable({ owner = 'servicetitan', name }: Repo) {\n return getGitUrls({ owner, name }).some(url => {\n try {\n runCommandOutput(`git ls-remote -qt ${url}`, { quiet: true });\n return true;\n } catch {\n return false;\n }\n });\n}\n\nfunction getGitUrls({ owner, name }: Repo) {\n const webUrl = `https://github.com/${owner}/${name}.git`;\n const sshUrl = `git@github.com:${owner}/${name}.git`;\n\n return isCI() && !!process.env.GITHUB_TOKEN\n ? [webUrl.replace('github.com', `oauth2:${process.env.GITHUB_TOKEN}@github.com`)]\n : [sshUrl, webUrl];\n}\n"],"names":["gitCloneRepo","gitGetBranch","gitGetCommitHash","gitIsReachable","runCommandOutput","trim","params","destination","name","owner","gitUrls","getGitUrls","url","command","log","debug","runCommand","quiet","env","process","GIT_TERMINAL_PROMPT","some","webUrl","sshUrl","isCI","GITHUB_TOKEN","replace"],"mappings":";;;;;;;;;;;QAiBsBA;eAAAA;;QAbNC;eAAAA;;QAIAC;eAAAA;;QAiCAC;eAAAA;;;uBAzCI;uBACyB;sBACxB;AAEd,SAASF;IACZ,OAAOG,IAAAA,uBAAgB,EAAC,mCAAmCC,IAAI;AACnE;AAEO,SAASH;IACZ,OAAOE,IAAAA,uBAAgB,EAAC,8BAA8BC,IAAI;AAC9D;AAOO,eAAeL,aAAaM,MAAsC;IACrE,MAAM,EAAEC,WAAW,EAAEC,IAAI,EAAEC,QAAQ,cAAc,EAAE,GAAGH;IACtD,MAAMI,UAAUC,WAAW;QAAEF;QAAOD;IAAK;IAEzC,KAAK,MAAMI,OAAOF,QAAS;QACvB,IAAI;YACA,MAAMG,UAAU,CAAC,aAAa,EAAED,IAAI,CAAC,EAAEL,aAAa;YACpDO,UAAG,CAACC,KAAK,CAAC,kBAAkB,CAAC,QAAQ,EAAEF,SAAS;YAEhD,4CAA4C;YAC5C,MAAMG,IAAAA,iBAAU,EAACH,SAAS;gBACtBI,OAAO;gBACP,gEAAgE;gBAChEC,KAAK;oBAAE,GAAGC,QAAQD,GAAG;oBAAEE,qBAAqB;gBAAI;YACpD;YACA,OAAO;QACX,EAAE,UAAM;QACJ,eAAe;QACnB;IACJ;IAEA,OAAO;AACX;AAEO,SAASjB,eAAe,EAAEM,QAAQ,cAAc,EAAED,IAAI,EAAQ;IACjE,OAAOG,WAAW;QAAEF;QAAOD;IAAK,GAAGa,IAAI,CAACT,CAAAA;QACpC,IAAI;YACAR,IAAAA,uBAAgB,EAAC,CAAC,kBAAkB,EAAEQ,KAAK,EAAE;gBAAEK,OAAO;YAAK;YAC3D,OAAO;QACX,EAAE,UAAM;YACJ,OAAO;QACX;IACJ;AACJ;AAEA,SAASN,WAAW,EAAEF,KAAK,EAAED,IAAI,EAAQ;IACrC,MAAMc,SAAS,CAAC,mBAAmB,EAAEb,MAAM,CAAC,EAAED,KAAK,IAAI,CAAC;IACxD,MAAMe,SAAS,CAAC,eAAe,EAAEd,MAAM,CAAC,EAAED,KAAK,IAAI,CAAC;IAEpD,OAAOgB,IAAAA,UAAI,OAAM,CAAC,CAACL,QAAQD,GAAG,CAACO,YAAY,GACrC;QAACH,OAAOI,OAAO,CAAC,cAAc,CAAC,OAAO,EAAEP,QAAQD,GAAG,CAACO,YAAY,CAAC,WAAW,CAAC;KAAE,GAC/E;QAACF;QAAQD;KAAO;AAC1B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/startup",
3
- "version": "32.0.1",
3
+ "version": "32.1.0",
4
4
  "description": "",
5
5
  "homepage": "https://docs.st.dev/docs/frontend/startup",
6
6
  "repository": {
@@ -37,8 +37,8 @@
37
37
  "@jest/core": "~29.7.0",
38
38
  "@jest/types": "~29.6.3",
39
39
  "@jsdevtools/coverage-istanbul-loader": "^3.0.5",
40
- "@servicetitan/eslint-config": "32.0.1",
41
- "@servicetitan/stylelint-config": "32.0.1",
40
+ "@servicetitan/eslint-config": "32.1.0",
41
+ "@servicetitan/stylelint-config": "32.1.0",
42
42
  "@svgr/webpack": "^8.1.0",
43
43
  "@swc/cli": "^0.5.0",
44
44
  "@swc/core": "1.13.5",
@@ -120,5 +120,5 @@
120
120
  "cli": {
121
121
  "webpack": false
122
122
  },
123
- "gitHead": "2b74dd72d39c2023151699d1cf7a6e6130d64279"
123
+ "gitHead": "5686f75473bd25104356c3fc6e7c8ffe478ca125"
124
124
  }
@@ -8,7 +8,13 @@ export function mockConfig({
8
8
  }: {
9
9
  id: string;
10
10
  level?: 'error' | 'warn';
11
- exclude: string | string[];
11
+ exclude: string | string[] | Record<string, string[]>;
12
12
  }): ReviewConfiguration {
13
- return { rules: { [id]: exclude ? [level, { exclude: toArray(exclude) }] : [level] } };
13
+ return {
14
+ rules: {
15
+ [id]: exclude
16
+ ? [level, { exclude: typeof exclude === 'object' ? exclude : toArray(exclude) }]
17
+ : [level],
18
+ },
19
+ };
14
20
  }
@@ -0,0 +1,123 @@
1
+ import { execSync } from 'child_process';
2
+ import path from 'path';
3
+ import {
4
+ ErrorSeverity,
5
+ FixCategory,
6
+ Package,
7
+ PackageError,
8
+ ReviewConfiguration,
9
+ } from '../../types';
10
+ import { expectCalls } from '../../__mocks__';
11
+ import { mockConfig, mockProject } from '../__mocks__';
12
+ import { NoDeprecatedContentBase } from '../no-deprecated-content-base';
13
+
14
+ jest.mock('child_process', () => ({ execSync: jest.fn() }));
15
+
16
+ describe(`[startup] Review ${NoDeprecatedContentBase.name}`, () => {
17
+ const id = 'no-deprecated-content-base';
18
+ const rule = new NoDeprecatedContentBase();
19
+ let config: ReviewConfiguration;
20
+ let pkg: Package;
21
+ let packages: Package[];
22
+
23
+ beforeEach(() => {
24
+ config = {};
25
+ pkg = { name: 'lib1', location: path.normalize('packages/lib') };
26
+ packages = [pkg];
27
+ jest.clearAllMocks();
28
+ });
29
+
30
+ const subject = () => rule.run(mockProject({ config, packages }));
31
+
32
+ const fixSubject = () => rule.fix(subject()![0]);
33
+
34
+ function itReturnsError() {
35
+ test('returns error', () => {
36
+ expect(subject()).toEqual([
37
+ expect.objectContaining({
38
+ id,
39
+ message: `package "${pkg.name}" uses deprecated cli.webpack.contentBase configuration`,
40
+ location: pkg.location,
41
+ fixable: FixCategory.isolated,
42
+ severity: ErrorSeverity.warning,
43
+ } satisfies PackageError),
44
+ ]);
45
+ });
46
+ }
47
+
48
+ function itReturnsNothing() {
49
+ test('returns nothing', () => {
50
+ expect(subject()).toEqual([]);
51
+ });
52
+ }
53
+
54
+ itReturnsNothing();
55
+
56
+ describe('when package uses cli.webpack.contentBase', () => {
57
+ const contentBase = 'foo';
58
+
59
+ beforeEach(() => {
60
+ pkg.cli = { webpack: { contentBase } };
61
+ });
62
+
63
+ itReturnsError();
64
+
65
+ test('fixes error', () => {
66
+ fixSubject();
67
+
68
+ expectCalls(
69
+ ...[
70
+ `npm pkg set cli.webpack.static.directory="${contentBase}" -w ${pkg.location}`,
71
+ `npm pkg delete cli.webpack.contentBase -w ${pkg.location}`,
72
+ ].map(command => [execSync, command, { stdio: 'inherit' }])
73
+ );
74
+ });
75
+
76
+ test('fix ignores invalid error', () => {
77
+ rule.fix({} as any);
78
+
79
+ expect(execSync).not.toHaveBeenCalled();
80
+ });
81
+
82
+ describe('when config excludes package', () => {
83
+ beforeEach(() => (config = mockConfig({ id, exclude: pkg.name })));
84
+
85
+ itReturnsNothing();
86
+ });
87
+
88
+ describe('when multiple packages use cli.webpack.contentBase', () => {
89
+ beforeEach(() => {
90
+ packages.push({
91
+ name: 'lib2',
92
+ location: path.normalize('packages/lib2'),
93
+ cli: { webpack: { contentBase: 'bar' } },
94
+ });
95
+ });
96
+
97
+ test('returns multiple errors', () => {
98
+ expect(subject()).toEqual([
99
+ expect.objectContaining({ location: packages[0].location }),
100
+ expect.objectContaining({ location: packages[1].location }),
101
+ ]);
102
+ });
103
+ });
104
+
105
+ describe('when cli.webpack.contentBase is an array', () => {
106
+ const contentBaseArray = ['foo', 'bar'];
107
+
108
+ beforeEach(() => (pkg.cli = { webpack: { contentBase: contentBaseArray } }));
109
+
110
+ test('fixes error', () => {
111
+ fixSubject();
112
+
113
+ expectCalls(
114
+ ...[
115
+ `npm pkg set cli.webpack.static[0].directory="${contentBaseArray[0]}" -w ${pkg.location}`,
116
+ `npm pkg set cli.webpack.static[1].directory="${contentBaseArray[1]}" -w ${pkg.location}`,
117
+ `npm pkg delete cli.webpack.contentBase -w ${pkg.location}`,
118
+ ].map(command => [execSync, command, { stdio: 'inherit' }])
119
+ );
120
+ });
121
+ });
122
+ });
123
+ });
@@ -0,0 +1,130 @@
1
+ import { execSync } from 'child_process';
2
+ import path from 'path';
3
+ import { FixCategory, Package, PackageError, ReviewConfiguration } from '../../types';
4
+ import { expectCalls } from '../../__mocks__';
5
+ import { mockConfig, mockProject } from '../__mocks__';
6
+ import { NoDirectPeerDependencies } from '../no-direct-peer-dependencies';
7
+
8
+ jest.mock('child_process', () => ({ execSync: jest.fn() }));
9
+
10
+ describe(`[startup] Review ${NoDirectPeerDependencies.name}`, () => {
11
+ const id = 'no-direct-peer-dependencies';
12
+ const rule = new NoDirectPeerDependencies();
13
+ let config: ReviewConfiguration;
14
+ let pkg: Package;
15
+ let packages: Package[];
16
+
17
+ beforeEach(() => {
18
+ config = {};
19
+ pkg = { name: 'lib1', location: path.normalize('packages/lib') };
20
+ packages = [pkg];
21
+ jest.clearAllMocks();
22
+ });
23
+
24
+ const subject = () => rule.run(mockProject({ config, packages }));
25
+
26
+ const fixSubject = () => rule.fix(subject()![0]);
27
+
28
+ function itReturnsError(message: () => string) {
29
+ test('returns error', () => {
30
+ expect(subject()).toEqual([
31
+ expect.objectContaining({
32
+ id,
33
+ message: message(),
34
+ location: pkg.location,
35
+ fixable: FixCategory.isolated,
36
+ } satisfies PackageError),
37
+ ]);
38
+ });
39
+ }
40
+
41
+ function itReturnsNothing() {
42
+ test('returns nothing', () => {
43
+ expect(subject()).toEqual([]);
44
+ });
45
+ }
46
+
47
+ itReturnsNothing();
48
+
49
+ describe('when package is both peer and direct dependency', () => {
50
+ beforeEach(() => {
51
+ Object.assign(pkg, {
52
+ dependencies: { foo: '^1.0.0', baz: '1.0.0' },
53
+ peerDependencies: { foo: '>=1.0.0', qux: '^1.0.0' },
54
+ });
55
+ });
56
+
57
+ itReturnsError(() => {
58
+ return `package "${pkg.name}" lists "foo" as both a direct and a peer dependency`;
59
+ });
60
+
61
+ test('fixes error', () => {
62
+ fixSubject();
63
+
64
+ expectCalls(
65
+ ...[
66
+ `npm pkg set devDependencies["foo"]="${pkg.dependencies!.foo}" -w ${pkg.location}`,
67
+ `npm pkg delete dependencies["foo"] -w ${pkg.location}`,
68
+ ].map(command => [execSync, command, { stdio: 'inherit' }])
69
+ );
70
+ });
71
+
72
+ test('fix ignores invalid error', () => {
73
+ rule.fix({} as any);
74
+
75
+ expect(execSync).not.toHaveBeenCalled();
76
+ });
77
+
78
+ describe('when config excludes package', () => {
79
+ beforeEach(() => (config = mockConfig({ id, exclude: pkg.name })));
80
+
81
+ itReturnsNothing();
82
+ });
83
+
84
+ describe('when multiple packages violate the rule', () => {
85
+ beforeEach(() => {
86
+ packages = [
87
+ pkg,
88
+ {
89
+ ...pkg,
90
+ name: 'lib2',
91
+ location: path.normalize('packages/lib2'),
92
+ },
93
+ ];
94
+ });
95
+
96
+ test('returns multiple errors', () => {
97
+ expect(subject()).toEqual([
98
+ expect.objectContaining({ location: packages[0].location }),
99
+ expect.objectContaining({ location: packages[1].location }),
100
+ ]);
101
+ });
102
+ });
103
+ });
104
+
105
+ describe('when multiple packages are peer and direct dependencies', () => {
106
+ beforeEach(() => {
107
+ Object.assign(pkg, {
108
+ dependencies: { foo: '^1.0.0', bar: '~1.0.0', baz: '1.0.0' },
109
+ peerDependencies: { foo: '>= 1.0.0', bar: '^1.0.0', quz: '^1.0.0' },
110
+ });
111
+ });
112
+
113
+ itReturnsError(() => {
114
+ return `package "${pkg.name}" lists "foo" and "bar" as both direct and peer dependencies`;
115
+ });
116
+
117
+ test('fixes multiple errors', () => {
118
+ fixSubject();
119
+
120
+ expectCalls(
121
+ ...[
122
+ `npm pkg set devDependencies["foo"]="${pkg.dependencies!.foo}" -w ${pkg.location}`,
123
+ `npm pkg delete dependencies["foo"] -w ${pkg.location}`,
124
+ `npm pkg set devDependencies["bar"]="${pkg.dependencies!.bar}" -w ${pkg.location}`,
125
+ `npm pkg delete dependencies["bar"] -w ${pkg.location}`,
126
+ ].map(command => [execSync, command, { stdio: 'inherit' }])
127
+ );
128
+ });
129
+ });
130
+ });
@@ -0,0 +1,121 @@
1
+ import { execSync } from 'child_process';
2
+ import { ErrorSeverity, FixCategory, Package, PackageError } from '../../types';
3
+ import { mockConfig, mockProject } from '../__mocks__';
4
+ import { PreferOpenEndedPeerDependencies } from '../prefer-open-ended-peer-dependencies';
5
+
6
+ jest.mock('child_process', () => ({ execSync: jest.fn() }));
7
+
8
+ describe(`[startup] Review ${PreferOpenEndedPeerDependencies.name}`, () => {
9
+ const id = 'prefer-open-ended-peer-dependencies';
10
+ const rule = new PreferOpenEndedPeerDependencies();
11
+ let config: any;
12
+ let pkg: Package;
13
+ let packages: Package[];
14
+
15
+ beforeEach(() => {
16
+ config = {};
17
+ pkg = { name: 'lib1', location: 'packages/lib1' };
18
+ packages = [pkg];
19
+ jest.clearAllMocks();
20
+ });
21
+
22
+ const subject = () => rule.run(mockProject({ config, packages }));
23
+
24
+ const fixSubject = () => rule.fix(subject()![0]);
25
+
26
+ function itReturnsError(message: () => string) {
27
+ test('returns error', () => {
28
+ expect(subject()).toEqual([
29
+ expect.objectContaining({
30
+ id,
31
+ message: message(),
32
+ location: pkg.location,
33
+ severity: ErrorSeverity.warning,
34
+ fixable: FixCategory.isolated,
35
+ } satisfies PackageError),
36
+ ]);
37
+ });
38
+ }
39
+
40
+ function itReturnsNothing() {
41
+ test('returns nothing', () => {
42
+ expect(subject()).toEqual([]);
43
+ });
44
+ }
45
+
46
+ itReturnsNothing();
47
+
48
+ describe('when a package has a closed-ended peer dependency', () => {
49
+ beforeEach(() => (pkg.peerDependencies = { foo: '^12.3.0' }));
50
+
51
+ itReturnsError(
52
+ () => `package "${pkg.name}" has closed-ended peer dependency on "foo@^12.3.0"`
53
+ );
54
+
55
+ test('fixes error', () => {
56
+ fixSubject();
57
+
58
+ expect(execSync).toHaveBeenCalledWith(
59
+ `npm pkg set peerDependencies["foo"]=">=12.3.0" -w ${pkg.location}`,
60
+ { stdio: 'inherit' }
61
+ );
62
+ });
63
+
64
+ test('fix ignores invalid error', () => {
65
+ rule.fix({} as any);
66
+
67
+ expect(execSync).not.toHaveBeenCalled();
68
+ });
69
+
70
+ describe('when config excludes package', () => {
71
+ beforeEach(() => (config = mockConfig({ id, exclude: pkg.name })));
72
+
73
+ itReturnsNothing();
74
+ });
75
+
76
+ describe('when peer is open-ended', () => {
77
+ beforeEach(() => (pkg.peerDependencies!.foo = '>=12.3.0'));
78
+
79
+ itReturnsNothing();
80
+ });
81
+
82
+ describe('when peer dependency is an exact version', () => {
83
+ beforeEach(() => (pkg.peerDependencies!.foo = '12.3.0'));
84
+
85
+ itReturnsNothing();
86
+ });
87
+
88
+ describe('with multiple closed-ended dependencies', () => {
89
+ beforeEach(() => (pkg.peerDependencies!.bar = '~12.3.4'));
90
+
91
+ test('returns multiple errors', () => {
92
+ expect(subject()).toEqual([
93
+ expect.objectContaining({ message: expect.stringContaining('foo@^12.3.0') }),
94
+ expect.objectContaining({ message: expect.stringContaining('bar@~12.3.4') }),
95
+ ]);
96
+ });
97
+
98
+ describe('when dependency is excluded', () => {
99
+ beforeEach(() => (config = mockConfig({ id, exclude: { [pkg.name]: ['foo'] } })));
100
+
101
+ test('omits excluded dependency', () => {
102
+ expect(subject()).toEqual([
103
+ expect.objectContaining({
104
+ message: expect.stringContaining('bar@~12.3.4'),
105
+ }),
106
+ ]);
107
+ });
108
+ });
109
+ });
110
+
111
+ describe.each(['<1', '^1 || ^2', '>1 <2', '1.0 - 2.0'])('when version is "%s"', version => {
112
+ beforeEach(() => (pkg.peerDependencies!.foo = version));
113
+
114
+ test('error is not fixable', () => {
115
+ expect(subject()).not.toEqual([
116
+ expect.objectContaining({ fixable: expect.anything() }),
117
+ ]);
118
+ });
119
+ });
120
+ });
121
+ });