UNPKG

47.1 kBPlain TextView Raw
1{"code":"function iter$__(a){ let v; return a ? ((v=a.toIterable) ? v.call(a) : a) : a; };;\nfunction defineName$__(cls,name){\n\tObject.defineProperty(cls,\"name\",{value:name,configurable:true});\n};;\nfunction extend$__(target,ext){\n\t// @ts-ignore\n\tconst descriptors = Object.getOwnPropertyDescriptors(ext);\n\tdelete descriptors.constructor;\n\tif(target.extend__ instanceof Function){\n\t\ttarget.extend__(descriptors,ext);\n\t} else {\n\t\t// @ts-ignore\n\t\tObject.defineProperties(target,descriptors);\n\t}\n\treturn target;\n};\n\n/*body*/\nimport nfs from 'fs';\n\nimport {ValidationError} from './protocol';\nimport {nameToTable,md5} from './utils';\nimport Coder from './util/coder';\nimport OPSQL from './base.sql?raw';\n\nclass ΩServerAdapter {\n\t\n\t\n\tgenerateΞschema(){\n\t\t\n\t\tlet doc = new Coder;\n\t\tlet docs = [doc];\n\t\t\n\t\tdoc.w(`create schema if not exists public;`);\n\t\t\n\t\t// clean up to keep the doc vars etc in separate variable\n\t\tlet extensions = doc.slot();\n\t\tlet tables = doc.slot();\n\t\tlet alters = doc.slot('',{unique: true});\n\t\tlet views = doc.slot();\n\t\t\n\t\tlet map = {};\n\t\tlet base = OPObject;\n\t\tlet roots = this.tables;\n\t\t\n\t\tlet meta = {};\n\t\t\n\t\tlet table = function(name,pass = 1) {\n\t\t\tlet blk;\n\t\t\t\n\t\t\treturn map[name + pass] ||= true && (\n\t\t\t\t\n\t\t\t\tblk = tables.expr((`CREATE TABLE IF NOT EXISTS ` + name + ` `),';'),\n\t\t\t\tblk\n\t\t\t);\n\t\t};\n\t\t\n\t\tlet viewslot = function(name) {\n\t\t\t\n\t\t\t// NOW DROPPING IT FIRST\n\t\t\treturn map[name] ||= views.indent((`DROP VIEW IF EXISTS ` + name + ` CASCADE; CREATE OR REPLACE VIEW ` + name + ` AS`));\n\t\t};\n\t\t\n\t\tfor (let type of iter$__(roots)){\n\t\t\t\n\t\t\tlet name = type.pgname;\n\t\t\tlet id = type.key;\n\t\t\tlet blk = table(name);\n\t\t\tblk.w((`id ` + (id.pgtype) + ` PRIMARY KEY`));\n\t\t\tblk.w(`_rev integer DEFAULT 8`);\n\t\t\tblk.w(`_cre integer DEFAULT op.now()`);\n\t\t\tblk.w(`_mod integer DEFAULT op.now()`);\n\t\t\tblk.w(`_typ text`);\n\t\t\tblk.w(`_del integer`);\n\t\t\t\n\t\t\tlet m = meta[name] = meta[type.ref] = {\n\t\t\t\tfields: [],\n\t\t\t\tpov: []\n\t\t\t};\n\t\t\t\n\t\t\t// special field indicating the last user to try to access / update row\n\t\t\t// simpler way to work with something akin to rls without needing to create\n\t\t\t// postgres-instance level roles for every user etc\n\t\t\tlet fields = {};\n\t\t\tlet subs = Array.from(type.types);\n\t\t\tlet all = [type].concat(subs);\n\t\t\t\n\t\t\tlet povs = {};\n\t\t\tfor (let sub of iter$__(all)){\n\t\t\t\t\n\t\t\t\tfor (let $1 = 0, $2 = iter$__(sub.$shape.$pov), $3 = $2.length; $1 < $3; $1++) {\n\t\t\t\t\tlet field = $2[$1];\n\t\t\t\t\tpovs[field.name] = field;\n\t\t\t\t\tm.pov.push(field);\n\t\t\t\t};\n\t\t\t};\n\t\t\t\n\t\t\tif (Object.keys(povs).length) {\n\t\t\t\t\n\t\t\t\tlet povtbl = table(name + '_pov');\n\t\t\t\tpovtbl.w(`id text PRIMARY KEY`);\n\t\t\t\tpovtbl.w(`_pov text`);\n\t\t\t\tpovtbl.w(`_for text`);\n\t\t\t\tpovtbl.w(`_rev integer DEFAULT 8`);\n\t\t\t\tpovtbl.w(`_cre integer DEFAULT op.now()`);\n\t\t\t\tpovtbl.w(`_mod integer DEFAULT op.now()`);\n\t\t\t};\n\t\t};\n\t\t\n\t\t// only for the tables\n\t\tfor (let type of iter$__(roots)){\n\t\t\t\n\t\t\tdoc.w((`INSERT into ` + (type.pgname) + ` (id,_rev,_cre,_mod,_del,_typ) VALUES ('',NULL,NULL,NULL,NULL,NULL) on conflict do nothing;`));\n\t\t};\n\t\t\n\t\tfor (let type of iter$__(roots)){\n\t\t\t\n\t\t\tlet name = type.pgname;\n\t\t\tlet fields = {_cre: 1,_mod: 1,_rev: 1,_del: 1,_typ: 1};\n\t\t\tlet subs = Array.from(type.types);\n\t\t\tlet all = [].concat(subs);\n\t\t\tlet pre = (`ALTER TABLE ` + name + ` `);\n\t\t\tlet tablename = name;\n\t\t\t\n\t\t\tfor (let sub of iter$__(all)){\n\t\t\t\t\n\t\t\t\t// loop through all the fields of each sub\n\t\t\t\t\n\t\t\t\t// for field of sub.fields\n\t\t\t\tfor (let $4 = 0, $5 = iter$__(sub.$shape), $6 = $5.length, typ, ddl, fk, foreignΦ, constraintname, constraint, idxpre; $4 < $6; $4++) {\n\t\t\t\t\tlet field = $5[$4];\n\t\t\t\t\tlet name = field.name + '__' + field.model.name;\n\t\t\t\t\t\n\t\t\t\t\tlet tbl = field.pov ? ((\"\" + tablename + `_pov`)) : tablename;\n\t\t\t\t\t\n\t\t\t\t\tlet pre = (`ALTER TABLE ` + tbl + ` `);\n\t\t\t\t\t\n\t\t\t\t\tlet decl = fields[field.name] ||= true && (\n\t\t\t\t\t\t\n\t\t\t\t\t\ttyp = field.pgtype,\n\t\t\t\t\t\t\n\t\t\t\t\t\tddl = (`\"` + (field.name) + `\" ` + typ),\n\t\t\t\t\t\tfield.keyΦ && (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tddl += ` PRIMARY KEY`\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\n\t\t\t\t\t\tfk = field.valuetype,\n\t\t\t\t\t\tforeignΦ = fk && (fk.prototype instanceof base),\n\t\t\t\t\t\t\n\t\t\t\t\t\t(fk && (fk.prototype instanceof base) && !(field.enum) && field.refΦ && field.foreign) && (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tfk?.table?.pgname && (\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tddl += (` REFERENCES ` + (fk.table.pgname) + `(id)`)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\n\t\t\t\t\t\t(typ && !(field.local) && !(field.virtual) && !(field.session)) && (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\talters.w(pre + (`ADD IF NOT EXISTS ` + ddl + `;`))\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\n\t\t\t\t\t\tfield.unique && (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// shotgun migration - not really checking the existing state at all.\n\t\t\t\t\t\t\tconstraintname = (\"\" + tbl + `_` + (field.name) + `_unique`),\n\t\t\t\t\t\t\tconstraint = (\"DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = '\" + constraintname + \"') THEN\t\t\t\t\t\t\t\tALTER TABLE \" + tbl + \" ADD CONSTRAINT \" + constraintname + \" UNIQUE (\" + (field.name) + \");\t\t\t\t\t\t\tEND IF;END;$$;\"),\n\t\t\t\t\t\t\talters.w(constraint)\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\n\t\t\t\t\t\t(typ == 'ltree') ? (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// only if it is not added already\n\t\t\t\t\t\t\textensions.w(`create extension if not exists ltree;`),\n\t\t\t\t\t\t\talters.w((`CREATE INDEX IF NOT EXISTS ` + tbl + `_` + (field.name) + `_idx on ` + tbl + ` USING GIST (` + (field.name) + `);`))\n\t\t\t\t\t\t\t// CREATE INDEX idx_your_table_parent_id ON your_table(parent_id);\n\t\t\t\t\t\t) : ((typ == 'citext') && (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\textensions.w(`create extension if not exists citext;`)\n\t\t\t\t\t\t)),\n\t\t\t\t\t\t\n\t\t\t\t\t\tfield.index && (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tidxpre = (`CREATE INDEX IF NOT EXISTS ` + tbl + `_` + (field.name) + `_idx`),\n\t\t\t\t\t\t\t(typ == 'jsonb') ? (\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\talters.w((\"\" + idxpre + ` on ` + tbl + ` USING gin(` + (field.name) + `);`))\n\t\t\t\t\t\t\t) : ((typ == 'text') && ( // will change\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\talters.w((\"\" + idxpre + ` on ` + tbl + `(` + (field.name) + `);`))\n\t\t\t\t\t\t\t))\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t};\n\t\t\t};\n\t\t\t\n\t\t\tfor (let sub of iter$__(subs)){\n\t\t\t\t\n\t\t\t\tif (sub === type) { continue; };\n\t\t\t\tlet cols = {};\n\t\t\t\t\n\t\t\t\tfor (let typ of iter$__(sub.types)){\n\t\t\t\t\t\n\t\t\t\t\tfor (let $7 = 0, $8 = iter$__(typ.$shape), $9 = $8.length; $7 < $9; $7++) {\n\t\t\t\t\t\tlet f = $8[$7];\n\t\t\t\t\t\t\n\t\t\t\t\t\t// TODO shared getter to tell if field is part of database or not\n\t\t\t\t\t\tif (f.pgtype && !(f.pov) && !(f.virtual) && !(f.local) && !(f.session)) {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tcols[f.name] ||= f;\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tlet view = viewslot(nameToTable(sub.name));\n\t\t\t\tview.w((\"SELECT \" + Object.keys(cols).map(function(_0) { return '\"' + _0 + '\"'; }).join(',')));\n\t\t\t\t\n\t\t\t\tlet include = Array.from(sub.types).map(function(_0) { return _0.id; }).map(function(_0) { return (\"'\" + _0 + \"'\"); }).join(',');\n\t\t\t\tview.w((`FROM ` + name + ` WHERE _typ = ANY(ARRAY[` + include + `])`));\n\t\t\t\tview.w(`WITH CASCADED CHECK OPTION;`);\n\t\t\t};\n\t\t};\n\t\t\n\t\t// add triggers for each root table\n\t\tfor (let type of iter$__(roots)){\n\t\t\t\n\t\t\t\n\t\t\tlet tbl = type.table.pgname;\n\t\t\tlet name = (\"\" + (type.table.pgname) + `_op`);\n\t\t\tlet povname = (\"\" + (type.table.pgname) + `_pov_op`);\n\t\t\tlet m = meta[type.ref];\n\t\t\t\n\t\t\tlet fun = function(name) {\n\t\t\t\t\n\t\t\t\tlet blk = doc[name];\n\t\t\t\t\n\t\t\t\tif (!(blk)) {\n\t\t\t\t\t\n\t\t\t\t\tlet decl = doc.block((`CREATE OR REPLACE FUNCTION ` + name + `() RETURNS TRIGGER AS $$ `),'$$ language plpgsql;');\n\t\t\t\t\tlet head = decl.indent('DECLARE');\n\t\t\t\t\tlet body = decl.block('BEGIN','END;');\n\t\t\t\t\tbody.name = name;\n\t\t\t\t\tbody.head = head;\n\t\t\t\t\tdecl.included = function() { return body.included(); };\n\t\t\t\t\tblk = doc[name] = body;\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\treturn blk;\n\t\t\t};\n\t\t\t\n\t\t\tlet before = fun((\"\" + name + `_before`));\n\t\t\tlet afterins = fun((\"\" + name + `_after_ins`));\n\t\t\t\n\t\t\t// the before method\n\t\t\tif (true) {\n\t\t\t\t\n\t\t\t\tlet body = before;// trigger.block('BEGIN','END;')\n\t\t\t\tlet types = type.types;\n\t\t\t\tlet poly = types.size > 1;\n\t\t\t\t\n\t\t\t\tbody.head.w(`row text;`);\n\t\t\t\tbody.head.w(`typ text;`);\n\t\t\t\tbody.head.w(`now int := op.now();`);\n\t\t\t\t\n\t\t\t\tbody.w(`typ := substring(NEW.id from '^[a-zA-Z]+');`);\n\t\t\t\t\n\t\t\t\tbody.pgif(`before? AND delete?`,function(blk) {\n\t\t\t\t\t\n\t\t\t\t\tblk.w((`UPDATE ` + (type.table.pgname) + ` set _del = op.now() where id = OLD.id;`));\n\t\t\t\t\treturn blk.w(`return NULL;`);\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tlet beforeupd = body.pgif(`before? AND update?`);\n\t\t\t\tlet beforeins = body.pgif(`before? AND insert?`);\n\t\t\t\t\n\t\t\t\tbeforeins.w(`NEW._typ := typ;`);\n\t\t\t\t\n\t\t\t\tbeforeupd.w('IF OLD IS NOT DISTINCT FROM NEW THEN RETURN NULL; END IF;');\n\t\t\t\tbeforeupd.w(`NEW._rev := OLD._rev + 4;`);// -- always?\n\t\t\t\t\n\t\t\t\t// need to take nested types into account for all this?\n\t\t\t\tfor (let typ of iter$__(types)){\n\t\t\t\t\t\n\t\t\t\t\tfor (let f of iter$__(typ.$shape.$shared)){\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (f.immutable) {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tbeforeupd.pgif((`old.` + f + `?`),(`new.` + f + ` := old.` + f + `;`));\n\t\t\t\t\t\t};\n\t\t\t\t\t\tif (f.required) {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// beforeupd.pgif(`!new.{f}?`,`ValidationError('{f} is required')`)\n\t\t\t\t\t\t\tbeforeupd.pgif((`!new.` + f + `?`),(`throw('ValidationError:` + f + ` is required')`));\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tfor (let $10 = 0, $11 = iter$__(type.$shape), $12 = $11.length; $10 < $12; $10++) {\n\t\t\t\t\tlet f = $11[$10];\n\t\t\t\t\tif (f.columnΦ && !(f.local) && !(f.session)) {\n\t\t\t\t\t\t\n\t\t\t\t\t\t// what about fields from subtypes?\n\t\t\t\t\t\t// for own k,v of type.fields when f.column? and !f.local and !f.session\n\t\t\t\t\t\t\n\t\t\t\t\t\t// what if it is a pov field\n\t\t\t\t\t\tif (!(f.pov) && f.default && f.default.sql != undefined) {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tbeforeins.pgif((`!new.` + (f.name) + `?`),function(blk) {\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\treturn blk.w((`new.` + (f.name) + ` := ` + (f.default.sql) + `;`));\n\t\t\t\t\t\t\t\t// beforeins.w 'IF OLD IS NOT DISTINCT FROM NEW THEN RETURN NULL; END IF;'\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\t// if we have op_cre\n\t\t\t\tbody.w(`NEW._cre := coalesce(NEW._cre,now);`);\n\t\t\t\tbody.w(`NEW._mod := now;`);\n\t\t\t\t\n\t\t\t\t// now check the rls\n\t\t\t\tif (type.rls) {\n\t\t\t\t\t\n\t\t\t\t\tfor (let $15 = type.rls, $13 = 0, $14 = Object.keys($15), $16 = $14.length, k, v; $13 < $16; $13++){\n\t\t\t\t\t\tk = $14[$13];v = $15[k];\n\t\t\t\t\t\tlet cond = body.pgif(k);\n\t\t\t\t\t\tif (v.error) {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tcond.w((`RAISE EXCEPTION '` + (v.error) + `';`));\n\t\t\t\t\t\t} else if (typeof v == 'string') {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tcond.w(v);\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tdoc.w((`CREATE OR REPLACE TRIGGER ` + name + `_before BEFORE INSERT OR UPDATE OR DELETE on ` + tbl + ` FOR EACH ROW EXECUTE PROCEDURE ` + name + `_before();`));\n\t\t\t\t\n\t\t\t\tbody.w('RETURN NEW;');\n\t\t\t};\n\t\t\t\n\t\t\tif (!(afterins.emptyΦ)) {\n\t\t\t\t\n\t\t\t\tafterins.w(`RETURN NULL;`);\n\t\t\t\tdoc.w((`CREATE OR REPLACE TRIGGER ` + (afterins.name) + ` AFTER INSERT on ` + tbl + ` FOR EACH ROW EXECUTE PROCEDURE ` + (afterins.name) + `();`));\n\t\t\t};\n\t\t\t\n\t\t\tif (m.pov.length) {\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tlet before = fun((\"\" + povname + `_before`));\n\t\t\t\tlet after = fun((\"\" + povname + `_after`));\n\t\t\t\t\n\t\t\t\tbefore.pgif(`before? AND insert?`,function(_0) {\n\t\t\t\t\t\n\t\t\t\t\t_0.w(`NEW._pov := split_part(NEW.id,'.',-1);`);\n\t\t\t\t\treturn _0.w(`NEW._for := array_to_string(trim_array(string_to_array(NEW.id,'.'),1),'.');`);\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tbefore.pgif(`before? AND update?`,function(_0) {\n\t\t\t\t\t\n\t\t\t\t\t_0.w('IF OLD IS NOT DISTINCT FROM NEW THEN RETURN NULL; END IF;');\n\t\t\t\t\treturn _0.w(`NEW._rev := OLD._rev + 4;`);\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tlet handled = {};\n\t\t\t\t\n\t\t\t\t// need to include sub-types here?!\n\t\t\t\t// Looping through the pov fields\n\t\t\t\tfor (let $17 = 0, $18 = iter$__(m.pov), $19 = $18.length; $17 < $19; $17++) {\n\t\t\t\t\tlet v = $18[$17];\n\t\t\t\t\tlet k = v.name;\n\t\t\t\t\tlet typ = v.pgtype;\n\t\t\t\t\t// temp workaround\n\t\t\t\t\tif (handled[k]) { continue; };\n\t\t\t\t\thandled[k] = v;\n\t\t\t\t\t// should be coded in the fields?\n\t\t\t\t\t\n\t\t\t\t\t// not really sure if this should happen live?\n\t\t\t\t\t// this is a pretty special case - move logic for generating schema into the Toggles themselves?\n\t\t\t\t\tlet agg = v.$agg;\n\t\t\t\t\t\n\t\t\t\t\tif (agg) {\n\t\t\t\t\t\t\n\t\t\t\t\t\tlet col = agg.name;// `_{k}_count`\n\t\t\t\t\t\tlet oldoff = (`(old.` + k + ` is null or old.` + k + ` < 1)`);\n\t\t\t\t\t\tlet incif = (`(new.` + k + ` > 0 and (insert? or ` + oldoff + `))`);\n\t\t\t\t\t\tlet decif = (`update? and new.` + k + ` < 1 and old.` + k + ` > 0`);\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (typ == 'integer') {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tincif = (`(new.` + k + ` > 0 and (insert? or (old.` + k + ` is null or old.` + k + ` < 1) ))`);\n\t\t\t\t\t\t\tdecif = (`update? and new.` + k + ` < 1 and old.` + k + ` > 0`);\n\t\t\t\t\t\t};\n\t\t\t\t\t\t\n\t\t\t\t\t\tafter.pgif(incif,function(blk) {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\treturn blk.w((`update ` + tbl + ` set ` + col + ` = COALESCE(` + col + `,0)+1 where id = new._for;`));\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\tafter.pgif(decif,function(blk) {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\treturn blk.w((`update ` + tbl + ` set ` + col + ` = COALESCE(` + col + `,1) - 1 where id = new._for;`));\n\t\t\t\t\t\t\t// blk.w `update {tbl} set _agg['{k}'][new._pov] = '1' where id = new.id;`\n\t\t\t\t\t\t});\n\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\tif (v.count && false) {\n\t\t\t\t\t\t\n\t\t\t\t\t\t// TODO create methods to denormalise these tables\n\t\t\t\t\t\t// update _entity set liked = sub.computed from (select id,_entity.liked,count(p.liked) as computed from _entity JOIN _entity__pov p USING(id) GROUP BY (id)) sub where sub.liked != sub.computed and _entity.id = sub.id;\n\t\t\t\t\t\t\n\t\t\t\t\t\tlet col = k;// `_{k}_count`\n\t\t\t\t\t\tlet oldoff = (`(old.` + k + ` is null or old.` + k + ` < 1)`);\n\t\t\t\t\t\tlet incif = (`(new.` + k + ` > 0 and (insert? or ` + oldoff + `))`);\n\t\t\t\t\t\tlet decif = (`update? and new.` + k + ` < 1 and old.` + k + ` > 0`);\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (typ == 'integer') {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tincif = (`(new.` + k + ` > 0 and (insert? or (old.` + k + ` is null or old.` + k + ` < 1) ))`);\n\t\t\t\t\t\t\tdecif = (`update? and new.` + k + ` < 1 and old.` + k + ` > 0`);\n\t\t\t\t\t\t};\n\t\t\t\t\t\t\n\t\t\t\t\t\tafter.pgif(incif,function(blk) {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// ends up with many different queries?\n\t\t\t\t\t\t\t// blk.w `update {tbl} set _agg['{k}'][new._pov] = '1' where id = new.id;`\n\t\t\t\t\t\t\treturn blk.w((`update ` + tbl + ` set ` + col + ` = ` + col + `+1 where id = new._for;`));\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\tafter.pgif(decif,function(blk) {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\treturn blk.w((`update ` + tbl + ` set ` + col + ` = ` + col + ` - 1 where id = new._for;`));\n\t\t\t\t\t\t\t// blk.w `update {tbl} set _agg['{k}'][new._pov] = '1' where id = new.id;`\n\t\t\t\t\t\t});\n\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\t// blk.w `update _entity set roles[new.user] = to_jsonb(new.roles) where id = new.entity;`\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tbefore.w(`NEW._mod := op.now();`);\n\t\t\t\tbefore.w('RETURN NEW;');\n\t\t\t\tafter.w('RETURN NEW;');\n\t\t\t\t\n\t\t\t\tdoc.w((`CREATE OR REPLACE TRIGGER ` + (before.name) + ` BEFORE INSERT OR UPDATE on ` + tbl + `_pov FOR EACH ROW EXECUTE PROCEDURE ` + (before.name) + `();`));\n\t\t\t\tdoc.w((`CREATE OR REPLACE TRIGGER ` + (after.name) + ` AFTER INSERT OR UPDATE on ` + tbl + `_pov FOR EACH ROW EXECUTE PROCEDURE ` + (after.name) + `();`));\n\t\t\t};\n\t\t\t// rewrite the shorthands for each individual field so that we can inspect the field type to act\n\t\t};\n\t\t\n\t\t// now potentially add null/none types for the different data\n\t\t// should we include ones for the subtypes as well?\n\t\t\n\t\t// make full on replacement strings to simplify this all\n\t\tlet str = doc.toString();\n\t\t\n\t\tstr = str.replace(/(\\!?)(agent|(new|old)\\.(\\w+))(\\?)/g,function(m,neg,row) {\n\t\t\t\n\t\t\t// allow numbers as well? maybe depending on the field\n\t\t\treturn (`(` + row + ` ` + (neg ? 'is' : 'is not') + ` null)`);\n\t\t});\n\t\t\n\t\tstr = str.replace(/changed\\.(\\w+)(\\?)?/g,function(m,name) {\n\t\t\t\n\t\t\treturn (`((insert? and new.` + name + ` is not null) or new.` + name + ` is distinct from old.` + name + `)`);\n\t\t});\n\t\t\n\t\tstr = str.replace(/(insert|delete|update)\\?/g,function(m,name) {\n\t\t\t\n\t\t\treturn (`(TG_OP = '` + name.toUpperCase() + `')`);\n\t\t});\n\t\t\n\t\tstr = str.replace(/throw\\(([^\\)]+)\\)/g,function(m,msg) {\n\t\t\t\n\t\t\treturn (`RAISE EXCEPTION ` + msg + `;`);\n\t\t});\n\t\t\n\t\tstr = str.replace(/(before|after)\\?/g,function(m,name) {\n\t\t\t\n\t\t\treturn (`(TG_WHEN = '` + name.toUpperCase() + `')`);\n\t\t});\n\t\t\n\t\treturn str;\n\t}\n\t\n\tasync migrate(){\n\t\tlet schema;\n\t\t\n\t\tObject.defineProperty(this,'schema',{enumerable: false,value: null,writable: true});\n\t\t\n\t\ttry {\n\t\t\tschema = this.schema = this.generateΞschema();\n\t\t} catch ($20) {\n\t\t\tschema = this.schema = $20;\n\t\t};\n\t\t\n\t\tif (schema instanceof Error) {\n\t\t\t\n\t\t\tconsole.log(\"failed to generate schema\",schema);\n\t\t\tthrow schema;\n\t\t};\n\t\t\n\t\ttry {\n\t\t\t\n\t\t\tawait this.pg.unsafe(String(OPSQL));\n\t\t\tlet settings = await this.pg`SELECT * from op.settings`;\n\t\t\tfor (let row of iter$__(settings)){\n\t\t\t\tsettings[row.id] = row.value;\n\t\t\t};\n\t\t\t\n\t\t\tlet hash = md5(schema);\n\t\t\tthis.log(settings,hash);\n\t\t\t// log 'will migrate',schema\n\t\t\t\n\t\t\tif (settings.schema_hash != hash) {\n\t\t\t\t\n\t\t\t\tthis.log('migrated app schema');\n\t\t\t\tschema += (`\\nUPDATE op.settings SET value = '` + hash + `' where id = 'schema_hash';`);\n\t\t\t\tawait this.pg.unsafe(schema);\n\t\t\t};\n\t\t\t\n\t\t\t// log schema\n\t\t\tnfs.writeFileSync(process.cwd() + '/schema.sql',schema);\n\t\t} catch (e) {\n\t\t\t\n\t\t\tconsole.log('error in migration!!',e);\n\t\t\tnfs.writeFileSync(process.cwd() + '/schema.sql',schema);\n\t\t};\n\t\t\n\t\t// will fail if it already exists\n\t\ttry {\n\t\t\treturn await this.pg.unsafe(`CREATE PUBLICATION alltables FOR ALL TABLES`);\n\t\t} catch (e) { };\n\t}\n\tstatic {\n\t\tdefineName$__(this,'ServerAdapter');}\n};\nextend$__(ServerAdapter.prototype,ΩServerAdapter.prototype);\n;\n","map":{"version":3,"file":"migrate.node.js","sourceRoot":"","sources":["/Users/abdellah/workspace/scrimba/op/src/migrate.node.imba"],"sourcesContent":["import nfs from 'fs'\n\nimport { ValidationError } from './protocol'\nimport { nameToTable, md5 } from './utils'\nimport Coder from './util/coder'\nimport OPSQL from './base.sql?raw'\n\nextend class ServerAdapter\n\n\tdef generate-schema\n\t\tlet doc = new Coder\n\t\tlet docs = [doc]\n\n\t\tdoc.w `create schema if not exists public;`\n\n\t\t# clean up to keep the doc vars etc in separate variable\n\t\tlet extensions = doc.slot!\n\t\tlet tables = doc.slot!\n\t\tlet alters = doc.slot('',unique: yes)\n\t\tlet views = doc.slot!\n\n\t\tlet map = {}\n\t\tlet base = OPObject\n\t\tlet roots = self.tables\n\n\t\tlet meta = {}\n\n\t\tlet table = do(name,pass = 1)\n\t\t\tmap[name + pass] ||= if true\n\t\t\t\tlet blk = tables.expr(`CREATE TABLE IF NOT EXISTS {name} `,';')\n\t\t\t\tblk\n\n\t\tlet viewslot = do(name)\n\t\t\t# NOW DROPPING IT FIRST\n\t\t\tmap[name] ||= views.indent(`DROP VIEW IF EXISTS {name} CASCADE; CREATE OR REPLACE VIEW {name} AS`)\n\n\t\tfor type of roots\n\t\t\tlet name = type.pgname\n\t\t\tlet id = type.key\n\t\t\tlet blk = table(name)\n\t\t\tblk.w `id {id.pgtype} PRIMARY KEY`\n\t\t\tblk.w `_rev integer DEFAULT 8`\n\t\t\tblk.w `_cre integer DEFAULT op.now()`\n\t\t\tblk.w `_mod integer DEFAULT op.now()`\n\t\t\tblk.w `_typ text`\n\t\t\tblk.w `_del integer`\n\n\t\t\tlet m = meta[name] = meta[type.ref] = {\n\t\t\t\tfields: []\n\t\t\t\tpov: []\n\t\t\t}\n\n\t\t\t# special field indicating the last user to try to access / update row\n\t\t\t# simpler way to work with something akin to rls without needing to create\n\t\t\t# postgres-instance level roles for every user etc\n\t\t\tlet fields = {}\n\t\t\tlet subs = Array.from(type.types)\n\t\t\tlet all = [type].concat(subs)\n\n\t\t\tlet povs = {}\n\t\t\tfor sub of all\n\t\t\t\tfor field in sub.$shape.$pov\n\t\t\t\t\tpovs[field.name] = field\n\t\t\t\t\tm.pov.push(field)\n\n\t\t\tif Object.keys(povs).length\n\t\t\t\tlet povtbl = table(name + '_pov')\n\t\t\t\tpovtbl.w `id text PRIMARY KEY`\n\t\t\t\tpovtbl.w `_pov text`\n\t\t\t\tpovtbl.w `_for text`\n\t\t\t\tpovtbl.w `_rev integer DEFAULT 8`\n\t\t\t\tpovtbl.w `_cre integer DEFAULT op.now()`\n\t\t\t\tpovtbl.w `_mod integer DEFAULT op.now()`\n\n\t\t# only for the tables\n\t\tfor type of roots\n\t\t\tdoc.w `INSERT into {type.pgname} (id,_rev,_cre,_mod,_del,_typ) VALUES ('',NULL,NULL,NULL,NULL,NULL) on conflict do nothing;`\n\n\t\tfor type of roots\n\t\t\tlet name = type.pgname\n\t\t\tlet fields = {_cre:1,_mod:1,_rev:1,_del:1,_typ:1}\n\t\t\tlet subs = Array.from(type.types)\n\t\t\tlet all = [].concat(subs)\n\t\t\tlet pre = `ALTER TABLE {name} `\n\t\t\tlet tablename = name\n\n\t\t\tfor sub of all\n\t\t\t\t# loop through all the fields of each sub\n\n\t\t\t\t# for field of sub.fields\n\t\t\t\tfor field in sub.$shape\n\t\t\t\t\tlet name = field.name + '__' + field.model.name\n\n\t\t\t\t\tlet tbl = field.pov ? `{tablename}_pov` : tablename\n\n\t\t\t\t\tlet pre = `ALTER TABLE {tbl} `\n\n\t\t\t\t\tlet decl = fields[field.name] ||= if true\n\t\t\t\t\t\tlet typ = field.pgtype\n\n\t\t\t\t\t\tlet ddl = `\"{field.name}\" {typ}`\n\t\t\t\t\t\tif field.key?\n\t\t\t\t\t\t\tddl += ` PRIMARY KEY`\n\n\t\t\t\t\t\tlet fk = field.valuetype\n\t\t\t\t\t\tlet foreign? = fk and fk.prototype isa base\n\n\t\t\t\t\t\tif fk and fk.prototype isa base and !field.enum and field.ref? and field.foreign\n\t\t\t\t\t\t\tif fk..table..pgname\n\t\t\t\t\t\t\t\tddl += ` REFERENCES {fk.table.pgname}(id)`\n\n\t\t\t\t\t\tif typ and !field.local and !field.virtual and !field.session\n\t\t\t\t\t\t\talters.w pre + `ADD IF NOT EXISTS {ddl};`\n\n\t\t\t\t\t\tif field.unique\n\t\t\t\t\t\t\t# shotgun migration - not really checking the existing state at all.\n\t\t\t\t\t\t\tlet constraintname = `{tbl}_{field.name}_unique`\n\t\t\t\t\t\t\tlet constraint = \"DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = '{constraintname}') THEN\n\t\t\t\t\t\t\t\tALTER TABLE {tbl} ADD CONSTRAINT {constraintname} UNIQUE ({field.name});\n\t\t\t\t\t\t\tEND IF;END;$$;\"\n\t\t\t\t\t\t\talters.w constraint\n\n\t\t\t\t\t\tif typ == 'ltree'\n\t\t\t\t\t\t\t# only if it is not added already\n\t\t\t\t\t\t\textensions.w `create extension if not exists ltree;`\n\t\t\t\t\t\t\talters.w `CREATE INDEX IF NOT EXISTS {tbl}_{field.name}_idx on {tbl} USING GIST ({field.name});`\n\t\t\t\t\t\t\t# CREATE INDEX idx_your_table_parent_id ON your_table(parent_id);\n\t\t\t\t\t\telif typ == 'citext'\n\t\t\t\t\t\t\textensions.w `create extension if not exists citext;`\n\n\t\t\t\t\t\tif field.index\n\t\t\t\t\t\t\tlet idxpre = `CREATE INDEX IF NOT EXISTS {tbl}_{field.name}_idx`\n\t\t\t\t\t\t\tif typ == 'jsonb'\n\t\t\t\t\t\t\t\talters.w `{idxpre} on {tbl} USING gin({field.name});`\n\t\t\t\t\t\t\telif typ == 'text' # will change\n\t\t\t\t\t\t\t\talters.w `{idxpre} on {tbl}({field.name});`\n\n\t\t\tfor sub of subs\n\t\t\t\tcontinue if sub is type\n\t\t\t\tlet cols = {}\n\n\t\t\t\tfor typ of sub.types\n\t\t\t\t\tfor f in typ.$shape\n\t\t\t\t\t\t# TODO shared getter to tell if field is part of database or not\n\t\t\t\t\t\tif f.pgtype and !f.pov and !f.virtual and !f.local and !f.session\n\t\t\t\t\t\t\tcols[f.name] ||= f\n\n\t\t\t\tlet view = viewslot(nameToTable(sub.name))\n\t\t\t\tview.w \"SELECT {Object.keys(cols).map(do '\"' + $1 + '\"').join(',')}\"\n\n\t\t\t\tlet include = Array.from(sub.types).map(do $1.id).map(do \"'{$1}'\").join(',')\n\t\t\t\tview.w `FROM {name} WHERE _typ = ANY(ARRAY[{include}])`\n\t\t\t\tview.w `WITH CASCADED CHECK OPTION;`\n\n\t\t# add triggers for each root table\n\t\tfor type of roots\n\n\t\t\tlet tbl = type.table.pgname\n\t\t\tlet name = `{type.table.pgname}_op`\n\t\t\tlet povname = `{type.table.pgname}_pov_op`\n\t\t\tlet m = meta[type.ref]\n\n\t\t\tlet fun = do(name)\n\t\t\t\tlet blk = doc[name]\n\n\t\t\t\tunless blk\n\t\t\t\t\tlet decl = doc.block(`CREATE OR REPLACE FUNCTION {name}() RETURNS TRIGGER AS $$ `,'$$ language plpgsql;')\n\t\t\t\t\tlet head = decl.indent('DECLARE')\n\t\t\t\t\tlet body = decl.block('BEGIN','END;')\n\t\t\t\t\tbody.name = name\n\t\t\t\t\tbody.head = head\n\t\t\t\t\tdecl.included = do body.included!\n\t\t\t\t\tblk = doc[name] = body\n\n\t\t\t\treturn blk\n\n\t\t\tlet before = fun(`{name}_before`)\n\t\t\tlet afterins = fun(`{name}_after_ins`)\n\n\t\t\t# the before method\n\t\t\tif true\n\t\t\t\tlet body = before # trigger.block('BEGIN','END;')\n\t\t\t\tlet types = type.types\n\t\t\t\tlet poly = types.size > 1\n\n\t\t\t\tbody.head.w `row text;`\n\t\t\t\tbody.head.w `typ text;`\n\t\t\t\tbody.head.w `now int := op.now();`\n\n\t\t\t\tbody.w `typ := substring(NEW.id from '^[a-zA-Z]+');`\n\n\t\t\t\tbody.pgif `before? AND delete?` do(blk)\n\t\t\t\t\tblk.w `UPDATE {type.table.pgname} set _del = op.now() where id = OLD.id;`\n\t\t\t\t\tblk.w `return NULL;`\n\n\t\t\t\tlet beforeupd = body.pgif `before? AND update?`\n\t\t\t\tlet beforeins = body.pgif `before? AND insert?`\n\n\t\t\t\tbeforeins.w `NEW._typ := typ;`\n\n\t\t\t\tbeforeupd.w 'IF OLD IS NOT DISTINCT FROM NEW THEN RETURN NULL; END IF;'\n\t\t\t\tbeforeupd.w `NEW._rev := OLD._rev + 4;` # -- always?\n\n\t\t\t\t# need to take nested types into account for all this?\n\t\t\t\tfor typ of types\n\t\t\t\t\tfor f of typ.$shape.$shared\n\t\t\t\t\t\tif f.immutable\n\t\t\t\t\t\t\tbeforeupd.pgif(`old.{f}?`,`new.{f} := old.{f};`)\n\t\t\t\t\t\tif f.required\n\t\t\t\t\t\t\t# beforeupd.pgif(`!new.{f}?`,`ValidationError('{f} is required')`)\n\t\t\t\t\t\t\tbeforeupd.pgif(`!new.{f}?`,`throw('ValidationError:{f} is required')`)\n\n\t\t\t\tfor f in type.$shape\n\t\t\t\t\tif f.column? and !f.local and !f.session\n\t\t\t\t\t\t# what about fields from subtypes?\n\t\t\t\t\t\t# for own k,v of type.fields when f.column? and !f.local and !f.session\n\n\t\t\t\t\t\t# what if it is a pov field\n\t\t\t\t\t\tif !f.pov and f.default and f.default.sql != undefined\n\n\t\t\t\t\t\t\tbeforeins.pgif `!new.{f.name}?` do(blk)\n\t\t\t\t\t\t\t\tblk.w `new.{f.name} := {f.default.sql};`\n\t\t\t\t\t\t\t\t# beforeins.w 'IF OLD IS NOT DISTINCT FROM NEW THEN RETURN NULL; END IF;'\n\n\t\t\t\t# if we have op_cre\n\t\t\t\tbody.w `NEW._cre := coalesce(NEW._cre,now);`\n\t\t\t\tbody.w `NEW._mod := now;`\n\n\t\t\t\t# now check the rls\n\t\t\t\tif type.rls\n\t\t\t\t\tfor own k,v of type.rls\n\t\t\t\t\t\tlet cond = body.pgif(k)\n\t\t\t\t\t\tif v.error\n\t\t\t\t\t\t\tcond.w `RAISE EXCEPTION '{v.error}';`\n\t\t\t\t\t\telif typeof v == 'string'\n\t\t\t\t\t\t\tcond.w v\n\n\t\t\t\tdoc.w `CREATE OR REPLACE TRIGGER {name}_before BEFORE INSERT OR UPDATE OR DELETE on {tbl} FOR EACH ROW EXECUTE PROCEDURE {name}_before();`\n\n\t\t\t\tbody.w 'RETURN NEW;'\n\n\t\t\tif !afterins.empty?\n\t\t\t\tafterins.w `RETURN NULL;`\n\t\t\t\tdoc.w `CREATE OR REPLACE TRIGGER {afterins.name} AFTER INSERT on {tbl} FOR EACH ROW EXECUTE PROCEDURE {afterins.name}();`\n\n\t\t\tif m.pov.length\n\n\t\t\t\tlet before = fun(`{povname}_before`)\n\t\t\t\tlet after = fun(`{povname}_after`)\n\n\t\t\t\tbefore.pgif `before? AND insert?` do\n\t\t\t\t\t$1.w `NEW._pov := split_part(NEW.id,'.',-1);`\n\t\t\t\t\t$1.w `NEW._for := array_to_string(trim_array(string_to_array(NEW.id,'.'),1),'.');`\n\n\t\t\t\tbefore.pgif `before? AND update?` do\n\t\t\t\t\t$1.w 'IF OLD IS NOT DISTINCT FROM NEW THEN RETURN NULL; END IF;'\n\t\t\t\t\t$1.w `NEW._rev := OLD._rev + 4;`\n\n\t\t\t\tlet handled = {}\n\n\t\t\t\t# need to include sub-types here?!\n\t\t\t\t# Looping through the pov fields\n\t\t\t\tfor v in m.pov\n\t\t\t\t\tlet k = v.name\n\t\t\t\t\tlet typ = v.pgtype\n\t\t\t\t\t# temp workaround\n\t\t\t\t\tcontinue if handled[k]\n\t\t\t\t\thandled[k] = v\n\t\t\t\t\t# should be coded in the fields?\n\n\t\t\t\t\t# not really sure if this should happen live?\n\t\t\t\t\t# this is a pretty special case - move logic for generating schema into the Toggles themselves?\n\t\t\t\t\tlet agg = v.$agg\n\n\t\t\t\t\tif agg\n\t\t\t\t\t\tlet col = agg.name # `_{k}_count`\n\t\t\t\t\t\tlet oldoff = `(old.{k} is null or old.{k} < 1)`\n\t\t\t\t\t\tlet incif = `(new.{k} > 0 and (insert? or {oldoff}))`\n\t\t\t\t\t\tlet decif = `update? and new.{k} < 1 and old.{k} > 0`\n\n\t\t\t\t\t\tif typ == 'integer'\n\t\t\t\t\t\t\tincif = `(new.{k} > 0 and (insert? or (old.{k} is null or old.{k} < 1) ))`\n\t\t\t\t\t\t\tdecif = `update? and new.{k} < 1 and old.{k} > 0`\n\n\t\t\t\t\t\tafter.pgif(incif) do(blk)\n\t\t\t\t\t\t\tblk.w `update {tbl} set {col} = COALESCE({col},0)+1 where id = new._for;`\n\n\t\t\t\t\t\tafter.pgif(decif) do(blk)\n\t\t\t\t\t\t\tblk.w `update {tbl} set {col} = COALESCE({col},1) - 1 where id = new._for;`\n\t\t\t\t\t\t\t# blk.w `update {tbl} set _agg['{k}'][new._pov] = '1' where id = new.id;`\n\n\t\t\t\t\tif v.count and false\n\t\t\t\t\t\t# TODO create methods to denormalise these tables\n\t\t\t\t\t\t# update _entity set liked = sub.computed from (select id,_entity.liked,count(p.liked) as computed from _entity JOIN _entity__pov p USING(id) GROUP BY (id)) sub where sub.liked != sub.computed and _entity.id = sub.id;\n\n\t\t\t\t\t\tlet col = k # `_{k}_count`\n\t\t\t\t\t\tlet oldoff = `(old.{k} is null or old.{k} < 1)`\n\t\t\t\t\t\tlet incif = `(new.{k} > 0 and (insert? or {oldoff}))`\n\t\t\t\t\t\tlet decif = `update? and new.{k} < 1 and old.{k} > 0`\n\n\t\t\t\t\t\tif typ == 'integer'\n\t\t\t\t\t\t\tincif = `(new.{k} > 0 and (insert? or (old.{k} is null or old.{k} < 1) ))`\n\t\t\t\t\t\t\tdecif = `update? and new.{k} < 1 and old.{k} > 0`\n\n\t\t\t\t\t\tafter.pgif(incif) do(blk)\n\t\t\t\t\t\t\t# ends up with many different queries?\n\t\t\t\t\t\t\t# blk.w `update {tbl} set _agg['{k}'][new._pov] = '1' where id = new.id;`\n\t\t\t\t\t\t\tblk.w `update {tbl} set {col} = {col}+1 where id = new._for;`\n\n\t\t\t\t\t\tafter.pgif(decif) do(blk)\n\t\t\t\t\t\t\tblk.w `update {tbl} set {col} = {col} - 1 where id = new._for;`\n\t\t\t\t\t\t\t# blk.w `update {tbl} set _agg['{k}'][new._pov] = '1' where id = new.id;`\n\n\t\t\t\t\t#\tblk.w `update _entity set roles[new.user] = to_jsonb(new.roles) where id = new.entity;`\n\n\t\t\t\tbefore.w `NEW._mod := op.now();`\n\t\t\t\tbefore.w 'RETURN NEW;'\n\t\t\t\tafter.w 'RETURN NEW;'\n\n\t\t\t\tdoc.w `CREATE OR REPLACE TRIGGER {before.name} BEFORE INSERT OR UPDATE on {tbl}_pov FOR EACH ROW EXECUTE PROCEDURE {before.name}();`\n\t\t\t\tdoc.w `CREATE OR REPLACE TRIGGER {after.name} AFTER INSERT OR UPDATE on {tbl}_pov FOR EACH ROW EXECUTE PROCEDURE {after.name}();`\n\t\t\t# rewrite the shorthands for each individual field so that we can inspect the field type to act\n\n\t\t# now potentially add null/none types for the different data\n\t\t# should we include ones for the subtypes as well?\n\n\t\t# make full on replacement strings to simplify this all\n\t\tlet str = doc.toString!\n\n\t\tstr = str.replace(/(\\!?)(agent|(new|old)\\.(\\w+))(\\?)/g) do(m,neg,row)\n\t\t\t# allow numbers as well? maybe depending on the field\n\t\t\t`({row} {neg ? 'is' : 'is not'} null)`\n\n\t\tstr = str.replace(/changed\\.(\\w+)(\\?)?/g) do(m,name)\n\t\t\t`((insert? and new.{name} is not null) or new.{name} is distinct from old.{name})`\n\n\t\tstr = str.replace(/(insert|delete|update)\\?/g) do(m,name)\n\t\t\t`(TG_OP = '{name.toUpperCase!}')`\n\n\t\tstr = str.replace(/throw\\(([^\\)]+)\\)/g) do(m,msg)\n\t\t\t`RAISE EXCEPTION {msg};`\n\n\t\tstr = str.replace(/(before|after)\\?/g) do(m,name)\n\t\t\t`(TG_WHEN = '{name.toUpperCase!}')`\n\n\t\treturn str\n\n\tdef migrate\n\t\tObject.defineProperty(self,'schema',enumerable: no, value: null, writable: yes)\n\n\t\tlet schema = self.schema = try generate-schema! catch\n\n\t\tif schema isa Error\n\t\t\tconsole.log \"failed to generate schema\",schema\n\t\t\tthrow schema\n\n\t\ttry\n\t\t\tawait pg.unsafe(String OPSQL)\n\t\t\tlet settings = await pg`SELECT * from op.settings`\n\t\t\tsettings[row.id] = row.value for row of settings\n\n\t\t\tlet hash = md5(schema)\n\t\t\tlog settings,hash\n\t\t\t# log 'will migrate',schema\n\n\t\t\tif settings.schema_hash != hash\n\t\t\t\tlog 'migrated app schema'\n\t\t\t\tschema += `\\nUPDATE op.settings SET value = '{hash}' where id = 'schema_hash';`\n\t\t\t\tawait pg.unsafe(schema)\n\n\t\t\t# log schema\n\t\t\tnfs.writeFileSync(process.cwd!+ '/schema.sql',schema)\n\n\t\tcatch e\n\t\t\tconsole.log 'error in migration!!',e\n\t\t\tnfs.writeFileSync(process.cwd!+ '/schema.sql',schema)\n\n\t\t# will fail if it already exists\n\t\ttry await pg.unsafe(`CREATE PUBLICATION alltables FOR ALL TABLES`)\n"],"names":[],"mappings":"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"},"dependencies":[],"meta":{"vite":{"lang":"js"}}}
\No newline at end of file