@millstone/synapse-cli 0.1.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.
Files changed (103) hide show
  1. package/README.md +135 -0
  2. package/bin/synapse.js +3 -0
  3. package/dist/commands/eject.d.ts +19 -0
  4. package/dist/commands/eject.d.ts.map +1 -0
  5. package/dist/commands/eject.js +146 -0
  6. package/dist/commands/eject.js.map +1 -0
  7. package/dist/commands/fetch-reference.d.ts +19 -0
  8. package/dist/commands/fetch-reference.d.ts.map +1 -0
  9. package/dist/commands/fetch-reference.js +93 -0
  10. package/dist/commands/fetch-reference.js.map +1 -0
  11. package/dist/commands/format.d.ts +26 -0
  12. package/dist/commands/format.d.ts.map +1 -0
  13. package/dist/commands/format.js +126 -0
  14. package/dist/commands/format.js.map +1 -0
  15. package/dist/commands/generate-pdf.d.ts +19 -0
  16. package/dist/commands/generate-pdf.d.ts.map +1 -0
  17. package/dist/commands/generate-pdf.js +140 -0
  18. package/dist/commands/generate-pdf.js.map +1 -0
  19. package/dist/commands/index.d.ts +17 -0
  20. package/dist/commands/index.d.ts.map +1 -0
  21. package/dist/commands/index.js +26 -0
  22. package/dist/commands/index.js.map +1 -0
  23. package/dist/commands/init.d.ts +58 -0
  24. package/dist/commands/init.d.ts.map +1 -0
  25. package/dist/commands/init.js +234 -0
  26. package/dist/commands/init.js.map +1 -0
  27. package/dist/commands/migrate.d.ts +29 -0
  28. package/dist/commands/migrate.d.ts.map +1 -0
  29. package/dist/commands/migrate.js +297 -0
  30. package/dist/commands/migrate.js.map +1 -0
  31. package/dist/commands/scaffold.d.ts +24 -0
  32. package/dist/commands/scaffold.d.ts.map +1 -0
  33. package/dist/commands/scaffold.js +244 -0
  34. package/dist/commands/scaffold.js.map +1 -0
  35. package/dist/commands/update.d.ts +25 -0
  36. package/dist/commands/update.d.ts.map +1 -0
  37. package/dist/commands/update.js +253 -0
  38. package/dist/commands/update.js.map +1 -0
  39. package/dist/commands/validate.d.ts +37 -0
  40. package/dist/commands/validate.d.ts.map +1 -0
  41. package/dist/commands/validate.js +526 -0
  42. package/dist/commands/validate.js.map +1 -0
  43. package/dist/index.d.ts +3 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +277 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/lib/bodyRules.d.ts +70 -0
  48. package/dist/lib/bodyRules.d.ts.map +1 -0
  49. package/dist/lib/bodyRules.js +711 -0
  50. package/dist/lib/bodyRules.js.map +1 -0
  51. package/dist/lib/config.d.ts +49 -0
  52. package/dist/lib/config.d.ts.map +1 -0
  53. package/dist/lib/config.js +91 -0
  54. package/dist/lib/config.js.map +1 -0
  55. package/dist/lib/git.d.ts +99 -0
  56. package/dist/lib/git.d.ts.map +1 -0
  57. package/dist/lib/git.js +266 -0
  58. package/dist/lib/git.js.map +1 -0
  59. package/dist/lib/graph.d.ts +6 -0
  60. package/dist/lib/graph.d.ts.map +1 -0
  61. package/dist/lib/graph.js +6 -0
  62. package/dist/lib/graph.js.map +1 -0
  63. package/dist/lib/homepage.d.ts +10 -0
  64. package/dist/lib/homepage.d.ts.map +1 -0
  65. package/dist/lib/homepage.js +172 -0
  66. package/dist/lib/homepage.js.map +1 -0
  67. package/dist/lib/markdown.d.ts +107 -0
  68. package/dist/lib/markdown.d.ts.map +1 -0
  69. package/dist/lib/markdown.js +318 -0
  70. package/dist/lib/markdown.js.map +1 -0
  71. package/dist/lib/mode-detection.d.ts +10 -0
  72. package/dist/lib/mode-detection.d.ts.map +1 -0
  73. package/dist/lib/mode-detection.js +29 -0
  74. package/dist/lib/mode-detection.js.map +1 -0
  75. package/dist/lib/naming.d.ts +47 -0
  76. package/dist/lib/naming.d.ts.map +1 -0
  77. package/dist/lib/naming.js +403 -0
  78. package/dist/lib/naming.js.map +1 -0
  79. package/dist/lib/schemas.d.ts +38 -0
  80. package/dist/lib/schemas.d.ts.map +1 -0
  81. package/dist/lib/schemas.js +248 -0
  82. package/dist/lib/schemas.js.map +1 -0
  83. package/dist/lib/templateLint.d.ts +21 -0
  84. package/dist/lib/templateLint.d.ts.map +1 -0
  85. package/dist/lib/templateLint.js +243 -0
  86. package/dist/lib/templateLint.js.map +1 -0
  87. package/dist/lib/templates.d.ts +53 -0
  88. package/dist/lib/templates.d.ts.map +1 -0
  89. package/dist/lib/templates.js +128 -0
  90. package/dist/lib/templates.js.map +1 -0
  91. package/dist/lib/tracking.d.ts +52 -0
  92. package/dist/lib/tracking.d.ts.map +1 -0
  93. package/dist/lib/tracking.js +135 -0
  94. package/dist/lib/tracking.js.map +1 -0
  95. package/dist/lib/types.generated.d.ts +54 -0
  96. package/dist/lib/types.generated.d.ts.map +1 -0
  97. package/dist/lib/types.generated.js +144 -0
  98. package/dist/lib/types.generated.js.map +1 -0
  99. package/dist/lib/validate-plugins.d.ts +22 -0
  100. package/dist/lib/validate-plugins.d.ts.map +1 -0
  101. package/dist/lib/validate-plugins.js +851 -0
  102. package/dist/lib/validate-plugins.js.map +1 -0
  103. package/package.json +85 -0
