@crombolo/schema 0.16.0 → 0.17.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crombolo/schema",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "description": "Schema-as-code for crombolo: TOML document, media and member type definitions.",
5
5
  "license": "MIT",
6
6
  "author": "Crombolo",
@@ -28,7 +28,7 @@
28
28
  "access": "public"
29
29
  },
30
30
  "dependencies": {
31
- "@crombolo/core": "0.16.0",
32
- "@crombolo/data": "0.16.0"
31
+ "@crombolo/core": "0.17.0",
32
+ "@crombolo/data": "0.17.0"
33
33
  }
34
34
  }
@@ -53,8 +53,16 @@ export interface ValidateFormsOptions {
53
53
  contentTypeAliases?: ReadonlySet<string>
54
54
  /** The field and workflow types in play: the built-ins, and the wired bundles'. */
55
55
  types?: FormTypes
56
+ /**
57
+ * The components that exist, by alias: a content type's templates and a Send
58
+ * email workflow's `template` are held to them. Omit to skip those checks.
59
+ */
60
+ componentAliases?: ReadonlySet<string>
56
61
  }
57
62
 
63
+ /** A component alias is a path under `components/`: folders and names, nothing that climbs. */
64
+ const COMPONENT_ALIAS = /^[A-Za-z0-9_-]+(\/[A-Za-z0-9_-]+)*$/
65
+
58
66
  export function validateForms(
59
67
  forms: readonly SchemaForm[],
60
68
  options: ValidateFormsOptions = {},
@@ -303,9 +311,16 @@ function validateCondition(
303
311
  const WORKFLOW_SETTINGS: Record<string, { required: string[]; optional: string[] }> = {
304
312
  sendEmail: {
305
313
  required: ['to', 'subject'],
306
- // No `template`: a TSX e-mail template is not built yet, and a setting that
307
- // silently does nothing is worse than one that is refused by name.
308
- optional: ['cc', 'bcc', 'reply-to', 'from', 'body', 'attach-uploads'],
314
+ optional: [
315
+ 'cc',
316
+ 'bcc',
317
+ 'reply-to',
318
+ 'from',
319
+ 'body',
320
+ 'template',
321
+ 'attach-uploads',
322
+ 'include-sensitive',
323
+ ],
309
324
  },
310
325
  saveAsContent: {
311
326
  required: ['content-type', 'parent'],
@@ -347,8 +362,7 @@ function validateWorkflows(
347
362
  if (!rules) continue
348
363
  const allowed = new Set([...rules.required, ...rules.optional])
349
364
  for (const key of rules.required)
350
- if (workflow.settings[key] === undefined)
351
- add(file, `${path}.settings.${key}`, `is required by a ${workflow.type} workflow`)
365
+ if (workflow.settings[key] === undefined) add(file, `${path}.settings.${key}`, 'is required')
352
366
  for (const key of Object.keys(workflow.settings))
353
367
  if (!allowed.has(key))
354
368
  add(
@@ -379,6 +393,26 @@ function validateWorkflows(
379
393
  add(file, `${path}.settings.name-field`, `unknown field "${nameField}"`)
380
394
  }
381
395
  if (workflow.type === 'sendEmail') {
396
+ const template = workflow.settings.template
397
+ if (template !== undefined) {
398
+ if (typeof template !== 'string' || !COMPONENT_ALIAS.test(template))
399
+ add(
400
+ file,
401
+ `${path}.settings.template`,
402
+ 'expected the alias of a component: its path under components/, without .tsx',
403
+ )
404
+ else if (options.componentAliases && !options.componentAliases.has(template))
405
+ add(file, `${path}.settings.template`, `there is no components/${template}.tsx`)
406
+ if (workflow.settings.body !== undefined)
407
+ add(
408
+ file,
409
+ `${path}.settings.body`,
410
+ 'the e-mail template writes the body, so a workflow with a template takes no body',
411
+ )
412
+ }
413
+ for (const key of ['attach-uploads', 'include-sensitive'])
414
+ if (workflow.settings[key] !== undefined && typeof workflow.settings[key] !== 'boolean')
415
+ add(file, `${path}.settings.${key}`, 'expected true or false')
382
416
  const attach = workflow.settings['attach-uploads']
383
417
  if (attach === true && !allFormFields(form).some((field) => field.type === 'fileUpload'))
384
418
  add(
package/src/validate.ts CHANGED
@@ -21,10 +21,8 @@ import {
21
21
  import { type ValidateFormsOptions, validateForms } from './validate-forms.ts'
22
22
  import { validateWorkflows } from './workflows.ts'
23
23
 
24
- export interface ValidateOptions extends ValidateFormsOptions {
25
- /** Template aliases that exist as view files; omit to skip template checks. */
26
- componentAliases?: ReadonlySet<string>
27
- }
24
+ /** `componentAliases` lives with the form options: a Send email workflow's template uses it too. */
25
+ export type ValidateOptions = ValidateFormsOptions
28
26
 
29
27
  const VERSION = /^\d+(\.\d+)*$/
30
28