@yongdall/api-model 0.1.2 → 0.2.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/package.json CHANGED
@@ -5,20 +5,20 @@
5
5
  "exports": {
6
6
  ".": "./index.mjs"
7
7
  },
8
- "version": "0.1.2",
8
+ "version": "0.2.0",
9
9
  "description": "",
10
10
  "keywords": [],
11
11
  "author": "",
12
12
  "license": "ISC",
13
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"
14
+ "@yongdall/common": "^0.2.0",
15
+ "@yongdall/context": "^0.2.0",
16
+ "@yongdall/core": "^0.2.0",
17
+ "@yongdall/model": "^0.2.0",
18
+ "@yongdall/connection": "^0.2.0",
19
+ "@yongdall/http": "^0.2.0"
20
20
  },
21
21
  "devDependencies": {
22
- "@yongdall/types": "^0.1.0"
22
+ "@yongdall/types": "^0.2.0"
23
23
  }
24
24
  }
@@ -3,7 +3,7 @@ import { Search, getPatternFields, runPattern, yieldPermissionConstraintFields }
3
3
  import { Query, Where, getLabelPattern, getModelOptions } from "@yongdall/model";
4
4
  import { ApiRouter, Param, e404, enumRouter, useBody } from "@yongdall/http";
5
5
  import { useDatabase } from "@yongdall/connection";
6
- import { createPermissionMatches, filterPermissionDocument, filterPermissionUpdate, getModel, getModelAuthorizationPermissions, isSingleUser, search2where, testPermissions, toDocumentFields } from "@yongdall/core";
6
+ import { createPermissionMatches, filterPermissionDocument, filterPermissionUpdate, getModel, getModelAuthorizationPermissions, search2where, testPermissions, toDocumentFields } from "@yongdall/core";
7
7
 
8
8
  //#region api/api-model/utils.mjs
9
9
  /** @import { ModelTable, TableDefine } from '@yongdall/model'*/
@@ -50,13 +50,13 @@ async function loadDocumentLabel(list, model, databaseId) {
50
50
  }
51
51
  /**
52
52
  *
53
- * @param {any[]} list
53
+ * @param {(Record<string, any> | null)[]} list
54
54
  * @param {ModelTable} model
55
55
  */
