create-next-hydra 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +91 -0
  3. package/dist/cli.js +0 -0
  4. package/dist/composition/add.d.ts +14 -0
  5. package/dist/composition/add.d.ts.map +1 -0
  6. package/dist/composition/add.js +453 -0
  7. package/dist/composition/catalog.d.ts +26 -0
  8. package/dist/composition/catalog.d.ts.map +1 -0
  9. package/dist/composition/catalog.js +313 -0
  10. package/dist/composition/errors.d.ts +5 -0
  11. package/dist/composition/errors.d.ts.map +1 -0
  12. package/dist/composition/errors.js +8 -0
  13. package/dist/composition/format.d.ts +6 -0
  14. package/dist/composition/format.d.ts.map +1 -0
  15. package/dist/composition/format.js +63 -0
  16. package/dist/composition/install.d.ts +16 -0
  17. package/dist/composition/install.d.ts.map +1 -0
  18. package/dist/composition/install.js +175 -0
  19. package/dist/composition/packages.d.ts +6 -0
  20. package/dist/composition/packages.d.ts.map +1 -0
  21. package/dist/composition/packages.js +54 -0
  22. package/dist/composition/paths.d.ts +4 -0
  23. package/dist/composition/paths.d.ts.map +1 -0
  24. package/dist/composition/paths.js +47 -0
  25. package/dist/composition/planner.d.ts +4 -0
  26. package/dist/composition/planner.d.ts.map +1 -0
  27. package/dist/composition/planner.js +320 -0
  28. package/dist/composition/schema.d.ts +235 -0
  29. package/dist/composition/schema.d.ts.map +1 -0
  30. package/dist/composition/schema.js +115 -0
  31. package/dist/composition/types.d.ts +87 -0
  32. package/dist/composition/types.d.ts.map +1 -0
  33. package/dist/composition/types.js +6 -0
  34. package/dist/composition/use.d.ts +23 -0
  35. package/dist/composition/use.d.ts.map +1 -0
  36. package/dist/composition/use.js +182 -0
  37. package/dist/composition/workspace.d.ts +10 -0
  38. package/dist/composition/workspace.d.ts.map +1 -0
  39. package/dist/composition/workspace.js +208 -0
  40. package/dist/constants.d.ts +4 -1
  41. package/dist/constants.d.ts.map +1 -1
  42. package/dist/constants.js +26 -1
  43. package/dist/fs-utils.js +3 -3
  44. package/dist/git.d.ts.map +1 -1
  45. package/dist/git.js +12 -12
  46. package/dist/index.d.ts +5 -1
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +55 -6
  49. package/dist/instruction-renderer.d.ts +17 -0
  50. package/dist/instruction-renderer.d.ts.map +1 -0
  51. package/dist/instruction-renderer.js +132 -0
  52. package/dist/logger.d.ts +2 -1
  53. package/dist/logger.d.ts.map +1 -1
  54. package/dist/logger.js +7 -3
  55. package/dist/prompts.d.ts +2 -0
  56. package/dist/prompts.d.ts.map +1 -1
  57. package/dist/prompts.js +25 -2
  58. package/dist/sanitize.d.ts +2 -1
  59. package/dist/sanitize.d.ts.map +1 -1
  60. package/dist/sanitize.js +13 -4
  61. package/dist/scaffold.d.ts +5 -1
  62. package/dist/scaffold.d.ts.map +1 -1
  63. package/dist/scaffold.js +247 -71
  64. package/dist/types.d.ts +5 -0
  65. package/dist/types.d.ts.map +1 -1
  66. package/dist/version.d.ts +2 -0
  67. package/dist/version.d.ts.map +1 -0
  68. package/dist/version.js +2 -0
  69. package/package.json +35 -23
  70. package/schema/selection-definition.json +237 -0
  71. package/schema/source-registry.json +37 -0
package/dist/constants.js CHANGED
@@ -7,7 +7,32 @@ export const DEFAULT_STARTER = {
7
7
  repoUrl: DEFAULT_REPO_URL,
8
8
  };
