@truto/ginger 1.0.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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +597 -0
  3. package/dist/adapters/bun-sqlite.d.ts +37 -0
  4. package/dist/adapters/bun-sqlite.d.ts.map +1 -0
  5. package/dist/adapters/bun-sqlite.js +136 -0
  6. package/dist/adapters/bun-sqlite.js.map +1 -0
  7. package/dist/adapters/durable-object.d.ts +40 -0
  8. package/dist/adapters/durable-object.d.ts.map +1 -0
  9. package/dist/adapters/durable-object.js +142 -0
  10. package/dist/adapters/durable-object.js.map +1 -0
  11. package/dist/adapters/index.d.ts +5 -0
  12. package/dist/adapters/index.d.ts.map +1 -0
  13. package/dist/adapters/index.js +3 -0
  14. package/dist/adapters/index.js.map +1 -0
  15. package/dist/crypto.d.ts +40 -0
  16. package/dist/crypto.d.ts.map +1 -0
  17. package/dist/crypto.js +148 -0
  18. package/dist/crypto.js.map +1 -0
  19. package/dist/errors.d.ts +64 -0
  20. package/dist/errors.d.ts.map +1 -0
  21. package/dist/errors.js +90 -0
  22. package/dist/errors.js.map +1 -0
  23. package/dist/example.d.ts +119 -0
  24. package/dist/example.d.ts.map +1 -0
  25. package/dist/example.js +297 -0
  26. package/dist/example.js.map +1 -0
  27. package/dist/index.d.ts +54 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +62 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/pagination.d.ts +31 -0
  32. package/dist/pagination.d.ts.map +1 -0
  33. package/dist/pagination.js +173 -0
  34. package/dist/pagination.js.map +1 -0
  35. package/dist/service.d.ts +81 -0
  36. package/dist/service.d.ts.map +1 -0
  37. package/dist/service.js +615 -0
  38. package/dist/service.js.map +1 -0
  39. package/dist/sql-builder.d.ts +48 -0
  40. package/dist/sql-builder.d.ts.map +1 -0
  41. package/dist/sql-builder.js +230 -0
  42. package/dist/sql-builder.js.map +1 -0
  43. package/dist/types.d.ts +266 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +2 -0
  46. package/dist/types.js.map +1 -0
  47. package/package.json +94 -0
