mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-04-09 09:10:06 -04:00
195 lines
5.0 KiB
JavaScript
Executable File
195 lines
5.0 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
/**
|
|
* Generates FieldKey constants for C#, Swift, and Kotlin from TypeScript source.
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
// Paths
|
|
const REPO_ROOT = path.join(__dirname, '../../..');
|
|
const TS_SOURCE = path.join(REPO_ROOT, 'shared/models/src/vault/FieldKey.ts');
|
|
const CS_OUTPUT = path.join(REPO_ROOT, 'apps/server/AliasVault.Client/Main/Models/Vault/FieldKey.cs');
|
|
const SWIFT_OUTPUT = path.join(REPO_ROOT, 'apps/mobile-app/ios/VaultModels/FieldKey.swift');
|
|
const KOTLIN_OUTPUT = path.join(REPO_ROOT, 'apps/mobile-app/android/app/src/main/java/net/aliasvault/app/vaultstore/models/FieldKey.kt');
|
|
|
|
/**
|
|
* Parse the TypeScript FieldKey.ts file and extract constants
|
|
*/
|
|
function parseTypeScriptFieldKeys(tsContent) {
|
|
const fieldKeys = {};
|
|
|
|
// Extract field comments
|
|
const lines = tsContent.split('\n');
|
|
let currentComment = '';
|
|
|
|
for (let i = 0; i < lines.length; i++) {
|
|
const line = lines[i].trim();
|
|
|
|
// Capture JSDoc comments
|
|
if (line.startsWith('/**') || line.startsWith('*')) {
|
|
const commentMatch = line.match(/\*\s*(.+)/);
|
|
if (commentMatch && !commentMatch[1].startsWith('/')) {
|
|
currentComment = commentMatch[1].trim();
|
|
}
|
|
}
|
|
|
|
// Match field definition
|
|
const fieldMatch = line.match(/^(\w+):\s*'([^']+)',?$/);
|
|
if (fieldMatch) {
|
|
const [, name, value] = fieldMatch;
|
|
fieldKeys[name] = {
|
|
value,
|
|
comment: currentComment
|
|
};
|
|
currentComment = '';
|
|
}
|
|
}
|
|
|
|
return fieldKeys;
|
|
}
|
|
|
|
/**
|
|
* Generate C# static class
|
|
*/
|
|
function generateCSharp(fieldKeys) {
|
|
const header = `// <auto-generated />
|
|
// This file is auto-generated from shared/models/src/vault/FieldKey.ts
|
|
// Do not edit this file directly. Run 'npm run generate:models' to regenerate.
|
|
|
|
namespace AliasClientDb.Models;
|
|
|
|
/// <summary>
|
|
/// System field keys for the field-based data model.
|
|
/// These keys map to FieldDefinition.FieldKey values.
|
|
/// </summary>
|
|
public static class FieldKey
|
|
{`;
|
|
|
|
const fields = Object.entries(fieldKeys)
|
|
.map(([name, { value, comment }]) => {
|
|
return ` /// <summary>
|
|
/// ${comment}
|
|
/// </summary>
|
|
public const string ${name} = "${value}";`;
|
|
})
|
|
.join('\n\n');
|
|
|
|
const footer = `
|
|
}
|
|
`;
|
|
|
|
return header + '\n' + fields + footer;
|
|
}
|
|
|
|
/**
|
|
* Generate Swift enum
|
|
*/
|
|
function generateSwift(fieldKeys) {
|
|
const header = `// <auto-generated />
|
|
// This file is auto-generated from shared/models/src/vault/FieldKey.ts
|
|
// Do not edit this file directly. Run 'npm run generate:models' to regenerate.
|
|
|
|
import Foundation
|
|
|
|
/// System field keys for the field-based data model.
|
|
/// These keys map to FieldDefinition.FieldKey values.
|
|
public struct FieldKey {`;
|
|
|
|
const fields = Object.entries(fieldKeys)
|
|
.map(([name, { value, comment }]) => {
|
|
// Convert PascalCase to camelCase for Swift
|
|
const swiftName = name.charAt(0).toLowerCase() + name.slice(1);
|
|
return ` /// ${comment}
|
|
public static let ${swiftName} = "${value}"`;
|
|
})
|
|
.join('\n\n');
|
|
|
|
const footer = `
|
|
}
|
|
`;
|
|
|
|
return header + '\n' + fields + footer;
|
|
}
|
|
|
|
/**
|
|
* Generate Kotlin object
|
|
*/
|
|
function generateKotlin(fieldKeys) {
|
|
const header = `// <auto-generated />
|
|
// This file is auto-generated from shared/models/src/vault/FieldKey.ts
|
|
// Do not edit this file directly. Run 'npm run generate:models' to regenerate.
|
|
|
|
package net.aliasvault.app.vaultstore.models
|
|
|
|
/**
|
|
* System field keys for the field-based data model.
|
|
* These keys map to FieldDefinition.FieldKey values.
|
|
*/
|
|
object FieldKey {`;
|
|
|
|
const fields = Object.entries(fieldKeys)
|
|
.map(([name, { value, comment }]) => {
|
|
// Convert to SCREAMING_SNAKE_CASE for Kotlin constants
|
|
const kotlinName = name.replace(/([A-Z])/g, '_$1').toUpperCase().replace(/^_/, '');
|
|
// Ensure comment ends with a period for Kotlin detekt
|
|
const kotlinComment = comment.endsWith('.') ? comment : `${comment}.`;
|
|
return ` /**
|
|
* ${kotlinComment}
|
|
*/
|
|
const val ${kotlinName} = "${value}"`;
|
|
})
|
|
.join('\n\n');
|
|
|
|
const footer = `
|
|
}
|
|
`;
|
|
|
|
return header + '\n' + fields + footer;
|
|
}
|
|
|
|
/**
|
|
* Ensure directory exists
|
|
*/
|
|
function ensureDir(filePath) {
|
|
const dir = path.dirname(filePath);
|
|
if (!fs.existsSync(dir)) {
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Main execution
|
|
*/
|
|
function main() {
|
|
|
|
// Read TypeScript source
|
|
if (!fs.existsSync(TS_SOURCE)) {
|
|
throw new Error(`Source file not found: ${TS_SOURCE}`);
|
|
}
|
|
|
|
const tsContent = fs.readFileSync(TS_SOURCE, 'utf8');
|
|
const fieldKeys = parseTypeScriptFieldKeys(tsContent);
|
|
|
|
if (Object.keys(fieldKeys).length === 0) {
|
|
throw new Error('No field keys found in source file');
|
|
}
|
|
|
|
// Generate C#
|
|
ensureDir(CS_OUTPUT);
|
|
const csContent = generateCSharp(fieldKeys);
|
|
fs.writeFileSync(CS_OUTPUT, csContent, 'utf8');
|
|
|
|
// Generate Swift
|
|
ensureDir(SWIFT_OUTPUT);
|
|
const swiftContent = generateSwift(fieldKeys);
|
|
fs.writeFileSync(SWIFT_OUTPUT, swiftContent, 'utf8');
|
|
|
|
// Generate Kotlin
|
|
ensureDir(KOTLIN_OUTPUT);
|
|
const kotlinContent = generateKotlin(fieldKeys);
|
|
fs.writeFileSync(KOTLIN_OUTPUT, kotlinContent, 'utf8');
|
|
}
|
|
|
|
main();
|