9
9
  export const SANITIZE_REMOVE_PATHS = [
10
+ ".changeset",
10
11
  ".git",
12
+ ".github/workflows/registry-integrity.yml",
13
+ ".github/workflows/release-create-next-hydra.yml",
14
+ ".scratch",
15
+ "RELEASING.md",
11
16
  "apps/docs",
12
- "pnpm-lock.yaml",
17
+ "next-hydra.json",
18
+ "packages/create-next-hydra",
19
+ "scripts/release-create-next-hydra.mjs",
20
+ "scripts/sync-registry-files.ts",
21
+ ];
22
+ export const SANITIZE_REMOVE_SCRIPTS = [
23
+ "changeset",
24
+ "changeset:status",
25
+ "publish:cli",
26
+ "registry:check",
27
+ "registry:sync",
28
+ "release:create-next-hydra",
29
+ "release:create-next-hydra:dry-run",
30
+ "version:cli",
31
+ ];
32
+ export const SANITIZE_REMOVE_ROOT_DEPENDENCIES = [
33
+ "@clack/prompts",
34
+ "commander",
35
+ ];
36
+ export const SANITIZE_REMOVE_ROOT_DEV_DEPENDENCIES = [
37
+ "@changesets/cli",
13
38
  ];
package/dist/fs-utils.js CHANGED
@@ -29,14 +29,14 @@ export async function ensureParentDirectory(targetPath) {
29
29
  await access(parentDir);
30
30
  }
31
31
  export async function removePath(targetPath) {
32
- await rm(targetPath, { recursive: true, force: true });
32
+ await rm(targetPath, { force: true, recursive: true });
33
33
  }
34
34
  export async function readJsonFile(filePath) {
35
- const raw = await readFile(filePath, "utf8");
35
+ const raw = await readFile(filePath, "utf-8");
36
36
  return JSON.parse(raw);
37
37
  }
