diff --git a/src/schemaExporter.ts b/src/schemaExporter.ts index bfb4c32..1cf7947 100644 --- a/src/schemaExporter.ts +++ b/src/schemaExporter.ts @@ -3,6 +3,7 @@ import { readFile, writeFile } from 'fs/promises'; import { condenseAction } from './condenseAction.js'; import type { IExporter } from './types'; import { ExportHelper } from './utils.js'; +import { exportHook } from './vendorSpecific.js' export class SchemaExporter implements IExporter { private _filePath: string; @@ -46,6 +47,7 @@ export class SchemaExporter implements IExporter { private createAndSaveSnapshot = async () => { const svc = this._getSchemaService(); let snapshot = await svc.snapshot(); + snapshot = exportHook(snapshot); let hash = svc.getHashedSnapshot(snapshot).hash; let json = JSON.stringify({ snapshot, hash }, null, 2); await writeFile(this._filePath, json); diff --git a/src/utils.test.ts b/src/utils.test.ts index cf03892..6bf515f 100644 --- a/src/utils.test.ts +++ b/src/utils.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { deepEqual, getDiff, sortObject } from "./utils.js"; +import { deepEqual, getDiff, sortObject, postgresSequenceToSerialType } from "./utils.js"; describe('sortObject', () => { it('should sort object keys alphabetically', () => { @@ -101,4 +101,122 @@ describe('deepEqual', () => { assert.strictEqual(deepEqual('hello', 'world'), false); assert.strictEqual(deepEqual(null, undefined), false); }); +}); + +describe('postgresSequenceToSerialType', () => { + it('should remove nextval default value and set has_auto_increment to true', () => { + const obj1 = { + "fields": [ + { + "collection": "test_collection", + "field": "id", + "type": "integer", + "meta": null, + "schema": { + "name": "id", + "table": "test_collection", + "data_type": "integer", + "default_value": "nextval('test_collection_id_seq'::regclass)", + "max_length": null, + "numeric_precision": 32, + "numeric_scale": 0, + "is_nullable": false, + "is_unique": true, + "is_primary_key": true, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } + } + ] + }; + const obj2 = { + "fields": [ + { + "collection": "test_collection", + "field": "id", + "type": "integer", + "meta": null, + "schema": { + "name": "id", + "table": "test_collection", + "data_type": "integer", + "default_value": null, + "max_length": null, + "numeric_precision": 32, + "numeric_scale": 0, + "is_nullable": false, + "is_unique": true, + "is_primary_key": true, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": true, + "foreign_key_table": null, + "foreign_key_column": null + } + } + ] + }; + assert.deepEqual(postgresSequenceToSerialType(obj1), obj2); + }); + + it('should return same snapshot if serial type is already used everywhere', () => { + const obj1 = { + "fields": [ + { + "collection": "test_collection", + "field": "id", + "type": "string", + "meta": null, + "schema": { + "name": "id", + "table": "test_collection", + "data_type": "integer", + "default_value": "test", + "max_length": null, + "numeric_precision": 32, + "numeric_scale": 0, + "is_nullable": false, + "is_unique": true, + "is_primary_key": true, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } + } + ] + }; + const obj2 = { + "fields": [ + { + "collection": "test_collection", + "field": "id", + "type": "string", + "meta": null, + "schema": { + "name": "id", + "table": "test_collection", + "data_type": "integer", + "default_value": "test", + "max_length": null, + "numeric_precision": 32, + "numeric_scale": 0, + "is_nullable": false, + "is_unique": true, + "is_primary_key": true, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } + } + ] + }; + assert.deepEqual(postgresSequenceToSerialType(obj1), obj2); + }); }); \ No newline at end of file diff --git a/src/utils.ts b/src/utils.ts index d0c9084..f9d3d1d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -126,4 +126,16 @@ export function sortObject | T[]>(obj: T): T { sortedObj[key] = sortObject((obj as Record)[key]); }); return sortedObj as T; +} + +export function postgresSequenceToSerialType>(snapshot: T): T { + snapshot.fields + .map( (field: any) => { + if (field.schema?.default_value=="nextval('"+field.schema?.table+"_"+field.schema?.name+"_seq'::regclass)") { + field.schema.default_value = null; + field.schema.has_auto_increment = true; + } + return field; + }) as T; + return snapshot; } \ No newline at end of file diff --git a/src/vendorSpecific.ts b/src/vendorSpecific.ts new file mode 100644 index 0000000..8316a53 --- /dev/null +++ b/src/vendorSpecific.ts @@ -0,0 +1,30 @@ +import { postgresSequenceToSerialType } from './utils'; + +const modifiers: modifiersType = { + import: { + }, + export: { + postgres: [postgresSequenceToSerialType] + } +} + +export function importHook(snapshot: any) { + if (modifiers.import[snapshot.vendor]?.length) + return modifiers.import[snapshot.vendor]?.reduce((_snapshot, modifier) => { + return modifier(_snapshot); + }, snapshot) + return snapshot; +}; + +export function exportHook(snapshot: any) { + if (modifiers.export[snapshot.vendor]?.length) + return modifiers.export[snapshot.vendor]!.reduce((_snapshot, modifier) => { + return modifier(_snapshot); + }, snapshot) + return snapshot; +}; + +type modifiersType = { + import: Record + export: Record +} \ No newline at end of file