@rx-ted/packages-honest-plugins 1.0.1

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 (266) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +45 -0
  3. package/api-doc/.turbo/turbo-build.log +1 -0
  4. package/api-doc/.turbo/turbo-test.log +11 -0
  5. package/api-doc/.turbo/turbo-typecheck.log +1 -0
  6. package/api-doc/CHANGELOG.md +22 -0
  7. package/api-doc/README.md +80 -0
  8. package/api-doc/dist/api-doc.plugin.d.ts +53 -0
  9. package/api-doc/dist/api-doc.plugin.js +452 -0
  10. package/api-doc/dist/index.d.ts +5 -0
  11. package/api-doc/dist/index.js +3 -0
  12. package/api-doc/dist/interfaces/renderer.interface.d.ts +7 -0
  13. package/api-doc/dist/interfaces/renderer.interface.js +1 -0
  14. package/api-doc/dist/renderers/scalar.renderer.d.ts +10 -0
  15. package/api-doc/dist/renderers/scalar.renderer.js +76 -0
  16. package/api-doc/dist/renderers/swagger.renderer.d.ts +10 -0
  17. package/api-doc/dist/renderers/swagger.renderer.js +83 -0
  18. package/api-doc/node_modules/.bin/esbuild +22 -0
  19. package/api-doc/node_modules/.bin/jiti +22 -0
  20. package/api-doc/node_modules/.bin/sass +22 -0
  21. package/api-doc/node_modules/.bin/tsx +22 -0
  22. package/api-doc/node_modules/.bin/vite +22 -0
  23. package/api-doc/node_modules/.bin/vitest +22 -0
  24. package/api-doc/node_modules/.bin/yaml +22 -0
  25. package/api-doc/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  26. package/api-doc/package.json +48 -0
  27. package/api-doc/src/api-doc.plugin.ts +554 -0
  28. package/api-doc/src/index.ts +5 -0
  29. package/api-doc/src/interfaces/renderer.interface.ts +5 -0
  30. package/api-doc/src/plugin.test.ts +740 -0
  31. package/api-doc/src/renderers/scalar.renderer.ts +82 -0
  32. package/api-doc/src/renderers/swagger.renderer.ts +89 -0
  33. package/api-doc/tsconfig.json +21 -0
  34. package/api-doc/vitest.config.ts +13 -0
  35. package/cache/.turbo/turbo-build.log +1 -0
  36. package/cache/.turbo/turbo-test.log +16 -0
  37. package/cache/CHANGELOG.md +23 -0
  38. package/cache/README.md +79 -0
  39. package/cache/dist/cache-service.d.ts +8 -0
  40. package/cache/dist/cache-service.js +21 -0
  41. package/cache/dist/cacheable.d.ts +2 -0
  42. package/cache/dist/cacheable.js +10 -0
  43. package/cache/dist/cloudflare/driver.d.ts +23 -0
  44. package/cache/dist/cloudflare/driver.js +102 -0
  45. package/cache/dist/cloudflare/index.d.ts +3 -0
  46. package/cache/dist/cloudflare/index.js +2 -0
  47. package/cache/dist/cloudflare/plugin.d.ts +19 -0
  48. package/cache/dist/cloudflare/plugin.js +58 -0
  49. package/cache/dist/index.d.ts +11 -0
  50. package/cache/dist/index.js +14 -0
  51. package/cache/dist/local/driver.d.ts +2 -0
  52. package/cache/dist/local/driver.js +98 -0
  53. package/cache/dist/local/index.d.ts +2 -0
  54. package/cache/dist/local/index.js +2 -0
  55. package/cache/dist/local/plugin.d.ts +14 -0
  56. package/cache/dist/local/plugin.js +24 -0
  57. package/cache/dist/redis/driver.d.ts +10 -0
  58. package/cache/dist/redis/driver.js +102 -0
  59. package/cache/dist/redis/index.d.ts +4 -0
  60. package/cache/dist/redis/index.js +2 -0
  61. package/cache/dist/redis/plugin.d.ts +25 -0
  62. package/cache/dist/redis/plugin.js +61 -0
  63. package/cache/dist/resolve.d.ts +24 -0
  64. package/cache/dist/resolve.js +114 -0
  65. package/cache/dist/types.d.ts +18 -0
  66. package/cache/dist/types.js +1 -0
  67. package/cache/node_modules/.bin/esbuild +22 -0
  68. package/cache/node_modules/.bin/jiti +22 -0
  69. package/cache/node_modules/.bin/sass +22 -0
  70. package/cache/node_modules/.bin/tsx +22 -0
  71. package/cache/node_modules/.bin/vite +22 -0
  72. package/cache/node_modules/.bin/vitest +22 -0
  73. package/cache/node_modules/.bin/yaml +22 -0
  74. package/cache/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  75. package/cache/package.json +46 -0
  76. package/cache/src/cache-service.test.ts +16 -0
  77. package/cache/src/cache-service.ts +15 -0
  78. package/cache/src/cacheable.test.ts +78 -0
  79. package/cache/src/cacheable.ts +16 -0
  80. package/cache/src/cloudflare/driver.test.ts +188 -0
  81. package/cache/src/cloudflare/driver.ts +118 -0
  82. package/cache/src/cloudflare/index.ts +3 -0
  83. package/cache/src/cloudflare/plugin.ts +71 -0
  84. package/cache/src/index.test.ts +68 -0
  85. package/cache/src/index.ts +20 -0
  86. package/cache/src/local/driver.ts +117 -0
  87. package/cache/src/local/index.ts +2 -0
  88. package/cache/src/local/plugin.ts +34 -0
  89. package/cache/src/redis/driver.test.ts +71 -0
  90. package/cache/src/redis/driver.ts +124 -0
  91. package/cache/src/redis/index.ts +4 -0
  92. package/cache/src/redis/plugin.ts +84 -0
  93. package/cache/src/resolve.test.ts +257 -0
  94. package/cache/src/resolve.ts +140 -0
  95. package/cache/src/types.ts +14 -0
  96. package/cache/tsconfig.json +21 -0
  97. package/cache/vitest.config.ts +13 -0
  98. package/db/.turbo/turbo-build.log +1 -0
  99. package/db/.turbo/turbo-test.log +21 -0
  100. package/db/CHANGELOG.md +26 -0
  101. package/db/README.md +99 -0
  102. package/db/dist/constants.d.ts +1 -0
  103. package/db/dist/constants.js +1 -0
  104. package/db/dist/d1/index.d.ts +3 -0
  105. package/db/dist/d1/index.js +2 -0
  106. package/db/dist/d1/plugin.d.ts +18 -0
  107. package/db/dist/d1/plugin.js +104 -0
  108. package/db/dist/db-service.d.ts +7 -0
  109. package/db/dist/db-service.js +21 -0
  110. package/db/dist/index.d.ts +15 -0
  111. package/db/dist/index.js +20 -0
  112. package/db/dist/mysql/client.d.ts +36 -0
  113. package/db/dist/mysql/client.js +84 -0
  114. package/db/dist/mysql/driver.d.ts +18 -0
  115. package/db/dist/mysql/driver.js +107 -0
  116. package/db/dist/mysql/index.d.ts +11 -0
  117. package/db/dist/mysql/index.js +11 -0
  118. package/db/dist/mysql/plugin.d.ts +51 -0
  119. package/db/dist/mysql/plugin.js +94 -0
  120. package/db/dist/mysql/types.d.ts +38 -0
  121. package/db/dist/mysql/types.js +1 -0
  122. package/db/dist/postgres/index.d.ts +2 -0
  123. package/db/dist/postgres/index.js +3 -0
  124. package/db/dist/repository.d.ts +14 -0
  125. package/db/dist/repository.js +79 -0
  126. package/db/dist/resolve.d.ts +6 -0
  127. package/db/dist/resolve.js +81 -0
  128. package/db/dist/schema-builder/column-builder.d.ts +26 -0
  129. package/db/dist/schema-builder/column-builder.js +53 -0
  130. package/db/dist/schema-builder/compile-d1.d.ts +5 -0
  131. package/db/dist/schema-builder/compile-d1.js +67 -0
  132. package/db/dist/schema-builder/compile-mysql.d.ts +12 -0
  133. package/db/dist/schema-builder/compile-mysql.js +78 -0
  134. package/db/dist/schema-builder/index.d.ts +8 -0
  135. package/db/dist/schema-builder/index.js +22 -0
  136. package/db/dist/schema-builder/table-builder.d.ts +16 -0
  137. package/db/dist/schema-builder/table-builder.js +38 -0
  138. package/db/dist/schema-builder/types.d.ts +26 -0
  139. package/db/dist/schema-builder/types.js +1 -0
  140. package/db/dist/schema-builder/zod-bridge.d.ts +24 -0
  141. package/db/dist/schema-builder/zod-bridge.js +53 -0
  142. package/db/dist/sqlite/index.d.ts +4 -0
  143. package/db/dist/sqlite/index.js +2 -0
  144. package/db/dist/sqlite/plugin.d.ts +17 -0
  145. package/db/dist/sqlite/plugin.js +33 -0
  146. package/db/dist/types.d.ts +42 -0
  147. package/db/dist/types.js +1 -0
  148. package/db/node_modules/.bin/esbuild +22 -0
  149. package/db/node_modules/.bin/jiti +22 -0
  150. package/db/node_modules/.bin/sass +22 -0
  151. package/db/node_modules/.bin/tsx +22 -0
  152. package/db/node_modules/.bin/vite +22 -0
  153. package/db/node_modules/.bin/vitest +22 -0
  154. package/db/node_modules/.bin/yaml +22 -0
  155. package/db/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  156. package/db/package.json +59 -0
  157. package/db/src/constants.test.ts +8 -0
  158. package/db/src/constants.ts +1 -0
  159. package/db/src/d1/index.ts +13 -0
  160. package/db/src/d1/plugin.ts +135 -0
  161. package/db/src/db-service.ts +14 -0
  162. package/db/src/index.test.ts +63 -0
  163. package/db/src/index.ts +57 -0
  164. package/db/src/mysql/client.ts +112 -0
  165. package/db/src/mysql/driver.test.ts +190 -0
  166. package/db/src/mysql/driver.ts +116 -0
  167. package/db/src/mysql/index.ts +51 -0
  168. package/db/src/mysql/plugin.test.ts +228 -0
  169. package/db/src/mysql/plugin.ts +128 -0
  170. package/db/src/mysql/types.ts +32 -0
  171. package/db/src/postgres/index.ts +15 -0
  172. package/db/src/repository.test.ts +195 -0
  173. package/db/src/repository.ts +95 -0
  174. package/db/src/resolve.ts +105 -0
  175. package/db/src/schema-builder/column-builder.test.ts +55 -0
  176. package/db/src/schema-builder/column-builder.ts +87 -0
  177. package/db/src/schema-builder/compile-d1.test.ts +60 -0
  178. package/db/src/schema-builder/compile-d1.ts +70 -0
  179. package/db/src/schema-builder/compile-mysql.test.ts +64 -0
  180. package/db/src/schema-builder/compile-mysql.ts +102 -0
  181. package/db/src/schema-builder/index.test.ts +36 -0
  182. package/db/src/schema-builder/index.ts +41 -0
  183. package/db/src/schema-builder/table-builder.test.ts +55 -0
  184. package/db/src/schema-builder/table-builder.ts +50 -0
  185. package/db/src/schema-builder/types.test.ts +68 -0
  186. package/db/src/schema-builder/types.ts +30 -0
  187. package/db/src/schema-builder/zod-bridge.ts +89 -0
  188. package/db/src/sqlite/index.ts +14 -0
  189. package/db/src/sqlite/plugin.ts +46 -0
  190. package/db/src/types.ts +45 -0
  191. package/db/tsconfig.json +21 -0
  192. package/db/vitest.config.ts +13 -0
  193. package/mail/.turbo/turbo-build.log +1 -0
  194. package/mail/.turbo/turbo-test.log +12 -0
  195. package/mail/.turbo/turbo-typecheck.log +1 -0
  196. package/mail/CHANGELOG.md +25 -0
  197. package/mail/README.md +214 -0
  198. package/mail/dist/index.d.ts +4 -0
  199. package/mail/dist/index.js +2 -0
  200. package/mail/dist/plugin.d.ts +64 -0
  201. package/mail/dist/plugin.js +232 -0
  202. package/mail/dist/providers/brevo.provider.d.ts +15 -0
  203. package/mail/dist/providers/brevo.provider.js +75 -0
  204. package/mail/dist/providers/custom.provider.d.ts +9 -0
  205. package/mail/dist/providers/custom.provider.js +22 -0
  206. package/mail/dist/providers/resend.provider.d.ts +16 -0
  207. package/mail/dist/providers/resend.provider.js +77 -0
  208. package/mail/dist/providers/smtp.provider.d.ts +21 -0
  209. package/mail/dist/providers/smtp.provider.js +86 -0
  210. package/mail/dist/rate-limiter.d.ts +16 -0
  211. package/mail/dist/rate-limiter.js +49 -0
  212. package/mail/dist/types.d.ts +68 -0
  213. package/mail/dist/types.js +6 -0
  214. package/mail/node_modules/.bin/esbuild +22 -0
  215. package/mail/node_modules/.bin/jiti +22 -0
  216. package/mail/node_modules/.bin/sass +22 -0
  217. package/mail/node_modules/.bin/tsx +22 -0
  218. package/mail/node_modules/.bin/vite +22 -0
  219. package/mail/node_modules/.bin/vitest +22 -0
  220. package/mail/node_modules/.bin/yaml +22 -0
  221. package/mail/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  222. package/mail/package.json +52 -0
  223. package/mail/src/index.ts +4 -0
  224. package/mail/src/plugin.test.ts +219 -0
  225. package/mail/src/plugin.ts +313 -0
  226. package/mail/src/providers/brevo.provider.ts +78 -0
  227. package/mail/src/providers/custom.provider.ts +29 -0
  228. package/mail/src/providers/resend.provider.ts +74 -0
  229. package/mail/src/providers/smtp.provider.ts +85 -0
  230. package/mail/src/rate-limiter.test.ts +81 -0
  231. package/mail/src/rate-limiter.ts +54 -0
  232. package/mail/src/types.ts +81 -0
  233. package/mail/tsconfig.json +21 -0
  234. package/mail/vitest.config.ts +13 -0
  235. package/package.json +36 -0
  236. package/s3/.turbo/turbo-build.log +1 -0
  237. package/s3/.turbo/turbo-test.log +11 -0
  238. package/s3/CHANGELOG.md +20 -0
  239. package/s3/README.md +90 -0
  240. package/s3/dist/index.d.ts +6 -0
  241. package/s3/dist/index.js +4 -0
  242. package/s3/dist/s3-service.d.ts +7 -0
  243. package/s3/dist/s3-service.js +21 -0
  244. package/s3/dist/s3.driver.d.ts +6 -0
  245. package/s3/dist/s3.driver.js +221 -0
  246. package/s3/dist/s3.plugin.d.ts +24 -0
  247. package/s3/dist/s3.plugin.js +58 -0
  248. package/s3/dist/types.d.ts +30 -0
  249. package/s3/dist/types.js +1 -0
  250. package/s3/node_modules/.bin/esbuild +22 -0
  251. package/s3/node_modules/.bin/jiti +22 -0
  252. package/s3/node_modules/.bin/sass +22 -0
  253. package/s3/node_modules/.bin/tsx +22 -0
  254. package/s3/node_modules/.bin/vite +22 -0
  255. package/s3/node_modules/.bin/vitest +22 -0
  256. package/s3/node_modules/.bin/yaml +22 -0
  257. package/s3/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  258. package/s3/package.json +47 -0
  259. package/s3/src/index.test.ts +20 -0
  260. package/s3/src/index.ts +13 -0
  261. package/s3/src/s3-service.ts +14 -0
  262. package/s3/src/s3.driver.ts +259 -0
  263. package/s3/src/s3.plugin.ts +80 -0
  264. package/s3/src/types.ts +37 -0
  265. package/s3/tsconfig.json +21 -0
  266. package/s3/vitest.config.ts +13 -0
