create-gtkx 2.0.0-beta.2 → 2.0.0-beta.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.
package/dist/command.d.ts CHANGED
@@ -40,6 +40,10 @@ declare const scaffoldCommand: import("citty").CommandDef<{
40
40
  readonly alias: "f";
41
41
  readonly description: "Replace scaffold files in a non-empty target directory when running without prompts";
42
42
  };
43
+ readonly "skip-install": {
44
+ readonly type: "boolean";
45
+ readonly description: "Create the project without installing dependencies";
46
+ };
43
47
  }>;
44
48
  export { scaffoldCommand };
45
49
  //# sourceMappingURL=command.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAmBA,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmDnB,CAAC;AAiCH,OAAO,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAwEA,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuDnB,CAAC;AAoCH,OAAO,EAAE,eAAe,EAAE,CAAC"}
package/dist/command.js CHANGED
@@ -1,9 +1,54 @@
1
1
  import * as p from "@clack/prompts";
2
+ import { assertSupportedNodeVersion } from "@gtkx/config/internal";
2
3
  import { errorMessage } from "@gtkx/utils";
3
4
  import { defineCommand } from "citty";
5
+ import { parseArgs } from "node:util";
4
6
  import { OperationCanceledError, ScaffoldAbortedError } from "./errors.js";
5
7
  import { PACKAGE_MANAGER_FLAG_DESCRIPTION } from "./package-managers.js";
6
8
  import { scaffold } from "./scaffolder.js";
9
+ const STRICT_OPTIONS = {
10
+ "application-id": { type: "string" },
11
+ applicationId: { type: "string" },
12
+ "display-name": { type: "string" },
13
+ displayName: { type: "string" },
14
+ "package-manager": { type: "string", short: "p" },
15
+ packageManager: { type: "string" },
16
+ typescript: { type: "boolean" },
17
+ vitest: { type: "boolean" },
18
+ yes: { type: "boolean", short: "y" },
19
+ "no-interactive": { type: "boolean" },
20
+ noInteractive: { type: "boolean" },
21
+ overwrite: { type: "boolean", short: "f" },
22
+ "skip-install": { type: "boolean" },
23
+ skipInstall: { type: "boolean" },
24
+ };
25
+ const BOOLEAN_OPTIONS = new Set([
26
+ "--typescript",
27
+ "--vitest",
28
+ "--yes",
29
+ "--overwrite",
30
+ "--skip-install",
31
+ "--skipInstall",
32
+ ]);
33
+ const normalizeBooleanArgument = (argument) => {
34
+ const [option, value, ...rest] = argument.split("=");
35
+ if (option === undefined || rest.length > 0 || !BOOLEAN_OPTIONS.has(option)) {
36
+ return argument;
37
+ }
38
+ if (value === "true") {
39
+ return option;
40
+ }
41
+ return value === "false" ? `--no-${option.slice(2)}` : argument;
42
+ };
43
+ const assertKnownArguments = (rawArgs) => {
44
+ parseArgs({
45
+ args: rawArgs.map((argument) => normalizeBooleanArgument(argument)),
46
+ options: STRICT_OPTIONS,
47
+ allowPositionals: true,
48
+ allowNegative: true,
49
+ strict: true,
50
+ });
51
+ };
7
52
  const scaffoldCommand = defineCommand({
8
53
  meta: {
9
54
  name: "create",
@@ -52,8 +97,12 @@ const scaffoldCommand = defineCommand({
52
97
  alias: "f",
53
98
  description: "Replace scaffold files in a non-empty target directory when running without prompts",
54
99
  },
100
+ "skip-install": {
101
+ type: "boolean",
102
+ description: "Create the project without installing dependencies",
103
+ },
55
104
  },
56
- run: ({ args }) => runCreate(args),
105
+ run: ({ args, rawArgs }) => runCreate(args, rawArgs),
57
106
  });
58
107
  const settleScaffoldFailure = (error) => {
59
108
  if (error instanceof OperationCanceledError) {
@@ -64,9 +113,11 @@ const settleScaffoldFailure = (error) => {
64
113
  }
65
114
  process.exitCode = 1;
66
115
  };
67
- const runCreate = async (args) => {
116
+ const runCreate = async (args, rawArgs) => {
68
117
  const isInteractive = args["no-interactive"] || args.yes ? false : process.stdin.isTTY;
69
118
  try {
119
+ assertKnownArguments(rawArgs);
120
+ assertSupportedNodeVersion();
70
121
  await scaffold({
71
122
  name: args.name,
72
123
  applicationId: args["application-id"],
@@ -76,6 +127,7 @@ const runCreate = async (args) => {
76
127
  shouldIncludeTesting: args.vitest,
77
128
  isInteractive,
78
129
  shouldOverwrite: args.overwrite,
130
+ shouldInstallDependencies: args["skip-install"] !== true,
79
131
  });
80
132
  }
81
133
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"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","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 \"display-name\"?: 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 \"display-name\": {\n type: \"string\",\n description: \"Application display name (e.g., My App)\",\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: \"Replace scaffold files in 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 displayName: args[\"display-name\"],\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"]}
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"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","sourcesContent":["import * as p from \"@clack/prompts\";\nimport { assertSupportedNodeVersion } from \"@gtkx/config/internal\";\nimport { errorMessage } from \"@gtkx/utils\";\nimport { defineCommand } from \"citty\";\nimport { parseArgs, type ParseArgsOptionsConfig } from \"node:util\";\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 \"display-name\"?: 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 \"skip-install\"?: boolean | undefined;\n};\n\nconst STRICT_OPTIONS: ParseArgsOptionsConfig = {\n \"application-id\": { type: \"string\" },\n applicationId: { type: \"string\" },\n \"display-name\": { type: \"string\" },\n displayName: { type: \"string\" },\n \"package-manager\": { type: \"string\", short: \"p\" },\n packageManager: { type: \"string\" },\n typescript: { type: \"boolean\" },\n vitest: { type: \"boolean\" },\n yes: { type: \"boolean\", short: \"y\" },\n \"no-interactive\": { type: \"boolean\" },\n noInteractive: { type: \"boolean\" },\n overwrite: { type: \"boolean\", short: \"f\" },\n \"skip-install\": { type: \"boolean\" },\n skipInstall: { type: \"boolean\" },\n};\n\nconst BOOLEAN_OPTIONS: ReadonlySet<string> = new Set([\n \"--typescript\",\n \"--vitest\",\n \"--yes\",\n \"--overwrite\",\n \"--skip-install\",\n \"--skipInstall\",\n]);\n\nconst normalizeBooleanArgument = (argument: string): string => {\n const [option, value, ...rest] = argument.split(\"=\");\n\n if (option === undefined || rest.length > 0 || !BOOLEAN_OPTIONS.has(option)) {\n return argument;\n }\n\n if (value === \"true\") {\n return option;\n }\n\n return value === \"false\" ? `--no-${option.slice(2)}` : argument;\n};\n\nconst assertKnownArguments = (rawArgs: string[]): void => {\n parseArgs({\n args: rawArgs.map((argument) => normalizeBooleanArgument(argument)),\n options: STRICT_OPTIONS,\n allowPositionals: true,\n allowNegative: true,\n strict: true,\n });\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 \"display-name\": {\n type: \"string\",\n description: \"Application display name (e.g., My App)\",\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: \"Replace scaffold files in a non-empty target directory when running without prompts\",\n },\n \"skip-install\": {\n type: \"boolean\",\n description: \"Create the project without installing dependencies\",\n },\n },\n run: ({ args, rawArgs }) => runCreate(args, rawArgs),\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, rawArgs: string[]): Promise<void> => {\n const isInteractive = args[\"no-interactive\"] || args.yes ? false : process.stdin.isTTY;\n\n try {\n assertKnownArguments(rawArgs);\n assertSupportedNodeVersion();\n await scaffold({\n name: args.name,\n applicationId: args[\"application-id\"],\n displayName: args[\"display-name\"],\n packageManager: args[\"package-manager\"],\n isTypescript: args.typescript,\n shouldIncludeTesting: args.vitest,\n isInteractive,\n shouldOverwrite: args.overwrite,\n shouldInstallDependencies: args[\"skip-install\"] !== true,\n });\n } catch (error) {\n settleScaffoldFailure(error);\n }\n};\n\nexport { scaffoldCommand };\n"]}
@@ -4,18 +4,21 @@ declare const PACKAGE_MANAGERS: readonly [{
4
4
  readonly label: "pnpm";
5
5
  readonly devCommand: "pnpm dev";
6
6
  readonly addCommand: "pnpm add";
7
+ readonly installCommand: "pnpm install";
7
8
  readonly isRecommended: true;
8
9
  }, {
9
10
  readonly value: "npm";
10
11
  readonly label: "npm";
11
12
  readonly devCommand: "npm run dev";
12
13
  readonly addCommand: "npm install";
14
+ readonly installCommand: "npm install";
13
15
  readonly isRecommended: false;
14
16
  }, {
15
17
  readonly value: "yarn";
16
18
  readonly label: "yarn";
17
19
  readonly devCommand: "yarn dev";
18
20
  readonly addCommand: "yarn add";
21
+ readonly installCommand: "yarn install";
19
22
  readonly isRecommended: false;
20
23
  }];
21
24
  declare const PACKAGE_MANAGER_VALUES: PackageManager[];
@@ -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;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"}
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;;;;;;;;;;;;;;;;;;;;;EAyBZ,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"}
@@ -1,7 +1,28 @@
1
1
  const PACKAGE_MANAGERS = [
2
- { value: "pnpm", label: "pnpm", devCommand: "pnpm dev", addCommand: "pnpm add", isRecommended: true },
3
- { value: "npm", label: "npm", devCommand: "npm run dev", addCommand: "npm install", isRecommended: false },
4
- { value: "yarn", label: "yarn", devCommand: "yarn dev", addCommand: "yarn add", isRecommended: false },
2
+ {
3
+ value: "pnpm",
4
+ label: "pnpm",
5
+ devCommand: "pnpm dev",
6
+ addCommand: "pnpm add",
7
+ installCommand: "pnpm install",
8
+ isRecommended: true,
9
+ },
10
+ {
11
+ value: "npm",
12
+ label: "npm",
13
+ devCommand: "npm run dev",
14
+ addCommand: "npm install",
15
+ installCommand: "npm install",
16
+ isRecommended: false,
17
+ },
18
+ {
19
+ value: "yarn",
20
+ label: "yarn",
21
+ devCommand: "yarn dev",
22
+ addCommand: "yarn add",
23
+ installCommand: "yarn install",
24
+ isRecommended: false,
25
+ },
5
26
  ];
6
27
  const PACKAGE_MANAGER_VALUES = PACKAGE_MANAGERS.map((manager) => manager.value);
7
28
  const PACKAGE_MANAGER_FLAG_DESCRIPTION = `Package manager (${PACKAGE_MANAGER_VALUES.join(", ")})`;
@@ -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,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"]}
1
+ {"version":3,"file":"package-managers.js","sourceRoot":"","sources":["../src/package-managers.ts"],"names":[],"mappings":"AAEA,MAAM,gBAAgB,GAAG;IACrB;QACI,KAAK,EAAE,MAAM;QACb,KAAK,EAAE,MAAM;QACb,UAAU,EAAE,UAAU;QACtB,UAAU,EAAE,UAAU;QACtB,cAAc,EAAE,cAAc;QAC9B,aAAa,EAAE,IAAI;KACtB;IACD;QACI,KAAK,EAAE,KAAK;QACZ,KAAK,EAAE,KAAK;QACZ,UAAU,EAAE,aAAa;QACzB,UAAU,EAAE,aAAa;QACzB,cAAc,EAAE,aAAa;QAC7B,aAAa,EAAE,KAAK;KACvB;IACD;QACI,KAAK,EAAE,MAAM;QACb,KAAK,EAAE,MAAM;QACb,UAAU,EAAE,UAAU;QACtB,UAAU,EAAE,UAAU;QACtB,cAAc,EAAE,cAAc;QAC9B,aAAa,EAAE,KAAK;KACvB;CACK,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 {\n value: \"pnpm\",\n label: \"pnpm\",\n devCommand: \"pnpm dev\",\n addCommand: \"pnpm add\",\n installCommand: \"pnpm install\",\n isRecommended: true,\n },\n {\n value: \"npm\",\n label: \"npm\",\n devCommand: \"npm run dev\",\n addCommand: \"npm install\",\n installCommand: \"npm install\",\n isRecommended: false,\n },\n {\n value: \"yarn\",\n label: \"yarn\",\n devCommand: \"yarn dev\",\n addCommand: \"yarn add\",\n installCommand: \"yarn install\",\n isRecommended: false,\n },\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"]}
@@ -7,6 +7,7 @@ type CreateOptions = {
7
7
  shouldIncludeTesting?: boolean | undefined;
8
8
  isInteractive?: boolean | undefined;
9
9
  shouldOverwrite?: boolean | undefined;
10
+ shouldInstallDependencies?: boolean | undefined;
10
11
  };
11
12
  declare const scaffold: (options?: CreateOptions) => Promise<void>;
12
13
  export { scaffold };
@@ -1 +1 @@
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,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,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;AA0sBF,QAAA,MAAM,QAAQ,GAAU,UAAS,aAAkB,KAAG,OAAO,CAAC,IAAI,CAUjE,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC"}
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,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,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;IACtC,yBAAyB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACnD,CAAC;AA8yBF,QAAA,MAAM,QAAQ,GAAU,UAAS,aAAkB,KAAG,OAAO,CAAC,IAAI,CAmBjE,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -25,6 +25,7 @@ const TYPESCRIPT_DEV_DEPENDENCIES = ["@types/node", "@types/react", "typescript"
25
25
  const TESTING_DEV_DEPENDENCIES = ["@gtkx/testing", "vitest"];
26
26
  const DEV_COMMAND = Object.fromEntries(PACKAGE_MANAGERS.map((manager) => [manager.value, manager.devCommand]));
27
27
  const ADD_COMMAND = Object.fromEntries(PACKAGE_MANAGERS.map((manager) => [manager.value, manager.addCommand]));
28
+ const INSTALL_COMMAND = Object.fromEntries(PACKAGE_MANAGERS.map((manager) => [manager.value, manager.installCommand]));
28
29
  const INHERITED_SCRIPT_POLICY_VARS = ["npm_config_allow_scripts", "npm_config_allow-scripts"];
29
30
  const TESTING_TEMPLATES = new Set(["vitest.config.ts", "tests/app.test.tsx"]);
30
31
  const TYPESCRIPT_TEMPLATES = new Set(["tsconfig.json", "src/gtkx-env.d.ts"]);
@@ -195,17 +196,36 @@ const shouldOverwriteDirectory = async (target, options) => {
195
196
  initialValue: false,
196
197
  }));
197
198
  };
