@proteinjs/db-driver-spanner 1.23.5 → 1.25.0
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/CHANGELOG.md +27 -0
- package/dist/generated/test/index.d.ts.map +1 -1
- package/dist/generated/test/index.js +17 -1
- package/dist/generated/test/index.js.map +1 -1
- package/dist/src/SpannerSchemaOperations.d.ts.map +1 -1
- package/dist/src/SpannerSchemaOperations.js +4 -1
- package/dist/src/SpannerSchemaOperations.js.map +1 -1
- package/dist/test/ColumnEncryption.test.d.ts +2 -0
- package/dist/test/ColumnEncryption.test.d.ts.map +1 -0
- package/dist/test/ColumnEncryption.test.js +482 -0
- package/dist/test/ColumnEncryption.test.js.map +1 -0
- package/dist/test/EncryptedSearch.test.d.ts +2 -0
- package/dist/test/EncryptedSearch.test.d.ts.map +1 -0
- package/dist/test/EncryptedSearch.test.js +455 -0
- package/dist/test/EncryptedSearch.test.js.map +1 -0
- package/dist/test/EncryptionLifecycleWalker.test.d.ts +2 -0
- package/dist/test/EncryptionLifecycleWalker.test.d.ts.map +1 -0
- package/dist/test/EncryptionLifecycleWalker.test.js +408 -0
- package/dist/test/EncryptionLifecycleWalker.test.js.map +1 -0
- package/dist/test/EncryptionPerf.test.d.ts +2 -0
- package/dist/test/EncryptionPerf.test.d.ts.map +1 -0
- package/dist/test/EncryptionPerf.test.js +278 -0
- package/dist/test/EncryptionPerf.test.js.map +1 -0
- package/dist/test/EncryptionSortAndUnique.test.d.ts +2 -0
- package/dist/test/EncryptionSortAndUnique.test.d.ts.map +1 -0
- package/dist/test/EncryptionSortAndUnique.test.js +229 -0
- package/dist/test/EncryptionSortAndUnique.test.js.map +1 -0
- package/dist/test/ReferenceColumnAdoptWidth.test.d.ts +2 -0
- package/dist/test/ReferenceColumnAdoptWidth.test.d.ts.map +1 -0
- package/dist/test/ReferenceColumnAdoptWidth.test.js +244 -0
- package/dist/test/ReferenceColumnAdoptWidth.test.js.map +1 -0
- package/dist/test/index.d.ts +1 -0
- package/dist/test/index.d.ts.map +1 -1
- package/dist/test/index.js +1 -0
- package/dist/test/index.js.map +1 -1
- package/dist/test/util/columnEncryptionTestHarness.d.ts +23 -0
- package/dist/test/util/columnEncryptionTestHarness.d.ts.map +1 -0
- package/dist/test/util/columnEncryptionTestHarness.js +136 -0
- package/dist/test/util/columnEncryptionTestHarness.js.map +1 -0
- package/dist/test/util/columnEncryptionTestTables.d.ts +75 -0
- package/dist/test/util/columnEncryptionTestTables.d.ts.map +1 -0
- package/dist/test/util/columnEncryptionTestTables.js +124 -0
- package/dist/test/util/columnEncryptionTestTables.js.map +1 -0
- package/dist/test/util/referenceAdoptWidthTestTables.d.ts +24 -0
- package/dist/test/util/referenceAdoptWidthTestTables.d.ts.map +1 -0
- package/dist/test/util/referenceAdoptWidthTestTables.js +35 -0
- package/dist/test/util/referenceAdoptWidthTestTables.js.map +1 -0
- package/dist/test/util/serviceUpdateVerbsTestTables.d.ts +2 -2
- package/generated/test/index.ts +17 -1
- package/package.json +6 -6
- package/src/SpannerSchemaOperations.ts +4 -1
- package/test/ColumnEncryption.test.ts +252 -0
- package/test/EncryptedSearch.test.ts +247 -0
- package/test/EncryptionLifecycleWalker.test.ts +223 -0
- package/test/EncryptionPerf.test.ts +156 -0
- package/test/EncryptionSortAndUnique.test.ts +130 -0
- package/test/ReferenceColumnAdoptWidth.test.ts +155 -0
- package/test/index.ts +1 -0
- package/test/util/columnEncryptionTestHarness.ts +54 -0
- package/test/util/columnEncryptionTestTables.ts +115 -0
- package/test/util/referenceAdoptWidthTestTables.ts +23 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { DataEncryptionKeyTable, EncryptedColumns, Table, TableManager } from '@proteinjs/db';
|
|
2
|
+
import { cascadeDeleteTestTables } from '@proteinjs/db/test';
|
|
3
|
+
import { SpannerDriver } from '@proteinjs/db-driver-spanner';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Schema loading for the column-encryption suites. `Db.delete` consults the reverse-cascade
|
|
7
|
+
* edge index over the WHOLE static table registry, and dynamic-reference edges are
|
|
8
|
+
* target-agnostic — so a delete from ANY table queries every registered table holding a
|
|
9
|
+
* `reverseCascadeDelete` dynamic-reference column (the cascade-delete test tables). A
|
|
10
|
+
* single-file run must therefore create those alongside the suite's own tables, plus the
|
|
11
|
+
* framework's data-key table. Serial `loadTable` (never batch `loadTables`): the registry
|
|
12
|
+
* deliberately holds same-name table pairs for schema-change tests, which a batch create
|
|
13
|
+
* would collide on.
|
|
14
|
+
*
|
|
15
|
+
* @internal This module is intended to be used only in tests.
|
|
16
|
+
*/
|
|
17
|
+
export const loadColumnEncryptionTestSchema = async (
|
|
18
|
+
tableManager: TableManager,
|
|
19
|
+
suiteTables: Table<any>[]
|
|
20
|
+
): Promise<void> => {
|
|
21
|
+
const tables: Table<any>[] = [
|
|
22
|
+
...Object.values(cascadeDeleteTestTables),
|
|
23
|
+
new DataEncryptionKeyTable(),
|
|
24
|
+
...suiteTables,
|
|
25
|
+
];
|
|
26
|
+
for (const table of tables) {
|
|
27
|
+
await tableManager.loadTable(table);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Clean-slate purge of a suite's tables (rows + their derived token tables) in beforeAll:
|
|
33
|
+
* a prior run killed mid-flight (or a teardown starved out by shared-emulator contention)
|
|
34
|
+
* leaves seeded rows behind, and exact-match search assertions must never depend on a
|
|
35
|
+
* previous process having exited cleanly.
|
|
36
|
+
*/
|
|
37
|
+
export const purgeColumnEncryptionTestRows = async (
|
|
38
|
+
spannerDriver: SpannerDriver,
|
|
39
|
+
suiteTables: Table<any>[]
|
|
40
|
+
): Promise<void> => {
|
|
41
|
+
const encryptedColumns = new EncryptedColumns();
|
|
42
|
+
const tables: Table<any>[] = [];
|
|
43
|
+
for (const table of suiteTables) {
|
|
44
|
+
tables.push(table);
|
|
45
|
+
const tokenTable = encryptedColumns.tokenTableFor(table);
|
|
46
|
+
if (tokenTable) {
|
|
47
|
+
tables.push(tokenTable);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
for (const table of tables) {
|
|
52
|
+
await spannerDriver.runDml(() => ({ sql: `DELETE FROM \`${table.name}\` WHERE TRUE` }));
|
|
53
|
+
}
|
|
54
|
+
};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Record, StringColumn, Table, withRecordColumns } from '@proteinjs/db';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tables for the column-encryption suites (`ColumnEncryption.test.ts`,
|
|
5
|
+
* `EncryptedSearch.test.ts`, `EncryptionSortAndUnique.test.ts`,
|
|
6
|
+
* `EncryptionLifecycleWalker.test.ts`, `EncryptionPerf.test.ts`).
|
|
7
|
+
*
|
|
8
|
+
* Defined here rather than in the test files so the reflection build registers them as
|
|
9
|
+
* `Table` loadables — the driver's statement generation and the framework's derived
|
|
10
|
+
* token-table subqueries resolve tables through `tableByName`.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Core seam suite: contains + equality + opaque encrypted + plaintext metadata. */
|
|
14
|
+
export interface EncNote extends Record {
|
|
15
|
+
scope: string;
|
|
16
|
+
title?: string | null; // encrypted + contains search
|
|
17
|
+
label?: string | null; // encrypted + equality lookup
|
|
18
|
+
body?: string | null; // encrypted, never queried by value
|
|
19
|
+
status?: string | null; // plaintext metadata
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class EncNoteTable extends Table<EncNote> {
|
|
23
|
+
name = 'db_test_enc_note';
|
|
24
|
+
columns: Table<EncNote>['columns'] = withRecordColumns<EncNote>({
|
|
25
|
+
scope: new StringColumn('scope', {}, 36),
|
|
26
|
+
title: new StringColumn('title', { encrypted: { searchable: 'contains' } }),
|
|
27
|
+
label: new StringColumn('label', { encrypted: { searchable: 'equality' } }),
|
|
28
|
+
body: new StringColumn('body', { encrypted: {} }, 'MAX'),
|
|
29
|
+
status: new StringColumn('status', { encrypted: false }),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Search-exactness suite: one contains column beside plaintext metadata. */
|
|
34
|
+
export interface EncSearchDoc extends Record {
|
|
35
|
+
scope: string;
|
|
36
|
+
title?: string | null; // encrypted + contains
|
|
37
|
+
name?: string | null; // encrypted + equality
|
|
38
|
+
kind?: string | null; // plaintext metadata
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class EncSearchDocTable extends Table<EncSearchDoc> {
|
|
42
|
+
name = 'db_test_enc_search_doc';
|
|
43
|
+
columns: Table<EncSearchDoc>['columns'] = withRecordColumns<EncSearchDoc>({
|
|
44
|
+
scope: new StringColumn('scope', {}, 36),
|
|
45
|
+
title: new StringColumn('title', { encrypted: { searchable: 'contains' } }),
|
|
46
|
+
name: new StringColumn('name', { encrypted: { searchable: 'equality' } }),
|
|
47
|
+
kind: new StringColumn('kind', { encrypted: false }),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** sortKey suite: the declared bounded-reveal native ORDER BY. */
|
|
52
|
+
export interface EncSortedItem extends Record {
|
|
53
|
+
scope: string;
|
|
54
|
+
title?: string | null; // encrypted + sortKey(3)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class EncSortedItemTable extends Table<EncSortedItem> {
|
|
58
|
+
name = 'db_test_enc_sorted_item';
|
|
59
|
+
columns: Table<EncSortedItem>['columns'] = withRecordColumns<EncSortedItem>({
|
|
60
|
+
scope: new StringColumn('scope', {}, 36),
|
|
61
|
+
title: new StringColumn('title', { encrypted: { searchable: 'contains', sortKey: { revealPrefix: 3 } } }),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Uniqueness suite: unique moves onto the equality fingerprint. */
|
|
66
|
+
export interface EncUniqueTag extends Record {
|
|
67
|
+
scope: string;
|
|
68
|
+
name?: string | null; // encrypted + equality, unique
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export class EncUniqueTagTable extends Table<EncUniqueTag> {
|
|
72
|
+
name = 'db_test_enc_unique_tag';
|
|
73
|
+
columns: Table<EncUniqueTag>['columns'] = withRecordColumns<EncUniqueTag>({
|
|
74
|
+
scope: new StringColumn('scope', {}, 36),
|
|
75
|
+
name: new StringColumn('name', { unique: { unique: true }, encrypted: { searchable: 'equality' } }),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Lifecycle-walker suite: encrypt / retokenize / decrypt / rotate transitions. */
|
|
80
|
+
export interface EncWalkRow extends Record {
|
|
81
|
+
scope: string;
|
|
82
|
+
title?: string | null; // encrypted + contains
|
|
83
|
+
body?: string | null; // encrypted, no search
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export class EncWalkRowTable extends Table<EncWalkRow> {
|
|
87
|
+
name = 'db_test_enc_walk_row';
|
|
88
|
+
columns: Table<EncWalkRow>['columns'] = withRecordColumns<EncWalkRow>({
|
|
89
|
+
scope: new StringColumn('scope', {}, 36),
|
|
90
|
+
title: new StringColumn('title', { encrypted: { searchable: 'contains' } }),
|
|
91
|
+
body: new StringColumn('body', { encrypted: {} }, 'MAX'),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Perf suite: encrypted-at-rest body vs a plaintext twin, 1k-row reads. */
|
|
96
|
+
export interface EncPerfRow extends Record {
|
|
97
|
+
scope: string;
|
|
98
|
+
body?: string | null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export class EncPerfRowTable extends Table<EncPerfRow> {
|
|
102
|
+
name = 'db_test_enc_perf_row';
|
|
103
|
+
columns: Table<EncPerfRow>['columns'] = withRecordColumns<EncPerfRow>({
|
|
104
|
+
scope: new StringColumn('scope', {}, 36),
|
|
105
|
+
body: new StringColumn('body', { encrypted: {} }, 'MAX'),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export class PlainPerfRowTable extends Table<EncPerfRow> {
|
|
110
|
+
name = 'db_test_plain_perf_row';
|
|
111
|
+
columns: Table<EncPerfRow>['columns'] = withRecordColumns<EncPerfRow>({
|
|
112
|
+
scope: new StringColumn('scope', {}, 36),
|
|
113
|
+
body: new StringColumn('body', { encrypted: false }, 'MAX'),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Record, Reference, ReferenceColumn, Table, withRecordColumns } from '@proteinjs/db';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The registered face of the width-adoption suite's table (ReferenceColumnAdoptWidth.test.ts):
|
|
5
|
+
* the retyped declaration — a reference adopting the column's pre-existing STRING(255) width.
|
|
6
|
+
* Declared here (not inline in the suite) because Db statement generation resolves tables by
|
|
7
|
+
* NAME through the reflection registry; the suite's string-era and stock-width variants of the
|
|
8
|
+
* same physical table stay inline there, reaching only instance-passed TableManager APIs.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export interface AdoptWidthRecord extends Record {
|
|
12
|
+
invitedBy?: Reference<Record> | null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const ADOPT_WIDTH_TABLE_NAME = 'db_test_reference_adopt_width';
|
|
16
|
+
export const ADOPT_WIDTH_TARGET_TABLE_NAME = 'db_test_reference_adopt_target';
|
|
17
|
+
|
|
18
|
+
export class ReferenceAdoptWidthTestTable extends Table<AdoptWidthRecord> {
|
|
19
|
+
name = ADOPT_WIDTH_TABLE_NAME;
|
|
20
|
+
columns = withRecordColumns<AdoptWidthRecord>({
|
|
21
|
+
invitedBy: new ReferenceColumn<Record>('invited_by', ADOPT_WIDTH_TARGET_TABLE_NAME, false, { maxLength: 255 }),
|
|
22
|
+
});
|
|
23
|
+
}
|