velocious 1.0.457 → 1.0.458

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.
@@ -90,6 +90,10 @@ function normalizeFrontendModelResourceConfiguration(resourceConfiguration) {
90
90
  builtInCollectionCommands: normalizedCommands.builtInCollectionCommands,
91
91
  builtInMemberCommands: normalizedCommands.builtInMemberCommands,
92
92
  collectionCommands: normalizedCommands.collectionCommands,
93
+ // Per-command metadata (typed args + declared return type) keyed by method
94
+ // name, derived from `{name, args?, returnType?}` command entries. The
95
+ // generator uses it to type each custom command method.
96
+ commandMetadata: normalizedCommands.commandMetadata,
93
97
  memberCommands: normalizedCommands.memberCommands
94
98
  }
95
99
  }
@@ -151,7 +155,7 @@ function defaultCrudAbilities() {
151
155
  /**
152
156
  * Runs normalize frontend model resource commands.
153
157
  * @param {import("../configuration-types.js").FrontendModelResourceConfiguration} resourceConfiguration - Raw resource configuration.
154
- * @returns {{builtInCollectionCommands: Record<string, string>, builtInMemberCommands: Record<string, string>, collectionCommands: Record<string, string>, memberCommands: Record<string, string>}} - Normalized command configuration.
158
+ * @returns {{builtInCollectionCommands: Record<string, string>, builtInMemberCommands: Record<string, string>, collectionCommands: Record<string, string>, commandMetadata: Record<string, {args: Array<{name: string, type: string}>, returnType: string | null}>, memberCommands: Record<string, string>}} - Normalized command configuration.
155
159
  */
156
160
  function normalizeFrontendModelResourceCommands(resourceConfiguration) {
157
161
  const builtInCollectionCommands = resourceConfiguration.builtInCollectionCommands
@@ -180,11 +184,15 @@ function normalizeFrontendModelResourceCommands(resourceConfiguration) {
180
184
  modelName: "MemberCommand"
181
185
  })
182
186
 
187
+ const normalizedCollectionCommands = normalizeFrontendModelCustomCommands({commandsConfig: customCollectionCommands, modelName: "CollectionCommand"})
188
+ const normalizedMemberCommands = normalizeFrontendModelCustomCommands({commandsConfig: customMemberCommands, modelName: "MemberCommand"})
189
+
183
190
  return {
184
191
  builtInCollectionCommands: normalizedBuiltInCollectionCommands,
185
192
  builtInMemberCommands: normalizedBuiltInMemberCommands,
186
- collectionCommands: normalizeFrontendModelCustomCommands({commandsConfig: customCollectionCommands, modelName: "CollectionCommand"}),
187
- memberCommands: normalizeFrontendModelCustomCommands({commandsConfig: customMemberCommands, modelName: "MemberCommand"})
193
+ collectionCommands: normalizedCollectionCommands.commands,
194
+ commandMetadata: {...normalizedCollectionCommands.metadata, ...normalizedMemberCommands.metadata},
195
+ memberCommands: normalizedMemberCommands.commands
188
196
  }
189
197
  }
190
198
 
