|
| 1 | +// @generated by @metaobjectsdev/codegen-ts — hand edits are kept by a three-way merge on regeneration; meta verify --codegen checks only the generated parts. |
| 2 | +// Source metadata: Article (Article) |
| 3 | +// Extend in your own module (e.g. Article.extra.ts) — nothing imports it for you. |
| 4 | +import type { InferInsertModel, InferSelectModel } from "drizzle-orm"; |
| 5 | +import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core"; |
| 6 | +import { z } from "zod"; |
| 7 | + |
| 8 | +export const articles = sqliteTable("articles", { |
| 9 | + id: integer("id").primaryKey({ autoIncrement: true }), |
| 10 | + title: text("title").notNull(), |
| 11 | + createdAt: text("created_at").$defaultFn(() => new Date().toISOString()), |
| 12 | + updatedAt: text("updated_at").$defaultFn(() => new Date().toISOString()), |
| 13 | +}); |
| 14 | +export type Article = InferSelectModel<typeof articles>; |
| 15 | +export type ArticleInsert = InferInsertModel<typeof articles>; |
| 16 | +export type ArticleUpdate = Partial<ArticleInsert>; |
| 17 | +/** A field.timestamp instant in UTC (`YYYY-MM-DDTHH:MM:SS[.fff]Z`): a value already spelled so is kept |
| 18 | + * as sent, an offset is applied, a zoneless value is UTC and a date alone is midnight UTC. |
| 19 | + * SQLite/D1 compare timestamps as text, so instants are stored in UTC. Generated. */ |
| 20 | +function utcIsoTimestamp(v: string): string { |
| 21 | + if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/.test(v)) { |
| 22 | + return v; |
| 23 | + } |
| 24 | + const m = |
| 25 | + /^(\d{4}-\d{2}-\d{2})(?:[Tt ](\d{2}:\d{2})(?::(\d{2})(?:\.(\d+))?)?(?:([Zz])|([+-]\d{2}):?(\d{2})?)?)?$/.exec( |
| 26 | + v, |
| 27 | + ); |
| 28 | + if (m === null) { |
| 29 | + return v; |
| 30 | + } |
| 31 | + const t = Date.parse( |
| 32 | + `${m[1]}T${m[2] ?? "00:00"}:${m[3] ?? "00"}.${(m[4] ?? "").slice(0, 3).padEnd(3, "0")}${ |
| 33 | + m[6] === undefined ? "Z" : `${m[6]}:${m[7] ?? "00"}` |
| 34 | + }`, |
| 35 | + ); |
| 36 | + return Number.isNaN(t) |
| 37 | + ? v |
| 38 | + : new Date(t).toISOString().replace(/\.?0+Z$/, "Z"); |
| 39 | +} |
| 40 | + |
| 41 | +export const ArticleInsertSchema = z.object({ |
| 42 | + title: z.string().min(1).max(200), |
| 43 | + createdAt: z |
| 44 | + .string() |
| 45 | + .optional() |
| 46 | + .transform(() => new Date().toISOString()), |
| 47 | + updatedAt: z |
| 48 | + .string() |
| 49 | + .optional() |
| 50 | + .transform(() => new Date().toISOString()), |
| 51 | +}); |
| 52 | + |
| 53 | +export const ArticleUpdateSchema = z.object({ |
| 54 | + title: z.string().min(1).max(200).optional(), |
| 55 | + updatedAt: z |
| 56 | + .string() |
| 57 | + .optional() |
| 58 | + .transform(() => new Date().toISOString()), |
| 59 | +}); |
| 60 | + |
| 61 | +/** Typed create shape for Article: the insert schema's INPUT (pre-transform) type. A |
| 62 | + * renamed/dropped/misspelt field is a compile error at every `createArticle` call site; |
| 63 | + * the schema still validates at runtime. */ |
| 64 | +export type ArticleCreate = z.input<typeof ArticleInsertSchema>; |
| 65 | + |
| 66 | +/** Typed patch shape for Article: every settable field, optional (FR-035 PATCH). A |
| 67 | + * renamed/dropped field is a compile error at every `updateArticle` call site. */ |
| 68 | +export type ArticlePatch = z.input<typeof ArticleUpdateSchema>; |
| 69 | + |
| 70 | +/** Insert-shape for import / restore / replication of Article: identical to |
| 71 | + * ArticleInsertSchema, but the @autoSet timestamp columns are written VERBATIM |
| 72 | + * (no create-time now() stamp) so the caller's original values are preserved. */ |
| 73 | +export const ArticleInsertPreservingSchema = z.object({ |
| 74 | + title: z.string().min(1).max(200), |
| 75 | + createdAt: z |
| 76 | + .string() |
| 77 | + .regex( |
| 78 | + /^(?:\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|02-(?:0[1-9]|1\d|2[0-8]))|(?:\d{2}(?:0[48]|[2468][048]|[13579][26])|(?:[02468][048]|[13579][26])00)-02-29)(?:[Tt ](?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:[Zz]|[+-](?:[01]\d|2[0-3])(?::?[0-5]\d)?)?)?$/, |
| 79 | + "must be an ISO 8601 timestamp (YYYY-MM-DD[THH:MM[:SS[.fff]]][Z|±HH:MM])", |
| 80 | + ) |
| 81 | + .transform(utcIsoTimestamp) |
| 82 | + .optional(), |
| 83 | + updatedAt: z |
| 84 | + .string() |
| 85 | + .regex( |
| 86 | + /^(?:\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|02-(?:0[1-9]|1\d|2[0-8]))|(?:\d{2}(?:0[48]|[2468][048]|[13579][26])|(?:[02468][048]|[13579][26])00)-02-29)(?:[Tt ](?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:[Zz]|[+-](?:[01]\d|2[0-3])(?::?[0-5]\d)?)?)?$/, |
| 87 | + "must be an ISO 8601 timestamp (YYYY-MM-DD[THH:MM[:SS[.fff]]][Z|±HH:MM])", |
| 88 | + ) |
| 89 | + .transform(utcIsoTimestamp) |
| 90 | + .optional(), |
| 91 | +}); |
| 92 | + |
| 93 | +/** Typed input of `insertPreservingArticle` — ArticleInsertPreservingSchema's pre-transform shape. */ |
| 94 | +export type ArticleCreatePreserving = z.input< |
| 95 | + typeof ArticleInsertPreservingSchema |
| 96 | +>; |
| 97 | +/** |
| 98 | + * Metadata constants for Article. |
| 99 | + * |
| 100 | + * Use these instead of magic strings so TS catches typos and refactors stay |
| 101 | + * coherent. Each non-dollar-prefixed key is a per-field object carrying |
| 102 | + * name, label, view, an htmlType where the field's view maps to one, and the |
| 103 | + * RHF-shaped validation rules derived from the field's validator children. |
| 104 | + * |
| 105 | + * placeholder and helpText are NOT emitted — no provider registers an attribute |
| 106 | + * for them, so nothing here could derive one. (htmlType is emitted, but derived |
| 107 | + * from the view subtype; the @htmlType override was removed for the same reason.) |
| 108 | + * useEntityForm still honours placeholder if you add it: this file is generated, |
| 109 | + * hand edits inside it survive regeneration through the three-way merge, and the |
| 110 | + * consumers read this const rather than the metadata. That is the intended way |
| 111 | + * to set it. |
| 112 | + * |
| 113 | + * Typical usage with the metaobjects React form helper: |
| 114 | + * |
| 115 | + * import { useEntityForm } from '@metaobjectsdev/react'; |
| 116 | + * const form = useEntityForm(Article, ArticleInsertSchema); |
| 117 | + * <input {...form.input.id} /> |
| 118 | + */ |
| 119 | +export const Article = { |
| 120 | + $entity: "Article", |
| 121 | + $table: "articles", |
| 122 | + $path: "/articles", |
| 123 | + id: { name: "id", label: "Id", view: "number", htmlType: "number" }, |
| 124 | + title: { |
| 125 | + name: "title", |
| 126 | + label: "Title", |
| 127 | + view: "text", |
| 128 | + htmlType: "text", |
| 129 | + rules: { |
| 130 | + required: "Title is required", |
| 131 | + maxLength: { value: 200, message: "Must be 200 characters or fewer" }, |
| 132 | + }, |
| 133 | + }, |
| 134 | + createdAt: { |
| 135 | + name: "createdAt", |
| 136 | + label: "Created At", |
| 137 | + view: "date", |
| 138 | + htmlType: "datetime-local", |
| 139 | + }, |
| 140 | + updatedAt: { |
| 141 | + name: "updatedAt", |
| 142 | + label: "Updated At", |
| 143 | + view: "date", |
| 144 | + htmlType: "datetime-local", |
| 145 | + }, |
| 146 | +} as const; |
| 147 | +import type { FilterAllowlist } from "@metaobjectsdev/runtime-ts/drizzle-fastify"; |
| 148 | + |
| 149 | +export const ArticleFilterAllowlist = {} as const satisfies FilterAllowlist; |
| 150 | +import type { SortAllowlist } from "@metaobjectsdev/runtime-ts/drizzle-fastify"; |
| 151 | + |
| 152 | +export const ArticleSortAllowlist = {} as const satisfies SortAllowlist; |
| 153 | +export type ArticleFilter = { |
| 154 | + limit?: number; |
| 155 | + offset?: number; |
| 156 | + sort?: string; |
| 157 | + or?: ArticleFilter[]; |
| 158 | + and?: ArticleFilter[]; |
| 159 | +}; |
0 commit comments