@dereekb/dbx-cli 13.11.1 → 13.11.3

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.
Files changed (32) hide show
  1. package/firebase-api-manifest/main.js +142 -25
  2. package/firebase-api-manifest/package.json +1 -1
  3. package/index.cjs.js +202 -26
  4. package/index.esm.js +201 -27
  5. package/manifest-extract/LICENSE +21 -0
  6. package/manifest-extract/index.cjs.default.js +1 -0
  7. package/manifest-extract/index.cjs.js +459 -0
  8. package/manifest-extract/index.cjs.mjs +2 -0
  9. package/manifest-extract/index.d.ts +1 -0
  10. package/manifest-extract/index.esm.js +457 -0
  11. package/manifest-extract/package.json +20 -0
  12. package/manifest-extract/src/index.d.ts +2 -0
  13. package/manifest-extract/src/lib/extract-crud.d.ts +36 -0
  14. package/manifest-extract/src/lib/types.d.ts +86 -0
  15. package/package.json +10 -4
  16. package/src/lib/api/call-model.command.factory.d.ts +1 -0
  17. package/src/lib/auth/auth.command.factory.d.ts +1 -0
  18. package/src/lib/auth/oidc.flow.d.ts +1 -0
  19. package/src/lib/config/env.d.ts +1 -1
  20. package/src/lib/config/paths.d.ts +1 -0
  21. package/src/lib/config/token.cache.d.ts +1 -0
  22. package/src/lib/context/cli.context.d.ts +1 -0
  23. package/src/lib/doctor/doctor.command.factory.d.ts +1 -0
  24. package/src/lib/env/env.command.factory.d.ts +1 -0
  25. package/src/lib/manifest/build-manifest-commands.d.ts +39 -0
  26. package/src/lib/manifest/types.d.ts +20 -0
  27. package/src/lib/middleware/auth.middleware.d.ts +1 -0
  28. package/src/lib/middleware/output.middleware.d.ts +1 -0
  29. package/src/lib/output/output.command.factory.d.ts +1 -0
  30. package/src/lib/runner/run.d.ts +1 -0
  31. package/src/lib/util/context.slot.d.ts +1 -0
  32. package/src/lib/util/output.d.ts +2 -0
