create-jilatax 0.0.3 โ†’ 0.0.4

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 (43) hide show
  1. package/README.md +38 -24
  2. package/THIRD_PARTY_NOTICES.md +7 -0
  3. package/dist/bin.cjs +6 -0
  4. package/dist/bin.d.cts +1 -0
  5. package/dist/bin.d.ts +1 -0
  6. package/dist/bin.js +8 -0
  7. package/dist/cli-BO6toXiq.cjs +450 -0
  8. package/dist/cli-BQK3vkvN.js +385 -0
  9. package/dist/index.cjs +8 -6
  10. package/dist/index.d.cts +32 -3
  11. package/dist/index.d.ts +32 -3
  12. package/dist/index.js +2 -6
  13. package/package.json +13 -5
  14. package/template/README.md.tmpl +31 -0
  15. package/template/android/app/build.gradle.kts +112 -0
  16. package/template/android/app/proguard-rules.pro +1 -0
  17. package/template/android/app/src/debug/AndroidManifest.xml +8 -0
  18. package/template/android/app/src/main/AndroidManifest.xml +30 -0
  19. package/template/android/app/src/main/res/drawable/jilatax_mark_foreground.xml +11 -0
  20. package/template/android/app/src/main/res/drawable/jilatax_splash.xml +9 -0
  21. package/template/android/app/src/main/res/mipmap-anydpi/jilatax_launcher.xml +12 -0
  22. package/template/android/app/src/main/res/mipmap-anydpi/jilatax_launcher_round.xml +12 -0
  23. package/template/android/app/src/main/res/mipmap-anydpi-v26/jilatax_launcher.xml +5 -0
  24. package/template/android/app/src/main/res/mipmap-anydpi-v26/jilatax_launcher_round.xml +5 -0
  25. package/template/android/app/src/main/res/values/styles.xml +16 -0
  26. package/template/android/app/src/main/res/values-v31/styles.xml +8 -0
  27. package/template/android/build.gradle.kts +5 -0
  28. package/template/android/gradle/wrapper/gradle-wrapper.jar.base64 +1112 -0
  29. package/template/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  30. package/template/android/gradle.properties +6 -0
  31. package/template/android/gradlew +248 -0
  32. package/template/android/gradlew.bat +92 -0
  33. package/template/android/keystore.properties.example +5 -0
  34. package/template/android/settings.gradle.kts.tmpl +29 -0
  35. package/template/gitignore +22 -0
  36. package/template/lynx.config.ts +17 -0
  37. package/template/src/App.css +95 -0
  38. package/template/src/App.tsx.tmpl +23 -0
  39. package/template/src/index.tsx +9 -0
  40. package/template/src/rspeedy-env.d.ts +1 -0
  41. package/template/src/tsconfig.json +13 -0
  42. package/template/tsconfig.json +15 -0
  43. package/template/tsconfig.node.json +12 -0
package/README.md CHANGED
@@ -1,21 +1,50 @@
1
1
  # create-jilatax
2
2
 
3
- > A minimal TypeScript library package with ESM, CommonJS, and declaration outputs.
3
+ Create an Android-first Lynx application backed by the Jilatax runtime and CLI.
4
4
 
5
- Requires Node.js 22.18 or newer.
5
+ Requires Node.js 22.18 or newer and Bun.
6
6
 
7
- ## Install
7
+ ## Create an application
8
8
 
9
9
  ```bash
10
- npm i create-jilatax
10
+ bunx create-jilatax@latest my-app
11
+ cd my-app
12
+ bun run run:android
11
13
  ```
12
14
 
13
- ## Usage
15
+ The creator asks for the application name, Android package ID, and whether to
16
+ install dependencies. In non-interactive environments, pass the directory and
17
+ options explicitly:
14
18
 
