@aotter/mantle 0.2.0 → 0.2.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/dist/build/compiler.d.ts +4 -4
- package/dist/build/compiler.js +6 -3
- package/dist/build/spec/domain/model/ManifestGrammar.d.ts +39 -1
- package/dist/build/spec/domain/model/RuntimePlan.d.ts +16 -3
- package/dist/build/spec/domain/model/SqlIr.d.ts +30 -0
- package/dist/build/spec/kernel/diagnostic.d.ts +1 -1
- package/dist/domain/describe/chunk-P6PP6VVV.js +1 -0
- package/dist/domain/describe/index.d.ts +1 -0
- package/dist/domain/describe/index.js +1 -1
- package/dist/domain/describe/match.d.ts +19 -0
- package/dist/domain/describe/target-hash.js +1 -1
- package/dist/infrastructure/adminEntries.js +19 -3
- package/dist/infrastructure/bundle.js +43 -8
- package/dist/infrastructure/cli.js +1 -1
- package/dist/infrastructure/generate.js +17 -3
- package/dist/kernel/binds.d.ts +18 -3
- package/dist/kernel/binds.js +1 -1
- package/dist/kernel/contracts.d.ts +7 -0
- package/dist/kernel/contracts.js +9 -0
- package/dist/kernel/driver/bun-sqlite.js +3 -3
- package/dist/kernel/driver/d1.d.ts +1 -1
- package/dist/kernel/driver/d1.js +6 -3
- package/dist/kernel/driver/postgres.d.ts +2 -1
- package/dist/kernel/driver/postgres.js +11 -6
- package/dist/kernel/mcp-handler.js +2 -1
- package/dist/kernel/rest-router.js +3 -5
- package/dist/kernel/rest.d.ts +2 -1
- package/dist/kernel/rest.js +1 -0
- package/dist/kernel/route-pattern.d.ts +26 -0
- package/dist/kernel/route-pattern.js +34 -0
- package/dist/kernel/store.d.ts +15 -1
- package/dist/kernel/store.js +51 -18
- package/dist/usecase/adminBindings.js +2 -2
- package/dist/usecase/adminClient.js +4 -1
- package/dist/usecase/generate.js +7 -5
- package/dist/usecase/handlers.js +1 -1
- package/dist/usecase/publishing.js +20 -7
- package/dist/usecase/rest.js +5 -5
- package/dist/usecase/stores.js +8 -3
- package/docs/examples/README.md +1 -1
- package/docs/examples/app-shell/README.md +58 -10
- package/docs/examples/app-shell/package.json +6 -6
- package/docs/examples/club-events/manifests/club-events.yaml +2 -0
- package/docs/examples/generated-web/seed.sql +5 -4
- package/docs/examples/purchasing/manifests/purchasing.yaml +3 -0
- package/docs/handbook/cloudflare/media-r2.md +6 -3
- package/docs/handbook/cloudflare/service-entry.md +2 -0
- package/docs/handbook/concepts/lifecycle-and-locales.md +21 -1
- package/docs/handbook/examples/hub.md +1 -1
- package/docs/handbook/guides/admin-ui.md +1 -1
- package/docs/handbook/guides/agent-setup.md +13 -8
- package/docs/handbook/guides/agent-workflow-acceptance.md +129 -19
- package/docs/handbook/guides/local-testing.md +50 -5
- package/docs/handbook/guides/native-admin.md +218 -11
- package/docs/handbook/guides/native-execution.md +5 -4
- package/docs/handbook/guides/revisions.md +584 -0
- package/docs/handbook/guides/size-and-startup.md +140 -0
- package/docs/handbook/guides/sql-patterns.md +47 -1
- package/docs/handbook/guides/typed-queries.md +8 -3
- package/docs/handbook/navigation.json +4 -0
- package/docs/handbook/reference/authorization.md +2 -0
- package/docs/handbook/reference/describe.md +42 -0
- package/docs/handbook/reference/diagnostics.md +12 -3
- package/docs/handbook/reference/procedure.md +4 -4
- package/docs/handbook/reference/schema.md +71 -7
- package/docs/handbook/reference/sql.md +2 -1
- package/docs/handbook/reference/surface.md +3 -2
- package/docs/handbook/reference/trigger.md +12 -0
- package/docs/handbook/releases/index.md +44 -1
- package/docs/handbook/start/agents.md +6 -2
- package/docs/handbook/start/project-and-cli.md +4 -0
- package/docs/handbook/start/quickstart-worker.md +1 -1
- package/docs/skills/develop/SKILL.md +15 -3
- package/docs/skills/integrate/SKILL.md +3 -1
- package/docs/skills/performance/SKILL.md +169 -0
- package/docs/skills/update/SKILL.md +9 -5
- package/docs/upgrade-0.1-to-0.2.md +151 -39
- package/package.json +9 -9
- package/skills/README.md +6 -2
- package/skills/mantle/SKILL.md +19 -5
- package/dist/domain/describe/chunk-SGMRVDGE.js +0 -1
package/dist/build/compiler.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
var __defProp=Object.defineProperty;var __export=(target2,all)=>{for(var name4 in all)__defProp(target2,name4,{get:all[name4],enumerable:!0})};function makeDiagnostic(input){let{code,phase,severity,path,source,value:value2,expected,candidates,suggestion}=input,msg=input.message;if(!msg){let parts=[`[${phase}/${code}] at ${path}`];expected&&parts.push(`expected ${expected}`),value2!==void 0&&parts.push(`got ${formatValue(value2)}`),suggestion&&parts.push(`(did you mean ${suggestion}?)`),msg=parts.join("; ")}return{code,phase,severity,path,...source?{source}:{},value:value2,expected,candidates,suggestion,message:msg,...input.failure?{failure:input.failure}:{},...input.conflict?{conflict:input.conflict}:{}}}var validateDiagnostic=input=>makeDiagnostic({...input,phase:"validate"}),bootDiagnostic=input=>makeDiagnostic({...input,phase:"boot"}),runtimeDiagnostic=input=>makeDiagnostic({...input,phase:"runtime"});function formatValue(v){if(v===null)return"null";if(v===void 0)return"undefined";if(typeof v=="string")return JSON.stringify(v);if(typeof v=="number"||typeof v=="boolean")return String(v);try{let s=JSON.stringify(v);return s.length>100?s.slice(0,97)+"...":s}catch{return"[unserializable]"}}var BRAND=Symbol.for("net.aotter.mantle.DiagnosticError"),DiagnosticError=class _DiagnosticError extends Error{static[Symbol.hasInstance](value2){return this!==_DiagnosticError?Function.prototype[Symbol.hasInstance].call(this,value2):typeof value2=="object"&&value2!==null&&value2[BRAND]===!0}[BRAND]=!0;diagnostics;constructor(diagnostic,options){let list=Array.isArray(diagnostic)?diagnostic:[diagnostic],head=list[0];super(head?head.message:"DiagnosticError",options),this.name="DiagnosticError",this.diagnostics=list}get diagnostic(){let d=this.diagnostics[0];if(!d)throw new Error("DiagnosticError carries no diagnostics");return d}};var NATIVE_OUTPUT_TYPES={version:"integer",created_at:"timestamptz",updated_at:"timestamptz"};var conjuncts=w=>w?.BoolExpr?.boolop==="AND_EXPR"?w.BoolExpr.args.flatMap(conjuncts):w?[w]:[],isInput=n=>n.ColumnRef?.fields?.length===2&&n.ColumnRef.fields[0].String?.sval==="input",isScalar=n=>!!n.A_Const||isInput(n),isIdCol=n=>{let f=n.ColumnRef?.fields;return!!f&&f.at(-1)?.String?.sval==="id"&&(f.length===1||f.length===2&&f[0].String?.sval!=="input")};function classify(stmt){return stmt.SelectStmt?"read":stmt.InsertStmt?stmt.InsertStmt.selectStmt?.SelectStmt?.valuesLists?.length===1&&!stmt.InsertStmt.onConflictClause?"row":"set":conjuncts((stmt.UpdateStmt??stmt.DeleteStmt).whereClause).filter(x=>x.A_Expr?.kind==="AEXPR_OP"&&x.A_Expr.name[0].String.sval==="=").some(x=>isIdCol(x.A_Expr.lexpr)&&isScalar(x.A_Expr.rexpr)||isIdCol(x.A_Expr.rexpr)&&isScalar(x.A_Expr.lexpr))?"row":"set"}function pinnedTarget(stmt){let body=stmt.UpdateStmt??stmt.DeleteStmt;if(!body||classify(stmt)!=="row")return;let eqs=conjuncts(body.whereClause).filter(x=>x.A_Expr?.kind==="AEXPR_OP"&&x.A_Expr.name[0].String.sval==="="),name4=n=>n.ColumnRef.fields[1].String.sval,idEq=eqs.find(x=>isIdCol(x.A_Expr.lexpr)&&isInput(x.A_Expr.rexpr)||isIdCol(x.A_Expr.rexpr)&&isInput(x.A_Expr.lexpr));if(!idEq)return;let verEq=eqs.find(x=>{let col=n=>n.ColumnRef?.fields?.at(-1)?.String?.sval==="version"&&!isInput(n);return col(x.A_Expr.lexpr)&&isInput(x.A_Expr.rexpr)||col(x.A_Expr.rexpr)&&isInput(x.A_Expr.lexpr)});return{schema:body.relation.relname,id:name4(isInput(idEq.A_Expr.rexpr)?idEq.A_Expr.rexpr:idEq.A_Expr.lexpr),...verEq?{version:name4(isInput(verEq.A_Expr.rexpr)?verEq.A_Expr.rexpr:verEq.A_Expr.lexpr)}:{}}}var API_VERSION="cms.mantle.aotter.net/v2";function isMediaMcpHint(value2){return value2==="media"||value2==="media-image"||value2==="media-video"||value2==="media-file"}var MANTLE_REF_KEYWORD="x-mantle-ref";function enumOptions(property){if(property?.enum?.length&&property.enum.every(v=>typeof v=="string"))return property.enum.map(value2=>({value:value2}));let branches=property?.oneOf;if(!(!branches?.length||!branches.every(b=>typeof b.const=="string")))return branches.map(b=>({value:b.const,...b.title!==void 0?{title:b.title}:{}}))}function resolveMantleRef(property){if(typeof property!="object"||property===null)return null;let ref2=property[MANTLE_REF_KEYWORD];if(typeof ref2=="string")return ref2.length>0?{schema:ref2,field:"id"}:null;if(typeof ref2!="object"||ref2===null||Array.isArray(ref2))return null;let{schema,field}=ref2;return typeof schema=="string"&&schema.length>0&&typeof field=="string"&&field.length>0?{schema,field}:null}var MCP_HINT_KEYWORD="x-mcp-hint",MANTLE_BIND_KEYWORD="x-mantle-bind";function resolveLocalizedText(value2,preferred,canonical2){if(value2==null)return null;if(typeof value2=="string")return value2;if(Object.prototype.hasOwnProperty.call(value2,preferred))return value2[preferred];if(canonical2&&Object.prototype.hasOwnProperty.call(value2,canonical2))return value2[canonical2];let firstKey=Object.keys(value2)[0];return firstKey!==void 0?value2[firstKey]:null}var VIEW_SURFACES=["public","admin","internal"],VIEW_INPUT_RESERVED=["limit","cursor"],PROCEDURE_TARGET_KEYS=["schema","id","version"],PROCEDURE_MCP_ANNOTATION_KEYS=["readOnlyHint","destructiveHint","openWorldHint"];var LIFECYCLE_HOOKS=["before_create","after_create","before_update","after_update","before_delete","after_delete","before_publish","after_publish"],MCP_TRIGGER_SURFACES=["admin","public"],RESERVED_ENTRY_COLUMNS=["id","status","version","createdAt","updatedAt","authorId"],EXPECTED_VERSION_PROPERTY="expectedVersion",INPUT_RULE_KEYWORDS=["dependentRequired","anyOf","if","then","else"],RESERVED_PROCEDURE_INPUT_NAMES=[EXPECTED_VERSION_PROPERTY];function protectedColumns(s,restrict){return[...(s.userScopes??[]).map(u=>u.column),...restrict?.owner?[restrict.owner]:[],...(restrict?.terms??[]).map(u=>u.column)]}function userScopeTerm(scope,swappable=!1){return[scope.column,"in",{k:"user",field:scope.field,type:scope.type,multiple:!0,...swappable?{scope:!0}:{}}]}function refChecks(s,schemas){return Object.entries(s.schema?.properties??{}).flatMap(([name4,property])=>{let ref2=resolveMantleRef(property),table=ref2?.schema.toLowerCase(),t=table?schemas[table]:void 0;if(!t||!t.scope&&!t.userScopes?.length)return[];let column=(x,field)=>Object.keys(x.names??{}).find(c=>x.names[c]===field)??field.toLowerCase(),same=(t.userScopes??[]).flatMap(u=>(s.userScopes??[]).filter(v=>v.field===u.field).map(v=>[u.column,v.column]));return[{column:column(s,name4),table,field:column(t,ref2.field),same,terms:rowPolicy(t,"caller",schemas)}]})}var PUBLISHED="published",NOW={k:"now"};function rowPolicy(s,mode,schemas){if(!["caller","admin","public","trusted"].includes(mode))throw new Error("An explicit row mode is required.");mode==="caller"&&(mode="admin");let parent=[];if(s.translates&&(mode==="public"||mode==="admin")){let table=s.translates.parent.toLowerCase(),schema=schemas?.[table];if(!schema)throw new Error(`Translation parent ${table} is unavailable to rowPolicy.`);parent=[[s.translates.on.toLowerCase(),"parent",{k:"admin"},{table,terms:rowPolicy(schema,schema.userScopes?.length&&mode==="admin"?"admin":"public",schemas),...schema.scope&&s.scope?{scope:[schema.scope,s.scope]}:{},...mode==="admin"&&!schema.userScopes?.length?{admin:!0}:{}}]]}return[...mode!=="trusted"&&s.scope?[[s.scope,"eq",{k:"uid"}]]:[],...s.ttl?[[s.ttl,"ttl",{k:"cutoff",seconds:s.ttlSeconds}]]:[],...s.publishing&&(mode==="public"||mode==="admin")?[mode==="public"?["status","eq",{k:"const",value:PUBLISHED}]:["status","admin",{k:"admin"},PUBLISHED]]:[],...parent,...mode!=="trusted"?(s.userScopes??[]).map(u=>userScopeTerm(u,!0)):[]]}function writePolicy(s,kind,o={}){let lock=kind!=="insert"&&o.lock?["version","eq",{k:"version"}]:void 0;if(kind==="delete")return{fills:[],sets:[],lock};let sets2=[["version","bump"],["updated_at",NOW],...o.status?[["status",{k:"const",value:o.status}]]:[]];if(kind==="update")return{fills:[],sets:sets2,lock};let uid={k:"uid"};return{fills:[...s.scope?[[s.scope,uid]]:[],["created_at",NOW],["updated_at",NOW],["author_id",uid],...o.idGiven&&!s.scope&&!s.userScopes?.length?[]:[["id","newId"]]],sets:sets2.slice(0,2)}}function canonical(v){return Array.isArray(v)?`[${v.map(canonical).join(",")}]`:v&&typeof v=="object"?`{${Object.keys(v).sort().filter(k=>v[k]!==void 0).map(k=>`${JSON.stringify(k)}:${canonical(v[k])}`).join(",")}}`:JSON.stringify(v)??"null"}var fnv=s=>[...s].reduce((h,c)=>Math.imul(h^c.codePointAt(0),16777619)>>>0,2166136261).toString(16).padStart(8,"0");async function planFingerprint(plan){let digest=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(canonical(plan)));return[...new Uint8Array(digest)].map(b=>b.toString(16).padStart(2,"0")).join("")}var SqlRefusal=class extends Error{code;offset;keyword;constructor(code,message2,offset,keyword){super(message2),this.code=code,this.offset=offset,this.keyword=keyword}};var MAX_NUMERIC_P=15;function parseNumeric(type){let m=/^numeric\((\d+),\s*(\d+)\)$/.exec(type);if(!m)return;let p=+m[1],s=+m[2];if(p<1||p>MAX_NUMERIC_P||s>p)throw new SqlRefusal("SQL_TYPE",`numeric(${p}, ${s}) is refused: precision is 1 to ${MAX_NUMERIC_P}, scale at most precision`);return{p,s}}var MAX_TTL_SECONDS=Math.floor(Number.MAX_SAFE_INTEGER/2e6),isTtlSeconds=x=>Number.isSafeInteger(x)&&x>=0&&x<=MAX_TTL_SECONDS,UNIT_US=Object.fromEntries(["second seconds sec secs s","minute minutes min mins m","hour hours hr hrs h"].flatMap((names,i)=>names.split(" ").map(u=>[u,[1e6,6e7,36e8][i]]))),TYPMOD_UNIT={1024:"hour",2048:"minute",4096:"second"};function intervalMicros(text,typmod){let m=/^\s*(-?\d+(?:\.\d+)?)\s*([a-z]+)\s*$/i.exec(text);if(!m&&typmod!==void 0&&TYPMOD_UNIT[typmod]&&/^\s*-?\d+(\.\d+)?\s*$/.test(text)&&(m=[text,text.trim(),TYPMOD_UNIT[typmod]]),!m)throw new SqlRefusal("SQL_TYPE",`interval '${text}' is not supported: write a number and second, minute or hour`);let unit=UNIT_US[m[2].toLowerCase()];if(!unit&&/^(days?|weeks?|months?|mons?|years?|y)$/i.test(m[2]))throw new SqlRefusal("SQL_TYPE",`interval unit '${m[2]}' is a calendar unit (a day is 23 or 25 hours across daylight saving): bind the boundary as an input instead`);if(!unit)throw new SqlRefusal("SQL_TYPE",`interval '${text}' is not supported: write a number and second, minute or hour`);let[,sign,whole,frac=""]=/^(-?)(\d+)(?:\.(\d+))?$/.exec(m[1]),scale=10n**BigInt(frac.length),fraction=BigInt(frac||"0")*BigInt(unit);if(fraction%scale!==0n)throw new SqlRefusal("SQL_TYPE",`interval '${text}' is finer than a microsecond`);let micros=(sign?-1:1)*Number(BigInt(whole)*BigInt(unit)+fraction/scale);if(!Number.isSafeInteger(micros))throw new SqlRefusal("SQL_TYPE",`interval '${text}' is longer than ${Number.MAX_SAFE_INTEGER} microseconds`);return micros}var ftsTableName=schema=>`_mantle_fts_${schema}`,geoTreeName=(schema,field)=>`_mantle_geo_${schema}_${field}`;function fieldType(p){let types=[...new Set([p.type].flat().filter(x=>x!=="null"))];if(types.length>1)return types.every(x=>x==="integer"||x==="number")?"real":"json";let t=types[0];return p.format==="geo"?"geo":!t&&enumOptions(p)?"text":t==="string"?p.format==="date-time"?"timestamptz":p.format==="date"?"date":"text":{integer:"integer",number:"real",boolean:"bool"}[String(t)]??"json"}function fieldTypes(schema){return Object.fromEntries(Object.entries(schema?.properties??{}).map(([name4,p])=>[name4.toLowerCase(),fieldType(p)]))}function viewCacheProblem(stmts,schemas){let pending=[...stmts];for(;pending.length;){let node=pending.pop();if(!node||typeof node!="object")continue;let n=node,fn3=n.FuncCall?.funcname?.map(x=>x.String.sval).join(".").replace(/^pg_catalog\./,"");if(fn3==="now"||fn3?.startsWith("auth."))return`shared caching cannot read ${fn3}()`;let relation2=n.RangeVar;if(relation2?.mantle==="table"){let schema=schemas[relation2.relname.toLowerCase()];if(schema?.userScopes?.length)return`shared caching cannot read field-scoped Schema '${relation2.relname}'`;if(schema?.ttl||schema&&!schema.publishing)return`shared caching cannot read ${schema.ttl?"TTL":"operational"} Schema '${relation2.relname}'`}pending.push(...Object.values(n))}}function storageColumns(s){let cols=new Map([["_rid","integer"],["id","text"],["version","integer"],["created_at","native"],["updated_at","native"],["author_id","text"]]);s.scope&&cols.set(s.scope,"text"),s.publishing&&(cols.set("status","text"),cols.set("published_at","timestamptz"));for(let[f,t]of Object.entries(s.fields??{}))f!==s.scope&&(t==="geo"?(cols.set(`${f}_lat`,"real"),cols.set(`${f}_lng`,"real")):cols.set(f,t));return cols}var AGGREGATES=new Set(["count","sum","min","max","avg","json_group_array","json_group_object","string_agg","jsonb_agg","jsonb_object_agg"]),NATIVE_NOT_NULL=new Set(["id","version","created_at","updated_at","status"]),NATIVE_COLUMNS={id:"id",status:"status",version:"version",createdAt:"created_at",updatedAt:"updated_at",authorId:"author_id"};function notNullColumns(s){let out=new Set;for(let u of s.userScopes??[])out.add(u.column);if(s.publishing||!s.schema?.required)return out;let required=new Set(s.schema.required);for(let[f,t]of Object.entries(s.fields)){let authored2=s.names?.[f]??f,p=s.schema.properties?.[authored2];f===s.scope||!required.has(authored2)||!p||p.nullable===!0||Array.isArray(p.type)&&p.type.includes("null")||(t==="geo"?out.add(`${f}_lat`).add(`${f}_lng`):out.add(f))}return out}function storageColumnClash(fields){let taken=new Set(["_rid",...Object.entries(fields).filter(([,t])=>t==="geo").flatMap(([f])=>[`${f}_lat`,`${f}_lng`])]);return Object.keys(fields).find(f=>taken.has(f))}var CHECK_FUNCTIONS=new Map([["lower",{takes:["text"],returns:"text"}],["upper",{takes:["text"],returns:"text"}],["length",{takes:["text"],returns:"integer"}],["abs",{takes:["integer","real"],returns:"argument"}]]);function checkShapeProblem(v,columns2){let columnOf=ref2=>{let fields=ref2?.fields,name4=Array.isArray(fields)&&fields.length===1?fields[0]?.String?.sval:void 0;return typeof name4=="string"&&columns2.has(name4)?name4:void 0},fname2=call=>Array.isArray(call?.funcname)?call.funcname.map(x=>x?.String?.sval).join("."):"",typeOf=n=>{if(n?.ColumnRef)return columns2.get(columnOf(n.ColumnRef)??"");if(n?.FuncCall){let f=CHECK_FUNCTIONS.get(fname2(n.FuncCall));return f?.returns==="argument"?typeOf(n.FuncCall.args?.[0]):f?.returns}if(n?.A_Const)return n.A_Const.sval?"text":n.A_Const.ival?"integer":n.A_Const.fval?"real":void 0},walk3=v2=>{if(!(!v2||typeof v2!="object"))for(let[k,c]of Object.entries(v2)){if(k==="SubLink")return"a check reads only the row's own columns: no subquery";if(k==="TypeCast"||k==="SQLValueFunction")return"a check reads only the row's own columns: no cast or SQL value function";if(k==="ColumnRef"&&!columnOf(c))return`a check names only its own Schema's columns, unqualified: ${JSON.stringify((c?.fields??[]).map(x=>x?.String?.sval??"*").join("."))} is not one`;if(k==="FuncCall"){let name4=fname2(c),takes=CHECK_FUNCTIONS.get(name4)?.takes;if(!takes)return`a check may call only ${[...CHECK_FUNCTIONS.keys()].join(", ")}: ${name4||"this call"}() is printed into the table's DDL as written`;if(c.agg_star||c.agg_distinct||c.agg_filter||c.agg_order||c.over||!Array.isArray(c.args)||c.args.length!==1)return`${name4}() in a check takes one argument, with no DISTINCT, *, FILTER, ORDER BY or OVER`;let t=typeOf(c.args[0]);if(!t||!takes.includes(t))return`${name4}() in a check takes a ${takes.join(" or ")} column, constant or call`}let inner=walk3(c);if(inner)return inner}};return walk3(v)}import{LineCounter as LineCounter2,parseAllDocuments}from"yaml";function validateLocalizedText(value2,idx,pointer2,fieldLabel,required){if(value2===void 0){if(required)throw new ManifestParseError(`${fieldLabel} is required (non-empty string, or an object mapping locale \u2192 non-empty string)`,idx,pointer2);return}if(typeof value2=="string"){if(value2.length===0)throw new ManifestParseError(`${fieldLabel} must be a non-empty string when present (or an object mapping locale \u2192 non-empty string)`,idx,pointer2);return}if(typeof value2=="object"&&value2!==null&&!Array.isArray(value2)){let entries=Object.entries(value2);if(entries.length===0)throw new ManifestParseError(`${fieldLabel} object form must have at least one locale \u2192 string entry; got {}`,idx,pointer2);for(let[key,entryValue]of entries){if(key.length===0)throw new ManifestParseError(`${fieldLabel} object form keys must be non-empty locale codes; got an empty key`,idx,pointer2);if(typeof entryValue!="string"||entryValue.length===0)throw new ManifestParseError(`${fieldLabel} object form value for locale '${key}' must be a non-empty string; got ${JSON.stringify(entryValue)}`,idx,`${pointer2}/${key}`)}return}throw new ManifestParseError(`${fieldLabel} must be a non-empty string, or an object mapping locale \u2192 non-empty string; got ${JSON.stringify(value2)}`,idx,pointer2)}var ManifestParseError=class extends Error{constructor(message2,docIndex,pointer2,code="INVALID_MANIFEST_ENVELOPE",details){super(docIndex!=null?`[doc ${docIndex}] ${message2}`:message2);this.docIndex=docIndex;this.pointer=pointer2;this.code=code;this.details=details;this.name="ManifestParseError"}docIndex;pointer;code;details},KNOWN_KINDS=new Set(["Schema","View","Procedure","Trigger"]),V01_TRIGGER_SOURCE_KINDS=new Set(["http","lifecycle","mcp","schedule"]),V01_HTTP_METHODS=new Set(["POST","PUT","PATCH","DELETE"]),V01_LIFECYCLE_HOOKS=new Set(LIFECYCLE_HOOKS),V01_MCP_TRIGGER_SURFACES=new Set(MCP_TRIGGER_SURFACES),V01_VIEW_SURFACES=new Set(VIEW_SURFACES),V01_LIFECYCLE_MODES=new Set(["publishing","operational"]);function rejectUnknownKeys(value2,allowed,idx,pointer2){let unknown=Object.keys(value2).find(key=>!allowed.includes(key));if(unknown!==void 0){let unknownPointer=pointer2==="/"?`/${unknown}`:`${pointer2}/${unknown}`;throw new ManifestParseError(`${unknownPointer.replaceAll("/",".").slice(1)} is not supported`,idx,unknownPointer)}}function escapeJsonPointerSegment(value2){return value2.replace(/~/g,"~0").replace(/\//g,"~1")}import{isMap,isNode,isScalar as isScalar2,isSeq}from"yaml";function sourceLocationAt(entry,path){let candidate=path,span=entry.sourceSpans[candidate];for(;!span&&candidate!=="/";){let slash=candidate.lastIndexOf("/");candidate=slash<=0?"/":candidate.slice(0,slash),span=entry.sourceSpans[candidate]}return{sourceId:entry.source.sourceId,documentIndex:entry.source.documentIndex,path,...span?{span}:{}}}function collectSourceSpans(root,lineCounter){let spans={},visit=(node,path)=>{if(!node)return;let span=sourceSpan(lineCounter,node.range);if(span&&(spans[path]=span),isMap(node))for(let pair of node.items){if(!isScalar2(pair.key))continue;let key=String(pair.key.value).replace(/~/g,"~0").replace(/\//g,"~1");visit(isNode(pair.value)?pair.value:null,path==="/"?`/${key}`:`${path}/${key}`)}else isSeq(node)&&node.items.forEach((item,index)=>visit(isNode(item)?item:null,path==="/"?`/${index}`:`${path}/${index}`))};return visit(root,"/"),Object.freeze(spans)}function sourceLocationForNode(sourceId,documentIndex,path,doc,lineCounter){let parts=path==="/"?[]:path.slice(1).split("/").map(part=>{let decoded2=part.replace(/~1/g,"/").replace(/~0/g,"~");return/^\d+$/.test(decoded2)?Number(decoded2):decoded2}),range;for(let length=parts.length;length>=0&&!range;length--){let node=length===0?doc.contents:doc.getIn(parts.slice(0,length),!0);node&&typeof node=="object"&&"range"in node&&(range=node.range)}return sourceLocation(sourceId,documentIndex,path,lineCounter,range??doc.range)}function sourceLocation(sourceId,documentIndex,path,lineCounter,range){let span=sourceSpan(lineCounter,range);return{sourceId,documentIndex,path,...span?{span}:{}}}function sourceSpan(lineCounter,range){if(!range||range.length<2)return;let startOffset=range[0],endOffset=range.length>2?range[2]:range[1];if(startOffset===void 0||endOffset===void 0)return;let start=lineCounter.linePos(startOffset),end=lineCounter.linePos(endOffset);return{start:{line:start.line,column:start.col,offset:startOffset},end:{line:end.line,column:end.col,offset:endOffset}}}var BUILT_IN_NAV_GROUPS=new Set(["content","operations","reports","more"]),ID=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,PLACEMENT={group:[v=>typeof v=="string"&&ID.test(v),"a kebab-case group id"],order:[Number.isInteger,"an integer"],hidden:[v=>typeof v=="boolean","a boolean"]};function navPlacementProblems(nav,own=[]){let keys=[...own,...Object.keys(PLACEMENT)];for(let[key,value2]of Object.entries(nav)){if(own.includes(key))continue;let rule=Object.hasOwn(PLACEMENT,key)?PLACEMENT[key]:null;if(!rule)return[key,`${keys.slice(0,-1).join(", ")} or ${keys.at(-1)}`];if(!rule[0](value2))return[key,rule[1]]}return null}var SAFE_INDEX_NAME=/^[A-Za-z][A-Za-z0-9_.-]*$/,NATIVE_INDEX_AFFINITY={id:"TEXT",status:"TEXT",version:"INTEGER",createdAt:"INTEGER",updatedAt:"INTEGER",authorId:"TEXT"},NATIVE_INDEX_FIELDS=new Map(Object.entries(NATIVE_INDEX_AFFINITY)),SOURCES=["uniqueIndexes","indexes"];function checkSchemaIndexes(manifest){let spec=manifest.spec,schema=isRecord(spec.schema)?spec.schema:{},properties=isRecord(schema.properties)?schema.properties:{},candidates=Object.keys(properties),declarations=[],problems=[],seen=new Map;SOURCES.some(source=>{let raw=spec[source];return Array.isArray(raw)&&raw.length>0})&&!SAFE_INDEX_NAME.test(manifest.metadata.name)&&problems.push({category:"invalid",pointer:"/metadata/name",value:manifest.metadata.name,expected:`indexed Schema name matching ${SAFE_INDEX_NAME}`,message:`Schema '${manifest.metadata.name}' uses indexes but its name is not a safe index identifier.`});for(let source of SOURCES){let raw=spec[source];if(raw!==void 0){if(!Array.isArray(raw)){problems.push({category:"shape",source,pointer:`/spec/${source}`,value:raw,expected:"an array of non-empty string arrays",message:`Schema.spec.${source} must be an array of non-empty string arrays.`});continue}for(let compositeIndex=0;compositeIndex<raw.length;compositeIndex+=1){let rawComposite=raw[compositeIndex],compositePointer=`/spec/${source}/${compositeIndex}`;if(!Array.isArray(rawComposite)){problems.push({category:"shape",source,pointer:compositePointer,value:rawComposite,expected:"a non-empty array of field-name strings",message:`Schema.spec.${source}[${compositeIndex}] must be a non-empty array of field-name strings.`});continue}if(rawComposite.length===0){problems.push({category:"invalid",source,pointer:compositePointer,value:rawComposite,expected:"at least one indexed field",message:`Schema.spec.${source}[${compositeIndex}] must not be empty.`});continue}let fields=[],fieldsSeen=new Set,valid=!0;for(let fieldIndex=0;fieldIndex<rawComposite.length;fieldIndex+=1){let rawField=rawComposite[fieldIndex],fieldPointer=`${compositePointer}/${fieldIndex}`;if(typeof rawField!="string"){valid=!1,problems.push({category:"shape",source,pointer:fieldPointer,value:rawField,expected:"a field-name string",message:`Schema.spec.${source}[${compositeIndex}][${fieldIndex}] must be a field-name string.`});continue}if(fieldsSeen.has(rawField)){valid=!1,problems.push({category:"invalid",source,pointer:fieldPointer,value:rawField,expected:"each field to appear once per composite index",message:`Schema.spec.${source}[${compositeIndex}] repeats field '${rawField}'.`});continue}if(fieldsSeen.add(rawField),!SAFE_INDEX_NAME.test(rawField)){valid=!1,problems.push({category:"invalid",source,pointer:fieldPointer,value:rawField,expected:`field name matching ${SAFE_INDEX_NAME}`,message:`Schema.spec.${source} field '${rawField}' is not a safe index identifier.`});continue}let nativeAffinity=NATIVE_INDEX_FIELDS.get(rawField);if(nativeAffinity!==void 0){if(source==="uniqueIndexes"){valid=!1,problems.push({category:"invalid",source,pointer:fieldPointer,value:rawField,expected:"a Schema data field; native columns carry no domain uniqueness",message:`Schema.spec.uniqueIndexes cannot include native entry column '${rawField}'; declare it under spec.indexes instead.`});continue}if(rawField==="status"&&(spec.lifecycle??"publishing")!=="publishing"){valid=!1,problems.push({category:"invalid",source,pointer:fieldPointer,value:rawField,expected:"a native column this Schema has",message:"Schema.spec.indexes field 'status' needs lifecycle: publishing; only a publishing Schema has a status column."});continue}fields.push({name:rawField,affinity:nativeAffinity});continue}if(!Object.hasOwn(properties,rawField)){valid=!1,problems.push({category:"field-unknown",source,pointer:fieldPointer,value:rawField,expected:"an exact top-level key in spec.schema.properties",candidates,message:`Schema '${manifest.metadata.name}' ${source} references unknown top-level field '${rawField}'.`});continue}let affinity=scalarAffinity(properties[rawField]);if(affinity===null){valid=!1,problems.push({category:"invalid",source,pointer:fieldPointer,value:rawField,expected:"a property with exactly one string, integer, number, or boolean type, optionally nullable",message:`Schema '${manifest.metadata.name}' ${source} field '${rawField}' is not an indexable scalar property.`});continue}fields.push({name:rawField,affinity})}if(!valid)continue;let key=JSON.stringify(fields.map(field=>field.name)),previous=seen.get(key);if(previous!==void 0){let crossKind=previous!==source;problems.push({category:"invalid",source,pointer:compositePointer,value:fields.map(field=>field.name),expected:crossKind?"a tuple not already supplied by uniqueIndexes":`a unique ordered tuple within ${source}`,message:crossKind?`Schema.spec.indexes duplicates uniqueIndexes tuple ${key}; the unique index already supplies that lookup path.`:`Schema.spec.${source} repeats ordered tuple ${key}.`});continue}seen.set(key,source),declarations.push({unique:source==="uniqueIndexes",fields})}}}return{declarations,problems}}function schemaIndexDiagnosticCode(problem3,parserShape=!1){return problem3.category==="shape"?parserShape?"INVALID_MANIFEST_ENVELOPE":"SCHEMA_INDEX_INVALID":problem3.category==="field-unknown"?problem3.source==="uniqueIndexes"?"UNIQUE_INDEX_FIELD_UNKNOWN":"SCHEMA_INDEX_FIELD_UNKNOWN":"SCHEMA_INDEX_INVALID"}function scalarAffinity(rawProperty){if(!isRecord(rawProperty)||rawProperty.nullable!==void 0&&typeof rawProperty.nullable!="boolean")return null;let rawType=rawProperty.type,types=typeof rawType=="string"?[rawType]:Array.isArray(rawType)&&rawType.every(value2=>typeof value2=="string")?rawType:null;if(types===null||types.length===0||new Set(types).size!==types.length)return null;let nonNull=types.filter(type=>type!=="null");if(nonNull.length!==1||types.length>2)return null;switch(nonNull[0]){case"string":return"TEXT";case"integer":case"boolean":return"INTEGER";case"number":return"REAL";default:return null}}function isRecord(value2){return typeof value2=="object"&&value2!==null&&!Array.isArray(value2)}var problem=(pointer2,value2,expected,message2)=>({pointer:pointer2,value:value2,expected,message:message2}),EMPTY_VIEW_LIST={columns:[],searchFields:[],filterFields:[]};function checkViewAdminUi(view){let uiSchema=view.spec.uiSchema;if(uiSchema===void 0)return{list:EMPTY_VIEW_LIST,problems:[]};if(view.spec.surface!=="admin")return{list:EMPTY_VIEW_LIST,problems:[problem("/spec/uiSchema",uiSchema,"Admin UI configuration on a surface: admin View","View.spec.uiSchema is only supported for surface: admin Views.")]};if(!uiSchema||typeof uiSchema!="object"||Array.isArray(uiSchema))return{list:EMPTY_VIEW_LIST,problems:[problem("/spec/uiSchema",uiSchema,"an object","View.spec.uiSchema must be an object.")]};let unknownRoot=Object.keys(uiSchema).find(key=>key!=="list"&&key!=="nav");if(unknownRoot)return{list:EMPTY_VIEW_LIST,problems:[problem(`/spec/uiSchema/${unknownRoot}`,uiSchema[unknownRoot],"list or nav",`View.spec.uiSchema.${unknownRoot} is not supported.`)]};let nav=uiSchema.nav;if(nav!==void 0){if(!nav||typeof nav!="object"||Array.isArray(nav))return{list:EMPTY_VIEW_LIST,problems:[problem("/spec/uiSchema/nav",nav,"an object","View.spec.uiSchema.nav must be an object.")]};let bad=navPlacementProblems(nav);if(bad)return{list:EMPTY_VIEW_LIST,problems:[problem(`/spec/uiSchema/nav/${bad[0]}`,nav[bad[0]],bad[1],`View.spec.uiSchema.nav.${bad[0]} must be ${bad[1]}.`)]}}let list=uiSchema.list;if(list===void 0)return{list:EMPTY_VIEW_LIST,problems:[]};if(!list||typeof list!="object"||Array.isArray(list))return{list:EMPTY_VIEW_LIST,problems:[problem("/spec/uiSchema/list",list,"an object","View.spec.uiSchema.list must be an object.")]};let config=list,allowed=new Set(["columns","searchFields","filterFields"]),unknown=Object.keys(config).find(key=>!allowed.has(key));if(unknown)return{list:EMPTY_VIEW_LIST,problems:[problem(`/spec/uiSchema/list/${unknown}`,config[unknown],"columns, searchFields, or filterFields",`View.spec.uiSchema.list.${unknown} is not supported.`)]};let normalized={columns:[],searchFields:[],filterFields:[]};for(let key of Object.keys(normalized)){let raw=config[key];if(raw!==void 0){if(!Array.isArray(raw)||!raw.every(field=>typeof field=="string"&&field.length>0&&!/["\\\0]/.test(field)))return{list:EMPTY_VIEW_LIST,problems:[problem(`/spec/uiSchema/list/${key}`,raw,"an array of non-empty View output field names",`View.spec.uiSchema.list.${key} must be an array of field-name strings.`)]};if(new Set(raw).size!==raw.length)return{list:EMPTY_VIEW_LIST,problems:[problem(`/spec/uiSchema/list/${key}`,raw,"field names without duplicates",`View.spec.uiSchema.list.${key} must not repeat a field.`)]};normalized[key]=raw}}return{list:normalized,problems:[]}}var EMPTY_LIST={primaryField:null,columns:[]},SCHEMA_UI_ROOTS=new Set(["fields","list","nav"]),SCHEMA_LIST_KEYS=new Set(["filterField","primaryField","columns"]),SCALAR_TYPES=new Set(["string","number","integer","boolean"]);function checkSchemaAdminUi(schema){let formProblem=checkFormUiSchema(schema.spec.schema,schema.spec.uiSchema,"Schema")[0];if(formProblem)return invalid(formProblem);let uiSchema=schema.spec.uiSchema;if(uiSchema===void 0)return{filter:null,list:EMPTY_LIST,nav:null,problems:[]};let roots=uiSchema,unknownRoot=Object.keys(roots).find(key=>!SCHEMA_UI_ROOTS.has(key));if(unknownRoot)return invalid(problem2(`/spec/uiSchema/${unknownRoot}`,roots[unknownRoot],"fields, list, or nav",`Schema.spec.uiSchema.${unknownRoot} is not supported.`));let list=roots.list;if(list!==void 0&&(!list||typeof list!="object"||Array.isArray(list)))return invalid(problem2("/spec/uiSchema/list",list,"an object","Schema.spec.uiSchema.list must be an object."));let config=list??{};if(list!==void 0){let unknownList=Object.keys(config).find(key=>!SCHEMA_LIST_KEYS.has(key));if(unknownList)return invalid(problem2(`/spec/uiSchema/list/${unknownList}`,config[unknownList],"filterField, primaryField, or columns",`Schema.spec.uiSchema.list.${unknownList} is not supported.`))}let filterResult=list===void 0?{filter:null}:checkListFilter(schema,config);if(filterResult.problem)return invalid(filterResult.problem);let primaryField=config.primaryField,columns2=config.columns;if((primaryField!==void 0||columns2!==void 0)&&(schema.spec.lifecycle??"publishing")!=="operational")return invalid(problem2("/spec/uiSchema/list",list,"list presentation fields on an operational Schema","Schema list primaryField/columns are supported only for lifecycle: operational Schemas; a publishing Schema's Admin list shows its title field and status."));if(primaryField!==void 0&&(typeof primaryField!="string"||!primaryField))return invalid(problem2("/spec/uiSchema/list/primaryField",primaryField,"a non-empty top-level scalar field name","Schema.spec.uiSchema.list.primaryField must be a field-name string."));if(columns2!==void 0&&(!Array.isArray(columns2)||!columns2.every(field=>typeof field=="string"&&field.length>0)))return invalid(problem2("/spec/uiSchema/list/columns",columns2,"an array of non-empty top-level field names","Schema.spec.uiSchema.list.columns must be an array of field-name strings."));let normalizedPrimary=typeof primaryField=="string"?primaryField:null,normalizedColumns=Array.isArray(columns2)?columns2:[],fields=[...normalizedPrimary?[normalizedPrimary]:[],...normalizedColumns];if(new Set(fields).size!==fields.length)return invalid(problem2("/spec/uiSchema/list/columns",columns2,"field names without duplicates or the primaryField","Schema list primaryField/columns must not repeat a field."));for(let field of fields){if(field!==normalizedPrimary&&NATIVE_LIST_FIELDS.has(field))continue;let property=schema.spec.schema.properties?.[field];if(!property)return invalid(problem2(`/spec/uiSchema/list/${field===normalizedPrimary?"primaryField":"columns"}`,field,"a top-level key in spec.schema.properties or a native entry column",`Schema '${schema.metadata.name}' list presentation references unknown field '${field}'.`));if(field===normalizedPrimary&&!isScalar3(property))return invalid(problem2("/spec/uiSchema/list/primaryField",field,"a top-level scalar Schema property",`Schema '${schema.metadata.name}' list primaryField '${field}' must be scalar.`))}let navResult=checkNav(schema,roots.nav);return navResult.problem?invalid(navResult.problem):{filter:filterResult.filter,list:{primaryField:normalizedPrimary,columns:normalizedColumns},nav:navResult.nav,problems:[]}}function checkFormUiSchema(schema,uiSchema,owner){if(uiSchema===void 0)return[];if(!uiSchema||typeof uiSchema!="object"||Array.isArray(uiSchema))return[problem2("/spec/uiSchema",uiSchema,"an object",`${owner}.spec.uiSchema must be an object.`)];let config=uiSchema;if(owner==="Procedure"){let unknownRoot=Object.keys(config).find(key=>key!=="collectionAction"&&key!=="fields");if(unknownRoot)return[problem2(`/spec/uiSchema/${unknownRoot}`,config[unknownRoot],"collectionAction or fields",`Procedure.spec.uiSchema.${unknownRoot} is not supported.`)]}let collectionAction=config.collectionAction;if(collectionAction!==void 0&&owner!=="Procedure")return[problem2("/spec/uiSchema/collectionAction",collectionAction,"a Procedure-only Admin collection name","Schema.spec.uiSchema.collectionAction is not supported.")];if(collectionAction!==void 0&&(typeof collectionAction!="string"||!collectionAction))return[problem2("/spec/uiSchema/collectionAction",collectionAction,"a non-empty Schema name","Procedure.spec.uiSchema.collectionAction must be a Schema-name string.")];let fields=config.fields;if(fields===void 0)return[];if(!fields||typeof fields!="object"||Array.isArray(fields))return[problem2("/spec/uiSchema/fields",fields,"an object keyed by top-level input field",`${owner}.spec.uiSchema.fields must be an object.`)];for(let[field,rawConfig]of Object.entries(fields)){let property=schema.properties?.[field];if(!property)return[problem2(`/spec/uiSchema/fields/${field}`,field,"an exact top-level key in the JSON Schema properties",`${owner}.spec.uiSchema.fields references unknown field '${field}'.`)];if(!rawConfig||typeof rawConfig!="object"||Array.isArray(rawConfig))return[problem2(`/spec/uiSchema/fields/${field}`,rawConfig,"an object with widget: textarea",`${owner}.spec.uiSchema.fields.${field} must be an object.`)];let config2=rawConfig,unknownKey=Object.keys(config2).find(key=>key!=="widget");if(unknownKey)return[problem2(`/spec/uiSchema/fields/${field}/${unknownKey}`,config2[unknownKey],"widget",`${owner}.spec.uiSchema.fields.${field}.${unknownKey} is not supported.`)];if(config2.widget!=="textarea")return[problem2(`/spec/uiSchema/fields/${field}/widget`,config2.widget,'"textarea"',`${owner}.spec.uiSchema.fields.${field}.widget must be 'textarea'.`)];if(!isString(property))return[problem2(`/spec/uiSchema/fields/${field}/widget`,field,"a top-level string property",`${owner}.spec.uiSchema.fields.${field}.widget can only target a string field.`)]}return[]}function checkListFilter(schema,list){let field=list.filterField;if(field===void 0)return{filter:null};if(typeof field!="string"||!field)return{problem:problem2("/spec/uiSchema/list/filterField",field,"a non-empty top-level field name","Schema.spec.uiSchema.list.filterField must be a field-name string."),filter:null};if((schema.spec.lifecycle??"publishing")!=="operational")return{problem:problem2("/spec/uiSchema/list/filterField",field,"a filter on an operational Schema","Schema list filter tabs are supported only for lifecycle: operational Schemas."),filter:null};let property=schema.spec.schema.properties?.[field],values=enumOptions(property)?.map(o=>o.value);return property?values?.length?checkSchemaIndexes(schema).declarations.some(({fields})=>fields[0]?.name===field)?{filter:{field,values}}:{problem:problem2("/spec/uiSchema/list/filterField",field,"the first field of a declared index tuple",`Schema '${schema.metadata.name}' list filter field '${field}' needs a left-prefix index.`),filter:null}:{problem:problem2("/spec/uiSchema/list/filterField",field,"a field with a non-empty string enum, or a oneOf of string consts",`Schema '${schema.metadata.name}' list filter field '${field}' must declare string enum values.`),filter:null}:{problem:problem2("/spec/uiSchema/list/filterField",field,"an exact top-level key in spec.schema.properties",`Schema '${schema.metadata.name}' list filter references unknown field '${field}'.`),filter:null}}function checkNav(schema,nav){if(nav===void 0)return{nav:null};if(!nav||typeof nav!="object"||Array.isArray(nav))return{nav:null,problem:problem2("/spec/uiSchema/nav",nav,"an object","Schema.spec.uiSchema.nav must be an object.")};let config=nav,bad=navPlacementProblems(config,["standalone","parentField"]);if(bad)return{nav:null,problem:problem2(`/spec/uiSchema/nav/${bad[0]}`,config[bad[0]],bad[1],`Schema.spec.uiSchema.nav.${bad[0]} must be ${bad[1]}.`)};let standalone=config.standalone;if(standalone!==void 0&&typeof standalone!="boolean")return{nav:null,problem:problem2("/spec/uiSchema/nav/standalone",standalone,"a boolean","Schema.spec.uiSchema.nav.standalone must be a boolean.")};let parentField=config.parentField;if(parentField!==void 0&&(typeof parentField!="string"||!parentField))return{nav:null,problem:problem2("/spec/uiSchema/nav/parentField",parentField,"a non-empty required x-mantle-ref field name","Schema.spec.uiSchema.nav.parentField must be a field-name string.")};if(parentField!==void 0&&standalone!==!0){let required=new Set(schema.spec.schema.required??[]);return!schema.spec.translates&&required.has(parentField)&&resolveMantleRef(schema.spec.schema.properties?.[parentField])!==null?{nav:null}:{nav:null,problem:problem2("/spec/uiSchema/nav/parentField",parentField,"a required x-mantle-ref field of a Schema that is not a translates child",schema.spec.translates?`Schema '${schema.metadata.name}' cannot declare nav.parentField because it is a translates child.`:`Schema '${schema.metadata.name}' nav.parentField must name a required x-mantle-ref field.`)}}if(standalone!==!0)return{nav:null};if(schema.spec.translates)return{nav:null,problem:problem2("/spec/uiSchema/nav/standalone",!0,"standalone on a Schema that folds under a required-ref parent",`Schema '${schema.metadata.name}' cannot declare nav.standalone because it is a translates child.`)};let eligible=requiredMantleRefFields(schema.spec.schema);if(eligible.length===0)return{nav:null,problem:problem2("/spec/uiSchema/nav/standalone",!0,"standalone on a Schema with a required x-mantle-ref parent",`Schema '${schema.metadata.name}' cannot declare nav.standalone: it has no required x-mantle-ref parent to fold under.`)};if(eligible.length===1){let only=eligible[0];return typeof parentField=="string"&&parentField!==only.field?{nav:null,problem:problem2("/spec/uiSchema/nav/parentField",parentField,`the Schema's only required x-mantle-ref field '${only.field}'`,`Schema '${schema.metadata.name}' nav.parentField must be '${only.field}'.`)}:{nav:{standalone:!0,parentField:only.field,parentCollection:only.collection}}}if(typeof parentField!="string")return{nav:null};let matched=eligible.find(item=>item.field===parentField);return matched?{nav:{standalone:!0,parentField:matched.field,parentCollection:matched.collection}}:{nav:null,problem:problem2("/spec/uiSchema/nav/parentField",parentField,`one of ${eligible.map(item=>item.field).join(", ")}`,`Schema '${schema.metadata.name}' nav.parentField must name a required x-mantle-ref field.`)}}function requiredMantleRefFields(body){let required=new Set(body.required??[]),properties=body.properties??{},fields=[];for(let[field,property]of Object.entries(properties)){if(!required.has(field))continue;let ref2=resolveMantleRef(property);ref2?.field==="id"&&fields.push({field,collection:ref2.schema})}return fields}function checkSchemaNavTargets(schema,schemasByName){let{nav,problems}=checkSchemaAdminUi(schema);if(problems.length>0||schema.spec.translates)return null;let declared=declaredParentField(schema),target2=nav?.parentCollection??(declared===void 0?void 0:resolveMantleRef(schema.spec.schema.properties?.[declared])?.schema);if(target2!==void 0&&!isFoldParent(schemasByName.get(target2)))return problem2(declared===void 0?"/spec/uiSchema/nav/standalone":"/spec/uiSchema/nav/parentField",target2,"the metadata.name of an existing non-translates Schema",`Schema '${schema.metadata.name}' nav parent collection '${target2}' is not an eligible fold parent.`);if(declared===void 0){let eligible=eligibleIdRefs(schema,schemasByName);if(eligible.length<2)return null;let names=eligible.join(", "),keep=eligible.find(field=>!closesParentCycle(schema,field,schemasByName));return problem2("/spec/uiSchema/nav/parentField",void 0,`one of ${names}`,`Schema '${schema.metadata.name}' has more than one required id x-mantle-ref (${names}); set uiSchema.nav.parentField to choose its parent.${keep===void 0?"":` To keep the current choice, add nav: { parentField: ${keep} }.`}`)}return closesParentCycle(schema,declared,schemasByName)?problem2("/spec/uiSchema/nav/parentField",declared,"a reference whose parent chain does not lead back to this Schema",`Schema '${schema.metadata.name}' nav.parentField '${declared}' creates a parent cycle.`):null}function closesParentCycle(schema,field,schemasByName){let seen=new Set;for(let at=resolveMantleRef(schema.spec.schema.properties?.[field])?.schema;at!==void 0&&!seen.has(at);at=foldParentOf(schemasByName.get(at),schemasByName)){if(at===schema.metadata.name)return!0;seen.add(at)}return!1}function declaredParentField(schema){let nav=schema.spec.uiSchema?.nav;return typeof nav?.parentField=="string"?nav.parentField:void 0}var isFoldParent=s=>!!s&&!s.spec.translates;function eligibleIdRefs(schema,schemasByName){return requiredMantleRefFields(schema.spec.schema).filter(r=>isFoldParent(schemasByName.get(r.collection))).map(r=>r.field)}function foldParentOf(schema,schemasByName){if(!schema||schema.spec.translates)return;let field=foldParentField(schema.spec.schema,declaredParentField(schema),name4=>isFoldParent(schemasByName.get(name4)));return field===void 0?void 0:resolveMantleRef(schema.spec.schema.properties?.[field])?.schema}function foldParentField(body,declared,isParent){let props=body.properties??{},required=new Set(body.required??[]),refs2=Object.keys(props).filter(f=>required.has(f)&&isParent(resolveMantleRef(props[f])?.schema??""));return declared??requiredMantleRefFields(body).find(r=>isParent(r.collection))?.field??refs2[0]}var NATIVE_LIST_FIELDS=new Set(RESERVED_ENTRY_COLUMNS);function isScalar3(schema){let types=Array.isArray(schema.type)?schema.type:schema.type?[schema.type]:[];return types.some(type=>SCALAR_TYPES.has(type))&&types.every(type=>type==="null"||SCALAR_TYPES.has(type))}function isString(schema){let types=Array.isArray(schema.type)?schema.type:schema.type?[schema.type]:[];return types.includes("string")&&types.every(type=>type==="string"||type==="null")}function problem2(pointer2,value2,expected,message2){return{pointer:pointer2,value:value2,expected,message:message2}}function invalid(problem3){return{filter:null,list:EMPTY_LIST,nav:null,problems:[problem3]}}function checkSchemaSearchableFields(manifest){let raw=manifest.spec.searchableFields;if(raw===void 0)return[];if(!Array.isArray(raw))return[{category:"shape",pointer:"/spec/searchableFields",value:raw,expected:"an array of unique top-level string field names",message:"Schema.spec.searchableFields must be an array of field-name strings."}];let properties=manifest.spec.schema.properties??{},candidates=Object.keys(properties),seen=new Set,problems=[];return raw.forEach((value2,index)=>{let pointer2=`/spec/searchableFields/${index}`;if(typeof value2!="string"){problems.push({category:"shape",pointer:pointer2,value:value2,expected:"a field-name string",message:`Schema.spec.searchableFields[${index}] must be a field-name string.`});return}if(seen.has(value2)){problems.push({category:"invalid",pointer:pointer2,value:value2,expected:"each field to appear once",message:`Schema.spec.searchableFields repeats field '${value2}'.`});return}if(seen.add(value2),!Object.hasOwn(properties,value2)){problems.push({category:"field-unknown",pointer:pointer2,value:value2,expected:"an exact top-level key in spec.schema.properties",candidates,message:`Schema '${manifest.metadata.name}' searchableFields references unknown top-level field '${value2}'.`});return}isStringProperty(properties[value2])||problems.push({category:"invalid",pointer:pointer2,value:value2,expected:"a top-level string property, optionally nullable, not a date or date-time",message:`Schema '${manifest.metadata.name}' searchable field '${value2}' is not a string property.`})}),problems}function isStringProperty(property){if(!property||typeof property!="object"||Array.isArray(property))return!1;let rawType=property.type;return["date","date-time"].includes(String(property.format))?!1:rawType==="string"?!0:Array.isArray(rawType)&&rawType.length>0&&rawType.every(type=>type==="string"||type==="null")&&rawType.includes("string")}var name=/^[a-z][a-zA-Z0-9_]{0,62}$/,reserved=" id email emailVerified name image createdAt updatedAt role banned banReason banExpires ",validUserFieldName=field=>name.test(field)&&!reserved.includes(" "+field+" ")&&!field.startsWith("mantle");function parseRowTemplate(text){if(typeof text!="string"||!text.trim())return"a row template is a non-empty predicate string";let owner,terms=[];for(let raw of text.trim().split(/\s+AND\s+/i)){let term2=raw.trim(),uid=/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*auth\.uid\(\)$/.exec(term2),user=/^([A-Za-z_][A-Za-z0-9_]*)\s+IN\s+auth\.user\('([^']*)'\)$/i.exec(term2);if(uid){if(owner)return"at most one `= auth.uid()` term";owner=uid[1];continue}if(!user)return`unsupported term '${term2}'; use column = auth.uid() or column IN auth.user('field'), joined by AND`;if(!validUserFieldName(user[2]))return`invalid or reserved user field '${user[2]}'`;if(terms.some(t=>t.column===user[1]||t.field===user[2]))return`column '${user[1]}' or field '${user[2]}' appears twice`;terms.push({column:user[1],field:user[2]})}return{...owner?{owner}:{},terms}}function validateSchemaSpec(m,idx){let s=m.spec;if(rejectUnknownKeys(s,["title","description","schema","uiSchema","checks","uniqueIndexes","indexes","searchableFields","localized","translates","lifecycle","ttl","scope"],idx,"/spec"),typeof s.schema!="object"||s.schema===null)throw new ManifestParseError("Schema.spec.schema is required",idx,"/spec/schema");validateLocalizedText(s.title,idx,"/spec/title","Schema.spec.title",!0),validateLocalizedText(s.description,idx,"/spec/description","Schema.spec.description",!1);let indexProblem=checkSchemaIndexes(m).problems[0];if(indexProblem)throw new ManifestParseError(indexProblem.message,idx,indexProblem.pointer,schemaIndexDiagnosticCode(indexProblem,!0));let searchProblem=checkSchemaSearchableFields(m)[0];if(searchProblem)throw new ManifestParseError(searchProblem.message,idx,searchProblem.pointer,searchProblem.category==="shape"?"INVALID_MANIFEST_ENVELOPE":searchProblem.category==="field-unknown"?"SCHEMA_SEARCH_FIELD_UNKNOWN":"SCHEMA_SEARCH_INVALID");let adminUiProblem=checkSchemaAdminUi(m).problems[0];if(adminUiProblem)throw new ManifestParseError(adminUiProblem.message,idx,adminUiProblem.pointer,"SCHEMA_UI_INVALID");if("checks"in s&&(!Array.isArray(s.checks)||s.checks.some(c=>typeof c!="string"||!c.trim())))throw new ManifestParseError("Schema.spec.checks must be a list of SQL boolean expressions",idx,"/spec/checks");if("localized"in s&&typeof s.localized!="boolean")throw new ManifestParseError(`Schema.spec.localized must be a boolean; got ${JSON.stringify(s.localized)}`,idx,"/spec/localized");let schema=s.schema,properties=schema.properties;if(s.ttl!==void 0){let ttl=s.ttl;if(!ttl||typeof ttl!="object"||Array.isArray(ttl))throw new ManifestParseError("Schema.spec.ttl must be a mapping",idx,"/spec/ttl","SCHEMA_TTL_INVALID");let policy=ttl;rejectUnknownKeys(policy,["field","expireAfterSeconds"],idx,"/spec/ttl");let field=policy.field,seconds=policy.expireAfterSeconds,property=typeof field=="string"&&properties&&typeof properties=="object"&&!Array.isArray(properties)?properties[field]:void 0,types=property&&(typeof property.type=="string"?[property.type]:property.type);if(typeof field!="string"||!field||!property||property.format!=="date-time"||!Array.isArray(types)||!types.includes("string")||types.some(type=>type!=="string"&&type!=="null")||!isTtlSeconds(seconds))throw new ManifestParseError(`Schema.spec.ttl requires a top-level date-time string field and expireAfterSeconds a whole number from 0 to ${MAX_TTL_SECONDS}`,idx,"/spec/ttl","SCHEMA_TTL_INVALID")}let propertyNames=properties&&typeof properties=="object"&&!Array.isArray(properties)?Object.keys(properties):[];if(s.scope!==void 0){let template=parseRowTemplate(s.scope);if(typeof template=="string")throw new ManifestParseError(`Schema.spec.scope: ${template}`,idx,"/spec/scope");let columns2=[...template.owner?[template.owner]:[],...template.terms.map(t=>t.column)];for(let field of columns2){let property=properties&&typeof properties=="object"&&!Array.isArray(properties)?properties[field]:void 0,owner=field===template.owner;if(!property||(owner?property.type!=="string":!["string","integer","number"].includes(property.type))||property.nullable===!0||property.oneOf!==void 0||!Array.isArray(schema.required)||!schema.required.includes(field))throw new ManifestParseError(`Schema.spec.scope column '${field}' must be a required, non-nullable ${owner?"string":"string or number"} property`,idx,"/spec/scope")}if(![...m.spec.uniqueIndexes??[],...m.spec.indexes??[]].some(index=>columns2.every((field,i)=>index[i]===field)))throw new ManifestParseError(`Schema.spec.scope needs an index beginning with its scoped columns [${columns2.join(", ")}]`,idx,"/spec/scope");if(!template.terms.length&&(m.spec.uniqueIndexes??[]).some(index=>index[0]!==columns2[0]))throw new ManifestParseError("Scoped Schema unique indexes must begin with the scope field",idx,"/spec/uniqueIndexes")}if(s.localized!==!0&&propertyNames.includes("locale"))throw new ManifestParseError("Non-localized Schema must not declare the reserved entry field 'locale'; use a domain name such as 'orderLocale', or set localized: true.",idx,"/spec/schema/properties/locale");for(let reserved2 of RESERVED_ENTRY_COLUMNS)if(propertyNames.includes(reserved2))throw new ManifestParseError(`Schema '${m.metadata.name}' must not declare the native entry column '${reserved2}' as a data property; use a domain name such as 'submittedAt' or 'orderStatus'. Native columns are readable in Views and indexable through spec.indexes without being declared (handbook: reference/schema.md#reserved-entry-columns).`,idx,`/spec/schema/properties/${reserved2}`);for(let reserved2 of RESERVED_PROCEDURE_INPUT_NAMES)if(propertyNames.includes(reserved2))throw new ManifestParseError(`Schema '${m.metadata.name}' must not declare reserved Procedure input name '${reserved2}' as a data property (ADR-0022). New reserved names need an ADR.`,idx,`/spec/schema/properties/${reserved2}`);let required=schema.required;if(Array.isArray(required)){let unknownIndex=required.findIndex(field=>typeof field=="string"&&!propertyNames.includes(field));if(unknownIndex>=0){let field=required[unknownIndex];throw new ManifestParseError(`Schema '${m.metadata.name}' lists '${String(field)}' in required but never declares it under properties \u2014 the constraint is silently unenforced.`,idx,`/spec/schema/required/${unknownIndex}`,"REQUIRED_FIELD_UNKNOWN",{value:field,expected:"name of a property declared in spec.schema.properties",candidates:propertyNames})}}if(validateJsonSchema(s.schema,idx,"Schema",m.metadata.name,"/spec/schema"),properties&&typeof properties=="object"&&!Array.isArray(properties)){for(let[propertyName,property]of Object.entries(properties))if(!(!property||typeof property!="object"||Array.isArray(property))&&MANTLE_BIND_KEYWORD in property)throw new ManifestParseError(`Schema '${m.metadata.name}' property '${propertyName}': x-mantle-bind is removed. Use spec.scope for the caller's own field, or set it in the Procedure's SQL (auth.uid(), now()).`,idx,`/spec/schema/properties/${propertyName}/${MANTLE_BIND_KEYWORD}`)}if("lifecycle"in s){let lc=s.lifecycle;if(typeof lc!="string"||!V01_LIFECYCLE_MODES.has(lc))throw new ManifestParseError(`Schema.spec.lifecycle must be one of ${[...V01_LIFECYCLE_MODES].join(", ")}; got ${JSON.stringify(lc)}`,idx,"/spec/lifecycle")}if("translates"in s&&s.translates!=null){let t=s.translates;if(typeof t!="object"||Array.isArray(t))throw new ManifestParseError("Schema.spec.translates must be an object { parent, on }",idx,"/spec/translates");let tr=t;if(rejectUnknownKeys(tr,["parent","on"],idx,"/spec/translates"),typeof tr.parent!="string"||tr.parent.length===0)throw new ManifestParseError("Schema.spec.translates.parent is required (non-empty Schema name)",idx,"/spec/translates/parent");if(typeof tr.on!="string"||tr.on.length===0)throw new ManifestParseError("Schema.spec.translates.on is required (non-empty field name)",idx,"/spec/translates/on");if(s.localized!==!0)throw new ManifestParseError("Schema.spec.translates requires Schema.spec.localized: true (a non-localized translation table is meaningless)",idx,"/spec/translates","TRANSLATES_REQUIRES_LOCALIZED");if(!propertyNames.some(name4=>name4!=="locale"&&name4!==tr.on))throw new ManifestParseError("Schema.spec.translates requires at least one locale-specific field besides 'locale' and the join field",idx,"/spec/schema/properties","TRANSLATES_REQUIRES_CONTENT_FIELD");if(!propertyNames.includes(tr.on))throw new ManifestParseError(`Schema '${m.metadata.name}' translates.on field '${String(tr.on)}' is not declared on this Schema's own properties.`,idx,"/spec/translates/on","TRANSLATES_FIELD_NOT_IN_CHILD",{value:tr.on,expected:`field declared in Schema '${m.metadata.name}' spec.schema.properties`,candidates:propertyNames})}return m}var UNSUPPORTED_JSON_SCHEMA_KEYWORDS=new Set(["allOf","not","$anchor","$dynamicAnchor","$dynamicRef","definitions","patternProperties","prefixItems","contains","dependentSchemas","propertyNames","unevaluatedProperties"]);function validateJsonSchema(root,idx,kind,name4,basePointer){if(!root||typeof root!="object"||Array.isArray(root))throw new ManifestParseError(`${kind} '${name4}' JSON Schema must be an object`,idx,basePointer);let rootObject=root,nodes=0,refs2=[],visit=(node,pointer2,depth)=>{if(!node||typeof node!="object"||Array.isArray(node))throw new ManifestParseError(`${kind} '${name4}' has a non-object JSON Schema at ${pointer2}`,idx,pointer2);if(depth>100||++nodes>1e4)throw new ManifestParseError(`${kind} '${name4}' exceeds the JSON Schema complexity limit`,idx,pointer2,"JSON_SCHEMA_LIMIT_EXCEEDED");let value2=node;for(let keyword of UNSUPPORTED_JSON_SCHEMA_KEYWORDS)if(keyword in value2)throw new ManifestParseError(`${kind} '${name4}' uses unsupported JSON Schema keyword '${keyword}'`,idx,`${pointer2}/${escapeJsonPointerSegment(keyword)}`,"JSON_SCHEMA_UNSUPPORTED");if(basePointer!=="/spec/input"){for(let keyword of INPUT_RULE_KEYWORDS)if(keyword in value2)throw new ManifestParseError(`${kind} '${name4}' uses JSON Schema keyword '${keyword}', which is supported only in View and Procedure input`,idx,`${pointer2}/${escapeJsonPointerSegment(keyword)}`,"JSON_SCHEMA_UNSUPPORTED")}if("$ref"in value2&&refs2.push([`${pointer2}/$ref`,value2.$ref,validateLocalSchemaRef(value2.$ref,rootObject,idx,kind,name4,`${pointer2}/$ref`)]),value2.enum!==void 0&&(!Array.isArray(value2.enum)||value2.enum.length>MAX_JSON_SCHEMA_ENUM))throw new ManifestParseError(`${kind} '${name4}' enum must be a list of at most ${MAX_JSON_SCHEMA_ENUM} values`,idx,`${pointer2}/enum`,"JSON_SCHEMA_LIMIT_EXCEEDED");if(value2.pattern!==void 0){let problem3=typeof value2.pattern=="string"?unsafePattern(value2.pattern):"a pattern is a string";if(problem3)throw new ManifestParseError(`${kind} '${name4}' has a regex pattern at ${pointer2} that could take exponential time: ${problem3}`,idx,`${pointer2}/pattern`,"INVALID_PATTERN",{value:value2.pattern,expected:`a regular expression of at most ${MAX_JSON_SCHEMA_PATTERN} characters with no repeated group that itself repeats or alternates`});try{new RegExp(value2.pattern)}catch(error){throw new ManifestParseError(`${kind} '${name4}' has an uncompilable regex pattern at ${pointer2}: ${error instanceof Error?error.message:String(error)}`,idx,`${pointer2}/pattern`,"INVALID_PATTERN",{value:value2.pattern,expected:"a valid JavaScript regular expression"})}let{exponent,branches}=patternCost(value2.pattern),maxLength=value2.maxLength,bounded=typeof maxLength=="number"&&Number.isInteger(maxLength)&&maxLength>=0;if(branches*(exponent===0?1:bounded?maxLength**exponent:1/0)>MAX_PATTERN_WORK){let limit=maxPatternLength(exponent,branches),cost=`${branches===1?"":`${branches} alternative paths \xD7 `}maxLength^${exponent}`;throw new ManifestParseError(`${kind} '${name4}' has a regex pattern at ${pointer2} that could cost ${cost} backtracking steps on one string (${exponent} = its variable quantifiers *, +, ?, {m,}, {m,n}, plus 1 unless it starts with ^), over the ${MAX_PATTERN_WORK} limit. ${limit>0?`Declare maxLength of at most ${limit}, anchor it with ^, or use fewer variable quantifiers or alternatives.`:"Use fewer alternatives, or an enum."}`,idx,`${pointer2}/pattern`,"INVALID_PATTERN",{value:value2.pattern,expected:limit>0?`a string with maxLength of at most ${limit}`:`at most ${MAX_PATTERN_WORK} alternative paths`})}}let properties=value2.properties;if(properties!==void 0&&(!properties||typeof properties!="object"||Array.isArray(properties)))throw new ManifestParseError(`${kind} '${name4}' properties must be an object`,idx,`${pointer2}/properties`);if(properties&&typeof properties=="object")for(let[property,child2]of Object.entries(properties))visit(child2,`${pointer2}/properties/${escapeJsonPointerSegment(property)}`,depth+1);if(value2.items!==void 0&&visit(value2.items,`${pointer2}/items`,depth+1),typeof value2.additionalProperties=="object"&&value2.additionalProperties!==null)visit(value2.additionalProperties,`${pointer2}/additionalProperties`,depth+1);else if(value2.additionalProperties!==void 0&&typeof value2.additionalProperties!="boolean")throw new ManifestParseError(`${kind} '${name4}' additionalProperties must be a boolean or schema`,idx,`${pointer2}/additionalProperties`);let defs=value2.$defs;if(defs!==void 0){if(!defs||typeof defs!="object"||Array.isArray(defs))throw new ManifestParseError(`${kind} '${name4}' $defs must be an object`,idx,`${pointer2}/$defs`);for(let[definition,child2]of Object.entries(defs))visit(child2,`${pointer2}/$defs/${escapeJsonPointerSegment(definition)}`,depth+1)}let oneOf=value2.oneOf;if(oneOf!==void 0){if(!Array.isArray(oneOf)||oneOf.length===0)throw new ManifestParseError(`${kind} '${name4}' oneOf must be a non-empty array`,idx,`${pointer2}/oneOf`);oneOf.forEach((child2,index)=>visit(child2,`${pointer2}/oneOf/${index}`,depth+1))}};visit(root,basePointer,0);let target2=new Map(refs2.map(([,ref2,node])=>[ref2,node])),next=node=>!node||typeof node!="object"?[]:[..."$ref"in node?[node.$ref]:[],...Array.isArray(node.oneOf)?node.oneOf.flatMap(next):[]],done=new Set,onPath=new Set,at=basePointer,cycle=ref2=>{if(onPath.has(ref2))return!0;if(done.has(ref2))return!1;onPath.add(ref2);let node=typeof ref2=="string"&&target2.has(ref2)?target2.get(ref2):validateLocalSchemaRef(ref2,rootObject,idx,kind,name4,at),found=next(node).some(cycle);return onPath.delete(ref2),done.add(ref2),found};for(let[pointer2,ref2]of refs2)if(at=pointer2,cycle(ref2))throw new ManifestParseError(`${kind} '${name4}' $ref '${ref2}' refers back to itself without reading any part of the value`,idx,pointer2,"JSON_SCHEMA_REF_INVALID",{value:ref2,expected:"a $ref cycle only through properties, items or additionalProperties"})}var MAX_JSON_SCHEMA_ENUM=1e3,MAX_JSON_SCHEMA_PATTERN=1e3;function unsafePattern(pattern){return scanPattern(pattern).problem}function patternCost(pattern){let{variable,branches,anchored}=scanPattern(pattern);return{exponent:variable+(anchored?0:1),branches}}var MAX_PATTERN_WORK=1e7;function maxPatternLength(exponent,branches=1){let work=MAX_PATTERN_WORK/branches;if(work<1)return 0;if(exponent===0)return 1/0;let n=Math.floor(work**(1/exponent));for(;(n+1)**exponent<=work;)n++;for(;n>0&&n**exponent>work;)n--;return n}function scanPattern(pattern){let variable=0,branches=1,anchored=pattern.startsWith("^");if(pattern.length>MAX_JSON_SCHEMA_PATTERN)return{problem:`longer than ${MAX_JSON_SCHEMA_PATTERN} characters`,variable,branches,anchored};let stack=[{quantified:!1,alternates:!1,branches:1}],group,atom=!1;for(let i=0;i<pattern.length;i++){let c=pattern[i],top=stack.at(-1),brace=c==="{"?/^\{(\d+)(,(\d*))?\}/.exec(pattern.slice(i)):null;if(atom&&(c==="*"||c==="+"||c==="?"||brace)){let min=brace?+brace[1]:c==="+"?1:0,max=brace?brace[2]===void 0?min:brace[3]?+brace[3]:1/0:c==="?"?1:1/0;if(brace&&(i+=brace[0].length-1),pattern[i+1]==="?"&&i++,group&&max>1&&group.quantified)return{problem:"a repeated group whose body repeats (nested quantifiers)",variable,branches,anchored};if(group&&max>1&&group.alternates)return{problem:"a repeated group whose body alternates",variable,branches,anchored};max!==min&&(top.quantified=!0,variable++),group=void 0,atom=!1;continue}if(group=void 0,atom=!0,c==="\\"){let e=pattern[i+1];if(e!==void 0&&(/[1-9]/.test(e)||e==="k"))return{problem:"a backreference",variable,branches,anchored};i++}else if(c==="["){let j=i+1;for(pattern[j]==="^"&&j++;j<pattern.length&&pattern[j]!=="]";)j+=pattern[j]==="\\"?2:1;i=j}else if(c==="("){if(stack.push({quantified:!1,alternates:!1,branches:1}),atom=!1,pattern[i+1]==="?"){let head=/^\?(?::|=|!|<=|<!|<[A-Za-z_$][\w$]*>)/.exec(pattern.slice(i+1));head&&(i+=head[0].length)}}else if(c===")"&&stack.length>1){let closed=stack.pop(),parent=stack.at(-1);parent.quantified||=closed.quantified,parent.alternates||=closed.alternates,branches*=closed.branches,group=closed}else c==="|"?(top.alternates=!0,top.branches++,atom=!1):(c==="^"||c==="$")&&(atom=!1)}return{variable,branches:branches*stack[0].branches,anchored:anchored&&stack[0].branches===1}}function validateLocalSchemaRef(ref2,root,idx,kind,name4,pointer2){if(typeof ref2!="string"||!ref2.startsWith("#/$defs/"))throw new ManifestParseError(`${kind} '${name4}' $ref must be a same-document pointer beginning '#/$defs/'`,idx,pointer2,"JSON_SCHEMA_REF_INVALID",{value:ref2,expected:"#/$defs/<definition>"});let tokens;try{tokens=decodeURIComponent(ref2.slice(2)).split("/")}catch{tokens=void 0}let current=tokens?root:void 0;for(let token of tokens??[])if(/~(?:[^01]|$)/.test(token))current=void 0;else if(current&&typeof current=="object"){let key=token.replace(/~1/g,"/").replace(/~0/g,"~");current=Object.prototype.hasOwnProperty.call(current,key)?current[key]:void 0}else current=void 0;if(!current||typeof current!="object"||Array.isArray(current))throw new ManifestParseError(`${kind} '${name4}' cannot resolve local $ref '${ref2}'`,idx,pointer2,"JSON_SCHEMA_REF_INVALID",{value:ref2,expected:"a JSON Schema object in this document"});return current}function validateViewSpec(m,idx){let s=m.spec;if(rejectUnknownKeys(s,["title","description","uiSchema","sql","surface","cache","requires","restrict","input"],idx,"/spec"),validateLocalizedText(s.title,idx,"/spec/title","View.spec.title",!1),validateLocalizedText(s.description,idx,"/spec/description","View.spec.description",!1),typeof s.sql!="string"||s.sql.trim().length===0)throw new ManifestParseError("View.spec.sql is required (one SELECT statement)",idx,"/spec/sql");let surface=s.surface;if(typeof surface!="string"||!V01_VIEW_SURFACES.has(surface))throw new ManifestParseError(`View.spec.surface is required and must be one of ${[...V01_VIEW_SURFACES].join(", ")}; got ${JSON.stringify(surface)}`,idx,"/spec/surface");"cache"in s&&validateViewCache(s.cache,m,idx),"requires"in s&&s.requires!=null&&validateRequires(s.requires,idx,"View");let adminUiProblem=checkViewAdminUi(m).problems[0];if(adminUiProblem)throw new ManifestParseError(adminUiProblem.message,idx,adminUiProblem.pointer,"VIEW_UI_INVALID");return"input"in s&&s.input!=null&&(validateViewInput(s.input,idx),validateJsonSchema(s.input,idx,"View",m.metadata.name,"/spec/input")),m}function validateViewCache(raw,view,idx){if(typeof raw!="object"||raw===null||Array.isArray(raw))throw new ManifestParseError("View.spec.cache must be an object",idx,"/spec/cache","VIEW_CACHE_INVALID");let cache=raw;rejectUnknownKeys(cache,["sharedMaxAge"],idx,"/spec/cache");let maxAge=cache.sharedMaxAge;if(!Number.isInteger(maxAge)||maxAge<1||maxAge>86400)throw new ManifestParseError("View.spec.cache.sharedMaxAge must be an integer from 1 to 86400",idx,"/spec/cache/sharedMaxAge","VIEW_CACHE_INVALID");if(view.spec.surface!=="public"||view.spec.requires||view.spec.restrict)throw new ManifestParseError("View.spec.cache requires an unguarded public View without restrict",idx,"/spec/cache","VIEW_CACHE_INVALID")}function validateViewInput(raw,idx){let invalid2=(message2,pointer2,code="VIEW_INPUT_INVALID_SHAPE")=>{throw new ManifestParseError(message2,idx,pointer2,code)};(typeof raw!="object"||raw===null||Array.isArray(raw))&&invalid2("View.spec.input must be a JSON Schema object","/spec/input");let p=raw;p.type!=="object"&&invalid2(`View.spec.input.type must be "object"; got ${JSON.stringify(p.type)}`,"/spec/input/type");let props=p.properties;(typeof props!="object"||props===null||Array.isArray(props))&&invalid2("View.spec.input.properties is required (declare each accepted parameter)","/spec/input/properties");for(let reserved2 of VIEW_INPUT_RESERVED)Object.hasOwn(props,reserved2)&&invalid2(`View.spec.input.properties.${reserved2} is reserved (the runtime owns ${VIEW_INPUT_RESERVED.join(", ")} for pagination); rename it.`,`/spec/input/properties/${reserved2}`,"VIEW_INPUT_RESERVED_NAME")}function validateProcedureSpec(m,idx){let s=m.spec;if(rejectUnknownKeys(s,["title","description","requires","restrict","input","uiSchema","output","handler","mcp","target"],idx,"/spec"),s.mcp!==void 0){let mcp=s.mcp;if(typeof mcp!="object"||mcp===null||Array.isArray(mcp))throw new ManifestParseError("Procedure.spec.mcp must be an object of boolean tool annotations",idx,"/spec/mcp");rejectUnknownKeys(mcp,[...PROCEDURE_MCP_ANNOTATION_KEYS],idx,"/spec/mcp");for(let key of PROCEDURE_MCP_ANNOTATION_KEYS){let value2=mcp[key];if(value2!==void 0&&typeof value2!="boolean")throw new ManifestParseError(`Procedure.spec.mcp.${key} must be a boolean`,idx,`/spec/mcp/${key}`)}let hints=mcp;if(hints.readOnlyHint===!0&&hints.destructiveHint===!0)throw new ManifestParseError("Procedure.spec.mcp cannot be both readOnlyHint: true and destructiveHint: true",idx,"/spec/mcp")}if(s.target!==void 0&&validateProcedureTargetShape(s.target,idx),validateLocalizedText(s.title,idx,"/spec/title","Procedure.spec.title",!1),validateLocalizedText(s.description,idx,"/spec/description","Procedure.spec.description",!1),typeof s.input!="object"||s.input===null)throw new ManifestParseError("Procedure.spec.input is required (JSON Schema)",idx,"/spec/input");validateJsonSchema(s.input,idx,"Procedure",m.metadata.name,"/spec/input");let uiProblem=checkFormUiSchema(s.input,s.uiSchema,"Procedure")[0];if(uiProblem)throw new ManifestParseError(uiProblem.message,idx,uiProblem.pointer,"SCHEMA_UI_INVALID");if(typeof s.output!="object"||s.output===null)throw new ManifestParseError("Procedure.spec.output is required (JSON Schema)",idx,"/spec/output");validateJsonSchema(s.output,idx,"Procedure",m.metadata.name,"/spec/output");let handler=s.handler;if(!handler)throw new ManifestParseError("Procedure.spec.handler is required",idx,"/spec/handler");return validateHandlerBinding(handler,idx),"requires"in s&&s.requires!=null&&validateRequires(s.requires,idx,"Procedure"),m}function validateProcedureTargetShape(target2,idx){if(typeof target2!="object"||target2===null||Array.isArray(target2))throw new ManifestParseError("Procedure.spec.target must be an object { schema, id, version? }",idx,"/spec/target","PROCEDURE_TARGET_INVALID");rejectUnknownKeys(target2,[...PROCEDURE_TARGET_KEYS],idx,"/spec/target");for(let key of PROCEDURE_TARGET_KEYS){let value2=target2[key];if(!(value2===void 0&&key==="version")&&(typeof value2!="string"||value2.length===0))throw new ManifestParseError(`Procedure.spec.target.${key} must be a non-empty string`,idx,`/spec/target/${key}`,"PROCEDURE_TARGET_INVALID")}}function validateHandlerBinding(h,idx){let keys=Object.keys(h),key=keys.length===1?keys[0]:void 0;if(key!=="ref"&&key!=="sql")throw new ManifestParseError(`Procedure.spec.handler must have exactly one key, \`ref\` or \`sql\`; got ${JSON.stringify(keys)}`,idx,"/spec/handler");if(typeof h[key]!="string"||h[key].trim().length===0)throw new ManifestParseError(key==="ref"?"Procedure.spec.handler.ref is required (non-empty registration key)":"Procedure.spec.handler.sql is required (one or more write statements)",idx,`/spec/handler/${key}`)}function validateRequires(req,idx,atom){if(typeof req!="object"||req===null)throw new ManifestParseError(`${atom}.spec.requires must be an object`,idx);let r=req;if(rejectUnknownKeys(r,["auth","guard"],idx,"/spec/requires"),"guard"in r){let guard=r.guard;if(typeof guard!="object"||guard===null||Array.isArray(guard))throw new ManifestParseError(`${atom}.spec.requires.guard must be an object`,idx);let g=guard;if(typeof g.procedure!="string"||g.procedure.length===0)throw new ManifestParseError(`${atom}.spec.requires.guard.procedure must be a non-empty Procedure name`,idx);let extra=Object.keys(g).find(key=>key!=="procedure");if(extra!==void 0)throw new ManifestParseError(`${atom}.spec.requires.guard.${extra} is not supported; guard accepts only \`procedure\``,idx)}if(!("auth"in r)||r.auth==null)return;let auth=r.auth;if(typeof auth!="object"||auth===null)throw new ManifestParseError(`${atom}.spec.requires.auth must be an object`,idx);let a=auth;if(rejectUnknownKeys(a,["all"],idx,"/spec/requires/auth"),!("all"in a))throw new ManifestParseError(`${atom}.spec.requires.auth must declare \`all\` (v0.1)`,idx);let all=a.all;if(!Array.isArray(all)||all.length===0)throw new ManifestParseError(`${atom}.spec.requires.auth.all must be a non-empty array`,idx);for(let i=0;i<all.length;i++)validateAuthPredicate(all[i],idx,`${atom}.spec.requires.auth.all[${i}]`,`/spec/requires/auth/all/${i}`)}function validateAuthPredicate(p,idx,path,pointer2){if(p==="ctx.staff"||typeof p=="object"&&p!==null&&"ctx.staff"in p)throw new ManifestParseError(`${path}: 'ctx.staff' was renamed to 'ctx.admin'; replace it with 'ctx.admin'.`,idx);if(!(p==="ctx.user"||p==="ctx.auth"||p==="ctx.admin")){if(typeof p=="object"&&p!==null&&!Array.isArray(p)){let o=p;if("ctx.auth.scope"in o){rejectUnknownKeys(o,["ctx.auth.scope"],idx,pointer2);let scope=o["ctx.auth.scope"];if(typeof scope!="string"||scope.length===0)throw new ManifestParseError(`${path}: 'ctx.auth.scope' value must be a non-empty string`,idx);return}if("ctx.admin"in o)throw new ManifestParseError(`${path}: role lists in requires ('ctx.admin: [...]') are withdrawn; use 'ctx.admin' (any admin) and decide per-target roles in the application's authorize(target, caller) seam`,idx)}throw new ManifestParseError(`${path} must be 'ctx.user', 'ctx.auth', 'ctx.admin', or { 'ctx.auth.scope': <scope> }; got ${JSON.stringify(p)}`,idx)}}function validateHttpSource(source,idx){rejectUnknownKeys(source,["kind","method","path"],idx,"/spec/source");let method=source.method;if(typeof method!="string"||!V01_HTTP_METHODS.has(method))throw new ManifestParseError(`Trigger.spec.source.method must be one of ${[...V01_HTTP_METHODS].join(", ")} (v0.1); got ${JSON.stringify(method)}`,idx,"/spec/source/method");let path=source.path;if(typeof path!="string"||path.length===0||!path.startsWith("/"))throw new ManifestParseError("Trigger.spec.source.path is required (non-empty string starting with '/')",idx,"/spec/source/path")}function validateLifecycleSource(source,idx){if(rejectUnknownKeys(source,["kind","schema","on"],idx,"/spec/source"),typeof source.schema!="string"||source.schema.length===0)throw new ManifestParseError("Trigger.spec.source.schema is required (Schema metadata.name) when source.kind is 'lifecycle'",idx,"/spec/source/schema");let on=source.on;if(!Array.isArray(on)||on.length===0)throw new ManifestParseError(`Trigger.spec.source.on must be a non-empty array of hook names (one of ${[...V01_LIFECYCLE_HOOKS].join(", ")})`,idx,"/spec/source/on");for(let i=0;i<on.length;i++){let hook=on[i];if(typeof hook!="string"||!V01_LIFECYCLE_HOOKS.has(hook))throw new ManifestParseError(`Trigger.spec.source.on[${i}] must be one of ${[...V01_LIFECYCLE_HOOKS].join(", ")}; got ${JSON.stringify(hook)}`,idx,`/spec/source/on/${i}`)}}function validateMcpSource(source,idx){rejectUnknownKeys(source,["kind","surface"],idx,"/spec/source");let surface=source.surface;if(typeof surface!="string"||!V01_MCP_TRIGGER_SURFACES.has(surface))throw new ManifestParseError(`Trigger.spec.source.surface must be one of ${[...V01_MCP_TRIGGER_SURFACES].join(", ")}; got ${JSON.stringify(surface)}`,idx,"/spec/source/surface")}function validateScheduleSource(source,idx){rejectUnknownKeys(source,["kind","cron","enabled"],idx,"/spec/source");let cron=source.cron,bounds=[[0,59],[0,23],[1,31],[1,12],[0,6]],fields=typeof cron=="string"?cron.split(" "):[];if(!(fields.length===5&&fields.every((field,index)=>{let[min,max]=bounds[index];return field.split(",").every(part=>{let match=/^(\*|\d+)(?:-(\d+))?(?:\/(\d+))?$/.exec(part);if(!match)return!1;let start=match[1]==="*"?min:Number(match[1]),end=match[2]===void 0?match[1]==="*"?max:start:Number(match[2]),step=match[3]===void 0?1:Number(match[3]);return start>=min&&end<=max&&start<=end&&step>=1&&(match[3]===void 0||match[1]==="*"||match[2]!==void 0)})})))throw new ManifestParseError("Trigger.spec.source.cron must be a five-field POSIX UTC cron expression (minute hour day month weekday, 0=Sunday)",idx,"/spec/source/cron");if(source.enabled!==void 0&&typeof source.enabled!="boolean")throw new ManifestParseError("Trigger.spec.source.enabled must be boolean",idx,"/spec/source/enabled")}function validateTriggerSpec(m,idx){let s=m.spec;rejectUnknownKeys(s,["source","target"],idx,"/spec");let source=s.source;if(!source)throw new ManifestParseError("Trigger.spec.source is required",idx,"/spec/source");let sourceKind=source.kind;if(typeof sourceKind!="string")throw new ManifestParseError(`Trigger.spec.source.kind is required (one of ${[...V01_TRIGGER_SOURCE_KINDS].join(", ")})`,idx,"/spec/source/kind");if(!V01_TRIGGER_SOURCE_KINDS.has(sourceKind))throw new ManifestParseError(`Trigger.spec.source.kind must be one of ${[...V01_TRIGGER_SOURCE_KINDS].join(", ")}; got '${sourceKind}'`,idx,"/spec/source/kind");sourceKind==="http"?validateHttpSource(source,idx):sourceKind==="lifecycle"?validateLifecycleSource(source,idx):sourceKind==="mcp"?validateMcpSource(source,idx):sourceKind==="schedule"&&validateScheduleSource(source,idx);let target2=s.target;if(!target2||typeof target2.procedure!="string")throw new ManifestParseError("Trigger.spec.target.procedure is required (string)",idx,"/spec/target/procedure");return rejectUnknownKeys(target2,["procedure"],idx,"/spec/target"),m}function parseManifestSources(sourceSet,defaultLifecycle="publishing"){let parsed=parseManifestSourcesInternal(sourceSet,defaultLifecycle);return parsed.diagnostics.some(diagnostic=>diagnostic.severity==="error")?{ok:!1,diagnostics:parsed.diagnostics}:{ok:!0,value:Object.freeze({entries:Object.freeze(parsed.entries)}),diagnostics:parsed.diagnostics}}function parseManifestSourcesInternal(sourceSet,defaultLifecycle){let entries=[],diagnostics=[],sources=sourceSet?.sources;if(!Array.isArray(sources))return diagnostics.push(invalidSourceDiagnostic("/sources","ManifestSourceSet.sources must be an array")),{entries,diagnostics};let seenIds=new Set;for(let index=0;index<sources.length;index++){let source=sources[index];if(!source||typeof source!="object"){diagnostics.push(invalidSourceDiagnostic(`/sources/${index}`,"manifest source must be an object"));continue}if(typeof source.sourceId!="string"||source.sourceId.length===0){diagnostics.push(invalidSourceDiagnostic(`/sources/${index}/sourceId`,"manifest sourceId must be a non-empty string"));continue}if(seenIds.has(source.sourceId)){diagnostics.push(invalidSourceDiagnostic(`/sources/${index}/sourceId`,`manifest sourceId '${source.sourceId}' is duplicated`,source.sourceId));continue}if(seenIds.add(source.sourceId),typeof source.text!="string"){diagnostics.push(invalidSourceDiagnostic(`/sources/${index}/text`,`manifest source '${source.sourceId}' text must be a string`,source.sourceId));continue}parseOneStream(source,entries,diagnostics,defaultLifecycle)}return{entries,diagnostics}}function invalidSourceDiagnostic(path,message2,sourceId){return validateDiagnostic({code:"INVALID_MANIFEST_ENVELOPE",severity:"error",path,...sourceId?{source:{sourceId,documentIndex:0,path}}:{},message:message2})}function parseOneStream(source,entries,diagnostics,defaultLifecycle){let lineCounter=new LineCounter2,docs=parseAllDocuments(source.text,{merge:!1,lineCounter});for(let i=0;i<docs.length;i++){let doc=docs[i],docIndex=i;if(doc.errors.length>0){let error=doc.errors[0],location=sourceLocation(source.sourceId,docIndex,"/",lineCounter,error?.pos??doc.range);diagnostics.push(validateDiagnostic({code:"INVALID_MANIFEST_ENVELOPE",severity:"error",path:"/",source:location,message:`[doc ${docIndex}] YAML parse error: ${doc.errors.map(e=>e.message).join("; ")}`}));continue}let value2;try{value2=doc.toJS({maxAliasCount:100})}catch(e){diagnostics.push(validateDiagnostic({code:"INVALID_MANIFEST_ENVELOPE",severity:"error",path:"/",source:sourceLocationForNode(source.sourceId,docIndex,"/",doc,lineCounter),message:`[doc ${docIndex}] YAML alias-expansion limit exceeded: ${e instanceof Error?e.message:String(e)}`}));continue}if(value2!=null)try{entries.push({manifest:normalizeManifest(validateEnvelope(value2,docIndex),defaultLifecycle),source:sourceLocationForNode(source.sourceId,docIndex,"/",doc,lineCounter),sourceSpans:collectSourceSpans(doc.contents,lineCounter)})}catch(e){if(e instanceof ManifestParseError){let path=e.pointer??"/";diagnostics.push(validateDiagnostic({code:e.code,severity:"error",path,source:sourceLocationForNode(source.sourceId,docIndex,path,doc,lineCounter),...e.details,message:e.message}))}else diagnostics.push(validateDiagnostic({code:"INVALID_MANIFEST_ENVELOPE",severity:"error",path:"/",source:sourceLocationForNode(source.sourceId,docIndex,"/",doc,lineCounter),message:e instanceof Error?`[doc ${docIndex}] ${e.message}`:`[doc ${docIndex}] unknown parse error`}))}}}function normalizeManifest(manifest,defaultLifecycle){return manifest.kind==="Schema"?{...manifest,spec:{...manifest.spec,uniqueIndexes:manifest.spec.uniqueIndexes??[],indexes:manifest.spec.indexes??[],searchableFields:manifest.spec.searchableFields??[],localized:manifest.spec.localized??!1,lifecycle:manifest.spec.lifecycle??defaultLifecycle}}:manifest}function validateEnvelope(raw,docIndex){if(typeof raw!="object"||raw===null||Array.isArray(raw))throw new ManifestParseError("manifest must be a YAML mapping",docIndex);let m=raw;if(rejectUnknownKeys(m,["apiVersion","kind","metadata","spec"],docIndex,"/"),m.apiVersion!==API_VERSION)throw new ManifestParseError(`apiVersion must be "${API_VERSION}"; got ${JSON.stringify(m.apiVersion)}`+(m.apiVersion==="cms.mantle.aotter.net/v1"?" (a 0.1.x manifest: follow node_modules/@aotter/mantle/docs/upgrade-0.1-to-0.2.md)":""),docIndex,"/apiVersion");let kind=m.kind;if(typeof kind!="string"||!KNOWN_KINDS.has(kind))throw new ManifestParseError(`kind must be one of ${[...KNOWN_KINDS].join(", ")}; got ${JSON.stringify(kind)}`,docIndex,"/kind");let meta=m.metadata;if(typeof meta!="object"||meta===null)throw new ManifestParseError("metadata is required and must be a mapping",docIndex,"/metadata");let name4=meta.name;if(rejectUnknownKeys(meta,["name"],docIndex,"/metadata"),typeof name4!="string"||name4.length===0)throw new ManifestParseError("metadata.name is required (non-empty string)",docIndex,"/metadata/name");let spec=m.spec;if(typeof spec!="object"||spec===null)throw new ManifestParseError("spec is required and must be a mapping",docIndex,"/spec");switch(kind){case"Schema":return validateSchemaSpec(raw,docIndex);case"View":return validateViewSpec(raw,docIndex);case"Procedure":return validateProcedureSpec(raw,docIndex);case"Trigger":return validateTriggerSpec(raw,docIndex);default:throw new ManifestParseError(`unhandled kind ${kind}`,docIndex)}}function manifestPath(kind,name4,jsonPointer,filePaths,occurrence=1){let locations=filePaths?.get(`${kind}/${name4}`),fp=locations?.[Math.max(0,occurrence-1)]??locations?.[0];return fp?`${fp.file}#/${fp.docIndex}${jsonPointer}`:`manifest:${kind}/${name4}#${jsonPointer}`}function bestMatch(target2,candidates){let best,bestD=3;for(let c of candidates){let d=editDistance(target2,c);d<bestD&&(bestD=d,best=c)}return best}function editDistance(a,b){if(a===b)return 0;if(a.length===0)return b.length;if(b.length===0)return a.length;let dp=Array.from({length:a.length+1},()=>Array(b.length+1).fill(0));for(let i=0;i<=a.length;i++)dp[i][0]=i;for(let j=0;j<=b.length;j++)dp[0][j]=j;for(let i=1;i<=a.length;i++)for(let j=1;j<=b.length;j++){let cost=a[i-1]===b[j-1]?0:1;dp[i][j]=Math.min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+cost)}return dp[a.length][b.length]}function checkTranslatesReferences(schemas,phase,filePaths){let out=[],schemasByName=new Map(schemas.map(schema=>[schema.metadata.name,schema]));for(let s of schemas){let translates=s.spec.translates;if(!translates)continue;let path=jsonPointer=>manifestPath("Schema",s.metadata.name,jsonPointer,filePaths),parent=schemasByName.get(translates.parent);if(!parent){out.push(emit(phase,{code:"TRANSLATES_PARENT_UNKNOWN",severity:"error",path:path("/spec/translates/parent"),value:translates.parent,expected:"name of a declared Schema",candidates:[...schemasByName.keys()],suggestion:bestMatch(translates.parent,[...schemasByName.keys()]),message:`Schema '${s.metadata.name}' translates.parent references unknown Schema '${translates.parent}'.`}));continue}(s.spec.ttl||parent.spec.ttl)&&out.push(emit(phase,{code:"SCHEMA_TTL_TRANSLATION_UNSUPPORTED",severity:"error",path:path("/spec/translates"),message:`Schema '${s.metadata.name}' cannot translate TTL Schema '${parent.metadata.name}' or declare TTL itself; joined translations cannot guarantee expiry across both Schemas.`,expected:"TTL only on Schemas outside a translation relationship"})),parent.spec.localized===!0&&out.push(emit(phase,{code:"TRANSLATES_PARENT_IS_LOCALIZED",severity:"error",path:path("/spec/translates/parent"),value:translates.parent,expected:"parent Schema must NOT be localized (it carries the non-translatable facts; translation rows are this Schema)",message:`Schema '${s.metadata.name}' translates.parent '${translates.parent}' is itself localized. The parent should hold non-translatable facts (e.g. sku, price); the localized child holds the translatable fields.`}));let parentProps=propertyKeys(parent);parentProps.has(translates.on)||out.push(emit(phase,{code:"TRANSLATES_FIELD_NOT_IN_PARENT",severity:"error",path:path("/spec/translates/on"),value:translates.on,expected:`field declared in Schema '${parent.metadata.name}' spec.schema.properties`,candidates:[...parentProps].sort(),suggestion:bestMatch(translates.on,[...parentProps]),message:`Schema '${s.metadata.name}' translates.on field '${translates.on}' is not declared on parent Schema '${parent.metadata.name}'.`}))}return out}function emit(phase,payload){return phase==="validate"?validateDiagnostic(payload):bootDiagnostic(payload)}function propertyKeys(s){let props=s.spec.schema.properties??{};return new Set(Object.keys(props))}var RESERVED_READER_NAMES=["constructor","then","__proto__","prototype","toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toJSON","__defineGetter__","__defineSetter__","__lookupGetter__","__lookupSetter__"],IDENTIFIER=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function readerName(schemaName){if(/[^\x00-\x7f]/.test(schemaName))return schemaName.toLowerCase();let parts=schemaName.split(/[^A-Za-z0-9]+/).filter(Boolean),projected=parts.length?parts[0][0].toLowerCase()+parts[0].slice(1)+parts.slice(1).map(p=>p[0].toUpperCase()+p.slice(1)).join(""):"";return IDENTIFIER.test(projected)?projected:schemaName.toLowerCase()}function readerNameProblems(names){let out=[],first=new Map;for(let name4 of names){let reader=readerName(name4);if(RESERVED_READER_NAMES.includes(reader)){out.push({name:name4,message:`Schema '${name4}' would be the reader '${reader}', a reserved property name. Rename the Schema.`});continue}let other=first.get(reader);other===void 0?first.set(reader,name4):other.toLowerCase()!==name4.toLowerCase()&&out.push({name:name4,message:`Schema '${name4}' and Schema '${other}' both become the reader '${reader}' (store.db.${reader}). Rename one.`})}return out}function partitionManifests(manifests){let schemas=[],views=[],procedures=[],triggers=[];for(let manifest of manifests)manifest.kind==="Schema"?schemas.push(manifest):manifest.kind==="View"?views.push(manifest):manifest.kind==="Procedure"?procedures.push(manifest):triggers.push(manifest);return{schemas,views,procedures,triggers}}import{z}from"zod";function jsonSchemaToZod(schema){let imported;try{imported=lengthBeforePattern(z.fromJSONSchema(normalizeNullable(schema)))}catch(error){let message2=error instanceof Error?error.message:String(error);imported=z.never({error:`Invalid JSON Schema: ${message2}`})}return jsonValueWithinLimits().pipe(imported)}function lengthBeforePattern(root){let seen=new WeakSet,visit=node=>{if(!node||typeof node!="object"||seen.has(node))return;seen.add(node);let def=node._zod?.def;if(!def){for(let child2 of Array.isArray(node)?node:Object.values(node))visit(child2);return}if(def.type==="string")for(let check2 of def.checks??[])check2._zod.def.check==="max_length"&&(check2._zod.def.abort=!0);for(let[key,child2]of Object.entries(def))key!=="checks"&&visit(key==="getter"&&typeof child2=="function"?child2():child2)};return visit(root),root}function normalizeNullable(schema){let transform=node=>{let out={...node};if(node.format==="url"&&(out.format="uri"),node.properties&&(out.properties=Object.fromEntries(Object.entries(node.properties).map(([name4,child2])=>[name4,transform(child2)]))),node.$defs&&(out.$defs=Object.fromEntries(Object.entries(node.$defs).map(([name4,child2])=>[name4,transform(child2)]))),node.items&&(out.items=transform(node.items)),typeof node.additionalProperties=="object"&&(out.additionalProperties=transform(node.additionalProperties)),node.oneOf&&(out.oneOf=node.oneOf.map(transform)),delete out.nullable,node.nullable===!0){if(typeof node.type=="string")out.type=[node.type,"null"];else if(Array.isArray(node.type)&&!node.type.includes("null"))out.type=[...node.type,"null"];else if(node.type===void 0){let{$defs,...base}=out,definitions=$defs;return{...definitions?{$defs:definitions}:{},oneOf:[base,{type:"null"}]}}}return out};return transform(schema)}function jsonValueWithinLimits(){return z.unknown().superRefine((value2,ctx)=>{let stack=[{value:value2,depth:0}],active=new WeakSet,nodes=0;for(;stack.length>0;){let current=stack.pop();if(!(current.value===null||typeof current.value!="object")){if(current.exit){active.delete(current.value);continue}if(active.has(current.value)){ctx.addIssue({code:"custom",message:"value must not contain object cycles"});return}if(active.add(current.value),current.depth>100||++nodes>1e4){ctx.addIssue({code:"custom",message:"value exceeds JSON Schema validation limits"});return}stack.push({...current,exit:!0});for(let child2 of Array.isArray(current.value)?current.value:Object.values(current.value))stack.push({value:child2,depth:current.depth+1})}}})}function lookupLocalRef(root,ref2){if(typeof ref2!="string"||!ref2.startsWith("#/"))return;let value2=root;try{for(let key of decodeURIComponent(ref2.slice(2)).split("/").map(key2=>key2.replace(/~1/g,"/").replace(/~0/g,"~")))value2=value2&&typeof value2=="object"&&Object.hasOwn(value2,key)?value2[key]:void 0}catch{return}return value2&&typeof value2=="object"?value2:void 0}function rootRefChain(input){let chain=[];for(let schema=input;schema!==void 0;schema=lookupLocalRef(input,schema.$ref)){if(chain.includes(schema))return;if(chain.push(schema),schema.$ref===void 0)return chain}}function mcpToolNameSegment(name4){return name4.toLowerCase().replace(/-/g,"_")}function toolTitle(name4){let words=name4.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/[-_.\s]+/g," ").trim().toLowerCase();return words.charAt(0).toUpperCase()+words.slice(1)}var viewAnnotations={readOnlyHint:!0,destructiveHint:!1};function procedureAnnotations(p){let readOnlyHint=p.mcp?.readOnlyHint??!1;return{readOnlyHint,destructiveHint:!readOnlyHint&&("ref"in p.handler||overwrites(p.handler.sql.stmts)),...p.mcp}}var overwrites=node=>!!node&&typeof node=="object"&&("DeleteStmt"in node||"UpdateStmt"in node||node.onConflictClause?.action==="ONCONFLICT_UPDATE"||Object.values(node).some(overwrites));function mcpTools(plan,surface,locale="en"){let text=t=>resolveLocalizedText(t,locale,"en")??void 0,tools=new Map,add=tool=>{let prior=tools.get(tool.name);if(prior&&(prior.kind!==tool.kind||prior.source!==tool.source))throw new TypeError(`MCP tool '${tool.name}' comes from both '${prior.source}' and '${tool.source}'.`);tools.set(tool.name,tool)};for(let t of Object.values(plan.triggers)){if(t.source.kind!=="mcp"||t.source.surface!==surface)continue;let p=plan.procedures[t.procedure],title=text(p.title);add({name:mcpToolNameSegment(t.procedure),kind:"procedure",source:t.procedure,title:title??toolTitle(t.procedure),description:text(p.description)??title??t.procedure,inputSchema:p.input,...p.output.type==="object"?{outputSchema:p.output}:{},annotations:procedureAnnotations(p),requires:p.requires})}for(let[name4,v]of Object.entries(plan.views)){if(v.surface!==surface)continue;let chain=(v.input?rootRefChain(v.input)??[v.input]:[]).reverse(),props=Object.assign({},...chain.map(s=>s.properties??{})),required=[...new Set(chain.flatMap(s=>s.required??[]))];if("limit"in props||"cursor"in props)throw new TypeError(`View '${name4}' declares an input named limit or cursor; the MCP tool reserves both for paging.`);let rules=chain.map(s=>Object.fromEntries(INPUT_RULE_KEYWORDS.flatMap(k=>s[k]===void 0?[]:[[k,s[k]]]))).filter(r=>Object.keys(r).length),defs=v.input?referencedDefs(v.input,props):{},title=text(v.title);add({name:mcpToolNameSegment(name4),kind:"view",source:name4,title:title??toolTitle(name4),description:text(v.description)??title??name4,inputSchema:{type:"object",properties:{...props,limit:{type:"integer",minimum:1,maximum:500},cursor:{type:"string"}},...required.length?{required}:{},...rules.length>1?{allOf:rules}:rules[0],...Object.keys(defs).length?{$defs:defs}:{}},annotations:viewAnnotations,requires:v.requires})}return[...tools.values()]}function referencedDefs(root,node,found={}){if(!node||typeof node!="object")return found;let ref2=node.$ref,[head,segment]=typeof ref2=="string"&&ref2.startsWith("#/")?decoded(ref2.slice(2)).split("/"):[],key=head==="$defs"?segment?.replace(/~1/g,"/").replace(/~0/g,"~"):void 0;key!==void 0&&!Object.hasOwn(found,key)&&root.$defs&&Object.hasOwn(root.$defs,key)&&(found[key]=root.$defs[key],referencedDefs(root,found[key],found));for(let child2 of Object.values(node))referencedDefs(root,child2,found);return found}var decoded=pointer2=>{try{return decodeURIComponent(pointer2)}catch{return""}};function checkProcedureTarget(procedure,schemasByName,filePaths){let target2=procedure.spec.target;if(!target2)return[];let name4=procedure.metadata.name,fail=(pointer2,value2,expected,message2,candidates)=>[validateDiagnostic({code:"PROCEDURE_TARGET_INVALID",severity:"error",path:manifestPath("Procedure",name4,`/spec/target${pointer2}`,filePaths),value:value2,expected,...candidates?{candidates}:{},message:message2})];if(!schemasByName.has(target2.schema))return fail("/schema",target2.schema,"the metadata.name of an existing Schema",`Procedure '${name4}' target references unknown Schema '${target2.schema}'.`,[...schemasByName.keys()]);let input=procedure.spec.input,properties=input.properties??{};return!new Set(input.required??[]).has(target2.id)||!hasType(properties[target2.id],["string"])?fail("/id",target2.id,"a required string input property",`Procedure '${name4}' target.id '${target2.id}' must be a required string property of spec.input.`,Object.keys(properties)):target2.version!==void 0&&!hasType(properties[target2.version],["number","integer"])?fail("/version",target2.version,"a number input property",`Procedure '${name4}' target.version '${target2.version}' must be a number property of spec.input.`,Object.keys(properties)):[]}function checkSqlHandler(p,filePaths){let h=p.spec.handler;if(!("sql"in h))return[];let hint=(key,value2,message2)=>p.spec.mcp?.[key]===value2?[validateDiagnostic({code:"INVALID_MANIFEST_ENVELOPE",severity:"error",path:manifestPath("Procedure",p.metadata.name,`/spec/mcp/${key}`,filePaths),value:value2,expected:`no ${key}, or ${key}: ${!value2}, on this sql handler`,message:`Procedure '${p.metadata.name}' declares mcp.${key}: ${value2} but its sql handler ${message2}.`})]:[];return[...hint("readOnlyHint",!0,"writes"),.../\bdelete\s+from\b/i.test(h.sql)?hint("destructiveHint",!1,"deletes"):[]]}function checkGuards(targets,proceduresByName,filePaths){let out=[];for(let target2 of targets){let guardName=target2.spec.requires?.guard?.procedure;if(!guardName)continue;let path=manifestPath(target2.kind,target2.metadata.name,"/spec/requires/guard/procedure",filePaths),guard=proceduresByName.get(guardName);if(!guard){out.push(validateDiagnostic({code:"GUARD_PROCEDURE_UNKNOWN",severity:"error",path,value:guardName,expected:"name of a declared Procedure",candidates:[...proceduresByName.keys()],suggestion:bestMatch(guardName,[...proceduresByName.keys()]),message:`${target2.kind} '${target2.metadata.name}' references unknown guard Procedure '${guardName}'.`}));continue}if(target2.kind==="Procedure"&&target2.metadata.name===guardName){out.push(validateDiagnostic({code:"GUARD_SELF_REFERENCE",severity:"error",path,value:guardName,expected:"a different, unguarded Procedure",message:`Procedure '${target2.metadata.name}' cannot guard itself.`}));continue}"ref"in guard.spec.handler||out.push(validateDiagnostic({code:"GUARD_PROCEDURE_NOT_REF",severity:"error",path,value:guardName,expected:"a Procedure with a ref handler",message:`${target2.kind} '${target2.metadata.name}' uses '${guardName}' as a guard, but guard Procedures must use a ref handler.`})),guard.spec.requires?.guard&&out.push(validateDiagnostic({code:"GUARD_CHAIN_NOT_ALLOWED",severity:"error",path,value:guardName,expected:"an unguarded Procedure",message:`${target2.kind} '${target2.metadata.name}' uses '${guardName}' as a guard, but guard chains are not allowed.`}))}return out}function checkTriggerRefs(triggers,proceduresByName,filePaths,schemasByName){let out=[],httpRoutes=new Map,undescribedMcpProcedures=new Set;for(let t of triggers){let procName=t.spec.target.procedure;if(proceduresByName.has(procName)||out.push(validateDiagnostic({code:"TRIGGER_TARGET_PROCEDURE_UNKNOWN",severity:"error",path:manifestPath("Trigger",t.metadata.name,"/spec/target/procedure",filePaths),value:procName,expected:"name of a declared Procedure",candidates:[...proceduresByName.keys()],suggestion:bestMatch(procName,[...proceduresByName.keys()]),message:`Trigger '${t.metadata.name}' targets unknown Procedure '${procName}'.`})),t.spec.source.kind==="schedule"){let target2=proceduresByName.get(procName);target2&&(target2.spec.requires?.auth?.all.length??0)>0&&out.push(validateDiagnostic({code:"SCHEDULE_AUTH_INVALID",severity:"error",path:manifestPath("Trigger",t.metadata.name,"/spec/target/procedure",filePaths),value:procName,expected:"a Procedure without user or admin authorization requirements",message:`Scheduled Trigger '${t.metadata.name}' cannot satisfy '${procName}' authorization with a system caller.`})),target2&&!jsonSchemaToZod(target2.spec.input).safeParse({}).success&&out.push(validateDiagnostic({code:"SCHEDULE_INPUT_INVALID",severity:"error",path:manifestPath("Trigger",t.metadata.name,"/spec/target/procedure",filePaths),value:procName,expected:"a Procedure whose input accepts an empty object",message:`Scheduled Trigger '${t.metadata.name}' cannot supply required Procedure input to '${procName}'.`}))}if(t.spec.source.kind==="http"){let httpPath=t.spec.source.path,isValidPrefix=httpPath.startsWith("/api/");isValidPrefix||out.push(validateDiagnostic({code:"TRIGGER_PATH_INVALID",severity:"error",path:manifestPath("Trigger",t.metadata.name,"/spec/source/path",filePaths),value:httpPath,expected:"path starting with '/api/'",message:`Trigger '${t.metadata.name}' has path '${httpPath}' \u2014 http Trigger paths MUST start with '/api/' so adapters can route public pages and Procedure endpoints without ambiguity.`}));let key=`${t.spec.source.method} ${httpPath}`,prior=httpRoutes.get(key);prior?out.push(validateDiagnostic({code:"TRIGGER_PATH_COLLISION",severity:"error",path:manifestPath("Trigger",t.metadata.name,"/spec/source",filePaths),value:key,expected:`unique (method, path) across all http Triggers (also declared by '${prior}')`,message:`Trigger '${t.metadata.name}' shares route ${key} with Trigger '${prior}'.`})):isValidPrefix&&httpRoutes.set(key,t.metadata.name)}if(t.spec.source.kind==="mcp"){let target2=proceduresByName.get(procName);target2&&!undescribedMcpProcedures.has(procName)&&!resolveLocalizedText(target2.spec.description,"en")?.trim()&&(undescribedMcpProcedures.add(procName),out.push(validateDiagnostic({code:"MCP_TOOL_DESCRIPTION_MISSING",severity:"warning",path:manifestPath("Procedure",procName,"/spec/description",filePaths),value:null,expected:"a description an agent can choose the tool by",message:`Procedure '${procName}' is exposed as an MCP tool on the ${t.spec.source.surface} surface by Trigger '${t.metadata.name}' but has no spec.description; tools/list will show a generated placeholder.`})))}let hookTarget=t.spec.source.kind==="lifecycle"?proceduresByName.get(t.spec.target.procedure):void 0;if(hookTarget&&!("ref"in hookTarget.spec.handler)&&out.push(validateDiagnostic({code:"LIFECYCLE_TARGET_NOT_REF",severity:"error",path:manifestPath("Trigger",t.metadata.name,"/spec/target/procedure",filePaths),value:t.spec.target.procedure,expected:"a Procedure with a ref handler",message:`Lifecycle Trigger '${t.metadata.name}' targets '${t.spec.target.procedure}', whose handler is an inline program; a hook target must use a ref handler.`})),t.spec.source.kind==="lifecycle"&&schemasByName&&!schemasByName.has(t.spec.source.schema)){let schemaName=t.spec.source.schema;out.push(validateDiagnostic({code:"LIFECYCLE_SCHEMA_UNKNOWN",severity:"error",path:manifestPath("Trigger",t.metadata.name,"/spec/source/schema",filePaths),value:schemaName,expected:"name of a declared Schema",candidates:[...schemasByName.keys()],suggestion:bestMatch(schemaName,[...schemasByName.keys()]),message:`Trigger '${t.metadata.name}' watches unknown Schema '${schemaName}'.`}))}}return out}function checkMcpToolNameCollisions(views,procedures,triggers,filePaths){let seen=new Map,out=[],exposed=new Set(triggers.flatMap(t=>t.spec.source.kind==="mcp"?[t.spec.target.procedure]:[])),claim=(kind,name4)=>{let segment=mcpToolNameSegment(name4);if((kind==="View"||exposed.has(name4))&&(segment.length>128||!/^[A-Za-z0-9_.-]+$/.test(segment))){out.push(validateDiagnostic({code:"MCP_TOOL_NAME_COLLISION",severity:"error",path:manifestPath(kind,name4,"/metadata/name",filePaths),value:segment,expected:"an MCP tool name of at most 128 characters from [A-Za-z0-9_.-]",message:`${kind} '${name4}' cannot be an MCP tool name: it must be at most 128 characters from [A-Za-z0-9_.-].`}));return}let prior=seen.get(segment);prior&&prior!==`${kind} ${name4}`?out.push(validateDiagnostic({code:"MCP_TOOL_NAME_COLLISION",severity:"error",path:manifestPath(kind,name4,"/metadata/name",filePaths),value:segment,expected:`${kind} name unique after kebab\u2192snake mangling (collides with ${prior})`,message:`${kind} '${name4}' mangles to MCP tool name '${segment}', which already comes from ${prior}.`})):prior||seen.set(segment,`${kind} ${name4}`)};for(let view of views)view.spec.surface!=="internal"&&claim("View",view.metadata.name);for(let procedure of procedures)claim("Procedure",procedure.metadata.name);let mcpTriggers=new Map;for(let trigger of triggers){let source=trigger.spec.source;if(source.kind!=="mcp")continue;let tool=mcpToolNameSegment(trigger.spec.target.procedure),key=`${source.surface}\0${tool}`,prior=mcpTriggers.get(key);prior?out.push(validateDiagnostic({code:"MCP_TOOL_NAME_COLLISION",severity:"error",path:manifestPath("Trigger",trigger.metadata.name,"/spec/source",filePaths),value:tool,expected:`one MCP Trigger per surface and tool name (already bound by '${prior}')`,message:`Trigger '${trigger.metadata.name}' and Trigger '${prior}' both bind '${tool}' on the ${source.surface} MCP surface; invocation would lose Trigger identity.`})):mcpTriggers.set(key,trigger.metadata.name)}return out}function hasType(schema,types){let declared=schema?.type,list=Array.isArray(declared)?declared:declared===void 0?[]:[declared];return list.length>0&&list.every(type=>types.includes(type)||type==="null")&&list.some(type=>types.includes(type))}function validateManifestGraph(manifests,filePaths){let diags=[],partitioned=partitionManifests(manifests),schemasByName=byName(partitioned.schemas),proceduresByName=byName(partitioned.procedures);diags.push(...checkDuplicates("Schema",partitioned.schemas,filePaths)),diags.push(...checkDuplicates("View",partitioned.views,filePaths)),diags.push(...checkDuplicates("Procedure",partitioned.procedures,filePaths)),diags.push(...checkDuplicates("Trigger",partitioned.triggers,filePaths)),diags.push(...checkSchemaReservedWireNames(partitioned.schemas,filePaths)),diags.push(...checkCaseCollisions(partitioned.schemas,[...partitioned.views,...partitioned.procedures],filePaths)),diags.push(...checkReaderNames(partitioned.schemas,filePaths)),diags.push(...checkTranslatesReferences(partitioned.schemas,"validate",filePaths)),diags.push(...checkSchemaNavTargetsGraph(partitioned.schemas,schemasByName,filePaths));for(let s of partitioned.schemas)diags.push(...checkMantleRefs("Schema",s.metadata.name,"/spec/schema",s.spec.schema,schemasByName,filePaths));for(let p of partitioned.procedures)diags.push(...checkSqlHandler(p,filePaths)),diags.push(...checkCollectionActionRef(p,schemasByName,filePaths)),diags.push(...checkMantleRefs("Procedure",p.metadata.name,"/spec/input",p.spec.input,schemasByName,filePaths)),diags.push(...checkProcedureTarget(p,schemasByName,filePaths));return diags.push(...checkGuards([...partitioned.procedures,...partitioned.views],proceduresByName,filePaths)),diags.push(...checkTriggerRefs(partitioned.triggers,proceduresByName,filePaths,schemasByName)),diags.push(...checkMcpToolNameCollisions(partitioned.views,partitioned.procedures,partitioned.triggers,filePaths)),{diagnostics:diags,...partitioned}}function checkSchemaNavTargetsGraph(schemas,schemasByName,filePaths){let out=[];for(let schema of schemas){let problem3=checkSchemaNavTargets(schema,schemasByName);problem3&&out.push(validateDiagnostic({code:"SCHEMA_UI_INVALID",severity:"error",path:manifestPath("Schema",schema.metadata.name,problem3.pointer,filePaths),value:problem3.value,expected:problem3.expected,message:problem3.message}))}return out}function checkCollectionActionRef(procedure,schemasByName,filePaths){let target2=procedure.spec.uiSchema?.collectionAction;return typeof target2!="string"||schemasByName.has(target2)?[]:[validateDiagnostic({code:"SCHEMA_UI_INVALID",severity:"error",path:manifestPath("Procedure",procedure.metadata.name,"/spec/uiSchema/collectionAction",filePaths),value:target2,expected:"the metadata.name of an existing Schema",message:`Procedure '${procedure.metadata.name}' collection action references unknown Schema '${target2}'.`})]}function checkMantleRefs(kind,name4,pointer2,schema,schemasByName,filePaths){let out=[];for(let[field,property]of Object.entries(schema.properties??{})){let raw=property?.[MANTLE_REF_KEYWORD];if(raw===void 0||typeof raw=="string")continue;let path=manifestPath(kind,name4,`${pointer2}/properties/${pointerSegment(field)}/${MANTLE_REF_KEYWORD}`,filePaths),ref2=resolveMantleRef(property),keys=typeof raw=="object"&&raw!==null&&!Array.isArray(raw)?Object.keys(raw):[];if(!ref2||keys.some(key=>key!=="schema"&&key!=="field")){out.push(validateDiagnostic({code:"MANTLE_REF_INVALID",severity:"error",path,value:raw,expected:"a Schema name, or { schema: <Schema name>, field: <id or single-field unique index> }",message:`${kind} '${name4}' field '${field}' has a malformed x-mantle-ref.`}));continue}let target2=schemasByName.get(ref2.schema);if(!target2){out.push(validateDiagnostic({code:"MANTLE_REF_INVALID",severity:"error",path:`${path}/schema`,value:ref2.schema,expected:"the metadata.name of an existing Schema",candidates:[...schemasByName.keys()],suggestion:bestMatch(ref2.schema,[...schemasByName.keys()]),message:`${kind} '${name4}' field '${field}' references unknown Schema '${ref2.schema}'.`}));continue}let keyFields=entryKeyFields(target2);keyFields.includes(ref2.field)||out.push(validateDiagnostic({code:"MANTLE_REF_INVALID",severity:"error",path:`${path}/field`,value:ref2.field,expected:`one of ${keyFields.join(", ")}`,candidates:keyFields,message:`${kind} '${name4}' field '${field}' references '${ref2.schema}.${ref2.field}', which does not identify one entry; use id or a single-field unique index.`}))}return out}function entryKeyFields(schema){let unique=checkSchemaIndexes(schema).declarations.filter(declaration=>declaration.unique&&declaration.fields.length===1).map(declaration=>declaration.fields[0].name);return["id",...new Set(unique)]}function pointerSegment(value2){return value2.replaceAll("~","~0").replaceAll("/","~1")}function byName(arr){let m=new Map;for(let x of arr)m.set(x.metadata.name,x);return m}function checkSchemaReservedWireNames(schemas,filePaths){let out=[];for(let schema of schemas){let properties=schema.spec.schema.properties??{};for(let reserved2 of RESERVED_PROCEDURE_INPUT_NAMES)!(reserved2 in properties)||properties[reserved2]===void 0||out.push(validateDiagnostic({code:"INVALID_MANIFEST_ENVELOPE",severity:"error",path:manifestPath("Schema",schema.metadata.name,`/spec/schema/properties/${reserved2}`,filePaths),value:reserved2,expected:`Schema data properties that do not collide with reserved Procedure input names (${RESERVED_PROCEDURE_INPUT_NAMES.join(", ")}). New reserved names need an ADR.`,message:`Schema '${schema.metadata.name}' must not declare reserved Procedure input name '${reserved2}' as a data property (ADR-0022). New reserved names need an ADR.`}))}return out}function checkCaseCollisions(schemas,programs,filePaths){let out=[],collide=(names,report)=>{let first=new Map;for(let n of names){let seen=first.get(n.toLowerCase());seen===void 0?first.set(n.toLowerCase(),n):seen!==n&&report(n,seen)}};collide(schemas.map(s=>s.metadata.name),(name4,other)=>out.push(validateDiagnostic({code:"SCHEMA_NAME_CASE_COLLISION",severity:"error",path:manifestPath("Schema",name4,"/metadata/name",filePaths),value:name4,message:`Schema '${name4}' and Schema '${other}' differ only by case; SQL names them the same table. Rename one.`})));for(let s of schemas)collide(Object.keys(s.spec.schema.properties??{}),(name4,other)=>out.push(validateDiagnostic({code:"FIELD_NAME_CASE_COLLISION",severity:"error",path:manifestPath("Schema",s.metadata.name,`/spec/schema/properties/${pointerSegment(name4)}`,filePaths),value:name4,message:`Schema '${s.metadata.name}' declares '${name4}' and '${other}', which differ only by case; SQL names them the same column. Rename one.`})));for(let m of programs.filter(p=>p.kind==="View"||"sql"in p.spec.handler))collide(Object.keys(m.spec.input?.properties??{}),(name4,other)=>out.push(validateDiagnostic({code:"FIELD_NAME_CASE_COLLISION",severity:"error",path:manifestPath(m.kind,m.metadata.name,`/spec/input/properties/${pointerSegment(name4)}`,filePaths),value:name4,message:`${m.kind} '${m.metadata.name}' declares the inputs '${name4}' and '${other}', which differ only by case; SQL names them the same input. Rename one.`})));return out}function checkReaderNames(schemas,filePaths){return readerNameProblems(schemas.map(s=>s.metadata.name)).map(p=>validateDiagnostic({code:"SCHEMA_READER_NAME_COLLISION",severity:"error",path:manifestPath("Schema",p.name,"/metadata/name",filePaths),value:p.name,message:p.message}))}function checkDuplicates(kind,arr,filePaths){let counts=new Map;for(let m of arr)counts.set(m.metadata.name,(counts.get(m.metadata.name)??0)+1);let seenIndex=new Map,out=[];for(let m of arr){let total=counts.get(m.metadata.name)??0;if(total<2)continue;let ordinal=(seenIndex.get(m.metadata.name)??0)+1;seenIndex.set(m.metadata.name,ordinal),out.push(validateDiagnostic({code:"DUPLICATE_NAME",severity:"error",path:manifestPath(kind,m.metadata.name,"/metadata/name",filePaths,ordinal),value:m.metadata.name,expected:`metadata.name unique within kind ${kind}`,message:`${kind} manifest '${m.metadata.name}' is duplicated (occurrence ${ordinal} of ${total}).`}))}return out}function linkManifestSet(parsed){let manifests=parsed.entries.map(entry=>entry.manifest),filePaths=sourceFilePaths(parsed.entries),graph=validateManifestGraph(manifests,filePaths),diagnostics=graph.diagnostics.map(diagnostic=>attachSource(diagnostic,parsed.entries));if(diagnostics.some(diagnostic=>diagnostic.severity==="error"))return{ok:!1,diagnostics};let entriesByManifest=new Map(parsed.entries.map(entry=>[entry.manifest,entry])),schemasByName=new Map(graph.schemas.map(manifest=>[manifest.metadata.name,manifest])),proceduresByName=new Map(graph.procedures.map(manifest=>[manifest.metadata.name,manifest])),resolve=manifest=>{let entry=entriesByManifest.get(manifest);if(!entry)throw new Error(`linked manifest '${manifest.kind}/${manifest.metadata.name}' lost its source`);return Object.freeze({manifest,source:entry.source})},resolveSchema=name4=>resolve(schemasByName.get(name4)),resolveProcedure=name4=>resolve(proceduresByName.get(name4)),schemas=graph.schemas.map(manifest=>Object.freeze({...resolve(manifest),...manifest.spec.translates?{translationParent:resolveSchema(manifest.spec.translates.parent)}:{}})),views=graph.views.map(manifest=>Object.freeze({...resolve(manifest),...manifest.spec.requires?.guard?{guard:resolveProcedure(manifest.spec.requires.guard.procedure)}:{}})),procedures=graph.procedures.map(manifest=>Object.freeze({...resolve(manifest),...typeof manifest.spec.uiSchema?.collectionAction=="string"?{collectionActionSchema:resolveSchema(manifest.spec.uiSchema.collectionAction)}:{},...manifest.spec.requires?.guard?{guard:resolveProcedure(manifest.spec.requires.guard.procedure)}:{}})),triggers=graph.triggers.map(manifest=>Object.freeze({...resolve(manifest),target:resolveProcedure(manifest.spec.target.procedure),...manifest.spec.source.kind==="lifecycle"?{lifecycleSchema:resolveSchema(manifest.spec.source.schema)}:{}}));return{ok:!0,value:Object.freeze({schemas:Object.freeze(schemas),views:Object.freeze(views),procedures:Object.freeze(procedures),triggers:Object.freeze(triggers)}),diagnostics}}function sourceFilePaths(entries){let paths=new Map;for(let entry of entries){let key=`${entry.manifest.kind}/${entry.manifest.metadata.name}`,location={file:entry.source.sourceId,docIndex:entry.source.documentIndex},list=paths.get(key);list?list.push(location):paths.set(key,[location])}return paths}function attachSource(diagnostic,entries){let match=entries.map(entry=>({entry,prefix:`${entry.source.sourceId}#/${entry.source.documentIndex}`})).filter(({prefix})=>diagnostic.path.startsWith(prefix)).sort((a,b)=>b.prefix.length-a.prefix.length)[0];if(!match)return diagnostic;let path=diagnostic.path.slice(match.prefix.length)||"/";return{...diagnostic,path,source:sourceLocationAt(match.entry,path)}}var compile_exports={};__export(compile_exports,{accepts:()=>validateProgram2,name:()=>name2,version:()=>version});var KEYS_SRC={SelectStmt:"targetList fromClause whereClause groupClause havingClause sortClause limitCount distinctClause valuesLists limitOption op withClause",InsertStmt:"relation cols selectStmt onConflictClause returningClause override",UpdateStmt:"relation targetList whereClause returningClause",DeleteStmt:"relation whereClause returningClause",WithClause:"ctes",CommonTableExpr:"ctename ctequery aliascolnames ctematerialized",ReturningClause:"exprs",ResTarget:"name val",ColumnRef:"fields",String:"sval",A_Star:"",A_Const:"ival fval sval boolval isnull",A_Expr:"kind name lexpr rexpr",BoolExpr:"boolop args",NullTest:"arg nulltesttype",CaseExpr:"arg args defresult",CaseWhen:"expr result",CoalesceExpr:"args",TypeCast:"arg typeName",TypeName:"names typemod typmods",FuncCall:"funcname args agg_star agg_distinct over funcformat",WindowDef:"partitionClause orderClause frameOptions",SubLink:"subLinkType testexpr subselect operName",SortBy:"node sortby_dir sortby_nulls",RangeVar:"relname alias inh relpersistence mantle",Alias:"aliasname",RangeSubselect:"subquery alias",RangeFunction:"functions alias",JoinExpr:"jointype larg rarg quals",List:"items",OnConflictClause:"action infer targetList whereClause",InferClause:"indexElems",IndexElem:"name ordering nulls_ordering"},KEYS=Object.fromEntries(Object.entries(KEYS_SRC).map(([k,v])=>[k,new Set(v.split(" ").filter(Boolean))])),EXPR="ColumnRef A_Const A_Expr BoolExpr NullTest CaseExpr CoalesceExpr TypeCast FuncCall SubLink MinMaxExpr",FROM="RangeVar RangeSubselect RangeFunction JoinExpr",SLOTS_SRC={"SelectStmt.targetList":"ResTarget","SelectStmt.fromClause":FROM,"SelectStmt.whereClause":EXPR,"SelectStmt.havingClause":EXPR,"SelectStmt.groupClause":EXPR,"SelectStmt.sortClause":"SortBy","SelectStmt.limitCount":EXPR,"SelectStmt.distinctClause":EXPR,"SelectStmt.valuesLists":"List","SelectStmt>List.items":EXPR,"InsertStmt.cols":"ResTarget","InsertStmt.selectStmt":"SelectStmt","UpdateStmt.targetList":"ResTarget","UpdateStmt.whereClause":EXPR,"DeleteStmt.whereClause":EXPR,"ReturningClause.exprs":"ResTarget","ResTarget.val":EXPR,"ColumnRef.fields":"String A_Star","A_Expr.name":"String","A_Expr.lexpr":EXPR,"A_Expr.rexpr":`${EXPR} List`,"A_Expr>List.items":EXPR,"BoolExpr.args":EXPR,"NullTest.arg":EXPR,"CaseExpr.arg":EXPR,"CaseExpr.args":"CaseWhen","CaseExpr.defresult":EXPR,"CaseWhen.expr":EXPR,"CaseWhen.result":EXPR,"CoalesceExpr.args":EXPR,"TypeCast.arg":EXPR,"TypeName.names":"String","TypeName.typmods":"A_Const","FuncCall.funcname":"String","FuncCall.args":EXPR,"FuncCall.agg_filter":EXPR,"FuncCall.agg_order":"SortBy","WindowDef.partitionClause":EXPR,"WindowDef.orderClause":"SortBy","WindowDef.startOffset":EXPR,"WindowDef.endOffset":EXPR,"SubLink.testexpr":EXPR,"SubLink.subselect":"SelectStmt","SubLink.operName":"String","SortBy.node":EXPR,"RangeSubselect.subquery":"SelectStmt","RangeFunction.functions":"List","RangeFunction>List.items":"FuncCall","Alias.colnames":"String","JoinExpr.larg":FROM,"JoinExpr.rarg":FROM,"JoinExpr.quals":EXPR,"OnConflictClause.targetList":"ResTarget","OnConflictClause.whereClause":EXPR,"InferClause.indexElems":"IndexElem","WithClause.ctes":"CommonTableExpr","CommonTableExpr.ctequery":"SelectStmt","CommonTableExpr.aliascolnames":"String","MinMaxExpr.args":EXPR},SLOTS=new Map(Object.entries(SLOTS_SRC).map(([k,v])=>[k,new Set(v.split(" "))])),BARE={alias:"Alias",typeName:"TypeName",infer:"InferClause",returningClause:"ReturningClause",relation:"RangeVar",over:"WindowDef",onConflictClause:"OnConflictClause",withClause:"WithClause","SelectStmt.larg":"SelectStmt","SelectStmt.rarg":"SelectStmt"},ENUM={"SelectStmt.op":["SETOP_NONE"],"SelectStmt.limitOption":["LIMIT_OPTION_DEFAULT","LIMIT_OPTION_COUNT"],"InsertStmt.override":["OVERRIDING_NOT_SET"],"RangeVar.inh":[!0],"RangeVar.relpersistence":["p"],"RangeVar.mantle":["table","cte"],"A_Expr.kind":["AEXPR_OP","AEXPR_IN","AEXPR_LIKE","AEXPR_BETWEEN","AEXPR_NOT_BETWEEN","AEXPR_DISTINCT","AEXPR_NOT_DISTINCT","AEXPR_NULLIF"],"BoolExpr.boolop":["AND_EXPR","OR_EXPR","NOT_EXPR"],"NullTest.nulltesttype":["IS_NULL","IS_NOT_NULL"],"SubLink.subLinkType":["EXISTS_SUBLINK","EXPR_SUBLINK","ANY_SUBLINK"],"JoinExpr.jointype":["JOIN_INNER","JOIN_LEFT"],"SortBy.sortby_dir":["SORTBY_DEFAULT","SORTBY_ASC","SORTBY_DESC"],"SortBy.sortby_nulls":["SORTBY_NULLS_DEFAULT","SORTBY_NULLS_FIRST","SORTBY_NULLS_LAST"],"CommonTableExpr.ctematerialized":["CTEMaterializeDefault"],"FuncCall.funcformat":["COERCE_EXPLICIT_CALL","COERCE_SQL_SYNTAX"],"WindowDef.frameOptions":[1058],"OnConflictClause.action":["ONCONFLICT_NOTHING","ONCONFLICT_UPDATE"],"TypeName.typemod":[-1],"IndexElem.ordering":["SORTBY_DEFAULT"],"IndexElem.nulls_ordering":["SORTBY_NULLS_DEFAULT"]},OPS=new Set(["=","<>","!=","<",">","<=",">=","+","-","*","/","%","||","->>"]),FUNCS=new Set(["count","sum","min","max","avg","json_group_array","json_group_object","row_number","rank","lower","upper","length","abs","round","substr","replace","btrim","ltrim","rtrim","instr","typeof","hex","json_extract","json_set","json_insert","json_remove","json_array_length","now","auth.uid","date_trunc","extract","like_escape","mantle.search","mantle.search_rank","mantle.near","mantle.distance"]),WINDOW=new Set(["row_number","rank","sum","count"]),WINDOW_ONLY=new Set(["row_number","rank","dense_rank","lag","lead","first_value","last_value"]),AGG=new Set(["count","sum","min","max","avg","json_group_array","json_group_object"]),TRUNC_UNITS=new Set(["hour","day","week","month","year"]),EXTRACT_FIELDS=new Set(["year","month","day","dow","hour"]),CAST_TYPES=new Set(["text","int4","int8","float8","bool","timestamptz","date","numeric","interval"]),MAX_RADIUS_M=5e4,MAX_NEAR_K=100,MAX_NODES=2e3,BASE_PROFILE={name:"base",keys:KEYS,enums:ENUM,ops:OPS,funcs:FUNCS,window:WINDOW,agg:AGG,trunc:TRUNC_UNITS,extract:EXTRACT_FIELDS,casts:CAST_TYPES,fromFuncs:new Set(["json_each"])},MORE_KEYS={SelectStmt:"withClause larg rarg all",WithClause:"ctes recursive",CommonTableExpr:"ctename ctequery aliascolnames ctematerialized",RangeSubselect:"lateral",RangeFunction:"ordinality",Alias:"colnames",FuncCall:"agg_filter agg_order",WindowDef:"startOffset endOffset",MinMaxExpr:"op args"},MORE_ENUM={"SelectStmt.op":["SETOP_UNION","SETOP_INTERSECT","SETOP_EXCEPT"],"A_Expr.kind":["AEXPR_ILIKE"],"CommonTableExpr.ctematerialized":["CTEMaterializeDefault","CTEMaterializeAlways","CTEMaterializeNever"],"MinMaxExpr.op":["IS_GREATEST","IS_LEAST"]},MORE_OPS=["->","#>","#>>","@>","<@","?","?|","?&","~","~*","!~","!~*","~~*","!~~*"],MORE_WINDOW=["avg","min","max","lag","lead","first_value","last_value","dense_rank"],MORE_AGG=["string_agg","jsonb_agg","jsonb_object_agg"],MORE_FUNCS=[...MORE_WINDOW,...MORE_AGG,"jsonb_build_object","jsonb_build_array","jsonb_strip_nulls","to_jsonb","jsonb_typeof","split_part","floor","ceil","sqrt","power","timezone"],FRAME_REFUSED=229384,union=(a,b)=>new Set([...a,...b]),REFERENCE_PROFILE={name:"reference",keys:Object.fromEntries([...new Set([...Object.keys(KEYS),...Object.keys(MORE_KEYS)])].map(k=>[k,union(KEYS[k]??[],(MORE_KEYS[k]??"").split(" ").filter(Boolean))])),enums:Object.fromEntries([...new Set([...Object.keys(ENUM),...Object.keys(MORE_ENUM)])].filter(k=>k!=="WindowDef.frameOptions").map(k=>[k,[...ENUM[k]??[],...MORE_ENUM[k]??[]]])),ops:union(OPS,MORE_OPS),funcs:union(FUNCS,MORE_FUNCS),window:union(WINDOW,MORE_WINDOW),agg:union(AGG,MORE_AGG),trunc:union(TRUNC_UNITS,["minute","quarter"]),extract:union(EXTRACT_FIELDS,["minute","quarter","week","isoyear","isodow","doy","epoch"]),casts:union(CAST_TYPES,["jsonb"]),fromFuncs:new Set(["jsonb_array_elements","jsonb_array_elements_text","jsonb_each","jsonb_each_text"])},PROFILES={base:BASE_PROFILE,reference:REFERENCE_PROFILE},SQLITE_ONLY_KEYWORDS=new Set(["add","alter","autoincrement","commit","delete","drop","escape","index","insert","nothing","raise","set","transaction","update"]),SYSTEM=new Set(["version","status","author_id","created_at","updated_at"]),sv=list=>list.map(n=>n.String?.sval??(n.A_Star?"*":no("SQL_UNSUPPORTED","a name part that is not an identifier"))).join("."),fname=n=>sv(n.funcname).replace(/^pg_catalog\./,"");function no(code,message2,offset,keyword){throw new SqlRefusal(code,message2,offset,keyword)}var KEYWORD={"SelectStmt.withClause":/\bWITH\b/i,"InsertStmt.withClause":/\bWITH\b/i,"UpdateStmt.withClause":/\bWITH\b/i,"DeleteStmt.withClause":/\bWITH\b/i,"SelectStmt.limitOffset":/\bOFFSET\b/i,"SelectStmt.lockingClause":/\bFOR\s+(NO\s+KEY\s+)?(UPDATE|SHARE|KEY\s+SHARE)\b/i,"SelectStmt.intoClause":/\bINTO\b/i,"SelectStmt.op":/\b(UNION|INTERSECT|EXCEPT)\b/i,"UpdateStmt.fromClause":/\bFROM\b/i,"DeleteStmt.usingClause":/\bUSING\b/i,"JoinExpr.jointype":/\b(RIGHT|FULL)\b/i,"JoinExpr.isNatural":/\bNATURAL\b/i,"JoinExpr.usingClause":/\bUSING\b/i,"WindowDef.frameOptions":/\b(ROWS|RANGE|GROUPS)\b/i,"A_Expr.kind":/\bILIKE\b/i,"InferClause.conname":/\bON\s+CONSTRAINT\b/i,"SelectStmt.distinctClause":/\bDISTINCT\s+ON\b/i,GroupingSet:/\bGROUPING\s+SETS\b/i};function firstLoc(v){if(!(!v||typeof v!="object")){if(typeof v.location=="number"&&v.location>=0)return v.location;for(let c of Array.isArray(v)?v:Object.values(v)){let l=firstLoc(c);if(l!==void 0)return l}}}function validateProgram(stmts,ctx,locs=[],profile=BASE_PROFILE){program(stmts,{...ctx,p:profile,scope:[]},locs)}function program(stmts,ctx,locs){(!Array.isArray(stmts)||!stmts.length)&&no("SQL_SHAPE","an empty program"),ctx.kind==="view"&&(stmts.length!==1||!stmts[0].SelectStmt)&&no("SQL_SHAPE","a View is exactly one SELECT",locs[1]),ctx={...ctx,known:knownColumns(stmts),fnCols:rowSourceColumns(stmts),cols:ctx.columns??schemaColumns(ctx.schemas)};let w={ctx,budget:{n:0}};stmts.forEach((s,i)=>{let t=Object.keys(s)[0]??"",at=locs[i]??firstLoc(s);["SelectStmt","InsertStmt","UpdateStmt","DeleteStmt"].includes(t)||no("SQL_UNSUPPORTED",`statement ${t} is refused`,at),t==="SelectStmt"&&ctx.kind!=="view"&&no("SQL_SHAPE","a Procedure statement is a write",at),t!=="SelectStmt"&&ctx.kind==="view"&&no("SQL_SHAPE","a View is one SELECT",at),walk(t,s[t],w,[t],at)}),ctx.public&&publishedJoin(stmts,ctx)}function*find(v,key){if(!(!v||typeof v!="object"))for(let[k,c]of Object.entries(v))k===key&&(yield c),yield*find(c,key)}function schemaColumns(schemas){let known=new Set,scopes=new Set,types=new Map;for(let s of Object.values(schemas)){s.publishing&&(known.add("published_at"),types.set("published_at","timestamptz")),typeof s.scope=="string"&&scopes.add(s.scope.toLowerCase());for(let[f,t]of Object.entries(s.fields))(t==="geo"?[f,`${f}_lat`,`${f}_lng`]:[f]).forEach(c=>known.add(c)),types.set(f,types.has(f)&&types.get(f)!==t?null:t)}return{known,scopes,types:new Map([...types].filter(e=>e[1]!==null))}}function rowSourceColumns(stmts){let out=new Map;for(let r of find(stmts,"RangeFunction")){let a=r.alias;a?.colnames?.length&&out.set(String(a.aliasname).toLowerCase(),new Set(a.colnames.map(c=>String(c.String?.sval).toLowerCase())))}return out}function knownColumns(stmts){let known=new Set(["id","key","value","type","atom","parent","fullkey","path",...SYSTEM]);for(let r of find(stmts,"ResTarget"))r.name&&known.add(String(r.name).toLowerCase());for(let r of find(stmts,"RangeVar"))[r.relname,r.alias?.aliasname].forEach(a=>a&&known.add(a.toLowerCase()));for(let cols of rowSourceColumns(stmts).values())cols.forEach(c=>known.add(c));for(let c of find(stmts,"CommonTableExpr"))[c.ctename,...(c.aliascolnames??[]).map(x=>x.String?.sval)].forEach(a=>a&&known.add(String(a).toLowerCase()));return known}function publishedJoin(stmts,ctx){let rels=[...find(stmts,"RangeVar")].filter(r=>r.mantle!=="cte").map(r=>({alias:(r.alias?.aliasname??r.relname).toLowerCase(),publishing:!!ctx.schemas[r.relname.toLowerCase()]?.publishing}));if(!rels.some(r=>r.publishing))return;let ons=[...find(stmts,"JoinExpr")].map(j=>new Set([...find(j.quals,"ColumnRef")].filter(c=>c.fields.length===2).map(c=>c.fields[0].String.sval.toLowerCase())));for(let r of rels)!r.publishing&&!ons.some(o=>o.has(r.alias)&&rels.some(p=>p.publishing&&o.has(p.alias)))&&no("SQL_RELATION",`${r.alias} has no published state: a public View must join it to a publishing Schema in a JOIN ... ON`)}function shape(type,node,w,here){let keys=w.ctx.p.keys[type]??no("SQL_UNSUPPORTED",`${type} is not in the subset`,here,KEYWORD[type]);for(let[k,v]of Object.entries(node)){if(k==="location"||k==="rexpr_list_start"||k==="rexpr_list_end")continue;keys.has(k)||no("SQL_UNSUPPORTED",`${type}.${k} is not in the subset`,firstLoc(v)??here,KEYWORD[`${type}.${k}`]);let e=w.ctx.p.enums[`${type}.${k}`];e&&!e.includes(v)&&no("SQL_UNSUPPORTED",`${type}.${k} = ${JSON.stringify(v)} is refused`,firstLoc(node)??here,KEYWORD[`${type}.${k}`])}type==="String"&&node.sval!==void 0&&typeof node.sval!="string"&&no("SQL_SHAPE","a name is a string",here),type==="A_Const"&&!constant(node)&&no("SQL_UNSUPPORTED","a literal is one integer, numeric, string, boolean or NULL",firstLoc(node)??here)}function constant(node){let own=Object.keys(node).filter(k2=>k2!=="location");if(own.length!==1)return!1;let[k]=own,v=node[k],only=(key,ok)=>!!v&&typeof v=="object"&&Object.keys(v).every(x=>x===key)&&(!(key in v)||ok(v[key]));switch(k){case"ival":return only("ival",Number.isSafeInteger);case"fval":return only("fval",x=>typeof x=="string"&&x.length<=64&&/^-?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][-+]?\d+)?$/.test(x)&&(/[.eE]/.test(x)||Math.abs(Number(x))>=2**31));case"sval":return only("sval",x=>typeof x=="string");case"boolval":return only("boolval",x=>typeof x=="boolean");case"isnull":return v===!0;default:return!1}}function withScope(w,names,f){w.ctx.scope.push(new Set(names));try{f()}finally{w.ctx.scope.pop()}}function walk(type,node,w,path,loc){++w.budget.n>MAX_NODES&&no("SQL_SHAPE","statement too large",loc);let here=typeof node.location=="number"?node.location:loc;shape(type,node,w,here);try{check[type]?.(node,w.ctx,path,here)}catch(e){throw e instanceof SqlRefusal&&e.offset===void 0&&!e.keyword&&(e.offset=here),e}let wc=type==="SelectStmt"?node.withClause:void 0,names=(wc?.ctes??[]).map(x=>String(x.CommonTableExpr?.ctename));wc&&(shape("WithClause",wc,w,here),wc.recursive!==void 0&&typeof wc.recursive!="boolean"&&no("SQL_UNSUPPORTED","WithClause.recursive is a flag",here),(wc.ctes??[]).forEach((x,j)=>withScope(w,wc.recursive?names:names.slice(0,j),()=>child(x,w,[...path,"WithClause"],"ctes",here))));let rels=type==="SelectStmt"||type==="UpdateStmt"||type==="DeleteStmt"?relationsOf(node):void 0;rels&&(w.ctx.rels??=[]).push(rels);try{withScope(w,names,()=>{for(let[k,v]of Object.entries(node)){if(type==="A_Const"||k==="location"||k==="rexpr_list_start"||k==="rexpr_list_end"||wc&&k==="withClause")continue;let bare=BARE[`${type}.${k}`]??BARE[k];if(!(bare||SLOTS.has(`${type}.${k}`)||type==="List"&&k==="items")){v!==null&&typeof v=="object"&&no("SQL_UNSUPPORTED",`${type}.${k} is a value, not a node`,here);continue}(v===null||typeof v!="object")&&no("SQL_UNSUPPORTED",`${type}.${k} holds a node`,here),bare?walk(bare,v,w,[...path,bare],here):Array.isArray(v)?v.forEach(c=>child(c,w,path,k,here)):child(v,w,path,k,here)}})}finally{rels&&w.ctx.rels.pop()}}function relationsOf(node){let out=new Map,add=n=>{if(n?.JoinExpr)return add(n.JoinExpr.larg),add(n.JoinExpr.rarg);let v=n?.RangeVar??n;v?.mantle==="table"&&out.set(String(v.alias?.aliasname??v.relname).toLowerCase(),String(v.relname).toLowerCase())};for(let f of node.fromClause??[])add(f);return add(node.relation),out}function child(c,w,path,k,loc){let keys=Object.keys(c);if(!keys.length){if(k==="distinctClause"||k==="items"&&path.at(-2)==="RangeFunction")return;no("SQL_UNSUPPORTED",`an empty node in ${k}`,loc)}(keys.length!==1||c[keys[0]]===null||typeof c[keys[0]]!="object")&&no("SQL_UNSUPPORTED","a malformed node",loc);let parent=path.at(-1),allowed=SLOTS.get(parent==="List"?`${path.at(-2)}>List.${k}`:`${parent}.${k}`);w.ctx.p.keys[keys[0]]&&!allowed?.has(keys[0])&&no("SQL_SHAPE",`${keys[0]} cannot stand in ${parent}.${k}`,loc),walk(keys[0],c[keys[0]],w,[...path,keys[0]],loc)}var castType=typeName=>{let names=(typeName?.names??[]).map(n=>n?.String?.sval);return names.every(x=>typeof x=="string"&&/^[a-z_][a-z0-9_]*$/.test(x))&&(names.length===1||names.length===2&&names[0]==="pg_catalog")||no("SQL_TYPE",`a cast names one type: ${JSON.stringify(names)}`),names.at(-1)},isConst=n=>!!n?.A_Const,isInputRef=n=>n?.ColumnRef?.fields?.length===2&&n.ColumnRef.fields[0].String?.sval==="input",check={RangeVar:(n,ctx,_p,at)=>{n.alias?.colnames&&no("SQL_SHAPE",`a column list after ${n.alias.aliasname} is only for a row source: Schema columns keep their names`,at),(typeof n.relname!="string"||n.relname!==n.relname.toLowerCase())&&no("SQL_RELATION",`${JSON.stringify(n.relname)}: a relation is named in lower case`,at);let name4=n.relname;(name4.startsWith("_mantle")||name4==="input"||name4==="auth")&&no("SQL_RELATION",`${name4} is not a declared Schema`,at);let reference=ctx.p.name==="reference";if(n.alias&&["input","auth","excluded"].includes(n.alias.aliasname)&&no("SQL_RELATION",`${n.alias.aliasname} is a reserved alias`,at),!reference)for(let ident2 of[name4,n.alias?.aliasname])ident2&&SQLITE_ONLY_KEYWORDS.has(ident2)&&no("SQL_UNSUPPORTED",`${ident2} is an SQLite keyword: the printer would not quote it`,at);if(n.mantle==="cte"){if(ctx.scope.some(s=>s.has(n.relname)))return;no("SQL_RELATION",`${name4}: a cte reference is not defined in scope`,at)}ctx.schemas[name4]||no("SQL_RELATION",`${name4} is not a declared Schema`,at),n.mantle!==void 0&&n.mantle!=="table"&&no("SQL_RELATION",`${name4}: relation not name-resolved`,at)},ColumnRef:(n,ctx,_p,at)=>{let f=sv(n.fields),last=f.split(".").pop().toLowerCase();n.fields.length>2&&no("SQL_COLUMN",`${f}: at most alias.column`,at),["rowid","oid","_rowid_","_rid"].includes(last)&&no("SQL_COLUMN",`${last} is not addressable`,at),ctx.cols.scopes.has(last)&&no("SQL_COLUMN",`${f}: the scope column is not addressable`,at),f.startsWith("input.")&&!(last in ctx.inputs)&&no("SQL_COLUMN",`${f} is not a declared input`,at),ctx.p.name==="base"&&SQLITE_ONLY_KEYWORDS.has(last)&&no("SQL_UNSUPPORTED",`${last} is an SQLite keyword: the printer would not quote it`,at);let own=n.fields.length===2?ctx.fnCols.get(String(n.fields[0].String?.sval).toLowerCase()):void 0;own&&last!=="*"&&!own.has(last)&&no("SQL_COLUMN",`${f}: the row source ${n.fields[0].String.sval} names its columns (${[...own].join(", ")})`,at),last!=="*"&&!f.startsWith("input.")&&!ctx.known.has(last)&&!ctx.cols.known.has(last)&&no("SQL_COLUMN",`${f} is not a declared field`,at)},FuncCall:(n,ctx,path,at)=>{let f=fname(n);if(ctx.p.fromFuncs.has(f)){(path.at(-2)!=="List"||path.at(-3)!=="RangeFunction")&&no("SQL_FUNCTION",`${f} is only allowed in FROM`,at);return}ctx.p.funcs.has(f)||no("SQL_FUNCTION",`function ${f} is not on the allowlist`,at),n.over&&(ctx.kind!=="view"||!ctx.p.window.has(f))&&no("SQL_FUNCTION",`window function ${f} is refused here`,at),!n.over&&WINDOW_ONLY.has(f)&&no("SQL_FUNCTION",`${f}() is a window function: it needs OVER (...)`,at),(f==="lag"||f==="lead")&&n.args?.[1]&&n.args[1].A_Const?.ival===void 0&&no("SQL_FUNCTION",`${f}'s offset is an integer literal`,at),(n.agg_filter||n.agg_order)&&!ctx.p.agg.has(f)&&no("SQL_FUNCTION",`FILTER and ORDER BY belong to an aggregate, and ${f} is not one`,at);let args=n.args??[],str2=a=>a?.A_Const?.sval?.sval;switch(f){case"like_escape":(path.at(-2)!=="A_Expr"||args.length!==2)&&no("SQL_FUNCTION","like_escape is only the ESCAPE of a LIKE",at);break;case"date_trunc":(args.length!==2||!ctx.p.trunc.has(str2(args[0])??""))&&no("SQL_TYPE",`date_trunc takes ${[...ctx.p.trunc].join(", ")} as a literal first argument`,at);break;case"extract":(args.length!==2||!ctx.p.extract.has(str2(args[0])??""))&&no("SQL_TYPE",`extract takes ${[...ctx.p.extract].join(", ")}`,at);break;case"now":case"auth.uid":args.length&&no("SQL_FUNCTION",`${f}() takes no arguments`,at);break;case"mantle.search":case"mantle.search_rank":(args.length!==(f==="mantle.search"?2:1)||args[0]?.ColumnRef?.fields?.length!==1)&&no("SQL_FUNCTION",f==="mantle.search"?"mantle.search(<alias>, <query>)":"mantle.search_rank(<alias>)",at);break;case"mantle.near":case"mantle.distance":{let want=f==="mantle.near"?4:3,fld=args[0]?.ColumnRef?.fields;(args.length!==want||fld?.length!==2)&&no("SQL_FUNCTION",`${f}(<alias>.<geo field>, lat, lng${f==="mantle.near"?", meters":""})`,at);for(let a of args.slice(1,3))!isConst(a)&&!isInputRef(a)&&no("SQL_FUNCTION",`${f}: latitude and longitude are a literal or input.<name>`,at);if(f==="mantle.near"){let m=args[3]?.A_Const?.ival?.ival??args[3]?.A_Const?.fval?.fval;m===void 0&&no("SQL_FUNCTION","mantle.near() needs a literal radius in meters",at),(Number(m)>MAX_RADIUS_M||Number(m)<=0)&&no("SQL_FUNCTION",`mantle.near() radius is at most ${MAX_RADIUS_M} m`,at)}break}}ctx.p.agg.has(f)&&n.args?.length===0&&!n.agg_star&&no("SQL_FUNCTION",`${f} needs an argument`,at),n.agg_star&&(f!=="count"||args.length)&&no("SQL_FUNCTION",`${f}(*) is refused: only count(*)`,at),n.agg_distinct&&(!ctx.p.agg.has(f)||args.length!==1||n.over)&&no("SQL_FUNCTION","DISTINCT is one argument of an aggregate, outside a window",at)},A_Expr:(n,ctx,_p,at)=>{let op2=sv(n.name),items=n.rexpr?.List?.items,range=n.kind==="AEXPR_BETWEEN"||n.kind==="AEXPR_NOT_BETWEEN";(!n.rexpr||!n.lexpr&&!(n.kind==="AEXPR_OP"&&(op2==="-"||op2==="+"))||range&&items?.length!==2||n.kind==="AEXPR_IN"&&!items?.length||!range&&n.kind!=="AEXPR_IN"&&n.rexpr.List)&&no("SQL_SHAPE",`a malformed ${op2} expression`,at),n.kind==="AEXPR_OP"&&!n.lexpr&&(op2==="-"||op2==="+")&&(n.rexpr?.A_Const?.ival!==void 0||n.rexpr?.A_Const?.fval!==void 0)&&no("SQL_SHAPE",`a sign over a number is that number: write ${op2==="-"?"the negative constant":"the constant"}`,at),ctx.p.name==="base"&&bareLiteralCompare(n,ctx,at),jsonCompare(n,ctx,at),n.kind==="AEXPR_OP"&&!ctx.p.ops.has(op2)&&no("SQL_UNSUPPORTED",`operator ${op2} is refused`,at),n.kind==="AEXPR_IN"&&!["=","<>"].includes(op2)&&no("SQL_UNSUPPORTED","a bad IN",at),n.kind==="AEXPR_LIKE"&&!["~~","!~~"].includes(op2)&&no("SQL_UNSUPPORTED","ILIKE and regular expressions are refused",at,/\bILIKE\b/i),n.kind==="AEXPR_ILIKE"&&!["~~*","!~~*"].includes(op2)&&no("SQL_UNSUPPORTED","a bad ILIKE",at);let esc=x=>!!x?.FuncCall&&fname(x.FuncCall)==="like_escape";(esc(n.lexpr)||esc(n.rexpr)&&n.kind!=="AEXPR_LIKE")&&no("SQL_FUNCTION","like_escape is only the ESCAPE of a LIKE",at)},TypeCast:(n,ctx,_p,at)=>{let t=castType(n.typeName);ctx.p.casts.has(t)||no("SQL_TYPE",`CAST to ${t} is refused`,at);let lit3=n.arg?.A_Const,base=ctx.p.name==="base";base&&(t==="int4"||t==="int8")&&!(lit3?.ival||/^\s*-?\d+\s*$/.test(lit3?.sval?.sval??"x"))&&no("SQL_TYPE",`CAST to ${t} takes an integer literal: SQLite truncates toward zero where PostgreSQL rounds. Write round(x)`,at);let mods=n.typeName.typmods??[],typmod=mods[0]?.A_Const?.ival?.ival;if(mods.length&&t!=="numeric"&&!(t==="interval"&&mods.length===1&&intervalMicros(lit3?.sval?.sval??"x",typmod)%intervalMicros("1",typmod)===0)&&no("SQL_TYPE",`CAST to ${t} takes no type modifier here, or one that truncates nothing`,at),t==="interval"&&(lit3?.sval||no("SQL_TYPE","an interval is a literal such as interval '36 hours'",at),intervalMicros(lit3.sval.sval,n.typeName.typmods?.[0]?.A_Const?.ival?.ival)),base&&(t==="timestamptz"||t==="date")&&!lit3?.sval&&no("SQL_TYPE",`CAST to ${t} takes a literal (the compiler folds it to its integer encoding)`,at),t==="numeric"){let[p,s]=(n.typeName.typmods??[]).map(m=>m.A_Const?.ival?.ival??0);p===void 0&&no("SQL_TYPE","numeric needs (precision, scale)",at),parseNumeric(`numeric(${p}, ${s})`),base&&!lit3&&no("SQL_TYPE","CAST to numeric takes a literal: numeric columns are integer counts of the smallest unit",at)}},ResTarget:(n,ctx,_p,at)=>{ctx.p.name==="base"&&n.name&&SQLITE_ONLY_KEYWORDS.has(n.name)&&no("SQL_UNSUPPORTED",`${n.name} is an SQLite keyword: the printer would not quote it`,at)},SubLink:(n,_c,_p,at)=>{n.subLinkType==="ANY_SUBLINK"&&n.operName&&sv(n.operName)!=="="&&no("SQL_UNSUPPORTED","only IN (subquery)",at)},JoinExpr:(n,_c,_p,at)=>{n.quals||no("SQL_SHAPE","a JOIN needs ON",at,/\bCROSS\s+JOIN\b|\bJOIN\b/i)},RangeFunction:(n,ctx,_p,at)=>{let fs=n.functions,only=`only ${[...ctx.p.fromFuncs].map(x=>`${x}()`).join(", ")} ${ctx.p.fromFuncs.size>1?"are":"is"} allowed in FROM`,f=fs.length===1&&fs[0]?.List?.items?.length===2?sv(fs[0].List.items[0].FuncCall?.funcname??[]):void 0;(!f||!ctx.p.fromFuncs.has(f))&&no("SQL_FUNCTION",only,at),fs[0].List.items[0].FuncCall.args?.length!==1&&no("SQL_FUNCTION",`${f} takes one argument`,at)},RangeSubselect:(n,_c,_p,at)=>{n.alias?.colnames&&no("SQL_SHAPE",`a column list after ${n.alias.aliasname} is only for a row source: name the columns in the subquery`,at),n.alias||no("SQL_SHAPE","a subquery in FROM needs an alias",at)},CommonTableExpr:(n,ctx,_p,at)=>{n.ctequery?.SelectStmt||no("SQL_SHAPE","a CTE body is a SELECT: a write inside WITH is refused",at);for(let name4 of[n.ctename,...(n.aliascolnames??[]).map(c=>c?.String?.sval)])(typeof name4!="string"||!/^[a-z_][a-z0-9_]*$/.test(name4))&&no("SQL_SHAPE",`a CTE name is lower case, a plain identifier: ${JSON.stringify(name4)}`,at),ctx.p.name==="base"&&SQLITE_ONLY_KEYWORDS.has(name4)&&no("SQL_UNSUPPORTED",`${name4} is an SQLite keyword: the printer would not quote it`,at)},BoolExpr:(n,_c,_p,at)=>{let k=(n.args??[]).length;(n.boolop==="NOT_EXPR"?k!==1:k<1)&&no("SQL_SHAPE",`a malformed ${n.boolop}`,at)},WindowDef:(n,_c,_p,at)=>{n.frameOptions&FRAME_REFUSED&&no("SQL_UNSUPPORTED","GROUPS frames and EXCLUDE are refused",at,/\b(GROUPS|EXCLUDE)\b/i);for(let o of[n.startOffset,n.endOffset])o&&!(o.A_Const?.ival!==void 0||o.TypeCast?.arg?.A_Const?.sval&&castType(o.TypeCast.typeName)==="interval")&&no("SQL_SHAPE","a frame offset is a literal: an integer, or an interval such as interval '6 days'",at)},SelectStmt:(n,ctx,path,at)=>{let reference=ctx.p.name==="reference",top=ctx.kind==="view"&&path.length===1,distinctOn=!!n.distinctClause&&(n.distinctClause.length!==1||Object.keys(n.distinctClause[0]).length>0);if(n.op&&n.op!=="SETOP_NONE"&&top&&no("SQL_SHAPE","UNION, INTERSECT and EXCEPT go inside a WITH or a subquery: Core pages the View's own SELECT",at,/\b(UNION|INTERSECT|EXCEPT)\b/i),n.limitCount&&!n.sortClause&&no("SQL_SHAPE","LIMIT needs an ORDER BY",firstLoc(n.limitCount)??at),distinctOn&&(!reference||top)&&no(reference?"SQL_SHAPE":"SQL_UNSUPPORTED",reference?"DISTINCT ON goes inside a WITH or a subquery: Core pages the View's own SELECT":"DISTINCT ON is refused",at,/\bDISTINCT\s+ON\b/i),n.distinctClause&&!distinctOn&&n.sortClause&&no("SQL_SHAPE","DISTINCT with ORDER BY is refused: the appended id key would change what is distinct",at),n.valuesLists&&(path.at(-2)!=="InsertStmt"||n.valuesLists.length!==1)&&no("SQL_SHAPE","VALUES is one row, in INSERT only",firstLoc(n.valuesLists)??at),(n.fromClause??[]).slice(1).some(f=>!f.RangeFunction&&!(reference&&f.RangeSubselect?.lateral))&&no("SQL_SHAPE",reference?"a comma join is refused (except a row source over a column, and LATERAL)":"a comma join is refused (except json_each)",at),reference&&n.sortClause&&!n.groupClause){let rows=f=>f?.JoinExpr?[...rows(f.JoinExpr.larg),...rows(f.JoinExpr.rarg)]:f?[f]:[];for(let r of(n.fromClause??[]).flatMap(rows)){let fc=r.RangeFunction?.functions?.[0]?.List?.items?.[0]?.FuncCall;fc&&(!r.RangeFunction.alias||!r.RangeFunction.ordinality)&&no("SQL_SHAPE",`ordering a row source (${sv(fc.funcname)}) needs an alias and WITH ORDINALITY: write ${sv(fc.funcname)}(...) WITH ORDINALITY AS j(value, n)`,fc.location??at)}}if(JSON.stringify(n.sortClause??[]).includes('"distance"')){let k=n.limitCount?.A_Const?.ival?.ival;(k===void 0||k>MAX_NEAR_K)&&no("SQL_SHAPE",`a query ordered by mantle.distance() needs a literal LIMIT of at most ${MAX_NEAR_K}`,firstLoc(n.sortClause)??at)}},UpdateStmt:(n,ctx)=>writeList(n.targetList,ctx,n.relation,!1),InsertStmt:(n,ctx,_p,at)=>{writeList(n.cols??no("SQL_WRITE","INSERT needs a column list",at),ctx,n.relation,!0,n.selectStmt?.SelectStmt?.valuesLists?.[0]?.List?.items),n.onConflictClause?.action==="ONCONFLICT_UPDATE"&&writeList(n.onConflictClause.targetList,ctx,n.relation,!1)}},STORED_AS_NUMBER=new Set(["timestamptz","date","bool"]),SYSTEM_TIMES=new Set(["created_at","updated_at","published_at"]);function columnType(ctx,name4){return SYSTEM_TIMES.has(name4)?"timestamptz":ctx.cols.types.get(name4)}function bareLiteralCompare(n,ctx,at){if(!(n.kind==="AEXPR_OP"?["=","<>","!=","<",">","<=",">="].includes(sv(n.name)):["AEXPR_IN","AEXPR_BETWEEN","AEXPR_NOT_BETWEEN","AEXPR_DISTINCT","AEXPR_NOT_DISTINCT"].includes(n.kind)))return;let typeOf=x=>{let f=x?.ColumnRef?.fields,name4=f?.at(-1)?.String?.sval;return name4&&!(f.length===2&&f[0].String?.sval==="input")?columnType(ctx,String(name4).toLowerCase()):void 0},literals=x=>x?.List?x.List.items.flatMap(literals):x?.A_Const?.sval?[x.A_Const.sval.sval]:[];for(let[colSide,other]of[[n.lexpr,n.rexpr],[n.rexpr,n.lexpr]]){let type=typeOf(colSide);if(!type||!STORED_AS_NUMBER.has(type))continue;let text=literals(other)[0];text!==void 0&&no("SQL_TYPE",`'${text}' is text and the column is ${type}, which is stored as a number: ${type==="bool"?"write true or false":`write CAST('${text}' AS ${type})`}, or bind it as an input`,at)}}function jsonCompare(n,ctx,at){let compares=n.kind==="AEXPR_OP"?["=","<>","!=","<",">","<=",">="].includes(sv(n.name)):["AEXPR_IN","AEXPR_BETWEEN","AEXPR_NOT_BETWEEN","AEXPR_DISTINCT","AEXPR_NOT_DISTINCT"].includes(n.kind),rels=ctx.rels?.at(-1);if(!(!compares||!rels))for(let side of[n.lexpr,n.rexpr]){let f=side?.ColumnRef?.fields;if(!f||f.length>2||!f.every(x=>x.String))continue;let name4=String(f.at(-1).String.sval).toLowerCase(),schemas=f.length===2?[rels.get(String(f[0].String.sval).toLowerCase())].filter(s=>!!s):[...new Set(rels.values())].filter(s=>Object.hasOwn(ctx.schemas[s]?.fields??{},name4));schemas.length===1&&ctx.schemas[schemas[0]]?.fields[name4]==="json"&&no("SQL_TYPE",`${f.at(-1).String.sval} is json: compare a value read with ->> (and CAST), or declare the field with one scalar type`,at)}}function writeList(list,ctx,rel,insert2,values){let s=ctx.schemas[rel.relname.toLowerCase()];for(let[i,{ResTarget:r}]of list.entries()){let at=firstLoc(r)??firstLoc(rel),name4=String(r.name).toLowerCase(),scopedId=insert2&&name4==="id"&&s?.scope;(name4===s?.scope?.toLowerCase()||SYSTEM.has(name4)||name4==="published_at"||!insert2&&name4==="id"||scopedId)&&no("SQL_WRITE",`${r.name} is filled by Mantle and cannot be written${scopedId?" (a scoped Schema generates its ids)":""}`,at);let cols=Object.entries(s?.fields??{}).flatMap(([f,t])=>t==="geo"?[`${f}_lat`,`${f}_lng`]:[f]);name4!=="id"&&!cols.includes(name4)&&no("SQL_WRITE",`${rel.relname} has no field ${r.name}`,at);let type=s?.fields[name4],literal=(insert2?values?.[i]:r.val)?.A_Const?.sval?.sval;ctx.p.name==="base"&&literal!==void 0&&type&&!["text","json"].includes(type)&&!/^-?\d+(\.\d+)?$/.test(literal)&&no("SQL_TYPE",`'${literal}' is text and ${r.name} is ${type}: write CAST('${literal}' AS ${type==="integer"?"int8":type==="real"?"float8":type}), or bind it as an input`,at)}}function refusalToDiagnostic(e){return{code:e.code,message:e.message}}function validateIr(plan,ctx,profile=BASE_PROFILE){try{return plan?.grammar!==180004&&no("SQL_UNSUPPORTED",`plan was compiled with PostgreSQL grammar ${plan?.grammar}, this runtime reads ${180004}`),validateProgram(plan.stmts,ctx,[],profile),[]}catch(e){return e instanceof SqlRefusal?[refusalToDiagnostic(e)]:[{code:"SQL_UNSUPPORTED",message:`malformed IR: ${e instanceof Error?e.message:String(e)}`}]}}var POSTGRES_ONLY="needs the PostgreSQL dialect; D1 runs Mantle SQL's base subset (ADR-0037)";function postgresOnly(stmts,ctx){try{return validateProgram(stmts,ctx,[],PROFILES.reference),!0}catch{return!1}}function validateProgram2(stmts,ctx,locs=[]){try{validateProgram(stmts,ctx,locs,PROFILES.base)}catch(e){throw e instanceof SqlRefusal&&postgresOnly(stmts,ctx)&&(e.message=`${e.message}: ${POSTGRES_ONLY}`),e}}function validateIr2(plan,ctx){let d=validateIr(plan,ctx,PROFILES.base);return d.length&&plan?.grammar===180004&&Array.isArray(plan.stmts)&&postgresOnly(plan.stmts,ctx)?[{...d[0],message:`${d[0].message}: ${POSTGRES_ONLY}`}]:d}var name2="@aotter/mantle/d1",version="1";async function parsePgSql(sql4){let{parse}=await import("libpg-query"),tree;try{tree=await parse(sql4)}catch(e){let at=e?.sqlDetails?.cursorPosition;throw new SqlRefusal("SQL_SYNTAX",String(e?.message??e).replace(/^.*?:\s*/,""),typeof at=="number"?new TextEncoder().encode(sql4.slice(0,at)).byteLength:void 0)}let raw=tree.stmts;return{stmts:raw.map(s=>s.stmt),locations:raw.map(s=>s.stmt_location)}}var STATEMENTS=new Set(["SelectStmt","InsertStmt","UpdateStmt","DeleteStmt","MergeStmt"]),WRITES=new Set(["InsertStmt","UpdateStmt","DeleteStmt","MergeStmt"]),MANTLE_FUNCTIONS=new Set(["mantle.search","mantle.search_rank","mantle.near","mantle.distance","auth.uid","auth.hasrole","auth.user"]),OUTSIDE=/^(pg_(try_)?advisory_|pg_read_(binary_)?file$|pg_ls_|pg_stat_file$|pg_file_|lo_|dblink|pg_(cancel|terminate|signal)_backend$|pg_reload_conf$|pg_rotate_logfile$|pg_notify$|(set|next)val$|(query|table|cursor|schema|database)_to_xml|ts_stat$|ts_rewrite$)/,no2=(code,message2,at)=>{throw new SqlRefusal(code,message2,at)};function functionName(n){return n.funcname.map(x=>String(x.String?.sval).toLowerCase()).slice(-2).join(".").replace(/^pg_catalog\./,"")}function refuseForEveryDialect(stmts,ctx,locations){ctx.kind==="view"&&(stmts.length!==1||!stmts[0].SelectStmt)&&no2("SQL_SHAPE","a View is exactly one SELECT",locations[1]??locations[0]),stmts.forEach((stmt,i)=>{let type=Object.keys(stmt)[0];STATEMENTS.has(type)||no2("SQL_UNSUPPORTED",`statement ${type} is refused`,locations[i]),walk2(stmt,new Set,locations[i],ctx)})}function walk2(v,ctes,at,ctx){if(Array.isArray(v))return v.forEach(x=>walk2(x,ctes,at,ctx));if(!(!v||typeof v!="object"))for(let[k,c]of Object.entries(v)){if(!c||typeof c!="object"||Array.isArray(c)){walk2(c,ctes,at,ctx);continue}let n=c,here=typeof n.location=="number"?n.location:at;if(k==="RangeVar"||k==="relation")relation(n,ctes,here,ctx,k==="relation");else if(STATEMENTS.has(k)||(k==="larg"||k==="rarg")&&"op"in n){ctx.kind==="view"&&WRITES.has(k)&&no2("SQL_SHAPE","a View reads only: no write in a WITH",here),n.intoClause&&no2("SQL_UNSUPPORTED","SELECT ... INTO creates a table and is refused",here);let w=n.withClause,names=(w?.ctes??[]).map(x=>String(x.CommonTableExpr.ctename));(w?.ctes??[]).forEach((x,j)=>walk2(x.CommonTableExpr.ctequery,new Set([...ctes,...w.recursive?names:names.slice(0,j)]),here,ctx));let inner=new Set([...ctes,...names]);for(let[key,body]of Object.entries(n))key!=="withClause"&&walk2({[key]:body},inner,here,ctx);continue}else if(k==="ColumnRef"){let f=n.fields.map(x=>x.String?.sval);f.length===2&&f[0]==="input"&&!Object.hasOwn(ctx.inputs,String(f[1]))&&no2("SQL_COLUMN",`input.${f[1]} is not a declared input`,here)}else if(k==="FuncCall"){let f=functionName(n);/^(mantle|auth)\./.test(f)&&!MANTLE_FUNCTIONS.has(f)&&no2("SQL_FUNCTION",`${f} is not one of Mantle's functions`,here),OUTSIDE.test(f)&&no2("SQL_FUNCTION",`${f} changes session or server state, or reaches outside the database`,here);let setting=n.args?.[0]?.A_Const?.sval?.sval;(f==="set_config"||f==="current_setting")&&(typeof setting!="string"||setting.toLowerCase().startsWith("mantle."))&&no2("SQL_FUNCTION",`${f} of a mantle.* setting is refused`,here)}walk2(n,ctes,here,ctx)}}function relation(n,ctes,at,ctx,written){let name4=String(n.relname);if((n.schemaname||n.catalogname)&&no2("SQL_RELATION",`${n.schemaname??n.catalogname}.${name4}: a relation is a declared Schema, never schema-qualified`,at),ctes.has(name4)){n.mantle="cte";return}let view=Object.hasOwn(ctx.schemas,name4)?void 0:ctx.views?.[name4];if(view){written&&no2("SQL_WRITE",`${name4} is a View: a View is read, never written`,at),view.refusal&&no2("SQL_RELATION",view.refusal,at),n.mantle="view";return}Object.hasOwn(ctx.schemas,name4)||no2("SQL_RELATION",`${name4} is not a declared Schema`,at)}var functionName2=n=>n?.FuncCall?.funcname?.map(v=>v.String.sval).join(".");function registerUserField(fields,field,spec){let old=fields[field],enumKey=values=>values?JSON.stringify([...values].sort((a,b)=>String(a).localeCompare(String(b)))):null;if(old&&(old.type!==spec.type||old.enum&&spec.enum&&enumKey(old.enum)!==enumKey(spec.enum)))throw new SqlRefusal("USER_FIELD_CONFLICT",`'${field}' is bound by Schema scopes with conflicting column types or enums.`);let merged=old?.enum&&!spec.enum?old:spec;fields[field]=Object.freeze(old?.integer&&!merged.integer?{...merged,integer:!0}:merged)}var USER_REF_SCOPE_ONLY=`auth.user() belongs in a Schema scope or this target's restrict: { <schema>: "<column> IN auth.user('<field>')" }, never in SQL.`;function refuseUserReferences(node){if(Array.isArray(node)){node.forEach(refuseUserReferences);return}if(!node||typeof node!="object")return;let fn3=functionName2(node);if(fn3==="auth.role"||fn3==="auth.hasrole")throw new SqlRefusal("AUTH_ROLE_REMOVED",`${fn3==="auth.role"?"auth.role()":"auth.hasRole()"} is removed; decide per-target permission in the application's authorize(target, caller) seam.`,node.FuncCall.location);if(fn3==="auth.user")throw new SqlRefusal("USER_REF_SCOPE_ONLY",USER_REF_SCOPE_ONLY,node.FuncCall.location);Object.values(node).forEach(refuseUserReferences)}async function relationNames(sql4){let names=new Set,walk3=(v,scope=new Set)=>{if(Array.isArray(v))return v.forEach(x=>walk3(x,scope));if(!v||typeof v!="object")return;typeof v.relname=="string"&&!scope.has(v.relname)&&names.add(v.relname);let w=v.withClause;if(w){let declared=w.ctes.map(x=>x.CommonTableExpr.ctename);w.ctes.forEach((x,i)=>walk3(x.CommonTableExpr.ctequery,new Set([...scope,...w.recursive?declared:declared.slice(0,i)]))),scope=new Set([...scope,...declared])}for(let[key,child2]of Object.entries(v))key!=="withClause"&&walk3(child2,scope)};try{walk3((await parsePgSql(sql4)).stmts)}catch{}return names}function locate(source,byteOffset){let prefix=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!1}).decode(new TextEncoder().encode(source).subarray(0,byteOffset)),lines=prefix.split(`
|
|
2
|
-
`),rest=source.slice(prefix.length),token=/^("[^"]*"|'[^']*'|[\w.$]+|\S)/.exec(rest)?.[0];return{offset:prefix.length,line:lines.length,column:lines[lines.length-1].length+1,...token?{token}:{}}}function toDiagnostic(e,source){let at=e.keyword?.exec(source.replace(/'(?:[^']|'')*'|"(?:[^"]|"")*"/g,m=>" ".repeat(m.length)));return at?{code:e.code,message:e.message,...locate(source,new TextEncoder().encode(source.slice(0,at.index)).byteLength),token:at[0]}:{code:e.code,message:e.message,...e.offset===void 0?{}:locate(source,e.offset)}}function tagRelations(v){if(Array.isArray(v))return v.map(tagRelations);if(!v||typeof v!="object")return v;let out={};for(let[k,c]of Object.entries(v))out[k]=tagRelations(c);return"relname"in out&&!("mantle"in out)&&(out.mantle="table"),out}function expandViews(v,views,share){if(Array.isArray(v))return v.map(x=>expandViews(x,views,share));if(!v||typeof v!="object")return v;if(!v.SelectStmt)return Object.fromEntries(Object.entries(v).map(([k,c])=>[k,expandViews(c,views,share)]));let used=new Set,tables=new Set,reserve=n=>{if(!(!n||typeof n!="object")){n.RangeVar?.mantle==="table"&&tables.add(n.RangeVar.relname);for(let[key,child2]of Object.entries(n))["relname","ctename","aliasname"].includes(key)&&used.add(String(child2)),reserve(child2)}};reserve(v);for(let ref2 of Object.values(views))reserve(ref2.select);let serial=0,fresh=()=>{let name4;do name4=`_view_${serial++}`;while(used.has(name4));return used.add(name4),name4},names=new Map,definitions=[],walk3=(n,scope=new Map)=>{if(Array.isArray(n))return n.map(x=>walk3(x,scope));if(!n||typeof n!="object")return n;let rv=n.RangeVar;if(rv?.mantle==="view"){if(!share)return{RangeSubselect:{subquery:{SelectStmt:walk3(views[rv.relname].select)},alias:rv.alias??{aliasname:rv.relname}}};let name4=names.get(rv.relname);if(!name4){names.set(rv.relname,name4=fresh());let select2=walk3(views[rv.relname].select);definitions.push({CommonTableExpr:{ctename:name4,ctequery:{SelectStmt:select2},ctematerialized:"CTEMaterializeDefault"}})}return{RangeVar:{...rv,mantle:"cte",relname:name4,alias:rv.alias??{aliasname:rv.relname}}}}if(rv?.mantle==="cte"&&scope.has(rv.relname)&&scope.get(rv.relname)!==rv.relname)return{RangeVar:{...rv,relname:scope.get(rv.relname),alias:rv.alias??{aliasname:rv.relname}}};let w=n.withClause;if(!w)return Object.fromEntries(Object.entries(n).map(([k,c])=>[k,walk3(c,scope)]));let local=new Map(w.ctes.map(x=>[x.CommonTableExpr.ctename,tables.has(x.CommonTableExpr.ctename)?fresh():x.CommonTableExpr.ctename])),inner=new Map([...scope,...local]),prior=new Map(scope),ctes=w.ctes.map(({CommonTableExpr:c})=>{let query=walk3(c.ctequery,w.recursive?inner:prior);return prior.set(c.ctename,local.get(c.ctename)),{CommonTableExpr:{...c,ctename:local.get(c.ctename),ctequery:query}}});return{...Object.fromEntries(Object.entries(n).filter(([k])=>k!=="withClause").map(([k,c])=>[k,walk3(c,inner)])),withClause:{...w,ctes}}},out=walk3(v);return definitions.length&&(out.SelectStmt.withClause={...out.SelectStmt.withClause,ctes:[...definitions,...out.SelectStmt.withClause?.ctes??[]]}),out}function stripLocations(v){return JSON.parse(JSON.stringify(v),(k,c)=>k==="location"||k==="rexpr_list_start"||k==="rexpr_list_end"?void 0:c)}async function compileSql(sql4,ctx,dialect=compile_exports){try{if(/\bIN\s+auth\.user\s*\(/i.test(sql4))throw new SqlRefusal("USER_REF_SCOPE_ONLY",USER_REF_SCOPE_ONLY);let parsed=await parsePgSql(sql4);if(/\/\*|\*\//.test(JSON.stringify(parsed.stmts)))throw new SqlRefusal("SQL_UNSUPPORTED","String literals and identifiers cannot contain '/*' or '*/'.");let tagged=tagRelations(parsed.stmts);refuseUserReferences(tagged),refuseForEveryDialect(tagged,ctx,parsed.locations);let stmts=expandViews(tagged,ctx.views??{},dialect.name===name2);return dialect.accepts(stmts,{...ctx,source:sql4},parsed.locations),{ok:!0,plan:{grammar:180004,stmts:stripLocations(stmts)},...ctx.kind==="view"?{reference:stripLocations(tagged)[0].SelectStmt}:{}}}catch(e){if(e instanceof SqlRefusal)return{ok:!1,diagnostic:toDiagnostic(e,sql4)};throw e}}var indexColumn=field=>Object.hasOwn(NATIVE_COLUMNS,field)?NATIVE_COLUMNS[field]:field.toLowerCase();function toDiagnostic2(d,source,pointer2){let at=d.line===void 0?void 0:{line:d.line,column:d.column,...d.token?{token:d.token}:{}};return validateDiagnostic({code:d.code,severity:"error",path:`${source.sourceId}#/${source.documentIndex}${pointer2}`,source:{...source,path:pointer2},...at?{value:at}:{},message:at?`SQL ${at.line}:${at.column}${at.token?` near ${JSON.stringify(at.token)}`:""}: ${d.message}`:d.message})}var starCols=s=>Object.entries(s.fields).filter(([f])=>f!==s.scope).flatMap(([f,t])=>t==="geo"?[`${f}_lat`,`${f}_lng`]:[f]);function viewOutputs(view,schemas,ctes=new Map,includeGeo=!1,includeAggregates=!0){let columns2=Object.create(null),sel=view.stmts[0]?.SelectStmt;if(!sel?.targetList)return{columns:columns2};let outputs=(stmt,scope2)=>viewOutputs({grammar:view.grammar,stmts:[stmt]},schemas,scope2,includeGeo,includeAggregates),scope=new Map(ctes);if(sel.withClause?.recursive)for(let{CommonTableExpr:c}of sel.withClause.ctes)scope.set(c.ctename,Object.create(null));for(let{CommonTableExpr:c}of sel.withClause?.ctes??[]){let body=outputs(c.ctequery,scope),renamed=c.aliascolnames?.map(x=>x.String.sval);scope.set(c.ctename,renamed?Object.fromEntries(renamed.flatMap((n,i)=>body.columns[body.positions?.[i]??""]?[[n,body.columns[body.positions[i]]]]:[])):body.columns)}let rels=new Map,subs=new Map,walk3=n=>{if(n.JoinExpr)return walk3(n.JoinExpr.larg),walk3(n.JoinExpr.rarg);let v=n.RangeVar;v?rels.set(v.alias?.aliasname??v.relname,v.mantle==="table"&&schemas[String(v.relname).toLowerCase()]?String(v.relname).toLowerCase():void 0):rels.set((n.RangeSubselect??n.RangeFunction)?.alias?.aliasname??"",void 0),v?.mantle==="cte"&&scope.has(v.relname)&&subs.set(v.alias?.aliasname??v.relname,scope.get(v.relname)),n.RangeSubselect?.subquery?.SelectStmt&&subs.set(n.RangeSubselect.alias?.aliasname??"",outputs(n.RangeSubselect.subquery,scope).columns)};for(let f of sel.fromClause??[])walk3(f);let typeOf=(schema,col)=>schemas[schema].fields[col]??(col==="published_at"&&schemas[schema].publishing?"timestamptz":Object.hasOwn(NATIVE_OUTPUT_TYPES,col)?NATIVE_OUTPUT_TYPES[col]:void 0),field=(schema,col)=>schema&&typeOf(schema,col)&&(includeGeo||typeOf(schema,col)!=="geo")?{schema,field:col}:void 0,keys=[];for(let{ResTarget:r}of sel.targetList){let agg=r.val?.FuncCall,fn3=agg?.funcname?.at(-1)?.String?.sval,arg=agg&&!agg.over&&!agg.agg_distinct&&agg.args?.length===1?agg.args[0].ColumnRef?.fields:void 0,refs2=r.val?.ColumnRef?.fields??(includeAggregates&&r.name&&arg&&["sum","min","max"].includes(fn3)?arg:void 0);if(!r.name&&refs2?.at(-1)?.A_Star){let from=refs2.length>1?[rels.get(refs2[0].String.sval)]:[...rels.values()];if(from.some(s=>!s)){keys=void 0;continue}for(let s of from)for(let c of starCols(schemas[s])){keys?.push(c);let f2=field(s,c);f2&&(columns2[c]=f2)}continue}let col=refs2?.at(-1)?.String?.sval,name4=r.name??col;if(!name4){keys=void 0;continue}keys?.push(name4);let relName=refs2?.length===2?refs2[0].String.sval:refs2?.length===1&&rels.size===1?[...rels.keys()][0]:void 0,rel=relName===void 0?void 0:rels.get(relName),f=col?field(rel,col)??(relName!==void 0?subs.get(relName)?.[col]:void 0):void 0;f&&(fn3!=="sum"||r.val?.ColumnRef||["integer","real"].includes(typeOf(f.schema,f.field))||typeOf(f.schema,f.field).startsWith("numeric("))&&(columns2[name4]=f)}return{...keys?{keys:[...new Set(keys)],positions:keys}:{},columns:columns2}}var JSON_FUNCS=new Set(["json_group_array","json_group_object","json_set","json_insert","json_remove","jsonb_agg","jsonb_object_agg","jsonb_build_object","jsonb_build_array","jsonb_strip_nulls","to_jsonb"]),isJson=n=>{if(n?.FuncCall)return JSON_FUNCS.has(n.FuncCall.funcname?.at(-1)?.String?.sval);if(n?.TypeCast)return n.TypeCast.typeName?.names?.at(-1)?.String?.sval==="jsonb";let sub=n?.SubLink?.subLinkType==="EXPR_SUBLINK"?n.SubLink.subselect?.SelectStmt:void 0;if(sub)return sub.targetList?.length===1&&isJson(sub.targetList[0].ResTarget?.val);let args=n?.CoalesceExpr?.args,literal=a=>{let text=a.A_Const?.sval?.sval;try{return text!==void 0&&(JSON.parse(text),!0)}catch{return!1}};return!!args?.some(isJson)&&args.every(a=>isJson(a)||literal(a))},jsonOutputs=view=>new Set((view.stmts[0]?.SelectStmt?.targetList??[]).flatMap(({ResTarget:r})=>r?.name&&isJson(r.val)?[r.name]:[])),aggregates=v=>{if(Array.isArray(v))return v.some(aggregates);if(!v||typeof v!="object"||"SubLink"in v)return!1;let call=v.FuncCall,name4=call?.funcname?.map(x=>x.String?.sval).join(".").replace(/^pg_catalog\./,"");return!!call&&!call.over&&AGGREGATES.has(name4)||Object.values(v).some(aggregates)};function tableOutputs(view,schemas){let out=Object.create(null),read=(sel2,qual,name4)=>{if(!sel2||sel2.op!=="SETOP_NONE"||sel2.withClause)return;let items=[],from=(n,nullable2)=>{n.JoinExpr?(from(n.JoinExpr.larg,nullable2),from(n.JoinExpr.rarg,nullable2||n.JoinExpr.jointype!=="JOIN_INNER")):items.push({node:n,nullable:nullable2})};for(let f of sel2.fromClause??[])from(f,!1);let alias=n=>n.RangeVar?n.RangeVar.alias?.aliasname??n.RangeVar.relname:(n.RangeSubselect??n.RangeFunction)?.alias?.aliasname,hit=qual===void 0?items:items.filter(i=>alias(i.node)===qual);if(hit.length!==1||qual===void 0&&items.length!==1)return;let{node,nullable}=hit[0],found;if(node.RangeVar?.mantle==="table"){let s=schemas[String(node.RangeVar.relname).toLowerCase()],type=s&&name4!=="_rid"?storageColumns(s).get(name4):void 0;type&&(found={type:type==="native"?"timestamptz":type,notNull:NATIVE_NOT_NULL.has(name4)||notNullColumns(s).has(name4)})}else if(node.RangeSubselect&&!node.RangeSubselect.lateral&&!node.RangeSubselect.alias?.colnames?.length){let inner=node.RangeSubselect.subquery?.SelectStmt,outs=(inner?.targetList??[]).filter(t=>(t.ResTarget.name??t.ResTarget.val?.ColumnRef?.fields?.at(-1)?.String?.sval)===name4);found=outs.length===1?bare(inner,outs[0].ResTarget.val):void 0}return found&&{type:found.type,notNull:found.notNull&&!nullable}},bare=(sel2,val)=>{let f=val?.ColumnRef?.fields;if(!f||f.length>2||f.some(x=>!x.String))return;let got=read(sel2,f.length===2?f[0].String.sval:void 0,f.at(-1).String.sval);return got&&{type:got.type,notNull:got.notNull&&(!!sel2.groupClause||!(sel2.havingClause||aggregates([sel2.targetList,sel2.sortClause])))}},sel=view.stmts[0]?.SelectStmt;for(let{ResTarget:r}of sel?.targetList??[]){let name4=r.name??r.val?.ColumnRef?.fields?.at(-1)?.String?.sval,got=name4?bare(sel,r.val):void 0;got&&(out[name4]=got)}return out}async function compileLinkedPlan(linked,dialect=compile_exports){let schemas={},userFields=Object.create(null),diagnostics=[];for(let{manifest:m}of linked.schemas){let template=m.spec.scope===void 0?void 0:parseRowTemplate(m.spec.scope),scope=template&&typeof template=="object"?template.owner?.toLowerCase():void 0,userScopes=template&&typeof template=="object"?template.terms.map(({column,field})=>{let property=m.spec.schema.properties?.[column],type=property?.type==="string"?"string":"number";try{registerUserField(userFields,field,{type,...[property?.type].flat().includes("integer")?{integer:!0}:{},multiple:!0,...property?.enum?{enum:property.enum}:{}})}catch(error){if(!(error instanceof SqlRefusal))throw error;diagnostics.push(validateDiagnostic({code:error.code,severity:"error",path:`schemas/${m.metadata.name}/scope`,message:error.message}))}return{column:column.toLowerCase(),field,type}}):[],props=m.spec.schema.properties??{},lower=xs=>xs.map(x=>x.toLowerCase());schemas[m.metadata.name.toLowerCase()]={name:m.metadata.name,title:m.spec.title,...m.spec.description?{description:m.spec.description}:{},...m.spec.uiSchema?{uiSchema:m.spec.uiSchema}:{},...m.spec.localized?{localized:!0}:{},...scope?{scope}:{},...userScopes.length?{userScopes}:{},...m.spec.ttl?{ttl:m.spec.ttl.field.toLowerCase(),ttlSeconds:m.spec.ttl.expireAfterSeconds}:{},publishing:m.spec.lifecycle==="publishing",schema:m.spec.schema,...m.spec.translates?{translates:{parent:m.spec.translates.parent,on:m.spec.translates.on}}:{},fields:fieldTypes(m.spec.schema),names:Object.fromEntries(Object.keys(props).map(n=>[n.toLowerCase(),n])),...m.spec.searchableFields?.length?{search:lower(m.spec.searchableFields)}:{},...m.spec.uniqueIndexes?.length?{unique:m.spec.uniqueIndexes.map(lower)}:{},...m.spec.indexes?.length?{indexes:m.spec.indexes.map(cols=>cols.map(indexColumn))}:{}}}let refs2={},refName=name4=>name4.toLowerCase().replace(/-/g,"_"),refOf=new Map(linked.views.map(x=>[refName(x.manifest.metadata.name),x])),readable2=new Set;for(let[ref2,{manifest:v}]of refOf){if(Object.hasOwn(schemas,ref2))continue;let why=v.spec.surface!=="internal"?`a ${v.spec.surface} View`:v.spec.input?"a View with an input":v.spec.requires?"a View with requires":void 0;why||readable2.add(ref2),refs2[ref2]={refusal:why?`${ref2} is ${why}: FROM reads only an internal View without input or requires`:`${ref2} did not compile`}}let ctxOf=(kind,input,isPublic=!1)=>({schemas,inputs:fieldTypes(input),kind,public:isPublic,views:refs2}),compile=async(kind,sql4,input,source,pointer2,isPublic=!1)=>{let res=await compileSql(sql4,ctxOf(kind,input,isPublic),dialect);if(res.ok)return res;diagnostics.push(toDiagnostic2(res.diagnostic,source,pointer2))};for(let{manifest:m,source}of linked.schemas){let name4=m.metadata.name.toLowerCase(),clash=storageColumnClash(schemas[name4].fields??{});clash&&diagnostics.push(toDiagnostic2({code:"SQL_SHAPE",message:`field '${clash}' is a column storage creates for another purpose (_rid, or a geo field's _lat/_lng)`},source,`/spec/schema/properties/${clash}`));let checks=[];for(let[i,text]of(m.spec.checks??[]).entries()){let pointer2=`/spec/checks/${i}`,res=await compileSql(`SELECT 1 FROM "${name4.replace(/"/g,'""')}" WHERE ${text}`,{schemas,inputs:{},kind:"view"},dialect);if(!res.ok){diagnostics.push(toDiagnostic2(res.diagnostic,source,pointer2));continue}let where=res.plan.stmts[0]?.SelectStmt?.whereClause,problem3=where?checkShapeProblem(where,storageColumns(schemas[name4])):"a check is one boolean expression";if(problem3){diagnostics.push(toDiagnostic2({code:"SQL_SHAPE",message:problem3},source,pointer2));continue}checks.push(where)}checks.length&&(schemas[name4]={...schemas[name4],checks})}let order=[],state=new Map,reads=new Map(await Promise.all(linked.views.map(async x=>[x.manifest.metadata.name,[...await relationNames(x.manifest.spec.sql)].filter(r=>readable2.has(r))]))),procedureReads=new Map(await Promise.all(linked.procedures.flatMap(({manifest:p})=>{let sql4=p.spec.handler.sql;return sql4===void 0?[]:[(async()=>[sql4,[...await relationNames(sql4)].filter(r=>readable2.has(r))])()]}))),viewRefs=sql4=>reads.get(linked.views.find(x=>x.manifest.spec.sql===sql4)?.manifest.metadata.name??"")??procedureReads.get(sql4)??[],visit=(x,path)=>{let name4=x.manifest.metadata.name;if(state.get(name4)!=="done"){if(state.get(name4)==="visiting"){diagnostics.push(toDiagnostic2({code:"SQL_RELATION",message:`View '${name4}' reads itself: ${[...path,name4].join(" -> ")}`},x.source,"/spec/sql"));return}state.set(name4,"visiting");for(let r of reads.get(name4)??[])visit(refOf.get(r),[...path,name4]);state.set(name4,"done"),order.push(x)}};for(let x of linked.views)visit(x,[]);let compiled=new Map;for(let{manifest:v,source}of order){if((reads.get(v.metadata.name)??[]).some(r=>!refs2[r]?.select))continue;let result=await compile("view",v.spec.sql,v.spec.input,source,"/spec/sql",v.spec.surface==="public"),plan=result?.plan;compiled.set(v.metadata.name,plan);let ref2=refName(v.metadata.name);plan&&readable2.has(ref2)&&(refs2[ref2]={select:result.reference})}let views={};for(let{manifest:v,source}of linked.views){let plan=compiled.get(v.metadata.name),cacheProblem=plan&&v.spec.cache?viewCacheProblem(plan.stmts,schemas):void 0;cacheProblem&&diagnostics.push(validateDiagnostic({code:"VIEW_CACHE_INVALID",severity:"error",path:`${source.sourceId}#/${source.documentIndex}/spec/cache`,source:{...source,path:"/spec/cache"},message:`View '${v.metadata.name}': ${cacheProblem}.`}));let outputs=plan?viewOutputs(plan,schemas):void 0,columns2=outputs?.columns??{},list=v.spec.uiSchema?.list??{};for(let key of["searchFields","filterFields"])for(let[i,f]of(list[key]??[]).entries())!outputs?.keys||outputs.keys.some(k=>k===f||k===f.toLowerCase())||diagnostics.push(validateDiagnostic({code:"VIEW_UI_INVALID",severity:"error",path:`${source.sourceId}#/${source.documentIndex}/spec/uiSchema/list/${key}/${i}`,source:{...source,path:`/spec/uiSchema/list/${key}/${i}`},value:f,expected:`one of the View's outputs: ${outputs.keys.join(", ")}`,message:`View '${v.metadata.name}' uiSchema.list.${key} names '${f}', which the View's SELECT does not output.`}));let wire=(outputs?.keys??[]).map(k=>columns2[k]?.field===k?schemas[columns2[k].schema].names?.[k]??k:k);for(let[i,f]of(list.columns??[]).entries()){if(!outputs?.keys||wire.includes(f))continue;let folded=wire.find(k=>k.toLowerCase()===f.toLowerCase());diagnostics.push(validateDiagnostic({code:"VIEW_UI_INVALID",severity:"error",path:`${source.sourceId}#/${source.documentIndex}/spec/uiSchema/list/columns/${i}`,source:{...source,path:`/spec/uiSchema/list/columns/${i}`},value:f,expected:`one of the View's outputs: ${wire.join(", ")}`,message:folded?`View '${v.metadata.name}' uiSchema.list.columns names '${f}', but the row carries '${folded}': an unquoted alias folds to lower case, so write AS "${f}".`:`View '${v.metadata.name}' uiSchema.list.columns names '${f}', which the View's SELECT does not output.`}))}plan&&(views[v.metadata.name]={...plan,...Object.keys(columns2).length?{columns:columns2}:{},...v.spec.title?{title:v.spec.title}:{},...v.spec.description?{description:v.spec.description}:{},...v.spec.uiSchema?{uiSchema:v.spec.uiSchema}:{},inputs:fieldTypes(v.spec.input),...v.spec.input?{input:v.spec.input}:{},source:v.spec.sql,surface:v.spec.surface,...v.spec.requires?{requires:v.spec.requires}:{},...v.spec.cache?{sharedMaxAge:v.spec.cache.sharedMaxAge}:{}})}let procedures={},declaredSchema=new Map(linked.schemas.map(x=>[x.manifest.metadata.name.toLowerCase(),x.manifest.metadata.name])),inferTarget=(p,stmts)=>{let rows=stmts.filter(s=>classify(s)==="row"),pinned=rows.length===1?pinnedTarget(rows[0]):void 0,props=Object.keys(p.spec.input.properties??{}),declared=lower=>props.find(k=>k.toLowerCase()===lower),id=pinned&&declared(pinned.id),schema=pinned&&declaredSchema.get(pinned.schema.toLowerCase());if(!pinned||!id||!schema||!p.spec.input.required?.includes(id)||p.spec.input.properties[id].type!=="string")return;let version3=pinned.version&&declared(pinned.version);if(!(version3&&!["number","integer"].includes(String(p.spec.input.properties[version3].type))))return{schema,id,...version3?{version:version3}:{}}};for(let{manifest:p,source}of linked.procedures){let common={...p.spec.title?{title:p.spec.title}:{},...p.spec.description?{description:p.spec.description}:{},...p.spec.uiSchema?{uiSchema:p.spec.uiSchema}:{},input:p.spec.input,output:p.spec.output,inputs:fieldTypes(p.spec.input),...p.spec.requires?{requires:p.spec.requires}:{},...p.spec.mcp?{mcp:p.spec.mcp}:{}};if("ref"in p.spec.handler){procedures[p.metadata.name]={...common,...p.spec.target?{target:p.spec.target}:{},handler:{ref:p.spec.handler.ref}};continue}let plan=(await compile("procedure",p.spec.handler.sql,p.spec.input,source,"/spec/handler/sql"))?.plan,target2=p.spec.target??(plan?inferTarget(p,plan.stmts):void 0);for(let stmt of plan?.stmts??[]){let write=stmt.UpdateStmt??stmt.InsertStmt,columns2=write?protectedColumns(schemas[write.relation.relname]):[];(stmt.UpdateStmt?.targetList??stmt.InsertStmt?.onConflictClause?.targetList??[]).some(set=>columns2.includes(set.ResTarget.name.toLowerCase()))&&diagnostics.push(validateDiagnostic({code:"USER_FIELD_POSITION",severity:"error",path:`procedures/${p.metadata.name}/handler/sql`,message:"The scoped column is never writable through SET."}))}plan&&(procedures[p.metadata.name]={...common,...target2?{target:target2}:{},handler:{sql:plan,source:p.spec.handler.sql}})}if(diagnostics.length)return{ok:!1,diagnostics};let touched=(node,includeCtes=!1,found=new Set)=>{if(!node||typeof node!="object")return found;let n=node,rel=includeCtes||n.RangeVar?.mantle!=="cte"?n.RangeVar?.relname:void 0;rel&&found.add(rel);for(let kind of["InsertStmt","UpdateStmt","DeleteStmt"])n[kind]?.relation?.relname&&found.add(n[kind].relation.relname);return Object.values(node).forEach(child2=>touched(child2,includeCtes,found)),found},restrictOf=(kind,name4,raw,stmts)=>{if(!raw)return;if(typeof raw!="object"||Array.isArray(raw)){diagnostics.push(validateDiagnostic({code:"USER_FIELD_CONFLICT",severity:"error",path:`${kind}/${name4}/restrict`,message:'restrict maps each Schema to a predicate, e.g. restrict: { orders: "author_id = auth.uid()" }.'}));return}let read=touched(stmts),out={};for(let[key,text]of Object.entries(raw)){let table=key.toLowerCase(),schema=schemas[table],path=`${kind}/${name4}/restrict/${key}`,fail=message2=>{diagnostics.push(validateDiagnostic({code:"USER_FIELD_CONFLICT",severity:"error",path,message:message2}))};if(!schema||!read.has(table)){fail(`restrict key '${key}' is not a Schema this target's SQL reads.`);continue}let template=parseRowTemplate(text);if(typeof template=="string"){fail(`restrict: ${template}`);continue}let column=c=>Object.keys(schema.fields).find(f=>f===c.toLowerCase()),owner=template.owner?.toLowerCase();if(owner&&owner!=="author_id"&&owner!==schema.scope){fail(`restrict '${template.owner} = auth.uid()': use author_id (stamped from the caller on insert) or the Schema's own '= auth.uid()' scope column; '${template.owner}' is writable.`);continue}let terms=template.terms.flatMap(({column:c,field})=>{let found=column(c);if(!found)return fail(`restrict column '${c}' is not a field of '${schema.name}'.`),[];let property=schema.schema?.properties?.[schema.names?.[found]??c],type=property?.type==="string"?"string":"number";try{registerUserField(userFields,field,{type,...[property?.type].flat().includes("integer")?{integer:!0}:{},multiple:!0,...property?.enum?{enum:property.enum}:{}})}catch(error){if(!(error instanceof SqlRefusal))throw error;fail(error.message)}return[{column:found,field,type}]});out[table]={...owner?{owner}:{},terms}}return Object.keys(out).length?out:void 0},inherit=(own,sql4,path)=>{let merged=Object.fromEntries(Object.entries(own??{}).map(([k,r])=>[k,{...r,terms:[...r.terms]}]));for(let ref2 of sql4===void 0?[]:viewRefs(sql4))for(let[table,r]of Object.entries(views[refOf.get(ref2).manifest.metadata.name]?.restrict??{})){let into=merged[table]??={terms:[]};if(r.owner&&into.owner&&r.owner!==into.owner){diagnostics.push(validateDiagnostic({code:"USER_FIELD_CONFLICT",severity:"error",path,message:`reads Views whose restrict on '${table}' names different owner columns.`}));continue}r.owner&&(into.owner=r.owner);for(let t of r.terms)into.terms.some(x=>x.column===t.column&&x.field===t.field)||into.terms.push(t)}return Object.keys(merged).length?merged:void 0};for(let{manifest:v}of order){let view=views[v.metadata.name],restrict=view&&inherit(restrictOf("views",v.metadata.name,v.spec.restrict,view.stmts),v.spec.sql,`views/${v.metadata.name}/restrict`);restrict&&(views[v.metadata.name]={...view,restrict})}for(let{manifest:p}of linked.procedures){let proc=procedures[p.metadata.name];if(p.spec.restrict&&proc&&"ref"in proc.handler){diagnostics.push(validateDiagnostic({code:"USER_FIELD_CONFLICT",severity:"error",path:`procedures/${p.metadata.name}/restrict`,message:"restrict applies to SQL Procedures; a ref handler restricts rows through its scoped ctx.store."}));continue}let restrict=proc&&"sql"in proc.handler&&inherit(restrictOf("procedures",p.metadata.name,p.spec.restrict,proc.handler.sql.stmts)||void 0,p.spec.handler.sql,`procedures/${p.metadata.name}/restrict`),trustedOnly=!!proc&&"sql"in proc.handler&&proc.handler.sql.stmts.some(stmt=>{let ins=stmt.InsertStmt,t=String(ins?.relation.relname??"").toLowerCase();return!!ins&&(!!schemas[t]?.userScopes?.length&&(!ins.selectStmt?.SelectStmt?.valuesLists||!!(restrict&&restrict[t]))||!ins.selectStmt?.SelectStmt?.valuesLists&&!!schemas[t]&&refChecks(schemas[t],schemas).some(r=>ins.cols?.some(x=>String(x.ResTarget.name).toLowerCase()===r.column)))});(restrict||trustedOnly)&&(procedures[p.metadata.name]={...proc,...restrict?{restrict}:{},...trustedOnly?{trustedOnly:!0}:{}})}let triggers=Object.fromEntries(linked.triggers.map(({manifest:t})=>[t.metadata.name,{source:t.spec.source,procedure:t.spec.target.procedure}])),warnings=[];for(let[field,spec]of Object.entries(userFields))spec.enum||warnings.push(`USER_FIELD_VALUES_UNENUMERATED: '${field}' has no enum; no generated list of all values is available.`);let scopedFields=schema=>(schemas[schema]?.userScopes??[]).map(u=>u.field).sort().join(",");for(let[name4,view]of Object.entries(views)){let read=[...touched(view.stmts,!0)].filter(schema=>schemas[schema]);view.surface==="public"&&read.some(schema=>schemas[schema].userScopes?.length)&&warnings.push(`USER_SCOPE_PUBLIC_ANON_EMPTY: public View '${name4}' reads field-scoped data; anonymous callers are refused (UNAUTHENTICATED).`),view.surface==="admin"&&read.some(schema=>schemas[schema].userScopes?.length)&&warnings.push(`USER_SCOPE_ADMIN_VALUES: admin View '${name4}' reads field-scoped data; admins without values for those fields see no rows.`);let sets2=new Set(read.filter(schema=>schemas[schema].userScopes?.length).map(scopedFields));sets2.size>1&&warnings.push(`USER_SCOPE_JOIN_DROPS: View '${name4}' joins Schemas scoped by different fields (${[...sets2].join(" / ")}); rows outside any caller set are dropped.`)}for(let[name4,schema]of Object.entries(schemas))for(let[field,property]of Object.entries(schema.schema?.properties??{})){let raw=property["x-mantle-ref"],ref2=typeof raw=="string"?raw:raw?.schema,target2=ref2?schemas[ref2.toLowerCase()]:void 0;for(let term2 of target2?target2.userScopes??[]:[])(schema.userScopes??[]).some(u=>u.field===term2.field)||diagnostics.push(validateDiagnostic({code:"USER_FIELD_CONFLICT",severity:"error",path:`schemas/${schema.name}/scope`,message:`'${schema.name}.${field}' references '${target2.name}', which is scoped by auth.user('${term2.field}'); scope '${schema.name}' by the same field so its rows cannot expose what that scope hides.`}))}if(diagnostics.length)return{ok:!1,diagnostics};let sealed={version:6,dialect:{name:dialect.name,version:dialect.version},schemas,views,procedures,triggers,...Object.keys(userFields).length?{access:{roles:[],userFields,warnings}}:{}};return{ok:!0,plan:{...sealed,fingerprint:await planFingerprint(sealed)}}}async function compilePlan(sources,dialect=compile_exports,defaultLifecycle="publishing"){let parsed=parseManifestSources(sources,defaultLifecycle);if(!parsed.ok)return parsed;let linked=linkManifestSet(parsed.value);return linked.ok?compileLinkedPlan(linked.value,dialect):linked}var MEDIA_PURPOSE_SLUG_PATTERN=/^[a-z0-9]+(-[a-z0-9]+)*$/;var SHORTHAND_TO_MIME={jpg:"image/jpeg",jpeg:"image/jpeg","image/jpg":"image/jpeg",png:"image/png","image/png":"image/png",webp:"image/webp","image/webp":"image/webp",avif:"image/avif","image/avif":"image/avif",gif:"image/gif","image/gif":"image/gif",svg:"image/svg+xml","image/svg+xml":"image/svg+xml","image/svg":"image/svg+xml"};function parseMimeAccept(entry){let seen=new Set,out=[];for(let raw of entry.split(",")){let tok=raw.trim().toLowerCase();if(!tok)continue;let expanded=SHORTHAND_TO_MIME[tok]??tok;seen.has(expanded)||(seen.add(expanded),out.push(expanded))}return out}function expandPolicyRequired(required){return required.map(parseMimeAccept)}var InvalidLocaleError=class extends Error{constructor(value2){super(`invalid locale: ${value2}`),this.name="InvalidLocaleError"}};var LANG=/^[a-z]{2,3}$/,REGION=/^[a-z]{2}$/,SCRIPT_SUBTAG_SHAPE=/^[a-z]{2,3}[-_][a-z]{4}(?:[-_][a-z]{2})?$/i;function toCanonicalLocale(input){if(typeof input!="string"||input.length===0)throw new InvalidLocaleError(String(input));let parts=input.replace(/_/g,"-").split("-"),head=parts[0];if(head===void 0)throw new InvalidLocaleError(input);parts.length===1&&head.length===4&&(parts=[head.slice(0,2),head.slice(2)]);let lang=parts[0].toLowerCase();if(!LANG.test(lang))throw new InvalidLocaleError(input);if(parts.length===1)return lang;let region=parts[1].toLowerCase();if(!REGION.test(region))throw new InvalidLocaleError(input);return`${lang}-${region.toUpperCase()}`}function canonicalizeLocaleList(inputs){let valid=[],invalid2=[],seen=new Set;for(let raw of inputs)try{let canonical2=toCanonicalLocale(raw);seen.has(canonical2)||(seen.add(canonical2),valid.push(canonical2))}catch{invalid2.push(raw)}return{valid,invalid:invalid2}}function containsScriptSubtagLocale(inputs){return inputs.some(raw=>SCRIPT_SUBTAG_SHAPE.test(raw))}var InvalidSiteDefaultsError=class extends Error{constructor(invalidLocales){let hasScriptSubtag=containsScriptSubtagLocale(invalidLocales);super("Invalid Mantle locale tag(s) in adapter siteDefaults.locales: "+invalidLocales.map(s=>`'${s}'`).join(", ")+". Use Mantle v0.1 locale form like 'en' or 'zh-TW' \u2014 the canonicalizer accepts mixed case ('zh-tw' / 'ZH_TW'), but the structure must be a 2/3-letter language plus optional 2-letter region. "+(hasScriptSubtag?"Script subtags such as 'zh-Hant', 'zh-Hans', 'sr-Latn', or 'sr-Cyrl' are valid BCP 47 but intentionally unsupported in Mantle v0.1; use region tags such as 'zh-TW' for Traditional Chinese or 'zh-CN' for Simplified Chinese. ":"")+"See ADR-0010 / cms-spec's canonicalizeLocaleList.");this.invalidLocales=invalidLocales;this.name="InvalidSiteDefaultsError"}invalidLocales},InvalidMediaPurposesError=class extends Error{constructor(issues){super("Invalid media purpose declaration(s) in adapter siteDefaults.media.purposes: "+issues.map(i=>{let tag=`'${i.name||"(unnamed)"}'`;switch(i.reason){case"invalid-slug":return`${tag} fails slug pattern ${MEDIA_PURPOSE_SLUG_PATTERN.source}`;case"empty-required":return`${tag} declares no required slots (need at least one)`;case"empty-required-slot":return`${tag} has a required slot that parses to zero mimes: ${i.detail}`;case"overlapping-slot-mimes":return`${tag} has slots with overlapping mime sets (variant\u2192slot mapping is ambiguous): ${i.detail}`;case"maxBytes-missing-mime":return`${tag} maxBytes is missing entries: ${i.detail}`;case"maxBytes-non-positive":return`${tag} maxBytes has non-positive entries: ${i.detail}`}}).join("; ")+`. Each purpose's name must match ${MEDIA_PURPOSE_SLUG_PATTERN.source} (lowercase alphanumerics, dash-separated, no leading/trailing or repeated dashes); required mimes are the closed set the variants manifest must cover; maxBytes caps each variant's declared byteSize and MUST name every mime in required. See aotter/mantle#272.`);this.issues=issues;this.name="InvalidMediaPurposesError"}issues},InvalidSiteIconsError=class extends Error{constructor(invalidIcons){super("Invalid adapter siteDefaults.icons: each icon needs a root-relative or absolute HTTPS src, an optional supported image mimeType, and sizes such as '64x64' or 'any'.");this.invalidIcons=invalidIcons;this.name="InvalidSiteIconsError"}invalidIcons};function assertSiteDefaultsCanonical(defaults){if(defaults?.locales&&defaults.locales.length>0){let{invalid:invalid2}=canonicalizeLocaleList(defaults.locales);if(invalid2.length>0)throw new InvalidSiteDefaultsError(invalid2)}if(defaults?.icons){let invalid2=defaults.icons.filter(icon=>!validSiteIcon(icon));if(defaults.icons.length===0||invalid2.length>0)throw new InvalidSiteIconsError(invalid2.length>0?invalid2:defaults.icons)}let origin=defaults?.origin;if(origin&&!(URL.canParse(origin)&&/^https?:$/.test(new URL(origin).protocol)&&new URL(origin).origin===origin))throw new Error(`siteDefaults.origin '${origin}' must be an absolute http(s) origin such as 'https://example.com', with no path or trailing slash.`);let purposes=defaults?.media?.purposes;if(purposes&&purposes.length>0){let issues=collectMediaPurposeIssues(purposes);if(issues.length>0)throw new InvalidMediaPurposesError(issues)}}function validSiteIcon(icon){return!icon||typeof icon!="object"||typeof icon.src!="string"?!1:!!((/^\/(?!\/)[^\s\\]*$/.test(icon.src)||URL.canParse(icon.src)&&new URL(icon.src).protocol==="https:")&&(!icon.mimeType||["image/png","image/jpeg","image/svg+xml","image/webp"].includes(icon.mimeType))&&(!icon.theme||icon.theme==="light"||icon.theme==="dark")&&(!icon.sizes||Array.isArray(icon.sizes)&&icon.sizes.length>0)&&(icon.sizes?.every(size=>typeof size=="string"&&(size==="any"||/^[1-9]\d*x[1-9]\d*$/.test(size)))??!0))}function collectMediaPurposeIssues(purposes){let out=[];for(let p of purposes){if(!MEDIA_PURPOSE_SLUG_PATTERN.test(p.name)){out.push({name:p.name,reason:"invalid-slug"});continue}if(p.required.length===0){out.push({name:p.name,reason:"empty-required"});continue}let slots=expandPolicyRequired(p.required),emptySlots=slots.map((mimes,i)=>({mimes,raw:p.required[i]})).filter(s=>s.mimes.length===0);if(emptySlots.length>0){out.push({name:p.name,reason:"empty-required-slot",detail:emptySlots.map(s=>`'${s.raw}'`).join(", ")});continue}let seen=new Map,overlaps=[];if(slots.forEach((mimes,slotIdx)=>{for(let mime of mimes)seen.has(mime)?overlaps.push(`'${mime}' in slots [${seen.get(mime)}, ${slotIdx}]`):seen.set(mime,slotIdx)}),overlaps.length>0){out.push({name:p.name,reason:"overlapping-slot-mimes",detail:overlaps.join(", ")});continue}let expandedMimes=Array.from(seen.keys()),missing=expandedMimes.filter(mime=>!(mime in p.maxBytes));if(missing.length>0){out.push({name:p.name,reason:"maxBytes-missing-mime",detail:missing.join(", ")});continue}let nonPositive=expandedMimes.filter(mime=>!(typeof p.maxBytes[mime]=="number"&&p.maxBytes[mime]>0));nonPositive.length>0&&out.push({name:p.name,reason:"maxBytes-non-positive",detail:nonPositive.map(m=>`${m}=${p.maxBytes[m]}`).join(", ")})}return out}var VERB={create:"insert",update:"update",delete:"delete",publish:"publish"},lifecycleKey=(plan,schema)=>Object.hasOwn(plan.schemas,schema.toLowerCase())?schema.toLowerCase():void 0;function lifecycleHookSets(plan){let byHook=new Map,before=new Set,after=new Set,triggers=Object.entries(plan.triggers).sort(([a],[b])=>a<b?-1:1);for(let[name4,t]of triggers)if(t.source.kind==="lifecycle")for(let hook of t.source.on){let[stage,op2]=hook.split("_"),schema=lifecycleKey(plan,t.source.schema);(stage==="before"?before:after).add(`${schema}.${VERB[op2]}`);let key=`${schema}|${hook}`;byHook.set(key,[...byHook.get(key)??[],[name4,t.procedure]])}return{before,after,byHook}}var MANTLE_VERSION="0.2.0";var S=s=>({String:{sval:s}}),ref=(...f)=>({ColumnRef:{fields:f.map(S)}}),op=(o,l,r)=>({A_Expr:{kind:"AEXPR_OP",name:[S(o)],lexpr:l,rexpr:r}}),num=n=>Number.isSafeInteger(n)&&Math.abs(n)<2147483648?{A_Const:{ival:{ival:n}}}:{A_Const:{fval:{fval:String(n)}}},target=(val,name4)=>({ResTarget:name4?{name:name4,val}:{val}}),ATOMIC=new Set(["ColumnRef","A_Const","ParamRef","FuncCall","TypeCast","CaseExpr","CoalesceExpr","MinMaxExpr","RowExpr","Raw"]),atomic=x=>!x||typeof x!="object"||Object.keys(x).some(k=>ATOMIC.has(k))||x.SubLink&&["EXPR_SUBLINK","ARRAY_SUBLINK"].includes(x.SubLink.subLinkType),paren=x=>atomic(x)?x:{Raw:{parts:[x]}};function parenthesized(key,n){if(key==="NullTest"||key==="BooleanTest")return{...n,arg:paren(n.arg)};if(key==="SubLink")return n.testexpr?{...n,testexpr:paren(n.testexpr)}:n;let r=n.rexpr,rexpr=r?.List?{List:{...r.List,items:r.List.items.map(paren)}}:r?.FuncCall&&r.FuncCall.funcname?.at(-1)?.String?.sval==="like_escape"?{FuncCall:{...r.FuncCall,args:r.FuncCall.args?.map(paren)}}:paren(r);return{...n,...n.lexpr?{lexpr:paren(n.lexpr)}:{},...r?{rexpr}:{}}}function writeTarget(ast){let node=ast;return(node.InsertStmt??node.UpdateStmt??node.DeleteStmt)?.relation?.relname?.toLowerCase()}var HOOK_PREFIX="_mantle_h_",param=n=>({ParamRef:{number:n}}),and=(...args)=>{let a=args.filter(Boolean);return a.length===0?void 0:a.length===1?a[0]:{BoolExpr:{boolop:"AND_EXPR",args:a}}},or=(...a)=>({BoolExpr:{boolop:"OR_EXPR",args:a}}),sort=(node,dir="SORTBY_DEFAULT")=>({SortBy:{node,sortby_dir:dir,sortby_nulls:"SORTBY_NULLS_DEFAULT"}}),declaredCols=s=>Object.entries(s.fields).filter(([f])=>f!==s.scope).flatMap(([f,t])=>t==="geo"?[`${f}_lat`,`${f}_lng`]:[f]),readable=s=>["id","version","created_at","updated_at","author_id",...s.publishing?["status","published_at"]:[],...declaredCols(s)],starCols2=s=>declaredCols(s);function param$(c,spec){let key=JSON.stringify(spec),n=c.keys.get(key);return n||(c.binds.push(spec),n=c.binds.length,c.keys.set(key,n)),param(n)}function term(c,a,t){if(t[1]==="in"){let value3=t[2];if(value3.k!=="user"||!c.lower.anyOf)throw new SqlRefusal("SQL_UNSUPPORTED","User scope needs native set lowering.");let kept=c.lower.anyOf(ref(a,t[0]),param$(c,value3),value3.type);return value3.scope?{Raw:{parts:[`/*s:${value3.field}*/`,kept,"/*|*/",or(structuredClone(kept),op("=",num(1),num(1))),"/*;*/"]}}:kept}if(t[1]==="parent"){let[column2,,value3,parent]=t,alias=a==="_mantle_parent"?"_mantle_parent_":"_mantle_parent",exists={SubLink:{subLinkType:"EXISTS_SUBLINK",subselect:{SelectStmt:{targetList:[target(num(1))],fromClause:[{RangeVar:{relname:parent.table,alias:{aliasname:alias},inh:!0,relpersistence:"p",mantle:"system"}}],whereClause:and(op("=",ref(alias,column2),ref(a,column2)),...parent.scope?[op("=",ref(alias,parent.scope[0]),ref(a,parent.scope[1]))]:[],...parent.terms.map(t2=>term(c,alias,t2))),limitOption:"LIMIT_OPTION_DEFAULT",op:"SETOP_NONE"}}}};return parent.admin?or(op("=",param$(c,value3),num(1)),exists):exists}let[column,kind,v,published]=t,value2=v.k==="const"?{A_Const:{sval:{sval:v.value}}}:param$(c,v);return kind==="admin"?or(op("=",ref(a,column),{A_Const:{sval:{sval:published}}}),op("=",value2,num(1))):kind==="ttl"?or({NullTest:{arg:ref(a,column),nulltesttype:"IS_NULL"}},op(">",ref(a,column),value2)):op("=",ref(a,column),value2)}function visible(s,a,c,table){if(c.unsafeNoVisibility)return;let r=table!==void 0&&c.mode!=="trusted"?c.restrict?.[table.toLowerCase()]:void 0,extra=r?[...r.owner?[[r.owner,"eq",{k:"uid"}]]:[],...r.terms.map(u=>userScopeTerm(u))]:[];return and(...[...rowPolicy(s,c.mode,c.schemas),...extra].map(t=>term(c,a,t)))}function refs(s,c,a,value2,child2,set=!1){if(c.mode==="trusted"||c.uncheckedRefs)return;let qualify=v=>Array.isArray(v)?v.map(qualify):!v||typeof v!="object"||v.SubLink?v:v.ColumnRef?.fields?.length===1&&v.ColumnRef.fields[0].String?ref(a,v.ColumnRef.fields[0].String.sval):Object.fromEntries(Object.entries(v).map(([k,x])=>[k,qualify(x)]));return and(...refChecks(s,c.schemas).flatMap(r=>{let v=value2(r.column);if(set&&v&&JSON.stringify(v).includes('"SubLink"'))throw new SqlRefusal("USER_FIELD_POSITION",`SET '${r.column}', a reference to a scoped Schema, takes no subquery for callers; read the value first or use trusted mode.`);return v?[or({NullTest:{arg:qualify(v),nulltesttype:"IS_NULL"}},{SubLink:{subLinkType:"EXISTS_SUBLINK",subselect:{SelectStmt:{targetList:[target(num(1))],fromClause:[{RangeVar:{relname:r.table,alias:{aliasname:"_mantle_ref"},inh:!0,relpersistence:"p",mantle:"system"}}],whereClause:and(op("=",ref("_mantle_ref",r.field),qualify(v)),...r.same.map(([parent,column])=>op("=",ref("_mantle_ref",parent),child2(column))),...r.terms.map(t=>term(c,"_mantle_ref",t))),limitOption:"LIMIT_OPTION_DEFAULT",op:"SETOP_NONE"}}}})]:[]}))}var sets=(w,c)=>w.sets.map(([column,v])=>target(v==="bump"?op("+",ref(column),num(1)):param$(c,v),column));function positionOf(c){switch(c.edge){case"JoinExpr.larg":return"join.left";case"JoinExpr.rarg":return"join.right";case"SelectStmt.fromClause":{let i=c.sel.at(-1);return i.hasWindow?"window":i.hasJsonEach?"json_each":i.container}}throw new SqlRefusal("SQL_RELATION",`internal: a relation reached through ${c.edge}, which has no position: refused (fail closed)`)}function wrap(rv,c){if(rv.mantle==="cte"){if(!c.ctes.some(m=>m.has(rv.relname)))throw new SqlRefusal("SQL_RELATION",`${rv.relname}: a cte reference is not defined in scope`);return{RangeVar:rv}}let s=c.schemas[String(rv.relname).toLowerCase()];if(!s)throw new SqlRefusal("SQL_RELATION",`${rv.relname} is not a declared Schema`);if(rv.mantle==="system")return{RangeVar:rv};if(rv.mantle!=="table")throw new SqlRefusal("SQL_RELATION",`${rv.relname}: a relation that is neither a Schema nor a CTE`);let position=positionOf(c);c.seen?.add(position);let a=rv.alias?.aliasname??rv.relname,targets=readable(s).map(f=>target(ref(f)));return targets.push(...c.lower.columns(s)),{RangeSubselect:{alias:{aliasname:a},subquery:{SelectStmt:{targetList:targets,fromClause:[{RangeVar:{relname:rv.relname,inh:!0,relpersistence:"p",mantle:"system"}}],whereClause:visible(s,rv.relname,c,rv.relname),limitOption:"LIMIT_OPTION_DEFAULT",op:"SETOP_NONE"}}}}}function relsOf(f,out=[]){return f&&(f.JoinExpr?(relsOf(f.JoinExpr.larg,out),relsOf(f.JoinExpr.rarg,out)):out.push(f)),out}var hasFunc=(v,pred)=>Array.isArray(v)?v.some(x=>hasFunc(x,pred)):!v||typeof v!="object"?!1:v.FuncCall&&pred(v.FuncCall.funcname.map(x=>x.String.sval).join(".").replace(/^pg_catalog\./,""),v.FuncCall)?!0:v.SubLink?!1:Object.values(v).some(x=>hasFunc(x,pred));function lookupAlias(c,alias){for(let info of[...c.sel].reverse()){let name4=info.scope.get(alias);if(name4)return{schema:name4,def:c.schemas[name4],searchQuery:info.searchQ.get(alias)}}throw new SqlRefusal("SQL_FUNCTION",`${alias} is not a Schema in scope: mantle.search() and mantle.near() take a Schema alias`)}var scopeOf=c=>({inputs:c.inputs,param:spec=>param$(c,spec),tx:node=>tx(node,c),alias:name4=>lookupAlias(c,name4),seen:p=>c.seen?.add(p)});function lowerFunc(n,c){let f=n.funcname.map(x=>x.String.sval).join(".").replace(/^pg_catalog\./,"");switch(f){case"auth.uid":return param$(c,{k:"uid"});case"auth.role":throw new SqlRefusal("AUTH_ROLE_REMOVED","auth.role() is removed; decide per-target permission in the application's authorize(target, caller) seam.");case"now":{let p=param$(c,{k:"now"});return c.lower.system?.(p,"timestamptz")??p}}return c.lower.func(f,n,scopeOf(c))??c.lower.call(deep(n,c,"FuncCall"))}var H={A_Expr:(n,c)=>({A_Expr:deep(n,c,"A_Expr")}),ColumnRef:(n,c)=>{let f=n.fields.map(x=>x.String?.sval);if(f[0]!=="input"||f.length!==2)return{ColumnRef:n};let type=c.inputs[f[1]];return c.lower.input(param$(c,{k:"input",name:f[1],type}),type)},FuncCall:(n,c)=>lowerFunc(n,c),SubLink:(n,c)=>c.lower.sublink(deep(n,c,"SubLink")),TypeCast:(n,c)=>c.lower.cast(n,scopeOf(c)),RangeVar:(n,c)=>wrap(n,c),SelectStmt:(n,c)=>select(n,c),UpdateStmt:(n,c)=>update(n,c),DeleteStmt:(n,c)=>del(n,c),InsertStmt:(n,c)=>insert(n,c)};function deep(n,c,type){let out={};for(let[k,v]of Object.entries(n)){if(k==="relation"){out[k]=v;continue}let saved={edge:c.edge,embed:c.embed};c.edge=`${type}.${k}`,c.edge==="SubLink.subselect"?c.embed="sublink":c.edge==="RangeSubselect.subquery"?c.embed="from-subquery":c.edge==="InsertStmt.selectStmt"?c.embed="insert-select":c.edge==="CommonTableExpr.ctequery"&&(c.embed="cte"),c.edge==="SelectStmt.larg"||c.edge==="SelectStmt.rarg"?(c.embed=c.edge==="SelectStmt.larg"?"setop.left":"setop.right",out[k]=select(v,c).SelectStmt):out[k]=tx(v,c),c.edge=saved.edge,c.embed=saved.embed}return out}function tx(v,c){if(Array.isArray(v))return v.map(x=>tx(x,c));if(!v||typeof v!="object")return v;let ks=Object.keys(v),k0=ks[0];if(ks.length===1&&H[k0])return H[k0](v[k0],c);if(ks.length===1&&/^[A-Z]/.test(k0)){let body=v[k0];return{[k0]:body&&typeof body=="object"&&!Array.isArray(body)?deep(body,c,k0):body}}return deep(v,c,"bare")}var outputsOf=sel=>sel.op&&sel.op!=="SETOP_NONE"?outputsOf(sel.larg):(sel.targetList??[]).map(t=>t.ResTarget.name??t.ResTarget.val?.ColumnRef?.fields?.at(-1)?.String?.sval),cteOutputs=cte=>cte.aliascolnames?.length?cte.aliascolnames.map(x=>x.String.sval):outputsOf(cte.ctequery.SelectStmt);function select(n,c){let w=n.withClause,defs=(w?.ctes??[]).map(x=>x.CommonTableExpr),scope=list=>new Map(list.map(d=>[d.ctename,d])),within=(m,f)=>{c.ctes.push(m);try{return f()}finally{c.ctes.pop()}},withClause=w&&{...w,ctes:defs.map((d,j)=>within(scope(w.recursive?defs:defs.slice(0,j)),()=>tx({CommonTableExpr:d},c)))};return within(scope(defs),()=>{let out=selectIn(w?{...n,withClause:void 0}:n,c);return withClause&&(out.SelectStmt.withClause=withClause),out})}function selectIn(n,c){let rels=relsOf(n.fromClause?.[0]),info={container:c.embed==="top"?"from":c.embed,hasWindow:hasFunc(n.targetList,(_f,fc)=>!!fc.over),hasJsonEach:(n.fromClause??[]).some(f=>f.RangeFunction),scope:new Map(rels.filter(r=>r.RangeVar).map(r=>[r.RangeVar.alias?.aliasname??r.RangeVar.relname,r.RangeVar.relname])),searchQ:new Map},findSearch=v=>{if(Array.isArray(v))return v.forEach(findSearch);if(!v||typeof v!="object")return;let f=v.FuncCall;f&&f.funcname.map(x=>x.String.sval).join(".")==="mantle.search"&&info.searchQ.set(f.args[0].ColumnRef.fields[0].String.sval,f.args[1]),Object.values(v).forEach(findSearch)};findSearch(n.whereClause),c.sel.push(info);let saved=c.embed,out=deep(expandStar(n,info,c),c,"SelectStmt");c.embed=saved,c.sel.pop();let first=rels[0],firstAlias=first?.RangeVar?first.RangeVar.alias?.aliasname??first.RangeVar.relname:first?.RangeSubselect?.alias?.aliasname,aggregate=!n.groupClause&&hasFunc(n.targetList,(f,fc)=>AGGREGATES.has(f)&&!fc.over);if(out.sortClause&&!aggregate){let dir=c.nativeOrder&&out.sortClause.at(-1)?.SortBy.sortby_dir==="SORTBY_DESC"?"SORTBY_DESC":"SORTBY_DEFAULT",have=new Set(out.sortClause.map(k=>{let node=k.SortBy.node,fields=node.ColumnRef?.fields,alias=fields?.length===1&&fields[0].String?.sval==="id"&&out.targetList.find(t=>t.ResTarget.name==="id"),actual=(alias?alias.ResTarget.val:node).ColumnRef?.fields;return JSON.stringify(!n.groupClause&&firstAlias&&actual?.at(-1)?.String?.sval==="id"&&(actual.length===1||actual.length===2&&actual[0].String?.sval===firstAlias)?ref(firstAlias,"id"):node)}));if(n.groupClause)out.sortClause=[...out.sortClause,...tx(n.groupClause,c).filter(g=>!have.has(JSON.stringify(g))).map(g=>sort(g,dir))];else if(firstAlias||first?.RangeFunction){if(first.RangeSubselect&&!outputsOf(first.RangeSubselect.subquery.SelectStmt).includes("id"))throw new SqlRefusal("SQL_SHAPE",`ordering ${firstAlias}, a subquery in FROM, needs the subquery to output id`);let cte=first.RangeVar?.mantle==="cte"?[...c.ctes].reverse().find(m=>m.has(first.RangeVar.relname))?.get(first.RangeVar.relname):void 0;if(cte&&!cteOutputs(cte).includes("id"))throw new SqlRefusal("SQL_SHAPE",`ordering ${firstAlias}, a CTE, needs the CTE to output id`);let extra=firstAlias?[ref(firstAlias,"id")]:[];for(let f of n.fromClause??[])for(let r of relsOf(f)){let je=r.RangeFunction;if(!je)continue;let fname2=je.functions[0]?.List?.items?.[0]?.FuncCall?.funcname?.at(-1)?.String?.sval;if(fname2==="json_each"){je.alias?extra.push(ref(je.alias.aliasname,"id")):r===first&&rels.length===1&&n.fromClause.length===1&&extra.push(ref("json_each","id"));continue}if(!je.alias||!je.ordinality)throw new SqlRefusal("SQL_SHAPE",`ordering a row source (${fname2}) needs an alias and WITH ORDINALITY: write ${fname2}(...) WITH ORDINALITY AS j(value, n)`);let own=String(fname2).startsWith("jsonb_each")?2:1,names=je.alias.colnames??[];extra.push(ref(je.alias.aliasname,names.length>own?names.at(-1).String.sval:"ordinality"))}out.sortClause=[...out.sortClause,...extra.filter(e=>!have.has(JSON.stringify(e))).map(e=>sort(e,dir))]}}if(firstAlias&&!n.groupClause)for(let t of out.targetList??[]){let fc=t.ResTarget.val?.FuncCall;fc?.over&&fc.funcname.at(-1).String.sval==="row_number"&&(fc.over.orderClause=[...fc.over.orderClause??[],sort(ref(firstAlias,"id"))])}return{SelectStmt:out}}function expandStar(n,info,c){if(!n.targetList?.some(t=>t.ResTarget.val?.ColumnRef?.fields?.at(-1)?.A_Star))return n;let list=n.targetList.flatMap(t=>{let f=t.ResTarget.val?.ColumnRef?.fields;if(!f?.at(-1)?.A_Star)return[t];if(f.length!==2&&(n.fromClause??[]).some(x=>relsOf(x).some(r=>!r.RangeVar||!c.schemas[String(r.RangeVar.relname).toLowerCase()]||r.RangeVar.mantle!=="table")))throw new SqlRefusal("SQL_SHAPE","SELECT * reads a subquery, json_each or a CTE: name the columns");return(f.length===2?[f[0].String.sval]:[...info.scope.keys()]).flatMap(a=>{let sc=info.scope.get(a);if(!sc||!c.schemas[sc])throw new SqlRefusal("SQL_SHAPE",`${a}.* needs a Schema alias`);return starCols2(c.schemas[sc]).map(cn=>target(ref(a,cn)))})});return{...n,targetList:list}}var alias$=rel=>rel.alias?.aliasname??rel.relname;function returning(rc,s,c,target2){let own=f=>!!f?.at(-1)?.A_Star&&(f.length===1||f[0]?.String?.sval===target2),exprs=(rc?.exprs??[]).flatMap(e=>own(e.ResTarget.val?.ColumnRef?.fields)?starCols2(s).map(f=>target(ref(f))):[e]);return c.hooked&&exprs.push(...readable(s).map(f=>target(ref(f),`${HOOK_PREFIX}${f}`))),exprs.length?{exprs}:void 0}function dmlScope(rel,c){c.sel.push({container:"from",hasWindow:!1,hasJsonEach:!1,scope:new Map([[alias$(rel),rel.relname]]),searchQ:new Map})}function update(n,c){let s=c.schemas[String(n.relation.relname).toLowerCase()],a=alias$(n.relation);c.seen?.add("update-target"),dmlScope(n.relation,c);let columns2=protectedColumns(s,c.mode!=="trusted"?c.restrict?.[String(n.relation.relname).toLowerCase()]:void 0);if(n.targetList.some(target2=>columns2.includes(String(target2.ResTarget.name).toLowerCase())))throw new SqlRefusal("USER_FIELD_POSITION","The scoped column is never writable through SET.");let out=deep(n,c,"UpdateStmt");c.sel.pop();let w=writePolicy(s,"update",{status:c.status,lock:c.lockVersion}),checked=refs(s,c,a,column=>out.targetList.find(t=>String(t.ResTarget.name).toLowerCase()===column)?.ResTarget.val,column=>ref(a,column),!0);return out.targetList.push(...sets(w,c)),out.whereClause=and(out.whereClause,visible(s,a,c,String(n.relation.relname)),w.lock&&term(c,a,w.lock),checked),out.returningClause=returning(out.returningClause,s,c,alias$(n.relation)),{UpdateStmt:out}}function del(n,c){let s=c.schemas[String(n.relation.relname).toLowerCase()],a=alias$(n.relation);c.seen?.add("delete-target"),dmlScope(n.relation,c);let out=deep(n,c,"DeleteStmt");c.sel.pop();let w=writePolicy(s,"delete",{lock:c.lockVersion});return out.whereClause=and(out.whereClause,visible(s,a,c,String(n.relation.relname)),w.lock&&term(c,a,w.lock)),out.returningClause=returning(out.returningClause,s,c,alias$(n.relation)),{DeleteStmt:out}}function insert(n0,c){let table=String(n0.relation.relname).toLowerCase(),s=c.schemas[table],caller=c.mode!=="trusted",columns2=protectedColumns(s,caller?c.restrict?.[table]:void 0);if(n0.onConflictClause?.action==="ONCONFLICT_UPDATE"&&n0.onConflictClause.targetList.some(target2=>columns2.includes(String(target2.ResTarget.name).toLowerCase())))throw new SqlRefusal("USER_FIELD_POSITION","The scoped column is never writable through SET.");let owner=caller?c.restrict?.[table]?.owner:void 0,scoped=caller?s.userScopes??[]:[],n=scoped.length?structuredClone(n0):n0,rows=n.selectStmt?.SelectStmt?.valuesLists;if(caller&&(scoped.length&&!rows||columns2.some(column=>column!==owner&&!scoped.some(u=>u.column===column))))throw new SqlRefusal("USER_FIELD_POSITION","Procedure INSERT/upsert into a restricted Schema, or INSERT ... SELECT into a field-scoped one, requires trusted mode; use its scoped Store.");let scopeFills=[],checked=[];for(let u of scoped){let at2=n.cols.flatMap((r,i)=>String(r.ResTarget.name).toLowerCase()===u.column?[i]:[]),type=s.fields[u.column],spec={k:"scoped",column:u.column,field:u.field,type:u.type};if(!at2.length){scopeFills.push([u.column,spec]);continue}let refuse3=why=>{throw new SqlRefusal("USER_FIELD_POSITION",`The scope column '${u.column}' ${why}`)};at2.length>1&&refuse3("is listed twice."),rows.forEach((row,r)=>{let item=row.List.items[at2[0]],f=item?.ColumnRef?.fields?.map(x=>x.String?.sval),k=item?.A_Const;f?.[0]==="input"&&f.length===2?(c.inputs[f[1]]!==type&&refuse3(`is ${type}; input '${f[1]}' must be declared with the same type.`),row.List.items[at2[0]]=param$(c,{...spec,name:f[1]})):type==="text"&&k?.sval?row.List.items[at2[0]]=param$(c,{...spec,value:k.sval.sval}):type!=="text"&&k&&"ival"in k?row.List.items[at2[0]]=param$(c,{...spec,value:k.ival.ival??0}):refuse3(`takes an input of type ${type}, a ${type==="text"?"string":"integer"} literal, or is omitted (filled from the caller).`),checked.push([r,at2[0],type])})}c.seen?.add("insert-target");let out=deep(n,c,"InsertStmt");for(let[r,i,type]of checked){let items2=out.selectStmt.SelectStmt.valuesLists[r].List.items;items2[i]=c.lower.input(items2[i],type)}let w=writePolicy(s,"insert",{idGiven:(x=>n.cols.some(r=>r.ResTarget.name===x))("id")}),fill=w.fills.map(([name4,v])=>[name4,v==="newId"?c.lower.newId():param$(c,v)]).concat(scopeFills.map(([name4,v])=>[name4,param$(c,v)]));out.cols=[...out.cols,...fill.map(([name4])=>({ResTarget:{name:name4}}))];let empty=!n.cols.length,items=out.selectStmt?.SelectStmt?.valuesLists?.[0]?.List.items,at=column=>n.cols.findIndex(r=>String(r.ResTarget.name).toLowerCase()===column);if(!items&&caller&&refChecks(s,c.schemas).some(r=>at(r.column)>=0))throw new SqlRefusal("USER_FIELD_POSITION","Procedure INSERT ... SELECT that writes a reference to a scoped Schema requires trusted mode; use INSERT ... VALUES.");let parents=items&&refs(s,c,String(n.relation.relname),column=>at(column)<0?void 0:structuredClone(items[at(column)]),column=>structuredClone(at(column)<0?fill.find(([name4])=>name4===column)[1]:items[at(column)]));out.selectStmt={SelectStmt:{targetList:[...empty?[]:[target({ColumnRef:{fields:[S("_v"),{A_Star:{}}]}})],...fill.map(([,v])=>target(v))],...empty?{}:{fromClause:[{RangeSubselect:{subquery:out.selectStmt,alias:{aliasname:"_v"}}}]},whereClause:parents??{A_Const:{boolval:{boolval:!0}}},limitOption:"LIMIT_OPTION_DEFAULT",op:"SETOP_NONE"}};let oc=out.onConflictClause;if(oc){let named2=(oc.infer?.indexElems??[]).some(e=>String(e.IndexElem?.name??"").toLowerCase()===s.scope);if(s.scope&&oc.infer&&!named2&&oc.infer.indexElems.unshift({IndexElem:{name:s.scope,ordering:"SORTBY_DEFAULT",nulls_ordering:"SORTBY_NULLS_DEFAULT"}}),oc.infer&&(s.userScopes??[]).forEach((u,i)=>{(oc.infer.indexElems??[]).some(e=>String(e.IndexElem?.name??"").toLowerCase()===u.column)||oc.infer.indexElems.splice((s.scope?1:0)+i,0,{IndexElem:{name:u.column,ordering:"SORTBY_DEFAULT",nulls_ordering:"SORTBY_NULLS_DEFAULT"}})}),oc.action==="ONCONFLICT_UPDATE"){c.seen?.add("conflict-update"),oc.targetList.push(...sets(w,c));let t=n.relation.relname,setRef=refs(s,c,t,column=>oc.targetList.find(x=>String(x.ResTarget.name).toLowerCase()===column)?.ResTarget.val,column=>ref(t,column),!0);oc.whereClause=and(oc.whereClause,visible(s,t,c,t),setRef)}}return out.returningClause=returning(out.returningClause,s,c,alias$(n.relation)),{InsertStmt:out}}function applyPolicy(stmt,opts){let t=Object.keys(stmt)[0],verb=t==="InsertStmt"?"insert":t==="UpdateStmt"?"update":t==="DeleteStmt"?"delete":void 0,schema=verb?String(stmt[t].relation.relname).toLowerCase():void 0,publish=opts.status==="published",hooked=!!schema&&!!opts.returning?.has(`${schema}.${publish?"publish":verb}`),c={...opts,hooked,binds:[],keys:new Map,edge:"",embed:"top",sel:[],ctes:[]};return{ast:tx(stmt,c),binds:c.binds,kind:classify(stmt),schema,verb,hooked,publish}}function compileProgram(stmts,ctx){let diagnostics=ctx.dialect.check({grammar:180004,stmts},{schemas:ctx.schemas,...ctx.columns?{columns:ctx.columns}:{},inputs:ctx.inputs,kind:ctx.kind,public:ctx.mode==="public"});if(diagnostics.length)throw new DiagnosticError(diagnostics.map(d=>runtimeDiagnostic({code:"INPUT_VALIDATION_FAILED",severity:"error",path:"store",message:`${d.code}: ${d.message}`})));let opts={restrict:ctx.restrict,schemas:ctx.schemas,inputs:ctx.inputs,mode:ctx.mode,lockVersion:ctx.lockVersion,returning:ctx.returning,seen:ctx.seen,unsafeNoVisibility:ctx.unsafeNoVisibility,uncheckedRefs:ctx.uncheckedRefs,lower:ctx.dialect.lowering,nativeOrder:ctx.dialect.nativeOrder};return stmts.map((stmt,i)=>{let c=applyPolicy(stmt,{...opts,status:ctx.statuses?.[i]});if(c.kind==="set"&&c.schema&&ctx.schemas[c.schema]?.publishing)throw new DiagnosticError(runtimeDiagnostic({code:"INPUT_VALIDATION_FAILED",severity:"error",path:"store",message:`SQL_SHAPE: a set op on ${c.schema} is refused: its lifecycle is publishing, so published entries are protected and writes take row ops only`}));return c})}var refuse=message2=>new DiagnosticError(runtimeDiagnostic({code:"INPUT_VALIDATION_FAILED",severity:"error",path:"store",message:message2})),refuseOutput=name4=>{throw refuse(`SQL_SHAPE: the View has no output named '${name4}'`)},outName=t=>t.ResTarget.name??t.ResTarget.val?.ColumnRef?.fields?.at(-1)?.String?.sval,nativeNotNull=(s,column)=>column==="id"||column==="version"||column==="created_at"||column==="updated_at"||column===s.scope||!!s.publishing&&column==="status";function fromItems(items,nullable=!1){return(items??[]).flatMap(n=>{let j=n.JoinExpr;return j?[...fromItems([j.larg],nullable||j.jointype==="JOIN_RIGHT"||j.jointype==="JOIN_FULL"),...fromItems([j.rarg],nullable||j.jointype==="JOIN_LEFT"||j.jointype==="JOIN_FULL")]:[{node:n,nullable}]})}function notNullIn(schemas,sel,qual,name4){if(!sel||sel.op!=="SETOP_NONE"||sel.withClause)return!1;let items=fromItems(sel.fromClause),alias=n=>n.RangeVar?n.RangeVar.alias?.aliasname??n.RangeVar.relname:n.RangeSubselect?.alias?.aliasname??n.RangeFunction?.alias?.aliasname,hit=qual===void 0?items:items.filter(i=>alias(i.node)===qual);if(hit.length!==1||qual===void 0&&items.length!==1||hit[0].nullable)return!1;let{node}=hit[0];if(node.RangeVar){let schema=node.RangeVar.mantle==="system"?schemas[node.RangeVar.relname]:void 0;return!!schema&&nativeNotNull(schema,name4)}let sub=node.RangeSubselect;if(!sub||sub.alias?.colnames?.length||sub.lateral)return!1;let outs=(sub.subquery.SelectStmt?.targetList??[]).filter(t=>(t.ResTarget.name??t.ResTarget.val?.ColumnRef?.fields?.at(-1)?.String?.sval)===name4),f=outs.length===1?outs[0].ResTarget.val?.ColumnRef?.fields:void 0;return!f||f.length>2||f.some(x=>!x.String)?!1:notNullIn(schemas,sub.subquery.SelectStmt,f.length===2?f[0].String.sval:void 0,f.at(-1).String.sval)}function rowComparable(env,keys,notNull){if(!env.dialect.nativeOrder||!keys.length)return!1;let desc=keys[0].SortBy.sortby_dir==="SORTBY_DESC";return keys.every((k,i)=>{let d=k.SortBy.sortby_dir;if(d!=="SORTBY_DEFAULT"&&d!=="SORTBY_ASC"&&d!=="SORTBY_DESC"||d==="SORTBY_DESC"!==desc)return!1;let nulls=k.SortBy.sortby_nulls;return nulls&&nulls!=="SORTBY_NULLS_DEFAULT"&&nulls!==(desc?"SORTBY_NULLS_FIRST":"SORTBY_NULLS_LAST")?!1:notNull[i]})}function pageShape(nkeys,cursor,match){let cursorShape=cursor?`${Array.from({length:nkeys},(_x,i)=>{let v=cursor[i];return v===null?"n":v===void 0?"u":"v"}).join("")}${cursor.length===nkeys?"=":"!"}`:"-",search=match?.search?.text?match.search:void 0;return JSON.stringify([cursorShape,search?.columns??null,(match?.eq??[]).map(e=>e.column)])}function pagedOf(env,c,cursor,match){let opts={cursor,match},sel=structuredClone(c.ast.SelectStmt),keys=sel.sortClause??[];if(opts.cursor&&!keys.length)throw refuse("SQL_SHAPE: this View has no ORDER BY, so it is one page and takes no cursor");let visible2=sel.targetList.map(outName);if(!keys.length&&!opts.match?.search?.text&&!opts.match?.eq?.length)return{ast:{SelectStmt:{...sel,limitCount:{ParamRef:{number:c.binds.length+1}},limitOption:"LIMIT_OPTION_COUNT"}},sources:[{limit:!0}],flat:!0,names:[],nkeys:0};if(visible2.some(n=>!n))throw refuse("SQL_SHAPE: a paged View names every output column");let names=visible2,aliasVal=new Map(sel.targetList.map(t=>[outName(t),t.ResTarget.val])),hidden=keys.map((k,i)=>{let node=k.SortBy.node,f=node.ColumnRef?.fields,position=node.A_Const?.ival?Number(node.A_Const.ival.ival):void 0,val=position!==void 0?sel.targetList[position-1]?.ResTarget.val??refuseOutput(String(position)):f?.length===1&&aliasVal.has(f[0].String.sval)?aliasVal.get(f[0].String.sval):node;return{ResTarget:{name:`_k${i}`,val}}}),desc=k=>k.SortBy.sortby_dir==="SORTBY_DESC",nullsFirst=k=>k.SortBy.sortby_nulls==="SORTBY_NULLS_FIRST"?!0:k.SortBy.sortby_nulls==="SORTBY_NULLS_LAST"?!1:desc(k)===!!env.dialect.nativeOrder,inner=sel.limitCount?{...sel,targetList:[...sel.targetList,...hidden]}:{...sel,targetList:[...sel.targetList,...hidden],sortClause:void 0,limitCount:void 0,limitOption:"LIMIT_OPTION_DEFAULT"},base=c.binds.length,sources=[],param2=source=>(sources.push(source),{ParamRef:{number:base+sources.length}}),col=n=>ref("_p",n),isNull=(n,t)=>({NullTest:{arg:n,nulltesttype:t}}),conditions=[];if(opts.cursor){let cur=opts.cursor,notNull=hidden.map(h=>{let f=h.ResTarget.val?.ColumnRef?.fields;return!!f&&f.length<=2&&f.every(x=>x.String)&¬NullIn(env.schemas,sel,f.length===2?f[0].String.sval:void 0,f.at(-1).String.sval)}),same=j=>cur[j]===null?isNull(col(`_k${j}`),"IS_NULL"):op("=",col(`_k${j}`),param2({cursor:j})),past=(k,i)=>{let at=col(`_k${i}`);if(cur[i]===null)return nullsFirst(k)?isNull(at,"IS_NOT_NULL"):void 0;let beyond=op(desc(k)?"<":">",at,param2({cursor:i}));return notNull[i]||nullsFirst(k)?beyond:{BoolExpr:{boolop:"OR_EXPR",args:[beyond,isNull(at,"IS_NULL")]}}};if(rowComparable(env,keys,notNull)&&cur.length===keys.length&&cur.every(v=>v!=null)){let row=args=>({RowExpr:{args,row_format:"COERCE_IMPLICIT_CAST"}});conditions.push(op(desc(keys[0])?"<":">",row(keys.map((_k,i)=>col(`_k${i}`))),row(cur.map((_v,i)=>param2({cursor:i})))))}else{cur[0]!==null&&cur[0]!==void 0&&(notNull[0]||nullsFirst(keys[0]))&&conditions.push(op(desc(keys[0])?"<=":">=",col("_k0"),param2({cursor:0})));let args=keys.flatMap((k,i)=>{let last=past(k,i);return last?[{BoolExpr:{boolop:"AND_EXPR",args:[...keys.slice(0,i).map((_x,j)=>same(j)),last]}}]:[]});conditions.push(args.length?{BoolExpr:{boolop:"OR_EXPR",args}}:{A_Const:{boolval:{boolval:!1}}})}}let output=name4=>names.find(n=>n===name4)??names.find(n=>n===name4.toLowerCase())??refuseOutput(name4),search=opts.match?.search;search?.text&&conditions.push({BoolExpr:{boolop:"OR_EXPR",args:search.columns.map(c2=>({A_Expr:{kind:"AEXPR_LIKE",name:[{String:{sval:"~~"}}],lexpr:col(output(c2)),rexpr:{FuncCall:{funcname:[{String:{sval:"like_escape"}}],args:[param2({search:!0}),{A_Const:{sval:{sval:"\\"}}}],funcformat:"COERCE_EXPLICIT_CALL"}}}}))}}),(opts.match?.eq??[]).forEach(({column},k)=>conditions.push(op("=",col(output(column)),param2({eq:k}))));let limitCount=param2({limit:!0});return{ast:{SelectStmt:{targetList:[...names.map(n=>({ResTarget:{val:col(n),name:n}})),...keys.map((_k,i)=>({ResTarget:{val:col(`_k${i}`),name:`_k${i}`}}))],fromClause:[{RangeSubselect:{subquery:{SelectStmt:inner},alias:{aliasname:"_p"}}}],whereClause:conditions.length>1?{BoolExpr:{boolop:"AND_EXPR",args:conditions}}:conditions[0],sortClause:keys.map((k,i)=>({SortBy:{node:col(`_k${i}`),sortby_dir:k.SortBy.sortby_dir,sortby_nulls:nullsFirst(k)?"SORTBY_NULLS_FIRST":"SORTBY_NULLS_LAST"}})),limitCount,limitOption:"LIMIT_OPTION_COUNT",op:"SETOP_NONE"}},sources,flat:!1,names,nkeys:keys.length}}var PROCEDURE_MODES=["caller","trusted"],returningClause=ast=>!!ast[Object.keys(ast)[0]]?.returningClause,stmtOf=(c,sql4)=>{let target2=writeTarget(c.ast);return{sql:sql4,binds:c.binds,kind:c.kind,...c.schema?{schema:c.schema}:{},...c.verb?{verb:c.verb}:{},...c.hooked?{hooked:!0}:{},...c.publish?{publish:!0}:{},...returningClause(c.ast)?{returns:!0}:{},...target2?{target:target2}:{}}},message=e=>e instanceof Error?e.message.split(`
|
|
3
|
-
`)[0]:String(e),printer=dialect=>dialect.print.bind(dialect);function lowerView(env,p,mode,columns2=schemaColumns(env.schemas),warn,at="",project,pageQuery){let print3=printer(env.dialect),c;try{[c]=compileProgram(p.ir,{dialect:env.dialect,schemas:env.schemas,columns:columns2,inputs:p.inputs,kind:"view",mode,restrict:p.restrict})}catch(e){warn?.(`${at} (${mode}): ${message(e)}`);return}let nkeys=c.ast.SelectStmt.sortClause?.length??0,paged={},pageCompiled=pageQuery?{...c,ast:pageQuery(c.ast)}:c;for(let cursor of[void 0,...nkeys?[Array(nkeys).fill(0)]:[]])try{let pg=pagedOf(env,pageCompiled,cursor,void 0);paged[pageShape(nkeys,cursor,void 0)]={sql:print3(project?.(pg.ast,pg)??pg.ast,env.schemas),sources:pg.sources,...pg.flat?{flat:!0}:{},names:pg.names,nkeys:pg.nkeys}}catch(e){warn?.(`${at} (${mode}, ${cursor?"next page":"first page"}): ${message(e)}`)}return{...stmtOf(c,print3(project?.(c.ast)??c.ast,env.schemas)),nkeys,paged}}function lowerProcedure(env,p,mode,returning2,columns2=schemaColumns(env.schemas),warn,at="",project){try{let print3=printer(env.dialect);return compileProgram(p.ir,{dialect:env.dialect,schemas:env.schemas,columns:columns2,inputs:p.inputs,kind:"procedure",mode,returning:returning2,restrict:p.restrict}).map(c=>stmtOf(c,print3(project?.(c.ast)??c.ast,env.schemas)))}catch(e){warn?.(`${at} (${mode}): ${message(e)}`);return}}function lowerPlan(plan,dialect,options={}){let warnings=[],warn=m=>warnings.push(m),env={dialect,schemas:plan.schemas},columns2=schemaColumns(plan.schemas),{before,after}=lifecycleHookSets(plan),returning2=before.size||after.size?after:void 0,views=Object.entries(plan.views).flatMap(([name4,v])=>{let modes=v.surface==="public"?["public"]:["caller","trusted"],lowered=Object.fromEntries(modes.flatMap(mode=>{let x=lowerView(env,{inputs:v.inputs,ir:v.stmts,restrict:v.restrict},mode,columns2,warn,`plan#/views/${name4}`,options.project&&((ast,page)=>options.project(ast,"view",name4,page)),options.pageQuery&&(ast=>options.pageQuery(ast,name4)));return x?[[mode,x]]:[]}));return Object.keys(lowered).length?[[name4,lowered]]:[]}),procedures=Object.entries(plan.procedures).flatMap(([name4,proc])=>{if(!("sql"in proc.handler))return[];let{inputs}=proc,ir=proc.handler.sql.stmts,lowered=Object.fromEntries(PROCEDURE_MODES.flatMap(mode=>{let x=lowerProcedure(env,{inputs,ir,restrict:proc.restrict},proc.trustedOnly?"trusted":mode,returning2,columns2,warn,`plan#/procedures/${name4}`,options.project&&(ast=>options.project(ast,"procedure",name4)));return x?[[mode,x]]:[]}));return Object.keys(lowered).length?[[name4,lowered]]:[]});return{lowered:{mantle:MANTLE_VERSION,dialect:{name:dialect.name,version:dialect.version,key:dialect.lowerKey??""},views:Object.fromEntries(views),procedures:Object.fromEntries(procedures)},warnings}}var US_PER_DAY=864e8;function sqliteType(type){if(parseNumeric(type))return"integer";switch(type){case"text":case"json":case"geo":return"text";case"int4":case"int8":case"integer":case"bool":case"timestamptz":case"date":return"integer";case"float8":case"real":return"real"}throw new SqlRefusal("SQL_TYPE",`unknown type ${type}`)}function encodeNumeric(v,p,s){let str2=typeof v=="number"?v.toString():v.trim(),m=/^(-?)(\d+)(?:\.(\d+))?$/.exec(str2);if(!m)throw new SqlRefusal("SQL_TYPE",`${str2} is not a decimal number`);let frac=m[3]??"";if(frac.length>s)throw new SqlRefusal("SQL_TYPE",`${str2} has more than ${s} fractional digits`);let digits=m[2]+frac.padEnd(s,"0");if(digits.replace(/^0+/,"").length>p)throw new SqlRefusal("SQL_TYPE",`${str2} does not fit numeric(${p}, ${s})`);let n=Number(digits);return m[1]?-n:n}function decodeNumeric(n,s){let neg=n<0,d=Math.abs(n).toString().padStart(s+1,"0"),out=s?`${d.slice(0,-s)}.${d.slice(-s)}`:d;return neg?`-${out}`:out}function encodeTimestamptz(v){if(v instanceof Date)return v.getTime()*1e3;if(typeof v=="number"){if(!Number.isSafeInteger(v))throw new SqlRefusal("SQL_TYPE",`${v} is not a whole number of microseconds within 2^53`);return v}let m=/^(\d{4}-\d\d-\d\d)[T ](\d\d:\d\d(?::\d\d)?)(?:\.(\d{1,6}))?(Z|[+-]\d\d(?::?\d\d)?)$/.exec(v.trim());if(!m)throw new SqlRefusal("SQL_TYPE",`'${v}' is not a timestamp with an explicit offset`);let[,day,time,fraction,offset]=m,frac=(fraction??"").padEnd(6,"0"),zone=offset==="Z"?"Z":offset.length===3?`${offset}:00`:offset.includes(":")?offset:`${offset.slice(0,3)}:${offset.slice(3)}`,secs=Date.parse(`${day}T${time.length===5?time+":00":time}${zone}`);encodeDate(day);let micros=secs*1e3+Number(frac);if(Number.isNaN(secs)||!Number.isSafeInteger(micros))throw new SqlRefusal("SQL_TYPE",`'${v}' is not a valid timestamp`);return micros}function decodeTimestamptz(us){let ms=Math.floor(us/1e3),rest=us-ms*1e3;return new Date(ms).toISOString().replace("Z",String(rest).padStart(3,"0")+"Z")}function encodeDate(v){let m=/^(\d{4})-(\d\d)-(\d\d)$/.exec(typeof v=="string"?v:v.toISOString().slice(0,10));if(!m)throw new SqlRefusal("SQL_TYPE",`'${v}' is not a date`);let[,y,mo,d]=m,dt=new Date(0);dt.setUTCFullYear(+y,+mo-1,+d);let days=dt.getTime()/(US_PER_DAY/1e3);if(dt.getUTCDate()!==+d)throw new SqlRefusal("SQL_TYPE",`'${v}' is not a valid date`);return days}var decodeDate=days=>new Date(days*864e5).toISOString().slice(0,10);var fn=(f,...args)=>({FuncCall:{funcname:[S(f)],args,funcformat:"COERCE_EXPLICIT_CALL"}}),cast=(x,t)=>({TypeCast:{arg:x,typeName:{names:[S(t)],typemod:-1}}}),clone=x=>structuredClone(x),TOKEN=/"(?:[^"]|"")*"|'(?:[^']|'')*'|__\w+/g;function sql(text,subst={}){let parts=[],last=0;for(let m of text.matchAll(TOKEN)){if(!m[0].startsWith("__"))continue;let node=subst[m[0]];if(!node)throw new Error(`lowering template names ${m[0]} but was not given it`);m.index>last&&parts.push(text.slice(last,m.index)),parts.push("(",clone(node),")"),last=m.index+m[0].length}return last<text.length&&parts.push(text.slice(last)),{Raw:{parts}}}var q=id=>`"${id.replace(/"/g,'""')}"`,OFF=x=>`coalesce((SELECT offset_us FROM _mantle_tz WHERE from_us <= ${x} ORDER BY from_us DESC LIMIT 1), 0)`,FD=(a,b)=>`((${a} - ((${a} % ${b}) + ${b}) % ${b}) / ${b})`,LOCAL=`(__ts + ${OFF("__ts")})`,DAY=864e8,TRUNC={hour:`(${FD(LOCAL,36e8)} * 3600000000)`,day:`(${FD(LOCAL,DAY)} * ${DAY})`,week:`((${FD(LOCAL,DAY)} - (((${FD(LOCAL,DAY)} + 3) % 7 + 7) % 7)) * ${DAY})`,month:`(unixepoch(strftime('%Y-%m-01 00:00:00', ${FD(LOCAL,1e6)}, 'unixepoch')) * 1000000)`,year:`(unixepoch(strftime('%Y-01-01 00:00:00', ${FD(LOCAL,1e6)}, 'unixepoch')) * 1000000)`},EXTRACT={year:"%Y",month:"%m",day:"%d",hour:"%H",dow:"%w"},HAV=(lat1,lng1)=>`(2 * 6371008.8 * asin(min(1.0, sqrt(sin(radians(__lat - ${lat1}) / 2) * sin(radians(__lat - ${lat1}) / 2) + cos(radians(${lat1})) * cos(radians(__lat)) * sin(radians(__lng - ${lng1}) / 2) * sin(radians(__lng - ${lng1}) / 2)))))`,strConst=n=>n?.A_Const?.sval?.sval,argOf=(n,scope)=>{let k=n.ColumnRef?.fields?.length===2?n.ColumnRef.fields[1].String.sval:void 0;return k?{input:k,type:scope.inputs[k]}:{const:Number(n.A_Const?.ival?.ival??n.A_Const?.fval?.fval)}};function lowerFunc2(f,n,scope){let args=n.args??[];switch(f){case"date_trunc":{let ts=scope.tx(args[1]);return sql(`(${TRUNC[strConst(args[0])]}) - ${OFF(`(${TRUNC[strConst(args[0])]}) - ${OFF("__ts")}`)}`,{__ts:ts})}case"extract":{let ts=scope.tx(args[1]);return sql(`CAST(strftime('${EXTRACT[strConst(args[0])]}', ${FD(LOCAL,1e6)}, 'unixepoch') AS INTEGER)`,{__ts:ts})}case"mantle.search":case"mantle.search_rank":{let alias=args[0].ColumnRef.fields[0].String.sval,{schema,def,searchQuery}=scope.alias(alias);if(!def.search?.length)throw new SqlRefusal("SQL_FUNCTION",`${schema} declares no search fields`);scope.seen("search");let fts=q(ftsTableName(schema)),a=q(alias),query=scope.tx(f==="mantle.search"?args[1]:searchQuery??(()=>{throw new SqlRefusal("SQL_FUNCTION",`mantle.search_rank(${alias}) needs a mantle.search(${alias}, ...) in the same query`)})()),phrase=`'"' || replace(__q, '"', '""') || '"'`;if(f==="mantle.search_rank")return sql(`coalesce((SELECT bm25(${fts}) FROM ${fts} WHERE ${fts} = ${phrase} AND rowid = ${a}._rid), 0)`,{__q:query});let like=def.search.map(fld=>`${a}.${q(fld)} LIKE '%' || replace(replace(replace(__q, '!', '!!'), '%', '!%'), '_', '!_') || '%' ESCAPE '!'`).join(" OR ");return sql(`CASE WHEN length(__q) >= 3 THEN ${a}._rid IN (SELECT rowid FROM ${fts} WHERE ${fts} = ${phrase}) ELSE (${like}) END`,{__q:query})}case"mantle.near":case"mantle.distance":{let[ref2,latN,lngN]=args,alias=ref2.ColumnRef.fields[0].String.sval,fld=ref2.ColumnRef.fields[1].String.sval,{schema,def}=scope.alias(alias);if(def.fields[fld]!=="geo")throw new SqlRefusal("SQL_FUNCTION",`${schema}.${fld} is not a geo field`);let a=q(alias),dist=HAV(`${a}.${q(fld+"_lat")}`,`${a}.${q(fld+"_lng")}`),sub={__lat:scope.tx(latN),__lng:scope.tx(lngN)};if(f==="mantle.distance")return sql(dist,sub);scope.seen("near");let meters=Number(args[3].A_Const.ival?.ival??args[3].A_Const.fval?.fval),b=which=>scope.param({k:"dialect",box:which,lat:argOf(latN,scope),lng:argOf(lngN,scope),meters}),geo=q(geoTreeName(schema,fld));return sql(`(${a}._rid IN (SELECT id FROM ${geo} WHERE minLat >= __b0 AND maxLat <= __b1 AND minLng >= __b2 AND maxLng <= __b3) AND ${dist} <= ${meters})`,{...sub,__b0:b("minLat"),__b1:b("maxLat"),__b2:b("minLng"),__b3:b("maxLng")})}}}var value=x=>({Raw:{parts:[x," + 0"]}});function lowerCast(n,scope){let t=n.typeName.names.at(-1).String.sval,lit3=n.arg?.A_Const,litStr=lit3?.sval?.sval??lit3?.fval?.fval??(lit3?.ival?.ival!==void 0?String(lit3.ival.ival):void 0);if(t==="interval")return value(num(intervalMicros(lit3.sval.sval,n.typeName.typmods?.[0]?.A_Const?.ival?.ival)));if(t==="timestamptz")return value(num(encodeTimestamptz(litStr)));if(t==="date")return value(num(encodeDate(litStr)));if(t==="numeric"){let[p,s]=n.typeName.typmods.map(m=>m.A_Const.ival.ival);return parseNumeric(`numeric(${p}, ${s})`),value(num(encodeNumeric(litStr,p,s)))}if(t==="bool")return sql("CASE WHEN typeof(__x) = 'text' THEN lower(__x) IN ('t', 'true', 'y', 'yes', 'on', '1') WHEN __x IS NULL THEN NULL ELSE __x <> 0 END",{__x:scope.tx(n.arg)});let target2=t==="int4"||t==="int8"?"integer":t==="float8"?"real":"text";return cast(scope.tx(n.arg),target2)}var d1Lowering={input:(param2,type)=>cast(param2,sqliteType(type)),func:lowerFunc2,call(out){return out.funcname[0].String.sval==="pg_catalog"&&(out.funcname=out.funcname.slice(1)),out.funcname.length===1&&out.funcname[0].String.sval==="btrim"&&(out.funcname=[S("trim")]),out.funcformat="COERCE_EXPLICIT_CALL",{FuncCall:out}},cast:lowerCast,anyOf:(x,set)=>sql("__x IN (SELECT value FROM json_each(__set))",{__x:x,__set:set}),sublink(out){return out.subLinkType==="ANY_SUBLINK"&&delete out.operName,{SubLink:out}},newId:()=>fn("lower",fn("hex",fn("randomblob",num(16)))),columns:s=>s.search?.length||Object.values(s.fields).includes("geo")?[target(ref("rowid"),"_rid")]:[]};import{Deparser}from"pgsql-deparser";var SqliteDeparser=class extends Deparser{ParamRef(n){return`?${n.number}`}TypeCast(n,ctx){return`CAST(${this.visit(n.arg,ctx)} AS ${n.typeName.names.at(-1).String.sval})`}A_Const(n,ctx){return n.sval?`'${String(n.sval.sval??"").replace(/'/g,"''")}'`:n.boolval?n.boolval.boolval===!0?"(1 = 1)":"(1 = 0)":super.A_Const(n,ctx)}A_Expr(node,ctx){let n=parenthesized("A_Expr",node),fc=n.rexpr?.FuncCall;if(n.kind==="AEXPR_LIKE"&&fc?.funcname?.at(-1)?.String?.sval==="like_escape"&&fc.args?.length===2){let[pat,esc]=fc.args,not=n.name[0].String.sval==="!~~"?"NOT ":"";return`${this.visit(n.lexpr,ctx)} ${not}LIKE ${this.visit(pat,ctx)} ESCAPE ${this.visit(esc,ctx)}`}let sign=n.name?.[0]?.String?.sval;return n.kind==="AEXPR_OP"&&!n.lexpr&&(sign==="+"||sign==="-")?`(${sign}(${this.visit(n.rexpr,ctx)}) + 0)`:super.A_Expr(n,ctx)}NullTest(n,ctx){return super.NullTest(parenthesized("NullTest",n),ctx)}BooleanTest(n,ctx){return super.BooleanTest(parenthesized("BooleanTest",n),ctx)}SubLink(n,ctx){return super.SubLink(parenthesized("SubLink",n),ctx)}Raw(n,ctx){return`(${n.parts.map(p=>typeof p=="string"?p:this.visit(p,ctx)).join("")})`}};function print(ast){return new SqliteDeparser([ast],{pretty:!1}).deparseQuery()}var d1Dialect={name:name2,version,check:validateIr2,lowering:d1Lowering,print:ast=>print(ast)};var compile_exports2={};__export(compile_exports2,{accepts:()=>validateProgram3,name:()=>name3,version:()=>version2});var REFUSED={typeof:"typeof() is SQLite's; PostgreSQL has pg_typeof() with other names",hex:"hex() is SQLite's; PostgreSQL's encode() is not on the allowlist",json_each:"json_each() is SQLite's: use jsonb_array_elements_text(x) WITH ORDINALITY AS j(value, n) for an array, or jsonb_each_text(x) WITH ORDINALITY AS j(key, value, n) for an object, in FROM",json_extract:"json_extract() is SQLite's: use x ->> 'key', x ->> 0 or x #>> '{a,b}'",json_set:"json_set() is SQLite's: build the value with jsonb_build_object() or jsonb_build_array()",json_insert:"json_insert() is SQLite's: build the value with jsonb_build_object() or jsonb_build_array()",json_remove:"json_remove() is SQLite's: use x - 'key' to drop a key"},DOLLAR_PATH=/^\$(?:[.[]|$)/;function refuse2(stmts){let walk3=v=>{if(Array.isArray(v))return v.forEach(walk3);if(!v||typeof v!="object")return;let a=v.A_Expr,key=a?.rexpr?.A_Const?.sval?.sval;if(a?.kind==="AEXPR_OP"&&["->>","->"].includes(a.name?.at(-1)?.String?.sval)&&typeof key=="string"&&DOLLAR_PATH.test(key))throw new SqlRefusal("SQL_UNSUPPORTED",`'${key}' is a SQLite JSON path: PostgreSQL reads it as a key named ${key}. Use x ->> 'key', x ->> 0 or x #>> '{a,b}'`,a.rexpr.A_Const.location??a.location);let f=v.FuncCall;if(f){let name4=f.funcname.map(x=>x.String?.sval).join(".").replace(/^pg_catalog\./,"");if(REFUSED[name4])throw new SqlRefusal("SQL_FUNCTION",REFUSED[name4],f.location);if(name4==="json_array_length"&&f.args?.length!==1)throw new SqlRefusal("SQL_FUNCTION","json_array_length() takes one argument on PostgreSQL",f.location)}Object.values(v).forEach(walk3)};walk3(stmts)}function validateProgram3(stmts,ctx,locs=[]){refuse2(stmts),validateProgram(stmts,ctx,locs,PROFILES.reference)}function validateIr3(plan,ctx){let d=validateIr(plan,ctx,PROFILES.reference);if(d.length)return d;try{return refuse2(plan.stmts),[]}catch(e){return[{code:e.code??"SQL_UNSUPPORTED",message:e.message}]}}var name3="@aotter/mantle/postgres",version2="2";function pgType(type){let num2=parseNumeric(type);if(num2)return`numeric(${num2.p}, ${num2.s})`;switch(type){case"text":case"geo":return"text";case"json":return"jsonb";case"int4":return"int4";case"int8":case"integer":return"int8";case"float8":case"real":return"float8";case"bool":return"bool";case"timestamptz":return"timestamptz";case"date":return"date"}throw new SqlRefusal("SQL_TYPE",`unknown type ${type}`)}var fn2=(f,args,extra={})=>({FuncCall:{funcname:[S(f)],args,funcformat:"COERCE_EXPLICIT_CALL",...extra}}),str=s=>({A_Const:{sval:{sval:s}}});function cast2(x,type){let t=pgType(type),m=/^numeric\((\d+), (\d+)\)$/.exec(t);return{TypeCast:{arg:x,typeName:m?{names:[S("numeric")],typmods:[num(Number(m[1])),num(Number(m[2]))],typemod:-1}:{names:[S(t)],typemod:-1}}}}var coalesce=(...args)=>({CoalesceExpr:{args}}),authored=(n,scope)=>n.agg_filter?{agg_filter:scope.tx(n.agg_filter)}:{},by=node=>({SortBy:{node:structuredClone(node),sortby_dir:"SORTBY_DEFAULT",sortby_nulls:"SORTBY_NULLS_DEFAULT"}}),json=text=>({TypeCast:{arg:str(text),typeName:{names:[S("json")],typemod:-1}}}),argOf2=(n,scope)=>{let k=n.ColumnRef?.fields?.length===2?n.ColumnRef.fields[1].String.sval:void 0;return k?{input:k,type:scope.inputs[k]}:{const:Number(n.A_Const?.ival?.ival??n.A_Const?.fval?.fval)}},HAV2=(lat1,lng1)=>`(2 * 6371008.8 * asin(least(1.0, sqrt(sin(radians(__lat - ${lat1}) / 2) * sin(radians(__lat - ${lat1}) / 2) + cos(radians(${lat1})) * cos(radians(__lat)) * sin(radians(__lng - ${lng1}) / 2) * sin(radians(__lng - ${lng1}) / 2)))))`,TOKEN2=/"(?:[^"]|"")*"|'(?:[^']|'')*'|__\w+/g;function sql2(text,subst={}){let parts=[],last=0;for(let m of text.matchAll(TOKEN2)){if(!m[0].startsWith("__"))continue;let node=subst[m[0]];if(!node)throw new Error(`lowering template names ${m[0]} but was not given it`);m.index>last&&parts.push(text.slice(last,m.index)),parts.push("(",structuredClone(node),")"),last=m.index+m[0].length}return last<text.length&&parts.push(text.slice(last)),{Raw:{parts}}}var q2=id=>`"${id.replace(/"/g,'""')}"`,lit=s=>`'${s.replace(/'/g,"''")}'`,strConst2=n=>n?.A_Const?.sval?.sval;function pgLowering(timeZone){let zone=str(timeZone);return{input:(param2,type)=>cast2(param2,type),system:(param2,type)=>cast2(param2,type),func(f,n,scope){let args=n.args??[];switch(f){case"date_trunc":return fn2("date_trunc",[args[0],scope.tx(args[1]),zone]);case"extract":return sql2(`CAST(extract(${strConst2(args[0])} FROM __ts AT TIME ZONE ${lit(timeZone)}) AS int8)`,{__ts:scope.tx(args[1])});case"json_group_array":{let x=scope.tx(args[0]);return coalesce(fn2("json_agg",[x],{...n.agg_distinct?{agg_order:[by(x)],agg_distinct:!0}:{agg_order:n.agg_order?scope.tx(n.agg_order):[by(fn2("to_jsonb",[x]))]},...authored(n,scope)}),json("[]"))}case"json_group_object":{let k=scope.tx(args[0]);return coalesce(fn2("json_object_agg",[k,scope.tx(args[1])],{agg_order:n.agg_order?scope.tx(n.agg_order):[by(k)],...authored(n,scope)}),json("{}"))}case"json_array_length":return fn2("jsonb_array_length",[cast2(scope.tx(args[0]),"json")]);case"instr":return fn2("strpos",[scope.tx(args[0]),scope.tx(args[1])]);case"round":return args.length===2?fn2("round",[{TypeCast:{arg:scope.tx(args[0]),typeName:{names:[S("numeric")],typemod:-1}}},scope.tx(args[1])]):void 0;case"mantle.search":{let alias=args[0].ColumnRef.fields[0].String.sval,{schema,def}=scope.alias(alias);if(!def.search?.length)throw new SqlRefusal("SQL_FUNCTION",`${schema} declares no search fields`);scope.seen("search");let pattern="'%' || replace(replace(replace(__q, '!', '!!'), '%', '!%'), '_', '!_') || '%'";return sql2(def.search.map(fld=>`${q2(alias)}.${q2(fld)} ILIKE ${pattern} ESCAPE '!'`).join(" OR "),{__q:scope.tx(args[1])})}case"mantle.search_rank":{let alias=args[0].ColumnRef.fields[0].String.sval,{schema,def,searchQuery}=scope.alias(alias);if(!def.search?.length)throw new SqlRefusal("SQL_FUNCTION",`${schema} declares no search fields`);if(!searchQuery)throw new SqlRefusal("SQL_FUNCTION",`mantle.search_rank(${alias}) needs a mantle.search(${alias}, ...) in the same query`);let count=fld=>`coalesce((length(lower(${q2(alias)}.${q2(fld)})) - length(replace(lower(${q2(alias)}.${q2(fld)}), lower(__q), ''))) / greatest(length(__q), 1), 0)`;return sql2(`-(${def.search.map(count).join(" + ")})`,{__q:scope.tx(searchQuery)})}case"mantle.near":case"mantle.distance":{let[ref2,latN,lngN]=args,alias=ref2.ColumnRef.fields[0].String.sval,fld=ref2.ColumnRef.fields[1].String.sval,{schema,def}=scope.alias(alias);if(def.fields[fld]!=="geo")throw new SqlRefusal("SQL_FUNCTION",`${schema}.${fld} is not a geo field`);let la=`${q2(alias)}.${q2(`${fld}_lat`)}`,ln=`${q2(alias)}.${q2(`${fld}_lng`)}`,sub={__lat:scope.tx(latN),__lng:scope.tx(lngN)};if(f==="mantle.distance")return sql2(HAV2(la,ln),sub);scope.seen("near");let meters=Number(args[3].A_Const.ival?.ival??args[3].A_Const.fval?.fval),b=box=>scope.param({k:"dialect",box,lat:argOf2(latN,scope),lng:argOf2(lngN,scope),meters});return sql2(`${la} BETWEEN __b0 AND __b1 AND ${ln} BETWEEN __b2 AND __b3 AND ${HAV2(la,ln)} <= ${meters}`,{...sub,__b0:b("minLat"),__b1:b("maxLat"),__b2:b("minLng"),__b3:b("maxLng")})}case"typeof":case"hex":case"json_extract":case"json_set":case"json_insert":case"json_remove":throw new SqlRefusal("SQL_FUNCTION",`${f} is not supported by the PostgreSQL dialect`)}},call:out=>({FuncCall:out}),anyOf:(x,set,type)=>sql2(`__x = ANY(CAST(CAST(__set AS text) AS ${pgType(type==="number"?"real":"text")}[]))`,{__x:x,__set:set}),cast(n,scope){let t=n.typeName.names.at(-1).String.sval,a=n.arg?.A_Const,text=a?.sval?.sval??a?.fval?.fval??(a?.ival?.ival!==void 0?String(a.ival.ival):void 0);if(t==="timestamptz"&&text!==void 0)return cast2(str(decodeTimestamptz(encodeTimestamptz(text))),"timestamptz");if(t==="date"&&text!==void 0)return cast2(str(decodeDate(encodeDate(text))),"date");if(t==="numeric"&&n.typeName.typmods?.length===2){let[p,s]=n.typeName.typmods.map(m=>m.A_Const.ival.ival);if(parseNumeric(`numeric(${p}, ${s})`),text!==void 0)return cast2(str(decodeNumeric(encodeNumeric(text,p,s),s)),`numeric(${p},${s})`)}return{TypeCast:{...n,arg:scope.tx(n.arg)}}},sublink:out=>({SubLink:out}),newId:()=>fn2("replace",[{TypeCast:{arg:fn2("gen_random_uuid",[]),typeName:{names:[S("text")],typemod:-1}}},str("-"),str("")]),columns:()=>[]}}import{Deparser as Deparser2}from"pgsql-deparser";var PgDeparser=class extends Deparser2{A_Expr(n,ctx){return super.A_Expr(parenthesized("A_Expr",n),ctx)}NullTest(n,ctx){return super.NullTest(parenthesized("NullTest",n),ctx)}BooleanTest(n,ctx){return super.BooleanTest(parenthesized("BooleanTest",n),ctx)}SubLink(n,ctx){return super.SubLink(parenthesized("SubLink",n),ctx)}FuncCall(n,ctx){return n.funcname?.length!==2||n.funcname[0]?.String?.sval!=="pg_catalog"||n.funcname[1]?.String?.sval==="like_escape"?super.FuncCall(n,ctx):`(${super.FuncCall({...n,args:n.args?.map(paren)},ctx)})`}Raw(n,ctx){return`(${n.parts.map(p=>typeof p=="string"?p:this.visit(p,ctx)).join("")})`}};function print2(ast){return new PgDeparser([ast],{pretty:!1}).deparseQuery()}function columnType2(s,col){switch(col){case"id":case"author_id":case"status":return"text";case"version":return"integer";case"created_at":case"updated_at":return"timestamptz"}if(col===s.scope)return"text";let geo=/^(.+)_(lat|lng)$/.exec(col);if(geo&&s.fields[geo[1]]==="geo")return"real";let t=s.fields[col];return t==="geo"?void 0:t}function typed(ast,schemas){let walk3=v=>{if(Array.isArray(v))return v.map(walk3);if(!v||typeof v!="object")return v;let out=Object.fromEntries(Object.entries(v).map(([k,c])=>[k,walk3(c)]));return out.InsertStmt&&insert2(out.InsertStmt),out.UpdateStmt&&assign(out.UpdateStmt.relation.relname,out.UpdateStmt.targetList),out},typeOf=(table,col)=>schemas[table]?columnType2(schemas[table],col.toLowerCase()):void 0,to=(table,col,val)=>{let t=typeOf(table,col);return t?cast2(val,t):val},assign=(table,targets)=>{for(let t of targets??[])t.ResTarget?.name&&t.ResTarget.val&&(t.ResTarget.val=to(table,t.ResTarget.name,t.ResTarget.val))},insert2=n=>{let table=n.relation.relname,cols=(n.cols??[]).map(c=>c.ResTarget.name),sel=n.selectStmt?.SelectStmt,list=sel?.targetList??[],star=list[0]?.ResTarget?.val?.ColumnRef?.fields,from=sel?.fromClause?.[0]?.RangeSubselect,k=cols.length-(list.length-1),inner=from?.subquery?.SelectStmt,first=b=>b?.op&&b.op!=="SETOP_NONE"?first(b.larg):b,width=inner?.valuesLists?.[0]?.List?.items?.length??first(inner)?.targetList?.length;if(star?.length===2&&star[1].A_Star&&from?.alias?.aliasname===star[0].String?.sval&&width===k){from.alias.colnames=Array.from({length:k},(_x,i)=>S(`c${i}`));let authored2=Array.from({length:k},(_x,i)=>({ResTarget:{val:to(table,cols[i],{ColumnRef:{fields:[S(from.alias.aliasname),S(`c${i}`)]}})}}));sel.targetList=[...authored2,...list.slice(1).map((t,j)=>({ResTarget:{...t.ResTarget,val:to(table,cols[k+j],t.ResTarget.val)}}))]}else sel?.targetList&&!sel.valuesLists&&(sel.targetList=list.map((t,i)=>cols[i]?{ResTarget:{...t.ResTarget,val:to(table,cols[i],t.ResTarget.val)}}:t));let target2=n.relation.alias?.aliasname??table,qualify=v=>Array.isArray(v)?v.map(qualify):!v||typeof v!="object"||v.SubLink?v:v.ColumnRef?.fields?.length===1&&v.ColumnRef.fields[0].String?{ColumnRef:{fields:[S(target2),v.ColumnRef.fields[0]]}}:Object.fromEntries(Object.entries(v).map(([k2,c])=>[k2,qualify(c)]));for(let t of n.onConflictClause?.targetList??[])t.ResTarget.val=qualify(t.ResTarget.val);n.onConflictClause?.whereClause&&(n.onConflictClause.whereClause=qualify(n.onConflictClause.whereClause)),assign(table,n.onConflictClause?.targetList)};return walk3(ast)}function postgresDialect(timeZone="UTC"){if(new Intl.DateTimeFormat("en-US",{timeZone}),/^[+-]|^(utc|gmt)[+-]/i.test(timeZone))throw new RangeError(`timeZone must be an IANA name such as Asia/Taipei, not the offset ${timeZone}`);return{name:name3,version:version2,check:validateIr3,lowering:pgLowering(timeZone),nativeOrder:!0,nativeSql:!0,print:(ast,schemas)=>print2(typed(ast,schemas)),lowerKey:timeZone}}var q3=id=>`"${id.replace(/"/g,'""')}"`,lit2=s=>`'${s.replace(/'/g,"''")}'`;function colType(t){if(parseNumeric(t))return"INTEGER";switch(t){case"text":case"json":return"TEXT";case"integer":case"bool":case"timestamptz":case"date":return"INTEGER";case"real":return"REAL"}throw new Error(`no column type for ${t}`)}function checkText(expr,s){let problem3=checkShapeProblem(expr,storageColumns(s));if(problem3)throw new Error(problem3);let qualify=v=>Array.isArray(v)?v.map(qualify):!v||typeof v!="object"?v:v.ColumnRef?.fields?.length===1?{ColumnRef:{fields:[{String:{sval:"new"}},v.ColumnRef.fields[0]]}}:Object.fromEntries(Object.entries(v).map(([k,c])=>[k,qualify(c)])),select2={SelectStmt:{targetList:[{ResTarget:{val:qualify(expr)}}],limitOption:"LIMIT_OPTION_DEFAULT",op:"SETOP_NONE"}};return print(select2).replace(/^SELECT\s+/i,"")}function desired(name4,s){let t=q3(name4),columns2=[{name:"_rid",type:"INTEGER",native:!0},{name:"id",type:"TEXT",native:!0},{name:"version",type:"INTEGER",native:!0},{name:"created_at",type:"INTEGER",native:!0},{name:"updated_at",type:"INTEGER",native:!0},{name:"author_id",type:"TEXT",native:!0},...s.scope?[{name:s.scope,type:"TEXT",native:!0}]:[],...s.publishing?[{name:"status",type:"TEXT",native:!0},{name:"published_at",type:"INTEGER",native:!1}]:[],...Object.entries(s.fields).filter(([f])=>f!==s.scope).flatMap(([f,ty])=>ty==="geo"?[{name:`${f}_lat`,type:"REAL",native:!1},{name:`${f}_lng`,type:"REAL",native:!1}]:[{name:f,type:colType(ty),native:!1}])],indexes2=[...(s.unique??[]).map((u,i)=>({name:`_mantle_uq_${name4}_${i}`,unique:!0,columns:s.userScopes?.length?[...new Set([...s.scope?[s.scope]:[],...s.userScopes.map(x=>x.column),...u])]:s.scope&&u[0]!==s.scope?[s.scope,...u]:[...u]})),...(s.indexes??[]).map((cols,i)=>({name:`_mantle_ix_${name4}_${i}`,unique:!1,columns:cols}))].map(i=>({...i,sql:`CREATE ${i.unique?"UNIQUE ":""}INDEX IF NOT EXISTS ${q3(i.name)} ON ${t} (${i.columns.map(q3).join(", ")})`})),triggers=[];(s.checks??[]).forEach((c,i)=>{let e=checkText(c,s);for(let ev of["INSERT","UPDATE"])triggers.push({name:`_mantle_chk_${name4}_${i}_${ev[0].toLowerCase()}`,sql:`CREATE TRIGGER ${q3(`_mantle_chk_${name4}_${i}_${ev[0].toLowerCase()}`)} BEFORE ${ev} ON ${t} WHEN NOT (${e}) BEGIN SELECT RAISE(ABORT, ${lit2(`MANTLE_CHECK ${name4}: ${e.replace(/\bnew\./g,"")}`)}); END`})});let virtuals=[];if(s.search?.length){let fts=q3(ftsTableName(name4)),f=s.search.map(q3).join(", "),n=s.search.map(c=>`new.${q3(c)}`).join(", "),o=s.search.map(c=>`old.${q3(c)}`).join(", ");virtuals.push({name:ftsTableName(name4),sql:`CREATE VIRTUAL TABLE ${fts} USING fts5(${f}, content=${lit2(name4)}, content_rowid='_rid', tokenize='trigram')`,rebuild:`INSERT INTO ${fts} (${fts}) VALUES ('rebuild')`}),triggers.push({name:`_mantle_fts_${name4}_i`,sql:`CREATE TRIGGER ${q3(`_mantle_fts_${name4}_i`)} AFTER INSERT ON ${t} BEGIN INSERT INTO ${fts} (rowid, ${f}) VALUES (new._rid, ${n}); END`},{name:`_mantle_fts_${name4}_d`,sql:`CREATE TRIGGER ${q3(`_mantle_fts_${name4}_d`)} AFTER DELETE ON ${t} BEGIN INSERT INTO ${fts} (${fts}, rowid, ${f}) VALUES ('delete', old._rid, ${o}); END`},{name:`_mantle_fts_${name4}_u`,sql:`CREATE TRIGGER ${q3(`_mantle_fts_${name4}_u`)} AFTER UPDATE OF ${f} ON ${t} BEGIN INSERT INTO ${fts} (${fts}, rowid, ${f}) VALUES ('delete', old._rid, ${o}); INSERT INTO ${fts} (rowid, ${f}) VALUES (new._rid, ${n}); END`})}for(let[geo,ty]of Object.entries(s.fields)){if(ty!=="geo")continue;let tree=geoTreeName(name4,geo),g=q3(tree),la=q3(`${geo}_lat`),ln=q3(`${geo}_lng`);virtuals.push({name:tree,sql:`CREATE VIRTUAL TABLE ${g} USING rtree(id, minLat, maxLat, minLng, maxLng)`,rebuild:`INSERT INTO ${g} SELECT _rid, ${la}, ${la}, ${ln}, ${ln} FROM ${t} WHERE ${la} IS NOT NULL AND ${ln} IS NOT NULL`}),triggers.push({name:`${tree}_i`,sql:`CREATE TRIGGER ${q3(`${tree}_i`)} AFTER INSERT ON ${t} WHEN new.${la} IS NOT NULL AND new.${ln} IS NOT NULL BEGIN INSERT INTO ${g} VALUES (new._rid, new.${la}, new.${la}, new.${ln}, new.${ln}); END`},{name:`${tree}_d`,sql:`CREATE TRIGGER ${q3(`${tree}_d`)} AFTER DELETE ON ${t} BEGIN DELETE FROM ${g} WHERE id = old._rid; END`},{name:`${tree}_u`,sql:`CREATE TRIGGER ${q3(`${tree}_u`)} AFTER UPDATE OF ${la}, ${ln} ON ${t} BEGIN DELETE FROM ${g} WHERE id = old._rid; INSERT INTO ${g} SELECT new._rid, new.${la}, new.${la}, new.${ln}, new.${ln} WHERE new.${la} IS NOT NULL AND new.${ln} IS NOT NULL; END`})}return{table:name4,columns:columns2,indexes:indexes2,triggers,virtuals}}function createTable(d,notNull=new Set){let cols=d.columns.map(c=>c.name==="_rid"?"_rid INTEGER PRIMARY KEY":c.name==="id"?"id TEXT NOT NULL UNIQUE":c.name==="version"?"version INTEGER NOT NULL DEFAULT 1":c.name==="created_at"?"created_at INTEGER NOT NULL":c.name==="updated_at"?"updated_at INTEGER NOT NULL DEFAULT 0":c.name==="author_id"?"author_id TEXT":c.name==="status"?"status TEXT NOT NULL DEFAULT 'draft'":`${q3(c.name)} ${c.type}${c.native&&c.type==="TEXT"||notNull.has(c.name)?" NOT NULL":""}`);return`CREATE TABLE IF NOT EXISTS ${q3(d.table)} (${cols.join(", ")}) STRICT`}var SYSTEM_DDL=["CREATE TABLE IF NOT EXISTS _mantle_assert (op INTEGER, ok INTEGER)","CREATE TRIGGER IF NOT EXISTS _mantle_assert_t BEFORE INSERT ON _mantle_assert BEGIN SELECT CASE WHEN new.ok IS NOT 1 THEN RAISE(ABORT, 'CONFLICT op=' || new.op) ELSE RAISE(IGNORE) END; END","CREATE TABLE IF NOT EXISTS _mantle_tz (from_us INTEGER PRIMARY KEY, offset_us INTEGER NOT NULL) STRICT"];function initialStorageSql(plan){return[SYSTEM_DDL[0],SYSTEM_DDL[1],SYSTEM_DDL[2],"INSERT OR IGNORE INTO _mantle_tz (from_us, offset_us) VALUES (-9007199254740991, 0)",...Object.entries(plan).flatMap(([name4,schema])=>{let d=desired(name4,schema);return[createTable(d,notNullColumns(schema)),...d.indexes.map(i=>i.sql),...d.virtuals.map(i=>i.sql),...d.triggers.map(i=>i.sql)]})]}var q4=id=>`"${id.replace(/"/g,'""')}"`,ident=n=>new TextEncoder().encode(n).length<=63?n:`${n.slice(0,50)}_${fnv(n)}`;function columns(s){return[...s.scope?[{name:s.scope,type:"text",native:!0}]:[],...s.publishing?[{name:"status",type:"text",native:!0},{name:"published_at",type:"timestamptz",native:!1}]:[],...Object.entries(s.fields).filter(([f])=>f!==s.scope).flatMap(([f,ty])=>ty==="geo"?[{name:`${f}_lat`,type:"float8",native:!1},{name:`${f}_lng`,type:"float8",native:!1}]:[{name:f,type:pgType(ty),native:!1}])]}function indexes(name4,s){return[...(s.unique??[]).map((u,i)=>({name:`_mantle_uq_${name4}_${i}`,unique:!0,columns:s.userScopes?.length?[...new Set([...s.scope?[s.scope]:[],...s.userScopes.map(x=>x.column),...u])]:s.scope&&u[0]!==s.scope?[s.scope,...u]:[...u]})),...(s.indexes??[]).map((cols,i)=>({name:`_mantle_ix_${name4}_${i}`,unique:!1,columns:[...cols]})),{name:`_mantle_ix_${name4}_updated`,unique:!1,columns:[...s.scope?[s.scope]:[],"updated_at","id"]}].map(i=>({...i,name:ident(i.name),sql:`CREATE ${i.unique?"UNIQUE ":""}INDEX IF NOT EXISTS ${q4(ident(i.name))} ON ${q4(name4)} (${i.columns.map(q4).join(", ")})`}))}function checkText2(expr,s){let problem3=checkShapeProblem(expr,storageColumns(s));if(problem3)throw new Error(problem3);return print2(typed({SelectStmt:{targetList:[{ResTarget:{val:expr}}],limitOption:"LIMIT_OPTION_DEFAULT",op:"SETOP_NONE"}},{})).replace(/^SELECT\s+/i,"")}var ddlType=type=>type==="text"?'text COLLATE "C"':type,createTable2=(name4,s,notNull=new Set)=>`CREATE TABLE ${q4(name4)} (${["_rid bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY",`id ${ddlType("text")} NOT NULL UNIQUE`,"version int8 NOT NULL DEFAULT 1","created_at timestamptz NOT NULL","updated_at timestamptz NOT NULL DEFAULT now()",`author_id ${ddlType("text")}`,...columns(s).map(c=>`${q4(c.name)} ${ddlType(c.type)}${c.name==="status"?" NOT NULL DEFAULT 'draft'":c.native||notNull.has(c.name)?" NOT NULL":""}`)].join(", ")})`;function initialStorageSql2(plan){return Object.entries(plan).flatMap(([name4,schema])=>[createTable2(name4,schema,notNullColumns(schema)),...indexes(name4,schema).filter(i=>i.name!==ident(`_mantle_ix_${name4}_updated`)).map(i=>i.sql),...(schema.checks??[]).map((check2,i)=>`ALTER TABLE ${q4(name4)} ADD CONSTRAINT ${q4(ident(`_mantle_chk_${name4}_${i}`))} CHECK (${checkText2(check2,schema)})`)])}var propsOf=s=>s.properties??{};function adminIndexColumns(s){let notNull=notNullColumns(s),required=new Set(s.schema.required??[]);return[...s.indexes??[],...s.unique??[]].map(i=>i[0]===s.scope?i[1]:i[0]).filter(f=>!!f&&f!==s.scope&&(required.has(s.names[f]??f)||NATIVE_NOT_NULL.has(f)||notNull.has(f)))}function collectionOf(s,schemas){let names=new Set(schemas.filter(x=>!x.translates).map(x=>x.name)),props=propsOf(s.schema),ui=s.uiSchema??{},list=ui.list??{},nav=ui.nav,filterField=list.filterField,declared=nav?.parentField,parentField=foldParentField(s.schema,declared,name4=>names.has(name4)),navField=nav?.standalone===!0?declared??(s.translates?void 0:requiredMantleRefFields(s.schema).find(r=>names.has(r.collection))?.field):void 0,navParent=navField?resolveMantleRef(props[navField]):null,children=schemas.filter(c=>c.translates?.parent===s.name);return{name:s.name,title:s.title??s.name,description:s.description??null,lifecycle:s.publishing?"publishing":"operational",parent:s.translates?{collection:s.translates.parent,parentField:s.translates.on,childField:s.translates.on}:parentField?{collection:resolveMantleRef(props[parentField]).schema,parentField:resolveMantleRef(props[parentField]).field,childField:parentField}:null,hasTranslations:children.length>0,localized:s.localized===!0||!!s.translates,translates:s.translates??null,schema:s.schema,uiSchema:s.uiSchema??null,mediaFields:[s,...children].flatMap(x=>Object.entries(propsOf(x.schema)).flatMap(([name4,p])=>isMediaMcpHint(p[MCP_HINT_KEYWORD])?[{name:name4,hint:p[MCP_HINT_KEYWORD]}]:[])),sortableFields:[...new Set(adminIndexColumns(s).map(f=>s.names[f]??f))],filter:filterField?{field:filterField,values:enumOptions(props[filterField])?.map(o=>o.value)??[]}:null,list:{primaryField:list.primaryField??null,columns:list.columns??[]},nav:navField&&navParent?{standalone:!0,parentField:navField,parentCollection:navParent.schema}:null}}function isPrimaryCollection(s,schemas){let c=collectionOf(s,schemas);return!s.translates&&(!c.parent||c.nav!==null)}function expression(node){if(!node)return"NULL";if(node.ColumnRef)return node.ColumnRef.fields.map(f=>f.String?f.String.sval:"*").join(".");let c=node.A_Const;if(c){if(c.isnull)return"NULL";if(c.sval)return`'${c.sval.sval.replace(/'/g,"''")}'`;if(c.ival)return String(c.ival.ival??0);if(c.fval)return c.fval.fval;if(c.boolval)return c.boolval.boolval?"TRUE":"FALSE"}let e=node.A_Expr;if(e?.kind==="AEXPR_OP"&&e.name?.length===1){let operand=v=>v.A_Expr||v.BoolExpr?`(${expression(v)})`:expression(v),op2=e.name[0].String.sval;if(!e.lexpr&&e.rexpr)return`${op2}(${expression(e.rexpr)})`;if(e.lexpr&&e.rexpr)return`${operand(e.lexpr)} ${op2} ${operand(e.rexpr)}`}if(node.BoolExpr){let b=node.BoolExpr;return b.boolop==="NOT_EXPR"?`NOT (${expression(b.args[0])})`:b.args.map(a=>`(${expression(a)})`).join(b.boolop==="AND_EXPR"?" AND ":" OR ")}throw new Error("opaque")}var sql3=node=>{try{return expression(node)}catch{return"[SQL expression \u2014 see authored SQL]"}};function procedureFlow(stmts,relations){return stmts.map((stmt,index)=>{let[operation,body]=Object.entries(stmt)[0],assignments=operation==="UpdateStmt"?body.targetList??[]:[],dependencies=relations?.([stmt]);return{index,logic:sqlLogic(stmt),operation:operation.replace("Stmt","").toUpperCase(),table:body.relation?.relname??null,mode:operation==="MergeStmt"?"set":classify(stmt),reads:[...dependencies?.reads??[]].sort(),writes:[...dependencies?.writes??[]].sort(),filter:body.whereClause?sql3(body.whereClause):body.selectStmt?.SelectStmt?.whereClause?sql3(body.selectStmt.SelectStmt.whereClause):null,returns:(body.returningClause?.exprs??[]).map(t=>sql3(t.ResTarget.val)),cases:assignments.flatMap(({ResTarget:target2})=>{let c=target2.val?.CaseExpr;return c?[{field:target2.name,branches:(c.args??[]).map(({CaseWhen:w})=>({condition:c.arg?`(${sql3(c.arg)}) = (${sql3(w.expr)})`:sql3(w.expr),value:sql3(w.result)})),otherwise:sql3(c.defresult)}]:[]})}})}var branch=(kind,label,children=[])=>({kind,label,children});function sqlLogic(node){let list=(items=[])=>items.map(sqlLogic),clause=(label,value2)=>value2?[branch("clause",label,[sqlLogic(value2)])]:[],group=(label,values)=>values?.length?[branch("clause",label,list(values))]:[];if(node.ColumnRef){let names=node.ColumnRef.fields.map(f=>f.String?.sval),result=branch("value",sql3(node));return names.every(n=>typeof n=="string")&&names.length<=2&&(result.column={name:names.at(-1),...names.length===2?{relation:names[0]}:{}}),result}if(node.BoolExpr){let b=node.BoolExpr;return branch("predicate",b.boolop==="AND_EXPR"?"AND \xB7 all conditions":b.boolop==="OR_EXPR"?"OR \xB7 any condition":"NOT",list(b.args))}if(node.A_Expr){let e=node.A_Expr,names={AEXPR_OP_ANY:`${e.name?.[0]?.String?.sval} ANY`,AEXPR_OP_ALL:`${e.name?.[0]?.String?.sval} ALL`,AEXPR_BETWEEN_SYM:"BETWEEN SYMMETRIC",AEXPR_NOT_BETWEEN_SYM:"NOT BETWEEN SYMMETRIC",AEXPR_IN:e.name?.[0]?.String?.sval==="<>"?"NOT IN":"IN",AEXPR_BETWEEN:"BETWEEN",AEXPR_NOT_BETWEEN:"NOT BETWEEN",AEXPR_DISTINCT:"IS DISTINCT FROM",AEXPR_NOT_DISTINCT:"IS NOT DISTINCT FROM",AEXPR_LIKE:e.name?.[0]?.String?.sval==="!~~"?"NOT LIKE":"LIKE",AEXPR_ILIKE:e.name?.[0]?.String?.sval==="!~~*"?"NOT ILIKE":"ILIKE",AEXPR_NULLIF:"NULLIF"};return branch("expression",names[e.kind]??e.name?.map(n=>n.String.sval).join(".")??e.kind,[e.lexpr,e.rexpr].filter(Boolean).map(sqlLogic))}if(node.NullTest)return branch("predicate",node.NullTest.nulltesttype==="IS_NOT_NULL"?"IS NOT NULL":"IS NULL",[sqlLogic(node.NullTest.arg)]);if(node.BooleanTest)return branch("predicate",node.BooleanTest.booltesttype.replaceAll("_"," "),[sqlLogic(node.BooleanTest.arg)]);if(node.CaseExpr){let c=node.CaseExpr;return branch("case",c.arg?"CASE \xB7 match value":"CASE \xB7 first TRUE condition",[...clause("Value",c.arg),...(c.args??[]).map((w,i)=>branch("when",`WHEN ${i+1}`,[branch("predicate","Condition",[sqlLogic(w.CaseWhen.expr)]),branch("value","THEN",[sqlLogic(w.CaseWhen.result)])])),branch("value","ELSE",[c.defresult?sqlLogic(c.defresult):branch("value","NULL")])])}if(node.SubLink){let s=node.SubLink;return branch("subquery",s.subLinkType==="ANY_SUBLINK"?"IN":s.subLinkType.replace("_SUBLINK",""),[...clause("Compared value",s.testexpr),sqlLogic(s.subselect)])}if(node.FuncCall){let f=node.FuncCall;return branch("function",f.funcname.map(n=>n.String.sval).join(".")+(f.agg_distinct?" \xB7 DISTINCT":"")+(f.agg_star?"(*)":""),[...list(f.args),...group("Aggregate ORDER BY",f.agg_order),...clause("FILTER",f.agg_filter),...clause("OVER",f.over?{WindowDef:f.over}:void 0)])}if(node.CoalesceExpr)return branch("function","COALESCE \xB7 first non-NULL value",list(node.CoalesceExpr.args));if(node.MinMaxExpr)return branch("function",node.MinMaxExpr.op==="IS_GREATEST"?"GREATEST":"LEAST",list(node.MinMaxExpr.args));if(node.TypeCast){let t=node.TypeCast;return branch("cast",`CAST \u2192 ${t.typeName.names.map(n=>n.String.sval).join(".")}${t.typeName.typmods?.length?t.typeName.names.at(-1)?.String?.sval==="numeric"?`(${t.typeName.typmods.map(sql3).join(", ")})`:" \xB7 type modifiers: see authored SQL":""}`,[sqlLogic(t.arg)])}if(node.List)return branch("list","Values",list(node.List.items));if(node.ResTarget)return branch("output",node.ResTarget.name??"Output",node.ResTarget.val?[sqlLogic(node.ResTarget.val)]:[]);if(node.SortBy)return branch("order",`${(node.SortBy.sortby_dir??"SORTBY_DEFAULT").replace("SORTBY_","")} \xB7 ${(node.SortBy.sortby_nulls??"SORTBY_NULLS_DEFAULT").replace("SORTBY_","")}`,[sqlLogic(node.SortBy.node)]);if(node.RangeVar)return{...branch("table",node.RangeVar.relname+(node.RangeVar.alias?` AS ${node.RangeVar.alias.aliasname}`:"")),relation:{name:node.RangeVar.relname,...node.RangeVar.alias?{alias:node.RangeVar.alias.aliasname}:{}}};if(node.RangeSubselect)return branch("subquery",`${node.RangeSubselect.lateral?"LATERAL ":""}${node.RangeSubselect.alias?.aliasname??"Subquery"}`,[sqlLogic(node.RangeSubselect.subquery)]);if(node.JoinExpr){let j=node.JoinExpr;return branch("join",`${j.jointype.replace("JOIN_","")} JOIN`,[sqlLogic(j.larg),sqlLogic(j.rarg),...clause("ON",j.quals),...group("USING",j.usingClause)])}if(node.WindowDef){let w=node.WindowDef;return branch("window",`Window${w.name?` ${w.name}`:""} \xB7 ${w.frameOptions&4?"ROWS":"RANGE"} frame (see authored SQL)`,[...group("PARTITION BY",w.partitionClause),...group("ORDER BY",w.orderClause),...clause("Frame start",w.startOffset),...clause("Frame end",w.endOffset)])}if(node.CommonTableExpr)return branch("cte",node.CommonTableExpr.ctename,[sqlLogic(node.CommonTableExpr.ctequery)]);let key=["SelectStmt","UpdateStmt","InsertStmt","DeleteStmt"].find(k=>node[k]);if(key){let b=node[key],children=[...group(b.withClause?.recursive?"WITH RECURSIVE":"WITH",b.withClause?.ctes),...b.relation?[branch("target","Target",[sqlLogic({RangeVar:b.relation})])]:[],...group(key==="UpdateStmt"?"SET":"SELECT",b.targetList),...group("FROM",b.fromClause??b.usingClause),...clause("WHERE \xB7 keep TRUE rows",b.whereClause),...group("GROUP BY",b.groupClause),...clause("HAVING \xB7 keep TRUE groups",b.havingClause),...group("ORDER BY",b.sortClause),...clause("LIMIT",b.limitCount),...group("VALUES",b.valuesLists),...group("Columns",b.cols),...clause("Source SELECT",b.selectStmt),...group("RETURNING",b.returningClause?.exprs)];if(b.distinctClause&&children.push(branch("clause",b.distinctClause.some(n=>n&&Object.keys(n).length)?"DISTINCT ON":"DISTINCT",list(b.distinctClause.filter(n=>n&&Object.keys(n).length)))),b.op&&b.op!=="SETOP_NONE"&&children.push(branch("set",b.op.replace("SETOP_","")+(b.all?" ALL":""),[sqlLogic({SelectStmt:b.larg}),sqlLogic({SelectStmt:b.rarg})])),b.onConflictClause){let c=b.onConflictClause;children.push(branch("conflict",`ON CONFLICT \xB7 ${c.action.replace("ONCONFLICT_","")}`,[...group("Conflict columns",c.infer?.indexElems),...group("SET",c.targetList),...clause("WHERE",c.whereClause)]))}return branch("statement",key.replace("Stmt","").toUpperCase(),children)}if(node.String)return branch("value",node.String.sval);if(node.IndexElem)return branch("column",node.IndexElem.name);let rendered=sql3(node);return branch(rendered.startsWith("[SQL")?"opaque":"value",rendered.startsWith("[SQL")?`${Object.keys(node)[0]} \xB7 see authored SQL`:rendered)}function rowPreconditions(stmts,target2,idInput,schema){let writes=stmts.flatMap(stmt=>[stmt.UpdateStmt??stmt.DeleteStmt].filter(body2=>body2?.relation?.relname?.toLowerCase()===target2.toLowerCase()));if(writes.length!==1)return[];let body=writes[0];if(body.fromClause?.length||body.usingClause?.length||body.withClause)return[];let terms=node=>node?.BoolExpr?.boolop==="AND_EXPR"?node.BoolExpr.args.flatMap(terms):[node],column=node=>{let fields=node?.ColumnRef?.fields?.map(f=>f.String?.sval);return fields&&(fields.length===1||fields.length===2&&fields[0]?.toLowerCase()===(body.relation.alias?.aliasname??target2).toLowerCase())?fields.at(-1)?.toLowerCase():void 0},input=node=>{let fields=node?.ColumnRef?.fields?.map(f=>f.String?.sval);return fields?.length===2&&fields[0]==="input"?fields[1]:void 0},literal=node=>{let c=node?.A_Const;if(!(!c||c.isnull)){if(c.sval)return c.sval.sval;if(c.boolval)return c.boolval.boolval}},boundId=!1,conditions=[];for(let term2 of terms(body.whereClause)){let e=term2?.A_Expr,op2=e?.name?.[0]?.String?.sval;if(!e||op2!=="="||!["AEXPR_OP","AEXPR_IN"].includes(e.kind))return[];let field=column(e.lexpr),value2=e.rexpr;if(!field&&e.kind==="AEXPR_OP"&&(field=column(e.rexpr),value2=e.lexpr),!field)return[];if(e.kind==="AEXPR_OP"&&input(value2)){field==="id"&&input(value2)?.toLowerCase()===idInput.toLowerCase()&&(boundId=!0);continue}let name4=Object.keys(schema.properties??{}).find(k=>k.toLowerCase()===field);if(!name4)continue;let property=schema.properties[name4];if(!["string","boolean"].includes(property.type)||["date","date-time"].includes(property.format??""))continue;let nodes=e.kind==="AEXPR_IN"?value2?.List?.items:[value2];if(!nodes?.length)return[];let values=nodes.map(literal);values.some(v=>typeof v!==property.type)||conditions.push({field:name4,values})}return boundId?conditions:[]}function audienceOf(requires){let all=requires?.auth?.all??[];return all.some(p=>p==="ctx.admin"||typeof p=="object"&&"ctx.admin"in p)?"admin":all.includes("ctx.user")?"members":all.some(p=>p==="ctx.auth"||typeof p=="object"&&"ctx.auth.scope"in p)?"api-clients":null}function relationsOf2(stmts){let reads=new Set,writes=new Set,walk3=(v,write)=>{if(Array.isArray(v))return v.forEach(x=>walk3(x,!1));if(!(!v||typeof v!="object"))for(let[k,c]of Object.entries(v)){let n=c;(k==="RangeVar"||k==="relation")&&n&&typeof n.relname=="string"&&n.mantle!=="cte"&&(write&&k==="relation"?writes:reads).add(n.relname.toLowerCase()),walk3(c,k==="InsertStmt"||k==="UpdateStmt"||k==="DeleteStmt"||k==="MergeStmt")}};return walk3(stmts,!1),{reads,writes}}var pointer=s=>s.replace(/~/g,"~0").replace(/\//g,"~1");function developerConsole(plan){let schemaName=key=>plan.schemas[key]?.name,schemas=Object.values(plan.schemas).sort((a,b)=>a.name.localeCompare(b.name)),views=Object.entries(plan.views).sort(([a],[b])=>a.localeCompare(b)),procedureAudience=name4=>audienceOf(plan.procedures[name4]?.requires)??"public",handlerOf=h=>{if("ref"in h)return{kind:"ref",ref:h.ref};let flow=procedureFlow(h.sql.stmts,relationsOf2),verbs={INSERT:"create",UPDATE:"update",DELETE:"delete"},hooks=Object.entries(plan.triggers).flatMap(([trigger,t])=>{if(t.source.kind!=="lifecycle")return[];let source=t.source,on=source.on.filter(hook=>flow.some(s=>s.writes.includes(source.schema.toLowerCase())&&hook.endsWith(`_${verbs[s.operation]}`)));return on.length?[{trigger,procedure:t.procedure,schema:source.schema,on}]:[]});return{kind:"sql",statement:h.source,flow,hooks}},procedures=Object.entries(plan.procedures).sort(([a],[b])=>a.localeCompare(b)).map(([name4,p])=>({name:name4,title:p.title??null,description:p.description??null,audience:procedureAudience(name4),input:p.input,output:p.output,authorization:p.requires?.auth?.all??[],guard:p.requires?.guard?.procedure??null,handler:handlerOf(p.handler),manifest:{...p,handler:"ref"in p.handler?p.handler:{source:p.handler.source}}})),triggers=Object.entries(plan.triggers).sort(([a],[b])=>a.localeCompare(b)).map(([name4,t])=>({name:name4,target:t.procedure,source:t.source,manifest:t,audience:t.source.kind==="lifecycle"||t.source.kind==="schedule"?"system":t.source.kind==="mcp"&&t.source.surface==="admin"?"admin":procedureAudience(t.procedure)})),viewAudience=v=>v.surface==="internal"?"system":v.surface==="admin"?"admin":audienceOf(v.requires)??"public",relation2=(id,kind,sourceId,targetId,at,value2)=>({id,kind,sourceId,targetId,pointer:at,value:value2}),relations=[...schemas.flatMap(s=>[...s.translates?[relation2(`Schema:${s.name}:translates:${s.translates.parent}`,"translation-parent",`Schema:${s.name}`,`Schema:${s.translates.parent}`,"/spec/translates/parent",s.translates.parent)]:[],...Object.entries(s.schema.properties??{}).flatMap(([field,property])=>{let target2=resolveMantleRef(property)?.schema;return target2&&schemaName(target2.toLowerCase())?[relation2(`Schema:${s.name}:field:${field}:${target2}`,"schema-reference",`Schema:${s.name}`,`Schema:${target2}`,`/spec/schema/properties/${pointer(field)}/x-mantle-ref`,target2)]:[]})]),...views.flatMap(([name4,v])=>[...[...relationsOf2(v.stmts).reads].flatMap(key=>schemaName(key)?[relation2(`View:${name4}:from:${schemaName(key)}`,"view-source",`View:${name4}`,`Schema:${schemaName(key)}`,"/spec/sql",schemaName(key))]:[]),...v.requires?.guard?[relation2(`View:${name4}:guard:${v.requires.guard.procedure}`,"authorization-guard",`View:${name4}`,`Procedure:${v.requires.guard.procedure}`,"/spec/requires/guard/procedure",v.requires.guard.procedure)]:[]]),...Object.entries(plan.procedures).flatMap(([name4,p])=>[...("sql"in p.handler?[...relationsOf2(p.handler.sql.stmts).writes].map(schemaName):[p.target&&schemaName(p.target.schema.toLowerCase())]).flatMap(s=>s?[relation2(`Procedure:${name4}:writes:${s}`,"procedure-schema",`Procedure:${name4}`,`Schema:${s}`,"sql"in p.handler?"/spec/handler/sql":"/spec/target/schema",s)]:[]),...p.requires?.guard?[relation2(`Procedure:${name4}:guard:${p.requires.guard.procedure}`,"authorization-guard",`Procedure:${name4}`,`Procedure:${p.requires.guard.procedure}`,"/spec/requires/guard/procedure",p.requires.guard.procedure)]:[]]),...Object.entries(plan.triggers).flatMap(([name4,t])=>[relation2(`Trigger:${name4}:target:${t.procedure}`,"trigger-target",`Trigger:${name4}`,`Procedure:${t.procedure}`,"/spec/target/procedure",t.procedure),...t.source.kind==="lifecycle"&&schemaName(t.source.schema.toLowerCase())?[relation2(`Trigger:${name4}:source:${t.source.schema}`,"lifecycle-source",`Trigger:${name4}`,`Schema:${schemaName(t.source.schema.toLowerCase())}`,"/spec/source/schema",t.source.schema)]:[]])].sort((a,b)=>a.id.localeCompare(b.id)),callable=["public","admin"].flatMap(surface=>mcpTools(plan,surface).map(tool=>({kind:tool.kind,name:tool.name,target:tool.source,surface,audience:surface==="admin"?"admin":audienceOf(tool.requires)??"public",title:tool.title??null,description:tool.description,input:tool.inputSchema,output:tool.outputSchema??null,trigger:tool.kind==="procedure"?Object.entries(plan.triggers).find(([,t])=>t.procedure===tool.source&&t.source.kind==="mcp"&&t.source.surface===surface)?.[0]??null:null}))),http=[...Object.entries(plan.triggers).flatMap(([name4,t])=>{if(t.source.kind!=="http")return[];let p=plan.procedures[t.procedure];return[{kind:"procedure",name:name4,target:t.procedure,method:t.source.method,path:t.source.path,audience:procedureAudience(t.procedure),title:typeof p.title=="string"?p.title:null,description:typeof p.description=="string"?p.description:`Invoke Procedure '${t.procedure}'.`,input:p.input,output:p.output}]}),...views.filter(([,v])=>v.surface==="public").map(([name4,v])=>({kind:"view",name:name4,target:name4,method:"GET",path:`/api/views/${name4}`,audience:viewAudience(v),title:typeof v.title=="string"?v.title:null,description:typeof v.description=="string"?v.description:`Read View '${name4}'.`,input:v.input??{type:"object"},output:null}))].sort((a,b)=>`${a.path}\0${a.method}`.localeCompare(`${b.path}\0${b.method}`));return{dataModel:{schemas:schemas.map(s=>({name:s.name,title:s.title??s.name,lifecycle:s.publishing?"publishing":"operational",localized:s.localized===!0,translates:s.translates??null,schema:s.schema,checks:(s.checks??[]).map(sqlLogic),uniqueIndexes:s.unique??[],indexes:s.indexes??[],searchableFields:s.search??[],manifest:(({checks:_ir,...rest})=>rest)(s)})),views:views.map(([name4,v])=>({name:name4,title:v.title??null,surface:v.surface,query:{kind:"sql",statement:v.source,...v.input?{params:v.input}:{}},authorization:v.requires?.auth?.all??[],guard:v.requires?.guard?.procedure??null,manifest:(({stmts:_ir,...rest})=>rest)(v)}))},logic:{triggers,procedures},interfaces:{http,callable},graph:{atoms:[...schemas.map(s=>({id:`Schema:${s.name}`,kind:"Schema",name:s.name,title:s.title??s.name})),...views.map(([name4,v])=>({id:`View:${name4}`,kind:"View",name:name4,title:v.title??null,audience:viewAudience(v)})),...procedures.map(({name:name4,title,description,audience,handler,input})=>({id:`Procedure:${name4}`,kind:"Procedure",name:name4,title,description,audience,handler,input})),...triggers.map(({name:name4,source,audience})=>({id:`Trigger:${name4}`,kind:"Trigger",name:name4,title:null,audience,transport:source.kind}))].sort((a,b)=>a.id.localeCompare(b.id)),relations},operations:{schedules:Object.entries(plan.triggers).flatMap(([id,{procedure,source}])=>source.kind==="schedule"?[{id,procedure,cron:source.cron,enabled:source.enabled??!0,registration:"not-observed"}]:[]),ttlPolicies:schemas.filter(s=>s.ttl).map(s=>({schema:s.name,field:s.names[s.ttl]??s.ttl,expireAfterSeconds:s.ttlSeconds??0,sweepObservation:"unavailable"})),observationAvailability:"unavailable",runs:[],latestRuns:[]}}}var nativeSchema=field=>Object.hasOwn(NATIVE_OUTPUT_TYPES,field)?NATIVE_OUTPUT_TYPES[field]==="integer"?{type:"integer"}:{type:"string",format:"date-time"}:void 0;function entrySchema(plan,v){let sel=v.stmts[0]?.SelectStmt,table=sel?.fromClause?.length===1?sel.fromClause[0].RangeVar:void 0,key=typeof table?.relname=="string"?table.relname.toLowerCase():void 0;return!key||table.mantle!=="table"||!Object.hasOwn(plan.schemas,key)?void 0:(sel.targetList??[]).some(({ResTarget:r})=>{let col=r.val?.ColumnRef?.fields?.at(-1)?.String?.sval;return col==="id"&&(r.name??col)==="id"})?key:void 0}function appCatalog(plan,surface){let tools=mcpTools(plan,surface),actions={},targets=new Map;for(let t of tools){let p=t.kind==="procedure"?plan.procedures[t.source]:void 0;if(!p?.target)continue;actions[t.name]={capability:t.name,...p.title!==void 0?{title:p.title}:{},inputSchema:p.input,...p.uiSchema?{uiSchema:p.uiSchema}:{},bind:[{input:p.target.id,field:"id"}],...p.target.version?{version:p.target.version}:{},mutates:!0};let key=p.target.schema.toLowerCase();targets.set(key,[...targets.get(key)??[],t.name])}let views={};for(let tool of tools){if(tool.kind!=="view")continue;let v=plan.views[tool.source],columns2={};for(let[k,c]of Object.entries(v.columns??{})){let s=plan.schemas[c.schema],field=s.names?.[c.field]??c.field,property=s.schema.properties?.[field]??nativeSchema(c.field);property&&(columns2[k===c.field?field:k]=property)}let list=v.uiSchema?.list??{},entry=entrySchema(plan,v);views[tool.name]={...v.title!==void 0?{title:v.title}:{},columns:columns2,list:{columns:list.columns??[]},actions:entry?targets.get(entry)??[]:[]}}return{views,actions}}export{BUILT_IN_NAV_GROUPS,DiagnosticError,INPUT_RULE_KEYWORDS,NATIVE_COLUMNS,NATIVE_NOT_NULL,adminIndexColumns,appCatalog,assertSiteDefaultsCanonical,canonical,canonicalizeLocaleList,collectionOf,compilePlan,compileProgram,d1Dialect,developerConsole,entrySchema,enumOptions,expandPolicyRequired,fnv,isPrimaryCollection,jsonOutputs,lookupLocalRef,lowerPlan,mcpToolNameSegment,mcpTools,navPlacementProblems,notNullColumns,pagedOf,parseNumeric,parsePgSql,compile_exports2 as postgresCompiler,postgresDialect,initialStorageSql2 as postgresSchema,procedureAnnotations,protectedColumns,refChecks,resolveLocalizedText,rootRefChain,rowPolicy,rowPreconditions,compile_exports as sqliteCompiler,initialStorageSql as sqliteSchema,tableOutputs,toolTitle,userScopeTerm,viewAnnotations,viewOutputs,writePolicy};
|
|
1
|
+
var __defProp=Object.defineProperty;var __export=(target2,all)=>{for(var name4 in all)__defProp(target2,name4,{get:all[name4],enumerable:!0})};function makeDiagnostic(input){let{code,phase,severity,path,source,value:value2,expected,candidates,suggestion}=input,msg=input.message;if(!msg){let parts=[`[${phase}/${code}] at ${path}`];expected&&parts.push(`expected ${expected}`),value2!==void 0&&parts.push(`got ${formatValue(value2)}`),suggestion&&parts.push(`(did you mean ${suggestion}?)`),msg=parts.join("; ")}return{code,phase,severity,path,...source?{source}:{},value:value2,expected,candidates,suggestion,message:msg,...input.failure?{failure:input.failure}:{},...input.conflict?{conflict:input.conflict}:{}}}var validateDiagnostic=input=>makeDiagnostic({...input,phase:"validate"}),bootDiagnostic=input=>makeDiagnostic({...input,phase:"boot"}),runtimeDiagnostic=input=>makeDiagnostic({...input,phase:"runtime"});function formatValue(v){if(v===null)return"null";if(v===void 0)return"undefined";if(typeof v=="string")return JSON.stringify(v);if(typeof v=="number"||typeof v=="boolean")return String(v);try{let s=JSON.stringify(v);return s.length>100?s.slice(0,97)+"...":s}catch{return"[unserializable]"}}var BRAND=Symbol.for("net.aotter.mantle.DiagnosticError"),DiagnosticError=class _DiagnosticError extends Error{static[Symbol.hasInstance](value2){return this!==_DiagnosticError?Function.prototype[Symbol.hasInstance].call(this,value2):typeof value2=="object"&&value2!==null&&value2[BRAND]===!0}[BRAND]=!0;diagnostics;constructor(diagnostic,options){let list=Array.isArray(diagnostic)?diagnostic:[diagnostic],head=list[0];super(head?head.message:"DiagnosticError",options),this.name="DiagnosticError",this.diagnostics=list}get diagnostic(){let d=this.diagnostics[0];if(!d)throw new Error("DiagnosticError carries no diagnostics");return d}};var API_VERSION="cms.mantle.aotter.net/v2";function isMediaMcpHint(value2){return value2==="media"||value2==="media-image"||value2==="media-video"||value2==="media-file"}var MANTLE_REF_KEYWORD="x-mantle-ref";function enumOptions(property){if(property?.enum?.length&&property.enum.every(v=>typeof v=="string"))return property.enum.map(value2=>({value:value2}));let branches=property?.oneOf;if(!(!branches?.length||!branches.every(b=>typeof b.const=="string")))return branches.map(b=>({value:b.const,...b.title!==void 0?{title:b.title}:{}}))}function resolveMantleRef(property){if(typeof property!="object"||property===null)return null;let ref2=property[MANTLE_REF_KEYWORD];if(typeof ref2=="string")return ref2.length>0?{schema:ref2,field:"id"}:null;if(typeof ref2!="object"||ref2===null||Array.isArray(ref2))return null;let{schema,field}=ref2;return typeof schema=="string"&&schema.length>0&&typeof field=="string"&&field.length>0?{schema,field}:null}var MCP_HINT_KEYWORD="x-mcp-hint",MANTLE_BIND_KEYWORD="x-mantle-bind";function resolveLocalizedText(value2,preferred,canonical2){if(value2==null)return null;if(typeof value2=="string")return value2;if(Object.prototype.hasOwnProperty.call(value2,preferred))return value2[preferred];if(canonical2&&Object.prototype.hasOwnProperty.call(value2,canonical2))return value2[canonical2];let firstKey=Object.keys(value2)[0];return firstKey!==void 0?value2[firstKey]:null}var LOCK_VERBS=["update","delete"],VIEW_SURFACES=["public","admin","internal"],VIEW_INPUT_RESERVED=["limit","cursor"],PROCEDURE_TARGET_KEYS=["schema","id","version"],PROCEDURE_MCP_ANNOTATION_KEYS=["readOnlyHint","destructiveHint","openWorldHint"],HANDLER_STEP_KEYS=["sql","onNoRows"];function stepProgram(steps){let sql4="",lines=[];for(let[i,step]of steps.entries()){lines.push(sql4.split(`
|
|
2
|
+
`).length-1);let text=step.sql.trimEnd().replace(/;$/,"").trimEnd();sql4+=i===steps.length-1?text:`${text}${/--[^\n]*$/.test(text)?`
|
|
3
|
+
;`:";"}
|
|
4
|
+
`}return{sql:sql4,lines}}var LIFECYCLE_HOOKS=["before_create","after_create","before_update","after_update","before_delete","after_delete","before_publish","after_publish"],MCP_TRIGGER_SURFACES=["admin","public"],RESERVED_ENTRY_COLUMNS=["id","status","version","createdAt","updatedAt","authorId"],EXPECTED_VERSION_PROPERTY="expectedVersion",INPUT_RULE_KEYWORDS=["dependentRequired","anyOf","if","then","else"],RESERVED_PROCEDURE_INPUT_NAMES=[EXPECTED_VERSION_PROPERTY];var NATIVE_OUTPUT_TYPES={version:"integer",created_at:"timestamptz",updated_at:"timestamptz"};var conjuncts=w=>w?.BoolExpr?.boolop==="AND_EXPR"?w.BoolExpr.args.flatMap(conjuncts):w?[w]:[],isInput=n=>n.ColumnRef?.fields?.length===2&&n.ColumnRef.fields[0].String?.sval==="input",isScalar=n=>!!n.A_Const||isInput(n),isIdCol=n=>{let f=n.ColumnRef?.fields;return!!f&&f.at(-1)?.String?.sval==="id"&&(f.length===1||f.length===2&&f[0].String?.sval!=="input")};function classify(stmt){return stmt.SelectStmt?"read":stmt.InsertStmt?stmt.InsertStmt.selectStmt?.SelectStmt?.valuesLists?.length===1&&!stmt.InsertStmt.onConflictClause?"row":"set":conjuncts((stmt.UpdateStmt??stmt.DeleteStmt).whereClause).filter(x=>x.A_Expr?.kind==="AEXPR_OP"&&x.A_Expr.name[0].String.sval==="=").some(x=>isIdCol(x.A_Expr.lexpr)&&isScalar(x.A_Expr.rexpr)||isIdCol(x.A_Expr.rexpr)&&isScalar(x.A_Expr.lexpr))?"row":"set"}function pinnedTarget(stmt){let body=stmt.UpdateStmt??stmt.DeleteStmt;if(!body||classify(stmt)!=="row")return;let eqs=conjuncts(body.whereClause).filter(x=>x.A_Expr?.kind==="AEXPR_OP"&&x.A_Expr.name[0].String.sval==="="),name4=n=>n.ColumnRef.fields[1].String.sval,idEq=eqs.find(x=>isIdCol(x.A_Expr.lexpr)&&isInput(x.A_Expr.rexpr)||isIdCol(x.A_Expr.rexpr)&&isInput(x.A_Expr.lexpr));if(!idEq)return;let verEq=eqs.find(x=>{let col=n=>n.ColumnRef?.fields?.at(-1)?.String?.sval==="version"&&!isInput(n);return col(x.A_Expr.lexpr)&&isInput(x.A_Expr.rexpr)||col(x.A_Expr.rexpr)&&isInput(x.A_Expr.lexpr)});return{schema:body.relation.relname,id:name4(isInput(idEq.A_Expr.rexpr)?idEq.A_Expr.rexpr:idEq.A_Expr.lexpr),...verEq?{version:name4(isInput(verEq.A_Expr.rexpr)?verEq.A_Expr.rexpr:verEq.A_Expr.lexpr)}:{}}}function protectedColumns(s,restrict){return[...(s.userScopes??[]).map(u=>u.column),...restrict?.owner?[restrict.owner]:[],...(restrict?.terms??[]).map(u=>u.column)]}function userScopeTerm(scope,swappable=!1){return[scope.column,"in",{k:"user",field:scope.field,type:scope.type,multiple:!0,...swappable?{scope:!0}:{}}]}function refChecks(s,schemas){return Object.entries(s.schema?.properties??{}).flatMap(([name4,property])=>{let ref2=resolveMantleRef(property),table=ref2?.schema.toLowerCase(),t=table?schemas[table]:void 0;if(!t||!t.scope&&!t.userScopes?.length)return[];let column=(x,field)=>Object.keys(x.names??{}).find(c=>x.names[c]===field)??field.toLowerCase(),same=(t.userScopes??[]).flatMap(u=>(s.userScopes??[]).filter(v=>v.field===u.field).map(v=>[u.column,v.column]));return[{column:column(s,name4),table,field:column(t,ref2.field),same,terms:rowPolicy(t,"caller",schemas)}]})}var PUBLISHED="published",NOW={k:"now"};function rowPolicy(s,mode,schemas){if(!["caller","admin","public","trusted"].includes(mode))throw new Error("An explicit row mode is required.");mode==="caller"&&(mode="admin");let parent=[];if(s.translates&&(mode==="public"||mode==="admin")){let table=s.translates.parent.toLowerCase(),schema=schemas?.[table];if(!schema)throw new Error(`Translation parent ${table} is unavailable to rowPolicy.`);parent=[[s.translates.on.toLowerCase(),"parent",{k:"admin"},{table,terms:rowPolicy(schema,schema.userScopes?.length&&mode==="admin"?"admin":"public",schemas),...schema.scope&&s.scope?{scope:[schema.scope,s.scope]}:{},...mode==="admin"&&!schema.userScopes?.length?{admin:!0}:{}}]]}return[...mode!=="trusted"&&s.scope?[[s.scope,"eq",{k:"uid"}]]:[],...s.ttl?[[s.ttl,"ttl",{k:"cutoff",seconds:s.ttlSeconds}]]:[],...s.publishing&&(mode==="public"||mode==="admin")?[mode==="public"?["status","eq",{k:"const",value:PUBLISHED}]:["status","admin",{k:"admin"},PUBLISHED]]:[],...parent,...mode!=="trusted"?(s.userScopes??[]).map(u=>userScopeTerm(u,!0)):[]]}function writePolicy(s,kind,o={}){let lock=kind!=="insert"&&o.lock?["version","eq",{k:"version"}]:void 0,locks=kind==="insert"||o.trusted?[]:(s.locks??[]).filter(l=>l.on.includes(kind)).map(l=>[l.name,"lock",l.when]);if(kind==="delete")return{fills:[],sets:[],lock,locks};let sets2=[["version","bump"],["updated_at",NOW],...o.status?[["status",{k:"const",value:o.status}]]:[]];if(kind==="update")return{fills:[],sets:sets2,lock,locks};let uid={k:"uid"};return{fills:[...s.scope?[[s.scope,uid]]:[],["created_at",NOW],["updated_at",NOW],["author_id",uid],...o.idGiven&&!s.scope&&!s.userScopes?.length?[]:[["id","newId"]]],sets:sets2.slice(0,2),locks}}function canonical(v){return Array.isArray(v)?`[${v.map(canonical).join(",")}]`:v&&typeof v=="object"?`{${Object.keys(v).sort().filter(k=>v[k]!==void 0).map(k=>`${JSON.stringify(k)}:${canonical(v[k])}`).join(",")}}`:JSON.stringify(v)??"null"}var fnv=s=>[...s].reduce((h,c)=>Math.imul(h^c.codePointAt(0),16777619)>>>0,2166136261).toString(16).padStart(8,"0");async function planFingerprint(plan){let digest=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(canonical(plan)));return[...new Uint8Array(digest)].map(b=>b.toString(16).padStart(2,"0")).join("")}var SqlRefusal=class extends Error{code;offset;keyword;constructor(code,message2,offset,keyword){super(message2),this.code=code,this.offset=offset,this.keyword=keyword}};var MAX_NUMERIC_P=15;function parseNumeric(type){let m=/^numeric\((\d+),\s*(\d+)\)$/.exec(type);if(!m)return;let p=+m[1],s=+m[2];if(p<1||p>MAX_NUMERIC_P||s>p)throw new SqlRefusal("SQL_TYPE",`numeric(${p}, ${s}) is refused: precision is 1 to ${MAX_NUMERIC_P}, scale at most precision`);return{p,s}}var MAX_TTL_SECONDS=Math.floor(Number.MAX_SAFE_INTEGER/2e6),isTtlSeconds=x=>Number.isSafeInteger(x)&&x>=0&&x<=MAX_TTL_SECONDS,UNIT_US=Object.fromEntries(["second seconds sec secs s","minute minutes min mins m","hour hours hr hrs h"].flatMap((names,i)=>names.split(" ").map(u=>[u,[1e6,6e7,36e8][i]]))),TYPMOD_UNIT={1024:"hour",2048:"minute",4096:"second"};function intervalMicros(text,typmod){let m=/^\s*(-?\d+(?:\.\d+)?)\s*([a-z]+)\s*$/i.exec(text);if(!m&&typmod!==void 0&&TYPMOD_UNIT[typmod]&&/^\s*-?\d+(\.\d+)?\s*$/.test(text)&&(m=[text,text.trim(),TYPMOD_UNIT[typmod]]),!m)throw new SqlRefusal("SQL_TYPE",`interval '${text}' is not supported: write a number and second, minute or hour`);let unit=UNIT_US[m[2].toLowerCase()];if(!unit&&/^(days?|weeks?|months?|mons?|years?|y)$/i.test(m[2]))throw new SqlRefusal("SQL_TYPE",`interval unit '${m[2]}' is a calendar unit (a day is 23 or 25 hours across daylight saving): bind the boundary as an input instead`);if(!unit)throw new SqlRefusal("SQL_TYPE",`interval '${text}' is not supported: write a number and second, minute or hour`);let[,sign,whole,frac=""]=/^(-?)(\d+)(?:\.(\d+))?$/.exec(m[1]),scale=10n**BigInt(frac.length),fraction=BigInt(frac||"0")*BigInt(unit);if(fraction%scale!==0n)throw new SqlRefusal("SQL_TYPE",`interval '${text}' is finer than a microsecond`);let micros=(sign?-1:1)*Number(BigInt(whole)*BigInt(unit)+fraction/scale);if(!Number.isSafeInteger(micros))throw new SqlRefusal("SQL_TYPE",`interval '${text}' is longer than ${Number.MAX_SAFE_INTEGER} microseconds`);return micros}var ftsTableName=schema=>`_mantle_fts_${schema}`,geoTreeName=(schema,field)=>`_mantle_geo_${schema}_${field}`;function fieldType(p){let types=[...new Set([p.type].flat().filter(x=>x!=="null"))];if(types.length>1)return types.every(x=>x==="integer"||x==="number")?"real":"json";let t=types[0];return p.format==="geo"?"geo":!t&&enumOptions(p)?"text":t==="string"?p.format==="date-time"?"timestamptz":p.format==="date"?"date":"text":{integer:"integer",number:"real",boolean:"bool"}[String(t)]??"json"}function fieldTypes(schema){return Object.fromEntries(Object.entries(schema?.properties??{}).map(([name4,p])=>[name4.toLowerCase(),fieldType(p)]))}function viewCacheProblem(stmts,schemas){let pending=[...stmts];for(;pending.length;){let node=pending.pop();if(!node||typeof node!="object")continue;let n=node,fn3=n.FuncCall?.funcname?.map(x=>x.String.sval).join(".").replace(/^pg_catalog\./,"");if(fn3==="now"||fn3?.startsWith("auth."))return`shared caching cannot read ${fn3}()`;let relation2=n.RangeVar;if(relation2?.mantle==="table"){let schema=schemas[relation2.relname.toLowerCase()];if(schema?.userScopes?.length)return`shared caching cannot read field-scoped Schema '${relation2.relname}'`;if(schema?.ttl||schema&&!schema.publishing)return`shared caching cannot read ${schema.ttl?"TTL":"operational"} Schema '${relation2.relname}'`}pending.push(...Object.values(n))}}function storageColumns(s){let cols=new Map([["_rid","integer"],["id","text"],["version","integer"],["created_at","native"],["updated_at","native"],["author_id","text"]]);s.scope&&cols.set(s.scope,"text"),s.publishing&&(cols.set("status","text"),cols.set("published_at","timestamptz"));for(let[f,t]of Object.entries(s.fields??{}))f!==s.scope&&(t==="geo"?(cols.set(`${f}_lat`,"real"),cols.set(`${f}_lng`,"real")):cols.set(f,t));return cols}var AGGREGATES=new Set(["count","sum","min","max","avg","json_group_array","json_group_object","string_agg","jsonb_agg","jsonb_object_agg"]),NATIVE_NOT_NULL=new Set(["id","version","created_at","updated_at","status"]),NATIVE_COLUMNS={id:"id",status:"status",version:"version",createdAt:"created_at",updatedAt:"updated_at",authorId:"author_id"};function notNullColumns(s){let out=new Set;for(let u of s.userScopes??[])out.add(u.column);if(s.publishing||!s.schema?.required)return out;let required=new Set(s.schema.required);for(let[f,t]of Object.entries(s.fields)){let authored2=s.names?.[f]??f,p=s.schema.properties?.[authored2];f===s.scope||!required.has(authored2)||!p||p.nullable===!0||Array.isArray(p.type)&&p.type.includes("null")||(t==="geo"?out.add(`${f}_lat`).add(`${f}_lng`):out.add(f))}return out}function storageColumnClash(fields){let taken=new Set(["_rid",...Object.entries(fields).filter(([,t])=>t==="geo").flatMap(([f])=>[`${f}_lat`,`${f}_lng`])]);return Object.keys(fields).find(f=>taken.has(f))}var CHECK_FUNCTIONS=new Map([["lower",{takes:["text"],returns:"text"}],["upper",{takes:["text"],returns:"text"}],["length",{takes:["text"],returns:"integer"}],["abs",{takes:["integer","real"],returns:"argument"}]]);function checkShapeProblem(v,columns2){let columnOf=ref2=>{let fields=ref2?.fields,name4=Array.isArray(fields)&&fields.length===1?fields[0]?.String?.sval:void 0;return typeof name4=="string"&&columns2.has(name4)?name4:void 0},fname2=call=>Array.isArray(call?.funcname)?call.funcname.map(x=>x?.String?.sval).join("."):"",typeOf=n=>{if(n?.ColumnRef)return columns2.get(columnOf(n.ColumnRef)??"");if(n?.FuncCall){let f=CHECK_FUNCTIONS.get(fname2(n.FuncCall));return f?.returns==="argument"?typeOf(n.FuncCall.args?.[0]):f?.returns}if(n?.A_Const)return n.A_Const.sval?"text":n.A_Const.ival?"integer":n.A_Const.fval?"real":void 0},walk3=v2=>{if(!(!v2||typeof v2!="object"))for(let[k,c]of Object.entries(v2)){if(k==="SubLink")return"a check reads only the row's own columns: no subquery";if(k==="TypeCast"||k==="SQLValueFunction")return"a check reads only the row's own columns: no cast or SQL value function";if(k==="ColumnRef"&&!columnOf(c))return`a check names only its own Schema's columns, unqualified: ${JSON.stringify((c?.fields??[]).map(x=>x?.String?.sval??"*").join("."))} is not one`;if(k==="FuncCall"){let name4=fname2(c),takes=CHECK_FUNCTIONS.get(name4)?.takes;if(!takes)return`a check may call only ${[...CHECK_FUNCTIONS.keys()].join(", ")}: ${name4||"this call"}() is printed into the table's DDL as written`;if(c.agg_star||c.agg_distinct||c.agg_filter||c.agg_order||c.over||!Array.isArray(c.args)||c.args.length!==1)return`${name4}() in a check takes one argument, with no DISTINCT, *, FILTER, ORDER BY or OVER`;let t=typeOf(c.args[0]);if(!t||!takes.includes(t))return`${name4}() in a check takes a ${takes.join(" or ")} column, constant or call`}let inner=walk3(c);if(inner)return inner}};return walk3(v)}var COMPARISONS=new Set(["=","<>","!=","<",">","<=",">="]);function lockShapeProblem(where,schemas,table){let columnsOf=name4=>storageColumns(schemas[name4]),shape2="a lock's when allows columns, constants, comparisons, AND/OR/NOT, IS [NOT] NULL and [NOT] EXISTS (SELECT \u2026 FROM <Schema> WHERE \u2026)",column=(n,frames)=>{let f=(n.fields??[]).map(x=>x?.String?.sval);if(f.some(x=>x===void 0)||f.length>2)return`${shape2}: ${f.map(x=>x??"*").join(".")} is not a column`;if(f.length===1)return frames.length>1?`inside a subquery qualify every column: '${f[0]}' would read the subquery's table, not the locked row; write ${table}.${f[0]} for the locked row`:frames[0].columns.has(f[0])?void 0:`'${f[0]}' is not a column of ${table}`;let frame=[...frames].reverse().find(x=>x.alias===f[0]);return frame?frame.columns.has(f[1])?void 0:`'${f[1]}' is not a column of ${f[0]}`:`'${f[0]}' is neither ${table} nor a subquery's alias`},value2=(n,frames)=>{if(!n?.A_Const){if(n?.ColumnRef)return column(n.ColumnRef,frames);if(n?.List){for(let x of n.List.items??[]){let p=value2(x,frames);if(p)return p}return}return n?.FuncCall?"a lock calls no function: now(), auth.*, aggregates and window functions are refused, so it holds the same for every caller and every request":`${shape2}: ${Object.keys(n??{})[0]??"this expression"} is refused`}},sub=(s,frames)=>{let from=s?.fromClause??[];if(!s||s.op!=="SETOP_NONE"||s.withClause||s.groupClause||s.havingClause||s.distinctClause||s.sortClause||s.limitCount||s.limitOffset||s.windowClause||s.valuesLists||from.length!==1||!from[0].RangeVar)return"a lock's subquery is SELECT \u2026 FROM one declared Schema [alias] WHERE \u2026: no join, WITH, GROUP BY, ORDER BY, LIMIT, DISTINCT or set operation";let rv=from[0].RangeVar,name4=String(rv.relname).toLowerCase();if(rv.mantle!=="table"||!schemas[name4])return`${rv.relname} is not a declared Schema`;let alias=rv.alias?.aliasname??rv.relname;if(frames.some(x=>x.alias===alias))return`the subquery's '${alias}' hides a name already in scope (the locked row is ${table}): give it its own alias`;let inner=[...frames,{alias,columns:columnsOf(name4)}];for(let t of s.targetList??[]){let p=value2(t.ResTarget?.val,inner);if(p)return p}return s.whereClause?expr(s.whereClause,inner):void 0},expr=(n,frames)=>{if(n.BoolExpr){for(let x of n.BoolExpr.args){let p=expr(x,frames);if(p)return p}return}if(n.NullTest)return value2(n.NullTest.arg,frames);if(n.SubLink)return n.SubLink.subLinkType==="EXISTS_SUBLINK"?sub(n.SubLink.subselect?.SelectStmt,frames):`${shape2}: only an EXISTS subquery`;let e=n.A_Expr;return e&&(e.kind==="AEXPR_OP"&&COMPARISONS.has(e.name?.[0]?.String?.sval)&&e.lexpr||e.kind==="AEXPR_IN"&&e.rexpr?.List)?value2(e.lexpr,frames)??value2(e.rexpr,frames):value2(n,frames)};return expr(where,[{alias:table,columns:columnsOf(table)}])}function lockIndexProblem(where,schemas){let walk3=n=>{if(!n||typeof n!="object")return;let s=n.SubLink?.subselect?.SelectStmt;if(s){let rv=s.fromClause[0].RangeVar,name4=String(rv.relname).toLowerCase(),alias=rv.alias?.aliasname??rv.relname,def=schemas[name4],own=x=>x?.ColumnRef?.fields?.length===2&&x.ColumnRef.fields[0].String?.sval===alias?String(x.ColumnRef.fields[1].String.sval):void 0,other=x=>!!x?.A_Const||x?.ColumnRef?.fields?.length===2&&x.ColumnRef.fields[0].String?.sval!==alias,terms=x=>x?.BoolExpr?.boolop==="AND_EXPR"?x.BoolExpr.args.flatMap(terms):x?[x]:[],columns2=[...new Set(terms(s.whereClause).flatMap(t=>{let e=t.A_Expr;if(e?.kind==="AEXPR_IN"&&own(e.lexpr)&&e.rexpr?.List?.items?.every(x=>x.A_Const))return[own(e.lexpr)];if(e?.kind!=="AEXPR_OP"||e.name?.[0]?.String?.sval!=="=")return[];let c=own(e.lexpr)&&other(e.rexpr)?own(e.lexpr):own(e.rexpr)&&other(e.lexpr)?own(e.rexpr):void 0;return c?[c]:[]}))];if(![["id"],...def.indexes??[],...def.unique??[]].some(index=>columns2.includes(index[0])))return{schema:name4,columns:columns2,...!columns2.length&&JSON.stringify(s.whereClause??null).includes('"OR_EXPR"')?{or:!0}:{}}}for(let v of Object.values(n)){let p=walk3(v);if(p)return p}};return walk3(where)}import{LineCounter as LineCounter2,parseAllDocuments}from"yaml";function validateLocalizedText(value2,idx,pointer2,fieldLabel,required){if(value2===void 0){if(required)throw new ManifestParseError(`${fieldLabel} is required (non-empty string, or an object mapping locale \u2192 non-empty string)`,idx,pointer2);return}if(typeof value2=="string"){if(value2.length===0)throw new ManifestParseError(`${fieldLabel} must be a non-empty string when present (or an object mapping locale \u2192 non-empty string)`,idx,pointer2);return}if(typeof value2=="object"&&value2!==null&&!Array.isArray(value2)){let entries=Object.entries(value2);if(entries.length===0)throw new ManifestParseError(`${fieldLabel} object form must have at least one locale \u2192 string entry; got {}`,idx,pointer2);for(let[key,entryValue]of entries){if(key.length===0)throw new ManifestParseError(`${fieldLabel} object form keys must be non-empty locale codes; got an empty key`,idx,pointer2);if(typeof entryValue!="string"||entryValue.length===0)throw new ManifestParseError(`${fieldLabel} object form value for locale '${key}' must be a non-empty string; got ${JSON.stringify(entryValue)}`,idx,`${pointer2}/${key}`)}return}throw new ManifestParseError(`${fieldLabel} must be a non-empty string, or an object mapping locale \u2192 non-empty string; got ${JSON.stringify(value2)}`,idx,pointer2)}var ManifestParseError=class extends Error{constructor(message2,docIndex,pointer2,code="INVALID_MANIFEST_ENVELOPE",details){super(docIndex!=null?`[doc ${docIndex}] ${message2}`:message2);this.docIndex=docIndex;this.pointer=pointer2;this.code=code;this.details=details;this.name="ManifestParseError"}docIndex;pointer;code;details},KNOWN_KINDS=new Set(["Schema","View","Procedure","Trigger"]),V01_TRIGGER_SOURCE_KINDS=new Set(["http","lifecycle","mcp","schedule"]),V01_HTTP_METHODS=new Set(["POST","PUT","PATCH","DELETE"]),V01_LIFECYCLE_HOOKS=new Set(LIFECYCLE_HOOKS),V01_MCP_TRIGGER_SURFACES=new Set(MCP_TRIGGER_SURFACES),V01_VIEW_SURFACES=new Set(VIEW_SURFACES),V01_LIFECYCLE_MODES=new Set(["publishing","operational"]);function rejectUnknownKeys(value2,allowed,idx,pointer2){let unknown=Object.keys(value2).find(key=>!allowed.includes(key));if(unknown!==void 0){let unknownPointer=pointer2==="/"?`/${unknown}`:`${pointer2}/${unknown}`;throw new ManifestParseError(`${unknownPointer.replaceAll("/",".").slice(1)} is not supported`,idx,unknownPointer)}}function escapeJsonPointerSegment(value2){return value2.replace(/~/g,"~0").replace(/\//g,"~1")}import{isMap,isNode,isScalar as isScalar2,isSeq}from"yaml";function sourceLocationAt(entry,path){let candidate=path,span=entry.sourceSpans[candidate];for(;!span&&candidate!=="/";){let slash=candidate.lastIndexOf("/");candidate=slash<=0?"/":candidate.slice(0,slash),span=entry.sourceSpans[candidate]}return{sourceId:entry.source.sourceId,documentIndex:entry.source.documentIndex,path,...span?{span}:{}}}function collectSourceSpans(root,lineCounter){let spans={},visit=(node,path)=>{if(!node)return;let span=sourceSpan(lineCounter,node.range);if(span&&(spans[path]=span),isMap(node))for(let pair of node.items){if(!isScalar2(pair.key))continue;let key=String(pair.key.value).replace(/~/g,"~0").replace(/\//g,"~1");visit(isNode(pair.value)?pair.value:null,path==="/"?`/${key}`:`${path}/${key}`)}else isSeq(node)&&node.items.forEach((item,index)=>visit(isNode(item)?item:null,path==="/"?`/${index}`:`${path}/${index}`))};return visit(root,"/"),Object.freeze(spans)}function sourceLocationForNode(sourceId,documentIndex,path,doc,lineCounter){let parts=path==="/"?[]:path.slice(1).split("/").map(part=>{let decoded2=part.replace(/~1/g,"/").replace(/~0/g,"~");return/^\d+$/.test(decoded2)?Number(decoded2):decoded2}),range;for(let length=parts.length;length>=0&&!range;length--){let node=length===0?doc.contents:doc.getIn(parts.slice(0,length),!0);node&&typeof node=="object"&&"range"in node&&(range=node.range)}return sourceLocation(sourceId,documentIndex,path,lineCounter,range??doc.range)}function sourceLocation(sourceId,documentIndex,path,lineCounter,range){let span=sourceSpan(lineCounter,range);return{sourceId,documentIndex,path,...span?{span}:{}}}function sourceSpan(lineCounter,range){if(!range||range.length<2)return;let startOffset=range[0],endOffset=range.length>2?range[2]:range[1];if(startOffset===void 0||endOffset===void 0)return;let start=lineCounter.linePos(startOffset),end=lineCounter.linePos(endOffset);return{start:{line:start.line,column:start.col,offset:startOffset},end:{line:end.line,column:end.col,offset:endOffset}}}var BUILT_IN_NAV_GROUPS=new Set(["content","operations","reports","more"]),ID=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,PLACEMENT={group:[v=>typeof v=="string"&&ID.test(v),"a kebab-case group id"],order:[Number.isInteger,"an integer"],hidden:[v=>typeof v=="boolean","a boolean"]};function navPlacementProblems(nav,own=[]){let keys=[...own,...Object.keys(PLACEMENT)];for(let[key,value2]of Object.entries(nav)){if(own.includes(key))continue;let rule=Object.hasOwn(PLACEMENT,key)?PLACEMENT[key]:null;if(!rule)return[key,`${keys.slice(0,-1).join(", ")} or ${keys.at(-1)}`];if(!rule[0](value2))return[key,rule[1]]}return null}var SAFE_INDEX_NAME=/^[A-Za-z][A-Za-z0-9_.-]*$/,NATIVE_INDEX_AFFINITY={id:"TEXT",status:"TEXT",version:"INTEGER",createdAt:"INTEGER",updatedAt:"INTEGER",authorId:"TEXT"},NATIVE_INDEX_FIELDS=new Map(Object.entries(NATIVE_INDEX_AFFINITY)),SOURCES=["uniqueIndexes","indexes"];function checkSchemaIndexes(manifest){let spec=manifest.spec,schema=isRecord(spec.schema)?spec.schema:{},properties=isRecord(schema.properties)?schema.properties:{},candidates=Object.keys(properties),declarations=[],problems=[],seen=new Map;SOURCES.some(source=>{let raw=spec[source];return Array.isArray(raw)&&raw.length>0})&&!SAFE_INDEX_NAME.test(manifest.metadata.name)&&problems.push({category:"invalid",pointer:"/metadata/name",value:manifest.metadata.name,expected:`indexed Schema name matching ${SAFE_INDEX_NAME}`,message:`Schema '${manifest.metadata.name}' uses indexes but its name is not a safe index identifier.`});for(let source of SOURCES){let raw=spec[source];if(raw!==void 0){if(!Array.isArray(raw)){problems.push({category:"shape",source,pointer:`/spec/${source}`,value:raw,expected:"an array of non-empty string arrays",message:`Schema.spec.${source} must be an array of non-empty string arrays.`});continue}for(let compositeIndex=0;compositeIndex<raw.length;compositeIndex+=1){let rawComposite=raw[compositeIndex],compositePointer=`/spec/${source}/${compositeIndex}`;if(!Array.isArray(rawComposite)){problems.push({category:"shape",source,pointer:compositePointer,value:rawComposite,expected:"a non-empty array of field-name strings",message:`Schema.spec.${source}[${compositeIndex}] must be a non-empty array of field-name strings.`});continue}if(rawComposite.length===0){problems.push({category:"invalid",source,pointer:compositePointer,value:rawComposite,expected:"at least one indexed field",message:`Schema.spec.${source}[${compositeIndex}] must not be empty.`});continue}let fields=[],fieldsSeen=new Set,valid=!0;for(let fieldIndex=0;fieldIndex<rawComposite.length;fieldIndex+=1){let rawField=rawComposite[fieldIndex],fieldPointer=`${compositePointer}/${fieldIndex}`;if(typeof rawField!="string"){valid=!1,problems.push({category:"shape",source,pointer:fieldPointer,value:rawField,expected:"a field-name string",message:`Schema.spec.${source}[${compositeIndex}][${fieldIndex}] must be a field-name string.`});continue}if(fieldsSeen.has(rawField)){valid=!1,problems.push({category:"invalid",source,pointer:fieldPointer,value:rawField,expected:"each field to appear once per composite index",message:`Schema.spec.${source}[${compositeIndex}] repeats field '${rawField}'.`});continue}if(fieldsSeen.add(rawField),!SAFE_INDEX_NAME.test(rawField)){valid=!1,problems.push({category:"invalid",source,pointer:fieldPointer,value:rawField,expected:`field name matching ${SAFE_INDEX_NAME}`,message:`Schema.spec.${source} field '${rawField}' is not a safe index identifier.`});continue}let nativeAffinity=NATIVE_INDEX_FIELDS.get(rawField);if(nativeAffinity!==void 0){if(source==="uniqueIndexes"){valid=!1,problems.push({category:"invalid",source,pointer:fieldPointer,value:rawField,expected:"a Schema data field; native columns carry no domain uniqueness",message:`Schema.spec.uniqueIndexes cannot include native entry column '${rawField}'; declare it under spec.indexes instead.`});continue}if(rawField==="status"&&(spec.lifecycle??"publishing")!=="publishing"){valid=!1,problems.push({category:"invalid",source,pointer:fieldPointer,value:rawField,expected:"a native column this Schema has",message:"Schema.spec.indexes field 'status' needs lifecycle: publishing; only a publishing Schema has a status column."});continue}fields.push({name:rawField,affinity:nativeAffinity});continue}if(!Object.hasOwn(properties,rawField)){valid=!1,problems.push({category:"field-unknown",source,pointer:fieldPointer,value:rawField,expected:"an exact top-level key in spec.schema.properties",candidates,message:`Schema '${manifest.metadata.name}' ${source} references unknown top-level field '${rawField}'.`});continue}let affinity=scalarAffinity(properties[rawField]);if(affinity===null){valid=!1,problems.push({category:"invalid",source,pointer:fieldPointer,value:rawField,expected:"a property with exactly one string, integer, number, or boolean type, optionally nullable",message:`Schema '${manifest.metadata.name}' ${source} field '${rawField}' is not an indexable scalar property.`});continue}fields.push({name:rawField,affinity})}if(!valid)continue;let key=JSON.stringify(fields.map(field=>field.name)),previous=seen.get(key);if(previous!==void 0){let crossKind=previous!==source;problems.push({category:"invalid",source,pointer:compositePointer,value:fields.map(field=>field.name),expected:crossKind?"a tuple not already supplied by uniqueIndexes":`a unique ordered tuple within ${source}`,message:crossKind?`Schema.spec.indexes duplicates uniqueIndexes tuple ${key}; the unique index already supplies that lookup path.`:`Schema.spec.${source} repeats ordered tuple ${key}.`});continue}seen.set(key,source),declarations.push({unique:source==="uniqueIndexes",fields})}}}return{declarations,problems}}function schemaIndexDiagnosticCode(problem3,parserShape=!1){return problem3.category==="shape"?parserShape?"INVALID_MANIFEST_ENVELOPE":"SCHEMA_INDEX_INVALID":problem3.category==="field-unknown"?problem3.source==="uniqueIndexes"?"UNIQUE_INDEX_FIELD_UNKNOWN":"SCHEMA_INDEX_FIELD_UNKNOWN":"SCHEMA_INDEX_INVALID"}function scalarAffinity(rawProperty){if(!isRecord(rawProperty)||rawProperty.nullable!==void 0&&typeof rawProperty.nullable!="boolean")return null;let rawType=rawProperty.type,types=typeof rawType=="string"?[rawType]:Array.isArray(rawType)&&rawType.every(value2=>typeof value2=="string")?rawType:null;if(types===null||types.length===0||new Set(types).size!==types.length)return null;let nonNull=types.filter(type=>type!=="null");if(nonNull.length!==1||types.length>2)return null;switch(nonNull[0]){case"string":return"TEXT";case"integer":case"boolean":return"INTEGER";case"number":return"REAL";default:return null}}function isRecord(value2){return typeof value2=="object"&&value2!==null&&!Array.isArray(value2)}var problem=(pointer2,value2,expected,message2)=>({pointer:pointer2,value:value2,expected,message:message2}),EMPTY_VIEW_LIST={columns:[],searchFields:[],filterFields:[]};function checkViewAdminUi(view){let uiSchema=view.spec.uiSchema;if(uiSchema===void 0)return{list:EMPTY_VIEW_LIST,problems:[]};if(view.spec.surface!=="admin")return{list:EMPTY_VIEW_LIST,problems:[problem("/spec/uiSchema",uiSchema,"Admin UI configuration on a surface: admin View","View.spec.uiSchema is only supported for surface: admin Views.")]};if(!uiSchema||typeof uiSchema!="object"||Array.isArray(uiSchema))return{list:EMPTY_VIEW_LIST,problems:[problem("/spec/uiSchema",uiSchema,"an object","View.spec.uiSchema must be an object.")]};let unknownRoot=Object.keys(uiSchema).find(key=>key!=="list"&&key!=="nav");if(unknownRoot)return{list:EMPTY_VIEW_LIST,problems:[problem(`/spec/uiSchema/${unknownRoot}`,uiSchema[unknownRoot],"list or nav",`View.spec.uiSchema.${unknownRoot} is not supported.`)]};let nav=uiSchema.nav;if(nav!==void 0){if(!nav||typeof nav!="object"||Array.isArray(nav))return{list:EMPTY_VIEW_LIST,problems:[problem("/spec/uiSchema/nav",nav,"an object","View.spec.uiSchema.nav must be an object.")]};let bad=navPlacementProblems(nav);if(bad)return{list:EMPTY_VIEW_LIST,problems:[problem(`/spec/uiSchema/nav/${bad[0]}`,nav[bad[0]],bad[1],`View.spec.uiSchema.nav.${bad[0]} must be ${bad[1]}.`)]}}let list=uiSchema.list;if(list===void 0)return{list:EMPTY_VIEW_LIST,problems:[]};if(!list||typeof list!="object"||Array.isArray(list))return{list:EMPTY_VIEW_LIST,problems:[problem("/spec/uiSchema/list",list,"an object","View.spec.uiSchema.list must be an object.")]};let config=list,allowed=new Set(["columns","searchFields","filterFields"]),unknown=Object.keys(config).find(key=>!allowed.has(key));if(unknown)return{list:EMPTY_VIEW_LIST,problems:[problem(`/spec/uiSchema/list/${unknown}`,config[unknown],"columns, searchFields, or filterFields",`View.spec.uiSchema.list.${unknown} is not supported.`)]};let normalized={columns:[],searchFields:[],filterFields:[]};for(let key of Object.keys(normalized)){let raw=config[key];if(raw!==void 0){if(!Array.isArray(raw)||!raw.every(field=>typeof field=="string"&&field.length>0&&!/["\\\0]/.test(field)))return{list:EMPTY_VIEW_LIST,problems:[problem(`/spec/uiSchema/list/${key}`,raw,"an array of non-empty View output field names",`View.spec.uiSchema.list.${key} must be an array of field-name strings.`)]};if(new Set(raw).size!==raw.length)return{list:EMPTY_VIEW_LIST,problems:[problem(`/spec/uiSchema/list/${key}`,raw,"field names without duplicates",`View.spec.uiSchema.list.${key} must not repeat a field.`)]};normalized[key]=raw}}return{list:normalized,problems:[]}}var EMPTY_LIST={primaryField:null,columns:[]},SCHEMA_UI_ROOTS=new Set(["fields","list","nav"]),SCHEMA_LIST_KEYS=new Set(["filterField","primaryField","columns"]),SCALAR_TYPES=new Set(["string","number","integer","boolean"]);function checkSchemaAdminUi(schema){let formProblem=checkFormUiSchema(schema.spec.schema,schema.spec.uiSchema,"Schema")[0];if(formProblem)return invalid(formProblem);let uiSchema=schema.spec.uiSchema;if(uiSchema===void 0)return{filter:null,list:EMPTY_LIST,nav:null,problems:[]};let roots=uiSchema,unknownRoot=Object.keys(roots).find(key=>!SCHEMA_UI_ROOTS.has(key));if(unknownRoot)return invalid(problem2(`/spec/uiSchema/${unknownRoot}`,roots[unknownRoot],"fields, list, or nav",`Schema.spec.uiSchema.${unknownRoot} is not supported.`));let list=roots.list;if(list!==void 0&&(!list||typeof list!="object"||Array.isArray(list)))return invalid(problem2("/spec/uiSchema/list",list,"an object","Schema.spec.uiSchema.list must be an object."));let config=list??{};if(list!==void 0){let unknownList=Object.keys(config).find(key=>!SCHEMA_LIST_KEYS.has(key));if(unknownList)return invalid(problem2(`/spec/uiSchema/list/${unknownList}`,config[unknownList],"filterField, primaryField, or columns",`Schema.spec.uiSchema.list.${unknownList} is not supported.`))}let filterResult=list===void 0?{filter:null}:checkListFilter(schema,config);if(filterResult.problem)return invalid(filterResult.problem);let primaryField=config.primaryField,columns2=config.columns;if((primaryField!==void 0||columns2!==void 0)&&(schema.spec.lifecycle??"publishing")!=="operational")return invalid(problem2("/spec/uiSchema/list",list,"list presentation fields on an operational Schema","Schema list primaryField/columns are supported only for lifecycle: operational Schemas; a publishing Schema's Admin list shows its title field and status."));if(primaryField!==void 0&&(typeof primaryField!="string"||!primaryField))return invalid(problem2("/spec/uiSchema/list/primaryField",primaryField,"a non-empty top-level scalar field name","Schema.spec.uiSchema.list.primaryField must be a field-name string."));if(columns2!==void 0&&(!Array.isArray(columns2)||!columns2.every(field=>typeof field=="string"&&field.length>0)))return invalid(problem2("/spec/uiSchema/list/columns",columns2,"an array of non-empty top-level field names","Schema.spec.uiSchema.list.columns must be an array of field-name strings."));let normalizedPrimary=typeof primaryField=="string"?primaryField:null,normalizedColumns=Array.isArray(columns2)?columns2:[],fields=[...normalizedPrimary?[normalizedPrimary]:[],...normalizedColumns];if(new Set(fields).size!==fields.length)return invalid(problem2("/spec/uiSchema/list/columns",columns2,"field names without duplicates or the primaryField","Schema list primaryField/columns must not repeat a field."));for(let field of fields){if(field!==normalizedPrimary&&NATIVE_LIST_FIELDS.has(field))continue;let property=schema.spec.schema.properties?.[field];if(!property)return invalid(problem2(`/spec/uiSchema/list/${field===normalizedPrimary?"primaryField":"columns"}`,field,"a top-level key in spec.schema.properties or a native entry column",`Schema '${schema.metadata.name}' list presentation references unknown field '${field}'.`));if(field===normalizedPrimary&&!isScalar3(property))return invalid(problem2("/spec/uiSchema/list/primaryField",field,"a top-level scalar Schema property",`Schema '${schema.metadata.name}' list primaryField '${field}' must be scalar.`))}let navResult=checkNav(schema,roots.nav);return navResult.problem?invalid(navResult.problem):{filter:filterResult.filter,list:{primaryField:normalizedPrimary,columns:normalizedColumns},nav:navResult.nav,problems:[]}}function checkFormUiSchema(schema,uiSchema,owner){if(uiSchema===void 0)return[];if(!uiSchema||typeof uiSchema!="object"||Array.isArray(uiSchema))return[problem2("/spec/uiSchema",uiSchema,"an object",`${owner}.spec.uiSchema must be an object.`)];let config=uiSchema;if(owner==="Procedure"){let unknownRoot=Object.keys(config).find(key=>key!=="collectionAction"&&key!=="fields");if(unknownRoot)return[problem2(`/spec/uiSchema/${unknownRoot}`,config[unknownRoot],"collectionAction or fields",`Procedure.spec.uiSchema.${unknownRoot} is not supported.`)]}let collectionAction=config.collectionAction;if(collectionAction!==void 0&&owner!=="Procedure")return[problem2("/spec/uiSchema/collectionAction",collectionAction,"a Procedure-only Admin collection name","Schema.spec.uiSchema.collectionAction is not supported.")];if(collectionAction!==void 0&&(typeof collectionAction!="string"||!collectionAction))return[problem2("/spec/uiSchema/collectionAction",collectionAction,"a non-empty Schema name","Procedure.spec.uiSchema.collectionAction must be a Schema-name string.")];let fields=config.fields;if(fields===void 0)return[];if(!fields||typeof fields!="object"||Array.isArray(fields))return[problem2("/spec/uiSchema/fields",fields,"an object keyed by top-level input field",`${owner}.spec.uiSchema.fields must be an object.`)];for(let[field,rawConfig]of Object.entries(fields)){let property=schema.properties?.[field];if(!property)return[problem2(`/spec/uiSchema/fields/${field}`,field,"an exact top-level key in the JSON Schema properties",`${owner}.spec.uiSchema.fields references unknown field '${field}'.`)];if(!rawConfig||typeof rawConfig!="object"||Array.isArray(rawConfig))return[problem2(`/spec/uiSchema/fields/${field}`,rawConfig,"an object with widget: textarea",`${owner}.spec.uiSchema.fields.${field} must be an object.`)];let config2=rawConfig,unknownKey=Object.keys(config2).find(key=>key!=="widget");if(unknownKey)return[problem2(`/spec/uiSchema/fields/${field}/${unknownKey}`,config2[unknownKey],"widget",`${owner}.spec.uiSchema.fields.${field}.${unknownKey} is not supported.`)];if(config2.widget!=="textarea")return[problem2(`/spec/uiSchema/fields/${field}/widget`,config2.widget,'"textarea"',`${owner}.spec.uiSchema.fields.${field}.widget must be 'textarea'.`)];if(!isString(property))return[problem2(`/spec/uiSchema/fields/${field}/widget`,field,"a top-level string property",`${owner}.spec.uiSchema.fields.${field}.widget can only target a string field.`)]}return[]}function checkListFilter(schema,list){let field=list.filterField;if(field===void 0)return{filter:null};if(typeof field!="string"||!field)return{problem:problem2("/spec/uiSchema/list/filterField",field,"a non-empty top-level field name","Schema.spec.uiSchema.list.filterField must be a field-name string."),filter:null};if((schema.spec.lifecycle??"publishing")!=="operational")return{problem:problem2("/spec/uiSchema/list/filterField",field,"a filter on an operational Schema","Schema list filter tabs are supported only for lifecycle: operational Schemas."),filter:null};let property=schema.spec.schema.properties?.[field],values=enumOptions(property)?.map(o=>o.value);return property?values?.length?checkSchemaIndexes(schema).declarations.some(({fields})=>fields[0]?.name===field)?{filter:{field,values}}:{problem:problem2("/spec/uiSchema/list/filterField",field,"the first field of a declared index tuple",`Schema '${schema.metadata.name}' list filter field '${field}' needs a left-prefix index.`),filter:null}:{problem:problem2("/spec/uiSchema/list/filterField",field,"a field with a non-empty string enum, or a oneOf of string consts",`Schema '${schema.metadata.name}' list filter field '${field}' must declare string enum values.`),filter:null}:{problem:problem2("/spec/uiSchema/list/filterField",field,"an exact top-level key in spec.schema.properties",`Schema '${schema.metadata.name}' list filter references unknown field '${field}'.`),filter:null}}function checkNav(schema,nav){if(nav===void 0)return{nav:null};if(!nav||typeof nav!="object"||Array.isArray(nav))return{nav:null,problem:problem2("/spec/uiSchema/nav",nav,"an object","Schema.spec.uiSchema.nav must be an object.")};let config=nav,bad=navPlacementProblems(config,["standalone","parentField"]);if(bad)return{nav:null,problem:problem2(`/spec/uiSchema/nav/${bad[0]}`,config[bad[0]],bad[1],`Schema.spec.uiSchema.nav.${bad[0]} must be ${bad[1]}.`)};let standalone=config.standalone;if(standalone!==void 0&&typeof standalone!="boolean")return{nav:null,problem:problem2("/spec/uiSchema/nav/standalone",standalone,"a boolean","Schema.spec.uiSchema.nav.standalone must be a boolean.")};let parentField=config.parentField;if(parentField!==void 0&&(typeof parentField!="string"||!parentField))return{nav:null,problem:problem2("/spec/uiSchema/nav/parentField",parentField,"a non-empty required x-mantle-ref field name","Schema.spec.uiSchema.nav.parentField must be a field-name string.")};if(parentField!==void 0&&standalone!==!0){let required=new Set(schema.spec.schema.required??[]);return!schema.spec.translates&&required.has(parentField)&&resolveMantleRef(schema.spec.schema.properties?.[parentField])!==null?{nav:null}:{nav:null,problem:problem2("/spec/uiSchema/nav/parentField",parentField,"a required x-mantle-ref field of a Schema that is not a translates child",schema.spec.translates?`Schema '${schema.metadata.name}' cannot declare nav.parentField because it is a translates child.`:`Schema '${schema.metadata.name}' nav.parentField must name a required x-mantle-ref field.`)}}if(standalone!==!0)return{nav:null};if(schema.spec.translates)return{nav:null,problem:problem2("/spec/uiSchema/nav/standalone",!0,"standalone on a Schema that folds under a required-ref parent",`Schema '${schema.metadata.name}' cannot declare nav.standalone because it is a translates child.`)};let eligible=requiredMantleRefFields(schema.spec.schema);if(eligible.length===0)return{nav:null,problem:problem2("/spec/uiSchema/nav/standalone",!0,"standalone on a Schema with a required x-mantle-ref parent",`Schema '${schema.metadata.name}' cannot declare nav.standalone: it has no required x-mantle-ref parent to fold under.`)};if(eligible.length===1){let only=eligible[0];return typeof parentField=="string"&&parentField!==only.field?{nav:null,problem:problem2("/spec/uiSchema/nav/parentField",parentField,`the Schema's only required x-mantle-ref field '${only.field}'`,`Schema '${schema.metadata.name}' nav.parentField must be '${only.field}'.`)}:{nav:{standalone:!0,parentField:only.field,parentCollection:only.collection}}}if(typeof parentField!="string")return{nav:null};let matched=eligible.find(item=>item.field===parentField);return matched?{nav:{standalone:!0,parentField:matched.field,parentCollection:matched.collection}}:{nav:null,problem:problem2("/spec/uiSchema/nav/parentField",parentField,`one of ${eligible.map(item=>item.field).join(", ")}`,`Schema '${schema.metadata.name}' nav.parentField must name a required x-mantle-ref field.`)}}function requiredMantleRefFields(body){let required=new Set(body.required??[]),properties=body.properties??{},fields=[];for(let[field,property]of Object.entries(properties)){if(!required.has(field))continue;let ref2=resolveMantleRef(property);ref2?.field==="id"&&fields.push({field,collection:ref2.schema})}return fields}function checkSchemaNavTargets(schema,schemasByName){let{nav,problems}=checkSchemaAdminUi(schema);if(problems.length>0||schema.spec.translates)return null;let declared=declaredParentField(schema),target2=nav?.parentCollection??(declared===void 0?void 0:resolveMantleRef(schema.spec.schema.properties?.[declared])?.schema);if(declared===void 0&&target2!==void 0&&yieldsFold(schemasByName.get(target2),schema.metadata.name))return problem2("/spec/uiSchema/nav/standalone",!0,"standalone on a Schema with a required x-mantle-ref parent",`Schema '${schema.metadata.name}' cannot declare nav.standalone: '${target2}' folds under it by nav.parentField, so it has no parent to fold under.`);if(target2!==void 0&&!isFoldParent(schemasByName.get(target2)))return problem2(declared===void 0?"/spec/uiSchema/nav/standalone":"/spec/uiSchema/nav/parentField",target2,"the metadata.name of an existing non-translates Schema",`Schema '${schema.metadata.name}' nav parent collection '${target2}' is not an eligible fold parent.`);if(declared===void 0){let eligible=eligibleIdRefs(schema,schemasByName);if(eligible.length<2)return null;let names=eligible.join(", "),keep=eligible.find(field=>!closesParentCycle(schema,field,schemasByName));return problem2("/spec/uiSchema/nav/parentField",void 0,`one of ${names}`,`Schema '${schema.metadata.name}' has more than one required id x-mantle-ref (${names}); set uiSchema.nav.parentField to choose its parent.${keep===void 0?"":` To keep the current choice, add nav: { parentField: ${keep} }.`}`)}return closesParentCycle(schema,declared,schemasByName)?problem2("/spec/uiSchema/nav/parentField",declared,"a reference whose parent chain does not lead back to this Schema",`Schema '${schema.metadata.name}' nav.parentField '${declared}' creates a parent cycle.`):null}function closesParentCycle(schema,field,schemasByName){let seen=new Set;for(let at=resolveMantleRef(schema.spec.schema.properties?.[field])?.schema;at!==void 0&&!seen.has(at);at=foldParentOf(schemasByName.get(at),schemasByName)){if(at===schema.metadata.name)return!0;seen.add(at)}return!1}function declaredParentField(schema){let nav=schema.spec.uiSchema?.nav;return typeof nav?.parentField=="string"?nav.parentField:void 0}var yieldsFold=(parent,child2)=>!!parent&&declaresFoldUnder(parent.spec.schema,parent.spec.uiSchema,child2);function declaresFoldUnder(body,uiSchema,name4){let field=uiSchema?.nav?.parentField;return typeof field=="string"&&resolveMantleRef(body.properties?.[field])?.schema===name4}var isFoldParent=s=>!!s&&!s.spec.translates;function eligibleIdRefs(schema,schemasByName){return requiredMantleRefFields(schema.spec.schema).filter(r=>inferredParent(schema,r.collection,schemasByName)).map(r=>r.field)}var inferredParent=(schema,name4,schemasByName)=>isFoldParent(schemasByName.get(name4))&&!yieldsFold(schemasByName.get(name4),schema.metadata.name);function foldParentOf(schema,schemasByName){if(!schema||schema.spec.translates)return;let field=foldParentField(schema.spec.schema,declaredParentField(schema),name4=>inferredParent(schema,name4,schemasByName));return field===void 0?void 0:resolveMantleRef(schema.spec.schema.properties?.[field])?.schema}function foldParentField(body,declared,isParent){let props=body.properties??{},required=new Set(body.required??[]),refs2=Object.keys(props).filter(f=>required.has(f)&&isParent(resolveMantleRef(props[f])?.schema??""));return declared??requiredMantleRefFields(body).find(r=>isParent(r.collection))?.field??refs2[0]}var NATIVE_LIST_FIELDS=new Set(RESERVED_ENTRY_COLUMNS);function isScalar3(schema){let types=Array.isArray(schema.type)?schema.type:schema.type?[schema.type]:[];return types.some(type=>SCALAR_TYPES.has(type))&&types.every(type=>type==="null"||SCALAR_TYPES.has(type))}function isString(schema){let types=Array.isArray(schema.type)?schema.type:schema.type?[schema.type]:[];return types.includes("string")&&types.every(type=>type==="string"||type==="null")}function problem2(pointer2,value2,expected,message2){return{pointer:pointer2,value:value2,expected,message:message2}}function invalid(problem3){return{filter:null,list:EMPTY_LIST,nav:null,problems:[problem3]}}function checkSchemaSearchableFields(manifest){let raw=manifest.spec.searchableFields;if(raw===void 0)return[];if(!Array.isArray(raw))return[{category:"shape",pointer:"/spec/searchableFields",value:raw,expected:"an array of unique top-level string field names",message:"Schema.spec.searchableFields must be an array of field-name strings."}];let properties=manifest.spec.schema.properties??{},candidates=Object.keys(properties),seen=new Set,problems=[];return raw.forEach((value2,index)=>{let pointer2=`/spec/searchableFields/${index}`;if(typeof value2!="string"){problems.push({category:"shape",pointer:pointer2,value:value2,expected:"a field-name string",message:`Schema.spec.searchableFields[${index}] must be a field-name string.`});return}if(seen.has(value2)){problems.push({category:"invalid",pointer:pointer2,value:value2,expected:"each field to appear once",message:`Schema.spec.searchableFields repeats field '${value2}'.`});return}if(seen.add(value2),!Object.hasOwn(properties,value2)){problems.push({category:"field-unknown",pointer:pointer2,value:value2,expected:"an exact top-level key in spec.schema.properties",candidates,message:`Schema '${manifest.metadata.name}' searchableFields references unknown top-level field '${value2}'.`});return}isStringProperty(properties[value2])||problems.push({category:"invalid",pointer:pointer2,value:value2,expected:"a top-level string property, optionally nullable, not a date or date-time",message:`Schema '${manifest.metadata.name}' searchable field '${value2}' is not a string property.`})}),problems}function isStringProperty(property){if(!property||typeof property!="object"||Array.isArray(property))return!1;let rawType=property.type;return["date","date-time"].includes(String(property.format))?!1:rawType==="string"?!0:Array.isArray(rawType)&&rawType.length>0&&rawType.every(type=>type==="string"||type==="null")&&rawType.includes("string")}var name=/^[a-z][a-zA-Z0-9_]{0,62}$/,reserved=" id email emailVerified name image createdAt updatedAt role banned banReason banExpires ",validUserFieldName=field=>name.test(field)&&!reserved.includes(" "+field+" ")&&!field.startsWith("mantle");function parseRowTemplate(text){if(typeof text!="string"||!text.trim())return"a row template is a non-empty predicate string";let owner,terms=[];for(let raw of text.trim().split(/\s+AND\s+/i)){let term2=raw.trim(),uid=/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*auth\.uid\(\)$/.exec(term2),user=/^([A-Za-z_][A-Za-z0-9_]*)\s+IN\s+auth\.user\('([^']*)'\)$/i.exec(term2);if(uid){if(owner)return"at most one `= auth.uid()` term";owner=uid[1];continue}if(!user)return`unsupported term '${term2}'; use column = auth.uid() or column IN auth.user('field'), joined by AND`;if(!validUserFieldName(user[2]))return`invalid or reserved user field '${user[2]}'`;if(terms.some(t=>t.column===user[1]||t.field===user[2]))return`column '${user[1]}' or field '${user[2]}' appears twice`;terms.push({column:user[1],field:user[2]})}return{...owner?{owner}:{},terms}}function validateSchemaSpec(m,idx){let s=m.spec;if(rejectUnknownKeys(s,["title","description","schema","uiSchema","checks","uniqueIndexes","indexes","searchableFields","localized","translates","lifecycle","publishing","ttl","scope","lock"],idx,"/spec"),typeof s.schema!="object"||s.schema===null)throw new ManifestParseError("Schema.spec.schema is required",idx,"/spec/schema");validateLocalizedText(s.title,idx,"/spec/title","Schema.spec.title",!0),validateLocalizedText(s.description,idx,"/spec/description","Schema.spec.description",!1);let indexProblem=checkSchemaIndexes(m).problems[0];if(indexProblem)throw new ManifestParseError(indexProblem.message,idx,indexProblem.pointer,schemaIndexDiagnosticCode(indexProblem,!0));let searchProblem=checkSchemaSearchableFields(m)[0];if(searchProblem)throw new ManifestParseError(searchProblem.message,idx,searchProblem.pointer,searchProblem.category==="shape"?"INVALID_MANIFEST_ENVELOPE":searchProblem.category==="field-unknown"?"SCHEMA_SEARCH_FIELD_UNKNOWN":"SCHEMA_SEARCH_INVALID");let adminUiProblem=checkSchemaAdminUi(m).problems[0];if(adminUiProblem)throw new ManifestParseError(adminUiProblem.message,idx,adminUiProblem.pointer,"SCHEMA_UI_INVALID");if("checks"in s&&(!Array.isArray(s.checks)||s.checks.some(c=>typeof c!="string"||!c.trim())))throw new ManifestParseError("Schema.spec.checks must be a list of SQL boolean expressions",idx,"/spec/checks");if(s.lock!==void 0&&validateLocks(s.lock,idx),"localized"in s&&typeof s.localized!="boolean")throw new ManifestParseError(`Schema.spec.localized must be a boolean; got ${JSON.stringify(s.localized)}`,idx,"/spec/localized");let schema=s.schema,properties=schema.properties;if(s.ttl!==void 0){let ttl=s.ttl;if(!ttl||typeof ttl!="object"||Array.isArray(ttl))throw new ManifestParseError("Schema.spec.ttl must be a mapping",idx,"/spec/ttl","SCHEMA_TTL_INVALID");let policy=ttl;rejectUnknownKeys(policy,["field","expireAfterSeconds"],idx,"/spec/ttl");let field=policy.field,seconds=policy.expireAfterSeconds,property=typeof field=="string"&&properties&&typeof properties=="object"&&!Array.isArray(properties)?properties[field]:void 0,types=property&&(typeof property.type=="string"?[property.type]:property.type);if(typeof field!="string"||!field||!property||property.format!=="date-time"||!Array.isArray(types)||!types.includes("string")||types.some(type=>type!=="string"&&type!=="null")||!isTtlSeconds(seconds))throw new ManifestParseError(`Schema.spec.ttl requires a top-level date-time string field and expireAfterSeconds a whole number from 0 to ${MAX_TTL_SECONDS}`,idx,"/spec/ttl","SCHEMA_TTL_INVALID")}let propertyNames=properties&&typeof properties=="object"&&!Array.isArray(properties)?Object.keys(properties):[];if(s.scope!==void 0){let template=parseRowTemplate(s.scope);if(typeof template=="string")throw new ManifestParseError(`Schema.spec.scope: ${template}`,idx,"/spec/scope");let columns2=[...template.owner?[template.owner]:[],...template.terms.map(t=>t.column)];for(let field of columns2){let property=properties&&typeof properties=="object"&&!Array.isArray(properties)?properties[field]:void 0,owner=field===template.owner;if(!property||(owner?property.type!=="string":!["string","integer","number"].includes(property.type))||property.nullable===!0||property.oneOf!==void 0||!Array.isArray(schema.required)||!schema.required.includes(field))throw new ManifestParseError(`Schema.spec.scope column '${field}' must be a required, non-nullable ${owner?"string":"string or number"} property`,idx,"/spec/scope")}if(![...m.spec.uniqueIndexes??[],...m.spec.indexes??[]].some(index=>columns2.every((field,i)=>index[i]===field)))throw new ManifestParseError(`Schema.spec.scope needs an index beginning with its scoped columns [${columns2.join(", ")}]`,idx,"/spec/scope");if(!template.terms.length&&(m.spec.uniqueIndexes??[]).some(index=>index[0]!==columns2[0]))throw new ManifestParseError("Scoped Schema unique indexes must begin with the scope field",idx,"/spec/uniqueIndexes")}if(s.localized!==!0&&propertyNames.includes("locale"))throw new ManifestParseError("Non-localized Schema must not declare the reserved entry field 'locale'; use a domain name such as 'orderLocale', or set localized: true.",idx,"/spec/schema/properties/locale");for(let reserved2 of RESERVED_ENTRY_COLUMNS)if(propertyNames.includes(reserved2))throw new ManifestParseError(`Schema '${m.metadata.name}' must not declare the native entry column '${reserved2}' as a data property; use a domain name such as 'submittedAt' or 'orderStatus'. Native columns are readable in Views and indexable through spec.indexes without being declared (handbook: reference/schema.md#reserved-entry-columns).`,idx,`/spec/schema/properties/${reserved2}`);for(let reserved2 of RESERVED_PROCEDURE_INPUT_NAMES)if(propertyNames.includes(reserved2))throw new ManifestParseError(`Schema '${m.metadata.name}' must not declare reserved Procedure input name '${reserved2}' as a data property (ADR-0022). New reserved names need an ADR.`,idx,`/spec/schema/properties/${reserved2}`);let required=schema.required;if(Array.isArray(required)){let unknownIndex=required.findIndex(field=>typeof field=="string"&&!propertyNames.includes(field));if(unknownIndex>=0){let field=required[unknownIndex];throw new ManifestParseError(`Schema '${m.metadata.name}' lists '${String(field)}' in required but never declares it under properties \u2014 the constraint is silently unenforced.`,idx,`/spec/schema/required/${unknownIndex}`,"REQUIRED_FIELD_UNKNOWN",{value:field,expected:"name of a property declared in spec.schema.properties",candidates:propertyNames})}}if(validateJsonSchema(s.schema,idx,"Schema",m.metadata.name,"/spec/schema"),properties&&typeof properties=="object"&&!Array.isArray(properties)){for(let[propertyName,property]of Object.entries(properties))if(!(!property||typeof property!="object"||Array.isArray(property))&&MANTLE_BIND_KEYWORD in property)throw new ManifestParseError(`Schema '${m.metadata.name}' property '${propertyName}': x-mantle-bind is removed. Use spec.scope for the caller's own field, or set it in the Procedure's SQL (auth.uid(), now()).`,idx,`/spec/schema/properties/${propertyName}/${MANTLE_BIND_KEYWORD}`)}if("lifecycle"in s){let lc=s.lifecycle;if(typeof lc!="string"||!V01_LIFECYCLE_MODES.has(lc))throw new ManifestParseError(`Schema.spec.lifecycle must be one of ${[...V01_LIFECYCLE_MODES].join(", ")}; got ${JSON.stringify(lc)}`,idx,"/spec/lifecycle")}if("publishing"in s){let p=s.publishing;if(!p||typeof p!="object"||Array.isArray(p))throw new ManifestParseError("Schema.spec.publishing must be a mapping { liveEdits }",idx,"/spec/publishing","SCHEMA_PUBLISHING_INVALID");if(rejectUnknownKeys(p,["liveEdits"],idx,"/spec/publishing"),"liveEdits"in p&&typeof p.liveEdits!="boolean")throw new ManifestParseError("Schema.spec.publishing.liveEdits must be a boolean",idx,"/spec/publishing/liveEdits","SCHEMA_PUBLISHING_INVALID");if(s.lifecycle!=="publishing")throw new ManifestParseError("Schema.spec.publishing applies only to lifecycle: publishing; an operational Schema already edits rows in place",idx,"/spec/publishing","SCHEMA_PUBLISHING_INVALID")}if("translates"in s&&s.translates!=null){let t=s.translates;if(typeof t!="object"||Array.isArray(t))throw new ManifestParseError("Schema.spec.translates must be an object { parent, on }",idx,"/spec/translates");let tr=t;if(rejectUnknownKeys(tr,["parent","on"],idx,"/spec/translates"),typeof tr.parent!="string"||tr.parent.length===0)throw new ManifestParseError("Schema.spec.translates.parent is required (non-empty Schema name)",idx,"/spec/translates/parent");if(typeof tr.on!="string"||tr.on.length===0)throw new ManifestParseError("Schema.spec.translates.on is required (non-empty field name)",idx,"/spec/translates/on");if(s.localized!==!0)throw new ManifestParseError("Schema.spec.translates requires Schema.spec.localized: true (a non-localized translation table is meaningless)",idx,"/spec/translates","TRANSLATES_REQUIRES_LOCALIZED");if(!propertyNames.some(name4=>name4!=="locale"&&name4!==tr.on))throw new ManifestParseError("Schema.spec.translates requires at least one locale-specific field besides 'locale' and the join field",idx,"/spec/schema/properties","TRANSLATES_REQUIRES_CONTENT_FIELD");if(!propertyNames.includes(tr.on))throw new ManifestParseError(`Schema '${m.metadata.name}' translates.on field '${String(tr.on)}' is not declared on this Schema's own properties.`,idx,"/spec/translates/on","TRANSLATES_FIELD_NOT_IN_CHILD",{value:tr.on,expected:`field declared in Schema '${m.metadata.name}' spec.schema.properties`,candidates:propertyNames})}return m}var UNSUPPORTED_JSON_SCHEMA_KEYWORDS=new Set(["allOf","not","$anchor","$dynamicAnchor","$dynamicRef","definitions","patternProperties","prefixItems","contains","dependentSchemas","propertyNames","unevaluatedProperties"]);function validateJsonSchema(root,idx,kind,name4,basePointer){if(!root||typeof root!="object"||Array.isArray(root))throw new ManifestParseError(`${kind} '${name4}' JSON Schema must be an object`,idx,basePointer);let rootObject=root,nodes=0,refs2=[],visit=(node,pointer2,depth)=>{if(!node||typeof node!="object"||Array.isArray(node))throw new ManifestParseError(`${kind} '${name4}' has a non-object JSON Schema at ${pointer2}`,idx,pointer2);if(depth>100||++nodes>1e4)throw new ManifestParseError(`${kind} '${name4}' exceeds the JSON Schema complexity limit`,idx,pointer2,"JSON_SCHEMA_LIMIT_EXCEEDED");let value2=node;for(let keyword of UNSUPPORTED_JSON_SCHEMA_KEYWORDS)if(keyword in value2)throw new ManifestParseError(`${kind} '${name4}' uses unsupported JSON Schema keyword '${keyword}'`,idx,`${pointer2}/${escapeJsonPointerSegment(keyword)}`,"JSON_SCHEMA_UNSUPPORTED");if(basePointer!=="/spec/input"){for(let keyword of INPUT_RULE_KEYWORDS)if(keyword in value2)throw new ManifestParseError(`${kind} '${name4}' uses JSON Schema keyword '${keyword}', which is supported only in View and Procedure input`,idx,`${pointer2}/${escapeJsonPointerSegment(keyword)}`,"JSON_SCHEMA_UNSUPPORTED")}if("$ref"in value2&&refs2.push([`${pointer2}/$ref`,value2.$ref,validateLocalSchemaRef(value2.$ref,rootObject,idx,kind,name4,`${pointer2}/$ref`)]),value2.enum!==void 0&&(!Array.isArray(value2.enum)||value2.enum.length>MAX_JSON_SCHEMA_ENUM))throw new ManifestParseError(`${kind} '${name4}' enum must be a list of at most ${MAX_JSON_SCHEMA_ENUM} values`,idx,`${pointer2}/enum`,"JSON_SCHEMA_LIMIT_EXCEEDED");if(value2.pattern!==void 0){let problem3=typeof value2.pattern=="string"?unsafePattern(value2.pattern):"a pattern is a string";if(problem3)throw new ManifestParseError(`${kind} '${name4}' has a regex pattern at ${pointer2} that could take exponential time: ${problem3}`,idx,`${pointer2}/pattern`,"INVALID_PATTERN",{value:value2.pattern,expected:`a regular expression of at most ${MAX_JSON_SCHEMA_PATTERN} characters with no repeated group that itself repeats or alternates`});try{new RegExp(value2.pattern)}catch(error){throw new ManifestParseError(`${kind} '${name4}' has an uncompilable regex pattern at ${pointer2}: ${error instanceof Error?error.message:String(error)}`,idx,`${pointer2}/pattern`,"INVALID_PATTERN",{value:value2.pattern,expected:"a valid JavaScript regular expression"})}let{exponent,branches}=patternCost(value2.pattern),maxLength=value2.maxLength,bounded=typeof maxLength=="number"&&Number.isInteger(maxLength)&&maxLength>=0;if(branches*(exponent===0?1:bounded?maxLength**exponent:1/0)>MAX_PATTERN_WORK){let limit=maxPatternLength(exponent,branches),cost=`${branches===1?"":`${branches} alternative paths \xD7 `}maxLength^${exponent}`;throw new ManifestParseError(`${kind} '${name4}' has a regex pattern at ${pointer2} that could cost ${cost} backtracking steps on one string (${exponent} = its variable quantifiers *, +, ?, {m,}, {m,n}, plus 1 unless it starts with ^), over the ${MAX_PATTERN_WORK} limit. ${limit>0?`Declare maxLength of at most ${limit}, anchor it with ^, or use fewer variable quantifiers or alternatives.`:"Use fewer alternatives, or an enum."}`,idx,`${pointer2}/pattern`,"INVALID_PATTERN",{value:value2.pattern,expected:limit>0?`a string with maxLength of at most ${limit}`:`at most ${MAX_PATTERN_WORK} alternative paths`})}}let properties=value2.properties;if(properties!==void 0&&(!properties||typeof properties!="object"||Array.isArray(properties)))throw new ManifestParseError(`${kind} '${name4}' properties must be an object`,idx,`${pointer2}/properties`);if(properties&&typeof properties=="object")for(let[property,child2]of Object.entries(properties))visit(child2,`${pointer2}/properties/${escapeJsonPointerSegment(property)}`,depth+1);if(value2.items!==void 0&&visit(value2.items,`${pointer2}/items`,depth+1),typeof value2.additionalProperties=="object"&&value2.additionalProperties!==null)visit(value2.additionalProperties,`${pointer2}/additionalProperties`,depth+1);else if(value2.additionalProperties!==void 0&&typeof value2.additionalProperties!="boolean")throw new ManifestParseError(`${kind} '${name4}' additionalProperties must be a boolean or schema`,idx,`${pointer2}/additionalProperties`);let defs=value2.$defs;if(defs!==void 0){if(!defs||typeof defs!="object"||Array.isArray(defs))throw new ManifestParseError(`${kind} '${name4}' $defs must be an object`,idx,`${pointer2}/$defs`);for(let[definition,child2]of Object.entries(defs))visit(child2,`${pointer2}/$defs/${escapeJsonPointerSegment(definition)}`,depth+1)}let oneOf=value2.oneOf;if(oneOf!==void 0){if(!Array.isArray(oneOf)||oneOf.length===0)throw new ManifestParseError(`${kind} '${name4}' oneOf must be a non-empty array`,idx,`${pointer2}/oneOf`);oneOf.forEach((child2,index)=>visit(child2,`${pointer2}/oneOf/${index}`,depth+1))}};visit(root,basePointer,0);let target2=new Map(refs2.map(([,ref2,node])=>[ref2,node])),next=node=>!node||typeof node!="object"?[]:[..."$ref"in node?[node.$ref]:[],...Array.isArray(node.oneOf)?node.oneOf.flatMap(next):[]],done=new Set,onPath=new Set,at=basePointer,cycle=ref2=>{if(onPath.has(ref2))return!0;if(done.has(ref2))return!1;onPath.add(ref2);let node=typeof ref2=="string"&&target2.has(ref2)?target2.get(ref2):validateLocalSchemaRef(ref2,rootObject,idx,kind,name4,at),found=next(node).some(cycle);return onPath.delete(ref2),done.add(ref2),found};for(let[pointer2,ref2]of refs2)if(at=pointer2,cycle(ref2))throw new ManifestParseError(`${kind} '${name4}' $ref '${ref2}' refers back to itself without reading any part of the value`,idx,pointer2,"JSON_SCHEMA_REF_INVALID",{value:ref2,expected:"a $ref cycle only through properties, items or additionalProperties"})}var MAX_JSON_SCHEMA_ENUM=1e3,MAX_JSON_SCHEMA_PATTERN=1e3;function unsafePattern(pattern){return scanPattern(pattern).problem}function patternCost(pattern){let{variable,branches,anchored}=scanPattern(pattern);return{exponent:variable+(anchored?0:1),branches}}var MAX_PATTERN_WORK=1e7;function maxPatternLength(exponent,branches=1){let work=MAX_PATTERN_WORK/branches;if(work<1)return 0;if(exponent===0)return 1/0;let n=Math.floor(work**(1/exponent));for(;(n+1)**exponent<=work;)n++;for(;n>0&&n**exponent>work;)n--;return n}function scanPattern(pattern){let variable=0,branches=1,anchored=pattern.startsWith("^");if(pattern.length>MAX_JSON_SCHEMA_PATTERN)return{problem:`longer than ${MAX_JSON_SCHEMA_PATTERN} characters`,variable,branches,anchored};let stack=[{quantified:!1,alternates:!1,branches:1}],group,atom=!1;for(let i=0;i<pattern.length;i++){let c=pattern[i],top=stack.at(-1),brace=c==="{"?/^\{(\d+)(,(\d*))?\}/.exec(pattern.slice(i)):null;if(atom&&(c==="*"||c==="+"||c==="?"||brace)){let min=brace?+brace[1]:c==="+"?1:0,max=brace?brace[2]===void 0?min:brace[3]?+brace[3]:1/0:c==="?"?1:1/0;if(brace&&(i+=brace[0].length-1),pattern[i+1]==="?"&&i++,group&&max>1&&group.quantified)return{problem:"a repeated group whose body repeats (nested quantifiers)",variable,branches,anchored};if(group&&max>1&&group.alternates)return{problem:"a repeated group whose body alternates",variable,branches,anchored};max!==min&&(top.quantified=!0,variable++),group=void 0,atom=!1;continue}if(group=void 0,atom=!0,c==="\\"){let e=pattern[i+1];if(e!==void 0&&(/[1-9]/.test(e)||e==="k"))return{problem:"a backreference",variable,branches,anchored};i++}else if(c==="["){let j=i+1;for(pattern[j]==="^"&&j++;j<pattern.length&&pattern[j]!=="]";)j+=pattern[j]==="\\"?2:1;i=j}else if(c==="("){if(stack.push({quantified:!1,alternates:!1,branches:1}),atom=!1,pattern[i+1]==="?"){let head=/^\?(?::|=|!|<=|<!|<[A-Za-z_$][\w$]*>)/.exec(pattern.slice(i+1));head&&(i+=head[0].length)}}else if(c===")"&&stack.length>1){let closed=stack.pop(),parent=stack.at(-1);parent.quantified||=closed.quantified,parent.alternates||=closed.alternates,branches*=closed.branches,group=closed}else c==="|"?(top.alternates=!0,top.branches++,atom=!1):(c==="^"||c==="$")&&(atom=!1)}return{variable,branches:branches*stack[0].branches,anchored:anchored&&stack[0].branches===1}}function validateLocalSchemaRef(ref2,root,idx,kind,name4,pointer2){if(typeof ref2!="string"||!ref2.startsWith("#/$defs/"))throw new ManifestParseError(`${kind} '${name4}' $ref must be a same-document pointer beginning '#/$defs/'`,idx,pointer2,"JSON_SCHEMA_REF_INVALID",{value:ref2,expected:"#/$defs/<definition>"});let tokens;try{tokens=decodeURIComponent(ref2.slice(2)).split("/")}catch{tokens=void 0}let current=tokens?root:void 0;for(let token of tokens??[])if(/~(?:[^01]|$)/.test(token))current=void 0;else if(current&&typeof current=="object"){let key=token.replace(/~1/g,"/").replace(/~0/g,"~");current=Object.prototype.hasOwnProperty.call(current,key)?current[key]:void 0}else current=void 0;if(!current||typeof current!="object"||Array.isArray(current))throw new ManifestParseError(`${kind} '${name4}' cannot resolve local $ref '${ref2}'`,idx,pointer2,"JSON_SCHEMA_REF_INVALID",{value:ref2,expected:"a JSON Schema object in this document"});return current}function validateLocks(value2,idx){let fail=(message2,pointer2="/spec/lock")=>{throw new ManifestParseError(`Schema.spec.lock${message2}`,idx,pointer2,"SCHEMA_LOCK_INVALID")};(!Array.isArray(value2)||!value2.length)&&fail(" must be a non-empty list of { name, on, when, message }");let names=new Set;value2.forEach((entry,i)=>{let at=`/spec/lock/${i}`;if(!entry||typeof entry!="object"||Array.isArray(entry))return fail(`[${i}] must be a mapping { name, on, when, message }`,at);let lock=entry;rejectUnknownKeys(lock,["name","on","when","message"],idx,at);let name4=lock.name,on=lock.on;(typeof name4!="string"||!/^[A-Za-z_][A-Za-z0-9_-]*$/.test(name4))&&fail(`[${i}].name must be an identifier`,`${at}/name`),names.has(String(name4).toLowerCase())&&fail(`[${i}].name '${name4}' is declared twice`,`${at}/name`),names.add(String(name4).toLowerCase()),(!Array.isArray(on)||!on.length||on.some(v=>!LOCK_VERBS.includes(v))||new Set(on).size!==on.length)&&fail(`[${i}].on must be a non-empty list of distinct verbs from ${LOCK_VERBS.join(", ")}`,`${at}/on`);for(let key of["when","message"])(typeof lock[key]!="string"||!lock[key].trim())&&fail(`[${i}].${key} must be a non-empty string`,`${at}/${key}`)})}function validateViewSpec(m,idx){let s=m.spec;if(rejectUnknownKeys(s,["title","description","uiSchema","sql","surface","cache","requires","restrict","input"],idx,"/spec"),validateLocalizedText(s.title,idx,"/spec/title","View.spec.title",!1),validateLocalizedText(s.description,idx,"/spec/description","View.spec.description",!1),typeof s.sql!="string"||s.sql.trim().length===0)throw new ManifestParseError("View.spec.sql is required (one SELECT statement)",idx,"/spec/sql");let surface=s.surface;if(typeof surface!="string"||!V01_VIEW_SURFACES.has(surface))throw new ManifestParseError(`View.spec.surface is required and must be one of ${[...V01_VIEW_SURFACES].join(", ")}; got ${JSON.stringify(surface)}`,idx,"/spec/surface");"cache"in s&&validateViewCache(s.cache,m,idx),"requires"in s&&s.requires!=null&&validateRequires(s.requires,idx,"View");let adminUiProblem=checkViewAdminUi(m).problems[0];if(adminUiProblem)throw new ManifestParseError(adminUiProblem.message,idx,adminUiProblem.pointer,"VIEW_UI_INVALID");return"input"in s&&s.input!=null&&(validateViewInput(s.input,idx),validateJsonSchema(s.input,idx,"View",m.metadata.name,"/spec/input")),m}function validateViewCache(raw,view,idx){if(typeof raw!="object"||raw===null||Array.isArray(raw))throw new ManifestParseError("View.spec.cache must be an object",idx,"/spec/cache","VIEW_CACHE_INVALID");let cache=raw;rejectUnknownKeys(cache,["sharedMaxAge"],idx,"/spec/cache");let maxAge=cache.sharedMaxAge;if(!Number.isInteger(maxAge)||maxAge<1||maxAge>86400)throw new ManifestParseError("View.spec.cache.sharedMaxAge must be an integer from 1 to 86400",idx,"/spec/cache/sharedMaxAge","VIEW_CACHE_INVALID");if(view.spec.surface!=="public"||view.spec.requires||view.spec.restrict)throw new ManifestParseError("View.spec.cache requires an unguarded public View without restrict",idx,"/spec/cache","VIEW_CACHE_INVALID")}function validateViewInput(raw,idx){let invalid2=(message2,pointer2,code="VIEW_INPUT_INVALID_SHAPE")=>{throw new ManifestParseError(message2,idx,pointer2,code)};(typeof raw!="object"||raw===null||Array.isArray(raw))&&invalid2("View.spec.input must be a JSON Schema object","/spec/input");let p=raw;p.type!=="object"&&invalid2(`View.spec.input.type must be "object"; got ${JSON.stringify(p.type)}`,"/spec/input/type");let props=p.properties;(typeof props!="object"||props===null||Array.isArray(props))&&invalid2("View.spec.input.properties is required (declare each accepted parameter)","/spec/input/properties");for(let reserved2 of VIEW_INPUT_RESERVED)Object.hasOwn(props,reserved2)&&invalid2(`View.spec.input.properties.${reserved2} is reserved (the runtime owns ${VIEW_INPUT_RESERVED.join(", ")} for pagination); rename it.`,`/spec/input/properties/${reserved2}`,"VIEW_INPUT_RESERVED_NAME")}function validateProcedureSpec(m,idx){let s=m.spec;if(rejectUnknownKeys(s,["title","description","requires","restrict","input","uiSchema","output","handler","mcp","target"],idx,"/spec"),s.mcp!==void 0){let mcp=s.mcp;if(typeof mcp!="object"||mcp===null||Array.isArray(mcp))throw new ManifestParseError("Procedure.spec.mcp must be an object of boolean tool annotations",idx,"/spec/mcp");rejectUnknownKeys(mcp,[...PROCEDURE_MCP_ANNOTATION_KEYS],idx,"/spec/mcp");for(let key of PROCEDURE_MCP_ANNOTATION_KEYS){let value2=mcp[key];if(value2!==void 0&&typeof value2!="boolean")throw new ManifestParseError(`Procedure.spec.mcp.${key} must be a boolean`,idx,`/spec/mcp/${key}`)}let hints=mcp;if(hints.readOnlyHint===!0&&hints.destructiveHint===!0)throw new ManifestParseError("Procedure.spec.mcp cannot be both readOnlyHint: true and destructiveHint: true",idx,"/spec/mcp")}if(s.target!==void 0&&validateProcedureTargetShape(s.target,idx),validateLocalizedText(s.title,idx,"/spec/title","Procedure.spec.title",!1),validateLocalizedText(s.description,idx,"/spec/description","Procedure.spec.description",!1),typeof s.input!="object"||s.input===null)throw new ManifestParseError("Procedure.spec.input is required (JSON Schema)",idx,"/spec/input");validateJsonSchema(s.input,idx,"Procedure",m.metadata.name,"/spec/input");let uiProblem=checkFormUiSchema(s.input,s.uiSchema,"Procedure")[0];if(uiProblem)throw new ManifestParseError(uiProblem.message,idx,uiProblem.pointer,"SCHEMA_UI_INVALID");if(typeof s.output!="object"||s.output===null)throw new ManifestParseError("Procedure.spec.output is required (JSON Schema)",idx,"/spec/output");validateJsonSchema(s.output,idx,"Procedure",m.metadata.name,"/spec/output");let handler=s.handler;if(!handler)throw new ManifestParseError("Procedure.spec.handler is required",idx,"/spec/handler");if(validateHandlerBinding(handler,idx),"requires"in s&&s.requires!=null&&validateRequires(s.requires,idx,"Procedure"),!("steps"in handler))return m;let steps=handler.steps;return{...m,spec:{...m.spec,handler:{sql:stepProgram(steps).sql,steps}}}}function validateProcedureTargetShape(target2,idx){if(typeof target2!="object"||target2===null||Array.isArray(target2))throw new ManifestParseError("Procedure.spec.target must be an object { schema, id, version? }",idx,"/spec/target","PROCEDURE_TARGET_INVALID");rejectUnknownKeys(target2,[...PROCEDURE_TARGET_KEYS],idx,"/spec/target");for(let key of PROCEDURE_TARGET_KEYS){let value2=target2[key];if(!(value2===void 0&&key==="version")&&(typeof value2!="string"||value2.length===0))throw new ManifestParseError(`Procedure.spec.target.${key} must be a non-empty string`,idx,`/spec/target/${key}`,"PROCEDURE_TARGET_INVALID")}}function validateHandlerBinding(h,idx){if("mustWrite"in h)throw new ManifestParseError('Procedure.spec.handler.mustWrite was replaced by handler.steps[].onNoRows: conflict (#1874). Write the program as steps, one statement each, and mark the set op that must write: handler: { steps: [{ sql: "INSERT INTO \u2026 SELECT \u2026 WHERE \u2026", onNoRows: conflict }, { sql: "UPDATE \u2026" }] }',idx,"/spec/handler/mustWrite");let keys=Object.keys(h),key=keys.length===1?keys[0]:void 0;if(key!=="ref"&&key!=="sql"&&key!=="steps")throw new ManifestParseError(`Procedure.spec.handler must have exactly one key, \`sql\`, \`steps\` or \`ref\`; got ${JSON.stringify(keys)}`,idx,"/spec/handler");if(key==="steps"){let steps=h.steps;if(!Array.isArray(steps)||steps.length===0)throw new ManifestParseError("Procedure.spec.handler.steps must be a non-empty list of steps, each { sql, onNoRows? }",idx,"/spec/handler/steps");for(let[i,step]of steps.entries()){let at=`/spec/handler/steps/${i}`;if(typeof step!="object"||step===null||Array.isArray(step))throw new ManifestParseError(`Procedure.spec.handler.steps[${i}] must be an object { sql, onNoRows? }`,idx,at);rejectUnknownKeys(step,HANDLER_STEP_KEYS,idx,at);let{sql:sql4,onNoRows}=step;if(typeof sql4!="string"||sql4.trim().length===0)throw new ManifestParseError(`Procedure.spec.handler.steps[${i}].sql is required (one statement)`,idx,`${at}/sql`);if(onNoRows!==void 0&&onNoRows!=="conflict")throw new ManifestParseError(`Procedure.spec.handler.steps[${i}].onNoRows must be \`conflict\`; got ${JSON.stringify(onNoRows)}`,idx,`${at}/onNoRows`)}return}if(typeof h[key]!="string"||h[key].trim().length===0)throw new ManifestParseError(key==="ref"?"Procedure.spec.handler.ref is required (non-empty registration key)":"Procedure.spec.handler.sql is required (one or more write statements)",idx,`/spec/handler/${key}`)}function validateRequires(req,idx,atom){if(typeof req!="object"||req===null)throw new ManifestParseError(`${atom}.spec.requires must be an object`,idx);let r=req;if(rejectUnknownKeys(r,["auth","guard"],idx,"/spec/requires"),"guard"in r){let guard=r.guard;if(typeof guard!="object"||guard===null||Array.isArray(guard))throw new ManifestParseError(`${atom}.spec.requires.guard must be an object`,idx);let g=guard;if(typeof g.procedure!="string"||g.procedure.length===0)throw new ManifestParseError(`${atom}.spec.requires.guard.procedure must be a non-empty Procedure name`,idx);let extra=Object.keys(g).find(key=>key!=="procedure");if(extra!==void 0)throw new ManifestParseError(`${atom}.spec.requires.guard.${extra} is not supported; guard accepts only \`procedure\``,idx)}if(!("auth"in r)||r.auth==null)return;let auth=r.auth;if(typeof auth!="object"||auth===null)throw new ManifestParseError(`${atom}.spec.requires.auth must be an object`,idx);let a=auth;if(rejectUnknownKeys(a,["all"],idx,"/spec/requires/auth"),!("all"in a))throw new ManifestParseError(`${atom}.spec.requires.auth must declare \`all\` (v0.1)`,idx);let all=a.all;if(!Array.isArray(all)||all.length===0)throw new ManifestParseError(`${atom}.spec.requires.auth.all must be a non-empty array`,idx);for(let i=0;i<all.length;i++)validateAuthPredicate(all[i],idx,`${atom}.spec.requires.auth.all[${i}]`,`/spec/requires/auth/all/${i}`)}function validateAuthPredicate(p,idx,path,pointer2){if(p==="ctx.staff"||typeof p=="object"&&p!==null&&"ctx.staff"in p)throw new ManifestParseError(`${path}: 'ctx.staff' was renamed to 'ctx.admin'; replace it with 'ctx.admin'.`,idx);if(!(p==="ctx.user"||p==="ctx.auth"||p==="ctx.admin")){if(typeof p=="object"&&p!==null&&!Array.isArray(p)){let o=p;if("ctx.auth.scope"in o){rejectUnknownKeys(o,["ctx.auth.scope"],idx,pointer2);let scope=o["ctx.auth.scope"];if(typeof scope!="string"||scope.length===0)throw new ManifestParseError(`${path}: 'ctx.auth.scope' value must be a non-empty string`,idx);return}if("ctx.admin"in o)throw new ManifestParseError(`${path}: role lists in requires ('ctx.admin: [...]') are withdrawn; use 'ctx.admin' (any admin) and decide per-target roles in the application's authorize(target, caller) seam`,idx)}throw new ManifestParseError(`${path} must be 'ctx.user', 'ctx.auth', 'ctx.admin', or { 'ctx.auth.scope': <scope> }; got ${JSON.stringify(p)}`,idx)}}function validateHttpSource(source,idx){rejectUnknownKeys(source,["kind","method","path"],idx,"/spec/source");let method=source.method;if(typeof method!="string"||!V01_HTTP_METHODS.has(method))throw new ManifestParseError(`Trigger.spec.source.method must be one of ${[...V01_HTTP_METHODS].join(", ")} (v0.1); got ${JSON.stringify(method)}`,idx,"/spec/source/method");let path=source.path;if(typeof path!="string"||path.length===0||!path.startsWith("/"))throw new ManifestParseError("Trigger.spec.source.path is required (non-empty string starting with '/')",idx,"/spec/source/path")}function validateLifecycleSource(source,idx){if(rejectUnknownKeys(source,["kind","schema","on"],idx,"/spec/source"),typeof source.schema!="string"||source.schema.length===0)throw new ManifestParseError("Trigger.spec.source.schema is required (Schema metadata.name) when source.kind is 'lifecycle'",idx,"/spec/source/schema");let on=source.on;if(!Array.isArray(on)||on.length===0)throw new ManifestParseError(`Trigger.spec.source.on must be a non-empty array of hook names (one of ${[...V01_LIFECYCLE_HOOKS].join(", ")})`,idx,"/spec/source/on");for(let i=0;i<on.length;i++){let hook=on[i];if(typeof hook!="string"||!V01_LIFECYCLE_HOOKS.has(hook))throw new ManifestParseError(`Trigger.spec.source.on[${i}] must be one of ${[...V01_LIFECYCLE_HOOKS].join(", ")}; got ${JSON.stringify(hook)}`,idx,`/spec/source/on/${i}`)}}function validateMcpSource(source,idx){rejectUnknownKeys(source,["kind","surface"],idx,"/spec/source");let surface=source.surface;if(typeof surface!="string"||!V01_MCP_TRIGGER_SURFACES.has(surface))throw new ManifestParseError(`Trigger.spec.source.surface must be one of ${[...V01_MCP_TRIGGER_SURFACES].join(", ")}; got ${JSON.stringify(surface)}`,idx,"/spec/source/surface")}function validateScheduleSource(source,idx){rejectUnknownKeys(source,["kind","cron","enabled"],idx,"/spec/source");let cron=source.cron,bounds=[[0,59],[0,23],[1,31],[1,12],[0,6]],fields=typeof cron=="string"?cron.split(" "):[];if(!(fields.length===5&&fields.every((field,index)=>{let[min,max]=bounds[index];return field.split(",").every(part=>{let match=/^(\*|\d+)(?:-(\d+))?(?:\/(\d+))?$/.exec(part);if(!match)return!1;let start=match[1]==="*"?min:Number(match[1]),end=match[2]===void 0?match[1]==="*"?max:start:Number(match[2]),step=match[3]===void 0?1:Number(match[3]);return start>=min&&end<=max&&start<=end&&step>=1&&(match[3]===void 0||match[1]==="*"||match[2]!==void 0)})})))throw new ManifestParseError("Trigger.spec.source.cron must be a five-field POSIX UTC cron expression (minute hour day month weekday, 0=Sunday)",idx,"/spec/source/cron");if(source.enabled!==void 0&&typeof source.enabled!="boolean")throw new ManifestParseError("Trigger.spec.source.enabled must be boolean",idx,"/spec/source/enabled")}function validateTriggerSpec(m,idx){let s=m.spec;rejectUnknownKeys(s,["source","target"],idx,"/spec");let source=s.source;if(!source)throw new ManifestParseError("Trigger.spec.source is required",idx,"/spec/source");let sourceKind=source.kind;if(typeof sourceKind!="string")throw new ManifestParseError(`Trigger.spec.source.kind is required (one of ${[...V01_TRIGGER_SOURCE_KINDS].join(", ")})`,idx,"/spec/source/kind");if(!V01_TRIGGER_SOURCE_KINDS.has(sourceKind))throw new ManifestParseError(`Trigger.spec.source.kind must be one of ${[...V01_TRIGGER_SOURCE_KINDS].join(", ")}; got '${sourceKind}'`,idx,"/spec/source/kind");sourceKind==="http"?validateHttpSource(source,idx):sourceKind==="lifecycle"?validateLifecycleSource(source,idx):sourceKind==="mcp"?validateMcpSource(source,idx):sourceKind==="schedule"&&validateScheduleSource(source,idx);let target2=s.target;if(!target2||typeof target2.procedure!="string")throw new ManifestParseError("Trigger.spec.target.procedure is required (string)",idx,"/spec/target/procedure");return rejectUnknownKeys(target2,["procedure"],idx,"/spec/target"),m}function parseManifestSources(sourceSet,defaultLifecycle="publishing"){let parsed=parseManifestSourcesInternal(sourceSet,defaultLifecycle);return parsed.diagnostics.some(diagnostic=>diagnostic.severity==="error")?{ok:!1,diagnostics:parsed.diagnostics}:{ok:!0,value:Object.freeze({entries:Object.freeze(parsed.entries)}),diagnostics:parsed.diagnostics}}function parseManifestSourcesInternal(sourceSet,defaultLifecycle){let entries=[],diagnostics=[],sources=sourceSet?.sources;if(!Array.isArray(sources))return diagnostics.push(invalidSourceDiagnostic("/sources","ManifestSourceSet.sources must be an array")),{entries,diagnostics};let seenIds=new Set;for(let index=0;index<sources.length;index++){let source=sources[index];if(!source||typeof source!="object"){diagnostics.push(invalidSourceDiagnostic(`/sources/${index}`,"manifest source must be an object"));continue}if(typeof source.sourceId!="string"||source.sourceId.length===0){diagnostics.push(invalidSourceDiagnostic(`/sources/${index}/sourceId`,"manifest sourceId must be a non-empty string"));continue}if(seenIds.has(source.sourceId)){diagnostics.push(invalidSourceDiagnostic(`/sources/${index}/sourceId`,`manifest sourceId '${source.sourceId}' is duplicated`,source.sourceId));continue}if(seenIds.add(source.sourceId),typeof source.text!="string"){diagnostics.push(invalidSourceDiagnostic(`/sources/${index}/text`,`manifest source '${source.sourceId}' text must be a string`,source.sourceId));continue}parseOneStream(source,entries,diagnostics,defaultLifecycle)}return{entries,diagnostics}}function invalidSourceDiagnostic(path,message2,sourceId){return validateDiagnostic({code:"INVALID_MANIFEST_ENVELOPE",severity:"error",path,...sourceId?{source:{sourceId,documentIndex:0,path}}:{},message:message2})}function parseOneStream(source,entries,diagnostics,defaultLifecycle){let lineCounter=new LineCounter2,docs=parseAllDocuments(source.text,{merge:!1,lineCounter});for(let i=0;i<docs.length;i++){let doc=docs[i],docIndex=i;if(doc.errors.length>0){let error=doc.errors[0],location=sourceLocation(source.sourceId,docIndex,"/",lineCounter,error?.pos??doc.range);diagnostics.push(validateDiagnostic({code:"INVALID_MANIFEST_ENVELOPE",severity:"error",path:"/",source:location,message:`[doc ${docIndex}] YAML parse error: ${doc.errors.map(e=>e.message).join("; ")}`}));continue}let value2;try{value2=doc.toJS({maxAliasCount:100})}catch(e){diagnostics.push(validateDiagnostic({code:"INVALID_MANIFEST_ENVELOPE",severity:"error",path:"/",source:sourceLocationForNode(source.sourceId,docIndex,"/",doc,lineCounter),message:`[doc ${docIndex}] YAML alias-expansion limit exceeded: ${e instanceof Error?e.message:String(e)}`}));continue}if(value2!=null)try{entries.push({manifest:normalizeManifest(validateEnvelope(value2,docIndex),defaultLifecycle),source:sourceLocationForNode(source.sourceId,docIndex,"/",doc,lineCounter),sourceSpans:collectSourceSpans(doc.contents,lineCounter)})}catch(e){if(e instanceof ManifestParseError){let path=e.pointer??"/";diagnostics.push(validateDiagnostic({code:e.code,severity:"error",path,source:sourceLocationForNode(source.sourceId,docIndex,path,doc,lineCounter),...e.details,message:e.message}))}else diagnostics.push(validateDiagnostic({code:"INVALID_MANIFEST_ENVELOPE",severity:"error",path:"/",source:sourceLocationForNode(source.sourceId,docIndex,"/",doc,lineCounter),message:e instanceof Error?`[doc ${docIndex}] ${e.message}`:`[doc ${docIndex}] unknown parse error`}))}}}function normalizeManifest(manifest,defaultLifecycle){return manifest.kind==="Schema"?{...manifest,spec:{...manifest.spec,uniqueIndexes:manifest.spec.uniqueIndexes??[],indexes:manifest.spec.indexes??[],searchableFields:manifest.spec.searchableFields??[],localized:manifest.spec.localized??!1,lifecycle:manifest.spec.lifecycle??defaultLifecycle}}:manifest}function validateEnvelope(raw,docIndex){if(typeof raw!="object"||raw===null||Array.isArray(raw))throw new ManifestParseError("manifest must be a YAML mapping",docIndex);let m=raw;if(rejectUnknownKeys(m,["apiVersion","kind","metadata","spec"],docIndex,"/"),m.apiVersion!==API_VERSION)throw new ManifestParseError(`apiVersion must be "${API_VERSION}"; got ${JSON.stringify(m.apiVersion)}`+(m.apiVersion==="cms.mantle.aotter.net/v1"?" (a 0.1.x manifest: follow node_modules/@aotter/mantle/docs/upgrade-0.1-to-0.2.md)":""),docIndex,"/apiVersion");let kind=m.kind;if(typeof kind!="string"||!KNOWN_KINDS.has(kind))throw new ManifestParseError(`kind must be one of ${[...KNOWN_KINDS].join(", ")}; got ${JSON.stringify(kind)}`,docIndex,"/kind");let meta=m.metadata;if(typeof meta!="object"||meta===null)throw new ManifestParseError("metadata is required and must be a mapping",docIndex,"/metadata");let name4=meta.name;if(rejectUnknownKeys(meta,["name"],docIndex,"/metadata"),typeof name4!="string"||name4.length===0)throw new ManifestParseError("metadata.name is required (non-empty string)",docIndex,"/metadata/name");let spec=m.spec;if(typeof spec!="object"||spec===null)throw new ManifestParseError("spec is required and must be a mapping",docIndex,"/spec");switch(kind){case"Schema":return validateSchemaSpec(raw,docIndex);case"View":return validateViewSpec(raw,docIndex);case"Procedure":return validateProcedureSpec(raw,docIndex);case"Trigger":return validateTriggerSpec(raw,docIndex);default:throw new ManifestParseError(`unhandled kind ${kind}`,docIndex)}}function manifestPath(kind,name4,jsonPointer,filePaths,occurrence=1){let locations=filePaths?.get(`${kind}/${name4}`),fp=locations?.[Math.max(0,occurrence-1)]??locations?.[0];return fp?`${fp.file}#/${fp.docIndex}${jsonPointer}`:`manifest:${kind}/${name4}#${jsonPointer}`}function bestMatch(target2,candidates){let best,bestD=3;for(let c of candidates){let d=editDistance(target2,c);d<bestD&&(bestD=d,best=c)}return best}function editDistance(a,b){if(a===b)return 0;if(a.length===0)return b.length;if(b.length===0)return a.length;let dp=Array.from({length:a.length+1},()=>Array(b.length+1).fill(0));for(let i=0;i<=a.length;i++)dp[i][0]=i;for(let j=0;j<=b.length;j++)dp[0][j]=j;for(let i=1;i<=a.length;i++)for(let j=1;j<=b.length;j++){let cost=a[i-1]===b[j-1]?0:1;dp[i][j]=Math.min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+cost)}return dp[a.length][b.length]}function checkTranslatesReferences(schemas,phase,filePaths){let out=[],schemasByName=new Map(schemas.map(schema=>[schema.metadata.name,schema]));for(let s of schemas){let translates=s.spec.translates;if(!translates)continue;let path=jsonPointer=>manifestPath("Schema",s.metadata.name,jsonPointer,filePaths),parent=schemasByName.get(translates.parent);if(!parent){out.push(emit(phase,{code:"TRANSLATES_PARENT_UNKNOWN",severity:"error",path:path("/spec/translates/parent"),value:translates.parent,expected:"name of a declared Schema",candidates:[...schemasByName.keys()],suggestion:bestMatch(translates.parent,[...schemasByName.keys()]),message:`Schema '${s.metadata.name}' translates.parent references unknown Schema '${translates.parent}'.`}));continue}(s.spec.ttl||parent.spec.ttl)&&out.push(emit(phase,{code:"SCHEMA_TTL_TRANSLATION_UNSUPPORTED",severity:"error",path:path("/spec/translates"),message:`Schema '${s.metadata.name}' cannot translate TTL Schema '${parent.metadata.name}' or declare TTL itself; joined translations cannot guarantee expiry across both Schemas.`,expected:"TTL only on Schemas outside a translation relationship"})),parent.spec.localized===!0&&out.push(emit(phase,{code:"TRANSLATES_PARENT_IS_LOCALIZED",severity:"error",path:path("/spec/translates/parent"),value:translates.parent,expected:"parent Schema must NOT be localized (it carries the non-translatable facts; translation rows are this Schema)",message:`Schema '${s.metadata.name}' translates.parent '${translates.parent}' is itself localized. The parent should hold non-translatable facts (e.g. sku, price); the localized child holds the translatable fields.`}));let parentProps=propertyKeys(parent);parentProps.has(translates.on)||out.push(emit(phase,{code:"TRANSLATES_FIELD_NOT_IN_PARENT",severity:"error",path:path("/spec/translates/on"),value:translates.on,expected:`field declared in Schema '${parent.metadata.name}' spec.schema.properties`,candidates:[...parentProps].sort(),suggestion:bestMatch(translates.on,[...parentProps]),message:`Schema '${s.metadata.name}' translates.on field '${translates.on}' is not declared on parent Schema '${parent.metadata.name}'.`}))}return out}function emit(phase,payload){return phase==="validate"?validateDiagnostic(payload):bootDiagnostic(payload)}function propertyKeys(s){let props=s.spec.schema.properties??{};return new Set(Object.keys(props))}var RESERVED_READER_NAMES=["constructor","then","__proto__","prototype","toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toJSON","__defineGetter__","__defineSetter__","__lookupGetter__","__lookupSetter__"],IDENTIFIER=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function readerName(schemaName){if(/[^\x00-\x7f]/.test(schemaName))return schemaName.toLowerCase();let parts=schemaName.split(/[^A-Za-z0-9]+/).filter(Boolean),projected=parts.length?parts[0][0].toLowerCase()+parts[0].slice(1)+parts.slice(1).map(p=>p[0].toUpperCase()+p.slice(1)).join(""):"";return IDENTIFIER.test(projected)?projected:schemaName.toLowerCase()}function readerNameProblems(names){let out=[],first=new Map;for(let name4 of names){let reader=readerName(name4);if(RESERVED_READER_NAMES.includes(reader)){out.push({name:name4,message:`Schema '${name4}' would be the reader '${reader}', a reserved property name. Rename the Schema.`});continue}let other=first.get(reader);other===void 0?first.set(reader,name4):other.toLowerCase()!==name4.toLowerCase()&&out.push({name:name4,message:`Schema '${name4}' and Schema '${other}' both become the reader '${reader}' (store.db.${reader}). Rename one.`})}return out}function partitionManifests(manifests){let schemas=[],views=[],procedures=[],triggers=[];for(let manifest of manifests)manifest.kind==="Schema"?schemas.push(manifest):manifest.kind==="View"?views.push(manifest):manifest.kind==="Procedure"?procedures.push(manifest):triggers.push(manifest);return{schemas,views,procedures,triggers}}import{z}from"zod";function jsonSchemaToZod(schema){let imported;try{imported=lengthBeforePattern(z.fromJSONSchema(normalizeNullable(schema)))}catch(error){let message2=error instanceof Error?error.message:String(error);imported=z.never({error:`Invalid JSON Schema: ${message2}`})}return jsonValueWithinLimits().pipe(imported)}function lengthBeforePattern(root){let seen=new WeakSet,visit=node=>{if(!node||typeof node!="object"||seen.has(node))return;seen.add(node);let def=node._zod?.def;if(!def){for(let child2 of Array.isArray(node)?node:Object.values(node))visit(child2);return}if(def.type==="string")for(let check2 of def.checks??[])check2._zod.def.check==="max_length"&&(check2._zod.def.abort=!0);for(let[key,child2]of Object.entries(def))key!=="checks"&&visit(key==="getter"&&typeof child2=="function"?child2():child2)};return visit(root),root}function normalizeNullable(schema){let transform=node=>{let out={...node};if(node.format==="url"&&(out.format="uri"),node.properties&&(out.properties=Object.fromEntries(Object.entries(node.properties).map(([name4,child2])=>[name4,transform(child2)]))),node.$defs&&(out.$defs=Object.fromEntries(Object.entries(node.$defs).map(([name4,child2])=>[name4,transform(child2)]))),node.items&&(out.items=transform(node.items)),typeof node.additionalProperties=="object"&&(out.additionalProperties=transform(node.additionalProperties)),node.oneOf&&(out.oneOf=node.oneOf.map(transform)),delete out.nullable,node.nullable===!0){if(typeof node.type=="string")out.type=[node.type,"null"];else if(Array.isArray(node.type)&&!node.type.includes("null"))out.type=[...node.type,"null"];else if(node.type===void 0){let{$defs,...base}=out,definitions=$defs;return{...definitions?{$defs:definitions}:{},oneOf:[base,{type:"null"}]}}}return out};return transform(schema)}function jsonValueWithinLimits(){return z.unknown().superRefine((value2,ctx)=>{let stack=[{value:value2,depth:0}],active=new WeakSet,nodes=0;for(;stack.length>0;){let current=stack.pop();if(!(current.value===null||typeof current.value!="object")){if(current.exit){active.delete(current.value);continue}if(active.has(current.value)){ctx.addIssue({code:"custom",message:"value must not contain object cycles"});return}if(active.add(current.value),current.depth>100||++nodes>1e4){ctx.addIssue({code:"custom",message:"value exceeds JSON Schema validation limits"});return}stack.push({...current,exit:!0});for(let child2 of Array.isArray(current.value)?current.value:Object.values(current.value))stack.push({value:child2,depth:current.depth+1})}}})}function lookupLocalRef(root,ref2){if(typeof ref2!="string"||!ref2.startsWith("#/"))return;let value2=root;try{for(let key of decodeURIComponent(ref2.slice(2)).split("/").map(key2=>key2.replace(/~1/g,"/").replace(/~0/g,"~")))value2=value2&&typeof value2=="object"&&Object.hasOwn(value2,key)?value2[key]:void 0}catch{return}return value2&&typeof value2=="object"?value2:void 0}function rootRefChain(input){let chain=[];for(let schema=input;schema!==void 0;schema=lookupLocalRef(input,schema.$ref)){if(chain.includes(schema))return;if(chain.push(schema),schema.$ref===void 0)return chain}}function mcpToolNameSegment(name4){return name4.toLowerCase().replace(/-/g,"_")}function toolTitle(name4){let words=name4.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/[-_.\s]+/g," ").trim().toLowerCase();return words.charAt(0).toUpperCase()+words.slice(1)}var viewAnnotations={readOnlyHint:!0,destructiveHint:!1};function procedureAnnotations(p){let readOnlyHint=p.mcp?.readOnlyHint??!1;return{readOnlyHint,destructiveHint:!readOnlyHint&&("ref"in p.handler||overwrites(p.handler.sql.stmts)),...p.mcp}}var overwrites=node=>!!node&&typeof node=="object"&&("DeleteStmt"in node||"UpdateStmt"in node||node.onConflictClause?.action==="ONCONFLICT_UPDATE"||Object.values(node).some(overwrites));function mcpTools(plan,surface,locale="en"){let text=t=>resolveLocalizedText(t,locale,"en")??void 0,tools=new Map,add=tool=>{let prior=tools.get(tool.name);if(prior&&(prior.kind!==tool.kind||prior.source!==tool.source))throw new TypeError(`MCP tool '${tool.name}' comes from both '${prior.source}' and '${tool.source}'.`);tools.set(tool.name,tool)};for(let t of Object.values(plan.triggers)){if(t.source.kind!=="mcp"||t.source.surface!==surface)continue;let p=plan.procedures[t.procedure],title=text(p.title);add({name:mcpToolNameSegment(t.procedure),kind:"procedure",source:t.procedure,title:title??toolTitle(t.procedure),description:text(p.description)??title??t.procedure,inputSchema:p.input,...p.output.type==="object"?{outputSchema:p.output}:{},annotations:procedureAnnotations(p),requires:p.requires})}for(let[name4,v]of Object.entries(plan.views)){if(v.surface!==surface)continue;let chain=(v.input?rootRefChain(v.input)??[v.input]:[]).reverse(),props=Object.assign({},...chain.map(s=>s.properties??{})),required=[...new Set(chain.flatMap(s=>s.required??[]))];if("limit"in props||"cursor"in props)throw new TypeError(`View '${name4}' declares an input named limit or cursor; the MCP tool reserves both for paging.`);let rules=chain.map(s=>Object.fromEntries(INPUT_RULE_KEYWORDS.flatMap(k=>s[k]===void 0?[]:[[k,s[k]]]))).filter(r=>Object.keys(r).length),defs=v.input?referencedDefs(v.input,props):{},title=text(v.title);add({name:mcpToolNameSegment(name4),kind:"view",source:name4,title:title??toolTitle(name4),description:text(v.description)??title??name4,inputSchema:{type:"object",properties:{...props,limit:{type:"integer",minimum:1,maximum:500},cursor:{type:"string"}},...required.length?{required}:{},...rules.length>1?{allOf:rules}:rules[0],...Object.keys(defs).length?{$defs:defs}:{}},annotations:viewAnnotations,requires:v.requires})}return[...tools.values()]}function referencedDefs(root,node,found={}){if(!node||typeof node!="object")return found;let ref2=node.$ref,[head,segment]=typeof ref2=="string"&&ref2.startsWith("#/")?decoded(ref2.slice(2)).split("/"):[],key=head==="$defs"?segment?.replace(/~1/g,"/").replace(/~0/g,"~"):void 0;key!==void 0&&!Object.hasOwn(found,key)&&root.$defs&&Object.hasOwn(root.$defs,key)&&(found[key]=root.$defs[key],referencedDefs(root,found[key],found));for(let child2 of Object.values(node))referencedDefs(root,child2,found);return found}var decoded=pointer2=>{try{return decodeURIComponent(pointer2)}catch{return""}};function checkProcedureTarget(procedure,schemasByName,filePaths){let target2=procedure.spec.target;if(!target2)return[];let name4=procedure.metadata.name,fail=(pointer2,value2,expected,message2,candidates)=>[validateDiagnostic({code:"PROCEDURE_TARGET_INVALID",severity:"error",path:manifestPath("Procedure",name4,`/spec/target${pointer2}`,filePaths),value:value2,expected,...candidates?{candidates}:{},message:message2})];if(!schemasByName.has(target2.schema))return fail("/schema",target2.schema,"the metadata.name of an existing Schema",`Procedure '${name4}' target references unknown Schema '${target2.schema}'.`,[...schemasByName.keys()]);let input=procedure.spec.input,properties=input.properties??{};return!new Set(input.required??[]).has(target2.id)||!hasType(properties[target2.id],["string"])?fail("/id",target2.id,"a required string input property",`Procedure '${name4}' target.id '${target2.id}' must be a required string property of spec.input.`,Object.keys(properties)):target2.version!==void 0&&!hasType(properties[target2.version],["number","integer"])?fail("/version",target2.version,"a number input property",`Procedure '${name4}' target.version '${target2.version}' must be a number property of spec.input.`,Object.keys(properties)):[]}function checkSqlHandler(p,filePaths){let h=p.spec.handler;if(!("sql"in h))return[];let hint=(key,value2,message2)=>p.spec.mcp?.[key]===value2?[validateDiagnostic({code:"INVALID_MANIFEST_ENVELOPE",severity:"error",path:manifestPath("Procedure",p.metadata.name,`/spec/mcp/${key}`,filePaths),value:value2,expected:`no ${key}, or ${key}: ${!value2}, on this sql handler`,message:`Procedure '${p.metadata.name}' declares mcp.${key}: ${value2} but its sql handler ${message2}.`})]:[];return[...hint("readOnlyHint",!0,"writes"),.../\bdelete\s+from\b/i.test(h.sql)?hint("destructiveHint",!1,"deletes"):[]]}function checkGuards(targets,proceduresByName,filePaths){let out=[];for(let target2 of targets){let guardName=target2.spec.requires?.guard?.procedure;if(!guardName)continue;let path=manifestPath(target2.kind,target2.metadata.name,"/spec/requires/guard/procedure",filePaths),guard=proceduresByName.get(guardName);if(!guard){out.push(validateDiagnostic({code:"GUARD_PROCEDURE_UNKNOWN",severity:"error",path,value:guardName,expected:"name of a declared Procedure",candidates:[...proceduresByName.keys()],suggestion:bestMatch(guardName,[...proceduresByName.keys()]),message:`${target2.kind} '${target2.metadata.name}' references unknown guard Procedure '${guardName}'.`}));continue}if(target2.kind==="Procedure"&&target2.metadata.name===guardName){out.push(validateDiagnostic({code:"GUARD_SELF_REFERENCE",severity:"error",path,value:guardName,expected:"a different, unguarded Procedure",message:`Procedure '${target2.metadata.name}' cannot guard itself.`}));continue}"ref"in guard.spec.handler||out.push(validateDiagnostic({code:"GUARD_PROCEDURE_NOT_REF",severity:"error",path,value:guardName,expected:"a Procedure with a ref handler",message:`${target2.kind} '${target2.metadata.name}' uses '${guardName}' as a guard, but guard Procedures must use a ref handler.`})),guard.spec.requires?.guard&&out.push(validateDiagnostic({code:"GUARD_CHAIN_NOT_ALLOWED",severity:"error",path,value:guardName,expected:"an unguarded Procedure",message:`${target2.kind} '${target2.metadata.name}' uses '${guardName}' as a guard, but guard chains are not allowed.`}))}return out}function checkTriggerRefs(triggers,proceduresByName,filePaths,schemasByName){let out=[],httpRoutes=new Map,undescribedMcpProcedures=new Set;for(let t of triggers){let procName=t.spec.target.procedure;if(proceduresByName.has(procName)||out.push(validateDiagnostic({code:"TRIGGER_TARGET_PROCEDURE_UNKNOWN",severity:"error",path:manifestPath("Trigger",t.metadata.name,"/spec/target/procedure",filePaths),value:procName,expected:"name of a declared Procedure",candidates:[...proceduresByName.keys()],suggestion:bestMatch(procName,[...proceduresByName.keys()]),message:`Trigger '${t.metadata.name}' targets unknown Procedure '${procName}'.`})),t.spec.source.kind==="schedule"){let target2=proceduresByName.get(procName);target2&&(target2.spec.requires?.auth?.all.length??0)>0&&out.push(validateDiagnostic({code:"SCHEDULE_AUTH_INVALID",severity:"error",path:manifestPath("Trigger",t.metadata.name,"/spec/target/procedure",filePaths),value:procName,expected:"a Procedure without user or admin authorization requirements",message:`Scheduled Trigger '${t.metadata.name}' cannot satisfy '${procName}' authorization with a system caller.`})),target2&&!jsonSchemaToZod(target2.spec.input).safeParse({}).success&&out.push(validateDiagnostic({code:"SCHEDULE_INPUT_INVALID",severity:"error",path:manifestPath("Trigger",t.metadata.name,"/spec/target/procedure",filePaths),value:procName,expected:"a Procedure whose input accepts an empty object",message:`Scheduled Trigger '${t.metadata.name}' cannot supply required Procedure input to '${procName}'.`}))}if(t.spec.source.kind==="http"){let httpPath=t.spec.source.path,ambiguous=httpPath.split("/").find(segment=>!/^\{[^{}/]+\}$/.test(segment)&&(segment.startsWith(":")||/[{}]/.test(segment))),isValidPrefix=httpPath.startsWith("/api/")&&ambiguous===void 0;ambiguous!==void 0?out.push(validateDiagnostic({code:"TRIGGER_PATH_INVALID",severity:"error",path:manifestPath("Trigger",t.metadata.name,"/spec/source/path",filePaths),value:httpPath,expected:"literal segments not starting with ':', and parameters as whole '{name}' segments",message:`Trigger '${t.metadata.name}' has path segment '${ambiguous}' \u2014 describe writes a '{name}' parameter as ':name', so this segment would be read as another route. Use '{name}' for a parameter.`})):httpPath.startsWith("/api/")||out.push(validateDiagnostic({code:"TRIGGER_PATH_INVALID",severity:"error",path:manifestPath("Trigger",t.metadata.name,"/spec/source/path",filePaths),value:httpPath,expected:"path starting with '/api/'",message:`Trigger '${t.metadata.name}' has path '${httpPath}' \u2014 http Trigger paths MUST start with '/api/' so adapters can route public pages and Procedure endpoints without ambiguity.`}));let key=`${t.spec.source.method} ${httpPath.replace(/\{[^}]+\}/g,"{}")}`,prior=httpRoutes.get(key);prior?out.push(validateDiagnostic({code:"TRIGGER_PATH_COLLISION",severity:"error",path:manifestPath("Trigger",t.metadata.name,"/spec/source",filePaths),value:`${t.spec.source.method} ${httpPath}`,expected:`unique (method, path) across all http Triggers, parameter names aside (also declared by '${prior}')`,message:`Trigger '${t.metadata.name}' shares route ${t.spec.source.method} ${httpPath} with Trigger '${prior}'; only one of them could ever match.`})):isValidPrefix&&httpRoutes.set(key,t.metadata.name)}if(t.spec.source.kind==="mcp"){let target2=proceduresByName.get(procName);target2&&!undescribedMcpProcedures.has(procName)&&!resolveLocalizedText(target2.spec.description,"en")?.trim()&&(undescribedMcpProcedures.add(procName),out.push(validateDiagnostic({code:"MCP_TOOL_DESCRIPTION_MISSING",severity:"warning",path:manifestPath("Procedure",procName,"/spec/description",filePaths),value:null,expected:"a description an agent can choose the tool by",message:`Procedure '${procName}' is exposed as an MCP tool on the ${t.spec.source.surface} surface by Trigger '${t.metadata.name}' but has no spec.description; tools/list will show a generated placeholder.`})))}let hookTarget=t.spec.source.kind==="lifecycle"?proceduresByName.get(t.spec.target.procedure):void 0;if(hookTarget&&!("ref"in hookTarget.spec.handler)&&out.push(validateDiagnostic({code:"LIFECYCLE_TARGET_NOT_REF",severity:"error",path:manifestPath("Trigger",t.metadata.name,"/spec/target/procedure",filePaths),value:t.spec.target.procedure,expected:"a Procedure with a ref handler",message:`Lifecycle Trigger '${t.metadata.name}' targets '${t.spec.target.procedure}', whose handler is an inline program; a hook target must use a ref handler.`})),t.spec.source.kind==="lifecycle"&&schemasByName&&!schemasByName.has(t.spec.source.schema)){let schemaName=t.spec.source.schema;out.push(validateDiagnostic({code:"LIFECYCLE_SCHEMA_UNKNOWN",severity:"error",path:manifestPath("Trigger",t.metadata.name,"/spec/source/schema",filePaths),value:schemaName,expected:"name of a declared Schema",candidates:[...schemasByName.keys()],suggestion:bestMatch(schemaName,[...schemasByName.keys()]),message:`Trigger '${t.metadata.name}' watches unknown Schema '${schemaName}'.`}))}}return out}function checkMcpToolNameCollisions(views,procedures,triggers,filePaths){let seen=new Map,out=[],exposed=new Set(triggers.flatMap(t=>t.spec.source.kind==="mcp"?[t.spec.target.procedure]:[])),claim=(kind,name4)=>{let segment=mcpToolNameSegment(name4);if((kind==="View"||exposed.has(name4))&&(segment.length>128||!/^[A-Za-z0-9_.-]+$/.test(segment))){out.push(validateDiagnostic({code:"MCP_TOOL_NAME_COLLISION",severity:"error",path:manifestPath(kind,name4,"/metadata/name",filePaths),value:segment,expected:"an MCP tool name of at most 128 characters from [A-Za-z0-9_.-]",message:`${kind} '${name4}' cannot be an MCP tool name: it must be at most 128 characters from [A-Za-z0-9_.-].`}));return}let prior=seen.get(segment);prior&&prior!==`${kind} ${name4}`?out.push(validateDiagnostic({code:"MCP_TOOL_NAME_COLLISION",severity:"error",path:manifestPath(kind,name4,"/metadata/name",filePaths),value:segment,expected:`${kind} name unique after kebab\u2192snake mangling (collides with ${prior})`,message:`${kind} '${name4}' mangles to MCP tool name '${segment}', which already comes from ${prior}.`})):prior||seen.set(segment,`${kind} ${name4}`)};for(let view of views)view.spec.surface!=="internal"&&claim("View",view.metadata.name);for(let procedure of procedures)claim("Procedure",procedure.metadata.name);let mcpTriggers=new Map;for(let trigger of triggers){let source=trigger.spec.source;if(source.kind!=="mcp")continue;let tool=mcpToolNameSegment(trigger.spec.target.procedure),key=`${source.surface}\0${tool}`,prior=mcpTriggers.get(key);prior?out.push(validateDiagnostic({code:"MCP_TOOL_NAME_COLLISION",severity:"error",path:manifestPath("Trigger",trigger.metadata.name,"/spec/source",filePaths),value:tool,expected:`one MCP Trigger per surface and tool name (already bound by '${prior}')`,message:`Trigger '${trigger.metadata.name}' and Trigger '${prior}' both bind '${tool}' on the ${source.surface} MCP surface; invocation would lose Trigger identity.`})):mcpTriggers.set(key,trigger.metadata.name)}return out}function hasType(schema,types){let declared=schema?.type,list=Array.isArray(declared)?declared:declared===void 0?[]:[declared];return list.length>0&&list.every(type=>types.includes(type)||type==="null")&&list.some(type=>types.includes(type))}function validateManifestGraph(manifests,filePaths){let diags=[],partitioned=partitionManifests(manifests),schemasByName=byName(partitioned.schemas),proceduresByName=byName(partitioned.procedures);diags.push(...checkDuplicates("Schema",partitioned.schemas,filePaths)),diags.push(...checkDuplicates("View",partitioned.views,filePaths)),diags.push(...checkDuplicates("Procedure",partitioned.procedures,filePaths)),diags.push(...checkDuplicates("Trigger",partitioned.triggers,filePaths)),diags.push(...checkSchemaReservedWireNames(partitioned.schemas,filePaths)),diags.push(...checkCaseCollisions(partitioned.schemas,[...partitioned.views,...partitioned.procedures],filePaths)),diags.push(...checkReaderNames(partitioned.schemas,filePaths)),diags.push(...checkTranslatesReferences(partitioned.schemas,"validate",filePaths)),diags.push(...checkSchemaNavTargetsGraph(partitioned.schemas,schemasByName,filePaths));for(let s of partitioned.schemas)diags.push(...checkMantleRefs("Schema",s.metadata.name,"/spec/schema",s.spec.schema,schemasByName,filePaths));for(let p of partitioned.procedures)diags.push(...checkSqlHandler(p,filePaths)),diags.push(...checkCollectionActionRef(p,schemasByName,filePaths)),diags.push(...checkMantleRefs("Procedure",p.metadata.name,"/spec/input",p.spec.input,schemasByName,filePaths)),diags.push(...checkProcedureTarget(p,schemasByName,filePaths));return diags.push(...checkGuards([...partitioned.procedures,...partitioned.views],proceduresByName,filePaths)),diags.push(...checkTriggerRefs(partitioned.triggers,proceduresByName,filePaths,schemasByName)),diags.push(...checkMcpToolNameCollisions(partitioned.views,partitioned.procedures,partitioned.triggers,filePaths)),{diagnostics:diags,...partitioned}}function checkSchemaNavTargetsGraph(schemas,schemasByName,filePaths){let out=[];for(let schema of schemas){let problem3=checkSchemaNavTargets(schema,schemasByName);problem3&&out.push(validateDiagnostic({code:"SCHEMA_UI_INVALID",severity:"error",path:manifestPath("Schema",schema.metadata.name,problem3.pointer,filePaths),value:problem3.value,expected:problem3.expected,message:problem3.message}))}return out}function checkCollectionActionRef(procedure,schemasByName,filePaths){let target2=procedure.spec.uiSchema?.collectionAction;return typeof target2!="string"||schemasByName.has(target2)?[]:[validateDiagnostic({code:"SCHEMA_UI_INVALID",severity:"error",path:manifestPath("Procedure",procedure.metadata.name,"/spec/uiSchema/collectionAction",filePaths),value:target2,expected:"the metadata.name of an existing Schema",message:`Procedure '${procedure.metadata.name}' collection action references unknown Schema '${target2}'.`})]}function checkMantleRefs(kind,name4,pointer2,schema,schemasByName,filePaths){let out=[];for(let[field,property]of Object.entries(schema.properties??{})){let raw=property?.[MANTLE_REF_KEYWORD];if(raw===void 0||typeof raw=="string")continue;let path=manifestPath(kind,name4,`${pointer2}/properties/${pointerSegment(field)}/${MANTLE_REF_KEYWORD}`,filePaths),ref2=resolveMantleRef(property),keys=typeof raw=="object"&&raw!==null&&!Array.isArray(raw)?Object.keys(raw):[];if(!ref2||keys.some(key=>key!=="schema"&&key!=="field")){out.push(validateDiagnostic({code:"MANTLE_REF_INVALID",severity:"error",path,value:raw,expected:"a Schema name, or { schema: <Schema name>, field: <id or single-field unique index> }",message:`${kind} '${name4}' field '${field}' has a malformed x-mantle-ref.`}));continue}let target2=schemasByName.get(ref2.schema);if(!target2){out.push(validateDiagnostic({code:"MANTLE_REF_INVALID",severity:"error",path:`${path}/schema`,value:ref2.schema,expected:"the metadata.name of an existing Schema",candidates:[...schemasByName.keys()],suggestion:bestMatch(ref2.schema,[...schemasByName.keys()]),message:`${kind} '${name4}' field '${field}' references unknown Schema '${ref2.schema}'.`}));continue}let keyFields=entryKeyFields(target2);keyFields.includes(ref2.field)||out.push(validateDiagnostic({code:"MANTLE_REF_INVALID",severity:"error",path:`${path}/field`,value:ref2.field,expected:`one of ${keyFields.join(", ")}`,candidates:keyFields,message:`${kind} '${name4}' field '${field}' references '${ref2.schema}.${ref2.field}', which does not identify one entry; use id or a single-field unique index.`}))}return out}function entryKeyFields(schema){let unique=checkSchemaIndexes(schema).declarations.filter(declaration=>declaration.unique&&declaration.fields.length===1).map(declaration=>declaration.fields[0].name);return["id",...new Set(unique)]}function pointerSegment(value2){return value2.replaceAll("~","~0").replaceAll("/","~1")}function byName(arr){let m=new Map;for(let x of arr)m.set(x.metadata.name,x);return m}function checkSchemaReservedWireNames(schemas,filePaths){let out=[];for(let schema of schemas){let properties=schema.spec.schema.properties??{};for(let reserved2 of RESERVED_PROCEDURE_INPUT_NAMES)!(reserved2 in properties)||properties[reserved2]===void 0||out.push(validateDiagnostic({code:"INVALID_MANIFEST_ENVELOPE",severity:"error",path:manifestPath("Schema",schema.metadata.name,`/spec/schema/properties/${reserved2}`,filePaths),value:reserved2,expected:`Schema data properties that do not collide with reserved Procedure input names (${RESERVED_PROCEDURE_INPUT_NAMES.join(", ")}). New reserved names need an ADR.`,message:`Schema '${schema.metadata.name}' must not declare reserved Procedure input name '${reserved2}' as a data property (ADR-0022). New reserved names need an ADR.`}))}return out}function checkCaseCollisions(schemas,programs,filePaths){let out=[],collide=(names,report)=>{let first=new Map;for(let n of names){let seen=first.get(n.toLowerCase());seen===void 0?first.set(n.toLowerCase(),n):seen!==n&&report(n,seen)}};collide(schemas.map(s=>s.metadata.name),(name4,other)=>out.push(validateDiagnostic({code:"SCHEMA_NAME_CASE_COLLISION",severity:"error",path:manifestPath("Schema",name4,"/metadata/name",filePaths),value:name4,message:`Schema '${name4}' and Schema '${other}' differ only by case; SQL names them the same table. Rename one.`})));for(let s of schemas)collide(Object.keys(s.spec.schema.properties??{}),(name4,other)=>out.push(validateDiagnostic({code:"FIELD_NAME_CASE_COLLISION",severity:"error",path:manifestPath("Schema",s.metadata.name,`/spec/schema/properties/${pointerSegment(name4)}`,filePaths),value:name4,message:`Schema '${s.metadata.name}' declares '${name4}' and '${other}', which differ only by case; SQL names them the same column. Rename one.`})));for(let m of programs.filter(p=>p.kind==="View"||"sql"in p.spec.handler))collide(Object.keys(m.spec.input?.properties??{}),(name4,other)=>out.push(validateDiagnostic({code:"FIELD_NAME_CASE_COLLISION",severity:"error",path:manifestPath(m.kind,m.metadata.name,`/spec/input/properties/${pointerSegment(name4)}`,filePaths),value:name4,message:`${m.kind} '${m.metadata.name}' declares the inputs '${name4}' and '${other}', which differ only by case; SQL names them the same input. Rename one.`})));return out}function checkReaderNames(schemas,filePaths){return readerNameProblems(schemas.map(s=>s.metadata.name)).map(p=>validateDiagnostic({code:"SCHEMA_READER_NAME_COLLISION",severity:"error",path:manifestPath("Schema",p.name,"/metadata/name",filePaths),value:p.name,message:p.message}))}function checkDuplicates(kind,arr,filePaths){let counts=new Map;for(let m of arr)counts.set(m.metadata.name,(counts.get(m.metadata.name)??0)+1);let seenIndex=new Map,out=[];for(let m of arr){let total=counts.get(m.metadata.name)??0;if(total<2)continue;let ordinal=(seenIndex.get(m.metadata.name)??0)+1;seenIndex.set(m.metadata.name,ordinal),out.push(validateDiagnostic({code:"DUPLICATE_NAME",severity:"error",path:manifestPath(kind,m.metadata.name,"/metadata/name",filePaths,ordinal),value:m.metadata.name,expected:`metadata.name unique within kind ${kind}`,message:`${kind} manifest '${m.metadata.name}' is duplicated (occurrence ${ordinal} of ${total}).`}))}return out}function linkManifestSet(parsed){let manifests=parsed.entries.map(entry=>entry.manifest),filePaths=sourceFilePaths(parsed.entries),graph=validateManifestGraph(manifests,filePaths),diagnostics=graph.diagnostics.map(diagnostic=>attachSource(diagnostic,parsed.entries));if(diagnostics.some(diagnostic=>diagnostic.severity==="error"))return{ok:!1,diagnostics};let entriesByManifest=new Map(parsed.entries.map(entry=>[entry.manifest,entry])),schemasByName=new Map(graph.schemas.map(manifest=>[manifest.metadata.name,manifest])),proceduresByName=new Map(graph.procedures.map(manifest=>[manifest.metadata.name,manifest])),resolve=manifest=>{let entry=entriesByManifest.get(manifest);if(!entry)throw new Error(`linked manifest '${manifest.kind}/${manifest.metadata.name}' lost its source`);return Object.freeze({manifest,source:entry.source})},resolveSchema=name4=>resolve(schemasByName.get(name4)),resolveProcedure=name4=>resolve(proceduresByName.get(name4)),schemas=graph.schemas.map(manifest=>Object.freeze({...resolve(manifest),...manifest.spec.translates?{translationParent:resolveSchema(manifest.spec.translates.parent)}:{}})),views=graph.views.map(manifest=>Object.freeze({...resolve(manifest),...manifest.spec.requires?.guard?{guard:resolveProcedure(manifest.spec.requires.guard.procedure)}:{}})),procedures=graph.procedures.map(manifest=>Object.freeze({...resolve(manifest),...typeof manifest.spec.uiSchema?.collectionAction=="string"?{collectionActionSchema:resolveSchema(manifest.spec.uiSchema.collectionAction)}:{},...manifest.spec.requires?.guard?{guard:resolveProcedure(manifest.spec.requires.guard.procedure)}:{}})),triggers=graph.triggers.map(manifest=>Object.freeze({...resolve(manifest),target:resolveProcedure(manifest.spec.target.procedure),...manifest.spec.source.kind==="lifecycle"?{lifecycleSchema:resolveSchema(manifest.spec.source.schema)}:{}}));return{ok:!0,value:Object.freeze({schemas:Object.freeze(schemas),views:Object.freeze(views),procedures:Object.freeze(procedures),triggers:Object.freeze(triggers)}),diagnostics}}function sourceFilePaths(entries){let paths=new Map;for(let entry of entries){let key=`${entry.manifest.kind}/${entry.manifest.metadata.name}`,location={file:entry.source.sourceId,docIndex:entry.source.documentIndex},list=paths.get(key);list?list.push(location):paths.set(key,[location])}return paths}function attachSource(diagnostic,entries){let match=entries.map(entry=>({entry,prefix:`${entry.source.sourceId}#/${entry.source.documentIndex}`})).filter(({prefix})=>diagnostic.path.startsWith(prefix)).sort((a,b)=>b.prefix.length-a.prefix.length)[0];if(!match)return diagnostic;let path=diagnostic.path.slice(match.prefix.length)||"/";return{...diagnostic,path,source:sourceLocationAt(match.entry,path)}}var compile_exports={};__export(compile_exports,{accepts:()=>validateProgram2,name:()=>name2,version:()=>version});var KEYS_SRC={SelectStmt:"targetList fromClause whereClause groupClause havingClause sortClause limitCount distinctClause valuesLists limitOption op withClause",InsertStmt:"relation cols selectStmt onConflictClause returningClause override",UpdateStmt:"relation targetList whereClause returningClause",DeleteStmt:"relation whereClause returningClause",WithClause:"ctes",CommonTableExpr:"ctename ctequery aliascolnames ctematerialized",ReturningClause:"exprs",ResTarget:"name val",ColumnRef:"fields",String:"sval",A_Star:"",A_Const:"ival fval sval boolval isnull",A_Expr:"kind name lexpr rexpr",BoolExpr:"boolop args",NullTest:"arg nulltesttype",CaseExpr:"arg args defresult",CaseWhen:"expr result",CoalesceExpr:"args",TypeCast:"arg typeName",TypeName:"names typemod typmods",FuncCall:"funcname args agg_star agg_distinct over funcformat",WindowDef:"partitionClause orderClause frameOptions",SubLink:"subLinkType testexpr subselect operName",SortBy:"node sortby_dir sortby_nulls",RangeVar:"relname alias inh relpersistence mantle",Alias:"aliasname",RangeSubselect:"subquery alias",RangeFunction:"functions alias",JoinExpr:"jointype larg rarg quals",List:"items",OnConflictClause:"action infer targetList whereClause",InferClause:"indexElems",IndexElem:"name ordering nulls_ordering"},KEYS=Object.fromEntries(Object.entries(KEYS_SRC).map(([k,v])=>[k,new Set(v.split(" ").filter(Boolean))])),EXPR="ColumnRef A_Const A_Expr BoolExpr NullTest CaseExpr CoalesceExpr TypeCast FuncCall SubLink MinMaxExpr",FROM="RangeVar RangeSubselect RangeFunction JoinExpr",SLOTS_SRC={"SelectStmt.targetList":"ResTarget","SelectStmt.fromClause":FROM,"SelectStmt.whereClause":EXPR,"SelectStmt.havingClause":EXPR,"SelectStmt.groupClause":EXPR,"SelectStmt.sortClause":"SortBy","SelectStmt.limitCount":EXPR,"SelectStmt.distinctClause":EXPR,"SelectStmt.valuesLists":"List","SelectStmt>List.items":EXPR,"InsertStmt.cols":"ResTarget","InsertStmt.selectStmt":"SelectStmt","UpdateStmt.targetList":"ResTarget","UpdateStmt.whereClause":EXPR,"DeleteStmt.whereClause":EXPR,"ReturningClause.exprs":"ResTarget","ResTarget.val":EXPR,"ColumnRef.fields":"String A_Star","A_Expr.name":"String","A_Expr.lexpr":EXPR,"A_Expr.rexpr":`${EXPR} List`,"A_Expr>List.items":EXPR,"BoolExpr.args":EXPR,"NullTest.arg":EXPR,"CaseExpr.arg":EXPR,"CaseExpr.args":"CaseWhen","CaseExpr.defresult":EXPR,"CaseWhen.expr":EXPR,"CaseWhen.result":EXPR,"CoalesceExpr.args":EXPR,"TypeCast.arg":EXPR,"TypeName.names":"String","TypeName.typmods":"A_Const","FuncCall.funcname":"String","FuncCall.args":EXPR,"FuncCall.agg_filter":EXPR,"FuncCall.agg_order":"SortBy","WindowDef.partitionClause":EXPR,"WindowDef.orderClause":"SortBy","WindowDef.startOffset":EXPR,"WindowDef.endOffset":EXPR,"SubLink.testexpr":EXPR,"SubLink.subselect":"SelectStmt","SubLink.operName":"String","SortBy.node":EXPR,"RangeSubselect.subquery":"SelectStmt","RangeFunction.functions":"List","RangeFunction>List.items":"FuncCall","Alias.colnames":"String","JoinExpr.larg":FROM,"JoinExpr.rarg":FROM,"JoinExpr.quals":EXPR,"OnConflictClause.targetList":"ResTarget","OnConflictClause.whereClause":EXPR,"InferClause.indexElems":"IndexElem","WithClause.ctes":"CommonTableExpr","CommonTableExpr.ctequery":"SelectStmt","CommonTableExpr.aliascolnames":"String","MinMaxExpr.args":EXPR},SLOTS=new Map(Object.entries(SLOTS_SRC).map(([k,v])=>[k,new Set(v.split(" "))])),BARE={alias:"Alias",typeName:"TypeName",infer:"InferClause",returningClause:"ReturningClause",relation:"RangeVar",over:"WindowDef",onConflictClause:"OnConflictClause",withClause:"WithClause","SelectStmt.larg":"SelectStmt","SelectStmt.rarg":"SelectStmt"},ENUM={"SelectStmt.op":["SETOP_NONE"],"SelectStmt.limitOption":["LIMIT_OPTION_DEFAULT","LIMIT_OPTION_COUNT"],"InsertStmt.override":["OVERRIDING_NOT_SET"],"RangeVar.inh":[!0],"RangeVar.relpersistence":["p"],"RangeVar.mantle":["table","cte"],"A_Expr.kind":["AEXPR_OP","AEXPR_IN","AEXPR_LIKE","AEXPR_BETWEEN","AEXPR_NOT_BETWEEN","AEXPR_DISTINCT","AEXPR_NOT_DISTINCT","AEXPR_NULLIF"],"BoolExpr.boolop":["AND_EXPR","OR_EXPR","NOT_EXPR"],"NullTest.nulltesttype":["IS_NULL","IS_NOT_NULL"],"SubLink.subLinkType":["EXISTS_SUBLINK","EXPR_SUBLINK","ANY_SUBLINK"],"JoinExpr.jointype":["JOIN_INNER","JOIN_LEFT"],"SortBy.sortby_dir":["SORTBY_DEFAULT","SORTBY_ASC","SORTBY_DESC"],"SortBy.sortby_nulls":["SORTBY_NULLS_DEFAULT","SORTBY_NULLS_FIRST","SORTBY_NULLS_LAST"],"CommonTableExpr.ctematerialized":["CTEMaterializeDefault"],"FuncCall.funcformat":["COERCE_EXPLICIT_CALL","COERCE_SQL_SYNTAX"],"WindowDef.frameOptions":[1058],"OnConflictClause.action":["ONCONFLICT_NOTHING","ONCONFLICT_UPDATE"],"TypeName.typemod":[-1],"IndexElem.ordering":["SORTBY_DEFAULT"],"IndexElem.nulls_ordering":["SORTBY_NULLS_DEFAULT"]},OPS=new Set(["=","<>","!=","<",">","<=",">=","+","-","*","/","%","||","->>"]),FUNCS=new Set(["count","sum","min","max","avg","json_group_array","json_group_object","row_number","rank","lower","upper","length","abs","round","substr","replace","btrim","ltrim","rtrim","instr","typeof","hex","json_extract","json_set","json_insert","json_remove","json_array_length","now","auth.uid","date_trunc","extract","like_escape","mantle.search","mantle.search_rank","mantle.near","mantle.distance"]),WINDOW=new Set(["row_number","rank","sum","count"]),WINDOW_ONLY=new Set(["row_number","rank","dense_rank","lag","lead","first_value","last_value"]),AGG=new Set(["count","sum","min","max","avg","json_group_array","json_group_object"]),TRUNC_UNITS=new Set(["hour","day","week","month","year"]),EXTRACT_FIELDS=new Set(["year","month","day","dow","hour"]),CAST_TYPES=new Set(["text","int4","int8","float8","bool","timestamptz","date","numeric","interval"]),MAX_RADIUS_M=5e4,MAX_NEAR_K=100,MAX_NODES=2e3,BASE_PROFILE={name:"base",keys:KEYS,enums:ENUM,ops:OPS,funcs:FUNCS,window:WINDOW,agg:AGG,trunc:TRUNC_UNITS,extract:EXTRACT_FIELDS,casts:CAST_TYPES,fromFuncs:new Set(["json_each"])},MORE_KEYS={SelectStmt:"withClause larg rarg all",WithClause:"ctes recursive",CommonTableExpr:"ctename ctequery aliascolnames ctematerialized",RangeSubselect:"lateral",RangeFunction:"ordinality",Alias:"colnames",FuncCall:"agg_filter agg_order",WindowDef:"startOffset endOffset",MinMaxExpr:"op args"},MORE_ENUM={"SelectStmt.op":["SETOP_UNION","SETOP_INTERSECT","SETOP_EXCEPT"],"A_Expr.kind":["AEXPR_ILIKE"],"CommonTableExpr.ctematerialized":["CTEMaterializeDefault","CTEMaterializeAlways","CTEMaterializeNever"],"MinMaxExpr.op":["IS_GREATEST","IS_LEAST"]},MORE_OPS=["->","#>","#>>","@>","<@","?","?|","?&","~","~*","!~","!~*","~~*","!~~*"],MORE_WINDOW=["avg","min","max","lag","lead","first_value","last_value","dense_rank"],MORE_AGG=["string_agg","jsonb_agg","jsonb_object_agg"],MORE_FUNCS=[...MORE_WINDOW,...MORE_AGG,"jsonb_build_object","jsonb_build_array","jsonb_strip_nulls","to_jsonb","jsonb_typeof","split_part","floor","ceil","sqrt","power","timezone"],FRAME_REFUSED=229384,union=(a,b)=>new Set([...a,...b]),REFERENCE_PROFILE={name:"reference",keys:Object.fromEntries([...new Set([...Object.keys(KEYS),...Object.keys(MORE_KEYS)])].map(k=>[k,union(KEYS[k]??[],(MORE_KEYS[k]??"").split(" ").filter(Boolean))])),enums:Object.fromEntries([...new Set([...Object.keys(ENUM),...Object.keys(MORE_ENUM)])].filter(k=>k!=="WindowDef.frameOptions").map(k=>[k,[...ENUM[k]??[],...MORE_ENUM[k]??[]]])),ops:union(OPS,MORE_OPS),funcs:union(FUNCS,MORE_FUNCS),window:union(WINDOW,MORE_WINDOW),agg:union(AGG,MORE_AGG),trunc:union(TRUNC_UNITS,["minute","quarter"]),extract:union(EXTRACT_FIELDS,["minute","quarter","week","isoyear","isodow","doy","epoch"]),casts:union(CAST_TYPES,["jsonb"]),fromFuncs:new Set(["jsonb_array_elements","jsonb_array_elements_text","jsonb_each","jsonb_each_text"])},PROFILES={base:BASE_PROFILE,reference:REFERENCE_PROFILE},SQLITE_ONLY_KEYWORDS=new Set(["add","alter","autoincrement","commit","delete","drop","escape","index","insert","nothing","raise","set","transaction","update"]),SYSTEM=new Set(["version","status","author_id","created_at","updated_at"]),sv=list=>list.map(n=>n.String?.sval??(n.A_Star?"*":no("SQL_UNSUPPORTED","a name part that is not an identifier"))).join("."),fname=n=>sv(n.funcname).replace(/^pg_catalog\./,"");function no(code,message2,offset,keyword){throw new SqlRefusal(code,message2,offset,keyword)}var KEYWORD={"SelectStmt.withClause":/\bWITH\b/i,"InsertStmt.withClause":/\bWITH\b/i,"UpdateStmt.withClause":/\bWITH\b/i,"DeleteStmt.withClause":/\bWITH\b/i,"SelectStmt.limitOffset":/\bOFFSET\b/i,"SelectStmt.lockingClause":/\bFOR\s+(NO\s+KEY\s+)?(UPDATE|SHARE|KEY\s+SHARE)\b/i,"SelectStmt.intoClause":/\bINTO\b/i,"SelectStmt.op":/\b(UNION|INTERSECT|EXCEPT)\b/i,"UpdateStmt.fromClause":/\bFROM\b/i,"DeleteStmt.usingClause":/\bUSING\b/i,"JoinExpr.jointype":/\b(RIGHT|FULL)\b/i,"JoinExpr.isNatural":/\bNATURAL\b/i,"JoinExpr.usingClause":/\bUSING\b/i,"WindowDef.frameOptions":/\b(ROWS|RANGE|GROUPS)\b/i,"A_Expr.kind":/\bILIKE\b/i,"InferClause.conname":/\bON\s+CONSTRAINT\b/i,"SelectStmt.distinctClause":/\bDISTINCT\s+ON\b/i,GroupingSet:/\bGROUPING\s+SETS\b/i};function firstLoc(v){if(!(!v||typeof v!="object")){if(typeof v.location=="number"&&v.location>=0)return v.location;for(let c of Array.isArray(v)?v:Object.values(v)){let l=firstLoc(c);if(l!==void 0)return l}}}function validateProgram(stmts,ctx,locs=[],profile=BASE_PROFILE){program(stmts,{...ctx,p:profile,scope:[]},locs)}function program(stmts,ctx,locs){(!Array.isArray(stmts)||!stmts.length)&&no("SQL_SHAPE","an empty program"),ctx.kind==="view"&&(stmts.length!==1||!stmts[0].SelectStmt)&&no("SQL_SHAPE","a View is exactly one SELECT",locs[1]),ctx={...ctx,known:knownColumns(stmts),fnCols:rowSourceColumns(stmts),cols:ctx.columns??schemaColumns(ctx.schemas)};let w={ctx,budget:{n:0}};stmts.forEach((s,i)=>{let t=Object.keys(s)[0]??"",at=locs[i]??firstLoc(s);["SelectStmt","InsertStmt","UpdateStmt","DeleteStmt"].includes(t)||no("SQL_UNSUPPORTED",`statement ${t} is refused`,at),t==="SelectStmt"&&ctx.kind!=="view"&&no("SQL_SHAPE","a Procedure statement is a write",at),t!=="SelectStmt"&&ctx.kind==="view"&&no("SQL_SHAPE","a View is one SELECT",at),walk(t,s[t],w,[t],at)}),ctx.public&&publishedJoin(stmts,ctx)}function*find(v,key){if(!(!v||typeof v!="object"))for(let[k,c]of Object.entries(v))k===key&&(yield c),yield*find(c,key)}function schemaColumns(schemas){let known=new Set,scopes=new Set,types=new Map;for(let s of Object.values(schemas)){s.publishing&&(known.add("published_at"),types.set("published_at","timestamptz")),typeof s.scope=="string"&&scopes.add(s.scope.toLowerCase());for(let[f,t]of Object.entries(s.fields))(t==="geo"?[f,`${f}_lat`,`${f}_lng`]:[f]).forEach(c=>known.add(c)),types.set(f,types.has(f)&&types.get(f)!==t?null:t)}return{known,scopes,types:new Map([...types].filter(e=>e[1]!==null))}}function rowSourceColumns(stmts){let out=new Map;for(let r of find(stmts,"RangeFunction")){let a=r.alias;a?.colnames?.length&&out.set(String(a.aliasname).toLowerCase(),new Set(a.colnames.map(c=>String(c.String?.sval).toLowerCase())))}return out}function knownColumns(stmts){let known=new Set(["id","key","value","type","atom","parent","fullkey","path",...SYSTEM]);for(let r of find(stmts,"ResTarget"))r.name&&known.add(String(r.name).toLowerCase());for(let r of find(stmts,"RangeVar"))[r.relname,r.alias?.aliasname].forEach(a=>a&&known.add(a.toLowerCase()));for(let cols of rowSourceColumns(stmts).values())cols.forEach(c=>known.add(c));for(let c of find(stmts,"CommonTableExpr"))[c.ctename,...(c.aliascolnames??[]).map(x=>x.String?.sval)].forEach(a=>a&&known.add(String(a).toLowerCase()));return known}function publishedJoin(stmts,ctx){let rels=[...find(stmts,"RangeVar")].filter(r=>r.mantle!=="cte").map(r=>({alias:(r.alias?.aliasname??r.relname).toLowerCase(),publishing:!!ctx.schemas[r.relname.toLowerCase()]?.publishing}));if(!rels.some(r=>r.publishing))return;let ons=[...find(stmts,"JoinExpr")].map(j=>new Set([...find(j.quals,"ColumnRef")].filter(c=>c.fields.length===2).map(c=>c.fields[0].String.sval.toLowerCase())));for(let r of rels)!r.publishing&&!ons.some(o=>o.has(r.alias)&&rels.some(p=>p.publishing&&o.has(p.alias)))&&no("SQL_RELATION",`${r.alias} has no published state: a public View must join it to a publishing Schema in a JOIN ... ON`)}function shape(type,node,w,here){let keys=w.ctx.p.keys[type]??no("SQL_UNSUPPORTED",`${type} is not in the subset`,here,KEYWORD[type]);for(let[k,v]of Object.entries(node)){if(k==="location"||k==="rexpr_list_start"||k==="rexpr_list_end")continue;keys.has(k)||no("SQL_UNSUPPORTED",`${type}.${k} is not in the subset`,firstLoc(v)??here,KEYWORD[`${type}.${k}`]);let e=w.ctx.p.enums[`${type}.${k}`];e&&!e.includes(v)&&no("SQL_UNSUPPORTED",`${type}.${k} = ${JSON.stringify(v)} is refused`,firstLoc(node)??here,KEYWORD[`${type}.${k}`])}type==="String"&&node.sval!==void 0&&typeof node.sval!="string"&&no("SQL_SHAPE","a name is a string",here),type==="A_Const"&&!constant(node)&&no("SQL_UNSUPPORTED","a literal is one integer, numeric, string, boolean or NULL",firstLoc(node)??here)}function constant(node){let own=Object.keys(node).filter(k2=>k2!=="location");if(own.length!==1)return!1;let[k]=own,v=node[k],only=(key,ok)=>!!v&&typeof v=="object"&&Object.keys(v).every(x=>x===key)&&(!(key in v)||ok(v[key]));switch(k){case"ival":return only("ival",Number.isSafeInteger);case"fval":return only("fval",x=>typeof x=="string"&&x.length<=64&&/^-?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][-+]?\d+)?$/.test(x)&&(/[.eE]/.test(x)||Math.abs(Number(x))>=2**31));case"sval":return only("sval",x=>typeof x=="string");case"boolval":return only("boolval",x=>typeof x=="boolean");case"isnull":return v===!0;default:return!1}}function withScope(w,names,f){w.ctx.scope.push(new Set(names));try{f()}finally{w.ctx.scope.pop()}}function walk(type,node,w,path,loc){++w.budget.n>MAX_NODES&&no("SQL_SHAPE","statement too large",loc);let here=typeof node.location=="number"?node.location:loc;shape(type,node,w,here);try{check[type]?.(node,w.ctx,path,here)}catch(e){throw e instanceof SqlRefusal&&e.offset===void 0&&!e.keyword&&(e.offset=here),e}let wc=type==="SelectStmt"?node.withClause:void 0,names=(wc?.ctes??[]).map(x=>String(x.CommonTableExpr?.ctename));wc&&(shape("WithClause",wc,w,here),wc.recursive!==void 0&&typeof wc.recursive!="boolean"&&no("SQL_UNSUPPORTED","WithClause.recursive is a flag",here),(wc.ctes??[]).forEach((x,j)=>withScope(w,wc.recursive?names:names.slice(0,j),()=>child(x,w,[...path,"WithClause"],"ctes",here))));let rels=type==="SelectStmt"||type==="UpdateStmt"||type==="DeleteStmt"?relationsOf(node):void 0;rels&&(w.ctx.rels??=[]).push(rels);try{withScope(w,names,()=>{for(let[k,v]of Object.entries(node)){if(type==="A_Const"||k==="location"||k==="rexpr_list_start"||k==="rexpr_list_end"||wc&&k==="withClause")continue;let bare=BARE[`${type}.${k}`]??BARE[k];if(!(bare||SLOTS.has(`${type}.${k}`)||type==="List"&&k==="items")){v!==null&&typeof v=="object"&&no("SQL_UNSUPPORTED",`${type}.${k} is a value, not a node`,here);continue}(v===null||typeof v!="object")&&no("SQL_UNSUPPORTED",`${type}.${k} holds a node`,here),bare?walk(bare,v,w,[...path,bare],here):Array.isArray(v)?v.forEach(c=>child(c,w,path,k,here)):child(v,w,path,k,here)}})}finally{rels&&w.ctx.rels.pop()}}function relationsOf(node){let out=new Map,add=n=>{if(n?.JoinExpr)return add(n.JoinExpr.larg),add(n.JoinExpr.rarg);let v=n?.RangeVar??n;v?.mantle==="table"&&out.set(String(v.alias?.aliasname??v.relname).toLowerCase(),String(v.relname).toLowerCase())};for(let f of node.fromClause??[])add(f);return add(node.relation),out}function child(c,w,path,k,loc){let keys=Object.keys(c);if(!keys.length){if(k==="distinctClause"||k==="items"&&path.at(-2)==="RangeFunction")return;no("SQL_UNSUPPORTED",`an empty node in ${k}`,loc)}(keys.length!==1||c[keys[0]]===null||typeof c[keys[0]]!="object")&&no("SQL_UNSUPPORTED","a malformed node",loc);let parent=path.at(-1),allowed=SLOTS.get(parent==="List"?`${path.at(-2)}>List.${k}`:`${parent}.${k}`);w.ctx.p.keys[keys[0]]&&!allowed?.has(keys[0])&&no("SQL_SHAPE",`${keys[0]} cannot stand in ${parent}.${k}`,loc),walk(keys[0],c[keys[0]],w,[...path,keys[0]],loc)}var castType=typeName=>{let names=(typeName?.names??[]).map(n=>n?.String?.sval);return names.every(x=>typeof x=="string"&&/^[a-z_][a-z0-9_]*$/.test(x))&&(names.length===1||names.length===2&&names[0]==="pg_catalog")||no("SQL_TYPE",`a cast names one type: ${JSON.stringify(names)}`),names.at(-1)},isConst=n=>!!n?.A_Const,isInputRef=n=>n?.ColumnRef?.fields?.length===2&&n.ColumnRef.fields[0].String?.sval==="input",check={RangeVar:(n,ctx,_p,at)=>{n.alias?.colnames&&no("SQL_SHAPE",`a column list after ${n.alias.aliasname} is only for a row source: Schema columns keep their names`,at),(typeof n.relname!="string"||n.relname!==n.relname.toLowerCase())&&no("SQL_RELATION",`${JSON.stringify(n.relname)}: a relation is named in lower case`,at);let name4=n.relname;(name4.startsWith("_mantle")||name4==="input"||name4==="auth")&&no("SQL_RELATION",`${name4} is not a declared Schema`,at);let reference=ctx.p.name==="reference";if(n.alias&&(["input","auth","excluded"].includes(n.alias.aliasname)||n.alias.aliasname.startsWith("_mantle"))&&no("SQL_RELATION",`${n.alias.aliasname} is a reserved alias`,at),!reference)for(let ident2 of[name4,n.alias?.aliasname])ident2&&SQLITE_ONLY_KEYWORDS.has(ident2)&&no("SQL_UNSUPPORTED",`${ident2} is an SQLite keyword: the printer would not quote it`,at);if(n.mantle==="cte"){if(ctx.scope.some(s=>s.has(n.relname)))return;no("SQL_RELATION",`${name4}: a cte reference is not defined in scope`,at)}ctx.schemas[name4]||no("SQL_RELATION",`${name4} is not a declared Schema`,at),n.mantle!==void 0&&n.mantle!=="table"&&no("SQL_RELATION",`${name4}: relation not name-resolved`,at)},ColumnRef:(n,ctx,_p,at)=>{let f=sv(n.fields),last=f.split(".").pop().toLowerCase();n.fields.length>2&&no("SQL_COLUMN",`${f}: at most alias.column`,at),["rowid","oid","_rowid_","_rid"].includes(last)&&no("SQL_COLUMN",`${last} is not addressable`,at),ctx.cols.scopes.has(last)&&no("SQL_COLUMN",`${f}: the scope column is not addressable`,at),f.startsWith("input.")&&!(last in ctx.inputs)&&no("SQL_COLUMN",`${f} is not a declared input`,at),ctx.p.name==="base"&&SQLITE_ONLY_KEYWORDS.has(last)&&no("SQL_UNSUPPORTED",`${last} is an SQLite keyword: the printer would not quote it`,at);let own=n.fields.length===2?ctx.fnCols.get(String(n.fields[0].String?.sval).toLowerCase()):void 0;own&&last!=="*"&&!own.has(last)&&no("SQL_COLUMN",`${f}: the row source ${n.fields[0].String.sval} names its columns (${[...own].join(", ")})`,at),last!=="*"&&!f.startsWith("input.")&&!ctx.known.has(last)&&!ctx.cols.known.has(last)&&no("SQL_COLUMN",`${f} is not a declared field`,at)},FuncCall:(n,ctx,path,at)=>{let f=fname(n);if(ctx.p.fromFuncs.has(f)){(path.at(-2)!=="List"||path.at(-3)!=="RangeFunction")&&no("SQL_FUNCTION",`${f} is only allowed in FROM`,at);return}ctx.p.funcs.has(f)||no("SQL_FUNCTION",`function ${f} is not on the allowlist`,at),n.over&&(ctx.kind!=="view"||!ctx.p.window.has(f))&&no("SQL_FUNCTION",`window function ${f} is refused here`,at),!n.over&&WINDOW_ONLY.has(f)&&no("SQL_FUNCTION",`${f}() is a window function: it needs OVER (...)`,at),(f==="lag"||f==="lead")&&n.args?.[1]&&n.args[1].A_Const?.ival===void 0&&no("SQL_FUNCTION",`${f}'s offset is an integer literal`,at),(n.agg_filter||n.agg_order)&&!ctx.p.agg.has(f)&&no("SQL_FUNCTION",`FILTER and ORDER BY belong to an aggregate, and ${f} is not one`,at);let args=n.args??[],str2=a=>a?.A_Const?.sval?.sval;switch(f){case"like_escape":(path.at(-2)!=="A_Expr"||args.length!==2)&&no("SQL_FUNCTION","like_escape is only the ESCAPE of a LIKE",at);break;case"date_trunc":(args.length!==2||!ctx.p.trunc.has(str2(args[0])??""))&&no("SQL_TYPE",`date_trunc takes ${[...ctx.p.trunc].join(", ")} as a literal first argument`,at);break;case"extract":(args.length!==2||!ctx.p.extract.has(str2(args[0])??""))&&no("SQL_TYPE",`extract takes ${[...ctx.p.extract].join(", ")}`,at);break;case"now":case"auth.uid":args.length&&no("SQL_FUNCTION",`${f}() takes no arguments`,at);break;case"mantle.search":case"mantle.search_rank":(args.length!==(f==="mantle.search"?2:1)||args[0]?.ColumnRef?.fields?.length!==1)&&no("SQL_FUNCTION",f==="mantle.search"?"mantle.search(<alias>, <query>)":"mantle.search_rank(<alias>)",at);break;case"mantle.near":case"mantle.distance":{let want=f==="mantle.near"?4:3,fld=args[0]?.ColumnRef?.fields;(args.length!==want||fld?.length!==2)&&no("SQL_FUNCTION",`${f}(<alias>.<geo field>, lat, lng${f==="mantle.near"?", meters":""})`,at);for(let a of args.slice(1,3))!isConst(a)&&!isInputRef(a)&&no("SQL_FUNCTION",`${f}: latitude and longitude are a literal or input.<name>`,at);if(f==="mantle.near"){let m=args[3]?.A_Const?.ival?.ival??args[3]?.A_Const?.fval?.fval;m===void 0&&no("SQL_FUNCTION","mantle.near() needs a literal radius in meters",at),(Number(m)>MAX_RADIUS_M||Number(m)<=0)&&no("SQL_FUNCTION",`mantle.near() radius is at most ${MAX_RADIUS_M} m`,at)}break}}ctx.p.agg.has(f)&&n.args?.length===0&&!n.agg_star&&no("SQL_FUNCTION",`${f} needs an argument`,at),n.agg_star&&(f!=="count"||args.length)&&no("SQL_FUNCTION",`${f}(*) is refused: only count(*)`,at),n.agg_distinct&&(!ctx.p.agg.has(f)||args.length!==1||n.over)&&no("SQL_FUNCTION","DISTINCT is one argument of an aggregate, outside a window",at)},A_Expr:(n,ctx,_p,at)=>{let op2=sv(n.name),items=n.rexpr?.List?.items,range=n.kind==="AEXPR_BETWEEN"||n.kind==="AEXPR_NOT_BETWEEN";(!n.rexpr||!n.lexpr&&!(n.kind==="AEXPR_OP"&&(op2==="-"||op2==="+"))||range&&items?.length!==2||n.kind==="AEXPR_IN"&&!items?.length||!range&&n.kind!=="AEXPR_IN"&&n.rexpr.List)&&no("SQL_SHAPE",`a malformed ${op2} expression`,at),n.kind==="AEXPR_OP"&&!n.lexpr&&(op2==="-"||op2==="+")&&(n.rexpr?.A_Const?.ival!==void 0||n.rexpr?.A_Const?.fval!==void 0)&&no("SQL_SHAPE",`a sign over a number is that number: write ${op2==="-"?"the negative constant":"the constant"}`,at),ctx.p.name==="base"&&bareLiteralCompare(n,ctx,at),jsonCompare(n,ctx,at),n.kind==="AEXPR_OP"&&!ctx.p.ops.has(op2)&&no("SQL_UNSUPPORTED",`operator ${op2} is refused`,at),n.kind==="AEXPR_IN"&&!["=","<>"].includes(op2)&&no("SQL_UNSUPPORTED","a bad IN",at),n.kind==="AEXPR_LIKE"&&!["~~","!~~"].includes(op2)&&no("SQL_UNSUPPORTED","ILIKE and regular expressions are refused",at,/\bILIKE\b/i),n.kind==="AEXPR_ILIKE"&&!["~~*","!~~*"].includes(op2)&&no("SQL_UNSUPPORTED","a bad ILIKE",at);let esc=x=>!!x?.FuncCall&&fname(x.FuncCall)==="like_escape";(esc(n.lexpr)||esc(n.rexpr)&&n.kind!=="AEXPR_LIKE")&&no("SQL_FUNCTION","like_escape is only the ESCAPE of a LIKE",at)},TypeCast:(n,ctx,_p,at)=>{let t=castType(n.typeName);ctx.p.casts.has(t)||no("SQL_TYPE",`CAST to ${t} is refused`,at);let lit3=n.arg?.A_Const,base=ctx.p.name==="base";base&&(t==="int4"||t==="int8")&&!(lit3?.ival||/^\s*-?\d+\s*$/.test(lit3?.sval?.sval??"x"))&&no("SQL_TYPE",`CAST to ${t} takes an integer literal: SQLite truncates toward zero where PostgreSQL rounds. Write round(x)`,at);let mods=n.typeName.typmods??[],typmod=mods[0]?.A_Const?.ival?.ival;if(mods.length&&t!=="numeric"&&!(t==="interval"&&mods.length===1&&intervalMicros(lit3?.sval?.sval??"x",typmod)%intervalMicros("1",typmod)===0)&&no("SQL_TYPE",`CAST to ${t} takes no type modifier here, or one that truncates nothing`,at),t==="interval"&&(lit3?.sval||no("SQL_TYPE","an interval is a literal such as interval '36 hours'",at),intervalMicros(lit3.sval.sval,n.typeName.typmods?.[0]?.A_Const?.ival?.ival)),base&&(t==="timestamptz"||t==="date")&&!lit3?.sval&&no("SQL_TYPE",`CAST to ${t} takes a literal (the compiler folds it to its integer encoding)`,at),t==="numeric"){let[p,s]=(n.typeName.typmods??[]).map(m=>m.A_Const?.ival?.ival??0);p===void 0&&no("SQL_TYPE","numeric needs (precision, scale)",at),parseNumeric(`numeric(${p}, ${s})`),base&&!lit3&&no("SQL_TYPE","CAST to numeric takes a literal: numeric columns are integer counts of the smallest unit",at)}},ResTarget:(n,ctx,_p,at)=>{ctx.p.name==="base"&&n.name&&SQLITE_ONLY_KEYWORDS.has(n.name)&&no("SQL_UNSUPPORTED",`${n.name} is an SQLite keyword: the printer would not quote it`,at)},SubLink:(n,_c,_p,at)=>{n.subLinkType==="ANY_SUBLINK"&&n.operName&&sv(n.operName)!=="="&&no("SQL_UNSUPPORTED","only IN (subquery)",at)},JoinExpr:(n,_c,_p,at)=>{n.quals||no("SQL_SHAPE","a JOIN needs ON",at,/\bCROSS\s+JOIN\b|\bJOIN\b/i)},RangeFunction:(n,ctx,_p,at)=>{let fs=n.functions,only=`only ${[...ctx.p.fromFuncs].map(x=>`${x}()`).join(", ")} ${ctx.p.fromFuncs.size>1?"are":"is"} allowed in FROM`,f=fs.length===1&&fs[0]?.List?.items?.length===2?sv(fs[0].List.items[0].FuncCall?.funcname??[]):void 0;(!f||!ctx.p.fromFuncs.has(f))&&no("SQL_FUNCTION",only,at),fs[0].List.items[0].FuncCall.args?.length!==1&&no("SQL_FUNCTION",`${f} takes one argument`,at)},RangeSubselect:(n,_c,_p,at)=>{n.alias?.colnames&&no("SQL_SHAPE",`a column list after ${n.alias.aliasname} is only for a row source: name the columns in the subquery`,at),n.alias||no("SQL_SHAPE","a subquery in FROM needs an alias",at),n.alias.aliasname.startsWith("_mantle")&&no("SQL_RELATION",`${n.alias.aliasname} is a reserved alias`,at)},CommonTableExpr:(n,ctx,_p,at)=>{n.ctequery?.SelectStmt||no("SQL_SHAPE","a CTE body is a SELECT: a write inside WITH is refused",at);for(let name4 of[n.ctename,...(n.aliascolnames??[]).map(c=>c?.String?.sval)])(typeof name4!="string"||!/^[a-z_][a-z0-9_]*$/.test(name4))&&no("SQL_SHAPE",`a CTE name is lower case, a plain identifier: ${JSON.stringify(name4)}`,at),ctx.p.name==="base"&&SQLITE_ONLY_KEYWORDS.has(name4)&&no("SQL_UNSUPPORTED",`${name4} is an SQLite keyword: the printer would not quote it`,at)},BoolExpr:(n,_c,_p,at)=>{let k=(n.args??[]).length;(n.boolop==="NOT_EXPR"?k!==1:k<1)&&no("SQL_SHAPE",`a malformed ${n.boolop}`,at)},WindowDef:(n,_c,_p,at)=>{n.frameOptions&FRAME_REFUSED&&no("SQL_UNSUPPORTED","GROUPS frames and EXCLUDE are refused",at,/\b(GROUPS|EXCLUDE)\b/i);for(let o of[n.startOffset,n.endOffset])o&&!(o.A_Const?.ival!==void 0||o.TypeCast?.arg?.A_Const?.sval&&castType(o.TypeCast.typeName)==="interval")&&no("SQL_SHAPE","a frame offset is a literal: an integer, or an interval such as interval '6 days'",at)},SelectStmt:(n,ctx,path,at)=>{let reference=ctx.p.name==="reference",top=ctx.kind==="view"&&path.length===1,distinctOn=!!n.distinctClause&&(n.distinctClause.length!==1||Object.keys(n.distinctClause[0]).length>0);if(n.op&&n.op!=="SETOP_NONE"&&top&&no("SQL_SHAPE","UNION, INTERSECT and EXCEPT go inside a WITH or a subquery: Core pages the View's own SELECT",at,/\b(UNION|INTERSECT|EXCEPT)\b/i),n.limitCount&&!n.sortClause&&no("SQL_SHAPE","LIMIT needs an ORDER BY",firstLoc(n.limitCount)??at),distinctOn&&(!reference||top)&&no(reference?"SQL_SHAPE":"SQL_UNSUPPORTED",reference?"DISTINCT ON goes inside a WITH or a subquery: Core pages the View's own SELECT":"DISTINCT ON is refused",at,/\bDISTINCT\s+ON\b/i),n.distinctClause&&!distinctOn&&n.sortClause&&no("SQL_SHAPE","DISTINCT with ORDER BY is refused: the appended id key would change what is distinct",at),n.valuesLists&&(path.at(-2)!=="InsertStmt"||n.valuesLists.length!==1)&&no("SQL_SHAPE","VALUES is one row, in INSERT only",firstLoc(n.valuesLists)??at),(n.fromClause??[]).slice(1).some(f=>!f.RangeFunction&&!(reference&&f.RangeSubselect?.lateral))&&no("SQL_SHAPE",reference?"a comma join is refused (except a row source over a column, and LATERAL)":"a comma join is refused (except json_each)",at),reference&&n.sortClause&&!n.groupClause){let rows=f=>f?.JoinExpr?[...rows(f.JoinExpr.larg),...rows(f.JoinExpr.rarg)]:f?[f]:[];for(let r of(n.fromClause??[]).flatMap(rows)){let fc=r.RangeFunction?.functions?.[0]?.List?.items?.[0]?.FuncCall;fc&&(!r.RangeFunction.alias||!r.RangeFunction.ordinality)&&no("SQL_SHAPE",`ordering a row source (${sv(fc.funcname)}) needs an alias and WITH ORDINALITY: write ${sv(fc.funcname)}(...) WITH ORDINALITY AS j(value, n)`,fc.location??at)}}if(JSON.stringify(n.sortClause??[]).includes('"distance"')){let k=n.limitCount?.A_Const?.ival?.ival;(k===void 0||k>MAX_NEAR_K)&&no("SQL_SHAPE",`a query ordered by mantle.distance() needs a literal LIMIT of at most ${MAX_NEAR_K}`,firstLoc(n.sortClause)??at)}},UpdateStmt:(n,ctx)=>writeList(n.targetList,ctx,n.relation,!1),InsertStmt:(n,ctx,_p,at)=>{writeList(n.cols??no("SQL_WRITE","INSERT needs a column list",at),ctx,n.relation,!0,n.selectStmt?.SelectStmt?.valuesLists?.[0]?.List?.items),n.onConflictClause?.action==="ONCONFLICT_UPDATE"&&writeList(n.onConflictClause.targetList,ctx,n.relation,!1)}},STORED_AS_NUMBER=new Set(["timestamptz","date","bool"]),SYSTEM_TIMES=new Set(["created_at","updated_at","published_at"]);function columnType(ctx,name4){return SYSTEM_TIMES.has(name4)?"timestamptz":ctx.cols.types.get(name4)}function bareLiteralCompare(n,ctx,at){if(!(n.kind==="AEXPR_OP"?["=","<>","!=","<",">","<=",">="].includes(sv(n.name)):["AEXPR_IN","AEXPR_BETWEEN","AEXPR_NOT_BETWEEN","AEXPR_DISTINCT","AEXPR_NOT_DISTINCT"].includes(n.kind)))return;let typeOf=x=>{let f=x?.ColumnRef?.fields,name4=f?.at(-1)?.String?.sval;return name4&&!(f.length===2&&f[0].String?.sval==="input")?columnType(ctx,String(name4).toLowerCase()):void 0},literals=x=>x?.List?x.List.items.flatMap(literals):x?.A_Const?.sval?[x.A_Const.sval.sval]:[];for(let[colSide,other]of[[n.lexpr,n.rexpr],[n.rexpr,n.lexpr]]){let type=typeOf(colSide);if(!type||!STORED_AS_NUMBER.has(type))continue;let text=literals(other)[0];text!==void 0&&no("SQL_TYPE",`'${text}' is text and the column is ${type}, which is stored as a number: ${type==="bool"?"write true or false":`write CAST('${text}' AS ${type})`}, or bind it as an input`,at)}}function jsonCompare(n,ctx,at){let compares=n.kind==="AEXPR_OP"?["=","<>","!=","<",">","<=",">="].includes(sv(n.name)):["AEXPR_IN","AEXPR_BETWEEN","AEXPR_NOT_BETWEEN","AEXPR_DISTINCT","AEXPR_NOT_DISTINCT"].includes(n.kind),rels=ctx.rels?.at(-1);if(!(!compares||!rels))for(let side of[n.lexpr,n.rexpr]){let f=side?.ColumnRef?.fields;if(!f||f.length>2||!f.every(x=>x.String))continue;let name4=String(f.at(-1).String.sval).toLowerCase(),schemas=f.length===2?[rels.get(String(f[0].String.sval).toLowerCase())].filter(s=>!!s):[...new Set(rels.values())].filter(s=>Object.hasOwn(ctx.schemas[s]?.fields??{},name4));schemas.length===1&&ctx.schemas[schemas[0]]?.fields[name4]==="json"&&no("SQL_TYPE",`${f.at(-1).String.sval} is json: compare a value read with ->> (and CAST), or declare the field with one scalar type`,at)}}function writeList(list,ctx,rel,insert2,values){let s=ctx.schemas[rel.relname.toLowerCase()];for(let[i,{ResTarget:r}]of list.entries()){let at=firstLoc(r)??firstLoc(rel),name4=String(r.name).toLowerCase(),scopedId=insert2&&name4==="id"&&s?.scope;(name4===s?.scope?.toLowerCase()||SYSTEM.has(name4)||name4==="published_at"||!insert2&&name4==="id"||scopedId)&&no("SQL_WRITE",`${r.name} is filled by Mantle and cannot be written${scopedId?" (a scoped Schema generates its ids)":""}`,at);let cols=Object.entries(s?.fields??{}).flatMap(([f,t])=>t==="geo"?[`${f}_lat`,`${f}_lng`]:[f]);name4!=="id"&&!cols.includes(name4)&&no("SQL_WRITE",`${rel.relname} has no field ${r.name}`,at);let type=s?.fields[name4],literal=(insert2?values?.[i]:r.val)?.A_Const?.sval?.sval;ctx.p.name==="base"&&literal!==void 0&&type&&!["text","json"].includes(type)&&!/^-?\d+(\.\d+)?$/.test(literal)&&no("SQL_TYPE",`'${literal}' is text and ${r.name} is ${type}: write CAST('${literal}' AS ${type==="integer"?"int8":type==="real"?"float8":type}), or bind it as an input`,at)}}function refusalToDiagnostic(e){return{code:e.code,message:e.message}}function validateIr(plan,ctx,profile=BASE_PROFILE){try{return plan?.grammar!==180004&&no("SQL_UNSUPPORTED",`plan was compiled with PostgreSQL grammar ${plan?.grammar}, this runtime reads ${180004}`),validateProgram(plan.stmts,ctx,[],profile),[]}catch(e){return e instanceof SqlRefusal?[refusalToDiagnostic(e)]:[{code:"SQL_UNSUPPORTED",message:`malformed IR: ${e instanceof Error?e.message:String(e)}`}]}}var POSTGRES_ONLY="needs the PostgreSQL dialect; D1 runs Mantle SQL's base subset (ADR-0037)";function postgresOnly(stmts,ctx){try{return validateProgram(stmts,ctx,[],PROFILES.reference),!0}catch{return!1}}function validateProgram2(stmts,ctx,locs=[]){try{validateProgram(stmts,ctx,locs,PROFILES.base)}catch(e){throw e instanceof SqlRefusal&&postgresOnly(stmts,ctx)&&(e.message=`${e.message}: ${POSTGRES_ONLY}`),e}}function validateIr2(plan,ctx){let d=validateIr(plan,ctx,PROFILES.base);return d.length&&plan?.grammar===180004&&Array.isArray(plan.stmts)&&postgresOnly(plan.stmts,ctx)?[{...d[0],message:`${d[0].message}: ${POSTGRES_ONLY}`}]:d}var name2="@aotter/mantle/d1",version="1";async function parsePgSql(sql4){let{parse}=await import("libpg-query"),tree;try{tree=await parse(sql4)}catch(e){let at=e?.sqlDetails?.cursorPosition;throw new SqlRefusal("SQL_SYNTAX",String(e?.message??e).replace(/^.*?:\s*/,""),typeof at=="number"?new TextEncoder().encode(sql4.slice(0,at)).byteLength:void 0)}let raw=tree.stmts;return{stmts:raw.map(s=>s.stmt),locations:raw.map(s=>s.stmt_location)}}var STATEMENTS=new Set(["SelectStmt","InsertStmt","UpdateStmt","DeleteStmt","MergeStmt"]),WRITES=new Set(["InsertStmt","UpdateStmt","DeleteStmt","MergeStmt"]),MANTLE_FUNCTIONS=new Set(["mantle.search","mantle.search_rank","mantle.near","mantle.distance","auth.uid","auth.hasrole","auth.user"]),OUTSIDE=/^(pg_(try_)?advisory_|pg_read_(binary_)?file$|pg_ls_|pg_stat_file$|pg_file_|lo_|dblink|pg_(cancel|terminate|signal)_backend$|pg_reload_conf$|pg_rotate_logfile$|pg_notify$|(set|next)val$|(query|table|cursor|schema|database)_to_xml|ts_stat$|ts_rewrite$)/,no2=(code,message2,at)=>{throw new SqlRefusal(code,message2,at)};function functionName(n){return n.funcname.map(x=>String(x.String?.sval).toLowerCase()).slice(-2).join(".").replace(/^pg_catalog\./,"")}function refuseForEveryDialect(stmts,ctx,locations){ctx.kind==="view"&&(stmts.length!==1||!stmts[0].SelectStmt)&&no2("SQL_SHAPE","a View is exactly one SELECT",locations[1]??locations[0]),stmts.forEach((stmt,i)=>{let type=Object.keys(stmt)[0];STATEMENTS.has(type)||no2("SQL_UNSUPPORTED",`statement ${type} is refused`,locations[i]),walk2(stmt,new Set,locations[i],ctx)})}function walk2(v,ctes,at,ctx){if(Array.isArray(v))return v.forEach(x=>walk2(x,ctes,at,ctx));if(!(!v||typeof v!="object"))for(let[k,c]of Object.entries(v)){if(!c||typeof c!="object"||Array.isArray(c)){walk2(c,ctes,at,ctx);continue}let n=c,here=typeof n.location=="number"?n.location:at;if(k==="RangeVar"||k==="relation")relation(n,ctes,here,ctx,k==="relation");else if(STATEMENTS.has(k)||(k==="larg"||k==="rarg")&&"op"in n){ctx.kind==="view"&&WRITES.has(k)&&no2("SQL_SHAPE","a View reads only: no write in a WITH",here),n.intoClause&&no2("SQL_UNSUPPORTED","SELECT ... INTO creates a table and is refused",here);let w=n.withClause,names=(w?.ctes??[]).map(x=>String(x.CommonTableExpr.ctename));(w?.ctes??[]).forEach((x,j)=>walk2(x.CommonTableExpr.ctequery,new Set([...ctes,...w.recursive?names:names.slice(0,j)]),here,ctx));let inner=new Set([...ctes,...names]);for(let[key,body]of Object.entries(n))key!=="withClause"&&walk2({[key]:body},inner,here,ctx);continue}else if(k==="ColumnRef"){let f=n.fields.map(x=>x.String?.sval);f.length===2&&f[0]==="input"&&!Object.hasOwn(ctx.inputs,String(f[1]))&&no2("SQL_COLUMN",`input.${f[1]} is not a declared input`,here)}else if(k==="FuncCall"){let f=functionName(n);/^(mantle|auth)\./.test(f)&&!MANTLE_FUNCTIONS.has(f)&&no2("SQL_FUNCTION",`${f} is not one of Mantle's functions`,here),OUTSIDE.test(f)&&no2("SQL_FUNCTION",`${f} changes session or server state, or reaches outside the database`,here);let setting=n.args?.[0]?.A_Const?.sval?.sval;(f==="set_config"||f==="current_setting")&&(typeof setting!="string"||setting.toLowerCase().startsWith("mantle."))&&no2("SQL_FUNCTION",`${f} of a mantle.* setting is refused`,here)}walk2(n,ctes,here,ctx)}}function relation(n,ctes,at,ctx,written){let name4=String(n.relname);if((n.schemaname||n.catalogname)&&no2("SQL_RELATION",`${n.schemaname??n.catalogname}.${name4}: a relation is a declared Schema, never schema-qualified`,at),ctes.has(name4)){n.mantle="cte";return}let view=Object.hasOwn(ctx.schemas,name4)?void 0:ctx.views?.[name4];if(view){written&&no2("SQL_WRITE",`${name4} is a View: a View is read, never written`,at),view.refusal&&no2("SQL_RELATION",view.refusal,at),n.mantle="view";return}Object.hasOwn(ctx.schemas,name4)||no2("SQL_RELATION",`${name4} is not a declared Schema`,at)}var functionName2=n=>n?.FuncCall?.funcname?.map(v=>v.String.sval).join(".");function registerUserField(fields,field,spec){let old=fields[field],enumKey=values=>values?JSON.stringify([...values].sort((a,b)=>String(a).localeCompare(String(b)))):null;if(old&&(old.type!==spec.type||old.enum&&spec.enum&&enumKey(old.enum)!==enumKey(spec.enum)))throw new SqlRefusal("USER_FIELD_CONFLICT",`'${field}' is bound by Schema scopes with conflicting column types or enums.`);let merged=old?.enum&&!spec.enum?old:spec;fields[field]=Object.freeze(old?.integer&&!merged.integer?{...merged,integer:!0}:merged)}var USER_REF_SCOPE_ONLY=`auth.user() belongs in a Schema scope or this target's restrict: { <schema>: "<column> IN auth.user('<field>')" }, never in SQL.`;function refuseUserReferences(node){if(Array.isArray(node)){node.forEach(refuseUserReferences);return}if(!node||typeof node!="object")return;let fn3=functionName2(node);if(fn3==="auth.role"||fn3==="auth.hasrole")throw new SqlRefusal("AUTH_ROLE_REMOVED",`${fn3==="auth.role"?"auth.role()":"auth.hasRole()"} is removed; decide per-target permission in the application's authorize(target, caller) seam.`,node.FuncCall.location);if(fn3==="auth.user")throw new SqlRefusal("USER_REF_SCOPE_ONLY",USER_REF_SCOPE_ONLY,node.FuncCall.location);Object.values(node).forEach(refuseUserReferences)}async function relationNames(sql4){let names=new Set,walk3=(v,scope=new Set)=>{if(Array.isArray(v))return v.forEach(x=>walk3(x,scope));if(!v||typeof v!="object")return;typeof v.relname=="string"&&!scope.has(v.relname)&&names.add(v.relname);let w=v.withClause;if(w){let declared=w.ctes.map(x=>x.CommonTableExpr.ctename);w.ctes.forEach((x,i)=>walk3(x.CommonTableExpr.ctequery,new Set([...scope,...w.recursive?declared:declared.slice(0,i)]))),scope=new Set([...scope,...declared])}for(let[key,child2]of Object.entries(v))key!=="withClause"&&walk3(child2,scope)};try{walk3((await parsePgSql(sql4)).stmts)}catch{}return names}async function statementCount(sql4){try{return(await parsePgSql(sql4)).stmts.length}catch(e){if(e instanceof SqlRefusal)return toDiagnostic(e,sql4);throw e}}function locate(source,byteOffset){let prefix=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!1}).decode(new TextEncoder().encode(source).subarray(0,byteOffset)),lines=prefix.split(`
|
|
5
|
+
`),rest=source.slice(prefix.length),token=/^("[^"]*"|'[^']*'|[\w.$]+|\S)/.exec(rest)?.[0];return{offset:prefix.length,line:lines.length,column:lines[lines.length-1].length+1,...token?{token}:{}}}function toDiagnostic(e,source){let at=e.keyword?.exec(source.replace(/'(?:[^']|'')*'|"(?:[^"]|"")*"/g,m=>" ".repeat(m.length)));return at?{code:e.code,message:e.message,...locate(source,new TextEncoder().encode(source.slice(0,at.index)).byteLength),token:at[0]}:{code:e.code,message:e.message,...e.offset===void 0?{}:locate(source,e.offset)}}function tagRelations(v){if(Array.isArray(v))return v.map(tagRelations);if(!v||typeof v!="object")return v;let out={};for(let[k,c]of Object.entries(v))out[k]=tagRelations(c);return"relname"in out&&!("mantle"in out)&&(out.mantle="table"),out}function expandViews(v,views,share){if(Array.isArray(v))return v.map(x=>expandViews(x,views,share));if(!v||typeof v!="object")return v;if(!v.SelectStmt)return Object.fromEntries(Object.entries(v).map(([k,c])=>[k,expandViews(c,views,share)]));let used=new Set,tables=new Set,reserve=n=>{if(!(!n||typeof n!="object")){n.RangeVar?.mantle==="table"&&tables.add(n.RangeVar.relname);for(let[key,child2]of Object.entries(n))["relname","ctename","aliasname"].includes(key)&&used.add(String(child2)),reserve(child2)}};reserve(v);for(let ref2 of Object.values(views))reserve(ref2.select);let serial=0,fresh=()=>{let name4;do name4=`_view_${serial++}`;while(used.has(name4));return used.add(name4),name4},names=new Map,definitions=[],walk3=(n,scope=new Map)=>{if(Array.isArray(n))return n.map(x=>walk3(x,scope));if(!n||typeof n!="object")return n;let rv=n.RangeVar;if(rv?.mantle==="view"){if(!share)return{RangeSubselect:{subquery:{SelectStmt:walk3(views[rv.relname].select)},alias:rv.alias??{aliasname:rv.relname}}};let name4=names.get(rv.relname);if(!name4){names.set(rv.relname,name4=fresh());let select2=walk3(views[rv.relname].select);definitions.push({CommonTableExpr:{ctename:name4,ctequery:{SelectStmt:select2},ctematerialized:"CTEMaterializeDefault"}})}return{RangeVar:{...rv,mantle:"cte",relname:name4,alias:rv.alias??{aliasname:rv.relname}}}}if(rv?.mantle==="cte"&&scope.has(rv.relname)&&scope.get(rv.relname)!==rv.relname)return{RangeVar:{...rv,relname:scope.get(rv.relname),alias:rv.alias??{aliasname:rv.relname}}};let w=n.withClause;if(!w)return Object.fromEntries(Object.entries(n).map(([k,c])=>[k,walk3(c,scope)]));let local=new Map(w.ctes.map(x=>[x.CommonTableExpr.ctename,tables.has(x.CommonTableExpr.ctename)?fresh():x.CommonTableExpr.ctename])),inner=new Map([...scope,...local]),prior=new Map(scope),ctes=w.ctes.map(({CommonTableExpr:c})=>{let query=walk3(c.ctequery,w.recursive?inner:prior);return prior.set(c.ctename,local.get(c.ctename)),{CommonTableExpr:{...c,ctename:local.get(c.ctename),ctequery:query}}});return{...Object.fromEntries(Object.entries(n).filter(([k])=>k!=="withClause").map(([k,c])=>[k,walk3(c,inner)])),withClause:{...w,ctes}}},out=walk3(v);return definitions.length&&(out.SelectStmt.withClause={...out.SelectStmt.withClause,ctes:[...definitions,...out.SelectStmt.withClause?.ctes??[]]}),out}function stripLocations(v){return JSON.parse(JSON.stringify(v),(k,c)=>k==="location"||k==="rexpr_list_start"||k==="rexpr_list_end"?void 0:c)}async function compileSql(sql4,ctx,dialect=compile_exports){try{if(/\bIN\s+auth\.user\s*\(/i.test(sql4))throw new SqlRefusal("USER_REF_SCOPE_ONLY",USER_REF_SCOPE_ONLY);let parsed=await parsePgSql(sql4);if(/\/\*|\*\//.test(JSON.stringify(parsed.stmts)))throw new SqlRefusal("SQL_UNSUPPORTED","String literals and identifiers cannot contain '/*' or '*/'.");let tagged=tagRelations(parsed.stmts);refuseUserReferences(tagged),refuseForEveryDialect(tagged,ctx,parsed.locations);let stmts=expandViews(tagged,ctx.views??{},dialect.name===name2);return dialect.accepts(stmts,{...ctx,source:sql4},parsed.locations),{ok:!0,plan:{grammar:180004,stmts:stripLocations(stmts)},...ctx.kind==="view"?{reference:stripLocations(tagged)[0].SelectStmt}:{}}}catch(e){if(e instanceof SqlRefusal)return{ok:!1,diagnostic:toDiagnostic(e,sql4)};throw e}}var indexColumn=field=>Object.hasOwn(NATIVE_COLUMNS,field)?NATIVE_COLUMNS[field]:field.toLowerCase();function toDiagnostic2(d,source,pointer2){let at=d.line===void 0?void 0:{line:d.line,column:d.column,...d.token?{token:d.token}:{}};return validateDiagnostic({code:d.code,severity:"error",path:`${source.sourceId}#/${source.documentIndex}${pointer2}`,source:{...source,path:pointer2},...at?{value:at}:{},message:at?`SQL ${at.line}:${at.column}${at.token?` near ${JSON.stringify(at.token)}`:""}: ${d.message}`:d.message})}var starCols=s=>Object.entries(s.fields).filter(([f])=>f!==s.scope).flatMap(([f,t])=>t==="geo"?[`${f}_lat`,`${f}_lng`]:[f]);function viewOutputs(view,schemas,ctes=new Map,includeGeo=!1,includeAggregates=!0){let columns2=Object.create(null),sel=view.stmts[0]?.SelectStmt;if(!sel?.targetList)return{columns:columns2};let outputs=(stmt,scope2)=>viewOutputs({grammar:view.grammar,stmts:[stmt]},schemas,scope2,includeGeo,includeAggregates),scope=new Map(ctes);if(sel.withClause?.recursive)for(let{CommonTableExpr:c}of sel.withClause.ctes)scope.set(c.ctename,Object.create(null));for(let{CommonTableExpr:c}of sel.withClause?.ctes??[]){let body=outputs(c.ctequery,scope),renamed=c.aliascolnames?.map(x=>x.String.sval);scope.set(c.ctename,renamed?Object.fromEntries(renamed.flatMap((n,i)=>body.columns[body.positions?.[i]??""]?[[n,body.columns[body.positions[i]]]]:[])):body.columns)}let rels=new Map,subs=new Map,walk3=n=>{if(n.JoinExpr)return walk3(n.JoinExpr.larg),walk3(n.JoinExpr.rarg);let v=n.RangeVar;v?rels.set(v.alias?.aliasname??v.relname,v.mantle==="table"&&schemas[String(v.relname).toLowerCase()]?String(v.relname).toLowerCase():void 0):rels.set((n.RangeSubselect??n.RangeFunction)?.alias?.aliasname??"",void 0),v?.mantle==="cte"&&scope.has(v.relname)&&subs.set(v.alias?.aliasname??v.relname,scope.get(v.relname)),n.RangeSubselect?.subquery?.SelectStmt&&subs.set(n.RangeSubselect.alias?.aliasname??"",outputs(n.RangeSubselect.subquery,scope).columns)};for(let f of sel.fromClause??[])walk3(f);let typeOf=(schema,col)=>schemas[schema].fields[col]??(col==="published_at"&&schemas[schema].publishing?"timestamptz":Object.hasOwn(NATIVE_OUTPUT_TYPES,col)?NATIVE_OUTPUT_TYPES[col]:void 0),field=(schema,col)=>schema&&typeOf(schema,col)&&(includeGeo||typeOf(schema,col)!=="geo")?{schema,field:col}:void 0,keys=[];for(let{ResTarget:r}of sel.targetList){let agg=r.val?.FuncCall,fn3=agg?.funcname?.at(-1)?.String?.sval,arg=agg&&!agg.over&&!agg.agg_distinct&&agg.args?.length===1?agg.args[0].ColumnRef?.fields:void 0,refs2=r.val?.ColumnRef?.fields??(includeAggregates&&r.name&&arg&&["sum","min","max"].includes(fn3)?arg:void 0);if(!r.name&&refs2?.at(-1)?.A_Star){let from=refs2.length>1?[rels.get(refs2[0].String.sval)]:[...rels.values()];if(from.some(s=>!s)){keys=void 0;continue}for(let s of from)for(let c of starCols(schemas[s])){keys?.push(c);let f2=field(s,c);f2&&(columns2[c]=f2)}continue}let col=refs2?.at(-1)?.String?.sval,name4=r.name??col;if(!name4){keys=void 0;continue}keys?.push(name4);let relName=refs2?.length===2?refs2[0].String.sval:refs2?.length===1&&rels.size===1?[...rels.keys()][0]:void 0,rel=relName===void 0?void 0:rels.get(relName),f=col?field(rel,col)??(relName!==void 0?subs.get(relName)?.[col]:void 0):void 0;f&&(fn3!=="sum"||r.val?.ColumnRef||["integer","real"].includes(typeOf(f.schema,f.field))||typeOf(f.schema,f.field).startsWith("numeric("))&&(columns2[name4]=f)}return{...keys?{keys:[...new Set(keys)],positions:keys}:{},columns:columns2}}var JSON_FUNCS=new Set(["json_group_array","json_group_object","json_set","json_insert","json_remove","jsonb_agg","jsonb_object_agg","jsonb_build_object","jsonb_build_array","jsonb_strip_nulls","to_jsonb"]),isJson=n=>{if(n?.FuncCall)return JSON_FUNCS.has(n.FuncCall.funcname?.at(-1)?.String?.sval);if(n?.TypeCast)return n.TypeCast.typeName?.names?.at(-1)?.String?.sval==="jsonb";let sub=n?.SubLink?.subLinkType==="EXPR_SUBLINK"?n.SubLink.subselect?.SelectStmt:void 0;if(sub)return sub.targetList?.length===1&&isJson(sub.targetList[0].ResTarget?.val);let args=n?.CoalesceExpr?.args,literal=a=>{let text=a.A_Const?.sval?.sval;try{return text!==void 0&&(JSON.parse(text),!0)}catch{return!1}};return!!args?.some(isJson)&&args.every(a=>isJson(a)||literal(a))},jsonOutputs=view=>new Set((view.stmts[0]?.SelectStmt?.targetList??[]).flatMap(({ResTarget:r})=>r?.name&&isJson(r.val)?[r.name]:[])),aggregates=v=>{if(Array.isArray(v))return v.some(aggregates);if(!v||typeof v!="object"||"SubLink"in v)return!1;let call=v.FuncCall,name4=call?.funcname?.map(x=>x.String?.sval).join(".").replace(/^pg_catalog\./,"");return!!call&&!call.over&&AGGREGATES.has(name4)||Object.values(v).some(aggregates)};function tableOutputs(view,schemas){let out=Object.create(null),read=(sel2,qual,name4)=>{if(!sel2||sel2.op!=="SETOP_NONE"||sel2.withClause)return;let items=[],from=(n,nullable2)=>{n.JoinExpr?(from(n.JoinExpr.larg,nullable2),from(n.JoinExpr.rarg,nullable2||n.JoinExpr.jointype!=="JOIN_INNER")):items.push({node:n,nullable:nullable2})};for(let f of sel2.fromClause??[])from(f,!1);let alias=n=>n.RangeVar?n.RangeVar.alias?.aliasname??n.RangeVar.relname:(n.RangeSubselect??n.RangeFunction)?.alias?.aliasname,hit=qual===void 0?items:items.filter(i=>alias(i.node)===qual);if(hit.length!==1||qual===void 0&&items.length!==1)return;let{node,nullable}=hit[0],found;if(node.RangeVar?.mantle==="table"){let s=schemas[String(node.RangeVar.relname).toLowerCase()],type=s&&name4!=="_rid"?storageColumns(s).get(name4):void 0;type&&(found={type:type==="native"?"timestamptz":type,notNull:NATIVE_NOT_NULL.has(name4)||notNullColumns(s).has(name4)})}else if(node.RangeSubselect&&!node.RangeSubselect.lateral&&!node.RangeSubselect.alias?.colnames?.length){let inner=node.RangeSubselect.subquery?.SelectStmt,outs=(inner?.targetList??[]).filter(t=>(t.ResTarget.name??t.ResTarget.val?.ColumnRef?.fields?.at(-1)?.String?.sval)===name4);found=outs.length===1?bare(inner,outs[0].ResTarget.val):void 0}return found&&{type:found.type,notNull:found.notNull&&!nullable}},bare=(sel2,val)=>{let f=val?.ColumnRef?.fields;if(!f||f.length>2||f.some(x=>!x.String))return;let got=read(sel2,f.length===2?f[0].String.sval:void 0,f.at(-1).String.sval);return got&&{type:got.type,notNull:got.notNull&&(!!sel2.groupClause||!(sel2.havingClause||aggregates([sel2.targetList,sel2.sortClause])))}},sel=view.stmts[0]?.SelectStmt;for(let{ResTarget:r}of sel?.targetList??[]){let name4=r.name??r.val?.ColumnRef?.fields?.at(-1)?.String?.sval,got=name4?bare(sel,r.val):void 0;got&&(out[name4]=got)}return out}async function compileLinkedPlan(linked,dialect=compile_exports){let schemas={},userFields=Object.create(null),diagnostics=[];for(let{manifest:m}of linked.schemas){let template=m.spec.scope===void 0?void 0:parseRowTemplate(m.spec.scope),scope=template&&typeof template=="object"?template.owner?.toLowerCase():void 0,userScopes=template&&typeof template=="object"?template.terms.map(({column,field:field2})=>{let property=m.spec.schema.properties?.[column],type=property?.type==="string"?"string":"number";try{registerUserField(userFields,field2,{type,...[property?.type].flat().includes("integer")?{integer:!0}:{},multiple:!0,...property?.enum?{enum:property.enum}:{}})}catch(error){if(!(error instanceof SqlRefusal))throw error;diagnostics.push(validateDiagnostic({code:error.code,severity:"error",path:`schemas/${m.metadata.name}/scope`,message:error.message}))}return{column:column.toLowerCase(),field:field2,type}}):[],props=m.spec.schema.properties??{},lower=xs=>xs.map(x=>x.toLowerCase());schemas[m.metadata.name.toLowerCase()]={name:m.metadata.name,title:m.spec.title,...m.spec.description?{description:m.spec.description}:{},...m.spec.uiSchema?{uiSchema:m.spec.uiSchema}:{},...m.spec.localized?{localized:!0}:{},...scope?{scope}:{},...userScopes.length?{userScopes}:{},...m.spec.ttl?{ttl:m.spec.ttl.field.toLowerCase(),ttlSeconds:m.spec.ttl.expireAfterSeconds}:{},publishing:m.spec.lifecycle==="publishing",...m.spec.publishing?.liveEdits?{liveEdits:!0}:{},schema:m.spec.schema,...m.spec.translates?{translates:{parent:m.spec.translates.parent,on:m.spec.translates.on}}:{},fields:fieldTypes(m.spec.schema),names:Object.fromEntries(Object.keys(props).map(n=>[n.toLowerCase(),n])),...m.spec.searchableFields?.length?{search:lower(m.spec.searchableFields)}:{},...m.spec.uniqueIndexes?.length?{unique:m.spec.uniqueIndexes.map(lower)}:{},...m.spec.indexes?.length?{indexes:m.spec.indexes.map(cols=>cols.map(indexColumn))}:{}}}let refs2={},refName=name4=>name4.toLowerCase().replace(/-/g,"_"),refOf=new Map(linked.views.map(x=>[refName(x.manifest.metadata.name),x])),readable2=new Set;for(let[ref2,{manifest:v}]of refOf){if(Object.hasOwn(schemas,ref2))continue;let why=v.spec.surface!=="internal"?`a ${v.spec.surface} View`:v.spec.input?"a View with an input":v.spec.requires?"a View with requires":void 0;why||readable2.add(ref2),refs2[ref2]={refusal:why?`${ref2} is ${why}: FROM reads only an internal View without input or requires`:`${ref2} did not compile`}}let ctxOf=(kind,input,isPublic=!1)=>({schemas,inputs:fieldTypes(input),kind,public:isPublic,views:refs2}),compile=async(kind,sql4,input,source,pointer2,isPublic=!1,steps)=>{let res=await compileSql(sql4,ctxOf(kind,input,isPublic),dialect);if(res.ok)return res;let d=res.diagnostic,step=steps&&d.line!==void 0?steps.findLastIndex(start=>start<d.line):-1;steps?diagnostics.push(step<0?toDiagnostic2(d,source,"/spec/handler/steps"):toDiagnostic2({...d,line:d.line-steps[step]},source,`/spec/handler/steps/${step}/sql`)):diagnostics.push(toDiagnostic2(d,source,pointer2))};for(let{manifest:m,source}of linked.schemas){let name4=m.metadata.name.toLowerCase(),clash=storageColumnClash(schemas[name4].fields??{});clash&&diagnostics.push(toDiagnostic2({code:"SQL_SHAPE",message:`field '${clash}' is a column storage creates for another purpose (_rid, or a geo field's _lat/_lng)`},source,`/spec/schema/properties/${clash}`));let checks=[];for(let[i,text]of(m.spec.checks??[]).entries()){let pointer2=`/spec/checks/${i}`,res=await compileSql(`SELECT 1 FROM "${name4.replace(/"/g,'""')}" WHERE ${text}`,{schemas,inputs:{},kind:"view"},dialect);if(!res.ok){diagnostics.push(toDiagnostic2(res.diagnostic,source,pointer2));continue}let where=res.plan.stmts[0]?.SelectStmt?.whereClause,problem3=where?checkShapeProblem(where,storageColumns(schemas[name4])):"a check is one boolean expression";if(problem3){diagnostics.push(toDiagnostic2({code:"SQL_SHAPE",message:problem3},source,pointer2));continue}checks.push(where)}checks.length&&(schemas[name4]={...schemas[name4],checks})}let field=(schema,column)=>schemas[schema].names?.[column]??Object.keys(NATIVE_COLUMNS).find(f=>NATIVE_COLUMNS[f]===column)??column;for(let{manifest:m,source}of linked.schemas){let name4=m.metadata.name.toLowerCase(),locks=[];for(let[i,lock]of(m.spec.lock??[]).entries()){let pointer2=`/spec/lock/${i}/when`,res=await compileSql(`SELECT 1 FROM "${name4.replace(/"/g,'""')}" WHERE ${lock.when}`,{schemas,inputs:{},kind:"view"},dialect);if(!res.ok){diagnostics.push(toDiagnostic2(res.diagnostic,source,pointer2));continue}let select2=res.plan.stmts[0]?.SelectStmt,where=select2?.whereClause,tail=Object.keys(select2??{}).find(k=>!["targetList","fromClause","whereClause","op","limitOption"].includes(k)),problem3=tail?`a lock's when is one boolean expression: ${tail} is refused`:where?lockShapeProblem(where,schemas,name4):"a lock is one boolean expression";if(problem3){diagnostics.push(toDiagnostic2({code:"SQL_SHAPE",message:problem3},source,pointer2));continue}let unindexed=lockIndexProblem(where,schemas);if(unindexed){let target2=schemas[unindexed.schema].name,columns2=unindexed.columns.map(c=>field(unindexed.schema,c));diagnostics.push(validateDiagnostic({code:"LOCK_INDEX_MISSING",severity:"error",path:`${source.sourceId}#/${source.documentIndex}${pointer2}`,source:{...source,path:pointer2},message:`Schema '${m.metadata.name}' lock '${lock.name}': no index serves its EXISTS on '${target2}', which every guarded write runs. ${columns2.length?`Declare indexes: [[${columns2.join(", ")}]] on Schema '${target2}'`:unindexed.or?"OR is not index-proven: split it into separate locks, each with an equality on an indexed column":`Correlate the subquery to the locked row by an equality on one of '${target2}''s columns (e.g. ${target2}.<field> = ${name4}.id), then index that column`} (handbook: reference/schema.md#locks).`}));continue}let serial=0,rename=(n,from,to)=>{if(!n||typeof n!="object")return;let f=n.ColumnRef?.fields;f?.length===2&&f[0].String?.sval===from&&(f[0]={String:{sval:to}}),Object.values(n).forEach(x=>rename(x,from,to))},system=n=>{if(!n||typeof n!="object")return;let s=n.SubLink?.subselect?.SelectStmt,v=s?.fromClause?.[0]?.RangeVar;if(v){let to=`_mantle_lock_${serial++}`;rename(s,v.alias?.aliasname??v.relname,to),v.alias={aliasname:to},v.mantle="system"}Object.values(n).forEach(system)};system(where),locks.push({name:lock.name,on:[...lock.on],when:where,message:lock.message})}locks.length&&(schemas[name4]={...schemas[name4],locks})}let order=[],state=new Map,reads=new Map(await Promise.all(linked.views.map(async x=>[x.manifest.metadata.name,[...await relationNames(x.manifest.spec.sql)].filter(r=>readable2.has(r))]))),procedureReads=new Map(await Promise.all(linked.procedures.flatMap(({manifest:p})=>{let sql4=p.spec.handler.sql;return sql4===void 0?[]:[(async()=>[sql4,[...await relationNames(sql4)].filter(r=>readable2.has(r))])()]}))),viewRefs=sql4=>reads.get(linked.views.find(x=>x.manifest.spec.sql===sql4)?.manifest.metadata.name??"")??procedureReads.get(sql4)??[],visit=(x,path)=>{let name4=x.manifest.metadata.name;if(state.get(name4)!=="done"){if(state.get(name4)==="visiting"){diagnostics.push(toDiagnostic2({code:"SQL_RELATION",message:`View '${name4}' reads itself: ${[...path,name4].join(" -> ")}`},x.source,"/spec/sql"));return}state.set(name4,"visiting");for(let r of reads.get(name4)??[])visit(refOf.get(r),[...path,name4]);state.set(name4,"done"),order.push(x)}};for(let x of linked.views)visit(x,[]);let compiled=new Map;for(let{manifest:v,source}of order){if((reads.get(v.metadata.name)??[]).some(r=>!refs2[r]?.select))continue;let result=await compile("view",v.spec.sql,v.spec.input,source,"/spec/sql",v.spec.surface==="public"),plan=result?.plan;compiled.set(v.metadata.name,plan);let ref2=refName(v.metadata.name);plan&&readable2.has(ref2)&&(refs2[ref2]={select:result.reference})}let views={};for(let{manifest:v,source}of linked.views){let plan=compiled.get(v.metadata.name),cacheProblem=plan&&v.spec.cache?viewCacheProblem(plan.stmts,schemas):void 0;cacheProblem&&diagnostics.push(validateDiagnostic({code:"VIEW_CACHE_INVALID",severity:"error",path:`${source.sourceId}#/${source.documentIndex}/spec/cache`,source:{...source,path:"/spec/cache"},message:`View '${v.metadata.name}': ${cacheProblem}.`}));let outputs=plan?viewOutputs(plan,schemas):void 0,columns2=outputs?.columns??{},list=v.spec.uiSchema?.list??{};for(let key of["searchFields","filterFields"])for(let[i,f]of(list[key]??[]).entries())!outputs?.keys||outputs.keys.some(k=>k===f||k===f.toLowerCase())||diagnostics.push(validateDiagnostic({code:"VIEW_UI_INVALID",severity:"error",path:`${source.sourceId}#/${source.documentIndex}/spec/uiSchema/list/${key}/${i}`,source:{...source,path:`/spec/uiSchema/list/${key}/${i}`},value:f,expected:`one of the View's outputs: ${outputs.keys.join(", ")}`,message:`View '${v.metadata.name}' uiSchema.list.${key} names '${f}', which the View's SELECT does not output.`}));let wire=(outputs?.keys??[]).map(k=>columns2[k]?.field===k?schemas[columns2[k].schema].names?.[k]??k:k);for(let[i,f]of(list.columns??[]).entries()){if(!outputs?.keys||wire.includes(f))continue;let folded=wire.find(k=>k.toLowerCase()===f.toLowerCase());diagnostics.push(validateDiagnostic({code:"VIEW_UI_INVALID",severity:"error",path:`${source.sourceId}#/${source.documentIndex}/spec/uiSchema/list/columns/${i}`,source:{...source,path:`/spec/uiSchema/list/columns/${i}`},value:f,expected:`one of the View's outputs: ${wire.join(", ")}`,message:folded?`View '${v.metadata.name}' uiSchema.list.columns names '${f}', but the row carries '${folded}': an unquoted alias folds to lower case, so write AS "${f}".`:`View '${v.metadata.name}' uiSchema.list.columns names '${f}', which the View's SELECT does not output.`}))}plan&&(views[v.metadata.name]={...plan,...Object.keys(columns2).length?{columns:columns2}:{},...v.spec.title?{title:v.spec.title}:{},...v.spec.description?{description:v.spec.description}:{},...v.spec.uiSchema?{uiSchema:v.spec.uiSchema}:{},inputs:fieldTypes(v.spec.input),...v.spec.input?{input:v.spec.input}:{},source:v.spec.sql,surface:v.spec.surface,...v.spec.requires?{requires:v.spec.requires}:{},...v.spec.cache?{sharedMaxAge:v.spec.cache.sharedMaxAge}:{}})}let procedures={},declaredSchema=new Map(linked.schemas.map(x=>[x.manifest.metadata.name.toLowerCase(),x.manifest.metadata.name])),inferTarget=(p,stmts)=>{let rows=stmts.filter(s=>classify(s)==="row"),pinned=rows.length===1?pinnedTarget(rows[0]):void 0,props=Object.keys(p.spec.input.properties??{}),declared=lower=>props.find(k=>k.toLowerCase()===lower),id=pinned&&declared(pinned.id),schema=pinned&&declaredSchema.get(pinned.schema.toLowerCase());if(!pinned||!id||!schema||!p.spec.input.required?.includes(id)||p.spec.input.properties[id].type!=="string")return;let version3=pinned.version&&declared(pinned.version);if(!(version3&&!["number","integer"].includes(String(p.spec.input.properties[version3].type))))return{schema,id,...version3?{version:version3}:{}}};for(let{manifest:p,source}of linked.procedures){let common={...p.spec.title?{title:p.spec.title}:{},...p.spec.description?{description:p.spec.description}:{},...p.spec.uiSchema?{uiSchema:p.spec.uiSchema}:{},input:p.spec.input,output:p.spec.output,inputs:fieldTypes(p.spec.input),...p.spec.requires?{requires:p.spec.requires}:{},...p.spec.mcp?{mcp:p.spec.mcp}:{}};if("ref"in p.spec.handler){procedures[p.metadata.name]={...common,...p.spec.target?{target:p.spec.target}:{},handler:{ref:p.spec.handler.ref}};continue}let{sql:sql4,steps}=p.spec.handler,single=!0;for(let[i,step]of(steps??[]).entries()){let n=await statementCount(step.sql);n!==1&&(single=!1,diagnostics.push(toDiagnostic2(typeof n=="number"?{code:"SQL_SHAPE",message:`Procedure '${p.metadata.name}' handler.steps[${i}] must be exactly one statement; it has ${n||"none"}. Write each statement as its own step`}:n,source,`/spec/handler/steps/${i}/sql`)))}let plan=single?(await compile("procedure",sql4,p.spec.input,source,"/spec/handler/sql",!1,steps&&stepProgram(steps).lines))?.plan:void 0,target2=p.spec.target??(plan?inferTarget(p,plan.stmts):void 0);for(let stmt of plan?.stmts??[]){let write=stmt.UpdateStmt??stmt.InsertStmt,columns2=write?protectedColumns(schemas[write.relation.relname]):[];(stmt.UpdateStmt?.targetList??stmt.InsertStmt?.onConflictClause?.targetList??[]).some(set=>columns2.includes(set.ResTarget.name.toLowerCase()))&&diagnostics.push(validateDiagnostic({code:"USER_FIELD_POSITION",severity:"error",path:`procedures/${p.metadata.name}/handler/sql`,message:"The scoped column is never writable through SET."}))}for(let[i,step]of(plan?steps??[]:[]).entries()){if(!step.onNoRows||classify(plan.stmts[i])!=="row")continue;let at=`/spec/handler/steps/${i}/onNoRows`;diagnostics.push(validateDiagnostic({code:"SQL_SHAPE",severity:"error",path:`${source.sourceId}#/${source.documentIndex}${at}`,source:{...source,path:at},value:step.onNoRows,message:`Procedure '${p.metadata.name}' handler.steps[${i}].onNoRows applies to a set-op write; this step is a row op (one-row INSERT \u2026 VALUES, or UPDATE/DELETE with WHERE id = \u2026), which already must change exactly one row.`}))}plan&&(procedures[p.metadata.name]={...common,...target2?{target:target2}:{},handler:{sql:plan,source:sql4,...steps?{steps}:{}}})}if(diagnostics.length)return{ok:!1,diagnostics};let touched=(node,includeCtes=!1,found=new Set)=>{if(!node||typeof node!="object")return found;let n=node,rel=includeCtes||n.RangeVar?.mantle!=="cte"?n.RangeVar?.relname:void 0;rel&&found.add(rel);for(let kind of["InsertStmt","UpdateStmt","DeleteStmt"])n[kind]?.relation?.relname&&found.add(n[kind].relation.relname);return Object.values(node).forEach(child2=>touched(child2,includeCtes,found)),found},restrictOf=(kind,name4,raw,stmts)=>{if(!raw)return;if(typeof raw!="object"||Array.isArray(raw)){diagnostics.push(validateDiagnostic({code:"USER_FIELD_CONFLICT",severity:"error",path:`${kind}/${name4}/restrict`,message:'restrict maps each Schema to a predicate, e.g. restrict: { orders: "author_id = auth.uid()" }.'}));return}let read=touched(stmts),out={};for(let[key,text]of Object.entries(raw)){let table=key.toLowerCase(),schema=schemas[table],path=`${kind}/${name4}/restrict/${key}`,fail=message2=>{diagnostics.push(validateDiagnostic({code:"USER_FIELD_CONFLICT",severity:"error",path,message:message2}))};if(!schema||!read.has(table)){fail(`restrict key '${key}' is not a Schema this target's SQL reads.`);continue}let template=parseRowTemplate(text);if(typeof template=="string"){fail(`restrict: ${template}`);continue}let column=c=>Object.keys(schema.fields).find(f=>f===c.toLowerCase()),owner=template.owner?.toLowerCase();if(owner&&owner!=="author_id"&&owner!==schema.scope){fail(`restrict '${template.owner} = auth.uid()': use author_id (stamped from the caller on insert) or the Schema's own '= auth.uid()' scope column; '${template.owner}' is writable.`);continue}let terms=template.terms.flatMap(({column:c,field:field2})=>{let found=column(c);if(!found)return fail(`restrict column '${c}' is not a field of '${schema.name}'.`),[];let property=schema.schema?.properties?.[schema.names?.[found]??c],type=property?.type==="string"?"string":"number";try{registerUserField(userFields,field2,{type,...[property?.type].flat().includes("integer")?{integer:!0}:{},multiple:!0,...property?.enum?{enum:property.enum}:{}})}catch(error){if(!(error instanceof SqlRefusal))throw error;fail(error.message)}return[{column:found,field:field2,type}]});out[table]={...owner?{owner}:{},terms}}return Object.keys(out).length?out:void 0},inherit=(own,sql4,path)=>{let merged=Object.fromEntries(Object.entries(own??{}).map(([k,r])=>[k,{...r,terms:[...r.terms]}]));for(let ref2 of sql4===void 0?[]:viewRefs(sql4))for(let[table,r]of Object.entries(views[refOf.get(ref2).manifest.metadata.name]?.restrict??{})){let into=merged[table]??={terms:[]};if(r.owner&&into.owner&&r.owner!==into.owner){diagnostics.push(validateDiagnostic({code:"USER_FIELD_CONFLICT",severity:"error",path,message:`reads Views whose restrict on '${table}' names different owner columns.`}));continue}r.owner&&(into.owner=r.owner);for(let t of r.terms)into.terms.some(x=>x.column===t.column&&x.field===t.field)||into.terms.push(t)}return Object.keys(merged).length?merged:void 0};for(let{manifest:v}of order){let view=views[v.metadata.name],restrict=view&&inherit(restrictOf("views",v.metadata.name,v.spec.restrict,view.stmts),v.spec.sql,`views/${v.metadata.name}/restrict`);restrict&&(views[v.metadata.name]={...view,restrict})}for(let{manifest:p}of linked.procedures){let proc=procedures[p.metadata.name];if(p.spec.restrict&&proc&&"ref"in proc.handler){diagnostics.push(validateDiagnostic({code:"USER_FIELD_CONFLICT",severity:"error",path:`procedures/${p.metadata.name}/restrict`,message:"restrict applies to SQL Procedures; a ref handler restricts rows through its scoped ctx.store."}));continue}let restrict=proc&&"sql"in proc.handler&&inherit(restrictOf("procedures",p.metadata.name,p.spec.restrict,proc.handler.sql.stmts)||void 0,p.spec.handler.sql,`procedures/${p.metadata.name}/restrict`),trustedOnly=!!proc&&"sql"in proc.handler&&proc.handler.sql.stmts.some(stmt=>{let ins=stmt.InsertStmt,t=String(ins?.relation.relname??"").toLowerCase();return!!ins&&(!!schemas[t]?.userScopes?.length&&(!ins.selectStmt?.SelectStmt?.valuesLists||!!(restrict&&restrict[t]))||!ins.selectStmt?.SelectStmt?.valuesLists&&!!schemas[t]&&refChecks(schemas[t],schemas).some(r=>ins.cols?.some(x=>String(x.ResTarget.name).toLowerCase()===r.column)))});(restrict||trustedOnly)&&(procedures[p.metadata.name]={...proc,...restrict?{restrict}:{},...trustedOnly?{trustedOnly:!0}:{}})}let triggers=Object.fromEntries(linked.triggers.map(({manifest:t})=>[t.metadata.name,{source:t.spec.source,procedure:t.spec.target.procedure}])),warnings=[];for(let[field2,spec]of Object.entries(userFields))spec.enum||warnings.push(`USER_FIELD_VALUES_UNENUMERATED: '${field2}' has no enum; no generated list of all values is available.`);let scopedFields=schema=>(schemas[schema]?.userScopes??[]).map(u=>u.field).sort().join(",");for(let[name4,view]of Object.entries(views)){let read=[...touched(view.stmts,!0)].filter(schema=>schemas[schema]);view.surface==="public"&&read.some(schema=>schemas[schema].userScopes?.length)&&warnings.push(`USER_SCOPE_PUBLIC_ANON_EMPTY: public View '${name4}' reads field-scoped data; anonymous callers are refused (UNAUTHENTICATED).`),view.surface==="admin"&&read.some(schema=>schemas[schema].userScopes?.length)&&warnings.push(`USER_SCOPE_ADMIN_VALUES: admin View '${name4}' reads field-scoped data; admins without values for those fields see no rows.`);let sets2=new Set(read.filter(schema=>schemas[schema].userScopes?.length).map(scopedFields));sets2.size>1&&warnings.push(`USER_SCOPE_JOIN_DROPS: View '${name4}' joins Schemas scoped by different fields (${[...sets2].join(" / ")}); rows outside any caller set are dropped.`)}for(let[name4,schema]of Object.entries(schemas))for(let[field2,property]of Object.entries(schema.schema?.properties??{})){let raw=property["x-mantle-ref"],ref2=typeof raw=="string"?raw:raw?.schema,target2=ref2?schemas[ref2.toLowerCase()]:void 0;for(let term2 of target2?target2.userScopes??[]:[])(schema.userScopes??[]).some(u=>u.field===term2.field)||diagnostics.push(validateDiagnostic({code:"USER_FIELD_CONFLICT",severity:"error",path:`schemas/${schema.name}/scope`,message:`'${schema.name}.${field2}' references '${target2.name}', which is scoped by auth.user('${term2.field}'); scope '${schema.name}' by the same field so its rows cannot expose what that scope hides.`}))}if(diagnostics.length)return{ok:!1,diagnostics};let sealed={version:6,dialect:{name:dialect.name,version:dialect.version},schemas,views,procedures,triggers,...Object.keys(userFields).length?{access:{roles:[],userFields,warnings}}:{}};return{ok:!0,plan:{...sealed,fingerprint:await planFingerprint(sealed)}}}async function compilePlan(sources,dialect=compile_exports,defaultLifecycle="publishing"){let parsed=parseManifestSources(sources,defaultLifecycle);if(!parsed.ok)return parsed;let linked=linkManifestSet(parsed.value);return linked.ok?compileLinkedPlan(linked.value,dialect):linked}var MEDIA_PURPOSE_SLUG_PATTERN=/^[a-z0-9]+(-[a-z0-9]+)*$/;var SHORTHAND_TO_MIME={jpg:"image/jpeg",jpeg:"image/jpeg","image/jpg":"image/jpeg",png:"image/png","image/png":"image/png",webp:"image/webp","image/webp":"image/webp",avif:"image/avif","image/avif":"image/avif",gif:"image/gif","image/gif":"image/gif",svg:"image/svg+xml","image/svg+xml":"image/svg+xml","image/svg":"image/svg+xml"};function parseMimeAccept(entry){let seen=new Set,out=[];for(let raw of entry.split(",")){let tok=raw.trim().toLowerCase();if(!tok)continue;let expanded=SHORTHAND_TO_MIME[tok]??tok;seen.has(expanded)||(seen.add(expanded),out.push(expanded))}return out}function expandPolicyRequired(required){return required.map(parseMimeAccept)}var InvalidLocaleError=class extends Error{constructor(value2){super(`invalid locale: ${value2}`),this.name="InvalidLocaleError"}};var LANG=/^[a-z]{2,3}$/,REGION=/^[a-z]{2}$/,SCRIPT_SUBTAG_SHAPE=/^[a-z]{2,3}[-_][a-z]{4}(?:[-_][a-z]{2})?$/i;function toCanonicalLocale(input){if(typeof input!="string"||input.length===0)throw new InvalidLocaleError(String(input));let parts=input.replace(/_/g,"-").split("-"),head=parts[0];if(head===void 0)throw new InvalidLocaleError(input);parts.length===1&&head.length===4&&(parts=[head.slice(0,2),head.slice(2)]);let lang=parts[0].toLowerCase();if(!LANG.test(lang))throw new InvalidLocaleError(input);if(parts.length===1)return lang;let region=parts[1].toLowerCase();if(!REGION.test(region))throw new InvalidLocaleError(input);return`${lang}-${region.toUpperCase()}`}function canonicalizeLocaleList(inputs){let valid=[],invalid2=[],seen=new Set;for(let raw of inputs)try{let canonical2=toCanonicalLocale(raw);seen.has(canonical2)||(seen.add(canonical2),valid.push(canonical2))}catch{invalid2.push(raw)}return{valid,invalid:invalid2}}function containsScriptSubtagLocale(inputs){return inputs.some(raw=>SCRIPT_SUBTAG_SHAPE.test(raw))}var InvalidSiteDefaultsError=class extends Error{constructor(invalidLocales){let hasScriptSubtag=containsScriptSubtagLocale(invalidLocales);super("Invalid Mantle locale tag(s) in adapter siteDefaults.locales: "+invalidLocales.map(s=>`'${s}'`).join(", ")+". Use Mantle v0.1 locale form like 'en' or 'zh-TW' \u2014 the canonicalizer accepts mixed case ('zh-tw' / 'ZH_TW'), but the structure must be a 2/3-letter language plus optional 2-letter region. "+(hasScriptSubtag?"Script subtags such as 'zh-Hant', 'zh-Hans', 'sr-Latn', or 'sr-Cyrl' are valid BCP 47 but intentionally unsupported in Mantle v0.1; use region tags such as 'zh-TW' for Traditional Chinese or 'zh-CN' for Simplified Chinese. ":"")+"See ADR-0010 / cms-spec's canonicalizeLocaleList.");this.invalidLocales=invalidLocales;this.name="InvalidSiteDefaultsError"}invalidLocales},InvalidMediaPurposesError=class extends Error{constructor(issues){super("Invalid media purpose declaration(s) in adapter siteDefaults.media.purposes: "+issues.map(i=>{let tag=`'${i.name||"(unnamed)"}'`;switch(i.reason){case"invalid-slug":return`${tag} fails slug pattern ${MEDIA_PURPOSE_SLUG_PATTERN.source}`;case"empty-required":return`${tag} declares no required slots (need at least one)`;case"empty-required-slot":return`${tag} has a required slot that parses to zero mimes: ${i.detail}`;case"overlapping-slot-mimes":return`${tag} has slots with overlapping mime sets (variant\u2192slot mapping is ambiguous): ${i.detail}`;case"maxBytes-missing-mime":return`${tag} maxBytes is missing entries: ${i.detail}`;case"maxBytes-non-positive":return`${tag} maxBytes has non-positive entries: ${i.detail}`}}).join("; ")+`. Each purpose's name must match ${MEDIA_PURPOSE_SLUG_PATTERN.source} (lowercase alphanumerics, dash-separated, no leading/trailing or repeated dashes); required mimes are the closed set the variants manifest must cover; maxBytes caps each variant's declared byteSize and MUST name every mime in required. See aotter/mantle#272.`);this.issues=issues;this.name="InvalidMediaPurposesError"}issues},InvalidSiteIconsError=class extends Error{constructor(invalidIcons){super("Invalid adapter siteDefaults.icons: each icon needs a root-relative or absolute HTTPS src, an optional supported image mimeType, and sizes such as '64x64' or 'any'.");this.invalidIcons=invalidIcons;this.name="InvalidSiteIconsError"}invalidIcons};function assertSiteDefaultsCanonical(defaults){if(defaults?.locales&&defaults.locales.length>0){let{invalid:invalid2}=canonicalizeLocaleList(defaults.locales);if(invalid2.length>0)throw new InvalidSiteDefaultsError(invalid2)}if(defaults?.icons){let invalid2=defaults.icons.filter(icon=>!validSiteIcon(icon));if(defaults.icons.length===0||invalid2.length>0)throw new InvalidSiteIconsError(invalid2.length>0?invalid2:defaults.icons)}let origin=defaults?.origin;if(origin&&!(URL.canParse(origin)&&/^https?:$/.test(new URL(origin).protocol)&&new URL(origin).origin===origin))throw new Error(`siteDefaults.origin '${origin}' must be an absolute http(s) origin such as 'https://example.com', with no path or trailing slash.`);let purposes=defaults?.media?.purposes;if(purposes&&purposes.length>0){let issues=collectMediaPurposeIssues(purposes);if(issues.length>0)throw new InvalidMediaPurposesError(issues)}}function validSiteIcon(icon){return!icon||typeof icon!="object"||typeof icon.src!="string"?!1:!!((/^\/(?!\/)[^\s\\]*$/.test(icon.src)||URL.canParse(icon.src)&&new URL(icon.src).protocol==="https:")&&(!icon.mimeType||["image/png","image/jpeg","image/svg+xml","image/webp"].includes(icon.mimeType))&&(!icon.theme||icon.theme==="light"||icon.theme==="dark")&&(!icon.sizes||Array.isArray(icon.sizes)&&icon.sizes.length>0)&&(icon.sizes?.every(size=>typeof size=="string"&&(size==="any"||/^[1-9]\d*x[1-9]\d*$/.test(size)))??!0))}function collectMediaPurposeIssues(purposes){let out=[];for(let p of purposes){if(!MEDIA_PURPOSE_SLUG_PATTERN.test(p.name)){out.push({name:p.name,reason:"invalid-slug"});continue}if(p.required.length===0){out.push({name:p.name,reason:"empty-required"});continue}let slots=expandPolicyRequired(p.required),emptySlots=slots.map((mimes,i)=>({mimes,raw:p.required[i]})).filter(s=>s.mimes.length===0);if(emptySlots.length>0){out.push({name:p.name,reason:"empty-required-slot",detail:emptySlots.map(s=>`'${s.raw}'`).join(", ")});continue}let seen=new Map,overlaps=[];if(slots.forEach((mimes,slotIdx)=>{for(let mime of mimes)seen.has(mime)?overlaps.push(`'${mime}' in slots [${seen.get(mime)}, ${slotIdx}]`):seen.set(mime,slotIdx)}),overlaps.length>0){out.push({name:p.name,reason:"overlapping-slot-mimes",detail:overlaps.join(", ")});continue}let expandedMimes=Array.from(seen.keys()),missing=expandedMimes.filter(mime=>!(mime in p.maxBytes));if(missing.length>0){out.push({name:p.name,reason:"maxBytes-missing-mime",detail:missing.join(", ")});continue}let nonPositive=expandedMimes.filter(mime=>!(typeof p.maxBytes[mime]=="number"&&p.maxBytes[mime]>0));nonPositive.length>0&&out.push({name:p.name,reason:"maxBytes-non-positive",detail:nonPositive.map(m=>`${m}=${p.maxBytes[m]}`).join(", ")})}return out}var VERB={create:"insert",update:"update",delete:"delete",publish:"publish"},lifecycleKey=(plan,schema)=>Object.hasOwn(plan.schemas,schema.toLowerCase())?schema.toLowerCase():void 0;function lifecycleHookSets(plan){let byHook=new Map,before=new Set,after=new Set,triggers=Object.entries(plan.triggers).sort(([a],[b])=>a<b?-1:1);for(let[name4,t]of triggers)if(t.source.kind==="lifecycle")for(let hook of t.source.on){let[stage,op2]=hook.split("_"),schema=lifecycleKey(plan,t.source.schema);(stage==="before"?before:after).add(`${schema}.${VERB[op2]}`);let key=`${schema}|${hook}`;byHook.set(key,[...byHook.get(key)??[],[name4,t.procedure]])}return{before,after,byHook}}var MANTLE_VERSION="0.2.1-alpha.1";var S=s=>({String:{sval:s}}),ref=(...f)=>({ColumnRef:{fields:f.map(S)}}),op=(o,l,r)=>({A_Expr:{kind:"AEXPR_OP",name:[S(o)],lexpr:l,rexpr:r}}),num=n=>Number.isSafeInteger(n)&&Math.abs(n)<2147483648?{A_Const:{ival:{ival:n}}}:{A_Const:{fval:{fval:String(n)}}},target=(val,name4)=>({ResTarget:name4?{name:name4,val}:{val}}),ATOMIC=new Set(["ColumnRef","A_Const","ParamRef","FuncCall","TypeCast","CaseExpr","CoalesceExpr","MinMaxExpr","RowExpr","Raw"]),atomic=x=>!x||typeof x!="object"||Object.keys(x).some(k=>ATOMIC.has(k))||x.SubLink&&["EXPR_SUBLINK","ARRAY_SUBLINK"].includes(x.SubLink.subLinkType),paren=x=>atomic(x)?x:{Raw:{parts:[x]}};function parenthesized(key,n){if(key==="NullTest"||key==="BooleanTest")return{...n,arg:paren(n.arg)};if(key==="SubLink")return n.testexpr?{...n,testexpr:paren(n.testexpr)}:n;let r=n.rexpr,rexpr=r?.List?{List:{...r.List,items:r.List.items.map(paren)}}:r?.FuncCall&&r.FuncCall.funcname?.at(-1)?.String?.sval==="like_escape"?{FuncCall:{...r.FuncCall,args:r.FuncCall.args?.map(paren)}}:paren(r);return{...n,...n.lexpr?{lexpr:paren(n.lexpr)}:{},...r?{rexpr}:{}}}function writeTarget(ast){let node=ast;return(node.InsertStmt??node.UpdateStmt??node.DeleteStmt)?.relation?.relname?.toLowerCase()}var HOOK_PREFIX="_mantle_h_",param=n=>({ParamRef:{number:n}}),and=(...args)=>{let a=args.filter(Boolean);return a.length===0?void 0:a.length===1?a[0]:{BoolExpr:{boolop:"AND_EXPR",args:a}}},or=(...a)=>({BoolExpr:{boolop:"OR_EXPR",args:a}}),sort=(node,dir="SORTBY_DEFAULT")=>({SortBy:{node,sortby_dir:dir,sortby_nulls:"SORTBY_NULLS_DEFAULT"}}),declaredCols=s=>Object.entries(s.fields).filter(([f])=>f!==s.scope).flatMap(([f,t])=>t==="geo"?[`${f}_lat`,`${f}_lng`]:[f]),readable=s=>["id","version","created_at","updated_at","author_id",...s.publishing?["status","published_at"]:[],...declaredCols(s)],starCols2=s=>declaredCols(s);function param$(c,spec){let key=JSON.stringify(spec),n=c.keys.get(key);return n||(c.binds.push(spec),n=c.binds.length,c.keys.set(key,n)),param(n)}function term(c,a,t){if(t[1]==="in"){let value3=t[2];if(value3.k!=="user"||!c.lower.anyOf)throw new SqlRefusal("SQL_UNSUPPORTED","User scope needs native set lowering.");let kept=c.lower.anyOf(ref(a,t[0]),param$(c,value3),value3.type);return value3.scope?{Raw:{parts:[`/*s:${value3.field}*/`,kept,"/*|*/",or(structuredClone(kept),op("=",num(1),num(1))),"/*;*/"]}}:kept}if(t[1]==="parent"){let[column2,,value3,parent]=t,alias=a==="_mantle_parent"?"_mantle_parent_":"_mantle_parent",exists={SubLink:{subLinkType:"EXISTS_SUBLINK",subselect:{SelectStmt:{targetList:[target(num(1))],fromClause:[{RangeVar:{relname:parent.table,alias:{aliasname:alias},inh:!0,relpersistence:"p",mantle:"system"}}],whereClause:and(op("=",ref(alias,column2),ref(a,column2)),...parent.scope?[op("=",ref(alias,parent.scope[0]),ref(a,parent.scope[1]))]:[],...parent.terms.map(t2=>term(c,alias,t2))),limitOption:"LIMIT_OPTION_DEFAULT",op:"SETOP_NONE"}}}};return parent.admin?or(op("=",param$(c,value3),num(1)),exists):exists}let[column,kind,v,published]=t,value2=v.k==="const"?{A_Const:{sval:{sval:v.value}}}:param$(c,v);return kind==="admin"?or(op("=",ref(a,column),{A_Const:{sval:{sval:published}}}),op("=",value2,num(1))):kind==="ttl"?or({NullTest:{arg:ref(a,column),nulltesttype:"IS_NULL"}},op(">",ref(a,column),value2)):op("=",ref(a,column),value2)}function holds(c,a,table,[,,when]){let rename=v=>Array.isArray(v)?v.map(rename):!v||typeof v!="object"?v:v.ColumnRef?.fields?.length===2&&v.ColumnRef.fields[0].String?.sval===table?ref(a,v.ColumnRef.fields[1].String.sval):Object.fromEntries(Object.entries(v).map(([k,x])=>[k,rename(x)]));return tx(a===table?structuredClone(when):rename(when),c)}var locked=(c,a,table,l)=>({BoolExpr:{boolop:"NOT_EXPR",args:[holds(c,a,table,l)]}});function probe(c,rel,a,where,locks){let table=String(rel.relname).toLowerCase(),name4=v=>({A_Const:{sval:{sval:v}}}),cases=locks.map(l=>({CaseWhen:{expr:{BooleanTest:{arg:holds(c,a,table,l),booltesttype:"IS_NOT_FALSE"}},result:name4(l[0])}}));return{SelectStmt:{targetList:[target({CaseExpr:{args:cases}},"lock")],fromClause:[{RangeVar:{relname:rel.relname,...rel.alias?{alias:rel.alias}:{},inh:!0,relpersistence:"p",mantle:"system"}}],whereClause:and(where&&structuredClone(where),visible(c.schemas[table],a,c,table)),limitOption:"LIMIT_OPTION_DEFAULT",op:"SETOP_NONE"}}}function visible(s,a,c,table){if(c.unsafeNoVisibility)return;let r=table!==void 0&&c.mode!=="trusted"?c.restrict?.[table.toLowerCase()]:void 0,extra=r?[...r.owner?[[r.owner,"eq",{k:"uid"}]]:[],...r.terms.map(u=>userScopeTerm(u))]:[];return and(...[...rowPolicy(s,c.mode,c.schemas),...extra].map(t=>term(c,a,t)))}function refs(s,c,a,value2,child2,set=!1){if(c.mode==="trusted"||c.uncheckedRefs)return;let qualify=v=>Array.isArray(v)?v.map(qualify):!v||typeof v!="object"||v.SubLink?v:v.ColumnRef?.fields?.length===1&&v.ColumnRef.fields[0].String?ref(a,v.ColumnRef.fields[0].String.sval):Object.fromEntries(Object.entries(v).map(([k,x])=>[k,qualify(x)]));return and(...refChecks(s,c.schemas).flatMap(r=>{let v=value2(r.column);if(set&&v&&JSON.stringify(v).includes('"SubLink"'))throw new SqlRefusal("USER_FIELD_POSITION",`SET '${r.column}', a reference to a scoped Schema, takes no subquery for callers; read the value first or use trusted mode.`);return v?[or({NullTest:{arg:qualify(v),nulltesttype:"IS_NULL"}},{SubLink:{subLinkType:"EXISTS_SUBLINK",subselect:{SelectStmt:{targetList:[target(num(1))],fromClause:[{RangeVar:{relname:r.table,alias:{aliasname:"_mantle_ref"},inh:!0,relpersistence:"p",mantle:"system"}}],whereClause:and(op("=",ref("_mantle_ref",r.field),qualify(v)),...r.same.map(([parent,column])=>op("=",ref("_mantle_ref",parent),child2(column))),...r.terms.map(t=>term(c,"_mantle_ref",t))),limitOption:"LIMIT_OPTION_DEFAULT",op:"SETOP_NONE"}}}})]:[]}))}var sets=(w,c)=>w.sets.map(([column,v])=>target(v==="bump"?op("+",ref(column),num(1)):param$(c,v),column));function positionOf(c){switch(c.edge){case"JoinExpr.larg":return"join.left";case"JoinExpr.rarg":return"join.right";case"SelectStmt.fromClause":{let i=c.sel.at(-1);return i.hasWindow?"window":i.hasJsonEach?"json_each":i.container}}throw new SqlRefusal("SQL_RELATION",`internal: a relation reached through ${c.edge}, which has no position: refused (fail closed)`)}function wrap(rv,c){if(rv.mantle==="cte"){if(!c.ctes.some(m=>m.has(rv.relname)))throw new SqlRefusal("SQL_RELATION",`${rv.relname}: a cte reference is not defined in scope`);return{RangeVar:rv}}let s=c.schemas[String(rv.relname).toLowerCase()];if(!s)throw new SqlRefusal("SQL_RELATION",`${rv.relname} is not a declared Schema`);if(rv.mantle==="system")return{RangeVar:rv};if(rv.mantle!=="table")throw new SqlRefusal("SQL_RELATION",`${rv.relname}: a relation that is neither a Schema nor a CTE`);let position=positionOf(c);c.seen?.add(position);let a=rv.alias?.aliasname??rv.relname,targets=readable(s).map(f=>target(ref(f)));return targets.push(...c.lower.columns(s)),{RangeSubselect:{alias:{aliasname:a},subquery:{SelectStmt:{targetList:targets,fromClause:[{RangeVar:{relname:rv.relname,inh:!0,relpersistence:"p",mantle:"system"}}],whereClause:visible(s,rv.relname,c,rv.relname),limitOption:"LIMIT_OPTION_DEFAULT",op:"SETOP_NONE"}}}}}function relsOf(f,out=[]){return f&&(f.JoinExpr?(relsOf(f.JoinExpr.larg,out),relsOf(f.JoinExpr.rarg,out)):out.push(f)),out}var hasFunc=(v,pred)=>Array.isArray(v)?v.some(x=>hasFunc(x,pred)):!v||typeof v!="object"?!1:v.FuncCall&&pred(v.FuncCall.funcname.map(x=>x.String.sval).join(".").replace(/^pg_catalog\./,""),v.FuncCall)?!0:v.SubLink?!1:Object.values(v).some(x=>hasFunc(x,pred));function lookupAlias(c,alias){for(let info of[...c.sel].reverse()){let name4=info.scope.get(alias);if(name4)return{schema:name4,def:c.schemas[name4],searchQuery:info.searchQ.get(alias)}}throw new SqlRefusal("SQL_FUNCTION",`${alias} is not a Schema in scope: mantle.search() and mantle.near() take a Schema alias`)}var scopeOf=c=>({inputs:c.inputs,param:spec=>param$(c,spec),tx:node=>tx(node,c),alias:name4=>lookupAlias(c,name4),seen:p=>c.seen?.add(p)});function lowerFunc(n,c){let f=n.funcname.map(x=>x.String.sval).join(".").replace(/^pg_catalog\./,"");switch(f){case"auth.uid":return param$(c,{k:"uid"});case"auth.role":throw new SqlRefusal("AUTH_ROLE_REMOVED","auth.role() is removed; decide per-target permission in the application's authorize(target, caller) seam.");case"now":{let p=param$(c,{k:"now"});return c.lower.system?.(p,"timestamptz")??p}}return c.lower.func(f,n,scopeOf(c))??c.lower.call(deep(n,c,"FuncCall"))}var H={A_Expr:(n,c)=>({A_Expr:deep(n,c,"A_Expr")}),ColumnRef:(n,c)=>{let f=n.fields.map(x=>x.String?.sval);if(f[0]!=="input"||f.length!==2)return{ColumnRef:n};let type=c.inputs[f[1]];return c.lower.input(param$(c,{k:"input",name:f[1],type}),type)},FuncCall:(n,c)=>lowerFunc(n,c),SubLink:(n,c)=>c.lower.sublink(deep(n,c,"SubLink")),TypeCast:(n,c)=>c.lower.cast(n,scopeOf(c)),RangeVar:(n,c)=>wrap(n,c),SelectStmt:(n,c)=>select(n,c),UpdateStmt:(n,c)=>update(n,c),DeleteStmt:(n,c)=>del(n,c),InsertStmt:(n,c)=>insert(n,c)};function deep(n,c,type){let out={};for(let[k,v]of Object.entries(n)){if(k==="relation"){out[k]=v;continue}let saved={edge:c.edge,embed:c.embed};c.edge=`${type}.${k}`,c.edge==="SubLink.subselect"?c.embed="sublink":c.edge==="RangeSubselect.subquery"?c.embed="from-subquery":c.edge==="InsertStmt.selectStmt"?c.embed="insert-select":c.edge==="CommonTableExpr.ctequery"&&(c.embed="cte"),c.edge==="SelectStmt.larg"||c.edge==="SelectStmt.rarg"?(c.embed=c.edge==="SelectStmt.larg"?"setop.left":"setop.right",out[k]=select(v,c).SelectStmt):out[k]=tx(v,c),c.edge=saved.edge,c.embed=saved.embed}return out}function tx(v,c){if(Array.isArray(v))return v.map(x=>tx(x,c));if(!v||typeof v!="object")return v;let ks=Object.keys(v),k0=ks[0];if(ks.length===1&&H[k0])return H[k0](v[k0],c);if(ks.length===1&&/^[A-Z]/.test(k0)){let body=v[k0];return{[k0]:body&&typeof body=="object"&&!Array.isArray(body)?deep(body,c,k0):body}}return deep(v,c,"bare")}var outputsOf=sel=>sel.op&&sel.op!=="SETOP_NONE"?outputsOf(sel.larg):(sel.targetList??[]).map(t=>t.ResTarget.name??t.ResTarget.val?.ColumnRef?.fields?.at(-1)?.String?.sval),cteOutputs=cte=>cte.aliascolnames?.length?cte.aliascolnames.map(x=>x.String.sval):outputsOf(cte.ctequery.SelectStmt);function select(n,c){let w=n.withClause,defs=(w?.ctes??[]).map(x=>x.CommonTableExpr),scope=list=>new Map(list.map(d=>[d.ctename,d])),within=(m,f)=>{c.ctes.push(m);try{return f()}finally{c.ctes.pop()}},withClause=w&&{...w,ctes:defs.map((d,j)=>within(scope(w.recursive?defs:defs.slice(0,j)),()=>tx({CommonTableExpr:d},c)))};return within(scope(defs),()=>{let out=selectIn(w?{...n,withClause:void 0}:n,c);return withClause&&(out.SelectStmt.withClause=withClause),out})}function selectIn(n,c){let rels=relsOf(n.fromClause?.[0]),info={container:c.embed==="top"?"from":c.embed,hasWindow:hasFunc(n.targetList,(_f,fc)=>!!fc.over),hasJsonEach:(n.fromClause??[]).some(f=>f.RangeFunction),scope:new Map(rels.filter(r=>r.RangeVar).map(r=>[r.RangeVar.alias?.aliasname??r.RangeVar.relname,r.RangeVar.relname])),searchQ:new Map},findSearch=v=>{if(Array.isArray(v))return v.forEach(findSearch);if(!v||typeof v!="object")return;let f=v.FuncCall;f&&f.funcname.map(x=>x.String.sval).join(".")==="mantle.search"&&info.searchQ.set(f.args[0].ColumnRef.fields[0].String.sval,f.args[1]),Object.values(v).forEach(findSearch)};findSearch(n.whereClause),c.sel.push(info);let saved=c.embed,out=deep(expandStar(n,info,c),c,"SelectStmt");c.embed=saved,c.sel.pop();let first=rels[0],firstAlias=first?.RangeVar?first.RangeVar.alias?.aliasname??first.RangeVar.relname:first?.RangeSubselect?.alias?.aliasname,aggregate=!n.groupClause&&hasFunc(n.targetList,(f,fc)=>AGGREGATES.has(f)&&!fc.over);if(out.sortClause&&!aggregate){let dir=c.nativeOrder&&out.sortClause.at(-1)?.SortBy.sortby_dir==="SORTBY_DESC"?"SORTBY_DESC":"SORTBY_DEFAULT",have=new Set(out.sortClause.map(k=>{let node=k.SortBy.node,fields=node.ColumnRef?.fields,alias=fields?.length===1&&fields[0].String?.sval==="id"&&out.targetList.find(t=>t.ResTarget.name==="id"),actual=(alias?alias.ResTarget.val:node).ColumnRef?.fields;return JSON.stringify(!n.groupClause&&firstAlias&&actual?.at(-1)?.String?.sval==="id"&&(actual.length===1||actual.length===2&&actual[0].String?.sval===firstAlias)?ref(firstAlias,"id"):node)}));if(n.groupClause)out.sortClause=[...out.sortClause,...tx(n.groupClause,c).filter(g=>!have.has(JSON.stringify(g))).map(g=>sort(g,dir))];else if(firstAlias||first?.RangeFunction){if(first.RangeSubselect&&!outputsOf(first.RangeSubselect.subquery.SelectStmt).includes("id"))throw new SqlRefusal("SQL_SHAPE",`ordering ${firstAlias}, a subquery in FROM, needs the subquery to output id`);let cte=first.RangeVar?.mantle==="cte"?[...c.ctes].reverse().find(m=>m.has(first.RangeVar.relname))?.get(first.RangeVar.relname):void 0;if(cte&&!cteOutputs(cte).includes("id"))throw new SqlRefusal("SQL_SHAPE",`ordering ${firstAlias}, a CTE, needs the CTE to output id`);let extra=firstAlias?[ref(firstAlias,"id")]:[];for(let f of n.fromClause??[])for(let r of relsOf(f)){let je=r.RangeFunction;if(!je)continue;let fname2=je.functions[0]?.List?.items?.[0]?.FuncCall?.funcname?.at(-1)?.String?.sval;if(fname2==="json_each"){je.alias?extra.push(ref(je.alias.aliasname,"id")):r===first&&rels.length===1&&n.fromClause.length===1&&extra.push(ref("json_each","id"));continue}if(!je.alias||!je.ordinality)throw new SqlRefusal("SQL_SHAPE",`ordering a row source (${fname2}) needs an alias and WITH ORDINALITY: write ${fname2}(...) WITH ORDINALITY AS j(value, n)`);let own=String(fname2).startsWith("jsonb_each")?2:1,names=je.alias.colnames??[];extra.push(ref(je.alias.aliasname,names.length>own?names.at(-1).String.sval:"ordinality"))}out.sortClause=[...out.sortClause,...extra.filter(e=>!have.has(JSON.stringify(e))).map(e=>sort(e,dir))]}}if(firstAlias&&!n.groupClause)for(let t of out.targetList??[]){let fc=t.ResTarget.val?.FuncCall;fc?.over&&fc.funcname.at(-1).String.sval==="row_number"&&(fc.over.orderClause=[...fc.over.orderClause??[],sort(ref(firstAlias,"id"))])}return{SelectStmt:out}}function expandStar(n,info,c){if(!n.targetList?.some(t=>t.ResTarget.val?.ColumnRef?.fields?.at(-1)?.A_Star))return n;let list=n.targetList.flatMap(t=>{let f=t.ResTarget.val?.ColumnRef?.fields;if(!f?.at(-1)?.A_Star)return[t];if(f.length!==2&&(n.fromClause??[]).some(x=>relsOf(x).some(r=>!r.RangeVar||!c.schemas[String(r.RangeVar.relname).toLowerCase()]||r.RangeVar.mantle!=="table")))throw new SqlRefusal("SQL_SHAPE","SELECT * reads a subquery, json_each or a CTE: name the columns");return(f.length===2?[f[0].String.sval]:[...info.scope.keys()]).flatMap(a=>{let sc=info.scope.get(a);if(!sc||!c.schemas[sc])throw new SqlRefusal("SQL_SHAPE",`${a}.* needs a Schema alias`);return starCols2(c.schemas[sc]).map(cn=>target(ref(a,cn)))})});return{...n,targetList:list}}var alias$=rel=>rel.alias?.aliasname??rel.relname;function returning(rc,s,c,target2){let own=f=>!!f?.at(-1)?.A_Star&&(f.length===1||f[0]?.String?.sval===target2),exprs=(rc?.exprs??[]).flatMap(e=>own(e.ResTarget.val?.ColumnRef?.fields)?starCols2(s).map(f=>target(ref(f))):[e]);return c.hooked&&exprs.push(...readable(s).map(f=>target(ref(f),`${HOOK_PREFIX}${f}`))),exprs.length?{exprs}:void 0}function dmlScope(rel,c){c.sel.push({container:"from",hasWindow:!1,hasJsonEach:!1,scope:new Map([[alias$(rel),rel.relname]]),searchQ:new Map})}function update(n,c){let s=c.schemas[String(n.relation.relname).toLowerCase()],a=alias$(n.relation);c.seen?.add("update-target"),dmlScope(n.relation,c);let columns2=protectedColumns(s,c.mode!=="trusted"?c.restrict?.[String(n.relation.relname).toLowerCase()]:void 0);if(n.targetList.some(target2=>columns2.includes(String(target2.ResTarget.name).toLowerCase())))throw new SqlRefusal("USER_FIELD_POSITION","The scoped column is never writable through SET.");let out=deep(n,c,"UpdateStmt");c.sel.pop();let w=writePolicy(s,"update",{status:c.status,lock:c.lockVersion,trusted:c.mode==="trusted"}),checked=refs(s,c,a,column=>out.targetList.find(t=>String(t.ResTarget.name).toLowerCase()===column)?.ResTarget.val,column=>ref(a,column),!0);return out.targetList.push(...sets(w,c)),w.locks.length&&(c.probe=probe(c,n.relation,a,out.whereClause,w.locks)),out.whereClause=and(out.whereClause,visible(s,a,c,String(n.relation.relname)),w.lock&&term(c,a,w.lock),checked,...w.locks.map(l=>locked(c,a,String(n.relation.relname).toLowerCase(),l))),out.returningClause=returning(out.returningClause,s,c,alias$(n.relation)),{UpdateStmt:out}}function del(n,c){let s=c.schemas[String(n.relation.relname).toLowerCase()],a=alias$(n.relation);c.seen?.add("delete-target"),dmlScope(n.relation,c);let out=deep(n,c,"DeleteStmt");c.sel.pop();let w=writePolicy(s,"delete",{lock:c.lockVersion,trusted:c.mode==="trusted"});return w.locks.length&&(c.probe=probe(c,n.relation,a,out.whereClause,w.locks)),out.whereClause=and(out.whereClause,visible(s,a,c,String(n.relation.relname)),w.lock&&term(c,a,w.lock),...w.locks.map(l=>locked(c,a,String(n.relation.relname).toLowerCase(),l))),out.returningClause=returning(out.returningClause,s,c,alias$(n.relation)),{DeleteStmt:out}}function insert(n0,c){let table=String(n0.relation.relname).toLowerCase(),s=c.schemas[table],caller=c.mode!=="trusted",columns2=protectedColumns(s,caller?c.restrict?.[table]:void 0);if(n0.onConflictClause?.action==="ONCONFLICT_UPDATE"&&n0.onConflictClause.targetList.some(target2=>columns2.includes(String(target2.ResTarget.name).toLowerCase())))throw new SqlRefusal("USER_FIELD_POSITION","The scoped column is never writable through SET.");let owner=caller?c.restrict?.[table]?.owner:void 0,scoped=caller?s.userScopes??[]:[],n=scoped.length?structuredClone(n0):n0,rows=n.selectStmt?.SelectStmt?.valuesLists;if(caller&&(scoped.length&&!rows||columns2.some(column=>column!==owner&&!scoped.some(u=>u.column===column))))throw new SqlRefusal("USER_FIELD_POSITION","Procedure INSERT/upsert into a restricted Schema, or INSERT ... SELECT into a field-scoped one, requires trusted mode; use its scoped Store.");let scopeFills=[],checked=[];for(let u of scoped){let at2=n.cols.flatMap((r,i)=>String(r.ResTarget.name).toLowerCase()===u.column?[i]:[]),type=s.fields[u.column],spec={k:"scoped",column:u.column,field:u.field,type:u.type};if(!at2.length){scopeFills.push([u.column,spec]);continue}let refuse3=why=>{throw new SqlRefusal("USER_FIELD_POSITION",`The scope column '${u.column}' ${why}`)};at2.length>1&&refuse3("is listed twice."),rows.forEach((row,r)=>{let item=row.List.items[at2[0]],f=item?.ColumnRef?.fields?.map(x=>x.String?.sval),k=item?.A_Const;f?.[0]==="input"&&f.length===2?(c.inputs[f[1]]!==type&&refuse3(`is ${type}; input '${f[1]}' must be declared with the same type.`),row.List.items[at2[0]]=param$(c,{...spec,name:f[1]})):type==="text"&&k?.sval?row.List.items[at2[0]]=param$(c,{...spec,value:k.sval.sval}):type!=="text"&&k&&"ival"in k?row.List.items[at2[0]]=param$(c,{...spec,value:k.ival.ival??0}):refuse3(`takes an input of type ${type}, a ${type==="text"?"string":"integer"} literal, or is omitted (filled from the caller).`),checked.push([r,at2[0],type])})}c.seen?.add("insert-target");let out=deep(n,c,"InsertStmt");for(let[r,i,type]of checked){let items2=out.selectStmt.SelectStmt.valuesLists[r].List.items;items2[i]=c.lower.input(items2[i],type)}let w=writePolicy(s,"insert",{idGiven:(x=>n.cols.some(r=>r.ResTarget.name===x))("id")}),fill=w.fills.map(([name4,v])=>[name4,v==="newId"?c.lower.newId():param$(c,v)]).concat(scopeFills.map(([name4,v])=>[name4,param$(c,v)]));out.cols=[...out.cols,...fill.map(([name4])=>({ResTarget:{name:name4}}))];let empty=!n.cols.length,items=out.selectStmt?.SelectStmt?.valuesLists?.[0]?.List.items,at=column=>n.cols.findIndex(r=>String(r.ResTarget.name).toLowerCase()===column);if(!items&&caller&&refChecks(s,c.schemas).some(r=>at(r.column)>=0))throw new SqlRefusal("USER_FIELD_POSITION","Procedure INSERT ... SELECT that writes a reference to a scoped Schema requires trusted mode; use INSERT ... VALUES.");let parents=items&&refs(s,c,String(n.relation.relname),column=>at(column)<0?void 0:structuredClone(items[at(column)]),column=>structuredClone(at(column)<0?fill.find(([name4])=>name4===column)[1]:items[at(column)]));out.selectStmt={SelectStmt:{targetList:[...empty?[]:[target({ColumnRef:{fields:[S("_v"),{A_Star:{}}]}})],...fill.map(([,v])=>target(v))],...empty?{}:{fromClause:[{RangeSubselect:{subquery:out.selectStmt,alias:{aliasname:"_v"}}}]},whereClause:parents??{A_Const:{boolval:{boolval:!0}}},limitOption:"LIMIT_OPTION_DEFAULT",op:"SETOP_NONE"}};let oc=out.onConflictClause;if(oc){let named2=(oc.infer?.indexElems??[]).some(e=>String(e.IndexElem?.name??"").toLowerCase()===s.scope);if(s.scope&&oc.infer&&!named2&&oc.infer.indexElems.unshift({IndexElem:{name:s.scope,ordering:"SORTBY_DEFAULT",nulls_ordering:"SORTBY_NULLS_DEFAULT"}}),oc.infer&&(s.userScopes??[]).forEach((u,i)=>{(oc.infer.indexElems??[]).some(e=>String(e.IndexElem?.name??"").toLowerCase()===u.column)||oc.infer.indexElems.splice((s.scope?1:0)+i,0,{IndexElem:{name:u.column,ordering:"SORTBY_DEFAULT",nulls_ordering:"SORTBY_NULLS_DEFAULT"}})}),oc.action==="ONCONFLICT_UPDATE"){c.seen?.add("conflict-update"),oc.targetList.push(...sets(w,c));let t=n.relation.relname,setRef=refs(s,c,t,column=>oc.targetList.find(x=>String(x.ResTarget.name).toLowerCase()===column)?.ResTarget.val,column=>ref(t,column),!0),locks=writePolicy(s,"update",{trusted:c.mode==="trusted"}).locks.map(l=>locked(c,alias$(n.relation),table,l));oc.whereClause=and(oc.whereClause,visible(s,t,c,t),setRef,...locks)}}return out.returningClause=returning(out.returningClause,s,c,alias$(n.relation)),{InsertStmt:out}}function renumber(ast,binds){let used=[],at=new Map,walk3=v=>{if(!(!v||typeof v!="object")){if(v.ParamRef){let n=v.ParamRef.number;at.has(n)||(used.push(binds[n-1]),at.set(n,used.length)),v.ParamRef.number=at.get(n);return}Object.values(v).forEach(walk3)}};return walk3(ast),{ast,binds:used}}function lockCondition(when,schemas,lower){let c={schemas,inputs:{},mode:"trusted",lower,hooked:!1,binds:[],keys:new Map,edge:"",embed:"top",sel:[],ctes:[]},out=tx(structuredClone(when),c);if(c.binds.length)throw new SqlRefusal("SQL_SHAPE","a lock binds no value");return out}function applyPolicy(stmt,opts){let t=Object.keys(stmt)[0],verb=t==="InsertStmt"?"insert":t==="UpdateStmt"?"update":t==="DeleteStmt"?"delete":void 0,schema=verb?String(stmt[t].relation.relname).toLowerCase():void 0,publish=opts.status==="published",hooked=!!schema&&!!opts.returning?.has(`${schema}.${publish?"publish":verb}`),c={...opts,hooked,binds:[],keys:new Map,edge:"",embed:"top",sel:[],ctes:[]};return{ast:tx(stmt,c),binds:c.binds,kind:classify(stmt),schema,verb,hooked,publish,...c.probe?{probe:renumber(c.probe,c.binds)}:{}}}function compileProgram(stmts,ctx){let diagnostics=ctx.dialect.check({grammar:180004,stmts},{schemas:ctx.schemas,...ctx.columns?{columns:ctx.columns}:{},inputs:ctx.inputs,kind:ctx.kind,public:ctx.mode==="public"});if(diagnostics.length)throw new DiagnosticError(diagnostics.map(d=>runtimeDiagnostic({code:"INPUT_VALIDATION_FAILED",severity:"error",path:"store",message:`${d.code}: ${d.message}`})));let opts={restrict:ctx.restrict,schemas:ctx.schemas,inputs:ctx.inputs,mode:ctx.mode,lockVersion:ctx.lockVersion,returning:ctx.returning,seen:ctx.seen,unsafeNoVisibility:ctx.unsafeNoVisibility,uncheckedRefs:ctx.uncheckedRefs,lower:ctx.dialect.lowering,nativeOrder:ctx.dialect.nativeOrder};return stmts.map((stmt,i)=>{let c=applyPolicy(stmt,{...opts,status:ctx.statuses?.[i]});if(c.kind==="set"&&c.schema&&ctx.schemas[c.schema]?.publishing)throw new DiagnosticError(runtimeDiagnostic({code:"INPUT_VALIDATION_FAILED",severity:"error",path:"store",message:`SQL_SHAPE: a set op on ${c.schema} is refused: its lifecycle is publishing, so published entries are protected and writes take row ops only`}));return c})}var refuse=message2=>new DiagnosticError(runtimeDiagnostic({code:"INPUT_VALIDATION_FAILED",severity:"error",path:"store",message:message2})),refuseOutput=name4=>{throw refuse(`SQL_SHAPE: the View has no output named '${name4}'`)},outName=t=>t.ResTarget.name??t.ResTarget.val?.ColumnRef?.fields?.at(-1)?.String?.sval,nativeNotNull=(s,column)=>column==="id"||column==="version"||column==="created_at"||column==="updated_at"||column===s.scope||!!s.publishing&&column==="status";function fromItems(items,nullable=!1){return(items??[]).flatMap(n=>{let j=n.JoinExpr;return j?[...fromItems([j.larg],nullable||j.jointype==="JOIN_RIGHT"||j.jointype==="JOIN_FULL"),...fromItems([j.rarg],nullable||j.jointype==="JOIN_LEFT"||j.jointype==="JOIN_FULL")]:[{node:n,nullable}]})}function notNullIn(schemas,sel,qual,name4){if(!sel||sel.op!=="SETOP_NONE"||sel.withClause)return!1;let items=fromItems(sel.fromClause),alias=n=>n.RangeVar?n.RangeVar.alias?.aliasname??n.RangeVar.relname:n.RangeSubselect?.alias?.aliasname??n.RangeFunction?.alias?.aliasname,hit=qual===void 0?items:items.filter(i=>alias(i.node)===qual);if(hit.length!==1||qual===void 0&&items.length!==1||hit[0].nullable)return!1;let{node}=hit[0];if(node.RangeVar){let schema=node.RangeVar.mantle==="system"?schemas[node.RangeVar.relname]:void 0;return!!schema&&nativeNotNull(schema,name4)}let sub=node.RangeSubselect;if(!sub||sub.alias?.colnames?.length||sub.lateral)return!1;let outs=(sub.subquery.SelectStmt?.targetList??[]).filter(t=>(t.ResTarget.name??t.ResTarget.val?.ColumnRef?.fields?.at(-1)?.String?.sval)===name4),f=outs.length===1?outs[0].ResTarget.val?.ColumnRef?.fields:void 0;return!f||f.length>2||f.some(x=>!x.String)?!1:notNullIn(schemas,sub.subquery.SelectStmt,f.length===2?f[0].String.sval:void 0,f.at(-1).String.sval)}function rowComparable(env,keys,notNull){if(!env.dialect.nativeOrder||!keys.length)return!1;let desc=keys[0].SortBy.sortby_dir==="SORTBY_DESC";return keys.every((k,i)=>{let d=k.SortBy.sortby_dir;if(d!=="SORTBY_DEFAULT"&&d!=="SORTBY_ASC"&&d!=="SORTBY_DESC"||d==="SORTBY_DESC"!==desc)return!1;let nulls=k.SortBy.sortby_nulls;return nulls&&nulls!=="SORTBY_NULLS_DEFAULT"&&nulls!==(desc?"SORTBY_NULLS_FIRST":"SORTBY_NULLS_LAST")?!1:notNull[i]})}function pageShape(nkeys,cursor,match){let cursorShape=cursor?`${Array.from({length:nkeys},(_x,i)=>{let v=cursor[i];return v===null?"n":v===void 0?"u":"v"}).join("")}${cursor.length===nkeys?"=":"!"}`:"-",search=match?.search?.text?match.search:void 0;return JSON.stringify([cursorShape,search?.columns??null,(match?.eq??[]).map(e=>e.column)])}function pagedOf(env,c,cursor,match){let opts={cursor,match},sel=structuredClone(c.ast.SelectStmt),keys=sel.sortClause??[];if(opts.cursor&&!keys.length)throw refuse("SQL_SHAPE: this View has no ORDER BY, so it is one page and takes no cursor");let visible2=sel.targetList.map(outName);if(!keys.length&&!opts.match?.search?.text&&!opts.match?.eq?.length)return{ast:{SelectStmt:{...sel,limitCount:{ParamRef:{number:c.binds.length+1}},limitOption:"LIMIT_OPTION_COUNT"}},sources:[{limit:!0}],flat:!0,names:[],nkeys:0};if(visible2.some(n=>!n))throw refuse("SQL_SHAPE: a paged View names every output column");let names=visible2,aliasVal=new Map(sel.targetList.map(t=>[outName(t),t.ResTarget.val])),hidden=keys.map((k,i)=>{let node=k.SortBy.node,f=node.ColumnRef?.fields,position=node.A_Const?.ival?Number(node.A_Const.ival.ival):void 0,val=position!==void 0?sel.targetList[position-1]?.ResTarget.val??refuseOutput(String(position)):f?.length===1&&aliasVal.has(f[0].String.sval)?aliasVal.get(f[0].String.sval):node;return{ResTarget:{name:`_k${i}`,val}}}),desc=k=>k.SortBy.sortby_dir==="SORTBY_DESC",nullsFirst=k=>k.SortBy.sortby_nulls==="SORTBY_NULLS_FIRST"?!0:k.SortBy.sortby_nulls==="SORTBY_NULLS_LAST"?!1:desc(k)===!!env.dialect.nativeOrder,inner=sel.limitCount?{...sel,targetList:[...sel.targetList,...hidden]}:{...sel,targetList:[...sel.targetList,...hidden],sortClause:void 0,limitCount:void 0,limitOption:"LIMIT_OPTION_DEFAULT"},base=c.binds.length,sources=[],param2=source=>(sources.push(source),{ParamRef:{number:base+sources.length}}),col=n=>ref("_p",n),isNull=(n,t)=>({NullTest:{arg:n,nulltesttype:t}}),conditions=[];if(opts.cursor){let cur=opts.cursor,notNull=hidden.map(h=>{let f=h.ResTarget.val?.ColumnRef?.fields;return!!f&&f.length<=2&&f.every(x=>x.String)&¬NullIn(env.schemas,sel,f.length===2?f[0].String.sval:void 0,f.at(-1).String.sval)}),same=j=>cur[j]===null?isNull(col(`_k${j}`),"IS_NULL"):op("=",col(`_k${j}`),param2({cursor:j})),past=(k,i)=>{let at=col(`_k${i}`);if(cur[i]===null)return nullsFirst(k)?isNull(at,"IS_NOT_NULL"):void 0;let beyond=op(desc(k)?"<":">",at,param2({cursor:i}));return notNull[i]||nullsFirst(k)?beyond:{BoolExpr:{boolop:"OR_EXPR",args:[beyond,isNull(at,"IS_NULL")]}}};if(rowComparable(env,keys,notNull)&&cur.length===keys.length&&cur.every(v=>v!=null)){let row=args=>({RowExpr:{args,row_format:"COERCE_IMPLICIT_CAST"}});conditions.push(op(desc(keys[0])?"<":">",row(keys.map((_k,i)=>col(`_k${i}`))),row(cur.map((_v,i)=>param2({cursor:i})))))}else{cur[0]!==null&&cur[0]!==void 0&&(notNull[0]||nullsFirst(keys[0]))&&conditions.push(op(desc(keys[0])?"<=":">=",col("_k0"),param2({cursor:0})));let args=keys.flatMap((k,i)=>{let last=past(k,i);return last?[{BoolExpr:{boolop:"AND_EXPR",args:[...keys.slice(0,i).map((_x,j)=>same(j)),last]}}]:[]});conditions.push(args.length?{BoolExpr:{boolop:"OR_EXPR",args}}:{A_Const:{boolval:{boolval:!1}}})}}let output=name4=>names.find(n=>n===name4)??names.find(n=>n===name4.toLowerCase())??refuseOutput(name4),search=opts.match?.search;search?.text&&conditions.push({BoolExpr:{boolop:"OR_EXPR",args:search.columns.map(c2=>({A_Expr:{kind:"AEXPR_LIKE",name:[{String:{sval:"~~"}}],lexpr:col(output(c2)),rexpr:{FuncCall:{funcname:[{String:{sval:"like_escape"}}],args:[param2({search:!0}),{A_Const:{sval:{sval:"\\"}}}],funcformat:"COERCE_EXPLICIT_CALL"}}}}))}}),(opts.match?.eq??[]).forEach(({column},k)=>conditions.push(op("=",col(output(column)),param2({eq:k}))));let limitCount=param2({limit:!0});return{ast:{SelectStmt:{targetList:[...names.map(n=>({ResTarget:{val:col(n),name:n}})),...keys.map((_k,i)=>({ResTarget:{val:col(`_k${i}`),name:`_k${i}`}}))],fromClause:[{RangeSubselect:{subquery:{SelectStmt:inner},alias:{aliasname:"_p"}}}],whereClause:conditions.length>1?{BoolExpr:{boolop:"AND_EXPR",args:conditions}}:conditions[0],sortClause:keys.map((k,i)=>({SortBy:{node:col(`_k${i}`),sortby_dir:k.SortBy.sortby_dir,sortby_nulls:nullsFirst(k)?"SORTBY_NULLS_FIRST":"SORTBY_NULLS_LAST"}})),limitCount,limitOption:"LIMIT_OPTION_COUNT",op:"SETOP_NONE"}},sources,flat:!1,names,nkeys:keys.length}}var PROCEDURE_MODES=["caller","trusted"],returningClause=ast=>!!ast[Object.keys(ast)[0]]?.returningClause,stmtOf=(c,sql4,print3)=>{let target2=writeTarget(c.ast);return{...c.probe&&print3?{probe:{sql:print3(c.probe.ast),binds:c.probe.binds}}:{},sql:sql4,binds:c.binds,kind:c.kind,...c.schema?{schema:c.schema}:{},...c.verb?{verb:c.verb}:{},...c.hooked?{hooked:!0}:{},...c.publish?{publish:!0}:{},...returningClause(c.ast)?{returns:!0}:{},...target2?{target:target2}:{}}},message=e=>e instanceof Error?e.message.split(`
|
|
6
|
+
`)[0]:String(e),printer=dialect=>dialect.print.bind(dialect);function lowerView(env,p,mode,columns2=schemaColumns(env.schemas),warn,at="",project,pageQuery){let print3=printer(env.dialect),c;try{[c]=compileProgram(p.ir,{dialect:env.dialect,schemas:env.schemas,columns:columns2,inputs:p.inputs,kind:"view",mode,restrict:p.restrict})}catch(e){warn?.(`${at} (${mode}): ${message(e)}`);return}let nkeys=c.ast.SelectStmt.sortClause?.length??0,paged={},pageCompiled=pageQuery?{...c,ast:pageQuery(c.ast)}:c;for(let cursor of[void 0,...nkeys?[Array(nkeys).fill(0)]:[]])try{let pg=pagedOf(env,pageCompiled,cursor,void 0);paged[pageShape(nkeys,cursor,void 0)]={sql:print3(project?.(pg.ast,pg)??pg.ast,env.schemas),sources:pg.sources,...pg.flat?{flat:!0}:{},names:pg.names,nkeys:pg.nkeys}}catch(e){warn?.(`${at} (${mode}, ${cursor?"next page":"first page"}): ${message(e)}`)}return{...stmtOf(c,print3(project?.(c.ast)??c.ast,env.schemas)),nkeys,paged}}function lowerProcedure(env,p,mode,returning2,columns2=schemaColumns(env.schemas),warn,at="",project){try{let print3=printer(env.dialect);return compileProgram(p.ir,{dialect:env.dialect,schemas:env.schemas,columns:columns2,inputs:p.inputs,kind:"procedure",mode,returning:returning2,restrict:p.restrict}).map(c=>stmtOf(c,print3(project?.(c.ast)??c.ast,env.schemas),ast=>print3(ast,env.schemas)))}catch(e){warn?.(`${at} (${mode}): ${message(e)}`);return}}function lowerPlan(plan,dialect,options={}){let warnings=[],warn=m=>warnings.push(m),env={dialect,schemas:plan.schemas},columns2=schemaColumns(plan.schemas),{before,after}=lifecycleHookSets(plan),returning2=before.size||after.size?after:void 0,views=Object.entries(plan.views).flatMap(([name4,v])=>{let modes=v.surface==="public"?["public"]:["caller","trusted"],lowered=Object.fromEntries(modes.flatMap(mode=>{let x=lowerView(env,{inputs:v.inputs,ir:v.stmts,restrict:v.restrict},mode,columns2,warn,`plan#/views/${name4}`,options.project&&((ast,page)=>options.project(ast,"view",name4,page)),options.pageQuery&&(ast=>options.pageQuery(ast,name4)));return x?[[mode,x]]:[]}));return Object.keys(lowered).length?[[name4,lowered]]:[]}),procedures=Object.entries(plan.procedures).flatMap(([name4,proc])=>{if(!("sql"in proc.handler))return[];let{inputs}=proc,ir=proc.handler.sql.stmts,steps=proc.handler.steps??[],lowered=Object.fromEntries(PROCEDURE_MODES.flatMap(mode=>{let x=lowerProcedure(env,{inputs,ir,restrict:proc.restrict},proc.trustedOnly?"trusted":mode,returning2,columns2,warn,`plan#/procedures/${name4}`,options.project&&(ast=>options.project(ast,"procedure",name4)));return x?[[mode,x.map((s,i)=>steps[i]?.onNoRows?{...s,onNoRows:steps[i].onNoRows}:s)]]:[]}));return Object.keys(lowered).length?[[name4,lowered]]:[]});return{lowered:{mantle:MANTLE_VERSION,dialect:{name:dialect.name,version:dialect.version,key:dialect.lowerKey??""},views:Object.fromEntries(views),procedures:Object.fromEntries(procedures)},warnings}}var US_PER_DAY=864e8;function sqliteType(type){if(parseNumeric(type))return"integer";switch(type){case"text":case"json":case"geo":return"text";case"int4":case"int8":case"integer":case"bool":case"timestamptz":case"date":return"integer";case"float8":case"real":return"real"}throw new SqlRefusal("SQL_TYPE",`unknown type ${type}`)}function encodeNumeric(v,p,s){let str2=typeof v=="number"?v.toString():v.trim(),m=/^(-?)(\d+)(?:\.(\d+))?$/.exec(str2);if(!m)throw new SqlRefusal("SQL_TYPE",`${str2} is not a decimal number`);let frac=m[3]??"";if(frac.length>s)throw new SqlRefusal("SQL_TYPE",`${str2} has more than ${s} fractional digits`);let digits=m[2]+frac.padEnd(s,"0");if(digits.replace(/^0+/,"").length>p)throw new SqlRefusal("SQL_TYPE",`${str2} does not fit numeric(${p}, ${s})`);let n=Number(digits);return m[1]?-n:n}function decodeNumeric(n,s){let neg=n<0,d=Math.abs(n).toString().padStart(s+1,"0"),out=s?`${d.slice(0,-s)}.${d.slice(-s)}`:d;return neg?`-${out}`:out}function encodeTimestamptz(v){if(v instanceof Date)return v.getTime()*1e3;if(typeof v=="number"){if(!Number.isSafeInteger(v))throw new SqlRefusal("SQL_TYPE",`${v} is not a whole number of microseconds within 2^53`);return v}let m=/^(\d{4}-\d\d-\d\d)[T ](\d\d:\d\d(?::\d\d)?)(?:\.(\d{1,6}))?(Z|[+-]\d\d(?::?\d\d)?)$/.exec(v.trim());if(!m)throw new SqlRefusal("SQL_TYPE",`'${v}' is not a timestamp with an explicit offset`);let[,day,time,fraction,offset]=m,frac=(fraction??"").padEnd(6,"0"),zone=offset==="Z"?"Z":offset.length===3?`${offset}:00`:offset.includes(":")?offset:`${offset.slice(0,3)}:${offset.slice(3)}`,secs=Date.parse(`${day}T${time.length===5?time+":00":time}${zone}`);encodeDate(day);let micros=secs*1e3+Number(frac);if(Number.isNaN(secs)||!Number.isSafeInteger(micros))throw new SqlRefusal("SQL_TYPE",`'${v}' is not a valid timestamp`);return micros}function decodeTimestamptz(us){let ms=Math.floor(us/1e3),rest=us-ms*1e3;return new Date(ms).toISOString().replace("Z",String(rest).padStart(3,"0")+"Z")}function encodeDate(v){let m=/^(\d{4})-(\d\d)-(\d\d)$/.exec(typeof v=="string"?v:v.toISOString().slice(0,10));if(!m)throw new SqlRefusal("SQL_TYPE",`'${v}' is not a date`);let[,y,mo,d]=m,dt=new Date(0);dt.setUTCFullYear(+y,+mo-1,+d);let days=dt.getTime()/(US_PER_DAY/1e3);if(dt.getUTCDate()!==+d)throw new SqlRefusal("SQL_TYPE",`'${v}' is not a valid date`);return days}var decodeDate=days=>new Date(days*864e5).toISOString().slice(0,10);var fn=(f,...args)=>({FuncCall:{funcname:[S(f)],args,funcformat:"COERCE_EXPLICIT_CALL"}}),cast=(x,t)=>({TypeCast:{arg:x,typeName:{names:[S(t)],typemod:-1}}}),clone=x=>structuredClone(x),TOKEN=/"(?:[^"]|"")*"|'(?:[^']|'')*'|__\w+/g;function sql(text,subst={}){let parts=[],last=0;for(let m of text.matchAll(TOKEN)){if(!m[0].startsWith("__"))continue;let node=subst[m[0]];if(!node)throw new Error(`lowering template names ${m[0]} but was not given it`);m.index>last&&parts.push(text.slice(last,m.index)),parts.push("(",clone(node),")"),last=m.index+m[0].length}return last<text.length&&parts.push(text.slice(last)),{Raw:{parts}}}var q=id=>`"${id.replace(/"/g,'""')}"`,OFF=x=>`coalesce((SELECT offset_us FROM _mantle_tz WHERE from_us <= ${x} ORDER BY from_us DESC LIMIT 1), 0)`,FD=(a,b)=>`((${a} - ((${a} % ${b}) + ${b}) % ${b}) / ${b})`,LOCAL=`(__ts + ${OFF("__ts")})`,DAY=864e8,TRUNC={hour:`(${FD(LOCAL,36e8)} * 3600000000)`,day:`(${FD(LOCAL,DAY)} * ${DAY})`,week:`((${FD(LOCAL,DAY)} - (((${FD(LOCAL,DAY)} + 3) % 7 + 7) % 7)) * ${DAY})`,month:`(unixepoch(strftime('%Y-%m-01 00:00:00', ${FD(LOCAL,1e6)}, 'unixepoch')) * 1000000)`,year:`(unixepoch(strftime('%Y-01-01 00:00:00', ${FD(LOCAL,1e6)}, 'unixepoch')) * 1000000)`},EXTRACT={year:"%Y",month:"%m",day:"%d",hour:"%H",dow:"%w"},HAV=(lat1,lng1)=>`(2 * 6371008.8 * asin(min(1.0, sqrt(sin(radians(__lat - ${lat1}) / 2) * sin(radians(__lat - ${lat1}) / 2) + cos(radians(${lat1})) * cos(radians(__lat)) * sin(radians(__lng - ${lng1}) / 2) * sin(radians(__lng - ${lng1}) / 2)))))`,strConst=n=>n?.A_Const?.sval?.sval,argOf=(n,scope)=>{let k=n.ColumnRef?.fields?.length===2?n.ColumnRef.fields[1].String.sval:void 0;return k?{input:k,type:scope.inputs[k]}:{const:Number(n.A_Const?.ival?.ival??n.A_Const?.fval?.fval)}};function lowerFunc2(f,n,scope){let args=n.args??[];switch(f){case"date_trunc":{let ts=scope.tx(args[1]);return sql(`(${TRUNC[strConst(args[0])]}) - ${OFF(`(${TRUNC[strConst(args[0])]}) - ${OFF("__ts")}`)}`,{__ts:ts})}case"extract":{let ts=scope.tx(args[1]);return sql(`CAST(strftime('${EXTRACT[strConst(args[0])]}', ${FD(LOCAL,1e6)}, 'unixepoch') AS INTEGER)`,{__ts:ts})}case"mantle.search":case"mantle.search_rank":{let alias=args[0].ColumnRef.fields[0].String.sval,{schema,def,searchQuery}=scope.alias(alias);if(!def.search?.length)throw new SqlRefusal("SQL_FUNCTION",`${schema} declares no search fields`);scope.seen("search");let fts=q(ftsTableName(schema)),a=q(alias),query=scope.tx(f==="mantle.search"?args[1]:searchQuery??(()=>{throw new SqlRefusal("SQL_FUNCTION",`mantle.search_rank(${alias}) needs a mantle.search(${alias}, ...) in the same query`)})()),phrase=`'"' || replace(__q, '"', '""') || '"'`;if(f==="mantle.search_rank")return sql(`coalesce((SELECT bm25(${fts}) FROM ${fts} WHERE ${fts} = ${phrase} AND rowid = ${a}._rid), 0)`,{__q:query});let like=def.search.map(fld=>`${a}.${q(fld)} LIKE '%' || replace(replace(replace(__q, '!', '!!'), '%', '!%'), '_', '!_') || '%' ESCAPE '!'`).join(" OR ");return sql(`CASE WHEN length(__q) >= 3 THEN ${a}._rid IN (SELECT rowid FROM ${fts} WHERE ${fts} = ${phrase}) ELSE (${like}) END`,{__q:query})}case"mantle.near":case"mantle.distance":{let[ref2,latN,lngN]=args,alias=ref2.ColumnRef.fields[0].String.sval,fld=ref2.ColumnRef.fields[1].String.sval,{schema,def}=scope.alias(alias);if(def.fields[fld]!=="geo")throw new SqlRefusal("SQL_FUNCTION",`${schema}.${fld} is not a geo field`);let a=q(alias),dist=HAV(`${a}.${q(fld+"_lat")}`,`${a}.${q(fld+"_lng")}`),sub={__lat:scope.tx(latN),__lng:scope.tx(lngN)};if(f==="mantle.distance")return sql(dist,sub);scope.seen("near");let meters=Number(args[3].A_Const.ival?.ival??args[3].A_Const.fval?.fval),b=which=>scope.param({k:"dialect",box:which,lat:argOf(latN,scope),lng:argOf(lngN,scope),meters}),geo=q(geoTreeName(schema,fld));return sql(`(${a}._rid IN (SELECT id FROM ${geo} WHERE minLat >= __b0 AND maxLat <= __b1 AND minLng >= __b2 AND maxLng <= __b3) AND ${dist} <= ${meters})`,{...sub,__b0:b("minLat"),__b1:b("maxLat"),__b2:b("minLng"),__b3:b("maxLng")})}}}var value=x=>({Raw:{parts:[x," + 0"]}});function lowerCast(n,scope){let t=n.typeName.names.at(-1).String.sval,lit3=n.arg?.A_Const,litStr=lit3?.sval?.sval??lit3?.fval?.fval??(lit3?.ival?.ival!==void 0?String(lit3.ival.ival):void 0);if(t==="interval")return value(num(intervalMicros(lit3.sval.sval,n.typeName.typmods?.[0]?.A_Const?.ival?.ival)));if(t==="timestamptz")return value(num(encodeTimestamptz(litStr)));if(t==="date")return value(num(encodeDate(litStr)));if(t==="numeric"){let[p,s]=n.typeName.typmods.map(m=>m.A_Const.ival.ival);return parseNumeric(`numeric(${p}, ${s})`),value(num(encodeNumeric(litStr,p,s)))}if(t==="bool")return sql("CASE WHEN typeof(__x) = 'text' THEN lower(__x) IN ('t', 'true', 'y', 'yes', 'on', '1') WHEN __x IS NULL THEN NULL ELSE __x <> 0 END",{__x:scope.tx(n.arg)});let target2=t==="int4"||t==="int8"?"integer":t==="float8"?"real":"text";return cast(scope.tx(n.arg),target2)}var d1Lowering={input:(param2,type)=>cast(param2,sqliteType(type)),func:lowerFunc2,call(out){return out.funcname[0].String.sval==="pg_catalog"&&(out.funcname=out.funcname.slice(1)),out.funcname.length===1&&out.funcname[0].String.sval==="btrim"&&(out.funcname=[S("trim")]),out.funcformat="COERCE_EXPLICIT_CALL",{FuncCall:out}},cast:lowerCast,anyOf:(x,set)=>sql("__x IN (SELECT value FROM json_each(__set))",{__x:x,__set:set}),sublink(out){return out.subLinkType==="ANY_SUBLINK"&&delete out.operName,{SubLink:out}},newId:()=>fn("lower",fn("hex",fn("randomblob",num(16)))),columns:s=>s.search?.length||Object.values(s.fields).includes("geo")?[target(ref("rowid"),"_rid")]:[]};import{Deparser}from"pgsql-deparser";var SqliteDeparser=class extends Deparser{ParamRef(n){return`?${n.number}`}TypeCast(n,ctx){return`CAST(${this.visit(n.arg,ctx)} AS ${n.typeName.names.at(-1).String.sval})`}A_Const(n,ctx){return n.sval?`'${String(n.sval.sval??"").replace(/'/g,"''")}'`:n.boolval?n.boolval.boolval===!0?"(1 = 1)":"(1 = 0)":super.A_Const(n,ctx)}A_Expr(node,ctx){let n=parenthesized("A_Expr",node),fc=n.rexpr?.FuncCall;if(n.kind==="AEXPR_LIKE"&&fc?.funcname?.at(-1)?.String?.sval==="like_escape"&&fc.args?.length===2){let[pat,esc]=fc.args,not=n.name[0].String.sval==="!~~"?"NOT ":"";return`${this.visit(n.lexpr,ctx)} ${not}LIKE ${this.visit(pat,ctx)} ESCAPE ${this.visit(esc,ctx)}`}let sign=n.name?.[0]?.String?.sval;return n.kind==="AEXPR_OP"&&!n.lexpr&&(sign==="+"||sign==="-")?`(${sign}(${this.visit(n.rexpr,ctx)}) + 0)`:super.A_Expr(n,ctx)}NullTest(n,ctx){return super.NullTest(parenthesized("NullTest",n),ctx)}BooleanTest(n,ctx){return super.BooleanTest(parenthesized("BooleanTest",n),ctx)}SubLink(n,ctx){return super.SubLink(parenthesized("SubLink",n),ctx)}Raw(n,ctx){return`(${n.parts.map(p=>typeof p=="string"?p:this.visit(p,ctx)).join("")})`}};function print(ast){return new SqliteDeparser([ast],{pretty:!1}).deparseQuery()}var d1Dialect={name:name2,version,check:validateIr2,lowering:d1Lowering,print:ast=>print(ast)};var compile_exports2={};__export(compile_exports2,{accepts:()=>validateProgram3,name:()=>name3,version:()=>version2});var REFUSED={typeof:"typeof() is SQLite's; PostgreSQL has pg_typeof() with other names",hex:"hex() is SQLite's; PostgreSQL's encode() is not on the allowlist",json_each:"json_each() is SQLite's: use jsonb_array_elements_text(x) WITH ORDINALITY AS j(value, n) for an array, or jsonb_each_text(x) WITH ORDINALITY AS j(key, value, n) for an object, in FROM",json_extract:"json_extract() is SQLite's: use x ->> 'key', x ->> 0 or x #>> '{a,b}'",json_set:"json_set() is SQLite's: build the value with jsonb_build_object() or jsonb_build_array()",json_insert:"json_insert() is SQLite's: build the value with jsonb_build_object() or jsonb_build_array()",json_remove:"json_remove() is SQLite's: use x - 'key' to drop a key"},DOLLAR_PATH=/^\$(?:[.[]|$)/;function refuse2(stmts){let walk3=v=>{if(Array.isArray(v))return v.forEach(walk3);if(!v||typeof v!="object")return;let a=v.A_Expr,key=a?.rexpr?.A_Const?.sval?.sval;if(a?.kind==="AEXPR_OP"&&["->>","->"].includes(a.name?.at(-1)?.String?.sval)&&typeof key=="string"&&DOLLAR_PATH.test(key))throw new SqlRefusal("SQL_UNSUPPORTED",`'${key}' is a SQLite JSON path: PostgreSQL reads it as a key named ${key}. Use x ->> 'key', x ->> 0 or x #>> '{a,b}'`,a.rexpr.A_Const.location??a.location);let f=v.FuncCall;if(f){let name4=f.funcname.map(x=>x.String?.sval).join(".").replace(/^pg_catalog\./,"");if(REFUSED[name4])throw new SqlRefusal("SQL_FUNCTION",REFUSED[name4],f.location);if(name4==="json_array_length"&&f.args?.length!==1)throw new SqlRefusal("SQL_FUNCTION","json_array_length() takes one argument on PostgreSQL",f.location)}Object.values(v).forEach(walk3)};walk3(stmts)}function validateProgram3(stmts,ctx,locs=[]){refuse2(stmts),validateProgram(stmts,ctx,locs,PROFILES.reference)}function validateIr3(plan,ctx){let d=validateIr(plan,ctx,PROFILES.reference);if(d.length)return d;try{return refuse2(plan.stmts),[]}catch(e){return[{code:e.code??"SQL_UNSUPPORTED",message:e.message}]}}var name3="@aotter/mantle/postgres",version2="2";function pgType(type){let num2=parseNumeric(type);if(num2)return`numeric(${num2.p}, ${num2.s})`;switch(type){case"text":case"geo":return"text";case"json":return"jsonb";case"int4":return"int4";case"int8":case"integer":return"int8";case"float8":case"real":return"float8";case"bool":return"bool";case"timestamptz":return"timestamptz";case"date":return"date"}throw new SqlRefusal("SQL_TYPE",`unknown type ${type}`)}var fn2=(f,args,extra={})=>({FuncCall:{funcname:[S(f)],args,funcformat:"COERCE_EXPLICIT_CALL",...extra}}),str=s=>({A_Const:{sval:{sval:s}}});function cast2(x,type){let t=pgType(type),m=/^numeric\((\d+), (\d+)\)$/.exec(t);return{TypeCast:{arg:x,typeName:m?{names:[S("numeric")],typmods:[num(Number(m[1])),num(Number(m[2]))],typemod:-1}:{names:[S(t)],typemod:-1}}}}var coalesce=(...args)=>({CoalesceExpr:{args}}),authored=(n,scope)=>n.agg_filter?{agg_filter:scope.tx(n.agg_filter)}:{},by=node=>({SortBy:{node:structuredClone(node),sortby_dir:"SORTBY_DEFAULT",sortby_nulls:"SORTBY_NULLS_DEFAULT"}}),json=text=>({TypeCast:{arg:str(text),typeName:{names:[S("json")],typemod:-1}}}),argOf2=(n,scope)=>{let k=n.ColumnRef?.fields?.length===2?n.ColumnRef.fields[1].String.sval:void 0;return k?{input:k,type:scope.inputs[k]}:{const:Number(n.A_Const?.ival?.ival??n.A_Const?.fval?.fval)}},HAV2=(lat1,lng1)=>`(2 * 6371008.8 * asin(least(1.0, sqrt(sin(radians(__lat - ${lat1}) / 2) * sin(radians(__lat - ${lat1}) / 2) + cos(radians(${lat1})) * cos(radians(__lat)) * sin(radians(__lng - ${lng1}) / 2) * sin(radians(__lng - ${lng1}) / 2)))))`,TOKEN2=/"(?:[^"]|"")*"|'(?:[^']|'')*'|__\w+/g;function sql2(text,subst={}){let parts=[],last=0;for(let m of text.matchAll(TOKEN2)){if(!m[0].startsWith("__"))continue;let node=subst[m[0]];if(!node)throw new Error(`lowering template names ${m[0]} but was not given it`);m.index>last&&parts.push(text.slice(last,m.index)),parts.push("(",structuredClone(node),")"),last=m.index+m[0].length}return last<text.length&&parts.push(text.slice(last)),{Raw:{parts}}}var q2=id=>`"${id.replace(/"/g,'""')}"`,lit=s=>`'${s.replace(/'/g,"''")}'`,strConst2=n=>n?.A_Const?.sval?.sval;function pgLowering(timeZone){let zone=str(timeZone);return{input:(param2,type)=>cast2(param2,type),system:(param2,type)=>cast2(param2,type),func(f,n,scope){let args=n.args??[];switch(f){case"date_trunc":return fn2("date_trunc",[args[0],scope.tx(args[1]),zone]);case"extract":return sql2(`CAST(extract(${strConst2(args[0])} FROM __ts AT TIME ZONE ${lit(timeZone)}) AS int8)`,{__ts:scope.tx(args[1])});case"json_group_array":{let x=scope.tx(args[0]);return coalesce(fn2("json_agg",[x],{...n.agg_distinct?{agg_order:[by(x)],agg_distinct:!0}:{agg_order:n.agg_order?scope.tx(n.agg_order):[by(fn2("to_jsonb",[x]))]},...authored(n,scope)}),json("[]"))}case"json_group_object":{let k=scope.tx(args[0]);return coalesce(fn2("json_object_agg",[k,scope.tx(args[1])],{agg_order:n.agg_order?scope.tx(n.agg_order):[by(k)],...authored(n,scope)}),json("{}"))}case"json_array_length":return fn2("jsonb_array_length",[cast2(scope.tx(args[0]),"json")]);case"instr":return fn2("strpos",[scope.tx(args[0]),scope.tx(args[1])]);case"round":return args.length===2?fn2("round",[{TypeCast:{arg:scope.tx(args[0]),typeName:{names:[S("numeric")],typemod:-1}}},scope.tx(args[1])]):void 0;case"mantle.search":{let alias=args[0].ColumnRef.fields[0].String.sval,{schema,def}=scope.alias(alias);if(!def.search?.length)throw new SqlRefusal("SQL_FUNCTION",`${schema} declares no search fields`);scope.seen("search");let pattern="'%' || replace(replace(replace(__q, '!', '!!'), '%', '!%'), '_', '!_') || '%'";return sql2(def.search.map(fld=>`${q2(alias)}.${q2(fld)} ILIKE ${pattern} ESCAPE '!'`).join(" OR "),{__q:scope.tx(args[1])})}case"mantle.search_rank":{let alias=args[0].ColumnRef.fields[0].String.sval,{schema,def,searchQuery}=scope.alias(alias);if(!def.search?.length)throw new SqlRefusal("SQL_FUNCTION",`${schema} declares no search fields`);if(!searchQuery)throw new SqlRefusal("SQL_FUNCTION",`mantle.search_rank(${alias}) needs a mantle.search(${alias}, ...) in the same query`);let count=fld=>`coalesce((length(lower(${q2(alias)}.${q2(fld)})) - length(replace(lower(${q2(alias)}.${q2(fld)}), lower(__q), ''))) / greatest(length(__q), 1), 0)`;return sql2(`-(${def.search.map(count).join(" + ")})`,{__q:scope.tx(searchQuery)})}case"mantle.near":case"mantle.distance":{let[ref2,latN,lngN]=args,alias=ref2.ColumnRef.fields[0].String.sval,fld=ref2.ColumnRef.fields[1].String.sval,{schema,def}=scope.alias(alias);if(def.fields[fld]!=="geo")throw new SqlRefusal("SQL_FUNCTION",`${schema}.${fld} is not a geo field`);let la=`${q2(alias)}.${q2(`${fld}_lat`)}`,ln=`${q2(alias)}.${q2(`${fld}_lng`)}`,sub={__lat:scope.tx(latN),__lng:scope.tx(lngN)};if(f==="mantle.distance")return sql2(HAV2(la,ln),sub);scope.seen("near");let meters=Number(args[3].A_Const.ival?.ival??args[3].A_Const.fval?.fval),b=box=>scope.param({k:"dialect",box,lat:argOf2(latN,scope),lng:argOf2(lngN,scope),meters});return sql2(`${la} BETWEEN __b0 AND __b1 AND ${ln} BETWEEN __b2 AND __b3 AND ${HAV2(la,ln)} <= ${meters}`,{...sub,__b0:b("minLat"),__b1:b("maxLat"),__b2:b("minLng"),__b3:b("maxLng")})}case"typeof":case"hex":case"json_extract":case"json_set":case"json_insert":case"json_remove":throw new SqlRefusal("SQL_FUNCTION",`${f} is not supported by the PostgreSQL dialect`)}},call:out=>({FuncCall:out}),anyOf:(x,set,type)=>sql2(`__x = ANY(CAST(CAST(__set AS text) AS ${pgType(type==="number"?"real":"text")}[]))`,{__x:x,__set:set}),cast(n,scope){let t=n.typeName.names.at(-1).String.sval,a=n.arg?.A_Const,text=a?.sval?.sval??a?.fval?.fval??(a?.ival?.ival!==void 0?String(a.ival.ival):void 0);if(t==="timestamptz"&&text!==void 0)return cast2(str(decodeTimestamptz(encodeTimestamptz(text))),"timestamptz");if(t==="date"&&text!==void 0)return cast2(str(decodeDate(encodeDate(text))),"date");if(t==="numeric"&&n.typeName.typmods?.length===2){let[p,s]=n.typeName.typmods.map(m=>m.A_Const.ival.ival);if(parseNumeric(`numeric(${p}, ${s})`),text!==void 0)return cast2(str(decodeNumeric(encodeNumeric(text,p,s),s)),`numeric(${p},${s})`)}return{TypeCast:{...n,arg:scope.tx(n.arg)}}},sublink:out=>({SubLink:out}),newId:()=>fn2("replace",[{TypeCast:{arg:fn2("gen_random_uuid",[]),typeName:{names:[S("text")],typemod:-1}}},str("-"),str("")]),columns:()=>[]}}import{Deparser as Deparser2}from"pgsql-deparser";var PgDeparser=class extends Deparser2{A_Expr(n,ctx){return super.A_Expr(parenthesized("A_Expr",n),ctx)}NullTest(n,ctx){return super.NullTest(parenthesized("NullTest",n),ctx)}BooleanTest(n,ctx){return super.BooleanTest(parenthesized("BooleanTest",n),ctx)}SubLink(n,ctx){return super.SubLink(parenthesized("SubLink",n),ctx)}FuncCall(n,ctx){return n.funcname?.length!==2||n.funcname[0]?.String?.sval!=="pg_catalog"||n.funcname[1]?.String?.sval==="like_escape"?super.FuncCall(n,ctx):`(${super.FuncCall({...n,args:n.args?.map(paren)},ctx)})`}Raw(n,ctx){return`(${n.parts.map(p=>typeof p=="string"?p:this.visit(p,ctx)).join("")})`}};function print2(ast){return new PgDeparser([ast],{pretty:!1}).deparseQuery()}function columnType2(s,col){switch(col){case"id":case"author_id":case"status":return"text";case"version":return"integer";case"created_at":case"updated_at":return"timestamptz"}if(col===s.scope)return"text";let geo=/^(.+)_(lat|lng)$/.exec(col);if(geo&&s.fields[geo[1]]==="geo")return"real";let t=s.fields[col];return t==="geo"?void 0:t}function typed(ast,schemas){let walk3=v=>{if(Array.isArray(v))return v.map(walk3);if(!v||typeof v!="object")return v;let out=Object.fromEntries(Object.entries(v).map(([k,c])=>[k,walk3(c)]));return out.InsertStmt&&insert2(out.InsertStmt),out.UpdateStmt&&assign(out.UpdateStmt.relation.relname,out.UpdateStmt.targetList),out},typeOf=(table,col)=>schemas[table]?columnType2(schemas[table],col.toLowerCase()):void 0,to=(table,col,val)=>{let t=typeOf(table,col);return t?cast2(val,t):val},assign=(table,targets)=>{for(let t of targets??[])t.ResTarget?.name&&t.ResTarget.val&&(t.ResTarget.val=to(table,t.ResTarget.name,t.ResTarget.val))},insert2=n=>{let table=n.relation.relname,cols=(n.cols??[]).map(c=>c.ResTarget.name),sel=n.selectStmt?.SelectStmt,list=sel?.targetList??[],star=list[0]?.ResTarget?.val?.ColumnRef?.fields,from=sel?.fromClause?.[0]?.RangeSubselect,k=cols.length-(list.length-1),inner=from?.subquery?.SelectStmt,first=b=>b?.op&&b.op!=="SETOP_NONE"?first(b.larg):b,width=inner?.valuesLists?.[0]?.List?.items?.length??first(inner)?.targetList?.length;if(star?.length===2&&star[1].A_Star&&from?.alias?.aliasname===star[0].String?.sval&&width===k){from.alias.colnames=Array.from({length:k},(_x,i)=>S(`c${i}`));let authored2=Array.from({length:k},(_x,i)=>({ResTarget:{val:to(table,cols[i],{ColumnRef:{fields:[S(from.alias.aliasname),S(`c${i}`)]}})}}));sel.targetList=[...authored2,...list.slice(1).map((t,j)=>({ResTarget:{...t.ResTarget,val:to(table,cols[k+j],t.ResTarget.val)}}))]}else sel?.targetList&&!sel.valuesLists&&(sel.targetList=list.map((t,i)=>cols[i]?{ResTarget:{...t.ResTarget,val:to(table,cols[i],t.ResTarget.val)}}:t));let target2=n.relation.alias?.aliasname??table,qualify=v=>Array.isArray(v)?v.map(qualify):!v||typeof v!="object"||v.SubLink?v:v.ColumnRef?.fields?.length===1&&v.ColumnRef.fields[0].String?{ColumnRef:{fields:[S(target2),v.ColumnRef.fields[0]]}}:Object.fromEntries(Object.entries(v).map(([k2,c])=>[k2,qualify(c)]));for(let t of n.onConflictClause?.targetList??[])t.ResTarget.val=qualify(t.ResTarget.val);n.onConflictClause?.whereClause&&(n.onConflictClause.whereClause=qualify(n.onConflictClause.whereClause)),assign(table,n.onConflictClause?.targetList)};return walk3(ast)}function postgresDialect(timeZone="UTC"){if(new Intl.DateTimeFormat("en-US",{timeZone}),/^[+-]|^(utc|gmt)[+-]/i.test(timeZone))throw new RangeError(`timeZone must be an IANA name such as Asia/Taipei, not the offset ${timeZone}`);return{name:name3,version:version2,check:validateIr3,lowering:pgLowering(timeZone),nativeOrder:!0,nativeSql:!0,print:(ast,schemas)=>print2(typed(ast,schemas)),lowerKey:timeZone}}var q3=id=>`"${id.replace(/"/g,'""')}"`,lit2=s=>`'${s.replace(/'/g,"''")}'`;function colType(t){if(parseNumeric(t))return"INTEGER";switch(t){case"text":case"json":return"TEXT";case"integer":case"bool":case"timestamptz":case"date":return"INTEGER";case"real":return"REAL"}throw new Error(`no column type for ${t}`)}function checkText(expr,s){let problem3=checkShapeProblem(expr,storageColumns(s));if(problem3)throw new Error(problem3);let qualify=v=>Array.isArray(v)?v.map(qualify):!v||typeof v!="object"?v:v.ColumnRef?.fields?.length===1?{ColumnRef:{fields:[{String:{sval:"new"}},v.ColumnRef.fields[0]]}}:Object.fromEntries(Object.entries(v).map(([k,c])=>[k,qualify(c)])),select2={SelectStmt:{targetList:[{ResTarget:{val:qualify(expr)}}],limitOption:"LIMIT_OPTION_DEFAULT",op:"SETOP_NONE"}};return print(select2).replace(/^SELECT\s+/i,"")}function desired(name4,s){let t=q3(name4),columns2=[{name:"_rid",type:"INTEGER",native:!0},{name:"id",type:"TEXT",native:!0},{name:"version",type:"INTEGER",native:!0},{name:"created_at",type:"INTEGER",native:!0},{name:"updated_at",type:"INTEGER",native:!0},{name:"author_id",type:"TEXT",native:!0},...s.scope?[{name:s.scope,type:"TEXT",native:!0}]:[],...s.publishing?[{name:"status",type:"TEXT",native:!0},{name:"published_at",type:"INTEGER",native:!1}]:[],...Object.entries(s.fields).filter(([f])=>f!==s.scope).flatMap(([f,ty])=>ty==="geo"?[{name:`${f}_lat`,type:"REAL",native:!1},{name:`${f}_lng`,type:"REAL",native:!1}]:[{name:f,type:colType(ty),native:!1}])],indexes2=[...(s.unique??[]).map((u,i)=>({name:`_mantle_uq_${name4}_${i}`,unique:!0,columns:s.userScopes?.length?[...new Set([...s.scope?[s.scope]:[],...s.userScopes.map(x=>x.column),...u])]:s.scope&&u[0]!==s.scope?[s.scope,...u]:[...u]})),...(s.indexes??[]).map((cols,i)=>({name:`_mantle_ix_${name4}_${i}`,unique:!1,columns:cols}))].map(i=>({...i,sql:`CREATE ${i.unique?"UNIQUE ":""}INDEX IF NOT EXISTS ${q3(i.name)} ON ${t} (${i.columns.map(q3).join(", ")})`})),triggers=[];(s.checks??[]).forEach((c,i)=>{let e=checkText(c,s);for(let ev of["INSERT","UPDATE"])triggers.push({name:`_mantle_chk_${name4}_${i}_${ev[0].toLowerCase()}`,sql:`CREATE TRIGGER ${q3(`_mantle_chk_${name4}_${i}_${ev[0].toLowerCase()}`)} BEFORE ${ev} ON ${t} WHEN NOT (${e}) BEGIN SELECT RAISE(ABORT, ${lit2(`MANTLE_CHECK ${name4}: ${e.replace(/\bnew\./g,"")}`)}); END`})});let virtuals=[];if(s.search?.length){let fts=q3(ftsTableName(name4)),f=s.search.map(q3).join(", "),n=s.search.map(c=>`new.${q3(c)}`).join(", "),o=s.search.map(c=>`old.${q3(c)}`).join(", ");virtuals.push({name:ftsTableName(name4),sql:`CREATE VIRTUAL TABLE ${fts} USING fts5(${f}, content=${lit2(name4)}, content_rowid='_rid', tokenize='trigram')`,rebuild:`INSERT INTO ${fts} (${fts}) VALUES ('rebuild')`}),triggers.push({name:`_mantle_fts_${name4}_i`,sql:`CREATE TRIGGER ${q3(`_mantle_fts_${name4}_i`)} AFTER INSERT ON ${t} BEGIN INSERT INTO ${fts} (rowid, ${f}) VALUES (new._rid, ${n}); END`},{name:`_mantle_fts_${name4}_d`,sql:`CREATE TRIGGER ${q3(`_mantle_fts_${name4}_d`)} AFTER DELETE ON ${t} BEGIN INSERT INTO ${fts} (${fts}, rowid, ${f}) VALUES ('delete', old._rid, ${o}); END`},{name:`_mantle_fts_${name4}_u`,sql:`CREATE TRIGGER ${q3(`_mantle_fts_${name4}_u`)} AFTER UPDATE OF ${f} ON ${t} BEGIN INSERT INTO ${fts} (${fts}, rowid, ${f}) VALUES ('delete', old._rid, ${o}); INSERT INTO ${fts} (rowid, ${f}) VALUES (new._rid, ${n}); END`})}for(let[geo,ty]of Object.entries(s.fields)){if(ty!=="geo")continue;let tree=geoTreeName(name4,geo),g=q3(tree),la=q3(`${geo}_lat`),ln=q3(`${geo}_lng`);virtuals.push({name:tree,sql:`CREATE VIRTUAL TABLE ${g} USING rtree(id, minLat, maxLat, minLng, maxLng)`,rebuild:`INSERT INTO ${g} SELECT _rid, ${la}, ${la}, ${ln}, ${ln} FROM ${t} WHERE ${la} IS NOT NULL AND ${ln} IS NOT NULL`}),triggers.push({name:`${tree}_i`,sql:`CREATE TRIGGER ${q3(`${tree}_i`)} AFTER INSERT ON ${t} WHEN new.${la} IS NOT NULL AND new.${ln} IS NOT NULL BEGIN INSERT INTO ${g} VALUES (new._rid, new.${la}, new.${la}, new.${ln}, new.${ln}); END`},{name:`${tree}_d`,sql:`CREATE TRIGGER ${q3(`${tree}_d`)} AFTER DELETE ON ${t} BEGIN DELETE FROM ${g} WHERE id = old._rid; END`},{name:`${tree}_u`,sql:`CREATE TRIGGER ${q3(`${tree}_u`)} AFTER UPDATE OF ${la}, ${ln} ON ${t} BEGIN DELETE FROM ${g} WHERE id = old._rid; INSERT INTO ${g} SELECT new._rid, new.${la}, new.${la}, new.${ln}, new.${ln} WHERE new.${la} IS NOT NULL AND new.${ln} IS NOT NULL; END`})}return{table:name4,columns:columns2,indexes:indexes2,triggers,virtuals}}function createTable(d,notNull=new Set){let cols=d.columns.map(c=>c.name==="_rid"?"_rid INTEGER PRIMARY KEY":c.name==="id"?"id TEXT NOT NULL UNIQUE":c.name==="version"?"version INTEGER NOT NULL DEFAULT 1":c.name==="created_at"?"created_at INTEGER NOT NULL":c.name==="updated_at"?"updated_at INTEGER NOT NULL DEFAULT 0":c.name==="author_id"?"author_id TEXT":c.name==="status"?"status TEXT NOT NULL DEFAULT 'draft'":`${q3(c.name)} ${c.type}${c.native&&c.type==="TEXT"||notNull.has(c.name)?" NOT NULL":""}`);return`CREATE TABLE IF NOT EXISTS ${q3(d.table)} (${cols.join(", ")}) STRICT`}var SYSTEM_DDL=["CREATE TABLE IF NOT EXISTS _mantle_assert (op INTEGER, ok INTEGER)","CREATE TRIGGER IF NOT EXISTS _mantle_assert_t BEFORE INSERT ON _mantle_assert BEGIN SELECT CASE WHEN new.ok IS NOT 1 THEN RAISE(ABORT, 'CONFLICT op=' || new.op) ELSE RAISE(IGNORE) END; END","CREATE TABLE IF NOT EXISTS _mantle_tz (from_us INTEGER PRIMARY KEY, offset_us INTEGER NOT NULL) STRICT"];function initialStorageSql(plan){return[SYSTEM_DDL[0],SYSTEM_DDL[1],SYSTEM_DDL[2],"INSERT OR IGNORE INTO _mantle_tz (from_us, offset_us) VALUES (-9007199254740991, 0)",...Object.entries(plan).flatMap(([name4,schema])=>{let d=desired(name4,schema);return[createTable(d,notNullColumns(schema)),...d.indexes.map(i=>i.sql),...d.virtuals.map(i=>i.sql),...d.triggers.map(i=>i.sql)]})]}var q4=id=>`"${id.replace(/"/g,'""')}"`,ident=n=>new TextEncoder().encode(n).length<=63?n:`${n.slice(0,50)}_${fnv(n)}`;function columns(s){return[...s.scope?[{name:s.scope,type:"text",native:!0}]:[],...s.publishing?[{name:"status",type:"text",native:!0},{name:"published_at",type:"timestamptz",native:!1}]:[],...Object.entries(s.fields).filter(([f])=>f!==s.scope).flatMap(([f,ty])=>ty==="geo"?[{name:`${f}_lat`,type:"float8",native:!1},{name:`${f}_lng`,type:"float8",native:!1}]:[{name:f,type:pgType(ty),native:!1}])]}function indexes(name4,s){return[...(s.unique??[]).map((u,i)=>({name:`_mantle_uq_${name4}_${i}`,unique:!0,columns:s.userScopes?.length?[...new Set([...s.scope?[s.scope]:[],...s.userScopes.map(x=>x.column),...u])]:s.scope&&u[0]!==s.scope?[s.scope,...u]:[...u]})),...(s.indexes??[]).map((cols,i)=>({name:`_mantle_ix_${name4}_${i}`,unique:!1,columns:[...cols]})),{name:`_mantle_ix_${name4}_updated`,unique:!1,columns:[...s.scope?[s.scope]:[],"updated_at","id"]}].map(i=>({...i,name:ident(i.name),sql:`CREATE ${i.unique?"UNIQUE ":""}INDEX IF NOT EXISTS ${q4(ident(i.name))} ON ${q4(name4)} (${i.columns.map(q4).join(", ")})`}))}function checkText2(expr,s){let problem3=checkShapeProblem(expr,storageColumns(s));if(problem3)throw new Error(problem3);return print2(typed({SelectStmt:{targetList:[{ResTarget:{val:expr}}],limitOption:"LIMIT_OPTION_DEFAULT",op:"SETOP_NONE"}},{})).replace(/^SELECT\s+/i,"")}var ddlType=type=>type==="text"?'text COLLATE "C"':type,createTable2=(name4,s,notNull=new Set)=>`CREATE TABLE ${q4(name4)} (${["_rid bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY",`id ${ddlType("text")} NOT NULL UNIQUE`,"version int8 NOT NULL DEFAULT 1","created_at timestamptz NOT NULL","updated_at timestamptz NOT NULL DEFAULT now()",`author_id ${ddlType("text")}`,...columns(s).map(c=>`${q4(c.name)} ${ddlType(c.type)}${c.name==="status"?" NOT NULL DEFAULT 'draft'":c.native||notNull.has(c.name)?" NOT NULL":""}`)].join(", ")})`;function initialStorageSql2(plan){return Object.entries(plan).flatMap(([name4,schema])=>[createTable2(name4,schema,notNullColumns(schema)),...indexes(name4,schema).filter(i=>i.name!==ident(`_mantle_ix_${name4}_updated`)).map(i=>i.sql),...(schema.checks??[]).map((check2,i)=>`ALTER TABLE ${q4(name4)} ADD CONSTRAINT ${q4(ident(`_mantle_chk_${name4}_${i}`))} CHECK (${checkText2(check2,schema)})`)])}var propsOf=s=>s.properties??{};function adminIndexColumns(s){let notNull=notNullColumns(s),required=new Set(s.schema.required??[]);return[...s.indexes??[],...s.unique??[]].map(i=>i[0]===s.scope?i[1]:i[0]).filter(f=>!!f&&f!==s.scope&&(required.has(s.names[f]??f)||NATIVE_NOT_NULL.has(f)||notNull.has(f)))}function collectionOf(s,schemas){let names=new Set(schemas.filter(x=>!x.translates&&!declaresFoldUnder(x.schema,x.uiSchema,s.name)).map(x=>x.name)),props=propsOf(s.schema),ui=s.uiSchema??{},list=ui.list??{},nav=ui.nav,filterField=list.filterField,declared=nav?.parentField,parentField=foldParentField(s.schema,declared,name4=>names.has(name4)),navField=nav?.standalone===!0?declared??(s.translates?void 0:requiredMantleRefFields(s.schema).find(r=>names.has(r.collection))?.field):void 0,navParent=navField?resolveMantleRef(props[navField]):null,children=schemas.filter(c=>c.translates?.parent===s.name);return{name:s.name,title:s.title??s.name,description:s.description??null,lifecycle:s.publishing?"publishing":"operational",parent:s.translates?{collection:s.translates.parent,parentField:s.translates.on,childField:s.translates.on}:parentField?{collection:resolveMantleRef(props[parentField]).schema,parentField:resolveMantleRef(props[parentField]).field,childField:parentField}:null,hasTranslations:children.length>0,localized:s.localized===!0||!!s.translates,translates:s.translates??null,schema:s.schema,uiSchema:s.uiSchema??null,mediaFields:[s,...children].flatMap(x=>Object.entries(propsOf(x.schema)).flatMap(([name4,p])=>isMediaMcpHint(p[MCP_HINT_KEYWORD])?[{name:name4,hint:p[MCP_HINT_KEYWORD]}]:[])),sortableFields:[...new Set(adminIndexColumns(s).map(f=>s.names[f]??f))],searchableFields:(s.search??[]).map(f=>s.names[f]??f),filter:filterField?{field:filterField,values:enumOptions(props[filterField])?.map(o=>o.value)??[]}:null,list:{primaryField:list.primaryField??null,columns:list.columns??[]},nav:navField&&navParent?{standalone:!0,parentField:navField,parentCollection:navParent.schema}:null}}function isPrimaryCollection(s,schemas){let c=collectionOf(s,schemas);return!s.translates&&(!c.parent||c.nav!==null)}function expression(node){if(!node)return"NULL";if(node.ColumnRef)return node.ColumnRef.fields.map(f=>f.String?f.String.sval:"*").join(".");let c=node.A_Const;if(c){if(c.isnull)return"NULL";if(c.sval)return`'${c.sval.sval.replace(/'/g,"''")}'`;if(c.ival)return String(c.ival.ival??0);if(c.fval)return c.fval.fval;if(c.boolval)return c.boolval.boolval?"TRUE":"FALSE"}let e=node.A_Expr;if(e?.kind==="AEXPR_OP"&&e.name?.length===1){let operand=v=>v.A_Expr||v.BoolExpr?`(${expression(v)})`:expression(v),op2=e.name[0].String.sval;if(!e.lexpr&&e.rexpr)return`${op2}(${expression(e.rexpr)})`;if(e.lexpr&&e.rexpr)return`${operand(e.lexpr)} ${op2} ${operand(e.rexpr)}`}if(node.BoolExpr){let b=node.BoolExpr;return b.boolop==="NOT_EXPR"?`NOT (${expression(b.args[0])})`:b.args.map(a=>`(${expression(a)})`).join(b.boolop==="AND_EXPR"?" AND ":" OR ")}throw new Error("opaque")}var sql3=node=>{try{return expression(node)}catch{return"[SQL expression \u2014 see authored SQL]"}};function procedureFlow(stmts,relations){return stmts.map((stmt,index)=>{let[operation,body]=Object.entries(stmt)[0],assignments=operation==="UpdateStmt"?body.targetList??[]:[],dependencies=relations?.([stmt]);return{index,logic:sqlLogic(stmt),operation:operation.replace("Stmt","").toUpperCase(),table:body.relation?.relname??null,mode:operation==="MergeStmt"?"set":classify(stmt),reads:[...dependencies?.reads??[]].sort(),writes:[...dependencies?.writes??[]].sort(),filter:body.whereClause?sql3(body.whereClause):body.selectStmt?.SelectStmt?.whereClause?sql3(body.selectStmt.SelectStmt.whereClause):null,returns:(body.returningClause?.exprs??[]).map(t=>sql3(t.ResTarget.val)),cases:assignments.flatMap(({ResTarget:target2})=>{let c=target2.val?.CaseExpr;return c?[{field:target2.name,branches:(c.args??[]).map(({CaseWhen:w})=>({condition:c.arg?`(${sql3(c.arg)}) = (${sql3(w.expr)})`:sql3(w.expr),value:sql3(w.result)})),otherwise:sql3(c.defresult)}]:[]})}})}var branch=(kind,label,children=[])=>({kind,label,children});function sqlLogic(node){let list=(items=[])=>items.map(sqlLogic),clause=(label,value2)=>value2?[branch("clause",label,[sqlLogic(value2)])]:[],group=(label,values)=>values?.length?[branch("clause",label,list(values))]:[];if(node.ColumnRef){let names=node.ColumnRef.fields.map(f=>f.String?.sval),result=branch("value",sql3(node));return names.every(n=>typeof n=="string")&&names.length<=2&&(result.column={name:names.at(-1),...names.length===2?{relation:names[0]}:{}}),result}if(node.BoolExpr){let b=node.BoolExpr;return branch("predicate",b.boolop==="AND_EXPR"?"AND \xB7 all conditions":b.boolop==="OR_EXPR"?"OR \xB7 any condition":"NOT",list(b.args))}if(node.A_Expr){let e=node.A_Expr,names={AEXPR_OP_ANY:`${e.name?.[0]?.String?.sval} ANY`,AEXPR_OP_ALL:`${e.name?.[0]?.String?.sval} ALL`,AEXPR_BETWEEN_SYM:"BETWEEN SYMMETRIC",AEXPR_NOT_BETWEEN_SYM:"NOT BETWEEN SYMMETRIC",AEXPR_IN:e.name?.[0]?.String?.sval==="<>"?"NOT IN":"IN",AEXPR_BETWEEN:"BETWEEN",AEXPR_NOT_BETWEEN:"NOT BETWEEN",AEXPR_DISTINCT:"IS DISTINCT FROM",AEXPR_NOT_DISTINCT:"IS NOT DISTINCT FROM",AEXPR_LIKE:e.name?.[0]?.String?.sval==="!~~"?"NOT LIKE":"LIKE",AEXPR_ILIKE:e.name?.[0]?.String?.sval==="!~~*"?"NOT ILIKE":"ILIKE",AEXPR_NULLIF:"NULLIF"};return branch("expression",names[e.kind]??e.name?.map(n=>n.String.sval).join(".")??e.kind,[e.lexpr,e.rexpr].filter(Boolean).map(sqlLogic))}if(node.NullTest)return branch("predicate",node.NullTest.nulltesttype==="IS_NOT_NULL"?"IS NOT NULL":"IS NULL",[sqlLogic(node.NullTest.arg)]);if(node.BooleanTest)return branch("predicate",node.BooleanTest.booltesttype.replaceAll("_"," "),[sqlLogic(node.BooleanTest.arg)]);if(node.CaseExpr){let c=node.CaseExpr;return branch("case",c.arg?"CASE \xB7 match value":"CASE \xB7 first TRUE condition",[...clause("Value",c.arg),...(c.args??[]).map((w,i)=>branch("when",`WHEN ${i+1}`,[branch("predicate","Condition",[sqlLogic(w.CaseWhen.expr)]),branch("value","THEN",[sqlLogic(w.CaseWhen.result)])])),branch("value","ELSE",[c.defresult?sqlLogic(c.defresult):branch("value","NULL")])])}if(node.SubLink){let s=node.SubLink;return branch("subquery",s.subLinkType==="ANY_SUBLINK"?"IN":s.subLinkType.replace("_SUBLINK",""),[...clause("Compared value",s.testexpr),sqlLogic(s.subselect)])}if(node.FuncCall){let f=node.FuncCall;return branch("function",f.funcname.map(n=>n.String.sval).join(".")+(f.agg_distinct?" \xB7 DISTINCT":"")+(f.agg_star?"(*)":""),[...list(f.args),...group("Aggregate ORDER BY",f.agg_order),...clause("FILTER",f.agg_filter),...clause("OVER",f.over?{WindowDef:f.over}:void 0)])}if(node.CoalesceExpr)return branch("function","COALESCE \xB7 first non-NULL value",list(node.CoalesceExpr.args));if(node.MinMaxExpr)return branch("function",node.MinMaxExpr.op==="IS_GREATEST"?"GREATEST":"LEAST",list(node.MinMaxExpr.args));if(node.TypeCast){let t=node.TypeCast;return branch("cast",`CAST \u2192 ${t.typeName.names.map(n=>n.String.sval).join(".")}${t.typeName.typmods?.length?t.typeName.names.at(-1)?.String?.sval==="numeric"?`(${t.typeName.typmods.map(sql3).join(", ")})`:" \xB7 type modifiers: see authored SQL":""}`,[sqlLogic(t.arg)])}if(node.List)return branch("list","Values",list(node.List.items));if(node.ResTarget)return branch("output",node.ResTarget.name??"Output",node.ResTarget.val?[sqlLogic(node.ResTarget.val)]:[]);if(node.SortBy)return branch("order",`${(node.SortBy.sortby_dir??"SORTBY_DEFAULT").replace("SORTBY_","")} \xB7 ${(node.SortBy.sortby_nulls??"SORTBY_NULLS_DEFAULT").replace("SORTBY_","")}`,[sqlLogic(node.SortBy.node)]);if(node.RangeVar)return{...branch("table",node.RangeVar.relname+(node.RangeVar.alias?` AS ${node.RangeVar.alias.aliasname}`:"")),relation:{name:node.RangeVar.relname,...node.RangeVar.alias?{alias:node.RangeVar.alias.aliasname}:{}}};if(node.RangeSubselect)return branch("subquery",`${node.RangeSubselect.lateral?"LATERAL ":""}${node.RangeSubselect.alias?.aliasname??"Subquery"}`,[sqlLogic(node.RangeSubselect.subquery)]);if(node.JoinExpr){let j=node.JoinExpr;return branch("join",`${j.jointype.replace("JOIN_","")} JOIN`,[sqlLogic(j.larg),sqlLogic(j.rarg),...clause("ON",j.quals),...group("USING",j.usingClause)])}if(node.WindowDef){let w=node.WindowDef;return branch("window",`Window${w.name?` ${w.name}`:""} \xB7 ${w.frameOptions&4?"ROWS":"RANGE"} frame (see authored SQL)`,[...group("PARTITION BY",w.partitionClause),...group("ORDER BY",w.orderClause),...clause("Frame start",w.startOffset),...clause("Frame end",w.endOffset)])}if(node.CommonTableExpr)return branch("cte",node.CommonTableExpr.ctename,[sqlLogic(node.CommonTableExpr.ctequery)]);let key=["SelectStmt","UpdateStmt","InsertStmt","DeleteStmt"].find(k=>node[k]);if(key){let b=node[key],children=[...group(b.withClause?.recursive?"WITH RECURSIVE":"WITH",b.withClause?.ctes),...b.relation?[branch("target","Target",[sqlLogic({RangeVar:b.relation})])]:[],...group(key==="UpdateStmt"?"SET":"SELECT",b.targetList),...group("FROM",b.fromClause??b.usingClause),...clause("WHERE \xB7 keep TRUE rows",b.whereClause),...group("GROUP BY",b.groupClause),...clause("HAVING \xB7 keep TRUE groups",b.havingClause),...group("ORDER BY",b.sortClause),...clause("LIMIT",b.limitCount),...group("VALUES",b.valuesLists),...group("Columns",b.cols),...clause("Source SELECT",b.selectStmt),...group("RETURNING",b.returningClause?.exprs)];if(b.distinctClause&&children.push(branch("clause",b.distinctClause.some(n=>n&&Object.keys(n).length)?"DISTINCT ON":"DISTINCT",list(b.distinctClause.filter(n=>n&&Object.keys(n).length)))),b.op&&b.op!=="SETOP_NONE"&&children.push(branch("set",b.op.replace("SETOP_","")+(b.all?" ALL":""),[sqlLogic({SelectStmt:b.larg}),sqlLogic({SelectStmt:b.rarg})])),b.onConflictClause){let c=b.onConflictClause;children.push(branch("conflict",`ON CONFLICT \xB7 ${c.action.replace("ONCONFLICT_","")}`,[...group("Conflict columns",c.infer?.indexElems),...group("SET",c.targetList),...clause("WHERE",c.whereClause)]))}return branch("statement",key.replace("Stmt","").toUpperCase(),children)}if(node.String)return branch("value",node.String.sval);if(node.IndexElem)return branch("column",node.IndexElem.name);let rendered=sql3(node);return branch(rendered.startsWith("[SQL")?"opaque":"value",rendered.startsWith("[SQL")?`${Object.keys(node)[0]} \xB7 see authored SQL`:rendered)}function rowPreconditions(stmts,target2,idInput,schema){let writes=stmts.flatMap(stmt=>[stmt.UpdateStmt??stmt.DeleteStmt].filter(body2=>body2?.relation?.relname?.toLowerCase()===target2.toLowerCase()));if(writes.length!==1)return[];let body=writes[0];if(body.fromClause?.length||body.usingClause?.length||body.withClause)return[];let terms=node=>node?.BoolExpr?.boolop==="AND_EXPR"?node.BoolExpr.args.flatMap(terms):[node],column=node=>{let fields=node?.ColumnRef?.fields?.map(f=>f.String?.sval);return fields&&(fields.length===1||fields.length===2&&fields[0]?.toLowerCase()===(body.relation.alias?.aliasname??target2).toLowerCase())?fields.at(-1)?.toLowerCase():void 0},input=node=>{let fields=node?.ColumnRef?.fields?.map(f=>f.String?.sval);return fields?.length===2&&fields[0]==="input"?fields[1]:void 0},literal=node=>{let c=node?.A_Const;if(!(!c||c.isnull)){if(c.sval)return c.sval.sval;if(c.boolval)return c.boolval.boolval}},boundId=!1,conditions=[];for(let term2 of terms(body.whereClause)){let e=term2?.A_Expr,op2=e?.name?.[0]?.String?.sval;if(!e||op2!=="="||!["AEXPR_OP","AEXPR_IN"].includes(e.kind))return[];let field=column(e.lexpr),value2=e.rexpr;if(!field&&e.kind==="AEXPR_OP"&&(field=column(e.rexpr),value2=e.lexpr),!field)return[];if(e.kind==="AEXPR_OP"&&input(value2)){field==="id"&&input(value2)?.toLowerCase()===idInput.toLowerCase()&&(boundId=!0);continue}let name4=Object.keys(schema.properties??{}).find(k=>k.toLowerCase()===field);if(!name4)continue;let property=schema.properties[name4];if(!["string","boolean"].includes(property.type)||["date","date-time"].includes(property.format??""))continue;let nodes=e.kind==="AEXPR_IN"?value2?.List?.items:[value2];if(!nodes?.length)return[];let values=nodes.map(literal);values.some(v=>typeof v!==property.type)||conditions.push({field:name4,values})}return boundId?conditions:[]}function audienceOf(requires){let all=requires?.auth?.all??[];return all.some(p=>p==="ctx.admin"||typeof p=="object"&&"ctx.admin"in p)?"admin":all.includes("ctx.user")?"members":all.some(p=>p==="ctx.auth"||typeof p=="object"&&"ctx.auth.scope"in p)?"api-clients":null}function relationsOf2(stmts){let reads=new Set,writes=new Set,walk3=(v,write)=>{if(Array.isArray(v))return v.forEach(x=>walk3(x,!1));if(!(!v||typeof v!="object"))for(let[k,c]of Object.entries(v)){let n=c;(k==="RangeVar"||k==="relation")&&n&&typeof n.relname=="string"&&n.mantle!=="cte"&&(write&&k==="relation"?writes:reads).add(n.relname.toLowerCase()),walk3(c,k==="InsertStmt"||k==="UpdateStmt"||k==="DeleteStmt"||k==="MergeStmt")}};return walk3(stmts,!1),{reads,writes}}var pointer=s=>s.replace(/~/g,"~0").replace(/\//g,"~1");function developerConsole(plan){let schemaName=key=>plan.schemas[key]?.name,schemas=Object.values(plan.schemas).sort((a,b)=>a.name.localeCompare(b.name)),views=Object.entries(plan.views).sort(([a],[b])=>a.localeCompare(b)),procedureAudience=name4=>audienceOf(plan.procedures[name4]?.requires)??"public",handlerOf=h=>{if("ref"in h)return{kind:"ref",ref:h.ref};let flow=procedureFlow(h.sql.stmts,relationsOf2),verbs={INSERT:"create",UPDATE:"update",DELETE:"delete"},hooks=Object.entries(plan.triggers).flatMap(([trigger,t])=>{if(t.source.kind!=="lifecycle")return[];let source=t.source,on=source.on.filter(hook=>flow.some(s=>s.writes.includes(source.schema.toLowerCase())&&hook.endsWith(`_${verbs[s.operation]}`)));return on.length?[{trigger,procedure:t.procedure,schema:source.schema,on}]:[]});return{kind:"sql",statement:h.source,flow,hooks}},procedures=Object.entries(plan.procedures).sort(([a],[b])=>a.localeCompare(b)).map(([name4,p])=>({name:name4,title:p.title??null,description:p.description??null,audience:procedureAudience(name4),input:p.input,output:p.output,authorization:p.requires?.auth?.all??[],guard:p.requires?.guard?.procedure??null,handler:handlerOf(p.handler),manifest:{...p,handler:"ref"in p.handler?p.handler:p.handler.steps?{steps:p.handler.steps}:{source:p.handler.source}}})),triggers=Object.entries(plan.triggers).sort(([a],[b])=>a.localeCompare(b)).map(([name4,t])=>({name:name4,target:t.procedure,source:t.source,manifest:t,audience:t.source.kind==="lifecycle"||t.source.kind==="schedule"?"system":t.source.kind==="mcp"&&t.source.surface==="admin"?"admin":procedureAudience(t.procedure)})),viewAudience=v=>v.surface==="internal"?"system":v.surface==="admin"?"admin":audienceOf(v.requires)??"public",relation2=(id,kind,sourceId,targetId,at,value2)=>({id,kind,sourceId,targetId,pointer:at,value:value2}),relations=[...schemas.flatMap(s=>[...s.translates?[relation2(`Schema:${s.name}:translates:${s.translates.parent}`,"translation-parent",`Schema:${s.name}`,`Schema:${s.translates.parent}`,"/spec/translates/parent",s.translates.parent)]:[],...Object.entries(s.schema.properties??{}).flatMap(([field,property])=>{let target2=resolveMantleRef(property)?.schema;return target2&&schemaName(target2.toLowerCase())?[relation2(`Schema:${s.name}:field:${field}:${target2}`,"schema-reference",`Schema:${s.name}`,`Schema:${target2}`,`/spec/schema/properties/${pointer(field)}/x-mantle-ref`,target2)]:[]})]),...views.flatMap(([name4,v])=>[...[...relationsOf2(v.stmts).reads].flatMap(key=>schemaName(key)?[relation2(`View:${name4}:from:${schemaName(key)}`,"view-source",`View:${name4}`,`Schema:${schemaName(key)}`,"/spec/sql",schemaName(key))]:[]),...v.requires?.guard?[relation2(`View:${name4}:guard:${v.requires.guard.procedure}`,"authorization-guard",`View:${name4}`,`Procedure:${v.requires.guard.procedure}`,"/spec/requires/guard/procedure",v.requires.guard.procedure)]:[]]),...Object.entries(plan.procedures).flatMap(([name4,p])=>[...("sql"in p.handler?[...relationsOf2(p.handler.sql.stmts).writes].map(schemaName):[p.target&&schemaName(p.target.schema.toLowerCase())]).flatMap(s=>s?[relation2(`Procedure:${name4}:writes:${s}`,"procedure-schema",`Procedure:${name4}`,`Schema:${s}`,"sql"in p.handler?"/spec/handler/sql":"/spec/target/schema",s)]:[]),...p.requires?.guard?[relation2(`Procedure:${name4}:guard:${p.requires.guard.procedure}`,"authorization-guard",`Procedure:${name4}`,`Procedure:${p.requires.guard.procedure}`,"/spec/requires/guard/procedure",p.requires.guard.procedure)]:[]]),...Object.entries(plan.triggers).flatMap(([name4,t])=>[relation2(`Trigger:${name4}:target:${t.procedure}`,"trigger-target",`Trigger:${name4}`,`Procedure:${t.procedure}`,"/spec/target/procedure",t.procedure),...t.source.kind==="lifecycle"&&schemaName(t.source.schema.toLowerCase())?[relation2(`Trigger:${name4}:source:${t.source.schema}`,"lifecycle-source",`Trigger:${name4}`,`Schema:${schemaName(t.source.schema.toLowerCase())}`,"/spec/source/schema",t.source.schema)]:[]])].sort((a,b)=>a.id.localeCompare(b.id)),callable=["public","admin"].flatMap(surface=>mcpTools(plan,surface).map(tool=>({kind:tool.kind,name:tool.name,target:tool.source,surface,audience:surface==="admin"?"admin":audienceOf(tool.requires)??"public",title:tool.title??null,description:tool.description,input:tool.inputSchema,output:tool.outputSchema??null,trigger:tool.kind==="procedure"?Object.entries(plan.triggers).find(([,t])=>t.procedure===tool.source&&t.source.kind==="mcp"&&t.source.surface===surface)?.[0]??null:null}))),http=[...Object.entries(plan.triggers).flatMap(([name4,t])=>{if(t.source.kind!=="http")return[];let p=plan.procedures[t.procedure];return[{kind:"procedure",name:name4,target:t.procedure,method:t.source.method,path:t.source.path,audience:procedureAudience(t.procedure),title:typeof p.title=="string"?p.title:null,description:typeof p.description=="string"?p.description:`Invoke Procedure '${t.procedure}'.`,input:p.input,output:p.output}]}),...views.filter(([,v])=>v.surface==="public").map(([name4,v])=>({kind:"view",name:name4,target:name4,method:"GET",path:`/api/views/${name4}`,audience:viewAudience(v),title:typeof v.title=="string"?v.title:null,description:typeof v.description=="string"?v.description:`Read View '${name4}'.`,input:v.input??{type:"object"},output:null}))].sort((a,b)=>`${a.path}\0${a.method}`.localeCompare(`${b.path}\0${b.method}`));return{dataModel:{schemas:schemas.map(s=>({name:s.name,title:s.title??s.name,lifecycle:s.publishing?"publishing":"operational",localized:s.localized===!0,translates:s.translates??null,schema:s.schema,checks:(s.checks??[]).map(sqlLogic),uniqueIndexes:s.unique??[],indexes:s.indexes??[],searchableFields:s.search??[],manifest:(({checks:_ir,...rest})=>rest)(s)})),views:views.map(([name4,v])=>({name:name4,title:v.title??null,surface:v.surface,query:{kind:"sql",statement:v.source,...v.input?{params:v.input}:{}},authorization:v.requires?.auth?.all??[],guard:v.requires?.guard?.procedure??null,manifest:(({stmts:_ir,...rest})=>rest)(v)}))},logic:{triggers,procedures},interfaces:{http,callable},graph:{atoms:[...schemas.map(s=>({id:`Schema:${s.name}`,kind:"Schema",name:s.name,title:s.title??s.name})),...views.map(([name4,v])=>({id:`View:${name4}`,kind:"View",name:name4,title:v.title??null,audience:viewAudience(v)})),...procedures.map(({name:name4,title,description,audience,handler,input})=>({id:`Procedure:${name4}`,kind:"Procedure",name:name4,title,description,audience,handler,input})),...triggers.map(({name:name4,source,audience})=>({id:`Trigger:${name4}`,kind:"Trigger",name:name4,title:null,audience,transport:source.kind}))].sort((a,b)=>a.id.localeCompare(b.id)),relations},operations:{schedules:Object.entries(plan.triggers).flatMap(([id,{procedure,source}])=>source.kind==="schedule"?[{id,procedure,cron:source.cron,enabled:source.enabled??!0,registration:"not-observed"}]:[]),ttlPolicies:schemas.filter(s=>s.ttl).map(s=>({schema:s.name,field:s.names[s.ttl]??s.ttl,expireAfterSeconds:s.ttlSeconds??0,sweepObservation:"unavailable"})),observationAvailability:"unavailable",runs:[],latestRuns:[]}}}var nativeSchema=field=>Object.hasOwn(NATIVE_OUTPUT_TYPES,field)?NATIVE_OUTPUT_TYPES[field]==="integer"?{type:"integer"}:{type:"string",format:"date-time"}:void 0;function entrySchema(plan,v){let sel=v.stmts[0]?.SelectStmt,table=sel?.fromClause?.length===1?sel.fromClause[0].RangeVar:void 0,key=typeof table?.relname=="string"?table.relname.toLowerCase():void 0;return!key||table.mantle!=="table"||!Object.hasOwn(plan.schemas,key)?void 0:(sel.targetList??[]).some(({ResTarget:r})=>{let col=r.val?.ColumnRef?.fields?.at(-1)?.String?.sval;return col==="id"&&(r.name??col)==="id"})?key:void 0}function appCatalog(plan,surface){let tools=mcpTools(plan,surface),actions={},targets=new Map;for(let t of tools){let p=t.kind==="procedure"?plan.procedures[t.source]:void 0;if(!p?.target)continue;actions[t.name]={capability:t.name,...p.title!==void 0?{title:p.title}:{},inputSchema:p.input,...p.uiSchema?{uiSchema:p.uiSchema}:{},bind:[{input:p.target.id,field:"id"}],...p.target.version?{version:p.target.version}:{},mutates:!0};let key=p.target.schema.toLowerCase();targets.set(key,[...targets.get(key)??[],t.name])}let views={};for(let tool of tools){if(tool.kind!=="view")continue;let v=plan.views[tool.source],columns2={};for(let[k,c]of Object.entries(v.columns??{})){let s=plan.schemas[c.schema],field=s.names?.[c.field]??c.field,property=s.schema.properties?.[field]??nativeSchema(c.field);property&&(columns2[k===c.field?field:k]=property)}let list=v.uiSchema?.list??{},entry=entrySchema(plan,v);views[tool.name]={...v.title!==void 0?{title:v.title}:{},columns:columns2,list:{columns:list.columns??[]},actions:entry?targets.get(entry)??[]:[]}}return{views,actions}}export{BUILT_IN_NAV_GROUPS,DiagnosticError,INPUT_RULE_KEYWORDS,NATIVE_COLUMNS,NATIVE_NOT_NULL,adminIndexColumns,appCatalog,assertSiteDefaultsCanonical,canonical,canonicalizeLocaleList,collectionOf,compilePlan,compileProgram,d1Dialect,developerConsole,entrySchema,enumOptions,expandPolicyRequired,fnv,isPrimaryCollection,jsonOutputs,lockCondition,lookupLocalRef,lowerPlan,mcpToolNameSegment,mcpTools,navPlacementProblems,notNullColumns,pagedOf,parseNumeric,parsePgSql,compile_exports2 as postgresCompiler,postgresDialect,initialStorageSql2 as postgresSchema,procedureAnnotations,protectedColumns,refChecks,resolveLocalizedText,rootRefChain,rowPolicy,rowPreconditions,compile_exports as sqliteCompiler,initialStorageSql as sqliteSchema,tableOutputs,toolTitle,userScopeTerm,viewAnnotations,viewOutputs,writePolicy};
|