@metaobjectsdev/codegen-ts 0.23.2 → 0.24.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 (168) hide show
  1. package/dist/generator.d.ts +9 -0
  2. package/dist/generator.d.ts.map +1 -1
  3. package/dist/generator.js.map +1 -1
  4. package/dist/generators/api-field-shape.js +1 -1
  5. package/dist/generators/api-field-shape.js.map +1 -1
  6. package/dist/generators/api-model.d.ts.map +1 -1
  7. package/dist/generators/api-model.js +71 -42
  8. package/dist/generators/api-model.js.map +1 -1
  9. package/dist/generators/docs-data-builder.d.ts.map +1 -1
  10. package/dist/generators/docs-data-builder.js +36 -1
  11. package/dist/generators/docs-data-builder.js.map +1 -1
  12. package/dist/generators/docs-data.d.ts +14 -0
  13. package/dist/generators/docs-data.d.ts.map +1 -1
  14. package/dist/generators/docs-file.d.ts.map +1 -1
  15. package/dist/generators/docs-file.js +13 -4
  16. package/dist/generators/docs-file.js.map +1 -1
  17. package/dist/generators/extractor-file.d.ts.map +1 -1
  18. package/dist/generators/extractor-file.js +7 -11
  19. package/dist/generators/extractor-file.js.map +1 -1
  20. package/dist/generators/index.d.ts +4 -0
  21. package/dist/generators/index.d.ts.map +1 -1
  22. package/dist/generators/index.js +5 -0
  23. package/dist/generators/index.js.map +1 -1
  24. package/dist/generators/output-parser-file.d.ts.map +1 -1
  25. package/dist/generators/output-parser-file.js +12 -7
  26. package/dist/generators/output-parser-file.js.map +1 -1
  27. package/dist/generators/output-prompt-file.d.ts.map +1 -1
  28. package/dist/generators/output-prompt-file.js +14 -24
  29. package/dist/generators/output-prompt-file.js.map +1 -1
  30. package/dist/generators/requirement-tests.d.ts +44 -0
  31. package/dist/generators/requirement-tests.d.ts.map +1 -0
  32. package/dist/generators/requirement-tests.js +127 -0
  33. package/dist/generators/requirement-tests.js.map +1 -0
  34. package/dist/generators/requirements-file.d.ts +9 -0
  35. package/dist/generators/requirements-file.d.ts.map +1 -0
  36. package/dist/generators/requirements-file.js +53 -0
  37. package/dist/generators/requirements-file.js.map +1 -0
  38. package/dist/generators/requirements-markdown.d.ts +10 -0
  39. package/dist/generators/requirements-markdown.d.ts.map +1 -0
  40. package/dist/generators/requirements-markdown.js +71 -0
  41. package/dist/generators/requirements-markdown.js.map +1 -0
  42. package/dist/generators/requirements-toon.d.ts +3 -0
  43. package/dist/generators/requirements-toon.d.ts.map +1 -0
  44. package/dist/generators/requirements-toon.js +47 -0
  45. package/dist/generators/requirements-toon.js.map +1 -0
  46. package/dist/generators/requirements-view.d.ts +32 -0
  47. package/dist/generators/requirements-view.d.ts.map +1 -0
  48. package/dist/generators/requirements-view.js +64 -0
  49. package/dist/generators/requirements-view.js.map +1 -0
  50. package/dist/generators/trace-helper-file.d.ts.map +1 -1
  51. package/dist/generators/trace-helper-file.js +19 -11
  52. package/dist/generators/trace-helper-file.js.map +1 -1
  53. package/dist/index.d.ts +13 -1
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +18 -0
  56. package/dist/index.js.map +1 -1
  57. package/dist/metaobjects-config.d.ts +12 -20
  58. package/dist/metaobjects-config.d.ts.map +1 -1
  59. package/dist/metaobjects-config.js +5 -1
  60. package/dist/metaobjects-config.js.map +1 -1
  61. package/dist/orphan-sweep.d.ts +38 -0
  62. package/dist/orphan-sweep.d.ts.map +1 -0
  63. package/dist/orphan-sweep.js +129 -0
  64. package/dist/orphan-sweep.js.map +1 -0
  65. package/dist/overwrite-policy.d.ts +97 -3
  66. package/dist/overwrite-policy.d.ts.map +1 -1
  67. package/dist/overwrite-policy.js +293 -81
  68. package/dist/overwrite-policy.js.map +1 -1
  69. package/dist/projection/build-projection-views.d.ts +8 -0
  70. package/dist/projection/build-projection-views.d.ts.map +1 -1
  71. package/dist/projection/build-projection-views.js +7 -4
  72. package/dist/projection/build-projection-views.js.map +1 -1
  73. package/dist/projection/extract-view-spec.d.ts.map +1 -1
  74. package/dist/projection/extract-view-spec.js +70 -4
  75. package/dist/projection/extract-view-spec.js.map +1 -1
  76. package/dist/projection/view-ddl-emit.d.ts.map +1 -1
  77. package/dist/projection/view-ddl-emit.js +52 -0
  78. package/dist/projection/view-ddl-emit.js.map +1 -1
  79. package/dist/projection/view-spec.d.ts +15 -0
  80. package/dist/projection/view-spec.d.ts.map +1 -1
  81. package/dist/reconcile-orphans.d.ts +80 -0
  82. package/dist/reconcile-orphans.d.ts.map +1 -0
  83. package/dist/reconcile-orphans.js +61 -0
  84. package/dist/reconcile-orphans.js.map +1 -0
  85. package/dist/render-engine/embedded-templates.generated.js +1 -1
  86. package/dist/render-engine/embedded-templates.generated.js.map +1 -1
  87. package/dist/requirement-walk.d.ts +57 -0
  88. package/dist/requirement-walk.d.ts.map +1 -0
  89. package/dist/requirement-walk.js +94 -0
  90. package/dist/requirement-walk.js.map +1 -0
  91. package/dist/runner.d.ts +35 -0
  92. package/dist/runner.d.ts.map +1 -1
  93. package/dist/runner.js +217 -21
  94. package/dist/runner.js.map +1 -1
  95. package/dist/templates/extractor.d.ts +4 -4
  96. package/dist/templates/extractor.d.ts.map +1 -1
  97. package/dist/templates/extractor.js +18 -22
  98. package/dist/templates/extractor.js.map +1 -1
  99. package/dist/templates/find-inbound.d.ts +44 -0
  100. package/dist/templates/find-inbound.d.ts.map +1 -0
  101. package/dist/templates/find-inbound.js +69 -0
  102. package/dist/templates/find-inbound.js.map +1 -0
  103. package/dist/templates/inferred-types.d.ts.map +1 -1
  104. package/dist/templates/inferred-types.js +8 -4
  105. package/dist/templates/inferred-types.js.map +1 -1
  106. package/dist/templates/output-format-spec-emitter.d.ts.map +1 -1
  107. package/dist/templates/output-format-spec-emitter.js +7 -4
  108. package/dist/templates/output-format-spec-emitter.js.map +1 -1
  109. package/dist/templates/output-parser.d.ts +8 -3
  110. package/dist/templates/output-parser.d.ts.map +1 -1
  111. package/dist/templates/output-parser.js +71 -31
  112. package/dist/templates/output-parser.js.map +1 -1
  113. package/dist/templates/output-prompt.d.ts +6 -5
  114. package/dist/templates/output-prompt.d.ts.map +1 -1
  115. package/dist/templates/output-prompt.js +26 -37
  116. package/dist/templates/output-prompt.js.map +1 -1
  117. package/dist/templates/queries.js +1 -1
  118. package/dist/templates/queries.js.map +1 -1
  119. package/dist/templates/requirement-test.d.ts +12 -0
  120. package/dist/templates/requirement-test.d.ts.map +1 -0
  121. package/dist/templates/requirement-test.js +120 -0
  122. package/dist/templates/requirement-test.js.map +1 -0
  123. package/dist/templates/zod-validators.d.ts.map +1 -1
  124. package/dist/templates/zod-validators.js +32 -15
  125. package/dist/templates/zod-validators.js.map +1 -1
  126. package/package.json +9 -8
  127. package/src/generator.ts +9 -0
  128. package/src/generators/api-field-shape.ts +1 -1
  129. package/src/generators/api-model.ts +69 -44
  130. package/src/generators/docs-data-builder.ts +37 -0
  131. package/src/generators/docs-data.ts +15 -0
  132. package/src/generators/docs-file.ts +13 -4
  133. package/src/generators/extractor-file.ts +7 -11
  134. package/src/generators/index.ts +11 -0
  135. package/src/generators/output-parser-file.ts +12 -7
  136. package/src/generators/output-prompt-file.ts +14 -27
  137. package/src/generators/requirement-tests.ts +203 -0
  138. package/src/generators/requirements-file.ts +71 -0
  139. package/src/generators/requirements-markdown.ts +72 -0
  140. package/src/generators/requirements-toon.ts +64 -0
  141. package/src/generators/requirements-view.ts +93 -0
  142. package/src/generators/trace-helper-file.ts +20 -10
  143. package/src/index.ts +47 -1
  144. package/src/metaobjects-config.ts +17 -22
  145. package/src/orphan-sweep.ts +178 -0
  146. package/src/overwrite-policy.ts +362 -89
  147. package/src/projection/build-projection-views.ts +15 -4
  148. package/src/projection/extract-view-spec.ts +62 -3
  149. package/src/projection/view-ddl-emit.ts +54 -0
  150. package/src/projection/view-spec.ts +25 -0
  151. package/src/reconcile-orphans.ts +136 -0
  152. package/src/reference/barrel.ts +4 -0
  153. package/src/reference/entity.ts +4 -0
  154. package/src/reference/queries.ts +4 -0
  155. package/src/reference/routes.ts +4 -0
  156. package/src/render-engine/embedded-templates.generated.ts +1 -1
  157. package/src/requirement-walk.ts +124 -0
  158. package/src/runner.ts +266 -27
  159. package/src/templates/extractor.ts +19 -24
  160. package/src/templates/find-inbound.ts +96 -0
  161. package/src/templates/inferred-types.ts +8 -4
  162. package/src/templates/output-format-spec-emitter.ts +7 -4
  163. package/src/templates/output-parser.ts +76 -34
  164. package/src/templates/output-prompt.ts +29 -42
  165. package/src/templates/queries.ts +1 -1
  166. package/src/templates/requirement-test.ts +140 -0
  167. package/src/templates/zod-validators.ts +32 -15
  168. package/templates/docs/entity-page.md.mustache +8 -0
