@gencow/core 0.1.26 → 0.1.28

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 (88) hide show
  1. package/dist/crud.d.ts +12 -0
  2. package/dist/crud.js +16 -0
  3. package/dist/db.d.ts +13 -0
  4. package/dist/db.js +16 -0
  5. package/dist/document-types.d.ts +65 -0
  6. package/dist/document-types.js +15 -0
  7. package/dist/grounded-answer-types.d.ts +62 -0
  8. package/dist/grounded-answer-types.js +6 -0
  9. package/dist/index.d.ts +12 -2
  10. package/dist/index.js +5 -1
  11. package/dist/rag-ingest-types.d.ts +39 -0
  12. package/dist/rag-ingest-types.js +1 -0
  13. package/dist/rag-operations-types.d.ts +81 -0
  14. package/dist/rag-operations-types.js +1 -0
  15. package/dist/rag-schema.d.ts +1557 -0
  16. package/dist/rag-schema.js +87 -0
  17. package/dist/reactive.d.ts +13 -0
  18. package/dist/rls-db.d.ts +9 -2
  19. package/dist/runtime-env-policy.d.ts +5 -0
  20. package/dist/runtime-env-policy.js +56 -0
  21. package/dist/search-types.d.ts +83 -0
  22. package/dist/search-types.js +1 -0
  23. package/dist/server.d.ts +1 -2
  24. package/dist/server.js +0 -1
  25. package/dist/storage-shared.d.ts +36 -0
  26. package/dist/storage-shared.js +39 -0
  27. package/dist/storage.d.ts +2 -26
  28. package/dist/storage.js +19 -15
  29. package/dist/workflow-types.d.ts +3 -1
  30. package/package.json +1 -1
  31. package/src/crud.ts +33 -0
  32. package/src/document-types.ts +95 -0
  33. package/src/grounded-answer-types.ts +78 -0
  34. package/src/index.ts +68 -2
  35. package/src/rag-ingest-types.ts +52 -0
  36. package/src/rag-operations-types.ts +90 -0
  37. package/src/rag-schema.ts +94 -0
  38. package/src/reactive.ts +13 -0
  39. package/src/rls-db.ts +9 -4
  40. package/src/runtime-env-policy.ts +66 -0
  41. package/src/search-types.ts +91 -0
  42. package/src/server.ts +1 -2
  43. package/src/storage-shared.ts +74 -0
  44. package/src/storage.ts +29 -46
  45. package/src/workflow-types.ts +3 -1
  46. package/src/__tests__/auth.test.ts +0 -118
  47. package/src/__tests__/crons.test.ts +0 -83
  48. package/src/__tests__/crud-codegen-integration.test.ts +0 -246
  49. package/src/__tests__/crud-owner-rls.test.ts +0 -387
  50. package/src/__tests__/crud.test.ts +0 -930
  51. package/src/__tests__/dist-exports.test.ts +0 -176
  52. package/src/__tests__/fixtures/basic/auth.ts +0 -32
  53. package/src/__tests__/fixtures/basic/drizzle.config.ts +0 -12
  54. package/src/__tests__/fixtures/basic/index.ts +0 -6
  55. package/src/__tests__/fixtures/basic/migrations/0000_last_warstar.sql +0 -75
  56. package/src/__tests__/fixtures/basic/migrations/meta/0000_snapshot.json +0 -497
  57. package/src/__tests__/fixtures/basic/migrations/meta/_journal.json +0 -13
  58. package/src/__tests__/fixtures/basic/schema.ts +0 -51
  59. package/src/__tests__/fixtures/basic/tasks.ts +0 -15
  60. package/src/__tests__/fixtures/common/auth-schema.ts +0 -67
  61. package/src/__tests__/helpers/basic-rls-fixture.ts +0 -135
  62. package/src/__tests__/helpers/pglite-migrations.ts +0 -32
  63. package/src/__tests__/helpers/pglite-rls-session.ts +0 -51
  64. package/src/__tests__/helpers/seed-like-fill.ts +0 -202
  65. package/src/__tests__/helpers/test-gencow-ctx-rls.ts +0 -50
  66. package/src/__tests__/httpaction.test.ts +0 -122
  67. package/src/__tests__/image-optimization.test.ts +0 -648
  68. package/src/__tests__/load.test.ts +0 -389
  69. package/src/__tests__/network-sim.test.ts +0 -319
  70. package/src/__tests__/reactive.test.ts +0 -479
  71. package/src/__tests__/retry.test.ts +0 -113
  72. package/src/__tests__/rls-crud-basic.test.ts +0 -317
  73. package/src/__tests__/rls-crud-no-owner-rls-pglite.test.ts +0 -117
  74. package/src/__tests__/rls-custom-mutation-handlers.test.ts +0 -142
  75. package/src/__tests__/rls-custom-query-handlers.test.ts +0 -128
  76. package/src/__tests__/rls-db-leased-connection.test.ts +0 -118
  77. package/src/__tests__/rls-session-and-policies.test.ts +0 -228
  78. package/src/__tests__/scheduler-durable-v2.test.ts +0 -288
  79. package/src/__tests__/scheduler-durable.test.ts +0 -173
  80. package/src/__tests__/scheduler-exec.test.ts +0 -328
  81. package/src/__tests__/scheduler.test.ts +0 -187
  82. package/src/__tests__/storage.test.ts +0 -334
  83. package/src/__tests__/tsconfig.json +0 -8
  84. package/src/__tests__/validator.test.ts +0 -323
  85. package/src/__tests__/workflow.test.ts +0 -606
  86. package/src/__tests__/ws-integration.test.ts +0 -309
  87. package/src/__tests__/ws-scale.test.ts +0 -241
  88. package/src/auth.ts +0 -155
