@yongdall/api-model 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/index.d.mts +10 -0
- package/index.mjs +3 -0
- package/package.json +24 -0
- package/routers.yongdall.mjs +298 -0
- package/routers.yongdall.mjs.map +1 -0
- package/useDocument-Bsmiy9SB.mjs +68 -0
- package/useDocument-Bsmiy9SB.mjs.map +1 -0
package/index.d.mts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import "@yongdall/http";
|
|
2
|
+
import { ModelTable } from "@yongdall/model";
|
|
3
|
+
|
|
4
|
+
//#region api/api-model/routers/useDocument.d.mts
|
|
5
|
+
declare function useDocument(): Promise<Record<string, any> | null>;
|
|
6
|
+
//#endregion
|
|
7
|
+
//#region api/api-model/routers/useModel.d.mts
|
|
8
|
+
declare function useModel(): Promise<ModelTable | null>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { useDocument, useModel };
|
package/index.mjs
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yongdall/api-model",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"main": "./index.mjs",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./index.mjs"
|
|
7
|
+
},
|
|
8
|
+
"version": "0.1.0",
|
|
9
|
+
"description": "",
|
|
10
|
+
"keywords": [],
|
|
11
|
+
"author": "",
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@yongdall/common": "^0.1.0",
|
|
15
|
+
"@yongdall/context": "^0.1.0",
|
|
16
|
+
"@yongdall/core": "^0.1.0",
|
|
17
|
+
"@yongdall/model": "^0.1.0",
|
|
18
|
+
"@yongdall/connection": "^0.1.0",
|
|
19
|
+
"@yongdall/http": "^0.1.0"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@yongdall/types": "^0.1.0"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { a as useModelId, i as useModel, n as useDocument, r as modelId, t as documentId } from "./useDocument-Bsmiy9SB.mjs";
|
|
2
|
+
import { Search, getPatternFields, runPattern, yieldPermissionConstraintFields } from "@yongdall/common";
|
|
3
|
+
import { Query, Where, getLabelPattern, getModelOptions } from "@yongdall/model";
|
|
4
|
+
import { ApiRouter, Param, e404, enumRouter, useBody } from "@yongdall/http";
|
|
5
|
+
import { useDatabase } from "@yongdall/connection";
|
|
6
|
+
import { createPermissionMatches, filterPermissionDocument, filterPermissionUpdate, getModel, getModelAuthorizationPermissions, isSingleUser, search2where, testPermissions, toDocumentFields } from "@yongdall/core";
|
|
7
|
+
|
|
8
|
+
//#region api/api-model/utils.mjs
|
|
9
|
+
/** @import { ModelTable, TableDefine } from '@yongdall/model'*/
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
* @param {[model: string, id: any, data: Record<string, any>, field: string][]} list
|
|
13
|
+
* @param {TableDefine} model
|
|
14
|
+
* @param {string?} [databaseId]
|
|
15
|
+
*/
|
|
16
|
+
async function loadDocumentLabel(list, model, databaseId) {
|
|
17
|
+
const labelPattern = getLabelPattern(model);
|
|
18
|
+
if (!labelPattern) return;
|
|
19
|
+
const labelFields = getPatternFields(labelPattern);
|
|
20
|
+
if (!labelFields.length) return;
|
|
21
|
+
const primaryFields = Object.entries(model.fields).filter(([, v]) => v.primary).sort(([, a], [, b]) => Number(a.primary) - Number(b.primary)).map(([v]) => v);
|
|
22
|
+
if (!primaryFields.length) return;
|
|
23
|
+
let query = new Query(model, true);
|
|
24
|
+
query = query.select(primaryFields).select(labelFields);
|
|
25
|
+
const ids = [...new Set(list.map(([, id]) => id))];
|
|
26
|
+
let where = new Where();
|
|
27
|
+
if (primaryFields.length === 1) {
|
|
28
|
+
const [field] = primaryFields;
|
|
29
|
+
where = where.and(field, "in", ids);
|
|
30
|
+
return;
|
|
31
|
+
} else {
|
|
32
|
+
/** @type {} */
|
|
33
|
+
const idsMap = [];
|
|
34
|
+
ids.map((v) => `${v}`.split("$"));
|
|
35
|
+
for (const id of ids) {
|
|
36
|
+
const values = `${id}`.split("$");
|
|
37
|
+
if (values.length !== primaryFields.length) continue;
|
|
38
|
+
idsMap.push([values]);
|
|
39
|
+
}
|
|
40
|
+
if (!idsMap.length) return;
|
|
41
|
+
where = where.and(primaryFields, "in", idsMap);
|
|
42
|
+
}
|
|
43
|
+
const result = await useDatabase(databaseId).select(query.where(where));
|
|
44
|
+
if (!result.length) return;
|
|
45
|
+
const labels = Object.fromEntries(result.map((v) => [primaryFields.map((f) => v[f]).join("$"), runPattern(labelPattern, v)]));
|
|
46
|
+
for (const [, id, data, field] of list) {
|
|
47
|
+
const label = Object.hasOwn(labels, id) && labels[id];
|
|
48
|
+
if (!label) continue;
|
|
49
|
+
data[`${field}~label`] = label;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
*
|
|
54
|
+
* @param {any[]} list
|
|
55
|
+
* @param {ModelTable} model
|
|
56
|
+
*/
|
|
57
|
+
async function loadDocumentsLabel(list, model) {
|
|
58
|
+
/** @type {[model: string, id: any, data: Record<string, any>, field: string][]} */
|
|
59
|
+
const setList = [];
|
|
60
|
+
/** @type {[model: ModelTable, list: any[]][]} */
|
|
61
|
+
const queue = [[model, list]];
|
|
62
|
+
for (let line = queue.shift(); line; line = queue.shift()) {
|
|
63
|
+
const [model, list] = line;
|
|
64
|
+
for (const [name, field] of Object.entries(model.fields)) {
|
|
65
|
+
const type = field.type;
|
|
66
|
+
if (!type) continue;
|
|
67
|
+
if (typeof type === "object") {
|
|
68
|
+
queue.push([type, list.flatMap((v) => v[name] || [])]);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const modelName = field.model;
|
|
72
|
+
if (!modelName) continue;
|
|
73
|
+
for (const item of list) {
|
|
74
|
+
const id = item[name];
|
|
75
|
+
if (!id) continue;
|
|
76
|
+
setList.push([
|
|
77
|
+
modelName,
|
|
78
|
+
id,
|
|
79
|
+
item,
|
|
80
|
+
name
|
|
81
|
+
]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const promises = [];
|
|
86
|
+
for (const [modelName, list] of Object.entries(Object.groupBy(setList, (v) => v[0]))) {
|
|
87
|
+
if (!list) continue;
|
|
88
|
+
promises.push(getModel(modelName).then((model) => model && loadDocumentLabel(list, model, model.databaseId)));
|
|
89
|
+
}
|
|
90
|
+
await Promise.all(promises);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region api/api-model/routers/model.documents.mjs
|
|
95
|
+
const documentsRouter = new ApiRouter();
|
|
96
|
+
documentsRouter.get(async function(ctx) {
|
|
97
|
+
const model = await useModel();
|
|
98
|
+
const modelId = await useModelId();
|
|
99
|
+
if (!model || !modelId) return e404(ctx);
|
|
100
|
+
const permissions = await isSingleUser() ? null : await getModelAuthorizationPermissions(modelId, "query");
|
|
101
|
+
if (permissions && !permissions.length) return e404(ctx);
|
|
102
|
+
const { sort, offset, limit, select, where, orWhere, or } = Search.merge(Search.parse(ctx.url.search.slice(1)), await useBody() || {});
|
|
103
|
+
const permissionMatches = permissions && await createPermissionMatches(permissions) || null;
|
|
104
|
+
let modelQuery = new Query(model, true).offset(offset).limit(limit);
|
|
105
|
+
if (permissionMatches) modelQuery = modelQuery.where(permissionMatches);
|
|
106
|
+
const searchWhere = await search2where(model.fields, where, orWhere, or);
|
|
107
|
+
if (searchWhere) modelQuery = modelQuery.where(searchWhere);
|
|
108
|
+
modelQuery = modelQuery.sort();
|
|
109
|
+
if (sort) modelQuery = modelQuery.sort(...sort);
|
|
110
|
+
const allFields = [
|
|
111
|
+
select || [],
|
|
112
|
+
Object.entries(model.fields).filter((v) => v[1].primary).map((v) => v[0]),
|
|
113
|
+
permissionMatches && permissions?.flatMap((v) => [...yieldPermissionConstraintFields(v)]) || []
|
|
114
|
+
].flat();
|
|
115
|
+
const [result, total] = await useDatabase(model.databaseId).transaction((t) => Promise.all([t.search(modelQuery, allFields), t.count(modelQuery)]));
|
|
116
|
+
const documents = permissions ? await Promise.all(result.map((v) => filterPermissionDocument(model, permissions, v))) : result;
|
|
117
|
+
await loadDocumentsLabel(documents, model);
|
|
118
|
+
return {
|
|
119
|
+
documents,
|
|
120
|
+
total
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
documentsRouter.post(async (ctx) => {
|
|
124
|
+
const model = await useModel();
|
|
125
|
+
const modelId = await useModelId();
|
|
126
|
+
if (!model || !modelId) return e404(ctx);
|
|
127
|
+
const permissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, "create");
|
|
128
|
+
if (permissions && !permissions.length) return e404(ctx);
|
|
129
|
+
const newDocument = (await useBody() || {}).document;
|
|
130
|
+
if (!newDocument) return e404(ctx);
|
|
131
|
+
const document = permissions ? await filterPermissionDocument(model, permissions, newDocument) : newDocument;
|
|
132
|
+
if (!document) return e404(ctx);
|
|
133
|
+
return await useDatabase(model.databaseId).create(model, document);
|
|
134
|
+
});
|
|
135
|
+
const documentRouter$1 = documentsRouter.route`${documentId}`();
|
|
136
|
+
documentRouter$1.onionskin(async (ctx, next) => {
|
|
137
|
+
if (!await useDocument()) return e404(ctx);
|
|
138
|
+
return next();
|
|
139
|
+
});
|
|
140
|
+
documentRouter$1.route(enumRouter("documentApi"));
|
|
141
|
+
var model_documents_default = documentsRouter;
|
|
142
|
+
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region api/api-model/routers/models.mjs
|
|
145
|
+
const modelsRouter = new ApiRouter();
|
|
146
|
+
const modelRouter = modelsRouter.route`${modelId}`();
|
|
147
|
+
async function loadPermissions() {
|
|
148
|
+
return {};
|
|
149
|
+
}
|
|
150
|
+
modelRouter.get(async function getDefine(ctx) {
|
|
151
|
+
const model = await useModel();
|
|
152
|
+
if (!model) return e404(ctx);
|
|
153
|
+
return {
|
|
154
|
+
...getModelOptions(model),
|
|
155
|
+
id: await useModelId() || "",
|
|
156
|
+
fields: toDocumentFields(model.fields),
|
|
157
|
+
permission: await loadPermissions()
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
modelRouter.route(enumRouter("modelApi"));
|
|
161
|
+
var models_default = modelsRouter;
|
|
162
|
+
|
|
163
|
+
//#endregion
|
|
164
|
+
//#region api/api-model/routers/model.document.mjs
|
|
165
|
+
const documentRouter = new ApiRouter();
|
|
166
|
+
documentRouter.get(async (ctx) => {
|
|
167
|
+
const model = await useModel();
|
|
168
|
+
const modelId = await useModelId();
|
|
169
|
+
if (!model || !modelId) return e404(ctx);
|
|
170
|
+
const readPermissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, "read");
|
|
171
|
+
if (readPermissions && !readPermissions.length) return e404(ctx);
|
|
172
|
+
const document = await useDocument();
|
|
173
|
+
if (!document) return e404(ctx);
|
|
174
|
+
if (!readPermissions) return { document: { ...await document.toJSON?.() || document } };
|
|
175
|
+
const doc = await filterPermissionDocument(model, readPermissions, document);
|
|
176
|
+
if (!doc) return e404(ctx);
|
|
177
|
+
return { document: doc };
|
|
178
|
+
});
|
|
179
|
+
documentRouter.put(async (ctx) => {
|
|
180
|
+
const model = await useModel();
|
|
181
|
+
const modelId = await useModelId();
|
|
182
|
+
if (!model || !modelId) return e404(ctx);
|
|
183
|
+
const updatePermissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, "update");
|
|
184
|
+
if (updatePermissions && !updatePermissions.length) return e404(ctx);
|
|
185
|
+
const document = await useDocument();
|
|
186
|
+
if (!document) return e404(ctx);
|
|
187
|
+
const data = await useBody();
|
|
188
|
+
if (!data) return;
|
|
189
|
+
const newValue = data.document;
|
|
190
|
+
if (!newValue) return;
|
|
191
|
+
const newData = updatePermissions ? await filterPermissionUpdate(model, updatePermissions, document, newValue) : newValue;
|
|
192
|
+
const result = Object.keys(newData).length ? await useDatabase(model.databaseId).save(model, document, newData) : document;
|
|
193
|
+
if (!result) return {};
|
|
194
|
+
const readPermissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, "read");
|
|
195
|
+
if (!readPermissions) return result || {};
|
|
196
|
+
if (!readPermissions.length) return {};
|
|
197
|
+
return await filterPermissionDocument(model, readPermissions, result);
|
|
198
|
+
});
|
|
199
|
+
documentRouter.delete(async (ctx) => {
|
|
200
|
+
const model = await useModel();
|
|
201
|
+
const modelId = await useModelId();
|
|
202
|
+
if (!model || !modelId) return e404(ctx);
|
|
203
|
+
const permissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, "read");
|
|
204
|
+
if (permissions && !permissions.length) return e404(ctx);
|
|
205
|
+
const document = await useDocument();
|
|
206
|
+
if (!document) return e404(ctx);
|
|
207
|
+
if (permissions && !await testPermissions(permissions, document)) return e404(ctx);
|
|
208
|
+
await useDatabase(model.databaseId).destroy(model, document).then(Boolean);
|
|
209
|
+
ctx.status = 204;
|
|
210
|
+
});
|
|
211
|
+
const fieldParam = new Param();
|
|
212
|
+
documentRouter.route`fields/${fieldParam}`().get(async (ctx) => {
|
|
213
|
+
const fieldName = fieldParam.param(ctx);
|
|
214
|
+
if (!fieldName) return e404(ctx);
|
|
215
|
+
const model = await useModel();
|
|
216
|
+
const modelId = await useModelId();
|
|
217
|
+
if (!model || !modelId) return e404(ctx);
|
|
218
|
+
const { fields } = model;
|
|
219
|
+
if (!Object.hasOwn(fields, fieldName)) return e404(ctx);
|
|
220
|
+
const field = fields[fieldName];
|
|
221
|
+
if (!field) return e404(ctx);
|
|
222
|
+
const readPermissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, "read");
|
|
223
|
+
if (readPermissions && !readPermissions.length) return e404(ctx);
|
|
224
|
+
if (readPermissions) {
|
|
225
|
+
const group = field.group;
|
|
226
|
+
if (!readPermissions.find((v) => {
|
|
227
|
+
const field = v.fields;
|
|
228
|
+
if (field === fieldName || field === "*" || Array.isArray(field) && (field.includes(fieldName) || field.includes("*"))) return true;
|
|
229
|
+
if (!group || v.group) return false;
|
|
230
|
+
if (v.group === group || Array.isArray(v.group) && v.group.includes(group)) return true;
|
|
231
|
+
})) return e404(ctx);
|
|
232
|
+
}
|
|
233
|
+
const document = await useDocument();
|
|
234
|
+
if (!document) return e404(ctx);
|
|
235
|
+
if (!readPermissions) return { document: { ...await document.toJSON?.() || document } };
|
|
236
|
+
const doc = await filterPermissionDocument(model, readPermissions, document);
|
|
237
|
+
if (!doc) return e404(ctx);
|
|
238
|
+
if (!Object.hasOwn(doc, fieldName)) return e404(ctx);
|
|
239
|
+
return { value: doc[fieldName] };
|
|
240
|
+
});
|
|
241
|
+
documentRouter.route`values`();
|
|
242
|
+
documentRouter.route`datasets`();
|
|
243
|
+
var model_document_default = documentRouter;
|
|
244
|
+
|
|
245
|
+
//#endregion
|
|
246
|
+
//#region api/api-model/routers/model.options.mjs
|
|
247
|
+
const optionsRouter = new ApiRouter();
|
|
248
|
+
optionsRouter.get(async function(ctx) {
|
|
249
|
+
const model = await useModel();
|
|
250
|
+
const modelId = await useModelId();
|
|
251
|
+
if (!model || !modelId) return e404(ctx);
|
|
252
|
+
const permissions = await isSingleUser() ? null : await getModelAuthorizationPermissions(modelId, "options");
|
|
253
|
+
if (permissions && !permissions.length) return e404(ctx);
|
|
254
|
+
const { sort, offset, limit, select, where, orWhere, or } = Search.merge(Search.parse(ctx.url.search.slice(1)), await useBody() || {});
|
|
255
|
+
const permissionMatches = permissions && await createPermissionMatches(permissions) || null;
|
|
256
|
+
let modelQuery = new Query(model, true).offset(offset).limit(limit);
|
|
257
|
+
if (permissionMatches) modelQuery = modelQuery.where(permissionMatches);
|
|
258
|
+
const searchWhere = await search2where(model.fields, where, orWhere, or);
|
|
259
|
+
if (searchWhere) modelQuery = modelQuery.where(searchWhere);
|
|
260
|
+
modelQuery = modelQuery.sort();
|
|
261
|
+
if (sort) modelQuery = modelQuery.sort(...sort);
|
|
262
|
+
modelQuery = modelQuery.select([...new Set([
|
|
263
|
+
select || [],
|
|
264
|
+
Object.entries(model.fields).filter(([, { type }]) => type && typeof type === "string").map((v) => v[0]),
|
|
265
|
+
permissionMatches && permissions?.flatMap((v) => [...yieldPermissionConstraintFields(v)]) || []
|
|
266
|
+
].flat())]);
|
|
267
|
+
const documents = await useDatabase(model.databaseId).transaction((t) => t.select(modelQuery));
|
|
268
|
+
const options = permissions ? await Promise.all(documents.map((v) => filterPermissionDocument(model, permissions, v))) : documents;
|
|
269
|
+
await loadDocumentsLabel(options, model);
|
|
270
|
+
return { options };
|
|
271
|
+
});
|
|
272
|
+
optionsRouter.get`${documentId}`(async (ctx) => {
|
|
273
|
+
const model = await useModel();
|
|
274
|
+
const modelId = await useModelId();
|
|
275
|
+
if (!model || !modelId) return e404(ctx);
|
|
276
|
+
const permissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, "options");
|
|
277
|
+
if (permissions && !permissions.length) return e404(ctx);
|
|
278
|
+
const document = await useDocument();
|
|
279
|
+
if (!document) return e404(ctx);
|
|
280
|
+
if (!permissions) return { document: { ...await document.toJSON?.() || document } };
|
|
281
|
+
const option = await filterPermissionDocument(model, permissions, document);
|
|
282
|
+
if (!option) return e404(ctx);
|
|
283
|
+
return { option };
|
|
284
|
+
});
|
|
285
|
+
var model_options_default = optionsRouter;
|
|
286
|
+
|
|
287
|
+
//#endregion
|
|
288
|
+
//#region api/api-model/routers/index.mjs
|
|
289
|
+
const api = { models: models_default };
|
|
290
|
+
const modelApi = {
|
|
291
|
+
documents: model_documents_default,
|
|
292
|
+
options: model_options_default
|
|
293
|
+
};
|
|
294
|
+
const documentApi = { "": model_document_default };
|
|
295
|
+
|
|
296
|
+
//#endregion
|
|
297
|
+
export { api, documentApi, modelApi };
|
|
298
|
+
//# sourceMappingURL=routers.yongdall.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routers.yongdall.mjs","names":["documentRouter","modelsRouter","documentsRouter","optionsRouter","documentRouter"],"sources":["../../api/api-model/utils.mjs","../../api/api-model/routers/model.documents.mjs","../../api/api-model/routers/models.mjs","../../api/api-model/routers/model.document.mjs","../../api/api-model/routers/model.options.mjs","../../api/api-model/routers/index.mjs"],"sourcesContent":["/** @import { ModelTable, TableDefine } from '@yongdall/model'*/\nimport { getPatternFields, runPattern } from '@yongdall/common';\nimport { Query, getLabelPattern, Where } from '@yongdall/model';\nimport { useDatabase } from '@yongdall/connection';\nimport { getModel } from '@yongdall/core';\n\n\n/**\n * \n * @param {[model: string, id: any, data: Record<string, any>, field: string][]} list\n * @param {TableDefine} model\n * @param {string?} [databaseId]\n */\nasync function loadDocumentLabel(list, model, databaseId) {\n\tconst labelPattern = getLabelPattern(model);\n\tif (!labelPattern) { return; }\n\tconst labelFields = getPatternFields(labelPattern);\n\tif (!labelFields.length) { return; }\n\tconst primaryFields = Object.entries(model.fields)\n\t\t.filter(([, v]) => v.primary)\n\t\t.sort(([, a], [, b]) => Number(a.primary) - Number(b.primary))\n\t\t.map(([v]) => v);\n\tif (!primaryFields.length) { return; }\n\tlet query = new Query(model, true);\n\tquery = query.select(primaryFields).select(labelFields);\n\tconst ids = [...new Set(list.map(([, id]) => id))];\n\tlet where = new Where();\n\tif (primaryFields.length === 1) {\n\t\tconst [field] = primaryFields;\n\t\twhere = where.and(field, 'in', ids);\n\t\treturn;\n\t} else {\n\t\t/** @type {} */\n\t\tconst idsMap = [];\n\t\tids.map(v => `${v}`.split('$'));\n\t\tfor (const id of ids) {\n\t\t\tconst values = `${id}`.split('$');\n\t\t\tif (values.length !== primaryFields.length) { continue; }\n\t\t\tidsMap.push([values]);\n\t\t}\n\t\tif (!idsMap.length) { return; }\n\t\twhere = where.and(primaryFields, 'in', idsMap);\n\n\n\t}\n\tconst result = await useDatabase(databaseId).select(query.where(where));\n\tif (!result.length) { return; }\n\tconst labels = Object.fromEntries(result.map(v => [\n\t\tprimaryFields.map(f => v[f]).join('$'),\n\t\trunPattern(labelPattern, v)\n\t]));\n\tfor (const [, id, data, field] of list) {\n\t\tconst label = Object.hasOwn(labels, id) && labels[id];\n\t\tif (!label) { continue; }\n\t\tdata[`${field}~label`] = label;\n\t}\n}\n/**\n * \n * @param {any[]} list \n * @param {ModelTable} model \n */\nexport async function loadDocumentsLabel(list, model) {\n\t/** @type {[model: string, id: any, data: Record<string, any>, field: string][]} */\n\tconst setList = [];\n\t/** @type {[model: ModelTable, list: any[]][]} */\n\tconst queue = [[model, list]];\n\tfor (let line = queue.shift(); line; line = queue.shift()) {\n\t\tconst [model, list] = line;\n\t\tfor (const [name, field] of Object.entries(model.fields)) {\n\t\t\tconst type = field.type;\n\t\t\tif (!type) { continue; }\n\t\t\tif (typeof type === 'object') {\n\t\t\t\tqueue.push([type, list.flatMap(v => v[name] || [])]);\n\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst modelName = field.model;\n\t\t\tif (!modelName) { continue; }\n\t\t\tfor (const item of list) {\n\t\t\t\tconst id = item[name];\n\t\t\t\tif (!id) { continue; }\n\t\t\t\tsetList.push([modelName, id, item, name]);\n\t\t\t}\n\t\t}\n\t}\n\tconst promises = [];\n\tfor (const [modelName, list] of Object.entries(Object.groupBy(setList, v => v[0]))) {\n\t\tif (!list) { continue; }\n\t\tpromises.push(\n\t\t\tgetModel(modelName)\n\t\t\t\t.then(model => model && loadDocumentLabel(list, model, model.databaseId)),\n\t\t);\n\t}\n\tawait Promise.all(promises);\n\n}\n","import { Search, yieldPermissionConstraintFields } from '@yongdall/common';\nimport { Query } from '@yongdall/model';\nimport { useBody, e404, enumRouter } from '@yongdall/http';\nimport { ApiRouter } from '@yongdall/http';\nimport useDocument, { documentId } from './useDocument.mjs';\nimport { useDatabase } from '@yongdall/connection';\nimport useModel, { useModelId } from './useModel.mjs';\nimport { createPermissionMatches, getModelAuthorizationPermissions, filterPermissionDocument, isSingleUser, search2where } from '@yongdall/core';\nimport { loadDocumentsLabel } from '../utils.mjs';\n\nconst documentsRouter = new ApiRouter();\n\n\n\ndocumentsRouter.get(async function (ctx) {\n\tconst model = await useModel();\n\tconst modelId = await useModelId();\n\tif (!model || !modelId) { return e404(ctx); }\n\tconst permissions = await isSingleUser() ? null : await getModelAuthorizationPermissions(modelId, 'query');\n\tif (permissions && !permissions.length) { return e404(ctx); }\n\tconst { sort, offset, limit, select, where, orWhere, or } = Search.merge(\n\t\tSearch.parse(ctx.url.search.slice(1)),\n\t\tawait useBody() || {},\n\t);\n\n\tconst permissionMatches = permissions && await createPermissionMatches(permissions) || null;\n\n\tlet modelQuery = new Query(model, true).offset(offset).limit(limit);\n\tif (permissionMatches) {\n\t\tmodelQuery = modelQuery.where(permissionMatches);\n\t}\n\tconst searchWhere = await search2where(model.fields, where, orWhere, or);\n\tif (searchWhere) { modelQuery = modelQuery.where(searchWhere); }\n\n\tmodelQuery = modelQuery.sort();\n\tif (sort) { modelQuery = modelQuery.sort(...sort); }\n\tconst allFields = [\n\t\tselect || [],\n\t\tObject.entries(model.fields).filter(v => v[1].primary).map(v => v[0]),\n\t\tpermissionMatches && permissions?.flatMap(v => [...yieldPermissionConstraintFields(v)]) || [],\n\t].flat();\n\n\tconst [result, total] = await useDatabase(model.databaseId).transaction(t => Promise.all([t.search(modelQuery, allFields), t.count(modelQuery)]));\n\n\tconst documents = permissions ? await Promise.all(result.map(v => filterPermissionDocument(model, permissions, v))) : result;\n\tawait loadDocumentsLabel(documents, model);\n\treturn { documents, total };\n});\n\ndocumentsRouter.post(async ctx => {\n\tconst model = await useModel();\n\tconst modelId = await useModelId();\n\tif (!model || !modelId) { return e404(ctx); }\n\tconst permissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, 'create');\n\tif (permissions && !permissions.length) { return e404(ctx); }\n\tconst data = await useBody() || {};\n\tconst newDocument = data.document;\n\tif (!newDocument) { return e404(ctx); }\n\tconst document = permissions ? await filterPermissionDocument(model, permissions, newDocument) : newDocument;\n\tif (!document) { return e404(ctx); }\n\tconst doc = await useDatabase(model.databaseId).create(model, document);\n\treturn doc;\n});\n\nconst documentRouter = documentsRouter.route`${documentId}`();\ndocumentRouter.onionskin(async (ctx, next) => {\n\tconst doc = await useDocument();\n\tif (!doc) { return e404(ctx); }\n\treturn next();\n});\n\ndocumentRouter.route(enumRouter('documentApi'));\n\nexport default documentsRouter;\n","import { ApiRouter } from '@yongdall/http';\nimport { e404, enumRouter } from '@yongdall/http';\nimport {toDocumentFields} from '@yongdall/core';\nimport useModel, { modelId, useModelId } from './useModel.mjs';\nimport { getModelOptions } from '@yongdall/model';\n\n\n\nconst modelsRouter = new ApiRouter();\nconst modelRouter = modelsRouter.route`${modelId}`();\n\nasync function loadPermissions() {\n\treturn {};\n}\nmodelRouter.get(async function getDefine(ctx) {\n\tconst model = await useModel();\n\tif (!model) { return e404(ctx); }\n\treturn {\n\t\t...getModelOptions(model),\n\t\tid: await useModelId() || '',\n\t\tfields: toDocumentFields(model.fields),\n\t\tpermission: await loadPermissions(),\n\t}\n});\nmodelRouter.route(enumRouter('modelApi'));\n\nexport default modelsRouter;\n","import { e404, Param, useBody } from '@yongdall/http';\nimport { ApiRouter } from '@yongdall/http';\nimport useDocument from './useDocument.mjs';\nimport { useDatabase } from '@yongdall/connection';\nimport useModel, { useModelId } from './useModel.mjs';\nimport { filterPermissionDocument, filterPermissionUpdate, getModelAuthorizationPermissions, testPermissions } from '@yongdall/core';\nimport { isSingleUser } from '@yongdall/core';\n\n\nconst documentRouter = new ApiRouter();\n\n\ndocumentRouter.get(async ctx => {\n\tconst model = await useModel();\n\tconst modelId = await useModelId();\n\tif (!model || !modelId) { return e404(ctx); }\n\tconst readPermissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, 'read');\n\tif (readPermissions && !readPermissions.length) { return e404(ctx); }\n\tconst document = await useDocument();\n\tif (!document) { return e404(ctx); }\n\tif (!readPermissions) { return { document: { ...await document.toJSON?.() || document } }; }\n\tconst doc = await filterPermissionDocument(model, readPermissions, document);\n\tif (!doc) { return e404(ctx); }\n\treturn { document: doc };\n});\n\ndocumentRouter.put(async ctx => {\n\tconst model = await useModel();\n\tconst modelId = await useModelId();\n\tif (!model || !modelId) { return e404(ctx); }\n\tconst updatePermissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, 'update');\n\tif (updatePermissions && !updatePermissions.length) { return e404(ctx); }\n\tconst document = await useDocument();\n\tif (!document) { return e404(ctx); }\n\tconst data = await useBody();\n\tif (!data) { return; }\n\tconst newValue = data.document;\n\tif (!newValue) { return; }\n\tconst newData = updatePermissions\n\t\t? await filterPermissionUpdate(model, updatePermissions, document, newValue)\n\t\t: newValue;\n\tconst result = Object.keys(newData).length\n\t\t? await useDatabase(model.databaseId).save(model, document, newData)\n\t\t: document;\n\tif (!result) { return {}; }\n\t// TODO: 更新附加文档\n\tconst readPermissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, 'read');\n\tif (!readPermissions) { return result || {}; }\n\tif (!readPermissions.length) { return {}; }\n\n\treturn await filterPermissionDocument(model, readPermissions, result);\n});\n\ndocumentRouter.delete(async ctx => {\n\tconst model = await useModel();\n\tconst modelId = await useModelId();\n\tif (!model || !modelId) { return e404(ctx); }\n\tconst permissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, 'read');\n\tif (permissions && !permissions.length) { return e404(ctx); }\n\tconst document = await useDocument();\n\tif (!document) { return e404(ctx); }\n\tif (permissions && !await testPermissions(permissions, document)) { return e404(ctx); }\n\tawait useDatabase(model.databaseId).destroy(model, document).then(Boolean);\n\t// TODO: 删除附加文档\n\tctx.status = 204;\n});\n\n\nconst fieldParam = new Param();\n\n// TODO: GET :field\n// TODO: POST :field\n// TODO: PUT :field\n// TODO: DELETE :field\nconst documentFieldsRouter = documentRouter.route`fields/${fieldParam}`();\ndocumentFieldsRouter.get(async ctx => {\n\tconst fieldName =fieldParam.param(ctx);\n\tif (!fieldName) { return e404(ctx); }\n\tconst model = await useModel();\n\tconst modelId = await useModelId();\n\tif (!model || !modelId) { return e404(ctx); }\n\tconst {fields} = model;\n\tif (!Object.hasOwn(fields, fieldName)) { return e404(ctx); }\n\tconst field = fields[fieldName];\n\tif (!field) { return e404(ctx) }\n\tconst readPermissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, 'read');\n\tif (readPermissions && !readPermissions.length) { return e404(ctx); }\n\tif (readPermissions) {\n\t\tconst group = field.group;\n\t\tif (!readPermissions.find(v => {\n\t\t\tconst field = v.fields;\n\t\t\tif (field === fieldName || field === '*' || Array.isArray(field) && (field.includes(fieldName) || field.includes('*'))) {return true; }\n\t\t\tif (!group || v.group) { return false; }\n\t\t\tif (v.group === group || Array.isArray(v.group) && v.group.includes(group)) {return true; }\n\t\t})) { return e404(ctx); }\n\t}\n\tconst document = await useDocument();\n\tif (!document) { return e404(ctx); }\n\tif (!readPermissions) { return { document: { ...await document.toJSON?.() || document } }; }\n\tconst doc = await filterPermissionDocument(model, readPermissions, document);\n\tif (!doc) { return e404(ctx); }\n\tif (!Object.hasOwn(doc, fieldName)) { return e404(ctx); }\n\treturn { value: doc[fieldName] };\n\n})\n\n// TODO: GET :value\n// TODO: POST :value\n// TODO: PUT :value\n// TODO: DELETE :field\nconst documentValuesRouter = documentRouter.route`values`();\n\n// TODO: GET :dataset/records\n// TODO: POST :dataset/records\n// TODO: GET :dataset/records/:record\n// TODO: PUT :dataset/records/:record\n// TODO: DELETE :dataset/records/:record\nconst documentDatasetsRouter = documentRouter.route`datasets`();\n\n\n\n\nexport default documentRouter;\n","import { useBody } from '@yongdall/http';\nimport { Search, yieldPermissionConstraintFields } from '@yongdall/common';\nimport { Query } from '@yongdall/model';\nimport { ApiRouter } from '@yongdall/http';\nimport useDocument, { documentId } from './useDocument.mjs';\nimport { useDatabase } from '@yongdall/connection';\nimport useModel, { useModelId } from './useModel.mjs';\nimport { createPermissionMatches, getModelAuthorizationPermissions, filterPermissionDocument, isSingleUser, search2where } from '@yongdall/core';\nimport { e404 } from '@yongdall/http';\nimport { loadDocumentsLabel } from '../utils.mjs';\n\n\n\n\nconst optionsRouter = new ApiRouter();\n\n\n\noptionsRouter.get(async function (ctx) {\n\tconst model = await useModel();\n\tconst modelId = await useModelId();\n\tif (!model || !modelId) { return e404(ctx); }\n\tconst permissions = await isSingleUser() ? null : await getModelAuthorizationPermissions(modelId, 'options');\n\tif (permissions && !permissions.length) { return e404(ctx); }\n\tconst { sort, offset, limit, select, where, orWhere, or } = Search.merge(\n\t\tSearch.parse(ctx.url.search.slice(1)),\n\t\tawait useBody() || {},\n\t);\n\n\tconst permissionMatches = permissions && await createPermissionMatches(permissions) || null;\n\n\tlet modelQuery = new Query(model, true).offset(offset).limit(limit);\n\tif (permissionMatches) {\n\t\tmodelQuery = modelQuery.where(permissionMatches);\n\t}\n\tconst searchWhere = await search2where(model.fields, where, orWhere, or);\n\tif (searchWhere) { modelQuery = modelQuery.where(searchWhere); }\n\n\tmodelQuery = modelQuery.sort();\n\tif (sort) { modelQuery = modelQuery.sort(...sort); }\n\tmodelQuery = modelQuery.select([...new Set([\n\t\tselect || [],\n\t\tObject.entries(model.fields).filter(([, { type }]) => type && typeof type === 'string').map(v => v[0]),\n\t\tpermissionMatches && permissions?.flatMap(v => [...yieldPermissionConstraintFields(v)]) || [],\n\t].flat())]);\n\n\tconst documents = await useDatabase(model.databaseId).transaction(t => t.select(modelQuery));\n\n\tconst options = permissions ? await Promise.all(documents.map(v => filterPermissionDocument(model, permissions, v))) : documents;\n\tawait loadDocumentsLabel(options, model);\n\treturn { options };\n});\n\n\noptionsRouter.get`${documentId}`(async ctx => {\n\tconst model = await useModel();\n\tconst modelId = await useModelId();\n\tif (!model || !modelId) { return e404(ctx); }\n\tconst permissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, 'options');\n\tif (permissions && !permissions.length) { return e404(ctx); }\n\tconst document = await useDocument();\n\tif (!document) { return e404(ctx); }\n\tif (!permissions) { return { document: { ...await document.toJSON?.() || document } }; }\n\tconst option = await filterPermissionDocument(model, permissions, document);\n\tif (!option) { return e404(ctx); }\n\treturn { option };\n});\n\nexport default optionsRouter;\n","import documentsRouter from './model.documents.mjs';\n\nimport modelsRouter from './models.mjs';\nimport documentRouter from './model.document.mjs';\nimport optionsRouter from './model.options.mjs';\n\nexport const api = {\n\tmodels: modelsRouter,\n}\nexport const modelApi = {\n\tdocuments: documentsRouter,\n\toptions: optionsRouter,\n}\nexport const documentApi = {\n\t'': documentRouter,\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Query } from "@yongdall/model";
|
|
2
|
+
import { Param, k99Context } from "@yongdall/http";
|
|
3
|
+
import { createStore } from "@yongdall/context";
|
|
4
|
+
import { useDatabase } from "@yongdall/connection";
|
|
5
|
+
import { getModel } from "@yongdall/core";
|
|
6
|
+
|
|
7
|
+
//#region api/api-model/routers/useModel.mjs
|
|
8
|
+
/** @import { ModelTable } from '@yongdall/model' */
|
|
9
|
+
const modelId = new Param();
|
|
10
|
+
const [getter$1, setter$1] = createStore(null);
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @returns {Promise<[ModelTable, string]?>}
|
|
14
|
+
*/
|
|
15
|
+
async function loadModel() {
|
|
16
|
+
const ctx = k99Context();
|
|
17
|
+
if (!ctx) return null;
|
|
18
|
+
const modelName = modelId.param(ctx) || "";
|
|
19
|
+
if (!modelName) return null;
|
|
20
|
+
const model = await getModel(modelName);
|
|
21
|
+
if (!model) return null;
|
|
22
|
+
return [model, modelName];
|
|
23
|
+
}
|
|
24
|
+
function useModel() {
|
|
25
|
+
let s = getter$1();
|
|
26
|
+
if (!s) {
|
|
27
|
+
s = loadModel();
|
|
28
|
+
setter$1(s);
|
|
29
|
+
}
|
|
30
|
+
return s.then((v) => v?.[0] || null);
|
|
31
|
+
}
|
|
32
|
+
function useModelId() {
|
|
33
|
+
let s = getter$1();
|
|
34
|
+
if (!s) {
|
|
35
|
+
s = loadModel();
|
|
36
|
+
setter$1(s);
|
|
37
|
+
}
|
|
38
|
+
return s.then((v) => v?.[1] || null);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region api/api-model/routers/useDocument.mjs
|
|
43
|
+
const documentId = new Param();
|
|
44
|
+
const [getter, setter] = createStore(null);
|
|
45
|
+
/**
|
|
46
|
+
*
|
|
47
|
+
* @returns {Promise<Record<String, any>?>}
|
|
48
|
+
*/
|
|
49
|
+
async function loadDocument() {
|
|
50
|
+
const model = await useModel();
|
|
51
|
+
if (!model) return null;
|
|
52
|
+
const ctx = k99Context();
|
|
53
|
+
if (!ctx) return null;
|
|
54
|
+
const name = decodeURIComponent(documentId.param(ctx) || "");
|
|
55
|
+
return await useDatabase(model.databaseId).first(new Query(model, true).primary(name));
|
|
56
|
+
}
|
|
57
|
+
function useDocument() {
|
|
58
|
+
let s = getter();
|
|
59
|
+
if (!s) {
|
|
60
|
+
s = loadDocument();
|
|
61
|
+
setter(s);
|
|
62
|
+
}
|
|
63
|
+
return s;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
//#endregion
|
|
67
|
+
export { useModelId as a, useModel as i, useDocument as n, modelId as r, documentId as t };
|
|
68
|
+
//# sourceMappingURL=useDocument-Bsmiy9SB.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDocument-Bsmiy9SB.mjs","names":["getter","setter"],"sources":["../../api/api-model/routers/useModel.mjs","../../api/api-model/routers/useDocument.mjs"],"sourcesContent":["import { k99Context } from '@yongdall/http';\nimport { createStore } from '@yongdall/context';\n/** @import { ModelTable } from '@yongdall/model' */\nimport { getModel } from '@yongdall/core';\nimport { Param } from '@yongdall/http';\n\n\nexport const modelId = new Param();\nconst [getter, setter] = createStore(/** @type {Promise<[ModelTable, string]?>?} */(null));\n\n/**\n * \n * @returns {Promise<[ModelTable, string]?>}\n */\nasync function loadModel() {\n\tconst ctx = k99Context();\n\tif (!ctx) { return null}\n\tconst modelName = modelId.param(ctx) || '';\n\tif (!modelName) { return null}\n\n\tconst model = await getModel(modelName);\n\tif (!model) { return null; }\n\treturn [model, modelName];\n\n}\nexport default function useModel() {\n\tlet s = getter();\n\tif (!s) {\n\t\ts = loadModel()\n\t\tsetter(s);\n\t}\n\treturn s.then(v => v?.[0] || null);\n}\nexport function useModelId() {\n\tlet s = getter();\n\tif (!s) {\n\t\ts = loadModel()\n\t\tsetter(s);\n\t}\n\treturn s.then(v => v?.[1] || null);\n}\n","import { createStore } from '@yongdall/context';\nimport { k99Context } from '@yongdall/http';\nimport { Query } from '@yongdall/model';\nimport { useDatabase } from '@yongdall/connection';\nimport useModel from './useModel.mjs';\nimport { Param } from '@yongdall/http';\n\n\nexport const documentId = new Param();\nconst [getter, setter] = createStore(/** @type {Promise<Record<String, any>?>?} */(null));\n\n\n/**\n * \n * @returns {Promise<Record<String, any>?>}\n */\nasync function loadDocument() {\n\tconst model = await useModel();\n\tif (!model) { return null; }\n\tconst ctx = k99Context();\n\tif (!ctx) { return null}\n\tconst name = decodeURIComponent(documentId.param(ctx) || '');\n\tconst doc = await useDatabase(model.databaseId).first(new Query(model, true).primary(name));\n\treturn doc;\n}\n\nexport default function useDocument() {\n\tlet s = getter();\n\tif (!s) {\n\t\ts = loadDocument()\n\t\tsetter(s);\n\t}\n\treturn s;\n}\n"],"mappings":";;;;;;;;AAOA,MAAa,UAAU,IAAI,OAAO;AAClC,MAAM,CAACA,UAAQC,YAAU,YAA2D,KAAM;;;;;AAM1F,eAAe,YAAY;CAC1B,MAAM,MAAM,YAAY;AACxB,KAAI,CAAC,IAAO,QAAO;CACnB,MAAM,YAAY,QAAQ,MAAM,IAAI,IAAI;AACxC,KAAI,CAAC,UAAa,QAAO;CAEzB,MAAM,QAAQ,MAAM,SAAS,UAAU;AACvC,KAAI,CAAC,MAAS,QAAO;AACrB,QAAO,CAAC,OAAO,UAAU;;AAG1B,SAAwB,WAAW;CAClC,IAAI,IAAID,UAAQ;AAChB,KAAI,CAAC,GAAG;AACP,MAAI,WAAW;AACf,WAAO,EAAE;;AAEV,QAAO,EAAE,MAAK,MAAK,IAAI,MAAM,KAAK;;AAEnC,SAAgB,aAAa;CAC5B,IAAI,IAAIA,UAAQ;AAChB,KAAI,CAAC,GAAG;AACP,MAAI,WAAW;AACf,WAAO,EAAE;;AAEV,QAAO,EAAE,MAAK,MAAK,IAAI,MAAM,KAAK;;;;;AC/BnC,MAAa,aAAa,IAAI,OAAO;AACrC,MAAM,CAAC,QAAQ,UAAU,YAA0D,KAAM;;;;;AAOzF,eAAe,eAAe;CAC7B,MAAM,QAAQ,MAAM,UAAU;AAC9B,KAAI,CAAC,MAAS,QAAO;CACrB,MAAM,MAAM,YAAY;AACxB,KAAI,CAAC,IAAO,QAAO;CACnB,MAAM,OAAO,mBAAmB,WAAW,MAAM,IAAI,IAAI,GAAG;AAE5D,QADY,MAAM,YAAY,MAAM,WAAW,CAAC,MAAM,IAAI,MAAM,OAAO,KAAK,CAAC,QAAQ,KAAK,CAAC;;AAI5F,SAAwB,cAAc;CACrC,IAAI,IAAI,QAAQ;AAChB,KAAI,CAAC,GAAG;AACP,MAAI,cAAc;AAClB,SAAO,EAAE;;AAEV,QAAO"}
|