@objectstack/plugin-auth 4.0.3 → 4.0.5

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.
Files changed (40) hide show
  1. package/README.md +4 -1
  2. package/dist/index.d.mts +345 -19928
  3. package/dist/index.d.ts +345 -19928
  4. package/dist/index.js +411 -857
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +415 -837
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +35 -12
  9. package/.turbo/turbo-build.log +0 -78
  10. package/ARCHITECTURE.md +0 -176
  11. package/CHANGELOG.md +0 -325
  12. package/IMPLEMENTATION_SUMMARY.md +0 -192
  13. package/examples/basic-usage.ts +0 -107
  14. package/objectstack.config.ts +0 -24
  15. package/src/auth-manager.test.ts +0 -758
  16. package/src/auth-manager.ts +0 -338
  17. package/src/auth-plugin.test.ts +0 -443
  18. package/src/auth-plugin.ts +0 -292
  19. package/src/auth-schema-config.ts +0 -339
  20. package/src/index.ts +0 -16
  21. package/src/objectql-adapter.test.ts +0 -281
  22. package/src/objectql-adapter.ts +0 -279
  23. package/src/objects/auth-account.object.ts +0 -7
  24. package/src/objects/auth-session.object.ts +0 -7
  25. package/src/objects/auth-user.object.ts +0 -7
  26. package/src/objects/auth-verification.object.ts +0 -7
  27. package/src/objects/index.ts +0 -40
  28. package/src/objects/sys-account.object.ts +0 -111
  29. package/src/objects/sys-api-key.object.ts +0 -104
  30. package/src/objects/sys-invitation.object.ts +0 -93
  31. package/src/objects/sys-member.object.ts +0 -68
  32. package/src/objects/sys-organization.object.ts +0 -82
  33. package/src/objects/sys-session.object.ts +0 -84
  34. package/src/objects/sys-team-member.object.ts +0 -61
  35. package/src/objects/sys-team.object.ts +0 -69
  36. package/src/objects/sys-two-factor.object.ts +0 -73
  37. package/src/objects/sys-user-preference.object.ts +0 -82
  38. package/src/objects/sys-user.object.ts +0 -91
  39. package/src/objects/sys-verification.object.ts +0 -75
  40. package/tsconfig.json +0 -18
