@pgpmjs/core 7.0.0 → 7.2.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.
Files changed (102) hide show
  1. package/bundle/apply.d.ts +93 -0
  2. package/bundle/apply.js +137 -0
  3. package/bundle/index.d.ts +12 -0
  4. package/bundle/index.js +31 -0
  5. package/core/class/pgpm.d.ts +2 -2
  6. package/core/class/pgpm.js +6 -6
  7. package/esm/bundle/apply.js +131 -0
  8. package/esm/bundle/index.js +15 -0
  9. package/esm/core/class/pgpm.js +6 -6
  10. package/esm/index.js +7 -3
  11. package/esm/migrate/client.js +1 -1
  12. package/esm/migrate/utils/hash.js +3 -6
  13. package/esm/modules/modules.js +1 -1
  14. package/esm/packaging/package.js +40 -24
  15. package/esm/rebundle/index.js +4 -0
  16. package/esm/rebundle/module.js +111 -0
  17. package/esm/rebundle/rebundle.js +170 -0
  18. package/esm/rebundle/workspace.js +170 -0
  19. package/esm/refactor/rename.js +5 -27
  20. package/esm/resolution/deps.js +2 -2
  21. package/esm/resolution/resolve.js +2 -2
  22. package/esm/slice/slice.js +1 -1
  23. package/esm/workspace/minimal.js +73 -0
  24. package/index.d.ts +6 -2
  25. package/index.js +8 -4
  26. package/migrate/client.js +1 -1
  27. package/migrate/utils/hash.d.ts +2 -4
  28. package/migrate/utils/hash.js +4 -8
  29. package/modules/modules.d.ts +1 -1
  30. package/modules/modules.js +1 -1
  31. package/package.json +4 -2
  32. package/packaging/package.d.ts +23 -1
  33. package/packaging/package.js +42 -25
  34. package/rebundle/index.d.ts +4 -0
  35. package/{files/sql-scripts → rebundle}/index.js +4 -2
  36. package/rebundle/module.d.ts +23 -0
  37. package/rebundle/module.js +116 -0
  38. package/rebundle/rebundle.d.ts +26 -0
  39. package/rebundle/rebundle.js +175 -0
  40. package/rebundle/types.d.ts +185 -0
  41. package/rebundle/workspace.d.ts +15 -0
  42. package/rebundle/workspace.js +173 -0
  43. package/refactor/rename.d.ts +2 -8
  44. package/refactor/rename.js +6 -29
  45. package/resolution/deps.d.ts +1 -1
  46. package/resolution/deps.js +2 -2
  47. package/resolution/resolve.js +2 -2
  48. package/slice/slice.d.ts +1 -1
  49. package/slice/slice.js +1 -1
  50. package/slice/types.d.ts +1 -1
  51. package/workspace/minimal.d.ts +64 -0
  52. package/workspace/minimal.js +82 -0
  53. package/esm/files/extension/index.js +0 -3
  54. package/esm/files/extension/reader.js +0 -79
  55. package/esm/files/extension/writer.js +0 -99
  56. package/esm/files/index.js +0 -6
  57. package/esm/files/plan/generator.js +0 -82
  58. package/esm/files/plan/index.js +0 -5
  59. package/esm/files/plan/parser.js +0 -297
  60. package/esm/files/plan/validators.js +0 -181
  61. package/esm/files/plan/writer.js +0 -142
  62. package/esm/files/sql/header.js +0 -259
  63. package/esm/files/sql/index.js +0 -2
  64. package/esm/files/sql/writer.js +0 -107
  65. package/esm/files/sql-scripts/index.js +0 -2
  66. package/esm/files/sql-scripts/reader.js +0 -19
  67. package/esm/files/types/index.js +0 -1
  68. package/esm/utils/author.js +0 -11
  69. package/files/extension/index.d.ts +0 -2
  70. package/files/extension/index.js +0 -19
  71. package/files/extension/reader.d.ts +0 -24
  72. package/files/extension/reader.js +0 -86
  73. package/files/extension/writer.d.ts +0 -48
  74. package/files/extension/writer.js +0 -107
  75. package/files/index.d.ts +0 -5
  76. package/files/index.js +0 -22
  77. package/files/plan/generator.d.ts +0 -23
  78. package/files/plan/generator.js +0 -90
  79. package/files/plan/index.d.ts +0 -4
  80. package/files/plan/index.js +0 -21
  81. package/files/plan/parser.d.ts +0 -28
  82. package/files/plan/parser.js +0 -304
  83. package/files/plan/validators.d.ts +0 -52
  84. package/files/plan/validators.js +0 -187
  85. package/files/plan/writer.d.ts +0 -27
  86. package/files/plan/writer.js +0 -152
  87. package/files/sql/header.d.ts +0 -114
  88. package/files/sql/header.js +0 -266
  89. package/files/sql/index.d.ts +0 -2
  90. package/files/sql/index.js +0 -18
  91. package/files/sql/writer.d.ts +0 -12
  92. package/files/sql/writer.js +0 -114
  93. package/files/sql-scripts/index.d.ts +0 -1
  94. package/files/sql-scripts/reader.d.ts +0 -8
  95. package/files/sql-scripts/reader.js +0 -23
  96. package/files/types/index.d.ts +0 -46
  97. package/files/types/index.js +0 -17
  98. package/files/types/package.d.ts +0 -20
  99. package/utils/author.d.ts +0 -5
  100. package/utils/author.js +0 -14
  101. /package/esm/{files/types/package.js → rebundle/types.js} +0 -0
  102. /package/{files/types/package.js → rebundle/types.js} +0 -0
