diff --git a/__fixtures__/output/index.ts b/__fixtures__/output/index.ts index 731be3cec..a88792338 100644 --- a/__fixtures__/output/index.ts +++ b/__fixtures__/output/index.ts @@ -18,11 +18,9 @@ import * as actions_public from "./schemas/actions_public"; export { actions_public }; import * as app_jobs from "./schemas/app_jobs"; export { app_jobs }; -import * as collections_public from "./schemas/collections_public"; -export { collections_public }; -import * as meta_public from "./schemas/meta_public"; -export { meta_public }; +import * as metaschema_public from "./schemas/metaschema_public"; +export { metaschema_public }; +import * as services_public from "./schemas/services_public"; +export { services_public }; import * as unique_names from "./schemas/unique_names"; export { unique_names }; -import * as modules_public from "./schemas/modules_public"; -export { modules_public }; \ No newline at end of file diff --git a/__fixtures__/output/schemas/collections_public.ts b/__fixtures__/output/schemas/metaschema_public.ts similarity index 100% rename from __fixtures__/output/schemas/collections_public.ts rename to __fixtures__/output/schemas/metaschema_public.ts diff --git a/__fixtures__/output/schemas/modules_public.ts b/__fixtures__/output/schemas/modules_public.ts deleted file mode 100644 index abc71dae7..000000000 --- a/__fixtures__/output/schemas/modules_public.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { UUID } from "./_common"; -export interface module_definitions { - id: UUID; - name: string; - context: string; - exec: any; - defn: any; - mls: string | null; - mods: any | null; - data: any | null; -} -export class module_definitions implements module_definitions { - id: UUID; - name: string; - context: string; - exec: any; - defn: any; - mls: string | null; - mods: any | null; - data: any | null; - constructor(data: module_definitions) { - this.id = data.id; - this.name = data.name; - this.context = data.context; - this.exec = data.exec; - this.defn = data.defn; - this.mls = data.mls; - this.mods = data.mods; - this.data = data.data; - } -} -export interface module_field { - id: UUID; - module_defn_id: UUID; - name: string; - description: string | null; - is_required: boolean; - default_value: string | null; - is_array: boolean; - default_module_id: UUID | null; - default_module_value: string | null; - type: any; - field_order: number; -} -export class module_field implements module_field { - id: UUID; - module_defn_id: UUID; - name: string; - description: string | null; - is_required: boolean; - default_value: string | null; - is_array: boolean; - default_module_id: UUID | null; - default_module_value: string | null; - type: any; - field_order: number; - constructor(data: module_field) { - this.id = data.id; - this.module_defn_id = data.module_defn_id; - this.name = data.name; - this.description = data.description; - this.is_required = data.is_required; - this.default_value = data.default_value; - this.is_array = data.is_array; - this.default_module_id = data.default_module_id; - this.default_module_value = data.default_module_value; - this.type = data.type; - this.field_order = data.field_order; - } -} -export interface module_input { - id: UUID; - module_id: UUID; - name: string; - value: string; -} -export class module_input implements module_input { - id: UUID; - module_id: UUID; - name: string; - value: string; - constructor(data: module_input) { - this.id = data.id; - this.module_id = data.module_id; - this.name = data.name; - this.value = data.value; - } -} -export interface module_output { - id: UUID; - module_id: UUID; - name: string; - value: string; -} -export class module_output implements module_output { - id: UUID; - module_id: UUID; - name: string; - value: string; - constructor(data: module_output) { - this.id = data.id; - this.module_id = data.module_id; - this.name = data.name; - this.value = data.value; - } -} -export interface modules { - id: UUID; - database_id: UUID; - module_defn_id: UUID; - context: string; - active: boolean | null; - data: any; - executed: boolean | null; - debug: any | null; - mods: any | null; -} -export class modules implements modules { - id: UUID; - database_id: UUID; - module_defn_id: UUID; - context: string; - active: boolean | null; - data: any; - executed: boolean | null; - debug: any | null; - mods: any | null; - constructor(data: modules) { - this.id = data.id; - this.database_id = data.database_id; - this.module_defn_id = data.module_defn_id; - this.context = data.context; - this.active = data.active; - this.data = data.data; - this.executed = data.executed; - this.debug = data.debug; - this.mods = data.mods; - } -} \ No newline at end of file diff --git a/__fixtures__/output/schemas/meta_public.ts b/__fixtures__/output/schemas/services_public.ts similarity index 100% rename from __fixtures__/output/schemas/meta_public.ts rename to __fixtures__/output/schemas/services_public.ts diff --git a/packages/cli/src/commands/get-graphql-schema.ts b/packages/cli/src/commands/get-graphql-schema.ts index eb189f9ca..1bd76bf35 100644 --- a/packages/cli/src/commands/get-graphql-schema.ts +++ b/packages/cli/src/commands/get-graphql-schema.ts @@ -20,8 +20,9 @@ Options: ` const defaultSchemas = [ - 'collections_public', - 'dashboard_public' + 'metaschema_public', + 'metaschema_modules_public', + 'services_public' ] export default async ( diff --git a/pgpm/cli/src/commands/export.ts b/pgpm/cli/src/commands/export.ts index cb9aa8a3b..d01961194 100644 --- a/pgpm/cli/src/commands/export.ts +++ b/pgpm/cli/src/commands/export.ts @@ -66,7 +66,7 @@ export default async ( }); const dbsResult = await selectedDb.query(` - SELECT id, name FROM collections_public.database; + SELECT id, name FROM metaschema_public.database; `); const { database_ids: selectedDatabaseName } = await prompter.prompt({} as any, [ @@ -112,7 +112,7 @@ export default async ( ]); const schemasResult = await selectedDb.query( - `SELECT * FROM collections_public.schema WHERE database_id = $1`, + `SELECT * FROM metaschema_public.schema WHERE database_id = $1`, [dbInfo.database_ids[0]] ); diff --git a/pgpm/core/__tests__/export/export-flow.test.ts b/pgpm/core/__tests__/export/export-flow.test.ts index e77659458..bb2c1aa16 100644 --- a/pgpm/core/__tests__/export/export-flow.test.ts +++ b/pgpm/core/__tests__/export/export-flow.test.ts @@ -5,7 +5,7 @@ * 1. Sets up a temporary workspace with required pgpm modules (db-meta-schema, db-meta-modules, db-migrate) * 2. Creates a custom module with migrations to seed test data: * - insert_sql_actions: Creates db_migrate.sql_actions table and inserts sample migration records - * - insert_meta_schema: Inserts collections_public data representing a pets application + * - insert_meta_schema: Inserts metaschema_public data representing a pets application * 3. Deploys everything to a test database * 4. Runs the export flow and verifies the output * @@ -177,7 +177,7 @@ requires = '' create_sql_actions 2017-08-11T08:11:51Z constructive # Create sql_actions table insert_sql_actions [create_sql_actions] 2017-08-11T08:11:52Z constructive # Insert migration records -insert_meta_schema [insert_sql_actions] 2017-08-11T08:11:53Z constructive # Insert collections_public data +insert_meta_schema [insert_sql_actions] 2017-08-11T08:11:53Z constructive # Insert metaschema_public data `; writeFileSync(join(testModuleDir, 'pgpm.plan'), planContent); @@ -194,12 +194,12 @@ insert_meta_schema [insert_sql_actions] 2017-08-11T08:11:53Z constructive { @@ -233,45 +233,46 @@ insert_meta_schema [insert_sql_actions] 2017-08-11T08:11:53Z constructive { - const dbResult = await db.pool.query('SELECT * FROM collections_public.database WHERE name = $1', ['pets']); + it('should have seeded the database with metaschema_public data', async () => { + const dbResult = await db.pool.query('SELECT * FROM metaschema_public.database WHERE name = $1', ['pets']); expect(dbResult.rows).toHaveLength(1); expect(dbResult.rows[0].name).toBe('pets'); - const schemaResult = await db.pool.query('SELECT COUNT(*) as count FROM collections_public.schema'); + const schemaResult = await db.pool.query('SELECT COUNT(*) as count FROM metaschema_public.schema'); expect(parseInt(schemaResult.rows[0].count)).toBeGreaterThan(0); - const tableResult = await db.pool.query('SELECT COUNT(*) as count FROM collections_public.table'); + const tableResult = await db.pool.query('SELECT COUNT(*) as count FROM metaschema_public.table'); expect(parseInt(tableResult.rows[0].count)).toBeGreaterThan(0); - const fieldResult = await db.pool.query('SELECT COUNT(*) as count FROM collections_public.field'); + const fieldResult = await db.pool.query('SELECT COUNT(*) as count FROM metaschema_public.field'); expect(parseInt(fieldResult.rows[0].count)).toBeGreaterThan(0); }); - it('should have seeded the database with meta_public data', async () => { - const apiResult = await db.pool.query('SELECT COUNT(*) as count FROM meta_public.apis'); + it('should have seeded the database with services_public data', async () => { + const apiResult = await db.pool.query('SELECT COUNT(*) as count FROM services_public.apis'); expect(parseInt(apiResult.rows[0].count)).toBeGreaterThan(0); - const siteResult = await db.pool.query('SELECT COUNT(*) as count FROM meta_public.sites'); + const siteResult = await db.pool.query('SELECT COUNT(*) as count FROM services_public.sites'); expect(parseInt(siteResult.rows[0].count)).toBeGreaterThan(0); - const domainResult = await db.pool.query('SELECT COUNT(*) as count FROM meta_public.domains'); + const domainResult = await db.pool.query('SELECT COUNT(*) as count FROM services_public.domains'); expect(parseInt(domainResult.rows[0].count)).toBeGreaterThan(0); }); @@ -608,7 +610,7 @@ INSERT INTO meta_public.api_schemata (id, database_id, schema_id, api_id) VALUES beforeAll(async () => { // Get schema names from the seeded data const schemaResult = await db.pool.query( - 'SELECT schema_name FROM collections_public.schema WHERE database_id = $1', + 'SELECT schema_name FROM metaschema_public.schema WHERE database_id = $1', [DATABASE_ID] ); const schemaNames = schemaResult.rows.map((r: any) => r.schema_name); diff --git a/pgpm/core/__tests__/export/export-meta.test.ts b/pgpm/core/__tests__/export/export-meta.test.ts index 2386479da..0eb16fecb 100644 --- a/pgpm/core/__tests__/export/export-meta.test.ts +++ b/pgpm/core/__tests__/export/export-meta.test.ts @@ -2,7 +2,7 @@ * Tests for export-meta.ts configuration validation * * These tests validate that the export-meta config uses correct table names - * and includes all required fields for exporting meta_public and collections_public data. + * and includes all required fields for exporting services_public and metaschema_public data. */ import { readFileSync } from 'fs'; @@ -19,7 +19,7 @@ describe('Export Meta Config Validation', () => { describe('table name validation', () => { it('should use singular table name "database_extension" (not plural "database_extensions")', () => { - // The actual table in collections_public is database_extension (singular) + // The actual table in metaschema_public is database_extension (singular) // This test ensures the config uses the correct table name // Check that the config defines the table correctly @@ -31,20 +31,20 @@ describe('Export Meta Config Validation', () => { expect(configSection).not.toContain("table: 'database_extensions'"); }); - it('should query the correct table name in collections_public.database_extension', () => { + it('should query the correct table name in metaschema_public.database_extension', () => { // The query should use the correct singular table name - expect(exportMetaSource).toContain('FROM collections_public.database_extension'); + expect(exportMetaSource).toContain('FROM metaschema_public.database_extension'); }); it('should include field table in queries', () => { // The field table should be queried (it was missing before) expect(exportMetaSource).toContain("queryAndParse('field'"); - expect(exportMetaSource).toContain('FROM collections_public.field'); + expect(exportMetaSource).toContain('FROM metaschema_public.field'); }); }); - describe('collections_public tables', () => { - it('should include all required collections_public tables in config', () => { + describe('metaschema_public tables', () => { + it('should include all required metaschema_public tables in config', () => { const requiredTables = [ 'database', 'database_extension', @@ -59,8 +59,8 @@ describe('Export Meta Config Validation', () => { }); }); - describe('meta_public tables', () => { - it('should include all required meta_public tables in config', () => { + describe('services_public tables', () => { + it('should include all required services_public tables in config', () => { const requiredTables = [ 'domains', 'sites', @@ -70,7 +70,18 @@ describe('Export Meta Config Validation', () => { 'site_themes', 'api_modules', 'api_extensions', - 'api_schemata', + 'api_schemata' + ]; + + for (const table of requiredTables) { + expect(exportMetaSource).toContain(`queryAndParse('${table}'`); + } + }); + }); + + describe('metaschema_modules_public tables', () => { + it('should include all required metaschema_modules_public tables in config', () => { + const requiredTables = [ 'rls_module', 'user_auth_module' ]; @@ -95,10 +106,10 @@ describe('Export Meta Config Validation', () => { }); describe('Export Meta Config Drift Detection', () => { - it('should document the expected table names in collections_public', () => { + it('should document the expected table names in metaschema_public', () => { // This test documents the expected table names that export-meta.ts should use // If these change, the export-meta.ts config needs to be updated - const expectedCollectionsPublicTables = [ + const expectedMetaschemaPublicTables = [ 'database', 'database_extension', // NOT 'database_extensions' (plural) 'schema', @@ -107,13 +118,13 @@ describe('Export Meta Config Drift Detection', () => { ]; // Document the expected tables - expect(expectedCollectionsPublicTables).toContain('database_extension'); - expect(expectedCollectionsPublicTables).not.toContain('database_extensions'); + expect(expectedMetaschemaPublicTables).toContain('database_extension'); + expect(expectedMetaschemaPublicTables).not.toContain('database_extensions'); }); - it('should document the expected table names in meta_public', () => { + it('should document the expected table names in services_public', () => { // This test documents the expected table names that export-meta.ts should use - const expectedMetaPublicTables = [ + const expectedServicesPublicTables = [ 'apis', 'api_extensions', 'api_modules', @@ -122,13 +133,22 @@ describe('Export Meta Config Drift Detection', () => { 'domains', 'site_modules', 'site_themes', - 'sites', + 'sites' + ]; + + // Document the expected tables + expect(expectedServicesPublicTables.length).toBe(9); + }); + + it('should document the expected table names in metaschema_modules_public', () => { + // This test documents the expected table names that export-meta.ts should use + const expectedMetaschemaModulesPublicTables = [ 'rls_module', 'user_auth_module' ]; // Document the expected tables - expect(expectedMetaPublicTables.length).toBe(11); + expect(expectedMetaschemaModulesPublicTables.length).toBe(2); }); it('should document the bug: config uses database_extensions but table is database_extension', () => { @@ -136,7 +156,7 @@ describe('Export Meta Config Drift Detection', () => { // In export-meta.ts, line 26, the config defines: // table: 'database_extensions' (plural) // But the actual table in db-meta-schema is: - // collections_public.database_extension (singular) + // metaschema_public.database_extension (singular) // // This causes the Parser to generate INSERT statements with the wrong table name, // which will fail when the exported SQL is replayed. diff --git a/pgpm/core/src/export/export-meta.ts b/pgpm/core/src/export/export-meta.ts index 501db8435..58592a073 100644 --- a/pgpm/core/src/export/export-meta.ts +++ b/pgpm/core/src/export/export-meta.ts @@ -12,7 +12,7 @@ interface TableConfig { const config: Record = { database: { - schema: 'collections_public', + schema: 'metaschema_public', table: 'database', fields: { id: 'uuid', @@ -22,7 +22,7 @@ const config: Record = { } }, database_extension: { - schema: 'collections_public', + schema: 'metaschema_public', table: 'database_extension', fields: { name: 'text', @@ -30,7 +30,7 @@ const config: Record = { } }, schema: { - schema: 'collections_public', + schema: 'metaschema_public', table: 'schema', fields: { id: 'uuid', @@ -41,7 +41,7 @@ const config: Record = { } }, table: { - schema: 'collections_public', + schema: 'metaschema_public', table: 'table', fields: { id: 'uuid', @@ -52,7 +52,7 @@ const config: Record = { } }, field: { - schema: 'collections_public', + schema: 'metaschema_public', table: 'field', fields: { id: 'uuid', @@ -64,7 +64,7 @@ const config: Record = { } }, domains: { - schema: 'meta_public', + schema: 'services_public', table: 'domains', fields: { id: 'uuid', @@ -76,7 +76,7 @@ const config: Record = { } }, sites: { - schema: 'meta_public', + schema: 'services_public', table: 'sites', fields: { id: 'uuid', @@ -91,7 +91,7 @@ const config: Record = { } }, apis: { - schema: 'meta_public', + schema: 'services_public', table: 'apis', fields: { id: 'uuid', @@ -104,7 +104,7 @@ const config: Record = { } }, apps: { - schema: 'meta_public', + schema: 'services_public', table: 'apps', fields: { id: 'uuid', @@ -119,7 +119,7 @@ const config: Record = { } }, site_modules: { - schema: 'meta_public', + schema: 'services_public', table: 'site_modules', fields: { id: 'uuid', @@ -130,7 +130,7 @@ const config: Record = { } }, site_themes: { - schema: 'meta_public', + schema: 'services_public', table: 'site_themes', fields: { id: 'uuid', @@ -140,7 +140,7 @@ const config: Record = { } }, api_modules: { - schema: 'meta_public', + schema: 'services_public', table: 'api_modules', fields: { id: 'uuid', @@ -151,7 +151,7 @@ const config: Record = { } }, api_extensions: { - schema: 'meta_public', + schema: 'services_public', table: 'api_extensions', fields: { id: 'uuid', @@ -161,7 +161,7 @@ const config: Record = { } }, api_schemata: { - schema: 'meta_public', + schema: 'services_public', table: 'api_schemata', fields: { id: 'uuid', @@ -171,7 +171,7 @@ const config: Record = { } }, rls_module: { - schema: 'meta_public', + schema: 'metaschema_modules_public', table: 'rls_module', fields: { id: 'uuid', @@ -188,7 +188,7 @@ const config: Record = { } }, user_auth_module: { - schema: 'meta_public', + schema: 'metaschema_modules_public', table: 'user_auth_module', fields: { id: 'uuid', @@ -243,22 +243,22 @@ export const exportMeta = async ({ opts, dbname, database_id }: ExportMetaParams } }; - await queryAndParse('database', `SELECT * FROM collections_public.database WHERE id = $1`); - await queryAndParse('schema', `SELECT * FROM collections_public.schema WHERE database_id = $1`); - await queryAndParse('table', `SELECT * FROM collections_public.table WHERE database_id = $1`); - await queryAndParse('field', `SELECT * FROM collections_public.field WHERE database_id = $1`); - await queryAndParse('domains', `SELECT * FROM meta_public.domains WHERE database_id = $1`); - await queryAndParse('apis', `SELECT * FROM meta_public.apis WHERE database_id = $1`); - await queryAndParse('sites', `SELECT * FROM meta_public.sites WHERE database_id = $1`); - await queryAndParse('api_modules', `SELECT * FROM meta_public.api_modules WHERE database_id = $1`); - await queryAndParse('site_modules', `SELECT * FROM meta_public.site_modules WHERE database_id = $1`); - await queryAndParse('site_themes', `SELECT * FROM meta_public.site_themes WHERE database_id = $1`); - await queryAndParse('apps', `SELECT * FROM meta_public.apps WHERE database_id = $1`); - await queryAndParse('database_extension', `SELECT * FROM collections_public.database_extension WHERE database_id = $1`); - await queryAndParse('api_extensions', `SELECT * FROM meta_public.api_extensions WHERE database_id = $1`); - await queryAndParse('api_schemata', `SELECT * FROM meta_public.api_schemata WHERE database_id = $1`); - await queryAndParse('rls_module', `SELECT * FROM meta_public.rls_module WHERE database_id = $1`); - await queryAndParse('user_auth_module', `SELECT * FROM meta_public.user_auth_module WHERE database_id = $1`); + await queryAndParse('database', `SELECT * FROM metaschema_public.database WHERE id = $1`); + await queryAndParse('schema', `SELECT * FROM metaschema_public.schema WHERE database_id = $1`); + await queryAndParse('table', `SELECT * FROM metaschema_public.table WHERE database_id = $1`); + await queryAndParse('field', `SELECT * FROM metaschema_public.field WHERE database_id = $1`); + await queryAndParse('domains', `SELECT * FROM services_public.domains WHERE database_id = $1`); + await queryAndParse('apis', `SELECT * FROM services_public.apis WHERE database_id = $1`); + await queryAndParse('sites', `SELECT * FROM services_public.sites WHERE database_id = $1`); + await queryAndParse('api_modules', `SELECT * FROM services_public.api_modules WHERE database_id = $1`); + await queryAndParse('site_modules', `SELECT * FROM services_public.site_modules WHERE database_id = $1`); + await queryAndParse('site_themes', `SELECT * FROM services_public.site_themes WHERE database_id = $1`); + await queryAndParse('apps', `SELECT * FROM services_public.apps WHERE database_id = $1`); + await queryAndParse('database_extension', `SELECT * FROM metaschema_public.database_extension WHERE database_id = $1`); + await queryAndParse('api_extensions', `SELECT * FROM services_public.api_extensions WHERE database_id = $1`); + await queryAndParse('api_schemata', `SELECT * FROM services_public.api_schemata WHERE database_id = $1`); + await queryAndParse('rls_module', `SELECT * FROM metaschema_modules_public.rls_module WHERE database_id = $1`); + await queryAndParse('user_auth_module', `SELECT * FROM metaschema_modules_public.user_auth_module WHERE database_id = $1`); return Object.entries(sql).reduce((m, [_, v]) => m + '\n\n' + v, ''); }; diff --git a/pgpm/core/src/export/export-migrations.ts b/pgpm/core/src/export/export-migrations.ts index ed35b5132..1afee2b58 100644 --- a/pgpm/core/src/export/export-migrations.ts +++ b/pgpm/core/src/export/export-migrations.ts @@ -204,12 +204,12 @@ const exportMigrationsToDisk = async ({ }); const db = await pgPool.query( - `select * from collections_public.database where id=$1`, + `select * from metaschema_public.database where id=$1`, [databaseId] ); const schemas = await pgPool.query( - `select * from collections_public.schema where database_id=$1`, + `select * from metaschema_public.schema where database_id=$1`, [databaseId] ); @@ -315,7 +315,7 @@ const exportMigrationsToDisk = async ({ deps: [], deploy: 'migrate/meta', content: `SET session_replication_role TO replica; --- using replica in case we are deploying triggers to collections_public +-- using replica in case we are deploying triggers to metaschema_public -- unaccent, postgis affected and require grants GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public to public; @@ -334,12 +334,12 @@ ${meta} -- TODO: Research needed - These UPDATE statements may be a security leak. -- They appear to rebind exported metadata to the target database after import, --- but exposing dbname in meta_public tables could leak internal database names. +-- but exposing dbname in services_public tables could leak internal database names. -- Consider removing entirely or gating behind an explicit flag. --- UPDATE meta_public.apis +-- UPDATE services_public.apis -- SET dbname = current_database() WHERE TRUE; --- UPDATE meta_public.sites +-- UPDATE services_public.sites -- SET dbname = current_database() WHERE TRUE; SET session_replication_role TO DEFAULT; diff --git a/postgres/pg-ast/src/asts.ts b/postgres/pg-ast/src/asts.ts index e816d9065..e06e4616c 100644 --- a/postgres/pg-ast/src/asts.ts +++ b/postgres/pg-ast/src/asts.ts @@ -1,5 +1,5 @@ /** -* This file was automatically generated by pg-proto-parser@1.30.2. +* This file was automatically generated by pg-proto-parser@1.30.4. * DO NOT MODIFY IT BY HAND. Instead, modify the source proto file, * and run the pg-proto-parser generate command to regenerate this file. */ diff --git a/postgres/pg-ast/src/wrapped.ts b/postgres/pg-ast/src/wrapped.ts index a8bff0279..385d0d935 100644 --- a/postgres/pg-ast/src/wrapped.ts +++ b/postgres/pg-ast/src/wrapped.ts @@ -1,5 +1,5 @@ /** -* This file was automatically generated by pg-proto-parser@1.30.2. +* This file was automatically generated by pg-proto-parser@1.30.4. * DO NOT MODIFY IT BY HAND. Instead, modify the source proto file, * and run the pg-proto-parser generate command to regenerate this file. */