@sanity/plugin-kit 5.0.1 → 5.0.3

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.
@@ -3,444 +3,43 @@ import path from "path";
3
3
  import util from "util";
4
4
  import githubUrlToObject from "github-url-to-object";
5
5
  import validateNpmPackageName from "validate-npm-package-name";
6
- import { URL, fileURLToPath } from "url";
7
- import licenses from "@rexxars/choosealicense-list";
8
- import gitRemoteOriginUrl from "git-remote-origin-url";
9
- import { log, urls, minPkgUtilsMajor, requiredNodeEngine, incompatiblePluginPackage, cliName } from "./index.js";
10
6
  import { createRequire } from "node:module";
11
7
  import chalk from "chalk";
12
- import outdent$1, { outdent } from "outdent";
8
+ import outdent from "outdent";
9
+ import { log, urls, minPkgUtilsMajor, requiredNodeEngine, incompatiblePluginPackage, cliName } from "./index.js";
13
10
  import crypto from "crypto";
14
11
  import json5 from "json5";
15
12
  import pAny from "p-any";
16
- import { pkg } from "./package2.js";
13
+ import { URL } from "url";
17
14
  import inquirer from "inquirer";
15
+ import { pkg } from "./package2.js";
18
16
  import getLatestVersion from "get-latest-version";
19
17
  import pProps from "p-props";
