@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,132 @@
1
+ /**
2
+ * Plugin Types
3
+ *
4
+ * Defines the Effect-native plugin interface where plugins are Effects
5
+ * that yield the services they need from context.
6
+ */
7
+ import { Effect } from "effect";
8
+ import { PluginExecutionFailed } from "../errors.js";
9
+ import { createFileBuilder } from "./file-builder.js";
10
+ // Import service tags for yielding in definePlugin
11
+ import { IR } from "./ir.js";
12
+ import { ArtifactStore } from "./artifact-store.js";
13
+ import { PluginMeta } from "./plugin-meta.js";
14
+ import { Inflection } from "./inflection.js";
15
+ import { Emissions } from "./emissions.js";
16
+ import { Symbols } from "./symbols.js";
17
+ import { TypeHints } from "./type-hints.js";
18
+ /**
19
+ * Create a plugin factory from a simple function-based definition.
20
+ *
21
+ * Returns a curried function that accepts config and returns a ConfiguredPlugin.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const myPlugin = definePlugin({
26
+ * name: "my-plugin",
27
+ * provides: ["types:row"],
28
+ * configSchema: S.Struct({ outputDir: S.String }),
29
+ * inflection: { ... },
30
+ *
31
+ * run: (ctx, config) => {
32
+ * for (const entity of ctx.ir.entities.values()) {
33
+ * ctx.emit(`${config.outputDir}/${entity.name}.ts`, generateType(entity))
34
+ * }
35
+ * }
36
+ * })
37
+ *
38
+ * // Usage in config:
39
+ * plugins: [
40
+ * myPlugin({ outputDir: "types" }),
41
+ * ]
42
+ * ```
43
+ */
44
+ export function definePlugin(def) {
45
+ // Build the internal plugin object
46
+ const plugin = {
47
+ name: def.name,
48
+ provides: def.provides,
49
+ configSchema: def.configSchema,
50
+ inflection: def.inflection,
51
+ run: (config) => Effect.gen(function* () {
52
+ // Yield all services from context
53
+ const ir = yield* IR;
54
+ const inflection = yield* Inflection;
55
+ const emissions = yield* Emissions;
56
+ const symbols = yield* Symbols;
57
+ const typeHints = yield* TypeHints;
58
+ const artifactStore = yield* ArtifactStore;
59
+ const meta = yield* PluginMeta;
60
+ // Build the simple context object
61
+ const ctx = {
62
+ ir,
63
+ inflection,
64
+ symbols,
65
+ typeHints,
66
+ pluginName: meta.name,
67
+ pluginInflection: def.inflection,
68
+ emit: (path, content) => {
69
+ emissions.emit(path, content, meta.name);
70
+ },
71
+ emitAst: (path, ast, header) => {
72
+ emissions.emitAst(path, ast, meta.name, header);
73
+ },
74
+ appendEmit: (path, content) => {
75
+ emissions.appendEmit(path, content, meta.name);
76
+ },
77
+ getArtifact: (capability) => artifactStore.get(capability),
78
+ setArtifact: (capability, data) => {
79
+ artifactStore.set(capability, meta.name, data);
80
+ },
81
+ file: (path) => createFileBuilder(path, meta.name, emissions, symbols),
82
+ log: {
83
+ // Use Effect logging with plugin name annotation
84
+ // These run synchronously since logging is side-effect only
85
+ debug: (message) => {
86
+ Effect.runSync(Effect.logDebug(message).pipe(Effect.annotateLogs("plugin", meta.name)));
87
+ },
88
+ info: (message) => {
89
+ Effect.runSync(Effect.logInfo(message).pipe(Effect.annotateLogs("plugin", meta.name)));
90
+ },
91
+ warn: (message) => {
92
+ Effect.runSync(Effect.logWarning(message).pipe(Effect.annotateLogs("plugin", meta.name)));
93
+ },
94
+ },
95
+ };
96
+ // Call the user's run function, handling sync/async errors
97
+ const result = yield* Effect.try({
98
+ try: () => def.run(ctx, config),
99
+ catch: (error) => new PluginExecutionFailed({
100
+ message: `Plugin ${def.name} failed`,
101
+ plugin: def.name,
102
+ cause: error instanceof Error ? error : new Error(String(error)),
103
+ }),
104
+ });
105
+ // If it returned a promise, await it
106
+ if (result instanceof Promise) {
107
+ yield* Effect.tryPromise({
108
+ try: () => result,
109
+ catch: (error) => new PluginExecutionFailed({
110
+ message: `Plugin ${def.name} failed`,
111
+ plugin: def.name,
112
+ cause: error instanceof Error ? error : new Error(String(error)),
113
+ }),
114
+ });
115
+ }
116
+ }),
117
+ };
118
+ // Add optional properties only if defined (exactOptionalPropertyTypes)
119
+ let finalPlugin = plugin;
120
+ if (def.requires !== undefined) {
121
+ finalPlugin = { ...finalPlugin, requires: def.requires };
122
+ }
123
+ if (def.inflectionDefaults !== undefined) {
124
+ finalPlugin = { ...finalPlugin, inflectionDefaults: def.inflectionDefaults };
125
+ }
126
+ // Return the curried factory function with plugin attached for inspection
127
+ return Object.assign((config) => ({
128
+ plugin: finalPlugin,
129
+ config,
130
+ }), { plugin: finalPlugin });
131
+ }
132
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/services/plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Smart Tags Parser
3
+ *
4
+ * Parses JSON smart tags from PostgreSQL COMMENT ON statements.
5
+ * Format: {"sourcerer": {...}} at the start of the comment,
6
+ * with optional description text after a newline.
7
+ */
8
+ import { Effect } from "effect";
9
+ import { SmartTags } from "../ir/smart-tags.js";
10
+ import { TagParseError } from "../errors.js";
11
+ /**
12
+ * Result of parsing a comment
13
+ */
14
+ export interface ParsedComment {
15
+ readonly tags: SmartTags;
16
+ readonly description: string | undefined;
17
+ }
18
+ /**
19
+ * Context for error reporting
20
+ */
21
+ export interface TagContext {
22
+ readonly objectType: "table" | "column" | "constraint" | "type";
23
+ readonly objectName: string;
24
+ }
25
+ /**
26
+ * Parse smart tags from a PostgreSQL comment.
27
+ *
28
+ * Format:
29
+ * - `{"sourcerer": {...}}` - JSON only
30
+ * - `{"sourcerer": {...}}\ndescription` - JSON with description after newline
31
+ * - `plain text` - no JSON, text is description
32
+ * - `null/undefined/""` - no tags, no description
33
+ *
34
+ * Errors on malformed JSON or invalid sourcerer schema.
35
+ */
36
+ export declare function parseSmartTags(comment: string | null | undefined, context: TagContext): Effect.Effect<ParsedComment, TagParseError>;
37
+ //# sourceMappingURL=smart-tags-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smart-tags-parser.d.ts","sourceRoot":"","sources":["../../src/services/smart-tags-parser.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,MAAM,EAAqB,MAAM,QAAQ,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE5C;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;CACzC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,UAAU,EAAE,OAAO,GAAG,QAAQ,GAAG,YAAY,GAAG,MAAM,CAAA;IAC/D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,OAAO,EAAE,UAAU,GAClB,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,aAAa,CAAC,CAuE7C"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Smart Tags Parser
3
+ *
4
+ * Parses JSON smart tags from PostgreSQL COMMENT ON statements.
5
+ * Format: {"sourcerer": {...}} at the start of the comment,
6
+ * with optional description text after a newline.
7
+ */
8
+ import { Effect, Schema as S, pipe } from "effect";
9
+ import { SmartTags } from "../ir/smart-tags.js";
10
+ import { TagParseError } from "../errors.js";
11
+ /**
12
+ * Schema for the raw JSON wrapper containing sourcerer key
13
+ */
14
+ const CommentJson = S.Struct({
15
+ sourcerer: S.optional(S.Unknown),
16
+ }).pipe(S.extend(S.Record({ key: S.String, value: S.Unknown })));
17
+ /**
18
+ * Parse smart tags from a PostgreSQL comment.
19
+ *
20
+ * Format:
21
+ * - `{"sourcerer": {...}}` - JSON only
22
+ * - `{"sourcerer": {...}}\ndescription` - JSON with description after newline
23
+ * - `plain text` - no JSON, text is description
24
+ * - `null/undefined/""` - no tags, no description
25
+ *
26
+ * Errors on malformed JSON or invalid sourcerer schema.
27
+ */
28
+ export function parseSmartTags(comment, context) {
29
+ // Handle null/undefined/empty
30
+ if (!comment || comment.trim() === "") {
31
+ return Effect.succeed({ tags: {}, description: undefined });
32
+ }
33
+ const trimmed = comment.trim();
34
+ // If doesn't start with {, it's plain text description
35
+ if (!trimmed.startsWith("{")) {
36
+ return Effect.succeed({ tags: {}, description: trimmed });
37
+ }
38
+ // Find the end of JSON and start of description
39
+ // JSON ends at first newline, description is everything after
40
+ const newlineIndex = trimmed.indexOf("\n");
41
+ const jsonPart = newlineIndex === -1 ? trimmed : trimmed.slice(0, newlineIndex);
42
+ const descriptionPart = newlineIndex === -1 ? undefined : trimmed.slice(newlineIndex + 1).trim() || undefined;
43
+ return pipe(
44
+ // Parse JSON
45
+ Effect.try({
46
+ try: () => JSON.parse(jsonPart),
47
+ catch: (error) => new TagParseError({
48
+ message: `Invalid JSON in comment: ${error instanceof Error ? error.message : String(error)}`,
49
+ objectType: context.objectType,
50
+ objectName: context.objectName,
51
+ comment,
52
+ cause: error,
53
+ }),
54
+ }),
55
+ // Validate wrapper structure and extract sourcerer
56
+ Effect.flatMap((parsed) => S.decodeUnknown(CommentJson)(parsed).pipe(Effect.mapError((error) => new TagParseError({
57
+ message: `Invalid comment structure: ${error.message}`,
58
+ objectType: context.objectType,
59
+ objectName: context.objectName,
60
+ comment,
61
+ cause: error,
62
+ })))),
63
+ // Check for sourcerer key
64
+ Effect.flatMap((wrapper) => {
65
+ if (wrapper.sourcerer === undefined) {
66
+ // Valid JSON but no sourcerer key - other tool's namespace
67
+ return Effect.succeed({ tags: {}, description: descriptionPart });
68
+ }
69
+ // Validate sourcerer against SmartTags schema
70
+ return S.decodeUnknown(SmartTags)(wrapper.sourcerer).pipe(Effect.map((tags) => ({ tags, description: descriptionPart })), Effect.mapError((error) => new TagParseError({
71
+ message: `Invalid sourcerer tags: ${error.message}`,
72
+ objectType: context.objectType,
73
+ objectName: context.objectName,
74
+ comment,
75
+ cause: error,
76
+ })));
77
+ }));
78
+ }
79
+ //# sourceMappingURL=smart-tags-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smart-tags-parser.js","sourceRoot":"","sources":["../../src/services/smart-tags-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Symbol Registry Service
3
+ *
4
+ * Tracks emitted symbols for cross-file import resolution.
5
+ */
6
+ import { Context, Layer } from "effect";
7
+ import type { CapabilityKey } from "../ir/index.js";
8
+ /**
9
+ * Reference to a symbol
10
+ */
11
+ export interface SymbolRef {
12
+ readonly capability: CapabilityKey;
13
+ readonly entity: string;
14
+ readonly shape?: string;
15
+ }
16
+ /**
17
+ * A registered symbol
18
+ */
19
+ export interface Symbol {
20
+ readonly name: string;
21
+ readonly file: string;
22
+ readonly capability: CapabilityKey;
23
+ readonly entity: string;
24
+ readonly shape?: string;
25
+ readonly isType: boolean;
26
+ readonly isDefault: boolean;
27
+ }
28
+ /**
29
+ * Import statement to add to a file
30
+ */
31
+ export interface ImportStatement {
32
+ readonly from: string;
33
+ readonly named: readonly string[];
34
+ readonly types: readonly string[];
35
+ readonly default?: string;
36
+ }
37
+ /**
38
+ * Symbol collision info
39
+ */
40
+ export interface SymbolCollision {
41
+ readonly symbol: string;
42
+ readonly file: string;
43
+ readonly plugins: readonly string[];
44
+ }
45
+ /**
46
+ * Symbol registry interface
47
+ */
48
+ export interface SymbolRegistry {
49
+ /**
50
+ * Register a symbol (called by plugins during emit)
51
+ */
52
+ readonly register: (symbol: Symbol, plugin: string) => void;
53
+ /**
54
+ * Resolve a reference to a symbol
55
+ */
56
+ readonly resolve: (ref: SymbolRef) => Symbol | undefined;
57
+ /**
58
+ * Generate import statement from one file to another
59
+ */
60
+ readonly importFor: (symbol: Symbol, fromFile: string) => ImportStatement;
61
+ /**
62
+ * Check for conflicts (same name in same file from different plugins)
63
+ */
64
+ readonly validate: () => readonly SymbolCollision[];
65
+ /**
66
+ * Get all registered symbols
67
+ */
68
+ readonly getAll: () => readonly Symbol[];
69
+ }
70
+ declare const Symbols_base: Context.TagClass<Symbols, "Symbols", SymbolRegistry>;
71
+ /**
72
+ * SymbolRegistry service tag
73
+ */
74
+ export declare class Symbols extends Symbols_base {
75
+ }
76
+ /**
77
+ * Create a new symbol registry
78
+ */
79
+ export declare function createSymbolRegistry(): SymbolRegistry;
80
+ /**
81
+ * Live layer - creates fresh symbol registry per use
82
+ */
83
+ export declare const SymbolsLive: Layer.Layer<Symbols, never, never>;
84
+ export {};
85
+ //# sourceMappingURL=symbols.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbols.d.ts","sourceRoot":"","sources":["../../src/services/symbols.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAgB,OAAO,EAAE,KAAK,EAAgC,MAAM,QAAQ,CAAA;AACnF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAA;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAA;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAE3D;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,MAAM,GAAG,SAAS,CAAA;IAExD;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,eAAe,CAAA;IAEzE;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,SAAS,eAAe,EAAE,CAAA;IAEnD;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,SAAS,MAAM,EAAE,CAAA;CACzC;;AAED;;GAEG;AACH,qBAAa,OAAQ,SAAQ,YAG1B;CAAG;AAEN;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CA4GrD;AAmDD;;GAEG;AACH,eAAO,MAAM,WAAW,oCAAoD,CAAA"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Symbol Registry Service
3
+ *
4
+ * Tracks emitted symbols for cross-file import resolution.
5
+ */
6
+ import { Array as Arr, Context, Layer, MutableHashMap, Option, pipe } from "effect";
7
+ /**
8
+ * SymbolRegistry service tag
9
+ */
10
+ export class Symbols extends Context.Tag("Symbols")() {
11
+ }
12
+ /**
13
+ * Create a new symbol registry
14
+ */
15
+ export function createSymbolRegistry() {
16
+ const symbols = MutableHashMap.empty();
17
+ // Key for deduplication: capability:entity:shape
18
+ const makeKey = (ref) => `${ref.capability}:${ref.entity}:${ref.shape ?? ""}`;
19
+ return {
20
+ register: (symbol, plugin) => {
21
+ const key = makeKey(symbol);
22
+ pipe(MutableHashMap.get(symbols, key), Option.match({
23
+ onNone: () => MutableHashMap.set(symbols, key, [{ symbol, plugin }]),
24
+ onSome: (existing) => {
25
+ existing.push({ symbol, plugin });
26
+ MutableHashMap.set(symbols, key, existing);
27
+ }
28
+ }));
29
+ },
30
+ resolve: (ref) => {
31
+ const key = makeKey(ref);
32
+ return pipe(MutableHashMap.get(symbols, key), Option.flatMap((entries) => Option.fromNullable(entries[0])), Option.map((entry) => entry.symbol), Option.getOrUndefined);
33
+ },
34
+ importFor: (symbol, fromFile) => {
35
+ // TODO: implement relative path calculation
36
+ const relativePath = calculateRelativePath(fromFile, symbol.file);
37
+ if (symbol.isDefault) {
38
+ return {
39
+ from: relativePath,
40
+ named: [],
41
+ types: [],
42
+ default: symbol.name,
43
+ };
44
+ }
45
+ if (symbol.isType) {
46
+ return {
47
+ from: relativePath,
48
+ named: [],
49
+ types: [symbol.name],
50
+ };
51
+ }
52
+ return {
53
+ from: relativePath,
54
+ named: [symbol.name],
55
+ types: [],
56
+ };
57
+ },
58
+ validate: () => {
59
+ // Flatten all entries, group by file+name+isType, find collisions
60
+ // A type and a value with the same name are allowed (different namespaces)
61
+ const allEntries = pipe(MutableHashMap.values(symbols), Arr.fromIterable, Arr.flatten);
62
+ // Group by file:name:isType (type vs value namespace)
63
+ const byFileNameAndKind = pipe(allEntries, Arr.reduce(new Map(), (map, entry) => {
64
+ const key = `${entry.symbol.file}:${entry.symbol.name}:${entry.symbol.isType}`;
65
+ const existing = map.get(key) ?? [];
66
+ existing.push(entry);
67
+ map.set(key, existing);
68
+ return map;
69
+ }));
70
+ // Find entries with multiple plugins in same namespace
71
+ return pipe([...byFileNameAndKind.entries()], Arr.filterMap(([key, entries]) => {
72
+ if (entries.length <= 1)
73
+ return Option.none();
74
+ const [file, symbol] = key.split(":");
75
+ const plugins = [...new Set(entries.map((e) => e.plugin))];
76
+ return plugins.length > 1
77
+ ? Option.some({ symbol, file, plugins })
78
+ : Option.none();
79
+ }));
80
+ },
81
+ getAll: () => pipe(MutableHashMap.values(symbols), Arr.fromIterable, Arr.flatMap((entries) => entries.map((e) => e.symbol))),
82
+ };
83
+ }
84
+ /**
85
+ * Calculate relative import path from one file to another.
86
+ *
87
+ * Both paths are relative to the output directory root.
88
+ * Returns a path with .js extension for ESM compatibility.
89
+ *
90
+ * @example
91
+ * calculateRelativePath("types/User.ts", "schemas/User.ts")
92
+ * // => "../schemas/User.js"
93
+ *
94
+ * calculateRelativePath("types/User.ts", "types/Post.ts")
95
+ * // => "./Post.js"
96
+ */
97
+ function calculateRelativePath(fromFile, toFile) {
98
+ // Normalize paths - remove leading ./ if present
99
+ const normalizedFrom = fromFile.replace(/^\.\//, "");
100
+ const normalizedTo = toFile.replace(/^\.\//, "");
101
+ // Split into directory parts and filename
102
+ const fromParts = normalizedFrom.split("/");
103
+ const toParts = normalizedTo.split("/");
104
+ // Get the filename from the target (without .ts, add .js)
105
+ const toFilename = toParts.pop() ?? "";
106
+ const toFilenameJs = toFilename.replace(/\.ts$/, ".js");
107
+ // Get the directory of the source file (remove filename)
108
+ fromParts.pop();
109
+ // Find common prefix length
110
+ let commonLength = 0;
111
+ const minLength = Math.min(fromParts.length, toParts.length);
112
+ while (commonLength < minLength && fromParts[commonLength] === toParts[commonLength]) {
113
+ commonLength++;
114
+ }
115
+ // Calculate how many directories to go up from fromFile
116
+ const upCount = fromParts.length - commonLength;
117
+ // Build the relative path
118
+ const upPath = upCount > 0 ? "../".repeat(upCount) : "./";
119
+ // Add remaining directories from toFile
120
+ const remainingDirs = toParts.slice(commonLength);
121
+ const dirPath = remainingDirs.length > 0 ? remainingDirs.join("/") + "/" : "";
122
+ return upPath + dirPath + toFilenameJs;
123
+ }
124
+ /**
125
+ * Live layer - creates fresh symbol registry per use
126
+ */
127
+ export const SymbolsLive = Layer.sync(Symbols, () => createSymbolRegistry());
128
+ //# sourceMappingURL=symbols.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbols.js","sourceRoot":"","sources":["../../src/services/symbols.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Type Hint Registry Service
3
+ *
4
+ * Provides user-configured type overrides that plugins can query.
5
+ *
6
+ * Precedence rules (higher score wins):
7
+ * - schema + table + column: 9 points
8
+ * - table + column: 7 points
9
+ * - schema + column: 6 points
10
+ * - schema + table: 5 points
11
+ * - column: 4 points
12
+ * - table: 3 points
13
+ * - schema: 2 points
14
+ * - pgType: 1 point
15
+ *
16
+ * For same specificity, later rules in config override earlier ones.
17
+ */
18
+ import { Context, Layer, Option } from "effect";
19
+ import type { TypeHint } from "../config.js";
20
+ /**
21
+ * Field matching criteria for type hints
22
+ */
23
+ export interface TypeHintFieldMatch {
24
+ readonly schema: string;
25
+ readonly table: string;
26
+ readonly column: string;
27
+ readonly pgType: string;
28
+ }
29
+ /**
30
+ * Type hint registry interface
31
+ */
32
+ export interface TypeHintRegistry {
33
+ /**
34
+ * Get all hints for a specific field (merged from all matching rules)
35
+ * More specific matches take precedence over general ones
36
+ */
37
+ readonly getHints: (field: TypeHintFieldMatch) => Record<string, unknown>;
38
+ /**
39
+ * Get a specific hint value for a field
40
+ */
41
+ readonly getHint: <T>(field: TypeHintFieldMatch, key: string) => Option.Option<T>;
42
+ }
43
+ declare const TypeHints_base: Context.TagClass<TypeHints, "TypeHints", TypeHintRegistry>;
44
+ /**
45
+ * TypeHintRegistry service tag
46
+ */
47
+ export declare class TypeHints extends TypeHints_base {
48
+ }
49
+ /**
50
+ * Create a type hint registry from configuration
51
+ */
52
+ export declare function createTypeHintRegistry(hints: readonly TypeHint[]): TypeHintRegistry;
53
+ /**
54
+ * Empty registry for testing
55
+ */
56
+ export declare const emptyTypeHintRegistry: TypeHintRegistry;
57
+ /**
58
+ * Create a live layer from config
59
+ */
60
+ export declare function TypeHintsLive(hints: readonly TypeHint[]): Layer.Layer<TypeHints, never, never>;
61
+ export {};
62
+ //# sourceMappingURL=type-hints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-hints.d.ts","sourceRoot":"","sources":["../../src/services/type-hints.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAA6B,MAAM,QAAQ,CAAA;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,cAAc,CAAA;AAE3D;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAEzE;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;CAClF;;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,cAG5B;CAAG;AA6DN;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,gBAAgB,CAqCnF;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,gBAGnC,CAAA;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,wCAEvD"}