@pgpmjs/transform 0.12.0 → 0.13.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/esm/index.js CHANGED
@@ -3,3 +3,4 @@ export { loadModule } from 'plpgsql-parser';
3
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';
6
+ export { emitSqlProgram, parseSqlProgram } from './program';
package/esm/program.js ADDED
@@ -0,0 +1,49 @@
1
+ import { classifyStatements } from '@pgsql/transform';
2
+ import { Deparser, parseSql } from 'plpgsql-parser';
3
+ /**
4
+ * Parse a SQL script into a statement program. Requires `loadModule()` from
5
+ * `plpgsql-parser` to have completed.
6
+ */
7
+ export function parseSqlProgram(source) {
8
+ const parseResult = parseSql(source);
9
+ const stmts = parseResult?.stmts ?? [];
10
+ const facts = classifyStatements(source);
11
+ const statements = [];
12
+ for (let i = 0; i < stmts.length; i++) {
13
+ const rawStmt = stmts[i];
14
+ if (!rawStmt?.stmt)
15
+ continue;
16
+ const { start, len } = facts[i].span;
17
+ statements.push({
18
+ stmt: rawStmt.stmt,
19
+ facts: facts[i],
20
+ span: { start, len },
21
+ raw: source.slice(start, start + len),
22
+ dirty: false
23
+ });
24
+ }
25
+ return { source, statements };
26
+ }
27
+ /**
28
+ * Emit a program back to SQL. Clean statements — and every byte between
29
+ * statements — are copied verbatim from the source; dirty statements are
30
+ * re-printed through the deparser. With no dirty statements the output is
31
+ * byte-identical to the source.
32
+ */
33
+ export function emitSqlProgram(program) {
34
+ const { source, statements } = program;
35
+ if (!statements.some(s => s.dirty))
36
+ return source;
37
+ const pieces = [];
38
+ let cursor = 0;
39
+ for (const statement of statements) {
40
+ const { start, len } = statement.span;
41
+ if (start > cursor)
42
+ pieces.push(source.slice(cursor, start));
43
+ pieces.push(statement.dirty ? Deparser.deparse(statement.stmt) : source.slice(start, start + len));
44
+ cursor = start + len;
45
+ }
46
+ if (cursor < source.length)
47
+ pieces.push(source.slice(cursor));
48
+ return pieces.join('');
49
+ }
package/index.d.ts CHANGED
@@ -6,3 +6,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';
8
8
  export { resolveFixtureClosure } from './fixture-closure';
