@celerity-sdk/cli 0.3.0 → 0.4.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/dist/index.cjs CHANGED
@@ -73,10 +73,12 @@ function buildScannedModule(rootModule) {
73
73
  const graph = (0, import_core.buildModuleGraph)(rootModule);
74
74
  const controllerClasses = [];
75
75
  const functionHandlers = [];
76
+ const guardClasses = [];
77
+ const functionGuards = [];
76
78
  const providers = [];
77
79
  const seenTokens = /* @__PURE__ */ new Set();
78
80
  for (const [moduleClass, node] of graph) {
79
- debug("scan: module %s \u2014 %d providers, %d controllers", moduleClass.name, node.providers.length, node.controllers.length);
81
+ debug("scan: module %s \u2014 %d providers, %d controllers, %d guards", moduleClass.name, node.providers.length, node.controllers.length, node.guards.length);
80
82
  for (const provider of node.providers) {
81
83
  const scanned = scanProvider(provider, seenTokens);
82
84
  if (scanned) providers.push(scanned);
@@ -92,11 +94,28 @@ function buildScannedModule(rootModule) {
92
94
  });
93
95
  }
94
96
  }
97
+ for (const guard of node.guards) {
98
+ if (typeof guard === "function") {
99
+ guardClasses.push(guard);
100
+ if (!seenTokens.has(guard)) {
101
+ seenTokens.add(guard);
102
+ providers.push({
103
+ token: guard,
104
+ providerType: "class",
105
+ dependencies: (0, import_core.getClassDependencyTokens)(guard)
106
+ });
107
+ }
108
+ } else {
109
+ functionGuards.push(guard);
110
+ }
111
+ }
95
112
  functionHandlers.push(...node.functionHandlers);
96
113
  }
97
114
  return {
98
115
  controllerClasses,
99
116
  functionHandlers,
117
+ guardClasses,
118
+ functionGuards,
100
119
  providers
101
120
  };
102
121
  }
@@ -181,8 +200,9 @@ __name(deriveCodeLocation, "deriveCodeLocation");
181
200
  function serializeManifest(scanned, sourceFile, options) {
182
201
  const handlers = [];
183
202
  const functionHandlers = [];
203
+ const guardHandlers = [];
184
204
  for (const controllerClass of scanned.controllerClasses) {
185
- const entries = serializeClassHandler(controllerClass, sourceFile, options);
205
+ const entries = serializeClassHandlers(controllerClass, sourceFile, options);
186
206
  handlers.push(...entries);
187
207
  }
188
208
  for (const fnHandler of scanned.functionHandlers) {
@@ -191,40 +211,76 @@ function serializeManifest(scanned, sourceFile, options) {
191
211
  functionHandlers.push(entry);
192
212
  }
193
213
  }
214
+ for (const guardClass of scanned.guardClasses) {
215
+ const entry = serializeClassGuard(guardClass, sourceFile, options);
216
+ if (entry) {
217
+ guardHandlers.push(entry);
218
+ }
219
+ }
220
+ for (const fnGuard of scanned.functionGuards) {
221
+ const entry = serializeFunctionGuard(fnGuard, sourceFile, options);
222
+ if (entry) {
223
+ guardHandlers.push(entry);
224
+ }
225
+ }
194
226
  return {
195
227
  version: "1.0.0",
196
228
  handlers,
197
229
  functionHandlers,
230
+ guardHandlers,
198
231
  dependencyGraph: serializeDependencyGraph(scanned)
199
232
  };
200
233
  }
201
234
  __name(serializeManifest, "serializeManifest");
