update requirements,
This commit is contained in:
86
001_documentation/Requirements/REQ0015/convert.js
Normal file
86
001_documentation/Requirements/REQ0015/convert.js
Normal file
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// # REQ0015:
|
||||
// ## PURPOSE:
|
||||
//
|
||||
// This is a script to convert `schema.json` exported from pocketbase to dbml formatted file `schema.dbml`
|
||||
//
|
||||
//
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
// Load schema.json
|
||||
const schemaPath = path.join(process.cwd(), "schema.json");
|
||||
const schema = JSON.parse(fs.readFileSync(schemaPath, "utf8"));
|
||||
|
||||
// Type mapping from PocketBase to DBML/SQL
|
||||
const typeMapping = {
|
||||
text: "text",
|
||||
number: "integer",
|
||||
bool: "boolean",
|
||||
email: "text",
|
||||
url: "varchar",
|
||||
date: "datetime",
|
||||
select: "varchar",
|
||||
json: "text",
|
||||
file: "file",
|
||||
password: "varchar",
|
||||
relation: "integer", // Assuming relations are stored as integer IDs
|
||||
autodate: "datetime",
|
||||
};
|
||||
|
||||
function convertToDBML(schema) {
|
||||
let dbml = "";
|
||||
dbml = "// Generated at: " + new Date().toISOString();
|
||||
dbml = dbml + "\n\n\n";
|
||||
|
||||
let collectionIdToTableMapping = {};
|
||||
for (const [idx, tableDef] of Object.entries(schema)) {
|
||||
collectionIdToTableMapping[tableDef.id] = tableDef.name;
|
||||
}
|
||||
|
||||
for (const [idx, tableDef] of Object.entries(schema)) {
|
||||
console.log({ idx });
|
||||
dbml += `// \n`;
|
||||
dbml += `// collection id: ${tableDef.id} \n`;
|
||||
dbml += `// collection name: ${tableDef.name} \n`;
|
||||
dbml += `// collection type: ${tableDef.type} \n`;
|
||||
dbml += `Table ${tableDef.name} {\n`;
|
||||
|
||||
for (const field of tableDef.fields) {
|
||||
// Get field type
|
||||
let fieldType = typeMapping[field.type] || "text";
|
||||
|
||||
// Handle special cases
|
||||
if (field.type === "number" && field.options?.max === 1) {
|
||||
fieldType = "boolean";
|
||||
}
|
||||
|
||||
// Build field definition
|
||||
let line = ` ${field.name} ${fieldType}`;
|
||||
|
||||
// Add constraints
|
||||
const constraints = [];
|
||||
if (field.name === "id" || field.primary) constraints.push("pk");
|
||||
if (field.required) constraints.push("not null");
|
||||
if (constraints.length > 0) line += ` [${constraints.join(", ")}]`;
|
||||
|
||||
if (field.collectionId) {
|
||||
line += ` [ref: > ${
|
||||
collectionIdToTableMapping[field.collectionId]
|
||||
}.id] // ${field.id}`;
|
||||
}
|
||||
|
||||
dbml += `${line}\n`;
|
||||
console.log({ line });
|
||||
}
|
||||
|
||||
dbml += "}\n\n";
|
||||
}
|
||||
|
||||
return dbml;
|
||||
}
|
||||
|
||||
// Convert and save
|
||||
const dbmlOutput = convertToDBML(schema);
|
||||
fs.writeFileSync("schema.dbml", dbmlOutput);
|
||||
console.log("DBML file generated successfully!");
|
9
001_documentation/Requirements/REQ0015/index.md
Normal file
9
001_documentation/Requirements/REQ0015/index.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
tags: mobile, cms, db, schema
|
||||
---
|
||||
|
||||
# pocketbase json schema to dbml converter
|
||||
|
||||
## description
|
||||
|
||||
to generate a `schema.dbml` form `schema.json` exported from pocketbase
|
18
001_documentation/Requirements/REQ0015/schema.dbml
Normal file
18
001_documentation/Requirements/REQ0015/schema.dbml
Normal file
@@ -0,0 +1,18 @@
|
||||
// Generated at: 2025-05-06T06:24:44.009Z
|
||||
|
||||
|
||||
//
|
||||
// collection id: pbc_3142635823
|
||||
// collection name: helloworld
|
||||
// collection type: auth
|
||||
Table helloworld {
|
||||
id text [pk, not null]
|
||||
password varchar [not null]
|
||||
tokenKey text [not null]
|
||||
email text [not null]
|
||||
emailVisibility boolean
|
||||
verified boolean
|
||||
created datetime
|
||||
updated datetime
|
||||
}
|
||||
|
174
001_documentation/Requirements/REQ0015/schema.json
Normal file
174
001_documentation/Requirements/REQ0015/schema.json
Normal file
@@ -0,0 +1,174 @@
|
||||
[
|
||||
{
|
||||
"id": "pbc_3142635823",
|
||||
"listRule": null,
|
||||
"viewRule": null,
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": null,
|
||||
"name": "helloworld",
|
||||
"type": "auth",
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"cost": 0,
|
||||
"hidden": true,
|
||||
"id": "password901924565",
|
||||
"max": 0,
|
||||
"min": 8,
|
||||
"name": "password",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "password"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "[a-zA-Z0-9]{50}",
|
||||
"hidden": true,
|
||||
"id": "text2504183744",
|
||||
"max": 60,
|
||||
"min": 30,
|
||||
"name": "tokenKey",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "email3885137012",
|
||||
"name": "email",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "email"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "bool1547992806",
|
||||
"name": "emailVisibility",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": true,
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "bool256245529",
|
||||
"name": "verified",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": true,
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": true,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": true,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
"CREATE UNIQUE INDEX `idx_tokenKey_pbc_3142635823` ON `_superusers` (`tokenKey`)",
|
||||
"CREATE UNIQUE INDEX `idx_email_pbc_3142635823` ON `_superusers` (`email`) WHERE `email` != ''"
|
||||
],
|
||||
"system": true,
|
||||
"authRule": "",
|
||||
"manageRule": null,
|
||||
"authAlert": {
|
||||
"enabled": true,
|
||||
"emailTemplate": {
|
||||
"subject": "Login from a new location",
|
||||
"body": "<p>Hello,</p>\n<p>We noticed a login to your {APP_NAME} account from a new location.</p>\n<p>If this was you, you may disregard this email.</p>\n<p><strong>If this wasn't you, you should immediately change your {APP_NAME} account password to revoke access from all other locations.</strong></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
}
|
||||
},
|
||||
"oauth2": {
|
||||
"mappedFields": {
|
||||
"id": "",
|
||||
"name": "",
|
||||
"username": "",
|
||||
"avatarURL": ""
|
||||
},
|
||||
"enabled": false
|
||||
},
|
||||
"passwordAuth": {
|
||||
"enabled": true,
|
||||
"identityFields": [
|
||||
"email"
|
||||
]
|
||||
},
|
||||
"mfa": {
|
||||
"enabled": false,
|
||||
"duration": 1800,
|
||||
"rule": ""
|
||||
},
|
||||
"otp": {
|
||||
"enabled": false,
|
||||
"duration": 180,
|
||||
"length": 8,
|
||||
"emailTemplate": {
|
||||
"subject": "OTP for {APP_NAME}",
|
||||
"body": "<p>Hello,</p>\n<p>Your one-time password is: <strong>{OTP}</strong></p>\n<p><i>If you didn't ask for the one-time password, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
}
|
||||
},
|
||||
"authToken": {
|
||||
"duration": 86400
|
||||
},
|
||||
"passwordResetToken": {
|
||||
"duration": 1800
|
||||
},
|
||||
"emailChangeToken": {
|
||||
"duration": 1800
|
||||
},
|
||||
"verificationToken": {
|
||||
"duration": 259200
|
||||
},
|
||||
"fileToken": {
|
||||
"duration": 180
|
||||
},
|
||||
"verificationTemplate": {
|
||||
"subject": "Verify your {APP_NAME} email",
|
||||
"body": "<p>Hello,</p>\n<p>Thank you for joining us at {APP_NAME}.</p>\n<p>Click on the button below to verify your email address.</p>\n<p>\n <a class=\"btn\" href=\"{APP_URL}/_/#/auth/confirm-verification/{TOKEN}\" target=\"_blank\" rel=\"noopener\">Verify</a>\n</p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
},
|
||||
"resetPasswordTemplate": {
|
||||
"subject": "Reset your {APP_NAME} password",
|
||||
"body": "<p>Hello,</p>\n<p>Click on the button below to reset your password.</p>\n<p>\n <a class=\"btn\" href=\"{APP_URL}/_/#/auth/confirm-password-reset/{TOKEN}\" target=\"_blank\" rel=\"noopener\">Reset password</a>\n</p>\n<p><i>If you didn't ask to reset your password, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
},
|
||||
"confirmEmailChangeTemplate": {
|
||||
"subject": "Confirm your {APP_NAME} new email address",
|
||||
"body": "<p>Hello,</p>\n<p>Click on the button below to confirm your new email address.</p>\n<p>\n <a class=\"btn\" href=\"{APP_URL}/_/#/auth/confirm-email-change/{TOKEN}\" target=\"_blank\" rel=\"noopener\">Confirm new email</a>\n</p>\n<p><i>If you didn't ask to change your email address, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
}
|
||||
}
|
||||
]
|
Reference in New Issue
Block a user