@pyric/cli 0.1.0-alpha.26 → 0.1.0-alpha.27
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 +1 -1
- package/dist/assurance/.generated/conformance-verdicts.d.ts +5 -0
- package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
- package/dist/assurance/.generated/conformance-verdicts.js +5 -0
- package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
- package/dist/assurance/capabilities.d.ts.map +1 -1
- package/dist/assurance/capabilities.js +24 -5
- package/dist/assurance/capabilities.js.map +1 -1
- package/dist/assurance/runner.d.ts.map +1 -1
- package/dist/assurance/runner.js +37 -50
- package/dist/assurance/runner.js.map +1 -1
- package/dist/assurance/types.d.ts +5 -0
- package/dist/assurance/types.d.ts.map +1 -1
- package/dist/assurance/types.js.map +1 -1
- package/dist/assurance/validation.d.ts +2 -16
- package/dist/assurance/validation.d.ts.map +1 -1
- package/dist/assurance/validation.js +121 -1
- package/dist/assurance/validation.js.map +1 -1
- package/dist/bridge/surface/arguments/assurance.d.ts +25 -0
- package/dist/bridge/surface/arguments/assurance.d.ts.map +1 -1
- package/dist/bridge/surface/arguments/assurance.js +1 -0
- package/dist/bridge/surface/arguments/assurance.js.map +1 -1
- package/dist/bridge/surface/methods/assurance/define.d.ts +2 -2
- package/dist/bridge/surface/methods/assurance/map.d.ts +23 -0
- package/dist/bridge/surface/methods/assurance/map.d.ts.map +1 -1
- package/dist/bridge/surface/methods/assurance/propose.d.ts +7 -0
- package/dist/bridge/surface/methods/assurance/propose.d.ts.map +1 -1
- package/dist/bridge/surface/render/discriminator-schemas.d.ts +2 -2
- package/dist/cli/database-rules.js +1 -1
- package/dist/cli/database-rules.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +13 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/pyric-config.d.ts +8 -0
- package/dist/cli/pyric-config.d.ts.map +1 -1
- package/dist/cli/pyric-config.js.map +1 -1
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +5 -3
- package/dist/cli/serve.js.map +1 -1
- package/dist/cli/verify.d.ts +6 -0
- package/dist/cli/verify.d.ts.map +1 -1
- package/dist/cli/verify.js +240 -15
- package/dist/cli/verify.js.map +1 -1
- package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
- package/dist/conformance/.generated/can-i-use.js +1 -1
- package/dist/conformance/.generated/can-i-use.js.map +1 -1
- package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
- package/dist/conformance/.generated/conformance-docs.js +1 -1
- package/dist/conformance/.generated/conformance-docs.js.map +1 -1
- package/dist/serve/repro/denials.d.ts.map +1 -1
- package/dist/serve/repro/denials.js +2 -1
- package/dist/serve/repro/denials.js.map +1 -1
- package/dist/serve/site-ui/_astro/{app.BpEphDR7.js → app.CiMHEvEW.js} +15 -15
- package/dist/serve/site-ui/_astro/{app.DFdWhpVY.js → app.DpzsBfos.js} +1 -1
- package/dist/serve/site-ui/_astro/{seed.vvXV1ioI.js → seed.BpXSRzLo.js} +1 -1
- package/dist/serve/site-ui/auth/index.html +1 -1
- package/dist/serve/site-ui/docs/database-compat/index.html +4 -0
- package/dist/serve/site-ui/docs/database-compat.md +4 -0
- package/dist/serve/site-ui/docs/get-started/start-building/index.html +1 -0
- package/dist/serve/site-ui/docs/get-started/start-building.md +2 -0
- package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +23 -4
- package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api.md +11 -4
- package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +15 -2
- package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api.md +11 -10
- package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite.md +1 -1
- package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +4 -1
- package/dist/serve/site-ui/docs/ship/ship-to-production.md +7 -1
- package/dist/serve/site-ui/examples/chess/index.html +1 -1
- package/dist/serve/site-ui/firestore/index.html +1 -1
- package/dist/serve/site-ui/rtdb/index.html +1 -1
- package/dist/serve/site-ui/settings/index.html +1 -1
- package/dist/serve/site-ui/storage/index.html +1 -1
- package/dist/serve/site-ui/studio/index.html +1 -1
- package/dist/serve/site-ui/traffic/index.html +1 -1
- package/dist/serve/verify-hint.d.ts +2 -0
- package/dist/serve/verify-hint.d.ts.map +1 -0
- package/dist/serve/verify-hint.js +10 -0
- package/dist/serve/verify-hint.js.map +1 -0
- package/dist/serve/vite-generation-rules-watch.d.ts.map +1 -1
- package/dist/serve/vite-generation-rules-watch.js +5 -3
- package/dist/serve/vite-generation-rules-watch.js.map +1 -1
- package/dist/verify/index.d.ts +16 -2
- package/dist/verify/index.d.ts.map +1 -1
- package/dist/verify/index.js +100 -18
- package/dist/verify/index.js.map +1 -1
- package/dist/verify/staging/engine.d.ts +102 -0
- package/dist/verify/staging/engine.d.ts.map +1 -0
- package/dist/verify/staging/engine.js +371 -0
- package/dist/verify/staging/engine.js.map +1 -0
- package/dist/verify/staging/rest.d.ts +68 -0
- package/dist/verify/staging/rest.d.ts.map +1 -0
- package/dist/verify/staging/rest.js +93 -0
- package/dist/verify/staging/rest.js.map +1 -0
- package/dist/verify/staging/target.d.ts +39 -0
- package/dist/verify/staging/target.d.ts.map +1 -0
- package/dist/verify/staging/target.js +117 -0
- package/dist/verify/staging/target.js.map +1 -0
- package/package.json +4 -4
- package/src/assurance/.generated/conformance-verdicts.ts +5 -0
- package/src/assurance/capabilities.ts +22 -4
- package/src/assurance/runner.ts +40 -58
- package/src/assurance/types.ts +3 -0
- package/src/assurance/validation.ts +137 -0
- package/src/bridge/surface/arguments/assurance.ts +1 -0
- package/src/cli/database-rules.ts +1 -1
- package/src/cli/index.ts +13 -2
- package/src/cli/pyric-config.ts +5 -0
- package/src/cli/serve.ts +6 -3
- package/src/cli/verify.ts +244 -18
- package/src/conformance/.generated/can-i-use.ts +1 -1
- package/src/conformance/.generated/conformance-docs.ts +1 -1
- package/src/serve/repro/denials.ts +2 -1
- package/src/serve/verify-hint.ts +8 -0
- package/src/serve/vite-generation-rules-watch.ts +6 -3
- package/src/verify/index.ts +119 -19
- package/src/verify/staging/engine.ts +455 -0
- package/src/verify/staging/rest.ts +129 -0
- package/src/verify/staging/target.ts +137 -0
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
</script><link rel="preconnect" href="https://use.typekit.net" crossorigin><link rel="stylesheet" href="https://use.typekit.net/jwb3ycu.css"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet"><link rel="stylesheet" href="/__pyric/ui/_astro/_studio_.CzyEuvVS.css">
|
|
7
7
|
<style>html{scrollbar-gutter:stable}
|
|
8
8
|
</style>
|
|
9
|
-
<link rel="stylesheet" href="/__pyric/ui/_astro/app.8TtSeQQX.css"></head> <body> <div id="root" data-astro-cid-w5sm6wlz> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event("astro:only"));})();</script><script>(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="b1btC" component-url="/__pyric/ui/_astro/app.
|
|
9
|
+
<link rel="stylesheet" href="/__pyric/ui/_astro/app.8TtSeQQX.css"></head> <body> <div id="root" data-astro-cid-w5sm6wlz> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event("astro:only"));})();</script><script>(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="b1btC" component-url="/__pyric/ui/_astro/app.DpzsBfos.js" component-export="StudioApp" renderer-url="/__pyric/ui/_astro/client.D2ORs4B-.js" props="{"data-astro-cid-w5sm6wlz":[0,true]}" ssr client="only" opts="{"name":"StudioApp","value":"react"}" await-children><p class="studio-loading" aria-live="polite" data-astro-cid-w5sm6wlz>
|
|
10
10
|
Starting Pyric Studio…
|
|
11
11
|
</p><template data-astro-template="fallback"><p class="studio-loading" aria-live="polite" data-astro-cid-w5sm6wlz>
|
|
12
12
|
Starting Pyric Studio…
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
</script><link rel="preconnect" href="https://use.typekit.net" crossorigin><link rel="stylesheet" href="https://use.typekit.net/jwb3ycu.css"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet"><link rel="stylesheet" href="/__pyric/ui/_astro/_studio_.CzyEuvVS.css">
|
|
7
7
|
<style>html{scrollbar-gutter:stable}
|
|
8
8
|
</style>
|
|
9
|
-
<link rel="stylesheet" href="/__pyric/ui/_astro/app.8TtSeQQX.css"></head> <body> <div id="root" data-astro-cid-w5sm6wlz> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event("astro:only"));})();</script><script>(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="b1btC" component-url="/__pyric/ui/_astro/app.
|
|
9
|
+
<link rel="stylesheet" href="/__pyric/ui/_astro/app.8TtSeQQX.css"></head> <body> <div id="root" data-astro-cid-w5sm6wlz> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event("astro:only"));})();</script><script>(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="b1btC" component-url="/__pyric/ui/_astro/app.DpzsBfos.js" component-export="StudioApp" renderer-url="/__pyric/ui/_astro/client.D2ORs4B-.js" props="{"data-astro-cid-w5sm6wlz":[0,true]}" ssr client="only" opts="{"name":"StudioApp","value":"react"}" await-children><p class="studio-loading" aria-live="polite" data-astro-cid-w5sm6wlz>
|
|
10
10
|
Starting Pyric Studio…
|
|
11
11
|
</p><template data-astro-template="fallback"><p class="studio-loading" aria-live="polite" data-astro-cid-w5sm6wlz>
|
|
12
12
|
Starting Pyric Studio…
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
</script><link rel="preconnect" href="https://use.typekit.net" crossorigin><link rel="stylesheet" href="https://use.typekit.net/jwb3ycu.css"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet"><link rel="stylesheet" href="/__pyric/ui/_astro/_studio_.CzyEuvVS.css">
|
|
7
7
|
<style>html{scrollbar-gutter:stable}
|
|
8
8
|
</style>
|
|
9
|
-
<link rel="stylesheet" href="/__pyric/ui/_astro/app.8TtSeQQX.css"></head> <body> <div id="root" data-astro-cid-w5sm6wlz> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event("astro:only"));})();</script><script>(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="b1btC" component-url="/__pyric/ui/_astro/app.
|
|
9
|
+
<link rel="stylesheet" href="/__pyric/ui/_astro/app.8TtSeQQX.css"></head> <body> <div id="root" data-astro-cid-w5sm6wlz> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event("astro:only"));})();</script><script>(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="b1btC" component-url="/__pyric/ui/_astro/app.DpzsBfos.js" component-export="StudioApp" renderer-url="/__pyric/ui/_astro/client.D2ORs4B-.js" props="{"data-astro-cid-w5sm6wlz":[0,true]}" ssr client="only" opts="{"name":"StudioApp","value":"react"}" await-children><p class="studio-loading" aria-live="polite" data-astro-cid-w5sm6wlz>
|
|
10
10
|
Starting Pyric Studio…
|
|
11
11
|
</p><template data-astro-template="fallback"><p class="studio-loading" aria-live="polite" data-astro-cid-w5sm6wlz>
|
|
12
12
|
Starting Pyric Studio…
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
</script><link rel="preconnect" href="https://use.typekit.net" crossorigin><link rel="stylesheet" href="https://use.typekit.net/jwb3ycu.css"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet"><link rel="stylesheet" href="/__pyric/ui/_astro/_studio_.CzyEuvVS.css">
|
|
7
7
|
<style>html{scrollbar-gutter:stable}
|
|
8
8
|
</style>
|
|
9
|
-
<link rel="stylesheet" href="/__pyric/ui/_astro/app.8TtSeQQX.css"></head> <body> <div id="root" data-astro-cid-w5sm6wlz> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event("astro:only"));})();</script><script>(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="b1btC" component-url="/__pyric/ui/_astro/app.
|
|
9
|
+
<link rel="stylesheet" href="/__pyric/ui/_astro/app.8TtSeQQX.css"></head> <body> <div id="root" data-astro-cid-w5sm6wlz> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event("astro:only"));})();</script><script>(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="b1btC" component-url="/__pyric/ui/_astro/app.DpzsBfos.js" component-export="StudioApp" renderer-url="/__pyric/ui/_astro/client.D2ORs4B-.js" props="{"data-astro-cid-w5sm6wlz":[0,true]}" ssr client="only" opts="{"name":"StudioApp","value":"react"}" await-children><p class="studio-loading" aria-live="polite" data-astro-cid-w5sm6wlz>
|
|
10
10
|
Starting Pyric Studio…
|
|
11
11
|
</p><template data-astro-template="fallback"><p class="studio-loading" aria-live="polite" data-astro-cid-w5sm6wlz>
|
|
12
12
|
Starting Pyric Studio…
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
</script><link rel="preconnect" href="https://use.typekit.net" crossorigin><link rel="stylesheet" href="https://use.typekit.net/jwb3ycu.css"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet"><link rel="stylesheet" href="/__pyric/ui/_astro/_studio_.CzyEuvVS.css">
|
|
7
7
|
<style>html{scrollbar-gutter:stable}
|
|
8
8
|
</style>
|
|
9
|
-
<link rel="stylesheet" href="/__pyric/ui/_astro/app.8TtSeQQX.css"></head> <body> <div id="root" data-astro-cid-w5sm6wlz> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event("astro:only"));})();</script><script>(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="b1btC" component-url="/__pyric/ui/_astro/app.
|
|
9
|
+
<link rel="stylesheet" href="/__pyric/ui/_astro/app.8TtSeQQX.css"></head> <body> <div id="root" data-astro-cid-w5sm6wlz> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event("astro:only"));})();</script><script>(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="b1btC" component-url="/__pyric/ui/_astro/app.DpzsBfos.js" component-export="StudioApp" renderer-url="/__pyric/ui/_astro/client.D2ORs4B-.js" props="{"data-astro-cid-w5sm6wlz":[0,true]}" ssr client="only" opts="{"name":"StudioApp","value":"react"}" await-children><p class="studio-loading" aria-live="polite" data-astro-cid-w5sm6wlz>
|
|
10
10
|
Starting Pyric Studio…
|
|
11
11
|
</p><template data-astro-template="fallback"><p class="studio-loading" aria-live="polite" data-astro-cid-w5sm6wlz>
|
|
12
12
|
Starting Pyric Studio…
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-hint.d.ts","sourceRoot":"","sources":["../../src/serve/verify-hint.ts"],"names":[],"mappings":"AAAA,wBAAgB,gBAAgB,IAAI,MAAM,MAAM,CAO/C"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function createVerifyHint() {
|
|
2
|
+
let printedVerifyHint = false;
|
|
3
|
+
return () => {
|
|
4
|
+
if (printedVerifyHint)
|
|
5
|
+
return '';
|
|
6
|
+
printedVerifyHint = true;
|
|
7
|
+
return ' (run `pyric verify` to replay the captured session against these rules)';
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=verify-hint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-hint.js","sourceRoot":"","sources":["../../src/serve/verify-hint.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,gBAAgB;IAC9B,IAAI,iBAAiB,GAAG,KAAK,CAAC;IAC9B,OAAO,GAAG,EAAE;QACV,IAAI,iBAAiB;YAAE,OAAO,EAAE,CAAC;QACjC,iBAAiB,GAAG,IAAI,CAAC;QACzB,OAAO,0EAA0E,CAAC;IACpF,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-generation-rules-watch.d.ts","sourceRoot":"","sources":["../../src/serve/vite-generation-rules-watch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"vite-generation-rules-watch.d.ts","sourceRoot":"","sources":["../../src/serve/vite-generation-rules-watch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,cAAc,CAAC;CACzB,GAAG,MAAM,IAAI,CA0Gb"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { formatDatabaseRulesRemoved, formatStorageRulesRemoved } from './rules.js';
|
|
3
|
+
import { createVerifyHint } from './verify-hint.js';
|
|
3
4
|
/**
|
|
4
5
|
* Adapt Vite's watcher to the session's last-good rules reload operations.
|
|
5
6
|
* The Firestore, Storage, and each Realtime Database instance's rules files are watched at
|
|
@@ -11,6 +12,7 @@ import { formatDatabaseRulesRemoved, formatStorageRulesRemoved } from './rules.j
|
|
|
11
12
|
* only the instances that deploy that file.
|
|
12
13
|
*/
|
|
13
14
|
export function watchViteGenerationRules(input) {
|
|
15
|
+
const getVerifyHint = createVerifyHint();
|
|
14
16
|
const { server, session } = input;
|
|
15
17
|
const databaseFiles = session.databaseRulesFiles();
|
|
16
18
|
const databaseFileByResolved = new Map(databaseFiles.map((file) => [path.resolve(file), file]));
|
|
@@ -47,7 +49,7 @@ export function watchViteGenerationRules(input) {
|
|
|
47
49
|
server.watcher.add([...session.firestoreRulesFiles()]);
|
|
48
50
|
const isReloaded = result.kind === 'reloaded';
|
|
49
51
|
if (isReloaded) {
|
|
50
|
-
server.config.logger.info(` ↻ [pyric] rules reloaded (${result.rulesHash})`);
|
|
52
|
+
server.config.logger.info(` ↻ [pyric] rules reloaded (${result.rulesHash})${getVerifyHint()}`);
|
|
51
53
|
if (result.fixtureCheck && result.fixtureCheck.ran > 0) {
|
|
52
54
|
const logFn = result.fixtureCheck.ok
|
|
53
55
|
? (m) => server.config.logger.info(m)
|
|
@@ -68,7 +70,7 @@ export function watchViteGenerationRules(input) {
|
|
|
68
70
|
void session.reloadDatabaseRules(databaseFile).then((results) => {
|
|
69
71
|
for (const { instance, result } of results) {
|
|
70
72
|
if (result.kind === 'reloaded') {
|
|
71
|
-
server.config.logger.info(` ↻ [pyric] rtdb rules reloaded for ${instance} (${result.rulesHash})`);
|
|
73
|
+
server.config.logger.info(` ↻ [pyric] rtdb rules reloaded for ${instance} (${result.rulesHash})${getVerifyHint()}`);
|
|
72
74
|
if (result.fixtureCheck && result.fixtureCheck.ran > 0) {
|
|
73
75
|
const logFn = result.fixtureCheck.ok
|
|
74
76
|
? (m) => server.config.logger.info(m)
|
|
@@ -89,7 +91,7 @@ export function watchViteGenerationRules(input) {
|
|
|
89
91
|
if (isStorageMatch) {
|
|
90
92
|
void session.reloadStorageRules().then((result) => {
|
|
91
93
|
if (result.kind === 'reloaded') {
|
|
92
|
-
server.config.logger.info(` ↻ [pyric] storage rules reloaded (${result.rulesHash})`);
|
|
94
|
+
server.config.logger.info(` ↻ [pyric] storage rules reloaded (${result.rulesHash})${getVerifyHint()}`);
|
|
93
95
|
}
|
|
94
96
|
else if (result.kind === 'rejected') {
|
|
95
97
|
server.config.logger.warn(` ⚠ [pyric] storage rules NOT reloaded (last-good stays live): ${result.error.message}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-generation-rules-watch.js","sourceRoot":"","sources":["../../src/serve/vite-generation-rules-watch.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"vite-generation-rules-watch.js","sourceRoot":"","sources":["../../src/serve/vite-generation-rules-watch.ts"],"names":[],"mappings":"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"}
|
package/dist/verify/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { type RtdbRulesDocument } from 'pyric/rules/internal/rtdb';
|
|
|
3
3
|
import { type ExpressionReportLevel, type TestResult } from 'pyric/rules/internal';
|
|
4
4
|
import type { ProjectScope } from '../credentials/core/types.js';
|
|
5
5
|
import { type PyricVerifyFixture } from './fixture.js';
|
|
6
|
+
import { type StagingRunHooks } from './staging/engine.js';
|
|
7
|
+
import type { RtdbRestClient } from './staging/rest.js';
|
|
6
8
|
import { type DeriveRulesTestCasesOptions, type DeriveRulesTestCasesResult } from './cases.js';
|
|
7
9
|
export { buildVerifyFixture, fixtureVerifiableServices, parseVerifyFixture, restoreStorageRulesFromFixture, VERIFY_FIXTURE_SCHEMA, type BuildVerifyFixtureInput, type PyricVerifyFixture, type VerifyFirestoreRulesBlock, type VerifyRtdbInstanceCapture, type VerifyRtdbRulesBlock, type VerifyStorageRulesBlock, } from './fixture.js';
|
|
8
10
|
export { capturedDefaultRtdbInstance, recordedRtdbInstances, recordsDefaultRtdbInstance, } from './rtdb-instances.js';
|
|
@@ -10,7 +12,7 @@ export { deriveRulesTestCases, type DerivedRulesTestCase, type DeriveRulesTestCa
|
|
|
10
12
|
export { createVerifyTools, type VerifyToolDeps } from './tools.js';
|
|
11
13
|
export { executeHostedRulesTest, HOSTED_CREDENTIAL_ENV_KEYS, HOSTED_CREDENTIAL_SOURCES, hostedRulesCredentials, isMissingCredentials, runHostedRulesTest, useHostedRulesTester, type HostedRulesCredentials, type HostedRulesScope, type HostedRulesTester, type HostedRulesTestOutcome, type MissingCredentials, } from './hosted-rules-test.js';
|
|
12
14
|
export type VerifiableService = 'firestore' | 'rtdb' | 'storage';
|
|
13
|
-
export type VerifyEngine = 'sandbox' | 'rulesTestApi';
|
|
15
|
+
export type VerifyEngine = 'sandbox' | 'rulesTestApi' | 'staging';
|
|
14
16
|
type RtdbCandidateRules = {
|
|
15
17
|
rules: Record<string, unknown>;
|
|
16
18
|
} | RtdbRulesDocument;
|
|
@@ -39,6 +41,15 @@ export interface VerifyFixtureOptions {
|
|
|
39
41
|
expressionReportLevel?: ExpressionReportLevel;
|
|
40
42
|
};
|
|
41
43
|
caseDerivation?: Omit<DeriveRulesTestCasesOptions, 'service'>;
|
|
44
|
+
/**
|
|
45
|
+
* The staging engine's instance: a client for a dedicated RTDB instance
|
|
46
|
+
* enrolled with `pyric verify staging init`, and the project it is
|
|
47
|
+
* enrolled for. Required when `engines` includes `staging`.
|
|
48
|
+
*/
|
|
49
|
+
staging?: {
|
|
50
|
+
client: RtdbRestClient;
|
|
51
|
+
projectId: string;
|
|
52
|
+
} & StagingRunHooks;
|
|
42
53
|
}
|
|
43
54
|
export interface VerifyResult {
|
|
44
55
|
ok: boolean;
|
|
@@ -108,7 +119,10 @@ type VerifyDivergenceKind = {
|
|
|
108
119
|
path?: string;
|
|
109
120
|
method?: string;
|
|
110
121
|
sandbox: string;
|
|
111
|
-
|
|
122
|
+
/** Firestore: the hosted Rules Test API's decision. */
|
|
123
|
+
rulesTestApi?: string;
|
|
124
|
+
/** RTDB: what production did on the staging instance. */
|
|
125
|
+
staging?: string;
|
|
112
126
|
reason?: string;
|
|
113
127
|
};
|
|
114
128
|
export declare class VerifyInputError extends Error {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/verify/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,YAAY,EAIlB,MAAM,eAAe,CAAC;AASvB,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAGL,KAAK,qBAAqB,EAE1B,KAAK,UAAU,EAChB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAMjE,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/verify/index.ts"],"names":[],"mappings":"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"}
|
package/dist/verify/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { rulesSourceRejection, SimulateFirestoreRulesHandler, } from 'pyric/rule
|
|
|
6
6
|
import { executeHostedRulesTest } from './hosted-rules-test.js';
|
|
7
7
|
import { isRtdbRulesDocument, parseRtdbRulesJson, } from '../rtdb/rules-json.js';
|
|
8
8
|
import { fixtureVerifiableServices, parseVerifyFixture, } from './fixture.js';
|
|
9
|
+
import { runStagingInstance, StagingDeployRefusedError, withStagingInstance } from './staging/engine.js';
|
|
9
10
|
import { recordedRtdbInstances, recordsDefaultRtdbInstance, replayRtdbInstance, } from './rtdb-instances.js';
|
|
10
11
|
import { deriveRulesTestCases, } from './cases.js';
|
|
11
12
|
export { buildVerifyFixture, fixtureVerifiableServices, parseVerifyFixture, restoreStorageRulesFromFixture, VERIFY_FIXTURE_SCHEMA, } from './fixture.js';
|
|
@@ -28,11 +29,14 @@ export async function verifyFixture(fixtureInput, opts) {
|
|
|
28
29
|
}
|
|
29
30
|
const services = {};
|
|
30
31
|
for (const service of selected) {
|
|
32
|
+
if (engines.includes('staging') && service !== 'rtdb') {
|
|
33
|
+
throw new VerifyInputError(`the staging engine checks RTDB only; ${service} is not supported by it yet. Select --service rtdb, or the sandbox engine for ${service}.`);
|
|
34
|
+
}
|
|
31
35
|
if (service === 'firestore') {
|
|
32
36
|
services.firestore = await verifyFirestore(fixture, requireFirestoreRules(opts.rules), engines, opts);
|
|
33
37
|
}
|
|
34
38
|
else if (service === 'rtdb') {
|
|
35
|
-
services.rtdb = await verifyRtdb(fixture, opts.rules, engines);
|
|
39
|
+
services.rtdb = await verifyRtdb(fixture, opts.rules, engines, opts.staging);
|
|
36
40
|
}
|
|
37
41
|
else if (service === 'storage') {
|
|
38
42
|
services.storage = await verifyStorage(fixture, opts.rules, engines);
|
|
@@ -336,18 +340,22 @@ async function verifyFirestoreRulesTestApi(fixture, rules, opts) {
|
|
|
336
340
|
divergences,
|
|
337
341
|
};
|
|
338
342
|
}
|
|
339
|
-
async function verifyRtdb(fixture, rules, engines) {
|
|
343
|
+
async function verifyRtdb(fixture, rules, engines, staging) {
|
|
340
344
|
const rtdb = fixture.services.rtdb;
|
|
341
345
|
if (!rtdb) {
|
|
342
346
|
throw new VerifyInputError('fixture does not contain services.rtdb.');
|
|
343
347
|
}
|
|
344
348
|
if (engines.includes('rulesTestApi')) {
|
|
345
|
-
throw new VerifyInputError('rulesTestApi verification is Firestore-only; select --service firestore or use the sandbox engine for RTDB.');
|
|
349
|
+
throw new VerifyInputError('rulesTestApi verification is Firestore-only; select --service firestore or use the sandbox or staging engine for RTDB.');
|
|
350
|
+
}
|
|
351
|
+
if (engines.includes('staging') && staging === undefined) {
|
|
352
|
+
throw new VerifyInputError('the staging engine needs a staging instance (opts.staging).');
|
|
346
353
|
}
|
|
347
|
-
|
|
354
|
+
// The instances to check, each with its candidate rules.
|
|
355
|
+
const checks = [];
|
|
348
356
|
const checksDefault = rules.rtdb !== undefined || recordsDefaultRtdbInstance(fixture);
|
|
349
357
|
if (checksDefault) {
|
|
350
|
-
|
|
358
|
+
checks.push({ rules: requireRtdbRules(rules.rtdb, 'missing candidate RTDB rules. Pass rules.rtdb.'), capturedState: rtdb.state.tree });
|
|
351
359
|
}
|
|
352
360
|
const skippedInstances = [];
|
|
353
361
|
for (const instance of recordedRtdbInstances(fixture)) {
|
|
@@ -357,25 +365,99 @@ async function verifyRtdb(fixture, rules, engines) {
|
|
|
357
365
|
continue;
|
|
358
366
|
}
|
|
359
367
|
const parsed = requireRtdbRules(candidate, `missing candidate RTDB rules for instance "${instance}".`, instance);
|
|
360
|
-
|
|
368
|
+
checks.push({ instance, rules: parsed, capturedState: rtdb.instances?.[instance]?.state.tree });
|
|
361
369
|
}
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
+
const engineResults = {};
|
|
371
|
+
if (engines.includes('sandbox')) {
|
|
372
|
+
const replays = [];
|
|
373
|
+
for (const check of checks)
|
|
374
|
+
replays.push(await replayRtdbInstance(fixture, check.rules, check.instance));
|
|
375
|
+
const divergences = replays.flatMap((replayed) => replayed.divergences.map(mapRtdbReplayDivergence));
|
|
376
|
+
engineResults.sandbox = {
|
|
377
|
+
engine: 'sandbox',
|
|
378
|
+
ok: divergences.every(isInformational),
|
|
379
|
+
checkedEvents: replays.reduce((total, replayed) => total + replayed.checkedEvents, 0),
|
|
380
|
+
divergences,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
if (engines.includes('staging') && staging !== undefined) {
|
|
384
|
+
engineResults.staging = await verifyRtdbOnStaging(fixture, checks, staging);
|
|
385
|
+
}
|
|
386
|
+
if (engineResults.sandbox && engineResults.staging) {
|
|
387
|
+
addRtdbEngineDrift(engineResults.sandbox, engineResults.staging);
|
|
388
|
+
}
|
|
389
|
+
const divergences = collectEngineDivergences(engineResults);
|
|
370
390
|
return {
|
|
371
391
|
service: 'rtdb',
|
|
372
392
|
ok: divergences.every(isInformational),
|
|
373
|
-
checkedEvents,
|
|
393
|
+
checkedEvents: engineResults.sandbox?.checkedEvents ?? engineResults.staging?.checkedEvents ?? 0,
|
|
374
394
|
divergences,
|
|
375
|
-
engines:
|
|
395
|
+
engines: engineResults,
|
|
376
396
|
...(skippedInstances.length > 0 ? { skippedInstances } : {}),
|
|
377
397
|
};
|
|
378
398
|
}
|
|
399
|
+
/**
|
|
400
|
+
* Replay each instance on the staging instance in turn, each run guarded and
|
|
401
|
+
* the instance put back before the next. Production refusing to deploy an
|
|
402
|
+
* instance's candidate rules is reported for that instance; the others run.
|
|
403
|
+
*/
|
|
404
|
+
async function verifyRtdbOnStaging(fixture, checks, staging) {
|
|
405
|
+
const divergences = [];
|
|
406
|
+
let checkedEvents = 0;
|
|
407
|
+
for (const check of checks) {
|
|
408
|
+
const tag = check.instance === undefined ? {} : { instance: check.instance };
|
|
409
|
+
try {
|
|
410
|
+
const { result } = await withStagingInstance(staging.client, staging.projectId, () => runStagingInstance({
|
|
411
|
+
client: staging.client,
|
|
412
|
+
events: fixture.events,
|
|
413
|
+
rules: check.rules,
|
|
414
|
+
capturedState: check.capturedState,
|
|
415
|
+
...(check.instance === undefined ? {} : { instance: check.instance }),
|
|
416
|
+
...(staging.signal ? { signal: staging.signal } : {}),
|
|
417
|
+
}), staging);
|
|
418
|
+
checkedEvents += result.checkedEvents;
|
|
419
|
+
divergences.push(...result.divergences.map((divergence) => ({ service: 'rtdb', ...divergence, ...tag })));
|
|
420
|
+
}
|
|
421
|
+
catch (error) {
|
|
422
|
+
if (!(error instanceof StagingDeployRefusedError))
|
|
423
|
+
throw error;
|
|
424
|
+
divergences.push({ service: 'rtdb', kind: 'unsupported', reason: error.message, ...tag });
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return { engine: 'staging', ok: divergences.every(isInformational), checkedEvents, divergences };
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Where the sandbox and production decided a captured step differently: one
|
|
431
|
+
* engine reports `now-denied`, `now-allowed` or `unsupported` for a step and
|
|
432
|
+
* the other reports something else, or nothing. Steps are matched by their
|
|
433
|
+
* index in the replay both engines walk.
|
|
434
|
+
*/
|
|
435
|
+
function addRtdbEngineDrift(sandbox, staging) {
|
|
436
|
+
const decisive = new Set(['now-denied', 'now-allowed', 'unsupported']);
|
|
437
|
+
const keyOf = (divergence) => `${divergence.instance ?? ''}|${divergence.step ?? `${divergence.method}|${divergence.path}`}`;
|
|
438
|
+
const byKey = (divergences) => new Map(divergences.filter((divergence) => decisive.has(divergence.kind)).map((divergence) => [keyOf(divergence), divergence]));
|
|
439
|
+
const local = byKey(sandbox.divergences);
|
|
440
|
+
const remote = byKey(staging.divergences);
|
|
441
|
+
for (const key of new Set([...local.keys(), ...remote.keys()])) {
|
|
442
|
+
const sandboxKind = local.get(key)?.kind ?? 'unchanged';
|
|
443
|
+
const stagingKind = remote.get(key)?.kind ?? 'unchanged';
|
|
444
|
+
if (sandboxKind === stagingKind)
|
|
445
|
+
continue;
|
|
446
|
+
const sample = (local.get(key) ?? remote.get(key));
|
|
447
|
+
staging.divergences.push({
|
|
448
|
+
service: 'rtdb',
|
|
449
|
+
kind: 'engine-drift',
|
|
450
|
+
path: sample.path,
|
|
451
|
+
method: sample.method,
|
|
452
|
+
sandbox: sandboxKind,
|
|
453
|
+
staging: stagingKind,
|
|
454
|
+
reason: `the sandbox reported ${sandboxKind}; production reported ${stagingKind}.`,
|
|
455
|
+
...(sample.instance === undefined ? {} : { instance: sample.instance }),
|
|
456
|
+
...(sample.step === undefined ? {} : { step: sample.step }),
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
staging.ok = staging.divergences.every(isInformational);
|
|
460
|
+
}
|
|
379
461
|
async function verifyStorage(fixture, rules, engines) {
|
|
380
462
|
const storage = fixture.services.storage;
|
|
381
463
|
if (!storage) {
|
|
@@ -585,7 +667,7 @@ function normalizeEngines(input) {
|
|
|
585
667
|
const engines = input ?? ['sandbox'];
|
|
586
668
|
const out = [];
|
|
587
669
|
for (const engine of engines) {
|
|
588
|
-
if (engine !== 'sandbox' && engine !== 'rulesTestApi') {
|
|
670
|
+
if (engine !== 'sandbox' && engine !== 'rulesTestApi' && engine !== 'staging') {
|
|
589
671
|
throw new VerifyInputError(`unsupported verify engine: ${String(engine)}`);
|
|
590
672
|
}
|
|
591
673
|
if (!out.includes(engine))
|
|
@@ -597,7 +679,7 @@ function collectEngineDivergences(engines) {
|
|
|
597
679
|
return Object.values(engines).flatMap((result) => result?.divergences ?? []);
|
|
598
680
|
}
|
|
599
681
|
function serviceCheckedEvents(engines) {
|
|
600
|
-
return engines.sandbox?.checkedEvents ?? engines.rulesTestApi?.checkedEvents ?? 0;
|
|
682
|
+
return engines.sandbox?.checkedEvents ?? engines.rulesTestApi?.checkedEvents ?? engines.staging?.checkedEvents ?? 0;
|
|
601
683
|
}
|
|
602
684
|
function mapUnsupportedEvent(event) {
|
|
603
685
|
return {
|