@sanity/plugin-kit 0.0.1-studio-v3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +398 -0
  3. package/assets/splat/LICENSE +21 -0
  4. package/assets/splat/editorconfig +13 -0
  5. package/assets/splat/eslint.config.js +5 -0
  6. package/assets/splat/gitignore +55 -0
  7. package/assets/splat/npmignore +9 -0
  8. package/assets/splat/prettierrc.js +6 -0
  9. package/assets/splat/sanity.json +8 -0
  10. package/assets/splat/template-tsconfig.json +23 -0
  11. package/assets/splat/v2-incompatible.js.template +11 -0
  12. package/lib/package.json +127 -0
  13. package/lib/src/actions/init.d.ts +65 -0
  14. package/lib/src/actions/init.js +83 -0
  15. package/lib/src/actions/init.js.map +1 -0
  16. package/lib/src/actions/link-watch.d.ts +3 -0
  17. package/lib/src/actions/link-watch.js +69 -0
  18. package/lib/src/actions/link-watch.js.map +1 -0
  19. package/lib/src/actions/splat.d.ts +26 -0
  20. package/lib/src/actions/splat.js +296 -0
  21. package/lib/src/actions/splat.js.map +1 -0
  22. package/lib/src/actions/verify/types.d.ts +77 -0
  23. package/lib/src/actions/verify/types.js +3 -0
  24. package/lib/src/actions/verify/types.js.map +1 -0
  25. package/lib/src/actions/verify/validations.d.ts +28 -0
  26. package/lib/src/actions/verify/validations.js +379 -0
  27. package/lib/src/actions/verify/validations.js.map +1 -0
  28. package/lib/src/actions/verify/verify-common.d.ts +43 -0
  29. package/lib/src/actions/verify/verify-common.js +88 -0
  30. package/lib/src/actions/verify/verify-common.js.map +1 -0
  31. package/lib/src/actions/verify-package.d.ts +5 -0
  32. package/lib/src/actions/verify-package.js +72 -0
  33. package/lib/src/actions/verify-package.js.map +1 -0
  34. package/lib/src/actions/verify-studio.d.ts +5 -0
  35. package/lib/src/actions/verify-studio.js +55 -0
  36. package/lib/src/actions/verify-studio.js.map +1 -0
  37. package/lib/src/actions/verify.d.ts +0 -0
  38. package/lib/src/actions/verify.js +330 -0
  39. package/lib/src/actions/verify.js.map +1 -0
  40. package/lib/src/cli.d.ts +2 -0
  41. package/lib/src/cli.js +86 -0
  42. package/lib/src/cli.js.map +1 -0
  43. package/lib/src/cmds/index.d.ts +8 -0
  44. package/lib/src/cmds/index.js +12 -0
  45. package/lib/src/cmds/index.js.map +1 -0
  46. package/lib/src/cmds/init.d.ts +4 -0
  47. package/lib/src/cmds/init.js +90 -0
  48. package/lib/src/cmds/init.js.map +1 -0
  49. package/lib/src/cmds/link-watch.d.ts +4 -0
  50. package/lib/src/cmds/link-watch.js +49 -0
  51. package/lib/src/cmds/link-watch.js.map +1 -0
  52. package/lib/src/cmds/splat.d.ts +4 -0
  53. package/lib/src/cmds/splat.js +63 -0
  54. package/lib/src/cmds/splat.js.map +1 -0
  55. package/lib/src/cmds/verify-package.d.ts +4 -0
  56. package/lib/src/cmds/verify-package.js +38 -0
  57. package/lib/src/cmds/verify-package.js.map +1 -0
  58. package/lib/src/cmds/verify-studio.d.ts +4 -0
  59. package/lib/src/cmds/verify-studio.js +38 -0
  60. package/lib/src/cmds/verify-studio.js.map +1 -0
  61. package/lib/src/cmds/verify.d.ts +0 -0
  62. package/lib/src/cmds/verify.js +42 -0
  63. package/lib/src/cmds/verify.js.map +1 -0
  64. package/lib/src/cmds/version.d.ts +4 -0
  65. package/lib/src/cmds/version.js +55 -0
  66. package/lib/src/cmds/version.js.map +1 -0
  67. package/lib/src/configs/buildExtensions.d.ts +1 -0
  68. package/lib/src/configs/buildExtensions.js +5 -0
  69. package/lib/src/configs/buildExtensions.js.map +1 -0
  70. package/lib/src/configs/default-source.d.ts +3 -0
  71. package/lib/src/configs/default-source.js +70 -0
  72. package/lib/src/configs/default-source.js.map +1 -0
  73. package/lib/src/configs/merged-packages.d.ts +1 -0
  74. package/lib/src/configs/merged-packages.js +24 -0
  75. package/lib/src/configs/merged-packages.js.map +1 -0
  76. package/lib/src/configs/uselessFiles.d.ts +1 -0
  77. package/lib/src/configs/uselessFiles.js +33 -0
  78. package/lib/src/configs/uselessFiles.js.map +1 -0
  79. package/lib/src/constants.d.ts +11 -0
  80. package/lib/src/constants.js +15 -0
  81. package/lib/src/constants.js.map +1 -0
  82. package/lib/src/dependencies/find.d.ts +0 -0
  83. package/lib/src/dependencies/find.js +195 -0
  84. package/lib/src/dependencies/find.js.map +1 -0
  85. package/lib/src/dependencies/import-linter.d.ts +3 -0
  86. package/lib/src/dependencies/import-linter.js +112 -0
  87. package/lib/src/dependencies/import-linter.js.map +1 -0
  88. package/lib/src/index.d.ts +2 -0
  89. package/lib/src/index.js +6 -0
  90. package/lib/src/index.js.map +1 -0
  91. package/lib/src/npm/manager.d.ts +7 -0
  92. package/lib/src/npm/manager.js +62 -0
  93. package/lib/src/npm/manager.js.map +1 -0
  94. package/lib/src/npm/package.d.ts +8 -0
  95. package/lib/src/npm/package.js +288 -0
  96. package/lib/src/npm/package.js.map +1 -0
  97. package/lib/src/npm/publish.d.ts +1 -0
  98. package/lib/src/npm/publish.js +14 -0
  99. package/lib/src/npm/publish.js.map +1 -0
  100. package/lib/src/npm/resolveLatestVersions.d.ts +3 -0
  101. package/lib/src/npm/resolveLatestVersions.js +35 -0
  102. package/lib/src/npm/resolveLatestVersions.js.map +1 -0
  103. package/lib/src/sanity/manifest.d.ts +48 -0
  104. package/lib/src/sanity/manifest.js +263 -0
  105. package/lib/src/sanity/manifest.js.map +1 -0
  106. package/lib/src/sharedFlags.d.ts +15 -0
  107. package/lib/src/sharedFlags.js +17 -0
  108. package/lib/src/sharedFlags.js.map +1 -0
  109. package/lib/src/util/command-parser.d.ts +9 -0
  110. package/lib/src/util/command-parser.js +41 -0
  111. package/lib/src/util/command-parser.js.map +1 -0
  112. package/lib/src/util/errorToUndefined.d.ts +1 -0
  113. package/lib/src/util/errorToUndefined.js +11 -0
  114. package/lib/src/util/errorToUndefined.js.map +1 -0
  115. package/lib/src/util/files.d.ts +36 -0
  116. package/lib/src/util/files.js +253 -0
  117. package/lib/src/util/files.js.map +1 -0
  118. package/lib/src/util/log.d.ts +14 -0
  119. package/lib/src/util/log.js +36 -0
  120. package/lib/src/util/log.js.map +1 -0
  121. package/lib/src/util/prompt.d.ts +13 -0
  122. package/lib/src/util/prompt.js +75 -0
  123. package/lib/src/util/prompt.js.map +1 -0
  124. package/lib/src/util/readme.d.ts +5 -0
  125. package/lib/src/util/readme.js +73 -0
  126. package/lib/src/util/readme.js.map +1 -0
  127. package/lib/src/util/request.d.ts +1 -0
  128. package/lib/src/util/request.js +19 -0
  129. package/lib/src/util/request.js.map +1 -0
  130. package/lib/src/util/user.d.ts +10 -0
  131. package/lib/src/util/user.js +106 -0
  132. package/lib/src/util/user.js.map +1 -0
  133. package/lib/test/cli.test.d.ts +1 -0
  134. package/lib/test/cli.test.js +64 -0
  135. package/lib/test/cli.test.js.map +1 -0
  136. package/lib/test/fixture-utils.d.ts +25 -0
  137. package/lib/test/fixture-utils.js +67 -0
  138. package/lib/test/fixture-utils.js.map +1 -0
  139. package/lib/test/init-verify-build.test.d.ts +1 -0
  140. package/lib/test/init-verify-build.test.js +75 -0
  141. package/lib/test/init-verify-build.test.js.map +1 -0
  142. package/lib/test/init.test.d.ts +1 -0
  143. package/lib/test/init.test.js +137 -0
  144. package/lib/test/init.test.js.map +1 -0
  145. package/lib/test/run-test-command.d.ts +1 -0
  146. package/lib/test/run-test-command.js +6 -0
  147. package/lib/test/run-test-command.js.map +1 -0
  148. package/lib/test/verify-package.test.d.ts +1 -0
  149. package/lib/test/verify-package.test.js +81 -0
  150. package/lib/test/verify-package.test.js.map +1 -0
  151. package/lib/test/version.test.d.ts +1 -0
  152. package/lib/test/version.test.js +48 -0
  153. package/lib/test/version.test.js.map +1 -0
  154. package/package.json +127 -0
  155. package/src/actions/init.ts +104 -0
  156. package/src/actions/link-watch.ts +74 -0
  157. package/src/actions/splat.ts +366 -0
  158. package/src/actions/verify/types.ts +84 -0
  159. package/src/actions/verify/validations.ts +401 -0
  160. package/src/actions/verify/verify-common.ts +92 -0
  161. package/src/actions/verify-package.ts +87 -0
  162. package/src/actions/verify-studio.ts +55 -0
  163. package/src/actions/verify.ts +328 -0
  164. package/src/cli.ts +77 -0
  165. package/src/cmds/index.ts +9 -0
  166. package/src/cmds/init.ts +85 -0
  167. package/src/cmds/link-watch.ts +51 -0
  168. package/src/cmds/splat.ts +59 -0
  169. package/src/cmds/verify-package.ts +36 -0
  170. package/src/cmds/verify-studio.ts +36 -0
  171. package/src/cmds/verify.ts +40 -0
  172. package/src/cmds/version.ts +67 -0
  173. package/src/configs/buildExtensions.ts +1 -0
  174. package/src/configs/default-source.ts +68 -0
  175. package/src/configs/merged-packages.ts +20 -0
  176. package/src/configs/uselessFiles.ts +29 -0
  177. package/src/constants.ts +13 -0
  178. package/src/dependencies/find.ts +193 -0
  179. package/src/dependencies/import-linter.ts +103 -0
  180. package/src/index.ts +4 -0
  181. package/src/npm/manager.ts +44 -0
  182. package/src/npm/package.ts +370 -0
  183. package/src/npm/publish.ts +9 -0
  184. package/src/npm/resolveLatestVersions.ts +26 -0
  185. package/src/sanity/manifest.ts +340 -0
  186. package/src/sharedFlags.ts +14 -0
  187. package/src/util/command-parser.ts +31 -0
  188. package/src/util/errorToUndefined.ts +7 -0
  189. package/src/util/files.ts +249 -0
  190. package/src/util/log.ts +44 -0
  191. package/src/util/prompt.ts +70 -0
  192. package/src/util/readme.ts +72 -0
  193. package/src/util/request.ts +13 -0
  194. package/src/util/user.ts +110 -0