package/dist/errors.js ADDED
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Base service error class
3
+ */
4
+ export class ServiceError extends Error {
5
+ code;
6
+ statusCode;
7
+ details;
8
+ constructor(message, code, statusCode = 500, details) {
9
+ super(message);
10
+ this.name = this.constructor.name;
11
+ this.code = code;
12
+ this.statusCode = statusCode;
13
+ this.details = details;
14
+ // Restore prototype chain for instanceof checks
15
+ Object.setPrototypeOf(this, new.target.prototype);
16
+ }
17
+ }
18
+ /**
19
+ * Resource not found error
20
+ */
21
+ export class NotFoundError extends ServiceError {
22
+ constructor(resource, id, details) {
23
+ super(`${resource} with id "${id}" not found`, 'NOT_FOUND', 404, details);
24
+ }
25
+ }
26
+ /**
27
+ * Validation error for schema validation failures
28
+ */
29
+ export class ValidationError extends ServiceError {
30
+ constructor(message, details) {
31
+ super(message, 'VALIDATION_ERROR', 400, details);
32
+ }
33
+ }
34
+ /**
35
+ * Authorization error for access control failures
36
+ */
37
+ export class AuthError extends ServiceError {
38
+ constructor(message = 'Access denied', details) {
39
+ super(message, 'AUTH_ERROR', 403, details);
40
+ }
41
+ }
42
+ /**
43
+ * Database operation error
44
+ */
45
+ export class DatabaseError extends ServiceError {
46
+ constructor(message, details) {
47
+ super(message, 'DATABASE_ERROR', 500, details);
48
+ }
49
+ }
50
+ /**
51
+ * Encryption/decryption error
52
+ */
53
+ export class EncryptionError extends ServiceError {
54
+ constructor(message, details) {
55
+ super(message, 'ENCRYPTION_ERROR', 500, details);
56
+ }
57
+ }
58
+ /**
59
+ * Hook execution error
60
+ */
61
+ export class HookError extends ServiceError {
62
+ constructor(hookPhase, methodName, originalError, details) {
63
+ super(`Hook error in ${hookPhase} phase of ${methodName}: ${originalError.message}`, 'HOOK_ERROR', 500, details ? { originalError, ...details } : { originalError });
64
+ }
65
+ }
66
+ /**
67
+ * Pagination cursor error
68
+ */
69
+ export class CursorError extends ServiceError {
70
+ constructor(message, details) {
71
+ super(message, 'CURSOR_ERROR', 400, details);
72
+ }
73
+ }
74
+ /**
75
+ * SQL builder error
76
+ */
77
+ export class SqlBuilderError extends ServiceError {
78
+ constructor(message, details) {
79
+ super(message, 'SQL_BUILDER_ERROR', 500, details);
80
+ }
81
+ }
82
+ /**
83
+ * Dependency injection error
84
+ */
85
+ export class DependencyError extends ServiceError {
86
+ constructor(message, details) {
87
+ super(message, 'DEPENDENCY_ERROR', 500, details);
88
+ }
89
+ }
90
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrB,IAAI,CAAQ;IACZ,UAAU,CAAQ;IAClB,OAAO,CAAU;IAEjC,YACE,OAAe,EACf,IAAY,EACZ,aAAqB,GAAG,EACxB,OAAiB;QAEjB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAA;QACjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QAEtB,gDAAgD;QAChD,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IACnD,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,YAAY;IAC7C,YAAY,QAAgB,EAAE,EAAmB,EAAE,OAAiB;QAClE,KAAK,CAAC,GAAG,QAAQ,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;IAC3E,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,YAAY;IAC/C,YAAY,OAAe,EAAE,OAAiB;QAC5C,KAAK,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;IAClD,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,SAAU,SAAQ,YAAY;IACzC,YAAY,UAAkB,eAAe,EAAE,OAAiB;QAC9D,KAAK,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;IAC5C,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,YAAY;IAC7C,YAAY,OAAe,EAAE,OAAiB;QAC5C,KAAK,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;IAChD,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,YAAY;IAC/C,YAAY,OAAe,EAAE,OAAiB;QAC5C,KAAK,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;IAClD,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,SAAU,SAAQ,YAAY;IACzC,YACE,SAAiB,EACjB,UAAkB,EAClB,aAAoB,EACpB,OAAiB;QAEjB,KAAK,CACH,iBAAiB,SAAS,aAAa,UAAU,KAAK,aAAa,CAAC,OAAO,EAAE,EAC7E,YAAY,EACZ,GAAG,EACH,OAAO,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAC5D,CAAA;IACH,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,WAAY,SAAQ,YAAY;IAC3C,YAAY,OAAe,EAAE,OAAiB;QAC5C,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;IAC9C,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,YAAY;IAC/C,YAAY,OAAe,EAAE,OAAiB;QAC5C,KAAK,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;IACnD,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,YAAY;IAC/C,YAAY,OAAe,EAAE,OAAiB;QAC5C,KAAK,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;IAClD,CAAC;CACF"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Complete example of using the Ginger library with:
3
+ * - Secret apiKey field
4
+ * - Join to teams table
5
+ * - Custom method withMembership
6
+ * - Hook that enforces tenant filtering via auth.user
7
+ */
8
+ import { z } from './index.js';
9
+ /**
10
+ * Factory function to create users service with tenant hooks and encryption keys
11
+ */
12
+ export declare function createUsersService(db: any, encryptionKeys: Record<string, string>): import("./service.js").Service<z.ZodObject<{
13
+ id: z.ZodNumber;
14
+ name: z.ZodString;
15
+ email: z.ZodString;
16
+ apiKey: z.ZodString;
17
+ tenantId: z.ZodString;
18
+ createdAt: z.ZodString;
19
+ updatedAt: z.ZodString;
20
+ }, z.core.$strip>, z.ZodObject<{
21
+ name: z.ZodString;
22
+ email: z.ZodString;
23
+ apiKey: z.ZodString;
24
+ tenantId: z.ZodString;
25
+ }, z.core.$strip>, z.ZodObject<{
26
+ name: z.ZodOptional<z.ZodString>;
27
+ email: z.ZodOptional<z.ZodString>;
28
+ apiKey: z.ZodOptional<z.ZodString>;
29
+ }, z.core.$strip>, {
30
+ teams: {
31
+ kind: "many";
32
+ localPk: string;
33
+ through: {
34
+ table: string;
35
+ from: string;
36
+ to: string;
37
+ };
38
+ remote: {
39
+ table: string;
40
+ pk: string;
41
+ select: string[];
42
+ alias: string;
43
+ };
44
+ where: string;
45
+ schema: z.ZodObject<{
46
+ id: z.ZodNumber;
47
+ name: z.ZodString;
48
+ description: z.ZodString;
49
+ }, z.core.$strip>;
50
+ };
51
+ }, readonly [{
52
+ readonly logicalName: "apiKey";
53
+ readonly columnName: "api_key_encrypted";
54
+ readonly keyId: "user-secrets";
55
+ }]>;
56
+ /**
57
+ * Example usage in a Cloudflare Worker
58
+ */
59
+ declare const _default: {
60
+ fetch(_request: Request, env: any, _ctx: any): Promise<Response>;
61
+ };
62
+ export default _default;
63
+ /**
64
+ * Cloudflare Worker Environment Setup:
65
+ *
66
+ * 1. Add these environment variables to your Cloudflare Worker:
67
+ * - ENCRYPTION_KEY_DEFAULT: A base64-encoded 256-bit encryption key
68
+ * - ENCRYPTION_KEY_USER_SECRETS: (Optional) A separate key for user secrets
69
+ *
70
+ * 2. Generate encryption keys using the library:
71
+ * ```typescript
72
+ * import { generateSecretKey } from './crypto.js'
73
+ * const key = await generateSecretKey()
74
+ * console.log('ENCRYPTION_KEY_DEFAULT=' + key)
75
+ * ```
76
+ *
77
+ * 3. Bind your D1 database as "DB" in wrangler.toml:
78
+ * ```toml
79
+ * [[d1_databases]]
80
+ * binding = "DB"
81
+ * database_name = "your-database"
82
+ * database_id = "your-database-id"
83
+ * ```
84
+ */
85
+ /**
86
+ * SQL schema for this example:
87
+ *
88
+ * ```sql
89
+ * CREATE TABLE users (
90
+ * id INTEGER PRIMARY KEY AUTOINCREMENT,
91
+ * name TEXT NOT NULL,
92
+ * email TEXT NOT NULL UNIQUE,
93
+ * api_key_encrypted TEXT NOT NULL,
94
+ * tenant_id TEXT NOT NULL,
95
+ * created_at TEXT NOT NULL,
96
+ * updated_at TEXT NOT NULL
97
+ * );
98
+ *
99
+ * CREATE TABLE teams (
100
+ * id INTEGER PRIMARY KEY AUTOINCREMENT,
101
+ * name TEXT NOT NULL,
102
+ * description TEXT,
103
+ * tenant_id TEXT NOT NULL,
104
+ * active INTEGER DEFAULT 1
105
+ * );
106
+ *
107
+ * CREATE TABLE user_teams (
108
+ * user_id INTEGER NOT NULL,
109
+ * team_id INTEGER NOT NULL,
110
+ * PRIMARY KEY (user_id, team_id),
111
+ * FOREIGN KEY (user_id) REFERENCES users(id),
112
+ * FOREIGN KEY (team_id) REFERENCES teams(id)
113
+ * );
114
+ *
115
+ * CREATE INDEX idx_users_tenant_id ON users(tenant_id);
116
+ * CREATE INDEX idx_teams_tenant_id ON teams(tenant_id);
117
+ * ```
118
+ */
119
+ //# sourceMappingURL=example.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example.d.ts","sourceRoot":"","sources":["../src/example.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAiB,CAAC,EAAqC,MAAM,YAAY,CAAA;AAoEhF;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,GAAG,EACP,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4DvC;AAED;;GAEG;;oBAEqB,OAAO,OAAO,GAAG,QAAQ,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC;;AADxE,wBAyHC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG"}
@@ -0,0 +1,297 @@
1
+ /**
2
+ * Complete example of using the Ginger library with:
3
+ * - Secret apiKey field
4
+ * - Join to teams table
5
+ * - Custom method withMembership
6
+ * - Hook that enforces tenant filtering via auth.user
7
+ */
8
+ import { createService, z } from './index.js';
9
+ // Schema definitions
10
+ const UserRowSchema = z.object({
11
+ id: z.number(),
12
+ name: z.string(),
13
+ email: z.string(),
14
+ apiKey: z.string(), // This will be encrypted
15
+ tenantId: z.string(),
16
+ createdAt: z.string(),
17
+ updatedAt: z.string(),
18
+ });
19
+ const UserCreateSchema = z.object({
20
+ name: z.string().min(1).max(255),
21
+ email: z.string().email().max(255),
22
+ apiKey: z.string().min(32).max(255),
23
+ tenantId: z.string().uuid(),
24
+ });
25
+ const UserUpdateSchema = z.object({
26
+ name: z.string().min(1).max(255).optional(),
27
+ email: z.string().email().max(255).optional(),
28
+ apiKey: z.string().min(32).max(255).optional(),
29
+ });
30
+ const TeamRowSchema = z.object({
31
+ id: z.number(),
32
+ name: z.string(),
33
+ description: z.string(),
34
+ });
35
+ // Join definitions
36
+ // Note: Auth-based filtering (like tenant_id checks) should NOT be embedded in join definitions.
37
+ // Instead, handle them through:
38
+ // 1. Hooks that modify where clauses before queries
39
+ // 2. Proper database design with foreign keys
40
+ // 3. Service-level filtering logic
41
+ // 4. Row-level security in the database
42
+ const userJoins = {
43
+ teams: {
44
+ kind: 'many',
45
+ localPk: 'id',
46
+ through: {
47
+ table: 'user_teams',
48
+ from: 'user_id',
49
+ to: 'team_id',
50
+ },
51
+ remote: {
52
+ table: 'teams',
53
+ pk: 'id',
54
+ select: ['id', 'name', 'description'],
55
+ alias: 'team',
56
+ },
57
+ where: 'teams.active = 1',
58
+ schema: TeamRowSchema,
59
+ },
60
+ };
61
+ // Secret field definitions
62
+ const userSecrets = [
63
+ {
64
+ logicalName: 'apiKey',
65
+ columnName: 'api_key_encrypted',
66
+ keyId: 'user-secrets',
67
+ },
68
+ ];
69
+ /**
70
+ * Factory function to create users service with tenant hooks and encryption keys
71
+ */
72
+ export function createUsersService(db, encryptionKeys) {
73
+ return createService({
74
+ table: 'users',
75
+ db,
76
+ rowSchema: UserRowSchema,
77
+ createSchema: UserCreateSchema,
78
+ updateSchema: UserUpdateSchema,
79
+ joins: userJoins,
80
+ secrets: userSecrets,
81
+ primaryKey: 'id',
82
+ defaultOrderBy: { column: 'created_at', direction: 'desc' },
83
+ encryptionKeys, // Pass encryption keys directly
84
+ hooks: {
85
+ // Enforce tenant filtering on all operations
86
+ list: {
87
+ before: async (ctx) => {
88
+ if (!ctx.auth.user?.tenantId) {
89
+ throw new Error('User must have a tenant ID');
90
+ }
91
+ // Add tenant filter to where clause
92
+ if (!ctx.params.where) {
93
+ ctx.params.where = {};
94
+ }
95
+ ctx.params.where.tenantId = ctx.auth.user.tenantId;
96
+ // For joins that need tenant filtering, you can:
97
+ // 1. Ensure proper foreign key relationships in your database schema
98
+ // 2. Use additional where clauses on the main query
99
+ // 3. Implement custom filtering logic in hooks
100
+ // The join definitions remain clean and auth-agnostic
101
+ },
102
+ },
103
+ get: {
104
+ before: async (ctx) => {
105
+ if (!ctx.auth.user?.tenantId) {
106
+ throw new Error('User must have a tenant ID');
107
+ }
108
+ // This would be handled by ensuring the ID belongs to the tenant
109
+ // In practice, you'd modify the query to include tenant check
110
+ },
111
+ },
112
+ create: {
113
+ before: async (ctx) => {
114
+ if (!ctx.auth.user?.tenantId) {
115
+ throw new Error('User must have a tenant ID');
116
+ }
117
+ // Ensure created records belong to the user's tenant
118
+ ctx.data.tenantId = ctx.auth.user.tenantId;
119
+ ctx.data.createdAt = new Date().toISOString();
120
+ ctx.data.updatedAt = new Date().toISOString();
121
+ },
122
+ },
123
+ update: {
124
+ before: async (ctx) => {
125
+ ctx.data.updatedAt = new Date().toISOString();
126
+ },
127
+ },
128
+ },
129
+ });
130
+ }
131
+ /**
132
+ * Example usage in a Cloudflare Worker
133
+ */
134
+ export default {
135
+ async fetch(_request, env, _ctx) {
136
+ // Get encryption keys from Cloudflare environment variables/secrets
137
+ const encryptionKeys = {
138
+ default: env.ENCRYPTION_KEY_DEFAULT, // Store as base64 encoded key
139
+ 'user-secrets': env.ENCRYPTION_KEY_USER_SECRETS || env.ENCRYPTION_KEY_DEFAULT,
140
+ };
141
+ // Initialize the service with the database binding and encryption keys
142
+ const usersService = createService({
143
+ table: 'users',
144
+ db: env.DB, // Cloudflare D1 binding
145
+ rowSchema: UserRowSchema,
146
+ createSchema: UserCreateSchema,
147
+ updateSchema: UserUpdateSchema,
148
+ joins: userJoins,
149
+ secrets: userSecrets,
150
+ encryptionKeys, // Pass encryption keys directly
151
+ hooks: {
152
+ // Enforce tenant filtering on all operations
153
+ list: {
154
+ before: async (ctx) => {
155
+ if (!ctx.auth.user?.tenantId) {
156
+ throw new Error('User must have a tenant ID');
157
+ }
158
+ // Add tenant filter to where clause
159
+ if (!ctx.params.where) {
160
+ ctx.params.where = {};
161
+ }
162
+ ctx.params.where.tenantId = ctx.auth.user.tenantId;
163
+ // For joins that need tenant filtering, you can:
164
+ // 1. Ensure proper foreign key relationships in your database schema
165
+ // 2. Use additional where clauses on the main query
166
+ // 3. Implement custom filtering logic in hooks
167
+ // The join definitions remain clean and auth-agnostic
168
+ },
169
+ },
170
+ create: {
171
+ before: async (ctx) => {
172
+ if (!ctx.auth.user?.tenantId) {
173
+ throw new Error('User must have a tenant ID');
174
+ }
175
+ // Ensure created records belong to the user's tenant
176
+ ctx.data.tenantId = ctx.auth.user.tenantId;
177
+ ctx.data.createdAt = new Date().toISOString();
178
+ ctx.data.updatedAt = new Date().toISOString();
179
+ },
180
+ },
181
+ },
182
+ });
183
+ try {
184
+ // Example: Create a new user
185
+ const newUser = await usersService.create({
186
+ name: 'John Doe',
187
+ email: 'john@example.com',
188
+ apiKey: 'sk_ex_abcdef1234567890abcdef1234567890',
189
+ tenantId: 'tenant-123',
190
+ }, {
191
+ auth: {
192
+ user: {
193
+ id: 'current-user-id',
194
+ tenantId: 'tenant-123',
195
+ roles: ['admin'],
196
+ },
197
+ },
198
+ });
199
+ // Example: List users with pagination
200
+ const users = await usersService.list({
201
+ auth: {
202
+ user: {
203
+ id: 'current-user-id',
204
+ tenantId: 'tenant-123',
205
+ roles: ['admin'],
206
+ },
207
+ },
208
+ limit: 10,
209
+ include: { teams: true },
210
+ orderBy: [{ column: 'created_at', direction: 'desc' }],
211
+ });
212
+ // Example: Get a user with secrets included
213
+ const userWithSecrets = await usersService.get(newUser.id, {
214
+ auth: {
215
+ user: {
216
+ id: 'current-user-id',
217
+ tenantId: 'tenant-123',
218
+ roles: ['admin'],
219
+ },
220
+ },
221
+ includeSecrets: true, // This will decrypt the API key
222
+ });
223
+ return new Response(JSON.stringify({
224
+ newUser,
225
+ users,
226
+ userWithSecrets,
227
+ }), {
228
+ headers: { 'content-type': 'application/json' },
229
+ });
230
+ }
231
+ catch (error) {
232
+ return new Response(JSON.stringify({
233
+ error: error instanceof Error ? error.message : 'Unknown error',
234
+ }), {
235
+ status: 500,
236
+ headers: { 'content-type': 'application/json' },
237
+ });
238
+ }
239
+ },
240
+ };
241
+ /**
242
+ * Cloudflare Worker Environment Setup:
243
+ *
244
+ * 1. Add these environment variables to your Cloudflare Worker:
245
+ * - ENCRYPTION_KEY_DEFAULT: A base64-encoded 256-bit encryption key
246
+ * - ENCRYPTION_KEY_USER_SECRETS: (Optional) A separate key for user secrets
247
+ *
248
+ * 2. Generate encryption keys using the library:
249
+ * ```typescript
250
+ * import { generateSecretKey } from './crypto.js'
251
+ * const key = await generateSecretKey()
252
+ * console.log('ENCRYPTION_KEY_DEFAULT=' + key)
253
+ * ```
254
+ *
255
+ * 3. Bind your D1 database as "DB" in wrangler.toml:
256
+ * ```toml
257
+ * [[d1_databases]]
258
+ * binding = "DB"
259
+ * database_name = "your-database"
260
+ * database_id = "your-database-id"
261
+ * ```
262
+ */
263
+ /**
264
+ * SQL schema for this example:
265
+ *
266
+ * ```sql
267
+ * CREATE TABLE users (
268
+ * id INTEGER PRIMARY KEY AUTOINCREMENT,
269
+ * name TEXT NOT NULL,
270
+ * email TEXT NOT NULL UNIQUE,
271
+ * api_key_encrypted TEXT NOT NULL,
272
+ * tenant_id TEXT NOT NULL,
273
+ * created_at TEXT NOT NULL,
274
+ * updated_at TEXT NOT NULL
275
+ * );
276
+ *
277
+ * CREATE TABLE teams (
278
+ * id INTEGER PRIMARY KEY AUTOINCREMENT,
279
+ * name TEXT NOT NULL,
280
+ * description TEXT,
281
+ * tenant_id TEXT NOT NULL,
282
+ * active INTEGER DEFAULT 1
283
+ * );
284
+ *
285
+ * CREATE TABLE user_teams (
286
+ * user_id INTEGER NOT NULL,
287
+ * team_id INTEGER NOT NULL,
288
+ * PRIMARY KEY (user_id, team_id),
289
+ * FOREIGN KEY (user_id) REFERENCES users(id),
290
+ * FOREIGN KEY (team_id) REFERENCES teams(id)
291
+ * );
292
+ *
293
+ * CREATE INDEX idx_users_tenant_id ON users(tenant_id);
294
+ * CREATE INDEX idx_teams_tenant_id ON teams(tenant_id);
295
+ * ```
296
+ */
297
+ //# sourceMappingURL=example.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example.js","sourceRoot":"","sources":["../src/example.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Ginger — A type-safe SQLite data access layer
3
+ *
4
+ * Works with Cloudflare D1, Bun SQLite, and Durable Object SqlStorage.
5
+ *
6
+ * Features:
7
+ * - Cursor-based pagination
8
+ * - Type-safe joins with conditional inclusion
9
+ * - AES-256-GCM encryption for secret fields
10
+ * - Comprehensive hook system
11
+ * - Dependency injection
12
+ * - Safe SQL generation
13
+ */
14
+ export { Service } from './service.js';
15
+ export type { AuthContext, BaseCtx, BaseService, ComputeJoins, CountParams, CreateParams, CursorToken, Database, ExecResult, PreparedStatement, QueryResult, DeleteParams, ErrorCtx, GetParams, Hook, HookMap, HookPhase, JoinDef, JoinKind, KeyProvider, ListParams, ListResult, MethodName, MethodOptions, OrderBy, OrderDirection, QueryParams, SecretFieldDef, ServiceCreate, ServiceDeps, ServiceOptions, ServiceRow, ServiceUpdate, UpdateParams, } from './types.js';
16
+ export { AuthError, CursorError, DatabaseError, DependencyError, EncryptionError, HookError, NotFoundError, ServiceError, SqlBuilderError, ValidationError, } from './errors.js';
17
+ export { decrypt, decryptSecrets, DefaultKeyProvider, encrypt, encryptSecrets, generateSecretKey, getSecretColumns, getSecretLogicalNames, } from './crypto.js';
18
+ export { buildCursorConditions, createCursor, decodeCursor, encodeCursor, getDefaultOrderBy, reverseOrderBy, validateOrderBy, } from './pagination.js';
19
+ export { buildCount, buildDelete, buildInsert, buildSelect, buildSelectById, buildUpdate, escapeColumn, escapeTable, } from './sql-builder.js';
20
+ export { fromBunSqlite, fromDurableObjectStorage } from './adapters/index.js';
21
+ export type { BunSqliteDatabase, BunSqliteStatement, DurableObjectSqlStorage, SqlStorageCursor, } from './adapters/index.js';
22
+ export * as z from 'zod/v4';
23
+ /**
24
+ * Create a new service instance with the provided configuration
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * import { createService, z } from 'ginger'
29
+ *
30
+ * const userService = createService({
31
+ * table: 'users',
32
+ * db, // Database instance (D1 binding, fromBunSqlite, or fromDurableObjectStorage)
33
+ * rowSchema: z.object({
34
+ * id: z.number(),
35
+ * name: z.string(),
36
+ * email: z.string(),
37
+ * }),
38
+ * createSchema: z.object({
39
+ * name: z.string(),
40
+ * email: z.string(),
41
+ * }),
42
+ * updateSchema: z.object({
43
+ * name: z.string().optional(),
44
+ * email: z.string().optional(),
45
+ * }),
46
+ * })
47
+ * ```
48
+ */
49
+ export declare function createService<TRow extends import('zod/v4').ZodTypeAny, TCreate extends import('zod/v4').ZodTypeAny, TUpdate extends import('zod/v4').ZodTypeAny, TJoins extends Record<string, import('./types.js').JoinDef> = Record<string, never>, TSecrets extends readonly import('./types.js').SecretFieldDef[] | undefined = undefined>(options: import('./types.js').ServiceOptions<TRow, TCreate, TUpdate, TJoins, TSecrets>): import('./service.js').Service<TRow, TCreate, TUpdate, TJoins, TSecrets>;
50
+ declare const _default: {
51
+ createService: typeof createService;
52
+ };
53
+ export default _default;
54
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAItC,YAAY,EACV,WAAW,EACX,OAAO,EACP,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,WAAW,EAEX,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,OAAO,EACP,SAAS,EAET,OAAO,EACP,QAAQ,EACR,WAAW,EAEX,UAAU,EACV,UAAU,EACV,UAAU,EACV,aAAa,EACb,OAAO,EACP,cAAc,EACd,WAAW,EACX,cAAc,EACd,aAAa,EACb,WAAW,EACX,cAAc,EAEd,UAAU,EACV,aAAa,EACb,YAAY,GACb,MAAM,YAAY,CAAA;AAGnB,OAAO,EACL,SAAS,EACT,WAAW,EACX,aAAa,EACb,eAAe,EACf,eAAe,EACf,SAAS,EACT,aAAa,EACb,YAAY,EACZ,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAA;AAGpB,OAAO,EACL,OAAO,EACP,cAAc,EACd,kBAAkB,EAClB,OAAO,EACP,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,aAAa,CAAA;AAGpB,OAAO,EACL,qBAAqB,EACrB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,eAAe,GAChB,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EACL,UAAU,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,eAAe,EACf,WAAW,EACX,YAAY,EACZ,WAAW,GACZ,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA;AAC7E,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,qBAAqB,CAAA;AAG5B,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAA;AAE3B;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,aAAa,CAC3B,IAAI,SAAS,OAAO,QAAQ,EAAE,UAAU,EACxC,OAAO,SAAS,OAAO,QAAQ,EAAE,UAAU,EAC3C,OAAO,SAAS,OAAO,QAAQ,EAAE,UAAU,EAC3C,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,YAAY,EAAE,OAAO,CAAC,GAAG,MAAM,CAClE,MAAM,EACN,KAAK,CACN,EACD,QAAQ,SACJ,SAAS,OAAO,YAAY,EAAE,cAAc,EAAE,GAC9C,SAAS,GAAG,SAAS,EAEzB,OAAO,EAAE,OAAO,YAAY,EAAE,cAAc,CAC1C,IAAI,EACJ,OAAO,EACP,OAAO,EACP,MAAM,EACN,QAAQ,CACT,GACA,OAAO,cAAc,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAE1E;;;;AAGD,wBAEC"}
package/dist/index.js ADDED
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Ginger — A type-safe SQLite data access layer
3
+ *
4
+ * Works with Cloudflare D1, Bun SQLite, and Durable Object SqlStorage.
5
+ *
6
+ * Features:
7
+ * - Cursor-based pagination
8
+ * - Type-safe joins with conditional inclusion
9
+ * - AES-256-GCM encryption for secret fields
10
+ * - Comprehensive hook system
11
+ * - Dependency injection
12
+ * - Safe SQL generation
13
+ */
14
+ // Main Service class
15
+ export { Service } from './service.js';
16
+ import { Service } from './service.js';
17
+ // Error classes
18
+ export { AuthError, CursorError, DatabaseError, DependencyError, EncryptionError, HookError, NotFoundError, ServiceError, SqlBuilderError, ValidationError, } from './errors.js';
19
+ // Encryption utilities
20
+ export { decrypt, decryptSecrets, DefaultKeyProvider, encrypt, encryptSecrets, generateSecretKey, getSecretColumns, getSecretLogicalNames, } from './crypto.js';
21
+ // Pagination utilities
22
+ export { buildCursorConditions, createCursor, decodeCursor, encodeCursor, getDefaultOrderBy, reverseOrderBy, validateOrderBy, } from './pagination.js';
23
+ // SQL builder utilities
24
+ export { buildCount, buildDelete, buildInsert, buildSelect, buildSelectById, buildUpdate, escapeColumn, escapeTable, } from './sql-builder.js';
25
+ // Database adapters
26
+ export { fromBunSqlite, fromDurableObjectStorage } from './adapters/index.js';
27
+ // Re-export zod v4 for convenience
28
+ export * as z from 'zod/v4';
29
+ /**
30
+ * Create a new service instance with the provided configuration
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * import { createService, z } from 'ginger'
35
+ *
36
+ * const userService = createService({
37
+ * table: 'users',
38
+ * db, // Database instance (D1 binding, fromBunSqlite, or fromDurableObjectStorage)
39
+ * rowSchema: z.object({
40
+ * id: z.number(),
41
+ * name: z.string(),
42
+ * email: z.string(),
43
+ * }),
44
+ * createSchema: z.object({
45
+ * name: z.string(),
46
+ * email: z.string(),
47
+ * }),
48
+ * updateSchema: z.object({
49
+ * name: z.string().optional(),
50
+ * email: z.string().optional(),
51
+ * }),
52
+ * })
53
+ * ```
54
+ */
55
+ export function createService(options) {
56
+ return new Service(options);
57
+ }
58
+ // Default export for convenience
59
+ export default {
60
+ createService,
61
+ };
62
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,qBAAqB;AACrB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AA4CtC,gBAAgB;AAChB,OAAO,EACL,SAAS,EACT,WAAW,EACX,aAAa,EACb,eAAe,EACf,eAAe,EACf,SAAS,EACT,aAAa,EACb,YAAY,EACZ,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAA;AAEpB,uBAAuB;AACvB,OAAO,EACL,OAAO,EACP,cAAc,EACd,kBAAkB,EAClB,OAAO,EACP,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,aAAa,CAAA;AAEpB,uBAAuB;AACvB,OAAO,EACL,qBAAqB,EACrB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,eAAe,GAChB,MAAM,iBAAiB,CAAA;AAExB,wBAAwB;AACxB,OAAO,EACL,UAAU,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,eAAe,EACf,WAAW,EACX,YAAY,EACZ,WAAW,GACZ,MAAM,kBAAkB,CAAA;AAEzB,oBAAoB;AACpB,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA;AAQ7E,mCAAmC;AACnC,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAA;AAE3B;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,aAAa,CAY3B,OAMC;IAED,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;AAC7B,CAAC;AAED,iCAAiC;AACjC,eAAe;IACb,aAAa;CACd,CAAA"}