@pgpmjs/core 3.0.9 → 3.1.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/index.js CHANGED
@@ -37,6 +37,7 @@ var client_1 = require("./migrate/client");
37
37
  Object.defineProperty(exports, "PgpmMigrate", { enumerable: true, get: function () { return client_1.PgpmMigrate; } });
38
38
  var client_2 = require("./init/client");
39
39
  Object.defineProperty(exports, "PgpmInit", { enumerable: true, get: function () { return client_2.PgpmInit; } });
40
+ __exportStar(require("./roles"), exports);
40
41
  var hash_1 = require("./migrate/utils/hash");
41
42
  Object.defineProperty(exports, "hashFile", { enumerable: true, get: function () { return hash_1.hashFile; } });
42
43
  Object.defineProperty(exports, "hashString", { enumerable: true, get: function () { return hash_1.hashString; } });
package/init/client.d.ts CHANGED
@@ -1,24 +1,39 @@
1
+ import { RoleMapping, TestUserCredentials } from '@pgpmjs/types';
1
2
  import { PgConfig } from 'pg-env';
2
3
  export declare class PgpmInit {
3
4
  private pool;
4
5
  private pgConfig;
5
6
  constructor(config: PgConfig);
6
7
  /**
7
- * Bootstrap standard roles (anonymous, authenticated, administrator)
8
+ * Bootstrap standard roles (anonymous, authenticated, administrator).
9
+ * Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
10
+ * @param roles - Role mapping from getConnEnvOptions().roles!
8
11
  */
9
- bootstrapRoles(): Promise<void>;
12
+ bootstrapRoles(roles: RoleMapping): Promise<void>;
10
13
  /**
11
- * Bootstrap test roles (roles only, no users)
14
+ * Bootstrap test roles (app_user, app_admin with grants to base roles).
15
+ * Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
16
+ * @param roles - Role mapping from getConnEnvOptions().roles!
17
+ * @param connections - Test user credentials from getConnEnvOptions().connections!
12
18
  */
13
- bootstrapTestRoles(): Promise<void>;
19
+ bootstrapTestRoles(roles: RoleMapping, connections: TestUserCredentials): Promise<void>;
14
20
  /**
15
- * Bootstrap database roles with custom username and password
21
+ * Bootstrap database roles with custom username and password.
22
+ * Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
23
+ * @param username - The username to create
24
+ * @param password - The password for the user
25
+ * @param roles - Role mapping from getConnEnvOptions().roles!
26
+ * @param useLocksForRoles - Whether to use advisory locks (from getConnEnvOptions().useLocksForRoles)
16
27
  */
17
- bootstrapDbRoles(username: string, password: string): Promise<void>;
28
+ bootstrapDbRoles(username: string, password: string, roles: RoleMapping, useLocksForRoles?: boolean): Promise<void>;
18
29
  /**
19
- * Remove database roles and revoke grants
30
+ * Remove database roles and revoke grants.
31
+ * Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
32
+ * @param username - The username to remove
33
+ * @param roles - Role mapping from getConnEnvOptions().roles!
34
+ * @param useLocksForRoles - Whether to use advisory locks (from getConnEnvOptions().useLocksForRoles)
20
35
  */
21
- removeDbRoles(username: string): Promise<void>;
36
+ removeDbRoles(username: string, roles: RoleMapping, useLocksForRoles?: boolean): Promise<void>;
22
37
  /**
23
38
  * Close the database connection
24
39
  */
package/init/client.js CHANGED
@@ -2,9 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PgpmInit = void 0;
4
4
  const logger_1 = require("@pgpmjs/logger");
5
- const fs_1 = require("fs");
6
- const path_1 = require("path");
7
5
  const pg_cache_1 = require("pg-cache");
6
+ const roles_1 = require("../roles");
8
7
  const log = new logger_1.Logger('init');
9
8
  class PgpmInit {
10
9
  pool;
@@ -14,13 +13,14 @@ class PgpmInit {
14
13
  this.pool = (0, pg_cache_1.getPgPool)(this.pgConfig);
15
14
  }
16
15
  /**
17
- * Bootstrap standard roles (anonymous, authenticated, administrator)
16
+ * Bootstrap standard roles (anonymous, authenticated, administrator).
17
+ * Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
18
+ * @param roles - Role mapping from getConnEnvOptions().roles!
18
19
  */
19
- async bootstrapRoles() {
20
+ async bootstrapRoles(roles) {
20
21
  try {
21
22
  log.info('Bootstrapping PGPM roles...');
22
- const sqlPath = (0, path_1.join)(__dirname, 'sql', 'bootstrap-roles.sql');
23
- const sql = (0, fs_1.readFileSync)(sqlPath, 'utf-8');
23
+ const sql = (0, roles_1.generateCreateBaseRolesSQL)(roles);
24
24
  await this.pool.query(sql);
25
25
  log.success('Successfully bootstrapped PGPM roles');
26
26
  }
@@ -30,14 +30,16 @@ class PgpmInit {
30
30
  }
31
31
  }
32
32
  /**
33
- * Bootstrap test roles (roles only, no users)
33
+ * Bootstrap test roles (app_user, app_admin with grants to base roles).
34
+ * Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
35
+ * @param roles - Role mapping from getConnEnvOptions().roles!
36
+ * @param connections - Test user credentials from getConnEnvOptions().connections!
34
37
  */
35
- async bootstrapTestRoles() {
38
+ async bootstrapTestRoles(roles, connections) {
36
39
  try {
37
40
  log.warn('WARNING: This command creates test roles and should NEVER be run on a production database!');
38
41
  log.info('Bootstrapping PGPM test roles...');
39
- const sqlPath = (0, path_1.join)(__dirname, 'sql', 'bootstrap-test-roles.sql');
40
- const sql = (0, fs_1.readFileSync)(sqlPath, 'utf-8');
42
+ const sql = (0, roles_1.generateCreateTestUsersSQL)(roles, connections);
41
43
  await this.pool.query(sql);
42
44
  log.success('Successfully bootstrapped PGPM test roles');
43
45
  }
@@ -47,58 +49,17 @@ class PgpmInit {
47
49
  }
48
50
  }
49
51
  /**
50
- * Bootstrap database roles with custom username and password
52
+ * Bootstrap database roles with custom username and password.
53
+ * Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
54
+ * @param username - The username to create
55
+ * @param password - The password for the user
56
+ * @param roles - Role mapping from getConnEnvOptions().roles!
57
+ * @param useLocksForRoles - Whether to use advisory locks (from getConnEnvOptions().useLocksForRoles)
51
58
  */
52
- async bootstrapDbRoles(username, password) {
59
+ async bootstrapDbRoles(username, password, roles, useLocksForRoles = false) {
53
60
  try {
54
61
  log.info(`Bootstrapping PGPM database roles for user: ${username}...`);
55
- const sql = `
56
- BEGIN;
57
- DO $do$
58
- DECLARE
59
- v_username TEXT := '${username.replace(/'/g, "''")}';
60
- v_password TEXT := '${password.replace(/'/g, "''")}';
61
- BEGIN
62
- BEGIN
63
- EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', v_username, v_password);
64
- EXCEPTION
65
- WHEN duplicate_object THEN
66
- -- Role already exists; optionally sync attributes here with ALTER ROLE
67
- NULL;
68
- END;
69
- END
70
- $do$;
71
-
72
- -- Robust GRANTs under concurrency: GRANT can race on pg_auth_members unique index.
73
- -- Catch unique_violation (23505) and continue so CI/CD concurrent jobs don't fail.
74
- DO $do$
75
- DECLARE
76
- v_username TEXT := '${username.replace(/'/g, "''")}';
77
- BEGIN
78
- BEGIN
79
- EXECUTE format('GRANT %I TO %I', 'anonymous', v_username);
80
- EXCEPTION
81
- WHEN unique_violation THEN
82
- -- Membership was granted concurrently; ignore.
83
- NULL;
84
- WHEN undefined_object THEN
85
- -- One of the roles doesn't exist yet; order operations as needed.
86
- RAISE NOTICE 'Missing role when granting % to %', 'anonymous', v_username;
87
- END;
88
-
89
- BEGIN
90
- EXECUTE format('GRANT %I TO %I', 'authenticated', v_username);
91
- EXCEPTION
92
- WHEN unique_violation THEN
93
- -- Membership was granted concurrently; ignore.
94
- NULL;
95
- WHEN undefined_object THEN
96
- RAISE NOTICE 'Missing role when granting % to %', 'authenticated', v_username;
97
- END;
98
- END
99
- $do$;
100
- COMMIT;
101
- `;
62
+ const sql = (0, roles_1.generateCreateUserSQL)(username, password, roles, useLocksForRoles);
102
63
  await this.pool.query(sql);
103
64
  log.success(`Successfully bootstrapped PGPM database roles for user: ${username}`);
104
65
  }
@@ -108,29 +69,16 @@ COMMIT;
108
69
  }
109
70
  }
110
71
  /**
111
- * Remove database roles and revoke grants
72
+ * Remove database roles and revoke grants.
73
+ * Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
74
+ * @param username - The username to remove
75
+ * @param roles - Role mapping from getConnEnvOptions().roles!
76
+ * @param useLocksForRoles - Whether to use advisory locks (from getConnEnvOptions().useLocksForRoles)
112
77
  */
113
- async removeDbRoles(username) {
78
+ async removeDbRoles(username, roles, useLocksForRoles = false) {
114
79
  try {
115
80
  log.info(`Removing PGPM database roles for user: ${username}...`);
116
- const sql = `
117
- BEGIN;
118
- DO $do$
119
- BEGIN
120
- IF EXISTS (
121
- SELECT 1
122
- FROM
123
- pg_catalog.pg_roles
124
- WHERE
125
- rolname = '${username}') THEN
126
- REVOKE anonymous FROM ${username};
127
- REVOKE authenticated FROM ${username};
128
- DROP ROLE ${username};
129
- END IF;
130
- END
131
- $do$;
132
- COMMIT;
133
- `;
81
+ const sql = (0, roles_1.generateRemoveUserSQL)(username, roles, useLocksForRoles);
134
82
  await this.pool.query(sql);
135
83
  log.success(`Successfully removed PGPM database roles for user: ${username}`);
136
84
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pgpmjs/core",
3
- "version": "3.0.9",
3
+ "version": "3.1.1",
4
4
  "author": "Constructive <developers@constructive.io>",
5
5
  "description": "PGPM Package and Migration Tools",
6
6
  "main": "index.js",
@@ -22,7 +22,7 @@
22
22
  "scripts": {
23
23
  "copy": "npm run copy:pkg; npm run copy:sql",
24
24
  "copy:pkg": "makage assets",
25
- "copy:sql": "copyfiles -f src/migrate/sql/* dist/migrate/sql && copyfiles -f src/migrate/sql/* dist/esm/migrate/sql && copyfiles -f src/init/sql/* dist/init/sql && copyfiles -f src/init/sql/* dist/esm/init/sql",
25
+ "copy:sql": "copyfiles -f src/migrate/sql/* dist/migrate/sql && copyfiles -f src/migrate/sql/* dist/esm/migrate/sql",
26
26
  "clean": "makage clean",
27
27
  "prepack": "npm run build",
28
28
  "build": "makage build && npm run copy",
@@ -47,21 +47,21 @@
47
47
  "makage": "^0.1.9"
48
48
  },
49
49
  "dependencies": {
50
- "@pgpmjs/env": "^2.8.5",
50
+ "@pgpmjs/env": "^2.8.7",
51
51
  "@pgpmjs/logger": "^1.3.5",
52
- "@pgpmjs/server-utils": "^2.8.7",
53
- "@pgpmjs/types": "^2.12.5",
52
+ "@pgpmjs/server-utils": "^2.8.8",
53
+ "@pgpmjs/types": "^2.12.6",
54
54
  "create-gen-app": "^0.6.0",
55
55
  "csv-to-pg": "^2.0.10",
56
56
  "glob": "^13.0.0",
57
57
  "komoji": "^0.7.11",
58
58
  "parse-package-name": "^1.0.0",
59
59
  "pg": "^8.16.3",
60
- "pg-cache": "^1.6.7",
60
+ "pg-cache": "^1.6.8",
61
61
  "pg-env": "^1.2.4",
62
62
  "pgsql-deparser": "^17.12.2",
63
63
  "pgsql-parser": "^17.9.2",
64
64
  "yanse": "^0.1.8"
65
65
  },
66
- "gitHead": "63d51202de99ec03c329e00e5cd1dff4bc60b367"
66
+ "gitHead": "248d4056d3191b71bcab5892ef98b09164de9f7f"
67
67
  }
@@ -0,0 +1,38 @@
1
+ import { RoleMapping, TestUserCredentials } from '@pgpmjs/types';
2
+ /**
3
+ * Generate SQL to create base roles (anonymous, authenticated, administrator).
4
+ * Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
5
+ * @param roles - Role mapping from getConnEnvOptions().roles!
6
+ * @throws Error if roles is undefined or missing required properties
7
+ */
8
+ export declare function generateCreateBaseRolesSQL(roles: RoleMapping): string;
9
+ /**
10
+ * Generate SQL to create a user with password and grant base roles.
11
+ * Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
12
+ * @param roles - Role mapping from getConnEnvOptions().roles!
13
+ * @param useLocksForRoles - Whether to use advisory locks (from getConnEnvOptions().useLocksForRoles)
14
+ */
15
+ export declare function generateCreateUserSQL(username: string, password: string, roles: RoleMapping, useLocksForRoles?: boolean): string;
16
+ /**
17
+ * Generate SQL to create test users with grants to base roles.
18
+ * Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
19
+ * @param roles - Role mapping from getConnEnvOptions().roles!
20
+ * @param connections - Test user credentials from getConnEnvOptions().connections!
21
+ */
22
+ export declare function generateCreateTestUsersSQL(roles: RoleMapping, connections: TestUserCredentials): string;
23
+ /**
24
+ * Generate SQL to grant a role to a user
25
+ */
26
+ export declare function generateGrantRoleSQL(role: string, user: string): string;
27
+ /**
28
+ * Generate SQL to remove a user and revoke grants.
29
+ * Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
30
+ * @param roles - Role mapping from getConnEnvOptions().roles!
31
+ * @param useLocksForRoles - Whether to use advisory locks (from getConnEnvOptions().useLocksForRoles)
32
+ */
33
+ export declare function generateRemoveUserSQL(username: string, roles: RoleMapping, useLocksForRoles?: boolean): string;
34
+ /**
35
+ * Generate SQL to create a user with grants to specified roles (for test harness)
36
+ * @param useLocksForRoles - Whether to use advisory locks (from getConnEnvOptions().useLocksForRoles)
37
+ */
38
+ export declare function generateCreateUserWithGrantsSQL(username: string, password: string, rolesToGrant: string[], useLocksForRoles?: boolean): string;