56
56
  async function loadDocumentsLabel(list, model) {
57
57
  /** @type {[model: string, id: any, data: Record<string, any>, field: string][]} */
58
58
  const setList = [];
59
- /** @type {[model: ModelTable, list: any[]][]} */
59
+ /** @type {[model: ModelTable, list: (Record<string, any> | null)[]][]} */
60
60
  const queue = [[model, list]];
61
61
  for (let line = queue.shift(); line; line = queue.shift()) {
62
62
  const [model, list] = line;
@@ -64,12 +64,13 @@ async function loadDocumentsLabel(list, model) {
64
64
  const type = field.type;
65
65
  if (!type) continue;
66
66
  if (typeof type === "object") {
67
- queue.push([type, list.flatMap((v) => v[name] || [])]);
67
+ queue.push([type, list.flatMap((v) => v?.[name] || [])]);
68
68
  continue;
69
69
  }
70
70
  const modelName = field.model;
71
71
  if (!modelName) continue;
72
72
  for (const item of list) {
73
+ if (!item) continue;
73
74
  const id = item[name];
74
75
  if (!id) continue;
75
76
  setList.push([
@@ -96,10 +97,10 @@ documentsRouter.get(async function(ctx) {
96
97
  const model = await useModel();
97
98
  const modelId = await useModelId();
98
99
  if (!model || !modelId) return e404(ctx);
99
- const permissions = await isSingleUser() ? null : await getModelAuthorizationPermissions(modelId, "query");
100
- if (permissions && !permissions.length) return e404(ctx);
101
- const { sort, offset, limit, select, where, orWhere, or } = Search.merge(Search.parse(ctx.url.search.slice(1)), await useBody() || {});
102
- const permissionMatches = permissions && await createPermissionMatches(permissions) || null;
100
+ const permissions = await getModelAuthorizationPermissions(modelId, "query");
101
+ if (!permissions?.length) return e404(ctx);
102
+ const { sort, offset, limit, select, where, orWhere, or, total: hasTotal } = Search.merge(Search.parse(ctx.url.search.slice(1)), await useBody() || {});
103
+ const permissionMatches = await createPermissionMatches(permissions);
103
104
  let modelQuery = new Query(model, true).offset(offset).limit(limit);
104
105
  if (permissionMatches) modelQuery = modelQuery.where(permissionMatches);
105
106
  const searchWhere = await search2where(model.fields, where, orWhere, or);
@@ -109,10 +110,10 @@ documentsRouter.get(async function(ctx) {
109
110
  const allFields = [
110
111
  select || [],
111
112
  Object.entries(model.fields).filter((v) => v[1].primary).map((v) => v[0]),
112
- permissionMatches && permissions?.flatMap((v) => [...yieldPermissionConstraintFields(v)]) || []
113
+ permissionMatches && permissions.flatMap((v) => [...yieldPermissionConstraintFields(v)]) || []
113
114
  ].flat();
114
- const [result, total] = await useDatabase(model.databaseId).transaction((t) => Promise.all([t.search(modelQuery, allFields), t.count(modelQuery)]));
115
- const documents = permissions ? await Promise.all(result.map((v) => filterPermissionDocument(model, permissions, v))) : result;
115
+ const [result, total] = await useDatabase(model.databaseId).transaction((t) => Promise.all([t.search(modelQuery, allFields), hasTotal ? t.count(modelQuery) : -1]));
116
+ const documents = await Promise.all(result.map((v) => filterPermissionDocument(model, permissions, v)));
116
117
  await loadDocumentsLabel(documents, model);
117
118
  return {
118
119
  documents,
@@ -123,11 +124,11 @@ documentsRouter.post(async (ctx) => {
123
124
  const model = await useModel();
124
125
  const modelId = await useModelId();
125
126
  if (!model || !modelId) return e404(ctx);
126
- const permissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, "create");
127
- if (permissions && !permissions.length) return e404(ctx);
127
+ const permissions = await getModelAuthorizationPermissions(modelId, "create");
128
+ if (!permissions?.length) return e404(ctx);
128
129
  const newDocument = (await useBody() || {}).document;
129
130
  if (!newDocument) return e404(ctx);
130
- const document = permissions ? await filterPermissionDocument(model, permissions, newDocument) : newDocument;
131
+ const document = await filterPermissionDocument(model, permissions, newDocument);
131
132
  if (!document) return e404(ctx);
132
133
  return await useDatabase(model.databaseId).create(model, document);
133
134
  });
@@ -148,7 +149,7 @@ async function loadPermissions() {
148
149
  }
149
150
  modelRouter.get(async function getDefine(ctx) {
150
151
  const model = await useModel();
151
- if (!model) return e404(ctx);
152
+ if (!model) return null;
152
153
  return {
153
154
  ...getModelOptions(model),
154
155
  id: await useModelId() || "",
@@ -166,11 +167,10 @@ documentRouter.get(async (ctx) => {
166
167
  const model = await useModel();
167
168
  const modelId = await useModelId();
168
169
  if (!model || !modelId) return e404(ctx);
169
- const readPermissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, "read");
170
- if (readPermissions && !readPermissions.length) return e404(ctx);
170
+ const readPermissions = await getModelAuthorizationPermissions(modelId, "read");
171
+ if (!readPermissions?.length) return e404(ctx);
171
172
  const document = await useDocument();
172
173
  if (!document) return e404(ctx);
173
- if (!readPermissions) return { document: { ...await document.toJSON?.() || document } };
174
174
  const doc = await filterPermissionDocument(model, readPermissions, document);
175
175
  if (!doc) return e404(ctx);
176
176
  return { document: doc };
@@ -179,31 +179,30 @@ documentRouter.put(async (ctx) => {
179
179
  const model = await useModel();
180
180
  const modelId = await useModelId();
181
181
  if (!model || !modelId) return e404(ctx);
182
- const updatePermissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, "update");
183
- if (updatePermissions && !updatePermissions.length) return e404(ctx);
182
+ const updatePermissions = await getModelAuthorizationPermissions(modelId, "update");
183
+ if (!updatePermissions?.length) return e404(ctx);
184
184
  const document = await useDocument();
185
185
  if (!document) return e404(ctx);
186
186
  const data = await useBody();
187
187
  if (!data) return;
188
188
  const newValue = data.document;
189
189
  if (!newValue) return;
190
- const newData = updatePermissions ? await filterPermissionUpdate(model, updatePermissions, document, newValue) : newValue;
191
- const result = Object.keys(newData).length ? await useDatabase(model.databaseId).save(model, document, newData) : document;
190
+ const newData = await filterPermissionUpdate(model, updatePermissions, document, newValue);
191
+ const result = newData && Object.keys(newData).length ? await useDatabase(model.databaseId).save(model, document, newData) : document;
192
192
  if (!result) return {};
193
- const readPermissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, "read");
194
- if (!readPermissions) return result || {};
195
- if (!readPermissions.length) return {};
193
+ const readPermissions = await getModelAuthorizationPermissions(modelId, "read");
194
+ if (!readPermissions?.length) return {};
196
195
  return await filterPermissionDocument(model, readPermissions, result);
197
196
  });
198
197
  documentRouter.delete(async (ctx) => {
199
198
  const model = await useModel();
200
199
  const modelId = await useModelId();
201
200
  if (!model || !modelId) return e404(ctx);
202
- const permissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, "read");
203
- if (permissions && !permissions.length) return e404(ctx);
201
+ const permissions = await getModelAuthorizationPermissions(modelId, "read");
202
+ if (!permissions?.length) return e404(ctx);
204
203
  const document = await useDocument();
205
204
  if (!document) return e404(ctx);
206
- if (permissions && !await testPermissions(permissions, document)) return e404(ctx);
205
+ if (!await testPermissions(permissions, document)) return e404(ctx);
207
206
  await useDatabase(model.databaseId).destroy(model, document).then(Boolean);
208
207
  ctx.status = 204;
209
208
  });
@@ -218,8 +217,8 @@ documentRouter.route`fields/${fieldParam}`().get(async (ctx) => {
218
217
  if (!Object.hasOwn(fields, fieldName)) return e404(ctx);
219
218
  const field = fields[fieldName];
220
219
  if (!field) return e404(ctx);
221
- const readPermissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, "read");
222
- if (readPermissions && !readPermissions.length) return e404(ctx);
220
+ const readPermissions = await getModelAuthorizationPermissions(modelId, "read");
221
+ if (!readPermissions?.length) return e404(ctx);
223
222
  if (readPermissions) {
224
223
  const group = field.group;
225
224
  if (!readPermissions.find((v) => {
@@ -231,7 +230,6 @@ documentRouter.route`fields/${fieldParam}`().get(async (ctx) => {
231
230
  }
232
231
  const document = await useDocument();
233
232
  if (!document) return e404(ctx);
234
- if (!readPermissions) return { document: { ...await document.toJSON?.() || document } };
235
233
  const doc = await filterPermissionDocument(model, readPermissions, document);
236
234
  if (!doc) return e404(ctx);
237
235
  if (!Object.hasOwn(doc, fieldName)) return e404(ctx);
@@ -248,10 +246,10 @@ optionsRouter.get(async function(ctx) {
248
246
  const model = await useModel();
249
247
  const modelId = await useModelId();
250
248
  if (!model || !modelId) return e404(ctx);
251
- const permissions = await isSingleUser() ? null : await getModelAuthorizationPermissions(modelId, "options");
252
- if (permissions && !permissions.length) return e404(ctx);
249
+ const permissions = await getModelAuthorizationPermissions(modelId, "options");
250
+ if (!permissions?.length) return e404(ctx);
253
251
  const { sort, offset, limit, select, where, orWhere, or } = Search.merge(Search.parse(ctx.url.search.slice(1)), await useBody() || {});
254
- const permissionMatches = permissions && await createPermissionMatches(permissions) || null;
252
+ const permissionMatches = await createPermissionMatches(permissions);
255
253
  let modelQuery = new Query(model, true).offset(offset).limit(limit);
256
254
  if (permissionMatches) modelQuery = modelQuery.where(permissionMatches);
257
255
  const searchWhere = await search2where(model.fields, where, orWhere, or);
@@ -261,10 +259,10 @@ optionsRouter.get(async function(ctx) {
261
259
  modelQuery = modelQuery.select([...new Set([
262
260
  select || [],
263
261
  Object.entries(model.fields).filter(([, { type }]) => type && typeof type === "string").map((v) => v[0]),
264
- permissionMatches && permissions?.flatMap((v) => [...yieldPermissionConstraintFields(v)]) || []
262
+ permissionMatches && permissions.flatMap((v) => [...yieldPermissionConstraintFields(v)]) || []
265
263
  ].flat())]);
266
264
  const documents = await useDatabase(model.databaseId).transaction((t) => t.select(modelQuery));
267
- const options = permissions ? await Promise.all(documents.map((v) => filterPermissionDocument(model, permissions, v))) : documents;
265
+ const options = await Promise.all(documents.map((v) => filterPermissionDocument(model, permissions, v)));
268
266
  await loadDocumentsLabel(options, model);
269
267
  return { options };
270
268
  });
@@ -272,11 +270,10 @@ optionsRouter.get`${documentId}`(async (ctx) => {
272
270
  const model = await useModel();
273
271
  const modelId = await useModelId();
274
272
  if (!model || !modelId) return e404(ctx);
275
- const permissions = !await isSingleUser() && await getModelAuthorizationPermissions(modelId, "options");
276
- if (permissions && !permissions.length) return e404(ctx);
273
+ const permissions = await getModelAuthorizationPermissions(modelId, "options");
274
+ if (!permissions?.length) return e404(ctx);
277
275
  const document = await useDocument();
278
276
  if (!document) return e404(ctx);
279
- if (!permissions) return { option: { ...await document.toJSON?.() || document } };
280
277
  const option = await filterPermissionDocument(model, permissions, document);
281
278
  if (!option) return e404(ctx);
282
279
  return { option };
@@ -1 +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} 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 { option: { ...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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"}
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} 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 {(Record<string, any> | null)[]} 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: (Record<string, any> | null)[]][]} */\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\tif (!item) { continue; }\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, 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 getModelAuthorizationPermissions(modelId, 'query');\n\tif (!permissions?.length) { return e404(ctx); }\n\tconst { sort, offset, limit, select, where, orWhere, or, total: hasTotal } = Search.merge(\n\t\tSearch.parse(ctx.url.search.slice(1)),\n\t\tawait useBody() || {},\n\t);\n\n\tconst permissionMatches = await createPermissionMatches(permissions);\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([\n\t\tt.search(modelQuery, allFields),\n\t\thasTotal ? t.count(modelQuery) : -1,\n\t]));\n\n\tconst documents = await Promise.all(result.map(v => filterPermissionDocument(model, permissions, v)));\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 getModelAuthorizationPermissions(modelId, 'create');\n\tif (!permissions?.length) { return e404(ctx); }\n\tconst data = await useBody() || {};\n\tconst newDocument = data.document;\n\tif (!newDocument) { return e404(ctx); }\n\tconst document = await filterPermissionDocument(model, permissions, 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 null; }\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';\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 getModelAuthorizationPermissions(modelId, 'read');\n\tif (!readPermissions?.length) { return e404(ctx); }\n\tconst document = await useDocument();\n\tif (!document) { return e404(ctx); }\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 getModelAuthorizationPermissions(modelId, 'update');\n\tif (!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 = await filterPermissionUpdate(model, updatePermissions, document, newValue);\n\tconst result = newData && Object.keys(newData).length\n\t\t? await useDatabase(model.databaseId).save(model, document, newData)\n\t\t: document;\n\tif (!result) { return {}; }\n\tconst readPermissions = await getModelAuthorizationPermissions(modelId, 'read');\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 getModelAuthorizationPermissions(modelId, 'read');\n\tif (!permissions?.length) { return e404(ctx); }\n\tconst document = await useDocument();\n\tif (!document) { return e404(ctx); }\n\tif (!await testPermissions(permissions, document)) { return e404(ctx); }\n\tawait useDatabase(model.databaseId).destroy(model, document).then(Boolean);\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 getModelAuthorizationPermissions(modelId, 'read');\n\tif (!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\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, 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 getModelAuthorizationPermissions(modelId, 'options');\n\tif (!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 = await createPermissionMatches(permissions);\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 = await Promise.all(documents.map(v => filterPermissionDocument(model, permissions, v)));\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 getModelAuthorizationPermissions(modelId, 'options');\n\tif (!permissions?.length) { return e404(ctx); }\n\tconst document = await useDocument();\n\tif (!document) { return e404(ctx); }\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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"}