38
38
  export async function writeJsonFile(filePath, value) {
39
- await writeFile(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
39
+ await writeFile(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf-8");
40
40
  }
41
41
  export function toDisplayPath(absolutePath, cwd = process.cwd()) {
42
42
  const relative = path.relative(cwd, absolutePath);
package/dist/git.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAElE,KAAK,iBAAiB,GAAG;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB;CAQF;AAED,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAqD3B;AAED,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAQ3B;AAED,wBAAsB,kBAAkB,CAAC,OAAO,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvE;AAED,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAC9C,OAAO,CAAC,aAAa,CAAC,CAoCxB"}
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAElE,KAAK,iBAAiB,GAAG;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,YAAY,MAAM,EAAE;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,EAOA;CACF;AAED,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAqD3B;AAED,wBAAsB,MAAM,CAC1B,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAQ3B;AAED,wBAAsB,kBAAkB,CAAC,OAAO,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvE;AAED,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAC9C,OAAO,CAAC,aAAa,CAAC,CAoCxB"}
package/dist/git.js CHANGED
@@ -45,25 +45,25 @@ export async function runCommand(command, args, options = {}) {
45
45
  child.on("close", resolve);
46
46
  }).catch((error) => {
47
47
  throw new CommandExecutionError({
48
- command: formatCommand(command, args),
49
48
  code: null,
50
- stdout,
51
- stderr,
49
+ command: formatCommand(command, args),
52
50
  message: error instanceof Error ? error.message : "Failed to start command",
51
+ stderr,
52
+ stdout,
53
53
  });
54
54
  });
55
55
  if (exitCode !== 0) {
56
56
  throw new CommandExecutionError({
57
- command: formatCommand(command, args),
58
57
  code: exitCode,
59
- stdout,
58
+ command: formatCommand(command, args),
60
59
  stderr,
60
+ stdout,
61
61
  });
62
62
  }
63
- return { stdout, stderr };
63
+ return { stderr, stdout };
64
64
  }
65
- export function runGit(args, options = {}) {
66
- return runCommand("git", args, {
65
+ export async function runGit(args, options = {}) {
66
+ return await runCommand("git", args, {
67
67
  ...options,
68
68
  env: {
69
69
  GIT_TERMINAL_PROMPT: "0",
@@ -79,8 +79,8 @@ export async function initializeGitRepository(targetPath, options) {
79
79
  await runGit(["init"], { cwd: targetPath, verbose });
80
80
  if (!options.commit) {
81
81
  return {
82
- gitInitialized: true,
83
82
  committed: false,
83
+ gitInitialized: true,
84
84
  };
85
85
  }
86
86
  await runGit(["add", "-A"], { cwd: targetPath, verbose });
@@ -90,16 +90,16 @@ export async function initializeGitRepository(targetPath, options) {
90
90
  verbose,
91
91
  });
92
92
  return {
93
- gitInitialized: true,
94
93
  committed: true,
94
+ gitInitialized: true,
95
95
  };
96
96
  }
97
97
  catch (error) {
98
98
  if (error instanceof CommandExecutionError) {
99
99
  return {
100
- gitInitialized: true,
101
- committed: false,
102
100
  commitError: error.stderr.trim() || error.stdout.trim() || error.message,
101
+ committed: false,
102
+ gitInitialized: true,
103
103
  };
104
104
  }
105
105
  throw error;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,7 @@
1
- export declare function runCli(argv?: string[]): Promise<void>;
1
+ import { useComposition } from "./composition/use.js";
2
+ type CliDependencies = {
3
+ useComposition?: typeof useComposition;
4
+ };
5
+ export declare function runCli(argv?: string[], dependencies?: CliDependencies): Promise<void>;
2
6
  export type { CreateOptions, ResolvedCreateOptions, ScaffoldResult, StarterDefinition, } from "./types.js";
3
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA+BA,wBAAsB,MAAM,CAAC,IAAI,WAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAoC/D;AACD,YAAY,EACV,aAAa,EACb,qBAAqB,EACrB,cAAc,EACd,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAsBtD,KAAK,eAAe,GAAG;IACrB,cAAc,CAAC,EAAE,OAAO,cAAc,CAAC;CACxC,CAAC;AA0BF,wBAAsB,MAAM,CAC1B,IAAI,WAAe,EACnB,YAAY,GAAE,eAAoB,GACjC,OAAO,CAAC,IAAI,CAAC,CA4Ff;AACD,YAAY,EACV,aAAa,EACb,qBAAqB,EACrB,cAAc,EACd,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,20 +1,28 @@
1
1
  import { Command } from "commander";
2
+ import { addRegistryItem } from "./composition/add.js";
3
+ import { useComposition } from "./composition/use.js";
2
4
  import { CLI_NAME, DEFAULT_REPO_URL } from "./constants.js";
3
5
  import { promptForTargetDirectory } from "./prompts.js";
4
6
  import { scaffoldProject } from "./scaffold.js";
7
+ import { CLI_VERSION } from "./version.js";
5
8
  function buildCreateOptions(targetDir, rawOptions) {
6
9
  return {
7
- targetDir,
8
- yes: rawOptions.yes ?? false,
9
- skipGit: rawOptions.skipGit ?? false,
10
+ addOns: rawOptions.addOn,
11
+ auth: rawOptions.auth,
12
+ cms: rawOptions.cms,
13
+ commerce: rawOptions.commerce,
10
14
  commit: rawOptions.commit ?? true,
15
+ preset: rawOptions.preset,
11
16
  ref: rawOptions.ref,
12
17
  repoUrl: rawOptions.repoUrl ?? DEFAULT_REPO_URL,
18
+ skipGit: rawOptions.skipGit ?? false,
19
+ targetDir,
13
20
  verbose: rawOptions.verbose ?? false,
21
+ yes: rawOptions.yes ?? false,
14
22
  };
15
23
  }
16
- export async function runCli(argv = process.argv) {
17
- const program = new Command();
24
+ export async function runCli(argv = process.argv, dependencies = {}) {
25
+ const program = new Command().enablePositionalOptions();
18
26
  program
19
27
  .name(CLI_NAME)
20
28
  .description("Scaffold a new next-hydra project")
@@ -24,8 +32,16 @@ export async function runCli(argv = process.argv) {
24
32
  .option("--no-commit", "Initialize git but skip initial commit")
25
33
  .option("--ref <git-ref>", "Clone and checkout a specific git ref")
26
34
  .option("--repo-url <url>", "Override the starter repo URL")
35
+ .option("--auth <provider>", "Select the Auth provider")
36
+ .option("--cms <provider>", "Select the CMS provider")
37
+ .option("--commerce <provider>", "Select the Commerce provider")
38
+ .option("--add-on <selection>", "Select an Add-on (repeatable)", (value, previous) => [
39
+ ...(previous ?? []),
40
+ value,
41
+ ])
42
+ .option("--preset <selection>", "Use a portable next-hydra preset")
27
43
  .option("--verbose", "Print git command output")
28
- .version("0.1.0")
44
+ .version(CLI_VERSION)
29
45
  .action(async (projectDirectory, rawOptions) => {
30
46
  let targetDir = projectDirectory?.trim();
31
47
  if (!targetDir) {
@@ -36,5 +52,38 @@ export async function runCli(argv = process.argv) {
36
52
  }
37
53
  await scaffoldProject(buildCreateOptions(targetDir, rawOptions));
38
54
  });
55
+ program
56
+ .command("use")
57
+ .description("Change or check the maintainer workspace composition")
58
+ .option("--auth <provider>", "Select the Auth provider")
59
+ .option("--cms <provider>", "Select the CMS provider")
60
+ .option("--commerce <provider>", "Select the Commerce provider")
61
+ .option("--add-on <selection>", "Select an Add-on (repeatable)", (value, previous) => [
62
+ ...(previous ?? []),
63
+ value,
64
+ ])
65
+ .option("--preset <selection>", "Use a portable next-hydra preset")
66
+ .option("--check", "Check for composition drift without writing")
67
+ .option("--dry-run", "Preview and validate changes without writing")
68
+ .option("-y, --yes", "Apply changes without confirmation")
69
+ .option("--verbose", "Print package-manager output")
70
+ .action(async (rawOptions) => {
71
+ await (dependencies.useComposition ?? useComposition)({
72
+ ...rawOptions,
73
+ addOns: rawOptions.addOn,
74
+ });
75
+ });
76
+ program
77
+ .command("add")
78
+ .description("Add a registry item to a customer-owned workspace")
79
+ .argument("<item-or-url>", "Registry item, URL, or local item JSON")
80
+ .option("-y, --yes", "Skip confirmation prompts")
81
+ .option("-o, --overwrite", "Overwrite changed files and package entries")
82
+ .action(async (reference, rawOptions) => {
83
+ await addRegistryItem(reference, {
84
+ overwrite: rawOptions.overwrite,
85
+ yes: rawOptions.yes,
86
+ });
87
+ });
39
88
  await program.parseAsync(argv);
40
89
  }
@@ -0,0 +1,17 @@
1
+ export type InstructionEntry = {
2
+ kind: "text";
3
+ text: string;
4
+ } | {
5
+ kind: "command";
6
+ command: string;
7
+ };
8
+ export type InstructionSection = {
9
+ title: string;
10
+ entries: readonly InstructionEntry[];
11
+ };
12
+ export type InstructionOutput = {
13
+ columns?: number;
14
+ isTTY: boolean;
15
+ };
16
+ export declare function renderInstructions(sections: readonly InstructionSection[], output: InstructionOutput): string;
17
+ //# sourceMappingURL=instruction-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instruction-renderer.d.ts","sourceRoot":"","sources":["../src/instruction-renderer.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AA4JF,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,EACvC,MAAM,EAAE,iBAAiB,GACxB,MAAM,CAQR"}
@@ -0,0 +1,132 @@
1
+ import { stripVTControlCharacters } from "node:util";
2
+ const DEFAULT_INSTRUCTION_COLUMNS = 80;
3
+ const MAX_INSTRUCTION_COLUMNS = 100;
4
+ const MIN_INSTRUCTION_COLUMNS = 12;
5
+ const PLAIN_INSTRUCTION_COLUMNS = 100;
6
+ function printableText(value) {
7
+ return stripVTControlCharacters(value).replaceAll(/\s+/g, " ").trim();
8
+ }
9
+ function printableWidth(value) {
10
+ return [...stripVTControlCharacters(value)].length;
11
+ }
12
+ function splitAtWidth(value, width) {
13
+ const characters = [...value];
14
+ return [
15
+ characters.slice(0, width).join(""),
16
+ characters.slice(width).join(""),
17
+ ];
18
+ }
19
+ function wrapText(value, width) {
20
+ const normalized = printableText(value);
21
+ if (!normalized) {
22
+ return [];
23
+ }
24
+ const lines = [];
25
+ let currentLine = "";
26
+ for (const inputWord of normalized.split(" ")) {
27
+ let word = inputWord;
28
+ while (printableWidth(word) > width) {
29
+ if (currentLine) {
30
+ lines.push(currentLine);
31
+ currentLine = "";
32
+ }
33
+ const [chunk, remainder] = splitAtWidth(word, width);
34
+ lines.push(chunk);
35
+ word = remainder;
36
+ }
37
+ if (!word) {
38
+ continue;
39
+ }
40
+ if (!currentLine) {
41
+ currentLine = word;
42
+ continue;
43
+ }
44
+ if (printableWidth(`${currentLine} ${word}`) <= width) {
45
+ currentLine += ` ${word}`;
46
+ continue;
47
+ }
48
+ lines.push(currentLine);
49
+ currentLine = word;
50
+ }
51
+ if (currentLine) {
52
+ lines.push(currentLine);
53
+ }
54
+ return lines;
55
+ }
56
+ function instructionColumns(output) {
57
+ if (!output.isTTY) {
58
+ return PLAIN_INSTRUCTION_COLUMNS;
59
+ }
60
+ const columns = Number.isFinite(output.columns)
61
+ ? Math.floor(output.columns ?? DEFAULT_INSTRUCTION_COLUMNS)
62
+ : DEFAULT_INSTRUCTION_COLUMNS;
63
+ return Math.max(MIN_INSTRUCTION_COLUMNS, Math.min(columns, MAX_INSTRUCTION_COLUMNS));
64
+ }
65
+ function shouldSeparateEntries(previous, current) {
66
+ return Boolean(previous && !(previous.kind === "command" && current.kind === "command"));
67
+ }
68
+ function renderTtyInstructions(sections, columns) {
69
+ const lines = ["│"];
70
+ for (const [sectionIndex, section] of sections.entries()) {
71
+ if (sectionIndex > 0) {
72
+ lines.push("│");
73
+ }
74
+ lines.push(`◇ ${printableText(section.title)}`, "│");
75
+ let instructionNumber = 0;
76
+ for (const [entryIndex, entry] of section.entries.entries()) {
77
+ if (shouldSeparateEntries(section.entries[entryIndex - 1], entry)) {
78
+ lines.push("│");
79
+ }
80
+ if (entry.kind === "command") {
81
+ lines.push(`│ $ ${printableText(entry.command)}`);
82
+ continue;
83
+ }
84
+ instructionNumber += 1;
85
+ const marker = `${instructionNumber}. `;
86
+ const firstPrefix = `│ ${marker}`;
87
+ const continuationPrefix = `│ ${" ".repeat(marker.length)}`;
88
+ const textWidth = Math.max(1, columns - printableWidth(firstPrefix));
89
+ const wrapped = wrapText(entry.text, textWidth);
90
+ for (const [lineIndex, line] of wrapped.entries()) {
91
+ lines.push(`${lineIndex === 0 ? firstPrefix : continuationPrefix}${line}`);
92
+ }
93
+ }
94
+ }
95
+ return `${lines.join("\n")}\n`;
96
+ }
97
+ function renderPlainInstructions(sections, columns) {
98
+ const lines = [];
99
+ for (const [sectionIndex, section] of sections.entries()) {
100
+ if (sectionIndex > 0) {
101
+ lines.push("");
102
+ }
103
+ lines.push(printableText(section.title), "");
104
+ let instructionNumber = 0;
105
+ for (const [entryIndex, entry] of section.entries.entries()) {
106
+ if (shouldSeparateEntries(section.entries[entryIndex - 1], entry)) {
107
+ lines.push("");
108
+ }
109
+ if (entry.kind === "command") {
110
+ lines.push(`$ ${printableText(entry.command)}`);
111
+ continue;
112
+ }
113
+ instructionNumber += 1;
114
+ const marker = `${instructionNumber}. `;
115
+ const continuationPrefix = " ".repeat(marker.length);
116
+ const wrapped = wrapText(entry.text, columns - marker.length);
117
+ for (const [lineIndex, line] of wrapped.entries()) {
118
+ lines.push(`${lineIndex === 0 ? marker : continuationPrefix}${line}`);
119
+ }
120
+ }
121
+ }
122
+ return `${lines.join("\n")}\n`;
123
+ }
124
+ export function renderInstructions(sections, output) {
125
+ if (sections.length === 0) {
126
+ return "";
127
+ }
128
+ const columns = instructionColumns(output);
129
+ return output.isTTY
130
+ ? renderTtyInstructions(sections, columns)
131
+ : renderPlainInstructions(sections, columns);
132
+ }
package/dist/logger.d.ts CHANGED
@@ -1,7 +1,8 @@
1
+ import type { InstructionSection } from "./instruction-renderer.js";
1
2
  export declare function info(message: string): void;
2
3
  export declare function warn(message: string): void;
3
4
  export declare function success(message: string): void;
4
- export declare function printNextSteps(message: string, title?: string): void;
5
+ export declare function printInstructions(sections: readonly InstructionSection[]): void;
5
6
  export declare function finish(message: string): void;
6
7
  export declare function createSpinner(): {
7
8
  start: (msg?: string) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAEA,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAAe,GAAG,IAAI,CAE1E;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE5C;AAED,wBAAgB,aAAa;eAO4uG,CAAC;cAAiC,CAAC,cAAc,CAAC;iBAAoC,CAAC;EAL/1G;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAErE"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,SAAS,kBAAkB,EAAE,GACtC,IAAI,CAON;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE5C;AAED,wBAAgB,aAAa;;;;EAE5B;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAErE"}
package/dist/logger.js CHANGED
@@ -1,4 +1,5 @@
1
- import { log, note, outro, spinner } from "@clack/prompts";
1
+ import { log, outro, spinner } from "@clack/prompts";
2
+ import { renderInstructions } from "./instruction-renderer.js";
2
3
  export function info(message) {
3
4
  log.info(message);
4
5
  }
@@ -8,8 +9,11 @@ export function warn(message) {
8
9
  export function success(message) {
9
10
  log.success(message);
10
11
  }
11
- export function printNextSteps(message, title = "Next steps") {
12
- note(message, title);
12
+ export function printInstructions(sections) {
13
+ process.stdout.write(renderInstructions(sections, {
14
+ columns: process.stdout.columns,
15
+ isTTY: process.stdout.isTTY,
16
+ }));
13
17
  }
14
18
  export function finish(message) {
15
19
  outro(message);
package/dist/prompts.d.ts CHANGED
@@ -1,5 +1,7 @@
1
+ import type { ProviderSlot } from "./composition/types.js";
1
2
  export declare class UserCancelledError extends Error {
2
3
  constructor();
3
4
  }
4
5
  export declare function promptForTargetDirectory(): Promise<string>;
6
+ export declare function promptForProvider(slot: ProviderSlot, initialValue?: string): Promise<string>;
5
7
  //# sourceMappingURL=prompts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAEA,qBAAa,kBAAmB,SAAQ,KAAK;;CAK5C;AAED,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,MAAM,CAAC,CAmBhE"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,cAGC;CACF;AAED,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,MAAM,CAAC,CAiBhE;AAkBD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,YAAY,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC,CAajB"}
package/dist/prompts.js CHANGED
@@ -1,4 +1,4 @@
1
- import { cancel, isCancel, text } from "@clack/prompts";
1
+ import { cancel, isCancel, select, text } from "@clack/prompts";
2
2
  export class UserCancelledError extends Error {
3
3
  constructor() {
4
4
  super("Operation cancelled by user.");
@@ -13,7 +13,6 @@ export async function promptForTargetDirectory() {
13
13
  if (!value?.trim()) {
14
14
  return "Please enter a folder name.";
15
15
  }
16
- return undefined;
17
16
  },
18
17
  });
19
18
  if (isCancel(result)) {
@@ -22,3 +21,27 @@ export async function promptForTargetDirectory() {
22
21
  }
23
22
  return result.trim();
24
23
  }
24
+ const PROVIDER_CHOICES = {
25
+ auth: [{ label: "WorkOS", value: "workos" }],
26
+ cms: [
27
+ {
28
+ hint: "includes the Drupal backend app",
29
+ label: "Drupal",
30
+ value: "drupal",
31
+ },
32
+ { label: "Contentstack", value: "contentstack" },
33
+ ],
34
+ commerce: [{ label: "Commercetools", value: "commercetools" }],
35
+ };
36
+ export async function promptForProvider(slot, initialValue) {
37
+ const result = await select({
38
+ initialValue,
39
+ message: `Choose the ${slot} provider`,
40
+ options: PROVIDER_CHOICES[slot],
41
+ });
42
+ if (isCancel(result)) {
43
+ cancel("Cancelled.");
44
+ throw new UserCancelledError();
45
+ }
46
+ return result;
47
+ }
@@ -1,8 +1,9 @@
1
1
  type SanitizeStarterOptions = {
2
2
  targetPath: string;
3
3
  targetName: string;
4
+ registryAuthoringPaths?: string[];
4
5
  };
5
- export declare function sanitizeStarter({ targetPath, targetName, }: SanitizeStarterOptions): Promise<{
6
+ export declare function sanitizeStarter({ targetPath, targetName, registryAuthoringPaths, }: SanitizeStarterOptions): Promise<{
6
7
  packageName: string;
7
8
  }>;
8
9
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AASA,KAAK,sBAAsB,GAAG;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAOF,wBAAsB,eAAe,CAAC,EACpC,UAAU,EACV,UAAU,GACX,EAAE,sBAAsB,GAAG,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAc3D"}
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAeA,KAAK,sBAAsB,GAAG;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;CACnC,CAAC;AAUF,wBAAsB,eAAe,CAAC,EACpC,UAAU,EACV,UAAU,EACV,sBAA2B,GAC5B,EAAE,sBAAsB,GAAG,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CA4B3D"}
package/dist/sanitize.js CHANGED
@@ -1,14 +1,23 @@
1
1
  import path from "node:path";
2
- import { SANITIZE_REMOVE_PATHS } from "./constants.js";
2
+ import { SANITIZE_REMOVE_PATHS, SANITIZE_REMOVE_ROOT_DEPENDENCIES, SANITIZE_REMOVE_ROOT_DEV_DEPENDENCIES, SANITIZE_REMOVE_SCRIPTS, } from "./constants.js";
3
3
  import { normalizePackageName, readJsonFile, removePath, writeJsonFile, } from "./fs-utils.js";
4
- export async function sanitizeStarter({ targetPath, targetName, }) {
5
- for (const relativePath of SANITIZE_REMOVE_PATHS) {
4
+ export async function sanitizeStarter({ targetPath, targetName, registryAuthoringPaths = [], }) {
5
+ await Promise.all([...SANITIZE_REMOVE_PATHS, ...registryAuthoringPaths].map(async (relativePath) => {
6
6
  await removePath(path.join(targetPath, relativePath));
7
- }
7
+ }));
8
8
  const packageJsonPath = path.join(targetPath, "package.json");
9
9
  const packageJson = await readJsonFile(packageJsonPath);
10
10
  const packageName = normalizePackageName(targetName);
11
11
  packageJson.name = packageName;
12
+ for (const script of SANITIZE_REMOVE_SCRIPTS) {
13
+ delete packageJson.scripts?.[script];
14
+ }
15
+ for (const dependency of SANITIZE_REMOVE_ROOT_DEPENDENCIES) {
16
+ delete packageJson.dependencies?.[dependency];
17
+ }
18
+ for (const dependency of SANITIZE_REMOVE_ROOT_DEV_DEPENDENCIES) {
19
+ delete packageJson.devDependencies?.[dependency];
20
+ }
12
21
  await writeJsonFile(packageJsonPath, packageJson);
13
22
  return { packageName };
14
23
  }
@@ -1,3 +1,7 @@
1
1
  import type { CreateOptions, ScaffoldResult } from "./types.js";
2
- export declare function scaffoldProject(options: CreateOptions): Promise<ScaffoldResult>;
2
+ type ScaffoldDependencies = {
3
+ install?: (cwd: string, verbose: boolean) => Promise<void>;
4
+ };
5
+ export declare function scaffoldProject(options: CreateOptions, dependencies?: ScaffoldDependencies): Promise<ScaffoldResult>;
6
+ export {};
3
7
  //# sourceMappingURL=scaffold.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EACV,aAAa,EAEb,cAAc,EACf,MAAM,YAAY,CAAC;AA8EpB,wBAAsB,eAAe,CACnC,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,cAAc,CAAC,CAyGzB"}
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAmDA,OAAO,KAAK,EACV,aAAa,EAEb,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB,KAAK,oBAAoB,GAAG;IAC1B,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D,CAAC;AA8KF,wBAAsB,eAAe,CACnC,OAAO,EAAE,aAAa,EACtB,YAAY,GAAE,oBAAyB,GACtC,OAAO,CAAC,cAAc,CAAC,CAuOzB"}