#! /usr/bin/env ts-node
import * as __typia_transform__assertGuard from "typia/lib/internal/_assertGuard.js";
import * as __typia_transform__accessExpressionAsString from "typia/lib/internal/_accessExpressionAsString.js";
import * as fs from 'fs';
import * as path from 'path';
import * as typia from 'typia';
/*
 * Populated in `main` function
 */
let oidSchema;
// --- Utility Functions ---
function oidArrayToString(oid) {
    return (oid.join('.'));
}
function toConstantCase(str) {
    return (str.replace(/[A-Z]/g, function (part) {
        return (`_${part}`);
    }).toUpperCase());
}
function toPascalCase(str) {
    return (str.split(/[_-]/).map(function (part) {
        return (part.charAt(0).toUpperCase() + part.slice(1));
    }).join(''));
}
function toSnakeCase(str) {
    return (str.replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, ''));
}
// --- Type Resolution ---
function resolveTypeReference(typeName) {
    if (typeName.startsWith('SEQUENCE OF ')) {
        return (`${resolveTypeReference(typeName.substring('SEQUENCE OF '.length).trim())}[]`);
    }
    switch (typeName.trim()) {
        case 'UTF8String':
        case 'Utf8String':
            return ('string');
        case 'GeneralizedTime':
            return ('Date');
        case 'ENUMERATED':
            return ('string');
        case 'OBJECT IDENTIFIER':
            return ('ASN1.ASN1OID');
        case 'OCTET STRING':
            return ('Buffer');
        default:
            return (toPascalCase(typeName));
    }
}
function resolveToBaseType(typeName) {
    typeName = typeName.trim();
    // Check if it's a primitive type first
    if (/^(UTF8String|Utf8String|GeneralizedTime)$/i.test(typeName)) {
        return (typeName);
    }
    // Check if it's defined as a sensitive attribute
    const sensitiveAttr = oidSchema.sensitive_attributes[typeName] ?? Object.values(oidSchema.sensitive_attributes).find(function (attr) {
        return (attr.token === typeName);
    });
    if (sensitiveAttr && !sensitiveAttr.fields && !sensitiveAttr.choices) {
        if (sensitiveAttr.type === undefined) {
            throw (new Error(`Sensitive attribute ${typeName} has no defined type.`));
        }
        return (resolveToBaseType(sensitiveAttr.type));
    }
    // Check if it's an ISO20022 primitive
    const primitive = oidSchema.iso20022_types.primitives[typeName];
    if (primitive) {
        return (resolveToBaseType(primitive.type));
    }
    // Otherwise return as-is
    return (typeName);
}
function isEnumerationType(typeName) {
    const normalized = toSnakeCase(typeName);
    return (Boolean(oidSchema.iso20022_types.enumerations[typeName] ??
        oidSchema.iso20022_types.enumerations[normalized]));
}
function isSequenceOfChoice(config) {
    const hasFields = config.fields && Object.keys(config.fields).length > 0;
    const allOptional = hasFields && Object.values(config.fields).every(function (field) {
        return (field.optional);
    });
    return (allOptional);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function _ignore_getPrimitiveType(type) {
    if (type === 'UTF8String' || type === 'Utf8String') {
        return ('string');
    }
    if (type === 'GeneralizedTime') {
        return ('date');
    }
    return ('string');
}
// --- Output Generators ---
function genHeader(comment) {
    return ([
        '/* eslint-disable */',
        '/**',
        ` * ${comment}`,
        ' * This file is auto-generated from oids.json.',
        ' */',
        ''
    ].join('\n'));
}
function genTypeAlias(name, type, description, oid) {
    return (`/** ${description} */\n/** OID: ${oid} */\nexport type ${name} = ${type};\n`);
}
function genEnumType(name, values, description, oid) {
    return (`/** ${description} */\n/** OID: ${oid} */\nexport type ${name} = ${values.map(function (value) {
        return (`'${value}'`);
    }).join(' | ')};\n`);
}
function genInterface(name, fields, description, oid) {
    const fieldLines = Object.entries(fields).map(function ([fieldName, fieldConfig]) {
        return (`\t${fieldName}${fieldConfig.optional ? '?' : ''}: ${resolveTypeReference(fieldConfig.type)};`);
    });
    return (`/** ${description} */\n/** OID: ${oid} */\nexport interface ${name} {\n${fieldLines.join('\n')}\n}\n`);
}
// Generate TypeScript **types** for sequence-of-choice
function genSequenceOfChoiceTypes(name, config) {
    const typeName = toPascalCase(name);
    const fieldOrder = config.field_order ?? Object.keys(config.fields);
    const choiceEntries = fieldOrder.map(function (fieldName) {
        if (!(fieldName in config.fields) || config.fields[fieldName] === undefined) {
            throw (new Error(`Field ${fieldName} not found in sequence of choice ${name}`));
        }
        return ([fieldName, config.fields[fieldName]]);
    });
    const choiceTypes = choiceEntries.map(function ([fieldName, fieldConfig], index) {
        if (fieldConfig === undefined) {
            throw (new Error(`Field ${fieldName} not found in sequence of choice ${name}`));
        }
        const fieldType = resolveTypeReference(fieldConfig.type);
        const choiceTypeName = `${typeName}${toPascalCase(fieldName)}Choice`;
        return ({
            code: `export interface ${choiceTypeName} {\n\ttag: ${index};\n\tname: '${fieldName}';\n\tvalue: ${fieldType};\n}\n`,
            name: choiceTypeName
        });
    });
    let out = '';
    // Individual choice interfaces
    out += choiceTypes.map(function (choiceInfo) {
        return (choiceInfo.code);
    }).join('\n');
    // Union type
    out += `export type ${typeName}Choice =\n\t| ${choiceTypes.map(function (choiceInfo) {
        return (choiceInfo.name);
    }).join('\n\t| ')};\n\n`;
    // Main type is array of choices
    out += `export type ${typeName} = ${typeName}Choice[];\n\n`;
    return (out);
}
// Generate ASN.1 **schema** for sequence-of-choice
function genSequenceOfChoiceSchema(name, config) {
    const typeName = toPascalCase(name);
    const fieldOrder = config.field_order ?? Object.keys(config.fields);
    const choiceEntries = fieldOrder.map(function (fieldName) {
        if (!(fieldName in config.fields) || config.fields[fieldName] === undefined) {
            throw (new Error(`Field ${fieldName} not found in sequence of choice ${name}`));
        }
        return ([fieldName, config.fields[fieldName]]);
    });
    let out = '';
    // ASN.1 schema
    out += `/** ASN.1 schema for ${typeName} */\n`;
    out += `export const ${typeName}Schema: ASN1.Schema = {\n\tsequenceOf: {\n\t\tchoice: [\n`;
    out += choiceEntries.map(function ([fieldName, fieldConfig], index) {
        if (fieldConfig === undefined) {
            throw (new Error(`Field ${fieldName} not found in sequence of choice ${name}`));
        }
        // Determine the type for this choice
        let fieldType = fieldConfig.type.trim();
        if (fieldType.startsWith('SEQUENCE OF ')) {
            fieldType = fieldType.substring('SEQUENCE OF '.length).trim();
        }
        fieldType = fieldType.replace(/\[\]$/, '');
        const fieldTypePascal = toPascalCase(fieldType);
        const fieldTypeSnake = toSnakeCase(fieldType);
        // Check if this is a complex type that has a schema
        const isChoice = oidSchema.iso20022_types.choices[fieldTypeSnake] ?? oidSchema.iso20022_types.choices[fieldType];
        const isSequence = oidSchema.iso20022_types.sequences[fieldTypeSnake] ?? oidSchema.iso20022_types.sequences[fieldType];
        const isSensitiveSequence = oidSchema.sensitive_attributes[fieldTypeSnake]?.fields;
        const isSensitiveChoice = oidSchema.sensitive_attributes[fieldTypeSnake]?.choices;
        const hasSchema = isChoice ?? isSequence ?? isSensitiveSequence ?? isSensitiveChoice;
        let contains;
        if (hasSchema) {
            contains = `${fieldTypePascal}Schema`;
        }
        else {
            // Primitive type
            contains = `{ type: 'string', kind: 'utf8' }`;
        }
        return (`\t\t\t{ type: 'context', kind: 'explicit', value: ${index}, contains: ${contains} }`);
    }).join(',\n');
    out += `\n\t\t]\n\t}\n};\n\n`;
    // Field names array
    out += `export const ${typeName}Fields = [\n${fieldOrder.map(function (fieldName) {
        return (`\t'${fieldName}'`);
    }).join(',\n')}\n] as const;\n\n`;
    return (out);
}
function deleteLastCommaIfFoundGenerator(lines) {
    return (function deleteLastCommaIfFound() {
        let lastLine = lines.pop();
        if (lastLine === undefined) {
            return;
        }
        if (lastLine.endsWith(',')) {
            lastLine = lastLine.slice(0, -1);
        }
        lines.push(lastLine);
    });
}
// --- Main Generation ---
function generateOidConstants() {
    const lines = [genHeader('Generated OID Constants')];
    const deleteLastCommaIfFound = deleteLastCommaIfFoundGenerator(lines);
    // Algorithm OID constants
    lines.push('// Algorithm OID constants');
    for (const [name, oid] of Object.entries(oidSchema.algorithms)) {
        lines.push(`export const ${toConstantCase(name.replace(/-/g, '_'))} = '${oidArrayToString(oid)}';`);
    }
    lines.push('');
    // Plain attribute OID constants
    lines.push('// Plain attribute OID constants');
    for (const [name, config] of Object.entries(oidSchema.plain_attributes)) {
        lines.push(`/** ${config.description} */`);
        lines.push(`/** @see ${config.reference} */`);
        lines.push(`export const ${toConstantCase(name)} = '${oidArrayToString(config.oid)}';`);
    }
    lines.push('');
    // Keeta namespace for sensitive attributes
    lines.push('// Keeta-specific OID constants');
    lines.push('// eslint-disable-next-line @typescript-eslint/no-namespace');
    lines.push('export namespace keeta {');
    for (const [name, config] of Object.entries(oidSchema.extensions)) {
        lines.push(`\t/** ${config.description} */`);
        if (config.reference) {
            lines.push(`\t/** @see ${config.reference} */`);
        }
        if (config.oid) {
            lines.push(`\texport const ${toConstantCase(name)} = '${oidArrayToString(config.oid)}';`);
        }
    }
    for (const [name, config] of Object.entries(oidSchema.sensitive_attributes)) {
        lines.push(`\t/** ${config.description} */`);
        lines.push(`\t/** @see ${config.reference} */`);
        lines.push(`\texport const ${toConstantCase(name)} = '${oidArrayToString(config.oid)}';`);
    }
    lines.push('}');
    lines.push('');
    // Lookup maps
    lines.push('// OID to name lookup maps');
    lines.push('export const OID_TO_NAME: { [key: string]: string } = {');
    for (const [name, config] of Object.entries({
        ...oidSchema.plain_attributes,
        ...oidSchema.sensitive_attributes
    })) {
        lines.push(`\t'${oidArrayToString(config.oid)}': '${name}',`);
    }
    deleteLastCommaIfFound();
    lines.push('};');
    lines.push('');
    lines.push('export const NAME_TO_OID: { [key: string]: string } = {');
    for (const [name, config] of Object.entries({
        ...oidSchema.plain_attributes,
        ...oidSchema.sensitive_attributes
    })) {
        lines.push(`\t'${name}': '${oidArrayToString(config.oid)}',`);
    }
    deleteLastCommaIfFound();
    lines.push('};');
    lines.push('');
    return (lines.join('\n'));
}
function genSequenceSchema(typeName, fields, config) {
    const fieldOrder = config?.field_order ?? Object.keys(fields);
    const structFields = {};
    for (const fname of fieldOrder) {
        const fcfg = fields[fname];
        if (!fcfg) {
            continue;
        }
        // Resolve to base type to handle aliases
        const baseType = resolveToBaseType(fcfg.type);
        let fieldSchema;
        let isChoiceType = false;
        // Check if field type is GeneralizedTime (date)
        if (baseType === 'GeneralizedTime') {
            fieldSchema = 'ASN1.ValidateASN1.IsDate';
        }
        else {
            // Check if this is a SEQUENCE OF type directly or via type reference
            let fieldType = baseType.trim();
            const isSequenceOf = fieldType.startsWith('SEQUENCE OF ');
            if (isSequenceOf) {
                fieldType = fieldType.substring('SEQUENCE OF '.length).trim();
            }
            fieldType = fieldType.replace(/\[\]$/, '');
            const fieldTypePascal = toPascalCase(fieldType);
            const fieldTypeSnake = toSnakeCase(fieldType);
            // Check if this is a COMPLEX type (not a primitive)
            const isChoice = oidSchema.iso20022_types.choices[fieldTypeSnake] ?? oidSchema.iso20022_types.choices[fieldType];
            const isSequence = oidSchema.iso20022_types.sequences[fieldTypeSnake] ?? oidSchema.iso20022_types.sequences[fieldType];
            const isSensitiveSequence = oidSchema.sensitive_attributes[fieldTypeSnake]?.fields;
            const isSensitiveChoice = oidSchema.sensitive_attributes[fieldTypeSnake]?.choices;
            const isExtension = oidSchema.extensions[fieldTypeSnake]?.fields ?? oidSchema.extensions[fieldType]?.fields;
            const hasSchema = isChoice ?? isSequence ?? isSensitiveSequence ?? isSensitiveChoice ?? isExtension;
            isChoiceType = !!(isChoice ?? isSensitiveChoice);
            if (hasSchema) {
                fieldSchema = `${fieldTypePascal}Schema`;
            }
            else {
                // Primitive type - use inline schema
                if (fieldType === 'OBJECT IDENTIFIER') {
                    fieldSchema = `ASN1.ValidateASN1.IsOID`;
                }
                else if (fieldType === 'OCTET STRING') {
                    fieldSchema = `ASN1.ValidateASN1.IsOctetString`;
                }
                else {
                    fieldSchema = `{ type: 'string', kind: 'utf8' }`;
                }
            }
            // Wrap in sequenceOf if this was a SEQUENCE OF type
            if (isSequenceOf) {
                fieldSchema = `{ sequenceOf: ${fieldSchema} }`;
            }
        }
        // Store field metadata
        structFields[fname] = {
            schema: fieldSchema,
            optional: fcfg.optional ?? false,
            isChoice: isChoiceType
        };
    }
    // Check if ANY field is optional - if so, ALL fields need context tags for proper ordering
    const hasAnyOptionalField = fieldOrder.some(function (fname) {
        const fieldInfo = structFields[fname];
        return (fieldInfo?.optional ?? false);
    });
    const containsObject = fieldOrder.map(function (fname, index) {
        const fieldInfo = structFields[fname];
        if (!fieldInfo) {
            throw (new Error(`Field ${fname} not found in structFields`));
        }
        const baseSchema = fieldInfo.schema;
        const isOptional = fieldInfo.optional;
        const isChoiceField = fieldInfo.isChoice;
        if (hasAnyOptionalField && !isChoiceField) {
            const wrappedInContext = `{ type: 'context', kind: 'explicit', value: ${index}, contains: ${baseSchema} }`;
            if (isOptional) {
                return (`\t\t${fname}: { optional: ${wrappedInContext} }`);
            }
            else {
                return (`\t\t${fname}: ${wrappedInContext}`);
            }
        }
        else if (isOptional) {
            return (`\t\t${fname}: { optional: ${baseSchema} }`);
        }
        else {
            return (`\t\t${fname}: ${baseSchema}`);
        }
    }).join(',\n');
    return (`export const ${typeName}Schema: ASN1.Schema = {\n\ttype: 'struct',\n\tfieldNames: [${fieldOrder.map(f => `'${f}'`).join(', ')}],\n\tcontains: {\n${containsObject}\n\t}\n};`);
}
function generateIso20022Types() {
    const lines = [
        genHeader('Generated ISO20022 Type Definitions'),
        "import * as ASN1 from '../../lib/utils/asn1.js';",
        "import { lib as KeetaNetLib } from '@keetanetwork/keetanet-client';",
        'type KeetaNetAccount = InstanceType<typeof KeetaNetLib.Account>;',
        ''
    ];
    const deleteLastCommaIfFound = deleteLastCommaIfFoundGenerator(lines);
    // Primitives
    lines.push('// ISO20022 Primitive Types');
    for (const [name, config] of Object.entries(oidSchema.iso20022_types.primitives)) {
        lines.push(genTypeAlias(toPascalCase(name), resolveTypeReference(config.type), config.description, oidArrayToString(config.oid)));
    }
    // Enumerations
    lines.push('// ISO20022 Enumeration Types');
    for (const [name, config] of Object.entries(oidSchema.iso20022_types.enumerations)) {
        lines.push(genEnumType(toPascalCase(name), config.values, config.description, oidArrayToString(config.oid)));
    }
    // Choices
    lines.push('// ISO20022 Choice Types');
    for (const [name, config] of Object.entries(oidSchema.iso20022_types.choices)) {
        const typeName = toPascalCase(name);
        const choices = Object.entries(config.choices ?? {});
        const hasComplexTypes = choices.some(function ([_ignore_choiceName, choiceConfig]) {
            const choiceType = choiceConfig.type.trim();
            return (choiceType !== 'UTF8String' && choiceType !== 'string');
        });
        if (hasComplexTypes) {
            const unionTypes = Array.from(new Set(choices.map(function ([_ignore_choiceName, choiceConfig]) {
                return (resolveTypeReference(choiceConfig.type.trim()));
            })));
            lines.push(genTypeAlias(typeName, unionTypes.join(' | '), config.description, oidArrayToString(config.oid)));
        }
        else {
            lines.push(genTypeAlias(typeName, 'string', config.description, oidArrayToString(config.oid)));
        }
    }
    // ISO20022 Sequences and Sequence-of-Choice Types
    lines.push('// ISO20022 Sequence Types');
    for (const [name, config] of Object.entries(oidSchema.iso20022_types.sequences)) {
        if (isSequenceOfChoice(config)) {
            lines.push(genSequenceOfChoiceTypes(name, config));
        }
        else {
            lines.push(genInterface(toPascalCase(name), config.fields, config.description, oidArrayToString(config.oid)));
        }
    }
    lines.push('');
    // --- Choice Type Schemas ---
    lines.push('// Generated ASN.1 schemas for ISO 20022 choice types');
    for (const [name, config] of Object.entries(oidSchema.iso20022_types.choices)) {
        const typeName = toPascalCase(name);
        const choices = Object.entries(config.choices ?? {});
        lines.push(`/** ASN.1 schema for ${typeName} */`);
        if (choices.length === 0) {
            // No choices defined - simple string schema
            lines.push(`export const ${typeName}Schema: ASN1.Schema = { type: 'string', kind: 'utf8' };`);
        }
        else {
            // Generate choice schema with context tags to make them differentiable
            const choiceSchemas = choices.map(function ([_ignore_choiceName, choiceConfig], index) {
                const choiceType = choiceConfig.type.trim();
                let containsSchema;
                // Check if it is a primitive type
                if (choiceType === 'UTF8String' || choiceType === 'Utf8String' || choiceType === 'string' || isEnumerationType(choiceType)) {
                    containsSchema = `{ type: 'string', kind: 'utf8' }`;
                }
                else {
                    // Complex type - reference its schema
                    const choiceTypeName = toPascalCase(choiceType);
                    containsSchema = `${choiceTypeName}Schema`;
                }
                // Wrap in context tag to make it differentiable
                return (`{ type: 'context', kind: 'explicit', value: ${index}, contains: ${containsSchema} }`);
            });
            lines.push(`export const ${typeName}Schema: ASN1.Schema = {`);
            lines.push(`\tchoice: [`);
            lines.push(`\t\t${choiceSchemas.join(',\n\t\t')}`);
            lines.push(`\t]`);
            lines.push(`};`);
        }
        lines.push('');
    }
    // --- Regular Sequence Type Schemas (SECOND - may depend on choice schemas) ---
    lines.push('// Generated ASN.1 schemas for ISO 20022 regular sequence types');
    for (const [name, config] of Object.entries(oidSchema.iso20022_types.sequences)) {
        const typeName = toPascalCase(name);
        if (config.fields && !isSequenceOfChoice(config)) {
            lines.push(`/** ASN.1 schema for ${typeName} */`);
            lines.push(genSequenceSchema(typeName, config.fields, config));
            lines.push('');
        }
    }
    // --- Sequence-of-Choice Type Schemas (THIRD - depend on regular sequence schemas) ---
    lines.push('// Generated ASN.1 schemas for ISO 20022 sequence-of-choice types');
    for (const [name, config] of Object.entries(oidSchema.iso20022_types.sequences)) {
        if (isSequenceOfChoice(config)) {
            lines.push(genSequenceOfChoiceSchema(name, config));
        }
    }
    // --- Choice-Type Sensitive Attribute Schemas ---
    lines.push('// Generated ASN.1 schemas for choice-type sensitive attributes');
    for (const [name, config] of Object.entries(oidSchema.sensitive_attributes)) {
        const typeName = toPascalCase(name);
        if (config.choices) {
            const choiceSchemas = Object.values(config.choices).map(function (choice) {
                const choiceTypeName = toPascalCase(choice.type.trim());
                return (`${choiceTypeName}Schema`);
            });
            lines.push(`/** ASN.1 schema for ${typeName} */`);
            lines.push(`export const ${typeName}Schema: ASN1.Schema = {`);
            lines.push(`\tchoice: [`);
            lines.push(`\t\t${choiceSchemas.join(',\n\t\t')}`);
            lines.push(`\t]`);
            lines.push(`};`);
            lines.push('');
        }
    }
    // Sensitive Attribute Types
    for (const [name, config] of Object.entries(oidSchema.sensitive_attributes)) {
        const typeName = toPascalCase(name);
        if (!config.fields && !config.choices) {
            // Primitive type
            let baseType;
            if (config.type === 'UTF8String' || config.type === 'Utf8String') {
                baseType = 'string';
            }
            else if (config.type === 'GeneralizedTime') {
                baseType = 'Date';
            }
            else {
                if (config.type === undefined) {
                    throw (new Error(`Sensitive attribute ${name} has no defined type.`));
                }
                baseType = toPascalCase(config.type);
            }
            lines.push(`/** ${config.description} */`);
            lines.push(`/** OID: ${oidArrayToString(config.oid)} */`);
            lines.push(`export type ${typeName} = ${baseType};`);
            lines.push('');
        }
        else if (config.fields) {
            // Sequence type
            lines.push(`/** ${config.description} */`);
            lines.push(`/** OID: ${oidArrayToString(config.oid)} */`);
            lines.push(`export interface ${typeName} {`);
            for (const [fieldName, fieldConfig] of Object.entries(config.fields)) {
                const optional = fieldConfig.optional ? '?' : '';
                const resolvedType = resolveTypeReference(fieldConfig.type);
                lines.push(`\t${fieldName}${optional}: ${resolvedType};`);
            }
            lines.push('}');
            lines.push('');
        }
        else if (config.choices) {
            // Choice type
            lines.push(`/** ${config.description} */`);
            lines.push(`/** OID: ${oidArrayToString(config.oid)} */`);
            const hasComplexTypes = Object.values(config.choices).some(function (choice) {
                const choiceType = choice.type.trim();
                return (choiceType !== 'UTF8String' && choiceType !== 'string');
            });
            if (hasComplexTypes) {
                const unionTypes = Object.values(config.choices).map(function (choice) {
                    return (toPascalCase(choice.type.trim()));
                });
                lines.push(`export type ${typeName} = ${unionTypes.join(' | ')};`);
            }
            else {
                lines.push(`export type ${typeName} = string;`);
            }
            lines.push('');
        }
    }
    // Extension Types with fields
    for (const [name, config] of Object.entries(oidSchema.extensions)) {
        if (config.fields) {
            const typeName = toPascalCase(name);
            lines.push(`/** ${config.description} */`);
            if (config.oid) {
                lines.push(`/** OID: ${oidArrayToString(config.oid)} */`);
            }
            lines.push(`export interface ${typeName} {`);
            for (const [fieldName, fieldConfig] of Object.entries(config.fields)) {
                const optional = fieldConfig.optional ? '?' : '';
                const resolvedType = resolveTypeReference(fieldConfig.type);
                lines.push(`\t${fieldName}${optional}: ${resolvedType};`);
            }
            /*
             * The "Reference" type is a special case where we inject
             * some additional attributes when decoding.
             */
            if (typeName === 'Reference') {
                lines.push('\t/**');
                lines.push('\t * TODOC');
                lines.push('\t */');
                lines.push('\t$blob: (principals?: KeetaNetAccount[]) => Promise<Blob>;');
            }
            lines.push('}');
            lines.push('');
            // Schema
            lines.push(genSequenceSchema(typeName, config.fields, config));
            lines.push('');
        }
    }
    // Token aliases for sensitive attributes
    lines.push('// Token aliases for sensitive attributes');
    for (const [name, config] of Object.entries(oidSchema.sensitive_attributes)) {
        if (config.token && config.token !== toPascalCase(name)) {
            const typeName = toPascalCase(name);
            const tokenName = config.token;
            lines.push(`/** Alias for ${typeName} */`);
            lines.push(`export type ${tokenName} = ${typeName};`);
            lines.push('');
        }
    }
    // Union type, value map, helper generic
    lines.push('/** Union type of all sensitive attribute types */');
    lines.push('export type SensitiveAttributeType =');
    lines.push(Object.keys(oidSchema.sensitive_attributes).map(function (name) {
        return (`\t| ${toPascalCase(name)}`);
    }).join('\n') + ';');
    lines.push('');
    lines.push('/** Map of attribute name to acceptable input type for CertificateBuilder.setAttribute */');
    lines.push('export interface CertificateAttributeValueMap {');
    for (const [name] of Object.entries(oidSchema.sensitive_attributes)) {
        lines.push(`\t'${name}': ${toPascalCase(name)};`);
    }
    lines.push('}');
    lines.push('');
    lines.push('/** Helper generic to get attribute value type by name */');
    lines.push('export type CertificateAttributeValue<Name extends keyof CertificateAttributeValueMap> = CertificateAttributeValueMap[Name];');
    lines.push('');
    // Field arrays and schemas for sequence types
    // Sort to ensure dependencies are defined before they're used
    const sensitiveAttrEntries = Object.entries(oidSchema.sensitive_attributes);
    const sortedEntries = [];
    const processed = new Set();
    function hasDependency(config, depName) {
        if (!config.fields) {
            return (false);
        }
        return (Object.values(config.fields).some(field => {
            const fieldType = field.type.trim();
            return (fieldType === toPascalCase(depName) || fieldType === depName);
        }));
    }
    // Process entries, dependencies first
    while (sortedEntries.length < sensitiveAttrEntries.length) {
        for (const [name, config] of sensitiveAttrEntries) {
            if (processed.has(name)) {
                continue;
            }
            // Check if all dependencies are processed
            let allDepsProcessed = true;
            if (config.fields) {
                for (const [otherName] of sensitiveAttrEntries) {
                    if (otherName === name || processed.has(otherName)) {
                        continue;
                    }
                    if (hasDependency(config, otherName)) {
                        allDepsProcessed = false;
                        break;
                    }
                }
            }
            if (allDepsProcessed) {
                sortedEntries.push([name, config]);
                processed.add(name);
            }
        }
    }
    for (const [name, config] of sortedEntries) {
        const typeName = toPascalCase(name);
        if (config.fields) {
            const fieldOrder = config.field_order ?? Object.keys(config.fields);
            lines.push(`export const ${typeName}Fields = [${fieldOrder.map(function (field) {
                return (`'${field}'`);
            }).join(', ')}] as const;`);
            lines.push(genSequenceSchema(typeName, config.fields, config));
        }
    }
    // OID DB
    lines.push('export const CertificateAttributeOIDDB = {');
    for (const [name, config] of Object.entries(oidSchema.sensitive_attributes)) {
        lines.push(`\t'${name}': '${oidArrayToString(config.oid)}',`);
    }
    deleteLastCommaIfFound();
    lines.push('} as const;');
    lines.push('');
    // Sensitive attribute list
    lines.push('export const SENSITIVE_CERTIFICATE_ATTRIBUTES = [');
    for (const name of Object.keys(oidSchema.sensitive_attributes)) {
        lines.push(`\t'${name}',`);
    }
    deleteLastCommaIfFound();
    lines.push('] as const;');
    lines.push('');
    lines.push('export type SensitiveCertificateAttributeNames = typeof SENSITIVE_CERTIFICATE_ATTRIBUTES[number];');
    lines.push('');
    // PascalCase names
    lines.push('export const SensitiveCertificateAttributeNames = [');
    for (const name of Object.keys(oidSchema.sensitive_attributes)) {
        lines.push(`\t'${toPascalCase(name)}',`);
    }
    deleteLastCommaIfFound();
    lines.push('] as const;');
    lines.push('');
    // Field name mapping
    lines.push('export const CertificateAttributeFieldNames: { readonly [K in keyof typeof CertificateAttributeOIDDB]?: readonly string[] } = {');
    for (const [name, config] of Object.entries(oidSchema.sensitive_attributes)) {
        if (config.fields) {
            const typeName = toPascalCase(name);
            lines.push(`\t'${name}': ${typeName}Fields,`);
        }
    }
    deleteLastCommaIfFound();
    lines.push('} as const;');
    lines.push('');
    // Complete schema mapping (ONCE, at the end)
    lines.push('export const CertificateAttributeSchema: { readonly [K in keyof typeof CertificateAttributeOIDDB]: ASN1.Schema } = {');
    for (const [name, config] of Object.entries(oidSchema.sensitive_attributes)) {
        const typeName = toPascalCase(name);
        let schemaRef;
        if (config.fields) {
            schemaRef = `${typeName}Schema`;
        }
        else if (config.choices) {
            schemaRef = `${typeName}Schema`;
        }
        else {
            if (config.type === undefined) {
                throw (new Error(`Sensitive attribute ${name} has no defined type.`));
            }
            const baseType = resolveToBaseType(config.type);
            const baseTypeSnake = toSnakeCase(baseType);
            const isExtensionType = oidSchema.extensions[baseTypeSnake]?.fields ?? oidSchema.extensions[baseType]?.fields;
            const isSensitiveType = oidSchema.sensitive_attributes[toSnakeCase(baseType)]?.fields ?? oidSchema.sensitive_attributes[baseType]?.fields;
            if (isSensitiveType) {
                schemaRef = `${baseType}Schema`;
            }
            else if (isExtensionType) {
                schemaRef = `${baseType}Schema`;
            }
            else if (baseType === 'GeneralizedTime') {
                schemaRef = 'ASN1.ValidateASN1.IsDate';
            }
            else if (baseType === 'OCTET STRING') {
                schemaRef = 'ASN1.ValidateASN1.IsOctetString';
            }
            else if (baseType === 'OBJECT IDENTIFIER') {
                schemaRef = 'ASN1.ValidateASN1.IsOID';
            }
            else {
                schemaRef = `{ type: 'string', kind: 'utf8' }`;
            }
        }
        lines.push(`\t'${name}': ${schemaRef},`);
    }
    deleteLastCommaIfFound();
    lines.push('} as const;');
    lines.push('');
    return (lines.join('\n'));
}
function parseArgs(argv) {
    let oidsJSONPath = undefined;
    let oidsOutputPath = undefined;
    let iso20022OutputPath = undefined;
    for (const arg of argv) {
        if (arg.startsWith('--oids-json=')) {
            oidsJSONPath = arg.substring('--oids-json='.length);
        }
        if (arg.startsWith('--oids-output=')) {
            oidsOutputPath = arg.substring('--oids-output='.length);
        }
        if (arg.startsWith('--iso20022-output=')) {
            iso20022OutputPath = arg.substring('--iso20022-output='.length);
        }
    }
    if (oidsJSONPath === undefined) {
        throw (new Error('Missing required argument: --oids-json=path/to/oids.json'));
    }
    if (oidsOutputPath === undefined) {
        throw (new Error('Missing required argument: --oids-output=path/to/oids.generated.ts'));
    }
    if (iso20022OutputPath === undefined) {
        throw (new Error('Missing required argument: --iso20022-output=path/to/iso20022.generated.ts'));
    }
    if (!fs.existsSync(oidsJSONPath)) {
        throw (new Error(`OID JSON file not found: ${oidsJSONPath}`));
    }
    return ({
        oidsJSONPath,
        oidsOutputPath,
        iso20022OutputPath
    });
}
// --- Main ---
function main(argv) {
    const { oidsJSONPath, oidsOutputPath, iso20022OutputPath } = parseArgs(argv);
    fs.mkdirSync(path.dirname(oidsOutputPath), { recursive: true });
    fs.mkdirSync(path.dirname(iso20022OutputPath), { recursive: true });
    oidSchema = (() => { const _io0 = input => "object" === typeof input.algorithms && null !== input.algorithms && false === Array.isArray(input.algorithms) && _io1(input.algorithms) && ("object" === typeof input.sensitive_attributes && null !== input.sensitive_attributes && false === Array.isArray(input.sensitive_attributes) && _io2(input.sensitive_attributes)) && ("object" === typeof input.plain_attributes && null !== input.plain_attributes && false === Array.isArray(input.plain_attributes) && _io2(input.plain_attributes)) && ("object" === typeof input.iso20022_types && null !== input.iso20022_types && _io8(input.iso20022_types)) && ("object" === typeof input.extensions && null !== input.extensions && false === Array.isArray(input.extensions) && _io21(input.extensions)); const _io1 = input => Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return Array.isArray(value) && value.every(elem => "number" === typeof elem);
    }); const _io2 = input => Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return "object" === typeof value && null !== value && _io3(value);
    }); const _io3 = input => Array.isArray(input.oid) && input.oid.every(elem => "number" === typeof elem) && (undefined === input.type || "string" === typeof input.type) && (undefined === input.token || "string" === typeof input.token) && "string" === typeof input.description && "string" === typeof input.reference && (undefined === input.fields || "object" === typeof input.fields && null !== input.fields && false === Array.isArray(input.fields) && _io4(input.fields)) && (undefined === input.choices || "object" === typeof input.choices && null !== input.choices && false === Array.isArray(input.choices) && _io6(input.choices)) && (undefined === input.field_order || Array.isArray(input.field_order) && input.field_order.every(elem => "string" === typeof elem)); const _io4 = input => Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return "object" === typeof value && null !== value && _io5(value);
    }); const _io5 = input => "string" === typeof input.type && (undefined === input.optional || "boolean" === typeof input.optional); const _io6 = input => Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return "object" === typeof value && null !== value && _io7(value);
    }); const _io7 = input => "string" === typeof input.type; const _io8 = input => "object" === typeof input.primitives && null !== input.primitives && false === Array.isArray(input.primitives) && _io9(input.primitives) && ("object" === typeof input.enumerations && null !== input.enumerations && false === Array.isArray(input.enumerations) && _io11(input.enumerations)) && ("object" === typeof input.choices && null !== input.choices && false === Array.isArray(input.choices) && _io13(input.choices)) && ("object" === typeof input.sequences && null !== input.sequences && false === Array.isArray(input.sequences) && _io17(input.sequences)); const _io9 = input => Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return "object" === typeof value && null !== value && _io10(value);
    }); const _io10 = input => Array.isArray(input.oid) && input.oid.every(elem => "number" === typeof elem) && "string" === typeof input.type && "string" === typeof input.description; const _io11 = input => Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return "object" === typeof value && null !== value && _io12(value);
    }); const _io12 = input => Array.isArray(input.oid) && input.oid.every(elem => "number" === typeof elem) && (Array.isArray(input.values) && input.values.every(elem => "string" === typeof elem)) && "string" === typeof input.description; const _io13 = input => Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return "object" === typeof value && null !== value && _io14(value);
    }); const _io14 = input => Array.isArray(input.oid) && input.oid.every(elem => "number" === typeof elem) && ("object" === typeof input.choices && null !== input.choices && false === Array.isArray(input.choices) && _io15(input.choices)) && "string" === typeof input.description; const _io15 = input => Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return "object" === typeof value && null !== value && _io16(value);
    }); const _io16 = input => "string" === typeof input.type; const _io17 = input => Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return "object" === typeof value && null !== value && _io18(value);
    }); const _io18 = input => Array.isArray(input.oid) && input.oid.every(elem => "number" === typeof elem) && ("object" === typeof input.fields && null !== input.fields && false === Array.isArray(input.fields) && _io19(input.fields)) && (undefined === input.field_order || Array.isArray(input.field_order) && input.field_order.every(elem => "string" === typeof elem)) && "string" === typeof input.description; const _io19 = input => Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return "object" === typeof value && null !== value && _io20(value);
    }); const _io20 = input => "string" === typeof input.type && (undefined === input.optional || "boolean" === typeof input.optional); const _io21 = input => Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return "object" === typeof value && null !== value && _io22(value);
    }); const _io22 = input => (undefined === input.oid || Array.isArray(input.oid) && input.oid.every(elem => "number" === typeof elem)) && (undefined === input.type || "string" === typeof input.type) && "string" === typeof input.description && (undefined === input.reference || "string" === typeof input.reference) && (undefined === input.fields || "object" === typeof input.fields && null !== input.fields && false === Array.isArray(input.fields) && _io23(input.fields)) && (undefined === input.field_order || Array.isArray(input.field_order) && input.field_order.every(elem => "string" === typeof elem)); const _io23 = input => Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return "object" === typeof value && null !== value && _io24(value);
    }); const _io24 = input => "string" === typeof input.type && (undefined === input.optional || "boolean" === typeof input.optional); const _ao0 = (input, _path, _exceptionable = true) => (("object" === typeof input.algorithms && null !== input.algorithms && false === Array.isArray(input.algorithms) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".algorithms",
        expected: "__type",
        value: input.algorithms
    }, _errorFactory)) && _ao1(input.algorithms, _path + ".algorithms", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".algorithms",
        expected: "__type",
        value: input.algorithms
    }, _errorFactory)) && (("object" === typeof input.sensitive_attributes && null !== input.sensitive_attributes && false === Array.isArray(input.sensitive_attributes) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".sensitive_attributes",
        expected: "oidSchemaContentsAttribute",
        value: input.sensitive_attributes
    }, _errorFactory)) && _ao2(input.sensitive_attributes, _path + ".sensitive_attributes", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".sensitive_attributes",
        expected: "oidSchemaContentsAttribute",
        value: input.sensitive_attributes
    }, _errorFactory)) && (("object" === typeof input.plain_attributes && null !== input.plain_attributes && false === Array.isArray(input.plain_attributes) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".plain_attributes",
        expected: "oidSchemaContentsAttribute",
        value: input.plain_attributes
    }, _errorFactory)) && _ao2(input.plain_attributes, _path + ".plain_attributes", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".plain_attributes",
        expected: "oidSchemaContentsAttribute",
        value: input.plain_attributes
    }, _errorFactory)) && (("object" === typeof input.iso20022_types && null !== input.iso20022_types || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".iso20022_types",
        expected: "__type.o6",
        value: input.iso20022_types
    }, _errorFactory)) && _ao8(input.iso20022_types, _path + ".iso20022_types", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".iso20022_types",
        expected: "__type.o6",
        value: input.iso20022_types
    }, _errorFactory)) && (("object" === typeof input.extensions && null !== input.extensions && false === Array.isArray(input.extensions) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".extensions",
        expected: "__type.o19",
        value: input.extensions
    }, _errorFactory)) && _ao21(input.extensions, _path + ".extensions", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".extensions",
        expected: "__type.o19",
        value: input.extensions
    }, _errorFactory)); const _ao1 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return (Array.isArray(value) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "Array<number>",
            value: value
        }, _errorFactory)) && value.every((elem, _index12) => "number" === typeof elem || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key) + "[" + _index12 + "]",
            expected: "number",
            value: elem
        }, _errorFactory)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "Array<number>",
            value: value
        }, _errorFactory);
    }); const _ao2 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return ("object" === typeof value && null !== value || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o1",
            value: value
        }, _errorFactory)) && _ao3(value, _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key), true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o1",
            value: value
        }, _errorFactory);
    }); const _ao3 = (input, _path, _exceptionable = true) => ((Array.isArray(input.oid) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid",
        expected: "Array<number>",
        value: input.oid
    }, _errorFactory)) && input.oid.every((elem, _index13) => "number" === typeof elem || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid[" + _index13 + "]",
        expected: "number",
        value: elem
    }, _errorFactory)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid",
        expected: "Array<number>",
        value: input.oid
    }, _errorFactory)) && (undefined === input.type || "string" === typeof input.type || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".type",
        expected: "(string | undefined)",
        value: input.type
    }, _errorFactory)) && (undefined === input.token || "string" === typeof input.token || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".token",
        expected: "(string | undefined)",
        value: input.token
    }, _errorFactory)) && ("string" === typeof input.description || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".description",
        expected: "string",
        value: input.description
    }, _errorFactory)) && ("string" === typeof input.reference || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".reference",
        expected: "string",
        value: input.reference
    }, _errorFactory)) && (undefined === input.fields || ("object" === typeof input.fields && null !== input.fields && false === Array.isArray(input.fields) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".fields",
        expected: "(__type.o2 | undefined)",
        value: input.fields
    }, _errorFactory)) && _ao4(input.fields, _path + ".fields", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".fields",
        expected: "(__type.o2 | undefined)",
        value: input.fields
    }, _errorFactory)) && (undefined === input.choices || ("object" === typeof input.choices && null !== input.choices && false === Array.isArray(input.choices) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".choices",
        expected: "(__type.o4 | undefined)",
        value: input.choices
    }, _errorFactory)) && _ao6(input.choices, _path + ".choices", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".choices",
        expected: "(__type.o4 | undefined)",
        value: input.choices
    }, _errorFactory)) && (undefined === input.field_order || (Array.isArray(input.field_order) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".field_order",
        expected: "(Array<string> | undefined)",
        value: input.field_order
    }, _errorFactory)) && input.field_order.every((elem, _index14) => "string" === typeof elem || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".field_order[" + _index14 + "]",
        expected: "string",
        value: elem
    }, _errorFactory)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".field_order",
        expected: "(Array<string> | undefined)",
        value: input.field_order
    }, _errorFactory)); const _ao4 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return ("object" === typeof value && null !== value || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o3",
            value: value
        }, _errorFactory)) && _ao5(value, _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key), true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o3",
            value: value
        }, _errorFactory);
    }); const _ao5 = (input, _path, _exceptionable = true) => ("string" === typeof input.type || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".type",
        expected: "string",
        value: input.type
    }, _errorFactory)) && (undefined === input.optional || "boolean" === typeof input.optional || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".optional",
        expected: "(boolean | undefined)",
        value: input.optional
    }, _errorFactory)); const _ao6 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return ("object" === typeof value && null !== value || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o5",
            value: value
        }, _errorFactory)) && _ao7(value, _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key), true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o5",
            value: value
        }, _errorFactory);
    }); const _ao7 = (input, _path, _exceptionable = true) => "string" === typeof input.type || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".type",
        expected: "string",
        value: input.type
    }, _errorFactory); const _ao8 = (input, _path, _exceptionable = true) => (("object" === typeof input.primitives && null !== input.primitives && false === Array.isArray(input.primitives) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".primitives",
        expected: "__type.o7",
        value: input.primitives
    }, _errorFactory)) && _ao9(input.primitives, _path + ".primitives", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".primitives",
        expected: "__type.o7",
        value: input.primitives
    }, _errorFactory)) && (("object" === typeof input.enumerations && null !== input.enumerations && false === Array.isArray(input.enumerations) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".enumerations",
        expected: "__type.o9",
        value: input.enumerations
    }, _errorFactory)) && _ao11(input.enumerations, _path + ".enumerations", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".enumerations",
        expected: "__type.o9",
        value: input.enumerations
    }, _errorFactory)) && (("object" === typeof input.choices && null !== input.choices && false === Array.isArray(input.choices) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".choices",
        expected: "__type.o11",
        value: input.choices
    }, _errorFactory)) && _ao13(input.choices, _path + ".choices", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".choices",
        expected: "__type.o11",
        value: input.choices
    }, _errorFactory)) && (("object" === typeof input.sequences && null !== input.sequences && false === Array.isArray(input.sequences) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".sequences",
        expected: "__type.o15",
        value: input.sequences
    }, _errorFactory)) && _ao17(input.sequences, _path + ".sequences", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".sequences",
        expected: "__type.o15",
        value: input.sequences
    }, _errorFactory)); const _ao9 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return ("object" === typeof value && null !== value || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o8",
            value: value
        }, _errorFactory)) && _ao10(value, _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key), true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o8",
            value: value
        }, _errorFactory);
    }); const _ao10 = (input, _path, _exceptionable = true) => ((Array.isArray(input.oid) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid",
        expected: "Array<number>",
        value: input.oid
    }, _errorFactory)) && input.oid.every((elem, _index15) => "number" === typeof elem || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid[" + _index15 + "]",
        expected: "number",
        value: elem
    }, _errorFactory)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid",
        expected: "Array<number>",
        value: input.oid
    }, _errorFactory)) && ("string" === typeof input.type || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".type",
        expected: "string",
        value: input.type
    }, _errorFactory)) && ("string" === typeof input.description || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".description",
        expected: "string",
        value: input.description
    }, _errorFactory)); const _ao11 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return ("object" === typeof value && null !== value || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o10",
            value: value
        }, _errorFactory)) && _ao12(value, _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key), true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o10",
            value: value
        }, _errorFactory);
    }); const _ao12 = (input, _path, _exceptionable = true) => ((Array.isArray(input.oid) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid",
        expected: "Array<number>",
        value: input.oid
    }, _errorFactory)) && input.oid.every((elem, _index16) => "number" === typeof elem || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid[" + _index16 + "]",
        expected: "number",
        value: elem
    }, _errorFactory)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid",
        expected: "Array<number>",
        value: input.oid
    }, _errorFactory)) && ((Array.isArray(input.values) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".values",
        expected: "Array<string>",
        value: input.values
    }, _errorFactory)) && input.values.every((elem, _index17) => "string" === typeof elem || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".values[" + _index17 + "]",
        expected: "string",
        value: elem
    }, _errorFactory)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".values",
        expected: "Array<string>",
        value: input.values
    }, _errorFactory)) && ("string" === typeof input.description || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".description",
        expected: "string",
        value: input.description
    }, _errorFactory)); const _ao13 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return ("object" === typeof value && null !== value || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o12",
            value: value
        }, _errorFactory)) && _ao14(value, _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key), true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o12",
            value: value
        }, _errorFactory);
    }); const _ao14 = (input, _path, _exceptionable = true) => ((Array.isArray(input.oid) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid",
        expected: "Array<number>",
        value: input.oid
    }, _errorFactory)) && input.oid.every((elem, _index18) => "number" === typeof elem || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid[" + _index18 + "]",
        expected: "number",
        value: elem
    }, _errorFactory)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid",
        expected: "Array<number>",
        value: input.oid
    }, _errorFactory)) && (("object" === typeof input.choices && null !== input.choices && false === Array.isArray(input.choices) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".choices",
        expected: "__type.o13",
        value: input.choices
    }, _errorFactory)) && _ao15(input.choices, _path + ".choices", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".choices",
        expected: "__type.o13",
        value: input.choices
    }, _errorFactory)) && ("string" === typeof input.description || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".description",
        expected: "string",
        value: input.description
    }, _errorFactory)); const _ao15 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return ("object" === typeof value && null !== value || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o14",
            value: value
        }, _errorFactory)) && _ao16(value, _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key), true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o14",
            value: value
        }, _errorFactory);
    }); const _ao16 = (input, _path, _exceptionable = true) => "string" === typeof input.type || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".type",
        expected: "string",
        value: input.type
    }, _errorFactory); const _ao17 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return ("object" === typeof value && null !== value || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o16",
            value: value
        }, _errorFactory)) && _ao18(value, _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key), true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o16",
            value: value
        }, _errorFactory);
    }); const _ao18 = (input, _path, _exceptionable = true) => ((Array.isArray(input.oid) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid",
        expected: "Array<number>",
        value: input.oid
    }, _errorFactory)) && input.oid.every((elem, _index19) => "number" === typeof elem || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid[" + _index19 + "]",
        expected: "number",
        value: elem
    }, _errorFactory)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid",
        expected: "Array<number>",
        value: input.oid
    }, _errorFactory)) && (("object" === typeof input.fields && null !== input.fields && false === Array.isArray(input.fields) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".fields",
        expected: "__type.o17",
        value: input.fields
    }, _errorFactory)) && _ao19(input.fields, _path + ".fields", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".fields",
        expected: "__type.o17",
        value: input.fields
    }, _errorFactory)) && (undefined === input.field_order || (Array.isArray(input.field_order) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".field_order",
        expected: "(Array<string> | undefined)",
        value: input.field_order
    }, _errorFactory)) && input.field_order.every((elem, _index20) => "string" === typeof elem || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".field_order[" + _index20 + "]",
        expected: "string",
        value: elem
    }, _errorFactory)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".field_order",
        expected: "(Array<string> | undefined)",
        value: input.field_order
    }, _errorFactory)) && ("string" === typeof input.description || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".description",
        expected: "string",
        value: input.description
    }, _errorFactory)); const _ao19 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return ("object" === typeof value && null !== value || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o18",
            value: value
        }, _errorFactory)) && _ao20(value, _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key), true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o18",
            value: value
        }, _errorFactory);
    }); const _ao20 = (input, _path, _exceptionable = true) => ("string" === typeof input.type || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".type",
        expected: "string",
        value: input.type
    }, _errorFactory)) && (undefined === input.optional || "boolean" === typeof input.optional || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".optional",
        expected: "(boolean | undefined)",
        value: input.optional
    }, _errorFactory)); const _ao21 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return ("object" === typeof value && null !== value || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o20",
            value: value
        }, _errorFactory)) && _ao22(value, _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key), true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o20",
            value: value
        }, _errorFactory);
    }); const _ao22 = (input, _path, _exceptionable = true) => (undefined === input.oid || (Array.isArray(input.oid) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid",
        expected: "(Array<number> | undefined)",
        value: input.oid
    }, _errorFactory)) && input.oid.every((elem, _index21) => "number" === typeof elem || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid[" + _index21 + "]",
        expected: "number",
        value: elem
    }, _errorFactory)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".oid",
        expected: "(Array<number> | undefined)",
        value: input.oid
    }, _errorFactory)) && (undefined === input.type || "string" === typeof input.type || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".type",
        expected: "(string | undefined)",
        value: input.type
    }, _errorFactory)) && ("string" === typeof input.description || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".description",
        expected: "string",
        value: input.description
    }, _errorFactory)) && (undefined === input.reference || "string" === typeof input.reference || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".reference",
        expected: "(string | undefined)",
        value: input.reference
    }, _errorFactory)) && (undefined === input.fields || ("object" === typeof input.fields && null !== input.fields && false === Array.isArray(input.fields) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".fields",
        expected: "(__type.o21 | undefined)",
        value: input.fields
    }, _errorFactory)) && _ao23(input.fields, _path + ".fields", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".fields",
        expected: "(__type.o21 | undefined)",
        value: input.fields
    }, _errorFactory)) && (undefined === input.field_order || (Array.isArray(input.field_order) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".field_order",
        expected: "(Array<string> | undefined)",
        value: input.field_order
    }, _errorFactory)) && input.field_order.every((elem, _index22) => "string" === typeof elem || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".field_order[" + _index22 + "]",
        expected: "string",
        value: elem
    }, _errorFactory)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".field_order",
        expected: "(Array<string> | undefined)",
        value: input.field_order
    }, _errorFactory)); const _ao23 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every(key => {
        const value = input[key];
        if (undefined === value)
            return true;
        return ("object" === typeof value && null !== value || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o22",
            value: value
        }, _errorFactory)) && _ao24(value, _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key), true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
            method: "typia.assert",
            path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
            expected: "__type.o22",
            value: value
        }, _errorFactory);
    }); const _ao24 = (input, _path, _exceptionable = true) => ("string" === typeof input.type || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".type",
        expected: "string",
        value: input.type
    }, _errorFactory)) && (undefined === input.optional || "boolean" === typeof input.optional || __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "typia.assert",
        path: _path + ".optional",
        expected: "(boolean | undefined)",
        value: input.optional
    }, _errorFactory)); const __is = input => "object" === typeof input && null !== input && _io0(input); let _errorFactory; return (input, errorFactory) => {
        if (false === __is(input)) {
            _errorFactory = errorFactory;
            ((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || __typia_transform__assertGuard._assertGuard(true, {
                method: "typia.assert",
                path: _path + "",
                expected: "oidSchemaContents",
                value: input
            }, _errorFactory)) && _ao0(input, _path + "", true) || __typia_transform__assertGuard._assertGuard(true, {
                method: "typia.assert",
                path: _path + "",
                expected: "oidSchemaContents",
                value: input
            }, _errorFactory))(input, "$input", true);
        }
        return input;
    }; })()(JSON.parse(fs.readFileSync(oidsJSONPath, 'utf8')));
    fs.writeFileSync(oidsOutputPath, generateOidConstants(), 'utf8');
    fs.writeFileSync(iso20022OutputPath, generateIso20022Types(), 'utf8');
}
main(process.argv.slice(2));
//# sourceMappingURL=generate-kyc-schema.js.map