@pgpmjs/transform 0.7.1 → 0.10.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/bundle-driver.d.ts +43 -9
- package/bundle-driver.js +73 -14
- package/esm/bundle-driver.js +73 -15
- package/esm/index.js +2 -1
- package/index.d.ts +3 -2
- package/index.js +4 -1
- package/package.json +4 -4
package/bundle-driver.d.ts
CHANGED
|
@@ -7,23 +7,57 @@
|
|
|
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 { SchemaTransformResult, TransformSqlOptions } from '@pgsql/transform';
|
|
10
|
+
import { 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;
|
|
14
14
|
kind: 'deploy' | 'revert' | 'verify';
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* A single object-level route: send one named object out of a source schema to
|
|
18
|
+
* a different target schema, independent of the schema-level default. The
|
|
19
|
+
* object `kind` selects the routing namespace (relation / function / type) so a
|
|
20
|
+
* table and a function of the same name route independently.
|
|
21
|
+
*/
|
|
22
|
+
export interface SchemaObjectRoute {
|
|
23
|
+
/** Source schema the object is defined in (e.g. `users`). */
|
|
24
|
+
fromSchema: string;
|
|
25
|
+
/** Object namespace. `table`/`view` → relation, `procedure` → function. */
|
|
26
|
+
kind: 'table' | 'view' | 'function' | 'procedure' | 'type';
|
|
27
|
+
/** Unqualified object name (e.g. `accounts`). */
|
|
28
|
+
name: string;
|
|
29
|
+
/** Target schema this object is routed to (e.g. `reporting`). */
|
|
30
|
+
toSchema: string;
|
|
31
|
+
}
|
|
16
32
|
export interface SchemaTranspilerOptions {
|
|
17
|
-
/**
|
|
18
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Whole-schema default: source schema → target schema. Optional when
|
|
35
|
+
* `routes` fully cover the objects being moved.
|
|
36
|
+
*/
|
|
37
|
+
schemaMap?: Record<string, string>;
|
|
38
|
+
/**
|
|
39
|
+
* Object-level overrides. Each route wins over the schema-level default for
|
|
40
|
+
* its specific object, letting a single source schema fan out per object.
|
|
41
|
+
*/
|
|
42
|
+
routes?: SchemaObjectRoute[];
|
|
19
43
|
/** Forwarded to {@link transformSql} (round-trip validation, extra passes). */
|
|
20
44
|
transform?: TransformSqlOptions;
|
|
21
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Build a {@link SchemaRouter} from a schema-level default map plus object
|
|
48
|
+
* routes. Object routes are grouped into the router's relation/function/type
|
|
49
|
+
* buckets; schema-level entries become each route's default target.
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildSchemaRouter(options: SchemaTranspilerOptions): SchemaRouter;
|
|
22
52
|
export interface SchemaTranspiler {
|
|
23
53
|
/**
|
|
24
|
-
* Change-name/path rewrite (the pgpm structural dimension):
|
|
25
|
-
* segment
|
|
26
|
-
*
|
|
54
|
+
* Change-name/path rewrite (the pgpm structural dimension): rewrites the
|
|
55
|
+
* schema segment of a change path to the object's routed target. The object
|
|
56
|
+
* identity is read from the path itself — `schemas/<schema>/<kind>/<name>` —
|
|
57
|
+
* so a table and a function under the same source schema can land in
|
|
58
|
+
* different target schemas, e.g. `schemas/users/tables/accounts/table` →
|
|
59
|
+
* `schemas/tenant_a/tables/accounts/table` while
|
|
60
|
+
* `schemas/users/procedures/account_count` → `schemas/reporting/procedures/account_count`.
|
|
27
61
|
*/
|
|
28
62
|
renameChange: (name: string) => string;
|
|
29
63
|
/**
|
|
@@ -39,9 +73,9 @@ export interface SchemaTranspiler {
|
|
|
39
73
|
result: SchemaTransformResult;
|
|
40
74
|
}
|
|
41
75
|
/**
|
|
42
|
-
* Build the caller-supplied callbacks for `transpileBundle` from a
|
|
43
|
-
*
|
|
44
|
-
* lockstep.
|
|
76
|
+
* Build the caller-supplied callbacks for `transpileBundle` from a schema map
|
|
77
|
+
* and/or object routes, so the folder/plan rename (change identity) and the
|
|
78
|
+
* in-SQL rewrite (AST) stay in lockstep on the exact same {@link SchemaRouter}.
|
|
45
79
|
*/
|
|
46
80
|
export declare function makeSchemaTranspiler(options: SchemaTranspilerOptions): SchemaTranspiler;
|
|
47
81
|
export interface NamespaceValidatorOptions {
|
package/bundle-driver.js
CHANGED
|
@@ -9,33 +9,92 @@
|
|
|
9
9
|
* stays a pure function factory over `transformSql` and `classifyStatements`.
|
|
10
10
|
*/
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.buildSchemaRouter = buildSchemaRouter;
|
|
12
13
|
exports.makeSchemaTranspiler = makeSchemaTranspiler;
|
|
13
14
|
exports.makeNamespaceValidator = makeNamespaceValidator;
|
|
14
15
|
const transform_1 = require("@pgsql/transform");
|
|
15
16
|
const transform_2 = require("@pgsql/transform");
|
|
17
|
+
/** pgpm change-path folder segment → transform routing namespace. */
|
|
18
|
+
const PATH_KIND_NS = {
|
|
19
|
+
tables: 'relation',
|
|
20
|
+
views: 'relation',
|
|
21
|
+
procedures: 'function',
|
|
22
|
+
functions: 'function',
|
|
23
|
+
types: 'type'
|
|
24
|
+
};
|
|
25
|
+
/** Object route `kind` → the {@link SchemaRoute} bucket it belongs in. */
|
|
26
|
+
const ROUTE_KIND_BUCKET = {
|
|
27
|
+
table: 'relations',
|
|
28
|
+
view: 'relations',
|
|
29
|
+
function: 'functions',
|
|
30
|
+
procedure: 'functions',
|
|
31
|
+
type: 'types'
|
|
32
|
+
};
|
|
16
33
|
/**
|
|
17
|
-
* Build
|
|
18
|
-
*
|
|
19
|
-
*
|
|
34
|
+
* Build a {@link SchemaRouter} from a schema-level default map plus object
|
|
35
|
+
* routes. Object routes are grouped into the router's relation/function/type
|
|
36
|
+
* buckets; schema-level entries become each route's default target.
|
|
37
|
+
*/
|
|
38
|
+
function buildSchemaRouter(options) {
|
|
39
|
+
const spec = {};
|
|
40
|
+
const ensure = (schema) => (spec[schema] ??= {});
|
|
41
|
+
for (const [from, to] of Object.entries(options.schemaMap ?? {})) {
|
|
42
|
+
ensure(from).schema = to;
|
|
43
|
+
}
|
|
44
|
+
for (const route of options.routes ?? []) {
|
|
45
|
+
const bucketKey = ROUTE_KIND_BUCKET[route.kind];
|
|
46
|
+
const target = ensure(route.fromSchema);
|
|
47
|
+
(target[bucketKey] ??= {})[route.name] = route.toSchema;
|
|
48
|
+
}
|
|
49
|
+
return new transform_2.SchemaRouter(spec);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Rewrite the schema segment of a pgpm change path to the object's routed
|
|
53
|
+
* target. Interprets `schemas/<schema>/<kind>/<name>...`: the bare
|
|
54
|
+
* `schemas/<schema>/schema` change resolves at the schema level; typed folders
|
|
55
|
+
* (`tables`, `procedures`, `types`, …) resolve the named object in its
|
|
56
|
+
* namespace, so object routes and the schema-level default both apply.
|
|
57
|
+
*/
|
|
58
|
+
function renameChangePath(name, router) {
|
|
59
|
+
const parts = name.split('/');
|
|
60
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
61
|
+
if (parts[i] !== 'schemas')
|
|
62
|
+
continue;
|
|
63
|
+
const schema = parts[i + 1];
|
|
64
|
+
if (!router.has(schema))
|
|
65
|
+
continue;
|
|
66
|
+
const folder = parts[i + 2];
|
|
67
|
+
let target;
|
|
68
|
+
if (folder === undefined || folder === 'schema') {
|
|
69
|
+
target = router.resolve(schema, undefined, 'schema');
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const ns = PATH_KIND_NS[folder];
|
|
73
|
+
const objectName = parts[i + 3];
|
|
74
|
+
target = ns
|
|
75
|
+
? router.resolve(schema, objectName, ns)
|
|
76
|
+
: router.resolve(schema, undefined, 'schema');
|
|
77
|
+
}
|
|
78
|
+
if (target && target !== schema)
|
|
79
|
+
parts[i + 1] = target;
|
|
80
|
+
}
|
|
81
|
+
return parts.join('/');
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build the caller-supplied callbacks for `transpileBundle` from a schema map
|
|
85
|
+
* and/or object routes, so the folder/plan rename (change identity) and the
|
|
86
|
+
* in-SQL rewrite (AST) stay in lockstep on the exact same {@link SchemaRouter}.
|
|
20
87
|
*/
|
|
21
88
|
function makeSchemaTranspiler(options) {
|
|
22
|
-
const
|
|
89
|
+
const router = buildSchemaRouter(options);
|
|
23
90
|
const result = {
|
|
24
91
|
schemasFound: new Set(),
|
|
25
92
|
schemasTransformed: new Map(),
|
|
26
93
|
errors: []
|
|
27
94
|
};
|
|
28
|
-
const renameChange = (name) =>
|
|
29
|
-
const parts = name.split('/');
|
|
30
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
31
|
-
if (parts[i] === 'schemas' && mapping.has(parts[i + 1])) {
|
|
32
|
-
parts[i + 1] = mapping.get(parts[i + 1]);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return parts.join('/');
|
|
36
|
-
};
|
|
95
|
+
const renameChange = (name) => renameChangePath(name, router);
|
|
37
96
|
const transformScript = (sql, _ctx) => {
|
|
38
|
-
return (0, transform_2.transformSql)(sql,
|
|
97
|
+
return (0, transform_2.transformSql)(sql, router, options.transform, result).content;
|
|
39
98
|
};
|
|
40
99
|
return { renameChange, transformScript, result };
|
|
41
100
|
}
|
package/esm/bundle-driver.js
CHANGED
|
@@ -8,30 +8,88 @@
|
|
|
8
8
|
* stays a pure function factory over `transformSql` and `classifyStatements`.
|
|
9
9
|
*/
|
|
10
10
|
import { classifyStatements } from '@pgsql/transform';
|
|
11
|
-
import { transformSql } from '@pgsql/transform';
|
|
11
|
+
import { SchemaRouter, transformSql } from '@pgsql/transform';
|
|
12
|
+
/** pgpm change-path folder segment → transform routing namespace. */
|
|
13
|
+
const PATH_KIND_NS = {
|
|
14
|
+
tables: 'relation',
|
|
15
|
+
views: 'relation',
|
|
16
|
+
procedures: 'function',
|
|
17
|
+
functions: 'function',
|
|
18
|
+
types: 'type'
|
|
19
|
+
};
|
|
20
|
+
/** Object route `kind` → the {@link SchemaRoute} bucket it belongs in. */
|
|
21
|
+
const ROUTE_KIND_BUCKET = {
|
|
22
|
+
table: 'relations',
|
|
23
|
+
view: 'relations',
|
|
24
|
+
function: 'functions',
|
|
25
|
+
procedure: 'functions',
|
|
26
|
+
type: 'types'
|
|
27
|
+
};
|
|
12
28
|
/**
|
|
13
|
-
* Build
|
|
14
|
-
*
|
|
15
|
-
*
|
|
29
|
+
* Build a {@link SchemaRouter} from a schema-level default map plus object
|
|
30
|
+
* routes. Object routes are grouped into the router's relation/function/type
|
|
31
|
+
* buckets; schema-level entries become each route's default target.
|
|
32
|
+
*/
|
|
33
|
+
export function buildSchemaRouter(options) {
|
|
34
|
+
const spec = {};
|
|
35
|
+
const ensure = (schema) => (spec[schema] ??= {});
|
|
36
|
+
for (const [from, to] of Object.entries(options.schemaMap ?? {})) {
|
|
37
|
+
ensure(from).schema = to;
|
|
38
|
+
}
|
|
39
|
+
for (const route of options.routes ?? []) {
|
|
40
|
+
const bucketKey = ROUTE_KIND_BUCKET[route.kind];
|
|
41
|
+
const target = ensure(route.fromSchema);
|
|
42
|
+
(target[bucketKey] ??= {})[route.name] = route.toSchema;
|
|
43
|
+
}
|
|
44
|
+
return new SchemaRouter(spec);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Rewrite the schema segment of a pgpm change path to the object's routed
|
|
48
|
+
* target. Interprets `schemas/<schema>/<kind>/<name>...`: the bare
|
|
49
|
+
* `schemas/<schema>/schema` change resolves at the schema level; typed folders
|
|
50
|
+
* (`tables`, `procedures`, `types`, …) resolve the named object in its
|
|
51
|
+
* namespace, so object routes and the schema-level default both apply.
|
|
52
|
+
*/
|
|
53
|
+
function renameChangePath(name, router) {
|
|
54
|
+
const parts = name.split('/');
|
|
55
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
56
|
+
if (parts[i] !== 'schemas')
|
|
57
|
+
continue;
|
|
58
|
+
const schema = parts[i + 1];
|
|
59
|
+
if (!router.has(schema))
|
|
60
|
+
continue;
|
|
61
|
+
const folder = parts[i + 2];
|
|
62
|
+
let target;
|
|
63
|
+
if (folder === undefined || folder === 'schema') {
|
|
64
|
+
target = router.resolve(schema, undefined, 'schema');
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
const ns = PATH_KIND_NS[folder];
|
|
68
|
+
const objectName = parts[i + 3];
|
|
69
|
+
target = ns
|
|
70
|
+
? router.resolve(schema, objectName, ns)
|
|
71
|
+
: router.resolve(schema, undefined, 'schema');
|
|
72
|
+
}
|
|
73
|
+
if (target && target !== schema)
|
|
74
|
+
parts[i + 1] = target;
|
|
75
|
+
}
|
|
76
|
+
return parts.join('/');
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Build the caller-supplied callbacks for `transpileBundle` from a schema map
|
|
80
|
+
* and/or object routes, so the folder/plan rename (change identity) and the
|
|
81
|
+
* in-SQL rewrite (AST) stay in lockstep on the exact same {@link SchemaRouter}.
|
|
16
82
|
*/
|
|
17
83
|
export function makeSchemaTranspiler(options) {
|
|
18
|
-
const
|
|
84
|
+
const router = buildSchemaRouter(options);
|
|
19
85
|
const result = {
|
|
20
86
|
schemasFound: new Set(),
|
|
21
87
|
schemasTransformed: new Map(),
|
|
22
88
|
errors: []
|
|
23
89
|
};
|
|
24
|
-
const renameChange = (name) =>
|
|
25
|
-
const parts = name.split('/');
|
|
26
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
27
|
-
if (parts[i] === 'schemas' && mapping.has(parts[i + 1])) {
|
|
28
|
-
parts[i + 1] = mapping.get(parts[i + 1]);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return parts.join('/');
|
|
32
|
-
};
|
|
90
|
+
const renameChange = (name) => renameChangePath(name, router);
|
|
33
91
|
const transformScript = (sql, _ctx) => {
|
|
34
|
-
return transformSql(sql,
|
|
92
|
+
return transformSql(sql, router, options.transform, result).content;
|
|
35
93
|
};
|
|
36
94
|
return { renameChange, transformScript, result };
|
|
37
95
|
}
|
package/esm/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from '@pgsql/transform';
|
|
2
|
-
export {
|
|
2
|
+
export { loadModule } from 'plpgsql-parser';
|
|
3
|
+
export { buildSchemaRouter, makeNamespaceValidator, makeSchemaTranspiler, } from './bundle-driver';
|
|
3
4
|
export { buildCategoryOf, categorizeChange, TIER_PROFILE, } from './categorize';
|
|
4
5
|
export { resolveFixtureClosure } from './fixture-closure';
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from '@pgsql/transform';
|
|
2
|
-
export
|
|
3
|
-
export {
|
|
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';
|
|
4
5
|
export type { CategoryProfile, ChangeCategory, } from './categorize';
|
|
5
6
|
export { buildCategoryOf, categorizeChange, TIER_PROFILE, } from './categorize';
|
|
6
7
|
export type { ClosureChange, ClosureInputChange, ClosureReason, FixtureClosure, ResolveFixtureClosureOptions, } from './fixture-closure';
|
package/index.js
CHANGED
|
@@ -14,9 +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 = void 0;
|
|
17
|
+
exports.resolveFixtureClosure = exports.TIER_PROFILE = exports.categorizeChange = exports.buildCategoryOf = exports.makeSchemaTranspiler = exports.makeNamespaceValidator = exports.buildSchemaRouter = exports.loadModule = void 0;
|
|
18
18
|
__exportStar(require("@pgsql/transform"), exports);
|
|
19
|
+
var plpgsql_parser_1 = require("plpgsql-parser");
|
|
20
|
+
Object.defineProperty(exports, "loadModule", { enumerable: true, get: function () { return plpgsql_parser_1.loadModule; } });
|
|
19
21
|
var bundle_driver_1 = require("./bundle-driver");
|
|
22
|
+
Object.defineProperty(exports, "buildSchemaRouter", { enumerable: true, get: function () { return bundle_driver_1.buildSchemaRouter; } });
|
|
20
23
|
Object.defineProperty(exports, "makeNamespaceValidator", { enumerable: true, get: function () { return bundle_driver_1.makeNamespaceValidator; } });
|
|
21
24
|
Object.defineProperty(exports, "makeSchemaTranspiler", { enumerable: true, get: function () { return bundle_driver_1.makeSchemaTranspiler; } });
|
|
22
25
|
var categorize_1 = require("./categorize");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pgpmjs/transform",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
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.
|
|
42
|
+
"@pgpmjs/bundle": "^0.11.0",
|
|
43
43
|
"makage": "^0.3.0"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@pgsql/transform": "^18.
|
|
46
|
+
"@pgsql/transform": "^18.5.0",
|
|
47
47
|
"plpgsql-parser": "^18.2.1"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "d85911699e8a50a9fdfeb7506195442525c1f238"
|
|
50
50
|
}
|