Upgrade system finished

This commit is contained in:
2026-03-22 21:47:09 -06:00
parent a71ba20176
commit bb1935027d
299 changed files with 8067 additions and 2758 deletions

View File

@@ -5,5 +5,6 @@
* Migrates existing email templates from filesystem to database.
* Run with: npx tsx api/src/scripts/seed-email-templates.ts
*/
export {};
declare function seedEmailTemplates(): Promise<void>;
export { seedEmailTemplates };
//# sourceMappingURL=seed-email-templates.d.ts.map

View File

@@ -1 +1 @@
{"version":3,"file":"seed-email-templates.d.ts","sourceRoot":"","sources":["../../src/scripts/seed-email-templates.ts"],"names":[],"mappings":";AACA;;;;;GAKG"}
{"version":3,"file":"seed-email-templates.d.ts","sourceRoot":"","sources":["../../src/scripts/seed-email-templates.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAiKH,iBAAe,kBAAkB,kBAqHhC;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC"}

View File

@@ -40,10 +40,10 @@ var __importStar = (this && this.__importStar) || (function () {
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.seedEmailTemplates = seedEmailTemplates;
const client_1 = require("@prisma/client");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const prisma = new client_1.PrismaClient();
const TEMPLATES = [
{
key: 'campaign-email',
@@ -124,8 +124,64 @@ const TEMPLATES = [
{ key: 'SHIFT_STATUS', label: 'Shift Status', description: 'Status of the shift (OPEN, FULL, CANCELLED)', isRequired: true, isConditional: false, sampleValue: 'OPEN', sortOrder: 10 },
],
},
{
key: 'email-verification',
name: 'Email Verification',
description: 'Sent to new users to verify their email address after self-registration',
category: 'SYSTEM',
subjectLine: 'Verify your email — {{ORGANIZATION_NAME}}',
isSystem: true,
variables: [
{ key: 'RECIPIENT_NAME', label: 'User Name', description: 'Name of the user being verified', isRequired: true, isConditional: false, sampleValue: 'Jane Doe', sortOrder: 0 },
{ key: 'VERIFICATION_URL', label: 'Verification URL', description: 'URL the user clicks to verify their email', isRequired: true, isConditional: false, sampleValue: 'https://app.cmlite.org/verify-email?token=abc123', sortOrder: 1 },
{ key: 'ORGANIZATION_NAME', label: 'Organization Name', description: 'Name of the organization', isRequired: true, isConditional: false, sampleValue: 'Changemaker Lite', sortOrder: 2 },
{ key: 'EXPIRY_HOURS', label: 'Expiry Hours', description: 'Number of hours until the verification link expires', isRequired: true, isConditional: false, sampleValue: '24', sortOrder: 3 },
],
},
{
key: 'password-reset',
name: 'Password Reset',
description: 'Sent when a user requests a password reset link',
category: 'SYSTEM',
subjectLine: 'Reset your password — {{ORGANIZATION_NAME}}',
isSystem: true,
variables: [
{ key: 'RECIPIENT_NAME', label: 'User Name', description: 'Name of the user requesting a reset', isRequired: true, isConditional: false, sampleValue: 'Jane Doe', sortOrder: 0 },
{ key: 'RESET_URL', label: 'Reset URL', description: 'URL the user clicks to reset their password', isRequired: true, isConditional: false, sampleValue: 'https://app.cmlite.org/reset-password?token=abc123', sortOrder: 1 },
{ key: 'ORGANIZATION_NAME', label: 'Organization Name', description: 'Name of the organization', isRequired: true, isConditional: false, sampleValue: 'Changemaker Lite', sortOrder: 2 },
],
},
{
key: 'account-approved',
name: 'Account Approved',
description: 'Sent to a user when an admin approves their account after email verification',
category: 'SYSTEM',
subjectLine: 'Account approved — {{ORGANIZATION_NAME}}',
isSystem: true,
variables: [
{ key: 'RECIPIENT_NAME', label: 'User Name', description: 'Name of the approved user', isRequired: true, isConditional: false, sampleValue: 'Jane Doe', sortOrder: 0 },
{ key: 'LOGIN_URL', label: 'Login URL', description: 'URL to the login page', isRequired: true, isConditional: false, sampleValue: 'https://app.cmlite.org/login', sortOrder: 1 },
{ key: 'ORGANIZATION_NAME', label: 'Organization Name', description: 'Name of the organization', isRequired: true, isConditional: false, sampleValue: 'Changemaker Lite', sortOrder: 2 },
],
},
{
key: 'account-pending-approval',
name: 'Account Pending Approval (Admin Notification)',
description: 'Sent to admins when a new user verifies their email and is awaiting approval',
category: 'SYSTEM',
subjectLine: 'New user awaiting approval — {{ORGANIZATION_NAME}}',
isSystem: true,
variables: [
{ key: 'NEW_USER_NAME', label: 'New User Name', description: 'Name of the new user requesting approval', isRequired: true, isConditional: false, sampleValue: 'Jane Doe', sortOrder: 0 },
{ key: 'NEW_USER_EMAIL', label: 'New User Email', description: 'Email of the new user', isRequired: true, isConditional: false, sampleValue: 'jane@example.com', sortOrder: 1 },
{ key: 'REGISTERED_AT', label: 'Registration Date', description: 'Date the user registered', isRequired: true, isConditional: false, sampleValue: 'February 16, 2026', sortOrder: 2 },
{ key: 'ADMIN_URL', label: 'Admin URL', description: 'URL to the admin users page filtered to pending approval', isRequired: true, isConditional: false, sampleValue: 'https://app.cmlite.org/app/users?status=PENDING_APPROVAL', sortOrder: 3 },
{ key: 'ORGANIZATION_NAME', label: 'Organization Name', description: 'Name of the organization', isRequired: true, isConditional: false, sampleValue: 'Changemaker Lite', sortOrder: 4 },
],
},
];
async function seedEmailTemplates() {
const prisma = new client_1.PrismaClient();
console.log('🌱 Starting email template seeding...\n');
// Find or create SUPER_ADMIN user for created_by
let adminUser = await prisma.user.findFirst({
@@ -139,6 +195,7 @@ async function seedEmailTemplates() {
password: 'not-used-for-login',
name: 'System',
role: 'SUPER_ADMIN',
roles: JSON.parse(JSON.stringify(['SUPER_ADMIN'])),
status: 'ACTIVE',
},
});
@@ -225,13 +282,14 @@ async function seedEmailTemplates() {
console.log(` Skipped: ${skippedCount}`);
console.log(` Errors: ${errorCount}`);
console.log('═'.repeat(60));
}
seedEmailTemplates()
.catch((error) => {
console.error('Fatal error:', error);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
}
// Only auto-execute when run directly (not when imported as a module)
if (require.main === module) {
seedEmailTemplates()
.catch((error) => {
console.error('Fatal error:', error);
process.exit(1);
});
}
//# sourceMappingURL=seed-email-templates.js.map

File diff suppressed because one or more lines are too long