@penvhq/cli 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -9,7 +9,7 @@ import { ProjectionProvider, Provider, ParameterRef, Scope, AnyProvider, Rotatio
9
9
  * second kind.
10
10
  */
11
11
  type DoctorSeverity = "pass" | "warning" | "failure" | "unknown";
12
- type DoctorCheck = "schema" | "missing" | "declared" | "weak" | "unused" | "unscoped-fallback" | "plaintext-secret" | "public-secret" | "encryption" | "rotation-overdue" | "rotation-stuck" | "provider-value-drift" | "provider" | "projection-unreachable" | "projection-name-drift" | "projection-manual-edit" | "projection-value-drift" | "environment-flag-shadow";
12
+ type DoctorCheck = "schema" | "missing" | "declared" | "weak" | "unused" | "unscoped-fallback" | "plaintext-secret" | "public-secret" | "encryption" | "rotation-overdue" | "rotation-stuck" | "provider-value-drift" | "snapshot-stale" | "bundle-invisible-plaintext" | "provider" | "projection-unreachable" | "projection-name-drift" | "projection-manual-edit" | "projection-value-drift" | "environment-flag-shadow";
13
13
  interface DoctorFinding {
14
14
  readonly check: DoctorCheck;
15
15
  readonly severity: DoctorSeverity;
@@ -250,7 +250,7 @@ declare function runGet(options: GetOptions): Promise<string>;
250
250
  declare function runExplain(options: GetOptions): Promise<GetExplanation>;
251
251
 
252
252
  /** What init touched, so a caller can report it and a test can assert it. */
253
- type InitTarget = "penv-dir" | "schema" | "config" | "tsconfig" | "gitignore" | "seam";
253
+ type InitTarget = "penv-dir" | "schema" | "env" | "config" | "snapshot" | "tsconfig" | "gitignore" | "seam";
254
254
  /**
255
255
  * `conflicted` is the one that is not a success. penv wanted to write something,
256
256
  * found the user's file already saying something else about the same thing, and
@@ -310,6 +310,8 @@ interface InitOptions {
310
310
  readonly cwd: string;
311
311
  /** What to write. Omitted means the plan's defaults, as `--yes` takes them. */
312
312
  readonly decisions?: InitDecisions;
313
+ /** The detected framework name, passed by the command so the seam step need not re-detect it. */
314
+ readonly framework?: string;
313
315
  }
314
316
  interface AliasEdit {
315
317
  readonly source: string;
@@ -341,7 +343,7 @@ declare function runInit(options: InitOptions): InitResult;
341
343
  /**
342
344
  * Reading the user's schema, and the distance between it and the parameter tree.
343
345
  *
344
- * `.penv/env.ts` declares what must exist and the tree holds what does. The gap
346
+ * The schema declares what must exist and the tree holds what does. The gap
345
347
  * between them is the signal `penv validate` exists to raise; this module makes
346
348
  * it legible without closing it. Nothing here writes or deletes a value file —
347
349
  * a declaration has no value, so materialising one could only invent it, and an
@@ -357,7 +359,7 @@ declare function runInit(options: InitOptions): InitResult;
357
359
  * understand produces no line at all.
358
360
  */
359
361
 
360
- /** A parameter `.penv/env.ts` declares that the tree has no value for. */
362
+ /** A parameter the schema declares that the tree has no value for. */
361
363
  interface DeclaredDrift {
362
364
  /** The parameter id, or the dotted schema path when no filename could reach it. */
363
365
  readonly subject: string;
@@ -367,7 +369,7 @@ interface DeclaredDrift {
367
369
  readonly remedy: string;
368
370
  readonly detail: string;
369
371
  }
370
- /** A parameter the tree holds a value for that `.penv/env.ts` does not declare. */
372
+ /** A parameter the tree holds a value for that the schema does not declare. */
371
373
  interface UndeclaredDrift {
372
374
  readonly ref: ParameterRef;
373
375
  /** The generated variable, which is the name the application would have read. */
@@ -392,7 +394,7 @@ interface OptionalDrift {
392
394
  readonly remedy: string;
393
395
  }
394
396
  /**
395
- * The distance between `.penv/env.ts` and the tree, in both directions. Named
397
+ * The distance between the schema and the tree, in both directions. Named
396
398
  * `declared`/`undeclared` for the side that has it, not for a verdict: neither
397
399
  * direction is by itself an error, and only `validate` decides that. `optional`
398
400
  * is the deliberately verdict-free third list — see {@link OptionalDrift}.
@@ -572,6 +574,8 @@ interface MoveResult {
572
574
  readonly was: string;
573
575
  readonly now: string;
574
576
  };
577
+ /** The file that holds the shape to rename — cohort-aware, so the tip names one that exists. */
578
+ readonly schemaFile: string;
575
579
  }
576
580
  declare function runMove(options: MoveOptions): Promise<MoveResult>;
577
581
  declare function renderMove(result: MoveResult): string[];
@@ -705,6 +709,46 @@ interface RotateResult {
705
709
  declare function runRotate(options: RotateOptions): Promise<RotateResult>;
706
710
  declare function renderRotate(result: RotateResult): string[];
707
711
 
712
+ /**
713
+ * The committed snapshot — `penv.snapshot.ts` at the project root — that lets
714
+ * `load()` resolve in a bundled or serverless runtime where no `penv.config.ts`
715
+ * or `.penv/` tree is on disk. It embeds the evaluated config and every committed
716
+ * sealed value; the scaffolded `env.ts` imports it and passes it to `load`.
717
+ *
718
+ * Sealed records only, by decision: the snapshot ships exactly what a git clone
719
+ * already sees — ciphertext, safe to commit — and never plaintext, at any scope,
720
+ * nor either `.local` scope. Determinism is the point of the text output: value
721
+ * keys are code-unit sorted, so `doctor snapshot-stale` is a plain text compare
722
+ * against a recomputed snapshot.
723
+ *
724
+ * It sits beside `penv.config.ts` and `penv.schema.ts`, outside `.penv/`, so the
725
+ * value-file grammar walker never sees it (no `StrayCodeFileError`) and it is
726
+ * committed by default — the same placement rationale as the schema shape.
727
+ */
728
+
729
+ interface SnapshotWriteResult {
730
+ readonly file: string;
731
+ readonly action: "created" | "updated" | "unchanged";
732
+ }
733
+ /** What {@link wireEnvModule} did — `manual` carries the exact lines to add by hand. */
734
+ interface WireResult {
735
+ readonly file: string;
736
+ readonly action: "wired" | "kept" | "manual";
737
+ /** The import line to add — printed on `manual`. */
738
+ readonly importLine: string;
739
+ /** How to add `snapshot` to the load options — printed on `manual`. */
740
+ readonly loadHint: string;
741
+ }
742
+
743
+ interface SnapshotResult {
744
+ readonly write: SnapshotWriteResult;
745
+ readonly wire: WireResult;
746
+ }
747
+ declare function runSnapshot(options: {
748
+ readonly cwd: string;
749
+ }): SnapshotResult;
750
+ declare function renderSnapshot(result: SnapshotResult): string[];
751
+
708
752
  interface WatchOptions {
709
753
  readonly cwd: string;
710
754
  readonly environment?: string;
@@ -753,4 +797,4 @@ declare function renderWatch(result: ValidateResult): string[];
753
797
  declare const main: citty.CommandDef<citty.ArgsDef>;
754
798
  declare function runMain(): Promise<void>;
755
799
 
756
- export { type DoctorCheck, type DoctorFinding, type DoctorReport, type DoctorSeverity, type FillOptions, type FillPrompt, type FillResult, type GenerateResult, type GetExplanation, type ImportReport, type InitResult, type InitStep, LAST_PUSHED_KEY, type ListResult, type MoveResult, type PullOptions, type PullResult, type PushOptions, type PushResult, type RemoveResult, type ResealResult, type RotateOptions, type RotatePhase, type RotateResult, type SetResult, type ValidateIssue, type ValidateResult, type WatchHandle, type WatchOptions, generateDotenv, importDotenv, insertEnvAlias, main, renderDoctor, renderFill, renderMove, renderPull, renderPush, renderRotate, renderWatch, runDecrypt, runDoctor, runEncrypt, runExplain, runFill, runGenerate, runGet, runInit, runList, runMain, runMove, runPull, runPush, runRemove, runRotate, runSet, runValidate, runWatch };
800
+ export { type DoctorCheck, type DoctorFinding, type DoctorReport, type DoctorSeverity, type FillOptions, type FillPrompt, type FillResult, type GenerateResult, type GetExplanation, type ImportReport, type InitResult, type InitStep, LAST_PUSHED_KEY, type ListResult, type MoveResult, type PullOptions, type PullResult, type PushOptions, type PushResult, type RemoveResult, type ResealResult, type RotateOptions, type RotatePhase, type RotateResult, type SetResult, type SnapshotResult, type ValidateIssue, type ValidateResult, type WatchHandle, type WatchOptions, generateDotenv, importDotenv, insertEnvAlias, main, renderDoctor, renderFill, renderMove, renderPull, renderPush, renderRotate, renderSnapshot, renderWatch, runDecrypt, runDoctor, runEncrypt, runExplain, runFill, runGenerate, runGet, runInit, runList, runMain, runMove, runPull, runPush, runRemove, runRotate, runSet, runSnapshot, runValidate, runWatch };
package/dist/index.d.ts CHANGED
@@ -9,7 +9,7 @@ import { ProjectionProvider, Provider, ParameterRef, Scope, AnyProvider, Rotatio
9
9
  * second kind.
10
10
  */
11
11
  type DoctorSeverity = "pass" | "warning" | "failure" | "unknown";
12
- type DoctorCheck = "schema" | "missing" | "declared" | "weak" | "unused" | "unscoped-fallback" | "plaintext-secret" | "public-secret" | "encryption" | "rotation-overdue" | "rotation-stuck" | "provider-value-drift" | "provider" | "projection-unreachable" | "projection-name-drift" | "projection-manual-edit" | "projection-value-drift" | "environment-flag-shadow";
12
+ type DoctorCheck = "schema" | "missing" | "declared" | "weak" | "unused" | "unscoped-fallback" | "plaintext-secret" | "public-secret" | "encryption" | "rotation-overdue" | "rotation-stuck" | "provider-value-drift" | "snapshot-stale" | "bundle-invisible-plaintext" | "provider" | "projection-unreachable" | "projection-name-drift" | "projection-manual-edit" | "projection-value-drift" | "environment-flag-shadow";
13
13
  interface DoctorFinding {
14
14
  readonly check: DoctorCheck;
15
15
  readonly severity: DoctorSeverity;
@@ -250,7 +250,7 @@ declare function runGet(options: GetOptions): Promise<string>;
250
250
  declare function runExplain(options: GetOptions): Promise<GetExplanation>;
251
251
 
252
252
  /** What init touched, so a caller can report it and a test can assert it. */
253
- type InitTarget = "penv-dir" | "schema" | "config" | "tsconfig" | "gitignore" | "seam";
253
+ type InitTarget = "penv-dir" | "schema" | "env" | "config" | "snapshot" | "tsconfig" | "gitignore" | "seam";
254
254
  /**
255
255
  * `conflicted` is the one that is not a success. penv wanted to write something,
256
256
  * found the user's file already saying something else about the same thing, and
@@ -310,6 +310,8 @@ interface InitOptions {
310
310
  readonly cwd: string;
311
311
  /** What to write. Omitted means the plan's defaults, as `--yes` takes them. */
312
312
  readonly decisions?: InitDecisions;
313
+ /** The detected framework name, passed by the command so the seam step need not re-detect it. */
314
+ readonly framework?: string;
313
315
  }
314
316
  interface AliasEdit {
315
317
  readonly source: string;
@@ -341,7 +343,7 @@ declare function runInit(options: InitOptions): InitResult;
341
343
  /**
342
344
  * Reading the user's schema, and the distance between it and the parameter tree.
343
345
  *
344
- * `.penv/env.ts` declares what must exist and the tree holds what does. The gap
346
+ * The schema declares what must exist and the tree holds what does. The gap
345
347
  * between them is the signal `penv validate` exists to raise; this module makes
346
348
  * it legible without closing it. Nothing here writes or deletes a value file —
347
349
  * a declaration has no value, so materialising one could only invent it, and an
@@ -357,7 +359,7 @@ declare function runInit(options: InitOptions): InitResult;
357
359
  * understand produces no line at all.
358
360
  */
359
361
 
360
- /** A parameter `.penv/env.ts` declares that the tree has no value for. */
362
+ /** A parameter the schema declares that the tree has no value for. */
361
363
  interface DeclaredDrift {
362
364
  /** The parameter id, or the dotted schema path when no filename could reach it. */
363
365
  readonly subject: string;
@@ -367,7 +369,7 @@ interface DeclaredDrift {
367
369
  readonly remedy: string;
368
370
  readonly detail: string;
369
371
  }
370
- /** A parameter the tree holds a value for that `.penv/env.ts` does not declare. */
372
+ /** A parameter the tree holds a value for that the schema does not declare. */
371
373
  interface UndeclaredDrift {
372
374
  readonly ref: ParameterRef;
373
375
  /** The generated variable, which is the name the application would have read. */
@@ -392,7 +394,7 @@ interface OptionalDrift {
392
394
  readonly remedy: string;
393
395
  }
394
396
  /**
395
- * The distance between `.penv/env.ts` and the tree, in both directions. Named
397
+ * The distance between the schema and the tree, in both directions. Named
396
398
  * `declared`/`undeclared` for the side that has it, not for a verdict: neither
397
399
  * direction is by itself an error, and only `validate` decides that. `optional`
398
400
  * is the deliberately verdict-free third list — see {@link OptionalDrift}.
@@ -572,6 +574,8 @@ interface MoveResult {
572
574
  readonly was: string;
573
575
  readonly now: string;
574
576
  };
577
+ /** The file that holds the shape to rename — cohort-aware, so the tip names one that exists. */
578
+ readonly schemaFile: string;
575
579
  }
576
580
  declare function runMove(options: MoveOptions): Promise<MoveResult>;
577
581
  declare function renderMove(result: MoveResult): string[];
@@ -705,6 +709,46 @@ interface RotateResult {
705
709
  declare function runRotate(options: RotateOptions): Promise<RotateResult>;
706
710
  declare function renderRotate(result: RotateResult): string[];
707
711
 
712
+ /**
713
+ * The committed snapshot — `penv.snapshot.ts` at the project root — that lets
714
+ * `load()` resolve in a bundled or serverless runtime where no `penv.config.ts`
715
+ * or `.penv/` tree is on disk. It embeds the evaluated config and every committed
716
+ * sealed value; the scaffolded `env.ts` imports it and passes it to `load`.
717
+ *
718
+ * Sealed records only, by decision: the snapshot ships exactly what a git clone
719
+ * already sees — ciphertext, safe to commit — and never plaintext, at any scope,
720
+ * nor either `.local` scope. Determinism is the point of the text output: value
721
+ * keys are code-unit sorted, so `doctor snapshot-stale` is a plain text compare
722
+ * against a recomputed snapshot.
723
+ *
724
+ * It sits beside `penv.config.ts` and `penv.schema.ts`, outside `.penv/`, so the
725
+ * value-file grammar walker never sees it (no `StrayCodeFileError`) and it is
726
+ * committed by default — the same placement rationale as the schema shape.
727
+ */
728
+
729
+ interface SnapshotWriteResult {
730
+ readonly file: string;
731
+ readonly action: "created" | "updated" | "unchanged";
732
+ }
733
+ /** What {@link wireEnvModule} did — `manual` carries the exact lines to add by hand. */
734
+ interface WireResult {
735
+ readonly file: string;
736
+ readonly action: "wired" | "kept" | "manual";
737
+ /** The import line to add — printed on `manual`. */
738
+ readonly importLine: string;
739
+ /** How to add `snapshot` to the load options — printed on `manual`. */
740
+ readonly loadHint: string;
741
+ }
742
+
743
+ interface SnapshotResult {
744
+ readonly write: SnapshotWriteResult;
745
+ readonly wire: WireResult;
746
+ }
747
+ declare function runSnapshot(options: {
748
+ readonly cwd: string;
749
+ }): SnapshotResult;
750
+ declare function renderSnapshot(result: SnapshotResult): string[];
751
+
708
752
  interface WatchOptions {
709
753
  readonly cwd: string;
710
754
  readonly environment?: string;
@@ -753,4 +797,4 @@ declare function renderWatch(result: ValidateResult): string[];
753
797
  declare const main: citty.CommandDef<citty.ArgsDef>;
754
798
  declare function runMain(): Promise<void>;
755
799
 
756
- export { type DoctorCheck, type DoctorFinding, type DoctorReport, type DoctorSeverity, type FillOptions, type FillPrompt, type FillResult, type GenerateResult, type GetExplanation, type ImportReport, type InitResult, type InitStep, LAST_PUSHED_KEY, type ListResult, type MoveResult, type PullOptions, type PullResult, type PushOptions, type PushResult, type RemoveResult, type ResealResult, type RotateOptions, type RotatePhase, type RotateResult, type SetResult, type ValidateIssue, type ValidateResult, type WatchHandle, type WatchOptions, generateDotenv, importDotenv, insertEnvAlias, main, renderDoctor, renderFill, renderMove, renderPull, renderPush, renderRotate, renderWatch, runDecrypt, runDoctor, runEncrypt, runExplain, runFill, runGenerate, runGet, runInit, runList, runMain, runMove, runPull, runPush, runRemove, runRotate, runSet, runValidate, runWatch };
800
+ export { type DoctorCheck, type DoctorFinding, type DoctorReport, type DoctorSeverity, type FillOptions, type FillPrompt, type FillResult, type GenerateResult, type GetExplanation, type ImportReport, type InitResult, type InitStep, LAST_PUSHED_KEY, type ListResult, type MoveResult, type PullOptions, type PullResult, type PushOptions, type PushResult, type RemoveResult, type ResealResult, type RotateOptions, type RotatePhase, type RotateResult, type SetResult, type SnapshotResult, type ValidateIssue, type ValidateResult, type WatchHandle, type WatchOptions, generateDotenv, importDotenv, insertEnvAlias, main, renderDoctor, renderFill, renderMove, renderPull, renderPush, renderRotate, renderSnapshot, renderWatch, runDecrypt, runDoctor, runEncrypt, runExplain, runFill, runGenerate, runGet, runInit, runList, runMain, runMove, runPull, runPush, runRemove, runRotate, runSet, runSnapshot, runValidate, runWatch };