@@ -0,0 +1,370 @@
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+ import util from 'util'
4
+ // @ts-expect-error missing types
5
+ import githubUrl from 'github-url-to-object'
6
+ // @ts-expect-error missing types
7
+ import validateNpmPackageName from 'validate-npm-package-name'
8
+ import {getPaths, ManifestOptions} from '../sanity/manifest'
9
+ import {resolveLatestVersions} from './resolveLatestVersions'
10
+ import {hasSourceEquivalent, writeJsonFile} from '../util/files'
11
+ import log from '../util/log'
12
+ import {cliName} from '../constants'
13
+ import {PackageData, SplatOptions} from '../actions/splat'
14
+ import {expectedScripts} from '../actions/verify/validations'
15
+ import {PackageJson} from '../actions/verify/types'
16
+
17
+ const readFile = util.promisify(fs.readFile)
18
+
19
+ const pathKeys: (keyof PackageJson)[] = ['main', 'module', 'browser', 'types', 'typings']
20
+
21
+ export async function getPackage(opts: ManifestOptions): Promise<PackageJson> {
22
+ const options = {flags: {}, ...opts}
23
+
24
+ validateOptions(options)
25
+
26
+ const {basePath, validate = true} = options
27
+ const manifestPath = path.normalize(path.join(basePath, 'package.json'))
28
+
29
+ let content
30
+ try {
31
+ content = await readFile(manifestPath, 'utf8')
32
+ } catch (err: any) {
33
+ if (err.code === 'ENOENT') {
34
+ throw new Error(
35
+ `No package.json found. package.json is required to publish to npm. Use \`${cliName} init\` for a new plugin, or \`npm init\` for an existing one`
36
+ )
37
+ }
38
+
39
+ throw new Error(`Failed to read "${manifestPath}": ${err.message}`)
40
+ }
41
+
42
+ let parsed
43
+ try {
44
+ parsed = JSON.parse(content)
45
+ } catch (err: any) {
46
+ throw new Error(`Error parsing "${manifestPath}": ${err.message}`)
47
+ }
48
+
49
+ if (!isObject(parsed)) {
50
+ throw new Error(`Invalid package.json: Root must be an object`)
51
+ }
52
+
53
+ if (validate) {
54
+ await validatePackage(parsed, options)
55
+ }
56
+
57
+ return parsed
58
+ }
59
+
60
+ export async function validatePackage(manifest: PackageJson, opts: ManifestOptions) {
61
+ validateOptions(opts)
62
+
63
+ const options = {isPlugin: true, ...opts}
64
+
65
+ if (options.isPlugin) {
66
+ await validatePluginPackage(manifest, options)
67
+ }
68
+
69
+ validateLockFiles(options)
70
+ }
71
+
72
+ function validateOptions(opts: {basePath: string}) {
73
+ const options = opts || {}
74
+ if (!isObject(options)) {
75
+ throw new Error(`Options must be an object`)
76
+ }
77
+
78
+ if (typeof options.basePath !== 'string') {
79
+ throw new Error(`"options.basePath" must be a string (path to plugin base path)`)
80
+ }
81
+ }
82
+
83
+ async function validatePluginPackage(manifest: PackageJson, options: ManifestOptions) {
84
+ validatePackageName(manifest)
85
+ await validatePaths(manifest, options)
86
+ }
87
+
88
+ function validatePackageName(manifest: PackageJson) {
89
+ if (typeof manifest.name !== 'string') {
90
+ throw new Error(`Invalid package.json: "name" must be a string`)
91
+ }
92
+
93
+ const valid: {validForNewPackages?: boolean; errors: string[]} = validateNpmPackageName(
94
+ manifest.name
95
+ )
96
+ if (!valid.validForNewPackages) {
97
+ throw new Error(`Invalid package.json: "name" is invalid: ${valid.errors.join(', ')}`)
98
+ }
99
+
100
+ const isScoped = manifest.name[0] === '@'
101
+ if (!isScoped && !manifest.name.startsWith('sanity-plugin-')) {
102
+ throw new Error(
103
+ `Invalid package.json: "name" should be prefixed with "sanity-plugin-" (or scoped - @your-company/plugin-name)`
104
+ )
105
+ }
106
+ }
107
+
108
+ async function validatePaths(manifest: PackageJson, options: ManifestOptions) {
109
+ const paths = await getPaths({
110
+ ...options,
111
+ pluginName: manifest.name ?? 'unknown',
112
+ verifySourceParts: false,
113
+ verifyCompiledParts: false,
114
+ })
115
+
116
+ const abs = (file: string) =>
117
+ path.isAbsolute(file) ? file : path.resolve(path.join(options.basePath, file))
118
+
119
+ const exists = (file: string) => fs.existsSync(abs(file))
120
+ const willExist = (file: string) => paths && hasSourceEquivalent(abs(file), paths)
121
+ const withinSourceDir = (file: string) => paths?.source && abs(file).startsWith(paths.source)
122
+ const withinTargetDir = (file: string) => paths?.compiled && abs(file).startsWith(paths.compiled)
123
+
124
+ for (const key of pathKeys) {
125
+ if (!(key in manifest)) {
126
+ continue
127
+ }
128
+
129
+ const manifestValue = manifest[key]
130
+ if (typeof manifestValue !== 'string') {
131
+ throw new Error(`Invalid package.json: "${key}" must be a string if defined`)
132
+ }
133
+
134
+ // We don't want to reference `./src/MyComponent.js` containing a bunch of JSX and whatnot,
135
+ // instead we want to target `./lib/MyComponent.js` which is the location it'll be compiled to
136
+ if (!options?.flags?.allowSourceTarget && paths && withinSourceDir(manifestValue)) {
137
+ throw new Error(
138
+ `Invalid package.json: "${key}" points to file within source (uncompiled) directory. Use --allow-source-target if you really want to do this.`
139
+ )
140
+ }
141
+
142
+ // Does it exist only because it was there prior to compilation?
143
+ // We're clearing the folder on compilation, so we shouldn't allow it
144
+ const fileExists = exists(manifestValue)
145
+ if (
146
+ fileExists &&
147
+ paths &&
148
+ withinTargetDir(manifestValue) &&
149
+ !(await willExist(manifestValue))
150
+ ) {
151
+ throw new Error(
152
+ `Invalid package.json: "${key}" points to file that will not exist after compiling`
153
+ )
154
+ }
155
+
156
+ // If it _doesn't_ exist and it _won't_ exist, then there isn't much point in continuing, is there?
157
+ if (!exists(manifestValue) && !(await willExist(manifestValue))) {
158
+ if (!paths) {
159
+ throw new Error(`Invalid package.json: "${key}" points to file that does not exist`)
160
+ }
161
+
162
+ const inOutDir = paths.compiled && !abs(manifestValue).startsWith(paths.compiled)
163
+ throw new Error(
164
+ inOutDir
165
+ ? `Invalid package.json: "${key}" points to file that does not exist, and "paths" is not configured to compile to this location`
166
+ : `Invalid package.json: "${key}" points to file that does not exist, and no equivalent is found in source directory`
167
+ )
168
+ }
169
+ }
170
+ }
171
+
172
+ function isObject(obj: unknown): obj is Record<string, unknown> {
173
+ return !Array.isArray(obj) && obj !== null && typeof obj === 'object'
174
+ }
175
+
176
+ function validateLockFiles(options: {basePath: string}) {
177
+ const npm = fs.existsSync(path.join(options.basePath, 'package-lock.json'))
178
+ const yarn = fs.existsSync(path.join(options.basePath, 'yarn.lock'))
179
+ if (npm && yarn) {
180
+ throw new Error(`Invalid plugin: contains both package-lock.json and yarn.lock`)
181
+ }
182
+ }
183
+
184
+ export function getReferencedPaths(
185
+ packageJson: Record<string, string>,
186
+ basePath: string
187
+ ): string[] {
188
+ return pathKeys
189
+ .filter((key) => key in packageJson)
190
+ .map((key) =>
191
+ path.isAbsolute(packageJson[key])
192
+ ? packageJson[key]
193
+ : path.resolve(basePath, packageJson[key])
194
+ )
195
+ }
196
+
197
+ export async function writePackageJson(data: PackageData, options: SplatOptions) {
198
+ const {user, pluginName, license, description, pkg: prevPkg, gitOrigin} = data
199
+ const {peerDependencies: addPeers, dependencies: addDeps, devDependencies: addDevDeps} = options
200
+ const {basePath, flags} = options
201
+ const prev = prevPkg || {}
202
+
203
+ const usePrettier = flags.prettier !== false
204
+ const useEslint = flags.eslint !== false
205
+ const useTypescript = flags.eslint !== false
206
+
207
+ const newDevDependencies = [cliName, 'parcel']
208
+
209
+ if (useTypescript) {
210
+ log.debug('Using TypeScript. Adding to dev dependencies.')
211
+ newDevDependencies.push('typescript')
212
+ }
213
+
214
+ if (usePrettier) {
215
+ log.debug('Using prettier. Adding to dev dependencies.')
216
+ newDevDependencies.push('prettier')
217
+ }
218
+
219
+ if (useEslint) {
220
+ log.debug('Using eslint. Adding to dev dependencies.')
221
+
222
+ newDevDependencies.push(
223
+ 'eslint',
224
+ 'eslint-config-sanity',
225
+ 'eslint-plugin-react',
226
+ 'eslint-plugin-react-hooks'
227
+ )
228
+
229
+ if (usePrettier) {
230
+ newDevDependencies.push('eslint-config-prettier', 'eslint-plugin-prettier')
231
+ }
232
+
233
+ if (useTypescript) {
234
+ newDevDependencies.push('@typescript-eslint/eslint-plugin', '@typescript-eslint/parser')
235
+ }
236
+ }
237
+
238
+ log.debug('Resolving latest versions for %s', newDevDependencies.join(', '))
239
+ const dependencies = {...(prev.dependencies || {}), ...(addDeps || {})}
240
+ const devDependencies = {
241
+ ...(addDevDeps || {}),
242
+ ...(prev.devDependencies || {}),
243
+ ...(await resolveLatestVersions(newDevDependencies)),
244
+ }
245
+ const peerDependencies = {...(prev.peerDependencies || {}), ...(addPeers || {})}
246
+
247
+ const alwaysOnTop = {
248
+ name: pluginName,
249
+ version: prev.version ?? '1.0.0',
250
+ description: description || '',
251
+ author: user?.email ? `${user.name} <${user.email}>` : user?.name,
252
+ license: license ? license.id : 'UNLICENSE',
253
+ }
254
+
255
+ const manifest: PackageJson = {
256
+ ...alwaysOnTop,
257
+ source: flags.typescript ? './src/index.ts' : './src/index.js',
258
+ main: './lib/cjs/index.js',
259
+ module: './lib/esm/index.js',
260
+ types: './lib/types/index.d.ts',
261
+ exports: {
262
+ '.': {
263
+ require: './lib/cjs/index.js',
264
+ default: './lib/esm/index.js',
265
+ },
266
+ },
267
+ files: ['src', 'lib', 'v2-incompatible.js', 'sanity.json'],
268
+ scripts: {},
269
+ repository: {},
270
+ engines: {
271
+ node: '>=14.0.0',
272
+ },
273
+
274
+ // Use already configured values by default
275
+ ...(prev || {}),
276
+
277
+ // We're de-declaring properties because of key order in package.json
278
+ ...alwaysOnTop,
279
+ dependencies: sortKeys(dependencies),
280
+ devDependencies: sortKeys(devDependencies),
281
+ peerDependencies: sortKeys(peerDependencies),
282
+ /* eslint-enable no-dupe-keys */
283
+
284
+ ...repoFromOrigin(gitOrigin),
285
+ ...urlsFromOrigin(gitOrigin),
286
+ }
287
+
288
+ const differs = JSON.stringify(prev) !== JSON.stringify(manifest)
289
+ log.debug('Does manifest differ? %s', differs ? 'yes' : 'no')
290
+ if (differs) {
291
+ await writeJsonFile(path.join(basePath, 'package.json'), manifest)
292
+ }
293
+
294
+ return differs ? manifest : prev
295
+ }
296
+
297
+ function urlsFromOrigin(gitOrigin?: string): {bugs?: {url: string}; homepage?: string} {
298
+ const details: {user: string; repo: string} | undefined = githubUrl(gitOrigin)
299
+ if (!details) {
300
+ return {}
301
+ }
302
+
303
+ return {
304
+ bugs: {
305
+ url: `https://github.com/${details.user}/${details.repo}/issues`,
306
+ },
307
+ homepage: `https://github.com/${details.user}/${details.repo}#readme`,
308
+ }
309
+ }
310
+
311
+ function repoFromOrigin(gitOrigin?: string) {
312
+ if (!gitOrigin) {
313
+ return {}
314
+ }
315
+
316
+ return {
317
+ repository: {
318
+ type: 'git',
319
+ url: gitOrigin,
320
+ },
321
+ }
322
+ }
323
+
324
+ function withSanityKeywords(keywords: string[] = []) {
325
+ const newKeywords = new Set(keywords)
326
+ newKeywords.add('sanity')
327
+ newKeywords.add('sanity-plugin')
328
+ return Array.from(newKeywords)
329
+ }
330
+
331
+ function addScript(cmd: string, existing: string) {
332
+ if (existing && existing.includes(cmd)) {
333
+ return existing
334
+ }
335
+
336
+ return existing ? `${existing} && ${cmd}` : cmd
337
+ }
338
+
339
+ export async function addBuildScripts(manifest: PackageJson, {basePath, flags}: SplatOptions) {
340
+ if (!flags.scripts) {
341
+ return false
342
+ }
343
+ const originalScripts = manifest.scripts || {}
344
+ const scripts = {...originalScripts}
345
+ scripts.clean = addScript(`rimraf lib`, scripts.clean)
346
+ scripts.lint = addScript(`eslint .`, scripts.lint)
347
+ scripts.prebuild = addScript('npm run clean && ' + expectedScripts.prebuild, scripts.prebuild)
348
+ scripts.build = addScript(expectedScripts.build, scripts.build)
349
+ scripts.watch = addScript(expectedScripts.watch, scripts.watch)
350
+ scripts['link-watch'] = addScript(expectedScripts['link-watch'], scripts['link-watch'])
351
+ scripts.prepublishOnly = addScript(expectedScripts.prepublishOnly, scripts.prepublishOnly)
352
+
353
+ const differs = Object.keys(scripts).some((key) => scripts[key] !== originalScripts[key])
354
+
355
+ if (differs) {
356
+ await writeJsonFile(path.join(basePath, 'package.json'), {...manifest, scripts})
357
+ }
358
+
359
+ return differs
360
+ }
361
+
362
+ function sortKeys<T extends Record<string, unknown>>(unordered: T): T {
363
+ return Object.keys(unordered)
364
+ .sort()
365
+ .reduce((obj, key) => {
366
+ // @ts-expect-error this WILL work
367
+ obj[key] = unordered[key]
368
+ return obj
369
+ }, {} as T)
370
+ }
@@ -0,0 +1,9 @@
1
+ import path from 'path'
2
+ // @ts-expect-error missing types
3
+ import npmPacklist from 'npm-packlist'
4
+
5
+ export function getPublishableFiles(basePath: string) {
6
+ return npmPacklist({basePath}).then((files: string[]) =>
7
+ files.map((file) => path.normalize(file))
8
+ )
9
+ }
@@ -0,0 +1,26 @@
1
+ import pProps from 'p-props'
2
+ // @ts-expect-error missing types
3
+ import getLatestVersion from 'get-latest-version'
4
+
5
+ // We may want to lock certain dependencies to specific versions
6
+ const lockedDependencies: Record<string, string> = {}
7
+
8
+ export function resolveLatestVersions(packages: string[]) {
9
+ const versions: Record<string, string> = {}
10
+ for (const pkgName of packages) {
11
+ versions[pkgName] = pkgName in lockedDependencies ? lockedDependencies[pkgName] : 'latest'
12
+ }
13
+
14
+ return pProps(
15
+ versions,
16
+ async (range, pkgName) => {
17
+ const version: string = await getLatestVersion(pkgName, {range})
18
+ return rangeify(version)
19
+ },
20
+ {concurrency: 8}
21
+ )
22
+ }
23
+
24
+ function rangeify(version: string) {
25
+ return `^${version}`
26
+ }