create-arkstack 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,61 @@
1
+ [![Create Arkstack][i1]][l1]
2
+ [![Downloads][d1]][l1]
3
+
4
+ # About Create Arkstack
5
+
6
+ Scaffold new applications using any of the Arkstack templates and starter kits.
7
+
8
+ ## Starter kits
9
+
10
+ You can choose between one of the following official starter kits
11
+
12
+ - `express` : An Express.js app scaffolded with Tonelix's Arkstack
13
+ - `h3` : An H3.js app scaffolded with Tonelix's Arkstack
14
+ - More coming soon...
15
+
16
+ ## Usage
17
+
18
+ ```sh
19
+ # Using npm
20
+ npm init arkstack
21
+
22
+ # Using yarn
23
+ yarn create arkstack
24
+
25
+ # Using pnpm
26
+ pnpm create arkstack
27
+ ```
28
+
29
+ ## Options
30
+
31
+ ### `location`
32
+
33
+ You can pass the installation `location` directory as the first argument to the command. For example:
34
+
35
+ ```sh
36
+ npm init arkstack my-app
37
+ ```
38
+
39
+ or even
40
+
41
+ ```sh
42
+ npm init arkstack ./
43
+ ```
44
+
45
+ This argument is optional and the command will prompt you to enter the installation `location` if not provided.
46
+
47
+ ## Contributing
48
+
49
+ Thank you for considering contributing to the Arkstack framework! The [Contribution Guide](https://github.com/toneflix/arkstack/blob/main/CONTRIBUTING.md) can be found in the Arkstack documentation and will provide you with all the information you need to get started.
50
+
51
+ ## Security Vulnerabilities
52
+
53
+ If you discover a security vulnerability within Arkstack, please send an e-mail to Legacy via [oss@toneflix.net](mailto:oss@toneflix.net). All security vulnerabilities will be promptly addressed.
54
+
55
+ ## License
56
+
57
+ [MIT License](LICENSE).
58
+
59
+ [i1]: https://img.shields.io/npm/v/create-arkstack?style=flat-square&label=create-arkstack&color=%230970ce
60
+ [l1]: https://www.npmjs.com/package/create-arkstack
61
+ [d1]: https://img.shields.io/npm/dt/create-arkstack?style=flat-square&label=Downloads&link=https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fcreate-arkstack
package/bin/run.cjs ADDED
@@ -0,0 +1,421 @@
1
+ #!/usr/bin/env node
2
+ //#region rolldown:runtime
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+
24
+ //#endregion
25
+ let __h3ravel_musket = require("@h3ravel/musket");
26
+ __h3ravel_musket = __toESM(__h3ravel_musket);
27
+ let inquirer = require("inquirer");
28
+ inquirer = __toESM(inquirer);
29
+ let __inquirer_core = require("@inquirer/core");
30
+ __inquirer_core = __toESM(__inquirer_core);
31
+ let node_path = require("node:path");
32
+ node_path = __toESM(node_path);
33
+ let __h3ravel_support = require("@h3ravel/support");
34
+ __h3ravel_support = __toESM(__h3ravel_support);
35
+ let __h3ravel_shared = require("@h3ravel/shared");
36
+ __h3ravel_shared = __toESM(__h3ravel_shared);
37
+ let node_fs_promises = require("node:fs/promises");
38
+ node_fs_promises = __toESM(node_fs_promises);
39
+ let __antfu_install_pkg = require("@antfu/install-pkg");
40
+ __antfu_install_pkg = __toESM(__antfu_install_pkg);
41
+ let node_process = require("node:process");
42
+ node_process = __toESM(node_process);
43
+ let giget = require("giget");
44
+ giget = __toESM(giget);
45
+ let node_fs = require("node:fs");
46
+ node_fs = __toESM(node_fs);
47
+ let ora = require("ora");
48
+ ora = __toESM(ora);
49
+
50
+ //#region src/logo.ts
51
+ const altLogo = String.raw`%c
52
+ _ __ _ _
53
+ /_\ _ __ ___/ _\ |_ __ _ ___| | __
54
+ //_\\| '__/ __\ \| __/ _\ |/ __| |/ /
55
+ / _ \ | | (___\ \ || (_| | (__| <
56
+ \_/ \_/_| \___\__/\__\__,_|\___|_|\_\
57
+
58
+ `;
59
+
60
+ //#endregion
61
+ //#region src/templates.ts
62
+ /**
63
+ * List of first party templates
64
+ */
65
+ const templates = [
66
+ {
67
+ name: "Express Starter Kit",
68
+ alias: "express",
69
+ hint: "An Express application starter kit",
70
+ source: "github:toneflix/arkstack"
71
+ },
72
+ {
73
+ name: "Express Lean Starter Kit",
74
+ alias: "express-lean",
75
+ hint: "A minimal Express application starter kit",
76
+ source: "github:toneflix/arkstack",
77
+ lean: true,
78
+ baseAlias: "express"
79
+ },
80
+ {
81
+ name: "H3 Starter Kit",
82
+ alias: "h3",
83
+ hint: "A H3 application starter kit",
84
+ source: "github:toneflix/arkstack"
85
+ },
86
+ {
87
+ name: "H3 Lean Starter Kit",
88
+ alias: "h3-lean",
89
+ hint: "A minimal H3 application starter kit",
90
+ source: "github:toneflix/arkstack",
91
+ lean: true,
92
+ baseAlias: "h3"
93
+ }
94
+ ];
95
+ const dependencyTemplates = {
96
+ "@arkstack/common": "^0.1.4",
97
+ "@arkstack/console": "^0.1.4",
98
+ "@arkstack/contract": "^0.1.4",
99
+ "@arkstack/database": "^0.1.4",
100
+ "@arkstack/driver-express": "^0.1.4"
101
+ };
102
+
103
+ //#endregion
104
+ //#region src/actions.ts
105
+ var actions_default = class {
106
+ skipInstallation;
107
+ constructor(location, appName, description) {
108
+ this.location = location;
109
+ this.appName = appName;
110
+ this.description = description;
111
+ if (!this.location) this.location = (0, node_path.join)(process.cwd(), ".temp");
112
+ }
113
+ async pm() {
114
+ return await (0, __antfu_install_pkg.detectPackageManager)() ?? "npm";
115
+ }
116
+ async runCmd(npx = false) {
117
+ if (npx) return "npx";
118
+ const pm = await this.pm();
119
+ return pm === "npm" ? "npm run" : pm;
120
+ }
121
+ async download(template, install = false, auth, overwrite = false) {
122
+ if (this.location?.includes(".temp") || overwrite && (0, node_fs.existsSync)(this.location)) await (0, node_fs_promises.rm)(this.location, {
123
+ force: true,
124
+ recursive: true
125
+ });
126
+ else if ((0, node_fs.existsSync)(this.location)) {
127
+ console.log("\n");
128
+ __h3ravel_shared.Logger.parse([
129
+ [" ERROR ", "bgRed"],
130
+ [this.location, ["gray", "italic"]],
131
+ ["is not empty.", "white"]
132
+ ], " ");
133
+ console.log("");
134
+ process.exit(0);
135
+ }
136
+ this.skipInstallation = !install;
137
+ this.removeLockFile();
138
+ return await (0, giget.downloadTemplate)(template, {
139
+ dir: this.location,
140
+ auth,
141
+ install,
142
+ registry: await this.pm(),
143
+ forceClean: false
144
+ });
145
+ }
146
+ async installPackage(name) {
147
+ await (0, __antfu_install_pkg.installPackage)(name, {
148
+ cwd: this.location,
149
+ silent: true
150
+ });
151
+ }
152
+ async complete(installed = false) {
153
+ console.log("");
154
+ const installPath = "./" + (0, node_path.relative)(process.cwd(), this.location);
155
+ try {
156
+ (0, node_process.chdir)(node_path.default.join(process.cwd(), installPath));
157
+ } catch {}
158
+ __h3ravel_shared.Logger.success("Your Arkstack project has been created successfully");
159
+ __h3ravel_shared.Logger.parse([
160
+ ["cd", "cyan"],
161
+ [installPath, "yellow"],
162
+ installPath === process.cwd() ? ["✔", "green"] : ["", "green"]
163
+ ], " ");
164
+ if (!installed) __h3ravel_shared.Logger.parse([[await __h3ravel_shared.Resolver.getPakageInstallCommand(), "cyan"]]);
165
+ __h3ravel_shared.Logger.parse([[await this.runCmd(), "cyan"], ["dev", "yellow"]], " ");
166
+ __h3ravel_shared.Logger.parse([["Open", "cyan"], ["http://localhost:3000", "yellow"]]);
167
+ console.log("");
168
+ __h3ravel_shared.Logger.parse([["Have any questions", "white"]]);
169
+ __h3ravel_shared.Logger.parse([["Checkout our other projects -", "white"], ["https://toneflix.net/open-source", "yellow"]]);
170
+ }
171
+ async cleanup() {
172
+ const pkgPath = (0, node_path.join)(this.location, "package.json");
173
+ const pkg = await (0, node_fs_promises.readFile)(pkgPath, "utf-8").then(JSON.parse);
174
+ delete pkg.packageManager;
175
+ delete pkg.scripts.predev;
176
+ delete pkg.scripts.prebuild;
177
+ delete pkg.scripts.precmd;
178
+ delete pkg.scripts.build;
179
+ delete pkg.scripts.dev;
180
+ pkg.name = __h3ravel_support.Str.slugify(this.appName ?? (0, node_path.basename)(this.location).replace(".", ""), "-");
181
+ if (this.description) pkg.description = this.description;
182
+ for (const [name, version] of Object.entries(dependencyTemplates)) pkg.dependencies[name] = version;
183
+ await Promise.allSettled([
184
+ (0, node_fs_promises.writeFile)(pkgPath, JSON.stringify(pkg, null, 2)),
185
+ this.removeLockFile(),
186
+ (0, node_fs_promises.rm)((0, node_path.join)(this.location, "pnpm-workspace.yaml"), { force: true }),
187
+ (0, node_fs_promises.rm)((0, node_path.join)(this.location, ".github"), {
188
+ force: true,
189
+ recursive: true
190
+ })
191
+ ]);
192
+ }
193
+ async removeLockFile() {
194
+ if (!this.skipInstallation) return;
195
+ await Promise.allSettled([
196
+ (0, node_fs_promises.unlink)((0, node_path.join)(this.location, "package-lock.json")),
197
+ (0, node_fs_promises.unlink)((0, node_path.join)(this.location, "yarn.lock")),
198
+ (0, node_fs_promises.unlink)((0, node_path.join)(this.location, "pnpm-lock.yaml"))
199
+ ]);
200
+ }
201
+ async getBanner() {
202
+ return await (0, node_fs_promises.readFile)((0, node_path.join)(process.cwd(), "./logo.txt"), "utf-8");
203
+ }
204
+ async copyExampleEnv() {
205
+ const envPath = (0, node_path.join)(this.location, ".env");
206
+ const exampleEnvPath = (0, node_path.join)(this.location, ".env.example");
207
+ if ((0, node_fs.existsSync)(exampleEnvPath)) await (0, node_fs_promises.copyFile)(exampleEnvPath, envPath);
208
+ }
209
+ async makeLeanProfile(_kit) {
210
+ await Promise.allSettled([
211
+ "src/app",
212
+ "src/routes/api.ts",
213
+ "src/core/database.ts",
214
+ "prisma",
215
+ "prisma.config.ts"
216
+ ].map((file) => (0, node_fs_promises.rm)((0, node_path.join)(this.location, file), {
217
+ force: true,
218
+ recursive: true
219
+ })));
220
+ const pkgPath = (0, node_path.join)(this.location, "package.json");
221
+ if ((0, node_fs.existsSync)(pkgPath)) {
222
+ const pkg = await (0, node_fs_promises.readFile)(pkgPath, "utf-8").then(JSON.parse);
223
+ for (const dep of [
224
+ "@arkstack/database",
225
+ "@prisma/adapter-pg",
226
+ "@prisma/client",
227
+ "pg",
228
+ "prisma",
229
+ "@types/pg"
230
+ ]) {
231
+ delete pkg.dependencies?.[dep];
232
+ delete pkg.devDependencies?.[dep];
233
+ }
234
+ await (0, node_fs_promises.writeFile)(pkgPath, JSON.stringify(pkg, null, 2));
235
+ }
236
+ for (const file of ["src/core/app.ts", "src/core/utils/request-handlers.ts"]) {
237
+ const filePath = (0, node_path.join)(this.location, file);
238
+ if (!(0, node_fs.existsSync)(filePath)) continue;
239
+ let content = await (0, node_fs_promises.readFile)(filePath, "utf-8");
240
+ content = content.replace("import { prisma } from \"src/core/database\";\n", "").replace("import { Prisma } from \"@prisma/client\";\n", "").replace(" async shutdown () {\n await prisma.$disconnect();\n process.exit(0);\n }", " async shutdown () {\n process.exit(0);\n }").replace(" * Shuts down the application by disconnecting from the database and exiting the process.", " * Shuts down the application and exits the process.").replace(/\n\s*if \((?:err|cause) instanceof Prisma\.PrismaClientKnownRequestError && (?:err|cause)\.code === "P2025"\) \{\n\s*error\.code = 404;\n\s*error\.message = `\$\{(?:err|cause)\.meta\?\.modelName\} not found!`;\n\s*\}\n/g, "\n");
241
+ await (0, node_fs_promises.writeFile)(filePath, content, "utf-8");
242
+ }
243
+ }
244
+ };
245
+
246
+ //#endregion
247
+ //#region src/utils.ts
248
+ /**
249
+ * Removes all files in dirPath except the one specified by keepFileName
250
+ *
251
+ * @param dirPath
252
+ * @param keepFileName
253
+ */
254
+ async function cleanDirectoryExcept(dirPath, keepFileName) {
255
+ const files = await (0, node_fs_promises.readdir)(dirPath);
256
+ for (const file of files) {
257
+ if (file === keepFileName) continue;
258
+ await (0, node_fs_promises.rm)(node_path.default.join(dirPath, file), {
259
+ recursive: true,
260
+ force: true
261
+ });
262
+ }
263
+ }
264
+ /**
265
+ * Moves all files from dirPath to parent directory and removes dirPath
266
+ *
267
+ * @param dirPath
268
+ * @param parent
269
+ */
270
+ async function hoistDirectoryContents(parent, dirPath) {
271
+ const source = node_path.default.isAbsolute(dirPath) ? dirPath : node_path.default.join(process.cwd(), dirPath);
272
+ const targetParent = node_path.default.isAbsolute(parent) ? parent : node_path.default.join(process.cwd(), parent);
273
+ if (!source.startsWith(targetParent)) throw new Error("Source must be inside the parent directory");
274
+ const entries = await (0, node_fs_promises.readdir)(source);
275
+ for (const entry of entries) await (0, node_fs_promises.rename)(node_path.default.join(source, entry), node_path.default.join(targetParent, entry));
276
+ await (0, node_fs_promises.rm)(source, { recursive: true });
277
+ }
278
+
279
+ //#endregion
280
+ //#region src/Commands/CreateArkstackCommand.ts
281
+ var CreateArkstackCommand = class extends __h3ravel_musket.Command {
282
+ signature = `create-arkstack
283
+ {location?: The location where this project should be created relative to the current dir.}
284
+ {--n|name?: The name of your project.}
285
+ {--i|install: Install node_modules right away}
286
+ {--t|token?: Kit repo authentication token.}
287
+ {--d|desc?: Project Description.}
288
+ {--k|kit?: Starter template kit.}
289
+ {--p|pre: Download prerelease version if available.}
290
+ {--o|overwrite: Overwrite the installation directory if it is not empty.}
291
+ `;
292
+ description = "Display a personalized greeting.";
293
+ async handle() {
294
+ const options = this.options();
295
+ const pathName = this.argument("location");
296
+ console.log(altLogo, `font-family: monospace`);
297
+ let { template } = await inquirer.default.prompt([{
298
+ type: "list",
299
+ name: "template",
300
+ message: "Choose starter template kit:",
301
+ choices: templates.map((e) => ({
302
+ name: e.name,
303
+ value: e.alias,
304
+ disabled: !e.source ? "(Unavailable at this time)" : false
305
+ })),
306
+ default: "full",
307
+ when: () => !options.kit
308
+ }]).catch((err) => {
309
+ if (err instanceof __inquirer_core.AbortPromptError || err instanceof __inquirer_core.ExitPromptError) {
310
+ this.info("Thanks for trying out our starter kit.");
311
+ process.exit(0);
312
+ }
313
+ return err;
314
+ });
315
+ let { appName, description } = await inquirer.default.prompt([{
316
+ type: "input",
317
+ name: "appName",
318
+ message: "What is the name of your project:",
319
+ default: `arkstack-${template}`,
320
+ when: () => !options.name
321
+ }, {
322
+ type: "input",
323
+ name: "description",
324
+ message: "Project Description:",
325
+ default: `Simple ${__h3ravel_support.Str.of(template).ucfirst()}.js project created with Arkstack.`,
326
+ when: () => !options.desc
327
+ }]).catch((err) => {
328
+ if (err instanceof __inquirer_core.AbortPromptError || err instanceof __inquirer_core.ExitPromptError) {
329
+ this.info("Thanks for trying out our starter kit.");
330
+ process.exit(0);
331
+ }
332
+ return err;
333
+ });
334
+ let { location } = await inquirer.default.prompt([{
335
+ type: "input",
336
+ name: "location",
337
+ message: "Installation location relative to the current dir:",
338
+ default: __h3ravel_support.Str.slugify(options.name ?? appName ?? (0, node_path.basename)(process.cwd()), "-"),
339
+ when: () => !pathName
340
+ }]).catch((err) => {
341
+ if (err instanceof __inquirer_core.AbortPromptError || err instanceof __inquirer_core.ExitPromptError) {
342
+ this.info("Thanks for trying out our starter kit.");
343
+ process.exit(0);
344
+ }
345
+ return err;
346
+ });
347
+ /**
348
+ * Find selected template kit
349
+ */
350
+ const kit = templates.find((e) => e.alias === template);
351
+ let { install, token, pre } = await inquirer.default.prompt([
352
+ {
353
+ type: "confirm",
354
+ name: "pre",
355
+ message: `An alpha version of the ${kit.name.replace(/\s*kit$/i, "").trim()} kit is available. Would you like to use it instead?`,
356
+ default: false,
357
+ when: () => kit.prereleaseSource && !options.pre
358
+ },
359
+ {
360
+ type: "input",
361
+ name: "token",
362
+ message: "Authentication token:",
363
+ when: () => options.kit && !options.token
364
+ },
365
+ {
366
+ type: "confirm",
367
+ name: "install",
368
+ message: "Would you want to install node_modules right away:",
369
+ default: true,
370
+ when: () => !options.install
371
+ }
372
+ ]).catch((err) => {
373
+ if (err instanceof __inquirer_core.AbortPromptError || err instanceof __inquirer_core.ExitPromptError) {
374
+ this.info("Thanks for trying out our starter kit.");
375
+ process.exit(0);
376
+ }
377
+ return err;
378
+ });
379
+ pre = options.pre ?? pre;
380
+ token = options.token ?? token;
381
+ appName = options.name ?? appName;
382
+ install = options.install ?? install;
383
+ template = options.kit ?? template;
384
+ location = pathName ?? location;
385
+ description = options.description ?? description;
386
+ /**
387
+ * Validate selected kit
388
+ */
389
+ if (kit && !kit.source) {
390
+ this.error(`ERROR: The ${kit.name} kit is not currently available`);
391
+ process.exit(1);
392
+ }
393
+ const source = pre && kit.prereleaseSource ? kit.prereleaseSource : kit.source;
394
+ const selectedAlias = (kit.baseAlias ?? kit.alias).replace(/-lean$/i, "");
395
+ const actions = new actions_default((0, node_path.join)(process.cwd(), location), appName, description);
396
+ const spinner = (0, ora.default)(`Loading Template...`).start();
397
+ const result = await actions.download(source, install, token, options.overwrite);
398
+ if (result.dir && selectedAlias) {
399
+ await cleanDirectoryExcept(result.dir, selectedAlias);
400
+ await hoistDirectoryContents(result.dir, (0, node_path.join)(result.dir, selectedAlias));
401
+ }
402
+ if (kit.lean) {
403
+ spinner.info(__h3ravel_shared.Logger.parse([["Applying lean profile...", "green"]], "", false)).start();
404
+ await actions.makeLeanProfile(selectedAlias);
405
+ }
406
+ spinner.info(__h3ravel_shared.Logger.parse([["Cleaning Up...", "green"]], "", false)).start();
407
+ await actions.cleanup();
408
+ spinner.info(__h3ravel_shared.Logger.parse([["Initializing Project...", "green"]], "", false)).start();
409
+ await actions.copyExampleEnv();
410
+ spinner.succeed(__h3ravel_shared.Logger.parse([["Project initialization complete!", "green"]], "", false));
411
+ await actions.complete(install);
412
+ }
413
+ };
414
+
415
+ //#endregion
416
+ //#region src/run.ts
417
+ var Application = class {};
418
+ __h3ravel_musket.Kernel.init(new Application(), { rootCommand: CreateArkstackCommand });
419
+
420
+ //#endregion
421
+ //# sourceMappingURL=run.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.cjs","names":["templates: {\n name: string;\n alias: \"express\" | \"h3\" | \"express-lean\" | \"h3-lean\";\n hint: string;\n source: string;\n lean?: boolean;\n baseAlias?: \"express\" | \"h3\";\n prereleaseSource?: string;\n}[]","location?: string","appName?: string","description?: string","path","Resolver","Str","path","Command","AbortPromptError","ExitPromptError","Str","source: string","Actions","Logger","Kernel"],"sources":["../src/logo.ts","../src/templates.ts","../src/actions.ts","../src/utils.ts","../src/Commands/CreateArkstackCommand.ts","../src/run.ts"],"sourcesContent":["export const altLogo = String.raw`%c\n _ __ _ _ \n /_\\ _ __ ___/ _\\ |_ __ _ ___| | __\n //_\\\\| '__/ __\\ \\| __/ _\\ |/ __| |/ /\n/ _ \\ | | (___\\ \\ || (_| | (__| < \n\\_/ \\_/_| \\___\\__/\\__\\__,_|\\___|_|\\_\\\n \n`;\n","/*\n * create-h3ravel\n *\n * (c) H3ravel Framework\n *\n * The H3ravel framework and all it's base packages are\n * open-sourced software licensed under the MIT license.\n */\n\n/**\n * List of first party templates\n */\nexport const templates: {\n name: string;\n alias: \"express\" | \"h3\" | \"express-lean\" | \"h3-lean\";\n hint: string;\n source: string;\n lean?: boolean;\n baseAlias?: \"express\" | \"h3\";\n prereleaseSource?: string;\n}[] = [\n {\n name: \"Express Starter Kit\",\n alias: \"express\",\n hint: \"An Express application starter kit\",\n source: \"github:toneflix/arkstack\",\n },\n {\n name: \"Express Lean Starter Kit\",\n alias: \"express-lean\",\n hint: \"A minimal Express application starter kit\",\n source: \"github:toneflix/arkstack\",\n lean: true,\n baseAlias: \"express\",\n },\n {\n name: \"H3 Starter Kit\",\n alias: \"h3\",\n hint: \"A H3 application starter kit\",\n source: \"github:toneflix/arkstack\",\n },\n {\n name: \"H3 Lean Starter Kit\",\n alias: \"h3-lean\",\n hint: \"A minimal H3 application starter kit\",\n source: \"github:toneflix/arkstack\",\n lean: true,\n baseAlias: \"h3\",\n },\n ];\n\nexport const dependencyTemplates = {\n \"@arkstack/common\": \"^0.1.4\",\n \"@arkstack/console\": \"^0.1.4\",\n \"@arkstack/contract\": \"^0.1.4\",\n \"@arkstack/database\": \"^0.1.4\",\n \"@arkstack/driver-express\": \"^0.1.4\"\n}","import { Logger, Resolver } from \"@h3ravel/shared\";\nimport { copyFile, readFile, rm, unlink, writeFile } from \"node:fs/promises\";\nimport { detectPackageManager, installPackage } from \"@antfu/install-pkg\";\nimport path, { basename, join, relative } from \"node:path\";\n\nimport { Str } from \"@h3ravel/support\";\nimport { chdir } from \"node:process\";\nimport { dependencyTemplates } from \"./templates\";\nimport { downloadTemplate } from \"giget\";\nimport { existsSync } from \"node:fs\";\n\nexport default class {\n skipInstallation?: boolean;\n\n constructor(\n private location?: string,\n private appName?: string,\n private description?: string,\n ) {\n if (!this.location) {\n this.location = join(process.cwd(), \".temp\");\n }\n }\n\n async pm () {\n return (await detectPackageManager()) ?? \"npm\";\n }\n\n async runCmd (npx: boolean = false) {\n if (npx) return \"npx\";\n\n const pm = await this.pm();\n\n return pm === \"npm\" ? \"npm run\" : pm;\n }\n\n async download (template: string, install = false, auth?: string, overwrite = false) {\n if (this.location?.includes(\".temp\") || (overwrite && existsSync(this.location!))) {\n await rm(this.location!, { force: true, recursive: true });\n } else if (existsSync(this.location!)) {\n console.log(\"\\n\");\n Logger.parse(\n [\n [\" ERROR \", \"bgRed\"],\n [this.location!, [\"gray\", \"italic\"]],\n [\"is not empty.\", \"white\"],\n ],\n \" \",\n );\n console.log(\"\");\n process.exit(0);\n }\n\n this.skipInstallation = !install;\n this.removeLockFile();\n\n return await downloadTemplate(template, {\n dir: this.location,\n auth,\n install,\n registry: await this.pm(),\n forceClean: false,\n });\n }\n\n async installPackage (name: string) {\n await installPackage(name, {\n cwd: this.location,\n silent: true,\n });\n }\n\n async complete (installed = false) {\n console.log(\"\");\n\n const installPath = \"./\" + relative(process.cwd(), this.location!);\n\n try {\n chdir(path.join(process.cwd(), installPath));\n } catch {\n /** */\n }\n\n Logger.success(\"Your Arkstack project has been created successfully\");\n Logger.parse(\n [\n [\"cd\", \"cyan\"],\n [installPath, \"yellow\"],\n installPath === process.cwd() ? [\"✔\", \"green\"] : [\"\", \"green\"],\n ],\n \" \",\n );\n\n if (!installed) {\n Logger.parse([[await Resolver.getPakageInstallCommand(), \"cyan\"]]);\n }\n\n Logger.parse(\n [\n [await this.runCmd(), \"cyan\"],\n [\"dev\", \"yellow\"],\n ],\n \" \",\n );\n Logger.parse([\n [\"Open\", \"cyan\"],\n [\"http://localhost:3000\", \"yellow\"],\n ]);\n\n console.log(\"\");\n\n Logger.parse([[\"Have any questions\", \"white\"]]);\n // Logger.parse([\n // [\"Join our Discord server -\", \"white\"],\n // [\"https://discord.gg/hsG2A8PuGb\", \"yellow\"],\n // ]);\n Logger.parse([\n [\"Checkout our other projects -\", \"white\"],\n [\"https://toneflix.net/open-source\", \"yellow\"],\n ]);\n }\n\n async cleanup () {\n const pkgPath = join(this.location!, \"package.json\");\n const pkg = await readFile(pkgPath!, \"utf-8\").then(JSON.parse);\n\n delete pkg.packageManager;\n delete pkg.scripts.predev;\n delete pkg.scripts.prebuild;\n delete pkg.scripts.precmd;\n delete pkg.scripts.build;\n delete pkg.scripts.dev;\n\n pkg.name = Str.slugify(\n this.appName ?? basename(this.location!).replace('.', ''), '-'\n );\n\n if (this.description) {\n pkg.description = this.description;\n }\n\n for (const [name, version] of Object.entries(dependencyTemplates)) {\n pkg.dependencies[name] = version;\n }\n\n await Promise.allSettled([\n writeFile(pkgPath, JSON.stringify(pkg, null, 2)),\n this.removeLockFile(),\n rm(join(this.location!, \"pnpm-workspace.yaml\"), { force: true }),\n rm(join(this.location!, \".github\"), { force: true, recursive: true }),\n ]);\n }\n\n async removeLockFile () {\n if (!this.skipInstallation) {\n return;\n }\n\n await Promise.allSettled([\n unlink(join(this.location!, \"package-lock.json\")),\n unlink(join(this.location!, \"yarn.lock\")),\n unlink(join(this.location!, \"pnpm-lock.yaml\")),\n ]);\n }\n\n async getBanner () {\n return await readFile(join(process.cwd(), \"./logo.txt\"), \"utf-8\");\n }\n\n async copyExampleEnv () {\n const envPath = join(this.location!, \".env\");\n const exampleEnvPath = join(this.location!, \".env.example\");\n\n if (existsSync(exampleEnvPath)) {\n await copyFile(exampleEnvPath, envPath);\n }\n }\n\n async makeLeanProfile (_kit: \"express\" | \"h3\") {\n const filesToRemove = [\n \"src/app\",\n \"src/routes/api.ts\",\n \"src/core/database.ts\",\n \"prisma\",\n \"prisma.config.ts\",\n ];\n\n await Promise.allSettled(\n filesToRemove.map((file) => rm(join(this.location!, file), { force: true, recursive: true })),\n );\n\n const pkgPath = join(this.location!, \"package.json\");\n if (existsSync(pkgPath)) {\n const pkg = await readFile(pkgPath, \"utf-8\").then(JSON.parse);\n const depsToRemove = [\n \"@arkstack/database\",\n \"@prisma/adapter-pg\",\n \"@prisma/client\",\n \"pg\",\n \"prisma\",\n \"@types/pg\",\n ];\n\n for (const dep of depsToRemove) {\n delete pkg.dependencies?.[dep];\n delete pkg.devDependencies?.[dep];\n }\n\n await writeFile(pkgPath, JSON.stringify(pkg, null, 2));\n }\n\n const filesToPatch = [\n \"src/core/app.ts\",\n \"src/core/utils/request-handlers.ts\",\n ];\n\n for (const file of filesToPatch) {\n const filePath = join(this.location!, file);\n\n if (!existsSync(filePath)) {\n continue;\n }\n\n let content = await readFile(filePath, \"utf-8\");\n\n content = content\n .replace('import { prisma } from \"src/core/database\";\\n', \"\")\n .replace('import { Prisma } from \"@prisma/client\";\\n', \"\")\n .replace(\" async shutdown () {\\n await prisma.$disconnect();\\n process.exit(0);\\n }\", \" async shutdown () {\\n process.exit(0);\\n }\")\n .replace(\n \" * Shuts down the application by disconnecting from the database and exiting the process.\",\n \" * Shuts down the application and exits the process.\",\n )\n .replace(\n /\\n\\s*if \\((?:err|cause) instanceof Prisma\\.PrismaClientKnownRequestError && (?:err|cause)\\.code === \"P2025\"\\) \\{\\n\\s*error\\.code = 404;\\n\\s*error\\.message = `\\$\\{(?:err|cause)\\.meta\\?\\.modelName\\} not found!`;\\n\\s*\\}\\n/g,\n \"\\n\",\n );\n\n await writeFile(filePath, content, \"utf-8\");\n }\n\n }\n}\n","import { readdir, rename, rm } from \"node:fs/promises\";\n\nimport path from \"node:path\";\n\n/**\n * Removes all files in dirPath except the one specified by keepFileName\n *\n * @param dirPath\n * @param keepFileName\n */\nexport async function cleanDirectoryExcept (dirPath: string, keepFileName: string) {\n const files = await readdir(dirPath);\n\n for (const file of files) {\n if (file === keepFileName) continue;\n\n const fullPath = path.join(dirPath, file);\n\n await rm(fullPath, { recursive: true, force: true });\n }\n}\n\n/**\n * Moves all files from dirPath to parent directory and removes dirPath\n *\n * @param dirPath\n * @param parent\n */\nexport async function hoistDirectoryContents (parent: string, dirPath: string) {\n const source = path.isAbsolute(dirPath) ? dirPath : path.join(process.cwd(), dirPath);\n\n const targetParent = path.isAbsolute(parent) ? parent : path.join(process.cwd(), parent);\n\n if (!source.startsWith(targetParent)) {\n throw new Error(\"Source must be inside the parent directory\");\n }\n\n const entries = await readdir(source);\n\n for (const entry of entries) {\n const from = path.join(source, entry);\n const to = path.join(targetParent, entry);\n\n await rename(from, to);\n }\n\n await rm(source, { recursive: true });\n}\n","import { Command } from \"@h3ravel/musket\";\nimport { altLogo } from \"src/logo\";\nimport inquirer from \"inquirer\";\nimport { AbortPromptError, ExitPromptError } from \"@inquirer/core\";\nimport { basename, join } from \"node:path\";\nimport { templates } from \"src/templates\";\nimport { Str } from \"@h3ravel/support\";\nimport Actions from \"src/actions\";\nimport ora from \"ora\";\nimport { Logger } from \"@h3ravel/shared\";\nimport { cleanDirectoryExcept, hoistDirectoryContents } from \"src/utils\";\n\nexport class CreateArkstackCommand extends Command {\n protected signature = `create-arkstack\n {location?: The location where this project should be created relative to the current dir.}\n {--n|name?: The name of your project.}\n {--i|install: Install node_modules right away}\n {--t|token?: Kit repo authentication token.}\n {--d|desc?: Project Description.}\n {--k|kit?: Starter template kit.}\n {--p|pre: Download prerelease version if available.}\n {--o|overwrite: Overwrite the installation directory if it is not empty.}\n `;\n protected description = \"Display a personalized greeting.\";\n\n async handle () {\n const options = this.options();\n const pathName = this.argument(\"location\");\n // const defaultName = pathName ? Str.of(pathName).afterLast(\"/\") : undefined;\n\n console.log(altLogo, `font-family: monospace`);\n\n let { template } = await inquirer\n .prompt([\n {\n type: \"list\",\n name: \"template\",\n message: \"Choose starter template kit:\",\n choices: <never>templates.map((e) => ({\n name: e.name,\n value: e.alias,\n disabled: !e.source ? \"(Unavailable at this time)\" : false,\n })),\n default: \"full\",\n when: () => !options.kit,\n },\n ])\n .catch((err) => {\n if (err instanceof AbortPromptError || err instanceof ExitPromptError) {\n this.info(\"Thanks for trying out our starter kit.\");\n process.exit(0);\n }\n return err;\n });\n\n let { appName, description } = await inquirer\n .prompt([\n {\n type: \"input\",\n name: \"appName\",\n message: \"What is the name of your project:\",\n default: `arkstack-${template}`,\n // default: defaultName ?? `arkstack-${template}`,\n when: () => !options.name,\n },\n {\n type: \"input\",\n name: \"description\",\n message: \"Project Description:\",\n default: `Simple ${Str.of(template).ucfirst()}.js project created with Arkstack.`,\n when: () => !options.desc,\n },\n ])\n .catch((err) => {\n if (err instanceof AbortPromptError || err instanceof ExitPromptError) {\n this.info(\"Thanks for trying out our starter kit.\");\n process.exit(0);\n }\n return err;\n });\n\n let { location } = await inquirer\n .prompt([\n {\n type: \"input\",\n name: \"location\",\n message: \"Installation location relative to the current dir:\",\n default: Str.slugify(options.name ?? appName ?? basename(process.cwd()), \"-\"),\n when: () => !pathName,\n },\n ])\n .catch((err) => {\n if (err instanceof AbortPromptError || err instanceof ExitPromptError) {\n this.info(\"Thanks for trying out our starter kit.\");\n process.exit(0);\n }\n return err;\n });\n\n /**\n * Find selected template kit\n */\n const kit = templates.find((e) => e.alias === template)!;\n\n let { install, token, pre } = await inquirer\n .prompt([\n {\n type: \"confirm\",\n name: \"pre\",\n message: `An alpha version of the ${kit.name.replace(/\\s*kit$/i, \"\").trim()} kit is available. Would you like to use it instead?`,\n default: false,\n when: () => kit.prereleaseSource && !options.pre,\n } as never,\n {\n type: \"input\",\n name: \"token\",\n message: \"Authentication token:\",\n when: () => options.kit && !options.token,\n },\n {\n type: \"confirm\",\n name: \"install\",\n message: \"Would you want to install node_modules right away:\",\n default: true,\n when: () => !options.install,\n },\n ])\n .catch((err) => {\n if (err instanceof AbortPromptError || err instanceof ExitPromptError) {\n this.info(\"Thanks for trying out our starter kit.\");\n process.exit(0);\n }\n return err;\n });\n\n pre = options.pre ?? pre;\n token = options.token ?? token;\n appName = options.name ?? appName;\n install = options.install ?? install;\n template = options.kit ?? template;\n location = pathName ?? location;\n description = options.description ?? description;\n\n /**\n * Validate selected kit\n */\n if (kit && !kit.source) {\n this.error(`ERROR: The ${kit.name} kit is not currently available`);\n process.exit(1);\n }\n\n const source: string = pre && kit.prereleaseSource ? kit.prereleaseSource! : kit.source;\n const selectedAlias = (kit.baseAlias ?? kit.alias).replace(/-lean$/i, \"\") as \"express\" | \"h3\";\n const actions = new Actions(join(process.cwd(), location), appName, description);\n const spinner = ora(`Loading Template...`).start();\n\n const result = await actions.download(source, install, token, options.overwrite);\n\n if (result.dir && selectedAlias) {\n await cleanDirectoryExcept(result.dir, selectedAlias);\n await hoistDirectoryContents(result.dir, join(result.dir, selectedAlias));\n }\n\n if (kit.lean) {\n spinner.info(Logger.parse([[\n \"Applying lean profile...\",\n \"green\",\n ]], \"\", false)).start();\n await actions.makeLeanProfile(selectedAlias);\n }\n\n spinner.info(Logger.parse([[\"Cleaning Up...\", \"green\"]], \"\", false)).start();\n await actions.cleanup();\n\n spinner.info(Logger.parse([[\"Initializing Project...\", \"green\"]], \"\", false)).start();\n await actions.copyExampleEnv();\n\n spinner.succeed(Logger.parse([[\"Project initialization complete!\", \"green\"]], \"\", false));\n\n await actions.complete(install);\n }\n}\n","#!/usr/bin/env node\n\nimport { CreateArkstackCommand } from \"./Commands/CreateArkstackCommand\";\nimport { Kernel } from \"@h3ravel/musket\";\n\nclass Application { }\n\nKernel.init(new Application(), {\n rootCommand: CreateArkstackCommand,\n});\n"],"mappings":"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"}
package/bin/run.d.cts ADDED
@@ -0,0 +1 @@
1
+ export { };
package/bin/run.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { };
package/bin/run.js ADDED
@@ -0,0 +1,387 @@
1
+ #!/usr/bin/env node
2
+ import { Command, Kernel } from "@h3ravel/musket";
3
+ import inquirer from "inquirer";
4
+ import { AbortPromptError, ExitPromptError } from "@inquirer/core";
5
+ import path, { basename, join, relative } from "node:path";
6
+ import { Str } from "@h3ravel/support";
7
+ import { Logger, Resolver } from "@h3ravel/shared";
8
+ import { copyFile, readFile, readdir, rename, rm, unlink, writeFile } from "node:fs/promises";
9
+ import { detectPackageManager, installPackage } from "@antfu/install-pkg";
10
+ import { chdir } from "node:process";
11
+ import { downloadTemplate } from "giget";
12
+ import { existsSync } from "node:fs";
13
+ import ora from "ora";
14
+
15
+ //#region src/logo.ts
16
+ const altLogo = String.raw`%c
17
+ _ __ _ _
18
+ /_\ _ __ ___/ _\ |_ __ _ ___| | __
19
+ //_\\| '__/ __\ \| __/ _\ |/ __| |/ /
20
+ / _ \ | | (___\ \ || (_| | (__| <
21
+ \_/ \_/_| \___\__/\__\__,_|\___|_|\_\
22
+
23
+ `;
24
+
25
+ //#endregion
26
+ //#region src/templates.ts
27
+ /**
28
+ * List of first party templates
29
+ */
30
+ const templates = [
31
+ {
32
+ name: "Express Starter Kit",
33
+ alias: "express",
34
+ hint: "An Express application starter kit",
35
+ source: "github:toneflix/arkstack"
36
+ },
37
+ {
38
+ name: "Express Lean Starter Kit",
39
+ alias: "express-lean",
40
+ hint: "A minimal Express application starter kit",
41
+ source: "github:toneflix/arkstack",
42
+ lean: true,
43
+ baseAlias: "express"
44
+ },
45
+ {
46
+ name: "H3 Starter Kit",
47
+ alias: "h3",
48
+ hint: "A H3 application starter kit",
49
+ source: "github:toneflix/arkstack"
50
+ },
51
+ {
52
+ name: "H3 Lean Starter Kit",
53
+ alias: "h3-lean",
54
+ hint: "A minimal H3 application starter kit",
55
+ source: "github:toneflix/arkstack",
56
+ lean: true,
57
+ baseAlias: "h3"
58
+ }
59
+ ];
60
+ const dependencyTemplates = {
61
+ "@arkstack/common": "^0.1.4",
62
+ "@arkstack/console": "^0.1.4",
63
+ "@arkstack/contract": "^0.1.4",
64
+ "@arkstack/database": "^0.1.4",
65
+ "@arkstack/driver-express": "^0.1.4"
66
+ };
67
+
68
+ //#endregion
69
+ //#region src/actions.ts
70
+ var actions_default = class {
71
+ skipInstallation;
72
+ constructor(location, appName, description) {
73
+ this.location = location;
74
+ this.appName = appName;
75
+ this.description = description;
76
+ if (!this.location) this.location = join(process.cwd(), ".temp");
77
+ }
78
+ async pm() {
79
+ return await detectPackageManager() ?? "npm";
80
+ }
81
+ async runCmd(npx = false) {
82
+ if (npx) return "npx";
83
+ const pm = await this.pm();
84
+ return pm === "npm" ? "npm run" : pm;
85
+ }
86
+ async download(template, install = false, auth, overwrite = false) {
87
+ if (this.location?.includes(".temp") || overwrite && existsSync(this.location)) await rm(this.location, {
88
+ force: true,
89
+ recursive: true
90
+ });
91
+ else if (existsSync(this.location)) {
92
+ console.log("\n");
93
+ Logger.parse([
94
+ [" ERROR ", "bgRed"],
95
+ [this.location, ["gray", "italic"]],
96
+ ["is not empty.", "white"]
97
+ ], " ");
98
+ console.log("");
99
+ process.exit(0);
100
+ }
101
+ this.skipInstallation = !install;
102
+ this.removeLockFile();
103
+ return await downloadTemplate(template, {
104
+ dir: this.location,
105
+ auth,
106
+ install,
107
+ registry: await this.pm(),
108
+ forceClean: false
109
+ });
110
+ }
111
+ async installPackage(name) {
112
+ await installPackage(name, {
113
+ cwd: this.location,
114
+ silent: true
115
+ });
116
+ }
117
+ async complete(installed = false) {
118
+ console.log("");
119
+ const installPath = "./" + relative(process.cwd(), this.location);
120
+ try {
121
+ chdir(path.join(process.cwd(), installPath));
122
+ } catch {}
123
+ Logger.success("Your Arkstack project has been created successfully");
124
+ Logger.parse([
125
+ ["cd", "cyan"],
126
+ [installPath, "yellow"],
127
+ installPath === process.cwd() ? ["✔", "green"] : ["", "green"]
128
+ ], " ");
129
+ if (!installed) Logger.parse([[await Resolver.getPakageInstallCommand(), "cyan"]]);
130
+ Logger.parse([[await this.runCmd(), "cyan"], ["dev", "yellow"]], " ");
131
+ Logger.parse([["Open", "cyan"], ["http://localhost:3000", "yellow"]]);
132
+ console.log("");
133
+ Logger.parse([["Have any questions", "white"]]);
134
+ Logger.parse([["Checkout our other projects -", "white"], ["https://toneflix.net/open-source", "yellow"]]);
135
+ }
136
+ async cleanup() {
137
+ const pkgPath = join(this.location, "package.json");
138
+ const pkg = await readFile(pkgPath, "utf-8").then(JSON.parse);
139
+ delete pkg.packageManager;
140
+ delete pkg.scripts.predev;
141
+ delete pkg.scripts.prebuild;
142
+ delete pkg.scripts.precmd;
143
+ delete pkg.scripts.build;
144
+ delete pkg.scripts.dev;
145
+ pkg.name = Str.slugify(this.appName ?? basename(this.location).replace(".", ""), "-");
146
+ if (this.description) pkg.description = this.description;
147
+ for (const [name, version] of Object.entries(dependencyTemplates)) pkg.dependencies[name] = version;
148
+ await Promise.allSettled([
149
+ writeFile(pkgPath, JSON.stringify(pkg, null, 2)),
150
+ this.removeLockFile(),
151
+ rm(join(this.location, "pnpm-workspace.yaml"), { force: true }),
152
+ rm(join(this.location, ".github"), {
153
+ force: true,
154
+ recursive: true
155
+ })
156
+ ]);
157
+ }
158
+ async removeLockFile() {
159
+ if (!this.skipInstallation) return;
160
+ await Promise.allSettled([
161
+ unlink(join(this.location, "package-lock.json")),
162
+ unlink(join(this.location, "yarn.lock")),
163
+ unlink(join(this.location, "pnpm-lock.yaml"))
164
+ ]);
165
+ }
166
+ async getBanner() {
167
+ return await readFile(join(process.cwd(), "./logo.txt"), "utf-8");
168
+ }
169
+ async copyExampleEnv() {
170
+ const envPath = join(this.location, ".env");
171
+ const exampleEnvPath = join(this.location, ".env.example");
172
+ if (existsSync(exampleEnvPath)) await copyFile(exampleEnvPath, envPath);
173
+ }
174
+ async makeLeanProfile(_kit) {
175
+ await Promise.allSettled([
176
+ "src/app",
177
+ "src/routes/api.ts",
178
+ "src/core/database.ts",
179
+ "prisma",
180
+ "prisma.config.ts"
181
+ ].map((file) => rm(join(this.location, file), {
182
+ force: true,
183
+ recursive: true
184
+ })));
185
+ const pkgPath = join(this.location, "package.json");
186
+ if (existsSync(pkgPath)) {
187
+ const pkg = await readFile(pkgPath, "utf-8").then(JSON.parse);
188
+ for (const dep of [
189
+ "@arkstack/database",
190
+ "@prisma/adapter-pg",
191
+ "@prisma/client",
192
+ "pg",
193
+ "prisma",
194
+ "@types/pg"
195
+ ]) {
196
+ delete pkg.dependencies?.[dep];
197
+ delete pkg.devDependencies?.[dep];
198
+ }
199
+ await writeFile(pkgPath, JSON.stringify(pkg, null, 2));
200
+ }
201
+ for (const file of ["src/core/app.ts", "src/core/utils/request-handlers.ts"]) {
202
+ const filePath = join(this.location, file);
203
+ if (!existsSync(filePath)) continue;
204
+ let content = await readFile(filePath, "utf-8");
205
+ content = content.replace("import { prisma } from \"src/core/database\";\n", "").replace("import { Prisma } from \"@prisma/client\";\n", "").replace(" async shutdown () {\n await prisma.$disconnect();\n process.exit(0);\n }", " async shutdown () {\n process.exit(0);\n }").replace(" * Shuts down the application by disconnecting from the database and exiting the process.", " * Shuts down the application and exits the process.").replace(/\n\s*if \((?:err|cause) instanceof Prisma\.PrismaClientKnownRequestError && (?:err|cause)\.code === "P2025"\) \{\n\s*error\.code = 404;\n\s*error\.message = `\$\{(?:err|cause)\.meta\?\.modelName\} not found!`;\n\s*\}\n/g, "\n");
206
+ await writeFile(filePath, content, "utf-8");
207
+ }
208
+ }
209
+ };
210
+
211
+ //#endregion
212
+ //#region src/utils.ts
213
+ /**
214
+ * Removes all files in dirPath except the one specified by keepFileName
215
+ *
216
+ * @param dirPath
217
+ * @param keepFileName
218
+ */
219
+ async function cleanDirectoryExcept(dirPath, keepFileName) {
220
+ const files = await readdir(dirPath);
221
+ for (const file of files) {
222
+ if (file === keepFileName) continue;
223
+ await rm(path.join(dirPath, file), {
224
+ recursive: true,
225
+ force: true
226
+ });
227
+ }
228
+ }
229
+ /**
230
+ * Moves all files from dirPath to parent directory and removes dirPath
231
+ *
232
+ * @param dirPath
233
+ * @param parent
234
+ */
235
+ async function hoistDirectoryContents(parent, dirPath) {
236
+ const source = path.isAbsolute(dirPath) ? dirPath : path.join(process.cwd(), dirPath);
237
+ const targetParent = path.isAbsolute(parent) ? parent : path.join(process.cwd(), parent);
238
+ if (!source.startsWith(targetParent)) throw new Error("Source must be inside the parent directory");
239
+ const entries = await readdir(source);
240
+ for (const entry of entries) await rename(path.join(source, entry), path.join(targetParent, entry));
241
+ await rm(source, { recursive: true });
242
+ }
243
+
244
+ //#endregion
245
+ //#region src/Commands/CreateArkstackCommand.ts
246
+ var CreateArkstackCommand = class extends Command {
247
+ signature = `create-arkstack
248
+ {location?: The location where this project should be created relative to the current dir.}
249
+ {--n|name?: The name of your project.}
250
+ {--i|install: Install node_modules right away}
251
+ {--t|token?: Kit repo authentication token.}
252
+ {--d|desc?: Project Description.}
253
+ {--k|kit?: Starter template kit.}
254
+ {--p|pre: Download prerelease version if available.}
255
+ {--o|overwrite: Overwrite the installation directory if it is not empty.}
256
+ `;
257
+ description = "Display a personalized greeting.";
258
+ async handle() {
259
+ const options = this.options();
260
+ const pathName = this.argument("location");
261
+ console.log(altLogo, `font-family: monospace`);
262
+ let { template } = await inquirer.prompt([{
263
+ type: "list",
264
+ name: "template",
265
+ message: "Choose starter template kit:",
266
+ choices: templates.map((e) => ({
267
+ name: e.name,
268
+ value: e.alias,
269
+ disabled: !e.source ? "(Unavailable at this time)" : false
270
+ })),
271
+ default: "full",
272
+ when: () => !options.kit
273
+ }]).catch((err) => {
274
+ if (err instanceof AbortPromptError || err instanceof ExitPromptError) {
275
+ this.info("Thanks for trying out our starter kit.");
276
+ process.exit(0);
277
+ }
278
+ return err;
279
+ });
280
+ let { appName, description } = await inquirer.prompt([{
281
+ type: "input",
282
+ name: "appName",
283
+ message: "What is the name of your project:",
284
+ default: `arkstack-${template}`,
285
+ when: () => !options.name
286
+ }, {
287
+ type: "input",
288
+ name: "description",
289
+ message: "Project Description:",
290
+ default: `Simple ${Str.of(template).ucfirst()}.js project created with Arkstack.`,
291
+ when: () => !options.desc
292
+ }]).catch((err) => {
293
+ if (err instanceof AbortPromptError || err instanceof ExitPromptError) {
294
+ this.info("Thanks for trying out our starter kit.");
295
+ process.exit(0);
296
+ }
297
+ return err;
298
+ });
299
+ let { location } = await inquirer.prompt([{
300
+ type: "input",
301
+ name: "location",
302
+ message: "Installation location relative to the current dir:",
303
+ default: Str.slugify(options.name ?? appName ?? basename(process.cwd()), "-"),
304
+ when: () => !pathName
305
+ }]).catch((err) => {
306
+ if (err instanceof AbortPromptError || err instanceof ExitPromptError) {
307
+ this.info("Thanks for trying out our starter kit.");
308
+ process.exit(0);
309
+ }
310
+ return err;
311
+ });
312
+ /**
313
+ * Find selected template kit
314
+ */
315
+ const kit = templates.find((e) => e.alias === template);
316
+ let { install, token, pre } = await inquirer.prompt([
317
+ {
318
+ type: "confirm",
319
+ name: "pre",
320
+ message: `An alpha version of the ${kit.name.replace(/\s*kit$/i, "").trim()} kit is available. Would you like to use it instead?`,
321
+ default: false,
322
+ when: () => kit.prereleaseSource && !options.pre
323
+ },
324
+ {
325
+ type: "input",
326
+ name: "token",
327
+ message: "Authentication token:",
328
+ when: () => options.kit && !options.token
329
+ },
330
+ {
331
+ type: "confirm",
332
+ name: "install",
333
+ message: "Would you want to install node_modules right away:",
334
+ default: true,
335
+ when: () => !options.install
336
+ }
337
+ ]).catch((err) => {
338
+ if (err instanceof AbortPromptError || err instanceof ExitPromptError) {
339
+ this.info("Thanks for trying out our starter kit.");
340
+ process.exit(0);
341
+ }
342
+ return err;
343
+ });
344
+ pre = options.pre ?? pre;
345
+ token = options.token ?? token;
346
+ appName = options.name ?? appName;
347
+ install = options.install ?? install;
348
+ template = options.kit ?? template;
349
+ location = pathName ?? location;
350
+ description = options.description ?? description;
351
+ /**
352
+ * Validate selected kit
353
+ */
354
+ if (kit && !kit.source) {
355
+ this.error(`ERROR: The ${kit.name} kit is not currently available`);
356
+ process.exit(1);
357
+ }
358
+ const source = pre && kit.prereleaseSource ? kit.prereleaseSource : kit.source;
359
+ const selectedAlias = (kit.baseAlias ?? kit.alias).replace(/-lean$/i, "");
360
+ const actions = new actions_default(join(process.cwd(), location), appName, description);
361
+ const spinner = ora(`Loading Template...`).start();
362
+ const result = await actions.download(source, install, token, options.overwrite);
363
+ if (result.dir && selectedAlias) {
364
+ await cleanDirectoryExcept(result.dir, selectedAlias);
365
+ await hoistDirectoryContents(result.dir, join(result.dir, selectedAlias));
366
+ }
367
+ if (kit.lean) {
368
+ spinner.info(Logger.parse([["Applying lean profile...", "green"]], "", false)).start();
369
+ await actions.makeLeanProfile(selectedAlias);
370
+ }
371
+ spinner.info(Logger.parse([["Cleaning Up...", "green"]], "", false)).start();
372
+ await actions.cleanup();
373
+ spinner.info(Logger.parse([["Initializing Project...", "green"]], "", false)).start();
374
+ await actions.copyExampleEnv();
375
+ spinner.succeed(Logger.parse([["Project initialization complete!", "green"]], "", false));
376
+ await actions.complete(install);
377
+ }
378
+ };
379
+
380
+ //#endregion
381
+ //#region src/run.ts
382
+ var Application = class {};
383
+ Kernel.init(new Application(), { rootCommand: CreateArkstackCommand });
384
+
385
+ //#endregion
386
+ export { };
387
+ //# sourceMappingURL=run.js.map
package/bin/run.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","names":["templates: {\n name: string;\n alias: \"express\" | \"h3\" | \"express-lean\" | \"h3-lean\";\n hint: string;\n source: string;\n lean?: boolean;\n baseAlias?: \"express\" | \"h3\";\n prereleaseSource?: string;\n}[]","location?: string","appName?: string","description?: string","source: string","Actions"],"sources":["../src/logo.ts","../src/templates.ts","../src/actions.ts","../src/utils.ts","../src/Commands/CreateArkstackCommand.ts","../src/run.ts"],"sourcesContent":["export const altLogo = String.raw`%c\n _ __ _ _ \n /_\\ _ __ ___/ _\\ |_ __ _ ___| | __\n //_\\\\| '__/ __\\ \\| __/ _\\ |/ __| |/ /\n/ _ \\ | | (___\\ \\ || (_| | (__| < \n\\_/ \\_/_| \\___\\__/\\__\\__,_|\\___|_|\\_\\\n \n`;\n","/*\n * create-h3ravel\n *\n * (c) H3ravel Framework\n *\n * The H3ravel framework and all it's base packages are\n * open-sourced software licensed under the MIT license.\n */\n\n/**\n * List of first party templates\n */\nexport const templates: {\n name: string;\n alias: \"express\" | \"h3\" | \"express-lean\" | \"h3-lean\";\n hint: string;\n source: string;\n lean?: boolean;\n baseAlias?: \"express\" | \"h3\";\n prereleaseSource?: string;\n}[] = [\n {\n name: \"Express Starter Kit\",\n alias: \"express\",\n hint: \"An Express application starter kit\",\n source: \"github:toneflix/arkstack\",\n },\n {\n name: \"Express Lean Starter Kit\",\n alias: \"express-lean\",\n hint: \"A minimal Express application starter kit\",\n source: \"github:toneflix/arkstack\",\n lean: true,\n baseAlias: \"express\",\n },\n {\n name: \"H3 Starter Kit\",\n alias: \"h3\",\n hint: \"A H3 application starter kit\",\n source: \"github:toneflix/arkstack\",\n },\n {\n name: \"H3 Lean Starter Kit\",\n alias: \"h3-lean\",\n hint: \"A minimal H3 application starter kit\",\n source: \"github:toneflix/arkstack\",\n lean: true,\n baseAlias: \"h3\",\n },\n ];\n\nexport const dependencyTemplates = {\n \"@arkstack/common\": \"^0.1.4\",\n \"@arkstack/console\": \"^0.1.4\",\n \"@arkstack/contract\": \"^0.1.4\",\n \"@arkstack/database\": \"^0.1.4\",\n \"@arkstack/driver-express\": \"^0.1.4\"\n}","import { Logger, Resolver } from \"@h3ravel/shared\";\nimport { copyFile, readFile, rm, unlink, writeFile } from \"node:fs/promises\";\nimport { detectPackageManager, installPackage } from \"@antfu/install-pkg\";\nimport path, { basename, join, relative } from \"node:path\";\n\nimport { Str } from \"@h3ravel/support\";\nimport { chdir } from \"node:process\";\nimport { dependencyTemplates } from \"./templates\";\nimport { downloadTemplate } from \"giget\";\nimport { existsSync } from \"node:fs\";\n\nexport default class {\n skipInstallation?: boolean;\n\n constructor(\n private location?: string,\n private appName?: string,\n private description?: string,\n ) {\n if (!this.location) {\n this.location = join(process.cwd(), \".temp\");\n }\n }\n\n async pm () {\n return (await detectPackageManager()) ?? \"npm\";\n }\n\n async runCmd (npx: boolean = false) {\n if (npx) return \"npx\";\n\n const pm = await this.pm();\n\n return pm === \"npm\" ? \"npm run\" : pm;\n }\n\n async download (template: string, install = false, auth?: string, overwrite = false) {\n if (this.location?.includes(\".temp\") || (overwrite && existsSync(this.location!))) {\n await rm(this.location!, { force: true, recursive: true });\n } else if (existsSync(this.location!)) {\n console.log(\"\\n\");\n Logger.parse(\n [\n [\" ERROR \", \"bgRed\"],\n [this.location!, [\"gray\", \"italic\"]],\n [\"is not empty.\", \"white\"],\n ],\n \" \",\n );\n console.log(\"\");\n process.exit(0);\n }\n\n this.skipInstallation = !install;\n this.removeLockFile();\n\n return await downloadTemplate(template, {\n dir: this.location,\n auth,\n install,\n registry: await this.pm(),\n forceClean: false,\n });\n }\n\n async installPackage (name: string) {\n await installPackage(name, {\n cwd: this.location,\n silent: true,\n });\n }\n\n async complete (installed = false) {\n console.log(\"\");\n\n const installPath = \"./\" + relative(process.cwd(), this.location!);\n\n try {\n chdir(path.join(process.cwd(), installPath));\n } catch {\n /** */\n }\n\n Logger.success(\"Your Arkstack project has been created successfully\");\n Logger.parse(\n [\n [\"cd\", \"cyan\"],\n [installPath, \"yellow\"],\n installPath === process.cwd() ? [\"✔\", \"green\"] : [\"\", \"green\"],\n ],\n \" \",\n );\n\n if (!installed) {\n Logger.parse([[await Resolver.getPakageInstallCommand(), \"cyan\"]]);\n }\n\n Logger.parse(\n [\n [await this.runCmd(), \"cyan\"],\n [\"dev\", \"yellow\"],\n ],\n \" \",\n );\n Logger.parse([\n [\"Open\", \"cyan\"],\n [\"http://localhost:3000\", \"yellow\"],\n ]);\n\n console.log(\"\");\n\n Logger.parse([[\"Have any questions\", \"white\"]]);\n // Logger.parse([\n // [\"Join our Discord server -\", \"white\"],\n // [\"https://discord.gg/hsG2A8PuGb\", \"yellow\"],\n // ]);\n Logger.parse([\n [\"Checkout our other projects -\", \"white\"],\n [\"https://toneflix.net/open-source\", \"yellow\"],\n ]);\n }\n\n async cleanup () {\n const pkgPath = join(this.location!, \"package.json\");\n const pkg = await readFile(pkgPath!, \"utf-8\").then(JSON.parse);\n\n delete pkg.packageManager;\n delete pkg.scripts.predev;\n delete pkg.scripts.prebuild;\n delete pkg.scripts.precmd;\n delete pkg.scripts.build;\n delete pkg.scripts.dev;\n\n pkg.name = Str.slugify(\n this.appName ?? basename(this.location!).replace('.', ''), '-'\n );\n\n if (this.description) {\n pkg.description = this.description;\n }\n\n for (const [name, version] of Object.entries(dependencyTemplates)) {\n pkg.dependencies[name] = version;\n }\n\n await Promise.allSettled([\n writeFile(pkgPath, JSON.stringify(pkg, null, 2)),\n this.removeLockFile(),\n rm(join(this.location!, \"pnpm-workspace.yaml\"), { force: true }),\n rm(join(this.location!, \".github\"), { force: true, recursive: true }),\n ]);\n }\n\n async removeLockFile () {\n if (!this.skipInstallation) {\n return;\n }\n\n await Promise.allSettled([\n unlink(join(this.location!, \"package-lock.json\")),\n unlink(join(this.location!, \"yarn.lock\")),\n unlink(join(this.location!, \"pnpm-lock.yaml\")),\n ]);\n }\n\n async getBanner () {\n return await readFile(join(process.cwd(), \"./logo.txt\"), \"utf-8\");\n }\n\n async copyExampleEnv () {\n const envPath = join(this.location!, \".env\");\n const exampleEnvPath = join(this.location!, \".env.example\");\n\n if (existsSync(exampleEnvPath)) {\n await copyFile(exampleEnvPath, envPath);\n }\n }\n\n async makeLeanProfile (_kit: \"express\" | \"h3\") {\n const filesToRemove = [\n \"src/app\",\n \"src/routes/api.ts\",\n \"src/core/database.ts\",\n \"prisma\",\n \"prisma.config.ts\",\n ];\n\n await Promise.allSettled(\n filesToRemove.map((file) => rm(join(this.location!, file), { force: true, recursive: true })),\n );\n\n const pkgPath = join(this.location!, \"package.json\");\n if (existsSync(pkgPath)) {\n const pkg = await readFile(pkgPath, \"utf-8\").then(JSON.parse);\n const depsToRemove = [\n \"@arkstack/database\",\n \"@prisma/adapter-pg\",\n \"@prisma/client\",\n \"pg\",\n \"prisma\",\n \"@types/pg\",\n ];\n\n for (const dep of depsToRemove) {\n delete pkg.dependencies?.[dep];\n delete pkg.devDependencies?.[dep];\n }\n\n await writeFile(pkgPath, JSON.stringify(pkg, null, 2));\n }\n\n const filesToPatch = [\n \"src/core/app.ts\",\n \"src/core/utils/request-handlers.ts\",\n ];\n\n for (const file of filesToPatch) {\n const filePath = join(this.location!, file);\n\n if (!existsSync(filePath)) {\n continue;\n }\n\n let content = await readFile(filePath, \"utf-8\");\n\n content = content\n .replace('import { prisma } from \"src/core/database\";\\n', \"\")\n .replace('import { Prisma } from \"@prisma/client\";\\n', \"\")\n .replace(\" async shutdown () {\\n await prisma.$disconnect();\\n process.exit(0);\\n }\", \" async shutdown () {\\n process.exit(0);\\n }\")\n .replace(\n \" * Shuts down the application by disconnecting from the database and exiting the process.\",\n \" * Shuts down the application and exits the process.\",\n )\n .replace(\n /\\n\\s*if \\((?:err|cause) instanceof Prisma\\.PrismaClientKnownRequestError && (?:err|cause)\\.code === \"P2025\"\\) \\{\\n\\s*error\\.code = 404;\\n\\s*error\\.message = `\\$\\{(?:err|cause)\\.meta\\?\\.modelName\\} not found!`;\\n\\s*\\}\\n/g,\n \"\\n\",\n );\n\n await writeFile(filePath, content, \"utf-8\");\n }\n\n }\n}\n","import { readdir, rename, rm } from \"node:fs/promises\";\n\nimport path from \"node:path\";\n\n/**\n * Removes all files in dirPath except the one specified by keepFileName\n *\n * @param dirPath\n * @param keepFileName\n */\nexport async function cleanDirectoryExcept (dirPath: string, keepFileName: string) {\n const files = await readdir(dirPath);\n\n for (const file of files) {\n if (file === keepFileName) continue;\n\n const fullPath = path.join(dirPath, file);\n\n await rm(fullPath, { recursive: true, force: true });\n }\n}\n\n/**\n * Moves all files from dirPath to parent directory and removes dirPath\n *\n * @param dirPath\n * @param parent\n */\nexport async function hoistDirectoryContents (parent: string, dirPath: string) {\n const source = path.isAbsolute(dirPath) ? dirPath : path.join(process.cwd(), dirPath);\n\n const targetParent = path.isAbsolute(parent) ? parent : path.join(process.cwd(), parent);\n\n if (!source.startsWith(targetParent)) {\n throw new Error(\"Source must be inside the parent directory\");\n }\n\n const entries = await readdir(source);\n\n for (const entry of entries) {\n const from = path.join(source, entry);\n const to = path.join(targetParent, entry);\n\n await rename(from, to);\n }\n\n await rm(source, { recursive: true });\n}\n","import { Command } from \"@h3ravel/musket\";\nimport { altLogo } from \"src/logo\";\nimport inquirer from \"inquirer\";\nimport { AbortPromptError, ExitPromptError } from \"@inquirer/core\";\nimport { basename, join } from \"node:path\";\nimport { templates } from \"src/templates\";\nimport { Str } from \"@h3ravel/support\";\nimport Actions from \"src/actions\";\nimport ora from \"ora\";\nimport { Logger } from \"@h3ravel/shared\";\nimport { cleanDirectoryExcept, hoistDirectoryContents } from \"src/utils\";\n\nexport class CreateArkstackCommand extends Command {\n protected signature = `create-arkstack\n {location?: The location where this project should be created relative to the current dir.}\n {--n|name?: The name of your project.}\n {--i|install: Install node_modules right away}\n {--t|token?: Kit repo authentication token.}\n {--d|desc?: Project Description.}\n {--k|kit?: Starter template kit.}\n {--p|pre: Download prerelease version if available.}\n {--o|overwrite: Overwrite the installation directory if it is not empty.}\n `;\n protected description = \"Display a personalized greeting.\";\n\n async handle () {\n const options = this.options();\n const pathName = this.argument(\"location\");\n // const defaultName = pathName ? Str.of(pathName).afterLast(\"/\") : undefined;\n\n console.log(altLogo, `font-family: monospace`);\n\n let { template } = await inquirer\n .prompt([\n {\n type: \"list\",\n name: \"template\",\n message: \"Choose starter template kit:\",\n choices: <never>templates.map((e) => ({\n name: e.name,\n value: e.alias,\n disabled: !e.source ? \"(Unavailable at this time)\" : false,\n })),\n default: \"full\",\n when: () => !options.kit,\n },\n ])\n .catch((err) => {\n if (err instanceof AbortPromptError || err instanceof ExitPromptError) {\n this.info(\"Thanks for trying out our starter kit.\");\n process.exit(0);\n }\n return err;\n });\n\n let { appName, description } = await inquirer\n .prompt([\n {\n type: \"input\",\n name: \"appName\",\n message: \"What is the name of your project:\",\n default: `arkstack-${template}`,\n // default: defaultName ?? `arkstack-${template}`,\n when: () => !options.name,\n },\n {\n type: \"input\",\n name: \"description\",\n message: \"Project Description:\",\n default: `Simple ${Str.of(template).ucfirst()}.js project created with Arkstack.`,\n when: () => !options.desc,\n },\n ])\n .catch((err) => {\n if (err instanceof AbortPromptError || err instanceof ExitPromptError) {\n this.info(\"Thanks for trying out our starter kit.\");\n process.exit(0);\n }\n return err;\n });\n\n let { location } = await inquirer\n .prompt([\n {\n type: \"input\",\n name: \"location\",\n message: \"Installation location relative to the current dir:\",\n default: Str.slugify(options.name ?? appName ?? basename(process.cwd()), \"-\"),\n when: () => !pathName,\n },\n ])\n .catch((err) => {\n if (err instanceof AbortPromptError || err instanceof ExitPromptError) {\n this.info(\"Thanks for trying out our starter kit.\");\n process.exit(0);\n }\n return err;\n });\n\n /**\n * Find selected template kit\n */\n const kit = templates.find((e) => e.alias === template)!;\n\n let { install, token, pre } = await inquirer\n .prompt([\n {\n type: \"confirm\",\n name: \"pre\",\n message: `An alpha version of the ${kit.name.replace(/\\s*kit$/i, \"\").trim()} kit is available. Would you like to use it instead?`,\n default: false,\n when: () => kit.prereleaseSource && !options.pre,\n } as never,\n {\n type: \"input\",\n name: \"token\",\n message: \"Authentication token:\",\n when: () => options.kit && !options.token,\n },\n {\n type: \"confirm\",\n name: \"install\",\n message: \"Would you want to install node_modules right away:\",\n default: true,\n when: () => !options.install,\n },\n ])\n .catch((err) => {\n if (err instanceof AbortPromptError || err instanceof ExitPromptError) {\n this.info(\"Thanks for trying out our starter kit.\");\n process.exit(0);\n }\n return err;\n });\n\n pre = options.pre ?? pre;\n token = options.token ?? token;\n appName = options.name ?? appName;\n install = options.install ?? install;\n template = options.kit ?? template;\n location = pathName ?? location;\n description = options.description ?? description;\n\n /**\n * Validate selected kit\n */\n if (kit && !kit.source) {\n this.error(`ERROR: The ${kit.name} kit is not currently available`);\n process.exit(1);\n }\n\n const source: string = pre && kit.prereleaseSource ? kit.prereleaseSource! : kit.source;\n const selectedAlias = (kit.baseAlias ?? kit.alias).replace(/-lean$/i, \"\") as \"express\" | \"h3\";\n const actions = new Actions(join(process.cwd(), location), appName, description);\n const spinner = ora(`Loading Template...`).start();\n\n const result = await actions.download(source, install, token, options.overwrite);\n\n if (result.dir && selectedAlias) {\n await cleanDirectoryExcept(result.dir, selectedAlias);\n await hoistDirectoryContents(result.dir, join(result.dir, selectedAlias));\n }\n\n if (kit.lean) {\n spinner.info(Logger.parse([[\n \"Applying lean profile...\",\n \"green\",\n ]], \"\", false)).start();\n await actions.makeLeanProfile(selectedAlias);\n }\n\n spinner.info(Logger.parse([[\"Cleaning Up...\", \"green\"]], \"\", false)).start();\n await actions.cleanup();\n\n spinner.info(Logger.parse([[\"Initializing Project...\", \"green\"]], \"\", false)).start();\n await actions.copyExampleEnv();\n\n spinner.succeed(Logger.parse([[\"Project initialization complete!\", \"green\"]], \"\", false));\n\n await actions.complete(install);\n }\n}\n","#!/usr/bin/env node\n\nimport { CreateArkstackCommand } from \"./Commands/CreateArkstackCommand\";\nimport { Kernel } from \"@h3ravel/musket\";\n\nclass Application { }\n\nKernel.init(new Application(), {\n rootCommand: CreateArkstackCommand,\n});\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "create-arkstack",
3
+ "type": "module",
4
+ "version": "0.1.0",
5
+ "description": "Scaffold new H3.js or Express.js applications using Toneflix's arkstack templates and starter kits",
6
+ "main": "build/index.js",
7
+ "private": false,
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "bin": {
12
+ "create-arkstack": "bin/run.js"
13
+ },
14
+ "exports": {
15
+ ".": "./bin/run.js"
16
+ },
17
+ "keywords": [
18
+ "toneflix",
19
+ "create-arkstack",
20
+ "h3",
21
+ "express",
22
+ "scaffold",
23
+ "template",
24
+ "starter kit",
25
+ "cli"
26
+ ],
27
+ "files": [
28
+ "bin",
29
+ "bin/run.d.ts",
30
+ "bin/run.js"
31
+ ],
32
+ "dependencies": {
33
+ "tsdown": "^0.15.4",
34
+ "@antfu/install-pkg": "1.1.0",
35
+ "@h3ravel/collect.js": "^5.3.4",
36
+ "@h3ravel/musket": "^0.10.1",
37
+ "@h3ravel/shared": "^0.28.4",
38
+ "@h3ravel/support": "^0.16.1",
39
+ "@inquirer/core": "^10.2.2",
40
+ "giget": "^2.0.0",
41
+ "inquirer": "^12.9.6",
42
+ "ora": "^9.0.0"
43
+ },
44
+ "devDependencies": {
45
+ "@changesets/cli": "^2.29.5",
46
+ "eslint": "^9.32.0",
47
+ "ts-node": "^10.9.2"
48
+ },
49
+ "scripts": {
50
+ "test": "vitest run",
51
+ "test:watch": "vitest",
52
+ "runner": "tsx --experimental-specifier-resolution=node src/run.ts",
53
+ "build": "tsdown",
54
+ "version": "pnpm run build",
55
+ "unlink": "npm unlink -g create-arkstack",
56
+ "release": "pnpm build && pnpm changeset version && pnpm changeset publish",
57
+ "publish-it": "pnpm build && pnpm publish --tag latest"
58
+ }
59
+ }