@@ -1,152 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.writePgpmPlan = writePgpmPlan;
7
- exports.writePlanFile = writePlanFile;
8
- exports.generatePlanFileContent = generatePlanFileContent;
9
- exports.generateChangeLineContent = generateChangeLineContent;
10
- exports.generateTagLineContent = generateTagLineContent;
11
- const fs_1 = __importDefault(require("fs"));
12
- const path_1 = __importDefault(require("path"));
13
- const author_1 = require("../../utils/author");
14
- /**
15
- * Sort dependencies by their order in the supplied plan, so prerequisites
16
- * (parent migrations) appear before their dependents in the bracket.
17
- * Internal dependencies are sorted by their plan index, and external
18
- * dependencies (not in the plan) preserve their original order.
19
- */
20
- const sortDependencies = (deps, order) => {
21
- const originalOrder = new Map(deps.map((dep, index) => [dep, index]));
22
- return [...deps].sort((a, b) => {
23
- const aIndex = order.get(a);
24
- const bIndex = order.get(b);
25
- const aOriginal = originalOrder.get(a);
26
- const bOriginal = originalOrder.get(b);
27
- if (aIndex !== undefined && bIndex !== undefined)
28
- return aIndex - bIndex || aOriginal - bOriginal;
29
- if (aIndex !== undefined)
30
- return -1;
31
- if (bIndex !== undefined)
32
- return 1;
33
- return aOriginal - bOriginal;
34
- });
35
- };
36
- /**
37
- * Write a PGPM plan file based on the provided rows
38
- */
39
- function writePgpmPlan(rows, opts) {
40
- const dir = path_1.default.resolve(path_1.default.join(opts.outdir, opts.name));
41
- fs_1.default.mkdirSync(dir, { recursive: true });
42
- const date = () => '2017-08-11T08:11:51Z'; // stubbed timestamp
43
- const { fullName, email } = (0, author_1.parseAuthor)(opts.author || 'constructive');
44
- const authorName = fullName;
45
- const authorEmail = email || `${fullName}@5b0c196eeb62`;
46
- const duplicates = {};
47
- // Build an order map from the row list so brackets can be sorted by plan order
48
- const rowOrder = new Map(rows.map((row, index) => [row.deploy, index]));
49
- const plan = opts.replacer(`%syntax-version=1.0.0
50
- %project=constructive-extension-name
51
- %uri=constructive-extension-name
52
-
53
- ${rows
54
- .map((row) => {
55
- if (duplicates[row.deploy]) {
56
- console.log('DUPLICATE ' + row.deploy);
57
- return '';
58
- }
59
- duplicates[row.deploy] = true;
60
- if (row.deps?.length) {
61
- return `${row.deploy} [${sortDependencies(row.deps, rowOrder).join(' ')}] ${date()} ${authorName} <${authorEmail}> # add ${row.name}`;
62
- }
63
- return `${row.deploy} ${date()} ${authorName} <${authorEmail}> # add ${row.name}`;
64
- })
65
- .join('\n')}
66
- `);
67
- fs_1.default.writeFileSync(path_1.default.join(dir, 'pgpm.plan'), plan);
68
- }
69
- /**
70
- * Write a plan file with the provided content
71
- */
72
- function writePlanFile(planPath, plan) {
73
- const content = generatePlanFileContent(plan);
74
- fs_1.default.writeFileSync(planPath, content);
75
- }
76
- /**
77
- * Generate content for a plan file
78
- */
79
- function generatePlanFileContent(plan) {
80
- const { package: packageName, uri, changes, tags } = plan;
81
- let content = `%syntax-version=1.0.0\n`;
82
- content += `%project=${packageName}\n`;
83
- if (uri) {
84
- content += `%uri=${uri}\n`;
85
- }
86
- content += `\n`;
87
- // Build an order map from the change list so brackets can be sorted by plan order
88
- const changeOrder = new Map(changes.map((change, index) => [change.name, index]));
89
- // Add changes and their associated tags
90
- for (const change of changes) {
91
- content += generateChangeLineContent(change, changeOrder);
92
- content += `\n`;
93
- const associatedTags = tags.filter(tag => tag.change === change.name);
94
- for (const tag of associatedTags) {
95
- content += generateTagLineContent(tag);
96
- content += `\n`;
97
- }
98
- }
99
- return content;
100
- }
101
- /**
102
- * Generate a line for a change in a plan file
103
- */
104
- function generateChangeLineContent(change, changeOrder) {
105
- const { name, dependencies, timestamp, planner, email, comment } = change;
106
- let line = name;
107
- // Add dependencies if present, sorted by plan order
108
- if (dependencies && dependencies.length > 0) {
109
- line += ` [${sortDependencies(dependencies, changeOrder || new Map()).join(' ')}]`;
110
- }
111
- // Add timestamp if present
112
- if (timestamp) {
113
- line += ` ${timestamp}`;
114
- // Add planner if present
115
- if (planner) {
116
- line += ` ${planner}`;
117
- // Add email if present
118
- if (email) {
119
- line += ` <${email}>`;
120
- }
121
- }
122
- }
123
- // Add comment if present
124
- if (comment) {
125
- line += ` # ${comment}`;
126
- }
127
- return line;
128
- }
129
- /**
130
- * Generate a line for a tag in a plan file
131
- */
132
- function generateTagLineContent(tag) {
133
- const { name, timestamp, planner, email, comment } = tag;
134
- let line = `@${name}`;
135
- // Add timestamp if present
136
- if (timestamp) {
137
- line += ` ${timestamp}`;
138
- // Add planner if present
139
- if (planner) {
140
- line += ` ${planner}`;
141
- // Add email if present
142
- if (email) {
143
- line += ` <${email}>`;
144
- }
145
- }
146
- }
147
- // Add comment if present
148
- if (comment) {
149
- line += ` # ${comment}`;
150
- }
151
- return line;
152
- }
@@ -1,114 +0,0 @@
1
- import { ParsedReference } from '../plan/validators';
2
- /**
3
- * A parsed `-- requires:` line from a pgpm SQL script header.
4
- */
5
- export interface PgpmHeaderRequire {
6
- /** The dependency reference exactly as written (e.g. `schema`, `pkg:tables/users`, `pkg:@v1`). */
7
- raw: string;
8
- /** Structured breakdown of the reference (package/change/tag), when parseable. */
9
- ref: ParsedReference | null;
10
- }
11
- /**
12
- * The parsed header block of a pgpm SQL script (deploy/revert/verify).
13
- *
14
- * The header is everything from the top of the file through the last
15
- * header-relevant comment line (`-- Deploy|Revert|Verify ...`,
16
- * `-- requires: ...`, and any interleaved comment/blank lines), with the
17
- * remainder of the file preserved as `body`.
18
- */
19
- export interface PgpmHeader {
20
- /** Header verb: Deploy, Revert or Verify. Null when no header line was found. */
21
- verb: 'Deploy' | 'Revert' | 'Verify' | null;
22
- /** The project (extension) name from `-- Deploy <project>:<change>`, if present. */
23
- project: string | null;
24
- /**
25
- * The change name from the header line. By convention this must equal the
26
- * script's path identity: `deploy/<change>.sql`.
27
- */
28
- change: string | null;
29
- /** Whether the header line carried the legacy ` to pg` suffix. */
30
- toPg: boolean;
31
- /** Parsed `-- requires:` dependencies, in file order. */
32
- requires: PgpmHeaderRequire[];
33
- /** The raw header lines, byte-exact, in file order. */
34
- lines: string[];
35
- }
36
- /**
37
- * Result of splitting a SQL script into header and body.
38
- */
39
- export interface ParsedPgpmScript {
40
- header: PgpmHeader;
41
- /** Everything after the header block, byte-exact. */
42
- body: string;
43
- }
44
- /**
45
- * Parse the header block of a pgpm SQL script into a structured model.
46
- *
47
- * Recognizes both header formats:
48
- * `-- Deploy <project>:<change> to pg` (legacy sqitch-compatible)
49
- * `-- Deploy <change>` / `-- Deploy: <change>` (new)
50
- * along with `-- requires: <ref>` lines where `<ref>` may be a plain change
51
- * name, `{package}:{change}`, `@tag`, or `{package}:@tag`.
52
- *
53
- * The parse is lossless: `header.lines` plus `body` reassemble the original
54
- * content byte-exactly (see {@link writePgpmScript}).
55
- */
56
- export declare function parsePgpmHeader(content: string): ParsedPgpmScript;
57
- /**
58
- * Serialize a header back to its raw lines. When the structured fields have
59
- * been modified via {@link renameInHeader}, the raw lines already reflect the
60
- * change; this simply joins header and body losslessly.
61
- */
62
- export declare function writePgpmScript(script: ParsedPgpmScript): string;
63
- /**
64
- * Rewrite change names in a script header according to a rename map
65
- * (old change name -> new change name). Rewrites both the `-- Deploy` line's
66
- * change identity and any `-- requires:` lines referencing renamed changes,
67
- * preserving format (project qualifier, ` to pg` suffix, tag refs untouched).
68
- *
69
- * Returns the number of substitutions applied; mutates `script` in place.
70
- */
71
- export declare function renameInHeader(script: ParsedPgpmScript, renames: Map<string, string>): number;
72
- /**
73
- * Options for {@link scanDeployScript}.
74
- */
75
- export interface ScanDeployScriptOptions {
76
- /** The script's path identity key (e.g. `/deploy/tables/users.sql`). */
77
- key: string;
78
- /** The current extension (project) name. */
79
- extname: string;
80
- /** Maps a change name to its path identity key. */
81
- makeKey: (change: string) => string;
82
- }
83
- /**
84
- * Scan a deploy script the way dependency resolution historically has:
85
- * line-by-line over the whole file, collecting `-- requires: <ref>` lines
86
- * verbatim and validating any `-- Deploy <project>:<change>[ to pg]` line
87
- * against the script's path identity and project name.
88
- *
89
- * Kept strictly line-regex-compatible with the original resolver behavior
90
- * (requires lines are honored anywhere in the file, and the legacy
91
- * `-- Deploy: <change>` colon form is not identity-validated).
92
- *
93
- * @throws when the Deploy line's project or change identity mismatches.
94
- */
95
- export declare function scanDeployScript(content: string, options: ScanDeployScriptOptions): {
96
- requires: string[];
97
- };
98
- /**
99
- * A single plan-vs-header discrepancy found by {@link verifyPlanMatchesHeaders}.
100
- */
101
- export interface HeaderDriftIssue {
102
- change: string;
103
- file: string;
104
- kind: 'missing-file' | 'identity-mismatch' | 'requires-drift';
105
- message: string;
106
- }
107
- /**
108
- * Verify that every change in a module's pgpm.plan has a deploy script whose
109
- * header identity matches its path, and report dependency drift between the
110
- * plan's dep lists and the scripts' `-- requires:` lines.
111
- *
112
- * Read-only diagnostic; returns issues rather than throwing.
113
- */
114
- export declare function verifyPlanMatchesHeaders(moduleDir: string): HeaderDriftIssue[];
@@ -1,266 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parsePgpmHeader = parsePgpmHeader;
4
- exports.writePgpmScript = writePgpmScript;
5
- exports.renameInHeader = renameInHeader;
6
- exports.scanDeployScript = scanDeployScript;
7
- exports.verifyPlanMatchesHeaders = verifyPlanMatchesHeaders;
8
- const fs_1 = require("fs");
9
- const path_1 = require("path");
10
- const parser_1 = require("../plan/parser");
11
- const validators_1 = require("../plan/validators");
12
- const HEADER_LINE = /^--\s*(Deploy|Revert|Verify)\b(:)?\s*(.*?)\s*$/;
13
- const REQUIRES_LINE = /^--\s*requires:\s*(.*?)\s*$/;
14
- const COMMENT_LINE = /^\s*--/;
15
- const TO_PG_SUFFIX = /\s+to\s+pg\s*$/;
16
- /**
17
- * Parse the header block of a pgpm SQL script into a structured model.
18
- *
19
- * Recognizes both header formats:
20
- * `-- Deploy <project>:<change> to pg` (legacy sqitch-compatible)
21
- * `-- Deploy <change>` / `-- Deploy: <change>` (new)
22
- * along with `-- requires: <ref>` lines where `<ref>` may be a plain change
23
- * name, `{package}:{change}`, `@tag`, or `{package}:@tag`.
24
- *
25
- * The parse is lossless: `header.lines` plus `body` reassemble the original
26
- * content byte-exactly (see {@link writePgpmScript}).
27
- */
28
- function parsePgpmHeader(content) {
29
- const header = {
30
- verb: null,
31
- project: null,
32
- change: null,
33
- toPg: false,
34
- requires: [],
35
- lines: []
36
- };
37
- const lines = content.split('\n');
38
- let lastHeaderIdx = -1;
39
- for (let i = 0; i < lines.length; i++) {
40
- const line = lines[i];
41
- if (line.trim() === '') {
42
- continue;
43
- }
44
- if (!COMMENT_LINE.test(line)) {
45
- break;
46
- }
47
- const headerMatch = line.match(HEADER_LINE);
48
- if (headerMatch && header.verb === null) {
49
- header.verb = headerMatch[1];
50
- let target = headerMatch[3];
51
- if (TO_PG_SUFFIX.test(target)) {
52
- header.toPg = true;
53
- target = target.replace(TO_PG_SUFFIX, '');
54
- }
55
- const colonIndex = target.indexOf(':');
56
- if (colonIndex > 0 && /^[a-zA-Z0-9_-]+$/.test(target.substring(0, colonIndex))) {
57
- header.project = target.substring(0, colonIndex);
58
- header.change = target.substring(colonIndex + 1).trim();
59
- }
60
- else {
61
- header.change = target.trim() || null;
62
- }
63
- lastHeaderIdx = i;
64
- continue;
65
- }
66
- const requiresMatch = line.match(REQUIRES_LINE);
67
- if (requiresMatch) {
68
- const raw = requiresMatch[1];
69
- header.requires.push({ raw, ref: (0, validators_1.parseReference)(raw) });
70
- lastHeaderIdx = i;
71
- continue;
72
- }
73
- // Other comment lines (e.g. attribution) before/between header lines are
74
- // tolerated but only absorbed into the header when a later header line
75
- // follows; trailing comments belong to the body.
76
- }
77
- header.lines = lines.slice(0, lastHeaderIdx + 1);
78
- return {
79
- header,
80
- body: lines.slice(lastHeaderIdx + 1).join('\n')
81
- };
82
- }
83
- /**
84
- * Serialize a header back to its raw lines. When the structured fields have
85
- * been modified via {@link renameInHeader}, the raw lines already reflect the
86
- * change; this simply joins header and body losslessly.
87
- */
88
- function writePgpmScript(script) {
89
- if (script.header.lines.length === 0)
90
- return script.body;
91
- return script.header.lines.join('\n') + '\n' + script.body;
92
- }
93
- /**
94
- * Rewrite change names in a script header according to a rename map
95
- * (old change name -> new change name). Rewrites both the `-- Deploy` line's
96
- * change identity and any `-- requires:` lines referencing renamed changes,
97
- * preserving format (project qualifier, ` to pg` suffix, tag refs untouched).
98
- *
99
- * Returns the number of substitutions applied; mutates `script` in place.
100
- */
101
- function renameInHeader(script, renames) {
102
- const { header } = script;
103
- let count = 0;
104
- const renameRef = (raw) => {
105
- const ref = (0, validators_1.parseReference)(raw);
106
- if (!ref) {
107
- const to = renames.get(raw);
108
- return to ?? null;
109
- }
110
- if (ref.tag || ref.symbolic || ref.relative)
111
- return null;
112
- const change = ref.change;
113
- if (!change)
114
- return null;
115
- const to = renames.get(change);
116
- if (!to)
117
- return null;
118
- return ref.package ? `${ref.package}:${to}` : to;
119
- };
120
- header.lines = header.lines.map(line => {
121
- const headerMatch = line.match(HEADER_LINE);
122
- if (headerMatch && header.change && renames.has(header.change)) {
123
- const to = renames.get(header.change);
124
- const oldTarget = header.project ? `${header.project}:${header.change}` : header.change;
125
- const newTarget = header.project ? `${header.project}:${to}` : to;
126
- const rewritten = line.replace(oldTarget, newTarget);
127
- if (rewritten !== line) {
128
- header.change = to;
129
- count++;
130
- return rewritten;
131
- }
132
- return line;
133
- }
134
- const requiresMatch = line.match(REQUIRES_LINE);
135
- if (requiresMatch) {
136
- const raw = requiresMatch[1];
137
- const renamed = renameRef(raw);
138
- if (renamed !== null) {
139
- count++;
140
- return line.replace(raw, renamed);
141
- }
142
- }
143
- return line;
144
- });
145
- header.requires = header.requires.map(req => {
146
- const renamed = renameRef(req.raw);
147
- if (renamed === null)
148
- return req;
149
- return { raw: renamed, ref: (0, validators_1.parseReference)(renamed) };
150
- });
151
- return count;
152
- }
153
- /**
154
- * Scan a deploy script the way dependency resolution historically has:
155
- * line-by-line over the whole file, collecting `-- requires: <ref>` lines
156
- * verbatim and validating any `-- Deploy <project>:<change>[ to pg]` line
157
- * against the script's path identity and project name.
158
- *
159
- * Kept strictly line-regex-compatible with the original resolver behavior
160
- * (requires lines are honored anywhere in the file, and the legacy
161
- * `-- Deploy: <change>` colon form is not identity-validated).
162
- *
163
- * @throws when the Deploy line's project or change identity mismatches.
164
- */
165
- function scanDeployScript(content, options) {
166
- const { key, extname, makeKey } = options;
167
- const requires = [];
168
- for (const line of content.split('\n')) {
169
- const requiresMatch = line.match(/^-- requires: (.*)/);
170
- if (requiresMatch) {
171
- requires.push(requiresMatch[1].trim());
172
- continue;
173
- }
174
- if (/:/.test(line)) {
175
- const m2 = line.match(/^-- Deploy ([^:]*):([\w\/]+)(?:\s+to\s+pg)?/);
176
- if (m2) {
177
- const actualProject = m2[1];
178
- const keyToTest = m2[2];
179
- if (extname !== actualProject) {
180
- throw new Error(`Mismatched project name in deploy file:
181
- Expected project: ${extname}
182
- Found in line : ${actualProject}
183
- Line : ${line}`);
184
- }
185
- const expectedKey = makeKey(keyToTest);
186
- if (key !== expectedKey) {
187
- throw new Error(`Deployment script path or internal name mismatch:
188
- Expected key : ${key}
189
- Found in line : ${expectedKey}
190
- Line : ${line}`);
191
- }
192
- }
193
- }
194
- else {
195
- const m2 = line.match(/^-- Deploy (.*?)(?:\s+to\s+pg)?\s*$/);
196
- if (m2) {
197
- const keyToTest = m2[1].trim();
198
- if (key !== makeKey(keyToTest)) {
199
- throw new Error('deployment script in wrong place or is named wrong internally\n' + line);
200
- }
201
- }
202
- }
203
- }
204
- return { requires };
205
- }
206
- /**
207
- * Verify that every change in a module's pgpm.plan has a deploy script whose
208
- * header identity matches its path, and report dependency drift between the
209
- * plan's dep lists and the scripts' `-- requires:` lines.
210
- *
211
- * Read-only diagnostic; returns issues rather than throwing.
212
- */
213
- function verifyPlanMatchesHeaders(moduleDir) {
214
- const issues = [];
215
- const planPath = (0, path_1.join)(moduleDir, 'pgpm.plan');
216
- const parsed = (0, parser_1.parsePlanFile)(planPath);
217
- if (!parsed.data) {
218
- throw new Error(`Failed to parse plan file: ${planPath}`);
219
- }
220
- for (const planChange of parsed.data.changes) {
221
- const change = planChange.name;
222
- const file = (0, path_1.join)(moduleDir, 'deploy', `${change}.sql`);
223
- let content;
224
- try {
225
- content = (0, fs_1.readFileSync)(file, 'utf-8');
226
- }
227
- catch {
228
- issues.push({
229
- change,
230
- file,
231
- kind: 'missing-file',
232
- message: `deploy script not found for plan change "${change}"`
233
- });
234
- continue;
235
- }
236
- const { header } = parsePgpmHeader(content);
237
- if (header.change && header.change !== change) {
238
- issues.push({
239
- change,
240
- file,
241
- kind: 'identity-mismatch',
242
- message: `header declares "${header.change}" but path identity is "${change}"`
243
- });
244
- }
245
- const planDeps = new Set(planChange.dependencies || []);
246
- const headerDeps = new Set(header.requires.map(r => r.raw));
247
- const missingInHeader = [...planDeps].filter(d => !headerDeps.has(d));
248
- const missingInPlan = [...headerDeps].filter(d => !planDeps.has(d));
249
- if (missingInHeader.length > 0 || missingInPlan.length > 0) {
250
- const parts = [];
251
- if (missingInHeader.length > 0) {
252
- parts.push(`in plan but not in header requires: ${missingInHeader.join(', ')}`);
253
- }
254
- if (missingInPlan.length > 0) {
255
- parts.push(`in header requires but not in plan: ${missingInPlan.join(', ')}`);
256
- }
257
- issues.push({
258
- change,
259
- file,
260
- kind: 'requires-drift',
261
- message: parts.join('; ')
262
- });
263
- }
264
- }
265
- return issues;
266
- }
@@ -1,2 +0,0 @@
1
- export * from './header';
2
- export * from './writer';
@@ -1,18 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./header"), exports);
18
- __exportStar(require("./writer"), exports);
@@ -1,12 +0,0 @@
1
- import { PgpmRow } from '../types';
2
- export interface SqlWriteOptions {
3
- outdir: string;
4
- name: string;
5
- replacer: (str: string) => string;
6
- author?: string;
7
- useTx?: boolean;
8
- }
9
- /**
10
- * Write SQL files for PGPM migrations (deploy, revert, verify)
11
- */
12
- export declare const writePgpmFiles: (rows: PgpmRow[], opts: SqlWriteOptions) => void;
@@ -1,114 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.writePgpmFiles = void 0;
7
- const env_1 = require("@pgpmjs/env");
8
- const fs_1 = __importDefault(require("fs"));
9
- const path_1 = __importDefault(require("path"));
10
- /**
11
- * Write SQL files for PGPM migrations (deploy, revert, verify)
12
- */
13
- const writePgpmFiles = (rows, opts) => {
14
- rows.forEach((row) => writeVerify(row, opts));
15
- rows.forEach((row) => writeRevert(row, opts));
16
- rows.forEach((row) => writeDeploy(row, opts));
17
- };
18
- exports.writePgpmFiles = writePgpmFiles;
19
- /**
20
- * Sort dependencies in a consistent order
21
- */
22
- const ordered = (arr) => {
23
- if (!arr)
24
- return [];
25
- return arr.sort((a, b) => a.length - b.length || a.localeCompare(b));
26
- };
27
- /**
28
- * Write a deploy SQL file for a PGPM change
29
- */
30
- const writeDeploy = (row, opts) => {
31
- const globalOpts = (0, env_1.getEnvOptions)({
32
- migrations: {
33
- codegen: {
34
- useTx: opts.useTx
35
- }
36
- }
37
- });
38
- const useTx = globalOpts.migrations.codegen.useTx;
39
- const deploy = opts.replacer(row.deploy);
40
- const dir = path_1.default.dirname(deploy);
41
- const prefix = path_1.default.join(opts.outdir, opts.name, 'deploy');
42
- const actualDir = path_1.default.resolve(prefix, dir);
43
- const actualFile = path_1.default.resolve(prefix, `${deploy}.sql`);
44
- fs_1.default.mkdirSync(actualDir, { recursive: true });
45
- const sqlContent = opts.replacer(row.content);
46
- const content = `-- Deploy: ${deploy}
47
- -- made with <3 @ constructive.io
48
-
49
- ${opts.replacer(ordered(row?.deps)
50
- .map((dep) => `-- requires: ${dep}`)
51
- .join('\n') || '')}
52
-
53
- ${useTx ? 'BEGIN;' : ''}
54
- ${sqlContent}
55
- ${useTx ? 'COMMIT;' : ''}
56
- `;
57
- fs_1.default.writeFileSync(actualFile, content);
58
- };
59
- /**
60
- * Write a verify SQL file for a PGPM change
61
- */
62
- const writeVerify = (row, opts) => {
63
- const globalOpts = (0, env_1.getEnvOptions)({
64
- migrations: {
65
- codegen: {
66
- useTx: opts.useTx
67
- }
68
- }
69
- });
70
- const useTx = globalOpts.migrations.codegen.useTx;
71
- const deploy = opts.replacer(row.deploy);
72
- const dir = path_1.default.dirname(deploy);
73
- const prefix = path_1.default.join(opts.outdir, opts.name, 'verify');
74
- const actualDir = path_1.default.resolve(prefix, dir);
75
- const actualFile = path_1.default.resolve(prefix, `${deploy}.sql`);
76
- fs_1.default.mkdirSync(actualDir, { recursive: true });
77
- const sqlContent = opts.replacer(row.verify);
78
- const content = opts.replacer(`-- Verify: ${deploy}
79
-
80
- ${useTx ? 'BEGIN;' : ''}
81
- ${sqlContent}
82
- ${useTx ? 'COMMIT;' : ''}
83
-
84
- `);
85
- fs_1.default.writeFileSync(actualFile, content);
86
- };
87
- /**
88
- * Write a revert SQL file for a PGPM change
89
- */
90
- const writeRevert = (row, opts) => {
91
- const globalOpts = (0, env_1.getEnvOptions)({
92
- migrations: {
93
- codegen: {
94
- useTx: opts.useTx
95
- }
96
- }
97
- });
98
- const useTx = globalOpts.migrations.codegen.useTx;
99
- const deploy = opts.replacer(row.deploy);
100
- const dir = path_1.default.dirname(deploy);
101
- const prefix = path_1.default.join(opts.outdir, opts.name, 'revert');
102
- const actualDir = path_1.default.resolve(prefix, dir);
103
- const actualFile = path_1.default.resolve(prefix, `${deploy}.sql`);
104
- fs_1.default.mkdirSync(actualDir, { recursive: true });
105
- const sqlContent = opts.replacer(row.revert);
106
- const content = `-- Revert: ${deploy}
107
-
108
- ${useTx ? 'BEGIN;' : ''}
109
- ${sqlContent}
110
- ${useTx ? 'COMMIT;' : ''}
111
-
112
- `;
113
- fs_1.default.writeFileSync(actualFile, content);
114
- };
@@ -1 +0,0 @@
1
- export * from './reader';