sprawlify 0.0.90 → 0.0.92
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +239 -162
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from "commander";
|
|
3
|
-
import fsExtra from "fs-extra";
|
|
4
3
|
import path, { join } from "path";
|
|
5
|
-
import
|
|
6
|
-
import { z } from "zod";
|
|
4
|
+
import fsExtra from "fs-extra";
|
|
7
5
|
import { cyan, green, red, yellow } from "kleur/colors";
|
|
6
|
+
import { z } from "zod";
|
|
8
7
|
import { existsSync } from "fs";
|
|
8
|
+
import prompts from "prompts";
|
|
9
|
+
import dedent from "dedent";
|
|
9
10
|
//#region package.json
|
|
10
|
-
var version = "0.0.
|
|
11
|
+
var version = "0.0.92";
|
|
11
12
|
//#endregion
|
|
12
13
|
//#region src/utils/file-helper.ts
|
|
13
14
|
const FILE_BACKUP_SUFFIX = ".bak";
|
|
@@ -148,27 +149,6 @@ function clearRegistryContext() {
|
|
|
148
149
|
context.headers = {};
|
|
149
150
|
}
|
|
150
151
|
//#endregion
|
|
151
|
-
//#region src/preset/presets.ts
|
|
152
|
-
const PRESETS = {
|
|
153
|
-
clay: {
|
|
154
|
-
name: "Clay",
|
|
155
|
-
frameworks: ["react"]
|
|
156
|
-
},
|
|
157
|
-
monochrome: {
|
|
158
|
-
name: "Monochrome",
|
|
159
|
-
frameworks: [
|
|
160
|
-
"react",
|
|
161
|
-
"solid",
|
|
162
|
-
"svelte",
|
|
163
|
-
"vue"
|
|
164
|
-
]
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
//#endregion
|
|
168
|
-
//#region src/frameworks/index.ts
|
|
169
|
-
const FRAMEWORKS = {};
|
|
170
|
-
const METAFRAMEWORKS = {};
|
|
171
|
-
//#endregion
|
|
172
152
|
//#region src/utils/env-loader.ts
|
|
173
153
|
async function loadEnvFiles(cwd = process.cwd()) {
|
|
174
154
|
try {
|
|
@@ -191,7 +171,46 @@ async function loadEnvFiles(cwd = process.cwd()) {
|
|
|
191
171
|
}
|
|
192
172
|
}
|
|
193
173
|
//#endregion
|
|
194
|
-
//#region src/
|
|
174
|
+
//#region src/frameworks/index.ts
|
|
175
|
+
const FRAMEWORKS = {
|
|
176
|
+
react: { title: "React" },
|
|
177
|
+
solid: { title: "Solid" },
|
|
178
|
+
svelte: { title: "Svelte" },
|
|
179
|
+
vue: { title: "Vue" }
|
|
180
|
+
};
|
|
181
|
+
const METAFRAMEWORKS = {
|
|
182
|
+
next: {
|
|
183
|
+
title: "Next.js",
|
|
184
|
+
frameworks: ["react"]
|
|
185
|
+
},
|
|
186
|
+
nuxt: {
|
|
187
|
+
title: "Nuxt",
|
|
188
|
+
frameworks: ["vue"]
|
|
189
|
+
},
|
|
190
|
+
sveltekit: {
|
|
191
|
+
title: "SvelteKit",
|
|
192
|
+
frameworks: ["svelte"]
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
//#endregion
|
|
196
|
+
//#region src/preset/presets.ts
|
|
197
|
+
const PRESETS = {
|
|
198
|
+
clay: {
|
|
199
|
+
name: "Clay",
|
|
200
|
+
frameworks: ["react"]
|
|
201
|
+
},
|
|
202
|
+
monochrome: {
|
|
203
|
+
name: "Monochrome",
|
|
204
|
+
frameworks: [
|
|
205
|
+
"react",
|
|
206
|
+
"solid",
|
|
207
|
+
"svelte",
|
|
208
|
+
"vue"
|
|
209
|
+
]
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
//#endregion
|
|
213
|
+
//#region src/commands/init/options.ts
|
|
195
214
|
const initOptionsSchema = z.object({
|
|
196
215
|
cwd: z.string(),
|
|
197
216
|
name: z.string().optional(),
|
|
@@ -199,102 +218,200 @@ const initOptionsSchema = z.object({
|
|
|
199
218
|
components: z.array(z.string()).optional(),
|
|
200
219
|
yes: z.boolean(),
|
|
201
220
|
defaults: z.boolean(),
|
|
202
|
-
|
|
221
|
+
override: z.boolean(),
|
|
203
222
|
reinstall: z.boolean().optional(),
|
|
204
223
|
framework: z.string().optional(),
|
|
205
224
|
metaframework: z.string().optional()
|
|
206
225
|
});
|
|
207
|
-
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
226
|
+
function parseInitOptions(opts) {
|
|
227
|
+
const parsed = opts;
|
|
228
|
+
return initOptionsSchema.parse({
|
|
229
|
+
...parsed,
|
|
230
|
+
reinstall: parsed.reinstall,
|
|
231
|
+
cwd: path.resolve(String(parsed.cwd ?? process.cwd()))
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
function applyDefaultInitOptions(options) {
|
|
235
|
+
if (!options.defaults) return;
|
|
236
|
+
options.preset = options.preset || "monochrome";
|
|
237
|
+
options.framework = options.framework || "react";
|
|
238
|
+
options.reinstall = options.reinstall ?? false;
|
|
239
|
+
}
|
|
240
|
+
function validateExplicitOptions(options) {
|
|
241
|
+
if (options.preset && !(options.preset in PRESETS)) exitForInvalidOption("preset", options.preset, Object.keys(PRESETS));
|
|
242
|
+
if (options.framework && !(options.framework in FRAMEWORKS)) exitForInvalidOption("framework", options.framework, Object.keys(FRAMEWORKS));
|
|
243
|
+
if (options.metaframework && !(options.metaframework in METAFRAMEWORKS)) exitForInvalidOption("metaframework", options.metaframework, Object.keys(METAFRAMEWORKS));
|
|
244
|
+
}
|
|
245
|
+
function exitForInvalidOption(optionName, receivedValue, allowedValues) {
|
|
246
|
+
logger.error(`Invalid ${optionName}: ${highlighter.info(receivedValue)}. Available ${optionName}s: ${allowedValues.map((value) => highlighter.info(value)).join(", ")}.`);
|
|
247
|
+
logger.break();
|
|
248
|
+
process.exit(1);
|
|
249
|
+
}
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region src/commands/init/prompts.ts
|
|
252
|
+
async function promptForMissingSelections(options) {
|
|
253
|
+
if (!options.name) {
|
|
254
|
+
const { name } = await prompts({
|
|
255
|
+
type: "text",
|
|
256
|
+
name: "name",
|
|
257
|
+
message: "What is your project name?",
|
|
258
|
+
initial: "my-project",
|
|
259
|
+
validate: (value) => value.trim().length > 0 || "Project name is required."
|
|
260
|
+
});
|
|
261
|
+
if (!name) {
|
|
262
|
+
logger.error("Project name is required.");
|
|
263
|
+
process.exit(1);
|
|
242
264
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
options.preset = preset;
|
|
265
|
+
options.name = name;
|
|
266
|
+
}
|
|
267
|
+
if (!options.framework) {
|
|
268
|
+
const { framework } = await prompts({
|
|
269
|
+
type: "select",
|
|
270
|
+
name: "framework",
|
|
271
|
+
message: "Which framework would you like to use?",
|
|
272
|
+
choices: Object.keys(FRAMEWORKS).map((frameworkKey) => ({
|
|
273
|
+
title: FRAMEWORKS[frameworkKey].title,
|
|
274
|
+
value: frameworkKey
|
|
275
|
+
})),
|
|
276
|
+
initial: 0
|
|
277
|
+
});
|
|
278
|
+
if (!framework) {
|
|
279
|
+
logger.error("Framework selection is required.");
|
|
280
|
+
process.exit(1);
|
|
260
281
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
})
|
|
290
|
-
|
|
282
|
+
options.framework = framework;
|
|
283
|
+
}
|
|
284
|
+
if (!options.preset) {
|
|
285
|
+
const { preset } = await prompts({
|
|
286
|
+
type: "select",
|
|
287
|
+
name: "preset",
|
|
288
|
+
message: "Which preset would you like to use?",
|
|
289
|
+
choices: Object.entries(PRESETS).map(([key, preset]) => ({
|
|
290
|
+
title: preset.name,
|
|
291
|
+
value: key,
|
|
292
|
+
disabled: !preset.frameworks.includes(options.framework)
|
|
293
|
+
})),
|
|
294
|
+
initial: 0
|
|
295
|
+
});
|
|
296
|
+
if (!preset) {
|
|
297
|
+
logger.error("Preset selection is required.");
|
|
298
|
+
process.exit(1);
|
|
299
|
+
}
|
|
300
|
+
options.preset = preset;
|
|
301
|
+
}
|
|
302
|
+
if (!options.metaframework) {
|
|
303
|
+
const { metaframework } = await prompts({
|
|
304
|
+
type: "select",
|
|
305
|
+
name: "metaframework",
|
|
306
|
+
message: "Which metaframework would you like to use (optional)?",
|
|
307
|
+
choices: [{
|
|
308
|
+
title: "None",
|
|
309
|
+
value: "none"
|
|
310
|
+
}, ...Object.entries(METAFRAMEWORKS).filter(([_, meta]) => meta.frameworks.includes(options.framework)).map(([key, meta]) => ({
|
|
311
|
+
title: meta.title,
|
|
312
|
+
value: key
|
|
313
|
+
}))],
|
|
314
|
+
initial: 0
|
|
315
|
+
});
|
|
316
|
+
options.metaframework = metaframework === "none" ? void 0 : metaframework;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
async function ensureOverwriteAllowed(options) {
|
|
320
|
+
if (!fsExtra.existsSync(path.resolve(options.cwd, "components.json")) || options.override) return;
|
|
321
|
+
const { overwrite } = await prompts({
|
|
322
|
+
type: "confirm",
|
|
323
|
+
name: "overwrite",
|
|
324
|
+
message: `A ${highlighter.info("components.json")} file already exists. Would you like to overwrite it?`,
|
|
325
|
+
initial: false
|
|
326
|
+
});
|
|
327
|
+
if (!overwrite) {
|
|
328
|
+
logger.info(` To start over, remove the ${highlighter.info("components.json")} file and run ${highlighter.info("init")} again.`);
|
|
329
|
+
logger.break();
|
|
330
|
+
process.exit(1);
|
|
331
|
+
}
|
|
332
|
+
options.override = true;
|
|
333
|
+
}
|
|
334
|
+
//#endregion
|
|
335
|
+
//#region src/templates/create-template.ts
|
|
336
|
+
function createTemplate(config) {
|
|
337
|
+
return {
|
|
338
|
+
...config,
|
|
339
|
+
frameworks: config.frameworks || []
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
//#endregion
|
|
343
|
+
//#region src/templates/index.ts
|
|
344
|
+
const templates = {
|
|
345
|
+
react: createTemplate({ files: [{
|
|
346
|
+
path: "tsconfig.app.json",
|
|
347
|
+
content: dedent`{
|
|
348
|
+
"compilerOptions": {
|
|
349
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
350
|
+
"target": "ES2023",
|
|
351
|
+
"useDefineForClassFields": true,
|
|
352
|
+
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
|
353
|
+
"module": "ESNext",
|
|
354
|
+
"types": ["vite/client"],
|
|
355
|
+
"skipLibCheck": true,
|
|
356
|
+
/* Bundler mode */
|
|
357
|
+
"moduleResolution": "bundler",
|
|
358
|
+
"allowImportingTsExtensions": true,
|
|
359
|
+
"verbatimModuleSyntax": true,
|
|
360
|
+
"moduleDetection": "force",
|
|
361
|
+
"noEmit": true,
|
|
362
|
+
"jsx": "react-jsx",
|
|
363
|
+
/* Linting */
|
|
364
|
+
"strict": true,
|
|
365
|
+
"noUnusedLocals": true,
|
|
366
|
+
"noUnusedParameters": true,
|
|
367
|
+
"erasableSyntaxOnly": true,
|
|
368
|
+
"noFallthroughCasesInSwitch": true,
|
|
369
|
+
"noUncheckedSideEffectImports": true
|
|
370
|
+
},
|
|
371
|
+
"include": ["src"]
|
|
372
|
+
}
|
|
373
|
+
`
|
|
374
|
+
}, {
|
|
375
|
+
path: "tsconfig.json",
|
|
376
|
+
content: dedent`{
|
|
377
|
+
"files": [],
|
|
378
|
+
"references": [
|
|
379
|
+
{ "path": "./tsconfig.app.json" },
|
|
380
|
+
{ "path": "./tsconfig.node.json" }
|
|
381
|
+
]
|
|
382
|
+
}`
|
|
383
|
+
}] }),
|
|
384
|
+
solid: createTemplate({}),
|
|
385
|
+
svelte: createTemplate({}),
|
|
386
|
+
vue: createTemplate({})
|
|
387
|
+
};
|
|
388
|
+
//#endregion
|
|
389
|
+
//#region src/commands/init/run-init.ts
|
|
390
|
+
async function runInit(options) {
|
|
391
|
+
let cwd = options.cwd;
|
|
392
|
+
if (options.name && options.name !== ".") {
|
|
393
|
+
cwd = path.resolve(options.cwd, options.name);
|
|
394
|
+
await fsExtra.ensureDir(cwd);
|
|
395
|
+
options.cwd = cwd;
|
|
396
|
+
logger.info(`Using project directory: ${highlighter.info(options.name)}`);
|
|
397
|
+
}
|
|
398
|
+
const selectedTemplate = options.framework && options.framework in templates ? templates[options.framework] : void 0;
|
|
399
|
+
if (selectedTemplate?.files.length) for (const file of selectedTemplate.files) {
|
|
400
|
+
const targetPath = path.resolve(cwd, file.path);
|
|
401
|
+
if (fsExtra.existsSync(targetPath) && !options.override) {
|
|
402
|
+
logger.warn(`Skipping ${highlighter.info(file.path)} because it already exists. Use ${highlighter.info("--override")} to replace it.`);
|
|
403
|
+
continue;
|
|
291
404
|
}
|
|
405
|
+
await fsExtra.ensureDir(path.dirname(targetPath));
|
|
406
|
+
await fsExtra.writeFile(targetPath, file.content, "utf8");
|
|
407
|
+
logger.success(`Created ${highlighter.info(file.path)} template file.`);
|
|
292
408
|
}
|
|
293
|
-
|
|
409
|
+
const componentsJsonPath = path.resolve(cwd, "components.json");
|
|
410
|
+
logger.info("Starting project initialization...");
|
|
294
411
|
const config = {
|
|
295
412
|
$schema: "https://ui.primitives.com/schema.json",
|
|
296
|
-
framework: options.framework
|
|
297
|
-
preset: options.preset
|
|
413
|
+
framework: options.framework,
|
|
414
|
+
preset: options.preset,
|
|
298
415
|
metaframework: options.metaframework,
|
|
299
416
|
aliases: {
|
|
300
417
|
components: "@/components",
|
|
@@ -322,63 +439,23 @@ async function runInit(options) {
|
|
|
322
439
|
throw error;
|
|
323
440
|
}
|
|
324
441
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
process.on("exit", restoreBackupOnExit);
|
|
442
|
+
//#endregion
|
|
443
|
+
//#region src/commands/init.ts
|
|
444
|
+
const init = new Command().name("init").alias("create").description("initialize your project and install dependencies").argument("[components...]", "names, url or local path to component").option("-p, --preset <preset>", "the preset to use. (monochrome, clay)").option("-f, --framework <framework>", "the framework to use. (react, solid, svelte, vue)").option("--metaframework <metaframework>", "the metaframework to use. (next, react-router, nuxt, sveltekit)").option("-y, --yes", "skip confirmation prompt.", true).option("-d, --defaults", "use default configuration: --preset=monochrome --framework=react --metaframework=vanilla", false).option("-o, --override", "override existing configuration.", false).option("-c, --cwd <cwd>", "the working directory. defaults to the current directory.", process.cwd()).option("-n, --name <name>", "the name for the new project.").option("-s, --silent", "mute output.", false).option("--reinstall", "re-install existing UI components.").option("--no-reinstall", "do not re-install existing UI components.").action(async (components, opts) => {
|
|
329
445
|
try {
|
|
330
|
-
const options =
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
if (options.defaults) {
|
|
336
|
-
options.preset = options.preset || "monochrome";
|
|
337
|
-
options.framework = options.framework || "react";
|
|
338
|
-
options.reinstall = options.reinstall ?? false;
|
|
339
|
-
}
|
|
340
|
-
if (options.preset && !(options.preset in PRESETS)) {
|
|
341
|
-
logger.error(`Invalid preset: ${highlighter.info(options.preset)}. Available presets: ${Object.keys(PRESETS).map((f) => highlighter.info(f)).join(", ")}.`);
|
|
342
|
-
logger.break();
|
|
343
|
-
process.exit(1);
|
|
344
|
-
}
|
|
345
|
-
if (options.framework && !(options.framework in FRAMEWORKS)) {
|
|
346
|
-
logger.error(`Invalid framework: ${highlighter.info(options.framework)}. Available frameworks: ${Object.keys(FRAMEWORKS).map((f) => highlighter.info(f)).join(", ")}.`);
|
|
347
|
-
logger.break();
|
|
348
|
-
process.exit(1);
|
|
349
|
-
}
|
|
350
|
-
if (options.metaframework && !(options.metaframework in METAFRAMEWORKS)) {
|
|
351
|
-
logger.error(`Invalid metaframework: ${highlighter.info(options.metaframework)}. Available metaframeworks: ${Object.keys(METAFRAMEWORKS).map((f) => highlighter.info(f)).join(", ")}.`);
|
|
352
|
-
logger.break();
|
|
353
|
-
process.exit(1);
|
|
354
|
-
}
|
|
355
|
-
const cwd = options.cwd;
|
|
356
|
-
if (fsExtra.existsSync(path.resolve(cwd, "components.json")) && !options.force) {
|
|
357
|
-
const { overwrite } = await prompts({
|
|
358
|
-
type: "confirm",
|
|
359
|
-
name: "overwrite",
|
|
360
|
-
message: `A ${highlighter.info("components.json")} file already exists. Would you like to overwrite it?`,
|
|
361
|
-
initial: false
|
|
362
|
-
});
|
|
363
|
-
if (!overwrite) {
|
|
364
|
-
logger.info(` To start over, remove the ${highlighter.info("components.json")} file and run ${highlighter.info("init")} again.`);
|
|
365
|
-
logger.break();
|
|
366
|
-
process.exit(1);
|
|
367
|
-
}
|
|
368
|
-
options.force = true;
|
|
369
|
-
}
|
|
370
|
-
if (reinstallComponents.length) components = [...components, ...reinstallComponents];
|
|
446
|
+
const options = parseInitOptions(opts);
|
|
447
|
+
applyDefaultInitOptions(options);
|
|
448
|
+
validateExplicitOptions(options);
|
|
449
|
+
await promptForMissingSelections(options);
|
|
450
|
+
await ensureOverwriteAllowed(options);
|
|
371
451
|
options.components = components;
|
|
372
452
|
await loadEnvFiles(options.cwd);
|
|
373
453
|
await runInit(options);
|
|
374
454
|
logger.break();
|
|
375
|
-
logger.log(`Project initialization completed.\nYou may now add components.`);
|
|
376
|
-
|
|
377
|
-
deleteFileBackup(path.resolve(cwd, "components.json"));
|
|
455
|
+
logger.log(`Project initialization completed in ${highlighter.info(options.cwd)}.\nYou may now add components.`);
|
|
456
|
+
deleteFileBackup(path.resolve(options.cwd, "components.json"));
|
|
378
457
|
logger.break();
|
|
379
458
|
} catch (error) {
|
|
380
|
-
process.removeListener("exit", restoreBackupOnExit);
|
|
381
|
-
restoreBackupOnExit();
|
|
382
459
|
logger.break();
|
|
383
460
|
handleError(error);
|
|
384
461
|
} finally {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sprawlify",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.92",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A command-line interface for Sprawlify.",
|
|
6
6
|
"author": "sprawlify <npm@sprawlify.com>",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@dotenvx/dotenvx": "^1.55.1",
|
|
21
21
|
"commander": "^14.0.3",
|
|
22
|
+
"dedent": "^1.7.2",
|
|
22
23
|
"fs-extra": "^11.3.4",
|
|
23
24
|
"kleur": "^4.1.5",
|
|
24
25
|
"prompts": "^2.4.2",
|