update migration of user fields

This commit is contained in:
JCEEE
2026-09-11 07:40:38 +01:00
parent 486f239fb1
commit 65afb5a721
2 changed files with 62 additions and 21 deletions
+61 -20
View File
@@ -407,6 +407,34 @@ async function ensureSchema(): Promise<void> {
console.log('[migrate] Schema bootstrapped.');
}
// Add theme + newer auth fields to `users` on installs where the collection
// already exists (fresh installs get them via ensureUsers). Idempotent —
// only adds missing fields. Mirrors ensureFamFields.
async function ensureUserFields(): Promise<void> {
const usersCol = await getCollection('users');
if (!usersCol) return;
const has = (n: string) => usersCol.fields.some((f: any) => f.name === n);
const needed: any[] = [];
if (!has('pattern')) {
needed.push({ name: 'pattern', type: 'text', required: false });
}
if (!has('themeSize')) {
needed.push({ name: 'themeSize', type: 'text', required: false });
}
if (!has('themeOpacity')) {
needed.push({ name: 'themeOpacity', type: 'text', required: false });
}
if (!has('passwordResetToken')) {
needed.push({ name: 'passwordResetToken', type: 'text', required: false });
}
if (!has('passwordResetExpiry')) {
needed.push({ name: 'passwordResetExpiry', type: 'text', required: false });
}
if (needed.length) {
await updateCollection(usersCol.id, { ...usersCol, fields: [...usersCol.fields, ...needed] });
}
}
// Add the access-gating fields to `fams` on installs where it already exists
// (fresh installs get them via SCHEMA_PLAN). Idempotent — only adds missing
// fields.
@@ -443,6 +471,7 @@ export async function migrate(): Promise<void> {
await ensureSchema();
// Runs even when the schema already exists (unlike ensureSchema's early
// return) so new platform collections/fields/seed land on existing installs.
await ensureUserFields();
await ensureFamFields();
await ensureBonusFields();
await ensureTemplateFields();
@@ -960,7 +989,7 @@ function addDays(d: Date, n: number): Date {
// Each kid's "completion personality" — Juno is reliable, Jackson solid, Jalipo spotty.
// Maps assigned chore customName → weekday (0=Sun) → probability of completion.
const COMPLETION_PROFILES: Record<string, Record<number, Record<string, number>>> = {
'Juno': {
Juno: {
0: { default: 0.85 }, // Sun
1: { default: 0.95 }, // Mon
2: { default: 0.9 },
@@ -969,7 +998,7 @@ const COMPLETION_PROFILES: Record<string, Record<number, Record<string, number>>
5: { default: 0.85 }, // Fri
6: { default: 0.8 } // Sat
},
'Jackson': {
Jackson: {
0: { default: 0.7 },
1: { default: 0.9 },
2: { default: 0.85 },
@@ -978,7 +1007,7 @@ const COMPLETION_PROFILES: Record<string, Record<number, Record<string, number>>
5: { default: 0.7 },
6: { default: 0.6 }
},
'Jalipo': {
Jalipo: {
0: { default: 0.4 },
1: { default: 0.75 },
2: { default: 0.65 },
@@ -1018,12 +1047,18 @@ async function seedDemoCompletions(): Promise<void> {
// Fetch members, assigned chores
const [membersRes, assignedRes] = await Promise.all([
fetch(`${PB_ENDPOINT}/api/collections/users/records?filter=${encodeURIComponent(`famId='${famId}' && role='child'`)}&perPage=10`, {
headers: { Authorization: `Bearer ${t}` }
}),
fetch(`${PB_ENDPOINT}/api/collections/assigned_chores/records?filter=famId='${famId}'&perPage=100`, {
headers: { Authorization: `Bearer ${t}` }
})
fetch(
`${PB_ENDPOINT}/api/collections/users/records?filter=${encodeURIComponent(`famId='${famId}' && role='child'`)}&perPage=10`,
{
headers: { Authorization: `Bearer ${t}` }
}
),
fetch(
`${PB_ENDPOINT}/api/collections/assigned_chores/records?filter=famId='${famId}'&perPage=100`,
{
headers: { Authorization: `Bearer ${t}` }
}
)
]);
const members: any[] = (await membersRes.json())?.items || [];
const assigned: any[] = (await assignedRes.json())?.items || [];
@@ -1032,12 +1067,18 @@ async function seedDemoCompletions(): Promise<void> {
// Delete existing completions and weekly_history for the demo family
const [oldCompsRes, oldHistoryRes] = await Promise.all([
fetch(`${PB_ENDPOINT}/api/collections/completions/records?filter=famId='${famId}'&perPage=500`, {
headers: { Authorization: `Bearer ${t}` }
}),
fetch(`${PB_ENDPOINT}/api/collections/weekly_history/records?filter=famId='${famId}'&perPage=500`, {
headers: { Authorization: `Bearer ${t}` }
})
fetch(
`${PB_ENDPOINT}/api/collections/completions/records?filter=famId='${famId}'&perPage=500`,
{
headers: { Authorization: `Bearer ${t}` }
}
),
fetch(
`${PB_ENDPOINT}/api/collections/weekly_history/records?filter=famId='${famId}'&perPage=500`,
{
headers: { Authorization: `Bearer ${t}` }
}
)
]);
const oldComps: any[] = (await oldCompsRes.json())?.items || [];
const oldHistory: any[] = (await oldHistoryRes.json())?.items || [];
@@ -1061,7 +1102,10 @@ async function seedDemoCompletions(): Promise<void> {
// Track per-member-per-week totals for weekly_history
type WeekKey = string; // "YYYY-MM-DD" (Monday)
const weekTotals: Record<string, Record<string, { points: number; money: number; count: number }>> = {};
const weekTotals: Record<
string,
Record<string, { points: number; money: number; count: number }>
> = {};
for (const member of members) {
const profile = COMPLETION_PROFILES[member.name] || COMPLETION_PROFILES['Jalipo'];
@@ -1092,10 +1136,7 @@ async function seedDemoCompletions(): Promise<void> {
const prob = dayProfile[chore.customName] || dayProfile.default;
const rng = demoRng(
famId.length * 1000 +
member.id.length * 100 +
d * 10 +
(chore.id?.charCodeAt(0) || 0)
famId.length * 1000 + member.id.length * 100 + d * 10 + (chore.id?.charCodeAt(0) || 0)
);
if (rng() > prob) continue; // missed this day