20
- import { getIt } from "get-it";
21
- import { promise, jsonRequest, jsonResponse, httpErrors, headers } from "get-it/middleware";
22
- import { execSync } from "child_process";
23
- import { validate } from "email-validator";
24
- import xdgBasedir from "xdg-basedir";
25
- function eslintrcTemplate(options) {
26
- const { flags } = options, eslintConfig = {
27
- root: !0,
28
- env: {
29
- node: !0,
30
- browser: !0
31
- },
32
- extends: [
33
- "sanity",
34
- flags.typescript && "sanity/typescript",
35
- "sanity/react",
36
- "plugin:react-hooks/recommended",
37
- flags.prettier && "plugin:prettier/recommended",
38
- "plugin:react/jsx-runtime"
39
- ].filter(Boolean)
40
- };
41
- return {
42
- type: "template",
43
- force: flags.force,
44
- to: ".eslintrc",
45
- value: JSON.stringify(eslintConfig, null, 2)
46
- };
47
- }
48
- function eslintignoreTemplate(options) {
49
- const { flags, outDir } = options, patterns = [
50
- ".eslintrc.js",
51
- "commitlint.config.js",
52
- outDir,
53
- "lint-staged.config.js",
54
- "package.config.ts",
55
- flags.typescript ? "*.js" : ""
56
- ].filter(Boolean);
57
- return patterns.sort(), {
58
- type: "template",
59
- force: flags.force,
60
- to: ".eslintignore",
61
- value: patterns.join(`
62
- `)
63
- };
64
- }
65
- function gitignoreTemplate() {
66
- return {
67
- type: "template",
68
- to: ".gitignore",
69
- value: outdent`
70
- # Logs
71
- logs
72
- *.log
73
- npm-debug.log*
74
-
75
- # Runtime data
76
- pids
77
- *.pid
78
- *.seed
79
-
80
- # Directory for instrumented libs generated by jscoverage/JSCover
81
- lib-cov
82
-
83
- # Coverage directory used by tools like istanbul
84
- coverage
85
-
86
- # nyc test coverage
87
- .nyc_output
88
-
89
- # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
90
- .grunt
91
-
92
- # node-waf configuration
93
- .lock-wscript
94
-
95
- # Compiled binary addons (http://nodejs.org/api/addons.html)
96
- build/Release
97
-
98
- # Dependency directories
99
- node_modules
100
- jspm_packages
101
-
102
- # Optional npm cache directory
103
- .npm
104
-
105
- # Optional REPL history
106
- .node_repl_history
107
-
108
- # macOS finder cache file
109
- .DS_Store
110
-
111
- # VS Code settings
112
- .vscode
113
-
114
- # IntelliJ
115
- .idea
116
- *.iml
117
-
118
- # Cache
119
- .cache
120
-
121
- # Yalc
122
- .yalc
123
- yalc.lock
124
-
125
- # npm package zips
126
- *.tgz
127
- `
128
- };
129
- }
130
- function pkgConfigTemplate(options) {
131
- const { flags, outDir } = options;
132
- return {
133
- type: "template",
134
- force: flags.force,
135
- // Always a `.ts` config: plugins are ESM (`"type": "module"`), so `@sanity/pkg-utils`
136
- // loads it without needing a `.mts`/`.mjs` extension to force ESM interpretation.
137
- to: "package.config.ts",
138
- value: outdent`
139
- import {defineConfig} from '@sanity/pkg-utils'
140
-
141
- export default defineConfig({
142
- dist: '${outDir}',
143
- tsconfig: 'tsconfig.${outDir}.json',
144
-
145
- // Remove this block to enable strict export validation
146
- extract: {
147
- rules: {
148
- 'ae-incompatible-release-tags': 'off',
149
- 'ae-internal-missing-underscore': 'off',
150
- 'ae-missing-release-tag': 'off',
151
- },
152
- },
153
- })
154
- `
155
- };
156
- }
157
- function prettierignoreTemplate(options) {
158
- const { outDir } = options;
159
- return {
160
- type: "template",
161
- to: ".prettierignore",
162
- value: [outDir, "pnpm-lock.yaml", "yarn.lock", "package-lock.json"].join(`
163
- `)
164
- };
165
- }
166
- function tsconfigTemplate(options) {
167
- const { flags } = options;
168
- return {
169
- type: "template",
170
- force: flags.force,
171
- to: "tsconfig.json",
172
- value: outdent`
173
- {
174
- "extends": "./tsconfig.settings",
175
- "include": ["./src", "./package.config.ts"]
176
- }
177
- `
178
- };
179
- }
180
- function tsconfigTemplateDist(options) {
181
- const { flags, outDir } = options;
182
- return {
183
- type: "template",
184
- force: flags.force,
185
- to: `tsconfig.${outDir}.json`,
186
- value: outdent`
187
- {
188
- "extends": "./tsconfig.settings",
189
- "include": ["./src"],
190
- "exclude": [
191
- "./src/**/__fixtures__",
192
- "./src/**/__mocks__",
193
- "./src/**/*.test.ts",
194
- "./src/**/*.test.tsx"
195
- ]
196
- }
197
- `
198
- };
199
- }
200
- function tsconfigTemplateSettings(options) {
201
- const { flags, outDir } = options;
202
- return {
203
- type: "template",
204
- force: flags.force,
205
- to: "tsconfig.settings.json",
206
- value: outdent`
207
- {
208
- "compilerOptions": {
209
- "rootDir": ".",
210
- "outDir": "./${outDir}",
211
-
212
- "target": "esnext",
213
- "jsx": "preserve",
214
- "module": "preserve",
215
- "moduleResolution": "bundler",
216
- "esModuleInterop": true,
217
- "resolveJsonModule": true,
218
- "moduleDetection": "force",
219
- "strict": true,
220
- "allowSyntheticDefaultImports": true,
221
- "skipLibCheck": true,
222
- "forceConsistentCasingInFileNames": true,
223
- "isolatedModules": true,
224
-
225
- // Don't emit by default, pkg-utils will ignore this when generating .d.ts files
226
- "noEmit": true
227
- }
228
- }
229
- `
230
- };
231
- }
232
- const renovatePreset = {
233
- name: "renovatebot",
234
- description: "Files to enable renovatebot.",
235
- apply: applyPreset$3
236
- };
237
- async function applyPreset$3(options) {
238
- await writeAssets(
239
- [
240
- {
241
- type: "copy",
242
- from: ["renovatebot", "renovate.json"],
243
- to: "renovate.json"
244
- }
245
- ],
246
- options
247
- );
248
- }
249
- const lockedDependencies = {
250
- "styled-components": "^6.1",
251
- eslint: "^8.57.0"
252
- };
253
- function resolveLatestVersions(packages) {
254
- const versions = {};
255
- for (const pkgName of packages)
256
- versions[pkgName] = pkgName in lockedDependencies ? lockedDependencies[pkgName] : "latest";
257
- return pProps(
258
- versions,
259
- async (range, pkgName) => {
260
- const version = await getLatestVersion(pkgName, { range });
261
- if (!version)
262
- throw new Error(`Found no version for ${pkgName}`);
263
- return rangeify(version);
264
- },
265
- { concurrency: 8 }
266
- );
267
- }
268
- function rangeify(version) {
269
- return `^${version}`;
270
- }
271
- function errorToUndefined(err) {
272
- if (err instanceof TypeError)
273
- throw err;
274
- }
275
- const buildExtensions = [".js", ".jsx", ".es6", ".es", ".mjs", ".ts", ".tsx"], stat$1 = util.promisify(fs.stat), readFile$2 = util.promisify(fs.readFile), allowedPartProps = ["name", "implements", "path", "description"], disallowedPluginProps = ["api", "project", "plugins", "env"];
276
- async function getPaths(options) {
277
- const { basePath } = options, manifest = await readManifest(options);
278
- return manifest.paths ? absolutifyPaths(manifest.paths, basePath) : null;
279
- }
280
- function absolutifyPaths(paths, basePath) {
281
- const getPath = (relative) => relative ? path.resolve(path.join(basePath, relative)) : void 0;
282
- return paths ? {
283
- basePath,
284
- compiled: getPath(paths.compiled),
285
- source: getPath(paths.source)
286
- } : { basePath };
287
- }
288
- async function readManifest(options) {
289
- const { basePath, validate: validate2 = !0 } = options, manifestPath = path.normalize(path.join(basePath, "sanity.json"));
290
- let content;
291
- try {
292
- content = await readFile$2(manifestPath, "utf8");
293
- } catch (err) {
294
- throw err.code === "ENOENT" ? new Error(
295
- `No sanity.json found. sanity.json is required for plugins to function. Use \`${pkg.binname} init\` for a new plugin, or create an empty \`sanity.json\` with an empty object (\`{}\`) for existing ones.`
296
- ) : new Error(`Failed to read "${manifestPath}": ${err.message}`);
297
- }
298
- let parsed;
299
- try {
300
- parsed = JSON.parse(content);
301
- } catch (err) {
302
- throw new Error(`Error parsing "${manifestPath}": ${err.message}`);
303
- }
304
- return validate2 && await validateManifest(parsed, options), parsed;
305
- }
306
- async function validateManifest(manifest, opts) {
307
- const options = { isPlugin: !0, ...opts };
308
- if (!isObject$1(manifest))
309
- throw new Error("Invalid sanity.json: Root must be an object");
310
- if (options.isPlugin ? await validatePluginManifest(manifest, options) : validateProjectManifest(manifest), "root" in manifest && typeof manifest.root != "boolean")
311
- throw new Error('Invalid sanity.json: "root" property must be a boolean if declared');
312
- await validateParts(manifest, {
313
- ...options,
314
- paths: absolutifyPaths(manifest.paths, options.basePath)
315
- });
316
- }
317
- function validateProjectManifest(manifest) {
318
- if ("paths" in manifest)
319
- throw new Error('Invalid sanity.json: "paths" property has no meaning in a project manifest');
320
- }
321
- async function validatePluginManifest(manifest, options) {
322
- const disallowed = Object.keys(manifest).filter((key) => disallowedPluginProps.includes(key)).map((key) => `"${key}"`);
323
- if (disallowed.length > 0) {
324
- const plural = disallowed.length > 1 ? "s" : "", joined = disallowed.join(", ");
325
- throw new Error(
326
- `Invalid sanity.json: Key${plural} ${joined} ${plural ? "are" : "is"} not allowed in a plugin manifest`
327
- );
328
- }
329
- if (manifest.root)
330
- throw new Error('Invalid sanity.json: "root" cannot be truthy in a plugin manifest');
331
- await validatePaths$1(manifest, options);
332
- }
333
- async function validatePaths$1(manifest, options) {
334
- if (!("paths" in manifest))
335
- return;
336
- if (!isObject$1(manifest.paths))
337
- throw new Error('Invalid sanity.json: "paths" must be an object if declared');
338
- if (typeof manifest.paths.compiled != "string")
339
- throw new Error(
340
- 'Invalid sanity.json: "paths" must have a (string) "compiled" property if declared'
341
- );
342
- if (typeof manifest.paths.source != "string")
343
- throw new Error(
344
- 'Invalid sanity.json: "paths" must have a (string) "source" property if declared'
345
- );
346
- const sourcePath = path.resolve(options.basePath, manifest.paths.source);
347
- let srcStats;
348
- try {
349
- srcStats = await stat$1(sourcePath);
350
- } catch (err) {
351
- if (err.code === "ENOENT")
352
- throw new Error(`sanity.json references "source" path which does not exist: "${sourcePath}"`);
353
- }
354
- if (!srcStats?.isDirectory())
355
- throw new Error(
356
- `sanity.json references "source" path which is not a directory: "${sourcePath}"`
357
- );
358
- }
359
- async function validateParts(manifest, options) {
360
- if (!("parts" in manifest))
361
- return;
362
- if (!Array.isArray(manifest.parts))
363
- throw new Error('Invalid sanity.json: "parts" must be an array if declared');
364
- let i = 0;
365
- for (const part of manifest.parts)
366
- await validatePart(part, i, options), i++;
367
- }
368
- async function validatePart(part, index, options) {
369
- if (!isObject$1(part))
370
- throw new Error(`Invalid sanity.json: "parts[${index}]" must be an object`);
371
- validateAllowedPartKeys(part, index), validatePartStringValues(part, index), validatePartNames(part, index, options), await validatePartFiles(part, index, options);
372
- }
373
- async function validatePartFiles(part, index, options) {
374
- const { verifyCompiledParts, verifySourceParts, paths } = options;
375
- if (!part?.path)
376
- return;
377
- const ext = path.extname(part.path);
378
- if (paths?.source && ext && ext !== ".js" && buildExtensions.includes(ext))
379
- throw new Error(
380
- `Invalid sanity.json: Part path has extension which is not applicable after compiling. ${ext} becomes .js after compiling. Specify filename without extension (${path.basename(
381
- part.path
382
- )}) (parts[${index}])`
383
- );
384
- if (!verifySourceParts && !verifyCompiledParts)
385
- return;
386
- const [srcExists, outDirExists] = await Promise.all([
387
- hasSourceFile(part.path, paths),
388
- verifyCompiledParts && hasCompiledFile(part.path, paths)
389
- ]);
390
- if (!srcExists)
391
- throw new Error(
392
- `Invalid sanity.json: Part path references file that does not exist in source directory (${paths?.source || paths?.basePath}) (parts[${index}])`
393
- );
394
- if (verifyCompiledParts && !outDirExists)
395
- throw new Error(
396
- `Invalid sanity.json: Part path references file ("${part.path}") that does not exist in compiled directory (${paths?.compiled}) (parts[${index}])`
397
- );
398
- }
399
- function validatePartNames(part, index, options) {
400
- const pluginName = options.pluginName ? options.pluginName.replace(/^sanity-plugin-/, "") : "";
401
- if (!part?.name || !part?.name?.startsWith(`part:${pluginName}/`))
402
- throw new Error(
403
- `Invalid sanity.json: "name" must be prefixed with "part:${pluginName}/" - got "${part?.name}" (parts[${index}])`
404
- );
405
- if (!part?.implements?.startsWith("part:"))
406
- throw new Error(
407
- `Invalid sanity.json: "implements" must be prefixed with "part:" - got "${part?.implements}" (parts[${index}])`
408
- );
409
- }
410
- function validateAllowedPartKeys(part, index) {
411
- const disallowed = Object.keys(part).filter((key) => !allowedPartProps.includes(key)).map((key) => `"${key}"`);
412
- if (disallowed.length > 0) {
413
- const plural = disallowed.length > 1 ? "s" : "", joined = disallowed.join(", ");
414
- throw new Error(
415
- `Invalid sanity.json: Key${plural} ${joined} ${plural ? "are" : "is"} not allowed in a part declaration (parts[${index}])`
416
- );
417
- }
418
- }
419
- function validatePartStringValues(part, index) {
420
- const nonStrings = Object.keys(part).filter((key) => typeof part[key] != "string").map((key) => `"${key}"`);
421
- if (nonStrings.length > 0) {
422
- const plural = nonStrings.length > 1 ? "s" : "", joined = nonStrings.join(", ");
423
- throw new Error(
424
- `Invalid sanity.json: Key${plural} ${joined} should be of type string (parts[${index}])`
425
- );
426
- }
427
- }
428
- function isObject$1(obj) {
429
- return !Array.isArray(obj) && obj !== null && typeof obj == "object";
430
- }
431
- async function hasSanityJson(basePath) {
432
- const file = await readJsonFile(path.join(basePath, "sanity.json")).catch(
433
- errorToUndefined
434
- );
435
- return { exists: !!file, isRoot: !!(file && file.root) };
436
- }
437
- async function findStudioV3Config(basePath) {
438
- const jsFile = "sanity.config.js";
439
- if (await fileExists(path.join(basePath, jsFile)))
440
- return { v3ConfigFile: jsFile };
441
- const tsFile = "sanity.config.ts";
442
- return { v3ConfigFile: await fileExists(path.join(basePath, tsFile)) ? tsFile : void 0 };
443
- }
18
+ const mergedPackages = [
19
+ "@sanity/base",
20
+ "@sanity/core",
21
+ "@sanity/types",
22
+ "@sanity/data-aspects",
23
+ "@sanity/default-layout",
24
+ "@sanity/default-login",
25
+ "@sanity/desk-tool",
26
+ "@sanity/field",
27
+ "@sanity/form-builder",
28
+ "@sanity/initial-value-templates",
29
+ "@sanity/language-filter",
30
+ "@sanity/production-preview",
31
+ "@sanity/react-hooks",
32
+ "@sanity/resolver",
33
+ "@sanity/state-router",
34
+ "@sanity/structure",
35
+ "@sanity/studio-hints"
36
+ ].sort(), deprecatedDevDeps = [
37
+ "tsdx",
38
+ "sanipack",
39
+ "parcel",
40
+ "@parcel/packager-ts",
41
+ "@parcel/transformer-typescript-types"
42
+ ], buildExtensions = [".js", ".jsx", ".es6", ".es", ".mjs", ".ts", ".tsx"];
444
43
  async function prompt(message, options) {
445
44
  const type = options.choices ? "list" : options.type, result = await inquirer.prompt([{ ...options, type, message, name: "single" }]);
446
45
  return result && result.single;
@@ -477,7 +76,7 @@ function promptForRepoOrigin(_options, defaultVal) {
477
76
  }
478
77
  });
479
78
  }
