@pgpmjs/core 3.0.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 (140) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +99 -0
  3. package/core/boilerplate-scanner.d.ts +41 -0
  4. package/core/boilerplate-scanner.js +106 -0
  5. package/core/boilerplate-types.d.ts +52 -0
  6. package/core/boilerplate-types.js +6 -0
  7. package/core/class/pgpm.d.ts +150 -0
  8. package/core/class/pgpm.js +1470 -0
  9. package/core/template-scaffold.d.ts +29 -0
  10. package/core/template-scaffold.js +168 -0
  11. package/esm/core/boilerplate-scanner.js +96 -0
  12. package/esm/core/boilerplate-types.js +5 -0
  13. package/esm/core/class/pgpm.js +1430 -0
  14. package/esm/core/template-scaffold.js +161 -0
  15. package/esm/export/export-meta.js +240 -0
  16. package/esm/export/export-migrations.js +180 -0
  17. package/esm/extensions/extensions.js +31 -0
  18. package/esm/files/extension/index.js +3 -0
  19. package/esm/files/extension/reader.js +79 -0
  20. package/esm/files/extension/writer.js +63 -0
  21. package/esm/files/index.js +6 -0
  22. package/esm/files/plan/generator.js +49 -0
  23. package/esm/files/plan/index.js +5 -0
  24. package/esm/files/plan/parser.js +296 -0
  25. package/esm/files/plan/validators.js +181 -0
  26. package/esm/files/plan/writer.js +114 -0
  27. package/esm/files/sql/index.js +1 -0
  28. package/esm/files/sql/writer.js +107 -0
  29. package/esm/files/sql-scripts/index.js +2 -0
  30. package/esm/files/sql-scripts/reader.js +19 -0
  31. package/esm/files/types/index.js +1 -0
  32. package/esm/files/types/package.js +1 -0
  33. package/esm/index.js +21 -0
  34. package/esm/init/client.js +144 -0
  35. package/esm/init/sql/bootstrap-roles.sql +55 -0
  36. package/esm/init/sql/bootstrap-test-roles.sql +72 -0
  37. package/esm/migrate/clean.js +23 -0
  38. package/esm/migrate/client.js +551 -0
  39. package/esm/migrate/index.js +5 -0
  40. package/esm/migrate/sql/procedures.sql +258 -0
  41. package/esm/migrate/sql/schema.sql +37 -0
  42. package/esm/migrate/types.js +1 -0
  43. package/esm/migrate/utils/event-logger.js +28 -0
  44. package/esm/migrate/utils/hash.js +27 -0
  45. package/esm/migrate/utils/transaction.js +125 -0
  46. package/esm/modules/modules.js +49 -0
  47. package/esm/packaging/package.js +96 -0
  48. package/esm/packaging/transform.js +70 -0
  49. package/esm/projects/deploy.js +123 -0
  50. package/esm/projects/revert.js +75 -0
  51. package/esm/projects/verify.js +61 -0
  52. package/esm/resolution/deps.js +526 -0
  53. package/esm/resolution/resolve.js +101 -0
  54. package/esm/utils/debug.js +147 -0
  55. package/esm/utils/target-utils.js +37 -0
  56. package/esm/workspace/paths.js +43 -0
  57. package/esm/workspace/utils.js +31 -0
  58. package/export/export-meta.d.ts +8 -0
  59. package/export/export-meta.js +244 -0
  60. package/export/export-migrations.d.ts +17 -0
  61. package/export/export-migrations.js +187 -0
  62. package/extensions/extensions.d.ts +5 -0
  63. package/extensions/extensions.js +35 -0
  64. package/files/extension/index.d.ts +2 -0
  65. package/files/extension/index.js +19 -0
  66. package/files/extension/reader.d.ts +24 -0
  67. package/files/extension/reader.js +86 -0
  68. package/files/extension/writer.d.ts +39 -0
  69. package/files/extension/writer.js +70 -0
  70. package/files/index.d.ts +5 -0
  71. package/files/index.js +22 -0
  72. package/files/plan/generator.d.ts +22 -0
  73. package/files/plan/generator.js +57 -0
  74. package/files/plan/index.d.ts +4 -0
  75. package/files/plan/index.js +21 -0
  76. package/files/plan/parser.d.ts +27 -0
  77. package/files/plan/parser.js +303 -0
  78. package/files/plan/validators.d.ts +52 -0
  79. package/files/plan/validators.js +187 -0
  80. package/files/plan/writer.d.ts +27 -0
  81. package/files/plan/writer.js +124 -0
  82. package/files/sql/index.d.ts +1 -0
  83. package/files/sql/index.js +17 -0
  84. package/files/sql/writer.d.ts +12 -0
  85. package/files/sql/writer.js +114 -0
  86. package/files/sql-scripts/index.d.ts +1 -0
  87. package/files/sql-scripts/index.js +18 -0
  88. package/files/sql-scripts/reader.d.ts +8 -0
  89. package/files/sql-scripts/reader.js +23 -0
  90. package/files/types/index.d.ts +46 -0
  91. package/files/types/index.js +17 -0
  92. package/files/types/package.d.ts +20 -0
  93. package/files/types/package.js +2 -0
  94. package/index.d.ts +21 -0
  95. package/index.js +45 -0
  96. package/init/client.d.ts +26 -0
  97. package/init/client.js +148 -0
  98. package/init/sql/bootstrap-roles.sql +55 -0
  99. package/init/sql/bootstrap-test-roles.sql +72 -0
  100. package/migrate/clean.d.ts +1 -0
  101. package/migrate/clean.js +27 -0
  102. package/migrate/client.d.ts +80 -0
  103. package/migrate/client.js +555 -0
  104. package/migrate/index.d.ts +5 -0
  105. package/migrate/index.js +21 -0
  106. package/migrate/sql/procedures.sql +258 -0
  107. package/migrate/sql/schema.sql +37 -0
  108. package/migrate/types.d.ts +67 -0
  109. package/migrate/types.js +2 -0
  110. package/migrate/utils/event-logger.d.ts +13 -0
  111. package/migrate/utils/event-logger.js +32 -0
  112. package/migrate/utils/hash.d.ts +12 -0
  113. package/migrate/utils/hash.js +32 -0
  114. package/migrate/utils/transaction.d.ts +27 -0
  115. package/migrate/utils/transaction.js +129 -0
  116. package/modules/modules.d.ts +31 -0
  117. package/modules/modules.js +56 -0
  118. package/package.json +70 -0
  119. package/packaging/package.d.ts +19 -0
  120. package/packaging/package.js +102 -0
  121. package/packaging/transform.d.ts +22 -0
  122. package/packaging/transform.js +75 -0
  123. package/projects/deploy.d.ts +8 -0
  124. package/projects/deploy.js +160 -0
  125. package/projects/revert.d.ts +15 -0
  126. package/projects/revert.js +112 -0
  127. package/projects/verify.d.ts +8 -0
  128. package/projects/verify.js +98 -0
  129. package/resolution/deps.d.ts +57 -0
  130. package/resolution/deps.js +531 -0
  131. package/resolution/resolve.d.ts +37 -0
  132. package/resolution/resolve.js +107 -0
  133. package/utils/debug.d.ts +21 -0
  134. package/utils/debug.js +153 -0
  135. package/utils/target-utils.d.ts +5 -0
  136. package/utils/target-utils.js +40 -0
  137. package/workspace/paths.d.ts +14 -0
  138. package/workspace/paths.js +50 -0
  139. package/workspace/utils.d.ts +8 -0
  140. package/workspace/utils.js +36 -0