202
- function extractClassMeta(controllerClass) {
203
- const controllerMeta = Reflect.getOwnMetadata(import_core2.CONTROLLER_METADATA, controllerClass);
204
- if (!controllerMeta) return null;
235
+ function extractControllerMeta(controllerClass) {
236
+ const httpMeta = Reflect.getOwnMetadata(import_core2.CONTROLLER_METADATA, controllerClass);
237
+ if (httpMeta) {
238
+ return {
239
+ controllerType: "http",
240
+ prefix: httpMeta.prefix ?? "",
241
+ ...extractSharedClassMeta(controllerClass)
242
+ };
243
+ }
244
+ const isWebSocket = Reflect.getOwnMetadata(import_core2.WEBSOCKET_CONTROLLER_METADATA, controllerClass);
245
+ if (isWebSocket) {
246
+ return {
247
+ controllerType: "websocket",
248
+ prefix: "",
249
+ ...extractSharedClassMeta(controllerClass)
250
+ };
251
+ }
252
+ const consumerMeta = Reflect.getOwnMetadata(import_core2.CONSUMER_METADATA, controllerClass);
253
+ if (consumerMeta) {
254
+ return {
255
+ controllerType: "consumer",
256
+ prefix: "",
257
+ sourceId: consumerMeta.sourceId,
258
+ ...extractSharedClassMeta(controllerClass)
259
+ };
260
+ }
261
+ return null;
262
+ }
263
+ __name(extractControllerMeta, "extractControllerMeta");
264
+ function extractSharedClassMeta(controllerClass) {
205
265
  return {
206
- prefix: controllerMeta.prefix ?? "",
207
266
  protectedBy: Reflect.getOwnMetadata(import_core2.GUARD_PROTECTEDBY_METADATA, controllerClass) ?? [],
208
267
  customGuardName: Reflect.getOwnMetadata(import_core2.GUARD_CUSTOM_METADATA, controllerClass),
209
- customMetadata: Reflect.getOwnMetadata(import_core2.CUSTOM_METADATA, controllerClass) ?? {}
268
+ customMetadata: Reflect.getOwnMetadata(import_core2.CUSTOM_METADATA, controllerClass) ?? {},
269
+ resourceRefs: Reflect.getOwnMetadata(import_core2.USE_RESOURCE_METADATA, controllerClass) ?? []
210
270
  };
211
271
  }
212
- __name(extractClassMeta, "extractClassMeta");
213
- function buildMethodAnnotations(classMeta, prototype, methodName, httpMethod, fullPath) {
214
- const annotations = {};
215
- annotations["celerity.handler.http"] = true;
216
- annotations["celerity.handler.http.method"] = httpMethod;
217
- annotations["celerity.handler.http.path"] = fullPath;
272
+ __name(extractSharedClassMeta, "extractSharedClassMeta");
273
+ function appendSharedAnnotations(annotations, meta, prototype, methodName) {
218
274
  const methodProtectedBy = Reflect.getOwnMetadata(import_core2.GUARD_PROTECTEDBY_METADATA, prototype, methodName) ?? [];
219
275
  const allProtectedBy = [
220
- ...classMeta.protectedBy,
276
+ ...meta.protectedBy,
221
277
  ...methodProtectedBy
222
278
  ];
223
279
  if (allProtectedBy.length > 0) {
224
280
  annotations["celerity.handler.guard.protectedBy"] = allProtectedBy;
225
281
  }
226
- if (classMeta.customGuardName) {
227
- annotations["celerity.handler.guard.custom"] = classMeta.customGuardName;
282
+ if (meta.customGuardName) {
283
+ annotations["celerity.handler.guard.custom"] = meta.customGuardName;
228
284
  }
229
285
  const isPublic = Reflect.getOwnMetadata(import_core2.PUBLIC_METADATA, prototype, methodName) === true;
230
286
  if (isPublic) {
@@ -232,57 +288,206 @@ function buildMethodAnnotations(classMeta, prototype, methodName, httpMethod, fu
232
288
  }
233
289
  const methodCustomMetadata = Reflect.getOwnMetadata(import_core2.CUSTOM_METADATA, prototype, methodName) ?? {};
234
290
  const customMetadata = {
235
- ...classMeta.customMetadata,
291
+ ...meta.customMetadata,
236
292
  ...methodCustomMetadata
237
293
  };
238
294
  for (const [key, value] of Object.entries(customMetadata)) {
239
295
  if (value === void 0) continue;
240
296
  annotations[`celerity.handler.metadata.${key}`] = serializeAnnotationValue(value);
241
297
  }
298
+ const methodResourceRefs = Reflect.getOwnMetadata(import_core2.USE_RESOURCE_METADATA, prototype, methodName) ?? [];
299
+ const allResourceRefs = [
300
+ .../* @__PURE__ */ new Set([
301
+ ...meta.resourceRefs,
302
+ ...methodResourceRefs
303
+ ])
304
+ ];
305
+ if (allResourceRefs.length > 0) {
306
+ annotations["celerity.handler.resource.ref"] = allResourceRefs;
307
+ }
308
+ }
309
+ __name(appendSharedAnnotations, "appendSharedAnnotations");
310
+ function buildHttpAnnotations(meta, prototype, methodName, httpMethod, fullPath) {
311
+ const annotations = {};
312
+ annotations["celerity.handler.http"] = true;
313
+ annotations["celerity.handler.http.method"] = httpMethod;
314
+ annotations["celerity.handler.http.path"] = fullPath;
315
+ appendSharedAnnotations(annotations, meta, prototype, methodName);
316
+ return annotations;
317
+ }
318
+ __name(buildHttpAnnotations, "buildHttpAnnotations");
319
+ function buildWebSocketAnnotations(meta, prototype, methodName, wsEvent) {
320
+ const annotations = {};
321
+ annotations["celerity.handler.websocket"] = true;
322
+ annotations["celerity.handler.websocket.route"] = wsEvent.route;
323
+ annotations["celerity.handler.websocket.eventType"] = wsEvent.eventType;
324
+ appendSharedAnnotations(annotations, meta, prototype, methodName);
325
+ return annotations;
326
+ }
327
+ __name(buildWebSocketAnnotations, "buildWebSocketAnnotations");
328
+ function buildConsumerAnnotations(meta, prototype, methodName, consumerHandler) {
329
+ const annotations = {};
330
+ annotations["celerity.handler.consumer"] = true;
331
+ if (meta.sourceId) {
332
+ annotations["celerity.handler.consumer.sourceId"] = meta.sourceId;
333
+ }
334
+ if (consumerHandler.route) {
335
+ annotations["celerity.handler.consumer.route"] = consumerHandler.route;
336
+ }
337
+ appendSharedAnnotations(annotations, meta, prototype, methodName);
338
+ return annotations;
339
+ }
340
+ __name(buildConsumerAnnotations, "buildConsumerAnnotations");
341
+ function buildScheduleAnnotations(meta, prototype, methodName, scheduleMeta) {
342
+ const annotations = {};
343
+ annotations["celerity.handler.schedule"] = true;
344
+ if (scheduleMeta.scheduleId) {
345
+ annotations["celerity.handler.schedule.scheduleId"] = scheduleMeta.scheduleId;
346
+ }
347
+ if (scheduleMeta.schedule) {
348
+ annotations["celerity.handler.schedule.expression"] = scheduleMeta.schedule;
349
+ }
350
+ appendSharedAnnotations(annotations, meta, prototype, methodName);
351
+ return annotations;
352
+ }
353
+ __name(buildScheduleAnnotations, "buildScheduleAnnotations");
354
+ function buildCustomAnnotations(meta, prototype, methodName, invokeMeta) {
355
+ const annotations = {};
356
+ annotations["celerity.handler.custom"] = true;
357
+ annotations["celerity.handler.custom.name"] = invokeMeta.name;
358
+ appendSharedAnnotations(annotations, meta, prototype, methodName);
242
359
  return annotations;
243
360
  }
244
- __name(buildMethodAnnotations, "buildMethodAnnotations");
245
- function serializeClassHandler(controllerClass, sourceFile, options) {
246
- const classMeta = extractClassMeta(controllerClass);
247
- if (!classMeta) return [];
361
+ __name(buildCustomAnnotations, "buildCustomAnnotations");
362
+ function serializeClassHandlers(controllerClass, sourceFile, options) {
363
+ const meta = extractControllerMeta(controllerClass);
364
+ if (!meta) return [];
248
365
  const className = controllerClass.name;
249
366
  const prototype = controllerClass.prototype;
250
367
  const methods = Object.getOwnPropertyNames(prototype).filter((n) => n !== "constructor");
251
368
  const entries = [];
252
369
  for (const methodName of methods) {
253
- const httpMethod = Reflect.getOwnMetadata(import_core2.HTTP_METHOD_METADATA, prototype, methodName);
254
- if (!httpMethod) continue;
255
- const routePath = Reflect.getOwnMetadata(import_core2.ROUTE_PATH_METADATA, prototype, methodName) ?? "/";
256
- const fullPath = (0, import_common.joinHandlerPath)(classMeta.prefix, routePath);
257
- const annotations = buildMethodAnnotations(classMeta, prototype, methodName, httpMethod, fullPath);
258
- entries.push({
259
- resourceName: deriveClassResourceName(className, methodName),
260
- className,
261
- methodName,
262
- sourceFile,
263
- handlerType: "http",
264
- annotations,
265
- spec: {
266
- handlerName: deriveClassHandlerName(className, methodName),
267
- codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
268
- handler: deriveClassHandlerFunction(sourceFile, className, methodName)
269
- }
270
- });
370
+ const typeEntry = serializeControllerTypeMethod(meta, className, prototype, methodName, sourceFile, options);
371
+ if (typeEntry) entries.push(typeEntry);
372
+ const scheduleMeta = Reflect.getOwnMetadata(import_core2.SCHEDULE_HANDLER_METADATA, prototype, methodName);
373
+ if (scheduleMeta) {
374
+ entries.push({
375
+ resourceName: deriveClassResourceName(className, methodName),
376
+ className,
377
+ methodName,
378
+ sourceFile,
379
+ handlerType: "schedule",
380
+ annotations: buildScheduleAnnotations(meta, prototype, methodName, scheduleMeta),
381
+ spec: {
382
+ handlerName: deriveClassHandlerName(className, methodName),
383
+ codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
384
+ handler: deriveClassHandlerFunction(sourceFile, className, methodName)
385
+ }
386
+ });
387
+ }
388
+ const invokeMeta = Reflect.getOwnMetadata(import_core2.INVOKE_METADATA, prototype, methodName);
389
+ if (invokeMeta) {
390
+ entries.push({
391
+ resourceName: deriveClassResourceName(className, methodName),
392
+ className,
393
+ methodName,
394
+ sourceFile,
395
+ handlerType: "custom",
396
+ annotations: buildCustomAnnotations(meta, prototype, methodName, invokeMeta),
397
+ spec: {
398
+ handlerName: deriveClassHandlerName(className, methodName),
399
+ codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
400
+ handler: deriveClassHandlerFunction(sourceFile, className, methodName)
401
+ }
402
+ });
403
+ }
271
404
  }
272
405
  return entries;
273
406
  }
274
- __name(serializeClassHandler, "serializeClassHandler");
407
+ __name(serializeClassHandlers, "serializeClassHandlers");
408
+ function serializeControllerTypeMethod(meta, className, prototype, methodName, sourceFile, options) {
409
+ switch (meta.controllerType) {
410
+ case "http":
411
+ return serializeHttpMethod(meta, className, prototype, methodName, sourceFile, options);
412
+ case "websocket":
413
+ return serializeWebSocketMethod(meta, className, prototype, methodName, sourceFile, options);
414
+ case "consumer":
415
+ return serializeConsumerMethod(meta, className, prototype, methodName, sourceFile, options);
416
+ default:
417
+ return null;
418
+ }
419
+ }
420
+ __name(serializeControllerTypeMethod, "serializeControllerTypeMethod");
421
+ function serializeHttpMethod(meta, className, prototype, methodName, sourceFile, options) {
422
+ const httpMethod = Reflect.getOwnMetadata(import_core2.HTTP_METHOD_METADATA, prototype, methodName);
423
+ if (!httpMethod) return null;
424
+ const routePath = Reflect.getOwnMetadata(import_core2.ROUTE_PATH_METADATA, prototype, methodName) ?? "/";
425
+ const fullPath = (0, import_common.joinHandlerPath)(meta.prefix, routePath);
426
+ return {
427
+ resourceName: deriveClassResourceName(className, methodName),
428
+ className,
429
+ methodName,
430
+ sourceFile,
431
+ handlerType: "http",
432
+ annotations: buildHttpAnnotations(meta, prototype, methodName, httpMethod, fullPath),
433
+ spec: {
434
+ handlerName: deriveClassHandlerName(className, methodName),
435
+ codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
436
+ handler: deriveClassHandlerFunction(sourceFile, className, methodName)
437
+ }
438
+ };
439
+ }
440
+ __name(serializeHttpMethod, "serializeHttpMethod");
441
+ function serializeWebSocketMethod(meta, className, prototype, methodName, sourceFile, options) {
442
+ const wsEvent = Reflect.getOwnMetadata(import_core2.WEBSOCKET_EVENT_METADATA, prototype, methodName);
443
+ if (!wsEvent) return null;
444
+ return {
445
+ resourceName: deriveClassResourceName(className, methodName),
446
+ className,
447
+ methodName,
448
+ sourceFile,
449
+ handlerType: "websocket",
450
+ annotations: buildWebSocketAnnotations(meta, prototype, methodName, wsEvent),
451
+ spec: {
452
+ handlerName: deriveClassHandlerName(className, methodName),
453
+ codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
454
+ handler: deriveClassHandlerFunction(sourceFile, className, methodName)
455
+ }
456
+ };
457
+ }
458
+ __name(serializeWebSocketMethod, "serializeWebSocketMethod");
459
+ function serializeConsumerMethod(meta, className, prototype, methodName, sourceFile, options) {
460
+ const consumerHandler = Reflect.getOwnMetadata(import_core2.CONSUMER_HANDLER_METADATA, prototype, methodName);
461
+ if (!consumerHandler) return null;
462
+ return {
463
+ resourceName: deriveClassResourceName(className, methodName),
464
+ className,
465
+ methodName,
466
+ sourceFile,
467
+ handlerType: "consumer",
468
+ annotations: buildConsumerAnnotations(meta, prototype, methodName, consumerHandler),
469
+ spec: {
470
+ handlerName: deriveClassHandlerName(className, methodName),
471
+ codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
472
+ handler: deriveClassHandlerFunction(sourceFile, className, methodName)
473
+ }
474
+ };
475
+ }
476
+ __name(serializeConsumerMethod, "serializeConsumerMethod");
275
477
  function serializeFunctionHandler(definition, sourceFile, options) {
478
+ const supported = [
479
+ "http",
480
+ "websocket",
481
+ "consumer",
482
+ "schedule",
483
+ "custom"
484
+ ];
485
+ if (!supported.includes(definition.type)) return null;
276
486
  const exportName = definition.metadata.handlerName ?? "handler";
277
487
  const customMetadata = definition.metadata.customMetadata ?? {};
488
+ const handlerType = definition.type;
278
489
  const annotations = {};
279
- const path = definition.metadata.path;
280
- const method = definition.metadata.method;
281
- if (path !== void 0 && method !== void 0) {
282
- annotations["celerity.handler.http"] = true;
283
- annotations["celerity.handler.http.method"] = method;
284
- annotations["celerity.handler.http.path"] = path;
285
- }
490
+ buildFunctionTypeAnnotations(annotations, definition);
286
491
  for (const [key, value] of Object.entries(customMetadata)) {
287
492
  if (value === void 0) continue;
288
493
  annotations[`celerity.handler.metadata.${key}`] = serializeAnnotationValue(value);
@@ -291,6 +496,7 @@ function serializeFunctionHandler(definition, sourceFile, options) {
291
496
  resourceName: deriveFunctionResourceName(exportName),
292
497
  exportName,
293
498
  sourceFile,
499
+ handlerType,
294
500
  ...Object.keys(annotations).length > 0 ? {
295
501
  annotations
296
502
  } : {},
@@ -302,6 +508,122 @@ function serializeFunctionHandler(definition, sourceFile, options) {
302
508
  };
303
509
  }
304
510
  __name(serializeFunctionHandler, "serializeFunctionHandler");
511
+ function buildFunctionTypeAnnotations(annotations, definition) {
512
+ const meta = definition.metadata;
513
+ switch (definition.type) {
514
+ case "http": {
515
+ const path = meta.path;
516
+ const method = meta.method;
517
+ if (path !== void 0 && method !== void 0) {
518
+ annotations["celerity.handler.http"] = true;
519
+ annotations["celerity.handler.http.method"] = method;
520
+ annotations["celerity.handler.http.path"] = path;
521
+ }
522
+ break;
523
+ }
524
+ case "websocket": {
525
+ annotations["celerity.handler.websocket"] = true;
526
+ const route = meta.route;
527
+ if (route) {
528
+ annotations["celerity.handler.websocket.route"] = route;
529
+ }
530
+ break;
531
+ }
532
+ case "consumer": {
533
+ annotations["celerity.handler.consumer"] = true;
534
+ const route = meta.route;
535
+ if (route) {
536
+ annotations["celerity.handler.consumer.route"] = route;
537
+ }
538
+ break;
539
+ }
540
+ case "schedule": {
541
+ annotations["celerity.handler.schedule"] = true;
542
+ const scheduleId = meta.scheduleId;
543
+ if (scheduleId) {
544
+ annotations["celerity.handler.schedule.scheduleId"] = scheduleId;
545
+ }
546
+ const schedule = meta.schedule;
547
+ if (schedule) {
548
+ annotations["celerity.handler.schedule.expression"] = schedule;
549
+ }
550
+ break;
551
+ }
552
+ case "custom": {
553
+ annotations["celerity.handler.custom"] = true;
554
+ const name = meta.name;
555
+ if (name) {
556
+ annotations["celerity.handler.custom.name"] = name;
557
+ }
558
+ break;
559
+ }
560
+ }
561
+ }
562
+ __name(buildFunctionTypeAnnotations, "buildFunctionTypeAnnotations");
563
+ function extractGuardMeta(guardClass) {
564
+ const guardName = Reflect.getOwnMetadata(import_core2.GUARD_CUSTOM_METADATA, guardClass);
565
+ if (!guardName) return null;
566
+ return {
567
+ guardName,
568
+ customMetadata: Reflect.getOwnMetadata(import_core2.CUSTOM_METADATA, guardClass) ?? {}
569
+ };
570
+ }
571
+ __name(extractGuardMeta, "extractGuardMeta");
572
+ function serializeClassGuard(guardClass, sourceFile, options) {
573
+ const meta = extractGuardMeta(guardClass);
574
+ if (!meta) return null;
575
+ const className = guardClass.name;
576
+ const methodName = "check";
577
+ const annotations = {
578
+ "celerity.handler.guard.custom": meta.guardName
579
+ };
580
+ for (const [key, value] of Object.entries(meta.customMetadata)) {
581
+ if (value === void 0) continue;
582
+ annotations[`celerity.handler.metadata.${key}`] = serializeAnnotationValue(value);
583
+ }
584
+ return {
585
+ resourceName: deriveClassResourceName(className, methodName),
586
+ guardName: meta.guardName,
587
+ sourceFile,
588
+ guardType: "class",
589
+ className,
590
+ annotations,
591
+ spec: {
592
+ handlerName: deriveClassHandlerName(className, methodName),
593
+ codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
594
+ handler: deriveClassHandlerFunction(sourceFile, className, methodName)
595
+ }
596
+ };
597
+ }
598
+ __name(serializeClassGuard, "serializeClassGuard");
599
+ function serializeFunctionGuard(definition, sourceFile, options) {
600
+ const guardName = definition.name;
601
+ if (!guardName) return null;
602
+ const meta = definition.metadata ?? {};
603
+ const customMetadata = meta.customMetadata ?? {};
604
+ const annotations = {
605
+ "celerity.handler.guard.custom": guardName
606
+ };
607
+ for (const [key, value] of Object.entries(customMetadata)) {
608
+ if (value === void 0) continue;
609
+ annotations[`celerity.handler.metadata.${key}`] = serializeAnnotationValue(value);
610
+ }
611
+ const exportName = guardName;
612
+ return {
613
+ resourceName: deriveFunctionResourceName(exportName),
614
+ guardName,
615
+ sourceFile,
616
+ guardType: "function",
617
+ exportName,
618
+ annotations,
619
+ spec: {
620
+ handlerName: exportName,
621
+ codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
622
+ handler: deriveFunctionHandlerFunction(sourceFile, exportName)
623
+ }
624
+ };
625
+ }
626
+ __name(serializeFunctionGuard, "serializeFunctionGuard");
305
627
  function serializeAnnotationValue(value) {
306
628
  if (typeof value === "boolean") return value;
307
629
  if (typeof value === "string") return value;