@@ -0,0 +1,129 @@
1
+ // FR-038 §8 — bind the orphan decision to the filesystem.
2
+ //
3
+ // reconcile-orphans.ts is deliberately pure: it answers "remove, refuse, or
4
+ // already gone?" from readers the caller supplies. This module supplies those
5
+ // readers, applies the answer, and keeps `.gen-state` honest afterwards. Keeping
6
+ // the two apart is what lets the RULE be tested without a filesystem and the
7
+ // PLUMBING be tested against real files, rather than only through a full runGen.
8
+ //
9
+ // Three properties this file is responsible for, none of which the pure decision
10
+ // can enforce on its own:
11
+ //
12
+ // 1. NAMESPACE SCOPE. A generator's `owns` predicate speaks in paths relative
13
+ // to its own output directory; gen-state speaks in project-relative paths.
14
+ // Translating between them is where a boundary is won or lost, so a path
15
+ // that resolves outside the generator's directory is never even offered to
16
+ // the predicate.
17
+ // 2. RECORD HYGIENE. A removed or already-gone path must be forgotten, or the
18
+ // next run re-decides a settled orphan forever. A REFUSED path must be
19
+ // kept, or a refusal degrades into permanent silence on the run after.
20
+ // 3. DRY-RUN HONESTY. `--dry-run` must report a pending deletion and perform
21
+ // none, because a preview that hides a deletion is worse than no preview.
22
+ import { existsSync, readFileSync, rmSync } from "node:fs";
23
+ import { isAbsolute, relative, resolve, sep } from "node:path";
24
+ import { listGeneratedPaths, isPristineGenerated, forgetGeneratedPaths, } from "./overwrite-policy.js";
25
+ import { reconcileOrphans } from "./reconcile-orphans.js";
26
+ /** gen-state keys carry the platform separator; an `owns` predicate is written
27
+ * against generated output, which is always `/`-separated. Normalize once so a
28
+ * predicate authored the obvious way is not silently wrong off Linux. */
29
+ function toPosix(p) {
30
+ return sep === "/" ? p : p.split(sep).join("/");
31
+ }
32
+ export function sweepOrphans(args) {
33
+ if (args.jobs.length === 0) {
34
+ return { removed: [], refused: [], forced: [], refusedBy: new Map() };
35
+ }
36
+ const previouslyGenerated = listGeneratedPaths(args.genStateDir);
37
+ if (previouslyGenerated.length === 0) {
38
+ return { removed: [], refused: [], forced: [], refusedBy: new Map() };
39
+ }
40
+ // NOT normalized: both sides of this comparison are produced by
41
+ // `relative(projectRoot, …)` — gen-state's keys and the runner's emitted paths
42
+ // alike — so they already share whatever separator the platform uses.
43
+ // Normalizing one side is what would break them apart. `toPosix` is used only
44
+ // where a HUMAN-authored string is involved (the `owns` predicate below).
45
+ const emitted = args.emittedRelPaths;
46
+ // A path can fall inside two jobs' namespaces (an app may register several
47
+ // requirementTests() instances). Sets keep the second visit from re-reporting
48
+ // a file the first already dealt with.
49
+ const removed = new Set();
50
+ const refused = new Set();
51
+ const forced = new Set();
52
+ const forget = new Set();
53
+ const refusedBy = new Map();
54
+ for (const job of args.jobs) {
55
+ const decision = reconcileOrphans({
56
+ previouslyGenerated,
57
+ emitted,
58
+ owns: (relPath) => {
59
+ const inTarget = relative(job.writeOutDir, resolve(args.projectRoot, relPath));
60
+ // "" is the directory itself; a `..` prefix or an absolute result means
61
+ // the path is outside this generator's output entirely. Neither is
62
+ // something the predicate should get a say in.
63
+ if (inTarget === "" || inTarget.startsWith("..") || isAbsolute(inTarget)) {
64
+ return false;
65
+ }
66
+ return job.policy.owns(toPosix(inTarget));
67
+ },
68
+ exists: (relPath) => existsSync(resolve(args.projectRoot, relPath)),
69
+ // The committed hash manifest, NOT the snapshot body — the bodies are
70
+ // gitignored, so on a fresh clone a body-based check could never prove a
71
+ // file untouched and orphan cleanup would refuse everything forever.
72
+ isUntouched: (relPath) => {
73
+ const full = resolve(args.projectRoot, relPath);
74
+ if (!existsSync(full))
75
+ return false;
76
+ return isPristineGenerated(args.genStateDir, relPath, readFileSync(full, "utf-8"));
77
+ },
78
+ });
79
+ for (const relPath of decision.remove) {
80
+ if (refused.has(relPath) || forced.has(relPath))
81
+ continue;
82
+ removed.add(relPath);
83
+ forget.add(relPath);
84
+ }
85
+ for (const relPath of decision.refused) {
86
+ // `refused` belongs in this guard too. Without it, a path already refused by a
87
+ // non-forcing job could be picked up by a later FORCING job whose namespace
88
+ // overlaps (the file anticipates several requirementTests() instances), landing
89
+ // in `refused` and `forced` at once — deleted from disk, while
90
+ // `refusedOrphanMessage` tells the user it "was NOT deleted".
91
+ //
92
+ // First decision wins: a refusal is the conservative answer, and letting a
93
+ // later job escalate it to a deletion would make the outcome depend on job
94
+ // ORDER, which is exactly the ambiguity the runner's duplicate-path guard
95
+ // exists to reject elsewhere.
96
+ if (removed.has(relPath) || forced.has(relPath) || refused.has(relPath))
97
+ continue;
98
+ if (job.policy.force === true) {
99
+ forced.add(relPath);
100
+ forget.add(relPath);
101
+ }
102
+ else {
103
+ // Deliberately NOT forgotten: the record is what makes the refusal
104
+ // repeat until someone resolves it.
105
+ refused.add(relPath);
106
+ refusedBy.set(relPath, job.generatorName);
107
+ }
108
+ }
109
+ // Nothing on disk to report — the file is already gone. Clear the stale
110
+ // record so this stops being reconsidered on every future run.
111
+ for (const relPath of decision.vanished)
112
+ forget.add(relPath);
113
+ }
114
+ if (!args.dryRun) {
115
+ for (const relPath of [...removed, ...forced]) {
116
+ rmSync(resolve(args.projectRoot, relPath), { force: true });
117
+ }
118
+ // Batched: the per-path form rewrites the whole manifest each call, so clearing
119
+ // k orphans rewrote it k times for an identical result.
120
+ forgetGeneratedPaths(args.genStateDir, forget);
121
+ }
122
+ return {
123
+ removed: [...removed].sort(),
124
+ refused: [...refused].sort(),
125
+ forced: [...forced].sort(),
126
+ refusedBy,
127
+ };
128
+ }
129
+ //# sourceMappingURL=orphan-sweep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orphan-sweep.js","sourceRoot":"","sources":["../src/orphan-sweep.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,10 @@
1
- export type WriteStatus = "new" | "unchanged" | "overwrite" | "merged" | "conflict" | "refused" | "skipped";
1
+ export type WriteStatus = "new" | "unchanged" | "overwrite" | "merged" | "conflict" | "refused" | "skipped"
2
+ /** FR-038 §8 — deleted because it was generated by a previous run, is no longer
3
+ * generated, and was never edited by hand. Reported as a file outcome rather
4
+ * than a warning because a deletion is exactly as consequential as a write,
5
+ * and a run summary that lists writes but hides deletions is how a silent
6
+ * deletion happens. */
7
+ | "removed";
2
8
  /**
3
9
  * "overwrite" — default; three-way merge if .gen-state exists, else write-if-
4
10
  * different / first-time-existing flow.
@@ -27,10 +33,74 @@ export interface DecideAndWriteOpts {
27
33
  export interface WriteResult {
28
34
  path: string;
29
35
  status: WriteStatus;
30
- /** Present when status is "conflict" — human-readable hint identifying the
31
- * file the user must resolve. */
36
+ /** Present when status is "conflict" or "refused" — human-readable reason,
37
+ * naming what the user must do. A refusal nobody can act on gets the file
38
+ * deleted by hand, which is the outcome refusing exists to prevent. */
32
39
  conflictHint?: string;
