/// PocketBase migration: recurring look-ahead templates. /// /// Apply on the server (from /opt/pocketbase or wherever the binary lives): /// /// sudo cp this_file /opt/pocketbase/pb_migrations/ /// sudo chown pocketbase:pocketbase /opt/pocketbase/pb_migrations/*.js /// sudo -u pocketbase /opt/pocketbase/pocketbase migrate up /// sudo systemctl restart pocketbase /// /// Depends on usersapp (same owner rules as labels / tx_meta). migrate((app) => { const users = app.findCollectionByNameOrId("usersapp"); const ownerRules = { listRule: "user = @request.auth.id", viewRule: "user = @request.auth.id", createRule: "@request.auth.id != '' && user = @request.auth.id", updateRule: "user = @request.auth.id", deleteRule: "user = @request.auth.id", }; const recurringTemplates = new Collection({ type: "base", name: "recurring_templates", ...ownerRules, fields: [ { type: "relation", name: "user", required: true, collectionId: users.id, cascadeDelete: true, maxSelect: 1, }, { // App-side RecurringTemplate.id type: "text", name: "client_id", required: true, min: 1, max: 120, }, { type: "text", name: "name", required: true, min: 1, max: 400, }, { type: "number", name: "day_of_month", required: true, }, { type: "text", name: "currency", required: true, min: 1, max: 8, }, { // "transaction" | "label" type: "text", name: "source", required: true, min: 1, max: 32, }, { // "lastValue" | "avgLastTxs" | "labelAvgMonths" type: "text", name: "amount_rule", required: true, min: 1, max: 32, }, { type: "text", name: "merchant_key", required: false, max: 500, }, { type: "text", name: "source_tx_id", required: false, max: 2000, }, { type: "text", name: "label_id", required: false, max: 80, }, { type: "number", name: "avg_count", required: false, }, { type: "bool", name: "auto_from_recurring", required: false, }, ], indexes: [ "CREATE UNIQUE INDEX idx_recurring_templates_user_client ON recurring_templates (user, client_id)", ], }); app.save(recurringTemplates); }, (app) => { try { const col = app.findCollectionByNameOrId("recurring_templates"); app.delete(col); } catch (_) {} });