@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.
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +104 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +133 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +47 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +129 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +41 -0
- package/dist/errors.js.map +1 -0
- package/dist/generate.d.ts +75 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +183 -0
- package/dist/generate.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +4 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +229 -0
- package/dist/init.js.map +1 -0
- package/dist/ir/index.d.ts +7 -0
- package/dist/ir/index.d.ts.map +1 -0
- package/dist/ir/index.js +7 -0
- package/dist/ir/index.js.map +1 -0
- package/dist/ir/relation-graph.d.ts +113 -0
- package/dist/ir/relation-graph.d.ts.map +1 -0
- package/dist/ir/relation-graph.js +232 -0
- package/dist/ir/relation-graph.js.map +1 -0
- package/dist/ir/semantic-ir.d.ts +448 -0
- package/dist/ir/semantic-ir.d.ts.map +1 -0
- package/dist/ir/semantic-ir.js +138 -0
- package/dist/ir/semantic-ir.js.map +1 -0
- package/dist/ir/smart-tags.d.ts +24 -0
- package/dist/ir/smart-tags.d.ts.map +1 -0
- package/dist/ir/smart-tags.js +30 -0
- package/dist/ir/smart-tags.js.map +1 -0
- package/dist/lib/conjure.d.ts +431 -0
- package/dist/lib/conjure.d.ts.map +1 -0
- package/dist/lib/conjure.js +697 -0
- package/dist/lib/conjure.js.map +1 -0
- package/dist/lib/field-utils.d.ts +61 -0
- package/dist/lib/field-utils.d.ts.map +1 -0
- package/dist/lib/field-utils.js +132 -0
- package/dist/lib/field-utils.js.map +1 -0
- package/dist/lib/hex.d.ts +117 -0
- package/dist/lib/hex.d.ts.map +1 -0
- package/dist/lib/hex.js +185 -0
- package/dist/lib/hex.js.map +1 -0
- package/dist/plugins/arktype.d.ts +11 -0
- package/dist/plugins/arktype.d.ts.map +1 -0
- package/dist/plugins/arktype.js +207 -0
- package/dist/plugins/arktype.js.map +1 -0
- package/dist/plugins/effect-model.d.ts +10 -0
- package/dist/plugins/effect-model.d.ts.map +1 -0
- package/dist/plugins/effect-model.js +261 -0
- package/dist/plugins/effect-model.js.map +1 -0
- package/dist/plugins/kysely-queries.d.ts +7 -0
- package/dist/plugins/kysely-queries.d.ts.map +1 -0
- package/dist/plugins/kysely-queries.js +380 -0
- package/dist/plugins/kysely-queries.js.map +1 -0
- package/dist/plugins/sql-queries.d.ts +6 -0
- package/dist/plugins/sql-queries.d.ts.map +1 -0
- package/dist/plugins/sql-queries.js +249 -0
- package/dist/plugins/sql-queries.js.map +1 -0
- package/dist/plugins/types.d.ts +18 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +263 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/plugins/zod.d.ts +11 -0
- package/dist/plugins/zod.d.ts.map +1 -0
- package/dist/plugins/zod.js +180 -0
- package/dist/plugins/zod.js.map +1 -0
- package/dist/services/artifact-store.d.ts +55 -0
- package/dist/services/artifact-store.d.ts.map +1 -0
- package/dist/services/artifact-store.js +51 -0
- package/dist/services/artifact-store.js.map +1 -0
- package/dist/services/config-loader.d.ts +45 -0
- package/dist/services/config-loader.d.ts.map +1 -0
- package/dist/services/config-loader.js +113 -0
- package/dist/services/config-loader.js.map +1 -0
- package/dist/services/emissions.d.ts +89 -0
- package/dist/services/emissions.d.ts.map +1 -0
- package/dist/services/emissions.js +194 -0
- package/dist/services/emissions.js.map +1 -0
- package/dist/services/file-builder.d.ts +81 -0
- package/dist/services/file-builder.d.ts.map +1 -0
- package/dist/services/file-builder.js +112 -0
- package/dist/services/file-builder.js.map +1 -0
- package/dist/services/file-writer.d.ts +57 -0
- package/dist/services/file-writer.d.ts.map +1 -0
- package/dist/services/file-writer.js +76 -0
- package/dist/services/file-writer.js.map +1 -0
- package/dist/services/inflection.d.ts +227 -0
- package/dist/services/inflection.d.ts.map +1 -0
- package/dist/services/inflection.js +350 -0
- package/dist/services/inflection.js.map +1 -0
- package/dist/services/introspection.d.ts +46 -0
- package/dist/services/introspection.d.ts.map +1 -0
- package/dist/services/introspection.js +99 -0
- package/dist/services/introspection.js.map +1 -0
- package/dist/services/ir-builder.d.ts +46 -0
- package/dist/services/ir-builder.d.ts.map +1 -0
- package/dist/services/ir-builder.js +923 -0
- package/dist/services/ir-builder.js.map +1 -0
- package/dist/services/ir.d.ts +28 -0
- package/dist/services/ir.d.ts.map +1 -0
- package/dist/services/ir.js +25 -0
- package/dist/services/ir.js.map +1 -0
- package/dist/services/pg-types.d.ts +197 -0
- package/dist/services/pg-types.d.ts.map +1 -0
- package/dist/services/pg-types.js +274 -0
- package/dist/services/pg-types.js.map +1 -0
- package/dist/services/plugin-meta.d.ts +33 -0
- package/dist/services/plugin-meta.d.ts.map +1 -0
- package/dist/services/plugin-meta.js +24 -0
- package/dist/services/plugin-meta.js.map +1 -0
- package/dist/services/plugin-runner.d.ts +52 -0
- package/dist/services/plugin-runner.d.ts.map +1 -0
- package/dist/services/plugin-runner.js +182 -0
- package/dist/services/plugin-runner.js.map +1 -0
- package/dist/services/plugin.d.ts +286 -0
- package/dist/services/plugin.d.ts.map +1 -0
- package/dist/services/plugin.js +132 -0
- package/dist/services/plugin.js.map +1 -0
- package/dist/services/smart-tags-parser.d.ts +37 -0
- package/dist/services/smart-tags-parser.d.ts.map +1 -0
- package/dist/services/smart-tags-parser.js +79 -0
- package/dist/services/smart-tags-parser.js.map +1 -0
- package/dist/services/symbols.d.ts +85 -0
- package/dist/services/symbols.d.ts.map +1 -0
- package/dist/services/symbols.js +128 -0
- package/dist/services/symbols.js.map +1 -0
- package/dist/services/type-hints.d.ts +62 -0
- package/dist/services/type-hints.d.ts.map +1 -0
- package/dist/services/type-hints.js +117 -0
- package/dist/services/type-hints.js.map +1 -0
- package/dist/testing.d.ts +77 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +84 -0
- package/dist/testing.js.map +1 -0
- 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":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAkB5C;;GAEG;AACH,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;CACjC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAA;AAEhE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAkC,EAClC,OAAmB;IAEnB,8BAA8B;IAC9B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACtC,OAAO,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAA;IAC7D,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAA;IAE9B,uDAAuD;IACvD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAA;IAC3D,CAAC;IAED,gDAAgD;IAChD,8DAA8D;IAC9D,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1C,MAAM,QAAQ,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAA;IAC/E,MAAM,eAAe,GACnB,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,SAAS,CAAA;IAEvF,OAAO,IAAI;IACT,aAAa;IACb,MAAM,CAAC,GAAG,CAAC;QACT,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAY;QAC1C,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,aAAa,CAAC;YAChB,OAAO,EAAE,4BAA4B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;YAC7F,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,OAAO;YACP,KAAK,EAAE,KAAK;SACb,CAAC;KACL,CAAC;IACF,mDAAmD;IACnD,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CACxB,CAAC,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CACvC,MAAM,CAAC,QAAQ,CACb,CAAC,KAAK,EAAE,EAAE,CACR,IAAI,aAAa,CAAC;QAChB,OAAO,EAAE,8BAA8B,KAAK,CAAC,OAAO,EAAE;QACtD,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,OAAO;QACP,KAAK,EAAE,KAAK;KACb,CAAC,CACL,CACF,CACF;IACD,0BAA0B;IAC1B,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QACzB,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACpC,2DAA2D;YAC3D,OAAO,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAAA;QACnE,CAAC;QAED,8CAA8C;QAC9C,OAAO,CAAC,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CACvD,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAAC,EAC9D,MAAM,CAAC,QAAQ,CACb,CAAC,KAAK,EAAE,EAAE,CACR,IAAI,aAAa,CAAC;YAChB,OAAO,EAAE,2BAA2B,KAAK,CAAC,OAAO,EAAE;YACnD,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,OAAO;YACP,KAAK,EAAE,KAAK;SACb,CAAC,CACL,CACF,CAAA;IACH,CAAC,CAAC,CACH,CAAA;AACH,CAAC"}
|
|
@@ -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"}
|