33
40
  }
41
+ /**
42
+ * Every snapshot key recorded under `genStateDir` — in a runner-driven project,
43
+ * the project-relative path of every file some previous `meta gen` wrote.
44
+ *
45
+ * Empty for a gen-state directory that does not exist yet, which is what makes a
46
+ * first run, an ephemeral test run and `verify --codegen`'s throwaway root all
47
+ * reconcile nothing.
48
+ */
49
+ export declare function listGeneratedPaths(genStateDir: string): string[];
50
+ /**
51
+ * sha-256 of `content`, hex — the same function that produces `.hashes.json`.
52
+ *
53
+ * Exported so a caller can ask the one question the manifest exists to answer
54
+ * ("is this file byte-for-byte what we recorded writing?") without needing the
55
+ * snapshot body, which is what makes the answer available on a fresh clone.
56
+ */
57
+ export declare function contentHash(content: string): string;
58
+ /**
59
+ * The hash we recorded when we last wrote `relPath`, or undefined if we have no
60
+ * record of ever writing it.
61
+ *
62
+ * This is the COMMITTED half of `.gen-state`. The snapshot bodies stay ignored —
63
+ * they are a second full copy of all generated output — but a hash per path is
64
+ * small enough to commit and review, and it is sufficient to distinguish "nobody
65
+ * touched this" from "somebody edited this", which is the only distinction the
66
+ * overwrite and delete decisions actually need.
67
+ */
68
+ export declare function readGeneratedHash(genStateDir: string, relPath: string): string | undefined;
69
+ /**
70
+ * True when the file at `relPath` is byte-for-byte what we recorded writing.
71
+ *
72
+ * FAILS CLOSED: with no recorded hash we cannot prove anything, so the answer is
73
+ * false. Both the write path and the orphan-delete path ask this one question of
74
+ * this one piece of evidence — before this existed they answered the same
75
+ * uncertainty in opposite directions inside a single feature, refusing to DELETE
76
+ * a hand-edited file while silently OVERWRITING one.
77
+ */
78
+ export declare function isPristineGenerated(genStateDir: string, relPath: string, current: string): boolean;
79
+ /**
80
+ * The snapshot of what we last wrote to `relPath`, or undefined when there is no
81
+ * trustworthy one.
82
+ *
83
+ * HASH-CHECKED on purpose. A caller comparing this against the file on disk is
84
+ * asking "is the output still exactly what I wrote?" — and a snapshot that fails
85
+ * its own hash cannot answer that. Returning the stale text would let a
86
+ * reconciling caller conclude "untouched" and delete a file it cannot vouch for,
87
+ * so a tampered snapshot reads as absent and the caller fails closed.
88
+ */
89
+ export declare function readGeneratedSnapshot(genStateDir: string, relPath: string): string | undefined;
90
+ /**
91
+ * Drop both halves of the record for paths this run no longer generates — each
92
+ * snapshot file and its `.hashes.json` entry.
93
+ *
94
+ * BOTH halves, or the next run sees the path again in `listGeneratedPaths` and
95
+ * re-decides an orphan that has already been dealt with. A no-op for a path that was
96
+ * never generated.
97
+ *
98
+ * Batched deliberately: one manifest read and one write for the whole set. A per-path
99
+ * variant re-reads, re-sorts and rewrites the entire manifest every call, so clearing k
100
+ * orphans rewrote it k times — on a project with hundreds of generated files that makes
101
+ * bookkeeping the dominant cost of `meta gen`, for an identical result.
102
+ */
103
+ export declare function forgetGeneratedPaths(genStateDir: string, relPaths: Iterable<string>): void;
34
104
  /**
35
105
  * The codegen engine version that last wrote this `.gen-state`, or undefined if it
36
106
  * was never stamped (a pre-#232 snapshot, or a fresh project). Informational only —
@@ -45,6 +115,30 @@ export declare function saveEngineVersion(genStateDir: string, version: string):
45
115
  export declare class GitMissingError extends Error {
46
116
  constructor();
47
117
  }
118
+ /** True when this project has a hash manifest at all — as opposed to a manifest
119
+ * that simply has no entry for some path.
120
+ *
121
+ * The distinction drives the upgrade message: a project with NO manifest predates
122
+ * the manifest being committed, so its refusals are one fixable configuration
123
+ * problem rather than N independent hand edits, and it deserves one instruction
124
+ * instead of a wall of per-file warnings. */
125
+ export declare function hasHashManifest(genStateDir: string): boolean;
126
+ /**
127
+ * What `decideAndWrite` WOULD do, touching nothing. Backs `meta gen --dry-run`.
128
+ *
129
+ * Exact for every outcome the hash manifest decides, because those are pure
130
+ * comparisons — `classifyWrite` above is the single source for which one applies.
131
+ * Deliberately COARSE in one place: with a snapshot body present the result depends
132
+ * on whether `git merge-file` comes back clean or conflicted, which cannot be known
133
+ * without performing the merge — so that case reports `overwrite`, meaning "this
134
+ * file will be rewritten", which is true either way.
135
+ *
136
+ * The reason this exists as its own function rather than a flag on
137
+ * `decideAndWrite`: a preview must be incapable of writing, and the cheapest way to
138
+ * guarantee that is to give it no write in its body at all — mapping a `WriteCase`
139
+ * to a status touches no file and no manifest.
140
+ */
141
+ export declare function previewWriteStatus(path: string, content: string, optsOrStrategy?: DecideAndWriteOpts | MergeStrategy): WriteStatus;
48
142
  /**
49
143
  * The main entry point. Backward-compatible with the rc.11 signature: passing
50
144
  * a `MergeStrategy` string as the third argument continues to work; passing
@@ -1 +1 @@
1
- {"version":3,"file":"overwrite-policy.d.ts","sourceRoot":"","sources":["../src/overwrite-policy.ts"],"names":[],"mappings":"AAqCA,MAAM,MAAM,WAAW,GACnB,KAAK,GACL,WAAW,GACX,WAAW,GACX,QAAQ,GACR,UAAU,GACV,SAAS,GACT,SAAS,CAAC;AAEd;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,eAAe,CAAC;AAE1D;;;iDAGiD;AACjD,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC;AAE/C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB;;+DAE2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;qEAEiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB;sCACkC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAgCD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAazE;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAM5E;AAwCD;gDACgD;AAChD,qBAAa,eAAgB,SAAQ,KAAK;;CAQzC;AAsFD;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,cAAc,GAAE,kBAAkB,GAAG,aAAkB,GACtD,WAAW,CAgGb"}
1
+ {"version":3,"file":"overwrite-policy.d.ts","sourceRoot":"","sources":["../src/overwrite-policy.ts"],"names":[],"mappings":"AA+CA,MAAM,MAAM,WAAW,GACnB,KAAK,GACL,WAAW,GACX,WAAW,GACX,QAAQ,GACR,UAAU,GACV,SAAS,GACT,SAAS;AACX;;;;wBAIwB;GACtB,SAAS,CAAC;AAEd;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,eAAe,CAAC;AAE1D;;;iDAGiD;AACjD,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC;AAE/C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB;;+DAE2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;qEAEiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB;;4EAEwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA8CD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAEhE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,SAAS,CAEpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAGT;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,SAAS,CAEpB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,GACzB,IAAI,CAYN;AAID;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAazE;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAM5E;AAwCD;gDACgD;AAChD,qBAAa,eAAgB,SAAQ,KAAK;;CAQzC;AA+FD;;;;;;8CAM8C;AAC9C,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE5D;AA+FD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,cAAc,GAAE,kBAAkB,GAAG,aAAkB,GACtD,WAAW,CAmBb;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,cAAc,GAAE,kBAAkB,GAAG,aAAkB,GACtD,WAAW,CA8Eb"}