198
- const validateTargetAvailability = async (root, target, options) => {
199
+ const formatFileList = (heading, files) => {
200
+ const indentedFiles = files.map((file) => ` ${file}`).join("\n");
201
+ return `${heading}:\n${indentedFiles}`;
202
+ };
203
+ const reportPlannedChanges = (changes) => {
204
+ if (changes.length > 0) {
205
+ p.log.info(formatFileList("Scaffold files to replace", changes));
206
+ }
207
+ };
208
+ const reportCompletedChanges = (changes) => {
209
+ if (changes.length > 0) {
210
+ p.log.success(formatFileList("Replaced scaffold files", changes));
211
+ }
212
+ };
213
+ const assertTargetIsDirectory = (root, target) => {
199
214
  const stats = statSync(root, { throwIfNoEntry: false });
215
+ if (stats !== undefined && !stats.isDirectory()) {
216
+ fail(`Target "${target}" is not a directory`);
217
+ }
218
+ };
219
+ const validateTargetAvailability = async (root, target, options, changes) => {
220
+ const stats = statSync(root, { throwIfNoEntry: false });
221
+ assertTargetIsDirectory(root, target);
200
222
  if (stats === undefined) {
201
223
  return;
202
224
  }
203
- if (!stats.isDirectory()) {
204
- return fail(`Target "${target}" is not a directory`);
205
- }
206
225
  if (isDirEmpty(root)) {
207
226
  return;
208
227
  }
228
+ reportPlannedChanges(changes);
209
229
  if (await shouldOverwriteDirectory(target, options)) {
210
230
  return;
211
231
  }
@@ -249,7 +269,6 @@ const resolveOptions = async (options) => {
249
269
  const root = resolve(process.cwd(), target);
250
270
  const isCurrentDirectory = root === process.cwd();
251
271
  const shouldInitialize = shouldInitializeGit(root);
252
- await validateTargetAvailability(root, target, options);
253
272
  const packageManager = await resolvePackageManager(requested, options);
254
273
  const isTypescript = await isOptionEnabled(options.isTypescript, options.isInteractive, "Use TypeScript?");
255
274
  const shouldIncludeTesting = await isOptionEnabled(options.shouldIncludeTesting, options.isInteractive, "Include testing setup (Vitest)?");
@@ -264,6 +283,7 @@ const resolveOptions = async (options) => {
264
283
  isTypescript,
265
284
  shouldIncludeTesting,
266
285
  shouldInitializeGit: shouldInitialize,
286
+ shouldInstallDependencies: options.shouldInstallDependencies !== false,
267
287
  };
268
288
  };
269
289
  const isTemplateIncluded = (templateRelativePath, resolved) => {
@@ -364,16 +384,41 @@ const auxiliaryDestinations = (root, resolved) => [
364
384
  ...(resolved.packageManager === "pnpm" ? [join(root, "pnpm-workspace.yaml")] : []),
365
385
  ...(resolved.isTypescript ? [join(root, "node_modules", ".gtkx", "env.d.ts")] : []),
366
386
  ];
367
- const scaffoldProject = async (root, resolved) => {
387
+ const classifyScaffoldChange = (root, destination) => {
388
+ const entry = lstatSync(destination, { throwIfNoEntry: false });
389
+ if (entry === undefined) {
390
+ return undefined;
391
+ }
392
+ return { destination, relativePath: projectRelativeDestination(root, destination) };
393
+ };
394
+ const addScaffoldChange = (plan, change) => {
395
+ if (change === undefined) {
396
+ return;
397
+ }
398
+ plan.replaceDestinations.push(change.destination);
399
+ plan.changes.push(change.relativePath);
400
+ };
401
+ const planScaffoldProject = async (root, resolved) => {
368
402
  const files = await plannedScaffoldFiles(root, resolved);
369
403
  const destinations = [...files.map((file) => file.destination), ...auxiliaryDestinations(root, resolved)];
370
404
  for (const destination of destinations) {
371
405
  assertSafeDestination(root, destination);
372
406
  }
407
+ const plan = {
408
+ files,
409
+ replaceDestinations: [],
410
+ changes: [],
411
+ };
373
412
  for (const destination of destinations) {
413
+ addScaffoldChange(plan, classifyScaffoldChange(root, destination));
414
+ }
415
+ return plan;
416
+ };
417
+ const scaffoldProject = (root, resolved, plan) => {
418
+ for (const destination of plan.replaceDestinations) {
374
419
  replaceTemplateDestination(destination);
375
420
  }
376
- for (const file of files) {
421
+ for (const file of plan.files) {
377
422
  mkdirSync(dirname(file.destination), { recursive: true });
378
423
  writeFileSync(file.destination, file.contents);
379
424
  }
@@ -406,6 +451,13 @@ const installDependencies = async (options) => {
406
451
  });
407
452
  };
408
453
  const pin = (names) => names.map((dependency) => dependency.startsWith("@gtkx/") ? `${dependency}@^${selfVersion}` : dependency);
454
+ const dependencyVersions = (names) => Object.fromEntries(names.map((dependency) => [dependency, dependency.startsWith("@gtkx/") ? `^${selfVersion}` : "latest"]));
455
+ const writeDependencies = (root, devDependencies) => {
456
+ updateManifest(root, (manifest) => {
457
+ manifest.dependencies = dependencyVersions(DEPENDENCIES);
458
+ manifest.devDependencies = dependencyVersions(devDependencies);
459
+ });
460
+ };
409
461
  const formatRecovery = ({ resolved, devDependencies }) => {
410
462
  const add = ADD_COMMAND[resolved.packageManager];
411
463
  const steps = [
@@ -491,17 +543,18 @@ const initializeGitRepo = async (root, shouldInitialize) => {
491
543
  const printNextSteps = (resolved) => {
492
544
  const devCmd = DEV_COMMAND[resolved.packageManager];
493
545
  const cdStep = resolved.isCurrentDirectory ? "" : `cd ${resolved.target}\n`;
546
+ const installStep = resolved.shouldInstallDependencies ? "" : `${INSTALL_COMMAND[resolved.packageManager]}\n`;
494
547
  const testingNote = resolved.shouldIncludeTesting ? HEADLESS_COMPOSITOR_NOTE : "";
495
- p.note(`${cdStep}${devCmd}${testingNote}`, "Next steps");
548
+ p.note(`${cdStep}${installStep}${devCmd}${testingNote}`, "Next steps");
496
549
  };
497
- const createProjectStructure = async (root, resolved) => {
550
+ const createProjectStructure = async (root, resolved, plan) => {
498
551
  await runWithSpinner({
499
552
  pending: "Creating project structure...",
500
553
  done: "Project structure created",
501
554
  failed: "Failed to create the project structure",
502
- run: async () => {
555
+ run: () => {
503
556
  mkdirSync(root, { recursive: true });
504
- await scaffoldProject(root, resolved);
557
+ scaffoldProject(root, resolved, plan);
505
558
  writeBuildAllowance(root, resolved.packageManager);
506
559
  if (resolved.isTypescript) {
507
560
  writeInitialEnvModule(root);
@@ -514,8 +567,17 @@ const scaffold = async (options = {}) => {
514
567
  const resolved = await resolveOptions(options);
515
568
  const { root } = resolved;
516
569
  const devDeps = getDevDependencies(resolved);
517
- await createProjectStructure(root, resolved);
518
- await installAllDependencies({ resolved, devDependencies: devDeps });
570
+ assertTargetIsDirectory(root, resolved.target);
571
+ const plan = await planScaffoldProject(root, resolved);
572
+ await validateTargetAvailability(root, resolved.target, options, plan.changes);
573
+ await createProjectStructure(root, resolved, plan);
574
+ reportCompletedChanges(plan.changes);
575
+ if (resolved.shouldInstallDependencies) {
576
+ await installAllDependencies({ resolved, devDependencies: devDeps });
577
+ }
578
+ else {
579
+ writeDependencies(root, devDeps);
580
+ }
519
581
  await initializeGitRepo(root, resolved.shouldInitializeGit);
520
582
  printNextSteps(resolved);
521
583
  };
@@ -1 +1 @@
1
- {"version":3,"file":"scaffolder.js","sourceRoot":"","sources":["../src/scaffolder.ts"],"names":[],"mappings":"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","sourcesContent":["import * as p from \"@clack/prompts\";\nimport { APPLICATION_ID_MAX_LENGTH, isValidApplicationId } from \"@gtkx/config/internal\";\nimport { errorMessage, tryResolveExecutable, upperFirst } from \"@gtkx/utils\";\nimport { execFileSync } from \"node:child_process\";\nimport { lstatSync, mkdirSync, readdirSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { basename, dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { addDependency, detectPackageManager as nypmDetectPackageManager } from \"nypm\";\nimport { x } from \"tinyexec\";\nimport packageManifest from \"../package.json\" with { type: \"json\" };\nimport { writeBuildAllowance } from \"./build-allowance.js\";\nimport { OperationCanceledError, ScaffoldAbortedError } from \"./errors.js\";\nimport { getInstallHint } from \"./install-hints.js\";\nimport { updateManifest } from \"./manifest.js\";\nimport {\n isKnownPackageManager,\n PACKAGE_MANAGER_VALUES,\n PACKAGE_MANAGERS,\n type PackageManager,\n} from \"./package-managers.js\";\nimport { isValidProjectName } from \"./project-name.js\";\nimport { listTemplates, renderFile, type TemplateContext } from \"./templates.js\";\n\ntype CreateOptions = {\n name?: string | undefined;\n applicationId?: string | undefined;\n displayName?: string | undefined;\n packageManager?: string | undefined;\n isTypescript?: boolean | undefined;\n shouldIncludeTesting?: boolean | undefined;\n isInteractive?: boolean | undefined;\n shouldOverwrite?: boolean | undefined;\n};\n\ntype ResolvedOptions = {\n target: string;\n root: string;\n isCurrentDirectory: boolean;\n name: string;\n displayName: string;\n applicationId: string;\n packageManager: PackageManager;\n isTypescript: boolean;\n shouldIncludeTesting: boolean;\n shouldInitializeGit: boolean;\n};\n\ntype ScaffoldFile = { destination: string; contents: string };\n\ntype InstallDependenciesOptions = {\n cwd: string;\n packageManager: PackageManager;\n dependencies: string[];\n isDev: boolean;\n};\n\ntype InstallAllOptions = {\n resolved: ResolvedOptions;\n devDependencies: string[];\n};\n\ntype InstallFailureOptions = {\n error: unknown;\n resolved: ResolvedOptions;\n devDependencies: string[];\n};\n\ntype SpinnerStep = {\n pending: string;\n done: string;\n failed: string;\n run: () => Promise<void>;\n explain?: ((error: unknown) => void) | undefined;\n};\n\nconst selfVersion = packageManifest.version;\nconst ICON_TEMPLATE_NAME = \"icon.svg\";\n\nconst GTKX_ENV_MODULE_HEADER = `/**\n * Generated by \\`gtkx codegen\\`, \\`gtkx dev\\`, and \\`gtkx build\\`; do not edit.\n */`;\n\nconst DEPENDENCIES = [\"@gtkx/cairo\", \"@gtkx/css\", \"@gtkx/runtime\", \"@gtkx/react\", \"react\"];\nconst DEV_DEPENDENCIES = [\"@gtkx/cli\", \"@gtkx/config\", \"@gtkx/mcp\", \"vite\"];\nconst TYPESCRIPT_DEV_DEPENDENCIES = [\"@types/node\", \"@types/react\", \"typescript\"];\nconst TESTING_DEV_DEPENDENCIES = [\"@gtkx/testing\", \"vitest\"];\n\nconst DEV_COMMAND: Record<PackageManager, string> = Object.fromEntries(\n PACKAGE_MANAGERS.map((manager) => [manager.value, manager.devCommand]),\n) as Record<PackageManager, string>;\n\nconst ADD_COMMAND: Record<PackageManager, string> = Object.fromEntries(\n PACKAGE_MANAGERS.map((manager) => [manager.value, manager.addCommand]),\n) as Record<PackageManager, string>;\n\nconst INHERITED_SCRIPT_POLICY_VARS = [\"npm_config_allow_scripts\", \"npm_config_allow-scripts\"];\nconst TESTING_TEMPLATES = new Set([\"vitest.config.ts\", \"tests/app.test.tsx\"]);\nconst TYPESCRIPT_TEMPLATES = new Set([\"tsconfig.json\", \"src/gtkx-env.d.ts\"]);\n\nconst HEADLESS_COMPOSITOR_NOTE = `\n\nTo run tests, you need a headless Wayland compositor installed:\n Fedora: sudo dnf install sway\n Ubuntu: sudo apt install sway`;\n\nconst RECOVERY_HEADING = \"Finish the setup by adding the dependencies again, which is safe to repeat:\";\nconst APPLICATION_ID_FORMAT_ERROR = \"Application ID must be reverse domain notation (e.g., com.example.myapp)\";\nconst APPLICATION_ID_PREFIX = \"com.\";\nconst APPLICATION_ID_SUFFIX = \".app\";\n\nconst APPLICATION_ID_SEGMENT_LIMIT = APPLICATION_ID_MAX_LENGTH - APPLICATION_ID_PREFIX.length -\n APPLICATION_ID_SUFFIX.length;\n\nconst displayNameFromProjectName = (name: string): string =>\n name.split(\"-\").map((part) => upperFirst(part)).join(\" \");\n\nconst gitConfigValue = (key: string): string | null => {\n const git = tryResolveExecutable(\"git\");\n\n if (git === undefined) {\n return null;\n }\n\n try {\n return execFileSync(git, [\"config\", \"--get\", key], { encoding: \"utf8\" }).trim() || null;\n } catch {\n return null;\n }\n};\n\nconst applicationIdSegment = (name: string): string => {\n const compact = name.replaceAll(\"-\", \"\");\n const segment = /^[A-Za-z_]/.test(compact) ? compact : `_${compact}`;\n\n return segment.slice(0, APPLICATION_ID_SEGMENT_LIMIT);\n};\n\nconst suggestApplicationId = (name: string): string =>\n `${APPLICATION_ID_PREFIX}${applicationIdSegment(name)}${APPLICATION_ID_SUFFIX}`;\n\nconst stripTrailingSlashes = (value: string): string => {\n let end = value.length;\n\n while (end > 0 && value[end - 1] === \"/\") {\n end--;\n }\n\n return value.slice(0, end);\n};\n\nconst formatTargetDir = (target: string): string =>\n stripTrailingSlashes(target.trim().replaceAll(/[<>:\"\\\\|?*]/g, \"\"));\n\nconst deriveProjectName = (target: string): string => basename(resolve(process.cwd(), target));\n\nconst isDirEmpty = (dir: string): boolean => {\n const entries = readdirSync(dir);\n\n return entries.length === 0 || (entries.length === 1 && entries[0] === \".git\");\n};\n\nconst shouldInitializeGit = (root: string): boolean => {\n const entry = lstatSync(root, { throwIfNoEntry: false });\n\n return entry === undefined || (entry.isDirectory() && readdirSync(root).length === 0);\n};\n\nconst getDevDependencies = ({\n isTypescript,\n shouldIncludeTesting,\n}: Pick<ResolvedOptions, \"isTypescript\" | \"shouldIncludeTesting\">): string[] => {\n const devDeps = [...DEV_DEPENDENCIES];\n\n if (isTypescript) {\n devDeps.push(...TYPESCRIPT_DEV_DEPENDENCIES);\n }\n\n if (shouldIncludeTesting) {\n devDeps.push(...TESTING_DEV_DEPENDENCIES);\n }\n\n return devDeps;\n};\n\nconst guardCancellation = <T>(value: T | symbol): T => {\n if (p.isCancel(value)) {\n p.cancel(\"Operation canceled\");\n throw new OperationCanceledError();\n }\n\n return value;\n};\n\nconst validateProjectName = (value: string | undefined): string | undefined => {\n if (!value) {\n return \"Project name is required\";\n }\n\n if (!isValidProjectName(value)) {\n return \"Project name must be lowercase letters, numbers, and hyphens only\";\n }\n\n return undefined;\n};\n\nconst validateApplicationIdFormat = (value: string): string | undefined =>\n isValidApplicationId(value) ? undefined : APPLICATION_ID_FORMAT_ERROR;\n\nconst validateApplicationIdInput = (value: string | undefined): string | undefined =>\n value ? validateApplicationIdFormat(value) : \"Application ID is required\";\n\nconst validateApplicationIdAnswer = (value: string | undefined): string | undefined =>\n value ? validateApplicationIdFormat(value) : undefined;\n\nconst validateDisplayName = (value: string | undefined): string | undefined => {\n if (value === undefined || value.trim().length === 0) {\n return \"Display name is required\";\n }\n\n return value.includes(\"\\n\") || value.includes(\"\\r\") ? \"Display name must be a single line\" : undefined;\n};\n\nconst validateDisplayNameAnswer = (value: string | undefined): string | undefined =>\n value ? validateDisplayName(value) : undefined;\n\nconst fail = (message: string): never => {\n p.log.error(message);\n throw new ScaffoldAbortedError(message);\n};\n\nconst requestedPackageManager = (value: string | undefined): PackageManager | undefined => {\n if (value === undefined) {\n return undefined;\n }\n\n if (!isKnownPackageManager(value)) {\n return fail(`Unknown package manager \"${value}\". Expected one of: ${PACKAGE_MANAGER_VALUES.join(\", \")}`);\n }\n\n return value;\n};\n\nconst validateTargetDir = (target: string): string | undefined => {\n if (!target) {\n return \"Project directory is required\";\n }\n\n return validateProjectName(deriveProjectName(target));\n};\n\nconst validateTargetAnswer = (value: string | undefined): string | undefined =>\n validateTargetDir(formatTargetDir(value ?? \"\"));\n\nconst promptTarget = async (): Promise<string> =>\n formatTargetDir(\n guardCancellation(\n await p.text({\n message: \"Project directory\",\n placeholder: \"my-app\",\n validate: validateTargetAnswer,\n }),\n ),\n );\n\nconst promptApplicationId = async (name: string): Promise<string> => {\n const defaultApplicationId = suggestApplicationId(name);\n\n return guardCancellation(\n await p.text({\n message: \"Application ID\",\n placeholder: defaultApplicationId,\n defaultValue: defaultApplicationId,\n validate: validateApplicationIdAnswer,\n }),\n );\n};\n\nconst promptDisplayName = async (name: string): Promise<string> => {\n const defaultDisplayName = displayNameFromProjectName(name);\n\n return guardCancellation(\n await p.text({\n message: \"Display name\",\n placeholder: defaultDisplayName,\n defaultValue: defaultDisplayName,\n validate: validateDisplayNameAnswer,\n }),\n );\n};\n\nconst packageManagerOption = (manager: (typeof PACKAGE_MANAGERS)[number], detected: PackageManager | undefined) => {\n let hint: string | undefined;\n\n if (detected === manager.value) {\n hint = \"detected\";\n } else if (manager.isRecommended) {\n hint = \"recommended\";\n }\n\n return { value: manager.value, label: manager.label, ...(hint !== undefined && { hint }) };\n};\n\nconst detectedPackageManager = async (): Promise<PackageManager | undefined> => {\n try {\n const detected = await nypmDetectPackageManager(process.cwd(), { includeParentDirs: true });\n\n return detected && isKnownPackageManager(detected.name) ? detected.name : undefined;\n } catch {\n return undefined;\n }\n};\n\nconst promptPackageManager = async (): Promise<PackageManager> => {\n const detected = await detectedPackageManager();\n const initial: PackageManager = detected ?? \"pnpm\";\n\n return guardCancellation(\n await p.select<PackageManager>({\n message: \"Package manager\",\n options: PACKAGE_MANAGERS.map((manager) => packageManagerOption(manager, detected)),\n initialValue: initial,\n }),\n );\n};\n\nconst isOptionEnabled = async (\n value: boolean | undefined,\n isInteractive: boolean | undefined,\n message: string,\n): Promise<boolean> =>\n value ??\n (isInteractive\n ? guardCancellation(await p.confirm({ message, initialValue: true }))\n : true);\n\nconst shouldOverwriteDirectory = async (target: string, options: CreateOptions): Promise<boolean> => {\n if (!options.isInteractive) {\n return options.shouldOverwrite === true;\n }\n\n return guardCancellation(\n await p.confirm({\n message: `Directory \"${target}\" is not empty. Replace scaffold files?`,\n initialValue: false,\n }),\n );\n};\n\nconst validateTargetAvailability = async (root: string, target: string, options: CreateOptions): Promise<void> => {\n const stats = statSync(root, { throwIfNoEntry: false });\n\n if (stats === undefined) {\n return;\n }\n\n if (!stats.isDirectory()) {\n return fail(`Target \"${target}\" is not a directory`);\n }\n\n if (isDirEmpty(root)) {\n return;\n }\n\n if (await shouldOverwriteDirectory(target, options)) {\n return;\n }\n\n fail(`Directory \"${target}\" is not empty`);\n};\n\nconst resolveTarget = async (options: CreateOptions): Promise<string> => {\n if (options.name === undefined && options.isInteractive) {\n return promptTarget();\n }\n\n const target = formatTargetDir(options.name ?? \"\");\n const error = validateTargetDir(target);\n\n return error === undefined ? target : fail(error);\n};\n\nconst resolveApplicationId = async (options: CreateOptions, name: string): Promise<string> => {\n const applicationId = options.applicationId ??\n (options.isInteractive ? await promptApplicationId(name) : suggestApplicationId(name));\n\n const error = validateApplicationIdInput(applicationId);\n\n return error === undefined ? applicationId : fail(error);\n};\n\nconst resolveDisplayName = async (options: CreateOptions, name: string): Promise<string> => {\n const value = options.displayName ??\n (options.isInteractive ? await promptDisplayName(name) : displayNameFromProjectName(name));\n const error = validateDisplayName(value);\n\n return error === undefined ? value.trim() : fail(error);\n};\n\nconst resolvePackageManager = async (\n requested: PackageManager | undefined,\n options: CreateOptions,\n): Promise<PackageManager> => {\n if (requested !== undefined) {\n return requested;\n }\n\n if (options.isInteractive) {\n return promptPackageManager();\n }\n\n return (await detectedPackageManager()) ?? \"pnpm\";\n};\n\nconst resolveOptions = async (options: CreateOptions): Promise<ResolvedOptions> => {\n const requested = requestedPackageManager(options.packageManager);\n const target = await resolveTarget(options);\n const name = deriveProjectName(target);\n const displayName = await resolveDisplayName(options, name);\n const applicationId = await resolveApplicationId(options, name);\n const root = resolve(process.cwd(), target);\n const isCurrentDirectory = root === process.cwd();\n const shouldInitialize = shouldInitializeGit(root);\n await validateTargetAvailability(root, target, options);\n const packageManager = await resolvePackageManager(requested, options);\n const isTypescript = await isOptionEnabled(options.isTypescript, options.isInteractive, \"Use TypeScript?\");\n\n const shouldIncludeTesting = await isOptionEnabled(\n options.shouldIncludeTesting,\n options.isInteractive,\n \"Include testing setup (Vitest)?\",\n );\n\n return {\n target,\n root,\n isCurrentDirectory,\n name,\n displayName,\n applicationId,\n packageManager,\n isTypescript,\n shouldIncludeTesting,\n shouldInitializeGit: shouldInitialize,\n };\n};\n\nconst isTemplateIncluded = (templateRelativePath: string, resolved: ResolvedOptions): boolean => {\n if (TESTING_TEMPLATES.has(templateRelativePath)) {\n return resolved.shouldIncludeTesting;\n }\n\n if (TYPESCRIPT_TEMPLATES.has(templateRelativePath)) {\n return resolved.isTypescript;\n }\n\n return true;\n};\n\nconst destinationPath = (template: string, resolved: ResolvedOptions): string => {\n const scriptPath = resolved.isTypescript ? template : template.replace(/\\.tsx$/, \".jsx\").replace(/\\.ts$/, \".js\");\n\n return scriptPath.endsWith(ICON_TEMPLATE_NAME)\n ? `${scriptPath.slice(0, -ICON_TEMPLATE_NAME.length)}${resolved.applicationId}.svg`\n : scriptPath;\n};\n\nconst templateContext = (resolved: ResolvedOptions): TemplateContext => ({\n name: resolved.name,\n applicationId: resolved.applicationId,\n displayName: resolved.displayName,\n shouldIncludeTesting: resolved.shouldIncludeTesting,\n isTypescript: resolved.isTypescript,\n importExtension: resolved.isTypescript ? \".js\" : \".jsx\",\n developerName: gitConfigValue(\"user.name\") ?? resolved.displayName,\n developerEmail: gitConfigValue(\"user.email\"),\n});\n\nconst replaceTemplateDestination = (destination: string): void => {\n const entry = lstatSync(destination, { throwIfNoEntry: false });\n\n if (entry === undefined) {\n return;\n }\n\n if (!entry.isFile() && !entry.isSymbolicLink()) {\n fail(`Cannot replace scaffold file because its destination is not a file: ${destination}`);\n }\n\n rmSync(destination, { force: true });\n};\n\nconst projectRelativeDestination = (root: string, destination: string): string => {\n const relativePath = relative(root, destination);\n const isOutsideProject = relativePath.length === 0 || relativePath.startsWith(`..${sep}`) ||\n isAbsolute(relativePath);\n\n if (isOutsideProject) {\n fail(`Scaffold destination is outside the project: ${destination}`);\n }\n\n return relativePath;\n};\n\nconst assertRootIsNotSymbolicLink = (root: string): void => {\n const rootEntry = lstatSync(root, { throwIfNoEntry: false });\n\n if (rootEntry?.isSymbolicLink()) {\n fail(`Cannot scaffold through a symbolic link: ${root}`);\n }\n};\n\nconst assertSafeAncestor = (ancestor: string): void => {\n const entry = lstatSync(ancestor, { throwIfNoEntry: false });\n\n if (entry?.isSymbolicLink()) {\n fail(`Cannot scaffold through a symbolic link: ${ancestor}`);\n }\n\n if (entry !== undefined && !entry.isDirectory()) {\n fail(`Cannot scaffold through a non-directory path: ${ancestor}`);\n }\n};\n\nconst assertSafeAncestors = (root: string, relativePath: string): void => {\n let ancestor = root;\n const segments = relativePath.split(sep);\n const ancestorSegments = segments.slice(0, -1);\n\n for (const segment of ancestorSegments) {\n ancestor = join(ancestor, segment);\n assertSafeAncestor(ancestor);\n }\n};\n\nconst assertReplaceableDestination = (destination: string): void => {\n const entry = lstatSync(destination, { throwIfNoEntry: false });\n const isReplaceable = entry === undefined || entry.isFile() || entry.isSymbolicLink();\n\n if (!isReplaceable) {\n fail(`Cannot replace scaffold file because its destination is not a file: ${destination}`);\n }\n};\n\nconst assertSafeDestination = (root: string, destination: string): void => {\n const relativePath = projectRelativeDestination(root, destination);\n assertRootIsNotSymbolicLink(root);\n assertSafeAncestors(root, relativePath);\n assertReplaceableDestination(destination);\n};\n\nconst plannedScaffoldFiles = async (root: string, resolved: ResolvedOptions): Promise<ScaffoldFile[]> => {\n const context = templateContext(resolved);\n const files: ScaffoldFile[] = [];\n\n for (const template of listTemplates()) {\n if (isTemplateIncluded(template, resolved)) {\n files.push({\n destination: join(root, destinationPath(template, resolved)),\n contents: await renderFile(template, context),\n });\n }\n }\n\n return files;\n};\n\nconst auxiliaryDestinations = (root: string, resolved: ResolvedOptions): string[] => [\n ...(resolved.packageManager === \"pnpm\" ? [join(root, \"pnpm-workspace.yaml\")] : []),\n ...(resolved.isTypescript ? [join(root, \"node_modules\", \".gtkx\", \"env.d.ts\")] : []),\n];\n\nconst scaffoldProject = async (root: string, resolved: ResolvedOptions): Promise<void> => {\n const files = await plannedScaffoldFiles(root, resolved);\n const destinations = [...files.map((file) => file.destination), ...auxiliaryDestinations(root, resolved)];\n\n for (const destination of destinations) {\n assertSafeDestination(root, destination);\n }\n\n for (const destination of destinations) {\n replaceTemplateDestination(destination);\n }\n\n for (const file of files) {\n mkdirSync(dirname(file.destination), { recursive: true });\n writeFileSync(file.destination, file.contents);\n }\n\n if (resolved.shouldIncludeTesting) {\n updateManifest(root, (manifest) => {\n (manifest.scripts as Record<string, string>).test = \"vitest run\";\n });\n }\n};\n\nconst withoutInheritedScriptPolicy = async (run: () => Promise<void>): Promise<void> => {\n const saved = INHERITED_SCRIPT_POLICY_VARS.map((key) => [key, process.env[key]] as const);\n\n for (const [key] of saved) {\n Reflect.deleteProperty(process.env, key);\n }\n\n try {\n await run();\n } finally {\n for (const [key, value] of saved) {\n if (value !== undefined) {\n process.env[key] = value;\n }\n }\n }\n};\n\nconst installDependencies = async (options: InstallDependenciesOptions): Promise<void> => {\n const { cwd, packageManager, dependencies, isDev } = options;\n\n await withoutInheritedScriptPolicy(async () => {\n await addDependency(dependencies, { cwd, packageManager, dev: isDev, silent: true });\n });\n};\n\nconst pin = (names: string[]): string[] =>\n names.map((dependency) => dependency.startsWith(\"@gtkx/\") ? `${dependency}@^${selfVersion}` : dependency);\n\nconst formatRecovery = ({ resolved, devDependencies }: InstallFailureOptions): string => {\n const add = ADD_COMMAND[resolved.packageManager];\n\n const steps = [\n ...(resolved.isCurrentDirectory ? [] : [`cd ${resolved.target}`]),\n `${add} ${pin(DEPENDENCIES).join(\" \")}`,\n `${add} -D ${pin(devDependencies).join(\" \")}`,\n ];\n\n const indented = steps.map((step) => ` ${step}`).join(\"\\n\");\n\n return `${RECOVERY_HEADING}\\n${indented}`;\n};\n\nconst explainInstallFailure = (options: InstallFailureOptions): void => {\n const hint = getInstallHint(errorMessage(options.error));\n\n if (hint !== undefined) {\n p.log.warn(hint);\n }\n\n p.log.info(formatRecovery(options));\n};\n\nconst runWithSpinner = async (step: SpinnerStep): Promise<void> => {\n const spinner = p.spinner();\n spinner.start(step.pending);\n\n try {\n await step.run();\n spinner.stop(step.done);\n } catch (error) {\n spinner.error(step.failed);\n p.log.error(errorMessage(error));\n step.explain?.(error);\n throw new ScaffoldAbortedError(step.failed);\n }\n};\n\nconst installAllDependencies = async (options: InstallAllOptions): Promise<void> => {\n const { resolved, devDependencies } = options;\n const { root, packageManager } = resolved;\n\n await runWithSpinner({\n pending: \"Installing dependencies...\",\n done: \"Dependencies installed\",\n failed: \"Failed to install dependencies\",\n run: async () => {\n await installDependencies({ cwd: root, packageManager, dependencies: pin(DEPENDENCIES), isDev: false });\n await installDependencies({ cwd: root, packageManager, dependencies: pin(devDependencies), isDev: true });\n },\n explain: (error) => {\n explainInstallFailure({ error, resolved, devDependencies });\n },\n });\n};\n\nconst writeInitialEnvModule = (root: string): void => {\n const storeDir = join(root, \"node_modules\", \".gtkx\");\n mkdirSync(storeDir, { recursive: true });\n writeFileSync(join(storeDir, \"env.d.ts\"), `${GTKX_ENV_MODULE_HEADER}\\n`);\n};\n\nconst isInsideGitRepository = (root: string): boolean => {\n const git = tryResolveExecutable(\"git\");\n\n if (git === undefined) {\n return false;\n }\n\n try {\n execFileSync(git, [\"-C\", root, \"rev-parse\", \"--show-toplevel\"], { stdio: \"ignore\" });\n\n return true;\n } catch {\n return false;\n }\n};\n\nconst initializeGitRepo = async (root: string, shouldInitialize: boolean): Promise<void> => {\n if (!shouldInitialize || isInsideGitRepository(root)) {\n return;\n }\n\n const spinner = p.spinner();\n spinner.start(\"Initializing git repository...\");\n\n try {\n const opts = { nodeOptions: { cwd: root }, throwOnError: true } as const;\n await x(\"git\", [\"init\"], opts);\n await x(\"git\", [\"add\", \"-A\"], opts);\n await x(\"git\", [\"commit\", \"-m\", \"Initial commit\"], opts);\n spinner.stop(\"Git repository initialized\");\n } catch {\n spinner.error(\"Failed to initialize git repository\");\n }\n};\n\nconst printNextSteps = (resolved: ResolvedOptions): void => {\n const devCmd = DEV_COMMAND[resolved.packageManager];\n const cdStep = resolved.isCurrentDirectory ? \"\" : `cd ${resolved.target}\\n`;\n const testingNote = resolved.shouldIncludeTesting ? HEADLESS_COMPOSITOR_NOTE : \"\";\n p.note(`${cdStep}${devCmd}${testingNote}`, \"Next steps\");\n};\n\nconst createProjectStructure = async (root: string, resolved: ResolvedOptions): Promise<void> => {\n await runWithSpinner({\n pending: \"Creating project structure...\",\n done: \"Project structure created\",\n failed: \"Failed to create the project structure\",\n run: async () => {\n mkdirSync(root, { recursive: true });\n await scaffoldProject(root, resolved);\n writeBuildAllowance(root, resolved.packageManager);\n\n if (resolved.isTypescript) {\n writeInitialEnvModule(root);\n }\n },\n });\n};\n\nconst scaffold = async (options: CreateOptions = {}): Promise<void> => {\n p.intro(\"Create GTKX App\");\n const resolved = await resolveOptions(options);\n const { root } = resolved;\n const devDeps = getDevDependencies(resolved);\n await createProjectStructure(root, resolved);\n await installAllDependencies({ resolved, devDependencies: devDeps });\n\n await initializeGitRepo(root, resolved.shouldInitializeGit);\n printNextSteps(resolved);\n};\n\nexport { scaffold };\n"]}
1
+ {"version":3,"file":"scaffolder.js","sourceRoot":"","sources":["../src/scaffolder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7F,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACxF,OAAO,EAAE,aAAa,EAAE,oBAAoB,IAAI,wBAAwB,EAAE,MAAM,MAAM,CAAC;AACvF,OAAO,EAAE,CAAC,EAAE,MAAM,UAAU,CAAC;AAC7B,OAAO,eAAe,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACH,qBAAqB,EACrB,sBAAsB,EACtB,gBAAgB,GAEnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAwB,MAAM,gBAAgB,CAAC;AAqEjF,MAAM,WAAW,GAAG,eAAe,CAAC,OAAO,CAAC;AAC5C,MAAM,kBAAkB,GAAG,UAAU,CAAC;AAEtC,MAAM,sBAAsB,GAAG;;IAE3B,CAAC;AAEL,MAAM,YAAY,GAAG,CAAC,aAAa,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;AAC3F,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;AAC5E,MAAM,2BAA2B,GAAG,CAAC,aAAa,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC;AAClF,MAAM,wBAAwB,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;AAE7D,MAAM,WAAW,GAAmC,MAAM,CAAC,WAAW,CAClE,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CACvC,CAAC;AAEpC,MAAM,WAAW,GAAmC,MAAM,CAAC,WAAW,CAClE,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CACvC,CAAC;AAEpC,MAAM,eAAe,GAAmC,MAAM,CAAC,WAAW,CACtE,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,CAC3C,CAAC;AAEpC,MAAM,4BAA4B,GAAG,CAAC,0BAA0B,EAAE,0BAA0B,CAAC,CAAC;AAC9F,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,kBAAkB,EAAE,oBAAoB,CAAC,CAAC,CAAC;AAC9E,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAE7E,MAAM,wBAAwB,GAAG;;;;gCAID,CAAC;AAEjC,MAAM,gBAAgB,GAAG,6EAA6E,CAAC;AACvG,MAAM,2BAA2B,GAAG,0EAA0E,CAAC;AAC/G,MAAM,qBAAqB,GAAG,MAAM,CAAC;AACrC,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAErC,MAAM,4BAA4B,GAAG,yBAAyB,GAAG,qBAAqB,CAAC,MAAM;IACzF,qBAAqB,CAAC,MAAM,CAAC;AAEjC,MAAM,0BAA0B,GAAG,CAAC,IAAY,EAAU,EAAE,CACxD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE9D,MAAM,cAAc,GAAG,CAAC,GAAW,EAAiB,EAAE;IAClD,MAAM,GAAG,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAExC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,CAAC;QACD,OAAO,YAAY,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;IAC5F,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,IAAY,EAAU,EAAE;IAClD,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC;IAErE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,4BAA4B,CAAC,CAAC;AAC1D,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,IAAY,EAAU,EAAE,CAClD,GAAG,qBAAqB,GAAG,oBAAoB,CAAC,IAAI,CAAC,GAAG,qBAAqB,EAAE,CAAC;AAEpF,MAAM,oBAAoB,GAAG,CAAC,KAAa,EAAU,EAAE;IACnD,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC;IAEvB,OAAO,GAAG,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;QACvC,GAAG,EAAE,CAAC;IACV,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,MAAc,EAAU,EAAE,CAC/C,oBAAoB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC;AAEvE,MAAM,iBAAiB,GAAG,CAAC,MAAc,EAAU,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;AAE/F,MAAM,UAAU,GAAG,CAAC,GAAW,EAAW,EAAE;IACxC,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAEjC,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;AACnF,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,IAAY,EAAW,EAAE;IAClD,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;IAEzD,OAAO,KAAK,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;AAC1F,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,EACxB,YAAY,EACZ,oBAAoB,GACyC,EAAY,EAAE;IAC3E,MAAM,OAAO,GAAG,CAAC,GAAG,gBAAgB,CAAC,CAAC;IAEtC,IAAI,YAAY,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,GAAG,2BAA2B,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,oBAAoB,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,GAAG,wBAAwB,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAI,KAAiB,EAAK,EAAE;IAClD,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,CAAC,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAC/B,MAAM,IAAI,sBAAsB,EAAE,CAAC;IACvC,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,KAAyB,EAAsB,EAAE;IAC1E,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,OAAO,0BAA0B,CAAC;IACtC,CAAC;IAED,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,mEAAmE,CAAC;IAC/E,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,2BAA2B,GAAG,CAAC,KAAa,EAAsB,EAAE,CACtE,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,2BAA2B,CAAC;AAE1E,MAAM,0BAA0B,GAAG,CAAC,KAAyB,EAAsB,EAAE,CACjF,KAAK,CAAC,CAAC,CAAC,2BAA2B,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,4BAA4B,CAAC;AAE9E,MAAM,2BAA2B,GAAG,CAAC,KAAyB,EAAsB,EAAE,CAClF,KAAK,CAAC,CAAC,CAAC,2BAA2B,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAE3D,MAAM,mBAAmB,GAAG,CAAC,KAAyB,EAAsB,EAAE;IAC1E,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnD,OAAO,0BAA0B,CAAC;IACtC,CAAC;IAED,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,oCAAoC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3G,CAAC,CAAC;AAEF,MAAM,yBAAyB,GAAG,CAAC,KAAyB,EAAsB,EAAE,CAChF,KAAK,CAAC,CAAC,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAEnD,MAAM,IAAI,GAAG,CAAC,OAAe,EAAS,EAAE;IACpC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACrB,MAAM,IAAI,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAG,CAAC,KAAyB,EAA8B,EAAE;IACtF,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC,4BAA4B,KAAK,uBAAuB,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7G,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,MAAc,EAAsB,EAAE;IAC7D,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,OAAO,+BAA+B,CAAC;IAC3C,CAAC;IAED,OAAO,mBAAmB,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;AAC1D,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,KAAyB,EAAsB,EAAE,CAC3E,iBAAiB,CAAC,eAAe,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;AAEpD,MAAM,YAAY,GAAG,KAAK,IAAqB,EAAE,CAC7C,eAAe,CACX,iBAAiB,CACb,MAAM,CAAC,CAAC,IAAI,CAAC;IACT,OAAO,EAAE,mBAAmB;IAC5B,WAAW,EAAE,QAAQ;IACrB,QAAQ,EAAE,oBAAoB;CACjC,CAAC,CACL,CACJ,CAAC;AAEN,MAAM,mBAAmB,GAAG,KAAK,EAAE,IAAY,EAAmB,EAAE;IAChE,MAAM,oBAAoB,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAExD,OAAO,iBAAiB,CACpB,MAAM,CAAC,CAAC,IAAI,CAAC;QACT,OAAO,EAAE,gBAAgB;QACzB,WAAW,EAAE,oBAAoB;QACjC,YAAY,EAAE,oBAAoB;QAClC,QAAQ,EAAE,2BAA2B;KACxC,CAAC,CACL,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,KAAK,EAAE,IAAY,EAAmB,EAAE;IAC9D,MAAM,kBAAkB,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC;IAE5D,OAAO,iBAAiB,CACpB,MAAM,CAAC,CAAC,IAAI,CAAC;QACT,OAAO,EAAE,cAAc;QACvB,WAAW,EAAE,kBAAkB;QAC/B,YAAY,EAAE,kBAAkB;QAChC,QAAQ,EAAE,yBAAyB;KACtC,CAAC,CACL,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,OAA0C,EAAE,QAAoC,EAAE,EAAE;IAC9G,IAAI,IAAwB,CAAC;IAE7B,IAAI,QAAQ,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,GAAG,UAAU,CAAC;IACtB,CAAC;SAAM,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC/B,IAAI,GAAG,aAAa,CAAC;IACzB,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAC/F,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,KAAK,IAAyC,EAAE;IAC3E,IAAI,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,wBAAwB,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC;QAE5F,OAAO,QAAQ,IAAI,qBAAqB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IACxF,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,SAAS,CAAC;IACrB,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,KAAK,IAA6B,EAAE;IAC7D,MAAM,QAAQ,GAAG,MAAM,sBAAsB,EAAE,CAAC;IAChD,MAAM,OAAO,GAAmB,QAAQ,IAAI,MAAM,CAAC;IAEnD,OAAO,iBAAiB,CACpB,MAAM,CAAC,CAAC,MAAM,CAAiB;QAC3B,OAAO,EAAE,iBAAiB;QAC1B,OAAO,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,oBAAoB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACnF,YAAY,EAAE,OAAO;KACxB,CAAC,CACL,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,KAAK,EACzB,KAA0B,EAC1B,aAAkC,EAClC,OAAe,EACC,EAAE,CAClB,KAAK;IACL,CAAC,aAAa;QACV,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,CAAC,CAAC,IAAI,CAAC,CAAC;AAEhB,MAAM,wBAAwB,GAAG,KAAK,EAAE,MAAc,EAAE,OAAsB,EAAoB,EAAE;IAChG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC,eAAe,KAAK,IAAI,CAAC;IAC5C,CAAC;IAED,OAAO,iBAAiB,CACpB,MAAM,CAAC,CAAC,OAAO,CAAC;QACZ,OAAO,EAAE,cAAc,MAAM,yCAAyC;QACtE,YAAY,EAAE,KAAK;KACtB,CAAC,CACL,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,OAAe,EAAE,KAAe,EAAU,EAAE;IAChE,MAAM,aAAa,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAElE,OAAO,GAAG,OAAO,MAAM,aAAa,EAAE,CAAC;AAC3C,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,OAAwB,EAAQ,EAAE;IAC5D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,2BAA2B,EAAE,OAAO,CAAC,CAAC,CAAC;IACrE,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,CAAC,OAAwB,EAAQ,EAAE;IAC9D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,yBAAyB,EAAE,OAAO,CAAC,CAAC,CAAC;IACtE,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAG,CAAC,IAAY,EAAE,MAAc,EAAQ,EAAE;IACnE,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;IAExD,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QAC9C,IAAI,CAAC,WAAW,MAAM,sBAAsB,CAAC,CAAC;IAClD,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,0BAA0B,GAAG,KAAK,EACpC,IAAY,EACZ,MAAc,EACd,OAAsB,EACtB,OAAwB,EACX,EAAE;IACf,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,uBAAuB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAEtC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO;IACX,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACnB,OAAO;IACX,CAAC;IAED,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAE9B,IAAI,MAAM,wBAAwB,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;QAClD,OAAO;IACX,CAAC;IAED,IAAI,CAAC,cAAc,MAAM,gBAAgB,CAAC,CAAC;AAC/C,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,KAAK,EAAE,OAAsB,EAAmB,EAAE;IACpE,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QACtD,OAAO,YAAY,EAAE,CAAC;IAC1B,CAAC;IAED,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAExC,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,KAAK,EAAE,OAAsB,EAAE,IAAY,EAAmB,EAAE;IACzF,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa;QACvC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC;IAE3F,MAAM,KAAK,GAAG,0BAA0B,CAAC,aAAa,CAAC,CAAC;IAExD,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC7D,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,KAAK,EAAE,OAAsB,EAAE,IAAY,EAAmB,EAAE;IACvF,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW;QAC7B,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/F,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAEzC,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,KAAK,EAC/B,SAAqC,EACrC,OAAsB,EACC,EAAE;IACzB,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QACxB,OAAO,oBAAoB,EAAE,CAAC;IAClC,CAAC;IAED,OAAO,CAAC,MAAM,sBAAsB,EAAE,CAAC,IAAI,MAAM,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,KAAK,EAAE,OAAsB,EAA4B,EAAE;IAC9E,MAAM,SAAS,GAAG,uBAAuB,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5D,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;IAC5C,MAAM,kBAAkB,GAAG,IAAI,KAAK,OAAO,CAAC,GAAG,EAAE,CAAC;IAClD,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,cAAc,GAAG,MAAM,qBAAqB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACvE,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;IAE3G,MAAM,oBAAoB,GAAG,MAAM,eAAe,CAC9C,OAAO,CAAC,oBAAoB,EAC5B,OAAO,CAAC,aAAa,EACrB,iCAAiC,CACpC,CAAC;IAEF,OAAO;QACH,MAAM;QACN,IAAI;QACJ,kBAAkB;QAClB,IAAI;QACJ,WAAW;QACX,aAAa;QACb,cAAc;QACd,YAAY;QACZ,oBAAoB;QACpB,mBAAmB,EAAE,gBAAgB;QACrC,yBAAyB,EAAE,OAAO,CAAC,yBAAyB,KAAK,KAAK;KACzE,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,oBAA4B,EAAE,QAAyB,EAAW,EAAE;IAC5F,IAAI,iBAAiB,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,CAAC;QAC9C,OAAO,QAAQ,CAAC,oBAAoB,CAAC;IACzC,CAAC;IAED,IAAI,oBAAoB,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,CAAC;QACjD,OAAO,QAAQ,CAAC,YAAY,CAAC;IACjC,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAE,QAAyB,EAAU,EAAE;IAC5E,MAAM,UAAU,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAEjH,OAAO,UAAU,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAC1C,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,aAAa,MAAM;QACnF,CAAC,CAAC,UAAU,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,QAAyB,EAAmB,EAAE,CAAC,CAAC;IACrE,IAAI,EAAE,QAAQ,CAAC,IAAI;IACnB,aAAa,EAAE,QAAQ,CAAC,aAAa;IACrC,WAAW,EAAE,QAAQ,CAAC,WAAW;IACjC,oBAAoB,EAAE,QAAQ,CAAC,oBAAoB;IACnD,YAAY,EAAE,QAAQ,CAAC,YAAY;IACnC,eAAe,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM;IACvD,aAAa,EAAE,cAAc,CAAC,WAAW,CAAC,IAAI,QAAQ,CAAC,WAAW;IAClE,cAAc,EAAE,cAAc,CAAC,YAAY,CAAC;CAC/C,CAAC,CAAC;AAEH,MAAM,0BAA0B,GAAG,CAAC,WAAmB,EAAQ,EAAE;IAC7D,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;IAEhE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO;IACX,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;QAC7C,IAAI,CAAC,uEAAuE,WAAW,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,MAAM,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACzC,CAAC,CAAC;AAEF,MAAM,0BAA0B,GAAG,CAAC,IAAY,EAAE,WAAmB,EAAU,EAAE;IAC7E,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IACjD,MAAM,gBAAgB,GAAG,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,YAAY,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC;QACrF,UAAU,CAAC,YAAY,CAAC,CAAC;IAE7B,IAAI,gBAAgB,EAAE,CAAC;QACnB,IAAI,CAAC,gDAAgD,WAAW,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,OAAO,YAAY,CAAC;AACxB,CAAC,CAAC;AAEF,MAAM,2BAA2B,GAAG,CAAC,IAAY,EAAQ,EAAE;IACvD,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;IAE7D,IAAI,SAAS,EAAE,cAAc,EAAE,EAAE,CAAC;QAC9B,IAAI,CAAC,4CAA4C,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,QAAgB,EAAQ,EAAE;IAClD,MAAM,KAAK,GAAG,SAAS,CAAC,QAAQ,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;IAE7D,IAAI,KAAK,EAAE,cAAc,EAAE,EAAE,CAAC;QAC1B,IAAI,CAAC,4CAA4C,QAAQ,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QAC9C,IAAI,CAAC,iDAAiD,QAAQ,EAAE,CAAC,CAAC;IACtE,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,IAAY,EAAE,YAAoB,EAAQ,EAAE;IACrE,IAAI,QAAQ,GAAG,IAAI,CAAC;IACpB,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,gBAAgB,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAE/C,KAAK,MAAM,OAAO,IAAI,gBAAgB,EAAE,CAAC;QACrC,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,4BAA4B,GAAG,CAAC,WAAmB,EAAQ,EAAE;IAC/D,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;IAChE,MAAM,aAAa,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;IAEtF,IAAI,CAAC,aAAa,EAAE,CAAC;QACjB,IAAI,CAAC,uEAAuE,WAAW,EAAE,CAAC,CAAC;IAC/F,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAAE,WAAmB,EAAQ,EAAE;IACtE,MAAM,YAAY,GAAG,0BAA0B,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IACnE,2BAA2B,CAAC,IAAI,CAAC,CAAC;IAClC,mBAAmB,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACxC,4BAA4B,CAAC,WAAW,CAAC,CAAC;AAC9C,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,KAAK,EAAE,IAAY,EAAE,QAAyB,EAA2B,EAAE;IACpG,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAmB,EAAE,CAAC;IAEjC,KAAK,MAAM,QAAQ,IAAI,aAAa,EAAE,EAAE,CAAC;QACrC,IAAI,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;YACzC,KAAK,CAAC,IAAI,CAAC;gBACP,WAAW,EAAE,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBAC5D,QAAQ,EAAE,MAAM,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC;aAChD,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAAE,QAAyB,EAAY,EAAE,CAAC;IACjF,GAAG,CAAC,QAAQ,CAAC,cAAc,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;CACtF,CAAC;AAEF,MAAM,sBAAsB,GAAG,CAC3B,IAAY,EACZ,WAAmB,EACO,EAAE;IAC5B,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;IAEhE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,0BAA0B,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,CAAC;AACxF,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,IAAkB,EAAE,MAAkC,EAAQ,EAAE;IACvF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO;IACX,CAAC;IAED,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAClD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;AAC3C,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,KAAK,EAAE,IAAY,EAAE,QAAyB,EAAyB,EAAE;IACjG,MAAM,KAAK,GAAG,MAAM,oBAAoB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACzD,MAAM,YAAY,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,GAAG,qBAAqB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE1G,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACrC,qBAAqB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,IAAI,GAAiB;QACvB,KAAK;QACL,mBAAmB,EAAE,EAAE;QACvB,OAAO,EAAE,EAAE;KACd,CAAC;IAEF,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACrC,iBAAiB,CAAC,IAAI,EAAE,sBAAsB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;IACvE,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,IAAY,EAAE,QAAyB,EAAE,IAAkB,EAAQ,EAAE;IAC1F,KAAK,MAAM,WAAW,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACjD,0BAA0B,CAAC,WAAW,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC5B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,QAAQ,CAAC,oBAAoB,EAAE,CAAC;QAChC,cAAc,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,EAAE;YAC7B,QAAQ,CAAC,OAAkC,CAAC,IAAI,GAAG,YAAY,CAAC;QACrE,CAAC,CAAC,CAAC;IACP,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,4BAA4B,GAAG,KAAK,EAAE,GAAwB,EAAiB,EAAE;IACnF,MAAM,KAAK,GAAG,4BAA4B,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAU,CAAC,CAAC;IAE1F,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,CAAC;QACD,MAAM,GAAG,EAAE,CAAC;IAChB,CAAC;YAAS,CAAC;QACP,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;YAC/B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACtB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YAC7B,CAAC;QACL,CAAC;IACL,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,KAAK,EAAE,OAAmC,EAAiB,EAAE;IACrF,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAE7D,MAAM,4BAA4B,CAAC,KAAK,IAAI,EAAE;QAC1C,MAAM,aAAa,CAAC,YAAY,EAAE,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,GAAG,GAAG,CAAC,KAAe,EAAY,EAAE,CACtC,KAAK,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,KAAK,WAAW,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;AAE9G,MAAM,kBAAkB,GAAG,CAAC,KAAe,EAA0B,EAAE,CAAC,MAAM,CAAC,WAAW,CACtF,KAAK,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAC1G,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAE,eAAyB,EAAQ,EAAE;IACxE,cAAc,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,EAAE;QAC9B,QAAQ,CAAC,YAAY,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC;QACzD,QAAQ,CAAC,eAAe,GAAG,kBAAkB,CAAC,eAAe,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAyB,EAAU,EAAE;IACpF,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IAEjD,MAAM,KAAK,GAAG;QACV,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACjE,GAAG,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QACvC,GAAG,GAAG,OAAO,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;KAChD,CAAC;IAEF,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE7D,OAAO,GAAG,gBAAgB,KAAK,QAAQ,EAAE,CAAC;AAC9C,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,OAA8B,EAAQ,EAAE;IACnE,MAAM,IAAI,GAAG,cAAc,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAEzD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACrB,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAED,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,KAAK,EAAE,IAAiB,EAAiB,EAAE;IAC9D,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAC5B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE5B,IAAI,CAAC;QACD,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;QACjC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QACtB,MAAM,IAAI,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChD,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,KAAK,EAAE,OAA0B,EAAiB,EAAE;IAC/E,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC;IAC9C,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,QAAQ,CAAC;IAE1C,MAAM,cAAc,CAAC;QACjB,OAAO,EAAE,4BAA4B;QACrC,IAAI,EAAE,wBAAwB;QAC9B,MAAM,EAAE,gCAAgC;QACxC,GAAG,EAAE,KAAK,IAAI,EAAE;YACZ,MAAM,mBAAmB,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,GAAG,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YACxG,MAAM,mBAAmB,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,GAAG,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9G,CAAC;QACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACf,qBAAqB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC,CAAC;QAChE,CAAC;KACJ,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAAQ,EAAE;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;IACrD,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,GAAG,sBAAsB,IAAI,CAAC,CAAC;AAC7E,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAAW,EAAE;IACpD,MAAM,GAAG,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAExC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,IAAI,CAAC;QACD,YAAY,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,iBAAiB,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAErF,OAAO,IAAI,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,KAAK,EAAE,IAAY,EAAE,gBAAyB,EAAiB,EAAE;IACvF,IAAI,CAAC,gBAAgB,IAAI,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO;IACX,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAC5B,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAEhD,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,YAAY,EAAE,IAAI,EAAW,CAAC;QACzE,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,gBAAgB,CAAC,EAAE,IAAI,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,QAAyB,EAAQ,EAAE;IACvD,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,MAAM,IAAI,CAAC;IAC5E,MAAM,WAAW,GAAG,QAAQ,CAAC,yBAAyB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC;IAC9G,MAAM,WAAW,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,CAAC,CAAC,IAAI,CAAC,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,GAAG,WAAW,EAAE,EAAE,YAAY,CAAC,CAAC;AAC3E,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,KAAK,EAChC,IAAY,EACZ,QAAyB,EACzB,IAAkB,EACL,EAAE;IACf,MAAM,cAAc,CAAC;QACjB,OAAO,EAAE,+BAA+B;QACxC,IAAI,EAAE,2BAA2B;QACjC,MAAM,EAAE,wCAAwC;QAChD,GAAG,EAAE,GAAG,EAAE;YACN,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACrC,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;YACtC,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;YAEnD,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;gBACxB,qBAAqB,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC;QACL,CAAC;KACJ,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,KAAK,EAAE,UAAyB,EAAE,EAAiB,EAAE;IAClE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC3B,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC;IAC/C,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;IAC1B,MAAM,OAAO,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC7C,uBAAuB,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACvD,MAAM,0BAA0B,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/E,MAAM,sBAAsB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IACnD,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAErC,IAAI,QAAQ,CAAC,yBAAyB,EAAE,CAAC;QACrC,MAAM,sBAAsB,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC,CAAC;IACzE,CAAC;SAAM,CAAC;QACJ,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IAC5D,cAAc,CAAC,QAAQ,CAAC,CAAC;AAC7B,CAAC,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC","sourcesContent":["import * as p from \"@clack/prompts\";\nimport { APPLICATION_ID_MAX_LENGTH, isValidApplicationId } from \"@gtkx/config/internal\";\nimport { errorMessage, tryResolveExecutable, upperFirst } from \"@gtkx/utils\";\nimport { execFileSync } from \"node:child_process\";\nimport { lstatSync, mkdirSync, readdirSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { basename, dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { addDependency, detectPackageManager as nypmDetectPackageManager } from \"nypm\";\nimport { x } from \"tinyexec\";\nimport packageManifest from \"../package.json\" with { type: \"json\" };\nimport { writeBuildAllowance } from \"./build-allowance.js\";\nimport { OperationCanceledError, ScaffoldAbortedError } from \"./errors.js\";\nimport { getInstallHint } from \"./install-hints.js\";\nimport { updateManifest } from \"./manifest.js\";\nimport {\n isKnownPackageManager,\n PACKAGE_MANAGER_VALUES,\n PACKAGE_MANAGERS,\n type PackageManager,\n} from \"./package-managers.js\";\nimport { isValidProjectName } from \"./project-name.js\";\nimport { listTemplates, renderFile, type TemplateContext } from \"./templates.js\";\n\ntype CreateOptions = {\n name?: string | undefined;\n applicationId?: string | undefined;\n displayName?: string | undefined;\n packageManager?: string | undefined;\n isTypescript?: boolean | undefined;\n shouldIncludeTesting?: boolean | undefined;\n isInteractive?: boolean | undefined;\n shouldOverwrite?: boolean | undefined;\n shouldInstallDependencies?: boolean | undefined;\n};\n\ntype ResolvedOptions = {\n target: string;\n root: string;\n isCurrentDirectory: boolean;\n name: string;\n displayName: string;\n applicationId: string;\n packageManager: PackageManager;\n isTypescript: boolean;\n shouldIncludeTesting: boolean;\n shouldInitializeGit: boolean;\n shouldInstallDependencies: boolean;\n};\n\ntype ScaffoldFile = { destination: string; contents: string };\n\ntype ScaffoldChanges = string[];\n\ntype ScaffoldPlan = {\n files: ScaffoldFile[];\n replaceDestinations: string[];\n changes: ScaffoldChanges;\n};\n\ntype ScaffoldChange = {\n destination: string;\n relativePath: string;\n};\n\ntype InstallDependenciesOptions = {\n cwd: string;\n packageManager: PackageManager;\n dependencies: string[];\n isDev: boolean;\n};\n\ntype InstallAllOptions = {\n resolved: ResolvedOptions;\n devDependencies: string[];\n};\n\ntype InstallFailureOptions = {\n error: unknown;\n resolved: ResolvedOptions;\n devDependencies: string[];\n};\n\ntype SpinnerStep = {\n pending: string;\n done: string;\n failed: string;\n run: () => Promise<void> | void;\n explain?: ((error: unknown) => void) | undefined;\n};\n\nconst selfVersion = packageManifest.version;\nconst ICON_TEMPLATE_NAME = \"icon.svg\";\n\nconst GTKX_ENV_MODULE_HEADER = `/**\n * Generated by \\`gtkx codegen\\`, \\`gtkx dev\\`, and \\`gtkx build\\`; do not edit.\n */`;\n\nconst DEPENDENCIES = [\"@gtkx/cairo\", \"@gtkx/css\", \"@gtkx/runtime\", \"@gtkx/react\", \"react\"];\nconst DEV_DEPENDENCIES = [\"@gtkx/cli\", \"@gtkx/config\", \"@gtkx/mcp\", \"vite\"];\nconst TYPESCRIPT_DEV_DEPENDENCIES = [\"@types/node\", \"@types/react\", \"typescript\"];\nconst TESTING_DEV_DEPENDENCIES = [\"@gtkx/testing\", \"vitest\"];\n\nconst DEV_COMMAND: Record<PackageManager, string> = Object.fromEntries(\n PACKAGE_MANAGERS.map((manager) => [manager.value, manager.devCommand]),\n) as Record<PackageManager, string>;\n\nconst ADD_COMMAND: Record<PackageManager, string> = Object.fromEntries(\n PACKAGE_MANAGERS.map((manager) => [manager.value, manager.addCommand]),\n) as Record<PackageManager, string>;\n\nconst INSTALL_COMMAND: Record<PackageManager, string> = Object.fromEntries(\n PACKAGE_MANAGERS.map((manager) => [manager.value, manager.installCommand]),\n) as Record<PackageManager, string>;\n\nconst INHERITED_SCRIPT_POLICY_VARS = [\"npm_config_allow_scripts\", \"npm_config_allow-scripts\"];\nconst TESTING_TEMPLATES = new Set([\"vitest.config.ts\", \"tests/app.test.tsx\"]);\nconst TYPESCRIPT_TEMPLATES = new Set([\"tsconfig.json\", \"src/gtkx-env.d.ts\"]);\n\nconst HEADLESS_COMPOSITOR_NOTE = `\n\nTo run tests, you need a headless Wayland compositor installed:\n Fedora: sudo dnf install sway\n Ubuntu: sudo apt install sway`;\n\nconst RECOVERY_HEADING = \"Finish the setup by adding the dependencies again, which is safe to repeat:\";\nconst APPLICATION_ID_FORMAT_ERROR = \"Application ID must be reverse domain notation (e.g., com.example.myapp)\";\nconst APPLICATION_ID_PREFIX = \"com.\";\nconst APPLICATION_ID_SUFFIX = \".app\";\n\nconst APPLICATION_ID_SEGMENT_LIMIT = APPLICATION_ID_MAX_LENGTH - APPLICATION_ID_PREFIX.length -\n APPLICATION_ID_SUFFIX.length;\n\nconst displayNameFromProjectName = (name: string): string =>\n name.split(\"-\").map((part) => upperFirst(part)).join(\" \");\n\nconst gitConfigValue = (key: string): string | null => {\n const git = tryResolveExecutable(\"git\");\n\n if (git === undefined) {\n return null;\n }\n\n try {\n return execFileSync(git, [\"config\", \"--get\", key], { encoding: \"utf8\" }).trim() || null;\n } catch {\n return null;\n }\n};\n\nconst applicationIdSegment = (name: string): string => {\n const compact = name.replaceAll(\"-\", \"\");\n const segment = /^[A-Za-z_]/.test(compact) ? compact : `_${compact}`;\n\n return segment.slice(0, APPLICATION_ID_SEGMENT_LIMIT);\n};\n\nconst suggestApplicationId = (name: string): string =>\n `${APPLICATION_ID_PREFIX}${applicationIdSegment(name)}${APPLICATION_ID_SUFFIX}`;\n\nconst stripTrailingSlashes = (value: string): string => {\n let end = value.length;\n\n while (end > 0 && value[end - 1] === \"/\") {\n end--;\n }\n\n return value.slice(0, end);\n};\n\nconst formatTargetDir = (target: string): string =>\n stripTrailingSlashes(target.trim().replaceAll(/[<>:\"\\\\|?*]/g, \"\"));\n\nconst deriveProjectName = (target: string): string => basename(resolve(process.cwd(), target));\n\nconst isDirEmpty = (dir: string): boolean => {\n const entries = readdirSync(dir);\n\n return entries.length === 0 || (entries.length === 1 && entries[0] === \".git\");\n};\n\nconst shouldInitializeGit = (root: string): boolean => {\n const entry = lstatSync(root, { throwIfNoEntry: false });\n\n return entry === undefined || (entry.isDirectory() && readdirSync(root).length === 0);\n};\n\nconst getDevDependencies = ({\n isTypescript,\n shouldIncludeTesting,\n}: Pick<ResolvedOptions, \"isTypescript\" | \"shouldIncludeTesting\">): string[] => {\n const devDeps = [...DEV_DEPENDENCIES];\n\n if (isTypescript) {\n devDeps.push(...TYPESCRIPT_DEV_DEPENDENCIES);\n }\n\n if (shouldIncludeTesting) {\n devDeps.push(...TESTING_DEV_DEPENDENCIES);\n }\n\n return devDeps;\n};\n\nconst guardCancellation = <T>(value: T | symbol): T => {\n if (p.isCancel(value)) {\n p.cancel(\"Operation canceled\");\n throw new OperationCanceledError();\n }\n\n return value;\n};\n\nconst validateProjectName = (value: string | undefined): string | undefined => {\n if (!value) {\n return \"Project name is required\";\n }\n\n if (!isValidProjectName(value)) {\n return \"Project name must be lowercase letters, numbers, and hyphens only\";\n }\n\n return undefined;\n};\n\nconst validateApplicationIdFormat = (value: string): string | undefined =>\n isValidApplicationId(value) ? undefined : APPLICATION_ID_FORMAT_ERROR;\n\nconst validateApplicationIdInput = (value: string | undefined): string | undefined =>\n value ? validateApplicationIdFormat(value) : \"Application ID is required\";\n\nconst validateApplicationIdAnswer = (value: string | undefined): string | undefined =>\n value ? validateApplicationIdFormat(value) : undefined;\n\nconst validateDisplayName = (value: string | undefined): string | undefined => {\n if (value === undefined || value.trim().length === 0) {\n return \"Display name is required\";\n }\n\n return value.includes(\"\\n\") || value.includes(\"\\r\") ? \"Display name must be a single line\" : undefined;\n};\n\nconst validateDisplayNameAnswer = (value: string | undefined): string | undefined =>\n value ? validateDisplayName(value) : undefined;\n\nconst fail = (message: string): never => {\n p.log.error(message);\n throw new ScaffoldAbortedError(message);\n};\n\nconst requestedPackageManager = (value: string | undefined): PackageManager | undefined => {\n if (value === undefined) {\n return undefined;\n }\n\n if (!isKnownPackageManager(value)) {\n return fail(`Unknown package manager \"${value}\". Expected one of: ${PACKAGE_MANAGER_VALUES.join(\", \")}`);\n }\n\n return value;\n};\n\nconst validateTargetDir = (target: string): string | undefined => {\n if (!target) {\n return \"Project directory is required\";\n }\n\n return validateProjectName(deriveProjectName(target));\n};\n\nconst validateTargetAnswer = (value: string | undefined): string | undefined =>\n validateTargetDir(formatTargetDir(value ?? \"\"));\n\nconst promptTarget = async (): Promise<string> =>\n formatTargetDir(\n guardCancellation(\n await p.text({\n message: \"Project directory\",\n placeholder: \"my-app\",\n validate: validateTargetAnswer,\n }),\n ),\n );\n\nconst promptApplicationId = async (name: string): Promise<string> => {\n const defaultApplicationId = suggestApplicationId(name);\n\n return guardCancellation(\n await p.text({\n message: \"Application ID\",\n placeholder: defaultApplicationId,\n defaultValue: defaultApplicationId,\n validate: validateApplicationIdAnswer,\n }),\n );\n};\n\nconst promptDisplayName = async (name: string): Promise<string> => {\n const defaultDisplayName = displayNameFromProjectName(name);\n\n return guardCancellation(\n await p.text({\n message: \"Display name\",\n placeholder: defaultDisplayName,\n defaultValue: defaultDisplayName,\n validate: validateDisplayNameAnswer,\n }),\n );\n};\n\nconst packageManagerOption = (manager: (typeof PACKAGE_MANAGERS)[number], detected: PackageManager | undefined) => {\n let hint: string | undefined;\n\n if (detected === manager.value) {\n hint = \"detected\";\n } else if (manager.isRecommended) {\n hint = \"recommended\";\n }\n\n return { value: manager.value, label: manager.label, ...(hint !== undefined && { hint }) };\n};\n\nconst detectedPackageManager = async (): Promise<PackageManager | undefined> => {\n try {\n const detected = await nypmDetectPackageManager(process.cwd(), { includeParentDirs: true });\n\n return detected && isKnownPackageManager(detected.name) ? detected.name : undefined;\n } catch {\n return undefined;\n }\n};\n\nconst promptPackageManager = async (): Promise<PackageManager> => {\n const detected = await detectedPackageManager();\n const initial: PackageManager = detected ?? \"pnpm\";\n\n return guardCancellation(\n await p.select<PackageManager>({\n message: \"Package manager\",\n options: PACKAGE_MANAGERS.map((manager) => packageManagerOption(manager, detected)),\n initialValue: initial,\n }),\n );\n};\n\nconst isOptionEnabled = async (\n value: boolean | undefined,\n isInteractive: boolean | undefined,\n message: string,\n): Promise<boolean> =>\n value ??\n (isInteractive\n ? guardCancellation(await p.confirm({ message, initialValue: true }))\n : true);\n\nconst shouldOverwriteDirectory = async (target: string, options: CreateOptions): Promise<boolean> => {\n if (!options.isInteractive) {\n return options.shouldOverwrite === true;\n }\n\n return guardCancellation(\n await p.confirm({\n message: `Directory \"${target}\" is not empty. Replace scaffold files?`,\n initialValue: false,\n }),\n );\n};\n\nconst formatFileList = (heading: string, files: string[]): string => {\n const indentedFiles = files.map((file) => ` ${file}`).join(\"\\n\");\n\n return `${heading}:\\n${indentedFiles}`;\n};\n\nconst reportPlannedChanges = (changes: ScaffoldChanges): void => {\n if (changes.length > 0) {\n p.log.info(formatFileList(\"Scaffold files to replace\", changes));\n }\n};\n\nconst reportCompletedChanges = (changes: ScaffoldChanges): void => {\n if (changes.length > 0) {\n p.log.success(formatFileList(\"Replaced scaffold files\", changes));\n }\n};\n\nconst assertTargetIsDirectory = (root: string, target: string): void => {\n const stats = statSync(root, { throwIfNoEntry: false });\n\n if (stats !== undefined && !stats.isDirectory()) {\n fail(`Target \"${target}\" is not a directory`);\n }\n};\n\nconst validateTargetAvailability = async (\n root: string,\n target: string,\n options: CreateOptions,\n changes: ScaffoldChanges,\n): Promise<void> => {\n const stats = statSync(root, { throwIfNoEntry: false });\n assertTargetIsDirectory(root, target);\n\n if (stats === undefined) {\n return;\n }\n\n if (isDirEmpty(root)) {\n return;\n }\n\n reportPlannedChanges(changes);\n\n if (await shouldOverwriteDirectory(target, options)) {\n return;\n }\n\n fail(`Directory \"${target}\" is not empty`);\n};\n\nconst resolveTarget = async (options: CreateOptions): Promise<string> => {\n if (options.name === undefined && options.isInteractive) {\n return promptTarget();\n }\n\n const target = formatTargetDir(options.name ?? \"\");\n const error = validateTargetDir(target);\n\n return error === undefined ? target : fail(error);\n};\n\nconst resolveApplicationId = async (options: CreateOptions, name: string): Promise<string> => {\n const applicationId = options.applicationId ??\n (options.isInteractive ? await promptApplicationId(name) : suggestApplicationId(name));\n\n const error = validateApplicationIdInput(applicationId);\n\n return error === undefined ? applicationId : fail(error);\n};\n\nconst resolveDisplayName = async (options: CreateOptions, name: string): Promise<string> => {\n const value = options.displayName ??\n (options.isInteractive ? await promptDisplayName(name) : displayNameFromProjectName(name));\n const error = validateDisplayName(value);\n\n return error === undefined ? value.trim() : fail(error);\n};\n\nconst resolvePackageManager = async (\n requested: PackageManager | undefined,\n options: CreateOptions,\n): Promise<PackageManager> => {\n if (requested !== undefined) {\n return requested;\n }\n\n if (options.isInteractive) {\n return promptPackageManager();\n }\n\n return (await detectedPackageManager()) ?? \"pnpm\";\n};\n\nconst resolveOptions = async (options: CreateOptions): Promise<ResolvedOptions> => {\n const requested = requestedPackageManager(options.packageManager);\n const target = await resolveTarget(options);\n const name = deriveProjectName(target);\n const displayName = await resolveDisplayName(options, name);\n const applicationId = await resolveApplicationId(options, name);\n const root = resolve(process.cwd(), target);\n const isCurrentDirectory = root === process.cwd();\n const shouldInitialize = shouldInitializeGit(root);\n const packageManager = await resolvePackageManager(requested, options);\n const isTypescript = await isOptionEnabled(options.isTypescript, options.isInteractive, \"Use TypeScript?\");\n\n const shouldIncludeTesting = await isOptionEnabled(\n options.shouldIncludeTesting,\n options.isInteractive,\n \"Include testing setup (Vitest)?\",\n );\n\n return {\n target,\n root,\n isCurrentDirectory,\n name,\n displayName,\n applicationId,\n packageManager,\n isTypescript,\n shouldIncludeTesting,\n shouldInitializeGit: shouldInitialize,\n shouldInstallDependencies: options.shouldInstallDependencies !== false,\n };\n};\n\nconst isTemplateIncluded = (templateRelativePath: string, resolved: ResolvedOptions): boolean => {\n if (TESTING_TEMPLATES.has(templateRelativePath)) {\n return resolved.shouldIncludeTesting;\n }\n\n if (TYPESCRIPT_TEMPLATES.has(templateRelativePath)) {\n return resolved.isTypescript;\n }\n\n return true;\n};\n\nconst destinationPath = (template: string, resolved: ResolvedOptions): string => {\n const scriptPath = resolved.isTypescript ? template : template.replace(/\\.tsx$/, \".jsx\").replace(/\\.ts$/, \".js\");\n\n return scriptPath.endsWith(ICON_TEMPLATE_NAME)\n ? `${scriptPath.slice(0, -ICON_TEMPLATE_NAME.length)}${resolved.applicationId}.svg`\n : scriptPath;\n};\n\nconst templateContext = (resolved: ResolvedOptions): TemplateContext => ({\n name: resolved.name,\n applicationId: resolved.applicationId,\n displayName: resolved.displayName,\n shouldIncludeTesting: resolved.shouldIncludeTesting,\n isTypescript: resolved.isTypescript,\n importExtension: resolved.isTypescript ? \".js\" : \".jsx\",\n developerName: gitConfigValue(\"user.name\") ?? resolved.displayName,\n developerEmail: gitConfigValue(\"user.email\"),\n});\n\nconst replaceTemplateDestination = (destination: string): void => {\n const entry = lstatSync(destination, { throwIfNoEntry: false });\n\n if (entry === undefined) {\n return;\n }\n\n if (!entry.isFile() && !entry.isSymbolicLink()) {\n fail(`Cannot replace scaffold file because its destination is not a file: ${destination}`);\n }\n\n rmSync(destination, { force: true });\n};\n\nconst projectRelativeDestination = (root: string, destination: string): string => {\n const relativePath = relative(root, destination);\n const isOutsideProject = relativePath.length === 0 || relativePath.startsWith(`..${sep}`) ||\n isAbsolute(relativePath);\n\n if (isOutsideProject) {\n fail(`Scaffold destination is outside the project: ${destination}`);\n }\n\n return relativePath;\n};\n\nconst assertRootIsNotSymbolicLink = (root: string): void => {\n const rootEntry = lstatSync(root, { throwIfNoEntry: false });\n\n if (rootEntry?.isSymbolicLink()) {\n fail(`Cannot scaffold through a symbolic link: ${root}`);\n }\n};\n\nconst assertSafeAncestor = (ancestor: string): void => {\n const entry = lstatSync(ancestor, { throwIfNoEntry: false });\n\n if (entry?.isSymbolicLink()) {\n fail(`Cannot scaffold through a symbolic link: ${ancestor}`);\n }\n\n if (entry !== undefined && !entry.isDirectory()) {\n fail(`Cannot scaffold through a non-directory path: ${ancestor}`);\n }\n};\n\nconst assertSafeAncestors = (root: string, relativePath: string): void => {\n let ancestor = root;\n const segments = relativePath.split(sep);\n const ancestorSegments = segments.slice(0, -1);\n\n for (const segment of ancestorSegments) {\n ancestor = join(ancestor, segment);\n assertSafeAncestor(ancestor);\n }\n};\n\nconst assertReplaceableDestination = (destination: string): void => {\n const entry = lstatSync(destination, { throwIfNoEntry: false });\n const isReplaceable = entry === undefined || entry.isFile() || entry.isSymbolicLink();\n\n if (!isReplaceable) {\n fail(`Cannot replace scaffold file because its destination is not a file: ${destination}`);\n }\n};\n\nconst assertSafeDestination = (root: string, destination: string): void => {\n const relativePath = projectRelativeDestination(root, destination);\n assertRootIsNotSymbolicLink(root);\n assertSafeAncestors(root, relativePath);\n assertReplaceableDestination(destination);\n};\n\nconst plannedScaffoldFiles = async (root: string, resolved: ResolvedOptions): Promise<ScaffoldFile[]> => {\n const context = templateContext(resolved);\n const files: ScaffoldFile[] = [];\n\n for (const template of listTemplates()) {\n if (isTemplateIncluded(template, resolved)) {\n files.push({\n destination: join(root, destinationPath(template, resolved)),\n contents: await renderFile(template, context),\n });\n }\n }\n\n return files;\n};\n\nconst auxiliaryDestinations = (root: string, resolved: ResolvedOptions): string[] => [\n ...(resolved.packageManager === \"pnpm\" ? [join(root, \"pnpm-workspace.yaml\")] : []),\n ...(resolved.isTypescript ? [join(root, \"node_modules\", \".gtkx\", \"env.d.ts\")] : []),\n];\n\nconst classifyScaffoldChange = (\n root: string,\n destination: string,\n): ScaffoldChange | undefined => {\n const entry = lstatSync(destination, { throwIfNoEntry: false });\n\n if (entry === undefined) {\n return undefined;\n }\n\n return { destination, relativePath: projectRelativeDestination(root, destination) };\n};\n\nconst addScaffoldChange = (plan: ScaffoldPlan, change: ScaffoldChange | undefined): void => {\n if (change === undefined) {\n return;\n }\n\n plan.replaceDestinations.push(change.destination);\n plan.changes.push(change.relativePath);\n};\n\nconst planScaffoldProject = async (root: string, resolved: ResolvedOptions): Promise<ScaffoldPlan> => {\n const files = await plannedScaffoldFiles(root, resolved);\n const destinations = [...files.map((file) => file.destination), ...auxiliaryDestinations(root, resolved)];\n\n for (const destination of destinations) {\n assertSafeDestination(root, destination);\n }\n\n const plan: ScaffoldPlan = {\n files,\n replaceDestinations: [],\n changes: [],\n };\n\n for (const destination of destinations) {\n addScaffoldChange(plan, classifyScaffoldChange(root, destination));\n }\n\n return plan;\n};\n\nconst scaffoldProject = (root: string, resolved: ResolvedOptions, plan: ScaffoldPlan): void => {\n for (const destination of plan.replaceDestinations) {\n replaceTemplateDestination(destination);\n }\n\n for (const file of plan.files) {\n mkdirSync(dirname(file.destination), { recursive: true });\n writeFileSync(file.destination, file.contents);\n }\n\n if (resolved.shouldIncludeTesting) {\n updateManifest(root, (manifest) => {\n (manifest.scripts as Record<string, string>).test = \"vitest run\";\n });\n }\n};\n\nconst withoutInheritedScriptPolicy = async (run: () => Promise<void>): Promise<void> => {\n const saved = INHERITED_SCRIPT_POLICY_VARS.map((key) => [key, process.env[key]] as const);\n\n for (const [key] of saved) {\n Reflect.deleteProperty(process.env, key);\n }\n\n try {\n await run();\n } finally {\n for (const [key, value] of saved) {\n if (value !== undefined) {\n process.env[key] = value;\n }\n }\n }\n};\n\nconst installDependencies = async (options: InstallDependenciesOptions): Promise<void> => {\n const { cwd, packageManager, dependencies, isDev } = options;\n\n await withoutInheritedScriptPolicy(async () => {\n await addDependency(dependencies, { cwd, packageManager, dev: isDev, silent: true });\n });\n};\n\nconst pin = (names: string[]): string[] =>\n names.map((dependency) => dependency.startsWith(\"@gtkx/\") ? `${dependency}@^${selfVersion}` : dependency);\n\nconst dependencyVersions = (names: string[]): Record<string, string> => Object.fromEntries(\n names.map((dependency) => [dependency, dependency.startsWith(\"@gtkx/\") ? `^${selfVersion}` : \"latest\"]),\n);\n\nconst writeDependencies = (root: string, devDependencies: string[]): void => {\n updateManifest(root, (manifest) => {\n manifest.dependencies = dependencyVersions(DEPENDENCIES);\n manifest.devDependencies = dependencyVersions(devDependencies);\n });\n};\n\nconst formatRecovery = ({ resolved, devDependencies }: InstallFailureOptions): string => {\n const add = ADD_COMMAND[resolved.packageManager];\n\n const steps = [\n ...(resolved.isCurrentDirectory ? [] : [`cd ${resolved.target}`]),\n `${add} ${pin(DEPENDENCIES).join(\" \")}`,\n `${add} -D ${pin(devDependencies).join(\" \")}`,\n ];\n\n const indented = steps.map((step) => ` ${step}`).join(\"\\n\");\n\n return `${RECOVERY_HEADING}\\n${indented}`;\n};\n\nconst explainInstallFailure = (options: InstallFailureOptions): void => {\n const hint = getInstallHint(errorMessage(options.error));\n\n if (hint !== undefined) {\n p.log.warn(hint);\n }\n\n p.log.info(formatRecovery(options));\n};\n\nconst runWithSpinner = async (step: SpinnerStep): Promise<void> => {\n const spinner = p.spinner();\n spinner.start(step.pending);\n\n try {\n await step.run();\n spinner.stop(step.done);\n } catch (error) {\n spinner.error(step.failed);\n p.log.error(errorMessage(error));\n step.explain?.(error);\n throw new ScaffoldAbortedError(step.failed);\n }\n};\n\nconst installAllDependencies = async (options: InstallAllOptions): Promise<void> => {\n const { resolved, devDependencies } = options;\n const { root, packageManager } = resolved;\n\n await runWithSpinner({\n pending: \"Installing dependencies...\",\n done: \"Dependencies installed\",\n failed: \"Failed to install dependencies\",\n run: async () => {\n await installDependencies({ cwd: root, packageManager, dependencies: pin(DEPENDENCIES), isDev: false });\n await installDependencies({ cwd: root, packageManager, dependencies: pin(devDependencies), isDev: true });\n },\n explain: (error) => {\n explainInstallFailure({ error, resolved, devDependencies });\n },\n });\n};\n\nconst writeInitialEnvModule = (root: string): void => {\n const storeDir = join(root, \"node_modules\", \".gtkx\");\n mkdirSync(storeDir, { recursive: true });\n writeFileSync(join(storeDir, \"env.d.ts\"), `${GTKX_ENV_MODULE_HEADER}\\n`);\n};\n\nconst isInsideGitRepository = (root: string): boolean => {\n const git = tryResolveExecutable(\"git\");\n\n if (git === undefined) {\n return false;\n }\n\n try {\n execFileSync(git, [\"-C\", root, \"rev-parse\", \"--show-toplevel\"], { stdio: \"ignore\" });\n\n return true;\n } catch {\n return false;\n }\n};\n\nconst initializeGitRepo = async (root: string, shouldInitialize: boolean): Promise<void> => {\n if (!shouldInitialize || isInsideGitRepository(root)) {\n return;\n }\n\n const spinner = p.spinner();\n spinner.start(\"Initializing git repository...\");\n\n try {\n const opts = { nodeOptions: { cwd: root }, throwOnError: true } as const;\n await x(\"git\", [\"init\"], opts);\n await x(\"git\", [\"add\", \"-A\"], opts);\n await x(\"git\", [\"commit\", \"-m\", \"Initial commit\"], opts);\n spinner.stop(\"Git repository initialized\");\n } catch {\n spinner.error(\"Failed to initialize git repository\");\n }\n};\n\nconst printNextSteps = (resolved: ResolvedOptions): void => {\n const devCmd = DEV_COMMAND[resolved.packageManager];\n const cdStep = resolved.isCurrentDirectory ? \"\" : `cd ${resolved.target}\\n`;\n const installStep = resolved.shouldInstallDependencies ? \"\" : `${INSTALL_COMMAND[resolved.packageManager]}\\n`;\n const testingNote = resolved.shouldIncludeTesting ? HEADLESS_COMPOSITOR_NOTE : \"\";\n p.note(`${cdStep}${installStep}${devCmd}${testingNote}`, \"Next steps\");\n};\n\nconst createProjectStructure = async (\n root: string,\n resolved: ResolvedOptions,\n plan: ScaffoldPlan,\n): Promise<void> => {\n await runWithSpinner({\n pending: \"Creating project structure...\",\n done: \"Project structure created\",\n failed: \"Failed to create the project structure\",\n run: () => {\n mkdirSync(root, { recursive: true });\n scaffoldProject(root, resolved, plan);\n writeBuildAllowance(root, resolved.packageManager);\n\n if (resolved.isTypescript) {\n writeInitialEnvModule(root);\n }\n },\n });\n};\n\nconst scaffold = async (options: CreateOptions = {}): Promise<void> => {\n p.intro(\"Create GTKX App\");\n const resolved = await resolveOptions(options);\n const { root } = resolved;\n const devDeps = getDevDependencies(resolved);\n assertTargetIsDirectory(root, resolved.target);\n const plan = await planScaffoldProject(root, resolved);\n await validateTargetAvailability(root, resolved.target, options, plan.changes);\n await createProjectStructure(root, resolved, plan);\n reportCompletedChanges(plan.changes);\n\n if (resolved.shouldInstallDependencies) {\n await installAllDependencies({ resolved, devDependencies: devDeps });\n } else {\n writeDependencies(root, devDeps);\n }\n\n await initializeGitRepo(root, resolved.shouldInitializeGit);\n printNextSteps(resolved);\n};\n\nexport { scaffold };\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-gtkx",
3
- "version": "2.0.0-beta.2",
3
+ "version": "2.0.0-beta.4",
4
4
  "description": "Create a native GTK4 + React desktop app. Real GTK widgets.",
5
5
  "keywords": [
6
6
  "gtkx",
@@ -49,8 +49,8 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "@clack/prompts": "^1.7.0",
52
- "@gtkx/config": "2.0.0-beta.2",
53
- "@gtkx/utils": "2.0.0-beta.2",
52
+ "@gtkx/config": "2.0.0-beta.4",
53
+ "@gtkx/utils": "2.0.0-beta.4",
54
54
  "ejs": "^6.0.1",
55
55
  "citty": "^0.2.2",
56
56
  "nypm": "^0.6.9",
package/src/command.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import * as p from "@clack/prompts";
2
+ import { assertSupportedNodeVersion } from "@gtkx/config/internal";
2
3
  import { errorMessage } from "@gtkx/utils";
3
4
  import { defineCommand } from "citty";
5
+ import { parseArgs, type ParseArgsOptionsConfig } from "node:util";
4
6
  import { OperationCanceledError, ScaffoldAbortedError } from "./errors.js";
5
7
  import { PACKAGE_MANAGER_FLAG_DESCRIPTION } from "./package-managers.js";
6
8
  import { scaffold } from "./scaffolder.js";
@@ -15,6 +17,57 @@ type CreateCommandArgs = {
15
17
  yes?: boolean | undefined;
16
18
  "no-interactive"?: boolean | undefined;
17
19
  overwrite?: boolean | undefined;
20
+ "skip-install"?: boolean | undefined;
21
+ };
22
+
23
+ const STRICT_OPTIONS: ParseArgsOptionsConfig = {
24
+ "application-id": { type: "string" },
25
+ applicationId: { type: "string" },
26
+ "display-name": { type: "string" },
27
+ displayName: { type: "string" },
28
+ "package-manager": { type: "string", short: "p" },
29
+ packageManager: { type: "string" },
30
+ typescript: { type: "boolean" },
31
+ vitest: { type: "boolean" },
32
+ yes: { type: "boolean", short: "y" },
33
+ "no-interactive": { type: "boolean" },
34
+ noInteractive: { type: "boolean" },
35
+ overwrite: { type: "boolean", short: "f" },
36
+ "skip-install": { type: "boolean" },
37
+ skipInstall: { type: "boolean" },
38
+ };
39
+
40
+ const BOOLEAN_OPTIONS: ReadonlySet<string> = new Set([
41
+ "--typescript",
42
+ "--vitest",
43
+ "--yes",
44
+ "--overwrite",
45
+ "--skip-install",
46
+ "--skipInstall",
47
+ ]);
48
+
49
+ const normalizeBooleanArgument = (argument: string): string => {
50
+ const [option, value, ...rest] = argument.split("=");
51
+
52
+ if (option === undefined || rest.length > 0 || !BOOLEAN_OPTIONS.has(option)) {
53
+ return argument;
54
+ }
55
+
56
+ if (value === "true") {
57
+ return option;
58
+ }
59
+
60
+ return value === "false" ? `--no-${option.slice(2)}` : argument;
61
+ };
62
+
63
+ const assertKnownArguments = (rawArgs: string[]): void => {
64
+ parseArgs({
65
+ args: rawArgs.map((argument) => normalizeBooleanArgument(argument)),
66
+ options: STRICT_OPTIONS,
67
+ allowPositionals: true,
68
+ allowNegative: true,
69
+ strict: true,
70
+ });
18
71
  };
19
72
 
20
73
  const scaffoldCommand = defineCommand({
@@ -66,8 +119,12 @@ const scaffoldCommand = defineCommand({
66
119
  alias: "f",
67
120
  description: "Replace scaffold files in a non-empty target directory when running without prompts",
68
121
  },
122
+ "skip-install": {
123
+ type: "boolean",
124
+ description: "Create the project without installing dependencies",
125
+ },
69
126
  },
70
- run: ({ args }) => runCreate(args),
127
+ run: ({ args, rawArgs }) => runCreate(args, rawArgs),
71
128
  });
72
129
 
73
130
  const settleScaffoldFailure = (error: unknown): void => {
@@ -82,10 +139,12 @@ const settleScaffoldFailure = (error: unknown): void => {
82
139
  process.exitCode = 1;
83
140
  };
84
141
 
85
- const runCreate = async (args: CreateCommandArgs): Promise<void> => {
142
+ const runCreate = async (args: CreateCommandArgs, rawArgs: string[]): Promise<void> => {
86
143
  const isInteractive = args["no-interactive"] || args.yes ? false : process.stdin.isTTY;
87
144
 
88
145
  try {
146
+ assertKnownArguments(rawArgs);
147
+ assertSupportedNodeVersion();
89
148
  await scaffold({
90
149
  name: args.name,
91
150
  applicationId: args["application-id"],
@@ -95,6 +154,7 @@ const runCreate = async (args: CreateCommandArgs): Promise<void> => {
95
154
  shouldIncludeTesting: args.vitest,
96
155
  isInteractive,
97
156
  shouldOverwrite: args.overwrite,
157
+ shouldInstallDependencies: args["skip-install"] !== true,
98
158
  });
99
159
  } catch (error) {
100
160
  settleScaffoldFailure(error);
@@ -1,9 +1,30 @@
1
1
  type PackageManager = (typeof PACKAGE_MANAGERS)[number]["value"];
2
2
 
3
3
  const PACKAGE_MANAGERS = [
4
- { value: "pnpm", label: "pnpm", devCommand: "pnpm dev", addCommand: "pnpm add", isRecommended: true },
5
- { value: "npm", label: "npm", devCommand: "npm run dev", addCommand: "npm install", isRecommended: false },
6
- { value: "yarn", label: "yarn", devCommand: "yarn dev", addCommand: "yarn add", isRecommended: false },
4
+ {
5
+ value: "pnpm",
6
+ label: "pnpm",
7
+ devCommand: "pnpm dev",
8
+ addCommand: "pnpm add",
9
+ installCommand: "pnpm install",
10
+ isRecommended: true,
11
+ },
12
+ {
13
+ value: "npm",
14
+ label: "npm",
15
+ devCommand: "npm run dev",
16
+ addCommand: "npm install",
17
+ installCommand: "npm install",
18
+ isRecommended: false,
19
+ },
20
+ {
21
+ value: "yarn",
22
+ label: "yarn",
23
+ devCommand: "yarn dev",
24
+ addCommand: "yarn add",
25
+ installCommand: "yarn install",
26
+ isRecommended: false,
27
+ },
7
28
  ] as const;
8
29
 
9
30
  const PACKAGE_MANAGER_VALUES: PackageManager[] = PACKAGE_MANAGERS.map((manager) => manager.value);
package/src/scaffolder.ts CHANGED
@@ -29,6 +29,7 @@ type CreateOptions = {
29
29
  shouldIncludeTesting?: boolean | undefined;
30
30
  isInteractive?: boolean | undefined;
31
31
  shouldOverwrite?: boolean | undefined;
32
+ shouldInstallDependencies?: boolean | undefined;
32
33
  };
33
34
 
34
35
  type ResolvedOptions = {
@@ -42,10 +43,24 @@ type ResolvedOptions = {
42
43
  isTypescript: boolean;
43
44
  shouldIncludeTesting: boolean;
44
45
  shouldInitializeGit: boolean;
46
+ shouldInstallDependencies: boolean;
45
47
  };
46
48
 
47
49
  type ScaffoldFile = { destination: string; contents: string };
48
50
 
51
+ type ScaffoldChanges = string[];
52
+
53
+ type ScaffoldPlan = {
54
+ files: ScaffoldFile[];
55
+ replaceDestinations: string[];
56
+ changes: ScaffoldChanges;
57
+ };
58
+
59
+ type ScaffoldChange = {
60
+ destination: string;
61
+ relativePath: string;
62
+ };
63
+
49
64
  type InstallDependenciesOptions = {
50
65
  cwd: string;
51
66
  packageManager: PackageManager;
@@ -68,7 +83,7 @@ type SpinnerStep = {
68
83
  pending: string;
69
84
  done: string;
70
85
  failed: string;
71
- run: () => Promise<void>;
86
+ run: () => Promise<void> | void;
72
87
  explain?: ((error: unknown) => void) | undefined;
73
88
  };
74
89
 
@@ -92,6 +107,10 @@ const ADD_COMMAND: Record<PackageManager, string> = Object.fromEntries(
92
107
  PACKAGE_MANAGERS.map((manager) => [manager.value, manager.addCommand]),
93
108
  ) as Record<PackageManager, string>;
94
109
 
110
+ const INSTALL_COMMAND: Record<PackageManager, string> = Object.fromEntries(
111
+ PACKAGE_MANAGERS.map((manager) => [manager.value, manager.installCommand]),
112
+ ) as Record<PackageManager, string>;
113
+
95
114
  const INHERITED_SCRIPT_POLICY_VARS = ["npm_config_allow_scripts", "npm_config_allow-scripts"];
96
115
  const TESTING_TEMPLATES = new Set(["vitest.config.ts", "tests/app.test.tsx"]);
97
116
  const TYPESCRIPT_TEMPLATES = new Set(["tsconfig.json", "src/gtkx-env.d.ts"]);
@@ -345,21 +364,51 @@ const shouldOverwriteDirectory = async (target: string, options: CreateOptions):
345
364
  );
346
365
  };
347
366
 
348
- const validateTargetAvailability = async (root: string, target: string, options: CreateOptions): Promise<void> => {
367
+ const formatFileList = (heading: string, files: string[]): string => {
368
+ const indentedFiles = files.map((file) => ` ${file}`).join("\n");
369
+
370
+ return `${heading}:\n${indentedFiles}`;
371
+ };
372
+
373
+ const reportPlannedChanges = (changes: ScaffoldChanges): void => {
374
+ if (changes.length > 0) {
375
+ p.log.info(formatFileList("Scaffold files to replace", changes));
376
+ }
377
+ };
378
+
379
+ const reportCompletedChanges = (changes: ScaffoldChanges): void => {
380
+ if (changes.length > 0) {
381
+ p.log.success(formatFileList("Replaced scaffold files", changes));
382
+ }
383
+ };
384
+
385
+ const assertTargetIsDirectory = (root: string, target: string): void => {
349
386
  const stats = statSync(root, { throwIfNoEntry: false });
350
387
 
351
- if (stats === undefined) {
352
- return;
388
+ if (stats !== undefined && !stats.isDirectory()) {
389
+ fail(`Target "${target}" is not a directory`);
353
390
  }
391
+ };
354
392
 
355
- if (!stats.isDirectory()) {
356
- return fail(`Target "${target}" is not a directory`);
393
+ const validateTargetAvailability = async (
394
+ root: string,
395
+ target: string,
396
+ options: CreateOptions,
397
+ changes: ScaffoldChanges,
398
+ ): Promise<void> => {
399
+ const stats = statSync(root, { throwIfNoEntry: false });
400
+ assertTargetIsDirectory(root, target);
401
+
402
+ if (stats === undefined) {
403
+ return;
357
404
  }
358
405
 
359
406
  if (isDirEmpty(root)) {
360
407
  return;
361
408
  }
362
409
 
410
+ reportPlannedChanges(changes);
411
+
363
412
  if (await shouldOverwriteDirectory(target, options)) {
364
413
  return;
365
414
  }
@@ -419,7 +468,6 @@ const resolveOptions = async (options: CreateOptions): Promise<ResolvedOptions>
419
468
  const root = resolve(process.cwd(), target);
420
469
  const isCurrentDirectory = root === process.cwd();
421
470
  const shouldInitialize = shouldInitializeGit(root);
422
- await validateTargetAvailability(root, target, options);
423
471
  const packageManager = await resolvePackageManager(requested, options);
424
472
  const isTypescript = await isOptionEnabled(options.isTypescript, options.isInteractive, "Use TypeScript?");
425
473
 
@@ -440,6 +488,7 @@ const resolveOptions = async (options: CreateOptions): Promise<ResolvedOptions>
440
488
  isTypescript,
441
489
  shouldIncludeTesting,
442
490
  shouldInitializeGit: shouldInitialize,
491
+ shouldInstallDependencies: options.shouldInstallDependencies !== false,
443
492
  };
444
493
  };
445
494
 
@@ -568,7 +617,29 @@ const auxiliaryDestinations = (root: string, resolved: ResolvedOptions): string[
568
617
  ...(resolved.isTypescript ? [join(root, "node_modules", ".gtkx", "env.d.ts")] : []),
569
618
  ];
570
619
 
571
- const scaffoldProject = async (root: string, resolved: ResolvedOptions): Promise<void> => {
620
+ const classifyScaffoldChange = (
621
+ root: string,
622
+ destination: string,
623
+ ): ScaffoldChange | undefined => {
624
+ const entry = lstatSync(destination, { throwIfNoEntry: false });
625
+
626
+ if (entry === undefined) {
627
+ return undefined;
628
+ }
629
+
630
+ return { destination, relativePath: projectRelativeDestination(root, destination) };
631
+ };
632
+
633
+ const addScaffoldChange = (plan: ScaffoldPlan, change: ScaffoldChange | undefined): void => {
634
+ if (change === undefined) {
635
+ return;
636
+ }
637
+
638
+ plan.replaceDestinations.push(change.destination);
639
+ plan.changes.push(change.relativePath);
640
+ };
641
+
642
+ const planScaffoldProject = async (root: string, resolved: ResolvedOptions): Promise<ScaffoldPlan> => {
572
643
  const files = await plannedScaffoldFiles(root, resolved);
573
644
  const destinations = [...files.map((file) => file.destination), ...auxiliaryDestinations(root, resolved)];
574
645
 
@@ -576,11 +647,25 @@ const scaffoldProject = async (root: string, resolved: ResolvedOptions): Promise
576
647
  assertSafeDestination(root, destination);
577
648
  }
578
649
 
650
+ const plan: ScaffoldPlan = {
651
+ files,
652
+ replaceDestinations: [],
653
+ changes: [],
654
+ };
655
+
579
656
  for (const destination of destinations) {
657
+ addScaffoldChange(plan, classifyScaffoldChange(root, destination));
658
+ }
659
+
660
+ return plan;
661
+ };
662
+
663
+ const scaffoldProject = (root: string, resolved: ResolvedOptions, plan: ScaffoldPlan): void => {
664
+ for (const destination of plan.replaceDestinations) {
580
665
  replaceTemplateDestination(destination);
581
666
  }
582
667
 
583
- for (const file of files) {
668
+ for (const file of plan.files) {
584
669
  mkdirSync(dirname(file.destination), { recursive: true });
585
670
  writeFileSync(file.destination, file.contents);
586
671
  }
@@ -621,6 +706,17 @@ const installDependencies = async (options: InstallDependenciesOptions): Promise
621
706
  const pin = (names: string[]): string[] =>
622
707
  names.map((dependency) => dependency.startsWith("@gtkx/") ? `${dependency}@^${selfVersion}` : dependency);
623
708
 
709
+ const dependencyVersions = (names: string[]): Record<string, string> => Object.fromEntries(
710
+ names.map((dependency) => [dependency, dependency.startsWith("@gtkx/") ? `^${selfVersion}` : "latest"]),
711
+ );
712
+
713
+ const writeDependencies = (root: string, devDependencies: string[]): void => {
714
+ updateManifest(root, (manifest) => {
715
+ manifest.dependencies = dependencyVersions(DEPENDENCIES);
716
+ manifest.devDependencies = dependencyVersions(devDependencies);
717
+ });
718
+ };
719
+
624
720
  const formatRecovery = ({ resolved, devDependencies }: InstallFailureOptions): string => {
625
721
  const add = ADD_COMMAND[resolved.packageManager];
626
722
 
@@ -722,18 +818,23 @@ const initializeGitRepo = async (root: string, shouldInitialize: boolean): Promi
722
818
  const printNextSteps = (resolved: ResolvedOptions): void => {
723
819
  const devCmd = DEV_COMMAND[resolved.packageManager];
724
820
  const cdStep = resolved.isCurrentDirectory ? "" : `cd ${resolved.target}\n`;
821
+ const installStep = resolved.shouldInstallDependencies ? "" : `${INSTALL_COMMAND[resolved.packageManager]}\n`;
725
822
  const testingNote = resolved.shouldIncludeTesting ? HEADLESS_COMPOSITOR_NOTE : "";
726
- p.note(`${cdStep}${devCmd}${testingNote}`, "Next steps");
823
+ p.note(`${cdStep}${installStep}${devCmd}${testingNote}`, "Next steps");
727
824
  };
728
825
 
729
- const createProjectStructure = async (root: string, resolved: ResolvedOptions): Promise<void> => {
826
+ const createProjectStructure = async (
827
+ root: string,
828
+ resolved: ResolvedOptions,
829
+ plan: ScaffoldPlan,
830
+ ): Promise<void> => {
730
831
  await runWithSpinner({
731
832
  pending: "Creating project structure...",
732
833
  done: "Project structure created",
733
834
  failed: "Failed to create the project structure",
734
- run: async () => {
835
+ run: () => {
735
836
  mkdirSync(root, { recursive: true });
736
- await scaffoldProject(root, resolved);
837
+ scaffoldProject(root, resolved, plan);
737
838
  writeBuildAllowance(root, resolved.packageManager);
738
839
 
739
840
  if (resolved.isTypescript) {
@@ -748,8 +849,17 @@ const scaffold = async (options: CreateOptions = {}): Promise<void> => {
748
849
  const resolved = await resolveOptions(options);
749
850
  const { root } = resolved;
750
851
  const devDeps = getDevDependencies(resolved);
751
- await createProjectStructure(root, resolved);
752
- await installAllDependencies({ resolved, devDependencies: devDeps });
852
+ assertTargetIsDirectory(root, resolved.target);
853
+ const plan = await planScaffoldProject(root, resolved);
854
+ await validateTargetAvailability(root, resolved.target, options, plan.changes);
855
+ await createProjectStructure(root, resolved, plan);
856
+ reportCompletedChanges(plan.changes);
857
+
858
+ if (resolved.shouldInstallDependencies) {
859
+ await installAllDependencies({ resolved, devDependencies: devDeps });
860
+ } else {
861
+ writeDependencies(root, devDeps);
862
+ }
753
863
 
754
864
  await initializeGitRepo(root, resolved.shouldInitializeGit);
755
865
  printNextSteps(resolved);
@@ -1,2 +0,0 @@
1
- [tools]
2
- node = "26"
@@ -1,2 +0,0 @@
1
- [tools]
2
- node = "26"