15
- ```ts
16
- import { hello } from "create-jilatax";
19
+ ```bash
20
+ bunx create-jilatax@latest my-app \
21
+ --name "My App" \
22
+ --package-id com.example.my_app \
23
+ --skip-install
24
+ ```
25
+
26
+ Generated projects include:
27
+
28
+ - a Lynx and Rspeedy application;
29
+ - `app.json` as the Jilatax application configuration;
30
+ - an Android Gradle project linked to `jilatax/android`;
31
+ - `bun run run:android` for development on a connected device;
32
+ - `bun run create:aab` for a Play Store Android App Bundle.
33
+
34
+ The creator only writes the project and can run `bun install`. Device, Gradle,
35
+ bundle, APK, and AAB orchestration belongs to `@jilatax/cli`.
17
36
 
18
- hello("world");
37
+ ## Programmatic API
38
+
39
+ ```ts
40
+ import { createProject } from 'create-jilatax';
41
+
42
+ await createProject({
43
+ targetDirectory: './my-app',
44
+ displayName: 'My App',
45
+ packageId: 'com.example.my_app',
46
+ install: false,
47
+ });
19
48
  ```
20
49
 
21
50
  ## Development
@@ -25,21 +54,6 @@ bun install
25
54
  bun run check
26
55
  ```
27
56
 
28
- ## ๐Ÿ“„ License
57
+ ## License
29
58
 