480
- const stat = util.promisify(fs.stat), mkdir = util.promisify(fs.mkdir), readdir = util.promisify(fs.readdir), copyFile = util.promisify(fs.copyFile), readFile$1 = util.promisify(fs.readFile), writeFile = util.promisify(fs.writeFile);
79
+ const stat$1 = util.promisify(fs.stat), mkdir = util.promisify(fs.mkdir), readdir = util.promisify(fs.readdir), copyFile = util.promisify(fs.copyFile), readFile$2 = util.promisify(fs.readFile), writeFile = util.promisify(fs.writeFile);
481
80
  function hasSourceEquivalent(compiledFile, paths) {
482
81
  if (!paths.source)
483
82
  return fileExists(
@@ -504,13 +103,13 @@ function hasCompiledFile(filePath, paths) {
504
103
  }
505
104
  function buildCandidateExists(pathStub) {
506
105
  const candidates = buildExtensions.map((extCandidate) => `${pathStub}${extCandidate}`);
507
- return pAny(candidates.map((candidate) => stat(candidate))).then(() => !0).catch(() => !1);
106
+ return pAny(candidates.map((candidate) => stat$1(candidate))).then(() => !0).catch(() => !1);
508
107
  }
509
108
  function fileExists(filePath) {
510
- return stat(filePath).then(() => !0).catch(() => !1);
109
+ return stat$1(filePath).then(() => !0).catch(() => !1);
511
110
  }
512
111
  async function readJsonFile(filePath) {
513
- const content = await readFile$1(filePath, "utf8");
112
+ const content = await readFile$2(filePath, "utf8");
514
113
  return JSON.parse(content);
515
114
  }
516
115
  function writeJsonFile(filePath, content) {
@@ -560,601 +159,41 @@ async function ensureDir(dirPath) {
560
159
  throw err;
561
160
  }
562
161
  }
563
- async function isEmptyish(dirPath) {
564
- const ignoredFiles = [".git", ".gitignore", "license", "readme.md"];
565
- return (await readdir(dirPath).catch(() => [])).filter((file) => !ignoredFiles.includes(file.toLowerCase())).length === 0;
566
- }
567
- async function readFileContent({
568
- filename,
569
- basePath
570
- }) {
571
- const filepath = path.normalize(path.join(basePath, filename));
572
- try {
573
- return await readFile$1(filepath, "utf8");
574
- } catch (err) {
575
- if (err.code === "ENOENT") {
576
- log.debug(`No ${filename} file found.`);
577
- return;
578
- }
579
- throw new Error(`Failed to read "${filepath}": ${err.message}`);
580
- }
581
- }
582
- async function readJson5File({
583
- filename,
584
- basePath
585
- }) {
586
- const content = await readFileContent({ filename, basePath });
587
- if (content)
588
- return parseJson5(content, filename);
589
- }
590
- function parseJson5(content, errorKey) {
591
- try {
592
- return json5.parse(content);
593
- } catch (err) {
594
- throw new Error(`Error parsing "${errorKey}": ${err.message}`);
595
- }
596
- }
597
- const request = getIt([
598
- promise({ onlyBody: !0 }),
599
- jsonRequest(),
600
- jsonResponse(),
601
- httpErrors(),
602
- headers({ "User-Agent": `${pkg.name}@${pkg.version}` })
603
- ]);
604
- async function getUserInfo({ requireUserConfirmation, flags }, pkg2) {
605
- const userInfo = getPackageUserInfo({ author: flags.author ?? pkg2?.author }) || await getSanityUserInfo() || await getGitUserInfo();
606
- return requireUserConfirmation ? promptForInfo(userInfo) : userInfo;
607
- }
608
- function getPackageUserInfo(pkg2) {
609
- let author = pkg2?.author;
610
- if (!author)
611
- return;
612
- if (author && typeof author != "string")
613
- return author;
614
- if (!author.includes("@"))
615
- return { name: author };
616
- const [pre, ...post] = author.replace(/[<>[\]]/g, "").split(/@/), nameParts = pre.split(/\s+/), email = [nameParts[nameParts.length - 1], ...post].join("@");
617
- return { name: nameParts.slice(0, -1).join(" "), email };
618
- }
619
- async function promptForInfo(defValue) {
620
- const name = await prompt("Author name", {
621
- filter: filterString,
622
- default: defValue && defValue.name,
623
- validate: requiredString
624
- }), email = await prompt("Author email", {
625
- filter: filterString,
626
- default: defValue && defValue.email,
627
- validate: validOrEmptyEmail
628
- });
629
- return { name, email };
630
- }
631
- async function getSanityUserInfo() {
632
- try {
633
- const token = (await readJsonFile(
634
- path.join(xdgBasedir.config ?? "", "sanity", "config.json")
635
- ))?.authToken;
636
- if (!token)
637
- return;
638
- const user = await request({
639
- url: "https://api.sanity.io/v1/users/me",
640
- headers: { Authorization: `Bearer ${token}` }
641
- });
642
- if (!user)
643
- return;
644
- const { name, email } = user;
645
- return { name, email };
646
- } catch {
647
- return;
648
- }
649
- }
650
- async function getGitUserInfo() {
651
- try {
652
- const name = execSync("git config user.name", { encoding: "utf8" }).trim(), email = execSync("git config user.email", { encoding: "utf8" }).trim();
653
- return name ? { name, email: email || void 0 } : void 0;
654
- } catch {
655
- return;
656
- }
657
- }
658
- function filterString(val) {
659
- return (val || "").trim();
660
- }
661
- function requiredString(value) {
662
- return value.length > 1 ? !0 : "Required";
663
- }
664
- function validOrEmptyEmail(value) {
665
- return value ? validate(value) ? !0 : "Must either be a valid email or empty" : !0;
666
- }
667
- function generateReadme(data) {
668
- const { user, pluginName, license } = data;
669
- return outdent$1`
670
- # ${pluginName}
671
-
672
-
673
- ${installationSnippet(pluginName ?? "unknown")}
674
-
675
- ## Usage
676
-
677
- Add it as a plugin in \`sanity.config.ts\` (or .js):
678
-
679
- \`\`\`ts
680
- import {defineConfig} from 'sanity'
681
- import {myPlugin} from '${pluginName}'
682
-
683
- export default defineConfig({
684
- //...
685
- plugins: [myPlugin({})],
686
- })
687
- \`\`\`
688
-
689
- ${getLicenseText(license?.id, user?.name ? user : void 0)}
690
- ${developTestSnippet()}
691
- ` + `
692
- `;
693
- }
694
- function installationSnippet(packageName) {
695
- return outdent$1`
696
- ## Installation
697
-
698
- \`\`\`sh
699
- npm install ${packageName}
700
- \`\`\`
701
- `;
702
- }
703
- function developTestSnippet() {
704
- return outdent$1`
705
- ## Develop & test
706
-
707
- This plugin uses [@sanity/plugin-kit](https://github.com/sanity-io/plugin-kit)
708
- with default configuration for build & watch scripts.
709
-
710
- See [Testing a plugin in Sanity Studio](https://github.com/sanity-io/plugin-kit#testing-a-plugin-in-sanity-studio)
711
- on how to run this plugin with hotreload in the studio.
712
- `;
713
- }
714
- function getLicenseText(licenseId, user) {
715
- if (!licenseId)
716
- return "";
717
- let licenseName = licenses.find(licenseId).title;
718
- licenseName = licenseName?.replace(/\s+license$/i, "");
719
- let licenseText = `## License
720
- `;
721
- return licenseName && user?.name ? licenseText = `${licenseText}
722
- [${licenseName}](LICENSE) \xA9 ${user?.name}
723
- ` : licenseName ? licenseText = `${licenseText}
724
- [${licenseName}](LICENSE)
725
- ` : licenseText = `${licenseText}
726
- See [LICENSE](LICENSE)`, licenseText;
727
- }
728
- function isDefaultGitHubReadme(readme) {
729
- if (!readme)
730
- return !1;
731
- const lines = readme.split(`
732
- `, 20).filter(Boolean);
733
- return lines.length <= 2 && lines[0].startsWith("#");
734
- }
735
- const semverWorkflowPreset = {
736
- name: "semver-workflow",
737
- description: "Files and dependencies for conventional-commits, github workflow and semantic-release.",
738
- apply: applyPreset$2
739
- }, info = (write, msg, ...args) => write && log.info(msg, ...args);
740
- async function applyPreset$2(options) {
741
- await writeAssets(semverWorkflowFiles(), options), await addPrepareScript(options), await addDevDependencies$2(options), await updateReadme(options);
742
- }
743
- async function addPrepareScript(options) {
744
- const pkg2 = await getPackage(options), didWrite = await addPackageJsonScripts(pkg2, options, (scripts) => (scripts.prepare = addScript("husky", scripts.prepare), scripts));
745
- info(didWrite, "Added prepare script to package.json");
746
- }
747
- async function addDevDependencies$2(options) {
748
- const pkg2 = await getPackage(options), devDeps = sortKeys({
749
- ...pkg2.devDependencies,
750
- ...await semverWorkflowDependencies()
751
- }), newPkg = { ...pkg2 };
752
- newPkg.devDependencies = devDeps, await writePackageJsonDirect(newPkg, options), log.info("Updated devDependencies."), log.info(
753
- chalk.green(
754
- outdent$1`
755
- semantic-release preset injected.
756
-
757
- Please confer
758
- https://github.com/sanity-io/plugin-kit/blob/main/docs/semver-workflow.md#manual-steps-after-inject
759
- to finalize configuration for this preset.
760
- `.trim()
761
- )
762
- );
763
- }
764
- async function updateReadme(options) {
765
- const { basePath } = options, readmePath = path.join(basePath, "README.md"), readme = await readFile$1(readmePath, "utf8").catch(errorToUndefined) ?? "", { install, usage, developTest, license, releaseSnippet } = await readmeSnippets(options), prependSections = missingSections(readme, [install, usage]), appendSections = missingSections(readme, [license, developTest, releaseSnippet]);
766
- if (prependSections.length || appendSections.length) {
767
- const updatedReadme = [...prependSections, readme, ...appendSections].filter(Boolean).join(`
768
-
769
- `);
770
- await writeFile(readmePath, updatedReadme, { encoding: "utf8" }), log.info("Updated README. Please review the changes.");
771
- }
772
- }
773
- async function readmeSnippets(options) {
774
- const pkg2 = await getPackage(options), user = await getUserInfo(options, pkg2), bestEffortUrl = readmeBaseurl(pkg2), install = installationSnippet(pkg2.name ?? "unknown"), usage = outdent$1`
775
- ## Usage
776
- `, license = getLicenseText(typeof pkg2.license == "string" ? pkg2.license : void 0, user), releaseSnippet = outdent$1`
777
- ### Release new version
778
-
779
- Run ["CI & Release" workflow](${bestEffortUrl}/actions/workflows/main.yml).
780
- Make sure to select the main branch and check "Release new version".
781
-
782
- Semantic release will only release on configured branches, so it is safe to run release on any branch.
783
- `;
784
- return {
785
- install,
786
- usage,
787
- license,
788
- developTest: developTestSnippet(),
789
- releaseSnippet
790
- };
791
- }
792
- function missingSections(readme, sections) {
793
- return sections.filter((section) => !closeEnough(section, readme));
794
- }
795
- function closeEnough(a, b) {
796
- const aLines = a.split(`
797
- `), bLines = b.split(`
798
- `);
799
- return aLines.filter((line) => bLines.find((bLine) => bLine === line)).length >= aLines.length * 0.5;
800
- }
801
- function semverWorkflowFiles() {
802
- return [
803
- {
804
- type: "copy",
805
- from: [".github", "workflows", "main.yml"],
806
- to: [".github", "workflows", "main.yml"]
807
- },
808
- { type: "copy", from: [".husky", "commit-msg"], to: [".husky", "commit-msg"] },
809
- { type: "copy", from: [".husky", "pre-commit"], to: [".husky", "pre-commit"] },
810
- { type: "copy", from: [".releaserc.json"], to: ".releaserc.json" },
811
- { type: "copy", from: ["commitlint.template.js"], to: "commitlint.config.js" },
812
- { type: "copy", from: ["lint-staged.template.js"], to: "lint-staged.config.js" }
813
- ].map((fromTo) => fromTo.type === "copy" ? {
814
- ...fromTo,
815
- from: ["semver-workflow", ...fromTo.from]
816
- } : fromTo);
817
- }
818
- async function semverWorkflowDependencies() {
819
- return resolveLatestVersions([
820
- "@commitlint/cli",
821
- "@commitlint/config-conventional",
822
- "@sanity/semantic-release-preset",
823
- "husky",
824
- "lint-staged"
825
- ]);
826
- }
827
- function readmeBaseurl(pkg2) {
828
- return (pkg2.repository?.url ?? pkg2.homepage ?? "TODO").replace(/.+:\/\//g, "https://").replace(/\.git/g, "").replace(/git@github.com\//g, "github.com/").replace(/git@github.com:/g, "https://github.com/").replace(/#.+/g, "");
829
- }
830
- const forcedPackageVersions = {}, forcedDevPackageVersions = {}, forcedPeerPackageVersions = {
831
- react: "^18",
832
- "react-dom": "^18",
833
- "@types/react": "^18",
834
- "@types/react-dom": "^18",
835
- sanity: "^3",
836
- "styled-components": "^5.2"
837
- }, ui = {
838
- name: "ui",
839
- description: "`@sanity/ui` and dependencies",
840
- apply: applyPreset$1
841
- };
842
- async function applyPreset$1(options) {
843
- await addDependencies(options), await addDevDependencies$1(options), log.info(chalk.green("ui preset injected"));
844
- }
845
- async function addDependencies(options) {
846
- const pkg2 = await getPackage(options), newDeps = sortKeys(
847
- forceDependencyVersions(
848
- {
849
- ...pkg2.dependencies,
850
- ...await resolveDependencyList()
851
- },
852
- forcedPackageVersions
853
- )
854
- ), newPkg = { ...pkg2 };
855
- newPkg.dependencies = newDeps, await writePackageJsonDirect(newPkg, options), log.info("Updated dependencies.");
856
- }
857
- async function addDevDependencies$1(options) {
858
- const pkg2 = await getPackage(options), newDeps = sortKeys(
859
- forceDependencyVersions(
860
- {
861
- ...pkg2.devDependencies,
862
- ...await resolveDevDependencyList()
863
- },
864
- forcedDevPackageVersions
865
- )
866
- ), newPkg = { ...pkg2 };
867
- newPkg.devDependencies = newDeps, await writePackageJsonDirect(newPkg, options), log.info("Updated devDependencies.");
868
- }
869
- async function resolveDependencyList() {
870
- return resolveLatestVersions(["@sanity/icons", "@sanity/ui"]);
871
- }
872
- async function resolveDevDependencyList() {
873
- return resolveLatestVersions([
874
- // install the peer dependencies of `@sanity/ui` as dev dependencies
875
- "react",
876
- "react-dom",
877
- "styled-components"
878
- ]);
879
- }
880
- const uiWorkshop = {
881
- name: "ui-workshop",
882
- description: "Files for testing custom components with @sanity/ui-workshop",
883
- apply: applyPreset
884
- };
885
- async function applyPreset(options) {
886
- await writeAssets(files(), options), await addDevDependencies(options), await updateGitIgnore(options), log.info(
887
- chalk.green(
888
- outdent$1`
889
- ui-workshop preset injected.
890
-
891
- Please confer
892
- https://github.com/sanity-io/plugin-kit/blob/main/docs/ui-workshop.md#manual-steps-after-inject
893
- to finalize configuration for this preset.
894
- `.trim()
895
- )
896
- );
897
- }
898
- function files() {
899
- return [
900
- { type: "copy", from: ["workshop.config.ts"], to: ["workshop.config.ts"] },
901
- { type: "copy", from: ["src", "CustomField.tsx"], to: ["src", "CustomField.tsx"] },
902
- {
903
- type: "copy",
904
- from: ["src", "__workshop__", "index.tsx"],
905
- to: ["src", "__workshop__", "index.tsx"]
906
- },
907
- {
908
- type: "copy",
909
- from: ["src", "__workshop__", "props.tsx"],
910
- to: ["src", "__workshop__", "props.tsx"]
911
- }
912
- ].map((fromTo) => fromTo.type === "copy" ? {
913
- ...fromTo,
914
- from: ["ui-workshop", ...fromTo.from]
915
- } : fromTo);
916
- }
917
- async function updateGitIgnore(options) {
918
- const { basePath } = options, gitignorePath = path.join(basePath, ".gitignore");
919
- let gitignore = await readFile$1(gitignorePath, "utf8").catch(errorToUndefined) ?? "";
920
- const value = ".workshop";
921
- gitignore.includes(value) || (gitignore += `
922
-
923
- ${value}`, await writeFile(gitignorePath, gitignore, { encoding: "utf8" }));
924
- }
925
- async function addDevDependencies(options) {
926
- const pkg2 = await getPackage(options), devDeps = sortKeys({
927
- ...pkg2.devDependencies,
928
- ...await devDependencies()
929
- }), newPkg = { ...pkg2 };
930
- newPkg.devDependencies = devDeps, await writePackageJsonDirect(newPkg, options), log.info("Updated devDependencies.");
931
- }
932
- async function devDependencies() {
933
- return resolveLatestVersions([
934
- "@sanity/ui-workshop",
935
- "@sanity/icons",
936
- "@sanity/ui",
937
- "react",
938
- "react-dom",
939
- "styled-components"
940
- ]);
941
- }
942
- const presets = [semverWorkflowPreset, renovatePreset, ui, uiWorkshop], presetNames = presets.map((p) => p?.name);
943
- function presetHelpList(padStart) {
944
- return presets.map((p) => `${"".padStart(padStart)}${p.name.padEnd(20)}${p.description}`).join(`
945
- `);
946
- }
947
- async function injectPresets(options) {
948
- if (options.flags.presetOnly && !options.flags.preset?.length)
949
- throw new Error("--preset-only, but no --preset [preset-name] was provided.");
950
- const applyPresets = presetsFromInput(options.flags.preset);
951
- for (const preset of applyPresets)
952
- await preset.apply(options);
953
- }
954
- function presetsFromInput(inputPresets) {
955
- if (!inputPresets)
956
- return [];
957
- const unknownPresets = inputPresets.filter((p) => !presetNames.includes(p));
958
- if (unknownPresets.length)
959
- throw new Error(
960
- `Unknown --preset(s): [${unknownPresets.join(", ")}]. Must be one of: [${presetNames.join(
961
- ", "
962
- )}]`
963
- );
964
- return inputPresets.filter(onlyUnique).map((presetName) => presets.find((p) => p.name === presetName)).filter((p) => !!p);
965
- }
966
- function onlyUnique(value, index, arr) {
967
- return arr.indexOf(value) === index;
968
- }
969
- const bannedFields = ["login", "description", "projecturl", "email"], preferredLicenses = ["MIT", "ISC", "BSD-3-Clause"], otherLicenses = Object.keys(licenses.list).filter((id) => {
970
- const license = licenses.list[id];
971
- return !preferredLicenses.includes(id) && !bannedFields.some((field) => license.body.includes(`[${field}]`));
972
- });
973
- async function inject(options) {
974
- options.flags.presetOnly ? log.info("Only apply presets, skipping default inject.") : await injectBase(options), await injectPresets(options);
975
- }
976
- async function injectBase(options) {
977
- const { basePath, flags, requireUserConfirmation } = options, info2 = (write, msg, ...args) => write && log.info(msg, ...args), pkg2 = await getPackage(options).catch(errorToUndefined);
978
- log.debug("Plugin has package.json: %s", pkg2 ? "yes" : "no");
979
- const user = await getUserInfo(options, pkg2);
980
- log.debug("User information: %o", user);
981
- const pkgName = flags.name ?? pkg2?.name, pluginName = requireUserConfirmation || !pkgName ? await promptForPackageName(options, pkgName) : pkgName;
982
- log.debug("Plugin name: %s", pluginName);
983
- const license = await getLicense(flags, { user, pluginName, pkg: pkg2, requireUserConfirmation }), licenseChanged = (pkg2 && pkg2.license) !== (license && license.id);
984
- log.debug("License: %s", license ? license.id : "<none>");
985
- const description = await getProjectDescription(basePath, pkg2, requireUserConfirmation);
986
- log.debug("Description: %s", description || "<none>");
987
- const repoUrl = flags.repo ?? (await gitRemoteOriginUrl(basePath).catch(errorToUndefined) || pkg2?.repository?.url), gitOrigin = requireUserConfirmation ? await promptForRepoOrigin(options, repoUrl) : repoUrl;
988
- log.debug("Remote origin: %s", gitOrigin || "<none>");
989
- const data = { user, pluginName, license, description, pkg: pkg2, gitOrigin };
990
- let didWrite;
991
- const newPkg = await writePackageJson(data, options);
992
- info2(newPkg !== pkg2, "Wrote package.json"), data.pkg = newPkg, didWrite = await writeLicense(data, options, licenseChanged), info2(didWrite, "Wrote license file (LICENSE)"), didWrite = await writeReadme(data, options), info2(didWrite, "Wrote readme file (README.md)"), didWrite = await writeStaticAssets(options), info2(didWrite.length > 0, "Wrote static asset files: %s", didWrite.join(", ")), didWrite = await addBuildScripts(newPkg, options), info2(didWrite, "Added build scripts to package.json"), didWrite = await addCompileDirToGitIgnore(options), info2(didWrite, "Added compilation output directory to .gitignore");
993
- }
994
- async function writeReadme(data, options) {
995
- const { basePath } = options, readmePath = path.join(basePath, "README.md"), readme = await readFile$1(readmePath, "utf8").catch(errorToUndefined);
996
- return readme && !isDefaultGitHubReadme(readme) ? !1 : (await writeFileWithOverwritePrompt(readmePath, generateReadme(data), {
997
- encoding: "utf8",
998
- force: options.flags.force
999
- }), !0);
1000
- }
1001
- async function writeLicense({ license }, options, licenseChanged) {
1002
- const { basePath, flags } = options;
1003
- if (flags.license === !1 || !license)
1004
- return !1;
1005
- const hasLicenseMdFile = await fileExists(path.join(basePath, "LICENSE.md")), licensePath = path.join(basePath, hasLicenseMdFile ? "LICENSE.md" : "LICENSE");
1006
- return await writeFileWithOverwritePrompt(licensePath, license.text, {
1007
- encoding: "utf8",
1008
- default: licenseChanged,
1009
- force: flags.force
1010
- }), !0;
1011
- }
1012
- async function getLicense(flags, {
1013
- user,
1014
- pluginName,
1015
- pkg: pkg2,
1016
- requireUserConfirmation
1017
- }) {
1018
- const license = await getLicenseIdentifier(flags, pkg2, requireUserConfirmation);
1019
- if (!license)
1020
- return;
1021
- const text = license.body.replace(/\[fullname\]/g, user?.name).replace(/\[project\]/g, pluginName).replace(/\[year\]/g, (/* @__PURE__ */ new Date()).getFullYear());
1022
- return { id: license.id, text };
1023
- }
1024
- async function getLicenseIdentifier(flags, pkg2, requireUserConfirmation = !1) {
1025
- if (flags.license === !1)
1026
- return null;
1027
- if (typeof flags.license == "string") {
1028
- const license = licenses.find(`${flags.license}`);
1029
- if (!license)
1030
- throw new Error(`License "${flags.license}" not found`);
1031
- return license;
1032
- }
1033
- if (pkg2 && pkg2.license && !requireUserConfirmation) {
1034
- const license = licenses.find(`${pkg2.license}`);
1035
- if (license)
1036
- return license;
1037
- log.warn(`package.json contains license "${pkg2.license}", which is not recognized`);
1038
- }
1039
- const licenseId = await prompt("Which license do you want to use?", {
1040
- default: pkg2 && pkg2.license && licenses.find(pkg2.license) ? pkg2.license : preferredLicenses[0],
1041
- choices: [
1042
- prompt.separator(),
1043
- ...preferredLicenses.map((value) => ({ value, name: licenses.list[value].title })),
1044
- prompt.separator(),
1045
- ...otherLicenses.map((value) => ({ value, name: licenses.list[value].title }))
1046
- ]
1047
- });
1048
- return licenses.find(licenseId);
1049
- }
1050
- async function getProjectDescription(basePath, pkg2, requireUserConfirmation = !1) {
1051
- let description = await resolveProjectDescription(basePath, pkg2);
1052
- return requireUserConfirmation && (description = await prompt("Plugin description", { default: description || "" })), description ?? "";
162
+ async function isEmptyish(dirPath) {
163
+ const ignoredFiles = [".git", ".gitignore", "license", "readme.md"];
164
+ return (await readdir(dirPath).catch(() => [])).filter((file) => !ignoredFiles.includes(file.toLowerCase())).length === 0;
1053
165
  }
1054
- async function resolveProjectDescription(basePath, pkg2) {
1055
- if (pkg2 && typeof pkg2.description == "string" && pkg2.description.length > 5)
1056
- return pkg2.description;
166
+ async function readFileContent({
167
+ filename,
168
+ basePath
169
+ }) {
170
+ const filepath = path.normalize(path.join(basePath, filename));
1057
171
  try {
1058
- const readmePath = path.join(basePath, "README.md"), readme = await readFile$1(readmePath, "utf8"), [title, description] = readme.split(`
1059
- `).filter(Boolean);
1060
- if (!title || !description || !title.match(/^#\s+\w+/))
1061
- return null;
1062
- const unlinked = description.replace(/\[(.*?)\]\(.*?\)/g, "$1");
1063
- return /^[^#]/.test(unlinked) ? unlinked : null;
172
+ return await readFile$2(filepath, "utf8");
1064
173
  } catch (err) {
1065
- return errorToUndefined(err);
1066
- }
1067
- }
1068
- async function writeAssets(injectables, { basePath, flags }) {
1069
- const assetsDir = await findAssetsDir(), from = (...segments) => path.join(assetsDir, "inject", ...segments), to = (...segments) => path.join(basePath, ...segments), writes = [];
1070
- for (const injectable of injectables) {
1071
- if (injectable.type === "copy") {
1072
- const fromPath = asArray(injectable.from), toPath = asArray(injectable.to);
1073
- await copyFileWithOverwritePrompt(from(...fromPath), to(...toPath), flags) && writes.push(path.join(...toPath));
1074
- continue;
1075
- }
1076
- if (injectable.type === "template") {
1077
- const toPath = asArray(injectable.to);
1078
- await writeFileWithOverwritePrompt(to(...toPath), `${injectable.value.trim()}
1079
- `, {
1080
- default: "n",
1081
- force: injectable.force || flags.force
1082
- }), writes.push(path.join(...toPath));
1083
- continue;
174
+ if (err.code === "ENOENT") {
175
+ log.debug(`No ${filename} file found.`);
176
+ return;
1084
177
  }
1085
- throw new Error(`Unknown operation type "${injectable.type}"`);
178
+ throw new Error(`Failed to read "${filepath}": ${err.message}`);
1086
179
  }
1087
- return writes;
1088
- }
1089
- async function writeStaticAssets(options) {
1090
- const { outDir, flags } = options, files2 = [
1091
- flags.eslint && eslintrcTemplate({ flags: options.flags }),
1092
- flags.eslint && eslintignoreTemplate({ outDir, flags: options.flags }),
1093
- { type: "copy", from: "editorconfig", to: ".editorconfig" },
1094
- { type: "copy", from: "sanity.json", to: "sanity.json" },
1095
- { type: "copy", from: "v2-incompatible.js.template", to: "v2-incompatible.js" },
1096
- pkgConfigTemplate({ outDir, flags: options.flags }),
1097
- flags.gitignore && gitignoreTemplate(),
1098
- flags.typescript && tsconfigTemplate({ flags: options.flags }),
1099
- flags.typescript && tsconfigTemplateDist({ outDir, flags: options.flags }),
1100
- flags.typescript && tsconfigTemplateSettings({ outDir, flags: options.flags }),
1101
- flags.prettier && prettierignoreTemplate({ outDir }),
1102
- flags.prettier && { type: "copy", from: "prettierrc.json", to: ".prettierrc" }
1103
- ].map((f) => f || void 0).filter((f) => !!f);
1104
- return writeAssets(files2, options);
1105
- }
1106
- function asArray(input) {
1107
- return typeof input == "string" ? [input] : input;
1108
- }
1109
- async function findAssetsDir() {
1110
- let maxBackpaddle = 3, currDir = path.dirname(fileURLToPath(import.meta.url)), assetsDir = "";
1111
- for (; !assetsDir && maxBackpaddle; ) {
1112
- currDir = path.join(currDir, "..");
1113
- const assets = path.join(currDir, "assets");
1114
- await fileExists(assets) ? assetsDir = assets : maxBackpaddle--;
180
+ }
181
+ async function readJson5File({
182
+ filename,
183
+ basePath
184
+ }) {
185
+ const content = await readFileContent({ filename, basePath });
186
+ if (content)
187
+ return parseJson5(content, filename);
188
+ }
189
+ function parseJson5(content, errorKey) {
190
+ try {
191
+ return json5.parse(content);
192
+ } catch (err) {
193
+ throw new Error(`Error parsing "${errorKey}": ${err.message}`);
1115
194
  }
1116
- if (!assetsDir)
1117
- throw new Error("Could not find assets directory!");
1118
- return assetsDir;
1119
- }
1120
- async function addCompileDirToGitIgnore(options) {
1121
- const gitIgnorePath = path.join(options.basePath, ".gitignore"), gitignore = await readFile$1(gitIgnorePath, "utf8").catch(errorToUndefined);
1122
- if (!gitignore)
1123
- return !1;
1124
- const ignore = options.outDir.replace(/^[./]+/, "").split("/")[0];
1125
- if (!ignore)
1126
- return !1;
1127
- const lines = gitignore.trim().split(`
1128
- `);
1129
- return lines.includes(ignore) ? !1 : (lines.push("", "# Compiled plugin", ignore), await writeFile(gitIgnorePath, lines.join(`
1130
- `) + `
1131
- `, { encoding: "utf8" }), !0);
1132
195
  }
1133
- const mergedPackages = [
1134
- "@sanity/base",
1135
- "@sanity/core",
1136
- "@sanity/types",
1137
- "@sanity/data-aspects",
1138
- "@sanity/default-layout",
1139
- "@sanity/default-login",
1140
- "@sanity/desk-tool",
1141
- "@sanity/field",
1142
- "@sanity/form-builder",
1143
- "@sanity/initial-value-templates",
1144
- "@sanity/language-filter",
1145
- "@sanity/production-preview",
1146
- "@sanity/react-hooks",
1147
- "@sanity/resolver",
1148
- "@sanity/state-router",
1149
- "@sanity/structure",
1150
- "@sanity/studio-hints"
1151
- ].sort(), deprecatedDevDeps = [
1152
- "tsdx",
1153
- "sanipack",
1154
- "parcel",
1155
- "@parcel/packager-ts",
1156
- "@parcel/transformer-typescript-types"
1157
- ], expectedScripts = {
196
+ const expectedScripts = {
1158
197
  build: "plugin-kit verify-package --silent && pkg-utils build --strict --check --clean",
1159
198
  watch: "pkg-utils watch --strict",
1160
199
  "link-watch": "plugin-kit link-watch",
@@ -1165,7 +204,7 @@ function filesWithSuffixes(fileBases, suffixes) {
1165
204
  }
1166
205
  function validateNodeEngine(packageJson) {
1167
206
  return packageJson.engines?.node !== requiredNodeEngine ? [
1168
- outdent$1`
207
+ outdent`
1169
208
  Expected package.json to contain engines.node: "${requiredNodeEngine}" to match @sanity/pkg-utils,
1170
209
  but it was: ${packageJson.engines?.node}
1171
210
 
@@ -1182,7 +221,7 @@ function validateScripts(packageJson) {
1182
221
  return !command || !command.includes(expectedCommand);
1183
222
  });
1184
223
  return divergentScripts.length && errors.push(
1185
- outdent$1`
224
+ outdent`
1186
225
  The following script commands did not contain expected defaults: ${divergentScripts.map(([key]) => key).join(", ")}
1187
226
 
1188
227
  This checks for that the commands-strings includes these terms.
@@ -1210,7 +249,7 @@ async function validateTsConfig(ts, options) {
1210
249
  const expectedOutput = wrongEntries.map(([key, value]) => `"${key}": ${typeof value == "string" ? `"${value}"` : value},`).join(`
1211
250
  `);
1212
251
  errors.push(
1213
- outdent$1`
252
+ outdent`
1214
253
  Recommended ${tsconfig} compilerOptions missing:
1215
254
 
1216
255
  The following fields had unexpected values: [${wrongEntries.map(([key]) => key).join(", ")}]
@@ -1225,7 +264,7 @@ async function validateTsConfig(ts, options) {
1225
264
  }
1226
265
  function validatePackageType({ type }) {
1227
266
  return type === "module" ? [] : [
1228
- outdent$1`
267
+ outdent`
1229
268
  package.json must set "type": "module" — plugins built with @sanity/plugin-kit are ESM-only.
1230
269
  Found: ${type ? `"type": "${type}"` : 'no "type" field (defaults to "commonjs")'}
1231
270
 
@@ -1235,9 +274,9 @@ function validatePackageType({ type }) {
1235
274
  `.trimStart()
1236
275
  ];
1237
276
  }
1238
- function validatePkgUtilsDependency({ devDependencies: devDependencies2 }) {
1239
- return devDependencies2?.["@sanity/pkg-utils"] ? [] : [
1240
- outdent$1`
277
+ function validatePkgUtilsDependency({ devDependencies }) {
278
+ return devDependencies?.["@sanity/pkg-utils"] ? [] : [
279
+ outdent`
1241
280
  package.json does not list @sanity/pkg-utils as a devDependency.
1242
281
  @sanity/pkg-utils replaced parcel as the recommended build tool in @sanity/plugin-kit 2.0.0
1243
282
 
@@ -1252,7 +291,7 @@ function validatePkgUtilsVersion({ basePath }) {
1252
291
  installedVersion = require2("@sanity/pkg-utils/package.json").version;
1253
292
  } catch {
1254
293
  return [
1255
- outdent$1`
294
+ outdent`
1256
295
  @sanity/pkg-utils is not installed.
1257
296
  plugin-kit loads package.config.ts through @sanity/pkg-utils (a peer dependency).
1258
297
 
@@ -1262,7 +301,7 @@ function validatePkgUtilsVersion({ basePath }) {
1262
301
  }
1263
302
  const major = Number.parseInt(installedVersion?.split(".")[0] ?? "", 10);
1264
303
  return !Number.isFinite(major) || major < minPkgUtilsMajor ? [
1265
- outdent$1`
304
+ outdent`
1266
305
  @sanity/pkg-utils ${installedVersion} is too old.
1267
306
  plugin-kit requires @sanity/pkg-utils >=${minPkgUtilsMajor} to load package.config.ts.
1268
307
 
@@ -1271,9 +310,9 @@ function validatePkgUtilsVersion({ basePath }) {
1271
310
  ] : [];
1272
311
  }
1273
312
  function validateSanityDependencies(packageJson) {
1274
- const { dependencies, devDependencies: devDependencies2, peerDependencies } = packageJson, allDependencies = { ...dependencies, ...devDependencies2, ...peerDependencies }, illegalDeps = Object.keys(allDependencies).filter((dep) => mergedPackages.includes(dep)), unique = [...new Set(illegalDeps).values()];
313
+ const { dependencies, devDependencies, peerDependencies } = packageJson, allDependencies = { ...dependencies, ...devDependencies, ...peerDependencies }, illegalDeps = Object.keys(allDependencies).filter((dep) => mergedPackages.includes(dep)), unique = [...new Set(illegalDeps).values()];
1275
314
  return unique.length ? [
1276
- outdent$1`
315
+ outdent`
1277
316
  package.json depends on "@sanity/*" packages that have moved into "sanity" package.
1278
317
 
1279
318
  The following dependencies should be replaced with "sanity":
@@ -1286,9 +325,9 @@ function validateSanityDependencies(packageJson) {
1286
325
  ] : [];
1287
326
  }
1288
327
  function validateDeprecatedDependencies(packageJson) {
1289
- const { dependencies, devDependencies: devDependencies2, peerDependencies } = packageJson, allDependencies = { ...dependencies, ...devDependencies2, ...peerDependencies }, illegalDeps = Object.keys(allDependencies).filter((dep) => deprecatedDevDeps.includes(dep)), unique = [...new Set(illegalDeps).values()];
328
+ const { dependencies, devDependencies, peerDependencies } = packageJson, allDependencies = { ...dependencies, ...devDependencies, ...peerDependencies }, illegalDeps = Object.keys(allDependencies).filter((dep) => deprecatedDevDeps.includes(dep)), unique = [...new Set(illegalDeps).values()];
1290
329
  return unique.length ? [
1291
- outdent$1`
330
+ outdent`
1292
331
  package.json contains deprecated dependencies that should be removed:
1293
332
  - ${unique.join(`
1294
333
  - `)}
@@ -1302,7 +341,7 @@ async function validateBabelConfig({ basePath }) {
1302
341
  await fileExists(filepath) && babelFiles.push(filename);
1303
342
  }
1304
343
  return babelFiles.length ? [
1305
- outdent$1`
344
+ outdent`
1306
345
  Found babel-config file: [${babelFiles.join(
1307
346
  ", "
1308
347
  )}]. When using default @sanity/plugin-kit build command,
@@ -1313,38 +352,38 @@ async function validateBabelConfig({ basePath }) {
1313
352
  ] : [];
1314
353
  }
1315
354
  async function validateStudioConfig({ basePath }) {
1316
- const suffixes = ["ts", "js", "tsx", "jsx"], filenames = filesWithSuffixes(["sanity.config", "sanity.cli"], suffixes), files2 = {};
355
+ const suffixes = ["ts", "js", "tsx", "jsx"], filenames = filesWithSuffixes(["sanity.config", "sanity.cli"], suffixes), files = {};
1317
356
  for (const filename of filenames) {
1318
357
  const filepath = path.normalize(path.join(basePath, filename));
1319
- files2[filename] = await fileExists(filepath);
358
+ files[filename] = await fileExists(filepath);
1320
359
  }
1321
- const sanityJson = await readJson5File({ basePath, filename: "sanity.json" }), hasConfigFile = (fileBase) => filesWithSuffixes([fileBase], suffixes).some((filename) => files2[filename]), hasCliConfig = hasConfigFile("sanity.cli"), hasStudioConfig = hasConfigFile("sanity.config"), errors = [];
360
+ const sanityJson = await readJson5File({ basePath, filename: "sanity.json" }), hasConfigFile = (fileBase) => filesWithSuffixes([fileBase], suffixes).some((filename) => files[filename]), hasCliConfig = hasConfigFile("sanity.cli"), hasStudioConfig = hasConfigFile("sanity.config"), errors = [];
1322
361
  if (sanityJson) {
1323
- const info2 = [
1324
- outdent$1`
362
+ const info = [
363
+ outdent`
1325
364
  Found sanity.json. This file is not used by Sanity Studio V3.
1326
365
 
1327
366
  Please consult the Studio V3 migration guide:
1328
367
  ${urls.migrationGuideStudio}
1329
368
  It will detail how to convert sanity.json to sanity.config.ts (or .js) and sanity.cli.ts (or .js) equivalents.
1330
369
  `.trimStart(),
1331
- sanityJson.plugins?.length && outdent$1`
370
+ sanityJson.plugins?.length && outdent`
1332
371
  For V3 versions and alternatives to V2 plugins, please refer to the Sanity Exchange:
1333
372
  ${urls.sanityExchange}
1334
373
  `.trimStart()
1335
374
  ].filter((s) => !!s);
1336
- errors.push(info2.join(`
375
+ errors.push(info.join(`
1337
376
 
1338
377
  `));
1339
378
  }
1340
379
  return hasCliConfig || errors.push(
1341
- outdent$1`
380
+ outdent`
1342
381
  sanity.cli.(${suffixes.join(
1343
382
  " | "
1344
383
  )}) missing. Please create a file named sanity.cli.ts with the following content:
1345
384
 
1346
385
  ${chalk.green(
1347
- outdent$1`
386
+ outdent`
1348
387
  import {createCliConfig} from 'sanity/cli'
1349
388
 
1350
389
  export default createCliConfig({
@@ -1360,13 +399,13 @@ async function validateStudioConfig({ basePath }) {
1360
399
  For more, see ${urls.migrationGuideStudio}
1361
400
  `.trimStart()
1362
401
  ), hasStudioConfig || errors.push(
1363
- outdent$1`
402
+ outdent`
1364
403
  sanity.config.(${suffixes.join(
1365
404
  " | "
1366
405
  )}) missing. At a minimum sanity.config.ts should contain:
1367
406
 
1368
407
  ${chalk.green(
1369
- outdent$1`
408
+ outdent`
1370
409
  import { defineConfig } from "sanity"
1371
410
  import { deskTool } from "sanity/desk"
1372
411
 
@@ -1416,13 +455,13 @@ async function validatePluginSanityJson({
1416
455
  hasSinglePart ? null : 'sanity.json should have exactly one entry in "parts", but did not.',
1417
456
  correctImplements ? null : `The part should implement ${expectedDefaults.parts[0].implements}, but did not.`,
1418
457
  firstPart?.path && !pathExists ? `The file in "path", ${firstPart?.path}, does not exist.` : null,
1419
- hasDependency ? null : outdent$1`
458
+ hasDependency ? null : outdent`
1420
459
  package.json should have ${incompatiblePluginPackage} as a dependency, but did not.
1421
460
  Install it with: npm install --save ${incompatiblePluginPackage}
1422
461
  `.trimStart()
1423
462
  ].filter((e) => !!e);
1424
463
  return [
1425
- outdent$1`
464
+ outdent`
1426
465
  Invalid sanity.json. It is used for compatibility checking in V2 studios:
1427
466
 
1428
467
  - ${errors.join(`
@@ -1451,7 +490,7 @@ async function validateSrcIndexFile(basePath) {
1451
490
  for (const indexFile of allowedIndexFiles)
1452
491
  hasIndex = hasIndex || await fileExists(indexFile);
1453
492
  return hasIndex ? [] : [
1454
- outdent$1`
493
+ outdent`
1455
494
  Expected one of [${paths.join(", ")}] to exist.
1456
495
 
1457
496
  @sanity/pkg-utils expects a non-jsx file to be the source entry-point for the plugin.
@@ -1463,21 +502,21 @@ async function disallowDuplicateConfig({
1463
502
  basePath,
1464
503
  pkgJson,
1465
504
  configKey,
1466
- files: files2
505
+ files
1467
506
  }) {
1468
507
  const found = [];
1469
- for (const file of files2) {
508
+ for (const file of files) {
1470
509
  const filePath = path.join(basePath, file);
1471
510
  await fileExists(filePath) && found.push(file);
1472
511
  }
1473
512
  return found.length > 1 ? [
1474
- outdent$1`
513
+ outdent`
1475
514
  Found multiple config files that serve the same purpose: [${found.join(", ")}].
1476
515
 
1477
516
  There should be at most one of these files. Delete the rest.
1478
517
  `
1479
518
  ] : found.length && pkgJson[configKey] ? [
1480
- outdent$1`
519
+ outdent`
1481
520
  package.json contains ${configKey}, but there also exists a config file that serves the same purpose.
1482
521
  Config file: ${found.join("")}]
1483
522
 
@@ -1519,6 +558,209 @@ async function disallowDuplicatePrettierConfig(basePath, pkgJson) {
1519
558
  ]
1520
559
  });
1521
560
  }
561
+ const forcedPackageVersions = {}, forcedDevPackageVersions = {}, forcedPeerPackageVersions = {
562
+ react: "^18",
563
+ "react-dom": "^18",
564
+ "@types/react": "^18",
565
+ "@types/react-dom": "^18",
566
+ sanity: "^3",
567
+ "styled-components": "^5.2"
568
+ };
569
+ function errorToUndefined(err) {
570
+ if (err instanceof TypeError)
571
+ throw err;
572
+ }
573
+ const stat = util.promisify(fs.stat), readFile$1 = util.promisify(fs.readFile), allowedPartProps = ["name", "implements", "path", "description"], disallowedPluginProps = ["api", "project", "plugins", "env"];
574
+ async function getPaths(options) {
575
+ const { basePath } = options, manifest = await readManifest(options);
576
+ return manifest.paths ? absolutifyPaths(manifest.paths, basePath) : null;
577
+ }
578
+ function absolutifyPaths(paths, basePath) {
579
+ const getPath = (relative) => relative ? path.resolve(path.join(basePath, relative)) : void 0;
580
+ return paths ? {
581
+ basePath,
582
+ compiled: getPath(paths.compiled),
583
+ source: getPath(paths.source)
584
+ } : { basePath };
585
+ }
586
+ async function readManifest(options) {
587
+ const { basePath, validate = !0 } = options, manifestPath = path.normalize(path.join(basePath, "sanity.json"));
588
+ let content;
589
+ try {
590
+ content = await readFile$1(manifestPath, "utf8");
591
+ } catch (err) {
592
+ throw err.code === "ENOENT" ? new Error(
593
+ `No sanity.json found. sanity.json is required for plugins to function. Use \`${pkg.binname} init\` for a new plugin, or create an empty \`sanity.json\` with an empty object (\`{}\`) for existing ones.`
594
+ ) : new Error(`Failed to read "${manifestPath}": ${err.message}`);
595
+ }
596
+ let parsed;
597
+ try {
598
+ parsed = JSON.parse(content);
599
+ } catch (err) {
600
+ throw new Error(`Error parsing "${manifestPath}": ${err.message}`);
601
+ }
602
+ return validate && await validateManifest(parsed, options), parsed;
603
+ }
604
+ async function validateManifest(manifest, opts) {
605
+ const options = { isPlugin: !0, ...opts };
606
+ if (!isObject$1(manifest))
607
+ throw new Error("Invalid sanity.json: Root must be an object");
608
+ if (options.isPlugin ? await validatePluginManifest(manifest, options) : validateProjectManifest(manifest), "root" in manifest && typeof manifest.root != "boolean")
609
+ throw new Error('Invalid sanity.json: "root" property must be a boolean if declared');
610
+ await validateParts(manifest, {
611
+ ...options,
612
+ paths: absolutifyPaths(manifest.paths, options.basePath)
613
+ });
614
+ }
615
+ function validateProjectManifest(manifest) {
616
+ if ("paths" in manifest)
617
+ throw new Error('Invalid sanity.json: "paths" property has no meaning in a project manifest');
618
+ }
619
+ async function validatePluginManifest(manifest, options) {
620
+ const disallowed = Object.keys(manifest).filter((key) => disallowedPluginProps.includes(key)).map((key) => `"${key}"`);
621
+ if (disallowed.length > 0) {
622
+ const plural = disallowed.length > 1 ? "s" : "", joined = disallowed.join(", ");
623
+ throw new Error(
624
+ `Invalid sanity.json: Key${plural} ${joined} ${plural ? "are" : "is"} not allowed in a plugin manifest`
625
+ );
626
+ }
627
+ if (manifest.root)
628
+ throw new Error('Invalid sanity.json: "root" cannot be truthy in a plugin manifest');
629
+ await validatePaths$1(manifest, options);
630
+ }
631
+ async function validatePaths$1(manifest, options) {
632
+ if (!("paths" in manifest))
633
+ return;
634
+ if (!isObject$1(manifest.paths))
635
+ throw new Error('Invalid sanity.json: "paths" must be an object if declared');
636
+ if (typeof manifest.paths.compiled != "string")
637
+ throw new Error(
638
+ 'Invalid sanity.json: "paths" must have a (string) "compiled" property if declared'
639
+ );
640
+ if (typeof manifest.paths.source != "string")
641
+ throw new Error(
642
+ 'Invalid sanity.json: "paths" must have a (string) "source" property if declared'
643
+ );
644
+ const sourcePath = path.resolve(options.basePath, manifest.paths.source);
645
+ let srcStats;
646
+ try {
647
+ srcStats = await stat(sourcePath);
648
+ } catch (err) {
649
+ if (err.code === "ENOENT")
650
+ throw new Error(`sanity.json references "source" path which does not exist: "${sourcePath}"`);
651
+ }
652
+ if (!srcStats?.isDirectory())
653
+ throw new Error(
654
+ `sanity.json references "source" path which is not a directory: "${sourcePath}"`
655
+ );
656
+ }
657
+ async function validateParts(manifest, options) {
658
+ if (!("parts" in manifest))
659
+ return;
660
+ if (!Array.isArray(manifest.parts))
661
+ throw new Error('Invalid sanity.json: "parts" must be an array if declared');
662
+ let i = 0;
663
+ for (const part of manifest.parts)
664
+ await validatePart(part, i, options), i++;
665
+ }
666
+ async function validatePart(part, index, options) {
667
+ if (!isObject$1(part))
668
+ throw new Error(`Invalid sanity.json: "parts[${index}]" must be an object`);
669
+ validateAllowedPartKeys(part, index), validatePartStringValues(part, index), validatePartNames(part, index, options), await validatePartFiles(part, index, options);
670
+ }
671
+ async function validatePartFiles(part, index, options) {
672
+ const { verifyCompiledParts, verifySourceParts, paths } = options;
673
+ if (!part?.path)
674
+ return;
675
+ const ext = path.extname(part.path);
676
+ if (paths?.source && ext && ext !== ".js" && buildExtensions.includes(ext))
677
+ throw new Error(
678
+ `Invalid sanity.json: Part path has extension which is not applicable after compiling. ${ext} becomes .js after compiling. Specify filename without extension (${path.basename(
679
+ part.path
680
+ )}) (parts[${index}])`
681
+ );
682
+ if (!verifySourceParts && !verifyCompiledParts)
683
+ return;
684
+ const [srcExists, outDirExists] = await Promise.all([
685
+ hasSourceFile(part.path, paths),
686
+ verifyCompiledParts && hasCompiledFile(part.path, paths)
687
+ ]);
688
+ if (!srcExists)
689
+ throw new Error(
690
+ `Invalid sanity.json: Part path references file that does not exist in source directory (${paths?.source || paths?.basePath}) (parts[${index}])`
691
+ );
692
+ if (verifyCompiledParts && !outDirExists)
693
+ throw new Error(
694
+ `Invalid sanity.json: Part path references file ("${part.path}") that does not exist in compiled directory (${paths?.compiled}) (parts[${index}])`
695
+ );
696
+ }
697
+ function validatePartNames(part, index, options) {
698
+ const pluginName = options.pluginName ? options.pluginName.replace(/^sanity-plugin-/, "") : "";
699
+ if (!part?.name || !part?.name?.startsWith(`part:${pluginName}/`))
700
+ throw new Error(
701
+ `Invalid sanity.json: "name" must be prefixed with "part:${pluginName}/" - got "${part?.name}" (parts[${index}])`
702
+ );
703
+ if (!part?.implements?.startsWith("part:"))
704
+ throw new Error(
705
+ `Invalid sanity.json: "implements" must be prefixed with "part:" - got "${part?.implements}" (parts[${index}])`
706
+ );
707
+ }
708
+ function validateAllowedPartKeys(part, index) {
709
+ const disallowed = Object.keys(part).filter((key) => !allowedPartProps.includes(key)).map((key) => `"${key}"`);
710
+ if (disallowed.length > 0) {
711
+ const plural = disallowed.length > 1 ? "s" : "", joined = disallowed.join(", ");
712
+ throw new Error(
713
+ `Invalid sanity.json: Key${plural} ${joined} ${plural ? "are" : "is"} not allowed in a part declaration (parts[${index}])`
714
+ );
715
+ }
716
+ }
717
+ function validatePartStringValues(part, index) {
718
+ const nonStrings = Object.keys(part).filter((key) => typeof part[key] != "string").map((key) => `"${key}"`);
719
+ if (nonStrings.length > 0) {
720
+ const plural = nonStrings.length > 1 ? "s" : "", joined = nonStrings.join(", ");
721
+ throw new Error(
722
+ `Invalid sanity.json: Key${plural} ${joined} should be of type string (parts[${index}])`
723
+ );
724
+ }
725
+ }
726
+ function isObject$1(obj) {
727
+ return !Array.isArray(obj) && obj !== null && typeof obj == "object";
728
+ }
729
+ async function hasSanityJson(basePath) {
730
+ const file = await readJsonFile(path.join(basePath, "sanity.json")).catch(
731
+ errorToUndefined
732
+ );
733
+ return { exists: !!file, isRoot: !!(file && file.root) };
734
+ }
735
+ async function findStudioV3Config(basePath) {
736
+ const jsFile = "sanity.config.js";
737
+ if (await fileExists(path.join(basePath, jsFile)))
738
+ return { v3ConfigFile: jsFile };
739
+ const tsFile = "sanity.config.ts";
740
+ return { v3ConfigFile: await fileExists(path.join(basePath, tsFile)) ? tsFile : void 0 };
741
+ }
742
+ const lockedDependencies = {
743
+ "styled-components": "^6.1",
744
+ eslint: "^8.57.0"
745
+ };
746
+ function resolveLatestVersions(packages) {
747
+ const versions = {};
748
+ for (const pkgName of packages)
749
+ versions[pkgName] = pkgName in lockedDependencies ? lockedDependencies[pkgName] : "latest";
750
+ return pProps(
751
+ versions,
752
+ async (range, pkgName) => {
753
+ const version = await getLatestVersion(pkgName, { range });
754
+ if (!version)
755
+ throw new Error(`Found no version for ${pkgName}`);
756
+ return rangeify(version);
757
+ },
758
+ { concurrency: 8 }
759
+ );
760
+ }
761
+ function rangeify(version) {
762
+ return `^${version}`;
763
+ }
1522
764
  const defaultDependencies = [incompatiblePluginPackage], defaultDevDependencies = [
1523
765
  "sanity",
1524
766
  // peer dependencies of `sanity`
@@ -1529,7 +771,7 @@ const defaultDependencies = [incompatiblePluginPackage], defaultDevDependencies
1529
771
  async function getPackage(opts) {
1530
772
  const options = { flags: {}, ...opts };
1531
773
  validateOptions(options);
1532
- const { basePath, validate: validate2 = !0 } = options, manifestPath = path.normalize(path.join(basePath, "package.json"));
774
+ const { basePath, validate = !0 } = options, manifestPath = path.normalize(path.join(basePath, "package.json"));
1533
775
  let content;
1534
776
  try {
1535
777
  content = await readFile(manifestPath, "utf8");
@@ -1546,7 +788,7 @@ async function getPackage(opts) {
1546
788
  }
1547
789
  if (!isObject(parsed))
1548
790
  throw new Error("Invalid package.json: Root must be an object");
1549
- return validate2 && await validatePackage(parsed, options), parsed;
791
+ return validate && await validatePackage(parsed, options), parsed;
1550
792
  }
1551
793
  async function validatePackage(manifest, opts) {
1552
794
  validateOptions(opts);
@@ -1635,7 +877,7 @@ async function writePackageJson(data, options) {
1635
877
  ...await resolveLatestVersions(defaultDependencies)
1636
878
  },
1637
879
  forcedPackageVersions
1638
- ), devDependencies2 = forceDependencyVersions(
880
+ ), devDependencies = forceDependencyVersions(
1639
881
  {
1640
882
  ...addDevDeps || {},
1641
883
  ...prev.devDependencies || {},
@@ -1649,8 +891,8 @@ async function writePackageJson(data, options) {
1649
891
  ...await resolveLatestVersions(defaultPeerDependencies)
1650
892
  },
1651
893
  forcedPeerPackageVersions
1652
- ), source = flags.typescript ? "./src/index.ts" : "./src/index.js", files2 = [outDir, "sanity.json", "src", "v2-incompatible.js"];
1653
- files2.sort();
894
+ ), source = flags.typescript ? "./src/index.ts" : "./src/index.js", files = [outDir, "sanity.json", "src", "v2-incompatible.js"];
895
+ files.sort();
1654
896
  const forcedOrder = {
1655
897
  name: pluginName,
1656
898
  version: prev.version ?? "1.0.0",
@@ -1670,10 +912,10 @@ async function writePackageJson(data, options) {
1670
912
  "./package.json": "./package.json"
1671
913
  },
1672
914
  ...flags.typescript ? { types: `./${outDir}/index.d.ts` } : {},
1673
- files: files2,
915
+ files,
1674
916
  scripts: { ...prev.scripts },
1675
917
  dependencies: sortKeys(dependencies),
1676
- devDependencies: sortKeys(devDependencies2),
918
+ devDependencies: sortKeys(devDependencies),
1677
919
  peerDependencies: sortKeys(peerDependencies),
1678
920
  engines: {
1679
921
  node: requiredNodeEngine
@@ -1728,19 +970,31 @@ function forceDependencyVersions(deps, versions = forcedPackageVersions) {
1728
970
  return Object.fromEntries(entries);
1729
971
  }
1730
972
  export {
973
+ addBuildScripts,
974
+ addPackageJsonScripts,
975
+ addScript,
976
+ copyFileWithOverwritePrompt,
1731
977
  disallowDuplicateEslintConfig,
1732
978
  disallowDuplicatePrettierConfig,
1733
979
  ensureDir,
980
+ errorToUndefined,
1734
981
  fileExists,
1735
982
  findStudioV3Config,
983
+ forceDependencyVersions,
984
+ forcedDevPackageVersions,
985
+ forcedPackageVersions,
1736
986
  getPackage,
1737
987
  hasSanityJson,
1738
- inject,
1739
988
  isEmptyish,
1740
989
  mergedPackages,
1741
990
  mkdir,
1742
- presetHelpList,
1743
991
  prompt,
992
+ promptForPackageName,
993
+ promptForRepoOrigin,
994
+ readFile$2 as readFile,
995
+ readJsonFile,
996
+ resolveLatestVersions,
997
+ sortKeys,
1744
998
  validateBabelConfig,
1745
999
  validateDeprecatedDependencies,
1746
1000
  validateNodeEngine,
@@ -1754,6 +1008,9 @@ export {
1754
1008
  validateSrcIndexFile,
1755
1009
  validateStudioConfig,
1756
1010
  validateTsConfig,
1757
- writeFile
1011
+ writeFile,
1012
+ writeFileWithOverwritePrompt,
1013
+ writePackageJson,
1014
+ writePackageJsonDirect
1758
1015
  };
1759
1016
  //# sourceMappingURL=package.js.map