@platformos/platformos-check-common 0.0.17 → 0.0.18

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 (50) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/checks/index.d.ts +1 -1
  3. package/dist/checks/index.js +6 -2
  4. package/dist/checks/index.js.map +1 -1
  5. package/dist/checks/json-literal-quote-style/index.d.ts +2 -0
  6. package/dist/checks/json-literal-quote-style/index.js +42 -0
  7. package/dist/checks/json-literal-quote-style/index.js.map +1 -0
  8. package/dist/checks/liquid-html-syntax-error/checks/InvalidAssignSyntax.d.ts +21 -0
  9. package/dist/checks/liquid-html-syntax-error/checks/InvalidAssignSyntax.js +60 -0
  10. package/dist/checks/liquid-html-syntax-error/checks/InvalidAssignSyntax.js.map +1 -0
  11. package/dist/checks/liquid-html-syntax-error/checks/InvalidOutputPush.d.ts +17 -0
  12. package/dist/checks/liquid-html-syntax-error/checks/InvalidOutputPush.js +37 -0
  13. package/dist/checks/liquid-html-syntax-error/checks/InvalidOutputPush.js.map +1 -0
  14. package/dist/checks/liquid-html-syntax-error/checks/InvalidTagSyntax.js +1 -1
  15. package/dist/checks/liquid-html-syntax-error/index.js +17 -0
  16. package/dist/checks/liquid-html-syntax-error/index.js.map +1 -1
  17. package/dist/checks/partial-call-arguments/extract-undefined-variables.d.ts +14 -0
  18. package/dist/checks/partial-call-arguments/extract-undefined-variables.js +234 -0
  19. package/dist/checks/partial-call-arguments/extract-undefined-variables.js.map +1 -0
  20. package/dist/checks/partial-call-arguments/index.d.ts +2 -0
  21. package/dist/checks/partial-call-arguments/index.js +117 -0
  22. package/dist/checks/partial-call-arguments/index.js.map +1 -0
  23. package/dist/checks/valid-frontmatter/index.d.ts +2 -0
  24. package/dist/checks/valid-frontmatter/index.js +279 -0
  25. package/dist/checks/valid-frontmatter/index.js.map +1 -0
  26. package/dist/frontmatter/index.d.ts +1 -59
  27. package/dist/frontmatter/index.js +6 -298
  28. package/dist/frontmatter/index.js.map +1 -1
  29. package/dist/tsconfig.tsbuildinfo +1 -1
  30. package/package.json +2 -2
  31. package/src/checks/index.ts +6 -2
  32. package/src/checks/json-literal-quote-style/index.spec.ts +129 -0
  33. package/src/checks/json-literal-quote-style/index.ts +45 -0
  34. package/src/checks/liquid-html-syntax-error/checks/InvalidAssignSyntax.spec.ts +422 -0
  35. package/src/checks/liquid-html-syntax-error/checks/InvalidAssignSyntax.ts +63 -0
  36. package/src/checks/liquid-html-syntax-error/checks/InvalidOutputPush.spec.ts +104 -0
  37. package/src/checks/liquid-html-syntax-error/checks/InvalidOutputPush.ts +39 -0
  38. package/src/checks/liquid-html-syntax-error/checks/InvalidTagSyntax.spec.ts +86 -2
  39. package/src/checks/liquid-html-syntax-error/checks/InvalidTagSyntax.ts +1 -1
  40. package/src/checks/liquid-html-syntax-error/index.ts +19 -0
  41. package/src/checks/partial-call-arguments/extract-undefined-variables.spec.ts +218 -0
  42. package/src/checks/{metadata-params → partial-call-arguments}/extract-undefined-variables.ts +31 -6
  43. package/src/checks/partial-call-arguments/index.spec.ts +436 -0
  44. package/src/checks/{metadata-params → partial-call-arguments}/index.ts +18 -11
  45. package/src/checks/undefined-object/index.spec.ts +101 -0
  46. package/src/checks/valid-frontmatter/index.spec.ts +666 -0
  47. package/src/checks/valid-frontmatter/index.ts +344 -0
  48. package/src/frontmatter/index.ts +9 -344
  49. package/src/checks/metadata-params/extract-undefined-variables.spec.ts +0 -115
  50. package/src/checks/metadata-params/index.spec.ts +0 -257
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PartialCallArguments = void 0;
4
+ const types_1 = require("../../types");
5
+ const platformos_common_1 = require("@platformos/platformos-common");
6
+ const vscode_uri_1 = require("vscode-uri");
7
+ const path_1 = require("../../path");
8
+ const extract_undefined_variables_1 = require("./extract-undefined-variables");
9
+ exports.PartialCallArguments = {
10
+ meta: {
11
+ code: 'PartialCallArguments',
12
+ aliases: ['MetadataParamsCheck'],
13
+ name: 'Partial Call Arguments',
14
+ docs: {
15
+ description: 'Ensures that all required arguments are passed at render/function call sites, and that no unknown arguments are passed. Required vs optional is determined from the {% doc %} block when present, or inferred from undefined variables in the partial source otherwise. Variables used with | default are treated as optional.',
16
+ recommended: true,
17
+ url: 'https://documentation.platformos.com/developer-guide/platformos-check/checks/partial-call-arguments',
18
+ },
19
+ type: types_1.SourceCodeType.LiquidHtml,
20
+ severity: types_1.Severity.ERROR,
21
+ schema: {},
22
+ targets: [],
23
+ },
24
+ create(context) {
25
+ const locator = new platformos_common_1.DocumentsLocator(context.fs);
26
+ const validate = async (nodeType, targetFile, args, position) => {
27
+ const locatedFile = await locator.locate(vscode_uri_1.URI.parse(context.config.rootUri), nodeType, targetFile);
28
+ if (!locatedFile) {
29
+ return;
30
+ }
31
+ const source = await context.fs.readFile(locatedFile);
32
+ const relativePath = (0, path_1.relative)(locatedFile, context.config.rootUri);
33
+ let requiredParams;
34
+ let allowedParams;
35
+ // Check for @doc tag first — if present, it's the complete param list
36
+ const docDef = context.getDocDefinition
37
+ ? await context.getDocDefinition(relativePath)
38
+ : undefined;
39
+ if (docDef?.liquidDoc?.parameters) {
40
+ const globalObjectNames = [];
41
+ if (context.platformosDocset) {
42
+ const objects = await context.platformosDocset.objects();
43
+ for (const obj of objects) {
44
+ if (!obj.access || obj.access.global === true || obj.access.template.length > 0) {
45
+ globalObjectNames.push(obj.name);
46
+ }
47
+ }
48
+ }
49
+ const { required: undefinedRequiredVars, optional: undefinedOptionalVars } = (0, extract_undefined_variables_1.extractUndefinedVariables)(source, globalObjectNames);
50
+ const undefinedVars = [...undefinedRequiredVars, ...undefinedOptionalVars];
51
+ const docRequiredNames = docDef.liquidDoc.parameters
52
+ .filter((p) => p.required)
53
+ .map((p) => p.name);
54
+ requiredParams = docRequiredNames.filter((name) => undefinedVars.includes(name));
55
+ allowedParams = docDef.liquidDoc.parameters.map((p) => p.name);
56
+ }
57
+ else {
58
+ // No @doc — infer required vs optional from undefined variables in the source.
59
+ // Variables used with `| default` are treated as optional.
60
+ const globalObjectNames = [];
61
+ if (context.platformosDocset) {
62
+ const objects = await context.platformosDocset.objects();
63
+ for (const obj of objects) {
64
+ if (!obj.access || obj.access.global === true || obj.access.template.length > 0) {
65
+ globalObjectNames.push(obj.name);
66
+ }
67
+ }
68
+ }
69
+ if (relativePath.includes('views/partials/') || relativePath.includes('/lib/')) {
70
+ if (!globalObjectNames.includes('app')) {
71
+ globalObjectNames.push('app');
72
+ }
73
+ }
74
+ const { required: requiredVars, optional: optionalVars } = (0, extract_undefined_variables_1.extractUndefinedVariables)(source, globalObjectNames);
75
+ if (requiredVars.length === 0 && optionalVars.length === 0)
76
+ return;
77
+ requiredParams = requiredVars;
78
+ allowedParams = [...requiredVars, ...optionalVars];
79
+ }
80
+ args
81
+ .filter((arg) => !allowedParams.includes(arg.name))
82
+ .forEach((arg) => {
83
+ context.report({
84
+ message: `Unknown parameter ${arg.name} passed to ${nodeType} call`,
85
+ startIndex: arg.position.start,
86
+ endIndex: arg.position.end,
87
+ });
88
+ });
89
+ requiredParams
90
+ .filter((param) => !args.find((arg) => arg.name === param))
91
+ .forEach((param) => {
92
+ context.report({
93
+ message: `Required parameter ${param} must be passed to ${nodeType} call`,
94
+ startIndex: position.start,
95
+ endIndex: position.end,
96
+ });
97
+ });
98
+ };
99
+ return {
100
+ async RenderMarkup(node) {
101
+ const targetFile = 'value' in node.partial ? node.partial.value : node.partial.name;
102
+ if (!targetFile) {
103
+ return;
104
+ }
105
+ await validate('render', targetFile, node.args, node.position);
106
+ },
107
+ async FunctionMarkup(node) {
108
+ const targetFile = 'value' in node.partial ? node.partial.value : node.partial.name;
109
+ if (!targetFile) {
110
+ return;
111
+ }
112
+ await validate('function', targetFile, node.args, node.position);
113
+ },
114
+ };
115
+ },
116
+ };
117
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/checks/partial-call-arguments/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { LiquidCheckDefinition } from '../../types';
2
+ export declare const ValidFrontmatter: LiquidCheckDefinition;
@@ -0,0 +1,279 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ValidFrontmatter = void 0;
4
+ const yaml_1 = require("yaml");
5
+ const types_1 = require("../../types");
6
+ const platformos_common_1 = require("@platformos/platformos-common");
7
+ const file_utils_1 = require("../../utils/file-utils");
8
+ exports.ValidFrontmatter = {
9
+ meta: {
10
+ code: 'ValidFrontmatter',
11
+ name: 'Valid Frontmatter',
12
+ docs: {
13
+ description: 'Validates YAML frontmatter properties (required fields, allowed values, deprecated keys) for known platformOS file types.',
14
+ recommended: true,
15
+ url: undefined,
16
+ },
17
+ type: types_1.SourceCodeType.LiquidHtml,
18
+ severity: types_1.Severity.WARNING,
19
+ schema: {},
20
+ targets: [],
21
+ },
22
+ create(context) {
23
+ return {
24
+ async onCodePathStart(file) {
25
+ const source = file.source;
26
+ if (/(?:^|\/)home\.html\.liquid$/.test(file.uri)) {
27
+ context.report({
28
+ message: "'home.html.liquid' is deprecated. Rename to 'index.html.liquid' to serve as the root page.",
29
+ startIndex: 0,
30
+ endIndex: 0,
31
+ });
32
+ }
33
+ // Locate the frontmatter block — may be preceded by whitespace
34
+ const trimmed = source.trimStart();
35
+ if (!trimmed.startsWith('---'))
36
+ return;
37
+ const leadingLen = source.length - trimmed.length;
38
+ const firstNewline = trimmed.indexOf('\n');
39
+ if (firstNewline === -1)
40
+ return;
41
+ const afterOpening = trimmed.slice(firstNewline + 1);
42
+ // The closing `---` may be the very first line of afterOpening (empty frontmatter)
43
+ // or may follow a newline (normal frontmatter with content).
44
+ let yamlBody;
45
+ if (afterOpening.startsWith('---')) {
46
+ yamlBody = '';
47
+ }
48
+ else {
49
+ const closeIdx = afterOpening.indexOf('\n---');
50
+ if (closeIdx === -1)
51
+ return;
52
+ yamlBody = afterOpening.slice(0, closeIdx);
53
+ }
54
+ // Absolute offset of the first character of yamlBody in source
55
+ const bodyOffset = leadingLen + firstNewline + 1;
56
+ const fileType = (0, platformos_common_1.getFileType)(file.uri);
57
+ const schema = (0, platformos_common_1.getFrontmatterSchema)(fileType);
58
+ if (!schema)
59
+ return;
60
+ // Parse YAML with position tracking (yaml v2 provides range arrays).
61
+ // Continue even when the document has parse errors — parseDocument is
62
+ // lenient and still builds a partial map for the valid pairs it finds.
63
+ // Normalize CRLF → LF so YAML values don't contain stray \r characters.
64
+ const doc = (0, yaml_1.parseDocument)(yamlBody.replace(/\r\n/g, '\n').replace(/\r/g, '\n'));
65
+ const entries = new Map();
66
+ // Only populate entries when the document parsed to a map (non-empty frontmatter).
67
+ // When frontmatter is empty (`---\n---\n`) doc.contents is null — entries stays empty
68
+ // and required-field validation below will still fire correctly.
69
+ if ((0, yaml_1.isMap)(doc.contents)) {
70
+ for (const pair of doc.contents.items) {
71
+ const keyNode = pair.key;
72
+ if (!(0, yaml_1.isScalar)(keyNode) || typeof keyNode.value !== 'string')
73
+ continue;
74
+ const [ks = 0, ke = 0] = keyNode.range ?? [];
75
+ const valNode = (0, yaml_1.isScalar)(pair.value) ? pair.value : undefined;
76
+ const jsValue = valNode?.value;
77
+ const [vs = 0, ve = 0] = valNode?.range ?? [];
78
+ entries.set(keyNode.value, {
79
+ jsValue,
80
+ absStart: bodyOffset + ks,
81
+ absEnd: bodyOffset + ke,
82
+ valueAbsStart: bodyOffset + vs,
83
+ valueAbsEnd: bodyOffset + ve,
84
+ });
85
+ }
86
+ }
87
+ const frontmatterStart = leadingLen; // position of opening `---`
88
+ // 1. Required field validation
89
+ for (const [fieldName, fieldSchema] of Object.entries(schema.fields)) {
90
+ if (fieldSchema.required && !entries.has(fieldName)) {
91
+ context.report({
92
+ message: `Missing required frontmatter field '${fieldName}' in ${schema.name} file`,
93
+ startIndex: frontmatterStart,
94
+ endIndex: frontmatterStart + 3,
95
+ });
96
+ }
97
+ }
98
+ // 2. Unrecognized key warnings
99
+ for (const [key, entry] of entries) {
100
+ if (!(key in schema.fields)) {
101
+ context.report({
102
+ message: `Unknown frontmatter field '${key}' in ${schema.name} file`,
103
+ startIndex: entry.absStart,
104
+ endIndex: entry.absEnd,
105
+ });
106
+ }
107
+ }
108
+ // 3. Deprecated field warnings
109
+ for (const [key, entry] of entries) {
110
+ const fieldSchema = schema.fields[key];
111
+ if (fieldSchema?.deprecated) {
112
+ context.report({
113
+ message: fieldSchema.deprecatedMessage ?? `'${key}' is deprecated`,
114
+ startIndex: entry.absStart,
115
+ endIndex: entry.absEnd,
116
+ });
117
+ }
118
+ }
119
+ // 4. Enum validation — allowed values are defined in the schema.
120
+ // Comparison is case-insensitive for string values: both the field value and
121
+ // each enum entry are lowercased before comparing, so `GET` matches `get` etc.
122
+ for (const [key, entry] of entries) {
123
+ const fieldSchema = schema.fields[key];
124
+ if (!fieldSchema?.enumValues)
125
+ continue;
126
+ const { jsValue, absStart, absEnd } = entry;
127
+ // Skip enum validation for Liquid expressions — they're dynamic and can't be statically checked.
128
+ if (typeof jsValue === 'string' && (0, platformos_common_1.containsLiquid)(jsValue))
129
+ continue;
130
+ const normalizedValue = typeof jsValue === 'string' ? jsValue.toLowerCase() : jsValue;
131
+ const matches = fieldSchema.enumValues.some((allowed) => typeof allowed === 'string'
132
+ ? allowed.toLowerCase() === normalizedValue
133
+ : allowed === normalizedValue);
134
+ if (!matches) {
135
+ context.report({
136
+ message: `Invalid value '${jsValue}' for '${key}'. Must be one of: ${fieldSchema.enumValues.join(', ')}`,
137
+ startIndex: absStart,
138
+ endIndex: absEnd,
139
+ });
140
+ }
141
+ }
142
+ // 5. Layout association validation (Page and Email).
143
+ // Both types share the primary `layout` key; deprecated aliases differ per type.
144
+ if (fileType === platformos_common_1.PlatformOSFileType.Page || fileType === platformos_common_1.PlatformOSFileType.Email) {
145
+ const deprecatedAlias = fileType === platformos_common_1.PlatformOSFileType.Page ? 'layout_name' : 'layout_path';
146
+ const layoutEntry = entries.get('layout') ?? entries.get(deprecatedAlias);
147
+ if (layoutEntry) {
148
+ if (layoutEntry.jsValue === false) {
149
+ // `layout: false` (YAML boolean) does NOT disable the layout — it falls back to the
150
+ // instance default. Use `layout: ''` to explicitly disable layout rendering.
151
+ context.report({
152
+ message: "`layout: false` falls back to the default layout. Use `layout: ''` to disable layout rendering.",
153
+ startIndex: layoutEntry.valueAbsStart,
154
+ endIndex: layoutEntry.valueAbsEnd,
155
+ suggest: [
156
+ {
157
+ message: "Replace with `layout: ''`",
158
+ fix: (corrector) => {
159
+ corrector.replace(layoutEntry.valueAbsStart, layoutEntry.valueAbsEnd, "''");
160
+ },
161
+ },
162
+ ],
163
+ });
164
+ }
165
+ else if (typeof layoutEntry.jsValue === 'string' &&
166
+ layoutEntry.jsValue !== '' &&
167
+ !(0, platformos_common_1.containsLiquid)(layoutEntry.jsValue)) {
168
+ await checkLayoutExists(layoutEntry.jsValue, layoutEntry, context);
169
+ }
170
+ }
171
+ }
172
+ // 6. Authorization policy association validation (Page)
173
+ if (fileType === platformos_common_1.PlatformOSFileType.Page) {
174
+ await checkNotificationArray(doc, bodyOffset, 'authorization_policies', `app/${platformos_common_1.FRONTMATTER_ASSOCIATION_DIRS['authorization_policies']}`, 'Authorization policy', context);
175
+ }
176
+ // 7. Notification association validation (FormConfiguration)
177
+ if (fileType === platformos_common_1.PlatformOSFileType.FormConfiguration) {
178
+ for (const [field, dir] of Object.entries(platformos_common_1.FRONTMATTER_ASSOCIATION_DIRS)) {
179
+ if (field === 'authorization_policies')
180
+ continue; // only on Page, handled above
181
+ await checkNotificationArray(doc, bodyOffset, field, `app/${dir}`, fieldLabel(field), context);
182
+ }
183
+ }
184
+ },
185
+ };
186
+ },
187
+ };
188
+ /**
189
+ * Checks each string item of a YAML sequence field against the filesystem.
190
+ *
191
+ * App-level items (e.g. `require_login`) are looked up at `{dir}/{name}.liquid`.
192
+ * Module-prefixed items (e.g. `modules/community/require_login`) are looked up
193
+ * at modules/{mod}/{public|private}/{moduleDir}/{name}.liquid where moduleDir
194
+ * is derived from dir by stripping the leading `app/` segment.
195
+ */
196
+ async function checkNotificationArray(doc, bodyOffset, fieldName, dir, label, context) {
197
+ if (!(0, yaml_1.isMap)(doc.contents))
198
+ return;
199
+ const pair = doc.contents.items.find((p) => (0, yaml_1.isScalar)(p.key) && p.key.value === fieldName);
200
+ if (!pair || !(0, yaml_1.isSeq)(pair.value))
201
+ return;
202
+ // Module-relative dir: strip leading 'app/' (e.g. 'app/authorization_policies' → 'authorization_policies')
203
+ const moduleDir = dir.slice('app/'.length);
204
+ for (const item of pair.value.items) {
205
+ if (!(0, yaml_1.isScalar)(item) || typeof item.value !== 'string')
206
+ continue;
207
+ const name = item.value;
208
+ if ((0, platformos_common_1.containsLiquid)(name))
209
+ continue;
210
+ const [is = 0, ie = 0] = item.range ?? [];
211
+ let exists;
212
+ if (name.startsWith('modules/')) {
213
+ const match = name.match(/^modules\/([^/]+)\/(.+)$/);
214
+ if (!match) {
215
+ exists = false;
216
+ }
217
+ else {
218
+ const [, mod, rest] = match;
219
+ exists =
220
+ (await (0, file_utils_1.doesFileExist)(context, `modules/${mod}/public/${moduleDir}/${rest}.liquid`)) ||
221
+ (await (0, file_utils_1.doesFileExist)(context, `modules/${mod}/private/${moduleDir}/${rest}.liquid`));
222
+ }
223
+ }
224
+ else {
225
+ exists = await (0, file_utils_1.doesFileExist)(context, `${dir}/${name}.liquid`);
226
+ }
227
+ if (!exists) {
228
+ context.report({
229
+ message: `${label} '${name}' does not exist`,
230
+ startIndex: bodyOffset + is,
231
+ endIndex: bodyOffset + ie,
232
+ });
233
+ }
234
+ }
235
+ }
236
+ /**
237
+ * Tries both `{base}.liquid` and `{base}.html.liquid` since layout files may
238
+ * carry a format extension (e.g. `application.html.liquid`).
239
+ */
240
+ async function layoutFileExists(context, base) {
241
+ return ((await (0, file_utils_1.doesFileExist)(context, `${base}.liquid`)) ||
242
+ (await (0, file_utils_1.doesFileExist)(context, `${base}.html.liquid`)));
243
+ }
244
+ async function checkLayoutExists(layoutName, entry, context) {
245
+ let exists;
246
+ if (layoutName.startsWith('modules/')) {
247
+ // modules/{mod}/rest → modules/{mod}/{public,private}/views/layouts/{rest}.{html.}liquid
248
+ const match = layoutName.match(/^modules\/([^/]+)\/(.+)$/);
249
+ if (!match)
250
+ return;
251
+ const [, mod, rest] = match;
252
+ exists =
253
+ (await layoutFileExists(context, `modules/${mod}/public/views/layouts/${rest}`)) ||
254
+ (await layoutFileExists(context, `modules/${mod}/private/views/layouts/${rest}`));
255
+ }
256
+ else {
257
+ exists = await layoutFileExists(context, `app/views/layouts/${layoutName}`);
258
+ }
259
+ if (!exists) {
260
+ context.report({
261
+ message: `Layout '${layoutName}' does not exist`,
262
+ startIndex: entry.absStart,
263
+ endIndex: entry.absEnd,
264
+ });
265
+ }
266
+ }
267
+ function fieldLabel(field) {
268
+ switch (field) {
269
+ case 'email_notifications':
270
+ return 'Email notification';
271
+ case 'sms_notifications':
272
+ return 'SMS notification';
273
+ case 'api_call_notifications':
274
+ return 'API call notification';
275
+ default:
276
+ return field;
277
+ }
278
+ }
279
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/checks/valid-frontmatter/index.ts"],"names":[],"mappings":"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"}
@@ -1,59 +1 @@
1
- /**
2
- * Frontmatter schema definitions for platformOS Liquid file types.
3
- *
4
- * Each Liquid file type in platformOS has a YAML frontmatter section at the
5
- * top of the file that configures server-side behaviour. The schema for each
6
- * type is different — Pages have slug/layout, Emails have to/from/subject, etc.
7
- *
8
- * This module provides:
9
- * - FrontmatterFieldSchema — type definition for a single field
10
- * - FrontmatterSchema — type definition for a complete schema
11
- * - FRONTMATTER_SCHEMAS — per-type schemas keyed by PlatformOSFileType
12
- * - getFrontmatterSchema() — convenience lookup that returns undefined for
13
- * types without a frontmatter schema
14
- */
15
- import { PlatformOSFileType } from '@platformos/platformos-common';
16
- export type FrontmatterFieldType = 'string' | 'boolean' | 'integer' | 'number' | 'array' | 'object';
17
- export interface FrontmatterFieldSchema {
18
- /** The expected YAML type(s) for this field's value. */
19
- type: FrontmatterFieldType | FrontmatterFieldType[];
20
- /** Whether this field must be present. */
21
- required?: boolean;
22
- /** Human-readable description of this field. */
23
- description?: string;
24
- /** Whether this field name is deprecated in favour of a newer one. */
25
- deprecated?: boolean;
26
- /** Message shown when this deprecated field is used. */
27
- deprecatedMessage?: string;
28
- }
29
- export interface FrontmatterSchema {
30
- /** Human-readable name of the file type, used in diagnostics. */
31
- name: string;
32
- /**
33
- * Known frontmatter fields.
34
- * Checks can use this to surface unknown keys or missing required keys.
35
- */
36
- fields: Record<string, FrontmatterFieldSchema>;
37
- /**
38
- * Whether fields not listed in `fields` are allowed without a warning.
39
- * Defaults to true — schemas are additive and may not be exhaustive.
40
- */
41
- allowAdditionalFields?: boolean;
42
- }
43
- /**
44
- * Per-type frontmatter schemas.
45
- *
46
- * Only Liquid file types are present here — GraphQL, YAML, and Asset types
47
- * do not use frontmatter.
48
- *
49
- * Field lists are based on real-world usage in platformOS apps. Set
50
- * `allowAdditionalFields: true` (the default) everywhere so that apps using
51
- * custom/undocumented keys don't get false-positive warnings until the schemas
52
- * are finalised.
53
- */
54
- export declare const FRONTMATTER_SCHEMAS: Partial<Record<PlatformOSFileType, FrontmatterSchema>>;
55
- /**
56
- * Returns the frontmatter schema for a given file type, or undefined if no
57
- * schema is defined for that type (e.g. GraphQL, YAML, Asset types).
58
- */
59
- export declare function getFrontmatterSchema(fileType: PlatformOSFileType | undefined): FrontmatterSchema | undefined;
1
+ export { type FrontmatterFieldType, type FrontmatterFieldSchema, type FrontmatterSchema, FRONTMATTER_SCHEMAS, getFrontmatterSchema, } from '@platformos/platformos-common';