@@ -0,0 +1,64 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { getTableName } from 'drizzle-orm';
3
+ import { compileMysql } from './compile-mysql';
4
+ import type { SchemaDefinition } from './types';
5
+
6
+ const schema: SchemaDefinition = {
7
+ users: {
8
+ name: 'users',
9
+ columns: {
10
+ id: { type: 'char', name: 'id', length: 36, primaryKey: true },
11
+ email: { type: 'varchar', name: 'email', length: 255, unique: true, notNull: true },
12
+ name: { type: 'varchar', name: 'name', length: 100 },
13
+ role: { type: 'enum', name: 'role', values: ['admin', 'user'], default: 'user' },
14
+ age: { type: 'integer', name: 'age' },
15
+ meta: { type: 'json', name: 'meta' },
16
+ createdAt: { type: 'timestamp', name: 'created_at', notNull: true },
17
+ },
18
+ },
19
+ };
20
+
21
+ describe('compileMysql', () => {
22
+ it('returns compiled table objects', () => {
23
+ const result = compileMysql(schema);
24
+ expect(result.users).toBeDefined();
25
+ });
26
+
27
+ it('compiled table has column accessors', () => {
28
+ const result = compileMysql(schema);
29
+ const u = result.users as any;
30
+ expect(typeof u.id).toBe('object');
31
+ expect(typeof u.email).toBe('object');
32
+ expect(typeof u.role).toBe('object');
33
+ });
34
+
35
+ it('compiled table name matches', () => {
36
+ const result = compileMysql(schema);
37
+ expect(getTableName(result.users)).toBe('users');
38
+ });
39
+
40
+ it('handles schema with two tables and FK reference', () => {
41
+ const schemaWithFk: SchemaDefinition = {
42
+ users: {
43
+ name: 'users',
44
+ columns: { id: { type: 'char', name: 'id', length: 36, primaryKey: true } },
45
+ },
46
+ user_auth: {
47
+ name: 'user_auth',
48
+ columns: {
49
+ id: { type: 'integer', name: 'id', autoIncrement: true, primaryKey: true },
50
+ userId: {
51
+ type: 'char',
52
+ name: 'user_id',
53
+ length: 36,
54
+ notNull: true,
55
+ references: { table: 'users', column: 'id', onDelete: 'cascade' },
56
+ },
57
+ },
58
+ },
59
+ };
60
+ const result = compileMysql(schemaWithFk);
61
+ expect(result.users).toBeDefined();
62
+ expect(result.user_auth).toBeDefined();
63
+ });
64
+ });
@@ -0,0 +1,102 @@
1
+ import {
2
+ mysqlTable,
3
+ varchar,
4
+ char,
5
+ text,
6
+ int,
7
+ bigint,
8
+ boolean,
9
+ datetime,
10
+ date,
11
+ mysqlEnum,
12
+ json,
13
+ decimal,
14
+ } from 'drizzle-orm/mysql-core';
15
+ import type { MySqlTableWithColumns } from 'drizzle-orm/mysql-core';
16
+ import type { TableDefinition, ColumnDefinition } from './types';
17
+
18
+ type AnyMySqlTable<N extends string = string> = MySqlTableWithColumns<{
19
+ name: N;
20
+ columns: Record<string, any>;
21
+ dialect: string;
22
+ schema: string | undefined;
23
+ }>;
24
+
25
+ export function compileMysql<T extends Record<string, TableDefinition>>(
26
+ schema: T,
27
+ ): { [K in keyof T]: T[K] extends TableDefinition<infer N> ? AnyMySqlTable<N & string> : never } {
28
+ const compiled: Record<string, any> = {};
29
+
30
+ const dbNameToKey: Record<string, string> = {};
31
+ for (const key of Object.keys(schema)) {
32
+ dbNameToKey[schema[key].name] = key;
33
+ }
34
+
35
+ for (const tableName of Object.keys(schema)) {
36
+ const tableDef = schema[tableName];
37
+ const builders: Record<string, any> = {};
38
+ for (const [colName, colDef] of Object.entries(tableDef.columns)) {
39
+ let col = toMysqlColumn(colDef.name, colDef);
40
+ if (colDef.references) {
41
+ const refKey = dbNameToKey[colDef.references.table] ?? colDef.references.table;
42
+ col = col.references(() => compiled[refKey]?.[colDef.references!.column], {
43
+ onDelete: colDef.references!.onDelete,
44
+ });
45
+ }
46
+ builders[colName] = col;
47
+ }
48
+ compiled[tableName] = mysqlTable(tableDef.name, builders);
49
+ }
50
+
51
+ return compiled as any;
52
+ }
53
+
54
+ function toMysqlColumn(name: string, def: ColumnDefinition): any {
55
+ let col: any;
56
+ switch (def.type) {
57
+ case 'varchar':
58
+ col = varchar(name, { length: def.length ?? 255 });
59
+ break;
60
+ case 'char':
61
+ col = char(name, { length: def.length ?? 1 });
62
+ break;
63
+ case 'text':
64
+ col = text(name);
65
+ break;
66
+ case 'bigint':
67
+ col = bigint(name, { mode: 'number', unsigned: true });
68
+ break;
69
+ case 'integer':
70
+ col = int(name);
71
+ break;
72
+ case 'boolean':
73
+ col = boolean(name);
74
+ break;
75
+ case 'timestamp':
76
+ col = datetime(name);
77
+ break;
78
+ case 'date':
79
+ col = date(name);
80
+ break;
81
+ case 'enum':
82
+ col =
83
+ def.values && def.values.length > 0
84
+ ? mysqlEnum(name, def.values as [string, ...string[]])
85
+ : text(name);
86
+ break;
87
+ case 'json':
88
+ col = json(name);
89
+ break;
90
+ case 'decimal':
91
+ col = decimal(name, { precision: def.precision, scale: def.scale });
92
+ break;
93
+ default:
94
+ col = text(name);
95
+ }
96
+ if (def.primaryKey) col = col.primaryKey();
97
+ if (def.autoIncrement) col = col.autoincrement();
98
+ if (def.notNull) col = col.notNull();
99
+ if (def.unique) col = col.unique();
100
+ if (def.default !== undefined) col = col.default(def.default);
101
+ return col;
102
+ }
@@ -0,0 +1,36 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { t, table, compileSchema } from './index';
3
+
4
+ describe('compileSchema dispatcher', () => {
5
+ const schema = {
6
+ users: table('users', {
7
+ id: t.char(36).primaryKey(),
8
+ email: t.varchar(255).unique().notNull(),
9
+ }),
10
+ };
11
+
12
+ it('compileSchema with mysql dialect', () => {
13
+ const result = compileSchema('mysql', schema);
14
+ expect(result.users).toBeDefined();
15
+ expect(typeof (result.users as any).id).toBe('object');
16
+ });
17
+
18
+ it('compileSchema with d1 dialect', () => {
19
+ const result = compileSchema('d1', schema);
20
+ expect(result.users).toBeDefined();
21
+ expect(typeof (result.users as any).id).toBe('object');
22
+ });
23
+
24
+ it('compileSchema with sqlite dialect', () => {
25
+ const result = compileSchema('sqlite', schema);
26
+ expect(result.users).toBeDefined();
27
+ expect(typeof (result.users as any).id).toBe('object');
28
+ });
29
+
30
+ it('sqlite produces same column types as d1', () => {
31
+ const sqlite = compileSchema('sqlite', schema);
32
+ const d1 = compileSchema('d1', schema);
33
+ expect(sqlite.users.constructor.name).toBe('SQLiteTable');
34
+ expect(d1.users.constructor.name).toBe('SQLiteTable');
35
+ });
36
+ });
@@ -0,0 +1,41 @@
1
+ export { t, table } from './table-builder';
2
+ export type {
3
+ Dialect,
4
+ ColumnDefinition,
5
+ TableDefinition,
6
+ SchemaDefinition,
7
+ ReferenceDef,
8
+ } from './types';
9
+ export { compileMysql } from './compile-mysql';
10
+ export { compileD1 } from './compile-d1';
11
+ export {
12
+ zdb,
13
+ getZodDbMeta,
14
+ isZodObject,
15
+ toTableDefinition,
16
+ toColumnDefinition,
17
+ } from './zod-bridge';
18
+ export type { ZodDbMeta } from './zod-bridge';
19
+ import { isZodObject, toTableDefinition } from './zod-bridge';
20
+ import type { Dialect } from './types';
21
+ import { compileMysql } from './compile-mysql';
22
+ import { compileD1 } from './compile-d1';
23
+
24
+ export function compileSchema<T extends Record<string, any>>(
25
+ dialect: Dialect,
26
+ schema: T,
27
+ ): Record<string, any> {
28
+ const definitions: Record<string, any> = {};
29
+ for (const [name, def] of Object.entries(schema)) {
30
+ definitions[name] = isZodObject(def) ? toTableDefinition(name, def) : def;
31
+ }
32
+ switch (dialect) {
33
+ case 'mysql':
34
+ return compileMysql(definitions);
35
+ case 'd1':
36
+ case 'sqlite':
37
+ return compileD1(definitions);
38
+ default:
39
+ throw new Error(`Unknown dialect: ${dialect}`);
40
+ }
41
+ }
@@ -0,0 +1,55 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { t, table } from './table-builder';
3
+
4
+ describe('table builder DSL', () => {
5
+ it('t.varchar creates builder with length', () => {
6
+ const def = t.varchar(255).build('email');
7
+ expect(def.type).toBe('varchar');
8
+ expect(def.length).toBe(255);
9
+ });
10
+
11
+ it('t supports all portable types', () => {
12
+ expect(t.char(36).build('a').type).toBe('char');
13
+ expect(t.text().build('a').type).toBe('text');
14
+ expect(t.bigint().build('a').type).toBe('bigint');
15
+ expect(t.integer().build('a').type).toBe('integer');
16
+ expect(t.boolean().build('a').type).toBe('boolean');
17
+ expect(t.timestamp().build('a').type).toBe('timestamp');
18
+ expect(t.date().build('a').type).toBe('date');
19
+ expect(t.enum(['x', 'y']).build('a').type).toBe('enum');
20
+ expect(t.json().build('a').type).toBe('json');
21
+ expect(t.decimal(10, 2).build('a').type).toBe('decimal');
22
+ });
23
+
24
+ it('table() creates TableDefinition with column names', () => {
25
+ const users = table('users', {
26
+ id: t.char(36).primaryKey(),
27
+ email: t.varchar(255).unique().notNull(),
28
+ name: t.varchar(100),
29
+ });
30
+ expect(users.name).toBe('users');
31
+ expect(Object.keys(users.columns)).toEqual(['id', 'email', 'name']);
32
+ expect(users.columns.id.primaryKey).toBe(true);
33
+ expect(users.columns.email.unique).toBe(true);
34
+ });
35
+
36
+ it('table() sets table/column names on builders for references', () => {
37
+ const users = table('users', { id: t.char(36).primaryKey() });
38
+ expect(users.columns.id.name).toBe('id');
39
+ });
40
+
41
+ it('two tables with foreign key reference', () => {
42
+ const users = table('users', {
43
+ id: t.char(36).primaryKey(),
44
+ });
45
+ const posts = table('posts', {
46
+ id: t.char(36).primaryKey(),
47
+ authorId: t.char(36).references(() => users.id),
48
+ });
49
+ expect(posts.columns.authorId.references).toEqual({
50
+ table: 'users',
51
+ column: 'id',
52
+ onDelete: undefined,
53
+ });
54
+ });
55
+ });
@@ -0,0 +1,50 @@
1
+ import { ColumnBuilder } from './column-builder';
2
+ import type { TableDefinition, ColumnDefinition } from './types';
3
+
4
+ function c(
5
+ type: ConstructorParameters<typeof ColumnBuilder>[0],
6
+ opts?: ConstructorParameters<typeof ColumnBuilder>[1],
7
+ ) {
8
+ return new ColumnBuilder(type, opts);
9
+ }
10
+
11
+ export const t = {
12
+ varchar: (length: number) => c('varchar', { length }),
13
+ char: (length: number) => c('char', { length }),
14
+ text: () => c('text'),
15
+ bigint: () => c('bigint'),
16
+ integer: () => c('integer'),
17
+ boolean: () => c('boolean'),
18
+ timestamp: () => c('timestamp'),
19
+ date: () => c('date'),
20
+ enum: (values: string[]) => c('enum', { values }),
21
+ json: () => c('json'),
22
+ decimal: (p: number, s: number) => c('decimal', { precision: p, scale: s }),
23
+ };
24
+
25
+ export function table<N extends string>(
26
+ name: N,
27
+ columns: Record<string, ColumnBuilder>,
28
+ ): TableDefinition<N> {
29
+ const defs: Record<string, ColumnDefinition> = {};
30
+ for (const [colName, builder] of Object.entries(columns)) {
31
+ builder.__tableName = name;
32
+ builder.__columnName = colName;
33
+ defs[colName] = builder.build(colName);
34
+ }
35
+ const tbl: TableDefinition<N> = { name, columns: defs };
36
+ return proxyTable(tbl, columns);
37
+ }
38
+
39
+ function proxyTable<N extends string>(
40
+ tbl: TableDefinition<N>,
41
+ columns: Record<string, ColumnBuilder>,
42
+ ): TableDefinition<N> {
43
+ return new Proxy(tbl, {
44
+ get(target, prop) {
45
+ if (prop in target) return (target as any)[prop];
46
+ if (typeof prop === 'string' && prop in columns) return columns[prop];
47
+ return undefined;
48
+ },
49
+ }) as unknown as TableDefinition<N>;
50
+ }
@@ -0,0 +1,68 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import type { ColumnDefinition, TableDefinition, SchemaDefinition } from './types';
3
+
4
+ describe('schema-builder types', () => {
5
+ it('ColumnDefinition shape with common fields', () => {
6
+ const col: ColumnDefinition = {
7
+ type: 'varchar',
8
+ name: 'email',
9
+ length: 255,
10
+ notNull: true,
11
+ unique: true,
12
+ };
13
+ expect(col.type).toBe('varchar');
14
+ expect(col.notNull).toBe(true);
15
+ });
16
+
17
+ it('ColumnDefinition supports autoIncrement', () => {
18
+ const col: ColumnDefinition = {
19
+ type: 'integer',
20
+ name: 'id',
21
+ autoIncrement: true,
22
+ primaryKey: true,
23
+ };
24
+ expect(col.autoIncrement).toBe(true);
25
+ });
26
+
27
+ it('ColumnDefinition supports enum values and default', () => {
28
+ const col: ColumnDefinition = {
29
+ type: 'enum',
30
+ name: 'role',
31
+ values: ['admin', 'user'],
32
+ default: 'user',
33
+ };
34
+ expect(col.values).toEqual(['admin', 'user']);
35
+ expect(col.default).toBe('user');
36
+ });
37
+
38
+ it('ColumnDefinition supports precision and scale', () => {
39
+ const col: ColumnDefinition = { type: 'decimal', name: 'price', precision: 10, scale: 2 };
40
+ expect(col.precision).toBe(10);
41
+ expect(col.scale).toBe(2);
42
+ });
43
+
44
+ it('ColumnDefinition supports references with onDelete', () => {
45
+ const col: ColumnDefinition = {
46
+ type: 'char',
47
+ name: 'user_id',
48
+ length: 36,
49
+ references: { table: 'users', column: 'id', onDelete: 'cascade' },
50
+ };
51
+ expect(col.references?.table).toBe('users');
52
+ expect(col.references?.onDelete).toBe('cascade');
53
+ });
54
+
55
+ it('TableDefinition shape', () => {
56
+ const t: TableDefinition = {
57
+ name: 'users',
58
+ columns: { id: { type: 'char', name: 'id', length: 36, primaryKey: true } },
59
+ };
60
+ expect(t.name).toBe('users');
61
+ expect(t.columns.id.primaryKey).toBe(true);
62
+ });
63
+
64
+ it('SchemaDefinition is record of tables', () => {
65
+ const s: SchemaDefinition = { users: { name: 'users', columns: {} } };
66
+ expect(s.users.name).toBe('users');
67
+ });
68
+ });
@@ -0,0 +1,30 @@
1
+ export type Dialect = 'mysql' | 'd1' | 'sqlite';
2
+
3
+ export interface ReferenceDef {
4
+ table: string;
5
+ column: string;
6
+ onDelete?: 'cascade' | 'set null' | 'restrict' | 'no action';
7
+ }
8
+
9
+ export interface ColumnDefinition {
10
+ type: string;
11
+ /** DB column name (distinct from the Record key which is the JS property name) */
12
+ name: string;
13
+ primaryKey?: boolean;
14
+ autoIncrement?: boolean;
15
+ notNull?: boolean;
16
+ unique?: boolean;
17
+ default?: unknown;
18
+ length?: number;
19
+ values?: string[];
20
+ precision?: number;
21
+ scale?: number;
22
+ references?: ReferenceDef;
23
+ }
24
+
25
+ export interface TableDefinition<N extends string = string> {
26
+ name: N;
27
+ columns: Record<string, ColumnDefinition>;
28
+ }
29
+
30
+ export type SchemaDefinition = Record<string, TableDefinition>;
@@ -0,0 +1,89 @@
1
+ import { z } from 'zod';
2
+ import type { ColumnDefinition, ReferenceDef } from './types';
3
+
4
+ const DB_COL = Symbol('zod:db-col');
5
+
6
+ export interface ZodDbMeta {
7
+ type:
8
+ | 'varchar'
9
+ | 'char'
10
+ | 'text'
11
+ | 'bigint'
12
+ | 'integer'
13
+ | 'boolean'
14
+ | 'timestamp'
15
+ | 'date'
16
+ | 'enum'
17
+ | 'json'
18
+ | 'decimal';
19
+ dbName?: string;
20
+ primaryKey?: boolean;
21
+ autoIncrement?: boolean;
22
+ notNull?: boolean;
23
+ unique?: boolean;
24
+ default?: unknown;
25
+ length?: number;
26
+ values?: string[];
27
+ precision?: number;
28
+ scale?: number;
29
+ references?: ReferenceDef;
30
+ }
31
+
32
+ export function zdb<T extends z.ZodType>(zod: T, meta: ZodDbMeta): T {
33
+ Object.defineProperty(zod, DB_COL, {
34
+ value: meta,
35
+ writable: true,
36
+ configurable: true,
37
+ });
38
+ return zod;
39
+ }
40
+
41
+ export function getZodDbMeta(zod: z.ZodType): ZodDbMeta | undefined {
42
+ return (zod as any)[DB_COL];
43
+ }
44
+
45
+ export function isZodObject(schema: unknown): schema is z.ZodObject<any> {
46
+ return typeof schema === 'object' && schema !== null && 'shape' in schema;
47
+ }
48
+
49
+ export function toColumnDefinition(jsName: string, zod: z.ZodType): ColumnDefinition {
50
+ const meta = getZodDbMeta(zod);
51
+ if (!meta) {
52
+ const inner = (zod as any)._def?.innerType;
53
+ if (zod instanceof z.ZodDefault && inner) {
54
+ return toColumnDefinition(jsName, inner);
55
+ }
56
+ if (zod instanceof z.ZodNullable && inner) {
57
+ return toColumnDefinition(jsName, inner);
58
+ }
59
+ if (zod instanceof z.ZodOptional && inner) {
60
+ return toColumnDefinition(jsName, inner);
61
+ }
62
+ throw new Error(`Column "${jsName}" has no db metadata. Use zdb() to attach metadata.`);
63
+ }
64
+ return {
65
+ name: meta.dbName ?? jsName,
66
+ type: meta.type,
67
+ primaryKey: meta.primaryKey,
68
+ autoIncrement: meta.autoIncrement,
69
+ notNull: meta.notNull,
70
+ unique: meta.unique,
71
+ default: meta.default,
72
+ length: meta.length,
73
+ values: meta.values,
74
+ precision: meta.precision,
75
+ scale: meta.scale,
76
+ references: meta.references,
77
+ };
78
+ }
79
+
80
+ export function toTableDefinition(
81
+ name: string,
82
+ schema: z.ZodObject<any>,
83
+ ): { name: string; columns: Record<string, ColumnDefinition> } {
84
+ const columns: Record<string, ColumnDefinition> = {};
85
+ for (const [key, zod] of Object.entries(schema.shape)) {
86
+ columns[key] = toColumnDefinition(key, zod as z.ZodType);
87
+ }
88
+ return { name, columns };
89
+ }
@@ -0,0 +1,14 @@
1
+ export {
2
+ sqliteTable,
3
+ text,
4
+ integer,
5
+ real,
6
+ blob,
7
+ uniqueIndex,
8
+ index,
9
+ primaryKey,
10
+ foreignKey,
11
+ } from 'drizzle-orm/sqlite-core';
12
+ export type { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core';
13
+ export { SqlitePlugin } from './plugin';
14
+ export type { SqlitePluginOptions } from './plugin';
@@ -0,0 +1,46 @@
1
+ import type { Hono } from 'hono';
2
+ import type { IPlugin, Application } from '@rx-ted/packages-honest';
3
+ import { ComponentManager, resolvePluginLogger } from '@rx-ted/packages-honest';
4
+ import { ENV_SYMBOL, type Env, type ILogger } from '@rx-ted/packages-core';
5
+ import { createClient } from '@libsql/client';
6
+ import { drizzle } from 'drizzle-orm/libsql';
7
+ import { DB_GLOBAL_KEY } from '../constants';
8
+ import { assertRuntimeSupport, type AppRuntime } from '../resolve';
9
+
10
+ export interface SqlitePluginOptions {
11
+ dbPath: string;
12
+ schema: Record<string, any>;
13
+ }
14
+
15
+ export class SqlitePlugin implements IPlugin {
16
+ readonly name = 'sqlite-plugin';
17
+ readonly version = '0.0.1';
18
+ logger?: ILogger;
19
+ private db: any = null;
20
+
21
+ constructor(private options: SqlitePluginOptions) {}
22
+
23
+ async beforeModulesRegistered(_app: Application, _hono: Hono): Promise<void> {
24
+ this.logger ??= resolvePluginLogger(this.name);
25
+
26
+ const env = ComponentManager.getPlugin<Env>(ENV_SYMBOL);
27
+ assertRuntimeSupport(env.platform as AppRuntime, 'sqlite');
28
+
29
+ this.logger.info(`connecting to SQLite: ${this.options.dbPath}`);
30
+
31
+ const client = createClient({ url: `file:${this.options.dbPath}` });
32
+ const raw = drizzle(client, { schema: this.options.schema });
33
+ this.db = raw;
34
+
35
+ ComponentManager.registerPlugin(DB_GLOBAL_KEY, this.db);
36
+
37
+ this.logger.info(`SQLite connected: ${this.options.dbPath}`);
38
+ }
39
+
40
+ async close(): Promise<void> {
41
+ if (this.db?.$client) {
42
+ this.db.$client.close();
43
+ this.logger?.info('SQLite connection closed');
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,45 @@
1
+ export interface PreparedStatement {
2
+ execute(params?: unknown[]): Promise<QueryResult>;
3
+ release(): void;
4
+ }
5
+
6
+ export interface DatabaseConnection {
7
+ prepare(sql: string): PreparedStatement;
8
+ query<T>(sql: string, params?: unknown[]): Promise<T[]>;
9
+ execute(sql: string, params?: unknown[]): Promise<QueryResult>;
10
+ release(): void;
11
+ }
12
+
13
+ export interface DatabaseClient {
14
+ prepare(sql: string): PreparedStatement;
15
+ getConnection(): Promise<DatabaseConnection>;
16
+ close(): Promise<void>;
17
+ }
18
+
19
+ export interface QueryResult {
20
+ affectedRows: number;
21
+ insertId?: number;
22
+ }
23
+
24
+ export interface DatabaseDriver {
25
+ query<T = unknown>(sql: string, params?: unknown[]): Promise<T[]>;
26
+ execute(sql: string, params?: unknown[]): Promise<QueryResult>;
27
+ transaction<T>(fn: (driver: DatabaseDriver) => Promise<T>): Promise<T>;
28
+ close(): Promise<void>;
29
+ healthCheck(): Promise<boolean>;
30
+ }
31
+
32
+ export interface QueryOptions {
33
+ where?: Record<string, any>;
34
+ orderBy?: Record<string, 'asc' | 'desc'>;
35
+ pagination?: { page: number; pageSize: number };
36
+ include?: string[];
37
+ }
38
+
39
+ export interface PaginationResult<T> {
40
+ data: T[];
41
+ total: number;
42
+ page: number;
43
+ pageSize: number;
44
+ totalPages: number;
45
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "declaration": true,
8
+ "sourceMap": false,
9
+ "experimentalDecorators": true,
10
+ "emitDecoratorMetadata": true,
11
+ "esModuleInterop": true,
12
+ "skipLibCheck": true,
13
+ "isolatedModules": true,
14
+ "verbatimModuleSyntax": true,
15
+ "types": ["node"],
16
+ "rootDir": "./src",
17
+ "outDir": "./dist"
18
+ },
19
+ "include": ["src"],
20
+ "exclude": ["**/*.test.ts"]
21
+ }
@@ -0,0 +1,13 @@
1
+ import { defineConfig } from 'vitest/config';
2
+ import { getWorkspaceAliases } from '../../../vitest.workspace-aliases';
3
+
4
+ export default defineConfig({
5
+ resolve: {
6
+ alias: getWorkspaceAliases(),
7
+ },
8
+ test: {
9
+ globals: true,
10
+ environment: 'node',
11
+ exclude: ['node_modules'],
12
+ },
13
+ });
@@ -0,0 +1 @@
1
+ $ tsc -p tsconfig.json