9
+ export type { SqlProgram, SqlStatementAst, SqlStatementSpan, } from './program';
10
+ export { emitSqlProgram, parseSqlProgram } from './program';
package/index.js CHANGED
@@ -14,7 +14,7 @@ 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.buildExtensionRouter = exports.loadModule = void 0;
17
+ exports.parseSqlProgram = exports.emitSqlProgram = 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; } });
@@ -29,3 +29,6 @@ Object.defineProperty(exports, "categorizeChange", { enumerable: true, get: func
29
29
  Object.defineProperty(exports, "TIER_PROFILE", { enumerable: true, get: function () { return categorize_1.TIER_PROFILE; } });
30
30
  var fixture_closure_1 = require("./fixture-closure");
31
31
  Object.defineProperty(exports, "resolveFixtureClosure", { enumerable: true, get: function () { return fixture_closure_1.resolveFixtureClosure; } });
32
+ var program_1 = require("./program");
33
+ Object.defineProperty(exports, "emitSqlProgram", { enumerable: true, get: function () { return program_1.emitSqlProgram; } });
34
+ Object.defineProperty(exports, "parseSqlProgram", { enumerable: true, get: function () { return program_1.parseSqlProgram; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pgpmjs/transform",
3
- "version": "0.12.0",
3
+ "version": "0.13.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.12.2",
42
+ "@pgpmjs/bundle": "^0.12.4",
43
43
  "makage": "^0.3.0"
44
44
  },
45
45
  "dependencies": {
46
- "@pgsql/transform": "^18.7.0",
47
- "plpgsql-parser": "^18.2.1"
46
+ "@pgsql/transform": "^18.8.0",
47
+ "plpgsql-parser": "^18.2.2"
48
48
  },
49
- "gitHead": "2832d5632d11eb22e1437df773706ac6a99175fe"
49
+ "gitHead": "04b34ce4b5efcebfd8e49d64d196e651288d97f3"
50
50
  }
package/program.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Statement-level SQL program AST.
3
+ *
4
+ * A `SqlProgram` is one parse of a SQL script into per-statement units, each
5
+ * carrying its parsed node, semantic facts, source span, verbatim text, and a
6
+ * dirty flag. Transformations mutate a statement's `stmt` node and mark it
7
+ * dirty; emission re-prints only dirty statements through the deparser and
8
+ * copies every other byte of the script verbatim (comments, whitespace,
9
+ * untouched statements). A program with no dirty statements emits its source
10
+ * byte-identically, so content-addressed hashes are preserved.
11
+ */
12
+ import type { StatementFacts } from '@pgsql/transform';
13
+ /** A statement's location in the source script (byte offsets). */
14
+ export type SqlStatementSpan = StatementFacts['span'];
15
+ /** One statement of a parsed SQL script. */
16
+ export interface SqlStatementAst {
17
+ /** The tagged statement node (e.g. `{ CreateStmt: {...} }`), mutable. */
18
+ stmt: any;
19
+ /** Semantic facts classified from the statement. */
20
+ facts: StatementFacts;
21
+ /** Source span within the program's `source`. */
22
+ span: SqlStatementSpan;
23
+ /** Verbatim source text of the statement (`source.slice(start, start+len)`). */
24
+ raw: string;
25
+ /** Whether the statement's AST has been mutated and must be deparsed. */
26
+ dirty: boolean;
27
+ }
28
+ /** A SQL script parsed once into statement units. */
29
+ export interface SqlProgram {
30
+ source: string;
31
+ statements: SqlStatementAst[];
32
+ }
33
+ /**
34
+ * Parse a SQL script into a statement program. Requires `loadModule()` from
35
+ * `plpgsql-parser` to have completed.
36
+ */
37
+ export declare function parseSqlProgram(source: string): SqlProgram;
38
+ /**
39
+ * Emit a program back to SQL. Clean statements — and every byte between
40
+ * statements — are copied verbatim from the source; dirty statements are
41
+ * re-printed through the deparser. With no dirty statements the output is
42
+ * byte-identical to the source.
43
+ */
44
+ export declare function emitSqlProgram(program: SqlProgram): string;
package/program.js ADDED
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseSqlProgram = parseSqlProgram;
4
+ exports.emitSqlProgram = emitSqlProgram;
5
+ const transform_1 = require("@pgsql/transform");
6
+ const plpgsql_parser_1 = require("plpgsql-parser");
7
+ /**
8
+ * Parse a SQL script into a statement program. Requires `loadModule()` from
9
+ * `plpgsql-parser` to have completed.
10
+ */
11
+ function parseSqlProgram(source) {
12
+ const parseResult = (0, plpgsql_parser_1.parseSql)(source);
13
+ const stmts = parseResult?.stmts ?? [];
14
+ const facts = (0, transform_1.classifyStatements)(source);
15
+ const statements = [];
16
+ for (let i = 0; i < stmts.length; i++) {
17
+ const rawStmt = stmts[i];
18
+ if (!rawStmt?.stmt)
19
+ continue;
20
+ const { start, len } = facts[i].span;
21
+ statements.push({
22
+ stmt: rawStmt.stmt,
23
+ facts: facts[i],
24
+ span: { start, len },
25
+ raw: source.slice(start, start + len),
26
+ dirty: false
27
+ });
28
+ }
29
+ return { source, statements };
30
+ }
31
+ /**
32
+ * Emit a program back to SQL. Clean statements — and every byte between
33
+ * statements — are copied verbatim from the source; dirty statements are
34
+ * re-printed through the deparser. With no dirty statements the output is
35
+ * byte-identical to the source.
36
+ */
37
+ function emitSqlProgram(program) {
38
+ const { source, statements } = program;
39
+ if (!statements.some(s => s.dirty))
40
+ return source;
41
+ const pieces = [];
42
+ let cursor = 0;
43
+ for (const statement of statements) {
44
+ const { start, len } = statement.span;
45
+ if (start > cursor)
46
+ pieces.push(source.slice(cursor, start));
47
+ pieces.push(statement.dirty ? plpgsql_parser_1.Deparser.deparse(statement.stmt) : source.slice(start, start + len));
48
+ cursor = start + len;
49
+ }
50
+ if (cursor < source.length)
51
+ pieces.push(source.slice(cursor));
52
+ return pieces.join('');
53
+ }