Skip to content

Commit 4188ee3

Browse files
committed
Better alignment with JSON Schema
1 parent 6d1ce0c commit 4188ee3

File tree

7 files changed

+28
-27
lines changed

7 files changed

+28
-27
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ assert(users.length === 1); // User was found
7272
### Using with an (extended) JSON schema
7373

7474
DBX extends JSON Schema (along [these](https://json-schema.org/understanding-json-schema/structuring.html#id21) lines) to
75-
provide a way to define the database schema (see specific extensions in the `types.ts` file). With a schema in hand (such as account.json) we
75+
provide a way to define the database schema (see specific extensions in the [`types.ts`](./src/types.ts) file). With a schema in hand (such as account.json) we
7676
can generate the DDL to create the tables, and use the schema to validate the data.
7777

7878
An example schema:

deno.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
"@std/assert": "jsr:@std/assert@^1",
1515
"@std/collections": "jsr:@std/collections@^1",
1616
"@std/fmt": "jsr:@std/fmt@^1",
17-
"@std/log": "jsr:@std/log@^0",
18-
"schema": "npm:@types/json-schema/7.0.15"
17+
"@std/log": "jsr:@std/log@^0"
1918
},
2019
"lock": false,
2120
"tasks": {

resources/account.json

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22
"name": "accounts",
33
"type": "Account",
44
"properties": {
5-
"id": { "type": "integer", "required": true, "primaryKey": true, "comment": "Unique identifier, auto-generated. It's the primary key." },
6-
"inserted": { "type": "date", "required": false, "dateOn": "insert", "comment": "Timestamp when current record is inserted" },
7-
"updated": { "type": "date", "required": false, "dateOn": "update", "comment": "Timestamp when current record is updated" },
8-
"etag": { "type": "string", "required": false, "maxLength": 1024, "comment": "Possible ETag for all resources that are external. Allows for better synch-ing." },
9-
"comments": { "type": "string", "required": false, "maxLength": 8192, "fullText": true, "comment": "General comments. Can be used for anything useful related to the instance." },
10-
"country": { "type": "string", "required": true, "maxLength": 16, "default": "'US'", "fullText": true, "comment": "Country code" },
11-
"email": { "type": "string", "required": false, "maxLength": 128, "unique": true, "comment": "Main email to communicate for that account" },
12-
"established": { "type": "date", "required": false, "maxLength": 6, "minimum": "2020-01-01", "comment": "Date on which the account was established" },
13-
"enabled": { "type": "boolean", "required": true, "default": true, "comment": "Whether it is enabled or not. Disabled instances will not be used." },
14-
"externalId": { "type": "string", "required": false, "maxLength": 512, "unique": true, "comment": "External unique ID, used to refer to external accounts" },
15-
"phone": { "type": "string", "required": false, "maxLength": 128, "fullText": true, "comment": "Handle associated with the account" },
16-
"name": { "type": "string", "required": true, "unique": true, "fullText": true, "comment": "Descriptive name to identify the instance" },
17-
"preferences": { "type": "json", "required": true, "default": { "wrap": true, "minAge": 18 }, "comment": "All the general options associated with the account." },
5+
"id": { "type": "integer", "required": true, "primaryKey": true, "description": "Unique identifier, auto-generated. It's the primary key." },
6+
"inserted": { "type": "date", "required": false, "dateOn": "insert", "description": "Timestamp when current record is inserted" },
7+
"updated": { "type": "date", "required": false, "dateOn": "update", "description": "Timestamp when current record is updated" },
8+
"etag": { "type": "string", "required": false, "maxLength": 1024, "description": "Possible ETag for all resources that are external. Allows for better synch-ing." },
9+
"comments": { "type": "string", "required": false, "maxLength": 8192, "fullText": true, "description": "General comments. Can be used for anything useful related to the instance." },
10+
"country": { "type": "string", "required": true, "maxLength": 16, "default": "'US'", "fullText": true, "description": "Country code" },
11+
"email": { "type": "string", "required": false, "maxLength": 128, "unique": true, "description": "Main email to communicate for that account" },
12+
"established": { "type": "date", "required": false, "maxLength": 6, "minimum": "2020-01-01", "description": "Date on which the account was established" },
13+
"enabled": { "type": "boolean", "required": true, "default": true, "description": "Whether it is enabled or not. Disabled instances will not be used." },
14+
"externalId": { "type": "string", "required": false, "maxLength": 512, "unique": true, "description": "External unique ID, used to refer to external accounts" },
15+
"phone": { "type": "string", "required": false, "maxLength": 128, "fullText": true, "description": "Handle associated with the account" },
16+
"name": { "type": "string", "required": true, "unique": true, "fullText": true, "description": "Descriptive name to identify the instance" },
17+
"preferences": { "type": "json", "required": true, "default": { "wrap": true, "minAge": 18 }, "description": "All the general options associated with the account." },
1818
"valueList": { "type": "json", "asExpression": "JSON_EXTRACT(preferences, '$.*')", "generatedType": "stored" }
1919
},
2020
"indices": [

resources/account.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
export default class Account {
2-
id!: number;
2+
/**
3+
* Internal auto-incremented ID
4+
*/
5+
id!: number;
36
comments?: string;
47
country = "US";
58
email?: string;

src/ddl.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ const serialType = {
1919
const _BaseSchema: DB.Schema = {
2020
name: "_BaseSchema",
2121
properties: {
22-
id: { type: "integer", required: true, primaryKey: true, comment: "Unique identifier, auto-generated. It's the primary key." },
23-
insertedAt: { type: "date", required: false, dateOn: "insert", comment: "Timestamp when current record is inserted" },
24-
updatedAt: { type: "date", required: false, dateOn: "update", comment: "Timestamp when current record is updated" },
25-
etag: { type: "string", required: false, maxLength: 1024, comment: "Possible ETag for all resources that are external. Allows for better synch-ing." },
22+
id: { type: "integer", required: true, primaryKey: true, description: "Unique identifier, auto-generated. It's the primary key." },
23+
insertedAt: { type: "date", required: false, dateOn: "insert", description: "Timestamp when current record is inserted" },
24+
updatedAt: { type: "date", required: false, dateOn: "update", description: "Timestamp when current record is updated" },
25+
etag: { type: "string", required: false, maxLength: 1024, description: "Possible ETag for all resources that are external. Allows for better synch-ing." },
2626
},
2727
indices: [
2828
{ name: "insertedAt", properties: ["insertedAt"] },
@@ -65,7 +65,7 @@ export class DDL {
6565
const as = asExpression ? " GENERATED ALWAYS AS (" + asExpression + ") " + (column.generatedType?.toUpperCase() || "VIRTUAL") : "";
6666
const def = Object.hasOwn(column, "default") ? " DEFAULT " + column.default : "";
6767
const key = column.primaryKey ? " PRIMARY KEY" : (column.unique ? " UNIQUE" : "");
68-
const comment = (dbType === DB.Provider.MYSQL) && column.comment ? " COMMENT '" + column.comment.replace(/'/g, "''") + "'" : "";
68+
const comment = (dbType === DB.Provider.MYSQL) && column.description ? " COMMENT '" + column.description.replace(/'/g, "''") + "'" : "";
6969

7070
// Correct Postgres JSON type
7171
if (dbType === DB.Provider.POSTGRES && type === "JSON") type = "JSONB";

src/types.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ export type Identifiable = { id?: number | string };
88

99
// JSON Schema Property
1010
export interface Property {
11-
comment?: string;
1211
default?: unknown;
12+
description?: string;
1313
format?: string;
1414
fullText?: boolean;
1515
maxLength?: number;
@@ -27,15 +27,14 @@ export interface Property {
2727
// JSON Schema Extensions Properties
2828
export interface Column extends Property {
2929
asExpression?: string | { [key: string]: string };
30-
comment?: string;
3130
dateOn?: "delete" | "insert" | "update";
3231
generatedType?: string | "virtual" | "stored";
3332
primaryKey?: boolean;
3433
}
3534

3635
export interface Index {
3736
array?: number;
38-
comment?: string;
37+
description?: string;
3938
properties: string[];
4039
name?: string;
4140
subType?: string;

test/schema.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env -S deno test -A --check
22

3-
import type { JSONSchema7 } from "schema";
3+
import type { JSONSchema7 } from "npm:@types/json-schema/7.0.15";
44
import AccountSchema from "../resources/account.json" with { type: "json" };
55

66
Deno.test("Schema Types are proper JSON Schema", function () {
@@ -12,7 +12,7 @@ Deno.test("Schema Types are proper JSON Schema", function () {
1212
const _inserted = _schema.properties.inserted as JSONSchema7;
1313
const _updated = _schema.properties.updated as JSONSchema7;
1414
const _etag = _schema.properties.etag as JSONSchema7;
15-
const _comments = _schema.properties.comments as JSONSchema7;
15+
const _description = _schema.properties.description as JSONSchema7;
1616
const _country = _schema.properties.country as JSONSchema7;
1717
const _email = _schema.properties.email as JSONSchema7;
1818
const _established = _schema.properties.established as JSONSchema7;

0 commit comments

Comments
 (0)