create-paratix 0.10.0 → 0.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -44,8 +44,9 @@ cd my-server
44
44
  Run the bootstrap flow:
45
45
 
46
46
  ```bash
47
+ pnpm apply:first-run:dry
48
+ pnpm apply:first-run
47
49
  pnpm apply:dry
48
- pnpm apply --first-run
49
50
  pnpm apply
50
51
  ```
51
52
 
@@ -75,12 +76,13 @@ The scaffolded project includes:
75
76
  The generated project keeps this explicit:
76
77
 
77
78
  - `paratix apply ... --first-run` stays on port `22`, completes the hardened bootstrap stage, and stops intentionally at the first-run checkpoint
78
- - later runs use the hardened path, usually on port `2222`, with strict host-key checking again
79
+ - first and later runs use strict host-key checking; pin `expectedHostFingerprint`/`expectedHostPublicKey` or pre-populate `known_hosts` before connecting
80
+ - later runs use the hardened path, usually on port `2222`, with the same strict host-key checking
79
81
 
80
82
  When you scaffold interactively, the CLI can also:
81
83
 
82
84
  - select an admin public key from `~/.ssh`
83
- - pin the current host key from SSH port `22` as `expectedHostFingerprint`
85
+ - scan the current host key from SSH port `22` and pin it as `expectedHostFingerprint` after you verify it out of band
84
86
 
85
87
  ## Non-Interactive Usage
86
88
 
