velocious 1.0.450 → 1.0.452

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 CHANGED
@@ -392,7 +392,7 @@ Generate classes:
392
392
  npx velocious g:frontend-models
393
393
  ```
394
394
 
395
- When `frontendModels.*.attributes` is an object, the generator can infer JSDoc typedefs from attribute metadata (`type`/`columnType`/`sqlType`/`dataType` and `null`). If metadata is absent, the generated attribute type falls back to `any`.
395
+ Frontend-model attributes can usually be declared by name. The generator infers JSDoc typedefs and nullability from backend model columns and translated attribute columns. When an attribute entry needs resource-specific options such as `selectedByDefault: false`, keep only that option in the resource config, for example `{name: "archivedAt", selectedByDefault: false}`; the column type and nullability are still inferred. For computed resource attributes, add a typed `${attributeName}Attribute(model)` method with an `@returns` tag in the backend project's `src` tree. Resource attribute return types take precedence over column types because the resource method controls the serialized value. If Velocious cannot infer a read attribute from a column, generated model accessor, resource method JSDoc, or explicit metadata, generation fails with a clear error instead of emitting a broad fallback type.
396
396
 
397
397
  This creates `src/frontend-models/user.js` (and one file per configured resource). Generated classes support:
398
398
 
@@ -583,7 +583,7 @@ const configuration = new Configuration({
583
583
 
584
584
  This opt-in is ignored in `production`; production frontend-model responses never include internal exception details.
585
585
 
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:
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. 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
587
 
588
588
  ```js
589
589
  configuration.addClientErrorPayloadReporter(async ({error, request, context}) => {
@@ -1597,7 +1597,7 @@ configuration.getErrorEvents().on("all-error", ({error, errorType}) => {
1597
1597
  })
1598
1598
  ```
1599
1599
 
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 own message — none of these reach the error bus.
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` / `errorType`-marked errors keep their expected-error status — none of these reach the error bus.
1601
1601
 
1602
1602
  ## Use the Websocket client API (HTTP-like)
1603
1603
 
@@ -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
  */
@@ -263,6 +286,8 @@
263
286
  * @property {string} [columnType] - Alias for column type name.
264
287
  * @property {string} [sqlType] - Alias for column type name.
265
288
  * @property {string} [dataType] - Alias for column type name.
289
+ * @property {string} [jsDocType] - Exact generated JSDoc type for non-column attributes.
290
+ * @property {string} [name] - Attribute name when configured as an array entry.
266
291
  * @property {boolean} [null] - Whether value can be null.
267
292
  * @property {boolean} [selectedByDefault] - Whether included in default serialization. Defaults to true.
268
293
  */
@@ -274,7 +299,7 @@
274
299
 
275
300
  /**
276
301
  * @typedef {object} FrontendModelResourceConfiguration
277
- * @property {string[] | Record<string, FrontendModelAttributeConfiguration | import("./database/drivers/base-column.js").default | boolean>} attributes - Attributes to expose on the frontend model.
302
+ * @property {Array<string | FrontendModelAttributeConfiguration> | Record<string, FrontendModelAttributeConfiguration | import("./database/drivers/base-column.js").default | boolean>} attributes - Attributes to expose on the frontend model.
278
303
  * @property {string[]} [abilities] - Ability action list (camelCase action names). Defaults to `["read"]` for `find` and `index` when omitted.
279
304
  * @property {Record<string, FrontendModelAttachmentConfiguration>} [attachments] - Attachment helpers keyed by attachment name.
280
305
  * @property {string[]} [commands] - Legacy built-in command names (`index`, `find`, `create`, `update`, `destroy`, `attach`, `download`, `url`).
@@ -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 {Array<(args: {context: ?, error: Error, request: ?}) => Promise<Record<string, ?> | void> | Record<string, ?> | void>} */
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 {(args: {context: ?, error: Error, request: ?}) => Promise<Record<string, ?> | void> | Record<string, ?> | void} reporter - Reporter callback.
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: ?, error: Error, request: ?}} args - Reporter args.
2399
- * @returns {Promise<Record<string, ?>>} - Merged client-safe reporter payload.
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 {Record<string, ?>} */
2402
+ /** @type {import("./configuration-types.js").ClientErrorPayloadReporterPayload} */
2403
2403
  const payload = {}
2404
2404
 
2405
2405
  for (const reporter of this._clientErrorPayloadReporters) {