mirror of
https://github.com/Lifeforge-app/lifeforge.git
synced 2026-06-28 06:46:24 +00:00
Former-commit-id: cff5e184f0cc274cd9b69e86241c22275b539cb4 [formerly 567f96d4baeb189ad4102c8d89041fe563fb78f0] [formerly a0b4dfddcdf8c3607f077720b10544c24d7be271 [formerly 3b4c1e287ccfedfc2c9a851e9245469793b6ffe0]] Former-commit-id: 94b4dcd0904254e9b6e953f3155c0adf07f8f909 [formerly a12e98efc5a5914e11513e7275411dac2b65f2c0] Former-commit-id: 935668eed616dea264b8439776ef112cee53150a
152 lines
5.9 KiB
JavaScript
152 lines
5.9 KiB
JavaScript
import chalk from 'chalk';
|
|
import dotenv from 'dotenv';
|
|
import fs from 'fs';
|
|
import _ from 'lodash';
|
|
import path from 'path';
|
|
import Pocketbase, {} from 'pocketbase';
|
|
import prettier from 'prettier';
|
|
dotenv.config({
|
|
path: path.resolve(__dirname, '../server/env/.env.local')
|
|
});
|
|
if (!process.env.PB_HOST || !process.env.PB_EMAIL || !process.env.PB_PASSWORD) {
|
|
console.error('Please provide PB_HOST, PB_EMAIL, and PB_PASSWORD in your environment variables.');
|
|
process.exit(1);
|
|
}
|
|
const pb = new Pocketbase(process.env.PB_HOST);
|
|
let SCHEMA_STRING = `
|
|
import flattenSchemas from '@functions/utils/flattenSchema'
|
|
import { z } from 'zod/v4'
|
|
|
|
export const SCHEMAS = {
|
|
`;
|
|
try {
|
|
await pb
|
|
.collection('_superusers')
|
|
.authWithPassword(process.env.PB_EMAIL, process.env.PB_PASSWORD);
|
|
if (!pb.authStore.isSuperuser || !pb.authStore.isValid) {
|
|
console.error('Invalid credentials.');
|
|
process.exit(1);
|
|
}
|
|
}
|
|
catch {
|
|
console.error('Server is not reachable or credentials are invalid.');
|
|
process.exit(1);
|
|
}
|
|
const allModules = [
|
|
...fs.readdirSync('./server/src/apps', { withFileTypes: true }),
|
|
...fs.readdirSync('./server/src/core/lib', { withFileTypes: true })
|
|
];
|
|
const modulesMap = {};
|
|
const allCollections = await pb.collections.getFullList();
|
|
const collections = allCollections.filter(e => !e.system);
|
|
for (const collection of collections) {
|
|
const module = allModules.find(e => collection.name.startsWith(_.snakeCase(e.name)));
|
|
if (!module) {
|
|
console.log(chalk.yellow('[WARNING]') +
|
|
` Collection ${collection.name} does not have a corresponding module.`);
|
|
continue;
|
|
}
|
|
if (!modulesMap[module.name]) {
|
|
modulesMap[module.name] = [];
|
|
}
|
|
modulesMap[module.name]?.push(collection);
|
|
}
|
|
console.log(chalk.green('[INFO]') +
|
|
` Found ${Object.values(modulesMap).flat().length} collections across ${Object.keys(modulesMap).length} modules.`);
|
|
for (const module of allModules) {
|
|
if (!modulesMap[module.name]) {
|
|
continue;
|
|
}
|
|
const collections = modulesMap[module.name];
|
|
if (!collections) {
|
|
console.warn(chalk.yellow('[WARNING]') +
|
|
` No collections found for module ${chalk.bold(module.name)}.`);
|
|
continue;
|
|
}
|
|
const moduleName = collections[0].name.split('__')[0];
|
|
SCHEMA_STRING += ` ${moduleName}: {\n`;
|
|
for (const collection of collections ?? []) {
|
|
console.log(chalk.blue('[INFO]') +
|
|
` Found ${collection.fields.length} fields in collection ${chalk.bold(collection.name)} in module ${chalk.bold(moduleName)}.`);
|
|
const zodSchemaObject = {};
|
|
for (const field of collection.fields) {
|
|
if (field.name === 'id') {
|
|
// Skip fields that are auto-generated by PocketBase
|
|
continue;
|
|
}
|
|
switch (field.type) {
|
|
case 'text':
|
|
zodSchemaObject[field.name] = 'z.string()';
|
|
break;
|
|
case 'richtext':
|
|
zodSchemaObject[field.name] = 'z.string()';
|
|
break;
|
|
case 'number':
|
|
zodSchemaObject[field.name] = 'z.number()';
|
|
break;
|
|
case 'bool':
|
|
zodSchemaObject[field.name] = 'z.boolean()';
|
|
break;
|
|
case 'email':
|
|
zodSchemaObject[field.name] = 'z.email()';
|
|
break;
|
|
case 'url':
|
|
zodSchemaObject[field.name] = 'z.url()';
|
|
break;
|
|
case 'date':
|
|
zodSchemaObject[field.name] = 'z.string()';
|
|
break;
|
|
case 'autodate':
|
|
zodSchemaObject[field.name] = 'z.string()';
|
|
break;
|
|
case 'select':
|
|
const value = [...field.values, ...(field.required ? [] : [''])];
|
|
zodSchemaObject[field.name] =
|
|
field.maxSelect > 1
|
|
? `z.array(z.enum(${JSON.stringify(value)}))`
|
|
: `z.enum(${JSON.stringify(value)})`;
|
|
break;
|
|
case 'file':
|
|
zodSchemaObject[field.name] =
|
|
field.maxSelect > 1 ? 'z.array(z.string())' : 'z.string()';
|
|
break;
|
|
case 'relation':
|
|
zodSchemaObject[field.name] =
|
|
field.maxSelect > 1 ? `z.array(z.string())` : `z.string()`;
|
|
break;
|
|
case 'json':
|
|
zodSchemaObject[field.name] = 'z.any()';
|
|
break;
|
|
case 'geoPoint':
|
|
zodSchemaObject[field.name] =
|
|
'z.object({ lat: z.number(), lon: z.number() })';
|
|
break;
|
|
case 'password':
|
|
zodSchemaObject[field.name] = 'z.string()';
|
|
break;
|
|
default:
|
|
console.warn(chalk.yellow('[WARNING]') +
|
|
` Unknown field type ${field.type} for field ${field.name} in collection ${collection.name}.`);
|
|
continue;
|
|
}
|
|
}
|
|
const zodSchemaString = `z.object({\n${Object.entries(zodSchemaObject)
|
|
.map(([key, value]) => ` ${key}: ${value},`)
|
|
.join('\n')}\n}),`;
|
|
SCHEMA_STRING += ` ${collection.name.split('__').pop()}: ${zodSchemaString}\n`;
|
|
console.log(chalk.green('[INFO]') +
|
|
` Generated Zod schema for collection ${chalk.bold(collection.name)} in module ${chalk.bold(moduleName)}.`);
|
|
}
|
|
SCHEMA_STRING += ` },\n`;
|
|
}
|
|
SCHEMA_STRING += `}
|
|
|
|
const COLLECTION_SCHEMAS = flattenSchemas(SCHEMAS)
|
|
|
|
export default COLLECTION_SCHEMAS
|
|
`;
|
|
const formattedSchemaString = await prettier.format(SCHEMA_STRING, {
|
|
parser: 'typescript'
|
|
});
|
|
fs.writeFileSync(path.resolve(__dirname, '../server/src/core/schema.ts'), formattedSchemaString);
|