@@ -0,0 +1,248 @@
1
+ import Ajv from 'ajv';
2
+ import addFormats from 'ajv-formats';
3
+ import fsExtra from 'fs-extra';
4
+ const fs = fsExtra;
5
+ import * as path from 'path';
6
+ import { createRequire } from 'module';
7
+ import { DOC_TYPES } from './types.generated.js';
8
+ export { isDocType, DOC_TYPES } from './types.generated.js';
9
+ // Cache for compiled schemas to improve performance
10
+ const schemaCache = new Map();
11
+ /**
12
+ * Resolve the frontmatter schema directory using a cascade:
13
+ * 1. Local project override: {projectRoot}/schemas/frontmatter/
14
+ * 2. @synapse/schemas npm package
15
+ * 3. Error with helpful message
16
+ */
17
+ function getDefaultSchemaDir() {
18
+ // Priority 1: Local project override
19
+ const localPaths = [
20
+ path.resolve(process.cwd(), 'schemas/frontmatter'),
21
+ path.resolve(process.cwd(), '../schemas/frontmatter'),
22
+ path.resolve(process.cwd(), '../../schemas/frontmatter'),
23
+ ];
24
+ for (const schemaPath of localPaths) {
25
+ if (fs.existsSync(schemaPath)) {
26
+ try {
27
+ const files = fs.readdirSync(schemaPath);
28
+ const hasSchemas = files.some(f => f.endsWith('.schema.json'));
29
+ if (hasSchemas) {
30
+ return schemaPath;
31
+ }
32
+ }
33
+ catch {
34
+ continue;
35
+ }
36
+ }
37
+ }
38
+ // Priority 2: @synapse/schemas package
39
+ try {
40
+ const require = createRequire(import.meta.url);
41
+ const pkgPath = require.resolve('@synapse/schemas/package.json');
42
+ const pkgDir = path.dirname(pkgPath);
43
+ const frontmatterDir = path.join(pkgDir, 'frontmatter');
44
+ if (fs.existsSync(frontmatterDir)) {
45
+ return frontmatterDir;
46
+ }
47
+ }
48
+ catch {
49
+ // Package not installed
50
+ }
51
+ // Priority 3: Error with helpful message
52
+ throw new Error('Could not find frontmatter schemas. Either place schemas in {projectRoot}/schemas/frontmatter/ ' +
53
+ 'or install the @synapse/schemas package: npm install @synapse/schemas');
54
+ }
55
+ /**
56
+ * Load a schema for a specific document type
57
+ * Resolves $ref references to base.schema.json automatically
58
+ */
59
+ export async function loadSchema(type, dir) {
60
+ const schemaDir = dir || getDefaultSchemaDir();
61
+ const schemaPath = path.join(schemaDir, `${type}.schema.json`);
62
+ const cacheKey = `${schemaDir}:${type}`;
63
+ // Return cached schema if available
64
+ if (schemaCache.has(cacheKey)) {
65
+ return schemaCache.get(cacheKey);
66
+ }
67
+ try {
68
+ // Read the schema file
69
+ const schemaContent = await fs.readFile(schemaPath, 'utf-8');
70
+ const schema = JSON.parse(schemaContent);
71
+ // If schema has allOf with $ref to base.schema.json, resolve it
72
+ if (schema.allOf && Array.isArray(schema.allOf)) {
73
+ const resolvedAllOf = await Promise.all(schema.allOf.map(async (item) => {
74
+ if (item.$ref === 'base.schema.json') {
75
+ const basePath = path.join(schemaDir, 'base.schema.json');
76
+ const baseContent = await fs.readFile(basePath, 'utf-8');
77
+ return JSON.parse(baseContent);
78
+ }
79
+ return item;
80
+ }));
81
+ // Merge base schema properties with type-specific schema
82
+ const mergedSchema = {
83
+ ...schema,
84
+ properties: {
85
+ ...resolvedAllOf[0]?.properties || {},
86
+ ...schema.properties || {}
87
+ },
88
+ required: [
89
+ ...(resolvedAllOf[0]?.required || []),
90
+ ...(schema.required || [])
91
+ ].filter((v, i, a) => a.indexOf(v) === i) // Remove duplicates
92
+ };
93
+ // Remove allOf since we've resolved it
94
+ delete mergedSchema.allOf;
95
+ schemaCache.set(cacheKey, mergedSchema);
96
+ return mergedSchema;
97
+ }
98
+ // Cache and return schema as-is if no allOf
99
+ schemaCache.set(cacheKey, schema);
100
+ return schema;
101
+ }
102
+ catch (error) {
103
+ if (error.code === 'ENOENT') {
104
+ throw new Error(`Schema file not found for type '${type}' at path: ${schemaPath}`);
105
+ }
106
+ throw new Error(`Failed to load schema for type '${type}': ${error.message}`);
107
+ }
108
+ }
109
+ /**
110
+ * List all available schema types in the schema directory
111
+ */
112
+ export async function listSchemas(dir) {
113
+ const schemaDir = dir || getDefaultSchemaDir();
114
+ try {
115
+ const files = await fs.readdir(schemaDir);
116
+ // Filter for .schema.json files and extract type names
117
+ const schemaTypes = files
118
+ .filter(file => file.endsWith('.schema.json') && file !== 'base.schema.json')
119
+ .map(file => file.replace('.schema.json', ''))
120
+ .sort();
121
+ return schemaTypes;
122
+ }
123
+ catch (error) {
124
+ if (error.code === 'ENOENT') {
125
+ throw new Error(`Schema directory not found: ${schemaDir}`);
126
+ }
127
+ throw new Error(`Failed to list schemas: ${error.message}`);
128
+ }
129
+ }
130
+ /**
131
+ * Validate frontmatter data against a JSON schema
132
+ */
133
+ export function validateFrontmatter(data, schema) {
134
+ // Create a temporary Ajv instance for validation
135
+ // Remove the $schema property to avoid draft version conflicts
136
+ const cleanSchema = { ...schema };
137
+ delete cleanSchema.$schema;
138
+ delete cleanSchema.$id;
139
+ const ajv = new Ajv({
140
+ allErrors: true,
141
+ strict: false,
142
+ validateSchema: false // Don't validate the schema itself
143
+ });
144
+ // Add format validation support
145
+ addFormats(ajv);
146
+ try {
147
+ const validate = ajv.compile(cleanSchema);
148
+ const valid = validate(data);
149
+ if (valid) {
150
+ return { valid: true };
151
+ }
152
+ else {
153
+ // Format errors to be more human-readable
154
+ const formattedErrors = (validate.errors || []).map(error => {
155
+ const path = error.instancePath || '/';
156
+ let message = error.message || 'validation error';
157
+ // Add more context for specific error types
158
+ if (error.keyword === 'required') {
159
+ const missingProp = error.params.missingProperty;
160
+ message = `missing required property '${missingProp}'`;
161
+ }
162
+ else if (error.keyword === 'type') {
163
+ const expectedType = error.params.type;
164
+ message = `must be ${expectedType}`;
165
+ }
166
+ else if (error.keyword === 'const') {
167
+ const expectedValue = error.params.allowedValue;
168
+ message = `must be equal to constant '${expectedValue}'`;
169
+ }
170
+ return { path, message };
171
+ });
172
+ return {
173
+ valid: false,
174
+ errors: formattedErrors
175
+ };
176
+ }
177
+ }
178
+ catch (error) {
179
+ // If compilation fails, return as validation error
180
+ return {
181
+ valid: false,
182
+ errors: [{
183
+ path: '/',
184
+ message: `Schema compilation failed: ${error.message}`
185
+ }]
186
+ };
187
+ }
188
+ }
189
+ /**
190
+ * Validate that all expected document types have schemas
191
+ * Returns an object with validation results
192
+ */
193
+ export async function validateSchemasCoverage(dir) {
194
+ // Use generated DOC_TYPES instead of hardcoded list
195
+ const expectedTypes = [...DOC_TYPES];
196
+ const errors = [];
197
+ try {
198
+ const foundTypes = await listSchemas(dir);
199
+ // Check for missing schemas
200
+ const missing = expectedTypes.filter(type => !foundTypes.includes(type));
201
+ // Check for extra schemas (not in expected list)
202
+ const extra = foundTypes.filter(type => !expectedTypes.includes(type));
203
+ // Validate each schema can be loaded and compiled
204
+ for (const type of expectedTypes) {
205
+ if (foundTypes.includes(type)) {
206
+ try {
207
+ const schema = await loadSchema(type, dir);
208
+ // Basic validation that schema has required structure
209
+ if (!schema.properties) {
210
+ errors.push(`Schema for '${type}' is missing 'properties' field`);
211
+ }
212
+ if (!schema.properties.type) {
213
+ errors.push(`Schema for '${type}' is missing 'type' property definition`);
214
+ }
215
+ else if (schema.properties.type.const !== type) {
216
+ errors.push(`Schema for '${type}' has mismatched type const: expected '${type}', got '${schema.properties.type.const}'`);
217
+ }
218
+ }
219
+ catch (error) {
220
+ errors.push(`Failed to load schema for '${type}': ${error.message}`);
221
+ }
222
+ }
223
+ }
224
+ return {
225
+ success: missing.length === 0 && errors.length === 0,
226
+ coverage: {
227
+ expected: expectedTypes,
228
+ found: foundTypes,
229
+ missing,
230
+ extra
231
+ },
232
+ errors
233
+ };
234
+ }
235
+ catch (error) {
236
+ return {
237
+ success: false,
238
+ coverage: {
239
+ expected: expectedTypes,
240
+ found: [],
241
+ missing: expectedTypes,
242
+ extra: []
243
+ },
244
+ errors: [`Failed to validate schema coverage: ${error.message}`]
245
+ };
246
+ }
247
+ }
248
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/lib/schemas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { type JSONSchema } from './schemas.js';
2
+ export interface TemplateLintIssue {
3
+ type: 'error' | 'warning';
4
+ message: string;
5
+ field?: string;
6
+ line?: number;
7
+ }
8
+ export interface TemplateLintResult {
9
+ templatePath: string;
10
+ errors: TemplateLintIssue[];
11
+ warnings: TemplateLintIssue[];
12
+ }
13
+ /**
14
+ * Analyzes a template file and checks it against its schema
15
+ */
16
+ export declare function analyzeTemplate(templatePath: string, schema?: JSONSchema, schemaDir?: string): Promise<TemplateLintResult>;
17
+ /**
18
+ * Lint all templates in a directory
19
+ */
20
+ export declare function lintTemplatesDirectory(templatesDir: string, schemaDir?: string): Promise<TemplateLintResult[]>;
21
+ //# sourceMappingURL=templateLint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templateLint.d.ts","sourceRoot":"","sources":["../../src/lib/templateLint.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAO3D,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AA0ID;;GAEG;AACH,wBAAsB,eAAe,CACnC,YAAY,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,UAAU,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,kBAAkB,CAAC,CA8G7B;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAkB/B"}
@@ -0,0 +1,243 @@
1
+ import fsExtra from 'fs-extra';
2
+ const fs = fsExtra;
3
+ import * as path from 'path';
4
+ import { loadSchema } from './schemas.js';
5
+ import { isDocType } from './types.generated.js';
6
+ import { extractFrontmatter, extractPlaceholders, parseFrontmatterKeys } from './markdown.js';
7
+ // Default Handlebars helpers that are always available
8
+ const DEFAULT_HELPERS = ['now', 'each', 'unless', 'if', 'with'];
9
+ // Default Handlebars helpers that are always available
10
+ /**
11
+ * Gets the document type from the template path or frontmatter
12
+ */
13
+ function getDocTypeFromTemplate(templatePath, frontmatter) {
14
+ // Try to extract from frontmatter first
15
+ const typeMatch = frontmatter.match(/^type:\s*([a-zA-Z_]+)/m);
16
+ if (typeMatch && isDocType(typeMatch[1])) {
17
+ return typeMatch[1];
18
+ }
19
+ // Try to infer from filename
20
+ const basename = path.basename(templatePath, '.hbs').toLowerCase();
21
+ if (isDocType(basename)) {
22
+ return basename;
23
+ }
24
+ // Map common variations to doc types
25
+ const typeMap = {
26
+ 'adr': 'adr',
27
+ 'capability': 'capability',
28
+ 'policy': 'policy',
29
+ 'prd': 'prd',
30
+ 'process': 'process',
31
+ 'runbook': 'runbook',
32
+ 'sop': 'sop',
33
+ 'standard': 'standard',
34
+ 'system': 'system',
35
+ 'tdd': 'tdd'
36
+ };
37
+ return typeMap[basename] || null;
38
+ }
39
+ /**
40
+ * Gets required fields from the merged schema
41
+ */
42
+ async function getRequiredFields(type, schemaDir) {
43
+ const requiredFields = new Set();
44
+ // For custom schema directories (like in tests), bypass loadSchema to avoid caching issues
45
+ if (schemaDir && !schemaDir.includes('content/schemas')) {
46
+ try {
47
+ // Load base schema
48
+ const baseSchemaPath = path.join(schemaDir, 'base.schema.json');
49
+ if (await fs.pathExists(baseSchemaPath)) {
50
+ const baseSchema = await fs.readJSON(baseSchemaPath);
51
+ if (baseSchema.required && Array.isArray(baseSchema.required)) {
52
+ baseSchema.required.forEach((field) => requiredFields.add(field));
53
+ }
54
+ }
55
+ // Load type-specific schema
56
+ const typeSchemaPath = path.join(schemaDir, `${type}.schema.json`);
57
+ if (await fs.pathExists(typeSchemaPath)) {
58
+ const typeSchema = await fs.readJSON(typeSchemaPath);
59
+ if (typeSchema.required && Array.isArray(typeSchema.required)) {
60
+ typeSchema.required.forEach((field) => requiredFields.add(field));
61
+ }
62
+ }
63
+ }
64
+ catch (error) {
65
+ // Schema loading failed
66
+ }
67
+ return requiredFields;
68
+ }
69
+ // For production schemas, use the cached loadSchema function
70
+ try {
71
+ const schema = await loadSchema(type, schemaDir);
72
+ if (schema.required && Array.isArray(schema.required)) {
73
+ schema.required.forEach((field) => requiredFields.add(field));
74
+ }
75
+ }
76
+ catch (error) {
77
+ // Schema might not exist yet
78
+ }
79
+ return requiredFields;
80
+ }
81
+ /**
82
+ * Gets all valid properties from the merged schema
83
+ */
84
+ async function getAllSchemaProperties(type, schemaDir) {
85
+ const allProperties = new Set();
86
+ // For custom schema directories (like in tests), bypass loadSchema to avoid caching issues
87
+ if (schemaDir && !schemaDir.includes('content/schemas')) {
88
+ try {
89
+ // Load base schema properties
90
+ const baseSchemaPath = path.join(schemaDir, 'base.schema.json');
91
+ if (await fs.pathExists(baseSchemaPath)) {
92
+ const baseSchema = await fs.readJSON(baseSchemaPath);
93
+ if (baseSchema.properties) {
94
+ Object.keys(baseSchema.properties).forEach(prop => allProperties.add(prop));
95
+ }
96
+ }
97
+ // Load type-specific schema properties
98
+ const typeSchemaPath = path.join(schemaDir, `${type}.schema.json`);
99
+ if (await fs.pathExists(typeSchemaPath)) {
100
+ const typeSchema = await fs.readJSON(typeSchemaPath);
101
+ if (typeSchema.properties) {
102
+ Object.keys(typeSchema.properties).forEach(prop => allProperties.add(prop));
103
+ }
104
+ }
105
+ }
106
+ catch (error) {
107
+ // Schema loading failed
108
+ }
109
+ return allProperties;
110
+ }
111
+ // For production schemas, use the cached loadSchema function
112
+ try {
113
+ const schema = await loadSchema(type, schemaDir);
114
+ if (schema.properties) {
115
+ Object.keys(schema.properties).forEach(prop => allProperties.add(prop));
116
+ }
117
+ }
118
+ catch (error) {
119
+ // Schema might not exist yet
120
+ }
121
+ return allProperties;
122
+ }
123
+ /**
124
+ * Analyzes a template file and checks it against its schema
125
+ */
126
+ export async function analyzeTemplate(templatePath, schema, schemaDir) {
127
+ const errors = [];
128
+ const warnings = [];
129
+ try {
130
+ // Read template content
131
+ const templateContent = await fs.readFile(templatePath, 'utf-8');
132
+ // Extract frontmatter
133
+ const { frontmatter, body, startLine } = extractFrontmatter(templateContent);
134
+ if (!frontmatter) {
135
+ errors.push({
136
+ type: 'error',
137
+ message: 'Template missing frontmatter block'
138
+ });
139
+ return { templatePath, errors, warnings };
140
+ }
141
+ // Get document type
142
+ const docType = getDocTypeFromTemplate(templatePath, frontmatter);
143
+ if (!docType) {
144
+ errors.push({
145
+ type: 'error',
146
+ message: 'Unable to determine document type from template'
147
+ });
148
+ return { templatePath, errors, warnings };
149
+ }
150
+ // Check for type const in frontmatter
151
+ const typePattern = new RegExp(`^type:\\s*${docType}\\s*$`, 'm');
152
+ if (!typePattern.test(frontmatter)) {
153
+ errors.push({
154
+ type: 'error',
155
+ message: `Frontmatter missing type constant field with value '${docType}'`,
156
+ field: 'type',
157
+ line: startLine
158
+ });
159
+ }
160
+ // Parse frontmatter keys
161
+ const frontmatterKeys = parseFrontmatterKeys(frontmatter);
162
+ // Extract all placeholders from entire template
163
+ const allPlaceholders = new Set([
164
+ ...extractPlaceholders(frontmatter),
165
+ ...extractPlaceholders(body)
166
+ ]);
167
+ // Get required fields from schema
168
+ const requiredFields = await getRequiredFields(docType, schemaDir);
169
+ // Check for missing required fields
170
+ for (const requiredField of requiredFields) {
171
+ // Skip 'type' as it should be a constant
172
+ if (requiredField === 'type')
173
+ continue;
174
+ // Check if field is in frontmatter or referenced as placeholder
175
+ if (!frontmatterKeys.has(requiredField) && !allPlaceholders.has(requiredField)) {
176
+ // Special case: 'now' helper can satisfy created/updated fields
177
+ if ((requiredField === 'created' || requiredField === 'updated') &&
178
+ allPlaceholders.has('now')) {
179
+ continue;
180
+ }
181
+ warnings.push({
182
+ type: 'warning',
183
+ message: `Required schema property '${requiredField}' is neither set nor referenced in template`,
184
+ field: requiredField
185
+ });
186
+ }
187
+ }
188
+ // Get all valid schema properties
189
+ const allSchemaProperties = await getAllSchemaProperties(docType, schemaDir);
190
+ // Check for unknown placeholders
191
+ for (const placeholder of allPlaceholders) {
192
+ // Skip if it's a known helper
193
+ if (DEFAULT_HELPERS.includes(placeholder))
194
+ continue;
195
+ // Skip @-prefixed variables (Handlebars built-ins like @last, @index)
196
+ if (placeholder.startsWith('@'))
197
+ continue;
198
+ // Skip 'this' keyword
199
+ if (placeholder === 'this')
200
+ continue;
201
+ // Check if it's a valid schema property
202
+ if (!allSchemaProperties.has(placeholder)) {
203
+ warnings.push({
204
+ type: 'warning',
205
+ message: `Unknown placeholder '${placeholder}' not found in schema properties or registered helpers`,
206
+ field: placeholder
207
+ });
208
+ }
209
+ }
210
+ }
211
+ catch (error) {
212
+ errors.push({
213
+ type: 'error',
214
+ message: `Failed to analyze template: ${error instanceof Error ? error.message : String(error)}`
215
+ });
216
+ }
217
+ return {
218
+ templatePath,
219
+ errors,
220
+ warnings
221
+ };
222
+ }
223
+ /**
224
+ * Lint all templates in a directory
225
+ */
226
+ export async function lintTemplatesDirectory(templatesDir, schemaDir) {
227
+ const results = [];
228
+ try {
229
+ const templateFiles = await fs.readdir(templatesDir);
230
+ for (const file of templateFiles) {
231
+ if (file.endsWith('.hbs')) {
232
+ const templatePath = path.join(templatesDir, file);
233
+ const result = await analyzeTemplate(templatePath, undefined, schemaDir);
234
+ results.push(result);
235
+ }
236
+ }
237
+ }
238
+ catch (error) {
239
+ // Directory might not exist
240
+ }
241
+ return results;
242
+ }
243
+ //# sourceMappingURL=templateLint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templateLint.js","sourceRoot":"","sources":["../../src/lib/templateLint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import Handlebars from 'handlebars';
2
+ /**
3
+ * Register custom Handlebars helpers
4
+ */
5
+ export declare function registerHelpers(helpers: Record<string, Handlebars.HelperDelegate>): void;
6
+ /**
7
+ * Register default helpers for Synapse templates
8
+ */
9
+ export declare function registerDefaultHelpers(): void;
10
+ /**
11
+ * Compile a single Handlebars template from file path
12
+ */
13
+ export declare function compileTemplate(templatePath: string): Promise<HandlebarsTemplateDelegate>;
14
+ /**
15
+ * Render a template with provided data
16
+ */
17
+ export declare function renderTemplate(templatePath: string, data: Record<string, any>): Promise<string>;
18
+ /**
19
+ * Discover all .hbs template files in a directory
20
+ */
21
+ export declare function discoverTemplates(baseDir: string): Promise<string[]>;
22
+ /**
23
+ * Compile and validate all templates, returning a report
24
+ */
25
+ export declare function compileAllTemplates(templateDir: string): Promise<{
26
+ success: boolean;
27
+ templates: Array<{
28
+ path: string;
29
+ name: string;
30
+ compiled: boolean;
31
+ error?: string;
32
+ }>;
33
+ }>;
34
+ /**
35
+ * Get template metadata including required fields from analysis
36
+ */
37
+ export declare function getTemplateMetadata(templatePath: string): Promise<{
38
+ name: string;
39
+ path: string;
40
+ variables: string[];
41
+ helpers: string[];
42
+ }>;
43
+ declare const _default: {
44
+ compileTemplate: typeof compileTemplate;
45
+ renderTemplate: typeof renderTemplate;
46
+ registerHelpers: typeof registerHelpers;
47
+ registerDefaultHelpers: typeof registerDefaultHelpers;
48
+ discoverTemplates: typeof discoverTemplates;
49
+ compileAllTemplates: typeof compileAllTemplates;
50
+ getTemplateMetadata: typeof getTemplateMetadata;
51
+ };
52
+ export default _default;
53
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/lib/templates.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;AASpC;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,cAAc,CAAC,GAAG,IAAI,CAIxF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAoB7C;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAO/F;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACxB,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAO1E;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,KAAK,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACJ,CAAC,CA4BD;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC,CAwBD;;;;;;;;;;AAED,wBAQE"}