@danielfgray/pg-sourcerer 0.1.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.
Files changed (145) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +104 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/config.d.ts +133 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +47 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/errors.d.ts +129 -0
  10. package/dist/errors.d.ts.map +1 -0
  11. package/dist/errors.js +41 -0
  12. package/dist/errors.js.map +1 -0
  13. package/dist/generate.d.ts +75 -0
  14. package/dist/generate.d.ts.map +1 -0
  15. package/dist/generate.js +183 -0
  16. package/dist/generate.js.map +1 -0
  17. package/dist/index.d.ts +35 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +62 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/init.d.ts +4 -0
  22. package/dist/init.d.ts.map +1 -0
  23. package/dist/init.js +229 -0
  24. package/dist/init.js.map +1 -0
  25. package/dist/ir/index.d.ts +7 -0
  26. package/dist/ir/index.d.ts.map +1 -0
  27. package/dist/ir/index.js +7 -0
  28. package/dist/ir/index.js.map +1 -0
  29. package/dist/ir/relation-graph.d.ts +113 -0
  30. package/dist/ir/relation-graph.d.ts.map +1 -0
  31. package/dist/ir/relation-graph.js +232 -0
  32. package/dist/ir/relation-graph.js.map +1 -0
  33. package/dist/ir/semantic-ir.d.ts +448 -0
  34. package/dist/ir/semantic-ir.d.ts.map +1 -0
  35. package/dist/ir/semantic-ir.js +138 -0
  36. package/dist/ir/semantic-ir.js.map +1 -0
  37. package/dist/ir/smart-tags.d.ts +24 -0
  38. package/dist/ir/smart-tags.d.ts.map +1 -0
  39. package/dist/ir/smart-tags.js +30 -0
  40. package/dist/ir/smart-tags.js.map +1 -0
  41. package/dist/lib/conjure.d.ts +431 -0
  42. package/dist/lib/conjure.d.ts.map +1 -0
  43. package/dist/lib/conjure.js +697 -0
  44. package/dist/lib/conjure.js.map +1 -0
  45. package/dist/lib/field-utils.d.ts +61 -0
  46. package/dist/lib/field-utils.d.ts.map +1 -0
  47. package/dist/lib/field-utils.js +132 -0
  48. package/dist/lib/field-utils.js.map +1 -0
  49. package/dist/lib/hex.d.ts +117 -0
  50. package/dist/lib/hex.d.ts.map +1 -0
  51. package/dist/lib/hex.js +185 -0
  52. package/dist/lib/hex.js.map +1 -0
  53. package/dist/plugins/arktype.d.ts +11 -0
  54. package/dist/plugins/arktype.d.ts.map +1 -0
  55. package/dist/plugins/arktype.js +207 -0
  56. package/dist/plugins/arktype.js.map +1 -0
  57. package/dist/plugins/effect-model.d.ts +10 -0
  58. package/dist/plugins/effect-model.d.ts.map +1 -0
  59. package/dist/plugins/effect-model.js +261 -0
  60. package/dist/plugins/effect-model.js.map +1 -0
  61. package/dist/plugins/kysely-queries.d.ts +7 -0
  62. package/dist/plugins/kysely-queries.d.ts.map +1 -0
  63. package/dist/plugins/kysely-queries.js +380 -0
  64. package/dist/plugins/kysely-queries.js.map +1 -0
  65. package/dist/plugins/sql-queries.d.ts +6 -0
  66. package/dist/plugins/sql-queries.d.ts.map +1 -0
  67. package/dist/plugins/sql-queries.js +249 -0
  68. package/dist/plugins/sql-queries.js.map +1 -0
  69. package/dist/plugins/types.d.ts +18 -0
  70. package/dist/plugins/types.d.ts.map +1 -0
  71. package/dist/plugins/types.js +263 -0
  72. package/dist/plugins/types.js.map +1 -0
  73. package/dist/plugins/zod.d.ts +11 -0
  74. package/dist/plugins/zod.d.ts.map +1 -0
  75. package/dist/plugins/zod.js +180 -0
  76. package/dist/plugins/zod.js.map +1 -0
  77. package/dist/services/artifact-store.d.ts +55 -0
  78. package/dist/services/artifact-store.d.ts.map +1 -0
  79. package/dist/services/artifact-store.js +51 -0
  80. package/dist/services/artifact-store.js.map +1 -0
  81. package/dist/services/config-loader.d.ts +45 -0
  82. package/dist/services/config-loader.d.ts.map +1 -0
  83. package/dist/services/config-loader.js +113 -0
  84. package/dist/services/config-loader.js.map +1 -0
  85. package/dist/services/emissions.d.ts +89 -0
  86. package/dist/services/emissions.d.ts.map +1 -0
  87. package/dist/services/emissions.js +194 -0
  88. package/dist/services/emissions.js.map +1 -0
  89. package/dist/services/file-builder.d.ts +81 -0
  90. package/dist/services/file-builder.d.ts.map +1 -0
  91. package/dist/services/file-builder.js +112 -0
  92. package/dist/services/file-builder.js.map +1 -0
  93. package/dist/services/file-writer.d.ts +57 -0
  94. package/dist/services/file-writer.d.ts.map +1 -0
  95. package/dist/services/file-writer.js +76 -0
  96. package/dist/services/file-writer.js.map +1 -0
  97. package/dist/services/inflection.d.ts +227 -0
  98. package/dist/services/inflection.d.ts.map +1 -0
  99. package/dist/services/inflection.js +350 -0
  100. package/dist/services/inflection.js.map +1 -0
  101. package/dist/services/introspection.d.ts +46 -0
  102. package/dist/services/introspection.d.ts.map +1 -0
  103. package/dist/services/introspection.js +99 -0
  104. package/dist/services/introspection.js.map +1 -0
  105. package/dist/services/ir-builder.d.ts +46 -0
  106. package/dist/services/ir-builder.d.ts.map +1 -0
  107. package/dist/services/ir-builder.js +923 -0
  108. package/dist/services/ir-builder.js.map +1 -0
  109. package/dist/services/ir.d.ts +28 -0
  110. package/dist/services/ir.d.ts.map +1 -0
  111. package/dist/services/ir.js +25 -0
  112. package/dist/services/ir.js.map +1 -0
  113. package/dist/services/pg-types.d.ts +197 -0
  114. package/dist/services/pg-types.d.ts.map +1 -0
  115. package/dist/services/pg-types.js +274 -0
  116. package/dist/services/pg-types.js.map +1 -0
  117. package/dist/services/plugin-meta.d.ts +33 -0
  118. package/dist/services/plugin-meta.d.ts.map +1 -0
  119. package/dist/services/plugin-meta.js +24 -0
  120. package/dist/services/plugin-meta.js.map +1 -0
  121. package/dist/services/plugin-runner.d.ts +52 -0
  122. package/dist/services/plugin-runner.d.ts.map +1 -0
  123. package/dist/services/plugin-runner.js +182 -0
  124. package/dist/services/plugin-runner.js.map +1 -0
  125. package/dist/services/plugin.d.ts +286 -0
  126. package/dist/services/plugin.d.ts.map +1 -0
  127. package/dist/services/plugin.js +132 -0
  128. package/dist/services/plugin.js.map +1 -0
  129. package/dist/services/smart-tags-parser.d.ts +37 -0
  130. package/dist/services/smart-tags-parser.d.ts.map +1 -0
  131. package/dist/services/smart-tags-parser.js +79 -0
  132. package/dist/services/smart-tags-parser.js.map +1 -0
  133. package/dist/services/symbols.d.ts +85 -0
  134. package/dist/services/symbols.d.ts.map +1 -0
  135. package/dist/services/symbols.js +128 -0
  136. package/dist/services/symbols.js.map +1 -0
  137. package/dist/services/type-hints.d.ts +62 -0
  138. package/dist/services/type-hints.d.ts.map +1 -0
  139. package/dist/services/type-hints.js +117 -0
  140. package/dist/services/type-hints.js.map +1 -0
  141. package/dist/testing.d.ts +77 -0
  142. package/dist/testing.d.ts.map +1 -0
  143. package/dist/testing.js +84 -0
  144. package/dist/testing.js.map +1 -0
  145. package/package.json +74 -0
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Emission Buffer Service
3
+ *
4
+ * Buffers code emissions from plugins before writing to disk.
5
+ * Supports both string content and AST nodes (serialized by the plugin runner).
6
+ * AST emissions to the same file are merged automatically.
7
+ */
8
+ import { Array as Arr, Context, Effect, Layer, MutableHashMap, MutableHashSet, Option, pipe } from "effect";
9
+ import { EmitConflict } from "../errors.js";
10
+ /**
11
+ * EmissionBuffer service tag
12
+ */
13
+ export class Emissions extends Context.Tag("Emissions")() {
14
+ }
15
+ // =============================================================================
16
+ // Import Resolution Helpers
17
+ // =============================================================================
18
+ import recast from "recast";
19
+ const b = recast.types.builders;
20
+ /**
21
+ * Resolve imports and prepend import statements to AST
22
+ */
23
+ function prependImports(ast, imports, forFile, symbols) {
24
+ // Group imports by source path for merging
25
+ const bySource = pipe(imports, Arr.reduce(new Map(), (map, ref) => {
26
+ const resolved = resolveImportRef(ref, forFile, symbols);
27
+ if (!resolved)
28
+ return map;
29
+ const { source, named, types, defaultImport } = resolved;
30
+ const existing = map.get(source) ?? { named: new Set(), types: new Set() };
31
+ named.forEach((n) => existing.named.add(n));
32
+ types.forEach((t) => existing.types.add(t));
33
+ if (defaultImport)
34
+ existing.default = defaultImport;
35
+ map.set(source, existing);
36
+ return map;
37
+ }));
38
+ const statements = pipe([...bySource.entries()], Arr.flatMap(([source, { named, types, default: defaultImport }]) => {
39
+ const result = [];
40
+ // Value imports (default + named)
41
+ const valueSpecifiers = [
42
+ ...(defaultImport ? [b.importDefaultSpecifier(b.identifier(defaultImport))] : []),
43
+ ...pipe([...named], Arr.map((name) => b.importSpecifier(b.identifier(name), b.identifier(name)))),
44
+ ];
45
+ if (valueSpecifiers.length > 0) {
46
+ result.push(b.importDeclaration(valueSpecifiers, b.stringLiteral(source)));
47
+ }
48
+ // Type imports as a separate type-only import declaration
49
+ if (types.size > 0) {
50
+ const typeSpecifiers = pipe([...types], Arr.map((name) => b.importSpecifier(b.identifier(name), b.identifier(name))));
51
+ const typeImport = b.importDeclaration(typeSpecifiers, b.stringLiteral(source));
52
+ typeImport.importKind = "type";
53
+ result.push(typeImport);
54
+ }
55
+ return result;
56
+ }));
57
+ // Prepend imports to program body
58
+ return b.program([...statements, ...ast.body]);
59
+ }
60
+ /** Normalize path for comparison (remove leading ./) */
61
+ const normalizePath = (path) => path.replace(/^\.\//, "");
62
+ /** Resolve an ImportRef to source/named/types/default */
63
+ function resolveImportRef(ref, forFile, symbols) {
64
+ switch (ref.kind) {
65
+ case "symbol": {
66
+ const symbol = symbols.resolve(ref.ref);
67
+ if (!symbol)
68
+ return undefined;
69
+ // Skip import if symbol is in the same file (already declared locally)
70
+ if (normalizePath(symbol.file) === normalizePath(forFile))
71
+ return undefined;
72
+ const importStmt = symbols.importFor(symbol, forFile);
73
+ const base = {
74
+ source: importStmt.from,
75
+ named: [...importStmt.named],
76
+ types: [...importStmt.types],
77
+ };
78
+ return importStmt.default !== undefined
79
+ ? { ...base, defaultImport: importStmt.default }
80
+ : base;
81
+ }
82
+ case "package":
83
+ case "relative": {
84
+ const base = {
85
+ source: ref.from,
86
+ named: ref.names ? [...ref.names] : [],
87
+ types: ref.types ? [...ref.types] : [],
88
+ };
89
+ return ref.default !== undefined
90
+ ? { ...base, defaultImport: ref.default }
91
+ : base;
92
+ }
93
+ }
94
+ }
95
+ // =============================================================================
96
+ // AST Emission Merging (Pure Functions)
97
+ // =============================================================================
98
+ /** Merge two import arrays */
99
+ const mergeImports = (a, b) => [...(a ?? []), ...(b ?? [])];
100
+ /** Merge two plugin attribution strings */
101
+ const mergePluginAttribution = (a, b) => `${a}, ${b}`;
102
+ /** Create an AST entry, only including optional fields when defined */
103
+ const makeAstEntry = (path, ast, plugin, header, imports) => pipe({ path, ast, plugin }, (entry) => header !== undefined ? { ...entry, header } : entry, (entry) => imports && imports.length > 0 ? { ...entry, imports } : entry);
104
+ /** Merge a new emission into an existing one (keeps first header) */
105
+ const mergeAstEntries = (existing, ast, plugin, _header, imports) => makeAstEntry(existing.path, b.program([...existing.ast.body, ...ast.body]), mergePluginAttribution(existing.plugin, plugin), existing.header, mergeImports(existing.imports, imports));
106
+ // =============================================================================
107
+ // Emission Buffer Implementation
108
+ // =============================================================================
109
+ /**
110
+ * Create a new emission buffer
111
+ */
112
+ export function createEmissionBuffer() {
113
+ const emissions = MutableHashMap.empty();
114
+ const astEmissions = MutableHashMap.empty();
115
+ // Track plugins per path for string emission conflict detection
116
+ const stringEmitPlugins = MutableHashMap.empty();
117
+ return {
118
+ emit: (path, content, plugin) => {
119
+ // Track plugin for conflict detection
120
+ MutableHashMap.modifyAt(stringEmitPlugins, path, Option.match({
121
+ onNone: () => Option.some(MutableHashSet.make(plugin)),
122
+ onSome: (set) => Option.some(MutableHashSet.add(set, plugin))
123
+ }));
124
+ MutableHashMap.set(emissions, path, { path, content, plugin });
125
+ },
126
+ emitAst: (path, ast, plugin, header, imports) => {
127
+ MutableHashMap.modifyAt(astEmissions, path, Option.match({
128
+ onNone: () => Option.some(makeAstEntry(path, ast, plugin, header, imports)),
129
+ onSome: (existing) => Option.some(mergeAstEntries(existing, ast, plugin, header, imports))
130
+ }));
131
+ },
132
+ appendEmit: (path, content, plugin) => {
133
+ pipe(MutableHashMap.get(emissions, path), Option.match({
134
+ onNone: () => {
135
+ MutableHashMap.modifyAt(stringEmitPlugins, path, Option.match({
136
+ onNone: () => Option.some(MutableHashSet.make(plugin)),
137
+ onSome: (set) => Option.some(MutableHashSet.add(set, plugin))
138
+ }));
139
+ MutableHashMap.set(emissions, path, { path, content, plugin });
140
+ },
141
+ onSome: (existing) => {
142
+ if (existing.plugin === plugin) {
143
+ MutableHashMap.set(emissions, path, {
144
+ path,
145
+ content: existing.content + content,
146
+ plugin,
147
+ });
148
+ }
149
+ else {
150
+ // Track conflict for validation
151
+ MutableHashMap.modifyAt(stringEmitPlugins, path, Option.match({
152
+ onNone: () => Option.some(MutableHashSet.make(plugin)),
153
+ onSome: (set) => Option.some(MutableHashSet.add(set, plugin))
154
+ }));
155
+ }
156
+ }
157
+ }));
158
+ },
159
+ getAll: () => MutableHashMap.values(emissions),
160
+ getAstEmissions: () => MutableHashMap.values(astEmissions),
161
+ serializeAst: (serialize, symbols) => {
162
+ for (const entry of MutableHashMap.values(astEmissions)) {
163
+ const finalAst = entry.imports && entry.imports.length > 0
164
+ ? prependImports(entry.ast, entry.imports, entry.path, symbols)
165
+ : entry.ast;
166
+ const code = serialize(finalAst);
167
+ const content = entry.header ? entry.header + code : code;
168
+ MutableHashMap.set(emissions, entry.path, { path: entry.path, content, plugin: entry.plugin });
169
+ }
170
+ MutableHashMap.clear(astEmissions);
171
+ },
172
+ validate: () => pipe([...stringEmitPlugins], Arr.findFirst(([_, plugins]) => MutableHashSet.size(plugins) > 1), Option.match({
173
+ onNone: () => Effect.void,
174
+ onSome: ([path, plugins]) => {
175
+ const pluginList = [...plugins].join(", ");
176
+ return Effect.fail(new EmitConflict({
177
+ message: `Multiple plugins emitted to the same file: ${path} (plugins: ${pluginList})`,
178
+ path,
179
+ plugins: [...plugins],
180
+ }));
181
+ }
182
+ })),
183
+ clear: () => {
184
+ MutableHashMap.clear(emissions);
185
+ MutableHashMap.clear(astEmissions);
186
+ MutableHashMap.clear(stringEmitPlugins);
187
+ },
188
+ };
189
+ }
190
+ /**
191
+ * Live layer - creates fresh emission buffer per use
192
+ */
193
+ export const EmissionsLive = Layer.sync(Emissions, () => createEmissionBuffer());
194
+ //# sourceMappingURL=emissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emissions.js","sourceRoot":"","sources":["../../src/services/emissions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ import type { namedTypes as n } from "ast-types";
2
+ import type { SymbolProgram } from "../lib/conjure.js";
3
+ import type { EmissionBuffer } from "./emissions.js";
4
+ import type { SymbolRegistry } from "./symbols.js";
5
+ /**
6
+ * Reference to a symbol from another file (resolved via SymbolRegistry)
7
+ */
8
+ export interface SymbolImportRef {
9
+ readonly kind: "symbol";
10
+ readonly ref: {
11
+ readonly capability: string;
12
+ readonly entity: string;
13
+ readonly shape?: string;
14
+ };
15
+ }
16
+ /**
17
+ * Import from an external package
18
+ */
19
+ export interface PackageImportRef {
20
+ readonly kind: "package";
21
+ readonly names?: readonly string[];
22
+ readonly types?: readonly string[];
23
+ readonly default?: string;
24
+ readonly from: string;
25
+ }
26
+ /**
27
+ * Import from a relative path (not tracked in SymbolRegistry)
28
+ */
29
+ export interface RelativeImportRef {
30
+ readonly kind: "relative";
31
+ readonly names?: readonly string[];
32
+ readonly types?: readonly string[];
33
+ readonly default?: string;
34
+ readonly from: string;
35
+ }
36
+ /**
37
+ * All import reference types
38
+ */
39
+ export type ImportRef = SymbolImportRef | PackageImportRef | RelativeImportRef;
40
+ /**
41
+ * Fluent builder for constructing files with imports, headers, and AST content
42
+ */
43
+ export interface FileBuilder {
44
+ /**
45
+ * Add a header comment or statements to the file
46
+ * Can be called multiple times - headers are concatenated
47
+ */
48
+ header(content: string | readonly n.Statement[]): FileBuilder;
49
+ /**
50
+ * Request an import (resolved after all plugins run)
51
+ */
52
+ import(ref: ImportRef): FileBuilder;
53
+ /**
54
+ * Add AST content to the file
55
+ * Can be called multiple times - bodies are concatenated
56
+ * Extracts symbols from SymbolProgram automatically
57
+ */
58
+ ast(program: n.Program | SymbolProgram): FileBuilder;
59
+ /**
60
+ * Add raw string content (mutually exclusive with ast())
61
+ */
62
+ content(text: string): FileBuilder;
63
+ /**
64
+ * Finalize and emit the file
65
+ * Registers symbols and queues for serialization
66
+ */
67
+ emit(): void;
68
+ }
69
+ /**
70
+ * Create a FileBuilder instance
71
+ */
72
+ export declare function createFileBuilder(path: string, plugin: string, emissions: EmissionBuffer, symbolRegistry: SymbolRegistry): FileBuilder;
73
+ /**
74
+ * Factory function type for creating FileBuilders
75
+ */
76
+ export type FileBuilderFactory = (path: string) => FileBuilder;
77
+ /**
78
+ * Create a factory that produces FileBuilders with shared context
79
+ */
80
+ export declare function createFileBuilderFactory(plugin: string, emissions: EmissionBuffer, symbolRegistry: SymbolRegistry): FileBuilderFactory;
81
+ //# sourceMappingURL=file-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-builder.d.ts","sourceRoot":"","sources":["../../src/services/file-builder.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,IAAI,CAAC,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,KAAK,EAAc,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,KAAK,EAAE,cAAc,EAAU,MAAM,cAAc,CAAA;AAM1D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,QAAQ,CAAC,GAAG,EAAE;QACZ,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;QAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;QACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KACxB,CAAA;CACF;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,eAAe,GAAG,gBAAgB,GAAG,iBAAiB,CAAA;AAM9E;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,SAAS,EAAE,GAAG,WAAW,CAAA;IAE7D;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,SAAS,GAAG,WAAW,CAAA;IAEnC;;;;OAIG;IACH,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,GAAG,aAAa,GAAG,WAAW,CAAA;IAEpD;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAA;IAElC;;;OAGG;IACH,IAAI,IAAI,IAAI,CAAA;CACb;AA0BD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,cAAc,EACzB,cAAc,EAAE,cAAc,GAC7B,WAAW,CA2Gb;AAMD;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,CAAA;AAE9D;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,cAAc,EACzB,cAAc,EAAE,cAAc,GAC7B,kBAAkB,CAGpB"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * FileBuilder - Fluent API for structured file emission
3
+ *
4
+ * Provides a builder pattern for constructing files with:
5
+ * - Header comments
6
+ * - Import declarations (resolved after all plugins run)
7
+ * - AST program body with symbol metadata extraction
8
+ */
9
+ import recast from "recast";
10
+ // =============================================================================
11
+ // Type Guards
12
+ // =============================================================================
13
+ function isSymbolProgram(prog) {
14
+ return "_tag" in prog && prog._tag === "SymbolProgram";
15
+ }
16
+ /**
17
+ * Create a FileBuilder instance
18
+ */
19
+ export function createFileBuilder(path, plugin, emissions, symbolRegistry) {
20
+ const state = {
21
+ path,
22
+ plugin,
23
+ headers: [],
24
+ imports: [],
25
+ statements: [],
26
+ symbols: [],
27
+ rawContent: null,
28
+ };
29
+ const builder = {
30
+ header(content) {
31
+ if (typeof content === "string") {
32
+ state.headers.push(content);
33
+ }
34
+ else {
35
+ // Convert statements to string via placeholder
36
+ // For now, just store a marker - actual serialization happens in emit()
37
+ throw new Error("AST headers not yet implemented - use string headers for now");
38
+ }
39
+ return builder;
40
+ },
41
+ import(ref) {
42
+ state.imports.push(ref);
43
+ return builder;
44
+ },
45
+ ast(program) {
46
+ if (state.rawContent !== null) {
47
+ throw new Error(`Cannot mix ast() and content() for file ${state.path}`);
48
+ }
49
+ if (isSymbolProgram(program)) {
50
+ // Extract statements and symbols
51
+ state.statements.push(...program.node.body);
52
+ state.symbols.push(...program.symbols);
53
+ }
54
+ else {
55
+ // Plain n.Program - just extract statements
56
+ state.statements.push(...program.body);
57
+ }
58
+ return builder;
59
+ },
60
+ content(text) {
61
+ if (state.statements.length > 0) {
62
+ throw new Error(`Cannot mix content() and ast() for file ${state.path}`);
63
+ }
64
+ state.rawContent =
65
+ state.rawContent !== null ? state.rawContent + text : text;
66
+ return builder;
67
+ },
68
+ emit() {
69
+ // Register all symbols with file path
70
+ for (const meta of state.symbols) {
71
+ const baseSymbol = {
72
+ name: meta.name,
73
+ file: state.path,
74
+ capability: meta.capability,
75
+ entity: meta.entity,
76
+ isType: meta.isType,
77
+ isDefault: meta.isDefault ?? false,
78
+ };
79
+ const symbol = meta.shape !== undefined
80
+ ? { ...baseSymbol, shape: meta.shape }
81
+ : baseSymbol;
82
+ symbolRegistry.register(symbol, state.plugin);
83
+ }
84
+ // Build header string
85
+ const headerStr = state.headers.length > 0 ? state.headers.join("\n") + "\n" : undefined;
86
+ if (state.rawContent !== null) {
87
+ // Raw content mode
88
+ const fullContent = headerStr
89
+ ? headerStr + state.rawContent
90
+ : state.rawContent;
91
+ emissions.emit(state.path, fullContent, state.plugin);
92
+ }
93
+ else {
94
+ // AST mode - create program and emit via emitAst
95
+ // Import resolution will happen in a later pass
96
+ const b = recast.types.builders;
97
+ // Type assertion needed: recast's StatementKind is compatible with n.Statement
98
+ const program = b.program(state.statements);
99
+ // Emit AST with imports for resolution during serializeAst
100
+ emissions.emitAst(state.path, program, state.plugin, headerStr, state.imports.length > 0 ? state.imports : undefined);
101
+ }
102
+ },
103
+ };
104
+ return builder;
105
+ }
106
+ /**
107
+ * Create a factory that produces FileBuilders with shared context
108
+ */
109
+ export function createFileBuilderFactory(plugin, emissions, symbolRegistry) {
110
+ return (path) => createFileBuilder(path, plugin, emissions, symbolRegistry);
111
+ }
112
+ //# sourceMappingURL=file-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-builder.js","sourceRoot":"","sources":["../../src/services/file-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * File Writer Service
3
+ *
4
+ * Writes buffered emissions to disk using @effect/platform FileSystem.
5
+ */
6
+ import { Context, Effect, Layer } from "effect";
7
+ import { FileSystem, Path } from "@effect/platform";
8
+ import type { EmissionEntry } from "./emissions.js";
9
+ import { WriteError } from "../errors.js";
10
+ /**
11
+ * Result of a write operation
12
+ */
13
+ export interface WriteResult {
14
+ readonly path: string;
15
+ readonly written: boolean;
16
+ readonly reason?: string;
17
+ }
18
+ /**
19
+ * Options for writing files
20
+ */
21
+ export interface WriteOptions {
22
+ /** Output directory root */
23
+ readonly outputDir: string;
24
+ /** Dry run mode - don't actually write, just return what would be written */
25
+ readonly dryRun?: boolean;
26
+ /** Header to prepend to generated files */
27
+ readonly header?: string;
28
+ }
29
+ /**
30
+ * File writer interface
31
+ */
32
+ export interface FileWriter {
33
+ /**
34
+ * Write all emissions to disk
35
+ */
36
+ readonly writeAll: (emissions: readonly EmissionEntry[], options: WriteOptions) => Effect.Effect<readonly WriteResult[], WriteError, FileSystem.FileSystem | Path.Path>;
37
+ }
38
+ declare const FileWriterSvc_base: Context.TagClass<FileWriterSvc, "FileWriter", FileWriter>;
39
+ /**
40
+ * FileWriter service tag
41
+ */
42
+ export declare class FileWriterSvc extends FileWriterSvc_base {
43
+ }
44
+ /**
45
+ * Default generated file header
46
+ */
47
+ export declare const defaultHeader: (timestamp?: Date) => string;
48
+ /**
49
+ * Create a file writer
50
+ */
51
+ export declare function createFileWriter(): FileWriter;
52
+ /**
53
+ * Live layer - provides the file writer with real filesystem operations
54
+ */
55
+ export declare const FileWriterLive: Layer.Layer<FileWriterSvc, never, never>;
56
+ export {};
57
+ //# sourceMappingURL=file-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-writer.d.ts","sourceRoot":"","sources":["../../src/services/file-writer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAsB,MAAM,QAAQ,CAAA;AACnE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AAEnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,4BAA4B;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,CACjB,SAAS,EAAE,SAAS,aAAa,EAAE,EACnC,OAAO,EAAE,YAAY,KAClB,MAAM,CAAC,MAAM,CAAC,SAAS,WAAW,EAAE,EAAE,UAAU,EAAE,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA;CAC1F;;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,kBAGhC;CAAG;AAEN;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,YAAW,IAAiB,KAAG,MAM5D,CAAA;AAYD;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,UAAU,CAiE7C;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,0CAAmD,CAAA"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * File Writer Service
3
+ *
4
+ * Writes buffered emissions to disk using @effect/platform FileSystem.
5
+ */
6
+ import { Context, Effect, Layer, pipe, Array as Arr } from "effect";
7
+ import { FileSystem, Path } from "@effect/platform";
8
+ import { WriteError } from "../errors.js";
9
+ /**
10
+ * FileWriter service tag
11
+ */
12
+ export class FileWriterSvc extends Context.Tag("FileWriter")() {
13
+ }
14
+ /**
15
+ * Default generated file header
16
+ */
17
+ export const defaultHeader = (timestamp = new Date()) => `/**
18
+ * AUTO-GENERATED FILE - DO NOT EDIT
19
+ * Generated by pg-sourcerer at ${timestamp.toISOString()}
20
+ */
21
+
22
+ `;
23
+ /**
24
+ * Map a PlatformError to a WriteError
25
+ */
26
+ const toWriteError = (path) => (err) => new WriteError({
27
+ message: `File operation failed: ${path} - ${err.message}`,
28
+ path,
29
+ cause: err,
30
+ });
31
+ /**
32
+ * Create a file writer
33
+ */
34
+ export function createFileWriter() {
35
+ return {
36
+ writeAll: (emissions, options) => Effect.gen(function* () {
37
+ const fs = yield* FileSystem.FileSystem;
38
+ const pathSvc = yield* Path.Path;
39
+ const header = options.header ?? defaultHeader();
40
+ const outputDir = options.outputDir;
41
+ // Collect unique directories that need to be created
42
+ const directories = pipe(emissions, Arr.map((e) => pathSvc.dirname(pathSvc.join(outputDir, e.path))), Arr.dedupe);
43
+ // In dry-run mode, just return what would be written
44
+ if (options.dryRun) {
45
+ return pipe(emissions, Arr.map((e) => ({
46
+ path: pathSvc.join(outputDir, e.path),
47
+ written: false,
48
+ reason: "dry-run",
49
+ })));
50
+ }
51
+ // Create directories
52
+ yield* Effect.forEach(directories, (dir) => fs.makeDirectory(dir, { recursive: true }).pipe(Effect.catchAll((err) =>
53
+ // Ignore "already exists" errors
54
+ err._tag === "SystemError" && err.reason === "AlreadyExists"
55
+ ? Effect.void
56
+ : Effect.fail(toWriteError(dir)(err)))), { concurrency: 1 } // Sequential to avoid race conditions
57
+ );
58
+ // Write files
59
+ const results = yield* Effect.forEach(emissions, (entry) => {
60
+ const fullPath = pathSvc.join(outputDir, entry.path);
61
+ const contentWithHeader = header + entry.content;
62
+ return fs.writeFileString(fullPath, contentWithHeader).pipe(Effect.map(() => ({
63
+ path: fullPath,
64
+ written: true,
65
+ })), Effect.catchAll((err) => Effect.fail(toWriteError(fullPath)(err))));
66
+ }, { concurrency: 10 } // Parallel file writes
67
+ );
68
+ return results;
69
+ }),
70
+ };
71
+ }
72
+ /**
73
+ * Live layer - provides the file writer with real filesystem operations
74
+ */
75
+ export const FileWriterLive = Layer.succeed(FileWriterSvc, createFileWriter());
76
+ //# sourceMappingURL=file-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-writer.js","sourceRoot":"","sources":["../../src/services/file-writer.ts"],"names":[],"mappings":"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"}