@@ -136,7 +136,7 @@ function stripJsonComments(text) {
136
136
  import { readdirSync, readFileSync as readFileSync3, statSync } from "node:fs";
137
137
  import { join as join2 } from "node:path";
138
138
 
139
- // packages/dbx-cli/firebase-api-manifest/src/generate-api-manifest/extract-crud.ts
139
+ // packages/dbx-cli/manifest-extract/src/lib/extract-crud.ts
140
140
  import { Node as Node2, Project as Project2 } from "ts-morph";
141
141
  var SUPPORTED_VERBS = /* @__PURE__ */ new Set(["create", "read", "update", "delete", "query"]);
142
142
  function extractCrudEntries(source) {
@@ -147,24 +147,51 @@ function extractCrudEntries(source) {
147
147
  const crudConfigType = findTypeAliasByEnding(sourceFile, "ModelCrudFunctionsConfig");
148
148
  const groupName = inferGroupName(sourceFile);
149
149
  const functionsClassName = findFunctionsClassName(sourceFile);
150
+ const typeDocsCache = /* @__PURE__ */ new Map();
151
+ const resolveTypeDocs = (typeName) => {
152
+ if (!typeName) {
153
+ return void 0;
154
+ }
155
+ if (typeDocsCache.has(typeName)) {
156
+ return typeDocsCache.get(typeName);
157
+ }
158
+ const docs = readTypeDocs(sourceFile, typeName);
159
+ if (docs) {
160
+ typeDocsCache.set(typeName, docs);
161
+ }
162
+ return docs;
163
+ };
150
164
  if (crudConfigType) {
151
165
  const literal = crudConfigType.getTypeNode();
152
166
  if (literal && Node2.isTypeLiteral(literal)) {
153
167
  for (const member of literal.getMembers()) {
154
- if (!Node2.isPropertySignature(member)) continue;
168
+ if (!Node2.isPropertySignature(member)) {
169
+ continue;
170
+ }
155
171
  const modelName = member.getName();
156
172
  modelKeys.push(modelName);
157
173
  const valueNode = member.getTypeNode();
158
- if (!valueNode) continue;
159
- if (isNullLiteralType(valueNode)) continue;
174
+ if (!valueNode) {
175
+ continue;
176
+ }
177
+ if (isNullLiteralType(valueNode)) {
178
+ continue;
179
+ }
160
180
  if (Node2.isTypeLiteral(valueNode)) {
161
181
  for (const verbMember of valueNode.getMembers()) {
162
- if (!Node2.isPropertySignature(verbMember)) continue;
163
- const verb = verbMember.getName();
164
- if (!SUPPORTED_VERBS.has(verb)) continue;
182
+ if (!Node2.isPropertySignature(verbMember)) {
183
+ continue;
184
+ }
185
+ const verbName = verbMember.getName();
186
+ if (!SUPPORTED_VERBS.has(verbName)) {
187
+ continue;
188
+ }
189
+ const verb = verbName;
165
190
  const verbValueNode = verbMember.getTypeNode();
166
- if (!verbValueNode) continue;
167
- collectVerbEntries({ modelName, verb, valueNode: verbValueNode, entries });
191
+ if (!verbValueNode) {
192
+ continue;
193
+ }
194
+ collectVerbEntries({ modelName, verb, valueNode: verbValueNode, entries, fallbackDescription: readJsDocSummary(verbMember), resolveTypeDocs });
168
195
  }
169
196
  }
170
197
  }
@@ -175,17 +202,26 @@ function extractCrudEntries(source) {
175
202
  const literal = functionTypeMap.getTypeNode();
176
203
  if (literal && Node2.isTypeLiteral(literal)) {
177
204
  for (const member of literal.getMembers()) {
178
- if (!Node2.isPropertySignature(member)) continue;
205
+ if (!Node2.isPropertySignature(member)) {
206
+ continue;
207
+ }
179
208
  const key = member.getName();
180
209
  const valueNode = member.getTypeNode();
181
210
  const tuple = valueNode ? readTupleParamsResult(valueNode) : void 0;
211
+ const paramsDocs = resolveTypeDocs(tuple?.params);
212
+ const resultDocs = resolveTypeDocs(tuple?.result);
182
213
  entries.push({
183
214
  model: key,
184
215
  verb: "standalone",
185
216
  specifier: void 0,
186
217
  paramsTypeName: tuple?.params,
187
218
  resultTypeName: tuple?.result,
188
- line: member.getStartLineNumber()
219
+ line: member.getStartLineNumber(),
220
+ description: readJsDocSummary(member),
221
+ paramsTypeDescription: paramsDocs?.typeDescription,
222
+ paramsFields: paramsDocs?.fields,
223
+ resultTypeDescription: resultDocs?.typeDescription,
224
+ resultFields: resultDocs?.fields
189
225
  });
190
226
  }
191
227
  }
@@ -194,15 +230,21 @@ function extractCrudEntries(source) {
194
230
  }
195
231
  function findTypeAliasByEnding(sourceFile, ending) {
196
232
  for (const alias of sourceFile.getTypeAliases()) {
197
- if (alias.getName().endsWith(ending) && alias.getTypeNode()) return alias;
233
+ if (alias.getName().endsWith(ending) && alias.getTypeNode()) {
234
+ return alias;
235
+ }
198
236
  }
199
237
  return void 0;
200
238
  }
201
239
  function findFunctionsClassName(sourceFile) {
202
240
  for (const cls of sourceFile.getClasses()) {
203
- if (!cls.isAbstract()) continue;
241
+ if (!cls.isAbstract()) {
242
+ continue;
243
+ }
204
244
  const name = cls.getName();
205
- if (name?.endsWith("Functions")) return name;
245
+ if (name?.endsWith("Functions")) {
246
+ return name;
247
+ }
206
248
  }
207
249
  return void 0;
208
250
  }
@@ -211,14 +253,18 @@ function inferGroupName(sourceFile) {
211
253
  const name = alias.getName();
212
254
  if (name.endsWith("ModelCrudFunctionsConfig")) {
213
255
  const stem = name.slice(0, -"ModelCrudFunctionsConfig".length);
214
- if (stem.length > 0) return stem;
256
+ if (stem.length > 0) {
257
+ return stem;
258
+ }
215
259
  }
216
260
  }
217
261
  for (const alias of sourceFile.getTypeAliases()) {
218
262
  const name = alias.getName();
219
263
  if (name.endsWith("FunctionTypeMap")) {
220
264
  const stem = name.slice(0, -"FunctionTypeMap".length);
221
- if (stem.length > 0) return stem;
265
+ if (stem.length > 0) {
266
+ return stem;
267
+ }
222
268
  }
223
269
  }
224
270
  return void 0;
@@ -226,50 +272,74 @@ function inferGroupName(sourceFile) {
226
272
  function isNullLiteralType(node) {
227
273
  if (Node2.isLiteralTypeNode(node)) {
228
274
  const literal = node.getLiteral();
229
- if (Node2.isNullLiteral(literal)) return true;
275
+ if (Node2.isNullLiteral(literal)) {
276
+ return true;
277
+ }
230
278
  }
231
279
  return false;
232
280
  }
233
281
  function collectVerbEntries(input) {
234
- const { modelName, verb, valueNode, entries } = input;
282
+ const { modelName, verb, valueNode, entries, fallbackDescription, resolveTypeDocs } = input;
235
283
  if (Node2.isTypeLiteral(valueNode)) {
236
284
  for (const specMember of valueNode.getMembers()) {
237
- if (!Node2.isPropertySignature(specMember)) continue;
285
+ if (!Node2.isPropertySignature(specMember)) {
286
+ continue;
287
+ }
238
288
  const specifier = specMember.getName();
239
289
  const leafNode = specMember.getTypeNode();
240
290
  const leaf2 = leafNode ? readTupleParamsResult(leafNode) ?? readBareParams(leafNode) : void 0;
291
+ const paramsDocs2 = resolveTypeDocs(leaf2?.params);
292
+ const resultDocs2 = resolveTypeDocs(leaf2?.result);
241
293
  entries.push({
242
294
  model: modelName,
243
295
  verb,
244
296
  specifier,
245
297
  paramsTypeName: leaf2?.params,
246
298
  resultTypeName: leaf2?.result,
247
- line: specMember.getStartLineNumber()
299
+ line: specMember.getStartLineNumber(),
300
+ description: readJsDocSummary(specMember),
301
+ paramsTypeDescription: paramsDocs2?.typeDescription,
302
+ paramsFields: paramsDocs2?.fields,
303
+ resultTypeDescription: resultDocs2?.typeDescription,
304
+ resultFields: resultDocs2?.fields
248
305
  });
249
306
  }
250
307
  return;
251
308
  }
252
309
  const leaf = readTupleParamsResult(valueNode) ?? readBareParams(valueNode);
310
+ const paramsDocs = resolveTypeDocs(leaf?.params);
311
+ const resultDocs = resolveTypeDocs(leaf?.result);
253
312
  entries.push({
254
313
  model: modelName,
255
314
  verb,
256
315
  specifier: void 0,
257
316
  paramsTypeName: leaf?.params,
258
317
  resultTypeName: leaf?.result,
259
- line: valueNode.getStartLineNumber()
318
+ line: valueNode.getStartLineNumber(),
319
+ description: fallbackDescription,
320
+ paramsTypeDescription: paramsDocs?.typeDescription,
321
+ paramsFields: paramsDocs?.fields,
322
+ resultTypeDescription: resultDocs?.typeDescription,
323
+ resultFields: resultDocs?.fields
260
324
  });
261
325
  }
262
326
  function readTupleParamsResult(node) {
263
- if (!Node2.isTupleTypeNode(node)) return void 0;
327
+ if (!Node2.isTupleTypeNode(node)) {
328
+ return void 0;
329
+ }
264
330
  const elements = node.getElements();
265
- if (elements.length === 0) return void 0;
331
+ if (elements.length === 0) {
332
+ return void 0;
333
+ }
266
334
  const params = elements[0] ? typeNodeName(elements[0]) : void 0;
267
335
  const result = elements[1] ? typeNodeName(elements[1]) : void 0;
268
336
  return { params, result };
269
337
  }
270
338
  function readBareParams(node) {
271
339
  const params = typeNodeName(node);
272
- if (!params) return void 0;
340
+ if (!params) {
341
+ return void 0;
342
+ }
273
343
  return { params, result: void 0 };
274
344
  }
275
345
  function typeNodeName(node) {
@@ -279,6 +349,40 @@ function typeNodeName(node) {
279
349
  const text = node.getText().trim();
280
350
  return text.length > 0 ? text : void 0;
281
351
  }
352
+ function readTypeDocs(sourceFile, typeName) {
353
+ const interfaceDecl = sourceFile.getInterface(typeName);
354
+ if (interfaceDecl) {
355
+ const typeDescription = readJsDocSummary(interfaceDecl);
356
+ const fields = [];
357
+ for (const property of interfaceDecl.getProperties()) {
358
+ const fieldName = property.getName();
359
+ const description = readJsDocSummary(property);
360
+ const typeNode = property.getTypeNode();
361
+ const typeText = typeNode?.getText().trim() ?? "";
362
+ const field = description ? { name: fieldName, typeText, description } : { name: fieldName, typeText };
363
+ fields.push(field);
364
+ }
365
+ if (!typeDescription && fields.length === 0) {
366
+ return void 0;
367
+ }
368
+ return { typeDescription, fields: fields.length > 0 ? fields : void 0 };
369
+ }
370
+ const typeAlias = sourceFile.getTypeAlias(typeName);
371
+ if (typeAlias) {
372
+ const typeDescription = readJsDocSummary(typeAlias);
373
+ return typeDescription ? { typeDescription } : void 0;
374
+ }
375
+ return void 0;
376
+ }
377
+ function readJsDocSummary(node) {
378
+ const docs = node.getJsDocs();
379
+ if (docs.length === 0) {
380
+ return void 0;
381
+ }
382
+ const last = docs[docs.length - 1];
383
+ const description = last.getDescription().trim();
384
+ return description.length > 0 ? description : void 0;
385
+ }
282
386
 
283
387
  // packages/dbx-cli/firebase-api-manifest/src/generate-api-manifest/find-api-files.ts
284
388
  function findApiFiles(packageRoot) {
@@ -437,10 +541,23 @@ function renderEntry({ entry, validatorName }) {
437
541
  validatorName ? `paramsValidator: ${validatorName}` : void 0,
438
542
  entry.resultTypeName ? `resultTypeName: ${JSON.stringify(entry.resultTypeName)}` : void 0,
439
543
  `groupName: ${JSON.stringify(entry.groupName)}`,
440
- `sourceFile: ${JSON.stringify(entry.sourceFile)}`
544
+ `sourceFile: ${JSON.stringify(entry.sourceFile)}`,
545
+ entry.description ? `description: ${JSON.stringify(entry.description)}` : void 0,
546
+ entry.paramsTypeDescription ? `paramsTypeDescription: ${JSON.stringify(entry.paramsTypeDescription)}` : void 0,
547
+ entry.paramsFields && entry.paramsFields.length > 0 ? `paramsFields: ${renderDocFields(entry.paramsFields)}` : void 0,
548
+ entry.resultTypeDescription ? `resultTypeDescription: ${JSON.stringify(entry.resultTypeDescription)}` : void 0,
549
+ entry.resultFields && entry.resultFields.length > 0 ? `resultFields: ${renderDocFields(entry.resultFields)}` : void 0
441
550
  ];
442
551
  return ` { ${fields.filter((v) => Boolean(v)).join(", ")} }`;
443
552
  }
553
+ function renderDocFields(fields) {
554
+ const items = fields.map((field) => {
555
+ const parts = [`name: ${JSON.stringify(field.name)}`, `typeText: ${JSON.stringify(field.typeText)}`];
556
+ if (field.description) parts.push(`description: ${JSON.stringify(field.description)}`);
557
+ return `{ ${parts.join(", ")} }`;
558
+ });
559
+ return `[${items.join(", ")}]`;
560
+ }
444
561
  async function formatWithPrettier(source, outputFile) {
445
562
  const config = await resolveConfig(outputFile);
446
563
  return format(source, { ...config, filepath: outputFile });
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli-firebase-api-manifest",
3
- "version": "13.11.1",
3
+ "version": "13.11.3",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "devDependencies": {