@workerstack/database 0.21.0 → 0.22.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.
- package/README.md +243 -40
- package/docs/meta-contract.md +55 -1
- package/package.json +3 -7
- package/src/cli/args.ts +4 -2
- package/src/cli/codegen.ts +2 -2
- package/src/cli/comb-config.ts +8 -3
- package/src/cli/file-path.ts +25 -0
- package/src/cli/migrate-apply.ts +5 -21
- package/src/cli/migrate-d1.ts +5 -1
- package/src/cli/migrate-json.ts +48 -0
- package/src/cli/migrate.ts +26 -4
- package/src/codegen/analyzer-types.ts +6 -1
- package/src/codegen/annotations.ts +66 -9
- package/src/codegen/format-constraints.ts +114 -0
- package/src/codegen/generators/dtos/entity-file.ts +2 -1
- package/src/codegen/generators/dtos/example-meta.ts +22 -2
- package/src/codegen/generators/dtos/field-schema.ts +31 -8
- package/src/codegen/generators/dtos/ip-patterns.ts +25 -11
- package/src/codegen/generators/dtos/number-range.ts +22 -3
- package/src/codegen/generators/dtos/schema-aliases.ts +5 -3
- package/src/codegen/generators/dtos/text-format.ts +63 -0
- package/src/codegen/generators/dtos/text-schema.ts +49 -2
- package/src/codegen/generators/manifest.ts +9 -1
- package/src/codegen/runtime/read-comb.ts +71 -3
- package/src/codegen/runtime/read-tables.ts +31 -19
- package/src/codegen/runtime/snapshot-types.ts +3 -1
- package/src/codegen/runtime/to-meta.ts +6 -3
- package/src/formats/catalog.ts +255 -0
- package/src/formats/iana-time-zone.ts +117 -0
- package/src/formats/iso3166-1.ts +78 -0
- package/src/formats/iso4217.ts +42 -0
- package/src/formats/iso639-1.ts +41 -0
- package/src/formats/uts35.ts +143 -0
- package/src/index.ts +5 -0
- package/src/meta/column.ts +22 -9
- package/src/migrate/core/apply.ts +63 -22
- package/src/migrate/core/atlas-apply-runs.ts +15 -26
- package/src/migrate/core/cleanup.ts +22 -10
- package/src/migrate/core/d1-engine-child.mjs +27 -11
- package/src/migrate/core/d1-history.ts +23 -26
- package/src/migrate/core/d1-wrangler-error.ts +24 -1
- package/src/migrate/core/pg-replay-commit.ts +41 -38
- package/src/migrate/core/pg-replay-drops.ts +17 -32
- package/src/migrate/core/pg-replay-hidden.ts +75 -0
- package/src/migrate/core/pg-replay-roles.ts +2 -4
- package/src/migrate/core/pg-replay.ts +21 -19
- package/src/migrate/core/pg-server-snapshot.ts +4 -24
- package/src/migrate/core/proof-readers.ts +80 -0
- package/src/migrate/core/proof-run.ts +19 -5
- package/src/migrate/core/proof-scope.ts +27 -14
- package/src/migrate/core/sql-code.ts +36 -5
- package/src/migrate/core/sql-scan.ts +7 -1
- package/src/migrate/core/sqlite-keywords.ts +70 -0
- package/src/migrate/core/stopped.ts +70 -0
- package/src/migrate/core/trigger-write.d.mts +7 -0
- package/src/migrate/core/trigger-write.mjs +42 -0
- package/src/pg/columns.ts +6 -4
- package/src/query/cursor-mint.ts +11 -18
- package/src/query/cursor-refusals.ts +22 -11
- package/src/query/descriptions.ts +4 -9
- package/src/query/filter-parse.ts +80 -22
- package/src/query/filter-validate.ts +10 -13
- package/src/query/filter.ts +40 -18
- package/src/query/list-extras.ts +7 -10
- package/src/query/list-schema.ts +0 -2
- package/src/query/merged.ts +3 -2
- package/src/query/pagination.ts +30 -6
- package/src/query/rounded-key.ts +5 -8
- package/src/query/schema-params.ts +12 -5
- package/src/query/select-validate.ts +7 -4
- package/src/query/sqlite/cursor-fit.ts +10 -2
- package/src/query/trusted.ts +7 -2
- package/src/sqlite/columns.ts +6 -4
- package/src/sqlite/constraints.ts +120 -6
- package/types/cli/args.d.ts.map +1 -1
- package/types/cli/comb-config.d.ts +5 -2
- package/types/cli/comb-config.d.ts.map +1 -1
- package/types/cli/file-path.d.ts +11 -0
- package/types/cli/file-path.d.ts.map +1 -0
- package/types/cli/migrate-apply.d.ts +1 -0
- package/types/cli/migrate-apply.d.ts.map +1 -1
- package/types/cli/migrate-d1.d.ts.map +1 -1
- package/types/cli/migrate-json.d.ts +4 -0
- package/types/cli/migrate-json.d.ts.map +1 -0
- package/types/cli/migrate.d.ts.map +1 -1
- package/types/codegen/analyzer-types.d.ts +6 -1
- package/types/codegen/analyzer-types.d.ts.map +1 -1
- package/types/codegen/annotations.d.ts +12 -7
- package/types/codegen/annotations.d.ts.map +1 -1
- package/types/codegen/format-constraints.d.ts +22 -0
- package/types/codegen/format-constraints.d.ts.map +1 -0
- package/types/codegen/generators/dtos/entity-file.d.ts.map +1 -1
- package/types/codegen/generators/dtos/example-meta.d.ts.map +1 -1
- package/types/codegen/generators/dtos/field-schema.d.ts.map +1 -1
- package/types/codegen/generators/dtos/ip-patterns.d.ts +7 -0
- package/types/codegen/generators/dtos/ip-patterns.d.ts.map +1 -1
- package/types/codegen/generators/dtos/number-range.d.ts +8 -0
- package/types/codegen/generators/dtos/number-range.d.ts.map +1 -1
- package/types/codegen/generators/dtos/schema-aliases.d.ts +1 -1
- package/types/codegen/generators/dtos/schema-aliases.d.ts.map +1 -1
- package/types/codegen/generators/dtos/text-format.d.ts +31 -0
- package/types/codegen/generators/dtos/text-format.d.ts.map +1 -0
- package/types/codegen/generators/dtos/text-schema.d.ts +8 -1
- package/types/codegen/generators/dtos/text-schema.d.ts.map +1 -1
- package/types/codegen/generators/manifest.d.ts +5 -0
- package/types/codegen/generators/manifest.d.ts.map +1 -1
- package/types/codegen/runtime/read-comb.d.ts +17 -3
- package/types/codegen/runtime/read-comb.d.ts.map +1 -1
- package/types/codegen/runtime/read-tables.d.ts.map +1 -1
- package/types/codegen/runtime/snapshot-types.d.ts +3 -1
- package/types/codegen/runtime/snapshot-types.d.ts.map +1 -1
- package/types/codegen/runtime/to-meta.d.ts.map +1 -1
- package/types/formats/catalog.d.ts +51 -0
- package/types/formats/catalog.d.ts.map +1 -0
- package/types/formats/iana-time-zone.d.ts +7 -0
- package/types/formats/iana-time-zone.d.ts.map +1 -0
- package/types/formats/iso3166-1.d.ts +12 -0
- package/types/formats/iso3166-1.d.ts.map +1 -0
- package/types/formats/iso4217.d.ts +7 -0
- package/types/formats/iso4217.d.ts.map +1 -0
- package/types/formats/iso639-1.d.ts +6 -0
- package/types/formats/iso639-1.d.ts.map +1 -0
- package/types/formats/uts35.d.ts +13 -0
- package/types/formats/uts35.d.ts.map +1 -0
- package/types/index.d.ts +5 -0
- package/types/index.d.ts.map +1 -1
- package/types/meta/column.d.ts +7 -1
- package/types/meta/column.d.ts.map +1 -1
- package/types/migrate/core/apply.d.ts +3 -2
- package/types/migrate/core/apply.d.ts.map +1 -1
- package/types/migrate/core/atlas-apply-runs.d.ts +6 -0
- package/types/migrate/core/atlas-apply-runs.d.ts.map +1 -1
- package/types/migrate/core/cleanup.d.ts +16 -4
- package/types/migrate/core/cleanup.d.ts.map +1 -1
- package/types/migrate/core/d1-history.d.ts.map +1 -1
- package/types/migrate/core/d1-wrangler-error.d.ts +11 -0
- package/types/migrate/core/d1-wrangler-error.d.ts.map +1 -1
- package/types/migrate/core/pg-replay-commit.d.ts +14 -9
- package/types/migrate/core/pg-replay-commit.d.ts.map +1 -1
- package/types/migrate/core/pg-replay-drops.d.ts +7 -12
- package/types/migrate/core/pg-replay-drops.d.ts.map +1 -1
- package/types/migrate/core/pg-replay-hidden.d.ts +36 -0
- package/types/migrate/core/pg-replay-hidden.d.ts.map +1 -0
- package/types/migrate/core/pg-replay-roles.d.ts +2 -4
- package/types/migrate/core/pg-replay-roles.d.ts.map +1 -1
- package/types/migrate/core/pg-replay.d.ts.map +1 -1
- package/types/migrate/core/pg-server-snapshot.d.ts +4 -11
- package/types/migrate/core/pg-server-snapshot.d.ts.map +1 -1
- package/types/migrate/core/proof-readers.d.ts +19 -0
- package/types/migrate/core/proof-readers.d.ts.map +1 -0
- package/types/migrate/core/proof-run.d.ts.map +1 -1
- package/types/migrate/core/proof-scope.d.ts +15 -7
- package/types/migrate/core/proof-scope.d.ts.map +1 -1
- package/types/migrate/core/sql-code.d.ts +7 -3
- package/types/migrate/core/sql-code.d.ts.map +1 -1
- package/types/migrate/core/sql-scan.d.ts.map +1 -1
- package/types/migrate/core/sqlite-keywords.d.ts +11 -0
- package/types/migrate/core/sqlite-keywords.d.ts.map +1 -0
- package/types/migrate/core/stopped.d.ts +23 -0
- package/types/migrate/core/stopped.d.ts.map +1 -0
- package/types/pg/columns.d.ts +3 -3
- package/types/pg/columns.d.ts.map +1 -1
- package/types/query/cursor-mint.d.ts.map +1 -1
- package/types/query/cursor-refusals.d.ts +17 -1
- package/types/query/cursor-refusals.d.ts.map +1 -1
- package/types/query/descriptions.d.ts +1 -1
- package/types/query/descriptions.d.ts.map +1 -1
- package/types/query/filter-parse.d.ts +15 -4
- package/types/query/filter-parse.d.ts.map +1 -1
- package/types/query/filter-validate.d.ts +1 -1
- package/types/query/filter-validate.d.ts.map +1 -1
- package/types/query/filter.d.ts +9 -1
- package/types/query/filter.d.ts.map +1 -1
- package/types/query/list-extras.d.ts.map +1 -1
- package/types/query/list-schema.d.ts.map +1 -1
- package/types/query/merged.d.ts.map +1 -1
- package/types/query/pagination.d.ts +13 -1
- package/types/query/pagination.d.ts.map +1 -1
- package/types/query/rounded-key.d.ts +2 -11
- package/types/query/rounded-key.d.ts.map +1 -1
- package/types/query/schema-params.d.ts.map +1 -1
- package/types/query/select-validate.d.ts.map +1 -1
- package/types/query/sqlite/cursor-fit.d.ts.map +1 -1
- package/types/query/trusted.d.ts +1 -1
- package/types/query/trusted.d.ts.map +1 -1
- package/types/sqlite/columns.d.ts +3 -3
- package/types/sqlite/columns.d.ts.map +1 -1
- package/types/sqlite/constraints.d.ts +117 -5
- package/types/sqlite/constraints.d.ts.map +1 -1
- package/src/sqlite/patterns.ts +0 -19
- package/types/sqlite/patterns.d.ts +0 -19
- package/types/sqlite/patterns.d.ts.map +0 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
/** What the runtime reader reads of a c helper's own record: its constraints and an enum's state machine, as JSON */
|
|
2
|
-
import
|
|
1
|
+
/** What the runtime reader reads of a c helper's own record: its constraints, a column schema and an enum's state machine, as JSON */
|
|
2
|
+
import * as z from "zod"
|
|
3
|
+
import type { CombColumnMeta } from "../../meta/column.ts"
|
|
4
|
+
import type { ModuleExport, SnapshotComb } from "./snapshot-types.ts"
|
|
3
5
|
|
|
4
6
|
const STRING_LIST = (value: unknown): value is string[] =>
|
|
5
7
|
Array.isArray(value) && value.every((item) => typeof item === "string")
|
|
@@ -21,6 +23,72 @@ function constraintsOf(raw: unknown, at: string): Record<string, boolean | numbe
|
|
|
21
23
|
return constraints
|
|
22
24
|
}
|
|
23
25
|
|
|
26
|
+
/** The packages a schema found nowhere might have been in, as its error names them; empty when every module loaded */
|
|
27
|
+
const skipped = (unloaded: readonly string[]): string =>
|
|
28
|
+
unloaded.length === 0 ? "" : ` (${unloaded.join(", ")} would not load on their own)`
|
|
29
|
+
|
|
30
|
+
/* the helpers whose `schema` key names a zod schema the generated DTOs pipe the value into; on any other the key stays a constraint, which the constraint check refuses by name */
|
|
31
|
+
// lookup-table: the c helpers that take a column schema
|
|
32
|
+
const SCHEMA_KINDS: ReadonlySet<string> = /* @__PURE__ */ new Set(["integer", "real", "text"])
|
|
33
|
+
|
|
34
|
+
const DEFS = "#/$defs/"
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* `node` with each `$ref` replaced by the entry of `defs` it points at, its sibling keywords kept:
|
|
38
|
+
* zod files a schema carrying an `id` under the root's `$defs`, a pointer that would dangle once the
|
|
39
|
+
* literal sits in another document's `allOf`. Every `$ref` zod writes points into `$defs`, as
|
|
40
|
+
* `cycles: "throw"` leaves no reference back to the root
|
|
41
|
+
*/
|
|
42
|
+
function inlined(node: unknown, defs: Readonly<Record<string, unknown>>): unknown {
|
|
43
|
+
if (Array.isArray(node)) return node.map((each) => inlined(each, defs))
|
|
44
|
+
if (typeof node !== "object" || node === null) return node
|
|
45
|
+
const { $ref, ...rest } = node as Record<string, unknown>
|
|
46
|
+
const own = Object.fromEntries(Object.entries(rest).map(([key, value]) => [key, inlined(value, defs)]))
|
|
47
|
+
if ($ref === undefined) return own
|
|
48
|
+
const name = ($ref as string).slice(DEFS.length).replaceAll("~1", "/").replaceAll("~0", "~")
|
|
49
|
+
return { ...(inlined(defs[name], defs) as object), ...own }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** The input JSON Schema of a zod schema as a self-contained literal, `$schema` dropped; an error naming the column when zod has none */
|
|
53
|
+
function inputJsonOf(schema: z.ZodType, at: string): Readonly<Record<string, unknown>> {
|
|
54
|
+
let json: Record<string, unknown>
|
|
55
|
+
try {
|
|
56
|
+
json = z.toJSONSchema(schema, { cycles: "throw", io: "input" }) as Record<string, unknown>
|
|
57
|
+
} catch (error) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
`${at}: the schema its schema key is given has no JSON Schema form (zod: ${(error as Error).message}); comb publishes every DTO rule`,
|
|
60
|
+
{ cause: error },
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
const { $defs, $schema: _dropped, ...root } = json
|
|
64
|
+
return inlined(root, ($defs ?? {}) as Record<string, unknown>) as Record<string, unknown>
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* A helper's constraints with its `schema` key read: on a text or number column, taken out for the
|
|
69
|
+
* export that holds it and its input JSON Schema; on any other helper, kept as `true` for the
|
|
70
|
+
* constraint check to refuse. An error naming the column for a value that is no zod schema, and
|
|
71
|
+
* for one no module exports, naming the modules that would not load (`unloaded`)
|
|
72
|
+
*/
|
|
73
|
+
function columnSchemaOf(
|
|
74
|
+
meta: CombColumnMeta,
|
|
75
|
+
at: string,
|
|
76
|
+
{ locate, unloaded }: { locate: (value: unknown) => ModuleExport | null; unloaded: readonly string[] },
|
|
77
|
+
): Pick<SnapshotComb, "schema" | "schemaJson"> & { constraints: Record<string, unknown> } {
|
|
78
|
+
const { schema: declared, ...constraints } = (meta.constraints ?? {}) as Record<string, unknown>
|
|
79
|
+
if (declared === undefined) return { constraints, schema: null, schemaJson: null }
|
|
80
|
+
if (!SCHEMA_KINDS.has(meta.kind))
|
|
81
|
+
return { constraints: { ...constraints, schema: true }, schema: null, schemaJson: null }
|
|
82
|
+
if (typeof declared !== "object" || declared === null || !("_zod" in declared))
|
|
83
|
+
throw new Error(`${at}: the constraint schema is no zod schema; comb's DTOs are zod 4, so the schema must be one`)
|
|
84
|
+
const schema = locate(declared)
|
|
85
|
+
if (schema === null)
|
|
86
|
+
throw new Error(
|
|
87
|
+
`${at}: no module of the project exports the schema its schema key is given${skipped(unloaded)}; export it, above the table that names it, so the generated DTOs can import it`,
|
|
88
|
+
)
|
|
89
|
+
return { constraints, schema, schemaJson: inputJsonOf(declared as z.ZodType, at) }
|
|
90
|
+
}
|
|
91
|
+
|
|
24
92
|
/* the keys a c.enum's state machine has; values, which docs/state-machines.md §4 holds in the same const, read from c.enum's second argument */
|
|
25
93
|
const STATE_KEYS = ["initial", "terminal", "transitions", "values"]
|
|
26
94
|
|
|
@@ -141,4 +209,4 @@ function refuseJsonDocument(
|
|
|
141
209
|
)
|
|
142
210
|
}
|
|
143
211
|
|
|
144
|
-
export { constraintsOf, refuseJsonDocument, statesOf, STRING_LIST }
|
|
212
|
+
export { columnSchemaOf, constraintsOf, refuseJsonDocument, skipped, statesOf, STRING_LIST }
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The runtime reader: load the tables module, find every drizzle table it exports, and read each
|
|
3
3
|
* as drizzle built it (getTableConfig) and as comb's `c` helpers recorded it (combColumnMeta).
|
|
4
|
-
* Objects a generated file must import, a c.json schema or a
|
|
5
|
-
* identity among the exports of the project modules the tables module loads.
|
|
4
|
+
* Objects a generated file must import, a c.json schema or a text or number column's schema, are
|
|
5
|
+
* located by identity among the exports of the project modules the tables module loads.
|
|
6
6
|
*/
|
|
7
7
|
import { Column, getTableColumns, is, type SQL, type Table } from "drizzle-orm"
|
|
8
8
|
import { ExtraConfigColumn, getTableConfig as pgConfig, IndexedColumn, PgDialect, PgTable } from "drizzle-orm/pg-core"
|
|
9
9
|
import { getTableConfig as sqliteConfig, SQLiteDialect, SQLiteTable } from "drizzle-orm/sqlite-core"
|
|
10
10
|
import { byCodeUnit } from "../utils/order.ts"
|
|
11
|
-
import { combColumnMeta } from "../../meta/column.ts"
|
|
11
|
+
import { combColumnMeta, type CombColumnMeta } from "../../meta/column.ts"
|
|
12
12
|
import { dimensionsOf, filledByDefault, type ReadColumn, unnamedUnique } from "./read-column.ts"
|
|
13
|
-
import { constraintsOf, refuseJsonDocument, statesOf, STRING_LIST } from "./read-comb.ts"
|
|
13
|
+
import { columnSchemaOf, constraintsOf, refuseJsonDocument, skipped, statesOf, STRING_LIST } from "./read-comb.ts"
|
|
14
14
|
import type { ElementNulls } from "./element-types.ts"
|
|
15
15
|
import type {
|
|
16
16
|
ModuleExport,
|
|
@@ -52,29 +52,41 @@ type Context = {
|
|
|
52
52
|
unloaded: readonly string[]
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/** Where `value` is exported, the first of `exportsHolding`; null when nowhere, or when nothing was given */
|
|
56
|
+
const locate = (value: unknown, context: Context): ModuleExport | null =>
|
|
57
|
+
value === undefined ? null : (exportsHolding(value, context.loaded, context.tablesPath)[0] ?? null)
|
|
58
|
+
|
|
59
|
+
/** Where a c.json column's schema is exported; an error naming the column when nowhere, or for a schema that is no stored document */
|
|
60
|
+
function jsonSchemaOf(
|
|
61
|
+
meta: CombColumnMeta,
|
|
62
|
+
column: ReadColumn,
|
|
63
|
+
{ at, context }: { at: string; context: Context },
|
|
64
|
+
): ModuleExport | null {
|
|
65
|
+
if (meta.kind !== "json") return null
|
|
66
|
+
const schema = locate(meta.schema, context)
|
|
67
|
+
if (schema === null)
|
|
68
|
+
throw new Error(
|
|
69
|
+
`${at}: no module of the project exports the schema its c.json is given${skipped(context.unloaded)}; export it, so the generated DTOs can import it`,
|
|
70
|
+
)
|
|
71
|
+
refuseJsonDocument(meta.schema, at, {
|
|
72
|
+
filled: filledByDefault(column),
|
|
73
|
+
notNull: column.notNull && !column.dimensions,
|
|
74
|
+
})
|
|
75
|
+
return schema
|
|
76
|
+
}
|
|
77
|
+
|
|
55
78
|
function combOf(column: ReadColumn, at: string, context: Context): SnapshotComb | null {
|
|
56
79
|
const meta = combColumnMeta(column)
|
|
57
80
|
if (meta === undefined) return null
|
|
58
|
-
const located = (value: unknown) =>
|
|
59
|
-
value === undefined ? null : (exportsHolding(value, context.loaded, context.tablesPath)[0] ?? null)
|
|
60
81
|
if (meta.values !== undefined && !STRING_LIST(meta.values)) throw new Error(`${at}: c.enum takes an array of strings`)
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
const skipped = context.unloaded.length === 0 ? "" : ` (${context.unloaded.join(", ")} would not load on their own)`
|
|
64
|
-
throw new Error(
|
|
65
|
-
`${at}: no module of the project exports the schema its c.json is given${skipped}; export it, so the generated DTOs can import it`,
|
|
66
|
-
)
|
|
67
|
-
}
|
|
68
|
-
if (meta.kind === "json")
|
|
69
|
-
refuseJsonDocument(meta.schema, at, {
|
|
70
|
-
filled: filledByDefault(column),
|
|
71
|
-
notNull: column.notNull && !column.dimensions,
|
|
72
|
-
})
|
|
82
|
+
const own = columnSchemaOf(meta, at, { locate: (value) => locate(value, context), unloaded: context.unloaded })
|
|
83
|
+
const schema = own.schema ?? jsonSchemaOf(meta, column, { at, context })
|
|
73
84
|
return {
|
|
74
|
-
constraints: constraintsOf(
|
|
85
|
+
constraints: constraintsOf(own.constraints, at),
|
|
75
86
|
kind: meta.kind,
|
|
76
87
|
prefix: meta.prefix ?? null,
|
|
77
88
|
schema,
|
|
89
|
+
schemaJson: own.schemaJson,
|
|
78
90
|
states: statesOf(meta.states, at, column),
|
|
79
91
|
values: meta.values === undefined ? null : [...meta.values],
|
|
80
92
|
}
|
|
@@ -14,8 +14,10 @@ type SnapshotComb = {
|
|
|
14
14
|
constraints: Record<string, boolean | number | string>
|
|
15
15
|
kind: string
|
|
16
16
|
prefix: string | null
|
|
17
|
-
/** where the exact zod schema a c.json column was given is exported; null when
|
|
17
|
+
/** where the exact zod schema a c.json column, or a text or number column's `schema` key, was given is exported; null when none was given */
|
|
18
18
|
schema: ModuleExport | null
|
|
19
|
+
/** a text or number column's schema as its input JSON Schema, self-contained (each `$defs` entry inlined) and `$schema` dropped; null on c.json and when undeclared */
|
|
20
|
+
schemaJson: Readonly<Record<string, unknown>> | null
|
|
19
21
|
states: { initial: string | null; terminal: string[] | null; transitions: Record<string, string[]> | null } | null
|
|
20
22
|
values: string[] | null
|
|
21
23
|
}
|
|
@@ -141,14 +141,15 @@ const TYPED_COLUMNS = {
|
|
|
141
141
|
/** What a column's `c` helper recorded, as FieldMeta names it; a plain drizzle column's own enum values */
|
|
142
142
|
function combFactsOf(
|
|
143
143
|
column: SnapshotColumn,
|
|
144
|
-
): Pick<FieldMeta, "enumValues" | "jsonSchemaName" | "prefix" | "schemaImports" | "states"> {
|
|
144
|
+
): Pick<FieldMeta, "enumValues" | "jsonSchemaName" | "prefix" | "schemaImports" | "schemaJson" | "states"> {
|
|
145
145
|
const comb = column.comb
|
|
146
146
|
const schema = comb?.schema ?? null
|
|
147
147
|
return {
|
|
148
148
|
enumValues: comb?.values ?? column.enumValues,
|
|
149
|
-
jsonSchemaName: schema
|
|
149
|
+
jsonSchemaName: comb?.kind === "json" ? (schema as ModuleExport).name : null,
|
|
150
150
|
prefix: comb?.prefix ?? null,
|
|
151
151
|
schemaImports: schema === null ? [] : [importOf(schema)],
|
|
152
|
+
schemaJson: comb?.schemaJson ?? null,
|
|
152
153
|
states: comb?.states ?? null,
|
|
153
154
|
}
|
|
154
155
|
}
|
|
@@ -172,19 +173,21 @@ function fieldOf(column: SnapshotColumn, { file, table, tables }: Build): FieldM
|
|
|
172
173
|
`${place}: comb has no rule for a ${column.columnType} column (${column.dataType}); build it with a c helper, or as drizzle ${TYPED_COLUMNS[table.dialect]}`,
|
|
173
174
|
)
|
|
174
175
|
const filled = isFilled(column, kind)
|
|
176
|
+
const facts = combFactsOf(column)
|
|
175
177
|
const constraints = fieldConstraintsOf(column.comb?.constraints ?? {}, {
|
|
176
178
|
fieldName: column.key,
|
|
177
179
|
filled,
|
|
178
180
|
helper: kind,
|
|
179
181
|
measure: measuredBy(column, kind),
|
|
180
182
|
place,
|
|
183
|
+
values: facts.enumValues,
|
|
181
184
|
})
|
|
182
185
|
if (constraints.mutable && column.foreignKey === null && kind !== "ref")
|
|
183
186
|
throw new Error(`${place}: mutable lets a reference move on update, and ${column.key} references nothing`)
|
|
184
187
|
if (constraints.relation !== null && column.foreignKey === null)
|
|
185
188
|
throw new Error(`${place}: relation names the relation of a key, and ${column.key} references nothing`)
|
|
186
189
|
return {
|
|
187
|
-
...
|
|
190
|
+
...facts,
|
|
188
191
|
autoIncrement: column.autoIncrement,
|
|
189
192
|
columnType: column.columnType,
|
|
190
193
|
combKind: kind,
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The standard formats a column declares with `format`: each id's standard, the source its DTO checks,
|
|
3
|
+
* its length bounds, the transforms that run before the check, and the pinned registry a value must
|
|
4
|
+
* also belong to. The DTO's failure is zod's `invalid_format` issue with the id and no message, so a
|
|
5
|
+
* zod locale or error map translates it; the catalog carries no text a person reads but `standard`.
|
|
6
|
+
*/
|
|
7
|
+
import { ipv4Source, strictIpv6Source } from "../codegen/generators/dtos/ip-patterns.ts"
|
|
8
|
+
import { isIanaTimeZone } from "./iana-time-zone.ts"
|
|
9
|
+
import { isIso3166Alpha2, isIso3166Alpha3 } from "./iso3166-1.ts"
|
|
10
|
+
import { isIso4217 } from "./iso4217.ts"
|
|
11
|
+
import { isIso639Alpha2 } from "./iso639-1.ts"
|
|
12
|
+
import {
|
|
13
|
+
CALENDARS,
|
|
14
|
+
FIRST_DAYS,
|
|
15
|
+
HOUR_CYCLES,
|
|
16
|
+
MEASUREMENT_SYSTEMS,
|
|
17
|
+
MEASUREMENT_UNITS,
|
|
18
|
+
NUMBERING_SYSTEMS,
|
|
19
|
+
} from "./uts35.ts"
|
|
20
|
+
|
|
21
|
+
/** The ids `c.text` and `c.enum` take as `format`, sorted by code unit */
|
|
22
|
+
export const TEXT_FORMATS = [
|
|
23
|
+
"base64url",
|
|
24
|
+
"bcp47",
|
|
25
|
+
"e164",
|
|
26
|
+
"iana-time-zone",
|
|
27
|
+
"ip",
|
|
28
|
+
"ipv4",
|
|
29
|
+
"ipv6",
|
|
30
|
+
"iso3166-1-alpha-2",
|
|
31
|
+
"iso3166-1-alpha-3",
|
|
32
|
+
"iso4217",
|
|
33
|
+
"iso639-1",
|
|
34
|
+
"kebab-slug",
|
|
35
|
+
"pkce-s256-challenge",
|
|
36
|
+
"rfc1123-hostname",
|
|
37
|
+
"semver",
|
|
38
|
+
"sha256-hex",
|
|
39
|
+
"sha512-hex",
|
|
40
|
+
"srgb-hex",
|
|
41
|
+
"srgb-hex-alpha",
|
|
42
|
+
"ulid",
|
|
43
|
+
"uts35-ca",
|
|
44
|
+
"uts35-fw",
|
|
45
|
+
"uts35-hc",
|
|
46
|
+
"uts35-ms",
|
|
47
|
+
"uts35-mu",
|
|
48
|
+
"uts35-nu",
|
|
49
|
+
"uuid",
|
|
50
|
+
"uuid-v4",
|
|
51
|
+
"uuid-v7",
|
|
52
|
+
] as const
|
|
53
|
+
|
|
54
|
+
/** The ids `c.integer` takes as `format`, sorted by code unit */
|
|
55
|
+
export const INTEGER_FORMATS = ["iso8601-month", "iso8601-weekday"] as const
|
|
56
|
+
|
|
57
|
+
/** A text format's id */
|
|
58
|
+
export type TextFormat = (typeof TEXT_FORMATS)[number]
|
|
59
|
+
|
|
60
|
+
/** An integer format's id */
|
|
61
|
+
export type IntegerFormat = (typeof INTEGER_FORMATS)[number]
|
|
62
|
+
|
|
63
|
+
/** The registry predicate a text format's value must also satisfy */
|
|
64
|
+
type Member = "isIanaTimeZone" | "isIso3166Alpha2" | "isIso3166Alpha3" | "isIso4217" | "isIso639Alpha2"
|
|
65
|
+
|
|
66
|
+
/** What a text format checks, after its transforms, on the value its DTO is given */
|
|
67
|
+
export type FormatSpec = {
|
|
68
|
+
/** The standard and the release it follows, as a person reads it */
|
|
69
|
+
readonly standard: string
|
|
70
|
+
/** The anchored pattern the value matches, portable to RE2 and JavaScript's `u` flag */
|
|
71
|
+
readonly source: string
|
|
72
|
+
/** The fewest characters a value has */
|
|
73
|
+
readonly min: number
|
|
74
|
+
/** The most characters a value has, or null when the format sets no cap and a column declares one */
|
|
75
|
+
readonly max: number | null
|
|
76
|
+
/** The transforms that run, in order, before the check */
|
|
77
|
+
readonly transform: readonly ("lowercase" | "trim" | "uppercase")[]
|
|
78
|
+
/** The pinned registry the value must belong to, by its predicate's name, or null when the source is the whole rule */
|
|
79
|
+
readonly member: Member | null
|
|
80
|
+
/** A value of the format as written, which the format takes and a generated DTO publishes as its example */
|
|
81
|
+
readonly example: string
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** The range an integer format's value lies in */
|
|
85
|
+
export type IntegerSpec = {
|
|
86
|
+
/** The standard that numbers the values, as a person reads it */
|
|
87
|
+
readonly standard: string
|
|
88
|
+
/** The least value */
|
|
89
|
+
readonly min: number
|
|
90
|
+
/** The greatest value */
|
|
91
|
+
readonly max: number
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** The transforms a format runs before its check: trim on all, then the one case its values are written in */
|
|
95
|
+
type Transforms = FormatSpec["transform"]
|
|
96
|
+
const TRIM: Transforms = ["trim"]
|
|
97
|
+
const LOWERCASE: Transforms = ["trim", "lowercase"]
|
|
98
|
+
const UPPERCASE: Transforms = ["trim", "uppercase"]
|
|
99
|
+
|
|
100
|
+
/*
|
|
101
|
+
* RFC 5646 §2.1's langtag: language (with up to three extlangs), script, region, variants, extensions
|
|
102
|
+
* and private use, each class case-insensitive; a grandfathered tag is no langtag
|
|
103
|
+
*/
|
|
104
|
+
const LANGUAGE = "(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}|[A-Za-z]{4,8})"
|
|
105
|
+
const VARIANTS = "(?:-(?:[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*"
|
|
106
|
+
const EXTENSIONS = "(?:-[0-9A-WYZa-wyz](?:-[A-Za-z0-9]{2,8})+)*"
|
|
107
|
+
const LANGTAG = `${LANGUAGE}(?:-[A-Za-z]{4})?(?:-(?:[A-Za-z]{2}|[0-9]{3}))?${VARIANTS}${EXTENSIONS}(?:-[Xx](?:-[A-Za-z0-9]{1,8})+)?`
|
|
108
|
+
|
|
109
|
+
/* semver.org 2.0.0's version pattern, its groups non-capturing */
|
|
110
|
+
const NUMBER = "(?:0|[1-9][0-9]*)"
|
|
111
|
+
const IDENTIFIER = "(?:0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)"
|
|
112
|
+
const BUILD = "(?:\\+[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*)?"
|
|
113
|
+
const SEMVER = `${NUMBER}\\.${NUMBER}\\.${NUMBER}(?:-${IDENTIFIER}(?:\\.${IDENTIFIER})*)?${BUILD}`
|
|
114
|
+
|
|
115
|
+
const HOST_LABEL = "[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?"
|
|
116
|
+
const HOSTNAME = `^${HOST_LABEL}(?:\\.${HOST_LABEL})*$`
|
|
117
|
+
const ZONE_NAME = "^[A-Za-z0-9_+-]+(?:/[A-Za-z0-9_+-]+){0,2}$"
|
|
118
|
+
const HEX = "[0-9a-f]"
|
|
119
|
+
const BASE64URL = "[A-Za-z0-9_-]"
|
|
120
|
+
/* whole quads, then two or three characters: a length of 1 mod 4 encodes no byte string */
|
|
121
|
+
const UNPADDED = `^(?:${BASE64URL}{4})*(?:${BASE64URL}{2,3})?$`
|
|
122
|
+
|
|
123
|
+
/* the examples too long for their format's row, the digests of no bytes among them */
|
|
124
|
+
const PHONE = "+385911234567"
|
|
125
|
+
const ZONE = "Europe/Zagreb"
|
|
126
|
+
const IPV6 = "2001:db8::1"
|
|
127
|
+
const PKCE_CHALLENGE = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"
|
|
128
|
+
const RGBA = "#1e90ff80"
|
|
129
|
+
const ULID = "01hzy3k8q2m4n5p6r7s8t9v0wx"
|
|
130
|
+
const UUID_V7 = "01890a5d-ac96-774b-bcce-b302099a8057"
|
|
131
|
+
const SHA256_EMPTY = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
|
132
|
+
const SHA512_EMPTY =
|
|
133
|
+
"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
|
|
134
|
+
const UUID_V4 = "0f8fad5b-d9cb-469f-a165-70867728950e"
|
|
135
|
+
|
|
136
|
+
/* the standards whose names would widen a row past the line */
|
|
137
|
+
const COUNTRY_2 = "ISO 3166-1 alpha-2 country code, Debian iso-codes v4.20.1"
|
|
138
|
+
const COUNTRY_3 = "ISO 3166-1 alpha-3 country code, Debian iso-codes v4.20.1"
|
|
139
|
+
const CURRENCY = "ISO 4217 alphabetic currency code, SIX list 2026-09-17"
|
|
140
|
+
const LANGUAGE_CODE = "ISO 639-1 language code, Debian iso-codes v4.20.1"
|
|
141
|
+
const CHALLENGE = "RFC 7636 §4.2 PKCE SHA-256 code challenge"
|
|
142
|
+
const SLUG = "kebab-case slug, lowercase letters and digits joined by single hyphens"
|
|
143
|
+
const ADDRESS = "IPv4 dotted quad or IPv6 address, RFC 4291 §2.2"
|
|
144
|
+
const DIGEST_256 = "SHA-256 digest, FIPS 180-4, lowercase hex"
|
|
145
|
+
const DIGEST_512 = "SHA-512 digest, FIPS 180-4, lowercase hex"
|
|
146
|
+
const COLOR_ALPHA = "sRGB color with alpha as #rrggbbaa, CSS Color 4"
|
|
147
|
+
|
|
148
|
+
/** One row of the table: a spec's fields in the order a reader scans them */
|
|
149
|
+
type Row = readonly [
|
|
150
|
+
standard: string,
|
|
151
|
+
source: string,
|
|
152
|
+
min: number,
|
|
153
|
+
max: number | null,
|
|
154
|
+
transform: Transforms,
|
|
155
|
+
member: Member | null,
|
|
156
|
+
example: string,
|
|
157
|
+
]
|
|
158
|
+
|
|
159
|
+
/** The spec a row states */
|
|
160
|
+
const spec = ([standard, source, min, max, transform, member, example]: Row): FormatSpec => ({
|
|
161
|
+
example,
|
|
162
|
+
max,
|
|
163
|
+
member,
|
|
164
|
+
min,
|
|
165
|
+
source,
|
|
166
|
+
standard,
|
|
167
|
+
transform,
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
/** RFC 9562's 8-4-4-4-12 layout in lowercase hex, its version digit and variant digit given */
|
|
171
|
+
const uuid = (standard: string, [version, variant]: [string, string], example: string): FormatSpec =>
|
|
172
|
+
spec([
|
|
173
|
+
standard,
|
|
174
|
+
`^${HEX}{8}-${HEX}{4}-${version}${HEX}{3}-${variant}${HEX}{3}-${HEX}{12}$`,
|
|
175
|
+
36,
|
|
176
|
+
36,
|
|
177
|
+
LOWERCASE,
|
|
178
|
+
null,
|
|
179
|
+
example,
|
|
180
|
+
])
|
|
181
|
+
|
|
182
|
+
/** A UTS #35 key's spec: an alternation of CLDR's values, the whole rule, bounded by the shortest and longest */
|
|
183
|
+
function uts35(key: string, values: readonly string[], example: string): FormatSpec {
|
|
184
|
+
const lengths = values.map((value) => value.length)
|
|
185
|
+
const standard = `UTS #35 ${key} key value, CLDR 49`
|
|
186
|
+
const [min, max] = [Math.min(...lengths), Math.max(...lengths)]
|
|
187
|
+
return spec([standard, `^(?:${values.join("|")})$`, min, max, LOWERCASE, null, example])
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** Every text format's spec, built in a function so importing the module runs nothing */
|
|
191
|
+
function specs(): { readonly [F in TextFormat]: FormatSpec } {
|
|
192
|
+
const ipv4 = ipv4Source()
|
|
193
|
+
const ipv6 = strictIpv6Source()
|
|
194
|
+
return {
|
|
195
|
+
base64url: spec(["RFC 4648 §5 base64url, unpadded", UNPADDED, 0, null, TRIM, null, "dGVzdA"]),
|
|
196
|
+
/* RFC 5646 §4.4.1's 35 is the buffer an implementation must hold, not a cap on a tag */
|
|
197
|
+
bcp47: spec(["BCP 47 language tag, RFC 5646 §2.1 well-formed", `^${LANGTAG}$`, 2, null, TRIM, null, "zh-Hant-TW"]),
|
|
198
|
+
e164: spec(["ITU-T E.164 phone number, + and up to 15 digits", "^\\+[1-9][0-9]{1,14}$", 3, 16, TRIM, null, PHONE]),
|
|
199
|
+
"iana-time-zone": spec(["IANA time zone name, tzdata 2026f", ZONE_NAME, 1, 64, TRIM, "isIanaTimeZone", ZONE]),
|
|
200
|
+
ip: spec([ADDRESS, `^(?:${ipv4}|${ipv6})$`, 2, 45, LOWERCASE, null, IPV6]),
|
|
201
|
+
ipv4: spec(["IPv4 address, dotted quad without leading zeros", `^${ipv4}$`, 7, 15, TRIM, null, "192.0.2.1"]),
|
|
202
|
+
ipv6: spec(["IPv6 address, RFC 4291 §2.2", `^(?:${ipv6})$`, 2, 45, LOWERCASE, null, IPV6]),
|
|
203
|
+
"iso3166-1-alpha-2": spec([COUNTRY_2, "^[A-Z]{2}$", 2, 2, UPPERCASE, "isIso3166Alpha2", "HR"]),
|
|
204
|
+
"iso3166-1-alpha-3": spec([COUNTRY_3, "^[A-Z]{3}$", 3, 3, UPPERCASE, "isIso3166Alpha3", "HRV"]),
|
|
205
|
+
iso4217: spec([CURRENCY, "^[A-Z]{3}$", 3, 3, UPPERCASE, "isIso4217", "EUR"]),
|
|
206
|
+
"iso639-1": spec([LANGUAGE_CODE, "^[a-z]{2}$", 2, 2, LOWERCASE, "isIso639Alpha2", "hr"]),
|
|
207
|
+
"kebab-slug": spec([SLUG, "^[a-z0-9]+(?:-[a-z0-9]+)*$", 1, 128, TRIM, null, "spring-sale-2026"]),
|
|
208
|
+
"pkce-s256-challenge": spec([CHALLENGE, `^${BASE64URL}{43}$`, 43, 43, TRIM, null, PKCE_CHALLENGE]),
|
|
209
|
+
"rfc1123-hostname": spec(["RFC 1123 §2.1 host name", HOSTNAME, 1, 253, LOWERCASE, null, "api.example.com"]),
|
|
210
|
+
semver: spec(["Semantic Versioning 2.0.0 version", `^${SEMVER}$`, 5, 256, TRIM, null, "1.4.0-rc.1"]),
|
|
211
|
+
"sha256-hex": spec([DIGEST_256, `^${HEX}{64}$`, 64, 64, LOWERCASE, null, SHA256_EMPTY]),
|
|
212
|
+
"sha512-hex": spec([DIGEST_512, `^${HEX}{128}$`, 128, 128, LOWERCASE, null, SHA512_EMPTY]),
|
|
213
|
+
"srgb-hex": spec(["sRGB color as #rrggbb, CSS Color 4", `^#${HEX}{6}$`, 7, 7, LOWERCASE, null, "#1e90ff"]),
|
|
214
|
+
"srgb-hex-alpha": spec([COLOR_ALPHA, `^#${HEX}{8}$`, 9, 9, LOWERCASE, null, RGBA]),
|
|
215
|
+
/* Crockford's base32 in lowercase, as generateUlid writes it; the first character holds 3 bits */
|
|
216
|
+
ulid: spec(["ULID, Crockford base32 in lowercase", "^[0-7][0-9a-hjkmnp-tv-z]{25}$", 26, 26, LOWERCASE, null, ULID]),
|
|
217
|
+
"uts35-ca": uts35("calendar (ca)", CALENDARS, "gregory"),
|
|
218
|
+
"uts35-fw": uts35("first day of the week (fw)", FIRST_DAYS, "mon"),
|
|
219
|
+
"uts35-hc": uts35("hour cycle (hc)", HOUR_CYCLES, "h23"),
|
|
220
|
+
"uts35-ms": uts35("measurement system (ms)", MEASUREMENT_SYSTEMS, "metric"),
|
|
221
|
+
"uts35-mu": uts35("measurement unit (mu)", MEASUREMENT_UNITS, "celsius"),
|
|
222
|
+
"uts35-nu": uts35("numbering system (nu)", NUMBERING_SYSTEMS, "latn"),
|
|
223
|
+
uuid: uuid("RFC 9562 UUID, lowercase hex", [HEX, HEX], UUID_V4),
|
|
224
|
+
"uuid-v4": uuid("RFC 9562 UUID version 4, lowercase hex", ["4", "[89ab]"], UUID_V4),
|
|
225
|
+
"uuid-v7": uuid("RFC 9562 UUID version 7, lowercase hex", ["7", "[89ab]"], UUID_V7),
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Every text format's spec, by id */
|
|
230
|
+
export const FORMATS: { readonly [F in TextFormat]: FormatSpec } = /* @__PURE__ */ specs()
|
|
231
|
+
|
|
232
|
+
/** Every integer format's range, by id */
|
|
233
|
+
export const INTEGER_SPECS: { readonly [F in IntegerFormat]: IntegerSpec } = {
|
|
234
|
+
"iso8601-month": { max: 12, min: 1, standard: "ISO 8601 month number, 1 January to 12 December" },
|
|
235
|
+
"iso8601-weekday": { max: 7, min: 1, standard: "ISO 8601 §3.2.2 weekday number, 1 Monday to 7 Sunday" },
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const MEMBERS: { readonly [M in Member]: (value: string) => boolean } = {
|
|
239
|
+
isIanaTimeZone,
|
|
240
|
+
isIso3166Alpha2,
|
|
241
|
+
isIso3166Alpha3,
|
|
242
|
+
isIso4217,
|
|
243
|
+
isIso639Alpha2,
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Whether `format` takes `value` exactly as written, its transforms not run: within the format's
|
|
248
|
+
* length bounds, matching its source, and a member of its registry when it names one. Never throws.
|
|
249
|
+
*/
|
|
250
|
+
export function formatTakes(format: TextFormat, value: string): boolean {
|
|
251
|
+
const { max, member, min, source } = FORMATS[format]
|
|
252
|
+
if (value.length < min || (max !== null && value.length > max)) return false
|
|
253
|
+
if (!new RegExp(source, "u").test(value)) return false
|
|
254
|
+
return member === null || MEMBERS[member](value)
|
|
255
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// Written by `bun scripts/registries.ts` from the pinned release below: edit the script, not this file.
|
|
2
|
+
// IANA tzdata 2026f: https://data.iana.org/time-zones/releases/tzdata2026f.tar.gz
|
|
3
|
+
// every Zone and Link name of africa, antarctica, asia, australasia, europe, northamerica, southamerica, etcetera, backward; Factory dropped
|
|
4
|
+
|
|
5
|
+
// lookup-table: the 597 time zone names of tzdata 2026f, one line per area, read by isIanaTimeZone
|
|
6
|
+
const NAMES: ReadonlySet<string> = /* @__PURE__ */ new Set(
|
|
7
|
+
/* @__PURE__ */ `Africa/Abidjan Africa/Accra Africa/Addis_Ababa Africa/Algiers Africa/Asmara Africa/Asmera Africa/Bamako
|
|
8
|
+
Africa/Bangui Africa/Banjul Africa/Bissau Africa/Blantyre Africa/Brazzaville Africa/Bujumbura Africa/Cairo
|
|
9
|
+
Africa/Casablanca Africa/Ceuta Africa/Conakry Africa/Dakar Africa/Dar_es_Salaam Africa/Djibouti Africa/Douala
|
|
10
|
+
Africa/El_Aaiun Africa/Freetown Africa/Gaborone Africa/Harare Africa/Johannesburg Africa/Juba Africa/Kampala
|
|
11
|
+
Africa/Khartoum Africa/Kigali Africa/Kinshasa Africa/Lagos Africa/Libreville Africa/Lome Africa/Luanda
|
|
12
|
+
Africa/Lubumbashi Africa/Lusaka Africa/Malabo Africa/Maputo Africa/Maseru Africa/Mbabane Africa/Mogadishu
|
|
13
|
+
Africa/Monrovia Africa/Nairobi Africa/Ndjamena Africa/Niamey Africa/Nouakchott Africa/Ouagadougou
|
|
14
|
+
Africa/Porto-Novo Africa/Sao_Tome Africa/Timbuktu Africa/Tripoli Africa/Tunis Africa/Windhoek
|
|
15
|
+
America/Adak America/Anchorage America/Anguilla America/Antigua America/Araguaina
|
|
16
|
+
America/Argentina/Buenos_Aires America/Argentina/Catamarca America/Argentina/ComodRivadavia
|
|
17
|
+
America/Argentina/Cordoba America/Argentina/Jujuy America/Argentina/La_Rioja America/Argentina/Mendoza
|
|
18
|
+
America/Argentina/Rio_Gallegos America/Argentina/Salta America/Argentina/San_Juan America/Argentina/San_Luis
|
|
19
|
+
America/Argentina/Tucuman America/Argentina/Ushuaia America/Aruba America/Asuncion America/Atikokan
|
|
20
|
+
America/Atka America/Bahia America/Bahia_Banderas America/Barbados America/Belem America/Belize
|
|
21
|
+
America/Blanc-Sablon America/Boa_Vista America/Bogota America/Boise America/Buenos_Aires America/Cambridge_Bay
|
|
22
|
+
America/Campo_Grande America/Cancun America/Caracas America/Catamarca America/Cayenne America/Cayman
|
|
23
|
+
America/Chicago America/Chihuahua America/Ciudad_Juarez America/Coral_Harbour America/Cordoba
|
|
24
|
+
America/Costa_Rica America/Coyhaique America/Creston America/Cuiaba America/Curacao America/Danmarkshavn
|
|
25
|
+
America/Dawson America/Dawson_Creek America/Denver America/Detroit America/Dominica America/Edmonton
|
|
26
|
+
America/Eirunepe America/El_Salvador America/Ensenada America/Fort_Nelson America/Fort_Wayne America/Fortaleza
|
|
27
|
+
America/Glace_Bay America/Godthab America/Goose_Bay America/Grand_Turk America/Grenada America/Guadeloupe
|
|
28
|
+
America/Guatemala America/Guayaquil America/Guyana America/Halifax America/Havana America/Hermosillo
|
|
29
|
+
America/Indiana/Indianapolis America/Indiana/Knox America/Indiana/Marengo America/Indiana/Petersburg
|
|
30
|
+
America/Indiana/Tell_City America/Indiana/Vevay America/Indiana/Vincennes America/Indiana/Winamac
|
|
31
|
+
America/Indianapolis America/Inuvik America/Iqaluit America/Jamaica America/Jujuy America/Juneau
|
|
32
|
+
America/Kentucky/Louisville America/Kentucky/Monticello America/Knox_IN America/Kralendijk America/La_Paz
|
|
33
|
+
America/Lima America/Los_Angeles America/Louisville America/Lower_Princes America/Maceio America/Managua
|
|
34
|
+
America/Manaus America/Marigot America/Martinique America/Matamoros America/Mazatlan America/Mendoza
|
|
35
|
+
America/Menominee America/Merida America/Metlakatla America/Mexico_City America/Miquelon America/Moncton
|
|
36
|
+
America/Monterrey America/Montevideo America/Montreal America/Montserrat America/Nassau America/New_York
|
|
37
|
+
America/Nipigon America/Nome America/Noronha America/North_Dakota/Beulah America/North_Dakota/Center
|
|
38
|
+
America/North_Dakota/New_Salem America/Nuuk America/Ojinaga America/Panama America/Pangnirtung
|
|
39
|
+
America/Paramaribo America/Phoenix America/Port-au-Prince America/Port_of_Spain America/Porto_Acre
|
|
40
|
+
America/Porto_Velho America/Puerto_Rico America/Punta_Arenas America/Rainy_River America/Rankin_Inlet
|
|
41
|
+
America/Recife America/Regina America/Resolute America/Rio_Branco America/Rosario America/Santa_Isabel
|
|
42
|
+
America/Santarem America/Santiago America/Santo_Domingo America/Sao_Paulo America/Scoresbysund
|
|
43
|
+
America/Shiprock America/Sitka America/St_Barthelemy America/St_Johns America/St_Kitts America/St_Lucia
|
|
44
|
+
America/St_Thomas America/St_Vincent America/Swift_Current America/Tegucigalpa America/Thule
|
|
45
|
+
America/Thunder_Bay America/Tijuana America/Toronto America/Tortola America/Vancouver America/Virgin
|
|
46
|
+
America/Whitehorse America/Winnipeg America/Yakutat America/Yellowknife
|
|
47
|
+
Antarctica/Casey Antarctica/Davis Antarctica/DumontDUrville Antarctica/Macquarie Antarctica/Mawson
|
|
48
|
+
Antarctica/McMurdo Antarctica/Palmer Antarctica/Rothera Antarctica/South_Pole Antarctica/Syowa
|
|
49
|
+
Antarctica/Troll Antarctica/Vostok
|
|
50
|
+
Arctic/Longyearbyen
|
|
51
|
+
Asia/Aden Asia/Almaty Asia/Amman Asia/Anadyr Asia/Aqtau Asia/Aqtobe Asia/Ashgabat Asia/Ashkhabad Asia/Atyrau
|
|
52
|
+
Asia/Baghdad Asia/Bahrain Asia/Baku Asia/Bangkok Asia/Barnaul Asia/Beirut Asia/Bishkek Asia/Brunei
|
|
53
|
+
Asia/Calcutta Asia/Chita Asia/Choibalsan Asia/Chongqing Asia/Chungking Asia/Colombo Asia/Dacca Asia/Damascus
|
|
54
|
+
Asia/Dhaka Asia/Dili Asia/Dubai Asia/Dushanbe Asia/Famagusta Asia/Gaza Asia/Harbin Asia/Hebron
|
|
55
|
+
Asia/Ho_Chi_Minh Asia/Hong_Kong Asia/Hovd Asia/Irkutsk Asia/Istanbul Asia/Jakarta Asia/Jayapura Asia/Jerusalem
|
|
56
|
+
Asia/Kabul Asia/Kamchatka Asia/Karachi Asia/Kashgar Asia/Kathmandu Asia/Katmandu Asia/Khandyga Asia/Kolkata
|
|
57
|
+
Asia/Krasnoyarsk Asia/Kuala_Lumpur Asia/Kuching Asia/Kuwait Asia/Macao Asia/Macau Asia/Magadan Asia/Makassar
|
|
58
|
+
Asia/Manila Asia/Muscat Asia/Nicosia Asia/Novokuznetsk Asia/Novosibirsk Asia/Omsk Asia/Oral Asia/Phnom_Penh
|
|
59
|
+
Asia/Pontianak Asia/Pyongyang Asia/Qatar Asia/Qostanay Asia/Qyzylorda Asia/Rangoon Asia/Riyadh Asia/Saigon
|
|
60
|
+
Asia/Sakhalin Asia/Samarkand Asia/Seoul Asia/Shanghai Asia/Singapore Asia/Srednekolymsk Asia/Taipei
|
|
61
|
+
Asia/Tashkent Asia/Tbilisi Asia/Tehran Asia/Tel_Aviv Asia/Thimbu Asia/Thimphu Asia/Tokyo Asia/Tomsk
|
|
62
|
+
Asia/Ujung_Pandang Asia/Ulaanbaatar Asia/Ulan_Bator Asia/Urumqi Asia/Ust-Nera Asia/Vientiane Asia/Vladivostok
|
|
63
|
+
Asia/Yakutsk Asia/Yangon Asia/Yekaterinburg Asia/Yerevan
|
|
64
|
+
Atlantic/Azores Atlantic/Bermuda Atlantic/Canary Atlantic/Cape_Verde Atlantic/Faeroe Atlantic/Faroe
|
|
65
|
+
Atlantic/Jan_Mayen Atlantic/Madeira Atlantic/Reykjavik Atlantic/South_Georgia Atlantic/St_Helena
|
|
66
|
+
Atlantic/Stanley
|
|
67
|
+
Australia/ACT Australia/Adelaide Australia/Brisbane Australia/Broken_Hill Australia/Canberra Australia/Currie
|
|
68
|
+
Australia/Darwin Australia/Eucla Australia/Hobart Australia/LHI Australia/Lindeman Australia/Lord_Howe
|
|
69
|
+
Australia/Melbourne Australia/NSW Australia/North Australia/Perth Australia/Queensland Australia/South
|
|
70
|
+
Australia/Sydney Australia/Tasmania Australia/Victoria Australia/West Australia/Yancowinna
|
|
71
|
+
Brazil/Acre Brazil/DeNoronha Brazil/East Brazil/West
|
|
72
|
+
CET CST6CDT
|
|
73
|
+
Canada/Atlantic Canada/Central Canada/Eastern Canada/Mountain Canada/Newfoundland Canada/Pacific
|
|
74
|
+
Canada/Saskatchewan Canada/Yukon
|
|
75
|
+
Chile/Continental Chile/EasterIsland
|
|
76
|
+
Cuba EET EST EST5EDT Egypt Eire
|
|
77
|
+
Etc/GMT Etc/GMT+0 Etc/GMT+1 Etc/GMT+10 Etc/GMT+11 Etc/GMT+12 Etc/GMT+2 Etc/GMT+3 Etc/GMT+4 Etc/GMT+5 Etc/GMT+6
|
|
78
|
+
Etc/GMT+7 Etc/GMT+8 Etc/GMT+9 Etc/GMT-0 Etc/GMT-1 Etc/GMT-10 Etc/GMT-11 Etc/GMT-12 Etc/GMT-13 Etc/GMT-14
|
|
79
|
+
Etc/GMT-2 Etc/GMT-3 Etc/GMT-4 Etc/GMT-5 Etc/GMT-6 Etc/GMT-7 Etc/GMT-8 Etc/GMT-9 Etc/GMT0 Etc/Greenwich Etc/UCT
|
|
80
|
+
Etc/UTC Etc/Universal Etc/Zulu
|
|
81
|
+
Europe/Amsterdam Europe/Andorra Europe/Astrakhan Europe/Athens Europe/Belfast Europe/Belgrade Europe/Berlin
|
|
82
|
+
Europe/Bratislava Europe/Brussels Europe/Bucharest Europe/Budapest Europe/Busingen Europe/Chisinau
|
|
83
|
+
Europe/Copenhagen Europe/Dublin Europe/Gibraltar Europe/Guernsey Europe/Helsinki Europe/Isle_of_Man
|
|
84
|
+
Europe/Istanbul Europe/Jersey Europe/Kaliningrad Europe/Kiev Europe/Kirov Europe/Kyiv Europe/Lisbon
|
|
85
|
+
Europe/Ljubljana Europe/London Europe/Luxembourg Europe/Madrid Europe/Malta Europe/Mariehamn Europe/Minsk
|
|
86
|
+
Europe/Monaco Europe/Moscow Europe/Nicosia Europe/Oslo Europe/Paris Europe/Podgorica Europe/Prague Europe/Riga
|
|
87
|
+
Europe/Rome Europe/Samara Europe/San_Marino Europe/Sarajevo Europe/Saratov Europe/Simferopol Europe/Skopje
|
|
88
|
+
Europe/Sofia Europe/Stockholm Europe/Tallinn Europe/Tirane Europe/Tiraspol Europe/Ulyanovsk Europe/Uzhgorod
|
|
89
|
+
Europe/Vaduz Europe/Vatican Europe/Vienna Europe/Vilnius Europe/Volgograd Europe/Warsaw Europe/Zagreb
|
|
90
|
+
Europe/Zaporozhye Europe/Zurich
|
|
91
|
+
GB GB-Eire GMT GMT+0 GMT-0 GMT0 Greenwich HST Hongkong Iceland
|
|
92
|
+
Indian/Antananarivo Indian/Chagos Indian/Christmas Indian/Cocos Indian/Comoro Indian/Kerguelen Indian/Mahe
|
|
93
|
+
Indian/Maldives Indian/Mauritius Indian/Mayotte Indian/Reunion
|
|
94
|
+
Iran Israel Jamaica Japan Kwajalein Libya MET MST MST7MDT
|
|
95
|
+
Mexico/BajaNorte Mexico/BajaSur Mexico/General
|
|
96
|
+
NZ NZ-CHAT Navajo PRC PST8PDT
|
|
97
|
+
Pacific/Apia Pacific/Auckland Pacific/Bougainville Pacific/Chatham Pacific/Chuuk Pacific/Easter Pacific/Efate
|
|
98
|
+
Pacific/Enderbury Pacific/Fakaofo Pacific/Fiji Pacific/Funafuti Pacific/Galapagos Pacific/Gambier
|
|
99
|
+
Pacific/Guadalcanal Pacific/Guam Pacific/Honolulu Pacific/Johnston Pacific/Kanton Pacific/Kiritimati
|
|
100
|
+
Pacific/Kosrae Pacific/Kwajalein Pacific/Majuro Pacific/Marquesas Pacific/Midway Pacific/Nauru Pacific/Niue
|
|
101
|
+
Pacific/Norfolk Pacific/Noumea Pacific/Pago_Pago Pacific/Palau Pacific/Pitcairn Pacific/Pohnpei Pacific/Ponape
|
|
102
|
+
Pacific/Port_Moresby Pacific/Rarotonga Pacific/Saipan Pacific/Samoa Pacific/Tahiti Pacific/Tarawa
|
|
103
|
+
Pacific/Tongatapu Pacific/Truk Pacific/Wake Pacific/Wallis Pacific/Yap
|
|
104
|
+
Poland Portugal ROC ROK Singapore Turkey UCT
|
|
105
|
+
US/Alaska US/Aleutian US/Arizona US/Central US/East-Indiana US/Eastern US/Hawaii US/Indiana-Starke US/Michigan
|
|
106
|
+
US/Mountain US/Pacific US/Samoa
|
|
107
|
+
UTC Universal W-SU WET Zulu`.split(/\s/u),
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Whether `value` names a time zone of IANA tzdata 2026f, exactly as written: a zone or a link to one, such as
|
|
112
|
+
* Europe/Zagreb, America/Argentina/Buenos_Aires, Etc/GMT+5, UTC or US/Pacific. Case counts, and Factory, a
|
|
113
|
+
* placeholder, is no zone. Any string is taken; this never throws.
|
|
114
|
+
*/
|
|
115
|
+
export function isIanaTimeZone(value: string): boolean {
|
|
116
|
+
return NAMES.has(value)
|
|
117
|
+
}
|