@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,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Introspection Service
|
|
3
|
+
*
|
|
4
|
+
* Provides typed database introspection using pg-introspection.
|
|
5
|
+
*/
|
|
6
|
+
import { Effect, Context } from "effect";
|
|
7
|
+
import pg from "pg";
|
|
8
|
+
import { makeIntrospectionQuery, parseIntrospectionResults, } from "@pg-sourcerer/pg-introspection";
|
|
9
|
+
import { ConnectionFailed, IntrospectionFailed } from "../errors.js";
|
|
10
|
+
/**
|
|
11
|
+
* Service tag for dependency injection
|
|
12
|
+
*/
|
|
13
|
+
export class DatabaseIntrospectionService extends Context.Tag("DatabaseIntrospection")() {
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Live implementation using pg
|
|
17
|
+
*/
|
|
18
|
+
export const DatabaseIntrospectionLive = Effect.sync(() => createDatabaseIntrospection());
|
|
19
|
+
/**
|
|
20
|
+
* Create a DatabaseIntrospection implementation
|
|
21
|
+
*/
|
|
22
|
+
export function createDatabaseIntrospection() {
|
|
23
|
+
return {
|
|
24
|
+
introspect: (options) => Effect.gen(function* () {
|
|
25
|
+
const { connectionString, role } = options;
|
|
26
|
+
// Create pool and connect
|
|
27
|
+
const pool = new pg.Pool({ connectionString });
|
|
28
|
+
const client = yield* Effect.tryPromise({
|
|
29
|
+
try: () => pool.connect(),
|
|
30
|
+
catch: (error) => new ConnectionFailed({
|
|
31
|
+
message: `Failed to connect to database`,
|
|
32
|
+
connectionString: connectionString.replace(/:[^:@]+@/, ":***@"), // Hide password
|
|
33
|
+
cause: error,
|
|
34
|
+
}),
|
|
35
|
+
});
|
|
36
|
+
try {
|
|
37
|
+
// Begin transaction
|
|
38
|
+
yield* Effect.tryPromise({
|
|
39
|
+
try: () => client.query("begin"),
|
|
40
|
+
catch: (error) => new IntrospectionFailed({
|
|
41
|
+
message: "Failed to begin transaction",
|
|
42
|
+
schema: "*",
|
|
43
|
+
cause: error,
|
|
44
|
+
}),
|
|
45
|
+
});
|
|
46
|
+
// Set role if specified
|
|
47
|
+
if (role) {
|
|
48
|
+
yield* Effect.tryPromise({
|
|
49
|
+
try: () => client.query("select set_config('role', $1, false)", [role]),
|
|
50
|
+
catch: (error) => new IntrospectionFailed({
|
|
51
|
+
message: `Failed to set role to '${role}'`,
|
|
52
|
+
schema: "*",
|
|
53
|
+
cause: error,
|
|
54
|
+
}),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
// Run introspection query
|
|
58
|
+
const result = yield* Effect.tryPromise({
|
|
59
|
+
try: () => client.query(makeIntrospectionQuery()),
|
|
60
|
+
catch: (error) => new IntrospectionFailed({
|
|
61
|
+
message: "Introspection query failed",
|
|
62
|
+
schema: "*",
|
|
63
|
+
cause: error,
|
|
64
|
+
}),
|
|
65
|
+
});
|
|
66
|
+
const rawIntrospection = result.rows[0]?.introspection;
|
|
67
|
+
if (!rawIntrospection) {
|
|
68
|
+
return yield* Effect.fail(new IntrospectionFailed({
|
|
69
|
+
message: "Introspection returned no results",
|
|
70
|
+
schema: "*",
|
|
71
|
+
cause: null,
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
// Rollback (we only read)
|
|
75
|
+
yield* Effect.tryPromise({
|
|
76
|
+
try: () => client.query("rollback"),
|
|
77
|
+
catch: (error) => new IntrospectionFailed({
|
|
78
|
+
message: "Failed to rollback transaction",
|
|
79
|
+
schema: "*",
|
|
80
|
+
cause: error,
|
|
81
|
+
}),
|
|
82
|
+
});
|
|
83
|
+
// Parse results
|
|
84
|
+
return parseIntrospectionResults(rawIntrospection, true);
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
client.release();
|
|
88
|
+
yield* Effect.promise(() => pool.end());
|
|
89
|
+
}
|
|
90
|
+
}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Convenience function for one-off introspection (e.g., scripts)
|
|
95
|
+
*/
|
|
96
|
+
export function introspectDatabase(options) {
|
|
97
|
+
return createDatabaseIntrospection().introspect(options);
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=introspection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"introspection.js","sourceRoot":"","sources":["../../src/services/introspection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IR Builder Service
|
|
3
|
+
*
|
|
4
|
+
* Transforms raw pg-introspection output into SemanticIR.
|
|
5
|
+
* Builds entities (tables, views, composites), shapes, fields,
|
|
6
|
+
* relations, and enums.
|
|
7
|
+
*/
|
|
8
|
+
import { Context, Effect, Layer } from "effect";
|
|
9
|
+
import type { Introspection } from "@pg-sourcerer/pg-introspection";
|
|
10
|
+
import type { SemanticIR } from "../ir/semantic-ir.js";
|
|
11
|
+
import { Inflection } from "./inflection.js";
|
|
12
|
+
import { IntrospectionFailed, TagParseError } from "../errors.js";
|
|
13
|
+
/**
|
|
14
|
+
* Options for IR building
|
|
15
|
+
*/
|
|
16
|
+
export interface IRBuilderOptions {
|
|
17
|
+
/** PostgreSQL schemas to include */
|
|
18
|
+
readonly schemas: readonly string[];
|
|
19
|
+
/** Exclude functions that belong to extensions (default: true) */
|
|
20
|
+
readonly excludeExtensionFunctions?: boolean;
|
|
21
|
+
/** Role to use for permission checks (defaults to current user) */
|
|
22
|
+
readonly role?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* IR Builder service interface
|
|
26
|
+
*/
|
|
27
|
+
export interface IRBuilder {
|
|
28
|
+
/** Build SemanticIR from pg-introspection output */
|
|
29
|
+
readonly build: (introspection: Introspection, options: IRBuilderOptions) => Effect.Effect<SemanticIR, IntrospectionFailed | TagParseError, Inflection>;
|
|
30
|
+
}
|
|
31
|
+
declare const IRBuilderSvc_base: Context.TagClass<IRBuilderSvc, "IRBuilder", IRBuilder>;
|
|
32
|
+
/** Service tag */
|
|
33
|
+
export declare class IRBuilderSvc extends IRBuilderSvc_base {
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Live layer - provides IRBuilder service
|
|
37
|
+
* Note: IRBuilder.build() requires Inflection to be provided at call time
|
|
38
|
+
*/
|
|
39
|
+
export declare const IRBuilderLive: Layer.Layer<IRBuilderSvc, never, never>;
|
|
40
|
+
/**
|
|
41
|
+
* Factory function for creating IR builder
|
|
42
|
+
* Note: The returned builder's build() method requires Inflection in the Effect context
|
|
43
|
+
*/
|
|
44
|
+
export declare function createIRBuilderService(): IRBuilder;
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=ir-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ir-builder.d.ts","sourceRoot":"","sources":["../../src/services/ir-builder.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAA8B,MAAM,QAAQ,CAAA;AAC3E,OAAO,KAAK,EACV,aAAa,EAOd,MAAM,gCAAgC,CAAA;AAEvC,OAAO,KAAK,EAcV,UAAU,EAKX,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAMjE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,kEAAkE;IAClE,QAAQ,CAAC,yBAAyB,CAAC,EAAE,OAAO,CAAA;IAC5C,mEAAmE;IACnE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,CACd,aAAa,EAAE,aAAa,EAC5B,OAAO,EAAE,gBAAgB,KACtB,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,mBAAmB,GAAG,aAAa,EAAE,UAAU,CAAC,CAAA;CAChF;;AAED,kBAAkB;AAClB,qBAAa,YAAa,SAAQ,iBAAmD;CAAG;AA4oCxF;;;GAGG;AACH,eAAO,MAAM,aAAa,yCAAqD,CAAA;AAE/E;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,SAAS,CAElD"}
|