pdf task-h
This commit is contained in:
105
scripts/audit-placeholder-integrity.ts
Normal file
105
scripts/audit-placeholder-integrity.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import {
|
||||
createSqlClient,
|
||||
extractTemplateFields,
|
||||
getActiveTemplateVersions,
|
||||
getEffectiveMappedKeys,
|
||||
getMappingsForVersion,
|
||||
isDesignerLabelField,
|
||||
summarizeIssues,
|
||||
writeAuditArtifact
|
||||
} from './pdf-audit-utils.ts';
|
||||
|
||||
const TYPO_PATTERNS = [/lable/i, /affter/i, /__+/, /\s{2,}/];
|
||||
const RESERVED_DYNAMIC_FIELD_NAMES = new Set(['topic', 'data_topic']);
|
||||
|
||||
function detectTypo(fieldName: string) {
|
||||
return TYPO_PATTERNS.some((pattern) => pattern.test(fieldName));
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const sql = createSqlClient();
|
||||
|
||||
try {
|
||||
const templates = await getActiveTemplateVersions(sql);
|
||||
const results = [];
|
||||
|
||||
for (const template of templates) {
|
||||
const fields = extractTemplateFields(template.schemaJson);
|
||||
const { mappings } = await getMappingsForVersion(sql, template.versionId);
|
||||
const fieldNames = new Set(fields.map((field) => field.name).filter(Boolean));
|
||||
const mappedKeys = getEffectiveMappedKeys(fields, mappings);
|
||||
const tokens = [...new Set(fields.flatMap((field) => field.tokens))].sort();
|
||||
const duplicateFieldNames = [...fieldNames].filter(
|
||||
(fieldName) => fields.filter((field) => field.name === fieldName).length > 1
|
||||
);
|
||||
const typoFields = fields
|
||||
.filter((field) => field.name && detectTypo(field.name) && !isDesignerLabelField(field))
|
||||
.map((field) => field.name);
|
||||
const unmappedPlaceholders = tokens.filter(
|
||||
(token) =>
|
||||
token !== 'item_topic' &&
|
||||
!token.startsWith('topic_') &&
|
||||
!token.startsWith('item_topic_') &&
|
||||
!mappedKeys.has(token)
|
||||
);
|
||||
const deadMappings = mappings
|
||||
.filter(
|
||||
(mapping) =>
|
||||
!fieldNames.has(mapping.placeholderKey) &&
|
||||
!tokens.includes(mapping.placeholderKey) &&
|
||||
mapping.placeholderKey !== 'items_table'
|
||||
)
|
||||
.map((mapping) => mapping.placeholderKey);
|
||||
const invalidReservedMappings = mappings
|
||||
.filter(
|
||||
(mapping) =>
|
||||
mapping.placeholderKey.startsWith('topic_') ||
|
||||
mapping.placeholderKey.startsWith('item_topic_')
|
||||
)
|
||||
.map((mapping) => mapping.placeholderKey);
|
||||
const missingReservedFields = [...RESERVED_DYNAMIC_FIELD_NAMES].filter(
|
||||
(name) => !fieldNames.has(name)
|
||||
);
|
||||
const status = summarizeIssues([
|
||||
duplicateFieldNames.length ? 'FAIL' : 'PASS',
|
||||
typoFields.length ? 'FAIL' : 'PASS',
|
||||
unmappedPlaceholders.length ? 'FAIL' : 'PASS',
|
||||
deadMappings.length ? 'FAIL' : 'PASS',
|
||||
invalidReservedMappings.length ? 'FAIL' : 'PASS',
|
||||
missingReservedFields.length ? 'FAIL' : 'PASS'
|
||||
]);
|
||||
|
||||
results.push({
|
||||
templateName: template.templateName,
|
||||
organizationId: template.organizationId,
|
||||
version: template.version,
|
||||
duplicateFieldNames,
|
||||
typoFields,
|
||||
unmappedPlaceholders,
|
||||
deadMappings,
|
||||
invalidReservedMappings,
|
||||
missingReservedFields,
|
||||
status
|
||||
});
|
||||
}
|
||||
|
||||
const overallStatus = summarizeIssues(
|
||||
results.map((result) => result.status) as Array<'PASS' | 'WARNING' | 'FAIL'>
|
||||
);
|
||||
const report = {
|
||||
audit: 'placeholder-integrity',
|
||||
overallStatus,
|
||||
results
|
||||
};
|
||||
const artifactPath = await writeAuditArtifact('placeholder-integrity-report.json', report);
|
||||
|
||||
console.log(JSON.stringify({ ...report, artifactPath }, null, 2));
|
||||
} finally {
|
||||
await sql.end({ timeout: 5 });
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(`[audit-placeholder-integrity] ${error.message}`);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user