@@ -228,27 +236,30 @@ function normalizeFrontendModelBuiltInCommands({commandDefaults, commandsConfig,
228
236
  }
229
237
 
230
238
  /**
231
- * Runs normalize frontend model custom commands.
239
+ * Runs normalize frontend model custom commands. Entries are either a plain
240
+ * camelCase method-name string or a `{name, args?, returnType?}` object that
241
+ * also declares the command's typed arguments and/or response type.
232
242
  * @param {object} args - Arguments.
233
- * @param {string[] | undefined} args.commandsConfig - Custom commands config (camelCase method-name list).
243
+ * @param {Array<string | {name: string, args?: Array<{name: string, type: string}>, returnType?: string}> | undefined} args.commandsConfig - Custom commands config.
234
244
  * @param {string} args.modelName - Diagnostic model name.
235
- * @returns {Record<string, string>} - Normalized custom command config (camelCase method name → kebab-case command slug).
245
+ * @returns {{commands: Record<string, string>, metadata: Record<string, {args: Array<{name: string, type: string}>, returnType: string | null}>}} - Route map (method name → kebab slug) + per-command metadata.
236
246
  */
237
247
  function normalizeFrontendModelCustomCommands({commandsConfig, modelName}) {
238
248
  if (!commandsConfig) {
239
- return {}
249
+ return {commands: {}, metadata: {}}
240
250
  }
241
251
 
242
252
  if (!Array.isArray(commandsConfig)) {
243
253
  throw new Error(`${modelName} configuration must use the array form. Object form is no longer supported.`)
244
254
  }
245
255
 
246
- /**
247
- * Normalized commands.
248
- * @type {Record<string, string>} */
249
- const normalizedCommands = {}
256
+ /** @type {Record<string, string>} */
257
+ const commands = {}
258
+ /** @type {Record<string, {args: Array<{name: string, type: string}>, returnType: string | null}>} */
259
+ const metadata = {}
250
260
 
251
- for (const methodName of commandsConfig) {
261
+ for (const commandEntry of commandsConfig) {
262
+ const {methodName, args, returnType} = normalizeFrontendModelCustomCommandEntry({commandEntry, modelName})
252
263
  const validatedMethodName = validateFrontendModelResourceCommandName({
253
264
  commandName: methodName,
254
265
  commandType: methodName,
@@ -256,10 +267,90 @@ function normalizeFrontendModelCustomCommands({commandsConfig, modelName}) {
256
267
  })
257
268
  const commandSlug = inflection.dasherize(inflection.underscore(validatedMethodName))
258
269
 
259
- normalizedCommands[validatedMethodName] = commandSlug
270
+ commands[validatedMethodName] = commandSlug
271
+ metadata[validatedMethodName] = {args, returnType}
260
272
  }
261
273
 
262
- return normalizedCommands
274
+ return {commands, metadata}
275
+ }
276
+
277
+ /**
278
+ * Normalizes one custom-command entry (string shorthand or contract object).
279
+ * @param {object} args - Arguments.
280
+ * @param {unknown} args.commandEntry - Raw command entry.
281
+ * @param {string} args.modelName - Diagnostic model name.
282
+ * @returns {{methodName: string, args: Array<{name: string, type: string}>, returnType: string | null}} - Method name + metadata.
283
+ */
284
+ function normalizeFrontendModelCustomCommandEntry({commandEntry, modelName}) {
285
+ if (typeof commandEntry === "string") {
286
+ return {methodName: commandEntry, args: [], returnType: null}
287
+ }
288
+
289
+ if (!commandEntry || typeof commandEntry !== "object" || Array.isArray(commandEntry)) {
290
+ throw new Error(`${modelName} entries must be a camelCase name string or a {name, args?, returnType?} object`)
291
+ }
292
+
293
+ const {name, args, returnType, ...rest} = /** @type {{name?: unknown, args?: unknown, returnType?: unknown}} */ (commandEntry)
294
+
295
+ if (Object.keys(rest).length > 0) {
296
+ throw new Error(`Unexpected ${modelName} keys: ${Object.keys(rest).join(", ")}. Allowed: name, args, returnType`)
297
+ }
298
+
299
+ if (typeof name !== "string" || name.length < 1) {
300
+ throw new Error(`${modelName} object entries require a non-empty 'name' string`)
301
+ }
302
+
303
+ return {
304
+ methodName: name,
305
+ args: normalizeFrontendModelCommandArgs({args, commandName: name, modelName}),
306
+ returnType: normalizeFrontendModelCommandReturnType({commandName: name, modelName, returnType})
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Validates and normalizes a custom command's typed-argument list.
312
+ * @param {object} args - Arguments.
313
+ * @param {unknown} args.args - Raw command args.
314
+ * @param {string} args.commandName - Command name for diagnostics.
315
+ * @param {string} args.modelName - Diagnostic model name.
316
+ * @returns {Array<{name: string, type: string}>} - Normalized typed command arguments.
317
+ */
318
+ function normalizeFrontendModelCommandArgs({args, commandName, modelName}) {
319
+ if (args === undefined || args === null) {
320
+ return []
321
+ }
322
+
323
+ if (!Array.isArray(args)) {
324
+ throw new Error(`${modelName} '${commandName}' args must be an array of {name, type} objects`)
325
+ }
326
+
327
+ return args.map((arg) => {
328
+ if (!arg || typeof arg !== "object" || typeof arg.name !== "string" || arg.name.length < 1 || typeof arg.type !== "string" || arg.type.trim().length < 1) {
329
+ throw new Error(`${modelName} '${commandName}' args entries require non-empty 'name' and JSDoc-type 'type' strings`)
330
+ }
331
+
332
+ return {name: arg.name, type: arg.type.trim()}
333
+ })
334
+ }
335
+
336
+ /**
337
+ * Validates and normalizes a custom command's declared JSDoc return type.
338
+ * @param {object} args - Arguments.
339
+ * @param {string} args.commandName - Command name for diagnostics.
340
+ * @param {string} args.modelName - Diagnostic model name.
341
+ * @param {unknown} args.returnType - Raw return type.
342
+ * @returns {string | null} - Normalized JSDoc return type.
343
+ */
344
+ function normalizeFrontendModelCommandReturnType({commandName, modelName, returnType}) {
345
+ if (returnType === undefined || returnType === null) {
346
+ return null
347
+ }
348
+
349
+ if (typeof returnType !== "string" || returnType.trim().length < 1) {
350
+ throw new Error(`${modelName} '${commandName}' returnType must be a non-empty JSDoc type string`)
351
+ }
352
+
353
+ return returnType.trim()
263
354
  }
264
355
 
265
356
  /**