@pgpmjs/core 7.1.0 → 7.2.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.
- package/bundle/apply.d.ts +93 -0
- package/bundle/apply.js +137 -0
- package/bundle/index.d.ts +12 -0
- package/bundle/index.js +31 -0
- package/core/class/pgpm.d.ts +2 -2
- package/core/class/pgpm.js +6 -6
- package/esm/bundle/apply.js +131 -0
- package/esm/bundle/index.js +15 -0
- package/esm/core/class/pgpm.js +6 -6
- package/esm/index.js +5 -3
- package/esm/migrate/client.js +1 -1
- package/esm/migrate/utils/hash.js +3 -6
- package/esm/modules/modules.js +1 -1
- package/esm/packaging/package.js +1 -1
- package/esm/rebundle/module.js +1 -1
- package/esm/rebundle/rebundle.js +2 -2
- package/esm/rebundle/workspace.js +1 -1
- package/esm/refactor/rename.js +5 -27
- package/esm/resolution/deps.js +2 -2
- package/esm/resolution/resolve.js +2 -2
- package/esm/slice/slice.js +7 -32
- package/index.d.ts +4 -2
- package/index.js +6 -4
- package/migrate/client.js +1 -1
- package/migrate/utils/hash.d.ts +2 -4
- package/migrate/utils/hash.js +4 -8
- package/modules/modules.d.ts +1 -1
- package/modules/modules.js +1 -1
- package/package.json +4 -2
- package/packaging/package.js +1 -1
- package/rebundle/module.js +1 -1
- package/rebundle/rebundle.js +2 -2
- package/rebundle/types.d.ts +1 -1
- package/rebundle/workspace.js +1 -1
- package/refactor/rename.d.ts +2 -8
- package/refactor/rename.js +6 -29
- package/resolution/deps.d.ts +1 -1
- package/resolution/deps.js +2 -2
- package/resolution/resolve.js +2 -2
- package/slice/slice.d.ts +1 -1
- package/slice/slice.js +7 -32
- package/slice/types.d.ts +1 -1
- package/workspace/minimal.d.ts +1 -1
- package/esm/files/extension/index.js +0 -3
- package/esm/files/extension/reader.js +0 -79
- package/esm/files/extension/writer.js +0 -99
- package/esm/files/index.js +0 -6
- package/esm/files/plan/generator.js +0 -82
- package/esm/files/plan/index.js +0 -5
- package/esm/files/plan/parser.js +0 -297
- package/esm/files/plan/validators.js +0 -181
- package/esm/files/plan/writer.js +0 -142
- package/esm/files/sql/header.js +0 -259
- package/esm/files/sql/index.js +0 -2
- package/esm/files/sql/writer.js +0 -107
- package/esm/files/sql-scripts/index.js +0 -2
- package/esm/files/sql-scripts/reader.js +0 -19
- package/esm/files/types/index.js +0 -1
- package/esm/files/types/package.js +0 -1
- package/esm/utils/author.js +0 -11
- package/files/extension/index.d.ts +0 -2
- package/files/extension/index.js +0 -19
- package/files/extension/reader.d.ts +0 -24
- package/files/extension/reader.js +0 -86
- package/files/extension/writer.d.ts +0 -48
- package/files/extension/writer.js +0 -107
- package/files/index.d.ts +0 -5
- package/files/index.js +0 -22
- package/files/plan/generator.d.ts +0 -23
- package/files/plan/generator.js +0 -90
- package/files/plan/index.d.ts +0 -4
- package/files/plan/index.js +0 -21
- package/files/plan/parser.d.ts +0 -28
- package/files/plan/parser.js +0 -304
- package/files/plan/validators.d.ts +0 -52
- package/files/plan/validators.js +0 -187
- package/files/plan/writer.d.ts +0 -27
- package/files/plan/writer.js +0 -152
- package/files/sql/header.d.ts +0 -114
- package/files/sql/header.js +0 -266
- package/files/sql/index.d.ts +0 -2
- package/files/sql/index.js +0 -18
- package/files/sql/writer.d.ts +0 -12
- package/files/sql/writer.js +0 -114
- package/files/sql-scripts/index.d.ts +0 -1
- package/files/sql-scripts/index.js +0 -18
- package/files/sql-scripts/reader.d.ts +0 -8
- package/files/sql-scripts/reader.js +0 -23
- package/files/types/index.d.ts +0 -46
- package/files/types/index.js +0 -17
- package/files/types/package.d.ts +0 -20
- package/files/types/package.js +0 -2
- package/utils/author.d.ts +0 -5
- package/utils/author.js +0 -14
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Validators for Sqitch change and tag names according to the spec:
|
|
3
|
-
* https://sqitch.org/docs/manual/sqitchchanges/
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Validate a change name according to Sqitch rules:
|
|
7
|
-
* - ≥1 character
|
|
8
|
-
* - Cannot contain whitespace
|
|
9
|
-
* - First and last characters must not be punctuation (except _)
|
|
10
|
-
* - Must not end in ~, ^, /, = or % followed by digits
|
|
11
|
-
* - Disallowed characters anywhere: :, @, #, \
|
|
12
|
-
*/
|
|
13
|
-
export declare function isValidChangeName(name: string): boolean;
|
|
14
|
-
/**
|
|
15
|
-
* Validate a tag name according to Sqitch rules:
|
|
16
|
-
* - Same as change name rules
|
|
17
|
-
* - Additionally, must not contain /
|
|
18
|
-
*/
|
|
19
|
-
export declare function isValidTagName(name: string): boolean;
|
|
20
|
-
/**
|
|
21
|
-
* Parse a reference that might include project qualifier and/or tag
|
|
22
|
-
* Examples:
|
|
23
|
-
* - "users_table"
|
|
24
|
-
* - "@v1.0"
|
|
25
|
-
* - "users_table@v1.0"
|
|
26
|
-
* - "otherproj:users_table"
|
|
27
|
-
* - "otherproj:@v1.2"
|
|
28
|
-
* - "otherproj:users_table@v1.2"
|
|
29
|
-
* - "40763784148fa190d75bad036730ef44d1c2eac6"
|
|
30
|
-
* - "project:40763784148fa190d75bad036730ef44d1c2eac6"
|
|
31
|
-
*/
|
|
32
|
-
export interface ParsedReference {
|
|
33
|
-
package?: string;
|
|
34
|
-
change?: string;
|
|
35
|
-
tag?: string;
|
|
36
|
-
sha1?: string;
|
|
37
|
-
symbolic?: 'HEAD' | 'ROOT';
|
|
38
|
-
relative?: {
|
|
39
|
-
base: string;
|
|
40
|
-
direction: '^' | '~';
|
|
41
|
-
count: number;
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Parse a reference string into its components
|
|
46
|
-
*/
|
|
47
|
-
export declare function parseReference(ref: string): ParsedReference | null;
|
|
48
|
-
/**
|
|
49
|
-
* Validate a dependency reference
|
|
50
|
-
* Dependencies can be any valid reference format
|
|
51
|
-
*/
|
|
52
|
-
export declare function isValidDependency(dep: string): boolean;
|
package/files/plan/validators.js
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Validators for Sqitch change and tag names according to the spec:
|
|
4
|
-
* https://sqitch.org/docs/manual/sqitchchanges/
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.isValidChangeName = isValidChangeName;
|
|
8
|
-
exports.isValidTagName = isValidTagName;
|
|
9
|
-
exports.parseReference = parseReference;
|
|
10
|
-
exports.isValidDependency = isValidDependency;
|
|
11
|
-
/**
|
|
12
|
-
* Check if a character is punctuation (excluding underscore)
|
|
13
|
-
*/
|
|
14
|
-
function isPunctuation(char) {
|
|
15
|
-
// Common punctuation marks, excluding underscore
|
|
16
|
-
const punctuation = /[!"#$%&'()*+,\-./:;<=>?@[\\\]^`{|}~]/;
|
|
17
|
-
return punctuation.test(char);
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Validate a change name according to Sqitch rules:
|
|
21
|
-
* - ≥1 character
|
|
22
|
-
* - Cannot contain whitespace
|
|
23
|
-
* - First and last characters must not be punctuation (except _)
|
|
24
|
-
* - Must not end in ~, ^, /, = or % followed by digits
|
|
25
|
-
* - Disallowed characters anywhere: :, @, #, \
|
|
26
|
-
*/
|
|
27
|
-
function isValidChangeName(name) {
|
|
28
|
-
if (!name || name.length === 0) {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
// Check for whitespace
|
|
32
|
-
if (/\s/.test(name)) {
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
// Check for disallowed characters anywhere
|
|
36
|
-
if (/[:@#\\]/.test(name)) {
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
// Check first character - must not be punctuation except underscore
|
|
40
|
-
const firstChar = name[0];
|
|
41
|
-
if (firstChar !== '_' && isPunctuation(firstChar)) {
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
// Check last character - must not be punctuation except underscore
|
|
45
|
-
const lastChar = name[name.length - 1];
|
|
46
|
-
if (lastChar !== '_' && isPunctuation(lastChar)) {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
// Check for endings like ~N, ^N, /N, =N, %N where N is digits
|
|
50
|
-
if (/[~^/=%]\d+$/.test(name)) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Validate a tag name according to Sqitch rules:
|
|
57
|
-
* - Same as change name rules
|
|
58
|
-
* - Additionally, must not contain /
|
|
59
|
-
*/
|
|
60
|
-
function isValidTagName(name) {
|
|
61
|
-
if (!isValidChangeName(name)) {
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
// Tags must not contain /
|
|
65
|
-
if (name.includes('/')) {
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
return true;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Check if a string is a valid SHA1 hash (40 hex characters)
|
|
72
|
-
*/
|
|
73
|
-
function isSHA1(str) {
|
|
74
|
-
return /^[0-9a-f]{40}$/i.test(str);
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Parse a reference string into its components
|
|
78
|
-
*/
|
|
79
|
-
function parseReference(ref) {
|
|
80
|
-
if (!ref) {
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
const result = {};
|
|
84
|
-
// Check for package qualifier
|
|
85
|
-
let workingRef = ref;
|
|
86
|
-
const colonIndex = ref.indexOf(':');
|
|
87
|
-
if (colonIndex > 0) {
|
|
88
|
-
const projectPart = ref.substring(0, colonIndex);
|
|
89
|
-
const remainingPart = ref.substring(colonIndex + 1);
|
|
90
|
-
// Check if this is actually a package qualifier or just a colon in the name
|
|
91
|
-
// Package names should be valid identifiers (alphanumeric, dash, underscore)
|
|
92
|
-
// Also check that the remaining part doesn't have more colons
|
|
93
|
-
if (/^[a-zA-Z0-9_-]+$/.test(projectPart) &&
|
|
94
|
-
remainingPart.length > 0 &&
|
|
95
|
-
remainingPart.indexOf(':') === -1) {
|
|
96
|
-
result.package = projectPart;
|
|
97
|
-
workingRef = remainingPart;
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
// Not a valid package qualifier, treat the whole thing as a reference
|
|
101
|
-
workingRef = ref;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
// Check for symbolic references
|
|
105
|
-
if (workingRef === 'HEAD' || workingRef === '@HEAD') {
|
|
106
|
-
result.symbolic = 'HEAD';
|
|
107
|
-
return result;
|
|
108
|
-
}
|
|
109
|
-
if (workingRef === 'ROOT' || workingRef === '@ROOT') {
|
|
110
|
-
result.symbolic = 'ROOT';
|
|
111
|
-
return result;
|
|
112
|
-
}
|
|
113
|
-
// Check for relative references (e.g., HEAD^, @beta~2, HEAD^^)
|
|
114
|
-
// Handle multiple ^ characters
|
|
115
|
-
const multiCaretMatch = workingRef.match(/^(.+?)(\^+)$/);
|
|
116
|
-
if (multiCaretMatch) {
|
|
117
|
-
const [, base, carets] = multiCaretMatch;
|
|
118
|
-
result.relative = {
|
|
119
|
-
base: base, // Keep the original base including @ prefix
|
|
120
|
-
direction: '^',
|
|
121
|
-
count: carets.length
|
|
122
|
-
};
|
|
123
|
-
return result;
|
|
124
|
-
}
|
|
125
|
-
// Handle ^N or ~N format
|
|
126
|
-
const relativeMatch = workingRef.match(/^(.+?)([~^])(\d+)$/);
|
|
127
|
-
if (relativeMatch) {
|
|
128
|
-
const [, base, direction, countStr] = relativeMatch;
|
|
129
|
-
const count = parseInt(countStr, 10);
|
|
130
|
-
result.relative = {
|
|
131
|
-
base: base, // Keep the original base including @ prefix
|
|
132
|
-
direction: direction,
|
|
133
|
-
count
|
|
134
|
-
};
|
|
135
|
-
return result;
|
|
136
|
-
}
|
|
137
|
-
// Handle single ^ or ~ without number
|
|
138
|
-
const singleRelativeMatch = workingRef.match(/^(.+?)([~^])$/);
|
|
139
|
-
if (singleRelativeMatch) {
|
|
140
|
-
const [, base, direction] = singleRelativeMatch;
|
|
141
|
-
result.relative = {
|
|
142
|
-
base: base, // Keep the original base including @ prefix
|
|
143
|
-
direction: direction,
|
|
144
|
-
count: 1
|
|
145
|
-
};
|
|
146
|
-
return result;
|
|
147
|
-
}
|
|
148
|
-
// Check if it's a SHA1
|
|
149
|
-
if (isSHA1(workingRef)) {
|
|
150
|
-
result.sha1 = workingRef;
|
|
151
|
-
return result;
|
|
152
|
-
}
|
|
153
|
-
// Check for tag reference (starts with @)
|
|
154
|
-
if (workingRef.startsWith('@')) {
|
|
155
|
-
const tagName = workingRef.substring(1);
|
|
156
|
-
if (isValidTagName(tagName)) {
|
|
157
|
-
result.tag = tagName;
|
|
158
|
-
return result;
|
|
159
|
-
}
|
|
160
|
-
return null; // Invalid tag name
|
|
161
|
-
}
|
|
162
|
-
// Check for change@tag format
|
|
163
|
-
const atIndex = workingRef.indexOf('@');
|
|
164
|
-
if (atIndex > 0) {
|
|
165
|
-
const changeName = workingRef.substring(0, atIndex);
|
|
166
|
-
const tagName = workingRef.substring(atIndex + 1);
|
|
167
|
-
if (isValidChangeName(changeName) && isValidTagName(tagName)) {
|
|
168
|
-
result.change = changeName;
|
|
169
|
-
result.tag = tagName;
|
|
170
|
-
return result;
|
|
171
|
-
}
|
|
172
|
-
return null; // Invalid change or tag name
|
|
173
|
-
}
|
|
174
|
-
// Must be a plain change name
|
|
175
|
-
if (isValidChangeName(workingRef)) {
|
|
176
|
-
result.change = workingRef;
|
|
177
|
-
return result;
|
|
178
|
-
}
|
|
179
|
-
return null; // Invalid reference
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* Validate a dependency reference
|
|
183
|
-
* Dependencies can be any valid reference format
|
|
184
|
-
*/
|
|
185
|
-
function isValidDependency(dep) {
|
|
186
|
-
return parseReference(dep) !== null;
|
|
187
|
-
}
|
package/files/plan/writer.d.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Change, ExtendedPlanFile, PgpmRow, Tag } from '../types';
|
|
2
|
-
export interface PlanWriteOptions {
|
|
3
|
-
outdir: string;
|
|
4
|
-
name: string;
|
|
5
|
-
replacer: (str: string) => string;
|
|
6
|
-
author?: string;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Write a PGPM plan file based on the provided rows
|
|
10
|
-
*/
|
|
11
|
-
export declare function writePgpmPlan(rows: PgpmRow[], opts: PlanWriteOptions): void;
|
|
12
|
-
/**
|
|
13
|
-
* Write a plan file with the provided content
|
|
14
|
-
*/
|
|
15
|
-
export declare function writePlanFile(planPath: string, plan: ExtendedPlanFile): void;
|
|
16
|
-
/**
|
|
17
|
-
* Generate content for a plan file
|
|
18
|
-
*/
|
|
19
|
-
export declare function generatePlanFileContent(plan: ExtendedPlanFile): string;
|
|
20
|
-
/**
|
|
21
|
-
* Generate a line for a change in a plan file
|
|
22
|
-
*/
|
|
23
|
-
export declare function generateChangeLineContent(change: Change, changeOrder?: Map<string, number>): string;
|
|
24
|
-
/**
|
|
25
|
-
* Generate a line for a tag in a plan file
|
|
26
|
-
*/
|
|
27
|
-
export declare function generateTagLineContent(tag: Tag): string;
|
package/files/plan/writer.js
DELETED
|
@@ -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
|
-
}
|
package/files/sql/header.d.ts
DELETED
|
@@ -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[];
|