@pgpmjs/transform 0.10.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@
7
7
  * purpose — no dependency on `@pgpmjs/bundle`/`@pgpmjs/core` — so the driver
8
8
  * stays a pure function factory over `transformSql` and `classifyStatements`.
9
9
  */
10
- import { SchemaRouter, SchemaTransformResult, TransformSqlOptions } from '@pgsql/transform';
10
+ import { ExtensionDefinition, ExtensionRouteSpec, ExtensionRouter, ExtensionTransformResult, RoleRouteSpec, RoleTransformResult, SchemaRouter, SchemaTransformResult, TransformSqlOptions } from '@pgsql/transform';
11
11
  /** Identity of the script being transformed/validated (matches the bundle seams). */
12
12
  export interface BundleScriptContext {
13
13
  change: string;
@@ -29,6 +29,42 @@ export interface SchemaObjectRoute {
29
29
  /** Target schema this object is routed to (e.g. `reporting`). */
30
30
  toSchema: string;
31
31
  }
32
+ /**
33
+ * Extension routing for a transpile: where to install extensions and where the
34
+ * symbols they provide (functions/types/operators) should resolve. Distinct
35
+ * from schema routing — the objects are owned by an extension, not declared in
36
+ * the SQL — so it is driven by a version-aware symbol inventory. See the
37
+ * upstream `ExtensionRouter` for the full model. `toSchema: null` (or a `routes`
38
+ * entry with `to: null`) strips qualification — the "rely on search_path"
39
+ * direction — so the same mechanism moves symbols into a dedicated schema and
40
+ * back out again.
41
+ */
42
+ export interface ExtensionRoutingInput {
43
+ /**
44
+ * Move the matched extensions and their provided symbols to this single
45
+ * schema (`null` strips qualification). Ignored when `routes` is given.
46
+ */
47
+ toSchema?: string | null;
48
+ /** With `toSchema`: limit to these extensions (default: every inventoried one). */
49
+ only?: string[];
50
+ /**
51
+ * With `toSchema`: which source qualifications to rewrite (a `null` entry
52
+ * also rewrites bare references). Defaults to `public` + bare.
53
+ */
54
+ from?: (string | null)[];
55
+ /** Advanced: explicit per-extension route spec. Overrides `toSchema`/`only`/`from`. */
56
+ routes?: ExtensionRouteSpec;
57
+ /** Target PostgreSQL major version, for core-graduation awareness (e.g. `gen_random_uuid`). */
58
+ serverVersion?: number;
59
+ /** Augmented or replacement symbol inventory (defaults to the curated common set). */
60
+ inventory?: ExtensionDefinition[];
61
+ }
62
+ /**
63
+ * Build an {@link ExtensionRouter} from the declarative {@link ExtensionRoutingInput}:
64
+ * an explicit `routes` spec when given, otherwise the "move everything matched
65
+ * to one schema" shortcut via `ExtensionRouter.toSchema`.
66
+ */
67
+ export declare function buildExtensionRouter(input: ExtensionRoutingInput): ExtensionRouter;
32
68
  export interface SchemaTranspilerOptions {
33
69
  /**
34
70
  * Whole-schema default: source schema → target schema. Optional when
@@ -40,6 +76,17 @@ export interface SchemaTranspilerOptions {
40
76
  * its specific object, letting a single source schema fan out per object.
41
77
  */
42
78
  routes?: SchemaObjectRoute[];
79
+ /**
80
+ * Route extension installs and provided-symbol references (a dimension
81
+ * orthogonal to schema routing). See {@link ExtensionRoutingInput}.
82
+ */
83
+ extensions?: ExtensionRoutingInput;
84
+ /**
85
+ * Rename role identifiers (source role name → target role name), for
86
+ * translating between databases that name equivalent roles differently.
87
+ * Renames identifiers only — never role attributes.
88
+ */
89
+ roles?: RoleRouteSpec | Map<string, string>;
43
90
  /** Forwarded to {@link transformSql} (round-trip validation, extra passes). */
44
91
  transform?: TransformSqlOptions;
45
92
  }
@@ -71,6 +118,16 @@ export interface SchemaTranspiler {
71
118
  * schemas found/transformed and any per-script errors.
72
119
  */
73
120
  result: SchemaTransformResult;
121
+ /**
122
+ * Accumulated extension-routing report (installs moved, symbols rewritten).
123
+ * Present only when `extensions` was configured.
124
+ */
125
+ extensionResult?: ExtensionTransformResult;
126
+ /**
127
+ * Accumulated role-routing report (role → rewrite count). Present only when
128
+ * `roles` was configured.
129
+ */
130
+ roleResult?: RoleTransformResult;
74
131
  }
75
132
  /**
76
133
  * Build the caller-supplied callbacks for `transpileBundle` from a schema map
package/bundle-driver.js CHANGED
@@ -9,11 +9,31 @@
9
9
  * stays a pure function factory over `transformSql` and `classifyStatements`.
10
10
  */
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.buildExtensionRouter = buildExtensionRouter;
12
13
  exports.buildSchemaRouter = buildSchemaRouter;
13
14
  exports.makeSchemaTranspiler = makeSchemaTranspiler;
14
15
  exports.makeNamespaceValidator = makeNamespaceValidator;
15
16
  const transform_1 = require("@pgsql/transform");
16
17
  const transform_2 = require("@pgsql/transform");
18
+ /**
19
+ * Build an {@link ExtensionRouter} from the declarative {@link ExtensionRoutingInput}:
20
+ * an explicit `routes` spec when given, otherwise the "move everything matched
21
+ * to one schema" shortcut via `ExtensionRouter.toSchema`.
22
+ */
23
+ function buildExtensionRouter(input) {
24
+ const opts = {};
25
+ if (input.serverVersion !== undefined)
26
+ opts.serverVersion = input.serverVersion;
27
+ if (input.inventory)
28
+ opts.inventory = input.inventory;
29
+ if (input.routes)
30
+ return new transform_2.ExtensionRouter(input.routes, opts);
31
+ return transform_2.ExtensionRouter.toSchema(input.toSchema ?? null, {
32
+ ...opts,
33
+ extensions: input.only,
34
+ from: input.from
35
+ });
36
+ }
17
37
  /** pgpm change-path folder segment → transform routing namespace. */
18
38
  const PATH_KIND_NS = {
19
39
  tables: 'relation',
@@ -92,11 +112,36 @@ function makeSchemaTranspiler(options) {
92
112
  schemasTransformed: new Map(),
93
113
  errors: []
94
114
  };
115
+ // Extension/role routing are additional, orthogonal AST dimensions applied
116
+ // after schema routing on each script. Each is a self-contained parse →
117
+ // rewrite → deparse pass, so they compose by threading the SQL through.
118
+ const extRouter = options.extensions ? buildExtensionRouter(options.extensions) : undefined;
119
+ const roleRouter = options.roles ? transform_2.RoleRouter.from(options.roles) : undefined;
120
+ const extensionResult = extRouter ? (0, transform_2.createExtensionResult)() : undefined;
121
+ const roleResult = roleRouter ? (0, transform_2.createRoleResult)() : undefined;
95
122
  const renameChange = (name) => renameChangePath(name, router);
96
123
  const transformScript = (sql, _ctx) => {
97
- return (0, transform_2.transformSql)(sql, router, options.transform, result).content;
124
+ let out = (0, transform_2.transformSql)(sql, router, options.transform, result).content;
125
+ if (extRouter) {
126
+ const r = (0, transform_2.transformExtensions)(out, extRouter);
127
+ out = r.sql;
128
+ for (const [name, schema] of r.result.installsMoved) {
129
+ extensionResult.installsMoved.set(name, schema);
130
+ }
131
+ for (const [name, count] of r.result.symbolsRewritten) {
132
+ extensionResult.symbolsRewritten.set(name, (extensionResult.symbolsRewritten.get(name) ?? 0) + count);
133
+ }
134
+ }
135
+ if (roleRouter) {
136
+ const r = (0, transform_2.transformRoles)(out, roleRouter);
137
+ out = r.sql;
138
+ for (const [name, count] of r.result.rolesRenamed) {
139
+ roleResult.rolesRenamed.set(name, (roleResult.rolesRenamed.get(name) ?? 0) + count);
140
+ }
141
+ }
142
+ return out;
98
143
  };
99
- return { renameChange, transformScript, result };
144
+ return { renameChange, transformScript, result, extensionResult, roleResult };
100
145
  }
101
146
  /**
102
147
  * Build an `applyBundle`-compatible `validateReferences` callback: returns a
@@ -8,7 +8,26 @@
8
8
  * stays a pure function factory over `transformSql` and `classifyStatements`.
9
9
  */
10
10
  import { classifyStatements } from '@pgsql/transform';
11
- import { SchemaRouter, transformSql } from '@pgsql/transform';
11
+ import { createExtensionResult, createRoleResult, ExtensionRouter, RoleRouter, SchemaRouter, transformExtensions, transformRoles, transformSql } from '@pgsql/transform';
12
+ /**
13
+ * Build an {@link ExtensionRouter} from the declarative {@link ExtensionRoutingInput}:
14
+ * an explicit `routes` spec when given, otherwise the "move everything matched
15
+ * to one schema" shortcut via `ExtensionRouter.toSchema`.
16
+ */
17
+ export function buildExtensionRouter(input) {
18
+ const opts = {};
19
+ if (input.serverVersion !== undefined)
20
+ opts.serverVersion = input.serverVersion;
21
+ if (input.inventory)
22
+ opts.inventory = input.inventory;
23
+ if (input.routes)
24
+ return new ExtensionRouter(input.routes, opts);
25
+ return ExtensionRouter.toSchema(input.toSchema ?? null, {
26
+ ...opts,
27
+ extensions: input.only,
28
+ from: input.from
29
+ });
30
+ }
12
31
  /** pgpm change-path folder segment → transform routing namespace. */
13
32
  const PATH_KIND_NS = {
14
33
  tables: 'relation',
@@ -87,11 +106,36 @@ export function makeSchemaTranspiler(options) {
87
106
  schemasTransformed: new Map(),
88
107
  errors: []
89
108
  };
109
+ // Extension/role routing are additional, orthogonal AST dimensions applied
110
+ // after schema routing on each script. Each is a self-contained parse →
111
+ // rewrite → deparse pass, so they compose by threading the SQL through.
112
+ const extRouter = options.extensions ? buildExtensionRouter(options.extensions) : undefined;
113
+ const roleRouter = options.roles ? RoleRouter.from(options.roles) : undefined;
114
+ const extensionResult = extRouter ? createExtensionResult() : undefined;
115
+ const roleResult = roleRouter ? createRoleResult() : undefined;
90
116
  const renameChange = (name) => renameChangePath(name, router);
91
117
  const transformScript = (sql, _ctx) => {
92
- return transformSql(sql, router, options.transform, result).content;
118
+ let out = transformSql(sql, router, options.transform, result).content;
119
+ if (extRouter) {
120
+ const r = transformExtensions(out, extRouter);
121
+ out = r.sql;
122
+ for (const [name, schema] of r.result.installsMoved) {
123
+ extensionResult.installsMoved.set(name, schema);
124
+ }
125
+ for (const [name, count] of r.result.symbolsRewritten) {
126
+ extensionResult.symbolsRewritten.set(name, (extensionResult.symbolsRewritten.get(name) ?? 0) + count);
127
+ }
128
+ }
129
+ if (roleRouter) {
130
+ const r = transformRoles(out, roleRouter);
131
+ out = r.sql;
132
+ for (const [name, count] of r.result.rolesRenamed) {
133
+ roleResult.rolesRenamed.set(name, (roleResult.rolesRenamed.get(name) ?? 0) + count);
134
+ }
135
+ }
136
+ return out;
93
137
  };
94
- return { renameChange, transformScript, result };
138
+ return { renameChange, transformScript, result, extensionResult, roleResult };
95
139
  }
96
140
  /**
97
141
  * Build an `applyBundle`-compatible `validateReferences` callback: returns a
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export * from '@pgsql/transform';
2
2
  export { loadModule } from 'plpgsql-parser';
3
- export { buildSchemaRouter, makeNamespaceValidator, makeSchemaTranspiler, } from './bundle-driver';
3
+ export { buildExtensionRouter, buildSchemaRouter, makeNamespaceValidator, makeSchemaTranspiler, } from './bundle-driver';
4
4
  export { buildCategoryOf, categorizeChange, TIER_PROFILE, } from './categorize';
5
5
  export { resolveFixtureClosure } from './fixture-closure';
package/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export * from '@pgsql/transform';
2
2
  export { loadModule } from 'plpgsql-parser';
3
- export type { BundleScriptContext, NamespaceValidatorOptions, SchemaObjectRoute, SchemaTranspiler, SchemaTranspilerOptions, } from './bundle-driver';
4
- export { buildSchemaRouter, makeNamespaceValidator, makeSchemaTranspiler, } from './bundle-driver';
3
+ export type { BundleScriptContext, ExtensionRoutingInput, NamespaceValidatorOptions, SchemaObjectRoute, SchemaTranspiler, SchemaTranspilerOptions, } from './bundle-driver';
4
+ export { buildExtensionRouter, buildSchemaRouter, makeNamespaceValidator, makeSchemaTranspiler, } from './bundle-driver';
5
5
  export type { CategoryProfile, ChangeCategory, } from './categorize';
6
6
  export { buildCategoryOf, categorizeChange, TIER_PROFILE, } from './categorize';
7
7
  export type { ClosureChange, ClosureInputChange, ClosureReason, FixtureClosure, ResolveFixtureClosureOptions, } from './fixture-closure';
package/index.js CHANGED
@@ -14,11 +14,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.resolveFixtureClosure = exports.TIER_PROFILE = exports.categorizeChange = exports.buildCategoryOf = exports.makeSchemaTranspiler = exports.makeNamespaceValidator = exports.buildSchemaRouter = exports.loadModule = void 0;
17
+ exports.resolveFixtureClosure = exports.TIER_PROFILE = exports.categorizeChange = exports.buildCategoryOf = exports.makeSchemaTranspiler = exports.makeNamespaceValidator = exports.buildSchemaRouter = exports.buildExtensionRouter = exports.loadModule = void 0;
18
18
  __exportStar(require("@pgsql/transform"), exports);
19
19
  var plpgsql_parser_1 = require("plpgsql-parser");
20
20
  Object.defineProperty(exports, "loadModule", { enumerable: true, get: function () { return plpgsql_parser_1.loadModule; } });
21
21
  var bundle_driver_1 = require("./bundle-driver");
22
+ Object.defineProperty(exports, "buildExtensionRouter", { enumerable: true, get: function () { return bundle_driver_1.buildExtensionRouter; } });
22
23
  Object.defineProperty(exports, "buildSchemaRouter", { enumerable: true, get: function () { return bundle_driver_1.buildSchemaRouter; } });
23
24
  Object.defineProperty(exports, "makeNamespaceValidator", { enumerable: true, get: function () { return bundle_driver_1.makeNamespaceValidator; } });
24
25
  Object.defineProperty(exports, "makeSchemaTranspiler", { enumerable: true, get: function () { return bundle_driver_1.makeSchemaTranspiler; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pgpmjs/transform",
3
- "version": "0.10.0",
3
+ "version": "0.11.1",
4
4
  "author": "Constructive <developers@constructive.io>",
5
5
  "description": "Change-aware SQL transformation for PGPM — superset of @pgsql/transform plus change categorization, fixture closure, and bundle transpile/apply drivers",
6
6
  "main": "index.js",
@@ -39,12 +39,12 @@
39
39
  "plpgsql"
40
40
  ],
41
41
  "devDependencies": {
42
- "@pgpmjs/bundle": "^0.11.0",
42
+ "@pgpmjs/bundle": "^0.12.1",
43
43
  "makage": "^0.3.0"
44
44
  },
45
45
  "dependencies": {
46
- "@pgsql/transform": "^18.5.0",
46
+ "@pgsql/transform": "^18.6.0",
47
47
  "plpgsql-parser": "^18.2.1"
48
48
  },
49
- "gitHead": "d85911699e8a50a9fdfeb7506195442525c1f238"
49
+ "gitHead": "0286d994d98717cb9b28842233d2db6d1e37c48e"
50
50
  }