@byline/db-postgres 1.12.0 → 1.12.2

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.
@@ -5,18 +5,7 @@
5
5
  *
6
6
  * Copyright (c) Infonomic Company Limited
7
7
  */
8
- /**
9
- * Integration test for the "make current" / restore-version flow.
10
- *
11
- * Validates that the Postgres locale='all' round-trip
12
- * (`getDocumentByVersion` → `createDocumentVersion`) preserves multi-locale
13
- * content and stable block `_id`s — the core invariant
14
- * `restoreDocumentVersion` in @byline/core depends on. Pure storage-layer:
15
- * the lifecycle wrapper, auth, and hooks are covered by unit tests in
16
- * `packages/core/src/services/document-lifecycle.test.node.ts`.
17
- */
18
- import assert from 'node:assert';
19
- import { after, before, describe, it } from 'node:test';
8
+ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
20
9
  import { setupTestDB, teardownTestDB } from '../../../lib/test-helper.js';
21
10
  let commandBuilders;
22
11
  let queryBuilders;
@@ -45,7 +34,7 @@ const RestoreCollectionConfig = {
45
34
  };
46
35
  let testCollection = {};
47
36
  describe('Document version restore — storage round-trip', () => {
48
- before(async () => {
37
+ beforeAll(async () => {
49
38
  const testDB = setupTestDB([RestoreCollectionConfig]);
50
39
  commandBuilders = testDB.commandBuilders;
51
40
  queryBuilders = testDB.queryBuilders;
@@ -55,7 +44,7 @@ describe('Document version restore — storage round-trip', () => {
55
44
  throw new Error('Failed to create test collection');
56
45
  testCollection = { id: collection.id };
57
46
  });
58
- after(async () => {
47
+ afterAll(async () => {
59
48
  try {
60
49
  await commandBuilders.collections.delete(testCollection.id);
61
50
  }
@@ -96,7 +85,7 @@ describe('Document version restore — storage round-trip', () => {
96
85
  });
97
86
  const v1Sections = v1Read.fields.sections;
98
87
  const v1ItemIds = v1Sections[0].sectionItem.map((item) => item._id);
99
- assert.ok(v1ItemIds.every((id) => typeof id === 'string' && id.length > 0), 'v1 items should have stable _ids');
88
+ expect(v1ItemIds.every((id) => typeof id === 'string' && id.length > 0), 'v1 items should have stable _ids').toBeTruthy();
100
89
  // Mutate to v2 (different content)
101
90
  const v2Data = {
102
91
  sku: v1Data.sku,
@@ -134,7 +123,7 @@ describe('Document version restore — storage round-trip', () => {
134
123
  locale: 'all',
135
124
  status: 'draft',
136
125
  });
137
- assert.strictEqual(v3.document.event_type, 'restore', 'event_type should be persisted as "restore"');
126
+ expect(v3.document.event_type, 'event_type should be persisted as "restore"').toBe('restore');
138
127
  // Reconstruct v3. Multi-locale fields, block _ids, and per-item content
139
128
  // should match v1 — not v2.
140
129
  const v3Read = await queryBuilders.documents.getDocumentByVersion({
@@ -142,16 +131,16 @@ describe('Document version restore — storage round-trip', () => {
142
131
  locale: 'all',
143
132
  });
144
133
  const v3Fields = v3Read.fields;
145
- assert.deepStrictEqual(v3Fields.title, v1Data.title, 'restored title should match v1 across all locales');
134
+ expect(v3Fields.title, 'restored title should match v1 across all locales').toEqual(v1Data.title);
146
135
  const v3Sections = v3Fields.sections;
147
136
  const v3ItemIds = v3Sections[0].sectionItem.map((item) => item._id);
148
- assert.deepStrictEqual(v3ItemIds, v1ItemIds, 'restored block items should keep the v1 _ids verbatim (identity preserved across restore)');
149
- assert.strictEqual(v3Sections[0].sectionItem.length, 2, "restored version should have v1's two items, not v2's single item");
150
- assert.deepStrictEqual(v3Sections[0].sectionItem[0].heading, {
137
+ expect(v3ItemIds, 'restored block items should keep the v1 _ids verbatim (identity preserved across restore)').toEqual(v1ItemIds);
138
+ expect(v3Sections[0].sectionItem.length, "restored version should have v1's two items, not v2's single item").toBe(2);
139
+ expect(v3Sections[0].sectionItem[0].heading).toEqual({
151
140
  en: 'Intro EN',
152
141
  fr: 'Intro FR',
153
142
  });
154
- assert.deepStrictEqual(v3Sections[0].sectionItem[1].heading, {
143
+ expect(v3Sections[0].sectionItem[1].heading).toEqual({
155
144
  en: 'Body EN',
156
145
  fr: 'Body FR',
157
146
  });
@@ -5,8 +5,7 @@
5
5
  *
6
6
  * Copyright (c) Infonomic Company Limited
7
7
  */
8
- import assert from 'node:assert';
9
- import { describe, it } from 'node:test';
8
+ import { describe, expect, it } from 'vitest';
10
9
  import { allStoreTypes, buildSelectList, columns, fieldTypeLiterals, UNIFIED_COLUMN_COUNT, } from '../storage-store-manifest.js';
11
10
  /**
12
11
  * Parse a generated SELECT list into individual column expressions.
@@ -36,13 +35,13 @@ describe('storage-store-manifest', () => {
36
35
  describe('column count', () => {
37
36
  it('UNIFIED_COLUMN_COUNT matches manifest', () => {
38
37
  // columns array has all columns except field_type, which is added during generation
39
- assert.strictEqual(UNIFIED_COLUMN_COUNT, columns.length + 1);
38
+ expect(UNIFIED_COLUMN_COUNT).toBe(columns.length + 1);
40
39
  });
41
40
  for (const storeType of allStoreTypes) {
42
41
  it(`${storeType} SELECT list has ${UNIFIED_COLUMN_COUNT} columns`, () => {
43
42
  const selectList = buildSelectList(storeType);
44
43
  const cols = parseColumns(selectList);
45
- assert.strictEqual(cols.length, UNIFIED_COLUMN_COUNT, `Expected ${UNIFIED_COLUMN_COUNT} columns for ${storeType}, got ${cols.length}:\n${cols.map((c, i) => ` ${i + 1}. ${c}`).join('\n')}`);
44
+ expect(cols.length, `Expected ${UNIFIED_COLUMN_COUNT} columns for ${storeType}, got ${cols.length}:\n${cols.map((c, i) => ` ${i + 1}. ${c}`).join('\n')}`).toBe(UNIFIED_COLUMN_COUNT);
46
45
  });
47
46
  }
48
47
  });
@@ -53,7 +52,7 @@ describe('storage-store-manifest', () => {
53
52
  if (storeType === 'text')
54
53
  continue;
55
54
  const aliases = parseColumns(buildSelectList(storeType)).map(extractAlias);
56
- assert.deepStrictEqual(aliases, referenceAliases, `Column order mismatch between text and ${storeType}`);
55
+ expect(aliases, `Column order mismatch between text and ${storeType}`).toEqual(referenceAliases);
57
56
  }
58
57
  });
59
58
  });
@@ -62,7 +61,7 @@ describe('storage-store-manifest', () => {
62
61
  for (const storeType of allStoreTypes) {
63
62
  const selectList = buildSelectList(storeType);
64
63
  const expected = fieldTypeLiterals[storeType];
65
- assert.ok(selectList.includes(`'${expected}' as "field_type"`), `Expected field_type '${expected}' for ${storeType}`);
64
+ expect(selectList.includes(`'${expected}' as "field_type"`), `Expected field_type '${expected}' for ${storeType}`).toBe(true);
66
65
  }
67
66
  });
68
67
  });
@@ -71,7 +70,7 @@ describe('storage-store-manifest', () => {
71
70
  for (const storeType of allStoreTypes) {
72
71
  const cols = parseColumns(buildSelectList(storeType));
73
72
  const fieldTypeCol = cols[3];
74
- assert.ok(fieldTypeCol?.includes('field_type'), `Expected field_type at index 3 for ${storeType}, got: ${fieldTypeCol}`);
73
+ expect(fieldTypeCol?.includes('field_type'), `Expected field_type at index 3 for ${storeType}, got: ${fieldTypeCol}`).toBe(true);
75
74
  }
76
75
  });
77
76
  });
@@ -79,20 +78,20 @@ describe('storage-store-manifest', () => {
79
78
  it('text store maps value → text_value', () => {
80
79
  const cols = parseColumns(buildSelectList('text'));
81
80
  const textValueCol = cols.find((c) => c.includes('text_value'));
82
- assert.ok(textValueCol, 'text_value column not found');
83
- assert.ok(textValueCol.includes('value as "text_value"'), `Expected 'value as "text_value"', got: ${textValueCol}`);
81
+ expect(textValueCol, 'text_value column not found').toBeTruthy();
82
+ expect(textValueCol?.includes('value as "text_value"'), `Expected 'value as "text_value"', got: ${textValueCol}`).toBe(true);
84
83
  });
85
84
  it('boolean store maps value → boolean_value', () => {
86
85
  const cols = parseColumns(buildSelectList('boolean'));
87
86
  const boolCol = cols.find((c) => c.includes('boolean_value'));
88
- assert.ok(boolCol, 'boolean_value column not found');
89
- assert.ok(boolCol.includes('value as "boolean_value"'), `Expected 'value as "boolean_value"', got: ${boolCol}`);
87
+ expect(boolCol, 'boolean_value column not found').toBeTruthy();
88
+ expect(boolCol?.includes('value as "boolean_value"'), `Expected 'value as "boolean_value"', got: ${boolCol}`).toBe(true);
90
89
  });
91
90
  it('numeric store includes number_type, value_integer, value_decimal, value_float', () => {
92
91
  const cols = parseColumns(buildSelectList('numeric'));
93
92
  const colText = cols.join(' ');
94
93
  for (const field of ['number_type', 'value_integer', 'value_decimal', 'value_float']) {
95
- assert.ok(colText.includes(field), `Expected ${field} in numeric SELECT list`);
94
+ expect(colText.includes(field), `Expected ${field} in numeric SELECT list`).toBe(true);
96
95
  }
97
96
  });
98
97
  it('file store includes all file-specific columns', () => {
@@ -107,14 +106,14 @@ describe('storage-store-manifest', () => {
107
106
  'storage_provider',
108
107
  'storage_path',
109
108
  ]) {
110
- assert.ok(colText.includes(field), `Expected ${field} in file SELECT list`);
109
+ expect(colText.includes(field), `Expected ${field} in file SELECT list`).toBe(true);
111
110
  }
112
111
  });
113
112
  it('non-owning stores emit NULL for type-specific columns', () => {
114
113
  const cols = parseColumns(buildSelectList('text'));
115
114
  const numericCol = cols.find((c) => c.includes('number_type'));
116
- assert.ok(numericCol, 'number_type column not found');
117
- assert.ok(numericCol.includes('NULL::varchar'), `Expected NULL for number_type in text store, got: ${numericCol}`);
115
+ expect(numericCol, 'number_type column not found').toBeTruthy();
116
+ expect(numericCol?.includes('NULL::varchar'), `Expected NULL for number_type in text store, got: ${numericCol}`).toBe(true);
118
117
  });
119
118
  });
120
119
  describe('base columns', () => {
@@ -132,7 +131,7 @@ describe('storage-store-manifest', () => {
132
131
  const cols = parseColumns(buildSelectList(storeType));
133
132
  for (const baseName of baseNames) {
134
133
  const col = cols.find((c) => c.trim() === baseName);
135
- assert.ok(col, `Expected bare column '${baseName}' in ${storeType} SELECT list`);
134
+ expect(col, `Expected bare column '${baseName}' in ${storeType} SELECT list`).toBeTruthy();
136
135
  }
137
136
  }
138
137
  });
@@ -5,8 +5,7 @@
5
5
  *
6
6
  * Copyright (c) Infonomic Company Limited
7
7
  */
8
- import assert from 'node:assert';
9
- import { after, before, describe, it } from 'node:test';
8
+ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
10
9
  import { setupTestDB, teardownTestDB } from '../../../lib/test-helper.js';
11
10
  // Test database setup
12
11
  let commandBuilders;
@@ -211,7 +210,7 @@ const complexProductDocument = {
211
210
  // Global test variables
212
211
  let testCollection = {};
213
212
  describe('03 Document Creation and Versioning', () => {
214
- before(async () => {
213
+ beforeAll(async () => {
215
214
  // Connect to test database
216
215
  const testDB = setupTestDB([VersionsCollectionConfig]);
217
216
  commandBuilders = testDB.commandBuilders;
@@ -225,7 +224,7 @@ describe('03 Document Creation and Versioning', () => {
225
224
  testCollection = { id: collection.id, name: collection.path };
226
225
  console.log('Test collection created:', testCollection);
227
226
  });
228
- after(async () => {
227
+ afterAll(async () => {
229
228
  // Clean up test collection (cascades to documents)
230
229
  try {
231
230
  await commandBuilders.collections.delete(testCollection.id);
@@ -253,7 +252,7 @@ describe('03 Document Creation and Versioning', () => {
253
252
  status: 'draft',
254
253
  });
255
254
  console.log('Document created:', result);
256
- assert.notStrictEqual(result.document.document_id, null, 'Document creation failed');
255
+ expect(result.document.document_id, 'Document creation failed').not.toBe(null);
257
256
  });
258
257
  it('should create a document and document version with the same path', async () => {
259
258
  const timestamp = Date.now();
@@ -271,7 +270,7 @@ describe('03 Document Creation and Versioning', () => {
271
270
  status: 'draft',
272
271
  });
273
272
  console.log('firstVersion created:', firstVersion);
274
- assert.notStrictEqual(firstVersion.document.document_id, null, 'Document creation failed');
273
+ expect(firstVersion.document.document_id, 'Document creation failed').not.toBe(null);
275
274
  const secondVersion = await commandBuilders.documents.createDocumentVersion({
276
275
  documentId: firstVersion.document.document_id,
277
276
  collectionId: testCollection.id,
@@ -300,7 +299,7 @@ describe('03 Document Creation and Versioning', () => {
300
299
  locale: 'all',
301
300
  status: 'draft',
302
301
  });
303
- assert.notStrictEqual(firstVersion.document.document_id, null, 'Document creation failed');
302
+ expect(firstVersion.document.document_id, 'Document creation failed').not.toBe(null);
304
303
  const secondVersion = await commandBuilders.documents.createDocumentVersion({
305
304
  documentId: firstVersion.document.document_id,
306
305
  collectionId: testCollection.id,
@@ -312,7 +311,7 @@ describe('03 Document Creation and Versioning', () => {
312
311
  locale: 'all',
313
312
  status: 'draft',
314
313
  });
315
- assert.notStrictEqual(secondVersion.document.document_id, null, 'Document creation failed');
314
+ expect(secondVersion.document.document_id, 'Document creation failed').not.toBe(null);
316
315
  const thirdVersion = await commandBuilders.documents.createDocumentVersion({
317
316
  documentId: firstVersion.document.document_id,
318
317
  collectionId: testCollection.id,
@@ -324,7 +323,7 @@ describe('03 Document Creation and Versioning', () => {
324
323
  locale: 'all',
325
324
  status: 'draft',
326
325
  });
327
- assert.notStrictEqual(thirdVersion.document.document_id, null, 'Document creation failed');
326
+ expect(thirdVersion.document.document_id, 'Document creation failed').not.toBe(null);
328
327
  const versionHistory = await queryBuilders.documents.getDocumentHistory({
329
328
  collection_id: testCollection.id,
330
329
  document_id: firstVersion.document.document_id,
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@byline/db-postgres",
3
3
  "private": false,
4
4
  "license": "MPL-2.0",
5
- "version": "1.12.0",
5
+ "version": "1.12.2",
6
6
  "engines": {
7
7
  "node": ">=20.9.0"
8
8
  },
@@ -41,6 +41,11 @@
41
41
  "import": "./dist/database/schema/index.js",
42
42
  "require": "./dist/database/schema/index.js"
43
43
  },
44
+ "./testing": {
45
+ "types": "./dist/lib/test-db.d.ts",
46
+ "import": "./dist/lib/test-db.js",
47
+ "require": "./dist/lib/test-db.js"
48
+ },
44
49
  "./package.json": "./package.json"
45
50
  },
46
51
  "files": [
@@ -52,9 +57,9 @@
52
57
  "pg": "^8.20.0",
53
58
  "uuid": "^14.0.0",
54
59
  "zod": "^4.4.3",
55
- "@byline/admin": "1.12.0",
56
- "@byline/auth": "1.12.0",
57
- "@byline/core": "1.12.0"
60
+ "@byline/auth": "1.12.2",
61
+ "@byline/core": "1.12.2",
62
+ "@byline/admin": "1.12.2"
58
63
  },
59
64
  "devDependencies": {
60
65
  "@biomejs/biome": "2.4.15",
@@ -62,10 +67,12 @@
62
67
  "@types/pg": "^8.20.0",
63
68
  "chokidar": "^5.0.0",
64
69
  "chokidar-cli": "^3.0.0",
70
+ "dotenv": "^17.4.2",
65
71
  "drizzle-kit": "^0.31.10",
66
72
  "tsc-alias": "^1.8.17",
67
73
  "tsx": "^4.21.0",
68
- "typescript": "6.0.3"
74
+ "typescript": "6.0.3",
75
+ "vitest": "^4.1.5"
69
76
  },
70
77
  "publishConfig": {
71
78
  "access": "public",
@@ -83,8 +90,9 @@
83
90
  "drizzle:push": "tsc -p tsconfig.json && drizzle-kit push --config=drizzle.config.ts",
84
91
  "drizzle:drop": "drizzle-kit drop --config=drizzle.config.ts",
85
92
  "drizzle:seed": "tsx --no-warnings --env-file=.env ./src/database/seeds/index.ts",
86
- "test": "LOG_LEVEL=off tsx --env-file=.env --test --test-concurrency=1 $(find . -name \"*.test.ts\")",
87
- "test:one": "LOG_LEVEL=off tsx --no-warnings --env-file=.env --test",
93
+ "test": "echo 'db-postgres has no unit tests; run pnpm test:integration for the DB-backed suite.'",
94
+ "test:integration": "LOG_LEVEL=off vitest run --mode=integration",
95
+ "test:watch": "LOG_LEVEL=off vitest --mode=integration",
88
96
  "typecheck": "tsc --noEmit"
89
97
  }
90
98
  }