package/dist/index.d.ts CHANGED
@@ -1,8 +1,3 @@
1
- type PackageManager = {
2
- command: string;
3
- name: string;
4
- };
5
-
6
1
  type InitialUserConfig = {
7
2
  kind: "admin";
8
3
  user: string;
@@ -10,6 +5,83 @@ type InitialUserConfig = {
10
5
  kind: "root";
11
6
  };
12
7
 
8
+ type PackageManagerCommand = {
9
+ args: readonly string[];
10
+ executable: string;
11
+ };
12
+ type PackageManager = {
13
+ command: PackageManagerCommand;
14
+ name: string;
15
+ };
16
+
17
+ type ExitWithMessage = (message: string) => never;
18
+ declare function normalizeInitialUserName(name: string): string;
19
+ declare function isValidInitialUserName(name: string): boolean;
20
+ declare function normalizeHost(value: string): string;
21
+ declare function isValidHost(value: string): boolean;
22
+ declare function isValidExpectedHostFingerprint(value: string): boolean;
23
+ type ParsedCliArguments = {
24
+ adminPublicKey: string | undefined;
25
+ adminPublicKeyFile: string | undefined;
26
+ expectedHostFingerprint: string | undefined;
27
+ host: string | undefined;
28
+ initialUser: string | undefined;
29
+ projectName: string | undefined;
30
+ };
31
+ declare function parseCliArguments$1(argv: string[], exitWithMessage: ExitWithMessage): ParsedCliArguments;
32
+
33
+ /**
34
+ * R-0000189: dedicated error type that signals a deterministic CLI exit. A
35
+ * synchronous `process.exit` call from inside an interactive prompt skips
36
+ * any in-flight cleanup (raw-mode reset, cursor visibility), which leaves
37
+ * the operator's terminal unusable. Throwing instead lets `main()` (or any
38
+ * other top-level driver) run cleanup and assign `process.exitCode` before
39
+ * the process exits naturally.
40
+ *
41
+ * Lives in its own module so low-level helpers (e.g. scaffoldConfig prompts)
42
+ * can reuse it without forming a circular dependency with cliValidation.
43
+ */
44
+ declare class CliExitError extends Error {
45
+ readonly cliMessage: string;
46
+ readonly exitCode: number;
47
+ readonly reported: boolean;
48
+ constructor(message: string, exitCode?: number, options?: {
49
+ reported?: boolean;
50
+ });
51
+ }
52
+
53
+ /**
54
+ * R-0000189: shared cleanup hook so `main()` can reset interactive terminal
55
+ * state (cursor visibility, raw mode) after a CliExitError was thrown from
56
+ * an in-flight prompt. Kept as a small no-op-friendly default so the unit
57
+ * tests can substitute their own implementation.
58
+ */
59
+ declare function restoreInteractiveTerminal(): void;
60
+ /**
61
+ * R-0000189: top-level handler that converts a thrown CliExitError into the
62
+ * intended exit code while running interactive cleanup. Other thrown errors
63
+ * are still surfaced as a generic CLI error. CliExitError instances thrown
64
+ * directly from prompt paths have not necessarily emitted their user-visible
65
+ * message yet, so this handler prints only unreported CliExitError messages.
66
+ *
67
+ * @param error - The error caught from the CLI pipeline.
68
+ */
69
+ declare function handleCliExit(error: unknown): void;
70
+ declare function parseCliArguments(argv: string[]): ReturnType<typeof parseCliArguments$1>;
71
+ declare function parseInitialUserConfig(value: string): InitialUserConfig;
72
+ declare function validateHost(value: string): string;
73
+ declare function validateExpectedHostFingerprint(value: string): string;
74
+ declare function resolveCliOrPromptHost(host: string | undefined, prompt?: () => Promise<string>): Promise<string>;
75
+
76
+ declare function deriveParatixDependencyRange(): string;
77
+
78
+ declare function isDirectExecution(moduleUrl: string, argv1: null | string | undefined): boolean;
79
+
80
+ type HostFingerprintScanResult = {
81
+ algorithm: string;
82
+ fingerprint: string;
83
+ };
84
+
13
85
  type SelectOption<TValue extends string> = {
14
86
  description: string;
15
87
  label: string;
@@ -18,19 +90,23 @@ type SelectOption<TValue extends string> = {
18
90
  type SelectFunction<TValue extends string> = (prompt: string, options: Array<SelectOption<TValue>>) => Promise<TValue>;
19
91
 
20
92
  type PromptFunction = (question: string) => Promise<string>;
93
+ type InitialUserPromptSession = {
94
+ ask: PromptFunction;
95
+ chooseInitialUser: SelectFunction<"admin" | "root">;
96
+ closePrompt: () => void;
97
+ closeSelect: () => void;
98
+ };
21
99
  declare function promptForHost(prompt?: PromptFunction, closePrompt?: () => void): Promise<string>;
22
- declare function promptForInitialUserConfig(prompt?: PromptFunction, select?: SelectFunction<"admin" | "root">): Promise<InitialUserConfig>;
100
+ declare function promptForInitialUserConfig(prompt?: PromptFunction, select?: SelectFunction<"admin" | "root">, createSession?: (prompt?: PromptFunction) => InitialUserPromptSession): Promise<InitialUserConfig>;
23
101
  declare function promptForAdminPublicKey(select?: SelectFunction<string>, publicKeys?: Array<{
24
102
  key: string;
25
103
  label: string;
26
104
  path: string;
27
- }>): Promise<string | undefined>;
28
- declare function promptForHostFingerprint(host: string, select?: SelectFunction<"placeholder" | "scan">, scanner?: (host: string) => Promise<string>): Promise<string | undefined>;
29
-
30
- declare function normalizeInitialUserName(name: string): string;
31
- declare function isValidInitialUserName(name: string): boolean;
32
- declare function normalizeHost(value: string): string;
33
- declare function isValidHost(value: string): boolean;
105
+ }>, options?: {
106
+ allowPlaceholder?: boolean;
107
+ }): Promise<string | undefined>;
108
+ type HostFingerprintSelectValue = "discard" | "pin" | "placeholder" | "scan";
109
+ declare function promptForHostFingerprint(host: string, select?: SelectFunction<HostFingerprintSelectValue>, scanner?: (host: string) => Promise<HostFingerprintScanResult>): Promise<string | undefined>;
34
110
 
35
111
  type ScaffoldOptions = {
36
112
  adminPublicKey?: string;
@@ -42,16 +118,6 @@ type ScaffoldOptions = {
42
118
  declare function writeProjectFiles(projectDirectory: string, options?: ScaffoldOptions): void;
43
119
  declare function isValidProjectName(name: string): boolean;
44
120
  declare function normalizeProjectName(name: string): string;
45
- declare function parseCliArguments(argv: string[]): {
46
- adminPublicKey: string | undefined;
47
- adminPublicKeyFile: string | undefined;
48
- host: string | undefined;
49
- initialUser: string | undefined;
50
- projectName: string | undefined;
51
- };
52
- declare function parseInitialUserConfig(value: string): InitialUserConfig;
53
- declare function validateHost(value: string): string;
54
121
  declare function scaffoldProject(projectName: string, pm: PackageManager, options?: ScaffoldOptions): boolean;
55
- declare function isDirectExecution(moduleUrl: string, argv1: null | string | undefined): boolean;
56
122
 
57
- export { type InitialUserConfig, isDirectExecution, isValidHost, isValidInitialUserName, isValidProjectName, normalizeHost, normalizeInitialUserName, normalizeProjectName, parseCliArguments, parseInitialUserConfig, promptForAdminPublicKey, promptForHost, promptForHostFingerprint, promptForInitialUserConfig, scaffoldProject, validateHost, writeProjectFiles };
123
+ export { CliExitError, type InitialUserConfig, type ScaffoldOptions, deriveParatixDependencyRange, handleCliExit, isDirectExecution, isValidExpectedHostFingerprint, isValidHost, isValidInitialUserName, isValidProjectName, normalizeHost, normalizeInitialUserName, normalizeProjectName, parseCliArguments, parseInitialUserConfig, promptForAdminPublicKey, promptForHost, promptForHostFingerprint, promptForInitialUserConfig, resolveCliOrPromptHost, restoreInteractiveTerminal, scaffoldProject, validateExpectedHostFingerprint, validateHost, writeProjectFiles };