@@ -1,497 +0,0 @@
1
- {
2
- "id": "d57dfdaa-8d90-493e-834f-580b33548adc",
3
- "prevId": "00000000-0000-0000-0000-000000000000",
4
- "version": "7",
5
- "dialect": "postgresql",
6
- "tables": {
7
- "public.news": {
8
- "name": "news",
9
- "schema": "",
10
- "columns": {
11
- "id": {
12
- "name": "id",
13
- "type": "text",
14
- "primaryKey": true,
15
- "notNull": true
16
- },
17
- "title": {
18
- "name": "title",
19
- "type": "text",
20
- "primaryKey": false,
21
- "notNull": true
22
- },
23
- "user_id": {
24
- "name": "user_id",
25
- "type": "text",
26
- "primaryKey": false,
27
- "notNull": true
28
- },
29
- "created_at": {
30
- "name": "created_at",
31
- "type": "timestamp",
32
- "primaryKey": false,
33
- "notNull": true,
34
- "default": "now()"
35
- },
36
- "updated_at": {
37
- "name": "updated_at",
38
- "type": "timestamp",
39
- "primaryKey": false,
40
- "notNull": true,
41
- "default": "now()"
42
- }
43
- },
44
- "indexes": {},
45
- "foreignKeys": {
46
- "news_user_id_user_id_fk": {
47
- "name": "news_user_id_user_id_fk",
48
- "tableFrom": "news",
49
- "tableTo": "user",
50
- "columnsFrom": [
51
- "user_id"
52
- ],
53
- "columnsTo": [
54
- "id"
55
- ],
56
- "onDelete": "cascade",
57
- "onUpdate": "no action"
58
- }
59
- },
60
- "compositePrimaryKeys": {},
61
- "uniqueConstraints": {},
62
- "policies": {},
63
- "checkConstraints": {},
64
- "isRLSEnabled": false
65
- },
66
- "public.tasks": {
67
- "name": "tasks",
68
- "schema": "",
69
- "columns": {
70
- "id": {
71
- "name": "id",
72
- "type": "text",
73
- "primaryKey": true,
74
- "notNull": true
75
- },
76
- "title": {
77
- "name": "title",
78
- "type": "text",
79
- "primaryKey": false,
80
- "notNull": true
81
- },
82
- "description": {
83
- "name": "description",
84
- "type": "text",
85
- "primaryKey": false,
86
- "notNull": false
87
- },
88
- "done": {
89
- "name": "done",
90
- "type": "boolean",
91
- "primaryKey": false,
92
- "notNull": true,
93
- "default": false
94
- },
95
- "user_id": {
96
- "name": "user_id",
97
- "type": "text",
98
- "primaryKey": false,
99
- "notNull": true
100
- },
101
- "created_at": {
102
- "name": "created_at",
103
- "type": "timestamp",
104
- "primaryKey": false,
105
- "notNull": true,
106
- "default": "now()"
107
- },
108
- "updated_at": {
109
- "name": "updated_at",
110
- "type": "timestamp",
111
- "primaryKey": false,
112
- "notNull": true,
113
- "default": "now()"
114
- }
115
- },
116
- "indexes": {},
117
- "foreignKeys": {
118
- "tasks_user_id_user_id_fk": {
119
- "name": "tasks_user_id_user_id_fk",
120
- "tableFrom": "tasks",
121
- "tableTo": "user",
122
- "columnsFrom": [
123
- "user_id"
124
- ],
125
- "columnsTo": [
126
- "id"
127
- ],
128
- "onDelete": "cascade",
129
- "onUpdate": "no action"
130
- }
131
- },
132
- "compositePrimaryKeys": {},
133
- "uniqueConstraints": {},
134
- "policies": {
135
- "rls-select": {
136
- "name": "rls-select",
137
- "as": "PERMISSIVE",
138
- "for": "SELECT",
139
- "to": [
140
- "public"
141
- ],
142
- "using": "\"tasks\".\"user_id\" = current_setting('app.current_user_id', true)"
143
- },
144
- "rls-insert": {
145
- "name": "rls-insert",
146
- "as": "PERMISSIVE",
147
- "for": "INSERT",
148
- "to": [
149
- "public"
150
- ],
151
- "withCheck": "\"tasks\".\"user_id\" = current_setting('app.current_user_id', true)"
152
- },
153
- "rls-update": {
154
- "name": "rls-update",
155
- "as": "PERMISSIVE",
156
- "for": "UPDATE",
157
- "to": [
158
- "public"
159
- ],
160
- "using": "\"tasks\".\"user_id\" = current_setting('app.current_user_id', true)",
161
- "withCheck": "\"tasks\".\"user_id\" = current_setting('app.current_user_id', true)"
162
- },
163
- "rls-delete": {
164
- "name": "rls-delete",
165
- "as": "PERMISSIVE",
166
- "for": "DELETE",
167
- "to": [
168
- "public"
169
- ],
170
- "using": "\"tasks\".\"user_id\" = current_setting('app.current_user_id', true)"
171
- }
172
- },
173
- "checkConstraints": {},
174
- "isRLSEnabled": false
175
- },
176
- "public.user": {
177
- "name": "user",
178
- "schema": "",
179
- "columns": {
180
- "id": {
181
- "name": "id",
182
- "type": "text",
183
- "primaryKey": true,
184
- "notNull": true
185
- },
186
- "name": {
187
- "name": "name",
188
- "type": "text",
189
- "primaryKey": false,
190
- "notNull": true
191
- },
192
- "email": {
193
- "name": "email",
194
- "type": "text",
195
- "primaryKey": false,
196
- "notNull": true
197
- },
198
- "email_verified": {
199
- "name": "email_verified",
200
- "type": "boolean",
201
- "primaryKey": false,
202
- "notNull": true,
203
- "default": false
204
- },
205
- "image": {
206
- "name": "image",
207
- "type": "text",
208
- "primaryKey": false,
209
- "notNull": false
210
- },
211
- "created_at": {
212
- "name": "created_at",
213
- "type": "timestamp",
214
- "primaryKey": false,
215
- "notNull": true,
216
- "default": "now()"
217
- },
218
- "updated_at": {
219
- "name": "updated_at",
220
- "type": "timestamp",
221
- "primaryKey": false,
222
- "notNull": true,
223
- "default": "now()"
224
- }
225
- },
226
- "indexes": {},
227
- "foreignKeys": {},
228
- "compositePrimaryKeys": {},
229
- "uniqueConstraints": {
230
- "user_email_unique": {
231
- "name": "user_email_unique",
232
- "nullsNotDistinct": false,
233
- "columns": [
234
- "email"
235
- ]
236
- }
237
- },
238
- "policies": {},
239
- "checkConstraints": {},
240
- "isRLSEnabled": false
241
- },
242
- "public.account": {
243
- "name": "account",
244
- "schema": "",
245
- "columns": {
246
- "id": {
247
- "name": "id",
248
- "type": "text",
249
- "primaryKey": true,
250
- "notNull": true
251
- },
252
- "account_id": {
253
- "name": "account_id",
254
- "type": "text",
255
- "primaryKey": false,
256
- "notNull": true
257
- },
258
- "provider_id": {
259
- "name": "provider_id",
260
- "type": "text",
261
- "primaryKey": false,
262
- "notNull": true
263
- },
264
- "user_id": {
265
- "name": "user_id",
266
- "type": "text",
267
- "primaryKey": false,
268
- "notNull": true
269
- },
270
- "access_token": {
271
- "name": "access_token",
272
- "type": "text",
273
- "primaryKey": false,
274
- "notNull": false
275
- },
276
- "refresh_token": {
277
- "name": "refresh_token",
278
- "type": "text",
279
- "primaryKey": false,
280
- "notNull": false
281
- },
282
- "id_token": {
283
- "name": "id_token",
284
- "type": "text",
285
- "primaryKey": false,
286
- "notNull": false
287
- },
288
- "access_token_expires_at": {
289
- "name": "access_token_expires_at",
290
- "type": "timestamp",
291
- "primaryKey": false,
292
- "notNull": false
293
- },
294
- "refresh_token_expires_at": {
295
- "name": "refresh_token_expires_at",
296
- "type": "timestamp",
297
- "primaryKey": false,
298
- "notNull": false
299
- },
300
- "scope": {
301
- "name": "scope",
302
- "type": "text",
303
- "primaryKey": false,
304
- "notNull": false
305
- },
306
- "password": {
307
- "name": "password",
308
- "type": "text",
309
- "primaryKey": false,
310
- "notNull": false
311
- },
312
- "created_at": {
313
- "name": "created_at",
314
- "type": "timestamp",
315
- "primaryKey": false,
316
- "notNull": true,
317
- "default": "now()"
318
- },
319
- "updated_at": {
320
- "name": "updated_at",
321
- "type": "timestamp",
322
- "primaryKey": false,
323
- "notNull": true,
324
- "default": "now()"
325
- }
326
- },
327
- "indexes": {},
328
- "foreignKeys": {
329
- "account_user_id_user_id_fk": {
330
- "name": "account_user_id_user_id_fk",
331
- "tableFrom": "account",
332
- "tableTo": "user",
333
- "columnsFrom": [
334
- "user_id"
335
- ],
336
- "columnsTo": [
337
- "id"
338
- ],
339
- "onDelete": "cascade",
340
- "onUpdate": "no action"
341
- }
342
- },
343
- "compositePrimaryKeys": {},
344
- "uniqueConstraints": {},
345
- "policies": {},
346
- "checkConstraints": {},
347
- "isRLSEnabled": false
348
- },
349
- "public.session": {
350
- "name": "session",
351
- "schema": "",
352
- "columns": {
353
- "id": {
354
- "name": "id",
355
- "type": "text",
356
- "primaryKey": true,
357
- "notNull": true
358
- },
359
- "expires_at": {
360
- "name": "expires_at",
361
- "type": "timestamp",
362
- "primaryKey": false,
363
- "notNull": true
364
- },
365
- "token": {
366
- "name": "token",
367
- "type": "text",
368
- "primaryKey": false,
369
- "notNull": true
370
- },
371
- "created_at": {
372
- "name": "created_at",
373
- "type": "timestamp",
374
- "primaryKey": false,
375
- "notNull": true,
376
- "default": "now()"
377
- },
378
- "updated_at": {
379
- "name": "updated_at",
380
- "type": "timestamp",
381
- "primaryKey": false,
382
- "notNull": true,
383
- "default": "now()"
384
- },
385
- "ip_address": {
386
- "name": "ip_address",
387
- "type": "text",
388
- "primaryKey": false,
389
- "notNull": false
390
- },
391
- "user_agent": {
392
- "name": "user_agent",
393
- "type": "text",
394
- "primaryKey": false,
395
- "notNull": false
396
- },
397
- "user_id": {
398
- "name": "user_id",
399
- "type": "text",
400
- "primaryKey": false,
401
- "notNull": true
402
- }
403
- },
404
- "indexes": {},
405
- "foreignKeys": {
406
- "session_user_id_user_id_fk": {
407
- "name": "session_user_id_user_id_fk",
408
- "tableFrom": "session",
409
- "tableTo": "user",
410
- "columnsFrom": [
411
- "user_id"
412
- ],
413
- "columnsTo": [
414
- "id"
415
- ],
416
- "onDelete": "cascade",
417
- "onUpdate": "no action"
418
- }
419
- },
420
- "compositePrimaryKeys": {},
421
- "uniqueConstraints": {
422
- "session_token_unique": {
423
- "name": "session_token_unique",
424
- "nullsNotDistinct": false,
425
- "columns": [
426
- "token"
427
- ]
428
- }
429
- },
430
- "policies": {},
431
- "checkConstraints": {},
432
- "isRLSEnabled": false
433
- },
434
- "public.verification": {
435
- "name": "verification",
436
- "schema": "",
437
- "columns": {
438
- "id": {
439
- "name": "id",
440
- "type": "text",
441
- "primaryKey": true,
442
- "notNull": true
443
- },
444
- "identifier": {
445
- "name": "identifier",
446
- "type": "text",
447
- "primaryKey": false,
448
- "notNull": true
449
- },
450
- "value": {
451
- "name": "value",
452
- "type": "text",
453
- "primaryKey": false,
454
- "notNull": true
455
- },
456
- "expires_at": {
457
- "name": "expires_at",
458
- "type": "timestamp",
459
- "primaryKey": false,
460
- "notNull": true
461
- },
462
- "created_at": {
463
- "name": "created_at",
464
- "type": "timestamp",
465
- "primaryKey": false,
466
- "notNull": false,
467
- "default": "now()"
468
- },
469
- "updated_at": {
470
- "name": "updated_at",
471
- "type": "timestamp",
472
- "primaryKey": false,
473
- "notNull": false,
474
- "default": "now()"
475
- }
476
- },
477
- "indexes": {},
478
- "foreignKeys": {},
479
- "compositePrimaryKeys": {},
480
- "uniqueConstraints": {},
481
- "policies": {},
482
- "checkConstraints": {},
483
- "isRLSEnabled": false
484
- }
485
- },
486
- "enums": {},
487
- "schemas": {},
488
- "sequences": {},
489
- "roles": {},
490
- "policies": {},
491
- "views": {},
492
- "_meta": {
493
- "columns": {},
494
- "schemas": {},
495
- "tables": {}
496
- }
497
- }
@@ -1,13 +0,0 @@
1
- {
2
- "version": "7",
3
- "dialect": "postgresql",
4
- "entries": [
5
- {
6
- "idx": 0,
7
- "version": "7",
8
- "when": 1776398037133,
9
- "tag": "0000_last_warstar",
10
- "breakpoints": true
11
- }
12
- ]
13
- }
@@ -1,51 +0,0 @@
1
- /**
2
- * gencow/schema.ts — Task App 스키마
3
- *
4
- * 🔒 Secure by Default:
5
- * - pgTable + ownerRls + crud로 사용자별 데이터 자동 격리
6
- * - onDelete: "cascade"로 유저 삭제 시 관련 데이터 자동 정리
7
- *
8
- * 변경 후: gencow dev가 자동 반영
9
- */
10
- import { ownerRls } from "../../../rls.js";
11
- import { pgTable } from "drizzle-orm/pg-core";
12
- import { text, boolean, timestamp } from "drizzle-orm/pg-core";
13
- import { user } from "../common/auth-schema.js";
14
- import { v4 as uuidv4 } from "uuid";
15
-
16
- export { user } from "../common/auth-schema.js";
17
-
18
- export const tasks = pgTable(
19
- "tasks",
20
- {
21
- id: text("id")
22
- .primaryKey()
23
- .$defaultFn(() => uuidv4()),
24
- title: text("title").notNull(),
25
- description: text("description"),
26
- done: boolean("done").default(false).notNull(),
27
- // 🔒 RLS (Role-Level Security)
28
- userId: text("user_id")
29
- .notNull()
30
- .references(() => user.id, { onDelete: "cascade" }),
31
- createdAt: timestamp("created_at").defaultNow().notNull(),
32
- updatedAt: timestamp("updated_at").defaultNow().notNull(),
33
- },
34
- (t) => ownerRls(t.userId),
35
- );
36
-
37
- /**
38
- * Public-ish content table **without** `ownerRls()` — no PostgreSQL RLS policies; used for
39
- * `crud(..., { public: true })` + no-DB-RLS integration tests.
40
- */
41
- export const news = pgTable("news", {
42
- id: text("id")
43
- .primaryKey()
44
- .$defaultFn(() => uuidv4()),
45
- title: text("title").notNull(),
46
- userId: text("user_id")
47
- .notNull()
48
- .references(() => user.id, { onDelete: "cascade" }),
49
- createdAt: timestamp("created_at").defaultNow().notNull(),
50
- updatedAt: timestamp("updated_at").defaultNow().notNull(),
51
- });
@@ -1,15 +0,0 @@
1
- /**
2
- * gencow/tasks.ts — Task CRUD (Zero-Boilerplate Pattern)
3
- *
4
- * 🔒 Secure by Default:
5
- * - ctx.db uses RLS (Row-Level Security) — auto-filters by userId
6
- * - crud auto-registers query/mutation with auth + realtime
7
- */
8
- import { crud } from "../../../crud.js";
9
- import { tasks } from "./schema.js";
10
-
11
- // 자동 생성: list, get, create, update, remove (query + mutation + auth + realtime)
12
- export const { list, get, create, update, remove } = crud(tasks, {
13
- searchFields: ["title", "description"],
14
- defaultLimit: 50,
15
- });
@@ -1,67 +0,0 @@
1
- /**
2
- * packages/server/src/auth-schema.ts
3
- *
4
- * better-auth가 사용하는 Drizzle 스키마 테이블 정의.
5
- * better-auth는 user, session, account, verification 4개 테이블을 필요로 합니다.
6
- *
7
- * @see https://www.better-auth.com/docs/adapters/drizzle
8
- */
9
- import { pgTable, text, boolean, timestamp } from "drizzle-orm/pg-core";
10
-
11
- // ─── user 테이블 ────────────────────────────────────────
12
-
13
- export const user = pgTable("user", {
14
- id: text("id").primaryKey(),
15
- name: text("name").notNull(),
16
- email: text("email").notNull().unique(),
17
- emailVerified: boolean("email_verified").notNull().default(false),
18
- image: text("image"),
19
- createdAt: timestamp("created_at").notNull().defaultNow(),
20
- updatedAt: timestamp("updated_at").notNull().defaultNow(),
21
- });
22
-
23
- // ─── session 테이블 ─────────────────────────────────────
24
-
25
- export const session = pgTable("session", {
26
- id: text("id").primaryKey(),
27
- expiresAt: timestamp("expires_at").notNull(),
28
- token: text("token").notNull().unique(),
29
- createdAt: timestamp("created_at").notNull().defaultNow(),
30
- updatedAt: timestamp("updated_at").notNull().defaultNow(),
31
- ipAddress: text("ip_address"),
32
- userAgent: text("user_agent"),
33
- userId: text("user_id")
34
- .notNull()
35
- .references(() => user.id, { onDelete: "cascade" }),
36
- });
37
-
38
- // ─── account 테이블 ─────────────────────────────────────
39
-
40
- export const account = pgTable("account", {
41
- id: text("id").primaryKey(),
42
- accountId: text("account_id").notNull(),
43
- providerId: text("provider_id").notNull(),
44
- userId: text("user_id")
45
- .notNull()
46
- .references(() => user.id, { onDelete: "cascade" }),
47
- accessToken: text("access_token"),
48
- refreshToken: text("refresh_token"),
49
- idToken: text("id_token"),
50
- accessTokenExpiresAt: timestamp("access_token_expires_at"),
51
- refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
52
- scope: text("scope"),
53
- password: text("password"),
54
- createdAt: timestamp("created_at").notNull().defaultNow(),
55
- updatedAt: timestamp("updated_at").notNull().defaultNow(),
56
- });
57
-
58
- // ─── verification 테이블 ────────────────────────────────
59
-
60
- export const verification = pgTable("verification", {
61
- id: text("id").primaryKey(),
62
- identifier: text("identifier").notNull(),
63
- value: text("value").notNull(),
64
- expiresAt: timestamp("expires_at").notNull(),
65
- createdAt: timestamp("created_at").defaultNow(),
66
- updatedAt: timestamp("updated_at").defaultNow(),
67
- });