30
59
  MIT ยฉ [JilataX](https://jilatax.dev) โ€” see [`LICENSE`](./LICENSE).
31
-
32
- <br>
33
-
34
- ---
35
-
36
- <div align="center">
37
- <p>
38
- Built with <strong>Bun</strong>, <strong>TypeScript</strong>, and <strong>Lynx</strong>.
39
- </p>
40
- <p>
41
- <a href="https://www.jilatax.dev/jilatax">Website</a> ยท
42
- <a href="https://github.com/jilatax/jilatax">GitHub</a> ยท
43
- <a href="https://www.npmjs.com/package/jilatax">npm</a>
44
- </p>
45
- </div>
@@ -0,0 +1,7 @@
1
+ # Third-party notices
2
+
3
+ The generated Android template includes the Gradle Wrapper from Gradle 8.11.1.
4
+ Gradle is licensed under the Apache License 2.0.
5
+
6
+ - Project: https://github.com/gradle/gradle
7
+ - License: https://www.apache.org/licenses/LICENSE-2.0
package/dist/bin.cjs ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ //#region src/bin.ts
3
+ require("./cli-BO6toXiq.cjs").runCreateCli().then((exitCode) => {
4
+ process.exitCode = exitCode;
5
+ });
6
+ //#endregion
package/dist/bin.d.cts ADDED
@@ -0,0 +1 @@
1
+ export {}
package/dist/bin.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {}
package/dist/bin.js ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import { n as runCreateCli } from "./cli-BQK3vkvN.js";
3
+ //#region src/bin.ts
4
+ runCreateCli().then((exitCode) => {
5
+ process.exitCode = exitCode;
6
+ });
7
+ //#endregion
8
+ export {};
@@ -0,0 +1,450 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+ //#endregion
23
+ let _clack_prompts = require("@clack/prompts");
24
+ _clack_prompts = __toESM(_clack_prompts, 1);
25
+ let node_fs_promises = require("node:fs/promises");
26
+ let node_process = require("node:process");
27
+ let node_child_process = require("node:child_process");
28
+ let node_path = require("node:path");
29
+ node_path = __toESM(node_path, 1);
30
+ let node_url = require("node:url");
31
+ let jilatax = require("jilatax");
32
+ //#region src/generator.ts
33
+ const JILATAX_CLI_VERSION = "^0.0.7";
34
+ const JILATAX_VERSION = "^0.0.5";
35
+ const LYNX_REACT_VERSION = "^0.116.2";
36
+ const LYNX_TYPES_VERSION = "^3.7.0";
37
+ const REACT_PLUGIN_VERSION = "^0.12.7";
38
+ const RSPEEDY_VERSION = "^0.13.3";
39
+ const TEXT_TEMPLATE_FILES = /* @__PURE__ */ new Set([
40
+ "README.md.tmpl",
41
+ "android/settings.gradle.kts.tmpl",
42
+ "src/App.tsx.tmpl"
43
+ ]);
44
+ async function createProject(options) {
45
+ const projectDirectory = node_path.default.resolve(options.targetDirectory);
46
+ const projectName = normalizeProjectName(node_path.default.basename(projectDirectory));
47
+ const displayName = normalizeDisplayName(options.displayName ?? titleCase$1(projectName));
48
+ const packageId = validatePackageId(options.packageId ?? defaultPackageId(projectName));
49
+ const config = createInitialConfig(displayName, projectName, packageId);
50
+ await assertTargetDoesNotExist(projectDirectory);
51
+ const parentDirectory = node_path.default.dirname(projectDirectory);
52
+ await (0, node_fs_promises.mkdir)(parentDirectory, { recursive: true });
53
+ const stagingDirectory = await (0, node_fs_promises.mkdtemp)(node_path.default.join(parentDirectory, `.${projectName}-`));
54
+ try {
55
+ await renderTemplate(stagingDirectory, {
56
+ displayName,
57
+ projectName
58
+ });
59
+ await writeGeneratedMetadata(stagingDirectory, config, projectName);
60
+ await (0, node_fs_promises.rename)(stagingDirectory, projectDirectory);
61
+ } catch (error) {
62
+ await (0, node_fs_promises.rm)(stagingDirectory, {
63
+ force: true,
64
+ recursive: true
65
+ });
66
+ throw error;
67
+ }
68
+ const shouldInstall = options.install === true;
69
+ if (shouldInstall) await (options.installer ?? installWithBun)(projectDirectory);
70
+ return {
71
+ displayName,
72
+ installed: shouldInstall,
73
+ packageId,
74
+ projectDirectory,
75
+ projectName
76
+ };
77
+ }
78
+ function normalizeProjectName(value) {
79
+ const projectName = value.trim().toLowerCase();
80
+ if (!/^[a-z0-9][a-z0-9._-]*$/u.test(projectName) || projectName.length > 214) throw new Error("Project directory name must start with a letter or number and contain only lowercase letters, numbers, dots, hyphens, or underscores.");
81
+ return projectName;
82
+ }
83
+ function normalizeDisplayName(value) {
84
+ const displayName = value.trim().replace(/\s+/gu, " ");
85
+ if (displayName.length === 0 || displayName.length > 80) throw new Error("Application name must contain between 1 and 80 characters.");
86
+ return displayName;
87
+ }
88
+ function defaultPackageId(projectName) {
89
+ return `com.example.${projectName.replace(/[^a-z0-9_]+/gu, "_").replace(/^[^a-z]+/u, "").replace(/_+$/gu, "") || "app"}`;
90
+ }
91
+ function validatePackageId(value) {
92
+ const packageId = value.trim();
93
+ (0, jilatax.parseAppConfig)({ jilatax: {
94
+ android: { package: packageId },
95
+ name: "Package validation"
96
+ } });
97
+ return packageId;
98
+ }
99
+ async function renderTemplate(targetRoot, values) {
100
+ await copyTemplateDirectory((0, node_url.fileURLToPath)(new URL("../template", require("url").pathToFileURL(__filename).href)), targetRoot, "", values);
101
+ }
102
+ async function copyTemplateDirectory(templateRoot, targetRoot, relativeDirectory, values) {
103
+ const entries = await (0, node_fs_promises.readdir)(node_path.default.join(templateRoot, relativeDirectory), { withFileTypes: true });
104
+ for (const entry of entries) {
105
+ const relativeSource = node_path.default.join(relativeDirectory, entry.name);
106
+ const normalizedSource = relativeSource.split(node_path.default.sep).join("/");
107
+ const sourcePath = node_path.default.join(templateRoot, relativeSource);
108
+ if (entry.isSymbolicLink() || !entry.isDirectory() && !entry.isFile()) throw new Error(`Unsupported template entry: ${normalizedSource}`);
109
+ if (entry.isDirectory()) {
110
+ await copyTemplateDirectory(templateRoot, targetRoot, relativeSource, values);
111
+ continue;
112
+ }
113
+ const outputRelative = templateOutputPath(normalizedSource);
114
+ const outputPath = node_path.default.join(targetRoot, ...outputRelative.split("/"));
115
+ await (0, node_fs_promises.mkdir)(node_path.default.dirname(outputPath), { recursive: true });
116
+ if (normalizedSource.endsWith("gradle-wrapper.jar.base64")) {
117
+ const encoded = (await (0, node_fs_promises.readFile)(sourcePath, "utf8")).replace(/\s+/gu, "");
118
+ await (0, node_fs_promises.writeFile)(outputPath, Buffer.from(encoded, "base64"));
119
+ continue;
120
+ }
121
+ if (TEXT_TEMPLATE_FILES.has(normalizedSource)) {
122
+ await (0, node_fs_promises.writeFile)(outputPath, renderTextTemplate(await (0, node_fs_promises.readFile)(sourcePath, "utf8"), values), "utf8");
123
+ continue;
124
+ }
125
+ if (normalizedSource.endsWith(".tmpl")) throw new Error(`Unregistered text template: ${normalizedSource}`);
126
+ await (0, node_fs_promises.copyFile)(sourcePath, outputPath);
127
+ }
128
+ }
129
+ function templateOutputPath(relativeSource) {
130
+ if (relativeSource === "gitignore") return ".gitignore";
131
+ if (relativeSource.endsWith("gradle-wrapper.jar.base64")) return relativeSource.slice(0, -7);
132
+ return relativeSource.endsWith(".tmpl") ? relativeSource.slice(0, -5) : relativeSource;
133
+ }
134
+ function renderTextTemplate(source, values) {
135
+ const replacements = /* @__PURE__ */ new Map([
136
+ ["{{displayNameJson}}", JSON.stringify(values.displayName)],
137
+ ["{{projectName}}", values.projectName],
138
+ ["{{projectNameJson}}", JSON.stringify(values.projectName)]
139
+ ]);
140
+ let rendered = source;
141
+ for (const [token, replacement] of replacements) rendered = rendered.replaceAll(token, replacement);
142
+ const unresolved = rendered.match(/\{\{[A-Za-z][A-Za-z0-9]*\}\}/u);
143
+ if (unresolved !== null) throw new Error(`Unresolved template token: ${unresolved[0]}`);
144
+ return rendered;
145
+ }
146
+ async function writeGeneratedMetadata(projectRoot, config, projectName) {
147
+ const packageJson = {
148
+ name: projectName,
149
+ version: config.jilatax.version,
150
+ private: true,
151
+ type: "module",
152
+ packageManager: "bun@1.3.4",
153
+ engines: { node: ">=22.18.0" },
154
+ scripts: {
155
+ dev: "rspeedy dev",
156
+ build: "rspeedy build",
157
+ typecheck: "tsc -b",
158
+ "run:android": "jilatax run:android",
159
+ "create:aab": "jilatax create:aab"
160
+ },
161
+ dependencies: {
162
+ "@lynx-js/react": LYNX_REACT_VERSION,
163
+ jilatax: JILATAX_VERSION
164
+ },
165
+ devDependencies: {
166
+ "@jilatax/cli": JILATAX_CLI_VERSION,
167
+ "@lynx-js/react-rsbuild-plugin": REACT_PLUGIN_VERSION,
168
+ "@lynx-js/rspeedy": RSPEEDY_VERSION,
169
+ "@lynx-js/types": LYNX_TYPES_VERSION,
170
+ "@types/node": "^22.20.1",
171
+ "@types/react": "^18.3.20",
172
+ typescript: "~5.9.3"
173
+ }
174
+ };
175
+ await (0, node_fs_promises.writeFile)(node_path.default.join(projectRoot, "package.json"), `${JSON.stringify(packageJson, null, 2)}\n`, "utf8");
176
+ await (0, node_fs_promises.writeFile)(node_path.default.join(projectRoot, "app.json"), `${JSON.stringify(config, null, 2)}\n`, "utf8");
177
+ await (0, node_fs_promises.writeFile)(node_path.default.join(projectRoot, "android", "jilatax.properties"), (0, jilatax.serializeAndroidProjectConfig)(config), "utf8");
178
+ if (process.platform !== "win32") await (0, node_fs_promises.chmod)(node_path.default.join(projectRoot, "android", "gradlew"), 493);
179
+ }
180
+ function createInitialConfig(displayName, projectName, packageId) {
181
+ const slug = projectName.replace(/[._-]+/gu, "-").replace(/^-|-$/gu, "");
182
+ const schemeBase = projectName.replace(/[^a-z0-9+.-]+/gu, "-").replace(/^[^a-z]+/u, "");
183
+ return (0, jilatax.parseAppConfig)({
184
+ $schema: "./node_modules/jilatax/schema/app.schema.json",
185
+ jilatax: {
186
+ android: {
187
+ package: packageId,
188
+ predictiveBackGestureEnabled: false,
189
+ versionCode: 1
190
+ },
191
+ name: displayName,
192
+ orientation: "portrait",
193
+ scheme: schemeBase || "jilatax-app",
194
+ slug,
195
+ splash: { backgroundColor: "#0F172A" },
196
+ userInterfaceStyle: "automatic",
197
+ version: "1.0.0"
198
+ }
199
+ });
200
+ }
201
+ async function assertTargetDoesNotExist(target) {
202
+ try {
203
+ await (0, node_fs_promises.lstat)(target);
204
+ } catch (error) {
205
+ if (error.code === "ENOENT") return;
206
+ throw error;
207
+ }
208
+ throw new Error(`Target directory already exists: ${target}`);
209
+ }
210
+ function titleCase$1(value) {
211
+ return value.split(/[-_.\s]+/u).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
212
+ }
213
+ function installWithBun(projectDirectory) {
214
+ return new Promise((resolveInstall, rejectInstall) => {
215
+ const child = (0, node_child_process.spawn)("bun", ["install"], {
216
+ cwd: projectDirectory,
217
+ env: process.env,
218
+ stdio: "inherit",
219
+ windowsHide: true
220
+ });
221
+ child.once("error", rejectInstall);
222
+ child.once("close", (code) => {
223
+ if (code === 0) {
224
+ resolveInstall();
225
+ return;
226
+ }
227
+ rejectInstall(/* @__PURE__ */ new Error(`bun install failed with exit code ${code ?? 1}.`));
228
+ });
229
+ });
230
+ }
231
+ //#endregion
232
+ //#region src/cli.ts
233
+ var PromptCancelledError = class extends Error {};
234
+ async function runCreateCli(args = process.argv.slice(2), services = {}) {
235
+ const log = services.log ?? console.log;
236
+ const warn = services.warn ?? console.error;
237
+ try {
238
+ const parsed = parseArgs(args);
239
+ if (parsed.showHelp) {
240
+ log(createHelpText());
241
+ return 0;
242
+ }
243
+ if (parsed.showVersion) {
244
+ log(await readCreatorVersion());
245
+ return 0;
246
+ }
247
+ const options = services.interactive ?? (node_process.stdin.isTTY && node_process.stdout.isTTY) ? await promptForOptions(parsed) : nonInteractiveOptions(parsed);
248
+ printResult(await (services.create ?? createProject)({
249
+ displayName: options.displayName,
250
+ install: options.install,
251
+ packageId: options.packageId,
252
+ targetDirectory: options.targetDirectory
253
+ }), log);
254
+ return 0;
255
+ } catch (error) {
256
+ if (error instanceof PromptCancelledError) return 0;
257
+ warn(error instanceof Error ? error.message : String(error));
258
+ return 1;
259
+ }
260
+ }
261
+ function createHelpText() {
262
+ return `Create an Android-first Jilatax application.
263
+
264
+ Usage:
265
+ create-jilatax [directory] [options]
266
+
267
+ Options:
268
+ --name <display-name> Human-readable application name
269
+ --package-id <id> Android application ID
270
+ --install Install dependencies with Bun
271
+ --skip-install Generate without installing dependencies
272
+ -h, --help Show this help
273
+ -V, --version Show the installed creator version`;
274
+ }
275
+ function parseArgs(args) {
276
+ let displayName;
277
+ let install;
278
+ let packageId;
279
+ let showHelp = false;
280
+ let showVersion = false;
281
+ let targetDirectory;
282
+ for (let index = 0; index < args.length; index += 1) {
283
+ const argument = args[index];
284
+ if (argument === void 0) continue;
285
+ if (argument === "--install") install = true;
286
+ else if (argument === "--skip-install" || argument === "--no-install") install = false;
287
+ else if (argument === "--name") {
288
+ displayName = readOptionValue(args, index, argument);
289
+ index += 1;
290
+ } else if (argument.startsWith("--name=")) displayName = readInlineValue(argument, "--name");
291
+ else if (argument === "--package-id") {
292
+ packageId = readOptionValue(args, index, argument);
293
+ index += 1;
294
+ } else if (argument.startsWith("--package-id=")) packageId = readInlineValue(argument, "--package-id");
295
+ else if (argument === "--help" || argument === "-h") showHelp = true;
296
+ else if (argument === "--version" || argument === "-V") showVersion = true;
297
+ else if (argument.startsWith("-")) throw new Error(`Unknown option: ${argument}`);
298
+ else if (targetDirectory === void 0) targetDirectory = argument;
299
+ else throw new Error(`Unexpected argument: ${argument}`);
300
+ }
301
+ return {
302
+ ...displayName === void 0 ? {} : { displayName },
303
+ ...install === void 0 ? {} : { install },
304
+ ...packageId === void 0 ? {} : { packageId },
305
+ showHelp,
306
+ showVersion,
307
+ ...targetDirectory === void 0 ? {} : { targetDirectory }
308
+ };
309
+ }
310
+ async function promptForOptions(options) {
311
+ _clack_prompts.intro("Jilatax ยท Android-first Lynx application");
312
+ const targetDirectory = options.targetDirectory ?? unwrapPrompt(await _clack_prompts.text({
313
+ message: "Where should the project be created?",
314
+ placeholder: "./my-jilatax-app",
315
+ validate(value) {
316
+ try {
317
+ normalizeProjectNameFromDirectory(value ?? "");
318
+ } catch (error) {
319
+ return validationMessage(error);
320
+ }
321
+ }
322
+ }));
323
+ const projectName = normalizeProjectNameFromDirectory(targetDirectory);
324
+ const displayName = options.displayName ?? unwrapPrompt(await _clack_prompts.text({
325
+ initialValue: titleCase(projectName),
326
+ message: "Application name",
327
+ validate(value) {
328
+ try {
329
+ normalizeDisplayName(value ?? "");
330
+ } catch (error) {
331
+ return validationMessage(error);
332
+ }
333
+ }
334
+ }));
335
+ const packageId = options.packageId ?? unwrapPrompt(await _clack_prompts.text({
336
+ initialValue: defaultPackageId(projectName),
337
+ message: "Android application ID",
338
+ validate(value) {
339
+ try {
340
+ validatePackageId(value ?? "");
341
+ } catch (error) {
342
+ return validationMessage(error);
343
+ }
344
+ }
345
+ }));
346
+ const install = options.install ?? unwrapPrompt(await _clack_prompts.confirm({
347
+ initialValue: true,
348
+ message: "Install dependencies with Bun?"
349
+ }));
350
+ return {
351
+ displayName: normalizeDisplayName(displayName),
352
+ install,
353
+ packageId: validatePackageId(packageId),
354
+ targetDirectory
355
+ };
356
+ }
357
+ function nonInteractiveOptions(options) {
358
+ if (options.targetDirectory === void 0) throw new Error("Project directory is required in a non-interactive terminal.");
359
+ const projectName = normalizeProjectNameFromDirectory(options.targetDirectory);
360
+ return {
361
+ displayName: normalizeDisplayName(options.displayName ?? titleCase(projectName)),
362
+ install: options.install ?? false,
363
+ packageId: validatePackageId(options.packageId ?? defaultPackageId(projectName)),
364
+ targetDirectory: options.targetDirectory
365
+ };
366
+ }
367
+ function normalizeProjectNameFromDirectory(directory) {
368
+ return normalizeProjectName(directory.trim().replace(/[\\/]+$/gu, "").split(/[\\/]/u).at(-1) ?? "");
369
+ }
370
+ function unwrapPrompt(value) {
371
+ if (_clack_prompts.isCancel(value)) {
372
+ _clack_prompts.cancel("Project creation cancelled.");
373
+ throw new PromptCancelledError();
374
+ }
375
+ return value;
376
+ }
377
+ function validationMessage(error) {
378
+ return error instanceof Error ? error.message : String(error);
379
+ }
380
+ function readOptionValue(args, index, option) {
381
+ const value = args[index + 1];
382
+ if (value === void 0 || value.startsWith("-") || value.trim().length === 0) throw new Error(`${option} requires a value.`);
383
+ return value.trim();
384
+ }
385
+ function readInlineValue(argument, option) {
386
+ const value = argument.slice(`${option}=`.length).trim();
387
+ if (value.length === 0) throw new Error(`${option} requires a value.`);
388
+ return value;
389
+ }
390
+ function titleCase(value) {
391
+ return value.split(/[-_.\s]+/u).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
392
+ }
393
+ function printResult(result, log) {
394
+ const installStep = result.installed ? "" : " bun install\n";
395
+ log(`Created ${result.displayName} in ${result.projectDirectory}.
396
+
397
+ Next steps:
398
+ cd ${JSON.stringify(result.projectDirectory)}
399
+ ${installStep} bun run run:android
400
+
401
+ Release bundle:
402
+ bun run create:aab`);
403
+ }
404
+ async function readCreatorVersion() {
405
+ const packageJson = JSON.parse(await (0, node_fs_promises.readFile)(new URL("../package.json", require("url").pathToFileURL(__filename).href), "utf8"));
406
+ return typeof packageJson.version === "string" ? packageJson.version : "unknown";
407
+ }
408
+ //#endregion
409
+ Object.defineProperty(exports, "createHelpText", {
410
+ enumerable: true,
411
+ get: function() {
412
+ return createHelpText;
413
+ }
414
+ });
415
+ Object.defineProperty(exports, "createProject", {
416
+ enumerable: true,
417
+ get: function() {
418
+ return createProject;
419
+ }
420
+ });
421
+ Object.defineProperty(exports, "defaultPackageId", {
422
+ enumerable: true,
423
+ get: function() {
424
+ return defaultPackageId;
425
+ }
426
+ });
427
+ Object.defineProperty(exports, "normalizeDisplayName", {
428
+ enumerable: true,
429
+ get: function() {
430
+ return normalizeDisplayName;
431
+ }
432
+ });
433
+ Object.defineProperty(exports, "normalizeProjectName", {
434
+ enumerable: true,
435
+ get: function() {
436
+ return normalizeProjectName;
437
+ }
438
+ });
439
+ Object.defineProperty(exports, "runCreateCli", {
440
+ enumerable: true,
441
+ get: function() {
442
+ return runCreateCli;
443
+ }
444
+ });
445
+ Object.defineProperty(exports, "validatePackageId", {
446
+ enumerable: true,
447
+ get: function() {
448
+ return validatePackageId;
449
+ }
450
+ });