velocious 1.0.451 → 1.0.453
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -5
- package/build/configuration-types.js +23 -0
- package/build/configuration.js +5 -5
- package/build/database/drivers/mssql/index.js +1 -1
- package/build/database/drivers/mysql/index.js +1 -1
- package/build/database/drivers/pgsql/index.js +1 -1
- package/build/database/drivers/sqlite/base.js +1 -1
- package/build/database/record/attachments/attachment-record.js +121 -0
- package/build/database/record/attachments/store.js +2 -0
- package/build/database/table-data/index.js +1 -1
- package/build/environment-handlers/node/cli/commands/generate/frontend-models.js +7 -2
- package/build/frontend-model-controller.js +302 -113
- package/build/frontend-model-resource/base-resource.js +2 -1
- package/build/frontend-model-resource/velocious-attachment-resource.js +221 -0
- package/build/frontend-models/base.js +127 -1
- package/build/frontend-models/built-in-resources.js +32 -0
- package/build/frontend-models/websocket-publishers.js +13 -3
- package/build/routes/hooks/frontend-model-command-route-hook.js +3 -2
- package/build/src/configuration-types.d.ts +56 -0
- package/build/src/configuration-types.d.ts.map +1 -1
- package/build/src/configuration-types.js +21 -1
- package/build/src/configuration.d.ts +9 -17
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +6 -6
- package/build/src/database/drivers/mssql/index.d.ts.map +1 -1
- package/build/src/database/drivers/mssql/index.js +2 -2
- package/build/src/database/drivers/mysql/index.d.ts.map +1 -1
- package/build/src/database/drivers/mysql/index.js +2 -2
- package/build/src/database/drivers/pgsql/index.d.ts.map +1 -1
- package/build/src/database/drivers/pgsql/index.js +2 -2
- package/build/src/database/drivers/sqlite/base.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/base.js +2 -2
- package/build/src/database/record/attachments/attachment-record.d.ts +67 -0
- package/build/src/database/record/attachments/attachment-record.d.ts.map +1 -0
- package/build/src/database/record/attachments/attachment-record.js +106 -0
- package/build/src/database/record/attachments/store.d.ts.map +1 -1
- package/build/src/database/record/attachments/store.js +2 -1
- package/build/src/database/table-data/index.js +2 -2
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.js +7 -3
- package/build/src/frontend-model-controller.d.ts +82 -9
- package/build/src/frontend-model-controller.d.ts.map +1 -1
- package/build/src/frontend-model-controller.js +270 -112
- package/build/src/frontend-model-resource/base-resource.d.ts +2 -0
- package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
- package/build/src/frontend-model-resource/base-resource.js +3 -2
- package/build/src/frontend-model-resource/velocious-attachment-resource.d.ts +105 -0
- package/build/src/frontend-model-resource/velocious-attachment-resource.d.ts.map +1 -0
- package/build/src/frontend-model-resource/velocious-attachment-resource.js +185 -0
- package/build/src/frontend-models/base.d.ts +87 -1
- package/build/src/frontend-models/base.d.ts.map +1 -1
- package/build/src/frontend-models/base.js +112 -2
- package/build/src/frontend-models/built-in-resources.d.ts +18 -0
- package/build/src/frontend-models/built-in-resources.d.ts.map +1 -0
- package/build/src/frontend-models/built-in-resources.js +29 -0
- package/build/src/frontend-models/websocket-publishers.d.ts.map +1 -1
- package/build/src/frontend-models/websocket-publishers.js +14 -4
- package/build/src/routes/hooks/frontend-model-command-route-hook.d.ts.map +1 -1
- package/build/src/routes/hooks/frontend-model-command-route-hook.js +4 -3
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/configuration-types.js +23 -0
- package/src/configuration.js +5 -5
- package/src/database/drivers/mssql/index.js +1 -1
- package/src/database/drivers/mysql/index.js +1 -1
- package/src/database/drivers/pgsql/index.js +1 -1
- package/src/database/drivers/sqlite/base.js +1 -1
- package/src/database/record/attachments/attachment-record.js +121 -0
- package/src/database/record/attachments/store.js +2 -0
- package/src/database/table-data/index.js +1 -1
- package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +7 -2
- package/src/frontend-model-controller.js +302 -113
- package/src/frontend-model-resource/base-resource.js +2 -1
- package/src/frontend-model-resource/velocious-attachment-resource.js +221 -0
- package/src/frontend-models/base.js +127 -1
- package/src/frontend-models/built-in-resources.js +32 -0
- package/src/frontend-models/websocket-publishers.js +13 -3
- package/src/routes/hooks/frontend-model-command-route-hook.js +3 -2
package/README.md
CHANGED
|
@@ -447,6 +447,7 @@ Frontend-model `where(...)` supports nested relationship descriptors (for exampl
|
|
|
447
447
|
Frontend-model `joins(...)` supports relationship-object descriptors only (for example `Task.joins({project: {creatingUser: true}})`) and rejects raw SQL join strings.
|
|
448
448
|
Frontend-model `distinct(...)` only accepts booleans (`true` by default) and is applied server-side through the backend query API.
|
|
449
449
|
Frontend-model `pluck(...)` validates attribute/path descriptors against configured model metadata and does not accept SQL fragments.
|
|
450
|
+
Frontend-model query fields are limited to attributes exposed by the backend resource. Use `{name: "attributeName", selectedByDefault: false}` for fields that may be selected or filtered explicitly but should stay out of default payloads.
|
|
450
451
|
|
|
451
452
|
When backend payloads include `__preloadedRelationships`, nested frontend-model relationships are hydrated recursively. Relationship methods can use `getRelationshipByName("relationship").loaded()` and will throw when a relationship was not preloaded.
|
|
452
453
|
|
|
@@ -546,11 +547,14 @@ For frontend models, configure `resourceConfig().attachments` and use:
|
|
|
546
547
|
await frontendTask.update({descriptionFile: file})
|
|
547
548
|
const descriptionFile = await frontendTask.descriptionFile().download()
|
|
548
549
|
const descriptionFileUrl = await frontendTask.descriptionFile().url()
|
|
550
|
+
const descriptionFileMetadata = await frontendTask.descriptionFile().first()
|
|
551
|
+
const filesMetadata = await frontendTask.files().toArray()
|
|
549
552
|
await frontendTask.attach(file)
|
|
550
553
|
```
|
|
551
554
|
|
|
552
555
|
Frontend model attachment input does not support `{path: ...}`.
|
|
553
556
|
Use `File`/`Blob`/bytes/`contentBase64` payloads instead.
|
|
557
|
+
Attachment metadata is exposed through the built-in `VelociousAttachment` frontend model with safe fields only: `id`, `recordType`, `recordId`, `name`, `position`, `filename`, `contentType`, `byteSize`, `createdAt`, and `updatedAt`. Storage internals such as `driver`, `storageKey`, and `contentBase64` remain hidden and non-queryable. Direct metadata queries require owner filters: `recordType`, `recordId`, and `name`.
|
|
554
558
|
|
|
555
559
|
When your frontend app calls a backend on another host/port (or under a path prefix), configure transport once:
|
|
556
560
|
|
|
@@ -583,7 +587,7 @@ const configuration = new Configuration({
|
|
|
583
587
|
|
|
584
588
|
This opt-in is ignored in `production`; production frontend-model responses never include internal exception details.
|
|
585
589
|
|
|
586
|
-
Backends can append client-safe metadata to frontend-model error responses with `configuration.addClientErrorPayloadReporter(...)`. Reporters receive the caught `error`, the current `request`, and a small `context` object, and should only return fields that are safe for clients to see. This is useful for attaching an error-reporting URL while keeping the normal production error message generic:
|
|
590
|
+
Backends can append client-safe metadata to frontend-model error responses with `configuration.addClientErrorPayloadReporter(...)`. Reporters receive the caught `error`, the current `request`, and a small `context` object, and should only return fields that are safe for clients to see. Frontend-model endpoint failures include `context.frontendModelEndpoint`, `action`, `commandType`, `model`, `requestId`, and `expectedError`. This is useful for attaching an error-reporting URL while keeping the normal production error message generic:
|
|
587
591
|
|
|
588
592
|
```js
|
|
589
593
|
configuration.addClientErrorPayloadReporter(async ({error, request, context}) => {
|
|
@@ -1002,6 +1006,8 @@ npx velocious g:migration create-tasks
|
|
|
1002
1006
|
```
|
|
1003
1007
|
|
|
1004
1008
|
## Write a migration
|
|
1009
|
+
Implicit `id` primary keys and `references(...)` columns use UUIDs by default. Use an explicit numeric `id` or reference `type` only for legacy schemas or external compatibility.
|
|
1010
|
+
|
|
1005
1011
|
```js
|
|
1006
1012
|
import Migration from "velocious/build/src/database/migration/index.js"
|
|
1007
1013
|
|
|
@@ -1011,9 +1017,9 @@ export default class CreateEvents extends Migration {
|
|
|
1011
1017
|
t.timestamps()
|
|
1012
1018
|
})
|
|
1013
1019
|
|
|
1014
|
-
//
|
|
1015
|
-
await this.createTable("
|
|
1016
|
-
t.
|
|
1020
|
+
// Legacy numeric primary key
|
|
1021
|
+
await this.createTable("legacy_events", {id: {type: "bigint"}}, (t) => {
|
|
1022
|
+
t.references("task", {type: "bigint"})
|
|
1017
1023
|
t.timestamps()
|
|
1018
1024
|
})
|
|
1019
1025
|
|
|
@@ -1597,7 +1603,7 @@ configuration.getErrorEvents().on("all-error", ({error, errorType}) => {
|
|
|
1597
1603
|
})
|
|
1598
1604
|
```
|
|
1599
1605
|
|
|
1600
|
-
Genuinely unexpected frontend-model command failures reach this bus too. The frontend-model controller catches them to return a client-safe `Request failed.` response, but it also emits them as `framework-error`/`all-error` (with `context.frontendModelEndpoint === true`) so they are reported instead of being silently swallowed. Expected user-flow errors are excluded: validation failures are forwarded with their real message (for example `Name can't be blank`) rather than the generic one, and `error.velocious`-annotated / `safeToExpose` errors keep their
|
|
1606
|
+
Genuinely unexpected frontend-model command failures reach this bus too. The frontend-model controller catches them to return a client-safe `Request failed.` response, but it also emits them as `framework-error`/`all-error` (with `context.frontendModelEndpoint === true`) so they are reported instead of being silently swallowed. Expected user-flow errors are excluded: validation failures are forwarded with their real message (for example `Name can't be blank`) rather than the generic one, and `error.velocious`-annotated / `safeToExpose` / `errorType`-marked errors keep their expected-error status — none of these reach the error bus.
|
|
1601
1607
|
|
|
1602
1608
|
## Use the Websocket client API (HTTP-like)
|
|
1603
1609
|
|
|
@@ -207,6 +207,29 @@
|
|
|
207
207
|
* @typedef {Record<string, string>} VelociousParams
|
|
208
208
|
*/
|
|
209
209
|
|
|
210
|
+
/**
|
|
211
|
+
* @typedef {Record<string, import("./frontend-models/query.js").FrontendModelTransportValue>} ClientErrorPayloadReporterPayload
|
|
212
|
+
*/
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* @typedef {object} ClientErrorPayloadContext
|
|
216
|
+
* @property {string} controller - Controller class name.
|
|
217
|
+
* @property {string} [action] - Controller action or endpoint label.
|
|
218
|
+
* @property {"index" | "find" | "create" | "update" | "destroy" | "attach" | "download" | "url" | "custom-command"} [commandType] - Frontend-model command type.
|
|
219
|
+
* @property {boolean} [expectedError] - Whether the error is an expected user-flow failure.
|
|
220
|
+
* @property {boolean} [frontendModelEndpoint] - Whether the error came from the frontend-model endpoint.
|
|
221
|
+
* @property {string} [model] - Frontend-model name from the failed request.
|
|
222
|
+
* @property {string} [requestId] - Shared frontend-model request id.
|
|
223
|
+
*/
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* @typedef {function({
|
|
227
|
+
* context: ClientErrorPayloadContext,
|
|
228
|
+
* error: Error,
|
|
229
|
+
* request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default | undefined
|
|
230
|
+
* }): Promise<ClientErrorPayloadReporterPayload | void> | ClientErrorPayloadReporterPayload | void} ClientErrorPayloadReporterType
|
|
231
|
+
*/
|
|
232
|
+
|
|
210
233
|
/**
|
|
211
234
|
* @typedef {Record<string, unknown> & {configuration?: import("./configuration.js").default, currentUser?: unknown, params?: VelociousParams, request?: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default}} VelociousLooseObject
|
|
212
235
|
*/
|
package/build/configuration.js
CHANGED
|
@@ -143,7 +143,7 @@ export default class VelociousConfiguration {
|
|
|
143
143
|
this._scheduledBackgroundJobs = scheduledBackgroundJobs
|
|
144
144
|
this._attachments = attachments || {}
|
|
145
145
|
this._backendProjects = backendProjects || []
|
|
146
|
-
/** @type {
|
|
146
|
+
/** @type {import("./configuration-types.js").ClientErrorPayloadReporterType[]} */
|
|
147
147
|
this._clientErrorPayloadReporters = []
|
|
148
148
|
this.cors = cors
|
|
149
149
|
this._cookieSecret = cookieSecret
|
|
@@ -2386,7 +2386,7 @@ export default class VelociousConfiguration {
|
|
|
2386
2386
|
|
|
2387
2387
|
/**
|
|
2388
2388
|
* Registers a reporter that can add client-safe metadata to frontend-model error payloads.
|
|
2389
|
-
* @param {(
|
|
2389
|
+
* @param {import("./configuration-types.js").ClientErrorPayloadReporterType} reporter - Reporter callback.
|
|
2390
2390
|
* @returns {void}
|
|
2391
2391
|
*/
|
|
2392
2392
|
addClientErrorPayloadReporter(reporter) {
|
|
@@ -2395,11 +2395,11 @@ export default class VelociousConfiguration {
|
|
|
2395
2395
|
|
|
2396
2396
|
/**
|
|
2397
2397
|
* Runs registered client error payload reporters.
|
|
2398
|
-
* @param {{context:
|
|
2399
|
-
* @returns {Promise<
|
|
2398
|
+
* @param {{context: import("./configuration-types.js").ClientErrorPayloadContext, error: Error, request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default | undefined}} args - Reporter args.
|
|
2399
|
+
* @returns {Promise<import("./configuration-types.js").ClientErrorPayloadReporterPayload>} - Merged client-safe reporter payload.
|
|
2400
2400
|
*/
|
|
2401
2401
|
async clientErrorPayloadForError(args) {
|
|
2402
|
-
/** @type {
|
|
2402
|
+
/** @type {import("./configuration-types.js").ClientErrorPayloadReporterPayload} */
|
|
2403
2403
|
const payload = {}
|
|
2404
2404
|
|
|
2405
2405
|
for (const reporter of this._clientErrorPayloadReporters) {
|
|
@@ -203,7 +203,7 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
203
203
|
* Runs primary key type.
|
|
204
204
|
* @returns {string} - The primary key type.
|
|
205
205
|
*/
|
|
206
|
-
primaryKeyType() { return "
|
|
206
|
+
primaryKeyType() { return "uuid" }
|
|
207
207
|
|
|
208
208
|
/**
|
|
209
209
|
* Runs query actual.
|
|
@@ -211,7 +211,7 @@ export default class VelociousDatabaseDriversMysql extends Base{
|
|
|
211
211
|
* Runs primary key type.
|
|
212
212
|
* @returns {string} - The primary key type.
|
|
213
213
|
*/
|
|
214
|
-
primaryKeyType() { return "
|
|
214
|
+
primaryKeyType() { return "uuid" }
|
|
215
215
|
|
|
216
216
|
/**
|
|
217
217
|
* Runs retryable database error.
|
|
@@ -269,7 +269,7 @@ export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
|
269
269
|
* Runs primary key type.
|
|
270
270
|
* @returns {string} - The type of the primary key for this driver.
|
|
271
271
|
*/
|
|
272
|
-
primaryKeyType() { return "
|
|
272
|
+
primaryKeyType() { return "uuid" }
|
|
273
273
|
|
|
274
274
|
/**
|
|
275
275
|
* Runs query to sql.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import DatabaseRecord from "../index.js"
|
|
4
|
+
import RecordAttachmentsStore from "./store.js"
|
|
5
|
+
|
|
6
|
+
const INTEGER_STRING_PATTERN = /^-?\d+$/
|
|
7
|
+
|
|
8
|
+
/** Frontend-readable metadata row for `velocious_attachments`. */
|
|
9
|
+
export default class VelociousAttachment extends DatabaseRecord {
|
|
10
|
+
/**
|
|
11
|
+
* Returns the backing attachment table name.
|
|
12
|
+
* @returns {string} - Backing attachment table name.
|
|
13
|
+
*/
|
|
14
|
+
static tableName() {
|
|
15
|
+
return "velocious_attachments"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Ensures the framework-owned attachment table exists before loading metadata.
|
|
20
|
+
* @param {object} args - Options object.
|
|
21
|
+
* @param {import("../../../configuration.js").default} args.configuration - Configuration instance.
|
|
22
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
23
|
+
*/
|
|
24
|
+
static async initializeRecord({configuration}) {
|
|
25
|
+
const store = new RecordAttachmentsStore({
|
|
26
|
+
configuration,
|
|
27
|
+
databaseIdentifier: this.getConfiguredDatabaseIdentifier()
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
await store.ensureReady()
|
|
31
|
+
await super.initializeRecord({configuration})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Returns the attachment id.
|
|
36
|
+
* @returns {string} - Attachment id.
|
|
37
|
+
*/
|
|
38
|
+
id() { return this.readAttribute("id") }
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns the owner model name.
|
|
42
|
+
* @returns {string} - Owner model name.
|
|
43
|
+
*/
|
|
44
|
+
recordType() { return this.readAttribute("recordType") }
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Returns the owner record id.
|
|
48
|
+
* @returns {string} - Owner record id.
|
|
49
|
+
*/
|
|
50
|
+
recordId() { return this.readAttribute("recordId") }
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Returns the attachment name on the owner model.
|
|
54
|
+
* @returns {string} - Attachment name on the owner model.
|
|
55
|
+
*/
|
|
56
|
+
name() { return this.readAttribute("name") }
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Returns the attachment position.
|
|
60
|
+
* @returns {number} - Attachment position.
|
|
61
|
+
*/
|
|
62
|
+
position() { return this.readAttribute("position") }
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Returns the attachment filename.
|
|
66
|
+
* @returns {string} - Attachment filename.
|
|
67
|
+
*/
|
|
68
|
+
filename() { return this.readAttribute("filename") }
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Returns the attachment content type.
|
|
72
|
+
* @returns {string | null} - Attachment content type.
|
|
73
|
+
*/
|
|
74
|
+
contentType() { return this.readAttribute("contentType") }
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Returns the attachment byte size.
|
|
78
|
+
* @returns {number} - Attachment byte size.
|
|
79
|
+
*/
|
|
80
|
+
byteSize() { return this.safeIntegerAttribute({attributeName: "byteSize", expectedDescription: "attachment byte size"}) }
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Returns the created-at timestamp in milliseconds.
|
|
84
|
+
* @returns {number} - Created-at timestamp in milliseconds.
|
|
85
|
+
*/
|
|
86
|
+
createdAtMs() { return this.safeIntegerAttribute({attributeName: "createdAtMs", expectedDescription: "safe millisecond timestamp"}) }
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Returns the updated-at timestamp in milliseconds.
|
|
90
|
+
* @returns {number} - Updated-at timestamp in milliseconds.
|
|
91
|
+
*/
|
|
92
|
+
updatedAtMs() { return this.safeIntegerAttribute({attributeName: "updatedAtMs", expectedDescription: "safe millisecond timestamp"}) }
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Returns a checked integer attribute value.
|
|
96
|
+
* @param {object} args - Options object.
|
|
97
|
+
* @param {"byteSize" | "createdAtMs" | "updatedAtMs"} args.attributeName - Integer attribute name.
|
|
98
|
+
* @param {string} args.expectedDescription - Description for error messages.
|
|
99
|
+
* @returns {number} - Safe integer value.
|
|
100
|
+
*/
|
|
101
|
+
safeIntegerAttribute({attributeName, expectedDescription}) {
|
|
102
|
+
const value = this.readAttribute(attributeName)
|
|
103
|
+
let integer
|
|
104
|
+
|
|
105
|
+
if (typeof value === "number") {
|
|
106
|
+
integer = value
|
|
107
|
+
} else if (typeof value === "bigint") {
|
|
108
|
+
integer = Number(value)
|
|
109
|
+
} else if (typeof value === "string" && INTEGER_STRING_PATTERN.test(value)) {
|
|
110
|
+
integer = Number(value)
|
|
111
|
+
} else {
|
|
112
|
+
throw new Error(`Expected ${attributeName} to be a ${expectedDescription}`)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!Number.isSafeInteger(integer)) {
|
|
116
|
+
throw new Error(`Expected ${attributeName} to be a ${expectedDescription}`)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return integer
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -98,6 +98,8 @@ export default class RecordAttachmentsStore {
|
|
|
98
98
|
|
|
99
99
|
this._readyPromise = (async () => {
|
|
100
100
|
await this._withDb(async (db) => {
|
|
101
|
+
db.clearSchemaCache()
|
|
102
|
+
|
|
101
103
|
if (await db.tableExists(ATTACHMENTS_TABLE)) {
|
|
102
104
|
await this.ensureAttachmentStoreSchema({db})
|
|
103
105
|
return
|
|
@@ -188,7 +188,7 @@ export default class TableData {
|
|
|
188
188
|
const referenceArgs = args || {}
|
|
189
189
|
const reference = new TableReference(name, referenceArgs)
|
|
190
190
|
const {index, polymorphic, ...restArgs} = referenceArgs
|
|
191
|
-
const columnArgs = Object.assign({isNewColumn: true, type: "
|
|
191
|
+
const columnArgs = Object.assign({isNewColumn: true, type: "uuid"}, restArgs)
|
|
192
192
|
const column = new TableColumn(columnName, columnArgs)
|
|
193
193
|
const indexArgs = typeof index == "object" ? {unique: index.unique === true} : undefined
|
|
194
194
|
const tableIndex = new TableIndex([column], indexArgs)
|
|
@@ -2,7 +2,8 @@ import BaseCommand from "../../../../../cli/base-command.js"
|
|
|
2
2
|
import fs from "fs/promises"
|
|
3
3
|
import path from "node:path"
|
|
4
4
|
import * as inflection from "inflection"
|
|
5
|
-
import {
|
|
5
|
+
import {frontendModelResourceIsBuiltIn, frontendModelResourcesWithBuiltInsForBackendProject} from "../../../../../frontend-models/built-in-resources.js"
|
|
6
|
+
import {frontendModelResourceClassFromDefinition, frontendModelResourceConfigurationFromDefinition} from "../../../../../frontend-models/resource-definition.js"
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Attribute metadata used for generated frontend-model JSDoc.
|
|
@@ -110,6 +111,10 @@ export default class DbGenerateFrontendModels extends BaseCommand {
|
|
|
110
111
|
this.validateModelConfig({availableFrontendModelClassNames, className, modelConfig, resourceClass})
|
|
111
112
|
|
|
112
113
|
if (generatedModelNames.has(className)) {
|
|
114
|
+
if (frontendModelResourceIsBuiltIn({modelName: modelClassName, resourceDefinition: resources[modelClassName]})) {
|
|
115
|
+
continue
|
|
116
|
+
}
|
|
117
|
+
|
|
113
118
|
throw new Error(`Duplicate frontend model definition for '${className}'`)
|
|
114
119
|
}
|
|
115
120
|
|
|
@@ -191,7 +196,7 @@ export default class DbGenerateFrontendModels extends BaseCommand {
|
|
|
191
196
|
* @returns {Record<string, import("../../../../../configuration-types.js").FrontendModelResourceDefinition>} - Resource definitions keyed by model class name.
|
|
192
197
|
*/
|
|
193
198
|
resourcesForBackendProject(backendProject) {
|
|
194
|
-
return
|
|
199
|
+
return frontendModelResourcesWithBuiltInsForBackendProject(backendProject)
|
|
195
200
|
}
|
|
196
201
|
|
|
197
202
|
/**
|