@sanity/cli 7.15.0 → 7.16.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.
- package/README.md +88 -1
- package/dist/actions/build/shouldAutoUpdate.js +28 -5
- package/dist/actions/build/shouldAutoUpdate.js.map +1 -1
- package/dist/actions/deploy/deployApp.js +4 -8
- package/dist/actions/deploy/deployApp.js.map +1 -1
- package/dist/actions/deploy/deployChecks.js +49 -31
- package/dist/actions/deploy/deployChecks.js.map +1 -1
- package/dist/actions/deploy/deployRunner.js +1 -1
- package/dist/actions/deploy/deployRunner.js.map +1 -1
- package/dist/actions/deploy/deployStudio.js +12 -10
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/deploy/deploymentPlan.js +2 -2
- package/dist/actions/deploy/deploymentPlan.js.map +1 -1
- package/dist/actions/deploy/resolveDeployTarget.js +13 -13
- package/dist/actions/deploy/resolveDeployTarget.js.map +1 -1
- package/dist/actions/init/bootstrapLocalTemplate.js +2 -3
- package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -1
- package/dist/actions/init/createAppCliConfig.js.map +1 -1
- package/dist/actions/init/createCliConfig.js.map +1 -1
- package/dist/actions/init/initNextJs.js +1 -1
- package/dist/actions/init/initNextJs.js.map +1 -1
- package/dist/actions/init/initStudio.js +10 -6
- package/dist/actions/init/initStudio.js.map +1 -1
- package/dist/actions/init/templates/appSanityUi.js +1 -1
- package/dist/actions/init/templates/appSanityUi.js.map +1 -1
- package/dist/actions/init/templates/getStarted.js +2 -2
- package/dist/actions/init/templates/getStarted.js.map +1 -1
- package/dist/actions/init/templates/nextjs/schemaTypes/blog.js +4 -4
- package/dist/actions/init/templates/nextjs/schemaTypes/blog.js.map +1 -1
- package/dist/actions/init/templates/shopify.js +2 -2
- package/dist/actions/init/templates/shopify.js.map +1 -1
- package/dist/actions/init/templates/shopifyOnline.js +2 -2
- package/dist/actions/init/templates/shopifyOnline.js.map +1 -1
- package/dist/actions/manifest/extractCoreAppManifest.js +7 -7
- package/dist/actions/manifest/extractCoreAppManifest.js.map +1 -1
- package/dist/actions/scaffold/createFrontend.js +107 -0
- package/dist/actions/scaffold/createFrontend.js.map +1 -0
- package/dist/actions/scaffold/scaffoldProject.js +202 -0
- package/dist/actions/scaffold/scaffoldProject.js.map +1 -0
- package/dist/actions/telemetry/resolveConsent.js +4 -2
- package/dist/actions/telemetry/resolveConsent.js.map +1 -1
- package/dist/commands/backups/list.js +1 -1
- package/dist/commands/backups/list.js.map +1 -1
- package/dist/commands/datasets/copy.js +5 -3
- package/dist/commands/datasets/copy.js.map +1 -1
- package/dist/commands/documents/query.js +5 -4
- package/dist/commands/documents/query.js.map +1 -1
- package/dist/commands/migrations/list.js +1 -1
- package/dist/commands/migrations/list.js.map +1 -1
- package/dist/commands/migrations/run.js +1 -1
- package/dist/commands/migrations/run.js.map +1 -1
- package/dist/commands/new.js +309 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/organizations/list.js +1 -1
- package/dist/commands/organizations/list.js.map +1 -1
- package/dist/commands/projects/unclaimed.js +205 -0
- package/dist/commands/projects/unclaimed.js.map +1 -0
- package/dist/commands/tokens/list.js +1 -1
- package/dist/commands/tokens/list.js.map +1 -1
- package/dist/commands/users/list.js +5 -1
- package/dist/commands/users/list.js.map +1 -1
- package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js +4 -0
- package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js.map +1 -1
- package/dist/exports/invokeSanityCli/index.d.ts +5 -9
- package/dist/exports/invokeSanityCli/index.js +47 -20
- package/dist/exports/invokeSanityCli/index.js.map +1 -1
- package/dist/exports/runtime.d.ts +12 -0
- package/dist/exports/runtime.js.map +1 -1
- package/dist/services/mintProject.js +91 -0
- package/dist/services/mintProject.js.map +1 -0
- package/dist/services/projects.js +19 -0
- package/dist/services/projects.js.map +1 -1
- package/dist/services/telemetry.js +4 -0
- package/dist/services/telemetry.js.map +1 -1
- package/dist/util/formatClaimDeadline.js +15 -0
- package/dist/util/formatClaimDeadline.js.map +1 -0
- package/dist/util/mintProjectConstants.js +6 -0
- package/dist/util/mintProjectConstants.js.map +1 -0
- package/dist/util/newCommandSplash.js +27 -0
- package/dist/util/newCommandSplash.js.map +1 -0
- package/dist/util/packageManager/installPackages.js +57 -28
- package/dist/util/packageManager/installPackages.js.map +1 -1
- package/dist/util/unclaimedProjects.js +105 -0
- package/dist/util/unclaimedProjects.js.map +1 -0
- package/oclif.manifest.json +150 -41
- package/package.json +7 -7
- package/templates/get-started/plugins/sanity-plugin-tutorial/GetStartedTutorial.tsx +1 -1
- package/templates/shopify/components/inputs/CollectionHidden.tsx +1 -1
- package/templates/shopify/components/inputs/ProductHidden.tsx +1 -1
- package/templates/shopify/components/inputs/ProductVariantHidden.tsx +1 -1
- package/templates/shopify/components/inputs/ProxyString.tsx +1 -1
- package/templates/shopify/components/media/ShopifyDocumentStatus.tsx +3 -1
- package/templates/shopify/constants.ts +3 -1
- package/templates/shopify/plugins/customDocumentActions/shopifyDelete.tsx +1 -1
- package/templates/shopify/plugins/customDocumentActions/shopifyLink.ts +1 -1
- package/templates/shopify/schemaTypes/documents/collection.tsx +1 -1
- package/templates/shopify/schemaTypes/documents/colorTheme.tsx +1 -1
- package/templates/shopify/schemaTypes/documents/page.ts +1 -1
- package/templates/shopify/schemaTypes/documents/product.tsx +1 -1
- package/templates/shopify/schemaTypes/documents/productVariant.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/collection/collectionGroupType.ts +1 -1
- package/templates/shopify/schemaTypes/objects/hotspot/imageWithProductHotspotsType.ts +1 -1
- package/templates/shopify/schemaTypes/objects/link/linkEmailType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/link/linkExternalType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/link/linkInternalType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/link/linkProductType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/module/accordionType.ts +1 -1
- package/templates/shopify/schemaTypes/objects/module/callToActionType.tsx +2 -1
- package/templates/shopify/schemaTypes/objects/module/calloutType.ts +1 -1
- package/templates/shopify/schemaTypes/objects/module/collectionReferenceType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/module/gridType.ts +1 -1
- package/templates/shopify/schemaTypes/objects/module/imageFeatureType.ts +1 -1
- package/templates/shopify/schemaTypes/objects/module/imageFeaturesType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/module/instagramType.ts +1 -1
- package/templates/shopify/schemaTypes/objects/module/productFeaturesType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/module/productReferenceType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/shopify/collectionRuleType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/shopify/optionType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/shopify/productWithVariantType.tsx +1 -1
- package/templates/shopify/schemaTypes/singletons/homeType.ts +1 -1
- package/templates/shopify/schemaTypes/singletons/settingsType.ts +5 -1
- package/templates/shopify/structure/pageStructure.ts +1 -1
- package/templates/shopify/structure/productStructure.ts +1 -1
- package/templates/shopify-online-storefront/components/inputs/CollectionHidden.tsx +1 -1
- package/templates/shopify-online-storefront/components/inputs/ProductHidden.tsx +1 -1
- package/templates/shopify-online-storefront/components/inputs/ProductVariantHidden.tsx +1 -1
- package/templates/shopify-online-storefront/components/inputs/ProxyString.tsx +1 -1
- package/templates/shopify-online-storefront/components/media/ShopifyDocumentStatus.tsx +3 -1
- package/templates/shopify-online-storefront/plugins/shopifyDocumentActions/shopifyDelete.tsx +1 -1
- package/templates/shopify-online-storefront/plugins/shopifyDocumentActions/shopifyLink.ts +1 -1
- package/templates/shopify-online-storefront/schemaTypes/documents/collection.tsx +1 -1
- package/templates/shopify-online-storefront/schemaTypes/documents/product.tsx +1 -1
- package/templates/shopify-online-storefront/schemaTypes/documents/productVariant.tsx +1 -1
- package/templates/shopify-online-storefront/schemaTypes/objects/accordion.ts +1 -1
- package/templates/shopify-online-storefront/schemaTypes/objects/callout.ts +1 -1
- package/templates/shopify-online-storefront/schemaTypes/objects/option.ts +1 -1
- package/templates/shopify-online-storefront/schemaTypes/objects/shopifyCollectionRule.tsx +1 -1
- package/templates/shopify-online-storefront/structure/productStructure.ts +1 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { subdebug } from '@sanity/cli-core';
|
|
3
|
+
import { spinner } from '@sanity/cli-core/ux';
|
|
4
|
+
import { execa } from 'execa';
|
|
5
|
+
import { installNewPackages } from '../../util/packageManager/installPackages.js';
|
|
6
|
+
import { getPartialEnvWithNpmPath } from '../../util/packageManager/packageManagerChoice.js';
|
|
7
|
+
const debug = subdebug('scaffold');
|
|
8
|
+
const CREATE_NEXT_APP_SPEC = 'create-next-app@^16';
|
|
9
|
+
const NEXT_SANITY_SPEC = 'next-sanity';
|
|
10
|
+
const SCAFFOLD_TIMEOUT_MS = 10 * 60_000;
|
|
11
|
+
const packageManagerFlag = {
|
|
12
|
+
bun: '--use-bun',
|
|
13
|
+
manual: undefined,
|
|
14
|
+
npm: '--use-npm',
|
|
15
|
+
pnpm: '--use-pnpm',
|
|
16
|
+
yarn: '--use-yarn'
|
|
17
|
+
};
|
|
18
|
+
const scaffolderFlags = [
|
|
19
|
+
'--typescript',
|
|
20
|
+
'--app',
|
|
21
|
+
'--eslint',
|
|
22
|
+
'--tailwind',
|
|
23
|
+
'--no-src-dir',
|
|
24
|
+
'--disable-git',
|
|
25
|
+
'--yes'
|
|
26
|
+
];
|
|
27
|
+
function scaffolderArgs(dirName, packageManager) {
|
|
28
|
+
const pmFlag = packageManager ? packageManagerFlag[packageManager] : undefined;
|
|
29
|
+
return [
|
|
30
|
+
'--yes',
|
|
31
|
+
CREATE_NEXT_APP_SPEC,
|
|
32
|
+
dirName,
|
|
33
|
+
...scaffolderFlags,
|
|
34
|
+
...pmFlag ? [
|
|
35
|
+
pmFlag
|
|
36
|
+
] : []
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
export class FrontendScaffoldError extends Error {
|
|
40
|
+
constructor(message){
|
|
41
|
+
super(message);
|
|
42
|
+
this.name = 'FrontendScaffoldError';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export async function createFrontend({ cancelSignal, dirName, output, packageManager, workDir }) {
|
|
46
|
+
const args = scaffolderArgs(dirName, packageManager);
|
|
47
|
+
debug('Scaffolding frontend: npx %s', args.join(' '));
|
|
48
|
+
const progress = spinner({
|
|
49
|
+
discardStdin: !cancelSignal,
|
|
50
|
+
text: 'Creating your Next.js app\n'
|
|
51
|
+
}).start();
|
|
52
|
+
let result;
|
|
53
|
+
try {
|
|
54
|
+
result = await execa('npx', args, {
|
|
55
|
+
cancelSignal,
|
|
56
|
+
cwd: workDir,
|
|
57
|
+
encoding: 'utf8',
|
|
58
|
+
env: {
|
|
59
|
+
...getPartialEnvWithNpmPath(workDir),
|
|
60
|
+
npm_config_yes: 'true'
|
|
61
|
+
},
|
|
62
|
+
reject: false,
|
|
63
|
+
stdio: [
|
|
64
|
+
'ignore',
|
|
65
|
+
'pipe',
|
|
66
|
+
'pipe'
|
|
67
|
+
],
|
|
68
|
+
timeout: SCAFFOLD_TIMEOUT_MS
|
|
69
|
+
});
|
|
70
|
+
cancelSignal?.throwIfAborted();
|
|
71
|
+
} catch (err) {
|
|
72
|
+
progress.fail();
|
|
73
|
+
cancelSignal?.throwIfAborted();
|
|
74
|
+
throw new FrontendScaffoldError(`create-next-app failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
75
|
+
}
|
|
76
|
+
if (!result || result.failed || result.exitCode) {
|
|
77
|
+
progress.fail();
|
|
78
|
+
const commandOutput = [
|
|
79
|
+
result?.stdout,
|
|
80
|
+
result?.stderr
|
|
81
|
+
].filter((chunk)=>typeof chunk === 'string' && chunk.length > 0).join('\n');
|
|
82
|
+
if (commandOutput) output.log(commandOutput);
|
|
83
|
+
throw new FrontendScaffoldError(`create-next-app failed${result?.exitCode ? ` with exit code ${result.exitCode}` : ''}`);
|
|
84
|
+
}
|
|
85
|
+
progress.succeed();
|
|
86
|
+
}
|
|
87
|
+
export async function installFrontendDeps({ cancelSignal, dirName, output, packageManager, workDir }) {
|
|
88
|
+
try {
|
|
89
|
+
await installNewPackages({
|
|
90
|
+
packageManager,
|
|
91
|
+
packages: [
|
|
92
|
+
NEXT_SANITY_SPEC
|
|
93
|
+
]
|
|
94
|
+
}, {
|
|
95
|
+
cancelSignal,
|
|
96
|
+
output,
|
|
97
|
+
timeout: SCAFFOLD_TIMEOUT_MS,
|
|
98
|
+
workDir: path.join(workDir, dirName)
|
|
99
|
+
});
|
|
100
|
+
cancelSignal?.throwIfAborted();
|
|
101
|
+
} catch (err) {
|
|
102
|
+
cancelSignal?.throwIfAborted();
|
|
103
|
+
throw new FrontendScaffoldError(`Installing next-sanity failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
//# sourceMappingURL=createFrontend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/scaffold/createFrontend.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {type Output, subdebug} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {execa} from 'execa'\n\nimport {installNewPackages} from '../../util/packageManager/installPackages.js'\nimport {\n getPartialEnvWithNpmPath,\n type PackageManager,\n} from '../../util/packageManager/packageManagerChoice.js'\n\nconst debug = subdebug('scaffold')\nconst CREATE_NEXT_APP_SPEC = 'create-next-app@^16'\nconst NEXT_SANITY_SPEC = 'next-sanity'\nconst SCAFFOLD_TIMEOUT_MS = 10 * 60_000\n\nconst packageManagerFlag: Record<PackageManager, string | undefined> = {\n bun: '--use-bun',\n manual: undefined,\n npm: '--use-npm',\n pnpm: '--use-pnpm',\n yarn: '--use-yarn',\n}\n\nconst scaffolderFlags = [\n '--typescript',\n '--app',\n '--eslint',\n '--tailwind',\n '--no-src-dir',\n '--disable-git',\n '--yes',\n]\n\nfunction scaffolderArgs(dirName: string, packageManager?: PackageManager): string[] {\n const pmFlag = packageManager ? packageManagerFlag[packageManager] : undefined\n return ['--yes', CREATE_NEXT_APP_SPEC, dirName, ...scaffolderFlags, ...(pmFlag ? [pmFlag] : [])]\n}\n\nexport class FrontendScaffoldError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'FrontendScaffoldError'\n }\n}\n\nexport async function createFrontend({\n cancelSignal,\n dirName,\n output,\n packageManager,\n workDir,\n}: {\n cancelSignal?: AbortSignal\n dirName: string\n output: Output\n packageManager: PackageManager\n workDir: string\n}): Promise<void> {\n const args = scaffolderArgs(dirName, packageManager)\n debug('Scaffolding frontend: npx %s', args.join(' '))\n\n const progress = spinner({\n discardStdin: !cancelSignal,\n text: 'Creating your Next.js app\\n',\n }).start()\n let result\n try {\n result = await execa('npx', args, {\n cancelSignal,\n cwd: workDir,\n encoding: 'utf8',\n env: {\n ...getPartialEnvWithNpmPath(workDir),\n npm_config_yes: 'true',\n },\n reject: false,\n stdio: ['ignore', 'pipe', 'pipe'],\n timeout: SCAFFOLD_TIMEOUT_MS,\n })\n cancelSignal?.throwIfAborted()\n } catch (err) {\n progress.fail()\n cancelSignal?.throwIfAborted()\n throw new FrontendScaffoldError(\n `create-next-app failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n\n if (!result || result.failed || result.exitCode) {\n progress.fail()\n const commandOutput = [result?.stdout, result?.stderr]\n .filter((chunk): chunk is string => typeof chunk === 'string' && chunk.length > 0)\n .join('\\n')\n if (commandOutput) output.log(commandOutput)\n throw new FrontendScaffoldError(\n `create-next-app failed${result?.exitCode ? ` with exit code ${result.exitCode}` : ''}`,\n )\n }\n\n progress.succeed()\n}\n\nexport async function installFrontendDeps({\n cancelSignal,\n dirName,\n output,\n packageManager,\n workDir,\n}: {\n cancelSignal?: AbortSignal\n dirName: string\n output: Output\n packageManager: PackageManager\n workDir: string\n}): Promise<void> {\n try {\n await installNewPackages(\n {packageManager, packages: [NEXT_SANITY_SPEC]},\n {\n cancelSignal,\n output,\n timeout: SCAFFOLD_TIMEOUT_MS,\n workDir: path.join(workDir, dirName),\n },\n )\n cancelSignal?.throwIfAborted()\n } catch (err) {\n cancelSignal?.throwIfAborted()\n throw new FrontendScaffoldError(\n `Installing next-sanity failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n}\n"],"names":["path","subdebug","spinner","execa","installNewPackages","getPartialEnvWithNpmPath","debug","CREATE_NEXT_APP_SPEC","NEXT_SANITY_SPEC","SCAFFOLD_TIMEOUT_MS","packageManagerFlag","bun","manual","undefined","npm","pnpm","yarn","scaffolderFlags","scaffolderArgs","dirName","packageManager","pmFlag","FrontendScaffoldError","Error","message","name","createFrontend","cancelSignal","output","workDir","args","join","progress","discardStdin","text","start","result","cwd","encoding","env","npm_config_yes","reject","stdio","timeout","throwIfAborted","err","fail","String","failed","exitCode","commandOutput","stdout","stderr","filter","chunk","length","log","succeed","installFrontendDeps","packages"],"mappings":"AAAA,OAAOA,UAAU,YAAW;AAE5B,SAAqBC,QAAQ,QAAO,mBAAkB;AACtD,SAAQC,OAAO,QAAO,sBAAqB;AAC3C,SAAQC,KAAK,QAAO,QAAO;AAE3B,SAAQC,kBAAkB,QAAO,+CAA8C;AAC/E,SACEC,wBAAwB,QAEnB,oDAAmD;AAE1D,MAAMC,QAAQL,SAAS;AACvB,MAAMM,uBAAuB;AAC7B,MAAMC,mBAAmB;AACzB,MAAMC,sBAAsB,KAAK;AAEjC,MAAMC,qBAAiE;IACrEC,KAAK;IACLC,QAAQC;IACRC,KAAK;IACLC,MAAM;IACNC,MAAM;AACR;AAEA,MAAMC,kBAAkB;IACtB;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,SAASC,eAAeC,OAAe,EAAEC,cAA+B;IACtE,MAAMC,SAASD,iBAAiBV,kBAAkB,CAACU,eAAe,GAAGP;IACrE,OAAO;QAAC;QAASN;QAAsBY;WAAYF;WAAqBI,SAAS;YAACA;SAAO,GAAG,EAAE;KAAE;AAClG;AAEA,OAAO,MAAMC,8BAA8BC;IACzC,YAAYC,OAAe,CAAE;QAC3B,KAAK,CAACA;QACN,IAAI,CAACC,IAAI,GAAG;IACd;AACF;AAEA,OAAO,eAAeC,eAAe,EACnCC,YAAY,EACZR,OAAO,EACPS,MAAM,EACNR,cAAc,EACdS,OAAO,EAOR;IACC,MAAMC,OAAOZ,eAAeC,SAASC;IACrCd,MAAM,gCAAgCwB,KAAKC,IAAI,CAAC;IAEhD,MAAMC,WAAW9B,QAAQ;QACvB+B,cAAc,CAACN;QACfO,MAAM;IACR,GAAGC,KAAK;IACR,IAAIC;IACJ,IAAI;QACFA,SAAS,MAAMjC,MAAM,OAAO2B,MAAM;YAChCH;YACAU,KAAKR;YACLS,UAAU;YACVC,KAAK;gBACH,GAAGlC,yBAAyBwB,QAAQ;gBACpCW,gBAAgB;YAClB;YACAC,QAAQ;YACRC,OAAO;gBAAC;gBAAU;gBAAQ;aAAO;YACjCC,SAASlC;QACX;QACAkB,cAAciB;IAChB,EAAE,OAAOC,KAAK;QACZb,SAASc,IAAI;QACbnB,cAAciB;QACd,MAAM,IAAItB,sBACR,CAAC,wBAAwB,EAAEuB,eAAetB,QAAQsB,IAAIrB,OAAO,GAAGuB,OAAOF,MAAM;IAEjF;IAEA,IAAI,CAACT,UAAUA,OAAOY,MAAM,IAAIZ,OAAOa,QAAQ,EAAE;QAC/CjB,SAASc,IAAI;QACb,MAAMI,gBAAgB;YAACd,QAAQe;YAAQf,QAAQgB;SAAO,CACnDC,MAAM,CAAC,CAACC,QAA2B,OAAOA,UAAU,YAAYA,MAAMC,MAAM,GAAG,GAC/ExB,IAAI,CAAC;QACR,IAAImB,eAAetB,OAAO4B,GAAG,CAACN;QAC9B,MAAM,IAAI5B,sBACR,CAAC,sBAAsB,EAAEc,QAAQa,WAAW,CAAC,gBAAgB,EAAEb,OAAOa,QAAQ,EAAE,GAAG,IAAI;IAE3F;IAEAjB,SAASyB,OAAO;AAClB;AAEA,OAAO,eAAeC,oBAAoB,EACxC/B,YAAY,EACZR,OAAO,EACPS,MAAM,EACNR,cAAc,EACdS,OAAO,EAOR;IACC,IAAI;QACF,MAAMzB,mBACJ;YAACgB;YAAgBuC,UAAU;gBAACnD;aAAiB;QAAA,GAC7C;YACEmB;YACAC;YACAe,SAASlC;YACToB,SAAS7B,KAAK+B,IAAI,CAACF,SAASV;QAC9B;QAEFQ,cAAciB;IAChB,EAAE,OAAOC,KAAK;QACZlB,cAAciB;QACd,MAAM,IAAItB,sBACR,CAAC,+BAA+B,EAAEuB,eAAetB,QAAQsB,IAAIrB,OAAO,GAAGuB,OAAOF,MAAM;IAExF;AACF"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { writeFileSync } from 'node:fs';
|
|
2
|
+
import { lstat } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { subdebug } from '@sanity/cli-core';
|
|
5
|
+
import { getErrorMessage } from '@sanity/cli-core/errors';
|
|
6
|
+
import { frameworks } from '@vercel/frameworks';
|
|
7
|
+
import { CLIInitStepCompleted } from '../../telemetry/init.telemetry.js';
|
|
8
|
+
import { detectFrameworkRecord } from '../../util/detectFramework.js';
|
|
9
|
+
import { dirIsEmptyOrNonExistent } from '../../util/dirIsEmptyOrNonExistent.js';
|
|
10
|
+
import { getProjectDefaults } from '../../util/getProjectDefaults.js';
|
|
11
|
+
import { initStudio } from '../init/initStudio.js';
|
|
12
|
+
import { resolvePackageManager } from '../init/resolvePackageManager.js';
|
|
13
|
+
import { createFrontend, FrontendScaffoldError, installFrontendDeps } from './createFrontend.js';
|
|
14
|
+
const debug = subdebug('scaffold');
|
|
15
|
+
export const STUDIO_DIR = 'sanity';
|
|
16
|
+
export const FRONTEND_DIR = 'web';
|
|
17
|
+
export const STUDIO_ENV_FILE = `${STUDIO_DIR}/.env.local`;
|
|
18
|
+
export const FRONTEND_ENV_FILE = `${FRONTEND_DIR}/.env.local`;
|
|
19
|
+
const STUDIO_PACKAGE_NAME = 'sanity-studio';
|
|
20
|
+
const STUDIO_PACKAGE_MANAGERS = new Set([
|
|
21
|
+
'npm',
|
|
22
|
+
'pnpm',
|
|
23
|
+
'yarn'
|
|
24
|
+
]);
|
|
25
|
+
export async function isStudioScaffoldTargetAvailable(workDir) {
|
|
26
|
+
return isScaffoldTargetAvailable(workDir, STUDIO_DIR);
|
|
27
|
+
}
|
|
28
|
+
async function isScaffoldTargetAvailable(workDir, targetDir) {
|
|
29
|
+
const targetPath = path.join(workDir, targetDir);
|
|
30
|
+
try {
|
|
31
|
+
if (!(await lstat(targetPath)).isDirectory()) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
} catch (err) {
|
|
35
|
+
if (err.code !== 'ENOENT') {
|
|
36
|
+
throw err;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return dirIsEmptyOrNonExistent(targetPath);
|
|
40
|
+
}
|
|
41
|
+
async function inspectScaffoldTargets(workDir) {
|
|
42
|
+
if (!await isStudioScaffoldTargetAvailable(workDir)) {
|
|
43
|
+
return {
|
|
44
|
+
unavailableTarget: STUDIO_DIR
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const detectedFramework = await detectFrameworkRecord({
|
|
48
|
+
frameworkList: frameworks,
|
|
49
|
+
rootPath: workDir
|
|
50
|
+
});
|
|
51
|
+
if (!detectedFramework && !await isScaffoldTargetAvailable(workDir, FRONTEND_DIR)) {
|
|
52
|
+
return {
|
|
53
|
+
unavailableTarget: FRONTEND_DIR
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
detectedFramework
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export async function getUnavailableScaffoldTarget(workDir) {
|
|
61
|
+
const { unavailableTarget } = await inspectScaffoldTargets(workDir);
|
|
62
|
+
return unavailableTarget;
|
|
63
|
+
}
|
|
64
|
+
function createScaffoldEnv(dataset, projectId, token) {
|
|
65
|
+
return {
|
|
66
|
+
SANITY_AUTH_TOKEN: token,
|
|
67
|
+
SANITY_DATASET: dataset,
|
|
68
|
+
SANITY_PROJECT_ID: projectId
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export async function scaffoldProject({ cancelSignal, dataset, displayName, output, packageManager, projectId, telemetry, token, workDir }) {
|
|
72
|
+
cancelSignal?.throwIfAborted();
|
|
73
|
+
const { detectedFramework: detected, unavailableTarget } = await inspectScaffoldTargets(workDir);
|
|
74
|
+
const studioPath = path.join(workDir, STUDIO_DIR);
|
|
75
|
+
if (unavailableTarget) {
|
|
76
|
+
throw new Error(`./${unavailableTarget} is not an empty directory`);
|
|
77
|
+
}
|
|
78
|
+
const resolvedPackageManager = await resolvePackageManager({
|
|
79
|
+
interactive: false,
|
|
80
|
+
output,
|
|
81
|
+
packageManager: packageManager,
|
|
82
|
+
targetDir: workDir
|
|
83
|
+
});
|
|
84
|
+
const options = {
|
|
85
|
+
autoUpdates: true,
|
|
86
|
+
bare: false,
|
|
87
|
+
dataset,
|
|
88
|
+
datasetDefault: true,
|
|
89
|
+
fromCreate: false,
|
|
90
|
+
git: false,
|
|
91
|
+
mcpMode: 'skip',
|
|
92
|
+
outputPath: studioPath,
|
|
93
|
+
packageManager: STUDIO_PACKAGE_MANAGERS.has(resolvedPackageManager) ? resolvedPackageManager : undefined,
|
|
94
|
+
project: projectId,
|
|
95
|
+
skillsMode: 'skip',
|
|
96
|
+
template: 'clean',
|
|
97
|
+
typescript: true,
|
|
98
|
+
unattended: true
|
|
99
|
+
};
|
|
100
|
+
const trace = telemetry.trace(CLIInitStepCompleted);
|
|
101
|
+
trace.start();
|
|
102
|
+
try {
|
|
103
|
+
// To avoid changing Studio initialization internals, we're deferring passing `cancelSignal`
|
|
104
|
+
// until post `sanity new` launch.
|
|
105
|
+
await initStudio({
|
|
106
|
+
datasetName: dataset,
|
|
107
|
+
defaults: await getProjectDefaults({
|
|
108
|
+
isPlugin: false,
|
|
109
|
+
workDir
|
|
110
|
+
}),
|
|
111
|
+
displayName,
|
|
112
|
+
isFirstProject: false,
|
|
113
|
+
mcpConfigured: [],
|
|
114
|
+
options,
|
|
115
|
+
organizationId: undefined,
|
|
116
|
+
output,
|
|
117
|
+
outputPath: studioPath,
|
|
118
|
+
preclaim: true,
|
|
119
|
+
projectId,
|
|
120
|
+
remoteTemplateInfo: undefined,
|
|
121
|
+
sluggedName: STUDIO_PACKAGE_NAME,
|
|
122
|
+
trace,
|
|
123
|
+
workbench: false,
|
|
124
|
+
workDir
|
|
125
|
+
});
|
|
126
|
+
trace.complete();
|
|
127
|
+
} catch (err) {
|
|
128
|
+
trace.error(err instanceof Error ? err : new Error(String(err)));
|
|
129
|
+
throw err;
|
|
130
|
+
}
|
|
131
|
+
cancelSignal?.throwIfAborted();
|
|
132
|
+
const scaffoldEnv = createScaffoldEnv(dataset, projectId, token);
|
|
133
|
+
writeScaffoldEnv(path.join(studioPath, '.env.local'), scaffoldEnv, `Studio scaffold completed, but writing ./${STUDIO_ENV_FILE} failed`);
|
|
134
|
+
if (detected) {
|
|
135
|
+
debug('Detected %s in %s, leaving the frontend alone', detected.name, workDir);
|
|
136
|
+
return {
|
|
137
|
+
detectedFramework: detected.name,
|
|
138
|
+
studioPath
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
await createFrontend({
|
|
143
|
+
cancelSignal,
|
|
144
|
+
dirName: FRONTEND_DIR,
|
|
145
|
+
output,
|
|
146
|
+
packageManager: resolvedPackageManager,
|
|
147
|
+
workDir
|
|
148
|
+
});
|
|
149
|
+
cancelSignal?.throwIfAborted();
|
|
150
|
+
} catch (err) {
|
|
151
|
+
if (err instanceof FrontendScaffoldError) {
|
|
152
|
+
return {
|
|
153
|
+
frontendCreationError: err.message,
|
|
154
|
+
frontendPackageManager: resolvedPackageManager,
|
|
155
|
+
studioPath
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
throw err;
|
|
159
|
+
}
|
|
160
|
+
const frontendPath = path.join(workDir, FRONTEND_DIR);
|
|
161
|
+
writeScaffoldEnv(path.join(frontendPath, '.env.local'), scaffoldEnv, `Website scaffold completed, but writing ./${FRONTEND_ENV_FILE} failed`);
|
|
162
|
+
let frontendDependenciesInstalled = resolvedPackageManager !== 'manual';
|
|
163
|
+
let frontendDependencyError;
|
|
164
|
+
if (frontendDependenciesInstalled) {
|
|
165
|
+
try {
|
|
166
|
+
await installFrontendDeps({
|
|
167
|
+
cancelSignal,
|
|
168
|
+
dirName: FRONTEND_DIR,
|
|
169
|
+
output,
|
|
170
|
+
packageManager: resolvedPackageManager,
|
|
171
|
+
workDir
|
|
172
|
+
});
|
|
173
|
+
cancelSignal?.throwIfAborted();
|
|
174
|
+
} catch (err) {
|
|
175
|
+
if (!(err instanceof FrontendScaffoldError)) throw err;
|
|
176
|
+
frontendDependenciesInstalled = false;
|
|
177
|
+
frontendDependencyError = err.message;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
frontendDependenciesInstalled,
|
|
182
|
+
frontendDependencyError,
|
|
183
|
+
frontendPackageManager: resolvedPackageManager,
|
|
184
|
+
frontendPath,
|
|
185
|
+
studioPath
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function writeScaffoldEnv(envPath, values, errorContext) {
|
|
189
|
+
const lines = [
|
|
190
|
+
'# Added by `sanity new`. Keep this file out of git: it holds a live project token.',
|
|
191
|
+
...Object.entries(values).map(([key, value])=>`${key}="${value}"`)
|
|
192
|
+
];
|
|
193
|
+
try {
|
|
194
|
+
writeFileSync(envPath, `${lines.join('\n')}\n`, 'utf8');
|
|
195
|
+
} catch (err) {
|
|
196
|
+
throw new Error(`${errorContext}: ${getErrorMessage(err)}`, {
|
|
197
|
+
cause: err
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
//# sourceMappingURL=scaffoldProject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/scaffold/scaffoldProject.ts"],"sourcesContent":["import {writeFileSync} from 'node:fs'\nimport {lstat} from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {type CLITelemetryStore, type Output, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {type Framework, frameworks} from '@vercel/frameworks'\n\nimport {CLIInitStepCompleted} from '../../telemetry/init.telemetry.js'\nimport {detectFrameworkRecord} from '../../util/detectFramework.js'\nimport {dirIsEmptyOrNonExistent} from '../../util/dirIsEmptyOrNonExistent.js'\nimport {getProjectDefaults} from '../../util/getProjectDefaults.js'\nimport {type PackageManager} from '../../util/packageManager/packageManagerChoice.js'\nimport {initStudio} from '../init/initStudio.js'\nimport {resolvePackageManager} from '../init/resolvePackageManager.js'\nimport {type InitOptions} from '../init/types.js'\nimport {createFrontend, FrontendScaffoldError, installFrontendDeps} from './createFrontend.js'\n\nconst debug = subdebug('scaffold')\n\nexport const STUDIO_DIR = 'sanity'\nexport const FRONTEND_DIR = 'web'\nexport const STUDIO_ENV_FILE = `${STUDIO_DIR}/.env.local`\nexport const FRONTEND_ENV_FILE = `${FRONTEND_DIR}/.env.local`\n\nconst STUDIO_PACKAGE_NAME = 'sanity-studio'\nconst STUDIO_PACKAGE_MANAGERS = new Set<PackageManager>(['npm', 'pnpm', 'yarn'])\n\nexport async function isStudioScaffoldTargetAvailable(workDir: string): Promise<boolean> {\n return isScaffoldTargetAvailable(workDir, STUDIO_DIR)\n}\n\nasync function isScaffoldTargetAvailable(workDir: string, targetDir: string): Promise<boolean> {\n const targetPath = path.join(workDir, targetDir)\n try {\n if (!(await lstat(targetPath)).isDirectory()) {\n return false\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw err\n }\n }\n\n return dirIsEmptyOrNonExistent(targetPath)\n}\n\nasync function inspectScaffoldTargets(workDir: string) {\n if (!(await isStudioScaffoldTargetAvailable(workDir))) {\n return {unavailableTarget: STUDIO_DIR}\n }\n\n const detectedFramework = await detectFrameworkRecord({\n frameworkList: frameworks as readonly Framework[],\n rootPath: workDir,\n })\n if (!detectedFramework && !(await isScaffoldTargetAvailable(workDir, FRONTEND_DIR))) {\n return {unavailableTarget: FRONTEND_DIR}\n }\n\n return {detectedFramework}\n}\n\nexport async function getUnavailableScaffoldTarget(workDir: string): Promise<string | undefined> {\n const {unavailableTarget} = await inspectScaffoldTargets(workDir)\n return unavailableTarget\n}\n\nexport interface ScaffoldResult {\n studioPath: string\n\n detectedFramework?: string\n frontendCreationError?: string\n frontendDependenciesInstalled?: boolean\n frontendDependencyError?: string\n frontendPackageManager?: PackageManager\n frontendPath?: string\n}\n\nfunction createScaffoldEnv(dataset: string, projectId: string, token: string) {\n return {\n SANITY_AUTH_TOKEN: token,\n SANITY_DATASET: dataset,\n SANITY_PROJECT_ID: projectId,\n }\n}\n\nexport async function scaffoldProject({\n cancelSignal,\n dataset,\n displayName,\n output,\n packageManager,\n projectId,\n telemetry,\n token,\n workDir,\n}: {\n cancelSignal?: AbortSignal\n dataset: string\n displayName: string\n output: Output\n packageManager?: PackageManager\n projectId: string\n telemetry: CLITelemetryStore\n token: string\n workDir: string\n}): Promise<ScaffoldResult> {\n cancelSignal?.throwIfAborted()\n const {detectedFramework: detected, unavailableTarget} = await inspectScaffoldTargets(workDir)\n const studioPath = path.join(workDir, STUDIO_DIR)\n if (unavailableTarget) {\n throw new Error(`./${unavailableTarget} is not an empty directory`)\n }\n\n const resolvedPackageManager = await resolvePackageManager({\n interactive: false,\n output,\n packageManager: packageManager as PackageManager,\n targetDir: workDir,\n })\n\n const options: InitOptions = {\n autoUpdates: true,\n bare: false,\n dataset,\n datasetDefault: true,\n fromCreate: false,\n git: false,\n mcpMode: 'skip',\n outputPath: studioPath,\n packageManager: STUDIO_PACKAGE_MANAGERS.has(resolvedPackageManager)\n ? (resolvedPackageManager as InitOptions['packageManager'])\n : undefined,\n project: projectId,\n skillsMode: 'skip',\n template: 'clean',\n typescript: true,\n unattended: true,\n }\n\n const trace = telemetry.trace(CLIInitStepCompleted)\n trace.start()\n try {\n // To avoid changing Studio initialization internals, we're deferring passing `cancelSignal`\n // until post `sanity new` launch.\n await initStudio({\n datasetName: dataset,\n defaults: await getProjectDefaults({isPlugin: false, workDir}),\n displayName,\n isFirstProject: false,\n mcpConfigured: [],\n options,\n organizationId: undefined,\n output,\n outputPath: studioPath,\n preclaim: true,\n projectId,\n remoteTemplateInfo: undefined,\n sluggedName: STUDIO_PACKAGE_NAME,\n trace,\n workbench: false,\n workDir,\n })\n trace.complete()\n } catch (err) {\n trace.error(err instanceof Error ? err : new Error(String(err)))\n throw err\n }\n\n cancelSignal?.throwIfAborted()\n const scaffoldEnv = createScaffoldEnv(dataset, projectId, token)\n writeScaffoldEnv(\n path.join(studioPath, '.env.local'),\n scaffoldEnv,\n `Studio scaffold completed, but writing ./${STUDIO_ENV_FILE} failed`,\n )\n\n if (detected) {\n debug('Detected %s in %s, leaving the frontend alone', detected.name, workDir)\n return {\n detectedFramework: detected.name,\n studioPath,\n }\n }\n\n try {\n await createFrontend({\n cancelSignal,\n dirName: FRONTEND_DIR,\n output,\n packageManager: resolvedPackageManager,\n workDir,\n })\n cancelSignal?.throwIfAborted()\n } catch (err) {\n if (err instanceof FrontendScaffoldError) {\n return {\n frontendCreationError: err.message,\n frontendPackageManager: resolvedPackageManager,\n studioPath,\n }\n }\n throw err\n }\n\n const frontendPath = path.join(workDir, FRONTEND_DIR)\n writeScaffoldEnv(\n path.join(frontendPath, '.env.local'),\n scaffoldEnv,\n `Website scaffold completed, but writing ./${FRONTEND_ENV_FILE} failed`,\n )\n\n let frontendDependenciesInstalled = resolvedPackageManager !== 'manual'\n let frontendDependencyError: string | undefined\n if (frontendDependenciesInstalled) {\n try {\n await installFrontendDeps({\n cancelSignal,\n dirName: FRONTEND_DIR,\n output,\n packageManager: resolvedPackageManager,\n workDir,\n })\n cancelSignal?.throwIfAborted()\n } catch (err) {\n if (!(err instanceof FrontendScaffoldError)) throw err\n frontendDependenciesInstalled = false\n frontendDependencyError = err.message\n }\n }\n\n return {\n frontendDependenciesInstalled,\n frontendDependencyError,\n frontendPackageManager: resolvedPackageManager,\n frontendPath,\n studioPath,\n }\n}\n\nfunction writeScaffoldEnv(\n envPath: string,\n values: Record<string, string>,\n errorContext: string,\n): void {\n const lines = [\n '# Added by `sanity new`. Keep this file out of git: it holds a live project token.',\n ...Object.entries(values).map(([key, value]) => `${key}=\"${value}\"`),\n ]\n try {\n writeFileSync(envPath, `${lines.join('\\n')}\\n`, 'utf8')\n } catch (err) {\n throw new Error(`${errorContext}: ${getErrorMessage(err)}`, {cause: err})\n }\n}\n"],"names":["writeFileSync","lstat","path","subdebug","getErrorMessage","frameworks","CLIInitStepCompleted","detectFrameworkRecord","dirIsEmptyOrNonExistent","getProjectDefaults","initStudio","resolvePackageManager","createFrontend","FrontendScaffoldError","installFrontendDeps","debug","STUDIO_DIR","FRONTEND_DIR","STUDIO_ENV_FILE","FRONTEND_ENV_FILE","STUDIO_PACKAGE_NAME","STUDIO_PACKAGE_MANAGERS","Set","isStudioScaffoldTargetAvailable","workDir","isScaffoldTargetAvailable","targetDir","targetPath","join","isDirectory","err","code","inspectScaffoldTargets","unavailableTarget","detectedFramework","frameworkList","rootPath","getUnavailableScaffoldTarget","createScaffoldEnv","dataset","projectId","token","SANITY_AUTH_TOKEN","SANITY_DATASET","SANITY_PROJECT_ID","scaffoldProject","cancelSignal","displayName","output","packageManager","telemetry","throwIfAborted","detected","studioPath","Error","resolvedPackageManager","interactive","options","autoUpdates","bare","datasetDefault","fromCreate","git","mcpMode","outputPath","has","undefined","project","skillsMode","template","typescript","unattended","trace","start","datasetName","defaults","isPlugin","isFirstProject","mcpConfigured","organizationId","preclaim","remoteTemplateInfo","sluggedName","workbench","complete","error","String","scaffoldEnv","writeScaffoldEnv","name","dirName","frontendCreationError","message","frontendPackageManager","frontendPath","frontendDependenciesInstalled","frontendDependencyError","envPath","values","errorContext","lines","Object","entries","map","key","value","cause"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getCliToken, isCi } from '@sanity/cli-core';
|
|
2
|
+
import { getCliExecutionContext } from '@sanity/cli-core/executionContext';
|
|
2
3
|
import { fetchTelemetryConsent, isValidApiConsentStatus, VALID_API_STATUSES } from '../../services/telemetry.js';
|
|
3
4
|
import { isTrueish } from './isTrueish.js';
|
|
4
5
|
import { telemetryDebug } from './telemetryDebug.js';
|
|
@@ -10,13 +11,14 @@ function parseApiConsentStatus(value) {
|
|
|
10
11
|
}
|
|
11
12
|
export async function resolveConsent() {
|
|
12
13
|
telemetryDebug('Resolving consent…');
|
|
13
|
-
|
|
14
|
+
const hasCliExecutionContext = Boolean(getCliExecutionContext());
|
|
15
|
+
if (!hasCliExecutionContext && isCi()) {
|
|
14
16
|
telemetryDebug('CI environment detected, treating telemetry consent as denied');
|
|
15
17
|
return {
|
|
16
18
|
status: 'denied'
|
|
17
19
|
};
|
|
18
20
|
}
|
|
19
|
-
if (isTrueish(process.env.DO_NOT_TRACK)) {
|
|
21
|
+
if (!hasCliExecutionContext && isTrueish(process.env.DO_NOT_TRACK)) {
|
|
20
22
|
telemetryDebug('DO_NOT_TRACK is set, consent is denied');
|
|
21
23
|
return {
|
|
22
24
|
reason: 'localOverride',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/telemetry/resolveConsent.ts"],"sourcesContent":["import {type ConsentInformation, getCliToken, isCi} from '@sanity/cli-core'\n\nimport {\n fetchTelemetryConsent,\n isValidApiConsentStatus,\n VALID_API_STATUSES,\n type ValidApiConsentStatus,\n} from '../../services/telemetry.js'\nimport {isTrueish} from './isTrueish.js'\nimport {telemetryDebug} from './telemetryDebug.js'\n\nfunction parseApiConsentStatus(value: unknown): ValidApiConsentStatus {\n if (typeof value === 'string' && isValidApiConsentStatus(value)) {\n return value\n }\n throw new Error(`Invalid consent status. Must be one of: ${VALID_API_STATUSES.join(', ')}`)\n}\n\nexport async function resolveConsent(): Promise<ConsentInformation> {\n telemetryDebug('Resolving consent…')\n if (isCi()) {\n telemetryDebug('CI environment detected, treating telemetry consent as denied')\n return {status: 'denied'}\n }\n\n if (isTrueish(process.env.DO_NOT_TRACK)) {\n telemetryDebug('DO_NOT_TRACK is set, consent is denied')\n return {\n reason: 'localOverride',\n status: 'denied',\n }\n }\n\n const token = await getCliToken()\n if (!token) {\n telemetryDebug('User is not logged in, consent is undetermined')\n return {\n reason: 'unauthenticated',\n status: 'undetermined',\n }\n }\n\n try {\n const response = await fetchTelemetryConsent()\n\n telemetryDebug('User consent status is %s', response.status)\n return {status: parseApiConsentStatus(response.status)}\n } catch (err) {\n telemetryDebug('Failed to fetch user consent status, treating it as \"undetermined\": %s', err)\n return {\n reason: 'fetchError',\n status: 'undetermined',\n }\n }\n}\n"],"names":["getCliToken","isCi","fetchTelemetryConsent","isValidApiConsentStatus","VALID_API_STATUSES","isTrueish","telemetryDebug","parseApiConsentStatus","value","Error","join","resolveConsent","status","process","env","DO_NOT_TRACK","reason","token","response","err"],"mappings":"AAAA,SAAiCA,WAAW,EAAEC,IAAI,QAAO,mBAAkB;
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/telemetry/resolveConsent.ts"],"sourcesContent":["import {type ConsentInformation, getCliToken, isCi} from '@sanity/cli-core'\nimport {getCliExecutionContext} from '@sanity/cli-core/executionContext'\n\nimport {\n fetchTelemetryConsent,\n isValidApiConsentStatus,\n VALID_API_STATUSES,\n type ValidApiConsentStatus,\n} from '../../services/telemetry.js'\nimport {isTrueish} from './isTrueish.js'\nimport {telemetryDebug} from './telemetryDebug.js'\n\nfunction parseApiConsentStatus(value: unknown): ValidApiConsentStatus {\n if (typeof value === 'string' && isValidApiConsentStatus(value)) {\n return value\n }\n throw new Error(`Invalid consent status. Must be one of: ${VALID_API_STATUSES.join(', ')}`)\n}\n\nexport async function resolveConsent(): Promise<ConsentInformation> {\n telemetryDebug('Resolving consent…')\n const hasCliExecutionContext = Boolean(getCliExecutionContext())\n\n if (!hasCliExecutionContext && isCi()) {\n telemetryDebug('CI environment detected, treating telemetry consent as denied')\n return {status: 'denied'}\n }\n\n if (!hasCliExecutionContext && isTrueish(process.env.DO_NOT_TRACK)) {\n telemetryDebug('DO_NOT_TRACK is set, consent is denied')\n return {\n reason: 'localOverride',\n status: 'denied',\n }\n }\n\n const token = await getCliToken()\n if (!token) {\n telemetryDebug('User is not logged in, consent is undetermined')\n return {\n reason: 'unauthenticated',\n status: 'undetermined',\n }\n }\n\n try {\n const response = await fetchTelemetryConsent()\n\n telemetryDebug('User consent status is %s', response.status)\n return {status: parseApiConsentStatus(response.status)}\n } catch (err) {\n telemetryDebug('Failed to fetch user consent status, treating it as \"undetermined\": %s', err)\n return {\n reason: 'fetchError',\n status: 'undetermined',\n }\n }\n}\n"],"names":["getCliToken","isCi","getCliExecutionContext","fetchTelemetryConsent","isValidApiConsentStatus","VALID_API_STATUSES","isTrueish","telemetryDebug","parseApiConsentStatus","value","Error","join","resolveConsent","hasCliExecutionContext","Boolean","status","process","env","DO_NOT_TRACK","reason","token","response","err"],"mappings":"AAAA,SAAiCA,WAAW,EAAEC,IAAI,QAAO,mBAAkB;AAC3E,SAAQC,sBAAsB,QAAO,oCAAmC;AAExE,SACEC,qBAAqB,EACrBC,uBAAuB,EACvBC,kBAAkB,QAEb,8BAA6B;AACpC,SAAQC,SAAS,QAAO,iBAAgB;AACxC,SAAQC,cAAc,QAAO,sBAAqB;AAElD,SAASC,sBAAsBC,KAAc;IAC3C,IAAI,OAAOA,UAAU,YAAYL,wBAAwBK,QAAQ;QAC/D,OAAOA;IACT;IACA,MAAM,IAAIC,MAAM,CAAC,wCAAwC,EAAEL,mBAAmBM,IAAI,CAAC,OAAO;AAC5F;AAEA,OAAO,eAAeC;IACpBL,eAAe;IACf,MAAMM,yBAAyBC,QAAQZ;IAEvC,IAAI,CAACW,0BAA0BZ,QAAQ;QACrCM,eAAe;QACf,OAAO;YAACQ,QAAQ;QAAQ;IAC1B;IAEA,IAAI,CAACF,0BAA0BP,UAAUU,QAAQC,GAAG,CAACC,YAAY,GAAG;QAClEX,eAAe;QACf,OAAO;YACLY,QAAQ;YACRJ,QAAQ;QACV;IACF;IAEA,MAAMK,QAAQ,MAAMpB;IACpB,IAAI,CAACoB,OAAO;QACVb,eAAe;QACf,OAAO;YACLY,QAAQ;YACRJ,QAAQ;QACV;IACF;IAEA,IAAI;QACF,MAAMM,WAAW,MAAMlB;QAEvBI,eAAe,6BAA6Bc,SAASN,MAAM;QAC3D,OAAO;YAACA,QAAQP,sBAAsBa,SAASN,MAAM;QAAC;IACxD,EAAE,OAAOO,KAAK;QACZf,eAAe,0EAA0Ee;QACzF,OAAO;YACLH,QAAQ;YACRJ,QAAQ;QACV;IACF;AACF"}
|
|
@@ -166,7 +166,7 @@ export class ListBackupCommand extends SanityCommand {
|
|
|
166
166
|
resource: 'Dataset'
|
|
167
167
|
});
|
|
168
168
|
}
|
|
169
|
-
table.
|
|
169
|
+
this.log(table.render());
|
|
170
170
|
listBackupDebug(`Successfully listed ${response.backups.length} backups for dataset ${dataset}`);
|
|
171
171
|
} catch (error) {
|
|
172
172
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/backups/list.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\nimport {type DatasetsResponse} from '@sanity/client'\nimport {Table} from 'console-table-printer'\nimport {isAfter} from 'date-fns/isAfter'\nimport {isValid} from 'date-fns/isValid'\nimport {lightFormat} from 'date-fns/lightFormat'\nimport {parse} from 'date-fns/parse'\n\nimport {assertDatasetExists} from '../../actions/backup/assertDatasetExist.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {listBackups} from '../../services/backup.js'\nimport {listDatasets} from '../../services/datasets.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst listBackupDebug = subdebug('backup:list')\n\nconst DEFAULT_LIST_BACKUP_LIMIT = 30\n\ntype ListBackupRequestQueryParams = {\n after?: string\n before?: string\n limit: string\n}\n\nexport class ListBackupCommand extends SanityCommand<typeof ListBackupCommand> {\n static override args = {\n dataset: Args.string({\n description: 'Dataset name to list backups for',\n required: false,\n }),\n }\n\n static override description = 'List available backups for a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'List backups for a dataset interactively',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production',\n description: 'List backups for the production dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production --limit 50',\n description: 'List up to 50 backups for the production dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production --after 2024-01-31 --limit 10',\n description: 'List up to 10 backups created after 2024-01-31',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to list backups for',\n semantics: 'override',\n }),\n after: Flags.string({\n description: 'Only return backups after this date (inclusive, YYYY-MM-DD format)',\n }),\n before: Flags.string({\n description: 'Only return backups before this date (exclusive, YYYY-MM-DD format)',\n }),\n limit: Flags.integer({\n char: 'l',\n default: DEFAULT_LIST_BACKUP_LIMIT,\n description: 'Maximum number of backups returned',\n }),\n }\n\n static override hiddenAliases: string[] = ['backup:list']\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(ListBackupCommand)\n let {dataset} = args\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'read', permission: 'sanity.project.datasets'}],\n }),\n })\n\n let datasets: DatasetsResponse\n\n try {\n datasets = await listDatasets(projectId)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n listBackupDebug(`Failed to list datasets: ${message}`, error)\n this.error(`Failed to list datasets: ${message}`, {exit: exitCodes.RUNTIME_ERROR})\n }\n\n if (datasets.length === 0) {\n this.error('No datasets found in this project.', {exit: exitCodes.RUNTIME_ERROR})\n }\n\n if (dataset) {\n assertDatasetExists(datasets, dataset, this.output)\n } else if (this.isUnattended()) {\n this.error('Dataset is required in unattended mode. Pass it as the `<dataset>` argument.', {\n exit: exitCodes.USAGE_ERROR,\n })\n } else {\n dataset = await this.promptForDataset(datasets)\n }\n\n // Validate date flags\n if (flags.before || flags.after) {\n try {\n const parsedBefore = this.processDateFlag(flags.before, 'before')\n const parsedAfter = this.processDateFlag(flags.after, 'after')\n\n if (parsedAfter && parsedBefore && isAfter(parsedAfter, parsedBefore)) {\n this.error('--after date must be before --before', {exit: exitCodes.RUNTIME_ERROR})\n }\n } catch (err) {\n this.error(`Parsing date flags: ${err instanceof Error ? err.message : err}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n // Validate limit flag\n if (flags.limit < 1 || flags.limit > Number.MAX_SAFE_INTEGER) {\n this.error(`Parsing --limit: must be an integer between 1 and ${Number.MAX_SAFE_INTEGER}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n const query: ListBackupRequestQueryParams = {\n limit: flags.limit.toString(),\n }\n\n if (flags.after) {\n query.after = flags.after\n }\n\n if (flags.before) {\n query.before = flags.before\n }\n\n try {\n const response = await listBackups({\n after: flags.after,\n before: flags.before,\n datasetName: dataset,\n limit: flags.limit,\n projectId,\n })\n\n if (response.backups.length === 0) {\n this.log('No backups found.')\n return\n }\n\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'resource', title: 'RESOURCE'},\n {alignment: 'left', name: 'createdAt', title: 'CREATED AT'},\n {alignment: 'left', name: 'backupId', title: 'BACKUP ID'},\n ],\n })\n\n for (const backup of response.backups) {\n const {createdAt, id} = backup\n table.addRow({\n backupId: id,\n createdAt: lightFormat(Date.parse(createdAt), 'yyyy-MM-dd HH:mm:ss'),\n resource: 'Dataset',\n })\n }\n\n table.printTable()\n\n listBackupDebug(\n `Successfully listed ${response.backups.length} backups for dataset ${dataset}`,\n )\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n listBackupDebug(`Failed to list backups for dataset ${dataset}:`, error)\n this.error(`List dataset backup failed: ${message}`, {exit: exitCodes.RUNTIME_ERROR})\n }\n }\n\n private processDateFlag(date: string | undefined, flagName: string): Date | undefined {\n if (!date) return undefined\n const parsedDate = parse(date, 'yyyy-MM-dd', new Date())\n if (isValid(parsedDate)) {\n return parsedDate\n }\n\n throw new Error(`Invalid date format for '--${flagName}' flag. Use YYYY-MM-DD`)\n }\n\n private async promptForDataset(datasets: DatasetsResponse): Promise<string> {\n try {\n const choices = datasets.map((dataset) => ({\n name: dataset.name,\n value: dataset.name,\n }))\n\n return select({\n choices,\n message: 'Select the dataset name:',\n })\n } catch (error) {\n listBackupDebug(`Error selecting dataset`, error)\n this.error(`Failed to select dataset:\\n${error instanceof Error ? error.message : error}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n}\n"],"names":["Args","Flags","exitCodes","SanityCommand","subdebug","select","Table","isAfter","isValid","lightFormat","parse","assertDatasetExists","promptForProject","listBackups","listDatasets","getProjectIdFlag","listBackupDebug","DEFAULT_LIST_BACKUP_LIMIT","ListBackupCommand","args","dataset","string","description","required","examples","command","flags","semantics","after","before","limit","integer","char","default","hiddenAliases","run","projectId","getProjectId","fallback","requiredPermissions","grant","permission","datasets","error","message","Error","String","exit","RUNTIME_ERROR","length","output","isUnattended","USAGE_ERROR","promptForDataset","parsedBefore","processDateFlag","parsedAfter","err","Number","MAX_SAFE_INTEGER","query","toString","response","datasetName","backups","log","table","columns","alignment","name","title","backup","createdAt","id","addRow","backupId","Date","resource","printTable","date","flagName","undefined","parsedDate","choices","map","value"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/backups/list.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\nimport {type DatasetsResponse} from '@sanity/client'\nimport {Table} from 'console-table-printer'\nimport {isAfter} from 'date-fns/isAfter'\nimport {isValid} from 'date-fns/isValid'\nimport {lightFormat} from 'date-fns/lightFormat'\nimport {parse} from 'date-fns/parse'\n\nimport {assertDatasetExists} from '../../actions/backup/assertDatasetExist.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {listBackups} from '../../services/backup.js'\nimport {listDatasets} from '../../services/datasets.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst listBackupDebug = subdebug('backup:list')\n\nconst DEFAULT_LIST_BACKUP_LIMIT = 30\n\ntype ListBackupRequestQueryParams = {\n after?: string\n before?: string\n limit: string\n}\n\nexport class ListBackupCommand extends SanityCommand<typeof ListBackupCommand> {\n static override args = {\n dataset: Args.string({\n description: 'Dataset name to list backups for',\n required: false,\n }),\n }\n\n static override description = 'List available backups for a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'List backups for a dataset interactively',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production',\n description: 'List backups for the production dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production --limit 50',\n description: 'List up to 50 backups for the production dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production --after 2024-01-31 --limit 10',\n description: 'List up to 10 backups created after 2024-01-31',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to list backups for',\n semantics: 'override',\n }),\n after: Flags.string({\n description: 'Only return backups after this date (inclusive, YYYY-MM-DD format)',\n }),\n before: Flags.string({\n description: 'Only return backups before this date (exclusive, YYYY-MM-DD format)',\n }),\n limit: Flags.integer({\n char: 'l',\n default: DEFAULT_LIST_BACKUP_LIMIT,\n description: 'Maximum number of backups returned',\n }),\n }\n\n static override hiddenAliases: string[] = ['backup:list']\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(ListBackupCommand)\n let {dataset} = args\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'read', permission: 'sanity.project.datasets'}],\n }),\n })\n\n let datasets: DatasetsResponse\n\n try {\n datasets = await listDatasets(projectId)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n listBackupDebug(`Failed to list datasets: ${message}`, error)\n this.error(`Failed to list datasets: ${message}`, {exit: exitCodes.RUNTIME_ERROR})\n }\n\n if (datasets.length === 0) {\n this.error('No datasets found in this project.', {exit: exitCodes.RUNTIME_ERROR})\n }\n\n if (dataset) {\n assertDatasetExists(datasets, dataset, this.output)\n } else if (this.isUnattended()) {\n this.error('Dataset is required in unattended mode. Pass it as the `<dataset>` argument.', {\n exit: exitCodes.USAGE_ERROR,\n })\n } else {\n dataset = await this.promptForDataset(datasets)\n }\n\n // Validate date flags\n if (flags.before || flags.after) {\n try {\n const parsedBefore = this.processDateFlag(flags.before, 'before')\n const parsedAfter = this.processDateFlag(flags.after, 'after')\n\n if (parsedAfter && parsedBefore && isAfter(parsedAfter, parsedBefore)) {\n this.error('--after date must be before --before', {exit: exitCodes.RUNTIME_ERROR})\n }\n } catch (err) {\n this.error(`Parsing date flags: ${err instanceof Error ? err.message : err}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n // Validate limit flag\n if (flags.limit < 1 || flags.limit > Number.MAX_SAFE_INTEGER) {\n this.error(`Parsing --limit: must be an integer between 1 and ${Number.MAX_SAFE_INTEGER}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n const query: ListBackupRequestQueryParams = {\n limit: flags.limit.toString(),\n }\n\n if (flags.after) {\n query.after = flags.after\n }\n\n if (flags.before) {\n query.before = flags.before\n }\n\n try {\n const response = await listBackups({\n after: flags.after,\n before: flags.before,\n datasetName: dataset,\n limit: flags.limit,\n projectId,\n })\n\n if (response.backups.length === 0) {\n this.log('No backups found.')\n return\n }\n\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'resource', title: 'RESOURCE'},\n {alignment: 'left', name: 'createdAt', title: 'CREATED AT'},\n {alignment: 'left', name: 'backupId', title: 'BACKUP ID'},\n ],\n })\n\n for (const backup of response.backups) {\n const {createdAt, id} = backup\n table.addRow({\n backupId: id,\n createdAt: lightFormat(Date.parse(createdAt), 'yyyy-MM-dd HH:mm:ss'),\n resource: 'Dataset',\n })\n }\n\n this.log(table.render())\n\n listBackupDebug(\n `Successfully listed ${response.backups.length} backups for dataset ${dataset}`,\n )\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n listBackupDebug(`Failed to list backups for dataset ${dataset}:`, error)\n this.error(`List dataset backup failed: ${message}`, {exit: exitCodes.RUNTIME_ERROR})\n }\n }\n\n private processDateFlag(date: string | undefined, flagName: string): Date | undefined {\n if (!date) return undefined\n const parsedDate = parse(date, 'yyyy-MM-dd', new Date())\n if (isValid(parsedDate)) {\n return parsedDate\n }\n\n throw new Error(`Invalid date format for '--${flagName}' flag. Use YYYY-MM-DD`)\n }\n\n private async promptForDataset(datasets: DatasetsResponse): Promise<string> {\n try {\n const choices = datasets.map((dataset) => ({\n name: dataset.name,\n value: dataset.name,\n }))\n\n return select({\n choices,\n message: 'Select the dataset name:',\n })\n } catch (error) {\n listBackupDebug(`Error selecting dataset`, error)\n this.error(`Failed to select dataset:\\n${error instanceof Error ? error.message : error}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n}\n"],"names":["Args","Flags","exitCodes","SanityCommand","subdebug","select","Table","isAfter","isValid","lightFormat","parse","assertDatasetExists","promptForProject","listBackups","listDatasets","getProjectIdFlag","listBackupDebug","DEFAULT_LIST_BACKUP_LIMIT","ListBackupCommand","args","dataset","string","description","required","examples","command","flags","semantics","after","before","limit","integer","char","default","hiddenAliases","run","projectId","getProjectId","fallback","requiredPermissions","grant","permission","datasets","error","message","Error","String","exit","RUNTIME_ERROR","length","output","isUnattended","USAGE_ERROR","promptForDataset","parsedBefore","processDateFlag","parsedAfter","err","Number","MAX_SAFE_INTEGER","query","toString","response","datasetName","backups","log","table","columns","alignment","name","title","backup","createdAt","id","addRow","backupId","Date","resource","render","date","flagName","undefined","parsedDate","choices","map","value"],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { Args, Flags } from '@oclif/core';
|
|
|
3
3
|
import { exit } from '@oclif/core/errors';
|
|
4
4
|
import { exitCodes } from '@sanity/cli-core';
|
|
5
5
|
import { subdebug } from '@sanity/cli-core/debug';
|
|
6
|
+
import { getCliExecutionContext } from '@sanity/cli-core/executionContext';
|
|
6
7
|
import { SanityCommand } from '@sanity/cli-core/SanityCommand';
|
|
7
8
|
import { spinner } from '@sanity/cli-core/ux';
|
|
8
9
|
import { Table } from 'console-table-printer';
|
|
@@ -385,6 +386,7 @@ export class CopyDatasetCommand extends SanityCommand {
|
|
|
385
386
|
}
|
|
386
387
|
async subscribeToProgress(projectId, jobId) {
|
|
387
388
|
const spin = spinner('').start();
|
|
389
|
+
const hasCliExecutionContext = Boolean(getCliExecutionContext());
|
|
388
390
|
return new Promise((resolve, reject)=>{
|
|
389
391
|
const sigintHandler = ()=>{
|
|
390
392
|
subscription.unsubscribe();
|
|
@@ -396,12 +398,12 @@ export class CopyDatasetCommand extends SanityCommand {
|
|
|
396
398
|
projectId
|
|
397
399
|
}).subscribe({
|
|
398
400
|
complete: ()=>{
|
|
399
|
-
process.off('SIGINT', sigintHandler);
|
|
401
|
+
if (!hasCliExecutionContext) process.off('SIGINT', sigintHandler);
|
|
400
402
|
spin.succeed('Copy finished.');
|
|
401
403
|
resolve();
|
|
402
404
|
},
|
|
403
405
|
error: (err)=>{
|
|
404
|
-
process.off('SIGINT', sigintHandler);
|
|
406
|
+
if (!hasCliExecutionContext) process.off('SIGINT', sigintHandler);
|
|
405
407
|
spin.fail('Copy failed.');
|
|
406
408
|
reject(err);
|
|
407
409
|
},
|
|
@@ -411,7 +413,7 @@ export class CopyDatasetCommand extends SanityCommand {
|
|
|
411
413
|
}
|
|
412
414
|
}
|
|
413
415
|
});
|
|
414
|
-
process.once('SIGINT', sigintHandler);
|
|
416
|
+
if (!hasCliExecutionContext) process.once('SIGINT', sigintHandler);
|
|
415
417
|
});
|
|
416
418
|
}
|
|
417
419
|
}
|