@@ -1,281 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- import { describe, it, expect, vi, beforeEach } from 'vitest';
4
- import {
5
- createObjectQLAdapter,
6
- createObjectQLAdapterFactory,
7
- AUTH_MODEL_TO_PROTOCOL,
8
- resolveProtocolName,
9
- } from './objectql-adapter';
10
- import {
11
- AUTH_USER_CONFIG,
12
- AUTH_SESSION_CONFIG,
13
- AUTH_ACCOUNT_CONFIG,
14
- AUTH_VERIFICATION_CONFIG,
15
- AUTH_ORGANIZATION_SCHEMA,
16
- AUTH_MEMBER_SCHEMA,
17
- AUTH_INVITATION_SCHEMA,
18
- AUTH_TEAM_SCHEMA,
19
- AUTH_TEAM_MEMBER_SCHEMA,
20
- AUTH_TWO_FACTOR_SCHEMA,
21
- AUTH_ORG_SESSION_FIELDS,
22
- buildOrganizationPluginSchema,
23
- buildTwoFactorPluginSchema,
24
- } from './auth-schema-config';
25
- import { SystemObjectName } from '@objectstack/spec/system';
26
- import type { IDataEngine } from '@objectstack/core';
27
-
28
- describe('AUTH_MODEL_TO_PROTOCOL mapping', () => {
29
- it('should map all four core better-auth models to sys_ protocol names', () => {
30
- expect(AUTH_MODEL_TO_PROTOCOL.user).toBe('sys_user');
31
- expect(AUTH_MODEL_TO_PROTOCOL.session).toBe('sys_session');
32
- expect(AUTH_MODEL_TO_PROTOCOL.account).toBe('sys_account');
33
- expect(AUTH_MODEL_TO_PROTOCOL.verification).toBe('sys_verification');
34
- });
35
-
36
- it('should align with SystemObjectName constants', () => {
37
- expect(AUTH_MODEL_TO_PROTOCOL.user).toBe(SystemObjectName.USER);
38
- expect(AUTH_MODEL_TO_PROTOCOL.session).toBe(SystemObjectName.SESSION);
39
- expect(AUTH_MODEL_TO_PROTOCOL.account).toBe(SystemObjectName.ACCOUNT);
40
- expect(AUTH_MODEL_TO_PROTOCOL.verification).toBe(SystemObjectName.VERIFICATION);
41
- });
42
- });
43
-
44
- describe('resolveProtocolName', () => {
45
- it('should resolve core models to sys_ prefixed names', () => {
46
- expect(resolveProtocolName('user')).toBe('sys_user');
47
- expect(resolveProtocolName('session')).toBe('sys_session');
48
- expect(resolveProtocolName('account')).toBe('sys_account');
49
- expect(resolveProtocolName('verification')).toBe('sys_verification');
50
- });
51
-
52
- it('should fall back to original name for unknown models', () => {
53
- expect(resolveProtocolName('organization')).toBe('organization');
54
- expect(resolveProtocolName('custom_model')).toBe('custom_model');
55
- });
56
- });
57
-
58
- describe('AUTH_*_CONFIG schema mappings', () => {
59
- it('should define correct modelName for all core models', () => {
60
- expect(AUTH_USER_CONFIG.modelName).toBe('sys_user');
61
- expect(AUTH_SESSION_CONFIG.modelName).toBe('sys_session');
62
- expect(AUTH_ACCOUNT_CONFIG.modelName).toBe('sys_account');
63
- expect(AUTH_VERIFICATION_CONFIG.modelName).toBe('sys_verification');
64
- });
65
-
66
- it('should map user camelCase fields to snake_case', () => {
67
- expect(AUTH_USER_CONFIG.fields).toEqual({
68
- emailVerified: 'email_verified',
69
- createdAt: 'created_at',
70
- updatedAt: 'updated_at',
71
- });
72
- });
73
-
74
- it('should map session camelCase fields to snake_case', () => {
75
- expect(AUTH_SESSION_CONFIG.fields).toEqual({
76
- userId: 'user_id',
77
- expiresAt: 'expires_at',
78
- createdAt: 'created_at',
79
- updatedAt: 'updated_at',
80
- ipAddress: 'ip_address',
81
- userAgent: 'user_agent',
82
- });
83
- });
84
-
85
- it('should map account camelCase fields to snake_case', () => {
86
- expect(AUTH_ACCOUNT_CONFIG.fields).toEqual({
87
- userId: 'user_id',
88
- providerId: 'provider_id',
89
- accountId: 'account_id',
90
- accessToken: 'access_token',
91
- refreshToken: 'refresh_token',
92
- idToken: 'id_token',
93
- accessTokenExpiresAt: 'access_token_expires_at',
94
- refreshTokenExpiresAt: 'refresh_token_expires_at',
95
- createdAt: 'created_at',
96
- updatedAt: 'updated_at',
97
- });
98
- });
99
-
100
- it('should map verification camelCase fields to snake_case', () => {
101
- expect(AUTH_VERIFICATION_CONFIG.fields).toEqual({
102
- expiresAt: 'expires_at',
103
- createdAt: 'created_at',
104
- updatedAt: 'updated_at',
105
- });
106
- });
107
- });
108
-
109
- describe('AUTH_*_SCHEMA plugin table mappings', () => {
110
- it('should define organization model mapping', () => {
111
- expect(AUTH_ORGANIZATION_SCHEMA.modelName).toBe('sys_organization');
112
- expect(AUTH_ORGANIZATION_SCHEMA.fields).toEqual({
113
- createdAt: 'created_at',
114
- updatedAt: 'updated_at',
115
- });
116
- });
117
-
118
- it('should define member model mapping', () => {
119
- expect(AUTH_MEMBER_SCHEMA.modelName).toBe('sys_member');
120
- expect(AUTH_MEMBER_SCHEMA.fields).toEqual({
121
- organizationId: 'organization_id',
122
- userId: 'user_id',
123
- createdAt: 'created_at',
124
- });
125
- });
126
-
127
- it('should define invitation model mapping', () => {
128
- expect(AUTH_INVITATION_SCHEMA.modelName).toBe('sys_invitation');
129
- expect(AUTH_INVITATION_SCHEMA.fields).toEqual({
130
- organizationId: 'organization_id',
131
- inviterId: 'inviter_id',
132
- expiresAt: 'expires_at',
133
- createdAt: 'created_at',
134
- teamId: 'team_id',
135
- });
136
- });
137
-
138
- it('should define team model mapping', () => {
139
- expect(AUTH_TEAM_SCHEMA.modelName).toBe('sys_team');
140
- expect(AUTH_TEAM_SCHEMA.fields).toEqual({
141
- organizationId: 'organization_id',
142
- createdAt: 'created_at',
143
- updatedAt: 'updated_at',
144
- });
145
- });
146
-
147
- it('should define team member model mapping', () => {
148
- expect(AUTH_TEAM_MEMBER_SCHEMA.modelName).toBe('sys_team_member');
149
- expect(AUTH_TEAM_MEMBER_SCHEMA.fields).toEqual({
150
- teamId: 'team_id',
151
- userId: 'user_id',
152
- createdAt: 'created_at',
153
- });
154
- });
155
-
156
- it('should define two-factor model mapping', () => {
157
- expect(AUTH_TWO_FACTOR_SCHEMA.modelName).toBe('sys_two_factor');
158
- expect(AUTH_TWO_FACTOR_SCHEMA.fields).toEqual({
159
- backupCodes: 'backup_codes',
160
- userId: 'user_id',
161
- });
162
- });
163
-
164
- it('should define org session additional fields', () => {
165
- expect(AUTH_ORG_SESSION_FIELDS).toEqual({
166
- activeOrganizationId: 'active_organization_id',
167
- activeTeamId: 'active_team_id',
168
- });
169
- });
170
- });
171
-
172
- describe('buildOrganizationPluginSchema', () => {
173
- it('should compose all org plugin table schemas', () => {
174
- const schema = buildOrganizationPluginSchema();
175
- expect(schema.organization).toBe(AUTH_ORGANIZATION_SCHEMA);
176
- expect(schema.member).toBe(AUTH_MEMBER_SCHEMA);
177
- expect(schema.invitation).toBe(AUTH_INVITATION_SCHEMA);
178
- expect(schema.team).toBe(AUTH_TEAM_SCHEMA);
179
- expect(schema.teamMember).toBe(AUTH_TEAM_MEMBER_SCHEMA);
180
- expect(schema.session.fields).toBe(AUTH_ORG_SESSION_FIELDS);
181
- });
182
- });
183
-
184
- describe('buildTwoFactorPluginSchema', () => {
185
- it('should compose two-factor model + user field schema', () => {
186
- const schema = buildTwoFactorPluginSchema();
187
- expect(schema.twoFactor).toBe(AUTH_TWO_FACTOR_SCHEMA);
188
- expect(schema.user.fields).toEqual({
189
- twoFactorEnabled: 'two_factor_enabled',
190
- });
191
- });
192
- });
193
-
194
- describe('createObjectQLAdapterFactory', () => {
195
- it('should return a function (adapter factory)', () => {
196
- const mockEngine = {
197
- insert: vi.fn(),
198
- findOne: vi.fn(),
199
- find: vi.fn(),
200
- count: vi.fn(),
201
- update: vi.fn(),
202
- delete: vi.fn(),
203
- } as unknown as IDataEngine;
204
-
205
- const factory = createObjectQLAdapterFactory(mockEngine);
206
- expect(typeof factory).toBe('function');
207
- });
208
- });
209
-
210
- describe('createObjectQLAdapter – legacy model name mapping', () => {
211
- let mockEngine: IDataEngine;
212
-
213
- beforeEach(() => {
214
- mockEngine = {
215
- insert: vi.fn().mockResolvedValue({ id: '1' }),
216
- findOne: vi.fn().mockResolvedValue({ id: '1' }),
217
- find: vi.fn().mockResolvedValue([]),
218
- count: vi.fn().mockResolvedValue(0),
219
- update: vi.fn().mockResolvedValue({ id: '1' }),
220
- delete: vi.fn().mockResolvedValue(undefined),
221
- } as unknown as IDataEngine;
222
- });
223
-
224
- it('create: should call dataEngine.insert with sys_ protocol name', async () => {
225
- const adapter = createObjectQLAdapter(mockEngine);
226
- await adapter.create({ model: 'user', data: { email: 'a@b.com' } });
227
- expect(mockEngine.insert).toHaveBeenCalledWith('sys_user', { email: 'a@b.com' });
228
- });
229
-
230
- it('findOne: should call dataEngine.findOne with sys_ protocol name', async () => {
231
- const adapter = createObjectQLAdapter(mockEngine);
232
- await adapter.findOne({
233
- model: 'session',
234
- where: [{ field: 'token', value: 'abc', operator: 'eq', connector: 'AND' }],
235
- });
236
- expect(mockEngine.findOne).toHaveBeenCalledWith('sys_session', expect.objectContaining({
237
- where: { token: 'abc' },
238
- }));
239
- });
240
-
241
- it('findMany: should call dataEngine.find with sys_ protocol name', async () => {
242
- const adapter = createObjectQLAdapter(mockEngine);
243
- await adapter.findMany({ model: 'account', limit: 10 });
244
- expect(mockEngine.find).toHaveBeenCalledWith('sys_account', expect.objectContaining({
245
- limit: 10,
246
- }));
247
- });
248
-
249
- it('count: should call dataEngine.count with sys_ protocol name', async () => {
250
- const adapter = createObjectQLAdapter(mockEngine);
251
- await adapter.count({ model: 'verification' });
252
- expect(mockEngine.count).toHaveBeenCalledWith('sys_verification', expect.anything());
253
- });
254
-
255
- it('update: should call dataEngine with sys_ protocol name', async () => {
256
- const adapter = createObjectQLAdapter(mockEngine);
257
- await adapter.update({
258
- model: 'user',
259
- where: [{ field: 'id', value: '1', operator: 'eq', connector: 'AND' }],
260
- update: { name: 'New' },
261
- });
262
- expect(mockEngine.findOne).toHaveBeenCalledWith('sys_user', expect.anything());
263
- expect(mockEngine.update).toHaveBeenCalledWith('sys_user', expect.objectContaining({ name: 'New', id: '1' }));
264
- });
265
-
266
- it('delete: should call dataEngine with sys_ protocol name', async () => {
267
- const adapter = createObjectQLAdapter(mockEngine);
268
- await adapter.delete({
269
- model: 'session',
270
- where: [{ field: 'id', value: '1', operator: 'eq', connector: 'AND' }],
271
- });
272
- expect(mockEngine.findOne).toHaveBeenCalledWith('sys_session', expect.anything());
273
- expect(mockEngine.delete).toHaveBeenCalledWith('sys_session', expect.anything());
274
- });
275
-
276
- it('should pass through unknown model names unchanged', async () => {
277
- const adapter = createObjectQLAdapter(mockEngine);
278
- await adapter.create({ model: 'organization', data: { name: 'Acme' } });
279
- expect(mockEngine.insert).toHaveBeenCalledWith('organization', { name: 'Acme' });
280
- });
281
- });
@@ -1,279 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- import type { IDataEngine } from '@objectstack/core';
4
- import { createAdapterFactory } from 'better-auth/adapters';
5
- import type { CleanedWhere } from 'better-auth/adapters';
6
- import { SystemObjectName } from '@objectstack/spec/system';
7
-
8
- /**
9
- * Mapping from better-auth model names to ObjectStack protocol object names.
10
- *
11
- * better-auth uses hardcoded model names ('user', 'session', 'account', 'verification')
12
- * while ObjectStack's protocol layer uses `sys_` prefixed names. This map bridges the two.
13
- */
14
- export const AUTH_MODEL_TO_PROTOCOL: Record<string, string> = {
15
- user: SystemObjectName.USER,
16
- session: SystemObjectName.SESSION,
17
- account: SystemObjectName.ACCOUNT,
18
- verification: SystemObjectName.VERIFICATION,
19
- };
20
-
21
- /**
22
- * Resolve a better-auth model name to the ObjectStack protocol object name.
23
- * Falls back to the original model name for custom / non-core models.
24
- */
25
- export function resolveProtocolName(model: string): string {
26
- return AUTH_MODEL_TO_PROTOCOL[model] ?? model;
27
- }
28
-
29
- // ---------------------------------------------------------------------------
30
- // Internal helpers
31
- // ---------------------------------------------------------------------------
32
-
33
- /**
34
- * Convert better-auth where clause to ObjectQL query format.
35
- *
36
- * Field names in the incoming {@link CleanedWhere} are expected to already be
37
- * in snake_case (transformed by `createAdapterFactory`).
38
- */
39
- function convertWhere(where: CleanedWhere[]): Record<string, any> {
40
- const filter: Record<string, any> = {};
41
-
42
- for (const condition of where) {
43
- const fieldName = condition.field;
44
-
45
- if (condition.operator === 'eq') {
46
- filter[fieldName] = condition.value;
47
- } else if (condition.operator === 'ne') {
48
- filter[fieldName] = { $ne: condition.value };
49
- } else if (condition.operator === 'in') {
50
- filter[fieldName] = { $in: condition.value };
51
- } else if (condition.operator === 'gt') {
52
- filter[fieldName] = { $gt: condition.value };
53
- } else if (condition.operator === 'gte') {
54
- filter[fieldName] = { $gte: condition.value };
55
- } else if (condition.operator === 'lt') {
56
- filter[fieldName] = { $lt: condition.value };
57
- } else if (condition.operator === 'lte') {
58
- filter[fieldName] = { $lte: condition.value };
59
- } else if (condition.operator === 'contains') {
60
- filter[fieldName] = { $regex: condition.value };
61
- }
62
- }
63
-
64
- return filter;
65
- }
66
-
67
- // ---------------------------------------------------------------------------
68
- // Adapter factory
69
- // ---------------------------------------------------------------------------
70
-
71
- /**
72
- * Create an ObjectQL adapter **factory** for better-auth.
73
- *
74
- * Uses better-auth's official `createAdapterFactory` so that model-name and
75
- * field-name transformations (declared via `modelName` / `fields` in the
76
- * betterAuth config) are applied **automatically** before any data reaches
77
- * ObjectQL. This eliminates the need for manual camelCase ↔ snake_case
78
- * conversion inside the adapter.
79
- *
80
- * The returned value is an `AdapterFactory` – a function of type
81
- * `(options: BetterAuthOptions) => DBAdapter` – which is the shape expected
82
- * by `betterAuth({ database: … })`.
83
- *
84
- * @param dataEngine - ObjectQL data engine instance
85
- * @returns better-auth AdapterFactory
86
- */
87
- export function createObjectQLAdapterFactory(dataEngine: IDataEngine) {
88
- return createAdapterFactory({
89
- config: {
90
- adapterId: 'objectql',
91
- // ObjectQL natively supports these types — no extra conversion needed
92
- supportsBooleans: true,
93
- supportsDates: true,
94
- supportsJSON: true,
95
- },
96
- adapter: () => ({
97
- create: async <T extends Record<string, any>>(
98
- { model, data, select: _select }: { model: string; data: T; select?: string[] },
99
- ): Promise<T> => {
100
- const result = await dataEngine.insert(model, data);
101
- return result as T;
102
- },
103
-
104
- findOne: async <T>(
105
- { model, where, select, join: _join }: { model: string; where: CleanedWhere[]; select?: string[]; join?: any },
106
- ): Promise<T | null> => {
107
- const filter = convertWhere(where);
108
-
109
- const result = await dataEngine.findOne(model, { where: filter, fields: select });
110
-
111
- return result ? (result as T) : null;
112
- },
113
-
114
- findMany: async <T>(
115
- { model, where, limit, offset, sortBy, join: _join }: {
116
- model: string; where?: CleanedWhere[]; limit: number;
117
- offset?: number; sortBy?: { field: string; direction: 'asc' | 'desc' }; join?: any;
118
- },
119
- ): Promise<T[]> => {
120
- const filter = where ? convertWhere(where) : {};
121
-
122
- const orderBy = sortBy
123
- ? [{ field: sortBy.field, order: sortBy.direction as 'asc' | 'desc' }]
124
- : undefined;
125
-
126
- const results = await dataEngine.find(model, {
127
- where: filter,
128
- limit: limit || 100,
129
- offset,
130
- orderBy,
131
- });
132
-
133
- return results as T[];
134
- },
135
-
136
- count: async (
137
- { model, where }: { model: string; where?: CleanedWhere[] },
138
- ): Promise<number> => {
139
- const filter = where ? convertWhere(where) : {};
140
- return await dataEngine.count(model, { where: filter });
141
- },
142
-
143
- update: async <T>(
144
- { model, where, update }: { model: string; where: CleanedWhere[]; update: T },
145
- ): Promise<T | null> => {
146
- const filter = convertWhere(where);
147
-
148
- // ObjectQL requires an ID for updates – find the record first
149
- const record = await dataEngine.findOne(model, { where: filter });
150
- if (!record) return null;
151
-
152
- const result = await dataEngine.update(model, { ...(update as any), id: record.id });
153
- return result ? (result as T) : null;
154
- },
155
-
156
- updateMany: async (
157
- { model, where, update }: { model: string; where: CleanedWhere[]; update: Record<string, any> },
158
- ): Promise<number> => {
159
- const filter = convertWhere(where);
160
-
161
- // Sequential updates: ObjectQL requires an ID per update
162
- const records = await dataEngine.find(model, { where: filter });
163
- for (const record of records) {
164
- await dataEngine.update(model, { ...update, id: record.id });
165
- }
166
- return records.length;
167
- },
168
-
169
- delete: async (
170
- { model, where }: { model: string; where: CleanedWhere[] },
171
- ): Promise<void> => {
172
- const filter = convertWhere(where);
173
-
174
- const record = await dataEngine.findOne(model, { where: filter });
175
- if (!record) return;
176
-
177
- await dataEngine.delete(model, { where: { id: record.id } });
178
- },
179
-
180
- deleteMany: async (
181
- { model, where }: { model: string; where: CleanedWhere[] },
182
- ): Promise<number> => {
183
- const filter = convertWhere(where);
184
-
185
- const records = await dataEngine.find(model, { where: filter });
186
- for (const record of records) {
187
- await dataEngine.delete(model, { where: { id: record.id } });
188
- }
189
- return records.length;
190
- },
191
- }),
192
- });
193
- }
194
-
195
- // ---------------------------------------------------------------------------
196
- // Legacy adapter (kept for backward compatibility)
197
- // ---------------------------------------------------------------------------
198
-
199
- /**
200
- * Create a raw ObjectQL adapter for better-auth (without factory wrapping).
201
- *
202
- * > **Prefer {@link createObjectQLAdapterFactory}** for production use.
203
- * > The factory version leverages `createAdapterFactory` and automatically
204
- * > handles model-name + field-name transformations declared in the
205
- * > better-auth config.
206
- *
207
- * This function is retained for direct / low-level usage where callers
208
- * manage field-name conversion themselves.
209
- *
210
- * @param dataEngine - ObjectQL data engine instance
211
- * @returns better-auth CustomAdapter (raw, without factory wrapping)
212
- */
213
- export function createObjectQLAdapter(dataEngine: IDataEngine) {
214
- return {
215
- create: async <T extends Record<string, any>>({ model, data, select: _select }: { model: string; data: T; select?: string[] }): Promise<T> => {
216
- const objectName = resolveProtocolName(model);
217
- const result = await dataEngine.insert(objectName, data);
218
- return result as T;
219
- },
220
-
221
- findOne: async <T>({ model, where, select, join: _join }: { model: string; where: CleanedWhere[]; select?: string[]; join?: any }): Promise<T | null> => {
222
- const objectName = resolveProtocolName(model);
223
- const filter = convertWhere(where);
224
- const result = await dataEngine.findOne(objectName, { where: filter, fields: select });
225
- return result ? result as T : null;
226
- },
227
-
228
- findMany: async <T>({ model, where, limit, offset, sortBy, join: _join }: { model: string; where?: CleanedWhere[]; limit: number; offset?: number; sortBy?: { field: string; direction: 'asc' | 'desc' }; join?: any }): Promise<T[]> => {
229
- const objectName = resolveProtocolName(model);
230
- const filter = where ? convertWhere(where) : {};
231
- const orderBy = sortBy ? [{ field: sortBy.field, order: sortBy.direction as 'asc' | 'desc' }] : undefined;
232
- const results = await dataEngine.find(objectName, { where: filter, limit: limit || 100, offset, orderBy });
233
- return results as T[];
234
- },
235
-
236
- count: async ({ model, where }: { model: string; where?: CleanedWhere[] }): Promise<number> => {
237
- const objectName = resolveProtocolName(model);
238
- const filter = where ? convertWhere(where) : {};
239
- return await dataEngine.count(objectName, { where: filter });
240
- },
241
-
242
- update: async <T>({ model, where, update }: { model: string; where: CleanedWhere[]; update: Record<string, any> }): Promise<T | null> => {
243
- const objectName = resolveProtocolName(model);
244
- const filter = convertWhere(where);
245
- const record = await dataEngine.findOne(objectName, { where: filter });
246
- if (!record) return null;
247
- const result = await dataEngine.update(objectName, { ...update, id: record.id });
248
- return result ? result as T : null;
249
- },
250
-
251
- updateMany: async ({ model, where, update }: { model: string; where: CleanedWhere[]; update: Record<string, any> }): Promise<number> => {
252
- const objectName = resolveProtocolName(model);
253
- const filter = convertWhere(where);
254
- const records = await dataEngine.find(objectName, { where: filter });
255
- for (const record of records) {
256
- await dataEngine.update(objectName, { ...update, id: record.id });
257
- }
258
- return records.length;
259
- },
260
-
261
- delete: async ({ model, where }: { model: string; where: CleanedWhere[] }): Promise<void> => {
262
- const objectName = resolveProtocolName(model);
263
- const filter = convertWhere(where);
264
- const record = await dataEngine.findOne(objectName, { where: filter });
265
- if (!record) return;
266
- await dataEngine.delete(objectName, { where: { id: record.id } });
267
- },
268
-
269
- deleteMany: async ({ model, where }: { model: string; where: CleanedWhere[] }): Promise<number> => {
270
- const objectName = resolveProtocolName(model);
271
- const filter = convertWhere(where);
272
- const records = await dataEngine.find(objectName, { where: filter });
273
- for (const record of records) {
274
- await dataEngine.delete(objectName, { where: { id: record.id } });
275
- }
276
- return records.length;
277
- },
278
- };
279
- }
@@ -1,7 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- /**
4
- * @deprecated Use `SysAccount` from `./sys-account.object` instead.
5
- * This re-export is kept for backward compatibility.
6
- */
7
- export { SysAccount as AuthAccount } from './sys-account.object.js';
@@ -1,7 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- /**
4
- * @deprecated Use `SysSession` from `./sys-session.object` instead.
5
- * This re-export is kept for backward compatibility.
6
- */
7
- export { SysSession as AuthSession } from './sys-session.object.js';
@@ -1,7 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- /**
4
- * @deprecated Use `SysUser` from `./sys-user.object` instead.
5
- * This re-export is kept for backward compatibility.
6
- */
7
- export { SysUser as AuthUser } from './sys-user.object.js';
@@ -1,7 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- /**
4
- * @deprecated Use `SysVerification` from `./sys-verification.object` instead.
5
- * This re-export is kept for backward compatibility.
6
- */
7
- export { SysVerification as AuthVerification } from './sys-verification.object.js';
@@ -1,40 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- /**
4
- * Auth Plugin — System Object Definitions (sys namespace)
5
- *
6
- * Canonical ObjectSchema definitions for all authentication-related system objects.
7
- * All objects belong to the `sys` namespace and follow the unified naming convention:
8
- * - File: `sys-{name}.object.ts`
9
- * - Export: `Sys{PascalCase}`
10
- * - Object name: `{name}` (snake_case, no prefix)
11
- * - Table name: `sys_{name}` (auto-derived from namespace)
12
- */
13
-
14
- // ── Core Auth Objects ──────────────────────────────────────────────────────
15
- export { SysUser } from './sys-user.object.js';
16
- export { SysSession } from './sys-session.object.js';
17
- export { SysAccount } from './sys-account.object.js';
18
- export { SysVerification } from './sys-verification.object.js';
19
-
20
- // ── Organization Objects ───────────────────────────────────────────────────
21
- export { SysOrganization } from './sys-organization.object.js';
22
- export { SysMember } from './sys-member.object.js';
23
- export { SysInvitation } from './sys-invitation.object.js';
24
- export { SysTeam } from './sys-team.object.js';
25
- export { SysTeamMember } from './sys-team-member.object.js';
26
-
27
- // ── Additional Auth Objects ────────────────────────────────────────────────
28
- export { SysApiKey } from './sys-api-key.object.js';
29
- export { SysTwoFactor } from './sys-two-factor.object.js';
30
- export { SysUserPreference } from './sys-user-preference.object.js';
31
-
32
- // ── Backward Compatibility (deprecated) ────────────────────────────────────
33
- /** @deprecated Use `SysUser` instead */
34
- export { AuthUser } from './auth-user.object.js';
35
- /** @deprecated Use `SysSession` instead */
36
- export { AuthSession } from './auth-session.object.js';
37
- /** @deprecated Use `SysAccount` instead */
38
- export { AuthAccount } from './auth-account.object.js';
39
- /** @deprecated Use `SysVerification` instead */
40
- export { AuthVerification } from './auth-verification.object.js';