@pgpmjs/core 5.0.0 → 5.1.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/export/export-meta.js +0 -18
- package/esm/export/export-migrations.js +0 -2
- package/esm/index.js +1 -0
- package/esm/slice/index.js +3 -0
- package/esm/slice/output.js +117 -0
- package/esm/slice/slice.js +520 -0
- package/esm/slice/types.js +1 -0
- package/export/export-meta.js +0 -18
- package/export/export-migrations.js +0 -2
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +3 -2
- package/slice/index.d.ts +3 -0
- package/slice/index.js +19 -0
- package/slice/output.d.ts +22 -0
- package/slice/output.js +124 -0
- package/slice/slice.d.ts +59 -0
- package/slice/slice.js +536 -0
- package/slice/types.d.ts +133 -0
- package/slice/types.js +2 -0
package/export/export-meta.js
CHANGED
|
@@ -94,14 +94,6 @@ const config = {
|
|
|
94
94
|
hash: 'uuid'
|
|
95
95
|
}
|
|
96
96
|
},
|
|
97
|
-
database_extension: {
|
|
98
|
-
schema: 'metaschema_public',
|
|
99
|
-
table: 'database_extension',
|
|
100
|
-
fields: {
|
|
101
|
-
name: 'text',
|
|
102
|
-
database_id: 'uuid'
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
97
|
schema: {
|
|
106
98
|
schema: 'metaschema_public',
|
|
107
99
|
table: 'schema',
|
|
@@ -432,16 +424,6 @@ const config = {
|
|
|
432
424
|
data: 'jsonb'
|
|
433
425
|
}
|
|
434
426
|
},
|
|
435
|
-
api_extensions: {
|
|
436
|
-
schema: 'services_public',
|
|
437
|
-
table: 'api_extensions',
|
|
438
|
-
fields: {
|
|
439
|
-
id: 'uuid',
|
|
440
|
-
database_id: 'uuid',
|
|
441
|
-
api_id: 'uuid',
|
|
442
|
-
schema_name: 'text'
|
|
443
|
-
}
|
|
444
|
-
},
|
|
445
427
|
api_schemas: {
|
|
446
428
|
schema: 'services_public',
|
|
447
429
|
table: 'api_schemas',
|
|
@@ -218,7 +218,6 @@ SET session_replication_role TO DEFAULT;`;
|
|
|
218
218
|
// Tables that depend on 'database' being inserted first
|
|
219
219
|
const tableOrder = [
|
|
220
220
|
'database',
|
|
221
|
-
'database_extension',
|
|
222
221
|
'schema',
|
|
223
222
|
'table',
|
|
224
223
|
'field',
|
|
@@ -244,7 +243,6 @@ SET session_replication_role TO DEFAULT;`;
|
|
|
244
243
|
'site_themes',
|
|
245
244
|
'site_metadata',
|
|
246
245
|
'api_modules',
|
|
247
|
-
'api_extensions',
|
|
248
246
|
'api_schemas',
|
|
249
247
|
'rls_module',
|
|
250
248
|
'user_auth_module',
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -18,6 +18,7 @@ exports.withTransaction = exports.executeQuery = exports.hashString = exports.ha
|
|
|
18
18
|
__exportStar(require("./core/class/pgpm"), exports);
|
|
19
19
|
__exportStar(require("./export/export-meta"), exports);
|
|
20
20
|
__exportStar(require("./export/export-migrations"), exports);
|
|
21
|
+
__exportStar(require("./slice"), exports);
|
|
21
22
|
__exportStar(require("./extensions/extensions"), exports);
|
|
22
23
|
__exportStar(require("./modules/modules"), exports);
|
|
23
24
|
__exportStar(require("./packaging/package"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pgpmjs/core",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
5
|
"description": "PGPM Package and Migration Tools",
|
|
6
6
|
"main": "index.js",
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"genomic": "^5.3.0",
|
|
57
57
|
"glob": "^13.0.0",
|
|
58
58
|
"komoji": "^0.8.0",
|
|
59
|
+
"minimatch": "^10.1.1",
|
|
59
60
|
"parse-package-name": "^1.0.0",
|
|
60
61
|
"pg": "^8.17.1",
|
|
61
62
|
"pg-cache": "^2.0.0",
|
|
@@ -64,5 +65,5 @@
|
|
|
64
65
|
"pgsql-parser": "^17.9.11",
|
|
65
66
|
"yanse": "^0.2.0"
|
|
66
67
|
},
|
|
67
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "20d7e992348542531e73f20c0fd084decec86325"
|
|
68
69
|
}
|
package/slice/index.d.ts
ADDED
package/slice/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
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("./types"), exports);
|
|
18
|
+
__exportStar(require("./slice"), exports);
|
|
19
|
+
__exportStar(require("./output"), exports);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SliceResult } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Options for writing sliced packages to disk
|
|
4
|
+
*/
|
|
5
|
+
export interface WriteSliceOptions {
|
|
6
|
+
/** Base output directory */
|
|
7
|
+
outputDir: string;
|
|
8
|
+
/** Whether to overwrite existing packages */
|
|
9
|
+
overwrite?: boolean;
|
|
10
|
+
/** Whether to copy SQL files from source */
|
|
11
|
+
copySourceFiles?: boolean;
|
|
12
|
+
/** Source directory containing deploy/revert/verify folders */
|
|
13
|
+
sourceDir?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Write sliced packages to disk
|
|
17
|
+
*/
|
|
18
|
+
export declare function writeSliceResult(result: SliceResult, options: WriteSliceOptions): void;
|
|
19
|
+
/**
|
|
20
|
+
* Generate a dry-run report of what would be created
|
|
21
|
+
*/
|
|
22
|
+
export declare function generateDryRunReport(result: SliceResult): string;
|
package/slice/output.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
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.writeSliceResult = writeSliceResult;
|
|
7
|
+
exports.generateDryRunReport = generateDryRunReport;
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
/**
|
|
11
|
+
* Write sliced packages to disk
|
|
12
|
+
*/
|
|
13
|
+
function writeSliceResult(result, options) {
|
|
14
|
+
const { outputDir, overwrite = false, copySourceFiles = false, sourceDir } = options;
|
|
15
|
+
// Create output directory
|
|
16
|
+
fs_1.default.mkdirSync(outputDir, { recursive: true });
|
|
17
|
+
// Write each package
|
|
18
|
+
for (const pkg of result.packages) {
|
|
19
|
+
writePackage(pkg, outputDir, overwrite, copySourceFiles, sourceDir);
|
|
20
|
+
}
|
|
21
|
+
// Write workspace manifest
|
|
22
|
+
const manifestPath = path_1.default.join(outputDir, 'pgpm-workspace.json');
|
|
23
|
+
const manifestContent = JSON.stringify({
|
|
24
|
+
packages: result.workspace.packages.map(p => `packages/${p}`),
|
|
25
|
+
slicing: {
|
|
26
|
+
deployOrder: result.workspace.deployOrder,
|
|
27
|
+
dependencies: result.workspace.dependencies
|
|
28
|
+
},
|
|
29
|
+
stats: result.stats
|
|
30
|
+
}, null, 2);
|
|
31
|
+
fs_1.default.writeFileSync(manifestPath, manifestContent);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Write a single package to disk
|
|
35
|
+
*/
|
|
36
|
+
function writePackage(pkg, outputDir, overwrite, copySourceFiles, sourceDir) {
|
|
37
|
+
const pkgDir = path_1.default.join(outputDir, 'packages', pkg.name);
|
|
38
|
+
// Check if package already exists
|
|
39
|
+
if (fs_1.default.existsSync(pkgDir) && !overwrite) {
|
|
40
|
+
throw new Error(`Package directory already exists: ${pkgDir}. Use --overwrite to replace.`);
|
|
41
|
+
}
|
|
42
|
+
// Create package directory structure
|
|
43
|
+
fs_1.default.mkdirSync(pkgDir, { recursive: true });
|
|
44
|
+
fs_1.default.mkdirSync(path_1.default.join(pkgDir, 'deploy'), { recursive: true });
|
|
45
|
+
fs_1.default.mkdirSync(path_1.default.join(pkgDir, 'revert'), { recursive: true });
|
|
46
|
+
fs_1.default.mkdirSync(path_1.default.join(pkgDir, 'verify'), { recursive: true });
|
|
47
|
+
// Write plan file
|
|
48
|
+
fs_1.default.writeFileSync(path_1.default.join(pkgDir, 'pgpm.plan'), pkg.planContent);
|
|
49
|
+
// Write control file
|
|
50
|
+
fs_1.default.writeFileSync(path_1.default.join(pkgDir, `${pkg.name}.control`), pkg.controlContent);
|
|
51
|
+
// Copy SQL files if requested
|
|
52
|
+
if (copySourceFiles && sourceDir) {
|
|
53
|
+
for (const change of pkg.changes) {
|
|
54
|
+
copyChangeFiles(change.name, sourceDir, pkgDir);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Copy deploy/revert/verify SQL files for a change
|
|
60
|
+
*/
|
|
61
|
+
function copyChangeFiles(changeName, sourceDir, targetDir) {
|
|
62
|
+
const types = ['deploy', 'revert', 'verify'];
|
|
63
|
+
for (const type of types) {
|
|
64
|
+
const sourceFile = path_1.default.join(sourceDir, type, `${changeName}.sql`);
|
|
65
|
+
const targetFile = path_1.default.join(targetDir, type, `${changeName}.sql`);
|
|
66
|
+
if (fs_1.default.existsSync(sourceFile)) {
|
|
67
|
+
// Create target directory if needed
|
|
68
|
+
const targetSubDir = path_1.default.dirname(targetFile);
|
|
69
|
+
fs_1.default.mkdirSync(targetSubDir, { recursive: true });
|
|
70
|
+
// Copy file
|
|
71
|
+
fs_1.default.copyFileSync(sourceFile, targetFile);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Generate a dry-run report of what would be created
|
|
77
|
+
*/
|
|
78
|
+
function generateDryRunReport(result) {
|
|
79
|
+
const lines = [];
|
|
80
|
+
lines.push('=== PGPM Slice Dry Run Report ===\n');
|
|
81
|
+
// Statistics
|
|
82
|
+
lines.push('Statistics:');
|
|
83
|
+
lines.push(` Total changes: ${result.stats.totalChanges}`);
|
|
84
|
+
lines.push(` Packages to create: ${result.stats.packagesCreated}`);
|
|
85
|
+
lines.push(` Internal edges: ${result.stats.internalEdges}`);
|
|
86
|
+
lines.push(` Cross-package edges: ${result.stats.crossPackageEdges}`);
|
|
87
|
+
lines.push(` Cross-package ratio: ${(result.stats.crossPackageRatio * 100).toFixed(1)}%`);
|
|
88
|
+
lines.push('');
|
|
89
|
+
// Warnings
|
|
90
|
+
if (result.warnings.length > 0) {
|
|
91
|
+
lines.push('Warnings:');
|
|
92
|
+
for (const warning of result.warnings) {
|
|
93
|
+
lines.push(` [${warning.type}] ${warning.message}`);
|
|
94
|
+
if (warning.suggestedAction) {
|
|
95
|
+
lines.push(` Suggestion: ${warning.suggestedAction}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
lines.push('');
|
|
99
|
+
}
|
|
100
|
+
// Deploy order
|
|
101
|
+
lines.push('Deploy Order:');
|
|
102
|
+
for (let i = 0; i < result.workspace.deployOrder.length; i++) {
|
|
103
|
+
const pkg = result.workspace.deployOrder[i];
|
|
104
|
+
const deps = result.workspace.dependencies[pkg] || [];
|
|
105
|
+
const depStr = deps.length > 0 ? ` (depends on: ${deps.join(', ')})` : '';
|
|
106
|
+
lines.push(` ${i + 1}. ${pkg}${depStr}`);
|
|
107
|
+
}
|
|
108
|
+
lines.push('');
|
|
109
|
+
// Package details
|
|
110
|
+
lines.push('Packages:');
|
|
111
|
+
for (const pkg of result.packages) {
|
|
112
|
+
lines.push(`\n ${pkg.name}/`);
|
|
113
|
+
lines.push(` Changes: ${pkg.changes.length}`);
|
|
114
|
+
lines.push(` Dependencies: ${pkg.packageDependencies.join(', ') || 'none'}`);
|
|
115
|
+
lines.push(' Contents:');
|
|
116
|
+
for (const change of pkg.changes.slice(0, 5)) {
|
|
117
|
+
lines.push(` - ${change.name}`);
|
|
118
|
+
}
|
|
119
|
+
if (pkg.changes.length > 5) {
|
|
120
|
+
lines.push(` ... and ${pkg.changes.length - 5} more`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return lines.join('\n');
|
|
124
|
+
}
|
package/slice/slice.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Change, Tag, ExtendedPlanFile } from '../files/types';
|
|
2
|
+
import { SliceConfig, SliceResult, DependencyGraph, PackageOutput, GroupingStrategy, PatternStrategy } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Build a dependency graph from a parsed plan file
|
|
5
|
+
*/
|
|
6
|
+
export declare function buildDependencyGraph(plan: ExtendedPlanFile): DependencyGraph;
|
|
7
|
+
/**
|
|
8
|
+
* Validate that the dependency graph is a DAG (no cycles)
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateDAG(graph: DependencyGraph): void;
|
|
11
|
+
/**
|
|
12
|
+
* Extract package name from a change path using folder-based strategy
|
|
13
|
+
*/
|
|
14
|
+
export declare function extractPackageFromPath(changeName: string, depth?: number, prefixToStrip?: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Find the matching package for a change using pattern-based strategy.
|
|
17
|
+
* Returns the first matching slice's package name, or undefined if no match.
|
|
18
|
+
*/
|
|
19
|
+
export declare function findMatchingPattern(changeName: string, strategy: PatternStrategy): string | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Assign changes to packages based on grouping strategy
|
|
22
|
+
*/
|
|
23
|
+
export declare function assignChangesToPackages(graph: DependencyGraph, strategy: GroupingStrategy, defaultPackage?: string): Map<string, Set<string>>;
|
|
24
|
+
/**
|
|
25
|
+
* Merge small packages into larger ones
|
|
26
|
+
*/
|
|
27
|
+
export declare function mergeSmallPackages(assignments: Map<string, Set<string>>, minChanges: number, defaultPackage?: string): Map<string, Set<string>>;
|
|
28
|
+
/**
|
|
29
|
+
* Build package-level dependency graph
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildPackageDependencies(graph: DependencyGraph, assignments: Map<string, Set<string>>): Map<string, Set<string>>;
|
|
32
|
+
/**
|
|
33
|
+
* Detect cycles in package dependency graph
|
|
34
|
+
*/
|
|
35
|
+
export declare function detectPackageCycle(deps: Map<string, Set<string>>): string[] | null;
|
|
36
|
+
/**
|
|
37
|
+
* Compute deployment order for packages (topological sort)
|
|
38
|
+
*/
|
|
39
|
+
export declare function computeDeployOrder(packageDeps: Map<string, Set<string>>): string[];
|
|
40
|
+
/**
|
|
41
|
+
* Topological sort of changes within a package
|
|
42
|
+
*/
|
|
43
|
+
export declare function topologicalSortWithinPackage(changes: Set<string>, graph: DependencyGraph): string[];
|
|
44
|
+
/**
|
|
45
|
+
* Generate plan file content for a package
|
|
46
|
+
*/
|
|
47
|
+
export declare function generatePlanContent(pkgName: string, entries: Change[], tags?: Tag[]): string;
|
|
48
|
+
/**
|
|
49
|
+
* Generate control file content for a package
|
|
50
|
+
*/
|
|
51
|
+
export declare function generateControlContent(pkgName: string, deps: Set<string>): string;
|
|
52
|
+
/**
|
|
53
|
+
* Generate a single package output
|
|
54
|
+
*/
|
|
55
|
+
export declare function generateSinglePackage(pkgName: string, changes: Set<string>, graph: DependencyGraph, changeToPackage: Map<string, string>, pkgDeps: Set<string>, useTagsForCrossPackageDeps?: boolean): PackageOutput;
|
|
56
|
+
/**
|
|
57
|
+
* Main slicing function
|
|
58
|
+
*/
|
|
59
|
+
export declare function slicePlan(config: SliceConfig): SliceResult;
|