@@ -0,0 +1,187 @@
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.exportMigrations = void 0;
7
+ const fs_1 = require("fs");
8
+ const glob_1 = require("glob");
9
+ const komoji_1 = require("komoji");
10
+ const path_1 = __importDefault(require("path"));
11
+ const pg_cache_1 = require("pg-cache");
12
+ const files_1 = require("../files");
13
+ const export_meta_1 = require("./export-meta");
14
+ const exportMigrationsToDisk = async ({ project, options, database, databaseId, author, outdir, schema_names, extensionName, metaExtensionName }) => {
15
+ outdir = outdir + '/';
16
+ const pgPool = (0, pg_cache_1.getPgPool)({
17
+ ...options.pg,
18
+ database
19
+ });
20
+ const db = await pgPool.query(`select * from collections_public.database where id=$1`, [databaseId]);
21
+ const schemas = await pgPool.query(`select * from collections_public.schema where database_id=$1`, [databaseId]);
22
+ if (!db?.rows?.length) {
23
+ console.log('NO DATABASES.');
24
+ return;
25
+ }
26
+ if (!schemas?.rows?.length) {
27
+ console.log('NO SCHEMAS.');
28
+ return;
29
+ }
30
+ const name = extensionName || db.rows[0].name;
31
+ const { replace, replacer } = makeReplacer({
32
+ schemas: schemas.rows.filter((schema) => schema_names.includes(schema.schema_name)),
33
+ name
34
+ });
35
+ const results = await pgPool.query(`select * from db_migrate.sql_actions order by id`);
36
+ const opts = {
37
+ name,
38
+ replacer,
39
+ outdir,
40
+ author
41
+ };
42
+ if (results?.rows?.length > 0) {
43
+ await preparePackage({
44
+ project,
45
+ author,
46
+ outdir,
47
+ name,
48
+ extensions: [
49
+ 'plpgsql',
50
+ 'uuid-ossp',
51
+ 'citext',
52
+ 'pgcrypto',
53
+ 'btree_gist',
54
+ 'postgis',
55
+ 'hstore',
56
+ 'db-meta-schema',
57
+ 'launchql-inflection',
58
+ 'launchql-uuid',
59
+ 'launchql-utils',
60
+ 'launchql-database-jobs',
61
+ 'launchql-jwt-claims',
62
+ 'launchql-stamps',
63
+ 'launchql-base32',
64
+ 'launchql-totp',
65
+ 'launchql-types',
66
+ 'launchql-default-roles'
67
+ ]
68
+ });
69
+ (0, files_1.writeSqitchPlan)(results.rows, opts);
70
+ (0, files_1.writeSqitchFiles)(results.rows, opts);
71
+ let meta = await (0, export_meta_1.exportMeta)({
72
+ opts: options,
73
+ dbname: database,
74
+ database_id: databaseId
75
+ });
76
+ meta = replacer(meta);
77
+ await preparePackage({
78
+ project,
79
+ author,
80
+ outdir,
81
+ extensions: ['plpgsql', 'db-meta-schema', 'db-meta-modules'],
82
+ name: metaExtensionName
83
+ });
84
+ const metaReplacer = makeReplacer({
85
+ schemas: schemas.rows.filter((schema) => schema_names.includes(schema.schema_name)),
86
+ name: metaExtensionName
87
+ });
88
+ const metaPackage = [
89
+ {
90
+ deps: [],
91
+ deploy: 'migrate/meta',
92
+ content: `SET session_replication_role TO replica;
93
+ -- using replica in case we are deploying triggers to collections_public
94
+
95
+ -- unaccent, postgis affected and require grants
96
+ GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public to public;
97
+
98
+ DO $LQLMIGRATION$
99
+ DECLARE
100
+ BEGIN
101
+
102
+ EXECUTE format('GRANT CONNECT ON DATABASE %I TO %I', current_database(), 'app_user');
103
+ EXECUTE format('GRANT CONNECT ON DATABASE %I TO %I', current_database(), 'app_admin');
104
+
105
+ END;
106
+ $LQLMIGRATION$;
107
+
108
+ ${meta}
109
+
110
+ UPDATE meta_public.apis
111
+ SET dbname = current_database() WHERE TRUE;
112
+
113
+ UPDATE meta_public.sites
114
+ SET dbname = current_database() WHERE TRUE;
115
+
116
+ SET session_replication_role TO DEFAULT;
117
+ `
118
+ }
119
+ ];
120
+ opts.replacer = metaReplacer.replacer;
121
+ opts.name = metaExtensionName;
122
+ (0, files_1.writeSqitchPlan)(metaPackage, opts);
123
+ (0, files_1.writeSqitchFiles)(metaPackage, opts);
124
+ }
125
+ pgPool.end();
126
+ };
127
+ const exportMigrations = async ({ project, options, dbInfo, author, outdir, schema_names, extensionName, metaExtensionName }) => {
128
+ for (let v = 0; v < dbInfo.database_ids.length; v++) {
129
+ const databaseId = dbInfo.database_ids[v];
130
+ await exportMigrationsToDisk({
131
+ project,
132
+ options,
133
+ extensionName,
134
+ metaExtensionName,
135
+ database: dbInfo.dbname,
136
+ databaseId,
137
+ schema_names,
138
+ author,
139
+ outdir
140
+ });
141
+ }
142
+ };
143
+ exports.exportMigrations = exportMigrations;
144
+ /**
145
+ * Creates a Sqitch package directory or resets the deploy/revert/verify directories if it exists.
146
+ */
147
+ const preparePackage = async ({ project, author, outdir, name, extensions }) => {
148
+ const curDir = process.cwd();
149
+ const sqitchDir = path_1.default.resolve(path_1.default.join(outdir, name));
150
+ (0, fs_1.mkdirSync)(sqitchDir, { recursive: true });
151
+ process.chdir(sqitchDir);
152
+ const plan = (0, glob_1.sync)(path_1.default.join(sqitchDir, 'pgpm.plan'));
153
+ if (!plan.length) {
154
+ await project.initModule({
155
+ name,
156
+ description: name,
157
+ author,
158
+ extensions,
159
+ });
160
+ }
161
+ else {
162
+ (0, fs_1.rmSync)(path_1.default.resolve(sqitchDir, 'deploy'), { recursive: true, force: true });
163
+ (0, fs_1.rmSync)(path_1.default.resolve(sqitchDir, 'revert'), { recursive: true, force: true });
164
+ (0, fs_1.rmSync)(path_1.default.resolve(sqitchDir, 'verify'), { recursive: true, force: true });
165
+ }
166
+ process.chdir(curDir);
167
+ };
168
+ /**
169
+ * Generates a function for replacing schema names and extension names in strings.
170
+ */
171
+ const makeReplacer = ({ schemas, name }) => {
172
+ const replacements = ['launchql-extension-name', name];
173
+ const schemaReplacers = schemas.map((schema) => [
174
+ schema.schema_name,
175
+ (0, komoji_1.toSnakeCase)(`${name}_${schema.name}`)
176
+ ]);
177
+ const replace = [...schemaReplacers, replacements].map(([from, to]) => [new RegExp(from, 'g'), to]);
178
+ const replacer = (str, n = 0) => {
179
+ if (!str)
180
+ return '';
181
+ if (replace[n] && replace[n].length === 2) {
182
+ return replacer(str.replace(replace[n][0], replace[n][1]), n + 1);
183
+ }
184
+ return str;
185
+ };
186
+ return { replacer, replace };
187
+ };
@@ -0,0 +1,5 @@
1
+ import { ModuleMap } from '../modules/modules';
2
+ /**
3
+ * Get the list of available extensions, including predefined core extensions.
4
+ */
5
+ export declare const getAvailableExtensions: (modules: ModuleMap) => string[];
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAvailableExtensions = void 0;
4
+ /**
5
+ * Get the list of available extensions, including predefined core extensions.
6
+ */
7
+ const getAvailableExtensions = (modules) => {
8
+ const coreExtensions = [
9
+ 'address_standardizer',
10
+ 'address_standardizer_data_us',
11
+ 'bloom',
12
+ 'btree_gin',
13
+ 'btree_gist',
14
+ 'citext',
15
+ 'hstore',
16
+ 'intarray',
17
+ 'pg_trgm',
18
+ 'pgcrypto',
19
+ 'plpgsql',
20
+ 'plperl',
21
+ 'plv8',
22
+ 'postgis_tiger_geocoder',
23
+ 'postgis_topology',
24
+ 'postgis',
25
+ 'postgres_fdw',
26
+ 'unaccent',
27
+ 'uuid-ossp',
28
+ ];
29
+ return Object.keys(modules).reduce((acc, module) => {
30
+ if (!acc.includes(module))
31
+ acc.push(module);
32
+ return acc;
33
+ }, [...coreExtensions]);
34
+ };
35
+ exports.getAvailableExtensions = getAvailableExtensions;
@@ -0,0 +1,2 @@
1
+ export * from './reader';
2
+ export * from './writer';
@@ -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
+ // Re-export all extension functionality
18
+ __exportStar(require("./reader"), exports);
19
+ __exportStar(require("./writer"), exports);
@@ -0,0 +1,24 @@
1
+ import { ExtensionInfo } from './writer';
2
+ export interface Module {
3
+ path: string;
4
+ requires: string[];
5
+ version: string;
6
+ }
7
+ /**
8
+ * Parse a .control file and extract its metadata.
9
+ * https://www.postgresql.org/docs/current/extend-extensions.html
10
+ */
11
+ export declare function parseControlFile(filePath: string, basePath: string): Module;
12
+ /**
13
+ * Parse the pgpm.plan file to get the extension name.
14
+ */
15
+ export declare const getExtensionName: (packageDir: string) => string;
16
+ /**
17
+ * Get detailed information about an extension in the specified directory.
18
+ */
19
+ export declare const getExtensionInfo: (packageDir: string) => ExtensionInfo;
20
+ /**
21
+ * Get a list of extensions required by an extension from its control file.
22
+ * Returns an empty array if the file doesn't exist or has no requires line.
23
+ */
24
+ export declare const getInstalledExtensions: (controlFilePath: string) => string[];
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getInstalledExtensions = exports.getExtensionInfo = exports.getExtensionName = void 0;
4
+ exports.parseControlFile = parseControlFile;
5
+ const fs_1 = require("fs");
6
+ const path_1 = require("path");
7
+ const plan_1 = require("../plan");
8
+ /**
9
+ * Parse a .control file and extract its metadata.
10
+ * https://www.postgresql.org/docs/current/extend-extensions.html
11
+ */
12
+ function parseControlFile(filePath, basePath) {
13
+ const contents = (0, fs_1.readFileSync)(filePath, 'utf-8');
14
+ const key = (0, path_1.basename)(filePath).split('.control')[0];
15
+ const requires = contents
16
+ .split('\n')
17
+ .find((line) => /^requires/.test(line))
18
+ ?.split('=')[1]
19
+ .split(',')
20
+ .map((req) => req.replace(/[\'\s]*/g, '').trim()) || [];
21
+ const version = contents
22
+ .split('\n')
23
+ .find((line) => /^default_version/.test(line))
24
+ ?.split('=')[1]
25
+ .replace(/[\']*/g, '')
26
+ .trim() || '';
27
+ return {
28
+ path: (0, path_1.dirname)((0, path_1.relative)(basePath, filePath)),
29
+ requires,
30
+ version,
31
+ };
32
+ }
33
+ /**
34
+ * Parse the pgpm.plan file to get the extension name.
35
+ */
36
+ const getExtensionName = (packageDir) => {
37
+ const planPath = `${packageDir}/pgpm.plan`;
38
+ const plan = (0, plan_1.parsePlanFileSimple)(planPath);
39
+ if (!plan.package) {
40
+ throw new Error('No package name found in pgpm.plan!');
41
+ }
42
+ return plan.package;
43
+ };
44
+ exports.getExtensionName = getExtensionName;
45
+ /**
46
+ * Get detailed information about an extension in the specified directory.
47
+ */
48
+ const getExtensionInfo = (packageDir) => {
49
+ const pkgPath = `${packageDir}/package.json`;
50
+ const pkg = require(pkgPath);
51
+ const extname = (0, exports.getExtensionName)(packageDir);
52
+ const version = pkg.version;
53
+ const Makefile = `${packageDir}/Makefile`;
54
+ const controlFile = `${packageDir}/${extname}.control`;
55
+ const sqlFile = `sql/${extname}--${version}.sql`;
56
+ return { extname, packageDir, version, Makefile, controlFile, sqlFile };
57
+ };
58
+ exports.getExtensionInfo = getExtensionInfo;
59
+ /**
60
+ * Get a list of extensions required by an extension from its control file.
61
+ * Returns an empty array if the file doesn't exist or has no requires line.
62
+ */
63
+ const getInstalledExtensions = (controlFilePath) => {
64
+ try {
65
+ const contents = (0, fs_1.readFileSync)(controlFilePath, 'utf-8');
66
+ const match = contents.match(/^\s*requires\s*=\s*'([^']*)'/m);
67
+ if (!match) {
68
+ return [];
69
+ }
70
+ const requiresValue = match[1];
71
+ if (!requiresValue || requiresValue.trim() === '') {
72
+ return [];
73
+ }
74
+ return requiresValue
75
+ .split(',')
76
+ .map((ext) => ext.trim())
77
+ .filter((ext) => ext.length > 0);
78
+ }
79
+ catch (e) {
80
+ if (e.code === 'ENOENT') {
81
+ return [];
82
+ }
83
+ throw new Error(`Error reading control file at ${controlFilePath}: ${e.message}`);
84
+ }
85
+ };
86
+ exports.getInstalledExtensions = getInstalledExtensions;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Write the Makefile for the extension.
3
+ */
4
+ export declare const writeExtensionMakefile: (outputPath: string, extname: string, version: string) => void;
5
+ /**
6
+ * Generate content for a .control file
7
+ * https://www.postgresql.org/docs/current/extend-extensions.html
8
+ */
9
+ export declare function generateControlFileContent(options: {
10
+ name: string;
11
+ version: string;
12
+ comment?: string;
13
+ requires?: string[];
14
+ default_version?: string;
15
+ relocatable?: boolean;
16
+ superuser?: boolean;
17
+ schema?: string;
18
+ module_pathname?: string;
19
+ }): string;
20
+ /**
21
+ * Write the control file for the extension.
22
+ */
23
+ export declare const writeExtensionControlFile: (outputPath: string, extname: string, extensions: string[], version: string) => void;
24
+ /**
25
+ * Interface for extension information
26
+ */
27
+ export interface ExtensionInfo {
28
+ extname: string;
29
+ packageDir: string;
30
+ version: string;
31
+ Makefile: string;
32
+ controlFile: string;
33
+ sqlFile: string;
34
+ }
35
+ /**
36
+ * Write control and Makefile for the extension with given data.
37
+ * If extInfo is not provided, it will be generated from packageDir.
38
+ */
39
+ export declare const writeExtensions: (packageDir: string, extensions: string[], extInfo?: ExtensionInfo) => void;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.writeExtensions = exports.writeExtensionControlFile = exports.writeExtensionMakefile = void 0;
4
+ exports.generateControlFileContent = generateControlFileContent;
5
+ const fs_1 = require("fs");
6
+ const reader_1 = require("./reader");
7
+ /**
8
+ * Write the Makefile for the extension.
9
+ */
10
+ const writeExtensionMakefile = (outputPath, extname, version) => {
11
+ const content = `EXTENSION = ${extname}
12
+ DATA = sql/${extname}--${version}.sql
13
+
14
+ PG_CONFIG = pg_config
15
+ PGXS := $(shell $(PG_CONFIG) --pgxs)
16
+ include $(PGXS)
17
+ `;
18
+ (0, fs_1.writeFileSync)(outputPath, content);
19
+ };
20
+ exports.writeExtensionMakefile = writeExtensionMakefile;
21
+ /**
22
+ * Generate content for a .control file
23
+ * https://www.postgresql.org/docs/current/extend-extensions.html
24
+ */
25
+ function generateControlFileContent(options) {
26
+ const { name, version, comment = `${name} extension`, requires = [], default_version = version, relocatable = false, superuser = false, schema, module_pathname } = options;
27
+ let content = `# ${name} extension
28
+ comment = '${comment}'
29
+ default_version = '${default_version}'
30
+ `;
31
+ if (module_pathname) {
32
+ content += `module_pathname = '${module_pathname}'\n`;
33
+ }
34
+ else {
35
+ content += `module_pathname = '$libdir/${name}'\n`;
36
+ }
37
+ if (requires.length > 0) {
38
+ content += `requires = '${requires.join(',')}'\n`;
39
+ }
40
+ content += `relocatable = ${relocatable}
41
+ superuser = ${superuser}\n`;
42
+ if (schema) {
43
+ content += `schema = ${schema}\n`;
44
+ }
45
+ return content;
46
+ }
47
+ /**
48
+ * Write the control file for the extension.
49
+ */
50
+ const writeExtensionControlFile = (outputPath, extname, extensions, version) => {
51
+ const content = generateControlFileContent({
52
+ name: extname,
53
+ version,
54
+ requires: extensions
55
+ });
56
+ (0, fs_1.writeFileSync)(outputPath, content);
57
+ };
58
+ exports.writeExtensionControlFile = writeExtensionControlFile;
59
+ /**
60
+ * Write control and Makefile for the extension with given data.
61
+ * If extInfo is not provided, it will be generated from packageDir.
62
+ */
63
+ const writeExtensions = (packageDir, extensions, extInfo) => {
64
+ // If extInfo is not provided, get it from packageDir
65
+ const info = extInfo || (0, reader_1.getExtensionInfo)(packageDir);
66
+ const { controlFile, Makefile, extname, version } = info;
67
+ (0, exports.writeExtensionControlFile)(controlFile, extname, extensions, version);
68
+ (0, exports.writeExtensionMakefile)(Makefile, extname, version);
69
+ };
70
+ exports.writeExtensions = writeExtensions;
@@ -0,0 +1,5 @@
1
+ export * from './extension';
2
+ export * from './plan';
3
+ export * from './sql';
4
+ export * from './sql-scripts';
5
+ export * from './types';
package/files/index.js ADDED
@@ -0,0 +1,22 @@
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
+ // Re-export all functionality from package-files
18
+ __exportStar(require("./extension"), exports);
19
+ __exportStar(require("./plan"), exports);
20
+ __exportStar(require("./sql"), exports);
21
+ __exportStar(require("./sql-scripts"), exports);
22
+ __exportStar(require("./types"), exports);
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Get a timestamp for the plan file
3
+ */
4
+ export declare function getNow(): string;
5
+ export interface PlanEntry {
6
+ change: string;
7
+ dependencies: string[];
8
+ comment?: string;
9
+ }
10
+ export interface GeneratePlanOptions {
11
+ moduleName: string;
12
+ uri?: string;
13
+ entries: PlanEntry[];
14
+ }
15
+ /**
16
+ * Generate a plan file content from structured data
17
+ */
18
+ export declare function generatePlan(options: GeneratePlanOptions): string;
19
+ /**
20
+ * Write a generated plan file to disk
21
+ */
22
+ export declare function writePlan(planPath: string, plan: string): void;
@@ -0,0 +1,57 @@
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.getNow = getNow;
7
+ exports.generatePlan = generatePlan;
8
+ exports.writePlan = writePlan;
9
+ const fs_1 = __importDefault(require("fs"));
10
+ /**
11
+ * Get a UTC timestamp string
12
+ */
13
+ function getUTCTimestamp(d = new Date()) {
14
+ return (d.getUTCFullYear() +
15
+ '-' + String(d.getUTCMonth() + 1).padStart(2, '0') +
16
+ '-' + String(d.getUTCDate()).padStart(2, '0') +
17
+ 'T' + String(d.getUTCHours()).padStart(2, '0') +
18
+ ':' + String(d.getUTCMinutes()).padStart(2, '0') +
19
+ ':' + String(d.getUTCSeconds()).padStart(2, '0') +
20
+ 'Z');
21
+ }
22
+ /**
23
+ * Get a timestamp for the plan file
24
+ */
25
+ function getNow() {
26
+ return process.env.NODE_ENV === 'test'
27
+ ? getUTCTimestamp(new Date('2017-08-11T08:11:51Z'))
28
+ : getUTCTimestamp(new Date());
29
+ }
30
+ /**
31
+ * Generate a plan file content from structured data
32
+ */
33
+ function generatePlan(options) {
34
+ const { moduleName, uri, entries } = options;
35
+ const now = getNow();
36
+ const planfile = [
37
+ `%syntax-version=1.0.0`,
38
+ `%project=${moduleName}`,
39
+ `%uri=${uri || moduleName}`
40
+ ];
41
+ // Generate the plan entries
42
+ entries.forEach(entry => {
43
+ if (entry.dependencies && entry.dependencies.length > 0) {
44
+ planfile.push(`${entry.change} [${entry.dependencies.join(' ')}] ${now} launchql <launchql@5b0c196eeb62>${entry.comment ? ` # ${entry.comment}` : ''}`);
45
+ }
46
+ else {
47
+ planfile.push(`${entry.change} ${now} launchql <launchql@5b0c196eeb62>${entry.comment ? ` # ${entry.comment}` : ''}`);
48
+ }
49
+ });
50
+ return planfile.join('\n');
51
+ }
52
+ /**
53
+ * Write a generated plan file to disk
54
+ */
55
+ function writePlan(planPath, plan) {
56
+ fs_1.default.writeFileSync(planPath, plan);
57
+ }
@@ -0,0 +1,4 @@
1
+ export * from './generator';
2
+ export * from './parser';
3
+ export * from './validators';
4
+ export * from './writer';
@@ -0,0 +1,21 @@
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
+ // Re-export all plan functionality
18
+ __exportStar(require("./generator"), exports);
19
+ __exportStar(require("./parser"), exports);
20
+ __exportStar(require("./validators"), exports);
21
+ __exportStar(require("./writer"), exports);
@@ -0,0 +1,27 @@
1
+ import { ExtendedPlanFile, ParseResult, PlanFile } from '../types';
2
+ /**
3
+ * Parse a Sqitch plan file with full validation
4
+ * Supports both changes and tags
5
+ */
6
+ export declare function parsePlanFile(planPath: string): ParseResult<ExtendedPlanFile>;
7
+ /**
8
+ * Resolve a reference within a plan file context
9
+ * Handles symbolic references (HEAD, ROOT) and relative references
10
+ */
11
+ export declare function resolveReference(ref: string, plan: ExtendedPlanFile, currentPackage?: string): {
12
+ change?: string;
13
+ tag?: string;
14
+ error?: string;
15
+ };
16
+ /**
17
+ * Simple plan file parser without validation (for backwards compatibility)
18
+ */
19
+ export declare function parsePlanFileSimple(planPath: string): PlanFile;
20
+ /**
21
+ * Get all change names from a plan file
22
+ */
23
+ export declare function getChanges(planPath: string): string[];
24
+ /**
25
+ * Get the latest (last) change from a plan file
26
+ */
27
+ export declare function getLatestChange(planPath: string): string;