diff --git a/src/dialects/postgres/utils.test.ts b/src/dialects/postgres/utils.test.ts new file mode 100644 index 0000000..647f969 --- /dev/null +++ b/src/dialects/postgres/utils.test.ts @@ -0,0 +1,121 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { sequenceToSerialType } from "./utils.js"; + +describe('sequenceToSerialType', () => { + 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(sequenceToSerialType(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(sequenceToSerialType(obj1), obj2); + }); + }); \ No newline at end of file diff --git a/src/dialects/postgres/utils.ts b/src/dialects/postgres/utils.ts new file mode 100644 index 0000000..a3c7201 --- /dev/null +++ b/src/dialects/postgres/utils.ts @@ -0,0 +1,11 @@ +export function sequenceToSerialType>(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/schemaExporter.ts b/src/schemaExporter.ts index bfb4c32..b10e212 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 './schemaExporterHooks.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/schemaExporterHooks.ts b/src/schemaExporterHooks.ts new file mode 100644 index 0000000..ef369fb --- /dev/null +++ b/src/schemaExporterHooks.ts @@ -0,0 +1,23 @@ +import * as pgUtils from './dialects/postgres/utils.js'; + +const modifiers: modifiersType = { + postgres: [pgUtils.sequenceToSerialType] +} + +export function exportHook>(snapshot: T) { + if (modifiers[snapshot.vendor]?.length) + return modifiers[snapshot.vendor]!.reduce((_snapshot, modifier) => { + return modifier(_snapshot); + }, snapshot) + return snapshot; +}; + +type modifiersType = Record + +type snapshotWithHashType = { + snapshot: Record, + hash: string +} + +type snapshotWithHashFunctionType = (snapshotWithHash: T) => T +type snapshotFunctionType = >(snapshotWithHash: T) => T \ No newline at end of file diff --git a/tsconfig.test.json b/tsconfig.test.json index 38e550a..228c446 100644 --- a/tsconfig.test.json +++ b/tsconfig.test.json @@ -26,5 +26,5 @@ "rootDir": "./src", "outDir": "./dist-test", }, - "include": ["src/utils.ts", "src/utils.test.ts"] + "include": ["src/utils.ts", "src/utils.test.ts", "src/dialects/postgres/utils.ts", "src/dialects/postgres/utils.test.ts"] } \ No newline at end of file