create-gtkx 1.0.0 → 1.2.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 +1 -1
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/command.d.ts +3 -14
- package/dist/command.d.ts.map +1 -1
- package/dist/command.js +10 -19
- package/dist/command.js.map +1 -1
- package/dist/package-managers.d.ts +2 -1
- package/dist/package-managers.d.ts.map +1 -1
- package/dist/package-managers.js +1 -1
- package/dist/package-managers.js.map +1 -1
- package/dist/scaffolder.d.ts +2 -3
- package/dist/scaffolder.d.ts.map +1 -1
- package/dist/scaffolder.js +165 -96
- package/dist/scaffolder.js.map +1 -1
- package/dist/templates/.gitignore.ejs +1 -0
- package/dist/templates/data/icons/hicolor/scalable/apps/icon.svg.ejs +5 -0
- package/dist/templates/gtkx.config.ts.ejs +9 -0
- package/dist/templates/package.json.ejs +9 -1
- package/dist/templates/tsconfig.json.ejs +5 -1
- package/dist/templates.d.ts +2 -0
- package/dist/templates.d.ts.map +1 -1
- package/dist/templates.js +2 -2
- package/dist/templates.js.map +1 -1
- package/package.json +9 -4
- package/src/cli.ts +2 -2
- package/src/command.ts +10 -23
- package/src/package-managers.ts +7 -1
- package/src/scaffolder.ts +220 -112
- package/src/templates/.gitignore.ejs +1 -0
- package/src/templates/data/icons/hicolor/scalable/apps/icon.svg.ejs +5 -0
- package/src/templates/gtkx.config.ts.ejs +9 -0
- package/src/templates/package.json.ejs +9 -1
- package/src/templates/tsconfig.json.ejs +5 -1
- package/src/templates.ts +4 -2
package/README.md
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { packageVersion } from "@gtkx/utils";
|
|
2
1
|
import { defineCommand, runMain } from "citty";
|
|
2
|
+
import packageManifest from "../package.json" with { type: "json" };
|
|
3
3
|
import { scaffoldCommand } from "./command.js";
|
|
4
|
-
const version =
|
|
4
|
+
const version = packageManifest.version;
|
|
5
5
|
const main = defineCommand({
|
|
6
6
|
...scaffoldCommand,
|
|
7
7
|
meta: {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,eAAe,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC;AAExC,MAAM,IAAI,GAAG,aAAa,CAAC;IACvB,GAAG,eAAe;IAClB,IAAI,EAAE;QACF,IAAI,EAAE,aAAa;QACnB,OAAO;QACP,WAAW,EAAE,iCAAiC;KACjD;CACJ,CAAC,CAAC;AAEH,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC","sourcesContent":["import { defineCommand, runMain } from \"citty\";\nimport packageManifest from \"../package.json\" with { type: \"json\" };\nimport { scaffoldCommand } from \"./command.js\";\n\nconst version = packageManifest.version;\n\nconst main = defineCommand({\n ...scaffoldCommand,\n meta: {\n name: \"create-gtkx\",\n version,\n description: \"Scaffold a new GTKX application\",\n },\n});\n\nvoid runMain(main);\n"]}
|
package/dist/command.d.ts
CHANGED
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
type CreateCommandArgs = {
|
|
2
|
-
name?: string | undefined;
|
|
3
|
-
"application-id"?: string | undefined;
|
|
4
|
-
"package-manager"?: string | undefined;
|
|
5
|
-
typescript?: boolean | undefined;
|
|
6
|
-
vitest?: boolean | undefined;
|
|
7
|
-
yes?: boolean | undefined;
|
|
8
|
-
"no-interactive"?: boolean | undefined;
|
|
9
|
-
overwrite?: boolean | undefined;
|
|
10
|
-
};
|
|
11
1
|
declare const scaffoldCommand: import("citty").CommandDef<{
|
|
12
2
|
readonly name: {
|
|
13
3
|
readonly type: "positional";
|
|
@@ -20,7 +10,7 @@ declare const scaffoldCommand: import("citty").CommandDef<{
|
|
|
20
10
|
};
|
|
21
11
|
readonly "package-manager": {
|
|
22
12
|
readonly type: "string";
|
|
23
|
-
readonly alias: "
|
|
13
|
+
readonly alias: "p";
|
|
24
14
|
readonly description: string;
|
|
25
15
|
};
|
|
26
16
|
readonly typescript: {
|
|
@@ -43,10 +33,9 @@ declare const scaffoldCommand: import("citty").CommandDef<{
|
|
|
43
33
|
};
|
|
44
34
|
readonly overwrite: {
|
|
45
35
|
readonly type: "boolean";
|
|
46
|
-
readonly alias: "
|
|
36
|
+
readonly alias: "f";
|
|
47
37
|
readonly description: "Overwrite the contents of a non-empty target directory when running without prompts";
|
|
48
38
|
};
|
|
49
39
|
}>;
|
|
50
|
-
|
|
51
|
-
export { scaffoldCommand, runCreate };
|
|
40
|
+
export { scaffoldCommand };
|
|
52
41
|
//# sourceMappingURL=command.d.ts.map
|
package/dist/command.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAkBA,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+CnB,CAAC;AAgCH,OAAO,EAAE,eAAe,EAAE,CAAC"}
|
package/dist/command.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import { errorMessage } from "@gtkx/utils";
|
|
1
3
|
import { defineCommand } from "citty";
|
|
2
4
|
import { OperationCanceledError, ScaffoldAbortedError } from "./errors.js";
|
|
3
|
-
import {
|
|
5
|
+
import { PACKAGE_MANAGER_FLAG_DESCRIPTION } from "./package-managers.js";
|
|
4
6
|
import { scaffold } from "./scaffolder.js";
|
|
5
7
|
const scaffoldCommand = defineCommand({
|
|
6
8
|
meta: {
|
|
@@ -19,7 +21,7 @@ const scaffoldCommand = defineCommand({
|
|
|
19
21
|
},
|
|
20
22
|
"package-manager": {
|
|
21
23
|
type: "string",
|
|
22
|
-
alias: "
|
|
24
|
+
alias: "p",
|
|
23
25
|
description: PACKAGE_MANAGER_FLAG_DESCRIPTION,
|
|
24
26
|
},
|
|
25
27
|
typescript: {
|
|
@@ -43,39 +45,28 @@ const scaffoldCommand = defineCommand({
|
|
|
43
45
|
},
|
|
44
46
|
overwrite: {
|
|
45
47
|
type: "boolean",
|
|
46
|
-
alias: "
|
|
48
|
+
alias: "f",
|
|
47
49
|
description: "Overwrite the contents of a non-empty target directory when running without prompts",
|
|
48
50
|
},
|
|
49
51
|
},
|
|
50
52
|
run: ({ args }) => runCreate(args),
|
|
51
53
|
});
|
|
52
|
-
const parsePackageManager = (value) => {
|
|
53
|
-
if (value === undefined) {
|
|
54
|
-
return undefined;
|
|
55
|
-
}
|
|
56
|
-
if (!isKnownPackageManager(value)) {
|
|
57
|
-
throw new Error(`Unknown package manager "${value}". Expected one of: ${PACKAGE_MANAGER_FLAG_DESCRIPTION}.`);
|
|
58
|
-
}
|
|
59
|
-
return value;
|
|
60
|
-
};
|
|
61
54
|
const settleScaffoldFailure = (error) => {
|
|
62
55
|
if (error instanceof OperationCanceledError) {
|
|
63
56
|
return;
|
|
64
57
|
}
|
|
65
|
-
if (error instanceof ScaffoldAbortedError) {
|
|
66
|
-
|
|
67
|
-
return;
|
|
58
|
+
if (!(error instanceof ScaffoldAbortedError)) {
|
|
59
|
+
p.log.error(errorMessage(error));
|
|
68
60
|
}
|
|
69
|
-
|
|
61
|
+
process.exitCode = 1;
|
|
70
62
|
};
|
|
71
63
|
const runCreate = async (args) => {
|
|
72
64
|
const isInteractive = args["no-interactive"] || args.yes ? false : process.stdin.isTTY;
|
|
73
|
-
const packageManager = parsePackageManager(args["package-manager"]);
|
|
74
65
|
try {
|
|
75
66
|
await scaffold({
|
|
76
67
|
name: args.name,
|
|
77
68
|
applicationId: args["application-id"],
|
|
78
|
-
packageManager,
|
|
69
|
+
packageManager: args["package-manager"],
|
|
79
70
|
isTypescript: args.typescript,
|
|
80
71
|
shouldIncludeTesting: args.vitest,
|
|
81
72
|
isInteractive,
|
|
@@ -86,5 +77,5 @@ const runCreate = async (args) => {
|
|
|
86
77
|
settleScaffoldFailure(error);
|
|
87
78
|
}
|
|
88
79
|
};
|
|
89
|
-
export { scaffoldCommand
|
|
80
|
+
export { scaffoldCommand };
|
|
90
81
|
//# sourceMappingURL=command.js.map
|
package/dist/command.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,gCAAgC,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAa3C,MAAM,eAAe,GAAG,aAAa,CAAC;IAClC,IAAI,EAAE;QACF,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,+BAA+B;KAC/C;IACD,IAAI,EAAE;QACF,IAAI,EAAE;YACF,IAAI,EAAE,YAAY;YAClB,WAAW,EAAE,gEAAgE;YAC7E,QAAQ,EAAE,KAAK;SAClB;QACD,gBAAgB,EAAE;YACd,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,0CAA0C;SAC1D;QACD,iBAAiB,EAAE;YACf,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,GAAG;YACV,WAAW,EAAE,gCAAgC;SAChD;QACD,UAAU,EAAE;YACR,IAAI,EAAE,SAAS;YACf,mBAAmB,EAAE,8DAA8D;YACnF,WAAW,EAAE,wCAAwC;SACxD;QACD,MAAM,EAAE;YACJ,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,gCAAgC;SAChD;QACD,GAAG,EAAE;YACD,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,GAAG;YACV,WAAW,EAAE,0DAA0D;SAC1E;QACD,gBAAgB,EAAE;YACd,IAAI,EAAE,SAAS;YACf,WAAW,EACP,yFAAyF;gBACzF,iBAAiB;SACxB;QACD,SAAS,EAAE;YACP,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,GAAG;YACV,WAAW,EAAE,qFAAqF;SACrG;KACJ;IACD,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC;CACrC,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG,CAAC,KAAc,EAAQ,EAAE;IACnD,IAAI,KAAK,YAAY,sBAAsB,EAAE,CAAC;QAC1C,OAAO;IACX,CAAC;IAED,IAAI,CAAC,CAAC,KAAK,YAAY,oBAAoB,CAAC,EAAE,CAAC;QAC3C,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,KAAK,EAAE,IAAuB,EAAiB,EAAE;IAC/D,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;IAEvF,IAAI,CAAC;QACD,MAAM,QAAQ,CAAC;YACX,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,aAAa,EAAE,IAAI,CAAC,gBAAgB,CAAC;YACrC,cAAc,EAAE,IAAI,CAAC,iBAAiB,CAAC;YACvC,YAAY,EAAE,IAAI,CAAC,UAAU;YAC7B,oBAAoB,EAAE,IAAI,CAAC,MAAM;YACjC,aAAa;YACb,eAAe,EAAE,IAAI,CAAC,SAAS;SAClC,CAAC,CAAC;IACP,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;AACL,CAAC,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,CAAC","sourcesContent":["import * as p from \"@clack/prompts\";\nimport { errorMessage } from \"@gtkx/utils\";\nimport { defineCommand } from \"citty\";\nimport { OperationCanceledError, ScaffoldAbortedError } from \"./errors.js\";\nimport { PACKAGE_MANAGER_FLAG_DESCRIPTION } from \"./package-managers.js\";\nimport { scaffold } from \"./scaffolder.js\";\n\ntype CreateCommandArgs = {\n name?: string | undefined;\n \"application-id\"?: string | undefined;\n \"package-manager\"?: string | undefined;\n typescript?: boolean | undefined;\n vitest?: boolean | undefined;\n yes?: boolean | undefined;\n \"no-interactive\"?: boolean | undefined;\n overwrite?: boolean | undefined;\n};\n\nconst scaffoldCommand = defineCommand({\n meta: {\n name: \"create\",\n description: \"Create a new GTKX application\",\n },\n args: {\n name: {\n type: \"positional\",\n description: \"Target directory or project name (e.g. my-app, ., apps/my-app)\",\n required: false,\n },\n \"application-id\": {\n type: \"string\",\n description: \"Application ID (e.g., com.example.myapp)\",\n },\n \"package-manager\": {\n type: \"string\",\n alias: \"p\",\n description: PACKAGE_MANAGER_FLAG_DESCRIPTION,\n },\n typescript: {\n type: \"boolean\",\n negativeDescription: \"Scaffold the application in JavaScript instead of TypeScript\",\n description: \"Scaffold the application in TypeScript\",\n },\n vitest: {\n type: \"boolean\",\n description: \"Include a Vitest testing setup\",\n },\n yes: {\n type: \"boolean\",\n alias: \"y\",\n description: \"Skip prompts and accept defaults for unspecified options\",\n },\n \"no-interactive\": {\n type: \"boolean\",\n description:\n \"Run without prompts, using the default for every option not passed on the command line \" +\n \"(same as --yes)\",\n },\n overwrite: {\n type: \"boolean\",\n alias: \"f\",\n description: \"Overwrite the contents of a non-empty target directory when running without prompts\",\n },\n },\n run: ({ args }) => runCreate(args),\n});\n\nconst settleScaffoldFailure = (error: unknown): void => {\n if (error instanceof OperationCanceledError) {\n return;\n }\n\n if (!(error instanceof ScaffoldAbortedError)) {\n p.log.error(errorMessage(error));\n }\n\n process.exitCode = 1;\n};\n\nconst runCreate = async (args: CreateCommandArgs): Promise<void> => {\n const isInteractive = args[\"no-interactive\"] || args.yes ? false : process.stdin.isTTY;\n\n try {\n await scaffold({\n name: args.name,\n applicationId: args[\"application-id\"],\n packageManager: args[\"package-manager\"],\n isTypescript: args.typescript,\n shouldIncludeTesting: args.vitest,\n isInteractive,\n shouldOverwrite: args.overwrite,\n });\n } catch (error) {\n settleScaffoldFailure(error);\n }\n};\n\nexport { scaffoldCommand };\n"]}
|
|
@@ -18,7 +18,8 @@ declare const PACKAGE_MANAGERS: readonly [{
|
|
|
18
18
|
readonly addCommand: "yarn add";
|
|
19
19
|
readonly isRecommended: false;
|
|
20
20
|
}];
|
|
21
|
+
declare const PACKAGE_MANAGER_VALUES: PackageManager[];
|
|
21
22
|
declare const PACKAGE_MANAGER_FLAG_DESCRIPTION: string;
|
|
22
23
|
declare const isKnownPackageManager: (name: string) => name is PackageManager;
|
|
23
|
-
export { PACKAGE_MANAGERS, PACKAGE_MANAGER_FLAG_DESCRIPTION, isKnownPackageManager, type PackageManager };
|
|
24
|
+
export { PACKAGE_MANAGERS, PACKAGE_MANAGER_FLAG_DESCRIPTION, PACKAGE_MANAGER_VALUES, isKnownPackageManager, type PackageManager, };
|
|
24
25
|
//# sourceMappingURL=package-managers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-managers.d.ts","sourceRoot":"","sources":["../src/package-managers.ts"],"names":[],"mappings":"AAAA,KAAK,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;AAEjE,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;EAIZ,CAAC;
|
|
1
|
+
{"version":3,"file":"package-managers.d.ts","sourceRoot":"","sources":["../src/package-managers.ts"],"names":[],"mappings":"AAAA,KAAK,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;AAEjE,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;EAIZ,CAAC;AAEX,QAAA,MAAM,sBAAsB,EAAE,cAAc,EAAqD,CAAC;AAClG,QAAA,MAAM,gCAAgC,QAA2D,CAAC;AAElG,QAAA,MAAM,qBAAqB,GAAI,MAAM,MAAM,KAAG,IAAI,IAAI,cACC,CAAC;AAExD,OAAO,EACH,gBAAgB,EAChB,gCAAgC,EAChC,sBAAsB,EACtB,qBAAqB,EACrB,KAAK,cAAc,GACtB,CAAC"}
|
package/dist/package-managers.js
CHANGED
|
@@ -6,5 +6,5 @@ const PACKAGE_MANAGERS = [
|
|
|
6
6
|
const PACKAGE_MANAGER_VALUES = PACKAGE_MANAGERS.map((manager) => manager.value);
|
|
7
7
|
const PACKAGE_MANAGER_FLAG_DESCRIPTION = `Package manager (${PACKAGE_MANAGER_VALUES.join(", ")})`;
|
|
8
8
|
const isKnownPackageManager = (name) => PACKAGE_MANAGER_VALUES.includes(name);
|
|
9
|
-
export { PACKAGE_MANAGERS, PACKAGE_MANAGER_FLAG_DESCRIPTION, isKnownPackageManager };
|
|
9
|
+
export { PACKAGE_MANAGERS, PACKAGE_MANAGER_FLAG_DESCRIPTION, PACKAGE_MANAGER_VALUES, isKnownPackageManager, };
|
|
10
10
|
//# sourceMappingURL=package-managers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-managers.js","sourceRoot":"","sources":["../src/package-managers.ts"],"names":[],"mappings":"AAEA,MAAM,gBAAgB,GAAG;IACrB,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,IAAI,EAAE;IACrG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,EAAE;IAC1G,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,KAAK,EAAE;CAChG,CAAC;AAEX,MAAM,sBAAsB,GAAqB,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAClG,MAAM,gCAAgC,GAAG,oBAAoB,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AAElG,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAA0B,EAAE,CAClE,sBAAmC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAExD,OAAO,
|
|
1
|
+
{"version":3,"file":"package-managers.js","sourceRoot":"","sources":["../src/package-managers.ts"],"names":[],"mappings":"AAEA,MAAM,gBAAgB,GAAG;IACrB,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,IAAI,EAAE;IACrG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,EAAE;IAC1G,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,KAAK,EAAE;CAChG,CAAC;AAEX,MAAM,sBAAsB,GAAqB,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAClG,MAAM,gCAAgC,GAAG,oBAAoB,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AAElG,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAA0B,EAAE,CAClE,sBAAmC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAExD,OAAO,EACH,gBAAgB,EAChB,gCAAgC,EAChC,sBAAsB,EACtB,qBAAqB,GAExB,CAAC","sourcesContent":["type PackageManager = (typeof PACKAGE_MANAGERS)[number][\"value\"];\n\nconst PACKAGE_MANAGERS = [\n { value: \"pnpm\", label: \"pnpm\", devCommand: \"pnpm dev\", addCommand: \"pnpm add\", isRecommended: true },\n { value: \"npm\", label: \"npm\", devCommand: \"npm run dev\", addCommand: \"npm install\", isRecommended: false },\n { value: \"yarn\", label: \"yarn\", devCommand: \"yarn dev\", addCommand: \"yarn add\", isRecommended: false },\n] as const;\n\nconst PACKAGE_MANAGER_VALUES: PackageManager[] = PACKAGE_MANAGERS.map((manager) => manager.value);\nconst PACKAGE_MANAGER_FLAG_DESCRIPTION = `Package manager (${PACKAGE_MANAGER_VALUES.join(\", \")})`;\n\nconst isKnownPackageManager = (name: string): name is PackageManager =>\n (PACKAGE_MANAGER_VALUES as string[]).includes(name);\n\nexport {\n PACKAGE_MANAGERS,\n PACKAGE_MANAGER_FLAG_DESCRIPTION,\n PACKAGE_MANAGER_VALUES,\n isKnownPackageManager,\n type PackageManager,\n};\n"]}
|
package/dist/scaffolder.d.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { type PackageManager } from "./package-managers.js";
|
|
2
1
|
type CreateOptions = {
|
|
3
2
|
name?: string | undefined;
|
|
4
3
|
applicationId?: string | undefined;
|
|
5
|
-
packageManager?:
|
|
4
|
+
packageManager?: string | undefined;
|
|
6
5
|
isTypescript?: boolean | undefined;
|
|
7
6
|
shouldIncludeTesting?: boolean | undefined;
|
|
8
7
|
isInteractive?: boolean | undefined;
|
|
9
8
|
shouldOverwrite?: boolean | undefined;
|
|
10
9
|
};
|
|
11
10
|
declare const scaffold: (options?: CreateOptions) => Promise<void>;
|
|
12
|
-
export { scaffold
|
|
11
|
+
export { scaffold };
|
|
13
12
|
//# sourceMappingURL=scaffolder.d.ts.map
|
package/dist/scaffolder.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffolder.d.ts","sourceRoot":"","sources":["../src/scaffolder.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scaffolder.d.ts","sourceRoot":"","sources":["../src/scaffolder.ts"],"names":[],"mappings":"AAsBA,KAAK,aAAa,GAAG;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,oBAAoB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3C,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACzC,CAAC;AAumBF,QAAA,MAAM,QAAQ,GAAU,UAAS,aAAkB,KAAG,OAAO,CAAC,IAAI,CAcjE,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|
package/dist/scaffolder.js
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
|
-
import { isValidApplicationId } from "@gtkx/config/internal";
|
|
3
|
-
import { errorMessage,
|
|
4
|
-
import {
|
|
2
|
+
import { APPLICATION_ID_MAX_LENGTH, isValidApplicationId } from "@gtkx/config/internal";
|
|
3
|
+
import { errorMessage, tryResolveExecutable, upperFirst } from "@gtkx/utils";
|
|
4
|
+
import { execFileSync } from "node:child_process";
|
|
5
|
+
import { mkdirSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
5
6
|
import { basename, dirname, join, resolve } from "node:path";
|
|
6
7
|
import { addDependency, detectPackageManager as nypmDetectPackageManager } from "nypm";
|
|
7
8
|
import { x } from "tinyexec";
|
|
9
|
+
import packageManifest from "../package.json" with { type: "json" };
|
|
8
10
|
import { writeBuildAllowance } from "./build-allowance.js";
|
|
9
11
|
import { OperationCanceledError, ScaffoldAbortedError } from "./errors.js";
|
|
10
12
|
import { getInstallHint } from "./install-hints.js";
|
|
11
13
|
import { updateManifest } from "./manifest.js";
|
|
12
|
-
import { isKnownPackageManager, PACKAGE_MANAGERS } from "./package-managers.js";
|
|
14
|
+
import { isKnownPackageManager, PACKAGE_MANAGER_VALUES, PACKAGE_MANAGERS, } from "./package-managers.js";
|
|
13
15
|
import { isValidProjectName } from "./project-name.js";
|
|
14
16
|
import { listTemplates, renderFile } from "./templates.js";
|
|
15
|
-
const selfVersion =
|
|
17
|
+
const selfVersion = packageManifest.version;
|
|
18
|
+
const ICON_TEMPLATE_NAME = "icon.svg";
|
|
16
19
|
const GTKX_ENV_MODULE_HEADER = `/**
|
|
17
20
|
* Generated by \`gtkx codegen\`, \`gtkx dev\`, and \`gtkx build\`; do not edit.
|
|
18
21
|
*/`;
|
|
@@ -31,11 +34,33 @@ To run tests, you need a headless Wayland compositor installed:
|
|
|
31
34
|
Fedora: sudo dnf install sway
|
|
32
35
|
Ubuntu: sudo apt install sway`;
|
|
33
36
|
const RECOVERY_HEADING = "Finish the setup by adding the dependencies again, which is safe to repeat:";
|
|
37
|
+
const APPLICATION_ID_FORMAT_ERROR = "Application ID must be reverse domain notation (e.g., com.example.myapp)";
|
|
38
|
+
const APPLICATION_ID_PREFIX = "com.";
|
|
39
|
+
const APPLICATION_ID_SUFFIX = ".app";
|
|
40
|
+
const APPLICATION_ID_SEGMENT_LIMIT = APPLICATION_ID_MAX_LENGTH - APPLICATION_ID_PREFIX.length -
|
|
41
|
+
APPLICATION_ID_SUFFIX.length;
|
|
34
42
|
const pinGtkxDependency = (name, version) => name.startsWith("@gtkx/") ? `${name}@^${version}` : name;
|
|
35
43
|
const getDevCommand = (packageManager) => DEV_COMMAND[packageManager];
|
|
36
44
|
const getAddCommand = (packageManager) => ADD_COMMAND[packageManager];
|
|
37
45
|
const titleFromName = (name) => name.split("-").map((part) => upperFirst(part)).join(" ");
|
|
38
|
-
const
|
|
46
|
+
const gitConfigValue = (key) => {
|
|
47
|
+
const git = tryResolveExecutable("git");
|
|
48
|
+
if (git === undefined) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
return execFileSync(git, ["config", "--get", key], { encoding: "utf8" }).trim() || null;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const applicationIdSegment = (name) => {
|
|
59
|
+
const compact = name.replaceAll("-", "");
|
|
60
|
+
const segment = /^[A-Za-z_]/.test(compact) ? compact : `_${compact}`;
|
|
61
|
+
return segment.slice(0, APPLICATION_ID_SEGMENT_LIMIT);
|
|
62
|
+
};
|
|
63
|
+
const suggestApplicationId = (name) => `${APPLICATION_ID_PREFIX}${applicationIdSegment(name)}${APPLICATION_ID_SUFFIX}`;
|
|
39
64
|
const stripTrailingSlashes = (value) => {
|
|
40
65
|
let end = value.length;
|
|
41
66
|
while (end > 0 && value[end - 1] === "/") {
|
|
@@ -75,37 +100,49 @@ const validateProjectName = (value) => {
|
|
|
75
100
|
}
|
|
76
101
|
return undefined;
|
|
77
102
|
};
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
if (!isValidApplicationId(value)) {
|
|
83
|
-
return "Application ID must be reverse domain notation (e.g., com.example.myapp)";
|
|
84
|
-
}
|
|
85
|
-
return undefined;
|
|
86
|
-
};
|
|
103
|
+
const validateApplicationIdFormat = (value) => isValidApplicationId(value) ? undefined : APPLICATION_ID_FORMAT_ERROR;
|
|
104
|
+
const validateApplicationIdInput = (value) => value ? validateApplicationIdFormat(value) : "Application ID is required";
|
|
105
|
+
const validateApplicationIdAnswer = (value) => value ? validateApplicationIdFormat(value) : undefined;
|
|
87
106
|
const fail = (message) => {
|
|
88
107
|
p.log.error(message);
|
|
89
108
|
throw new ScaffoldAbortedError(message);
|
|
90
109
|
};
|
|
91
|
-
const
|
|
92
|
-
if (
|
|
110
|
+
const requestedPackageManager = (value) => {
|
|
111
|
+
if (value === undefined) {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
if (!isKnownPackageManager(value)) {
|
|
115
|
+
return fail(`Unknown package manager "${value}". Expected one of: ${PACKAGE_MANAGER_VALUES.join(", ")}`);
|
|
116
|
+
}
|
|
117
|
+
return value;
|
|
118
|
+
};
|
|
119
|
+
const targetStats = (root) => {
|
|
120
|
+
try {
|
|
121
|
+
return statSync(root, { throwIfNoEntry: false });
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
const validateTargetDir = (target) => {
|
|
128
|
+
if (!target) {
|
|
93
129
|
return "Project directory is required";
|
|
94
130
|
}
|
|
95
|
-
return validateProjectName(deriveProjectName(
|
|
131
|
+
return validateProjectName(deriveProjectName(target));
|
|
96
132
|
};
|
|
97
|
-
const
|
|
133
|
+
const validateTargetAnswer = (value) => validateTargetDir(formatTargetDir(value ?? ""));
|
|
134
|
+
const promptTarget = async () => formatTargetDir(guardCancellation(await p.text({
|
|
98
135
|
message: "Project directory",
|
|
99
136
|
placeholder: "my-app",
|
|
100
|
-
validate:
|
|
101
|
-
}));
|
|
137
|
+
validate: validateTargetAnswer,
|
|
138
|
+
})));
|
|
102
139
|
const promptApplicationId = async (name) => {
|
|
103
140
|
const defaultApplicationId = suggestApplicationId(name);
|
|
104
141
|
return guardCancellation(await p.text({
|
|
105
142
|
message: "Application ID",
|
|
106
143
|
placeholder: defaultApplicationId,
|
|
107
|
-
|
|
108
|
-
validate:
|
|
144
|
+
defaultValue: defaultApplicationId,
|
|
145
|
+
validate: validateApplicationIdAnswer,
|
|
109
146
|
}));
|
|
110
147
|
};
|
|
111
148
|
const detectPackageManager = async (cwd) => {
|
|
@@ -161,14 +198,10 @@ const emptyDir = (root) => {
|
|
|
161
198
|
rmSync(join(root, entry), { recursive: true, force: true });
|
|
162
199
|
}
|
|
163
200
|
};
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
if (
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
const applicationIdError = validateApplicationIdInput(applicationId);
|
|
170
|
-
if (applicationIdError) {
|
|
171
|
-
fail(applicationIdError);
|
|
201
|
+
const prepareTargetDirectory = (root, shouldEmptyTarget) => {
|
|
202
|
+
mkdirSync(root, { recursive: true });
|
|
203
|
+
if (shouldEmptyTarget) {
|
|
204
|
+
emptyDir(root);
|
|
172
205
|
}
|
|
173
206
|
};
|
|
174
207
|
const shouldOverwriteDirectory = async (target, options) => {
|
|
@@ -180,34 +213,39 @@ const shouldOverwriteDirectory = async (target, options) => {
|
|
|
180
213
|
initialValue: false,
|
|
181
214
|
}));
|
|
182
215
|
};
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
216
|
+
const shouldEmptyTargetDirectory = async (root, target, options) => {
|
|
217
|
+
const stats = targetStats(root);
|
|
218
|
+
if (stats === undefined) {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
if (!stats.isDirectory()) {
|
|
222
|
+
return fail(`Target "${target}" is not a directory`);
|
|
223
|
+
}
|
|
224
|
+
if (isDirEmpty(root)) {
|
|
225
|
+
return false;
|
|
186
226
|
}
|
|
187
227
|
if (await shouldOverwriteDirectory(target, options)) {
|
|
188
|
-
|
|
189
|
-
return;
|
|
228
|
+
return true;
|
|
190
229
|
}
|
|
191
|
-
fail(`Directory "${target}" is not empty`);
|
|
230
|
+
return fail(`Directory "${target}" is not empty`);
|
|
192
231
|
};
|
|
193
232
|
const resolveTarget = async (options) => {
|
|
194
|
-
if (options.name
|
|
195
|
-
return
|
|
233
|
+
if (options.name === undefined && options.isInteractive) {
|
|
234
|
+
return promptTarget();
|
|
196
235
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
return formatTargetDir(await promptTarget());
|
|
236
|
+
const target = formatTargetDir(options.name ?? "");
|
|
237
|
+
const error = validateTargetDir(target);
|
|
238
|
+
return error === undefined ? target : fail(error);
|
|
201
239
|
};
|
|
202
240
|
const resolveApplicationId = async (options, name) => {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
return
|
|
241
|
+
const applicationId = options.applicationId ??
|
|
242
|
+
(options.isInteractive ? await promptApplicationId(name) : suggestApplicationId(name));
|
|
243
|
+
const error = validateApplicationIdInput(applicationId);
|
|
244
|
+
return error === undefined ? applicationId : fail(error);
|
|
207
245
|
};
|
|
208
|
-
const resolvePackageManager = async (options) => {
|
|
209
|
-
if (
|
|
210
|
-
return
|
|
246
|
+
const resolvePackageManager = async (requested, options) => {
|
|
247
|
+
if (requested !== undefined) {
|
|
248
|
+
return requested;
|
|
211
249
|
}
|
|
212
250
|
if (options.isInteractive) {
|
|
213
251
|
return promptPackageManager();
|
|
@@ -227,16 +265,27 @@ const isTestingIncluded = async (options) => {
|
|
|
227
265
|
return options.isInteractive ? shouldSetUpTesting() : true;
|
|
228
266
|
};
|
|
229
267
|
const resolveOptions = async (options) => {
|
|
268
|
+
const requested = requestedPackageManager(options.packageManager);
|
|
230
269
|
const target = await resolveTarget(options);
|
|
231
270
|
const name = deriveProjectName(target);
|
|
232
271
|
const applicationId = await resolveApplicationId(options, name);
|
|
233
|
-
validateResolvedOptions(name, applicationId);
|
|
234
272
|
const root = resolve(process.cwd(), target);
|
|
235
|
-
|
|
236
|
-
const
|
|
273
|
+
const isCurrentDirectory = root === process.cwd();
|
|
274
|
+
const shouldEmptyTarget = await shouldEmptyTargetDirectory(root, target, options);
|
|
275
|
+
const packageManager = await resolvePackageManager(requested, options);
|
|
237
276
|
const isTypescript = await isTypescriptSelected(options);
|
|
238
277
|
const shouldIncludeTesting = await isTestingIncluded(options);
|
|
239
|
-
return {
|
|
278
|
+
return {
|
|
279
|
+
target,
|
|
280
|
+
root,
|
|
281
|
+
isCurrentDirectory,
|
|
282
|
+
name,
|
|
283
|
+
applicationId,
|
|
284
|
+
packageManager,
|
|
285
|
+
isTypescript,
|
|
286
|
+
shouldIncludeTesting,
|
|
287
|
+
shouldEmptyTarget,
|
|
288
|
+
};
|
|
240
289
|
};
|
|
241
290
|
const isTemplateIncluded = (templateRelativePath, resolved) => {
|
|
242
291
|
if (TESTING_TEMPLATES.has(templateRelativePath)) {
|
|
@@ -247,28 +296,32 @@ const isTemplateIncluded = (templateRelativePath, resolved) => {
|
|
|
247
296
|
}
|
|
248
297
|
return true;
|
|
249
298
|
};
|
|
250
|
-
const
|
|
299
|
+
const toScriptExtension = (templateRelativePath, isTypescript) => isTypescript ? templateRelativePath : templateRelativePath.replace(/\.tsx$/, ".jsx").replace(/\.ts$/, ".js");
|
|
300
|
+
const toIconPath = (path, applicationId) => path.endsWith(ICON_TEMPLATE_NAME) ? `${path.slice(0, -ICON_TEMPLATE_NAME.length)}${applicationId}.svg` : path;
|
|
301
|
+
const toDestinationPath = (templateRelativePath, isTypescript, applicationId) => toIconPath(toScriptExtension(templateRelativePath, isTypescript), applicationId);
|
|
251
302
|
const addTestScript = (root) => {
|
|
252
303
|
updateManifest(root, (manifest) => {
|
|
253
304
|
manifest.scripts.test = "vitest run";
|
|
254
305
|
});
|
|
255
306
|
};
|
|
307
|
+
const templateContext = (resolved) => ({
|
|
308
|
+
name: resolved.name,
|
|
309
|
+
applicationId: resolved.applicationId,
|
|
310
|
+
title: titleFromName(resolved.name),
|
|
311
|
+
shouldIncludeTesting: resolved.shouldIncludeTesting,
|
|
312
|
+
isTypescript: resolved.isTypescript,
|
|
313
|
+
importExtension: resolved.isTypescript ? ".js" : ".jsx",
|
|
314
|
+
developerName: gitConfigValue("user.name") ?? titleFromName(resolved.name),
|
|
315
|
+
developerEmail: gitConfigValue("user.email"),
|
|
316
|
+
});
|
|
256
317
|
const scaffoldProject = async (root, resolved) => {
|
|
257
|
-
const {
|
|
258
|
-
const context =
|
|
259
|
-
name,
|
|
260
|
-
applicationId,
|
|
261
|
-
title: titleFromName(name),
|
|
262
|
-
shouldIncludeTesting,
|
|
263
|
-
isTypescript,
|
|
264
|
-
importExtension: isTypescript ? ".js" : ".jsx",
|
|
265
|
-
};
|
|
266
|
-
mkdirSync(root, { recursive: true });
|
|
318
|
+
const { applicationId, isTypescript, shouldIncludeTesting } = resolved;
|
|
319
|
+
const context = templateContext(resolved);
|
|
267
320
|
for (const template of listTemplates()) {
|
|
268
321
|
if (!isTemplateIncluded(template, resolved)) {
|
|
269
322
|
continue;
|
|
270
323
|
}
|
|
271
|
-
const destination = join(root, toDestinationPath(template, isTypescript));
|
|
324
|
+
const destination = join(root, toDestinationPath(template, isTypescript, applicationId));
|
|
272
325
|
mkdirSync(dirname(destination), { recursive: true });
|
|
273
326
|
writeFileSync(destination, await renderFile(template, context));
|
|
274
327
|
}
|
|
@@ -299,40 +352,53 @@ const installDependencies = async (options) => {
|
|
|
299
352
|
});
|
|
300
353
|
};
|
|
301
354
|
const pin = (names) => names.map((dependency) => pinGtkxDependency(dependency, selfVersion));
|
|
302
|
-
const formatRecovery = ({
|
|
303
|
-
const add = getAddCommand(packageManager);
|
|
355
|
+
const formatRecovery = ({ resolved, devDependencies }) => {
|
|
356
|
+
const add = getAddCommand(resolved.packageManager);
|
|
304
357
|
const steps = [
|
|
305
|
-
...(
|
|
358
|
+
...(resolved.isCurrentDirectory ? [] : [`cd ${resolved.target}`]),
|
|
306
359
|
`${add} ${pin(DEPENDENCIES).join(" ")}`,
|
|
307
360
|
`${add} -D ${pin(devDependencies).join(" ")}`,
|
|
308
361
|
];
|
|
309
362
|
const indented = steps.map((step) => ` ${step}`).join("\n");
|
|
310
363
|
return `${RECOVERY_HEADING}\n${indented}`;
|
|
311
364
|
};
|
|
312
|
-
const
|
|
313
|
-
const
|
|
314
|
-
p.log.error(`Failed to install dependencies: ${message}`);
|
|
315
|
-
const hint = getInstallHint(message);
|
|
365
|
+
const explainInstallFailure = (options) => {
|
|
366
|
+
const hint = getInstallHint(errorMessage(options.error));
|
|
316
367
|
if (hint !== undefined) {
|
|
317
368
|
p.log.warn(hint);
|
|
318
369
|
}
|
|
319
370
|
p.log.info(formatRecovery(options));
|
|
320
371
|
};
|
|
321
|
-
const
|
|
322
|
-
const { root, target, packageManager, devDependencies } = options;
|
|
372
|
+
const runWithSpinner = async (step) => {
|
|
323
373
|
const spinner = p.spinner();
|
|
324
|
-
spinner.start(
|
|
374
|
+
spinner.start(step.pending);
|
|
325
375
|
try {
|
|
326
|
-
await
|
|
327
|
-
|
|
328
|
-
spinner.stop("Dependencies installed");
|
|
376
|
+
await step.run();
|
|
377
|
+
spinner.stop(step.done);
|
|
329
378
|
}
|
|
330
379
|
catch (error) {
|
|
331
|
-
spinner.
|
|
332
|
-
|
|
333
|
-
|
|
380
|
+
spinner.error(step.failed);
|
|
381
|
+
p.log.error(errorMessage(error));
|
|
382
|
+
step.explain?.(error);
|
|
383
|
+
throw new ScaffoldAbortedError(step.failed);
|
|
334
384
|
}
|
|
335
385
|
};
|
|
386
|
+
const installAllDependencies = async (options) => {
|
|
387
|
+
const { resolved, devDependencies } = options;
|
|
388
|
+
const { root, packageManager } = resolved;
|
|
389
|
+
await runWithSpinner({
|
|
390
|
+
pending: "Installing dependencies...",
|
|
391
|
+
done: "Dependencies installed",
|
|
392
|
+
failed: "Failed to install dependencies",
|
|
393
|
+
run: async () => {
|
|
394
|
+
await installDependencies({ cwd: root, packageManager, dependencies: pin(DEPENDENCIES), isDev: false });
|
|
395
|
+
await installDependencies({ cwd: root, packageManager, dependencies: pin(devDependencies), isDev: true });
|
|
396
|
+
},
|
|
397
|
+
explain: (error) => {
|
|
398
|
+
explainInstallFailure({ error, resolved, devDependencies });
|
|
399
|
+
},
|
|
400
|
+
});
|
|
401
|
+
};
|
|
336
402
|
const writeInitialEnvModule = (root) => {
|
|
337
403
|
const storeDir = join(root, "node_modules", ".gtkx");
|
|
338
404
|
mkdirSync(storeDir, { recursive: true });
|
|
@@ -349,31 +415,34 @@ const initializeGitRepo = async (root) => {
|
|
|
349
415
|
spinner.stop("Git repository initialized");
|
|
350
416
|
}
|
|
351
417
|
catch {
|
|
352
|
-
spinner.
|
|
418
|
+
spinner.error("Failed to initialize git repository");
|
|
353
419
|
}
|
|
354
420
|
};
|
|
355
421
|
const printNextSteps = (resolved) => {
|
|
356
422
|
const devCmd = getDevCommand(resolved.packageManager);
|
|
357
|
-
const cdStep = resolved.
|
|
423
|
+
const cdStep = resolved.isCurrentDirectory ? "" : `cd ${resolved.target}\n`;
|
|
358
424
|
const testingNote = resolved.shouldIncludeTesting ? HEADLESS_COMPOSITOR_NOTE : "";
|
|
359
425
|
p.note(`${cdStep}${devCmd}${testingNote}`, "Next steps");
|
|
360
426
|
};
|
|
427
|
+
const createProjectStructure = async (root, resolved) => {
|
|
428
|
+
await runWithSpinner({
|
|
429
|
+
pending: "Creating project structure...",
|
|
430
|
+
done: "Project structure created",
|
|
431
|
+
failed: "Failed to create the project structure",
|
|
432
|
+
run: async () => {
|
|
433
|
+
prepareTargetDirectory(root, resolved.shouldEmptyTarget);
|
|
434
|
+
await scaffoldProject(root, resolved);
|
|
435
|
+
writeBuildAllowance(root, resolved.packageManager);
|
|
436
|
+
},
|
|
437
|
+
});
|
|
438
|
+
};
|
|
361
439
|
const scaffold = async (options = {}) => {
|
|
362
440
|
p.intro("Create GTKX App");
|
|
363
441
|
const resolved = await resolveOptions(options);
|
|
364
|
-
const root =
|
|
442
|
+
const { root } = resolved;
|
|
365
443
|
const devDeps = getDevDependencies(resolved);
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
await scaffoldProject(root, resolved);
|
|
369
|
-
writeBuildAllowance(root, resolved.packageManager);
|
|
370
|
-
projectSpinner.stop("Project structure created");
|
|
371
|
-
await installAllDependencies({
|
|
372
|
-
root,
|
|
373
|
-
target: resolved.target,
|
|
374
|
-
packageManager: resolved.packageManager,
|
|
375
|
-
devDependencies: devDeps,
|
|
376
|
-
});
|
|
444
|
+
await createProjectStructure(root, resolved);
|
|
445
|
+
await installAllDependencies({ resolved, devDependencies: devDeps });
|
|
377
446
|
if (resolved.isTypescript) {
|
|
378
447
|
writeInitialEnvModule(root);
|
|
379
448
|
}
|