@elysiumjs/mnemosyne-drizzle 0.2.0 → 0.4.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 +112 -0
- package/dist/cache.d.ts +60 -0
- package/dist/commands/migration_run.command.d.ts +13 -0
- package/dist/commands/project.d.ts +11 -0
- package/dist/database.d.ts +82 -31
- package/dist/driver.d.ts +39 -0
- package/dist/drivers/bun-sql.d.ts +25 -0
- package/dist/drivers/bun-sql.js +1 -0
- package/dist/drivers/hyperdrive.d.ts +46 -0
- package/dist/drivers/hyperdrive.js +1 -0
- package/dist/drivers/node-postgres.d.ts +23 -0
- package/dist/drivers/node-postgres.js +1 -0
- package/dist/drivers/postgres-js.d.ts +25 -0
- package/dist/drivers/postgres-js.js +1 -0
- package/dist/drizzle.module.d.ts +3 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +11 -1
- package/dist/migrations.d.ts +12 -0
- package/dist/model.d.ts +9 -9
- package/dist/query.d.ts +28 -0
- package/dist/repository.d.ts +34 -6
- package/dist/tenancy.d.ts +25 -8
- package/package.json +63 -11
- package/.omc/state/agent-replay-3920b579-6d8e-4f5f-924a-319202936685.jsonl +0 -7
- package/.omc/state/sessions/3920b579-6d8e-4f5f-924a-319202936685/last-tool-error-state.json +0 -7
- package/.omc/state/sessions/3920b579-6d8e-4f5f-924a-319202936685/mission-state.json +0 -93
- package/.omc/state/sessions/3920b579-6d8e-4f5f-924a-319202936685/pre-tool-advisory-throttle.json +0 -18
- package/.omc/state/sessions/3920b579-6d8e-4f5f-924a-319202936685/subagent-tracking-state.json +0 -61
- package/.turbo/turbo-build.log +0 -3
- package/dist/commands/migration_generate.command.js +0 -1
- package/dist/commands/migration_run.command.js +0 -15
- package/dist/database.js +0 -1
- package/dist/drizzle.module.js +0 -1
- package/dist/migrations.js +0 -1
- package/dist/model.js +0 -1
- package/dist/repository.js +0 -1
- package/dist/table.js +0 -1
- package/dist/tenancy.js +0 -1
- package/scripts/minify.ts +0 -10
- package/src/commands/migration_generate.command.ts +0 -101
- package/src/commands/migration_run.command.ts +0 -160
- package/src/database.ts +0 -205
- package/src/drizzle.module.ts +0 -97
- package/src/index.ts +0 -47
- package/src/migrations.ts +0 -100
- package/src/model.ts +0 -178
- package/src/repository.ts +0 -113
- package/src/table.ts +0 -70
- package/src/tenancy.ts +0 -249
- package/tests/drizzle.module.test.ts +0 -201
- package/tests/migrations.test.ts +0 -123
- package/tests/model.test.ts +0 -362
- package/tests/setup.ts +0 -0
- package/tests/table.test.ts +0 -72
- package/tests/tenancy.test.ts +0 -212
- package/tsconfig.json +0 -12
package/src/index.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2026-present Workbud Technologies Inc. All rights reserved.
|
|
2
|
-
//
|
|
3
|
-
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
// you may not use this file except in compliance with the License.
|
|
5
|
-
// You may obtain a copy of the License at
|
|
6
|
-
//
|
|
7
|
-
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
//
|
|
9
|
-
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
// See the License for the specific language governing permissions and
|
|
13
|
-
// limitations under the License.
|
|
14
|
-
|
|
15
|
-
// Re-export drizzle-orm/pg-core with enhanced pgTable
|
|
16
|
-
export * from 'drizzle-orm';
|
|
17
|
-
export * from 'drizzle-orm/pg-core';
|
|
18
|
-
export type {
|
|
19
|
-
SelectedFields,
|
|
20
|
-
SelectedFieldsFlat,
|
|
21
|
-
SelectedFieldsOrdered,
|
|
22
|
-
TableConfig
|
|
23
|
-
} from 'drizzle-orm/pg-core';
|
|
24
|
-
export { pgTable, getTableBuilders } from './table';
|
|
25
|
-
|
|
26
|
-
// Re-exports
|
|
27
|
-
export { Database, DrizzleDatabaseCache } from './database';
|
|
28
|
-
export type { DrizzleConnectionProps, DrizzleConnection } from './database';
|
|
29
|
-
export {
|
|
30
|
-
DrizzleModel,
|
|
31
|
-
createSchemaFromDrizzle,
|
|
32
|
-
drizzleAdapter,
|
|
33
|
-
type DrizzleModelOptions
|
|
34
|
-
} from './model';
|
|
35
|
-
export { DrizzleModule, type DrizzleModuleConfig } from './drizzle.module';
|
|
36
|
-
export { DrizzleRepository } from './repository';
|
|
37
|
-
export {
|
|
38
|
-
DrizzleSchemaTenancy,
|
|
39
|
-
DrizzleRLSTenancy,
|
|
40
|
-
wrapTenantSchema,
|
|
41
|
-
registerTenantSchema,
|
|
42
|
-
getTenantSchema,
|
|
43
|
-
withRLS,
|
|
44
|
-
setConnectionTenant,
|
|
45
|
-
getSessionTenant,
|
|
46
|
-
createRLSPolicy
|
|
47
|
-
} from './tenancy';
|
package/src/migrations.ts
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2025-present Workbud Technologies Inc. All rights reserved.
|
|
2
|
-
//
|
|
3
|
-
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
// you may not use this file except in compliance with the License.
|
|
5
|
-
// You may obtain a copy of the License at
|
|
6
|
-
//
|
|
7
|
-
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
//
|
|
9
|
-
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
// See the License for the specific language governing permissions and
|
|
13
|
-
// limitations under the License.
|
|
14
|
-
|
|
15
|
-
import { basename, dirname } from 'node:path';
|
|
16
|
-
|
|
17
|
-
/** A migration recorded as applied in `elysium_migrations`. */
|
|
18
|
-
export type AppliedMigration = {
|
|
19
|
-
name: string;
|
|
20
|
-
appliedAt: Date;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/** The migrations to run, and the applied records to rename to their new names. */
|
|
24
|
-
export type MigrationPlan = {
|
|
25
|
-
pending: string[];
|
|
26
|
-
renames: { from: string; to: string }[];
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const FOLDER_MIGRATION_FILE = 'migration.sql';
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Gets the name under which a migration file is tracked. Drizzle Kit 1.0 stores each migration
|
|
33
|
-
* as `<folder>/migration.sql`, in which case the folder name identifies the migration.
|
|
34
|
-
* @author Axel Nana <axel.nana@workbud.com>
|
|
35
|
-
* @param path The path of the migration file.
|
|
36
|
-
*/
|
|
37
|
-
export const getMigrationName = (path: string): string =>
|
|
38
|
-
basename(path) === FOLDER_MIGRATION_FILE ? basename(dirname(path)) : basename(path);
|
|
39
|
-
|
|
40
|
-
/** Drops the `.sql` extension and the leading index or timestamp: `0001_users.sql` → `users`. */
|
|
41
|
-
const descriptiveName = (name: string): string =>
|
|
42
|
-
name
|
|
43
|
-
.replace(/\.sql$/, '')
|
|
44
|
-
.split('_')
|
|
45
|
-
.slice(1)
|
|
46
|
-
.join('_');
|
|
47
|
-
|
|
48
|
-
/** Reads the UTC `YYYYMMDDHHmmss` timestamp that starts a Drizzle Kit 1.0 folder name. */
|
|
49
|
-
const folderTime = (name: string): number | undefined => {
|
|
50
|
-
const match = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/.exec(name);
|
|
51
|
-
return match
|
|
52
|
-
? Date.UTC(+match[1]!, +match[2]! - 1, +match[3]!, +match[4]!, +match[5]!, +match[6]!)
|
|
53
|
-
: undefined;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Decides which migration files to run.
|
|
58
|
-
*
|
|
59
|
-
* `drizzle-kit up` moves each flat `<prefix>_<name>.sql` file into a
|
|
60
|
-
* `<timestamp>_<name>/migration.sql` folder, where the timestamp is when the migration was
|
|
61
|
-
* generated. An applied record whose flat file is gone is matched, in order, to a folder with
|
|
62
|
-
* the same `<name>` generated before the record was applied; that folder is not run again and
|
|
63
|
-
* the record is renamed. Folders generated later are new migrations and run.
|
|
64
|
-
* @author Axel Nana <axel.nana@workbud.com>
|
|
65
|
-
* @param files The paths of the migration files.
|
|
66
|
-
* @param applied The applied migrations.
|
|
67
|
-
*/
|
|
68
|
-
export const planMigrations = (files: string[], applied: AppliedMigration[]): MigrationPlan => {
|
|
69
|
-
const appliedNames = new Set(applied.map(({ name }) => name));
|
|
70
|
-
const fileNames = new Set(files.map(getMigrationName));
|
|
71
|
-
|
|
72
|
-
const moved = new Map<string, AppliedMigration[]>();
|
|
73
|
-
for (const record of [...applied].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
74
|
-
if (!record.name.endsWith('.sql') || fileNames.has(record.name)) continue;
|
|
75
|
-
const key = descriptiveName(record.name);
|
|
76
|
-
moved.set(key, [...(moved.get(key) ?? []), record]);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const plan: MigrationPlan = { pending: [], renames: [] };
|
|
80
|
-
for (const file of [...files].sort()) {
|
|
81
|
-
const name = getMigrationName(file);
|
|
82
|
-
if (appliedNames.has(name)) continue;
|
|
83
|
-
|
|
84
|
-
const from = basename(file) === FOLDER_MIGRATION_FILE ? takeMoved(moved, name) : undefined;
|
|
85
|
-
if (from) plan.renames.push({ from, to: name });
|
|
86
|
-
else plan.pending.push(file);
|
|
87
|
-
}
|
|
88
|
-
return plan;
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
/** Removes and returns the first moved record that the folder `name` can be the new home of. */
|
|
92
|
-
const takeMoved = (moved: Map<string, AppliedMigration[]>, name: string): string | undefined => {
|
|
93
|
-
const records = moved.get(descriptiveName(name));
|
|
94
|
-
const generatedAt = folderTime(name);
|
|
95
|
-
const index =
|
|
96
|
-
records?.findIndex(
|
|
97
|
-
({ appliedAt }) => generatedAt === undefined || generatedAt <= appliedAt.getTime()
|
|
98
|
-
) ?? -1;
|
|
99
|
-
return index < 0 ? undefined : records!.splice(index, 1)[0]!.name;
|
|
100
|
-
};
|
package/src/model.ts
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2026-present Workbud Technologies Inc. All rights reserved.
|
|
2
|
-
//
|
|
3
|
-
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
// you may not use this file except in compliance with the License.
|
|
5
|
-
// You may obtain a copy of the License at
|
|
6
|
-
//
|
|
7
|
-
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
//
|
|
9
|
-
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
// See the License for the specific language governing permissions and
|
|
13
|
-
// limitations under the License.
|
|
14
|
-
|
|
15
|
-
import type { ColumnMetadata, ModelAdapter } from '@elysiumjs/mnemosyne';
|
|
16
|
-
import type { PgColumn, PgTableWithColumns, TableConfig } from 'drizzle-orm/pg-core';
|
|
17
|
-
|
|
18
|
-
import { AbstractModel, createSchemaFromModel } from '@elysiumjs/mnemosyne';
|
|
19
|
-
import { getTableConfig } from 'drizzle-orm/pg-core';
|
|
20
|
-
|
|
21
|
-
import { getTableBuilders } from './table';
|
|
22
|
-
import { wrapTenantSchema } from './tenancy';
|
|
23
|
-
|
|
24
|
-
// ============================================================================
|
|
25
|
-
// Column Type Mapping
|
|
26
|
-
// ============================================================================
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Maps a Drizzle column to a normalized data type.
|
|
30
|
-
* @param col The Drizzle column to inspect.
|
|
31
|
-
* @returns A normalized data type string.
|
|
32
|
-
*/
|
|
33
|
-
const mapDrizzleDataType = (col: PgColumn): ColumnMetadata['dataType'] => {
|
|
34
|
-
if (col.columnType === 'PgUUID') return 'uuid';
|
|
35
|
-
if ((col as { dimensions?: number }).dimensions) return 'array';
|
|
36
|
-
|
|
37
|
-
// Drizzle 1.0 column data types are `<kind>` or `<kind> <constraint>` (e.g. `object json`).
|
|
38
|
-
const [kind, constraint] = col.dataType.split(' ');
|
|
39
|
-
switch (kind) {
|
|
40
|
-
case 'number':
|
|
41
|
-
return 'number';
|
|
42
|
-
case 'boolean':
|
|
43
|
-
return 'boolean';
|
|
44
|
-
case 'array':
|
|
45
|
-
return 'array';
|
|
46
|
-
case 'bigint':
|
|
47
|
-
return 'bigint';
|
|
48
|
-
case 'object':
|
|
49
|
-
switch (constraint) {
|
|
50
|
-
case 'json':
|
|
51
|
-
return 'json';
|
|
52
|
-
case 'date':
|
|
53
|
-
return 'date';
|
|
54
|
-
case 'buffer':
|
|
55
|
-
return 'buffer';
|
|
56
|
-
default:
|
|
57
|
-
return 'string';
|
|
58
|
-
}
|
|
59
|
-
default:
|
|
60
|
-
return 'string';
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
// ============================================================================
|
|
65
|
-
// Drizzle Model Adapter
|
|
66
|
-
// ============================================================================
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Drizzle-specific model adapter.
|
|
70
|
-
*
|
|
71
|
-
* Bridges Drizzle's `PgTableWithColumns` to the framework's
|
|
72
|
-
* normalized model metadata.
|
|
73
|
-
*
|
|
74
|
-
* @author Axel Nana <axel.nana@workbud.com>
|
|
75
|
-
*/
|
|
76
|
-
export const drizzleAdapter: ModelAdapter<PgTableWithColumns<any>> = {
|
|
77
|
-
getTableName(table) {
|
|
78
|
-
return getTableConfig(table).name;
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
getColumns(table): ColumnMetadata[] {
|
|
82
|
-
const config = getTableConfig(table);
|
|
83
|
-
return config.columns.map((col: PgColumn) => ({
|
|
84
|
-
name: col.name,
|
|
85
|
-
dataType: mapDrizzleDataType(col),
|
|
86
|
-
nullable: !col.notNull,
|
|
87
|
-
hasDefault: col.hasDefault,
|
|
88
|
-
isPrimaryKey:
|
|
89
|
-
col.primary || config.primaryKeys.some((pk) => pk.columns.some((c) => c.name === col.name))
|
|
90
|
-
}));
|
|
91
|
-
},
|
|
92
|
-
|
|
93
|
-
createTenantTable(table, tenant) {
|
|
94
|
-
const builders = getTableBuilders(table);
|
|
95
|
-
if (!builders) {
|
|
96
|
-
throw new Error(
|
|
97
|
-
`No column builders registered for table. ` +
|
|
98
|
-
`Use pgTable() from '@elysiumjs/mnemosyne-drizzle' for tenant support.`
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
const config = getTableConfig(table);
|
|
102
|
-
return wrapTenantSchema(tenant, config.name, builders) as PgTableWithColumns<any>;
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
// ============================================================================
|
|
107
|
-
// Schema Helper
|
|
108
|
-
// ============================================================================
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Creates Elysia validation schemas from a Drizzle table.
|
|
112
|
-
*
|
|
113
|
-
* This is a convenience wrapper around `createSchemaFromModel` that
|
|
114
|
-
* automatically extracts column metadata via the `drizzleAdapter`.
|
|
115
|
-
*
|
|
116
|
-
* @author Axel Nana <axel.nana@workbud.com>
|
|
117
|
-
* @param table The Drizzle table to generate schemas for.
|
|
118
|
-
* @param opts Schema generation options.
|
|
119
|
-
* @returns An Elysia validation schema.
|
|
120
|
-
*/
|
|
121
|
-
export const createSchemaFromDrizzle = (
|
|
122
|
-
table: PgTableWithColumns<any>,
|
|
123
|
-
opts?: { mode?: 'create' | 'update' | 'select' }
|
|
124
|
-
) => {
|
|
125
|
-
return createSchemaFromModel(drizzleAdapter.getColumns(table), opts);
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
// ============================================================================
|
|
129
|
-
// DrizzleModel Options
|
|
130
|
-
// ============================================================================
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Options for creating a DrizzleModel.
|
|
134
|
-
*/
|
|
135
|
-
export interface DrizzleModelOptions {
|
|
136
|
-
/**
|
|
137
|
-
* Enable tenant schema support for this model.
|
|
138
|
-
* @default false
|
|
139
|
-
*/
|
|
140
|
-
supportTenancy?: boolean;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// ============================================================================
|
|
144
|
-
// DrizzleModel Function
|
|
145
|
-
// ============================================================================
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Creates a model class backed by a Drizzle pgTable.
|
|
149
|
-
*
|
|
150
|
-
* @author Axel Nana <axel.nana@workbud.com>
|
|
151
|
-
* @param table The Drizzle table (created with enhanced pgTable).
|
|
152
|
-
* @param options Model configuration options.
|
|
153
|
-
* @returns A model class with Drizzle-backed static metadata.
|
|
154
|
-
*/
|
|
155
|
-
export const DrizzleModel = <TTable extends PgTableWithColumns<TableConfig>>(
|
|
156
|
-
table: TTable,
|
|
157
|
-
options?: DrizzleModelOptions
|
|
158
|
-
) => {
|
|
159
|
-
const config = getTableConfig(table);
|
|
160
|
-
const builders = getTableBuilders(table);
|
|
161
|
-
|
|
162
|
-
type TSelect = TTable['$inferSelect'];
|
|
163
|
-
type TInsert = TTable['$inferInsert'];
|
|
164
|
-
|
|
165
|
-
const Base = AbstractModel(config.name, builders ?? {}, drizzleAdapter, table);
|
|
166
|
-
|
|
167
|
-
// Override supportTenancy if specified
|
|
168
|
-
if (options?.supportTenancy !== undefined) {
|
|
169
|
-
(Base as any).supportTenancy = options.supportTenancy;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return Base as typeof Base & {
|
|
173
|
-
readonly $inferSelect: TSelect;
|
|
174
|
-
readonly $inferInsert: TInsert;
|
|
175
|
-
readonly $inferUpdate: Partial<TInsert>;
|
|
176
|
-
readonly table: TTable;
|
|
177
|
-
};
|
|
178
|
-
};
|
package/src/repository.ts
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2026-present Workbud Technologies Inc. All rights reserved.
|
|
2
|
-
//
|
|
3
|
-
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
// you may not use this file except in compliance with the License.
|
|
5
|
-
// You may obtain a copy of the License at
|
|
6
|
-
//
|
|
7
|
-
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
//
|
|
9
|
-
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
// See the License for the specific language governing permissions and
|
|
13
|
-
// limitations under the License.
|
|
14
|
-
|
|
15
|
-
import type { IdType, ModelClass } from '@elysiumjs/mnemosyne';
|
|
16
|
-
import type { PgTableWithColumns } from 'drizzle-orm/pg-core';
|
|
17
|
-
import type { DrizzleConnection } from './database';
|
|
18
|
-
|
|
19
|
-
import { AbstractRepository } from '@elysiumjs/mnemosyne';
|
|
20
|
-
import { eq } from 'drizzle-orm';
|
|
21
|
-
|
|
22
|
-
import { Database } from './database';
|
|
23
|
-
|
|
24
|
-
// ============================================================================
|
|
25
|
-
// DrizzleRepository Mixin
|
|
26
|
-
// ============================================================================
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Drizzle-specific repository mixin with concrete CRUD operations.
|
|
30
|
-
*
|
|
31
|
-
* Extends the abstract repository with Drizzle query builder calls
|
|
32
|
-
* for all standard CRUD methods.
|
|
33
|
-
*
|
|
34
|
-
* @author Axel Nana <axel.nana@workbud.com>
|
|
35
|
-
* @template TModel The model class type.
|
|
36
|
-
* @param model The model class to create the repository for.
|
|
37
|
-
* @returns A concrete repository class with CRUD methods.
|
|
38
|
-
*/
|
|
39
|
-
export const DrizzleRepository = <
|
|
40
|
-
TModel extends ModelClass<any, any, any, PgTableWithColumns<any>>
|
|
41
|
-
>(
|
|
42
|
-
model: TModel
|
|
43
|
-
) => {
|
|
44
|
-
type TSelect = TModel['$inferSelect'];
|
|
45
|
-
type TInsert = TModel['$inferInsert'];
|
|
46
|
-
type TUpdate = TModel['$inferUpdate'];
|
|
47
|
-
|
|
48
|
-
class R extends AbstractRepository<TModel, DrizzleConnection>(model, Database) {
|
|
49
|
-
public async all(): Promise<TSelect[]> {
|
|
50
|
-
return await this.db.select().from(model.table);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public async paginate(
|
|
54
|
-
count: number,
|
|
55
|
-
page: number = 1
|
|
56
|
-
): Promise<{ page: number; data: TSelect[]; total: number }> {
|
|
57
|
-
const total = await this.db.$count(model.table);
|
|
58
|
-
const offset = Math.max(page - 1, 0) * count;
|
|
59
|
-
return {
|
|
60
|
-
page,
|
|
61
|
-
total,
|
|
62
|
-
data: await this.db.select().from(model.table).offset(offset).limit(count)
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
public async find(id: IdType): Promise<TSelect | null> {
|
|
67
|
-
const [row] = await this.db.select().from(model.table).where(eq(model.table.id, id));
|
|
68
|
-
return (row ?? null) as TSelect | null;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
public async findBy<TKey extends keyof TSelect>(
|
|
72
|
-
column: TKey,
|
|
73
|
-
value: TSelect[TKey]
|
|
74
|
-
): Promise<TSelect | null> {
|
|
75
|
-
const [row] = await this.db.select().from(model.table).where(eq(model.table[column], value));
|
|
76
|
-
return (row ?? null) as TSelect | null;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
public async insert(data: TInsert): Promise<TSelect> {
|
|
80
|
-
const [row] = await this.db.insert(model.table).values(data).returning();
|
|
81
|
-
return row as TSelect;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
public async update(id: IdType, data: TUpdate): Promise<TSelect> {
|
|
85
|
-
const [row] = await this.db
|
|
86
|
-
.update(model.table)
|
|
87
|
-
.set(data)
|
|
88
|
-
.where(eq(model.table.id, id))
|
|
89
|
-
.returning();
|
|
90
|
-
return row as TSelect;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
public async updateAll(data: TUpdate): Promise<TSelect[]> {
|
|
94
|
-
return await this.db.update(model.table).set(data).returning();
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
public async delete(id: IdType): Promise<TSelect> {
|
|
98
|
-
const [row] = await this.db.delete(model.table).where(eq(model.table.id, id)).returning();
|
|
99
|
-
return row as TSelect;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
public async deleteAll(): Promise<TSelect[]> {
|
|
103
|
-
return await this.db.delete(model.table).returning();
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
public async exists(id: IdType): Promise<boolean> {
|
|
107
|
-
const count = await this.db.$count(model.table, eq(model.table.id, id));
|
|
108
|
-
return count > 0;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return R;
|
|
113
|
-
};
|
package/src/table.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2026-present Workbud Technologies Inc. All rights reserved.
|
|
2
|
-
//
|
|
3
|
-
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
// you may not use this file except in compliance with the License.
|
|
5
|
-
// You may obtain a copy of the License at
|
|
6
|
-
//
|
|
7
|
-
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
//
|
|
9
|
-
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
// See the License for the specific language governing permissions and
|
|
13
|
-
// limitations under the License.
|
|
14
|
-
|
|
15
|
-
import type { AnyPgColumnBuilder, PgTableWithColumns } from 'drizzle-orm/pg-core';
|
|
16
|
-
|
|
17
|
-
import { pgTable as drizzlePgTable } from 'drizzle-orm/pg-core';
|
|
18
|
-
|
|
19
|
-
// ============================================================================
|
|
20
|
-
// Column Builder Registry
|
|
21
|
-
// ============================================================================
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Maps tables to their original column builder definitions.
|
|
25
|
-
*
|
|
26
|
-
* When `pgTable()` is called, column builders are consumed and turned into
|
|
27
|
-
* built `PgColumn` instances. This registry preserves the original builder
|
|
28
|
-
* objects so that tenant tables can be re-created in different schemas.
|
|
29
|
-
*/
|
|
30
|
-
const tableRegistry = new WeakMap<PgTableWithColumns<any>, Record<string, AnyPgColumnBuilder>>();
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Retrieves the original column builders for a table.
|
|
34
|
-
* @param table The table created with enhanced pgTable.
|
|
35
|
-
* @returns The original column builder definitions, or `undefined`.
|
|
36
|
-
*/
|
|
37
|
-
export const getTableBuilders = (
|
|
38
|
-
table: PgTableWithColumns<any>
|
|
39
|
-
): Record<string, AnyPgColumnBuilder> | undefined => {
|
|
40
|
-
return tableRegistry.get(table);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
// ============================================================================
|
|
44
|
-
// Enhanced pgTable Function
|
|
45
|
-
// ============================================================================
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Creates a PostgreSQL table with automatic column builder registration.
|
|
49
|
-
*
|
|
50
|
-
* This is an enhanced version of Drizzle's `pgTable` that automatically
|
|
51
|
-
* registers column builders for tenancy support. It has the exact same
|
|
52
|
-
* signature and behavior as the original.
|
|
53
|
-
*
|
|
54
|
-
* @param tableName The name of the database table.
|
|
55
|
-
* @param columns The column definitions.
|
|
56
|
-
* @param extraConfig Optional extra Drizzle table configuration.
|
|
57
|
-
* @returns A Drizzle PostgreSQL table with registered column builders.
|
|
58
|
-
*/
|
|
59
|
-
export const pgTable = <
|
|
60
|
-
TTableName extends string,
|
|
61
|
-
TColumns extends Record<string, AnyPgColumnBuilder>
|
|
62
|
-
>(
|
|
63
|
-
tableName: TTableName,
|
|
64
|
-
columns: TColumns,
|
|
65
|
-
extraConfig?: (table: any) => any
|
|
66
|
-
) => {
|
|
67
|
-
const table = drizzlePgTable(tableName, columns, extraConfig);
|
|
68
|
-
tableRegistry.set(table, columns);
|
|
69
|
-
return table;
|
|
70
|
-
};
|