@lovrozagar/oat 0.1.0
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/LICENSE +21 -0
- package/README.md +401 -0
- package/bin/oat.js +2 -0
- package/dist/cli.js +386 -0
- package/dist/config/define-config.d.ts +165 -0
- package/dist/config/define-config.d.ts.map +1 -0
- package/dist/config/define-config.js +24 -0
- package/dist/config/define-config.js.map +1 -0
- package/dist/config/load.d.ts +10 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/load.js +61 -0
- package/dist/config/load.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +9 -0
- package/dist/reference/defects.d.ts +254 -0
- package/dist/reference/defects.d.ts.map +1 -0
- package/dist/reference/defects.js +265 -0
- package/dist/reference/defects.js.map +1 -0
- package/dist/reference/dialect.d.ts +104 -0
- package/dist/reference/dialect.d.ts.map +1 -0
- package/dist/reference/dialect.js +174 -0
- package/dist/reference/dialect.js.map +1 -0
- package/dist/reference/http.d.ts +79 -0
- package/dist/reference/http.d.ts.map +1 -0
- package/dist/reference/http.js +889 -0
- package/dist/reference/http.js.map +1 -0
- package/dist/reference/model.d.ts +56 -0
- package/dist/reference/model.d.ts.map +1 -0
- package/dist/reference/model.js +156 -0
- package/dist/reference/model.js.map +1 -0
- package/dist/reference/query.d.ts +45 -0
- package/dist/reference/query.d.ts.map +1 -0
- package/dist/reference/query.js +353 -0
- package/dist/reference/query.js.map +1 -0
- package/dist/reference/spec.d.ts +13 -0
- package/dist/reference/spec.d.ts.map +1 -0
- package/dist/reference/spec.js +547 -0
- package/dist/reference/spec.js.map +1 -0
- package/dist/reference/store-api.d.ts +59 -0
- package/dist/reference/store-api.d.ts.map +1 -0
- package/dist/reference/store-api.js +76 -0
- package/dist/reference/store-api.js.map +1 -0
- package/dist/reference/stores/memory.d.ts +27 -0
- package/dist/reference/stores/memory.d.ts.map +1 -0
- package/dist/reference/stores/memory.js +97 -0
- package/dist/reference/stores/memory.js.map +1 -0
- package/dist/reference/stores/postgres.d.ts +61 -0
- package/dist/reference/stores/postgres.d.ts.map +1 -0
- package/dist/reference/stores/postgres.js +406 -0
- package/dist/reference/stores/postgres.js.map +1 -0
- package/dist/reference/stores/sqlite-driver.d.ts +54 -0
- package/dist/reference/stores/sqlite-driver.d.ts.map +1 -0
- package/dist/reference/stores/sqlite-driver.js +99 -0
- package/dist/reference/stores/sqlite-driver.js.map +1 -0
- package/dist/reference/stores/sqlite.d.ts +68 -0
- package/dist/reference/stores/sqlite.d.ts.map +1 -0
- package/dist/reference/stores/sqlite.js +464 -0
- package/dist/reference/stores/sqlite.js.map +1 -0
- package/dist/report/console.d.ts +33 -0
- package/dist/report/console.d.ts.map +1 -0
- package/dist/report/console.js +237 -0
- package/dist/report/console.js.map +1 -0
- package/dist/report/matrix.d.ts +131 -0
- package/dist/report/matrix.d.ts.map +1 -0
- package/dist/report/matrix.js +865 -0
- package/dist/report/matrix.js.map +1 -0
- package/dist/report/render.d.ts +66 -0
- package/dist/report/render.d.ts.map +1 -0
- package/dist/report/render.js +423 -0
- package/dist/report/render.js.map +1 -0
- package/dist/runtime/async.d.ts +34 -0
- package/dist/runtime/async.d.ts.map +1 -0
- package/dist/runtime/async.js +130 -0
- package/dist/runtime/async.js.map +1 -0
- package/dist/runtime/auth.d.ts +46 -0
- package/dist/runtime/auth.d.ts.map +1 -0
- package/dist/runtime/auth.js +236 -0
- package/dist/runtime/auth.js.map +1 -0
- package/dist/runtime/checks.d.ts +89 -0
- package/dist/runtime/checks.d.ts.map +1 -0
- package/dist/runtime/checks.js +3400 -0
- package/dist/runtime/checks.js.map +1 -0
- package/dist/runtime/client.d.ts +65 -0
- package/dist/runtime/client.d.ts.map +1 -0
- package/dist/runtime/client.js +122 -0
- package/dist/runtime/client.js.map +1 -0
- package/dist/runtime/finding.d.ts +50 -0
- package/dist/runtime/finding.d.ts.map +1 -0
- package/dist/runtime/finding.js +50 -0
- package/dist/runtime/finding.js.map +1 -0
- package/dist/runtime/fixture.d.ts +20 -0
- package/dist/runtime/fixture.d.ts.map +1 -0
- package/dist/runtime/fixture.js +175 -0
- package/dist/runtime/fixture.js.map +1 -0
- package/dist/runtime/progress.d.ts +41 -0
- package/dist/runtime/progress.d.ts.map +1 -0
- package/dist/runtime/progress.js +186 -0
- package/dist/runtime/progress.js.map +1 -0
- package/dist/runtime/run.d.ts +69 -0
- package/dist/runtime/run.d.ts.map +1 -0
- package/dist/runtime/run.js +575 -0
- package/dist/runtime/run.js.map +1 -0
- package/dist/runtime/teardown.d.ts +38 -0
- package/dist/runtime/teardown.d.ts.map +1 -0
- package/dist/runtime/teardown.js +129 -0
- package/dist/runtime/teardown.js.map +1 -0
- package/dist/runtime/validate.d.ts +31 -0
- package/dist/runtime/validate.d.ts.map +1 -0
- package/dist/runtime/validate.js +111 -0
- package/dist/runtime/validate.js.map +1 -0
- package/dist/runtime/world.d.ts +49 -0
- package/dist/runtime/world.d.ts.map +1 -0
- package/dist/runtime/world.js +119 -0
- package/dist/runtime/world.js.map +1 -0
- package/dist/spec/collection.d.ts +31 -0
- package/dist/spec/collection.d.ts.map +1 -0
- package/dist/spec/collection.js +121 -0
- package/dist/spec/collection.js.map +1 -0
- package/dist/spec/conventions.d.ts +103 -0
- package/dist/spec/conventions.d.ts.map +1 -0
- package/dist/spec/conventions.js +275 -0
- package/dist/spec/conventions.js.map +1 -0
- package/dist/spec/extensions.d.ts +74 -0
- package/dist/spec/extensions.d.ts.map +1 -0
- package/dist/spec/extensions.js +335 -0
- package/dist/spec/extensions.js.map +1 -0
- package/dist/spec/graph.d.ts +89 -0
- package/dist/spec/graph.d.ts.map +1 -0
- package/dist/spec/graph.js +318 -0
- package/dist/spec/graph.js.map +1 -0
- package/dist/spec/load.d.ts +36 -0
- package/dist/spec/load.d.ts.map +1 -0
- package/dist/spec/load.js +166 -0
- package/dist/spec/load.js.map +1 -0
- package/dist/spec/types.d.ts +57 -0
- package/dist/spec/types.d.ts.map +1 -0
- package/dist/spec/types.js +24 -0
- package/dist/spec/types.js.map +1 -0
- package/labs/README.md +130 -0
- package/labs/annotated-openapi.yaml +311 -0
- package/labs/anyrow.config.ts +107 -0
- package/labs/demo.mjs +124 -0
- package/labs/local.config.ts +41 -0
- package/labs/minimal.config.ts +32 -0
- package/package.json +80 -0
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates the reference backend's OpenAPI document from the entity model, fully annotated with
|
|
3
|
+
* the meta tags in the README. This is the "ideal citizen" spec: everything oat wants to know
|
|
4
|
+
* is declared, so a run against the clean baseline exercises the tag path rather than the
|
|
5
|
+
* heuristic fallbacks. The conformance suite also serves stripped variants to test the fallbacks.
|
|
6
|
+
*/
|
|
7
|
+
import { POSTGREST } from "./dialect.js";
|
|
8
|
+
import { ENTITIES, JOB, TABLE, fieldsWhere, writableFields } from "./model.js";
|
|
9
|
+
function fieldSchema(field) {
|
|
10
|
+
const base = { type: field.type };
|
|
11
|
+
if (field.enum !== undefined)
|
|
12
|
+
base.enum = [...field.enum];
|
|
13
|
+
if (field.maxLength !== undefined)
|
|
14
|
+
base.maxLength = field.maxLength;
|
|
15
|
+
if (field.generated === true)
|
|
16
|
+
base.readOnly = true;
|
|
17
|
+
if (field.nullable === true)
|
|
18
|
+
return { oneOf: [base, { type: "null" }] };
|
|
19
|
+
return base;
|
|
20
|
+
}
|
|
21
|
+
function itemSchema(entity) {
|
|
22
|
+
const properties = {};
|
|
23
|
+
for (const field of entity.fields)
|
|
24
|
+
properties[field.name] = fieldSchema(field);
|
|
25
|
+
return {
|
|
26
|
+
additionalProperties: false,
|
|
27
|
+
properties,
|
|
28
|
+
required: entity.fields.filter((f) => f.required === true).map((f) => f.name),
|
|
29
|
+
type: "object",
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function bodySchema(entity, phase) {
|
|
33
|
+
const properties = {};
|
|
34
|
+
for (const field of writableFields(entity, phase))
|
|
35
|
+
properties[field.name] = fieldSchema(field);
|
|
36
|
+
return {
|
|
37
|
+
additionalProperties: false,
|
|
38
|
+
properties,
|
|
39
|
+
required: phase === "create" ? writableFields(entity, "create").filter((f) => f.required === true).map((f) => f.name) : [],
|
|
40
|
+
type: "object",
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/** The collection's property name under a dialect — entity-named, or a fixed key like `data`. */
|
|
44
|
+
function collectionKey(entity, dialect) {
|
|
45
|
+
return dialect.envelope?.collection ?? entity.plural;
|
|
46
|
+
}
|
|
47
|
+
function listSchema(entity, dialect) {
|
|
48
|
+
const env = dialect.envelope;
|
|
49
|
+
/* No envelope: the response *is* the array. A document that says so is the only place oat can
|
|
50
|
+
* learn it, so the schema has to say it rather than describe a wrapper that does not exist. */
|
|
51
|
+
if (env === null)
|
|
52
|
+
return { items: itemSchema(entity), type: "array" };
|
|
53
|
+
const key = collectionKey(entity, dialect);
|
|
54
|
+
const properties = {
|
|
55
|
+
[env.hasMore]: { type: "boolean" },
|
|
56
|
+
[env.limit]: { minimum: 1, type: "integer" },
|
|
57
|
+
[env.page]: { oneOf: [{ minimum: 1, type: "integer" }, { type: "null" }] },
|
|
58
|
+
[env.total]: { minimum: 0, type: "integer" },
|
|
59
|
+
[key]: { items: itemSchema(entity), type: "array" },
|
|
60
|
+
};
|
|
61
|
+
const required = [env.hasMore, env.limit, env.page, env.total, key];
|
|
62
|
+
if (env.nextCursor !== undefined) {
|
|
63
|
+
properties[env.nextCursor] = { oneOf: [{ type: "string" }, { type: "null" }] };
|
|
64
|
+
required.push(env.nextCursor);
|
|
65
|
+
}
|
|
66
|
+
return { additionalProperties: false, properties, required, type: "object" };
|
|
67
|
+
}
|
|
68
|
+
function errorSchema(status, key) {
|
|
69
|
+
return {
|
|
70
|
+
additionalProperties: false,
|
|
71
|
+
properties: {
|
|
72
|
+
error_key: { enum: [key], type: "string" },
|
|
73
|
+
message: { type: "string" },
|
|
74
|
+
status: { enum: [status], type: "integer" },
|
|
75
|
+
success: { const: false },
|
|
76
|
+
},
|
|
77
|
+
required: ["error_key", "message", "status", "success"],
|
|
78
|
+
type: "object",
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const ERRORS = [
|
|
82
|
+
[400, "invalid_input"],
|
|
83
|
+
[401, "unauthorized"],
|
|
84
|
+
[403, "forbidden"],
|
|
85
|
+
[404, "not_found"],
|
|
86
|
+
[415, "unsupported_media_type"],
|
|
87
|
+
];
|
|
88
|
+
function errorResponses(codes) {
|
|
89
|
+
const out = {};
|
|
90
|
+
for (const [status, key] of ERRORS) {
|
|
91
|
+
if (!codes.includes(status))
|
|
92
|
+
continue;
|
|
93
|
+
out[String(status)] = {
|
|
94
|
+
content: { "application/json": { schema: { $ref: `#/components/schemas/Err${status}` } } },
|
|
95
|
+
description: key,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
function jsonResponse(description, schema, headers) {
|
|
101
|
+
const response = { content: { "application/json": { schema } }, description };
|
|
102
|
+
if (headers !== undefined)
|
|
103
|
+
response.headers = headers;
|
|
104
|
+
return response;
|
|
105
|
+
}
|
|
106
|
+
/** RFC 8288 pagination links, declared only by dialects that actually publish them. */
|
|
107
|
+
function listResponseHeaders(dialect) {
|
|
108
|
+
if (dialect.envelope !== null)
|
|
109
|
+
return undefined;
|
|
110
|
+
return {
|
|
111
|
+
Link: {
|
|
112
|
+
description: 'Pagination links; rel="next" is present while further pages remain',
|
|
113
|
+
schema: { type: "string" },
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* The sort parameter's description, demonstrating the grammar this dialect expects.
|
|
119
|
+
*
|
|
120
|
+
* A document that expects `-created_at` and describes `field.asc` is lying, and oat would infer
|
|
121
|
+
* the wrong grammar from it — correctly, since the document is the only thing it can read.
|
|
122
|
+
*/
|
|
123
|
+
function sortDescription(dialect) {
|
|
124
|
+
switch (dialect.sortGrammar ?? "dotted") {
|
|
125
|
+
case "prefixed":
|
|
126
|
+
return "Sort by field; prefix with - for descending. e.g. -created_at, name";
|
|
127
|
+
case "colon":
|
|
128
|
+
return "Sort: field:asc or field:desc, comma-separated. e.g. created_at:desc";
|
|
129
|
+
case "spaced":
|
|
130
|
+
return "Sort: field asc or field desc, comma-separated. e.g. created_at desc";
|
|
131
|
+
case "dotted":
|
|
132
|
+
return "Sort: field[.asc|.desc][.nullsfirst|.nullslast], comma-separated";
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function listQueryParams(dialect, entity) {
|
|
136
|
+
const p = dialect.params;
|
|
137
|
+
const filterDescription = dialect.grammar === "postgrest"
|
|
138
|
+
? "PostgREST-style filter expression: field.op.value, and(...), or(...)"
|
|
139
|
+
: "Filter expression: field=op:value, comma-separated. e.g. status=eq:active";
|
|
140
|
+
const params = [];
|
|
141
|
+
if (dialect.grammar === "equality") {
|
|
142
|
+
/* One parameter per filterable field, which *is* the filter language here. Declaring them
|
|
143
|
+
* individually is the only way a document can express this shape, and it is how oat learns
|
|
144
|
+
* what may be filtered on. */
|
|
145
|
+
for (const field of fieldsWhere(entity, "filterable")) {
|
|
146
|
+
const declared = entity.fields.find((f) => f.name === field);
|
|
147
|
+
const numeric = declared?.type === "integer" || declared?.type === "number";
|
|
148
|
+
params.push([
|
|
149
|
+
field,
|
|
150
|
+
declared?.enum === undefined
|
|
151
|
+
? { type: numeric ? "number" : "string" }
|
|
152
|
+
: { enum: declared.enum, type: "string" },
|
|
153
|
+
`Exact match on ${field}`,
|
|
154
|
+
]);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
params.push([p.filter, { type: "string" }, filterDescription]);
|
|
159
|
+
}
|
|
160
|
+
params.push([p.order, { type: "string" }, sortDescription(dialect)], [
|
|
161
|
+
/* JSON:API carries the resource type in the parameter *name*, so the name itself is
|
|
162
|
+
* part of the grammar and has to be declared per entity. */
|
|
163
|
+
dialect.selectGrammar === "bracketed" ? `${p.select}[${entity.name}]` : p.select,
|
|
164
|
+
{ type: "string" },
|
|
165
|
+
"Comma-separated sparse fieldset; * selects all",
|
|
166
|
+
], [p.search, { maxLength: 200, type: "string" }, "Free-text search across searchable fields"]);
|
|
167
|
+
/* Exactly one paging model is published, because that is what a real document does — and a
|
|
168
|
+
* document advertising a parameter the backend ignores is itself a defect oat reports. */
|
|
169
|
+
if (p.page !== undefined) {
|
|
170
|
+
params.push([p.page, { minimum: 1, type: "integer" }, "1-based page number"]);
|
|
171
|
+
}
|
|
172
|
+
if (p.offset !== undefined) {
|
|
173
|
+
params.push([p.offset, { minimum: 0, type: "integer" }, "Number of records to skip"]);
|
|
174
|
+
}
|
|
175
|
+
if (p.cursor !== undefined) {
|
|
176
|
+
params.push([p.cursor, { type: "string" }, "Opaque forward cursor; takes precedence over page"]);
|
|
177
|
+
}
|
|
178
|
+
return params;
|
|
179
|
+
}
|
|
180
|
+
function pathParams(entity, includeItem) {
|
|
181
|
+
const params = entity.parents.map((name) => ({
|
|
182
|
+
in: "path",
|
|
183
|
+
name,
|
|
184
|
+
required: true,
|
|
185
|
+
schema: { type: "string" },
|
|
186
|
+
...(name === "project_id" ? { "x-root": true } : {}),
|
|
187
|
+
}));
|
|
188
|
+
if (includeItem) {
|
|
189
|
+
params.push({ in: "path", name: entity.itemParam, required: true, schema: { type: "string" } });
|
|
190
|
+
}
|
|
191
|
+
return params;
|
|
192
|
+
}
|
|
193
|
+
function tenantParam(entity) {
|
|
194
|
+
return entity.parents[0] ?? "project_id";
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Read routes belonging to an entity's parent, when a write here changes what they serve.
|
|
198
|
+
*
|
|
199
|
+
* Only the table/row relationship qualifies in this fixture: a table publishes `row_count`, so a
|
|
200
|
+
* row write genuinely changes the table's representation. Declaring routes that a write does not
|
|
201
|
+
* actually affect would make the invalidation check assert something false.
|
|
202
|
+
*/
|
|
203
|
+
function parentReadRoutes(entity) {
|
|
204
|
+
if (entity.name !== "row")
|
|
205
|
+
return [];
|
|
206
|
+
const table = ENTITIES.find((candidate) => candidate.name === "table");
|
|
207
|
+
if (table === undefined)
|
|
208
|
+
return [];
|
|
209
|
+
return [`GET ${table.collectionPath}`, `GET ${table.itemPath}`];
|
|
210
|
+
}
|
|
211
|
+
function buildEntityPaths(entity, dialect) {
|
|
212
|
+
const listRoute = `GET ${entity.collectionPath}`;
|
|
213
|
+
const itemRoute = `GET ${entity.itemPath}`;
|
|
214
|
+
const surface = [listRoute, itemRoute];
|
|
215
|
+
const title = entity.name[0]?.toUpperCase() + entity.name.slice(1);
|
|
216
|
+
const query = {
|
|
217
|
+
/* Declared rather than inferred: the grammar decides what oat can even express. */
|
|
218
|
+
grammar: dialect.grammar,
|
|
219
|
+
filterable: fieldsWhere(entity, "filterable"),
|
|
220
|
+
maxLimit: entity.maxLimit,
|
|
221
|
+
searchable: fieldsWhere(entity, "searchable"),
|
|
222
|
+
selectable: entity.fields.map((f) => f.name),
|
|
223
|
+
sortable: fieldsWhere(entity, "sortable"),
|
|
224
|
+
stableTiebreak: entity.identity,
|
|
225
|
+
};
|
|
226
|
+
const collection = {
|
|
227
|
+
get: {
|
|
228
|
+
operationId: `${entity.name}.list`,
|
|
229
|
+
parameters: [
|
|
230
|
+
...pathParams(entity, false),
|
|
231
|
+
...listQueryParams(dialect, entity).map(([name, schema, description]) => ({
|
|
232
|
+
description,
|
|
233
|
+
in: "query",
|
|
234
|
+
name,
|
|
235
|
+
required: false,
|
|
236
|
+
schema,
|
|
237
|
+
})),
|
|
238
|
+
{
|
|
239
|
+
in: "query",
|
|
240
|
+
name: dialect.params.limit,
|
|
241
|
+
required: false,
|
|
242
|
+
schema: { default: entity.defaultLimit, maximum: entity.maxLimit, minimum: 1, type: "integer" },
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
responses: {
|
|
246
|
+
"200": jsonResponse(`List ${entity.plural}`, listSchema(entity, dialect), listResponseHeaders(dialect)),
|
|
247
|
+
...errorResponses([400, 401, 403, 404]),
|
|
248
|
+
},
|
|
249
|
+
summary: `List ${entity.plural}`,
|
|
250
|
+
tags: [title],
|
|
251
|
+
"x-entity": { action: "list", identity: entity.identity, name: entity.name },
|
|
252
|
+
"x-query": query,
|
|
253
|
+
"x-tenant": tenantParam(entity),
|
|
254
|
+
...(entity.softDeleteField === undefined ? {} : { "x-soft-delete": entity.softDeleteField }),
|
|
255
|
+
},
|
|
256
|
+
post: {
|
|
257
|
+
operationId: `${entity.name}.create`,
|
|
258
|
+
parameters: [
|
|
259
|
+
...pathParams(entity, false),
|
|
260
|
+
/* Declared as an ordinary header parameter, because that is how real APIs publish
|
|
261
|
+
* it. oat needs no new meta tag to find this: a create operation naming a header
|
|
262
|
+
* whose name reads as an idempotency key is enough to know replay is promised. */
|
|
263
|
+
{
|
|
264
|
+
description: "Client-supplied key. Replaying a request with the same key must return the "
|
|
265
|
+
+ "original result rather than creating a second record.",
|
|
266
|
+
in: "header",
|
|
267
|
+
name: "Idempotency-Key",
|
|
268
|
+
required: false,
|
|
269
|
+
schema: { type: "string" },
|
|
270
|
+
},
|
|
271
|
+
],
|
|
272
|
+
requestBody: {
|
|
273
|
+
content: { "application/json": { schema: bodySchema(entity, "create") } },
|
|
274
|
+
required: true,
|
|
275
|
+
},
|
|
276
|
+
responses: {
|
|
277
|
+
"201": jsonResponse(`Created ${entity.name}`, itemSchema(entity)),
|
|
278
|
+
...errorResponses([400, 401, 403, 404, 415]),
|
|
279
|
+
},
|
|
280
|
+
summary: `Create ${entity.name}`,
|
|
281
|
+
tags: [title],
|
|
282
|
+
"x-entity": { action: "create", identity: entity.identity, name: entity.name },
|
|
283
|
+
"x-generated": fieldsWhere(entity, "generated"),
|
|
284
|
+
/*
|
|
285
|
+
* A create invalidates its own listing, and — where the entity has a parent that
|
|
286
|
+
* carries a derived value — the parent's routes as well. Declaring it is what makes
|
|
287
|
+
* the cross-entity consistency testable rather than assumed.
|
|
288
|
+
*/
|
|
289
|
+
"x-invalidate": [listRoute, ...parentReadRoutes(entity)],
|
|
290
|
+
"x-tenant": tenantParam(entity),
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
const item = {
|
|
294
|
+
delete: {
|
|
295
|
+
operationId: `${entity.name}.delete`,
|
|
296
|
+
parameters: pathParams(entity, true),
|
|
297
|
+
responses: {
|
|
298
|
+
"200": jsonResponse(`Deleted ${entity.name}`, itemSchema(entity)),
|
|
299
|
+
...errorResponses([400, 401, 403, 404]),
|
|
300
|
+
},
|
|
301
|
+
summary: `Delete ${entity.name}`,
|
|
302
|
+
tags: [title],
|
|
303
|
+
"x-entity": { action: "delete", identity: entity.identity, name: entity.name },
|
|
304
|
+
"x-invalidate": surface,
|
|
305
|
+
"x-tenant": tenantParam(entity),
|
|
306
|
+
...(entity.softDeleteField === undefined ? {} : { "x-soft-delete": entity.softDeleteField }),
|
|
307
|
+
},
|
|
308
|
+
get: {
|
|
309
|
+
operationId: `${entity.name}.get`,
|
|
310
|
+
parameters: pathParams(entity, true),
|
|
311
|
+
responses: {
|
|
312
|
+
"200": jsonResponse(entity.name, itemSchema(entity)),
|
|
313
|
+
...errorResponses([400, 401, 403, 404]),
|
|
314
|
+
},
|
|
315
|
+
summary: `Get ${entity.name}`,
|
|
316
|
+
tags: [title],
|
|
317
|
+
"x-entity": { action: "read", identity: entity.identity, name: entity.name },
|
|
318
|
+
"x-tenant": tenantParam(entity),
|
|
319
|
+
},
|
|
320
|
+
patch: {
|
|
321
|
+
operationId: `${entity.name}.update`,
|
|
322
|
+
parameters: pathParams(entity, true),
|
|
323
|
+
requestBody: {
|
|
324
|
+
content: { "application/json": { schema: bodySchema(entity, "update") } },
|
|
325
|
+
required: true,
|
|
326
|
+
},
|
|
327
|
+
responses: {
|
|
328
|
+
"200": jsonResponse(`Updated ${entity.name}`, itemSchema(entity)),
|
|
329
|
+
...errorResponses([400, 401, 403, 404, 415]),
|
|
330
|
+
},
|
|
331
|
+
summary: `Update ${entity.name}`,
|
|
332
|
+
tags: [title],
|
|
333
|
+
"x-entity": { action: "update", identity: entity.identity, name: entity.name },
|
|
334
|
+
/* Declared here as well as on create. Real documents often list server-owned fields
|
|
335
|
+
* only where they are conspicuous — the fields a caller may not supply — and a tool
|
|
336
|
+
* that reads just one operation then treats a generated field as client-owned. */
|
|
337
|
+
"x-generated": fieldsWhere(entity, "generated"),
|
|
338
|
+
"x-immutable": entity.fields.filter((f) => f.immutable === true).map((f) => f.name),
|
|
339
|
+
"x-invalidate": surface,
|
|
340
|
+
"x-tenant": tenantParam(entity),
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
return { [entity.collectionPath]: collection, [entity.itemPath]: item };
|
|
344
|
+
}
|
|
345
|
+
export function buildSpec(dialect = POSTGREST) {
|
|
346
|
+
const paths = {};
|
|
347
|
+
for (const entity of ENTITIES)
|
|
348
|
+
Object.assign(paths, buildEntityPaths(entity, dialect));
|
|
349
|
+
paths[`${TABLE.itemPath}/invites`] = {
|
|
350
|
+
post: {
|
|
351
|
+
operationId: "table.invite",
|
|
352
|
+
parameters: pathParams(TABLE, true),
|
|
353
|
+
requestBody: {
|
|
354
|
+
content: {
|
|
355
|
+
"application/json": {
|
|
356
|
+
schema: {
|
|
357
|
+
additionalProperties: false,
|
|
358
|
+
properties: { key: { type: "string" } },
|
|
359
|
+
required: ["key"],
|
|
360
|
+
type: "object",
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
required: true,
|
|
365
|
+
},
|
|
366
|
+
responses: {
|
|
367
|
+
"201": jsonResponse("Invite created", {
|
|
368
|
+
additionalProperties: false,
|
|
369
|
+
properties: { grant_id: { type: "string" }, token: { type: "string" } },
|
|
370
|
+
required: ["grant_id", "token"],
|
|
371
|
+
type: "object",
|
|
372
|
+
}),
|
|
373
|
+
...errorResponses([400, 401, 403, 404, 415]),
|
|
374
|
+
},
|
|
375
|
+
summary: "Invite another principal to read this table",
|
|
376
|
+
tags: ["Table"],
|
|
377
|
+
"x-entity": { action: "action", identity: TABLE.identity, name: TABLE.name },
|
|
378
|
+
"x-invite": {
|
|
379
|
+
accept: "invite.accept",
|
|
380
|
+
grantPointer: "$.grant_id",
|
|
381
|
+
granteeField: "key",
|
|
382
|
+
invite: "table.invite",
|
|
383
|
+
revoke: "table.revoke",
|
|
384
|
+
tokenPointer: "$.token",
|
|
385
|
+
},
|
|
386
|
+
"x-tenant": tenantParam(TABLE),
|
|
387
|
+
},
|
|
388
|
+
};
|
|
389
|
+
paths["/v1/invites/{token}/accept"] = {
|
|
390
|
+
post: {
|
|
391
|
+
operationId: "invite.accept",
|
|
392
|
+
parameters: [
|
|
393
|
+
{ in: "path", name: "token", required: true, schema: { type: "string" } },
|
|
394
|
+
],
|
|
395
|
+
responses: {
|
|
396
|
+
"200": jsonResponse("Invite accepted", {
|
|
397
|
+
additionalProperties: false,
|
|
398
|
+
properties: { accepted: { type: "boolean" } },
|
|
399
|
+
required: ["accepted"],
|
|
400
|
+
type: "object",
|
|
401
|
+
}),
|
|
402
|
+
...errorResponses([400, 401, 404]),
|
|
403
|
+
},
|
|
404
|
+
summary: "Accept an invite",
|
|
405
|
+
tags: ["Table"],
|
|
406
|
+
"x-entity": { action: "action", identity: TABLE.identity, name: TABLE.name },
|
|
407
|
+
},
|
|
408
|
+
};
|
|
409
|
+
paths[`${TABLE.itemPath}/grants/{grant_id}`] = {
|
|
410
|
+
delete: {
|
|
411
|
+
operationId: "table.revoke",
|
|
412
|
+
parameters: [
|
|
413
|
+
...pathParams(TABLE, true),
|
|
414
|
+
{ in: "path", name: "grant_id", required: true, schema: { type: "string" } },
|
|
415
|
+
],
|
|
416
|
+
responses: {
|
|
417
|
+
"200": jsonResponse("Grant revoked", {
|
|
418
|
+
additionalProperties: false,
|
|
419
|
+
properties: { revoked: { type: "boolean" } },
|
|
420
|
+
required: ["revoked"],
|
|
421
|
+
type: "object",
|
|
422
|
+
}),
|
|
423
|
+
...errorResponses([400, 401, 403, 404]),
|
|
424
|
+
},
|
|
425
|
+
summary: "Revoke a grant",
|
|
426
|
+
tags: ["Table"],
|
|
427
|
+
"x-entity": { action: "action", identity: TABLE.identity, name: TABLE.name },
|
|
428
|
+
"x-tenant": tenantParam(TABLE),
|
|
429
|
+
},
|
|
430
|
+
};
|
|
431
|
+
/* The async lifecycle: a start operation returning a receipt, and a poll route that
|
|
432
|
+
* eventually reports a terminal state. x-async ties the two together. */
|
|
433
|
+
paths[`${JOB.collectionPath}/start`] = {
|
|
434
|
+
post: {
|
|
435
|
+
operationId: "job.start",
|
|
436
|
+
parameters: pathParams(JOB, false),
|
|
437
|
+
requestBody: {
|
|
438
|
+
content: {
|
|
439
|
+
"application/json": {
|
|
440
|
+
schema: {
|
|
441
|
+
additionalProperties: false,
|
|
442
|
+
properties: { name: { maxLength: 128, minLength: 1, type: "string" } },
|
|
443
|
+
required: ["name"],
|
|
444
|
+
type: "object",
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
},
|
|
448
|
+
required: true,
|
|
449
|
+
},
|
|
450
|
+
responses: {
|
|
451
|
+
"202": jsonResponse("Job accepted", {
|
|
452
|
+
additionalProperties: false,
|
|
453
|
+
properties: { accepted: { type: "boolean" }, job_id: { type: "string" } },
|
|
454
|
+
required: ["job_id", "accepted"],
|
|
455
|
+
type: "object",
|
|
456
|
+
}),
|
|
457
|
+
...errorResponses([400, 401, 403, 404, 415]),
|
|
458
|
+
},
|
|
459
|
+
summary: "Start a job",
|
|
460
|
+
tags: ["Job"],
|
|
461
|
+
"x-async": {
|
|
462
|
+
idFrom: "$.job_id",
|
|
463
|
+
poll: `GET ${JOB.itemPath}`,
|
|
464
|
+
pollIntervalMs: 20,
|
|
465
|
+
successWhen: "status.eq.complete",
|
|
466
|
+
timeoutMs: 3000,
|
|
467
|
+
until: "status.in.(complete,failed)",
|
|
468
|
+
},
|
|
469
|
+
"x-effects": [{ count: 1, entity: "job", op: "create" }],
|
|
470
|
+
"x-entity": { action: "action", identity: "id", name: "job" },
|
|
471
|
+
"x-tenant": tenantParam(JOB),
|
|
472
|
+
},
|
|
473
|
+
};
|
|
474
|
+
paths["/v1/auth/token"] = {
|
|
475
|
+
post: {
|
|
476
|
+
operationId: "auth.token",
|
|
477
|
+
requestBody: {
|
|
478
|
+
content: {
|
|
479
|
+
"application/json": {
|
|
480
|
+
schema: {
|
|
481
|
+
additionalProperties: false,
|
|
482
|
+
properties: { key: { type: "string" } },
|
|
483
|
+
required: ["key"],
|
|
484
|
+
type: "object",
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
required: true,
|
|
489
|
+
},
|
|
490
|
+
responses: {
|
|
491
|
+
"200": jsonResponse("Access token", {
|
|
492
|
+
additionalProperties: false,
|
|
493
|
+
properties: {
|
|
494
|
+
access_token: { type: "string" },
|
|
495
|
+
expires_in: { type: "integer" },
|
|
496
|
+
project_id: { type: "string" },
|
|
497
|
+
},
|
|
498
|
+
required: ["access_token", "expires_in", "project_id"],
|
|
499
|
+
type: "object",
|
|
500
|
+
}),
|
|
501
|
+
...errorResponses([400, 401, 415]),
|
|
502
|
+
},
|
|
503
|
+
security: [],
|
|
504
|
+
summary: "Exchange an API key for an access token",
|
|
505
|
+
tags: ["Auth"],
|
|
506
|
+
},
|
|
507
|
+
};
|
|
508
|
+
const schemas = {};
|
|
509
|
+
for (const [status, key] of ERRORS)
|
|
510
|
+
schemas[`Err${status}`] = errorSchema(status, key);
|
|
511
|
+
return {
|
|
512
|
+
components: {
|
|
513
|
+
schemas,
|
|
514
|
+
securitySchemes: { bearer: { bearerFormat: "JWT", scheme: "bearer", type: "http" } },
|
|
515
|
+
},
|
|
516
|
+
info: { title: "oat reference backend", version: "1.0.0" },
|
|
517
|
+
openapi: "3.1.0",
|
|
518
|
+
paths,
|
|
519
|
+
security: [{ bearer: [] }],
|
|
520
|
+
"x-auth-flows": {
|
|
521
|
+
default: {
|
|
522
|
+
acquire: { credential: "$.access_token", operationId: "auth.token" },
|
|
523
|
+
expiresIn: "$.expires_in",
|
|
524
|
+
inject: { header: "authorization", template: "Bearer {credential}" },
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
/** Variant with every oat meta tag removed — exercises the heuristic fallbacks. */
|
|
530
|
+
export function buildUntaggedSpec(dialect = POSTGREST) {
|
|
531
|
+
const spec = buildSpec(dialect);
|
|
532
|
+
const strip = (node) => {
|
|
533
|
+
if (Array.isArray(node))
|
|
534
|
+
return node.map(strip);
|
|
535
|
+
if (node === null || typeof node !== "object")
|
|
536
|
+
return node;
|
|
537
|
+
const out = {};
|
|
538
|
+
for (const [key, value] of Object.entries(node)) {
|
|
539
|
+
if (key.startsWith("x-") && key !== "x-root")
|
|
540
|
+
continue;
|
|
541
|
+
out[key] = strip(value);
|
|
542
|
+
}
|
|
543
|
+
return out;
|
|
544
|
+
};
|
|
545
|
+
return strip(spec);
|
|
546
|
+
}
|
|
547
|
+
//# sourceMappingURL=spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/reference/spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage contract shared by the reference backends.
|
|
3
|
+
*
|
|
4
|
+
* One HTTP server implementation runs against every store, so a defect is defined once and
|
|
5
|
+
* exercised on each engine. Where two engines disagree about what a defect *does*, that is
|
|
6
|
+
* itself the finding — SQLite and Postgres differ on NULL ordering, type discipline, collation
|
|
7
|
+
* and case-insensitive matching, and those are exactly the semantics oat's checks reason about.
|
|
8
|
+
*
|
|
9
|
+
* Async throughout, because a real database is: SQLite implementations resolve immediately.
|
|
10
|
+
*/
|
|
11
|
+
import type { EntityDef } from "./model.ts";
|
|
12
|
+
export type Row = Record<string, unknown>;
|
|
13
|
+
export interface QueryParams {
|
|
14
|
+
filter?: string | undefined;
|
|
15
|
+
order?: string | undefined;
|
|
16
|
+
select?: string | undefined;
|
|
17
|
+
q?: string | undefined;
|
|
18
|
+
limit?: number | undefined;
|
|
19
|
+
page?: number | undefined;
|
|
20
|
+
cursor?: string | undefined;
|
|
21
|
+
}
|
|
22
|
+
export interface QueryOptions {
|
|
23
|
+
softDeleteField?: string | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Applied to each row *before* the sparse fieldset, so a derived value cannot reintroduce a
|
|
26
|
+
* column the caller deselected.
|
|
27
|
+
*/
|
|
28
|
+
transform?: ((row: Row) => Row) | undefined;
|
|
29
|
+
}
|
|
30
|
+
export interface QueryResult {
|
|
31
|
+
items: Row[];
|
|
32
|
+
count: number;
|
|
33
|
+
hasMore: boolean;
|
|
34
|
+
nextCursor: string | null;
|
|
35
|
+
page: number | null;
|
|
36
|
+
limit: number;
|
|
37
|
+
}
|
|
38
|
+
export interface Store {
|
|
39
|
+
close(): Promise<void>;
|
|
40
|
+
nextId(prefix: string): string;
|
|
41
|
+
now(): number;
|
|
42
|
+
insert(entity: EntityDef, record: Row): Promise<Row>;
|
|
43
|
+
byId(entity: EntityDef, id: string): Promise<Row | null>;
|
|
44
|
+
update(entity: EntityDef, id: string, patch: Row): Promise<Row | null>;
|
|
45
|
+
remove(entity: EntityDef, id: string): Promise<void>;
|
|
46
|
+
query(entity: EntityDef, scope: Record<string, string>, params: QueryParams, options: QueryOptions): Promise<QueryResult>;
|
|
47
|
+
}
|
|
48
|
+
/** Raised for input the storage layer rejects — surfaces as 400, or 500 under the defect. */
|
|
49
|
+
export declare class SqlError extends Error {
|
|
50
|
+
readonly code: string;
|
|
51
|
+
constructor(code: string, message: string);
|
|
52
|
+
}
|
|
53
|
+
export declare function encodeCursor(id: string): string;
|
|
54
|
+
export declare function decodeCursor(cursor: string): string;
|
|
55
|
+
/** Splits on commas at paren depth zero — shared by the filter and order grammars. */
|
|
56
|
+
export declare function splitTopLevel(input: string): string[];
|
|
57
|
+
export declare function stripParens(value: string): string;
|
|
58
|
+
export declare function project(row: Row, select: string | undefined, ignore: boolean, excluded?: readonly string[]): Row;
|
|
59
|
+
//# sourceMappingURL=store-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-api.d.ts","sourceRoot":"","sources":["../../src/reference/store-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEzC,MAAM,WAAW,WAAW;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC3B;AAED,MAAM,WAAW,YAAY;IAC5B,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,CAAC,GAAG,SAAS,CAAA;CAC3C;AAED,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,GAAG,EAAE,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,KAAK;IACrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACtB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B,GAAG,IAAI,MAAM,CAAA;IACb,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;IACpD,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAA;IACxD,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAA;IACtE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpD,KAAK,CACJ,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,YAAY,GACnB,OAAO,CAAC,WAAW,CAAC,CAAA;CACvB;AAED,6FAA6F;AAC7F,qBAAa,QAAS,SAAQ,KAAK;IAEjC,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM;CAIhB;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAQnD;AAED,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAerD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,OAAO,CACtB,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,OAAO,EAIf,QAAQ,GAAE,SAAS,MAAM,EAAO,GAC9B,GAAG,CAaL"}
|