diff --git a/CLAUDE.md b/CLAUDE.md index 3fbe53c..fca80de 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,13 +8,13 @@ The extension display name is **ERD Studio** (package name `erd-studio`). ### Directory Structure -ERD domain files live at `{project_root}/erd-studio/{layer}/{domain}.json`. Each file is a unified domain containing the logical stage data. The custom editor activates for files matching: -- `**/erd-studio/*/*.json` +ERD domain files live at `{project_root}/.erd-studio/{layer}/{domain}.json`. Each file is a unified domain containing the logical stage data. The custom editor activates for files matching: +- `**/.erd-studio/*/*.json` -The base directory is configurable via the `dbtSemantic.semanticDir` setting (default: `erd-studio`). +The base directory is configurable via the `dbtSemantic.semanticDir` setting (default: `.erd-studio`). ``` -erd-studio/ +.erd-studio/ ├── layers.json ├── templates/ ├── silver/ @@ -80,7 +80,7 @@ manifest.json ─→ ManifestService ─→ buildPhysicalDomain() ─→ Display ``` 1. **ManifestService** stream-parses `target/manifest.json` (handles 40MB+ files via `stream-json`). Extracts model nodes, relationship test nodes (`relationships`, `relationships_where`, custom), `unique` tests, and `unique_combination_of_columns` tests. -2. **DomainService** reads unified domain JSON from `erd-studio/{layer}/*.json` → `UnifiedDomain`, then extracts a stage section via `getDomainStage()` → `DisplayDomain` +2. **DomainService** reads unified domain JSON from `.erd-studio/{layer}/*.json` → `UnifiedDomain`, then extracts a stage section via `getDomainStage()` → `DisplayDomain` 3. For physical stage: `DomainService.buildPhysicalDomain()` derives models from logical filtered by manifest. **Relationships are derived entirely from manifest relationship tests** (not copied from logical). Cardinality is inferred from manifest `unique`/`unique_combination_of_columns` tests (no unique test = "many" side). Relationships are scoped to models within the domain to prevent conformed dimensions from pulling in external edges. See `derivePhysicalRelationships()` in `domainService.ts`. 4. **DiscrepancyService** compares two `DisplayDomain` objects to produce a `DiscrepancyReport` 5. Extension sends `domainLoaded` / `stageData` message to webview diff --git a/README.md b/README.md index 01d5ded..b63d7e9 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ When design and warehouse disagree, ERD Studio generates a JSON plan mapping eve 1. **Install** ERD Studio from the [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=liamwynne.erd-studio). 2. **Open your dbt project** in VS Code and click the ERD Studio icon in the Activity Bar. -3. **Initialize** — follow the prompt to create the `erd-studio/` folder. +3. **Initialize** — follow the prompt to create the `.erd-studio/` folder. 4. **Install the AI harness** — Cmd+Shift+P → `dbt: Install AI Coding Harness`. 5. **Create a domain** — Cmd+Shift+P → `dbt: Create Semantic Domain`. 6. **Tell your AI what to build** — describe the scope, point it at bronze, let it draft the ERD. Review on the canvas. Prompt it to generate the dbt code. @@ -120,7 +120,7 @@ The harness installs the right file for your assistant: | Google Gemini | `.gemini/styleguide.md` | | OpenAI Codex | `AGENTS.md` | -The baseline harness teaches your assistant the domain format and sync workflow, with a guard that blocks AI edits to `erd-studio/` until the spec is loaded. Layer your own skills, prompts, and style guides on top so the generated dbt reflects your team's conventions. +The baseline harness teaches your assistant the domain format and sync workflow, with a guard that blocks AI edits to `.erd-studio/` until the spec is loaded. Layer your own skills, prompts, and style guides on top so the generated dbt reflects your team's conventions.
@@ -148,7 +148,7 @@ After setup, your dbt project gets: ``` your-dbt-project/ -├── erd-studio/ +├── .erd-studio/ │ ├── layers.json # Layer definitions (silver, gold, etc.) │ ├── logical-models/ # Model definitions — one YAML per table │ │ ├── dim_customer.yml @@ -172,7 +172,7 @@ Layer folders match what's in `layers.json`. You're not stuck with `silver`/`gol ### Anatomy of a model file -`erd-studio/logical-models/dim_customer.yml`: +`.erd-studio/logical-models/dim_customer.yml`: ```yaml name: dim_customer @@ -208,7 +208,7 @@ columns: ### Anatomy of a domain file -`erd-studio/silver/orders.json`: +`.erd-studio/silver/orders.json`: ```json { @@ -282,7 +282,7 @@ The spec teaches the AI: - The naming conventions (`dim_`, `fct_`, `ref_`, `brg_` prefixes for dimensions, facts, references, bridges) - The full field reference (every key documented above) -For Claude Code, the install also adds a **PreToolUse hook** at `.claude/settings.local.json` that blocks the first edit to any `erd-studio/` file in a session until the assistant has loaded the skill. No half-read spec, no drift. +For Claude Code, the install also adds a **PreToolUse hook** at `.claude/settings.local.json` that blocks the first edit to any `.erd-studio/` file in a session until the assistant has loaded the skill. No half-read spec, no drift. The harness embeds a version marker. When you upgrade ERD Studio, the extension detects out-of-date harness files and prompts to update. @@ -317,7 +317,7 @@ So `dbt run --selector domain_silver_orders` refreshes every model in your "orde Type comparison normalises common aliases (`varchar`/`string`, `int`/`integer`, `timestamp_ntz`/`timestamp`, etc.) so equivalent types don't show as mismatches. -For unrecoverable drift, the AI can generate a **sync plan** at `erd-studio/.sync-plan.json` — every discrepancy mapped to a concrete action (`add-to-logical`, `update-type-in-physical`, etc.). You pick the source of truth per item; the AI executes it. +For unrecoverable drift, the AI can generate a **sync plan** at `.erd-studio/.sync-plan.json` — every discrepancy mapped to a concrete action (`add-to-logical`, `update-type-in-physical`, etc.). You pick the source of truth per item; the AI executes it. ### Editing by hand vs by AI vs on the canvas diff --git a/docs/semantic-domain-json-reference.md b/docs/semantic-domain-json-reference.md index 81adb2a..feeeaca 100644 --- a/docs/semantic-domain-json-reference.md +++ b/docs/semantic-domain-json-reference.md @@ -4,10 +4,10 @@ ## File Layout -Domain files are organized by stage and layer under the `erd-studio/` directory: +Domain files are organized by stage and layer under the `.erd-studio/` directory: ``` -erd-studio/ +.erd-studio/ conceptual/ {layer}/ {domain}.json @@ -22,7 +22,7 @@ erd-studio/ There are three stages: **conceptual**, **logical**, and **physical**. Conceptual and logical have persisted JSON files. Physical has no files -- it is derived at runtime by merging the logical domain with the dbt manifest. -## Domain File (`erd-studio/{stage}/{layer}/{domain}.json`) +## Domain File (`.erd-studio/{stage}/{layer}/{domain}.json`) ### Top-Level Schema @@ -187,7 +187,7 @@ When generating new domains, omit `positions` -- the extension auto-layouts on f ### Conceptual Stage -Conceptual domains capture high-level entity design. Files live at `erd-studio/conceptual/{layer}/{domain}.json`. +Conceptual domains capture high-level entity design. Files live at `.erd-studio/conceptual/{layer}/{domain}.json`. - Models can omit `columns` entirely (entity-level modelling only). - When columns are present, `dataType` can be `""` if the type is not yet decided. @@ -196,7 +196,7 @@ Conceptual domains capture high-level entity design. Files live at `erd-studio/c ### Logical Stage -Logical domains capture detailed column-level design. Files live at `erd-studio/logical/{layer}/{domain}.json`. +Logical domains capture detailed column-level design. Files live at `.erd-studio/logical/{layer}/{domain}.json`. - Models should have full `columns` arrays with `dataType` and `description` populated. - FK relationships should specify concrete column references. @@ -207,7 +207,7 @@ Logical domains capture detailed column-level design. Files live at `erd-studio/ Physical has no files. It is derived at runtime by merging the logical domain with the dbt manifest. Do not create files for the physical stage. -## Layers File (`erd-studio/layers.json`) +## Layers File (`.erd-studio/layers.json`) Defines the medallion architecture layers available in the project. @@ -248,7 +248,7 @@ Defines the medallion architecture layers available in the project. **Known layer defaults:** `bronze` (`#cd7f32`, creatable: false), `silver` (`#a0a0a0`, creatable: true), `gold` (`#d4a800`, creatable: true). -## Model Templates (`erd-studio/templates/{id}.json`) +## Model Templates (`.erd-studio/templates/{id}.json`) Templates provide preset columns when creating new models. @@ -303,7 +303,7 @@ Templates provide preset columns when creating new models. A conceptual domain focuses on entities, relationships, and design intent. Columns are optional or minimal. -File path: `erd-studio/conceptual/silver/sales.json` +File path: `.erd-studio/conceptual/silver/sales.json` ```json { @@ -403,7 +403,7 @@ File path: `erd-studio/conceptual/silver/sales.json` The same sales domain at the logical stage with full column definitions, data types, and metadata flags. -File path: `erd-studio/logical/silver/sales.json` +File path: `.erd-studio/logical/silver/sales.json` ```json { diff --git a/docs/vision.md b/docs/vision.md index 07ad69f..3dcd184 100644 --- a/docs/vision.md +++ b/docs/vision.md @@ -38,7 +38,7 @@ Claude generates a complete semantic domain: - Relationships with cardinalities - Column definitions with data types -The design is written to a `.json` file in `erd-studio/logical/`. +The design is written to a `.json` file in `.erd-studio/logical/`. ### 3. Data Engineer Reviews in VS Code **Actor:** Human diff --git a/forge-app/static/config/build/assets/index-Crna0F04.js b/forge-app/static/config/build/assets/index-Crna0F04.js index 318d245..c33f32e 100644 --- a/forge-app/static/config/build/assets/index-Crna0F04.js +++ b/forge-app/static/config/build/assets/index-Crna0F04.js @@ -40,4 +40,4 @@ Error generating stack: `+o.message+` `+o.stack}return{value:e,source:t,stack:i,digest:null}}function vl(e,t,r){return{value:e,source:null,stack:r??null,digest:t??null}}function ka(e,t){try{console.error(t.value)}catch(r){setTimeout(function(){throw r})}}var By=typeof WeakMap=="function"?WeakMap:Map;function hv(e,t,r){r=Je(-1,r),r.tag=3,r.payload={element:null};var n=t.value;return r.callback=function(){fo||(fo=!0,Fa=n),ka(e,t)},r}function vv(e,t,r){r=Je(-1,r),r.tag=3;var n=e.type.getDerivedStateFromError;if(typeof n=="function"){var i=t.value;r.payload=function(){return n(i)},r.callback=function(){ka(e,t)}}var o=e.stateNode;return o!==null&&typeof o.componentDidCatch=="function"&&(r.callback=function(){ka(e,t),typeof n!="function"&&(yt===null?yt=new Set([this]):yt.add(this));var l=t.stack;this.componentDidCatch(t.value,{componentStack:l!==null?l:""})}),r}function xc(e,t,r){var n=e.pingCache;if(n===null){n=e.pingCache=new By;var i=new Set;n.set(t,i)}else i=n.get(t),i===void 0&&(i=new Set,n.set(t,i));i.has(r)||(i.add(r),e=Jy.bind(null,e,t,r),t.then(e,e))}function jc(e){do{var t;if((t=e.tag===13)&&(t=e.memoizedState,t=t!==null?t.dehydrated!==null:!0),t)return e;e=e.return}while(e!==null);return null}function Mc(e,t,r,n,i){return e.mode&1?(e.flags|=65536,e.lanes=i,e):(e===t?e.flags|=65536:(e.flags|=128,r.flags|=131072,r.flags&=-52805,r.tag===1&&(r.alternate===null?r.tag=17:(t=Je(-1,1),t.tag=2,mt(r,t,1))),r.lanes|=1),e)}var qy=nt.ReactCurrentOwner,pe=!1;function ae(e,t,r,n){t.child=e===null?Hh(t,null,r,n):vr(t,e.child,r,n)}function Fc(e,t,r,n,i){r=r.render;var o=t.ref;return cr(t,i),n=ms(e,t,r,n,o,i),r=ys(),e!==null&&!pe?(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~i,rt(e,t,i)):(U&&r&&os(t),t.flags|=1,ae(e,t,n,i),t.child)}function Nc(e,t,r,n,i){if(e===null){var o=r.type;return typeof o=="function"&&!Ts(o)&&o.defaultProps===void 0&&r.compare===null&&r.defaultProps===void 0?(t.tag=15,t.type=o,gv(e,t,o,n,i)):(e=Hi(r.type,null,n,t,t.mode,i),e.ref=t.ref,e.return=t,t.child=e)}if(o=e.child,!(e.lanes&i)){var l=o.memoizedProps;if(r=r.compare,r=r!==null?r:Yn,r(l,n)&&e.ref===t.ref)return rt(e,t,i)}return t.flags|=1,e=wt(o,n),e.ref=t.ref,e.return=t,t.child=e}function gv(e,t,r,n,i){if(e!==null){var o=e.memoizedProps;if(Yn(o,n)&&e.ref===t.ref)if(pe=!1,t.pendingProps=n=o,(e.lanes&i)!==0)e.flags&131072&&(pe=!0);else return t.lanes=e.lanes,rt(e,t,i)}return Ca(e,t,r,n,i)}function mv(e,t,r){var n=t.pendingProps,i=n.children,o=e!==null?e.memoizedState:null;if(n.mode==="hidden")if(!(t.mode&1))t.memoizedState={baseLanes:0,cachePool:null,transitions:null},A(or,ye),ye|=r;else{if(!(r&1073741824))return e=o!==null?o.baseLanes|r:r,t.lanes=t.childLanes=1073741824,t.memoizedState={baseLanes:e,cachePool:null,transitions:null},t.updateQueue=null,A(or,ye),ye|=e,null;t.memoizedState={baseLanes:0,cachePool:null,transitions:null},n=o!==null?o.baseLanes:r,A(or,ye),ye|=n}else o!==null?(n=o.baseLanes|r,t.memoizedState=null):n=r,A(or,ye),ye|=n;return ae(e,t,i,r),t.child}function yv(e,t){var r=t.ref;(e===null&&r!==null||e!==null&&e.ref!==r)&&(t.flags|=512,t.flags|=2097152)}function Ca(e,t,r,n,i){var o=ve(r)?qt:ue.current;return o=pr(t,o),cr(t,i),r=ms(e,t,r,n,o,i),n=ys(),e!==null&&!pe?(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~i,rt(e,t,i)):(U&&n&&os(t),t.flags|=1,ae(e,t,r,i),t.child)}function Lc(e,t,r,n,i){if(ve(r)){var o=!0;to(t)}else o=!1;if(cr(t,i),t.stateNode===null)Ui(e,t),pv(t,r,n),Ea(t,r,n,i),n=!0;else if(e===null){var l=t.stateNode,u=t.memoizedProps;l.props=u;var a=l.context,s=r.contextType;typeof s=="object"&&s!==null?s=Te(s):(s=ve(r)?qt:ue.current,s=pr(t,s));var d=r.getDerivedStateFromProps,g=typeof d=="function"||typeof l.getSnapshotBeforeUpdate=="function";g||typeof l.UNSAFE_componentWillReceiveProps!="function"&&typeof l.componentWillReceiveProps!="function"||(u!==n||a!==s)&&Ic(t,l,n,s),at=!1;var m=t.memoizedState;l.state=m,lo(t,n,l,i),a=t.memoizedState,u!==n||m!==a||he.current||at?(typeof d=="function"&&(Sa(t,r,d,n),a=t.memoizedState),(u=at||Tc(t,r,u,n,m,a,s))?(g||typeof l.UNSAFE_componentWillMount!="function"&&typeof l.componentWillMount!="function"||(typeof l.componentWillMount=="function"&&l.componentWillMount(),typeof l.UNSAFE_componentWillMount=="function"&&l.UNSAFE_componentWillMount()),typeof l.componentDidMount=="function"&&(t.flags|=4194308)):(typeof l.componentDidMount=="function"&&(t.flags|=4194308),t.memoizedProps=n,t.memoizedState=a),l.props=n,l.state=a,l.context=s,n=u):(typeof l.componentDidMount=="function"&&(t.flags|=4194308),n=!1)}else{l=t.stateNode,Wh(e,t),u=t.memoizedProps,s=t.type===t.elementType?u:Ne(t.type,u),l.props=s,g=t.pendingProps,m=l.context,a=r.contextType,typeof a=="object"&&a!==null?a=Te(a):(a=ve(r)?qt:ue.current,a=pr(t,a));var h=r.getDerivedStateFromProps;(d=typeof h=="function"||typeof l.getSnapshotBeforeUpdate=="function")||typeof l.UNSAFE_componentWillReceiveProps!="function"&&typeof l.componentWillReceiveProps!="function"||(u!==g||m!==a)&&Ic(t,l,n,a),at=!1,m=t.memoizedState,l.state=m,lo(t,n,l,i);var y=t.memoizedState;u!==g||m!==y||he.current||at?(typeof h=="function"&&(Sa(t,r,h,n),y=t.memoizedState),(s=at||Tc(t,r,s,n,m,y,a)||!1)?(d||typeof l.UNSAFE_componentWillUpdate!="function"&&typeof l.componentWillUpdate!="function"||(typeof l.componentWillUpdate=="function"&&l.componentWillUpdate(n,y,a),typeof l.UNSAFE_componentWillUpdate=="function"&&l.UNSAFE_componentWillUpdate(n,y,a)),typeof l.componentDidUpdate=="function"&&(t.flags|=4),typeof l.getSnapshotBeforeUpdate=="function"&&(t.flags|=1024)):(typeof l.componentDidUpdate!="function"||u===e.memoizedProps&&m===e.memoizedState||(t.flags|=4),typeof l.getSnapshotBeforeUpdate!="function"||u===e.memoizedProps&&m===e.memoizedState||(t.flags|=1024),t.memoizedProps=n,t.memoizedState=y),l.props=n,l.state=y,l.context=a,n=s):(typeof l.componentDidUpdate!="function"||u===e.memoizedProps&&m===e.memoizedState||(t.flags|=4),typeof l.getSnapshotBeforeUpdate!="function"||u===e.memoizedProps&&m===e.memoizedState||(t.flags|=1024),n=!1)}return Pa(e,t,r,n,o,i)}function Pa(e,t,r,n,i,o){yv(e,t);var l=(t.flags&128)!==0;if(!n&&!l)return i&&wc(t,r,!1),rt(e,t,o);n=t.stateNode,qy.current=t;var u=l&&typeof r.getDerivedStateFromError!="function"?null:n.render();return t.flags|=1,e!==null&&l?(t.child=vr(t,e.child,null,o),t.child=vr(t,null,u,o)):ae(e,t,u,o),t.memoizedState=n.state,i&&wc(t,r,!0),t.child}function _v(e){var t=e.stateNode;t.pendingContext?_c(e,t.pendingContext,t.pendingContext!==t.context):t.context&&_c(e,t.context,!1),ps(e,t.containerInfo)}function Dc(e,t,r,n,i){return hr(),us(i),t.flags|=256,ae(e,t,r,n),t.child}var Ra={dehydrated:null,treeContext:null,retryLane:0};function Oa(e){return{baseLanes:e,cachePool:null,transitions:null}}function wv(e,t,r){var n=t.pendingProps,i=b.current,o=!1,l=(t.flags&128)!==0,u;if((u=l)||(u=e!==null&&e.memoizedState===null?!1:(i&2)!==0),u?(o=!0,t.flags&=-129):(e===null||e.memoizedState!==null)&&(i|=1),A(b,i&1),e===null)return _a(t),e=t.memoizedState,e!==null&&(e=e.dehydrated,e!==null)?(t.mode&1?e.data==="$!"?t.lanes=8:t.lanes=1073741824:t.lanes=1,null):(l=n.children,e=n.fallback,o?(n=t.mode,o=t.child,l={mode:"hidden",children:l},!(n&1)&&o!==null?(o.childLanes=0,o.pendingProps=l):o=Io(l,n,0,null),e=Bt(e,n,r,null),o.return=t,e.return=t,o.sibling=e,t.child=o,t.child.memoizedState=Oa(r),t.memoizedState=Ra,e):Ss(t,l));if(i=e.memoizedState,i!==null&&(u=i.dehydrated,u!==null))return zy(e,t,l,n,u,i,r);if(o){o=n.fallback,l=t.mode,i=e.child,u=i.sibling;var a={mode:"hidden",children:n.children};return!(l&1)&&t.child!==i?(n=t.child,n.childLanes=0,n.pendingProps=a,t.deletions=null):(n=wt(i,a),n.subtreeFlags=i.subtreeFlags&14680064),u!==null?o=wt(u,o):(o=Bt(o,l,r,null),o.flags|=2),o.return=t,n.return=t,n.sibling=o,t.child=n,n=o,o=t.child,l=e.child.memoizedState,l=l===null?Oa(r):{baseLanes:l.baseLanes|r,cachePool:null,transitions:l.transitions},o.memoizedState=l,o.childLanes=e.childLanes&~r,t.memoizedState=Ra,n}return o=e.child,e=o.sibling,n=wt(o,{mode:"visible",children:n.children}),!(t.mode&1)&&(n.lanes=r),n.return=t,n.sibling=null,e!==null&&(r=t.deletions,r===null?(t.deletions=[e],t.flags|=16):r.push(e)),t.child=n,t.memoizedState=null,n}function Ss(e,t){return t=Io({mode:"visible",children:t},e.mode,0,null),t.return=e,e.child=t}function Ti(e,t,r,n){return n!==null&&us(n),vr(t,e.child,null,r),e=Ss(t,t.pendingProps.children),e.flags|=2,t.memoizedState=null,e}function zy(e,t,r,n,i,o,l){if(r)return t.flags&256?(t.flags&=-257,n=vl(Error(E(422))),Ti(e,t,l,n)):t.memoizedState!==null?(t.child=e.child,t.flags|=128,null):(o=n.fallback,i=t.mode,n=Io({mode:"visible",children:n.children},i,0,null),o=Bt(o,i,l,null),o.flags|=2,n.return=t,o.return=t,n.sibling=o,t.child=n,t.mode&1&&vr(t,e.child,null,l),t.child.memoizedState=Oa(l),t.memoizedState=Ra,o);if(!(t.mode&1))return Ti(e,t,l,null);if(i.data==="$!"){if(n=i.nextSibling&&i.nextSibling.dataset,n)var u=n.dgst;return n=u,o=Error(E(419)),n=vl(o,n,void 0),Ti(e,t,l,n)}if(u=(l&e.childLanes)!==0,pe||u){if(n=ee,n!==null){switch(l&-l){case 4:i=2;break;case 16:i=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:i=32;break;case 536870912:i=268435456;break;default:i=0}i=i&(n.suspendedLanes|l)?0:i,i!==0&&i!==o.retryLane&&(o.retryLane=i,tt(e,i),Be(n,e,i,-1))}return Os(),n=vl(Error(E(421))),Ti(e,t,l,n)}return i.data==="$?"?(t.flags|=128,t.child=e.child,t=Zy.bind(null,e),i._reactRetry=t,null):(e=o.treeContext,_e=gt(i.nextSibling),we=t,U=!0,De=null,e!==null&&(Ce[Pe++]=Ye,Ce[Pe++]=Xe,Ce[Pe++]=zt,Ye=e.id,Xe=e.overflow,zt=t),t=Ss(t,n.children),t.flags|=4096,t)}function Ac(e,t,r){e.lanes|=t;var n=e.alternate;n!==null&&(n.lanes|=t),wa(e.return,t,r)}function gl(e,t,r,n,i){var o=e.memoizedState;o===null?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:n,tail:r,tailMode:i}:(o.isBackwards=t,o.rendering=null,o.renderingStartTime=0,o.last=n,o.tail=r,o.tailMode=i)}function Sv(e,t,r){var n=t.pendingProps,i=n.revealOrder,o=n.tail;if(ae(e,t,n.children,r),n=b.current,n&2)n=n&1|2,t.flags|=128;else{if(e!==null&&e.flags&128)e:for(e=t.child;e!==null;){if(e.tag===13)e.memoizedState!==null&&Ac(e,r,t);else if(e.tag===19)Ac(e,r,t);else if(e.child!==null){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;e.sibling===null;){if(e.return===null||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}n&=1}if(A(b,n),!(t.mode&1))t.memoizedState=null;else switch(i){case"forwards":for(r=t.child,i=null;r!==null;)e=r.alternate,e!==null&&uo(e)===null&&(i=r),r=r.sibling;r=i,r===null?(i=t.child,t.child=null):(i=r.sibling,r.sibling=null),gl(t,!1,i,r,o);break;case"backwards":for(r=null,i=t.child,t.child=null;i!==null;){if(e=i.alternate,e!==null&&uo(e)===null){t.child=i;break}e=i.sibling,i.sibling=r,r=i,i=e}gl(t,!0,r,null,o);break;case"together":gl(t,!1,null,null,void 0);break;default:t.memoizedState=null}return t.child}function Ui(e,t){!(t.mode&1)&&e!==null&&(e.alternate=null,t.alternate=null,t.flags|=2)}function rt(e,t,r){if(e!==null&&(t.dependencies=e.dependencies),bt|=t.lanes,!(r&t.childLanes))return null;if(e!==null&&t.child!==e.child)throw Error(E(153));if(t.child!==null){for(e=t.child,r=wt(e,e.pendingProps),t.child=r,r.return=t;e.sibling!==null;)e=e.sibling,r=r.sibling=wt(e,e.pendingProps),r.return=t;r.sibling=null}return t.child}function Uy(e,t,r){switch(t.tag){case 3:_v(t),hr();break;case 5:$h(t);break;case 1:ve(t.type)&&to(t);break;case 4:ps(t,t.stateNode.containerInfo);break;case 10:var n=t.type._context,i=t.memoizedProps.value;A(io,n._currentValue),n._currentValue=i;break;case 13:if(n=t.memoizedState,n!==null)return n.dehydrated!==null?(A(b,b.current&1),t.flags|=128,null):r&t.child.childLanes?wv(e,t,r):(A(b,b.current&1),e=rt(e,t,r),e!==null?e.sibling:null);A(b,b.current&1);break;case 19:if(n=(r&t.childLanes)!==0,e.flags&128){if(n)return Sv(e,t,r);t.flags|=128}if(i=t.memoizedState,i!==null&&(i.rendering=null,i.tail=null,i.lastEffect=null),A(b,b.current),n)break;return null;case 22:case 23:return t.lanes=0,mv(e,t,r)}return rt(e,t,r)}var Ev,Ta,kv,Cv;Ev=function(e,t){for(var r=t.child;r!==null;){if(r.tag===5||r.tag===6)e.appendChild(r.stateNode);else if(r.tag!==4&&r.child!==null){r.child.return=r,r=r.child;continue}if(r===t)break;for(;r.sibling===null;){if(r.return===null||r.return===t)return;r=r.return}r.sibling.return=r.return,r=r.sibling}};Ta=function(){};kv=function(e,t,r,n){var i=e.memoizedProps;if(i!==n){e=t.stateNode,Dt(He.current);var o=null;switch(r){case"input":i=Yu(e,i),n=Yu(e,n),o=[];break;case"select":i=H({},i,{value:void 0}),n=H({},n,{value:void 0}),o=[];break;case"textarea":i=Zu(e,i),n=Zu(e,n),o=[];break;default:typeof i.onClick!="function"&&typeof n.onClick=="function"&&(e.onclick=Zi)}ta(r,n);var l;r=null;for(s in i)if(!n.hasOwnProperty(s)&&i.hasOwnProperty(s)&&i[s]!=null)if(s==="style"){var u=i[s];for(l in u)u.hasOwnProperty(l)&&(r||(r={}),r[l]="")}else s!=="dangerouslySetInnerHTML"&&s!=="children"&&s!=="suppressContentEditableWarning"&&s!=="suppressHydrationWarning"&&s!=="autoFocus"&&(Vn.hasOwnProperty(s)?o||(o=[]):(o=o||[]).push(s,null));for(s in n){var a=n[s];if(u=i!=null?i[s]:void 0,n.hasOwnProperty(s)&&a!==u&&(a!=null||u!=null))if(s==="style")if(u){for(l in u)!u.hasOwnProperty(l)||a&&a.hasOwnProperty(l)||(r||(r={}),r[l]="");for(l in a)a.hasOwnProperty(l)&&u[l]!==a[l]&&(r||(r={}),r[l]=a[l])}else r||(o||(o=[]),o.push(s,r)),r=a;else s==="dangerouslySetInnerHTML"?(a=a?a.__html:void 0,u=u?u.__html:void 0,a!=null&&u!==a&&(o=o||[]).push(s,a)):s==="children"?typeof a!="string"&&typeof a!="number"||(o=o||[]).push(s,""+a):s!=="suppressContentEditableWarning"&&s!=="suppressHydrationWarning"&&(Vn.hasOwnProperty(s)?(a!=null&&s==="onScroll"&&B("scroll",e),o||u===a||(o=[])):(o=o||[]).push(s,a))}r&&(o=o||[]).push("style",r);var s=o;(t.updateQueue=s)&&(t.flags|=4)}};Cv=function(e,t,r,n){r!==n&&(t.flags|=4)};function jr(e,t){if(!U)switch(e.tailMode){case"hidden":t=e.tail;for(var r=null;t!==null;)t.alternate!==null&&(r=t),t=t.sibling;r===null?e.tail=null:r.sibling=null;break;case"collapsed":r=e.tail;for(var n=null;r!==null;)r.alternate!==null&&(n=r),r=r.sibling;n===null?t||e.tail===null?e.tail=null:e.tail.sibling=null:n.sibling=null}}function oe(e){var t=e.alternate!==null&&e.alternate.child===e.child,r=0,n=0;if(t)for(var i=e.child;i!==null;)r|=i.lanes|i.childLanes,n|=i.subtreeFlags&14680064,n|=i.flags&14680064,i.return=e,i=i.sibling;else for(i=e.child;i!==null;)r|=i.lanes|i.childLanes,n|=i.subtreeFlags,n|=i.flags,i.return=e,i=i.sibling;return e.subtreeFlags|=n,e.childLanes=r,t}function by(e,t,r){var n=t.pendingProps;switch(ls(t),t.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return oe(t),null;case 1:return ve(t.type)&&eo(),oe(t),null;case 3:return n=t.stateNode,gr(),q(he),q(ue),vs(),n.pendingContext&&(n.context=n.pendingContext,n.pendingContext=null),(e===null||e.child===null)&&(Ri(t)?t.flags|=4:e===null||e.memoizedState.isDehydrated&&!(t.flags&256)||(t.flags|=1024,De!==null&&(Da(De),De=null))),Ta(e,t),oe(t),null;case 5:hs(t);var i=Dt(ti.current);if(r=t.type,e!==null&&t.stateNode!=null)kv(e,t,r,n,i),e.ref!==t.ref&&(t.flags|=512,t.flags|=2097152);else{if(!n){if(t.stateNode===null)throw Error(E(166));return oe(t),null}if(e=Dt(He.current),Ri(t)){n=t.stateNode,r=t.type;var o=t.memoizedProps;switch(n[be]=t,n[Zn]=o,e=(t.mode&1)!==0,r){case"dialog":B("cancel",n),B("close",n);break;case"iframe":case"object":case"embed":B("load",n);break;case"video":case"audio":for(i=0;i<\/script>",e=e.removeChild(e.firstChild)):typeof n.is=="string"?e=l.createElement(r,{is:n.is}):(e=l.createElement(r),r==="select"&&(l=e,n.multiple?l.multiple=!0:n.size&&(l.size=n.size))):e=l.createElementNS(e,r),e[be]=t,e[Zn]=n,Ev(e,t,!1,!1),t.stateNode=e;e:{switch(l=ra(r,n),r){case"dialog":B("cancel",e),B("close",e),i=n;break;case"iframe":case"object":case"embed":B("load",e),i=n;break;case"video":case"audio":for(i=0;iyr&&(t.flags|=128,n=!0,jr(o,!1),t.lanes=4194304)}else{if(!n)if(e=uo(l),e!==null){if(t.flags|=128,n=!0,r=e.updateQueue,r!==null&&(t.updateQueue=r,t.flags|=4),jr(o,!0),o.tail===null&&o.tailMode==="hidden"&&!l.alternate&&!U)return oe(t),null}else 2*$()-o.renderingStartTime>yr&&r!==1073741824&&(t.flags|=128,n=!0,jr(o,!1),t.lanes=4194304);o.isBackwards?(l.sibling=t.child,t.child=l):(r=o.last,r!==null?r.sibling=l:t.child=l,o.last=l)}return o.tail!==null?(t=o.tail,o.rendering=t,o.tail=t.sibling,o.renderingStartTime=$(),t.sibling=null,r=b.current,A(b,n?r&1|2:r&1),t):(oe(t),null);case 22:case 23:return Rs(),n=t.memoizedState!==null,e!==null&&e.memoizedState!==null!==n&&(t.flags|=8192),n&&t.mode&1?ye&1073741824&&(oe(t),t.subtreeFlags&6&&(t.flags|=8192)):oe(t),null;case 24:return null;case 25:return null}throw Error(E(156,t.tag))}function Vy(e,t){switch(ls(t),t.tag){case 1:return ve(t.type)&&eo(),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return gr(),q(he),q(ue),vs(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 5:return hs(t),null;case 13:if(q(b),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(E(340));hr()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return q(b),null;case 4:return gr(),null;case 10:return cs(t.type._context),null;case 22:case 23:return Rs(),null;case 24:return null;default:return null}}var Ii=!1,le=!1,Hy=typeof WeakSet=="function"?WeakSet:Set,P=null;function ir(e,t){var r=e.ref;if(r!==null)if(typeof r=="function")try{r(null)}catch(n){G(e,t,n)}else r.current=null}function Ia(e,t,r){try{r()}catch(n){G(e,t,n)}}var Bc=!1;function Gy(e,t){if(da=Yi,e=Ih(),is(e)){if("selectionStart"in e)var r={start:e.selectionStart,end:e.selectionEnd};else e:{r=(r=e.ownerDocument)&&r.defaultView||window;var n=r.getSelection&&r.getSelection();if(n&&n.rangeCount!==0){r=n.anchorNode;var i=n.anchorOffset,o=n.focusNode;n=n.focusOffset;try{r.nodeType,o.nodeType}catch{r=null;break e}var l=0,u=-1,a=-1,s=0,d=0,g=e,m=null;t:for(;;){for(var h;g!==r||i!==0&&g.nodeType!==3||(u=l+i),g!==o||n!==0&&g.nodeType!==3||(a=l+n),g.nodeType===3&&(l+=g.nodeValue.length),(h=g.firstChild)!==null;)m=g,g=h;for(;;){if(g===e)break t;if(m===r&&++s===i&&(u=l),m===o&&++d===n&&(a=l),(h=g.nextSibling)!==null)break;g=m,m=g.parentNode}g=h}r=u===-1||a===-1?null:{start:u,end:a}}else r=null}r=r||{start:0,end:0}}else r=null;for(pa={focusedElem:e,selectionRange:r},Yi=!1,P=t;P!==null;)if(t=P,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,P=e;else for(;P!==null;){t=P;try{var y=t.alternate;if(t.flags&1024)switch(t.tag){case 0:case 11:case 15:break;case 1:if(y!==null){var v=y.memoizedProps,_=y.memoizedState,f=t.stateNode,c=f.getSnapshotBeforeUpdate(t.elementType===t.type?v:Ne(t.type,v),_);f.__reactInternalSnapshotBeforeUpdate=c}break;case 3:var p=t.stateNode.containerInfo;p.nodeType===1?p.textContent="":p.nodeType===9&&p.documentElement&&p.removeChild(p.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(E(163))}}catch(w){G(t,t.return,w)}if(e=t.sibling,e!==null){e.return=t.return,P=e;break}P=t.return}return y=Bc,Bc=!1,y}function zn(e,t,r){var n=t.updateQueue;if(n=n!==null?n.lastEffect:null,n!==null){var i=n=n.next;do{if((i.tag&e)===e){var o=i.destroy;i.destroy=void 0,o!==void 0&&Ia(t,r,o)}i=i.next}while(i!==n)}}function Oo(e,t){if(t=t.updateQueue,t=t!==null?t.lastEffect:null,t!==null){var r=t=t.next;do{if((r.tag&e)===e){var n=r.create;r.destroy=n()}r=r.next}while(r!==t)}}function xa(e){var t=e.ref;if(t!==null){var r=e.stateNode;switch(e.tag){case 5:e=r;break;default:e=r}typeof t=="function"?t(e):t.current=e}}function Pv(e){var t=e.alternate;t!==null&&(e.alternate=null,Pv(t)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(t=e.stateNode,t!==null&&(delete t[be],delete t[Zn],delete t[ga],delete t[Oy],delete t[Ty])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function Rv(e){return e.tag===5||e.tag===3||e.tag===4}function qc(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||Rv(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function ja(e,t,r){var n=e.tag;if(n===5||n===6)e=e.stateNode,t?r.nodeType===8?r.parentNode.insertBefore(e,t):r.insertBefore(e,t):(r.nodeType===8?(t=r.parentNode,t.insertBefore(e,r)):(t=r,t.appendChild(e)),r=r._reactRootContainer,r!=null||t.onclick!==null||(t.onclick=Zi));else if(n!==4&&(e=e.child,e!==null))for(ja(e,t,r),e=e.sibling;e!==null;)ja(e,t,r),e=e.sibling}function Ma(e,t,r){var n=e.tag;if(n===5||n===6)e=e.stateNode,t?r.insertBefore(e,t):r.appendChild(e);else if(n!==4&&(e=e.child,e!==null))for(Ma(e,t,r),e=e.sibling;e!==null;)Ma(e,t,r),e=e.sibling}var te=null,Le=!1;function ot(e,t,r){for(r=r.child;r!==null;)Ov(e,t,r),r=r.sibling}function Ov(e,t,r){if(Ve&&typeof Ve.onCommitFiberUnmount=="function")try{Ve.onCommitFiberUnmount(_o,r)}catch{}switch(r.tag){case 5:le||ir(r,t);case 6:var n=te,i=Le;te=null,ot(e,t,r),te=n,Le=i,te!==null&&(Le?(e=te,r=r.stateNode,e.nodeType===8?e.parentNode.removeChild(r):e.removeChild(r)):te.removeChild(r.stateNode));break;case 18:te!==null&&(Le?(e=te,r=r.stateNode,e.nodeType===8?sl(e.parentNode,r):e.nodeType===1&&sl(e,r),Kn(e)):sl(te,r.stateNode));break;case 4:n=te,i=Le,te=r.stateNode.containerInfo,Le=!0,ot(e,t,r),te=n,Le=i;break;case 0:case 11:case 14:case 15:if(!le&&(n=r.updateQueue,n!==null&&(n=n.lastEffect,n!==null))){i=n=n.next;do{var o=i,l=o.destroy;o=o.tag,l!==void 0&&(o&2||o&4)&&Ia(r,t,l),i=i.next}while(i!==n)}ot(e,t,r);break;case 1:if(!le&&(ir(r,t),n=r.stateNode,typeof n.componentWillUnmount=="function"))try{n.props=r.memoizedProps,n.state=r.memoizedState,n.componentWillUnmount()}catch(u){G(r,t,u)}ot(e,t,r);break;case 21:ot(e,t,r);break;case 22:r.mode&1?(le=(n=le)||r.memoizedState!==null,ot(e,t,r),le=n):ot(e,t,r);break;default:ot(e,t,r)}}function zc(e){var t=e.updateQueue;if(t!==null){e.updateQueue=null;var r=e.stateNode;r===null&&(r=e.stateNode=new Hy),t.forEach(function(n){var i=e0.bind(null,e,n);r.has(n)||(r.add(n),n.then(i,i))})}}function je(e,t){var r=t.deletions;if(r!==null)for(var n=0;ni&&(i=l),n&=~o}if(n=i,n=$()-n,n=(120>n?120:480>n?480:1080>n?1080:1920>n?1920:3e3>n?3e3:4320>n?4320:1960*$y(n/1960))-n,10e?16:e,dt===null)var n=!1;else{if(e=dt,dt=null,po=0,N&6)throw Error(E(331));var i=N;for(N|=4,P=e.current;P!==null;){var o=P,l=o.child;if(P.flags&16){var u=o.deletions;if(u!==null){for(var a=0;a$()-Cs?At(e,0):ks|=r),ge(e,t)}function Lv(e,t){t===0&&(e.mode&1?(t=wi,wi<<=1,!(wi&130023424)&&(wi=4194304)):t=1);var r=se();e=tt(e,t),e!==null&&(ui(e,t,r),ge(e,r))}function Zy(e){var t=e.memoizedState,r=0;t!==null&&(r=t.retryLane),Lv(e,r)}function e0(e,t){var r=0;switch(e.tag){case 13:var n=e.stateNode,i=e.memoizedState;i!==null&&(r=i.retryLane);break;case 19:n=e.stateNode;break;default:throw Error(E(314))}n!==null&&n.delete(t),Lv(e,r)}var Dv;Dv=function(e,t,r){if(e!==null)if(e.memoizedProps!==t.pendingProps||he.current)pe=!0;else{if(!(e.lanes&r)&&!(t.flags&128))return pe=!1,Uy(e,t,r);pe=!!(e.flags&131072)}else pe=!1,U&&t.flags&1048576&&zh(t,no,t.index);switch(t.lanes=0,t.tag){case 2:var n=t.type;Ui(e,t),e=t.pendingProps;var i=pr(t,ue.current);cr(t,r),i=ms(null,t,n,e,i,r);var o=ys();return t.flags|=1,typeof i=="object"&&i!==null&&typeof i.render=="function"&&i.$$typeof===void 0?(t.tag=1,t.memoizedState=null,t.updateQueue=null,ve(n)?(o=!0,to(t)):o=!1,t.memoizedState=i.state!==null&&i.state!==void 0?i.state:null,ds(t),i.updater=Ro,t.stateNode=i,i._reactInternals=t,Ea(t,n,e,r),t=Pa(null,t,n,!0,o,r)):(t.tag=0,U&&o&&os(t),ae(null,t,i,r),t=t.child),t;case 16:n=t.elementType;e:{switch(Ui(e,t),e=t.pendingProps,i=n._init,n=i(n._payload),t.type=n,i=t.tag=r0(n),e=Ne(n,e),i){case 0:t=Ca(null,t,n,e,r);break e;case 1:t=Lc(null,t,n,e,r);break e;case 11:t=Fc(null,t,n,e,r);break e;case 14:t=Nc(null,t,n,Ne(n.type,e),r);break e}throw Error(E(306,n,""))}return t;case 0:return n=t.type,i=t.pendingProps,i=t.elementType===n?i:Ne(n,i),Ca(e,t,n,i,r);case 1:return n=t.type,i=t.pendingProps,i=t.elementType===n?i:Ne(n,i),Lc(e,t,n,i,r);case 3:e:{if(_v(t),e===null)throw Error(E(387));n=t.pendingProps,o=t.memoizedState,i=o.element,Wh(e,t),lo(t,n,null,r);var l=t.memoizedState;if(n=l.element,o.isDehydrated)if(o={element:n,isDehydrated:!1,cache:l.cache,pendingSuspenseBoundaries:l.pendingSuspenseBoundaries,transitions:l.transitions},t.updateQueue.baseState=o,t.memoizedState=o,t.flags&256){i=mr(Error(E(423)),t),t=Dc(e,t,n,r,i);break e}else if(n!==i){i=mr(Error(E(424)),t),t=Dc(e,t,n,r,i);break e}else for(_e=gt(t.stateNode.containerInfo.firstChild),we=t,U=!0,De=null,r=Hh(t,null,n,r),t.child=r;r;)r.flags=r.flags&-3|4096,r=r.sibling;else{if(hr(),n===i){t=rt(e,t,r);break e}ae(e,t,n,r)}t=t.child}return t;case 5:return $h(t),e===null&&_a(t),n=t.type,i=t.pendingProps,o=e!==null?e.memoizedProps:null,l=i.children,ha(n,i)?l=null:o!==null&&ha(n,o)&&(t.flags|=32),yv(e,t),ae(e,t,l,r),t.child;case 6:return e===null&&_a(t),null;case 13:return wv(e,t,r);case 4:return ps(t,t.stateNode.containerInfo),n=t.pendingProps,e===null?t.child=vr(t,null,n,r):ae(e,t,n,r),t.child;case 11:return n=t.type,i=t.pendingProps,i=t.elementType===n?i:Ne(n,i),Fc(e,t,n,i,r);case 7:return ae(e,t,t.pendingProps,r),t.child;case 8:return ae(e,t,t.pendingProps.children,r),t.child;case 12:return ae(e,t,t.pendingProps.children,r),t.child;case 10:e:{if(n=t.type._context,i=t.pendingProps,o=t.memoizedProps,l=i.value,A(io,n._currentValue),n._currentValue=l,o!==null)if(qe(o.value,l)){if(o.children===i.children&&!he.current){t=rt(e,t,r);break e}}else for(o=t.child,o!==null&&(o.return=t);o!==null;){var u=o.dependencies;if(u!==null){l=o.child;for(var a=u.firstContext;a!==null;){if(a.context===n){if(o.tag===1){a=Je(-1,r&-r),a.tag=2;var s=o.updateQueue;if(s!==null){s=s.shared;var d=s.pending;d===null?a.next=a:(a.next=d.next,d.next=a),s.pending=a}}o.lanes|=r,a=o.alternate,a!==null&&(a.lanes|=r),wa(o.return,r,t),u.lanes|=r;break}a=a.next}}else if(o.tag===10)l=o.type===t.type?null:o.child;else if(o.tag===18){if(l=o.return,l===null)throw Error(E(341));l.lanes|=r,u=l.alternate,u!==null&&(u.lanes|=r),wa(l,r,t),l=o.sibling}else l=o.child;if(l!==null)l.return=o;else for(l=o;l!==null;){if(l===t){l=null;break}if(o=l.sibling,o!==null){o.return=l.return,l=o;break}l=l.return}o=l}ae(e,t,i.children,r),t=t.child}return t;case 9:return i=t.type,n=t.pendingProps.children,cr(t,r),i=Te(i),n=n(i),t.flags|=1,ae(e,t,n,r),t.child;case 14:return n=t.type,i=Ne(n,t.pendingProps),i=Ne(n.type,i),Nc(e,t,n,i,r);case 15:return gv(e,t,t.type,t.pendingProps,r);case 17:return n=t.type,i=t.pendingProps,i=t.elementType===n?i:Ne(n,i),Ui(e,t),t.tag=1,ve(n)?(e=!0,to(t)):e=!1,cr(t,r),pv(t,n,i),Ea(t,n,i,r),Pa(null,t,n,!0,e,r);case 19:return Sv(e,t,r);case 22:return mv(e,t,r)}throw Error(E(156,t.tag))};function Av(e,t){return ch(e,t)}function t0(e,t,r,n){this.tag=e,this.key=r,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=n,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Re(e,t,r,n){return new t0(e,t,r,n)}function Ts(e){return e=e.prototype,!(!e||!e.isReactComponent)}function r0(e){if(typeof e=="function")return Ts(e)?1:0;if(e!=null){if(e=e.$$typeof,e===$a)return 11;if(e===Ka)return 14}return 2}function wt(e,t){var r=e.alternate;return r===null?(r=Re(e.tag,t,e.key,e.mode),r.elementType=e.elementType,r.type=e.type,r.stateNode=e.stateNode,r.alternate=e,e.alternate=r):(r.pendingProps=t,r.type=e.type,r.flags=0,r.subtreeFlags=0,r.deletions=null),r.flags=e.flags&14680064,r.childLanes=e.childLanes,r.lanes=e.lanes,r.child=e.child,r.memoizedProps=e.memoizedProps,r.memoizedState=e.memoizedState,r.updateQueue=e.updateQueue,t=e.dependencies,r.dependencies=t===null?null:{lanes:t.lanes,firstContext:t.firstContext},r.sibling=e.sibling,r.index=e.index,r.ref=e.ref,r}function Hi(e,t,r,n,i,o){var l=2;if(n=e,typeof e=="function")Ts(e)&&(l=1);else if(typeof e=="string")l=5;else e:switch(e){case Qt:return Bt(r.children,i,o,t);case Wa:l=8,i|=8;break;case Wu:return e=Re(12,r,t,i|2),e.elementType=Wu,e.lanes=o,e;case $u:return e=Re(13,r,t,i),e.elementType=$u,e.lanes=o,e;case Ku:return e=Re(19,r,t,i),e.elementType=Ku,e.lanes=o,e;case $p:return Io(r,i,o,t);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case Gp:l=10;break e;case Wp:l=9;break e;case $a:l=11;break e;case Ka:l=14;break e;case ut:l=16,n=null;break e}throw Error(E(130,e==null?e:typeof e,""))}return t=Re(l,r,t,i),t.elementType=e,t.type=n,t.lanes=o,t}function Bt(e,t,r,n){return e=Re(7,e,n,t),e.lanes=r,e}function Io(e,t,r,n){return e=Re(22,e,n,t),e.elementType=$p,e.lanes=r,e.stateNode={isHidden:!1},e}function ml(e,t,r){return e=Re(6,e,null,t),e.lanes=r,e}function yl(e,t,r){return t=Re(4,e.children!==null?e.children:[],e.key,t),t.lanes=r,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function n0(e,t,r,n,i){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=Jo(0),this.expirationTimes=Jo(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=Jo(0),this.identifierPrefix=n,this.onRecoverableError=i,this.mutableSourceEagerHydrationData=null}function Is(e,t,r,n,i,o,l,u,a){return e=new n0(e,t,r,u,a),t===1?(t=1,o===!0&&(t|=8)):t=0,o=Re(3,null,null,t),e.current=o,o.stateNode=e,o.memoizedState={element:n,isDehydrated:r,cache:null,transitions:null,pendingSuspenseBoundaries:null},ds(o),e}function i0(e,t,r){var n=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(Uv)}catch(e){console.error(e)}}Uv(),Up.exports=Ee;var s0=Up.exports,bv,Kc=s0;bv=Kc.createRoot,Kc.hydrateRoot;var $e={},Aa=function(e,t){return Aa=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(r,n){r.__proto__=n}||function(r,n){for(var i in n)Object.prototype.hasOwnProperty.call(n,i)&&(r[i]=n[i])},Aa(e,t)};function Vv(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");Aa(e,t);function r(){this.constructor=e}e.prototype=t===null?Object.create(t):(r.prototype=t.prototype,new r)}var go=function(){return go=Object.assign||function(t){for(var r,n=1,i=arguments.length;n=0;u--)(l=e[u])&&(o=(i<3?l(o):i>3?l(t,r,o):l(t,r))||o);return i>3&&o&&Object.defineProperty(t,r,o),o}function Wv(e,t){return function(r,n){t(r,n,e)}}function $v(e,t,r,n,i,o){function l(f){if(f!==void 0&&typeof f!="function")throw new TypeError("Function expected");return f}for(var u=n.kind,a=u==="getter"?"get":u==="setter"?"set":"value",s=!t&&e?n.static?e:e.prototype:null,d=t||(s?Object.getOwnPropertyDescriptor(s,n.name):{}),g,m=!1,h=r.length-1;h>=0;h--){var y={};for(var v in n)y[v]=v==="access"?{}:n[v];for(var v in n.access)y.access[v]=n.access[v];y.addInitializer=function(f){if(m)throw new TypeError("Cannot add initializers after decoration has completed");o.push(l(f||null))};var _=(0,r[h])(u==="accessor"?{get:d.get,set:d.set}:d[a],y);if(u==="accessor"){if(_===void 0)continue;if(_===null||typeof _!="object")throw new TypeError("Object expected");(g=l(_.get))&&(d.get=g),(g=l(_.set))&&(d.set=g),(g=l(_.init))&&i.unshift(g)}else(g=l(_))&&(u==="field"?i.unshift(g):d[a]=g)}s&&Object.defineProperty(s,n.name,d),m=!0}function Kv(e,t,r){for(var n=arguments.length>2,i=0;i0&&o[o.length-1])&&(s[0]===6||s[0]===2)){r=0;continue}if(s[0]===3&&(!o||s[1]>o[0]&&s[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function Fs(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var n=r.call(e),i,o=[],l;try{for(;(t===void 0||t-- >0)&&!(i=n.next()).done;)o.push(i.value)}catch(u){l={error:u}}finally{try{i&&!i.done&&(r=n.return)&&r.call(n)}finally{if(l)throw l.error}}return o}function tg(){for(var e=[],t=0;t1||a(h,v)})},y&&(i[h]=y(i[h])))}function a(h,y){try{s(n[h](y))}catch(v){m(o[0][3],v)}}function s(h){h.value instanceof _r?Promise.resolve(h.value.v).then(d,g):m(o[0][2],h)}function d(h){a("next",h)}function g(h){a("throw",h)}function m(h,y){h(y),o.shift(),o.length&&a(o[0][0],o[0][1])}}function og(e){var t,r;return t={},n("next"),n("throw",function(i){throw i}),n("return"),t[Symbol.iterator]=function(){return this},t;function n(i,o){t[i]=e[i]?function(l){return(r=!r)?{value:_r(e[i](l)),done:!1}:o?o(l):l}:o}}function lg(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof mo=="function"?mo(e):e[Symbol.iterator](),r={},n("next"),n("throw"),n("return"),r[Symbol.asyncIterator]=function(){return this},r);function n(o){r[o]=e[o]&&function(l){return new Promise(function(u,a){l=e[o](l),i(u,a,l.done,l.value)})}}function i(o,l,u,a){Promise.resolve(a).then(function(s){o({value:s,done:u})},l)}}function ug(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e}var c0=Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t},Ba=function(e){return Ba=Object.getOwnPropertyNames||function(t){var r=[];for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(r[r.length]=n);return r},Ba(e)};function ag(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=Ba(e),n=0;n{if(!t(window.__bridge))throw new e.BridgeAPIError(` Unable to establish a connection with the Custom UI bridge. If you are trying to run your app locally, Forge apps only work in the context of Atlassian products. Refer to https://go.atlassian.com/forge-tunneling-with-custom-ui for how to tunnel when using a local development server. - `);return window.__bridge.callBridge};return Fr.getCallBridge=r,Fr}var Lr={},Xc;function Do(){if(Xc)return Lr;Xc=1,Object.defineProperty(Lr,"__esModule",{value:!0}),Lr.withRateLimiter=void 0;const e=Q(),t=(r,n,i,o)=>{let l=Date.now(),u=0;return async(...a)=>{const s=Date.now();if(s-l>i&&(l=s,u=0),u>=n)throw new e.BridgeAPIError(o||"Too many invocations.");return u=u+1,r(...a)}};return Lr.withRateLimiter=t,Lr}var Jc;function h0(){return Jc||(Jc=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.makeInvoke=e.invoke=void 0;const t=D(),r=Q(),n=Do(),i=(0,t.getCallBridge)(),o=a=>{if(a&&Object.values(a).some(s=>typeof s=="function"))throw new r.BridgeAPIError("Passing functions as part of the payload is not supported!")},l=(a,s)=>{if(typeof a!="string")throw new r.BridgeAPIError("functionKey must be a string!");return o(s),i("invoke",{functionKey:a,payload:s})};e.invoke=(0,n.withRateLimiter)(l,500,1e3*25,"Resolver calls are rate limited at 500req/25s");function u(){return e.invoke}e.makeInvoke=u}(wl)),wl}var Zc;function fi(){return Zc||(Zc=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),me.__exportStar(h0(),e)}(_l)),_l}var Sl={},Dr={},El={},ef;function gg(){return ef||(ef=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e._invokeEndpointFn=e.InvokeType=void 0;const t=D(),r=Q(),n=Do(),i=500,o=25,l=1e3*o;(function(g){g.REMOTE="Remote",g.SERVICE="Container"})(e.InvokeType||(e.InvokeType={}));const u=(0,t.getCallBridge)(),a=g=>{if(g&&Object.values(g).some(m=>typeof m=="function"))throw new r.BridgeAPIError("Passing functions as part of the payload is not supported!")},s=g=>async m=>{a(m);const h={...m,invokeType:`ui-${g.toLowerCase()}-fetch`},y=await u("invoke",h),{success:v,payload:_,error:f}=y??{},c={...v?_:f};if(c&&c.headers)for(const p in c.headers)Array.isArray(c.headers[p])&&(c.headers[p]=c.headers[p].join(","));return c},d=g=>{const m=s(g);return(0,n.withRateLimiter)(m,i,l,`${g} invocation calls are rate limited at ${i}/${o}s`)};e._invokeEndpointFn=d}(El)),El}var tf;function v0(){if(tf)return Dr;tf=1,Object.defineProperty(Dr,"__esModule",{value:!0}),Dr.invokeRemote=void 0;const e=gg(),t=r=>(0,e._invokeEndpointFn)(e.InvokeType.REMOTE)(r);return Dr.invokeRemote=t,Dr}var Ar={},rf;function g0(){if(rf)return Ar;rf=1,Object.defineProperty(Ar,"__esModule",{value:!0}),Ar.invokeService=void 0;const e=gg(),t=r=>(0,e._invokeEndpointFn)(e.InvokeType.SERVICE)(r);return Ar.invokeService=t,Ar}var nf;function m0(){return nf||(nf=1,function(e){Object.defineProperty(e,"__esModule",{value:!0});const t=me;t.__exportStar(v0(),e),t.__exportStar(g0(),e)}(Sl)),Sl}var kl={},Br={},qr={},of;function y0(){if(of)return qr;of=1,Object.defineProperty(qr,"__esModule",{value:!0}),qr.submit=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=async i=>{if(await r("submit",i)===!1)throw new t.BridgeAPIError("this resource's view is not submittable.")};return qr.submit=n,qr}var zr={},lf;function _0(){if(lf)return zr;lf=1,Object.defineProperty(zr,"__esModule",{value:!0}),zr.close=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=async i=>{try{if(await r("close",i)===!1)throw new t.BridgeAPIError("this resource's view is not closable.")}catch{throw new t.BridgeAPIError("this resource's view is not closable.")}};return zr.close=n,zr}var Ur={},uf;function w0(){if(uf)return Ur;uf=1,Object.defineProperty(Ur,"__esModule",{value:!0}),Ur.open=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=async()=>{try{if(await r("open")===!1)throw new t.BridgeAPIError("this resource's view is not openable.")}catch{throw new t.BridgeAPIError("this resource's view is not openable.")}};return Ur.open=n,Ur}var br={},af;function S0(){if(af)return br;af=1,Object.defineProperty(br,"__esModule",{value:!0}),br.refresh=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=async i=>{if(await r("refresh",i)===!1)throw new t.BridgeAPIError("this resource's view is not refreshable.")};return br.refresh=n,br}var Vr={},sf;function E0(){if(sf)return Vr;sf=1,Object.defineProperty(Vr,"__esModule",{value:!0}),Vr.createHistory=void 0;const t=(0,D().getCallBridge)(),r=async()=>{const n=await t("createHistory");return n.listen(i=>{n.location=i}),n};return Vr.createHistory=r,Vr}var Hr={},Cl={},Ge={},cf;function mg(){return cf||(cf=1,Object.defineProperty(Ge,"__esModule",{value:!0}),Ge.FORGE_SUPPORTED_LOCALE_CODES=Ge.I18N_BUNDLE_FOLDER_NAME=Ge.I18N_INFO_FILE_NAME=void 0,Ge.I18N_INFO_FILE_NAME="i18n-info.json",Ge.I18N_BUNDLE_FOLDER_NAME="__LOCALES__",Ge.FORGE_SUPPORTED_LOCALE_CODES=["zh-CN","zh-TW","cs-CZ","da-DK","nl-NL","en-US","en-GB","et-EE","fi-FI","fr-FR","de-DE","hu-HU","is-IS","it-IT","ja-JP","ko-KR","no-NO","pl-PL","pt-BR","pt-PT","ro-RO","ru-RU","sk-SK","tr-TR","es-ES","sv-SE"]),Ge}var Tt={},ff;function k0(){if(ff)return Tt;ff=1,Object.defineProperty(Tt,"__esModule",{value:!0}),Tt.TranslationsGetter=Tt.TranslationGetterError=void 0;const e=(n,i)=>{n.includes(i)||n.push(i)};class t extends Error{constructor(i){super(i),this.name="TranslationGetterError"}}Tt.TranslationGetterError=t;class r{constructor(i){it(this,"resourcesAccessor");it(this,"i18nInfoConfig",null);it(this,"translationResources",new Map);this.resourcesAccessor=i}async getTranslations(i,o={fallback:!0}){const l=await this.getI18nInfoConfig(),{fallback:u}=o;if(!u){let a;return l.locales.includes(i)&&(a=await this.getTranslationResource(i)),{translations:a??null,locale:i}}for(const a of this.getLocaleLookupOrder(i,l)){const s=await this.getTranslationResource(a);if(s)return{translations:s,locale:a}}return{translations:null,locale:i}}async getTranslationsByLocaleLookupOrder(i){const o=await this.getI18nInfoConfig(),l=this.getLocaleLookupOrder(i,o);return await Promise.all(l.map(async u=>{const a=await this.getTranslationResource(u);return{locale:u,translations:a}}))}reset(){this.i18nInfoConfig=null,this.translationResources.clear()}async getTranslationResource(i){let o=this.translationResources.get(i);if(!o)try{o=await this.resourcesAccessor.getTranslationResource(i),this.translationResources.set(i,o)}catch(l){throw l instanceof t?l:new t(`Failed to get translation resource for locale: ${i}`)}return o}async getI18nInfoConfig(){if(!this.i18nInfoConfig)try{this.i18nInfoConfig=await this.resourcesAccessor.getI18nInfoConfig()}catch(i){throw i instanceof t?i:new t("Failed to get i18n info config")}return this.i18nInfoConfig}getLocaleLookupOrder(i,o){const{locales:l,fallback:u}=o,a=[i],s=u[i];return s&&Array.isArray(s)&&s.length>0&&a.push(...s),e(a,o.fallback.default),a.filter(d=>l.includes(d))}}return Tt.TranslationsGetter=r,Tt}var Gr={},Pl={},Rl,df;function Ns(){if(df)return Rl;df=1;var e=Array.isArray;return Rl=e,Rl}var Ol,pf;function C0(){if(pf)return Ol;pf=1;var e=typeof hi=="object"&&hi&&hi.Object===Object&&hi;return Ol=e,Ol}var Tl,hf;function Ls(){if(hf)return Tl;hf=1;var e=C0(),t=typeof self=="object"&&self&&self.Object===Object&&self,r=e||t||Function("return this")();return Tl=r,Tl}var Il,vf;function Ds(){if(vf)return Il;vf=1;var e=Ls(),t=e.Symbol;return Il=t,Il}var xl,gf;function P0(){if(gf)return xl;gf=1;var e=Ds(),t=Object.prototype,r=t.hasOwnProperty,n=t.toString,i=e?e.toStringTag:void 0;function o(l){var u=r.call(l,i),a=l[i];try{l[i]=void 0;var s=!0}catch{}var d=n.call(l);return s&&(u?l[i]=a:delete l[i]),d}return xl=o,xl}var jl,mf;function R0(){if(mf)return jl;mf=1;var e=Object.prototype,t=e.toString;function r(n){return t.call(n)}return jl=r,jl}var Ml,yf;function yg(){if(yf)return Ml;yf=1;var e=Ds(),t=P0(),r=R0(),n="[object Null]",i="[object Undefined]",o=e?e.toStringTag:void 0;function l(u){return u==null?u===void 0?i:n:o&&o in Object(u)?t(u):r(u)}return Ml=l,Ml}var Fl,_f;function O0(){if(_f)return Fl;_f=1;function e(t){return t!=null&&typeof t=="object"}return Fl=e,Fl}var Nl,wf;function As(){if(wf)return Nl;wf=1;var e=yg(),t=O0(),r="[object Symbol]";function n(i){return typeof i=="symbol"||t(i)&&e(i)==r}return Nl=n,Nl}var Ll,Sf;function T0(){if(Sf)return Ll;Sf=1;var e=Ns(),t=As(),r=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,n=/^\w*$/;function i(o,l){if(e(o))return!1;var u=typeof o;return u=="number"||u=="symbol"||u=="boolean"||o==null||t(o)?!0:n.test(o)||!r.test(o)||l!=null&&o in Object(l)}return Ll=i,Ll}var Dl,Ef;function _g(){if(Ef)return Dl;Ef=1;function e(t){var r=typeof t;return t!=null&&(r=="object"||r=="function")}return Dl=e,Dl}var Al,kf;function I0(){if(kf)return Al;kf=1;var e=yg(),t=_g(),r="[object AsyncFunction]",n="[object Function]",i="[object GeneratorFunction]",o="[object Proxy]";function l(u){if(!t(u))return!1;var a=e(u);return a==n||a==i||a==r||a==o}return Al=l,Al}var Bl,Cf;function x0(){if(Cf)return Bl;Cf=1;var e=Ls(),t=e["__core-js_shared__"];return Bl=t,Bl}var ql,Pf;function j0(){if(Pf)return ql;Pf=1;var e=x0(),t=function(){var n=/[^.]+$/.exec(e&&e.keys&&e.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}();function r(n){return!!t&&t in n}return ql=r,ql}var zl,Rf;function M0(){if(Rf)return zl;Rf=1;var e=Function.prototype,t=e.toString;function r(n){if(n!=null){try{return t.call(n)}catch{}try{return n+""}catch{}}return""}return zl=r,zl}var Ul,Of;function F0(){if(Of)return Ul;Of=1;var e=I0(),t=j0(),r=_g(),n=M0(),i=/[\\^$.*+?()[\]{}|]/g,o=/^\[object .+?Constructor\]$/,l=Function.prototype,u=Object.prototype,a=l.toString,s=u.hasOwnProperty,d=RegExp("^"+a.call(s).replace(i,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function g(m){if(!r(m)||t(m))return!1;var h=e(m)?d:o;return h.test(n(m))}return Ul=g,Ul}var bl,Tf;function N0(){if(Tf)return bl;Tf=1;function e(t,r){return t==null?void 0:t[r]}return bl=e,bl}var Vl,If;function wg(){if(If)return Vl;If=1;var e=F0(),t=N0();function r(n,i){var o=t(n,i);return e(o)?o:void 0}return Vl=r,Vl}var Hl,xf;function Ao(){if(xf)return Hl;xf=1;var e=wg(),t=e(Object,"create");return Hl=t,Hl}var Gl,jf;function L0(){if(jf)return Gl;jf=1;var e=Ao();function t(){this.__data__=e?e(null):{},this.size=0}return Gl=t,Gl}var Wl,Mf;function D0(){if(Mf)return Wl;Mf=1;function e(t){var r=this.has(t)&&delete this.__data__[t];return this.size-=r?1:0,r}return Wl=e,Wl}var $l,Ff;function A0(){if(Ff)return $l;Ff=1;var e=Ao(),t="__lodash_hash_undefined__",r=Object.prototype,n=r.hasOwnProperty;function i(o){var l=this.__data__;if(e){var u=l[o];return u===t?void 0:u}return n.call(l,o)?l[o]:void 0}return $l=i,$l}var Kl,Nf;function B0(){if(Nf)return Kl;Nf=1;var e=Ao(),t=Object.prototype,r=t.hasOwnProperty;function n(i){var o=this.__data__;return e?o[i]!==void 0:r.call(o,i)}return Kl=n,Kl}var Ql,Lf;function q0(){if(Lf)return Ql;Lf=1;var e=Ao(),t="__lodash_hash_undefined__";function r(n,i){var o=this.__data__;return this.size+=this.has(n)?0:1,o[n]=e&&i===void 0?t:i,this}return Ql=r,Ql}var Yl,Df;function z0(){if(Df)return Yl;Df=1;var e=L0(),t=D0(),r=A0(),n=B0(),i=q0();function o(l){var u=-1,a=l==null?0:l.length;for(this.clear();++u-1}return ru=t,ru}var nu,Vf;function W0(){if(Vf)return nu;Vf=1;var e=Bo();function t(r,n){var i=this.__data__,o=e(i,r);return o<0?(++this.size,i.push([r,n])):i[o][1]=n,this}return nu=t,nu}var iu,Hf;function $0(){if(Hf)return iu;Hf=1;var e=U0(),t=V0(),r=H0(),n=G0(),i=W0();function o(l){var u=-1,a=l==null?0:l.length;for(this.clear();++u{const a=o[u];return a?(0,e.getTranslationValueFromContent)(a,l):null};e.getTranslationValue=n;const i=(o,l)=>{let u=o[l];if(!u){const a=l.split(".");a.length>1&&(u=(0,r.default)(o,a,null))}return typeof u=="string"?u:null};e.getTranslationValueFromContent=i}(Pl)),Pl}var fd;function d1(){if(fd)return Gr;fd=1,Object.defineProperty(Gr,"__esModule",{value:!0}),Gr.Translator=void 0;const e=Sg();class t{constructor(n,i){it(this,"locale");it(this,"translationsGetter");it(this,"localeLookupOrderedTranslations",null);it(this,"cache",new Map);this.locale=n,this.translationsGetter=i}async init(){this.localeLookupOrderedTranslations=await this.translationsGetter.getTranslationsByLocaleLookupOrder(this.locale)}translate(n){if(!this.localeLookupOrderedTranslations)throw new Error("TranslationLookup not initialized");let i=this.cache.get(n);if(i===void 0){for(const{translations:o}of this.localeLookupOrderedTranslations){const l=(0,e.getTranslationValueFromContent)(o,n);if(l!==null){i=l;break}}i=i??null,this.cache.set(n,i)}return i}}return Gr.Translator=t,Gr}var Wr={},dd;function p1(){if(dd)return Wr;dd=1,Object.defineProperty(Wr,"__esModule",{value:!0}),Wr.ensureLocale=void 0;const e=mg(),t=new Set(e.FORGE_SUPPORTED_LOCALE_CODES),r={"en-UK":"en-GB","nb-NO":"no-NO"},n=e.FORGE_SUPPORTED_LOCALE_CODES.reduce((o,l)=>{const[u]=l.split("-");return o[u]||(o[u]=l),o},{nb:"no-NO",pt:"pt-PT"}),i=o=>{const l=o.replace("_","-");return t.has(l)?l:n[l]??r[l]??null};return Wr.ensureLocale=i,Wr}var Cu={},pd;function h1(){return pd||(pd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.extractI18nPropertiesFromModules=e.extractI18nKeysFromModules=e.getI18nSupportedModuleEntries=void 0;const t=s=>typeof s=="object"&&s!==null&&!Array.isArray(s),r=s=>typeof(s==null?void 0:s.i18n)=="string",n=s=>s.startsWith("connect-"),i=s=>s.startsWith("core:"),o=s=>{const d=new Set,g=(m,h)=>!t(m)||d.has(m)?[]:(d.add(m),Object.entries(m).flatMap(([y,v])=>{const _=[...h,y];return r(v)?[{propertyPath:_,key:v.i18n}]:Array.isArray(v)?v.flatMap(f=>g(f,_)):g(v,_)}));return g(s,[])},l=s=>Object.entries(s).flatMap(([d,g])=>!n(d)&&!i(d)&&g&&Array.isArray(g)&&g.length>0?g.map(m=>[m,d]):[]);e.getI18nSupportedModuleEntries=l;const u=s=>{const d=new Set;for(const g of(0,e.getI18nSupportedModuleEntries)(s)){const m=o(g[0]);for(const{key:h}of m)d.add(h)}return d.size>0?Array.from(d):[]};e.extractI18nKeysFromModules=u;const a=s=>{const d=[];for(const g of(0,e.getI18nSupportedModuleEntries)(s)){const m=o(g[0]);for(const h of m)d.push({moduleName:g[1],...h})}return d};e.extractI18nPropertiesFromModules=a}(Cu)),Cu}var Pu={},hd;function v1(){return hd||(hd=1,Object.defineProperty(Pu,"__esModule",{value:!0})),Pu}var vd;function Eg(){return vd||(vd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.getI18nSupportedModuleEntries=e.extractI18nPropertiesFromModules=e.extractI18nKeysFromModules=e.getTranslationValue=void 0;const t=me;t.__exportStar(mg(),e),t.__exportStar(k0(),e),t.__exportStar(d1(),e),t.__exportStar(p1(),e);var r=Sg();Object.defineProperty(e,"getTranslationValue",{enumerable:!0,get:function(){return r.getTranslationValue}});var n=h1();Object.defineProperty(e,"extractI18nKeysFromModules",{enumerable:!0,get:function(){return n.extractI18nKeysFromModules}}),Object.defineProperty(e,"extractI18nPropertiesFromModules",{enumerable:!0,get:function(){return n.extractI18nPropertiesFromModules}}),Object.defineProperty(e,"getI18nSupportedModuleEntries",{enumerable:!0,get:function(){return n.getI18nSupportedModuleEntries}}),t.__exportStar(v1(),e)}(Cl)),Cl}var gd;function g1(){if(gd)return Hr;gd=1,Object.defineProperty(Hr,"__esModule",{value:!0}),Hr.getContext=void 0;const e=D(),t=Eg(),r=(0,e.getCallBridge)(),n=async()=>{var i;const o=await r("getContext"),l=o==null?void 0:o.locale;return l&&(o.locale=(i=(0,t.ensureLocale)(l))!==null&&i!==void 0?i:l),o};return Hr.getContext=n,Hr}var $r={},md;function m1(){if(md)return $r;md=1,Object.defineProperty($r,"__esModule",{value:!0}),$r.changeWindowTitle=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=async i=>{try{await r("changeWindowTitle",i)}catch{throw new t.BridgeAPIError("the window title wasn't changed due to error.")}};return $r.changeWindowTitle=n,$r}var Kr={},yd;function y1(){if(yd)return Kr;yd=1,Object.defineProperty(Kr,"__esModule",{value:!0}),Kr.theme=void 0;const t=(0,D().getCallBridge)();return Kr.theme={enable:()=>t("enableTheming")},Kr}var Qr={},Yr={},Ru={},It={},_d;function kg(){if(_d)return It;_d=1,Object.defineProperty(It,"__esModule",{value:!0}),It.blobToBase64=It.base64ToBlob=void 0;const e=(r,n)=>{if(!r)return null;const i=r.includes(";base64")?r.split(",")[1]:r,o=atob(i),l=new Array(o.length);for(let a=0;anew Promise((n,i)=>{const o=new FileReader;o.onloadend=()=>{n(o.result)},o.onerror=i,o.readAsDataURL(r)});return It.blobToBase64=t,It}var wd;function _1(){return wd||(wd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.containsSerialisedBlobs=e.containsBlobs=e.deserialiseBlobsInPayload=e.serialiseBlobsInPayload=void 0;const t=kg(),r=s=>{if(typeof s!="object"||s===null||Object.prototype.toString.call(s)!=="[object Object]")return!1;const d=Object.getPrototypeOf(s);if(d===null)return!0;const g=Object.prototype.hasOwnProperty.call(d,"constructor")&&d.constructor;return typeof g=="function"&&g instanceof g&&Function.prototype.call(g)===Function.prototype.call(s)},n=async s=>({data:await(0,t.blobToBase64)(s),type:s.type}),i=s=>(0,t.base64ToBlob)(s.data,s.type),o=async s=>{if(s instanceof Blob)return{...await n(s),__isBlobData:!0};if(Array.isArray(s))return Promise.all(s.map(d=>(0,e.serialiseBlobsInPayload)(d)));if(s&&r(s)){const d=await Promise.all(Object.entries(s).map(async([g,m])=>[g,await(0,e.serialiseBlobsInPayload)(m)]));return Object.fromEntries(d)}return s};e.serialiseBlobsInPayload=o;const l=s=>{if(s&&r(s)&&"__isBlobData"in s){const d=s;return i({data:d.data,type:d.type})}if(Array.isArray(s))return s.map(d=>(0,e.deserialiseBlobsInPayload)(d));if(s&&r(s)){const d={};for(const[g,m]of Object.entries(s))d[g]=(0,e.deserialiseBlobsInPayload)(m);return d}return s};e.deserialiseBlobsInPayload=l;const u=s=>s instanceof Blob?!0:Array.isArray(s)?s.some(d=>(0,e.containsBlobs)(d)):s&&r(s)?Object.values(s).some(d=>(0,e.containsBlobs)(d)):!1;e.containsBlobs=u;const a=s=>s&&r(s)&&"__isBlobData"in s?!0:Array.isArray(s)?s.some(d=>(0,e.containsSerialisedBlobs)(d)):s&&r(s)?Object.values(s).some(d=>(0,e.containsSerialisedBlobs)(d)):!1;e.containsSerialisedBlobs=a}(Ru)),Ru}var Sd;function Cg(){if(Sd)return Yr;Sd=1,Object.defineProperty(Yr,"__esModule",{value:!0}),Yr.events=void 0;const e=D(),t=_1(),r=(0,e.getCallBridge)(),n=a=>s=>{let d=s;return(0,t.containsSerialisedBlobs)(s)&&(d=(0,t.deserialiseBlobsInPayload)(s)),a(d)},i=async(a,s)=>{let d=s;return(0,t.containsBlobs)(s)&&(d=await(0,t.serialiseBlobsInPayload)(s)),r("emit",{event:a,payload:d})},o=(a,s)=>r("on",{event:a,callback:n(s)}),l=async(a,s)=>{let d=s;return(0,t.containsBlobs)(s)&&(d=await(0,t.serialiseBlobsInPayload)(s)),r("emitPublic",{event:a,payload:d})},u=(a,s)=>r("onPublic",{event:a,callback:n(s)});return Yr.events={emit:i,on:o,emitPublic:l,onPublic:u},Yr}var Ed;function w1(){if(Ed)return Qr;Ed=1,Object.defineProperty(Qr,"__esModule",{value:!0}),Qr.emitReadyEvent=void 0;const e=Cg(),t=Tg(),n=(0,D().getCallBridge)(),i="EXTENSION_READY",o=async()=>{const l=await t.view.getContext();await e.events.emit(i,{localId:l.localId});try{await n("emitReadyEvent")}catch{}};return Qr.emitReadyEvent=o,Qr}const S1="modulepreload",E1=function(e,t){return new URL(e,t).href},kd={},k1=function(t,r,n){let i=Promise.resolve();if(r&&r.length>0){const l=document.getElementsByTagName("link"),u=document.querySelector("meta[property=csp-nonce]"),a=(u==null?void 0:u.nonce)||(u==null?void 0:u.getAttribute("nonce"));i=Promise.allSettled(r.map(s=>{if(s=E1(s,n),s in kd)return;kd[s]=!0;const d=s.endsWith(".css"),g=d?'[rel="stylesheet"]':"";if(!!n)for(let y=l.length-1;y>=0;y--){const v=l[y];if(v.href===s&&(!d||v.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${s}"]${g}`))return;const h=document.createElement("link");if(h.rel=d?"stylesheet":S1,d||(h.as="script"),h.crossOrigin="",h.href=s,a&&h.setAttribute("nonce",a),document.head.appendChild(h),d)return new Promise((y,v)=>{h.addEventListener("load",y),h.addEventListener("error",()=>v(new Error(`Unable to preload CSS for ${s}`)))})}))}function o(l){const u=new Event("vite:preloadError",{cancelable:!0});if(u.payload=l,window.dispatchEvent(u),!u.defaultPrevented)throw l}return i.then(l=>{for(const u of l||[])u.status==="rejected"&&o(u.reason);return t().catch(o)})};var Xr={},Ou={},Jr={},Mi={},Cd;function Pg(){if(Cd)return Mi;Cd=1,Object.defineProperty(Mi,"__esModule",{value:!0}),Mi.default=r;let e;const t=new Uint8Array(16);function r(){if(!e&&(e=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!e))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return e(t)}return Mi}var $t={},Zr={},en={},Pd;function C1(){if(Pd)return en;Pd=1,Object.defineProperty(en,"__esModule",{value:!0}),en.default=void 0;var e=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;return en.default=e,en}var Rd;function zo(){if(Rd)return Zr;Rd=1,Object.defineProperty(Zr,"__esModule",{value:!0}),Zr.default=void 0;var e=t(C1());function t(i){return i&&i.__esModule?i:{default:i}}function r(i){return typeof i=="string"&&e.default.test(i)}var n=r;return Zr.default=n,Zr}var Od;function Uo(){if(Od)return $t;Od=1,Object.defineProperty($t,"__esModule",{value:!0}),$t.default=void 0,$t.unsafeStringify=n;var e=t(zo());function t(l){return l&&l.__esModule?l:{default:l}}const r=[];for(let l=0;l<256;++l)r.push((l+256).toString(16).slice(1));function n(l,u=0){return r[l[u+0]]+r[l[u+1]]+r[l[u+2]]+r[l[u+3]]+"-"+r[l[u+4]]+r[l[u+5]]+"-"+r[l[u+6]]+r[l[u+7]]+"-"+r[l[u+8]]+r[l[u+9]]+"-"+r[l[u+10]]+r[l[u+11]]+r[l[u+12]]+r[l[u+13]]+r[l[u+14]]+r[l[u+15]]}function i(l,u=0){const a=n(l,u);if(!(0,e.default)(a))throw TypeError("Stringified UUID is invalid");return a}var o=i;return $t.default=o,$t}var Td;function P1(){if(Td)return Jr;Td=1,Object.defineProperty(Jr,"__esModule",{value:!0}),Jr.default=void 0;var e=r(Pg()),t=Uo();function r(s){return s&&s.__esModule?s:{default:s}}let n,i,o=0,l=0;function u(s,d,g){let m=d&&g||0;const h=d||new Array(16);s=s||{};let y=s.node||n,v=s.clockseq!==void 0?s.clockseq:i;if(y==null||v==null){const S=s.random||(s.rng||e.default)();y==null&&(y=n=[S[0]|1,S[1],S[2],S[3],S[4],S[5]]),v==null&&(v=i=(S[6]<<8|S[7])&16383)}let _=s.msecs!==void 0?s.msecs:Date.now(),f=s.nsecs!==void 0?s.nsecs:l+1;const c=_-o+(f-l)/1e4;if(c<0&&s.clockseq===void 0&&(v=v+1&16383),(c<0||_>o)&&s.nsecs===void 0&&(f=0),f>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");o=_,l=f,i=v,_+=122192928e5;const p=((_&268435455)*1e4+f)%4294967296;h[m++]=p>>>24&255,h[m++]=p>>>16&255,h[m++]=p>>>8&255,h[m++]=p&255;const w=_/4294967296*1e4&268435455;h[m++]=w>>>8&255,h[m++]=w&255,h[m++]=w>>>24&15|16,h[m++]=w>>>16&255,h[m++]=v>>>8|128,h[m++]=v&255;for(let S=0;S<6;++S)h[m+S]=y[S];return d||(0,t.unsafeStringify)(h)}var a=u;return Jr.default=a,Jr}var tn={},lt={},rn={},Id;function Rg(){if(Id)return rn;Id=1,Object.defineProperty(rn,"__esModule",{value:!0}),rn.default=void 0;var e=t(zo());function t(i){return i&&i.__esModule?i:{default:i}}function r(i){if(!(0,e.default)(i))throw TypeError("Invalid UUID");let o;const l=new Uint8Array(16);return l[0]=(o=parseInt(i.slice(0,8),16))>>>24,l[1]=o>>>16&255,l[2]=o>>>8&255,l[3]=o&255,l[4]=(o=parseInt(i.slice(9,13),16))>>>8,l[5]=o&255,l[6]=(o=parseInt(i.slice(14,18),16))>>>8,l[7]=o&255,l[8]=(o=parseInt(i.slice(19,23),16))>>>8,l[9]=o&255,l[10]=(o=parseInt(i.slice(24,36),16))/1099511627776&255,l[11]=o/4294967296&255,l[12]=o>>>24&255,l[13]=o>>>16&255,l[14]=o>>>8&255,l[15]=o&255,l}var n=r;return rn.default=n,rn}var xd;function Og(){if(xd)return lt;xd=1,Object.defineProperty(lt,"__esModule",{value:!0}),lt.URL=lt.DNS=void 0,lt.default=l;var e=Uo(),t=r(Rg());function r(u){return u&&u.__esModule?u:{default:u}}function n(u){u=unescape(encodeURIComponent(u));const a=[];for(let s=0;s>5]>>>f%32&255,p=parseInt(_.charAt(c>>>4&15)+_.charAt(c&15),16);y.push(p)}return y}function r(h){return(h+64>>>9<<4)+14+1}function n(h,y){h[y>>5]|=128<>5]|=(h[_/8]&255)<<_%32;return v}function o(h,y){const v=(h&65535)+(y&65535);return(h>>16)+(y>>16)+(v>>16)<<16|v&65535}function l(h,y){return h<>>32-y}function u(h,y,v,_,f,c){return o(l(o(o(y,h),o(_,c)),f),v)}function a(h,y,v,_,f,c,p){return u(y&v|~y&_,h,y,f,c,p)}function s(h,y,v,_,f,c,p){return u(y&_|v&~_,h,y,f,c,p)}function d(h,y,v,_,f,c,p){return u(y^v^_,h,y,f,c,p)}function g(h,y,v,_,f,c,p){return u(v^(y|~_),h,y,f,c,p)}var m=e;return nn.default=m,nn}var Md;function O1(){if(Md)return tn;Md=1,Object.defineProperty(tn,"__esModule",{value:!0}),tn.default=void 0;var e=r(Og()),t=r(R1());function r(o){return o&&o.__esModule?o:{default:o}}var i=(0,e.default)("v3",48,t.default);return tn.default=i,tn}var on={},ln={},Fd;function T1(){if(Fd)return ln;Fd=1,Object.defineProperty(ln,"__esModule",{value:!0}),ln.default=void 0;var t={randomUUID:typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto)};return ln.default=t,ln}var Nd;function I1(){if(Nd)return on;Nd=1,Object.defineProperty(on,"__esModule",{value:!0}),on.default=void 0;var e=n(T1()),t=n(Pg()),r=Uo();function n(l){return l&&l.__esModule?l:{default:l}}function i(l,u,a){if(e.default.randomUUID&&!u&&!l)return e.default.randomUUID();l=l||{};const s=l.random||(l.rng||t.default)();if(s[6]=s[6]&15|64,s[8]=s[8]&63|128,u){a=a||0;for(let d=0;d<16;++d)u[a+d]=s[d];return u}return(0,r.unsafeStringify)(s)}var o=i;return on.default=o,on}var un={},an={},Ld;function x1(){if(Ld)return an;Ld=1,Object.defineProperty(an,"__esModule",{value:!0}),an.default=void 0;function e(i,o,l,u){switch(i){case 0:return o&l^~o&u;case 1:return o^l^u;case 2:return o&l^o&u^l&u;case 3:return o^l^u}}function t(i,o){return i<>>32-o}function r(i){const o=[1518500249,1859775393,2400959708,3395469782],l=[1732584193,4023233417,2562383102,271733878,3285377520];if(typeof i=="string"){const d=unescape(encodeURIComponent(i));i=[];for(let g=0;g>>0;_=v,v=y,y=t(h,30)>>>0,h=m,m=p}l[0]=l[0]+m>>>0,l[1]=l[1]+h>>>0,l[2]=l[2]+y>>>0,l[3]=l[3]+v>>>0,l[4]=l[4]+_>>>0}return[l[0]>>24&255,l[0]>>16&255,l[0]>>8&255,l[0]&255,l[1]>>24&255,l[1]>>16&255,l[1]>>8&255,l[1]&255,l[2]>>24&255,l[2]>>16&255,l[2]>>8&255,l[2]&255,l[3]>>24&255,l[3]>>16&255,l[3]>>8&255,l[3]&255,l[4]>>24&255,l[4]>>16&255,l[4]>>8&255,l[4]&255]}var n=r;return an.default=n,an}var Dd;function j1(){if(Dd)return un;Dd=1,Object.defineProperty(un,"__esModule",{value:!0}),un.default=void 0;var e=r(Og()),t=r(x1());function r(o){return o&&o.__esModule?o:{default:o}}var i=(0,e.default)("v5",80,t.default);return un.default=i,un}var sn={},Ad;function M1(){if(Ad)return sn;Ad=1,Object.defineProperty(sn,"__esModule",{value:!0}),sn.default=void 0;var e="00000000-0000-0000-0000-000000000000";return sn.default=e,sn}var cn={},Bd;function F1(){if(Bd)return cn;Bd=1,Object.defineProperty(cn,"__esModule",{value:!0}),cn.default=void 0;var e=t(zo());function t(i){return i&&i.__esModule?i:{default:i}}function r(i){if(!(0,e.default)(i))throw TypeError("Invalid UUID");return parseInt(i.slice(14,15),16)}var n=r;return cn.default=n,cn}var qd;function N1(){return qd||(qd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"NIL",{enumerable:!0,get:function(){return o.default}}),Object.defineProperty(e,"parse",{enumerable:!0,get:function(){return s.default}}),Object.defineProperty(e,"stringify",{enumerable:!0,get:function(){return a.default}}),Object.defineProperty(e,"v1",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"v3",{enumerable:!0,get:function(){return r.default}}),Object.defineProperty(e,"v4",{enumerable:!0,get:function(){return n.default}}),Object.defineProperty(e,"v5",{enumerable:!0,get:function(){return i.default}}),Object.defineProperty(e,"validate",{enumerable:!0,get:function(){return u.default}}),Object.defineProperty(e,"version",{enumerable:!0,get:function(){return l.default}});var t=d(P1()),r=d(O1()),n=d(I1()),i=d(j1()),o=d(M1()),l=d(F1()),u=d(zo()),a=d(Uo()),s=d(Rg());function d(g){return g&&g.__esModule?g:{default:g}}}(Ou)),Ou}var zd;function L1(){if(zd)return Xr;zd=1,Object.defineProperty(Xr,"__esModule",{value:!0}),Xr.createAdfRendererIframeProps=void 0;const e=N1(),t=async(r,n)=>{const i=await k1(()=>import("./index-BLip8HpJ.js").then(d=>d.i),[],import.meta.url),o=i.default||i,l=new URL(document.referrer).origin,u=`${l}/forge-apps/adf-renderer`,a=n||`forge-adf-renderer-iframe-${(0,e.v4)()}`,s=()=>{var d,g,m,h,y,v;const _=document.getElementById(a),f={type:"adf-document",document:(d=r.extension.macro)===null||d===void 0?void 0:d.body,timestamp:Date.now(),source:"forge-adf-renderer",localId:r.localId,isEditing:(m=(g=r.extension)===null||g===void 0?void 0:g.isEditing)!==null&&m!==void 0?m:!1,contentId:(y=(h=r.extension)===null||h===void 0?void 0:h.content)===null||y===void 0?void 0:y.id};o.iframeResizer({heightCalculationMethod:"taggedElement",widthCalculationMethod:"bodyScroll",initCallback:c=>{var p;(p=c==null?void 0:c.iFrameResizer)===null||p===void 0||p.resize()}},_||""),(v=_==null?void 0:_.contentWindow)===null||v===void 0||v.postMessage(f,l)};return setTimeout(()=>{document.documentElement.style.height="auto",document.body.style.height="auto"},200),{id:a,src:u,onLoad:s}};return Xr.createAdfRendererIframeProps=t,Xr}var fn={},Ud;function D1(){if(Ud)return fn;Ud=1,Object.defineProperty(fn,"__esModule",{value:!0}),fn.onClose=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=async i=>{try{if(await r("onClose",i)===!1)throw new t.BridgeAPIError("`onClose` call has failed.")}catch{throw new t.BridgeAPIError("`onClose` failed because this resource's view is not closable.")}};return fn.onClose=n,fn}var bd;function Tg(){if(bd)return Br;bd=1,Object.defineProperty(Br,"__esModule",{value:!0}),Br.view=void 0;const e=y0(),t=_0(),r=w0(),n=S0(),i=E0(),o=g1(),l=m1(),u=y1(),a=w1(),s=L1(),d=D1();return Br.view={submit:e.submit,close:t.close,onClose:d.onClose,open:r.open,refresh:n.refresh,createHistory:i.createHistory,getContext:o.getContext,theme:u.theme,changeWindowTitle:l.changeWindowTitle,emitReadyEvent:a.emitReadyEvent,createAdfRendererIframeProps:s.createAdfRendererIframeProps},Br}var Vd;function bo(){return Vd||(Vd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),me.__exportStar(Tg(),e)}(kl)),kl}var Tu={},dn={},Hd;function A1(){if(Hd)return dn;Hd=1,Object.defineProperty(dn,"__esModule",{value:!0}),dn.router=void 0;const t=(0,D().getCallBridge)(),r=async l=>{if(!(l!=null&&l.target))throw new Error("target is required for getUrl");const u=await t("getUrl",l);if(!u)throw new Error("Failed to get URL");try{return new URL(u)}catch(a){throw new Error(`Failed to parse URL: ${u} (${a})`)}},n=l=>{if(typeof l=="string")return t("navigate",{url:l,type:"same-tab"});if(!(l!=null&&l.target))throw new Error("target is required for navigation");return t("navigate",{...l,type:"same-tab"})},i=l=>{if(typeof l=="string")return t("navigate",{url:l,type:"new-tab"});if(!(l!=null&&l.target))throw new Error("target is required for navigation");return t("navigate",{...l,type:"new-tab"})},o=async()=>t("reload");return dn.router={getUrl:r,navigate:n,open:i,reload:o},dn}var Gd;function B1(){return Gd||(Gd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),me.__exportStar(A1(),e)}(Tu)),Tu}var Iu={},pn={},Wd;function q1(){if(Wd)return pn;Wd=1,Object.defineProperty(pn,"__esModule",{value:!0}),pn.Modal=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=()=>{};class i{constructor(l){var u,a;this.resource=(l==null?void 0:l.resource)||null,this.onClose=(l==null?void 0:l.onClose)||n,this.size=(l==null?void 0:l.size)||"medium",this.context=(l==null?void 0:l.context)||{},this.closeOnEscape=(u=l==null?void 0:l.closeOnEscape)!==null&&u!==void 0?u:!0,this.closeOnOverlayClick=(a=l==null?void 0:l.closeOnOverlayClick)!==null&&a!==void 0?a:!0,this.title=(l==null?void 0:l.title)||"",this.icon=(l==null?void 0:l.icon)||""}async open(){try{if(await r("openModal",{resource:this.resource,onClose:this.onClose,size:this.size,context:this.context,closeOnEscape:this.closeOnEscape,closeOnOverlayClick:this.closeOnOverlayClick,title:this.title,icon:this.icon})===!1)throw new t.BridgeAPIError("Unable to open modal.")}catch{throw new t.BridgeAPIError("Unable to open modal.")}}}return pn.Modal=i,pn}var $d;function z1(){return $d||($d=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),me.__exportStar(q1(),e)}(Iu)),Iu}var Me={},xt={},Kd;function U1(){if(Kd)return xt;Kd=1,Object.defineProperty(xt,"__esModule",{value:!0}),xt.productFetchApi=xt.remoteFetchApi=void 0;const e=kg(),t=async(l,u=!1)=>{const a={};for(const[s,d]of l.entries())if(u?s.startsWith("file"):s==="file"){const m=d.name,h=d.type;a[s]=await(0,e.blobToBase64)(d),a[`__${s}Name`]=m,a[`__${s}Type`]=h}else a[s]=d;return JSON.stringify(a)},r=l=>{if(!l)return l;if("signal"in l){const{signal:u,...a}=l;return console.error("Signal is not supported in @forge/bridge and was removed from fetch options. Please use the fetch method from @forge/api for signal support."),a}return l},n=async(l,u)=>{const a=(u==null?void 0:u.body)instanceof FormData,s=a?await t(u==null?void 0:u.body,l==="remote"):u==null?void 0:u.body,d=new Request("",{body:s,method:u==null?void 0:u.method,headers:u==null?void 0:u.headers}),g=Object.fromEntries(d.headers.entries());return{body:d.method!=="GET"?await d.text():null,headers:new Headers(g),isMultipartFormData:a}},i=l=>{const u=async(a,s)=>{const d=r(s),{body:g,headers:m,isMultipartFormData:h}=await n("remote",d),y={remoteKey:a,fetchRequestInit:{...d,body:g,headers:[...m.entries()]},isMultipartFormData:h},{body:v,headers:_,statusText:f,status:c,isAttachment:p}=await l("fetchRemote",y),w=p?(0,e.base64ToBlob)(v,_["content-type"]):v;return new Response(w||null,{headers:_,status:c,statusText:f})};return{requestRemote:(a,s)=>u(a,s)}};xt.remoteFetchApi=i;const o=l=>{const u=async(a,s,d)=>{const g=r(d),{body:m,headers:h,isMultipartFormData:y}=await n("product",g);h.has("X-Atlassian-Token")||h.set("X-Atlassian-Token","no-check");const v={product:a,restPath:s,fetchRequestInit:{...g,body:m,headers:[...h.entries()]},isMultipartFormData:y},{body:_,headers:f,statusText:c,status:p,isAttachment:w}=await l("fetchProduct",v),S=w?(0,e.base64ToBlob)(_,f["content-type"]):_;return new Response(S||null,{headers:f,status:p,statusText:c})};return{requestConfluence:(a,s)=>u("confluence",a,s),requestJira:(a,s)=>u("jira",a,s),requestBitbucket:(a,s)=>u("bitbucket",a,s)}};return xt.productFetchApi=o,xt}var Qd;function b1(){if(Qd)return Me;Qd=1;var e;Object.defineProperty(Me,"__esModule",{value:!0}),Me.requestRemote=Me.requestBitbucket=Me.requestJira=Me.requestConfluence=void 0;const t=D(),r=U1();return e=(0,r.productFetchApi)((0,t.getCallBridge)()),Me.requestConfluence=e.requestConfluence,Me.requestJira=e.requestJira,Me.requestBitbucket=e.requestBitbucket,Me.requestRemote=(0,r.remoteFetchApi)((0,t.getCallBridge)()).requestRemote,Me}var xu={},hn={},Yd;function V1(){if(Yd)return hn;Yd=1,Object.defineProperty(hn,"__esModule",{value:!0}),hn.showFlag=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=i=>{var o;if(!i.id)throw new t.BridgeAPIError('"id" must be defined in flag options');const l=r("showFlag",{...i,type:(o=i.type)!==null&&o!==void 0?o:"info"});return{close:async()=>(await l,r("closeFlag",{id:i.id}))}};return hn.showFlag=n,hn}var Xd;function H1(){return Xd||(Xd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.showFlag=void 0;var t=V1();Object.defineProperty(e,"showFlag",{enumerable:!0,get:function(){return t.showFlag}})}(xu)),xu}var ju={},Jd;function G1(){return Jd||(Jd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),me.__exportStar(Cg(),e)}(ju)),ju}var Mu={},vn={},Zd;function W1(){if(Zd)return vn;Zd=1,Object.defineProperty(vn,"__esModule",{value:!0}),vn.realtime=void 0;const t=(0,D().getCallBridge)(),r=(l,u,a)=>t("publishRealtimeChannel",{channelName:l,eventPayload:u,options:a}),n=(l,u,a)=>t("subscribeRealtimeChannel",{channelName:l,onEvent:u,options:a}),i=(l,u,a)=>t("publishRealtimeChannel",{channelName:l,eventPayload:u,options:a,isGlobal:!0}),o=(l,u,a)=>t("subscribeRealtimeChannel",{channelName:l,onEvent:u,options:a,isGlobal:!0});return vn.realtime={publish:r,subscribe:n,publishGlobal:i,subscribeGlobal:o},vn}var Fu={},ep;function $1(){return ep||(ep=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.Bitbucket=e.Confluence=e.Jira=void 0,function(t){t.Board="board",t.Issue="issue",t.Project="project"}(e.Jira||(e.Jira={})),function(t){t.Content="content",t.Space="space"}(e.Confluence||(e.Confluence={})),function(t){t.Repository="repository",t.PullRequest="pullRequest"}(e.Bitbucket||(e.Bitbucket={}))}(Fu)),Fu}var tp;function K1(){return tp||(tp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.Bitbucket=e.Confluence=e.Jira=e.realtime=void 0;var t=W1();Object.defineProperty(e,"realtime",{enumerable:!0,get:function(){return t.realtime}});var r=$1();Object.defineProperty(e,"Jira",{enumerable:!0,get:function(){return r.Jira}}),Object.defineProperty(e,"Confluence",{enumerable:!0,get:function(){return r.Confluence}}),Object.defineProperty(e,"Bitbucket",{enumerable:!0,get:function(){return r.Bitbucket}})}(Mu)),Mu}var Nu={},gn={},Lu={},rp;function Q1(){return rp||(rp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.open=e.OPEN_ROVO_BRIDGE_ERROR_MESSAGE=void 0;const t=D(),r=Q(),n=30,i=(0,t.getCallBridge)();e.OPEN_ROVO_BRIDGE_ERROR_MESSAGE="Unable to open Rovo Chat due to usage in an unsupported product. Only Confluence, Jira and some Jira Service Management modules are supported at this point. See https://developer.atlassian.com/platform/forge/apis-reference/ui-api-bridge/rovo/";const o=u=>{switch(u.type){case"forge":return{agentName:u.agentName,agentKey:u.agentKey,prompt:u.prompt};case"atlassian":return{agentName:u.agentName,prompt:u.prompt};default:return{prompt:u.prompt}}},l=async u=>{if(u.type==="forge"){if(u.agentName.length>n)throw new Error("rovo agent name too long");if(u.agentKey.length>n)throw new Error("rovo agent key too long")}const a=o(u);if(await i("openRovo",a)===!1)throw new r.BridgeAPIError(e.OPEN_ROVO_BRIDGE_ERROR_MESSAGE)};e.open=l}(Lu)),Lu}var mn={},np;function Y1(){if(np)return mn;np=1,Object.defineProperty(mn,"__esModule",{value:!0}),mn.isEnabled=void 0;const t=(0,D().getCallBridge)(),r=()=>t("isRovoEnabled");return mn.isEnabled=r,mn}var ip;function X1(){if(ip)return gn;ip=1,Object.defineProperty(gn,"__esModule",{value:!0}),gn.rovo=void 0;const e=Q1(),t=Y1();return gn.rovo={open:e.open,isEnabled:t.isEnabled},gn}var op;function J1(){return op||(op=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),me.__exportStar(X1(),e)}(Nu)),Nu}var We={},lp;function Z1(){if(lp)return We;lp=1,Object.defineProperty(We,"__esModule",{value:!0}),We.createTranslationFunction=We.getTranslations=We.resetTranslationsCache=void 0;const e=Eg(),t=bo(),r={getI18nInfoConfig:async()=>{const u=await fetch(`./${e.I18N_BUNDLE_FOLDER_NAME}/${e.I18N_INFO_FILE_NAME}`);if(!u.ok)throw new Error("Failed to get i18n info config: "+u.statusText);return(await u.json()).config},getTranslationResource:async u=>{const a=await fetch(`./${e.I18N_BUNDLE_FOLDER_NAME}/${u}.json`);if(!a.ok)throw new Error(`Failed to get translation resource for locale: ${u}`);return a.json()}},n=new e.TranslationsGetter(r),i=()=>{n.reset()};We.resetTranslationsCache=i;const o=async(u=null,a={fallback:!0})=>{let s=u;return s||(s=(await t.view.getContext()).locale),await n.getTranslations(s,a)};We.getTranslations=o;const l=async(u=null)=>{let a=u;a||(a=(await t.view.getContext()).locale);const s=new e.Translator(a,n);return await s.init(),(d,g)=>{var m,h;return(h=(m=s.translate(d))!==null&&m!==void 0?m:g)!==null&&h!==void 0?h:d}};return We.createTranslationFunction=l,We}var Du={},yn={},up;function e_(){if(up)return yn;up=1,Object.defineProperty(yn,"__esModule",{value:!0}),yn.permissions=void 0;const t=(0,D().getCallBridge)(),r=async a=>t("__permission__egressGet",a),n=async a=>t("__permission__egressSet",a),i=async a=>t("__permission__egressDeleteDomain",a),o=async a=>t("__permission__egressDeleteGroup",a),l=async a=>t("__permission__remoteGet",a),u=async a=>t("__permission__remoteSet",a);return yn.permissions={egress:{get:r,set:n,deleteDomain:i,deleteGroup:o},remote:{get:l,set:u}},yn}var jt={},Au={},Bu={},_n={},wn={},ap;function Bs(){if(ap)return wn;ap=1,Object.defineProperty(wn,"__esModule",{value:!0}),wn.parseUrl=void 0;function e(t){var r,n;const i=(n=(r=t.match(/^(.*?:)/))===null||r===void 0?void 0:r[0])!==null&&n!==void 0?n:"https:",o=t.replace(i,"").replace(/^\/*/,"").replace(/^\\*/,"").split("?")[0].split("#")[0],l=o.split("/")[0],u=o.slice(l.length)||"/";return{protocol:i,hostname:l,pathname:u}}return wn.parseUrl=e,wn}var qu={},sp;function Ig(){return sp||(sp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.getEgressesBasedOnToggles=e.sortAndGroupEgressPermissionsByDomain=e.EgressCategory=e.EgressType=e.globToRegex=void 0;const t=Bs();function r(l){const a=l.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${a}$`)}e.globToRegex=r;const n=l=>{if((l==null?void 0:l.length)===0)return[];const u=/^(.*?:\/\/)/,a=new Set,s=[];return l.forEach(d=>{const g=u.test(d)?d:`https://${d}`,m=(0,t.parseUrl)(g);m.hostname.startsWith("*")?(a.add(m.hostname.substring(2)),s.push(r(m.hostname))):a.add(m.hostname)}),[...a].sort().reduce((d,g)=>(s.some(m=>m.test(g))||d.push(g),d),[])};e.sortAndGroupEgressPermissionsByDomain=n,function(l){l.FetchBackendSide="FETCH_BACKEND_SIDE",l.FetchClientSide="FETCH_CLIENT_SIDE",l.Fonts="FONTS",l.Frames="FRAMES",l.Images="IMAGES",l.Media="MEDIA",l.Navigation="NAVIGATION",l.Scripts="SCRIPTS",l.Styles="STYLES"}(e.EgressType||(e.EgressType={}));var i;(function(l){l.ANALYTICS="ANALYTICS"})(i=e.EgressCategory||(e.EgressCategory={}));const o=l=>{const u=l.egress.filter(s=>{var d;if(((d=s.category)===null||d===void 0?void 0:d.toUpperCase())===i.ANALYTICS)if(l.installationConfig){const g=l.installationConfig.find(m=>m.key.toUpperCase()==="ALLOW_EGRESS_ANALYTICS");return(g==null?void 0:g.value)!==!1}else return l.overrides.ALLOW_EGRESS_ANALYTICS!==!1;return!0}),a=new Map;for(const s of u)a.has(s.type)||a.set(s.type,s.addresses),a.set(s.type,[...a.get(s.type),...s.addresses]);return[...a.entries()].map(([s,d])=>({type:s,addresses:[...new Set(d)]}))};e.getEgressesBasedOnToggles=o}(qu)),qu}var cp;function t_(){if(cp)return _n;cp=1,Object.defineProperty(_n,"__esModule",{value:!0}),_n.EgressFilteringService=void 0;const e=Bs(),t=Ig();class r{constructor(i){this.URLs=i.filter(o=>!o.startsWith("*")).map(o=>this.parseUrl(o)),this.wildcardDomains=i.filter(o=>o!=="*").map(o=>this.parseUrl(o)).filter(o=>decodeURIComponent(o.hostname).startsWith("*")).map(o=>({...o,regex:(0,t.globToRegex)(decodeURIComponent(o.hostname))})),this.allowsEverything=i.includes("*")}parseUrl(i){return(0,e.parseUrl)(i)}containsWildCardEgress(){return this.allowsEverything}isValidUrl(i){if(this.allowsEverything)return!0;const o=this.parseUrl(i);return this.allowedDomainExact(o,this.URLs)||this.allowedDomainPattern(o,this.wildcardDomains)}isValidUrlCSP(i){if(this.allowsEverything)return!0;const o=this.parseUrl(i);return this.allowedDomainExactAndPath(o,this.URLs)||this.allowedDomainPatternAndPath(o,this.wildcardDomains)}allowedDomainExact(i,o){return o.filter(l=>l.protocol===i.protocol).some(l=>l.hostname===i.hostname)}allowedDomainExactAndPath(i,o){return o.filter(l=>this.protocolMatchesCSP(l.protocol,i.protocol)).filter(l=>l.hostname===i.hostname).some(l=>this.pathMatches(l.pathname,i.pathname))}allowedDomainPattern(i,o){return o.filter(l=>l.protocol===i.protocol).some(l=>l.regex.test(i.hostname))}allowedDomainPatternAndPath(i,o){return o.filter(l=>this.protocolMatchesCSP(l.protocol,i.protocol)).filter(l=>l.regex.test(i.hostname)).some(l=>this.pathMatches(l.pathname,i.pathname))}protocolMatchesCSP(i,o){return i===o||i==="http:"&&o==="https:"||i==="ws:"&&o==="wss:"}pathMatches(i,o){return i==="/"?!0:i.endsWith("/")?o.startsWith(i):o===i}}return _n.EgressFilteringService=r,_n}var fp;function r_(){return fp||(fp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0});const t=me;t.__exportStar(t_(),e),t.__exportStar(Bs(),e),t.__exportStar(Ig(),e)}(Bu)),Bu}var dp;function n_(){return dp||(dp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),me.__exportStar(r_(),e)}(Au)),Au}var pp;function i_(){if(pp)return jt;pp=1,Object.defineProperty(jt,"__esModule",{value:!0}),jt.checkPermissions=jt.createPermissionUtils=void 0;const e=n_(),t=bo();function r(y){return typeof y=="string"?y:"address"in y&&y.address?y.address:y.remote||""}const n=["fonts","styles","frames","images","media","scripts"],i=["backend","client"];function o(y){if(!y)return null;const{scopes:v,external:_={}}=y,f=Array.isArray(v)?v:Object.keys(v||{});return{hasScope:c=>f.includes(c),canFetchFrom:(c,p)=>{var w;const S=(w=_.fetch)===null||w===void 0?void 0:w[c];if(!(S!=null&&S.length))return!1;const k=S.map(r).filter(M=>M.length>0);if(k.length===0)return!1;const C=new e.EgressFilteringService(k);return c==="client"?C.isValidUrlCSP(p):C.isValidUrl(p)},canLoadResource:(c,p)=>{const w=_[c];if(!(w!=null&&w.length))return!1;const S=w.map(r).filter(O=>O.length>0);return S.length===0?!1:new e.EgressFilteringService(S).isValidUrlCSP(p)},getScopes:()=>f,getExternalPermissions:()=>_,hasAnyPermissions:()=>f.length>0||Object.keys(_).length>0}}jt.createPermissionUtils=o;function l(y,v){if(!(y!=null&&y.length))return;const _=y.filter(f=>!v.hasScope(f));return _.length>0?_:void 0}function u(y,v){if(!(y!=null&&y.fetch))return;const _={};return i.forEach(f=>{var c;const p=(c=y.fetch)===null||c===void 0?void 0:c[f];if(p!=null&&p.length){const w=p.filter(S=>!v.canFetchFrom(f,S));w.length>0&&(_[f]=w)}}),Object.keys(_).length>0?_:void 0}function a(y,v){const _={};return n.forEach(f=>{const c=y==null?void 0:y[f];if(c!=null&&c.length){const p=c.filter(w=>!v.canLoadResource(f,w));p.length>0&&(_[f]=p)}}),Object.keys(_).length>0?_:void 0}function s(y,v){if(!y)return;const _=u(y,v),f=a(y,v);if(!_&&!f)return;const c={};return _&&(c.fetch=_),f&&Object.assign(c,f),c}function d(y,v){if(y!==void 0&&(typeof y!="object"||y===null||Array.isArray(y)))throw new TypeError(`${v} should be an object, not ${Array.isArray(y)?"an array":`a ${typeof y}`}`)}function g(y,v){if(y!==void 0&&!Array.isArray(y))throw new TypeError(`${v} should be an array, not a ${typeof y}`)}function m(y){g(y.scopes,"scopes");const v=y.external;if(v!==void 0){if(d(v,"external"),v.fetch!==void 0){d(v.fetch,"external.fetch");for(const _ of i)g(v.fetch[_],`external.fetch.${_}`)}for(const _ of n)g(v[_],`external.${_}`)}}async function h(y,v){var _;if(!y)return{granted:!1,missing:null};if(m(y),!(!((_=y.scopes)===null||_===void 0)&&_.length)&&!y.external)return{granted:!0,missing:null};let f=v;f||(f=(await t.view.getContext()).permissions);const c=o(f);if(!c)return{granted:!1,missing:null};const p={};let w=!0;const S=l(y.scopes,c);S&&(p.scopes=S,w=!1);const k=s(y.external,c);return k&&(p.external=k,w=!1),{granted:w,missing:w?null:p}}return jt.checkPermissions=h,jt}var hp;function o_(){return hp||(hp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0});const t=me;t.__exportStar(e_(),e),t.__exportStar(i_(),e)}(Du)),Du}var zu={},Uu={},bu={},Sn={},En={},vp;function xg(){return vp||(vp=1,Object.defineProperty(En,"__esModule",{value:!0}),En.BRIDGE_OBJECT_STORE_RESTRICTED_ENVIRONMENT_ERROR=void 0,En.BRIDGE_OBJECT_STORE_RESTRICTED_ENVIRONMENT_ERROR="Object Store bridge methods are restricted to Forge apps in a non-production environment. For more information please see https://developer.atlassian.com/platform/forge/cli-reference/environments/ for reference on Forge app environments."),En}var gp;function Vo(){if(gp)return Sn;gp=1,Object.defineProperty(Sn,"__esModule",{value:!0}),Sn.checkRestrictedEnvironment=void 0;const e=Q(),t=bo(),r=xg(),n=async()=>{const{environmentType:i}=await t.view.getContext();if(i==="PRODUCTION")throw new e.BridgeAPIError(r.BRIDGE_OBJECT_STORE_RESTRICTED_ENVIRONMENT_ERROR)};return Sn.checkRestrictedEnvironment=n,Sn}var mp;function l_(){return mp||(mp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.upload=e.createUploadPromises=void 0;const t=fi(),r=Q(),n=Vo(),o=(0,D().getCallBridge)(),l=(d,g)=>{const m=atob(d),h=new Array(m.length);for(let v=0;v{const g=d.size,m=await d.arrayBuffer(),h=await crypto.subtle.digest("SHA-256",m),y=new Uint8Array(h),v=btoa(String.fromCharCode(...y));return{length:g,checksum:v,checksumType:"SHA256"}},a=async({functionKey:d,objects:g})=>{if(!d||d.length===0)throw new r.BridgeAPIError("functionKey is required to filter and generate presigned URLs");if(!Array.isArray(g)||g.length===0)throw new r.BridgeAPIError("objects array is required and must not be empty");const m=g.map((c,p)=>{if(c instanceof Blob)return c;if(!(c&&typeof c=="object"&&"data"in c&&typeof c.data=="string"))throw new r.BridgeAPIError(`Invalid object type at index ${p}. Only Blob or Base64Object (with data string and optional mimeType) are accepted.`);try{return l(c.data,c.mimeType)}catch{throw new r.BridgeAPIError(`Invalid base64 data at index ${p}. The data string must be valid base64 encoded.`)}}),h=await Promise.all(m.map(c=>u(c))),y=await(0,t.invoke)(d,{allObjectMetadata:h});if(!y||typeof y!="object")throw new r.BridgeAPIError("Invalid response from functionKey");const v=new Map,_=new Map;return m.forEach((c,p)=>{const w=h[p];v.set(w.checksum,c),_.set(w.checksum,p)}),Object.entries(y).map(([c,p])=>{const{key:w,checksum:S}=p,k=v.get(S),C=_.get(S);return C===void 0?{promise:Promise.resolve({success:!1,key:w,error:`Index not found for checksum ${S}`}),index:-1}:k?{promise:(async()=>{try{const M=await fetch(c,{method:"PUT",body:k,headers:{"Content-Type":k.type||"application/octet-stream","Content-Length":k.size.toString()}});return{success:M.ok,key:w,status:M.status,error:M.ok?void 0:`Upload failed with status ${M.status}`}}catch(M){return{success:!1,key:w,status:503,error:M instanceof Error?M.message:"Upload failed"}}})(),index:C,objectType:k.type,objectSize:k.size}:{promise:Promise.resolve({success:!1,key:w,error:`Blob not found for checksum ${S}`}),index:C}})};e.createUploadPromises=a;const s=async({functionKey:d,objects:g})=>{await(0,n.checkRestrictedEnvironment)(),o("trackObjectStoreAction",{action:"upload"});const m=await(0,e.createUploadPromises)({functionKey:d,objects:g});return await Promise.all(m.map(y=>y.promise))};e.upload=s}(bu)),bu}var kn={},yp;function u_(){if(yp)return kn;yp=1,Object.defineProperty(kn,"__esModule",{value:!0}),kn.deleteObjects=void 0;const e=fi(),t=Q(),r=Vo(),i=(0,D().getCallBridge)(),o=async({functionKey:l,keys:u})=>{if(await(0,r.checkRestrictedEnvironment)(),i("trackObjectStoreAction",{action:"delete"}),!l||l.length===0)throw new t.BridgeAPIError("functionKey is required to delete objects");if(!Array.isArray(u)||u.length===0)throw new t.BridgeAPIError("keys array is required and must not be empty");await Promise.all(u.map(async a=>{await(0,e.invoke)(l,{key:a})}))};return kn.deleteObjects=o,kn}var Cn={},_p;function a_(){if(_p)return Cn;_p=1,Object.defineProperty(Cn,"__esModule",{value:!0}),Cn.download=void 0;const e=fi(),t=Q(),r=Vo(),i=(0,D().getCallBridge)(),o=async({functionKey:l,keys:u})=>{if(await(0,r.checkRestrictedEnvironment)(),i("trackObjectStoreAction",{action:"download"}),!l||l.length===0)throw new t.BridgeAPIError("functionKey is required to filter and generate download URLs");if(!Array.isArray(u)||u.length===0)throw new t.BridgeAPIError("keys array is required and must not be empty");const a=await(0,e.invoke)(l,{keys:u});if(!a||typeof a!="object")throw new t.BridgeAPIError("Invalid response from functionKey");const s=Object.entries(a).map(async([g,m])=>{try{const h=await fetch(g,{method:"GET"});if(!h.ok)return{success:!1,key:m,status:h.status,error:`Download failed with status ${h.status}`};const y=await h.blob();return{success:!0,key:m,blob:y,status:h.status}}catch(h){return{success:!1,key:m,status:503,error:h instanceof Error?h.message:"Download failed"}}});return await Promise.all(s)};return Cn.download=o,Cn}var Pn={},wp;function s_(){if(wp)return Pn;wp=1,Object.defineProperty(Pn,"__esModule",{value:!0}),Pn.getMetadata=void 0;const e=fi(),t=Q(),r=Vo(),i=(0,D().getCallBridge)(),o=async({functionKey:l,keys:u})=>{if(await(0,r.checkRestrictedEnvironment)(),i("trackObjectStoreAction",{action:"getMetadata"}),!l||l.length===0)throw new t.BridgeAPIError("functionKey is required to filter and generate object metadata");if(!Array.isArray(u)||u.length===0)throw new t.BridgeAPIError("keys array is required and must not be empty");return await Promise.all(u.map(async s=>{const d=await(0,e.invoke)(l,{key:s});return!d||typeof d!="object"?{key:s,error:"Invalid response from functionKey"}:d}))};return Pn.getMetadata=o,Pn}var Sp;function c_(){return Sp||(Sp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.createUploadPromises=e.objectStore=void 0;const t=l_();Object.defineProperty(e,"createUploadPromises",{enumerable:!0,get:function(){return t.createUploadPromises}});const r=u_(),n=a_(),i=s_();e.objectStore={upload:t.upload,download:n.download,getMetadata:i.getMetadata,delete:r.deleteObjects}}(Uu)),Uu}var Ep;function f_(){return Ep||(Ep=1,function(e){Object.defineProperty(e,"__esModule",{value:!0});const t=me;t.__exportStar(c_(),e),t.__exportStar(xg(),e)}(zu)),zu}var Vu={},Rn={},On={},kp;function d_(){if(kp)return On;kp=1,Object.defineProperty(On,"__esModule",{value:!0}),On.Evaluator=void 0;class e{constructor(r){this.results=r}checkFlag(r,n){if(!this.results||!this.results.feature_flags)return n;const i=this.results.feature_flags;let o="";try{o=this.getHashedValue(r)}catch(u){return console.error("Unexpected error occurred while evaluating flag ",u),n}if(!o)return n;const l=i[o];return l?l.disabled?!1:l.value:n}shutDown(){this.results=void 0}getHashedValue(r){if(typeof r!="string")return"";const n=r.trim();if(n.length===0)return"";let i=5381;for(let o=0;o>>0).toString()}}return On.Evaluator=e,On}var Tn={},Hu={},Cp;function jg(){return Cp||(Cp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.FeatureFlagEventType=void 0,function(t){t.CHECKFLAG="checkFlag"}(e.FeatureFlagEventType||(e.FeatureFlagEventType={}))}(Hu)),Hu}var Pp;function p_(){if(Pp)return Tn;Pp=1,Object.defineProperty(Tn,"__esModule",{value:!0}),Tn.trackFeatureFlagEvent=void 0;const e=D(),t=Q(),r=Do(),n=jg(),i=500,o=1e3*25,l=(0,e.getCallBridge)(),u=s=>{if(!s||!s.type||!s.properties)throw new t.BridgeAPIError("Missing required parameters. Parameter type, and properties are required in the payload.");if(!(s.type.toUpperCase()in n.FeatureFlagEventType))throw new t.BridgeAPIError("Event type is not supported");if(Object.values(s).some(d=>typeof d=="function"))throw new t.BridgeAPIError("Passing functions as part of the payload is not supported!")},a=s=>(u(s),l("trackFeatureFlagEvent",s));return Tn.trackFeatureFlagEvent=(0,r.withRateLimiter)(a,i,o,`Feature flags calls are rate limited at ${i}req/${o/1e3}s`),Tn}var In={},Rp;function h_(){if(Rp)return In;Rp=1,Object.defineProperty(In,"__esModule",{value:!0}),In.initFeatureFlags=void 0;const e=D(),t=Q(),r=Do(),n=500,i=1e3*25,o=(0,e.getCallBridge)(),l=a=>{if(!a||!a.user||!a.config)throw new t.BridgeAPIError("Missing required parameters. Parameter user is required in the payload.");if(Object.values(a).some(s=>typeof s=="function"))throw new t.BridgeAPIError("Passing functions as part of the payload is not supported!")},u=a=>(l(a),o("initFeatureFlags",{user:a.user,config:a.config}));return In.initFeatureFlags=(0,r.withRateLimiter)(u,n,i,`Feature flags initialisation calls are rate limited at ${n}req/${i/1e3}s`),In}var Op;function v_(){if(Op)return Rn;Op=1,Object.defineProperty(Rn,"__esModule",{value:!0}),Rn.FeatureFlags=void 0;const e=d_(),t=p_(),r=h_(),n=jg();class i{constructor(){this.initialized=!1,this.eventProps={}}async initialize(l,u={environment:"development"}){if(this.isInitialized())return;this.eventProps.environment=u.environment;const a=await(0,r.initFeatureFlags)({user:l,config:u});this.initialized=!0,this.evaluator=new e.Evaluator(a)}checkFlag(l,u=!1){if(!this.isInitialized()||!this.evaluator)throw this.sendCheckFlagEvent(l,!1),new Error("FeatureFlags not initialized. Call initialize() first.");return this.sendCheckFlagEvent(l,!0),this.evaluator.checkFlag(l,u)}shutdown(){this.isInitialized()&&(this.initialized=!1,this.evaluator.shutDown())}isInitialized(){return this.initialized}sendCheckFlagEvent(l,u){const a={type:n.FeatureFlagEventType.CHECKFLAG,properties:{...this.eventProps,environment:this.eventProps.environment||"development",name:l,success:u}};(0,t.trackFeatureFlagEvent)(a)}}return Rn.FeatureFlags=i,Rn}var Tp;function g_(){return Tp||(Tp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.FeatureFlags=void 0;var t=v_();Object.defineProperty(e,"FeatureFlags",{enumerable:!0,get:function(){return t.FeatureFlags}})}(Vu)),Vu}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.i18n=e.NavigationTarget=void 0;const t=me;var r=Lo;Object.defineProperty(e,"NavigationTarget",{enumerable:!0,get:function(){return r.NavigationTarget}}),t.__exportStar(fi(),e),t.__exportStar(m0(),e),t.__exportStar(bo(),e),t.__exportStar(B1(),e),t.__exportStar(z1(),e),t.__exportStar(b1(),e),t.__exportStar(H1(),e),t.__exportStar(G1(),e),t.__exportStar(K1(),e),t.__exportStar(J1(),e),e.i18n=t.__importStar(Z1()),t.__exportStar(o_(),e),t.__exportStar(f_(),e),t.__exportStar(g_(),e)})($e);const Ip={repo:"",branch:"main",domainPath:"",height:"1200",githubUrl:""},m_=[{value:"600",label:"Small (600px)"},{value:"800",label:"Medium (800px)"},{value:"1200",label:"Large (1200px)"},{value:"1600",label:"Extra Large (1600px)"},{value:"2000",label:"Full Screen (2000px)"}];function y_(e){const t=e.trim(),r=t.match(/github\.com\/([^/]+\/[^/]+)\/blob\/([^/]+)\/(.+)/);if(r)return{repo:r[1],branch:r[2],domainPath:r[3]};const n=t.match(/github\.com\/([^/]+\/[^/]+)\/tree\/([^/]+)\/(.+)/);return n?{repo:n[1],branch:n[2],domainPath:n[3]}:null}function __(){var f,c;const[e,t]=Fe.useState(Ip),[r,n]=Fe.useState(null),[i,o]=Fe.useState(!1),[l,u]=Fe.useState(null),[a,s]=Fe.useState(null),[d,g]=Fe.useState(!0);Fe.useEffect(()=>{async function p(){try{const w=await $e.invoke("getAuthStatus");s(w)}catch{s({authenticated:!1})}finally{g(!1)}}p()},[]),Fe.useEffect(()=>{async function p(){var C;const w=await $e.view.getContext(),S=(C=w==null?void 0:w.extension)==null?void 0:C.config;if(S&&S.repo){const{githubToken:O,...M}=S;t({...Ip,...M}),u({repo:M.repo,branch:M.branch||"main",domainPath:M.domainPath});return}const k=await $e.invoke("getConfig");k&&k.repo&&(t(k),u({repo:k.repo,branch:k.branch||"main",domainPath:k.domainPath}))}p()},[]);const m=p=>{t(S=>({...S,githubUrl:p})),n(null);const w=y_(p);w?(u(w),t(S=>({...S,repo:w.repo,branch:w.branch,domainPath:w.domainPath}))):p.trim()&&u(null)},h=async()=>{var p,w;if(!e.repo||!e.domainPath){n("Please paste a valid GitHub URL to a domain JSON file.");return}o(!0),n(null);try{const S=await $e.invoke("getDomain",e);if(S.error)n(`Error: ${S.error}`);else{const k=((p=S.models)==null?void 0:p.length)??0,C=((w=S.relationships)==null?void 0:w.length)??0;n(`Connected! Found ${k} models and ${C} relationships.`);const O=await $e.invoke("getAuthStatus");s(O)}}catch(S){n(`Error: ${S.message}`)}finally{o(!1)}},y=async()=>{if(!e.repo||!e.domainPath){n("Please paste a valid GitHub URL to a domain JSON file.");return}try{await $e.invoke("saveConfig",e)}catch(p){n(`Save failed: ${p.message}`);return}try{await $e.view.submit(e);return}catch{}try{await $e.view.close();return}catch{}n("__DONE__")};if(r==="__DONE__")return x.jsx("div",{style:z.container,children:x.jsxs("div",{style:{padding:"24px",textAlign:"center"},children:[x.jsx("div",{style:{fontSize:"24px",marginBottom:"8px"},children:"✓"}),x.jsx("div",{style:{fontSize:"14px",fontWeight:600,color:"#006644",marginBottom:"4px"},children:"Configuration saved"}),x.jsx("div",{style:{fontSize:"13px",color:"#6b778c"},children:"Publish the page to see your ERD diagram."})]})});const v=(r==null?void 0:r.startsWith("Connected"))||(r==null?void 0:r.startsWith("Saved")),_=(a==null?void 0:a.authenticated)===!0;return x.jsxs("div",{style:z.container,children:[x.jsx("h3",{style:z.title,children:"ERD Studio Configuration"}),x.jsx("p",{style:z.subtitle,children:"Paste a GitHub link to your domain JSON file. GitHub authentication is handled automatically via OAuth when you test the connection."}),x.jsxs("div",{style:{...z.field,borderBottom:"1px solid #dfe1e6",paddingBottom:"12px",marginBottom:"16px"},children:[x.jsx("label",{style:z.label,children:"GitHub Account"}),d?x.jsx("div",{style:z.authBox,children:x.jsx("span",{style:{fontSize:"13px",color:"#6b778c"},children:"Checking..."})}):_?x.jsx("div",{style:{...z.authBox,backgroundColor:"#e3fcef",borderColor:"#006644"},children:x.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px"},children:[((f=a==null?void 0:a.user)==null?void 0:f.avatarUrl)&&x.jsx("img",{src:a.user.avatarUrl,alt:"",style:{width:"20px",height:"20px",borderRadius:"50%"}}),x.jsxs("span",{style:{fontSize:"13px",color:"#006644",fontWeight:600},children:["Connected",(c=a==null?void 0:a.user)!=null&&c.displayName?` as ${a.user.displayName}`:""]})]})}):x.jsx("div",{style:z.authBox,children:x.jsx("span",{style:{fontSize:"13px",color:"#6b778c"},children:"Not connected — click Test Connection to authenticate via OAuth."})})]}),x.jsxs("div",{style:z.field,children:[x.jsx("label",{style:z.label,children:"GitHub URL"}),x.jsx("input",{style:z.input,type:"text",placeholder:"https://github.com/owner/repo/blob/main/erd-studio/silver/domain.json",value:e.githubUrl,onChange:p=>m(p.target.value)}),l&&x.jsxs("div",{style:z.parsedInfo,children:[x.jsx("span",{style:z.parsedLabel,children:"Repo:"})," ",l.repo,x.jsx("span",{style:{...z.parsedLabel,marginLeft:"12px"},children:"Branch:"})," ",l.branch,x.jsx("br",{}),x.jsx("span",{style:z.parsedLabel,children:"Path:"})," ",l.domainPath]}),e.githubUrl&&!l&&x.jsx("span",{style:{...z.hint,color:"#de350b"},children:"Could not parse URL. Expected format: github.com/owner/repo/blob/branch/path/to/file.json"})]}),x.jsxs("div",{style:{...z.field,borderTop:"1px solid #dfe1e6",paddingTop:"12px",marginTop:"16px"},children:[x.jsx("label",{style:z.label,children:"Diagram Height"}),x.jsx("select",{style:{...z.input,cursor:"pointer"},value:e.height,onChange:p=>{t(w=>({...w,height:p.target.value})),n(null)},children:m_.map(p=>x.jsx("option",{value:p.value,children:p.label},p.value))})]}),r&&x.jsx("div",{style:{...z.status,color:v?"#006644":"#de350b",backgroundColor:v?"#e3fcef":"#ffebe6"},children:r}),x.jsxs("div",{style:z.buttons,children:[x.jsx("button",{style:{...z.testButton,opacity:l?1:.5},onClick:h,disabled:i||!l,children:i?"Testing...":"Test Connection"}),x.jsx("button",{style:{...z.saveButton,opacity:l?1:.5},onClick:y,disabled:!l,children:"Save"})]})]})}const z={container:{fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',padding:"16px",maxWidth:"520px"},title:{margin:"0 0 4px 0",fontSize:"16px",fontWeight:600,color:"#172b4d"},subtitle:{margin:"0 0 16px 0",fontSize:"13px",color:"#6b778c"},field:{marginBottom:"12px"},label:{display:"block",fontSize:"12px",fontWeight:600,color:"#172b4d",marginBottom:"4px"},input:{width:"100%",padding:"6px 8px",fontSize:"13px",border:"1px solid #dfe1e6",borderRadius:"3px",backgroundColor:"#fafbfc",color:"#172b4d",boxSizing:"border-box"},hint:{display:"block",fontSize:"11px",color:"#97a0af",marginTop:"2px"},parsedInfo:{marginTop:"6px",padding:"6px 8px",backgroundColor:"#f4f5f7",borderRadius:"3px",fontSize:"11px",color:"#172b4d",lineHeight:"1.6"},parsedLabel:{fontWeight:600,color:"#6b778c"},status:{padding:"8px 12px",borderRadius:"3px",fontSize:"13px",marginBottom:"12px"},buttons:{display:"flex",gap:"8px",marginTop:"16px"},testButton:{padding:"6px 12px",fontSize:"13px",border:"1px solid #dfe1e6",borderRadius:"3px",backgroundColor:"#ffffff",color:"#172b4d",cursor:"pointer"},saveButton:{padding:"6px 16px",fontSize:"13px",border:"none",borderRadius:"3px",backgroundColor:"#0052cc",color:"#ffffff",cursor:"pointer",fontWeight:600},authBox:{padding:"8px 12px",borderRadius:"3px",border:"1px solid #dfe1e6",backgroundColor:"#f4f5f7"}},w_=bv(document.getElementById("root"));w_.render(x.jsx(Jg.StrictMode,{children:x.jsx(__,{})}));export{Lg as g}; + `);return window.__bridge.callBridge};return Fr.getCallBridge=r,Fr}var Lr={},Xc;function Do(){if(Xc)return Lr;Xc=1,Object.defineProperty(Lr,"__esModule",{value:!0}),Lr.withRateLimiter=void 0;const e=Q(),t=(r,n,i,o)=>{let l=Date.now(),u=0;return async(...a)=>{const s=Date.now();if(s-l>i&&(l=s,u=0),u>=n)throw new e.BridgeAPIError(o||"Too many invocations.");return u=u+1,r(...a)}};return Lr.withRateLimiter=t,Lr}var Jc;function h0(){return Jc||(Jc=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.makeInvoke=e.invoke=void 0;const t=D(),r=Q(),n=Do(),i=(0,t.getCallBridge)(),o=a=>{if(a&&Object.values(a).some(s=>typeof s=="function"))throw new r.BridgeAPIError("Passing functions as part of the payload is not supported!")},l=(a,s)=>{if(typeof a!="string")throw new r.BridgeAPIError("functionKey must be a string!");return o(s),i("invoke",{functionKey:a,payload:s})};e.invoke=(0,n.withRateLimiter)(l,500,1e3*25,"Resolver calls are rate limited at 500req/25s");function u(){return e.invoke}e.makeInvoke=u}(wl)),wl}var Zc;function fi(){return Zc||(Zc=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),me.__exportStar(h0(),e)}(_l)),_l}var Sl={},Dr={},El={},ef;function gg(){return ef||(ef=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e._invokeEndpointFn=e.InvokeType=void 0;const t=D(),r=Q(),n=Do(),i=500,o=25,l=1e3*o;(function(g){g.REMOTE="Remote",g.SERVICE="Container"})(e.InvokeType||(e.InvokeType={}));const u=(0,t.getCallBridge)(),a=g=>{if(g&&Object.values(g).some(m=>typeof m=="function"))throw new r.BridgeAPIError("Passing functions as part of the payload is not supported!")},s=g=>async m=>{a(m);const h={...m,invokeType:`ui-${g.toLowerCase()}-fetch`},y=await u("invoke",h),{success:v,payload:_,error:f}=y??{},c={...v?_:f};if(c&&c.headers)for(const p in c.headers)Array.isArray(c.headers[p])&&(c.headers[p]=c.headers[p].join(","));return c},d=g=>{const m=s(g);return(0,n.withRateLimiter)(m,i,l,`${g} invocation calls are rate limited at ${i}/${o}s`)};e._invokeEndpointFn=d}(El)),El}var tf;function v0(){if(tf)return Dr;tf=1,Object.defineProperty(Dr,"__esModule",{value:!0}),Dr.invokeRemote=void 0;const e=gg(),t=r=>(0,e._invokeEndpointFn)(e.InvokeType.REMOTE)(r);return Dr.invokeRemote=t,Dr}var Ar={},rf;function g0(){if(rf)return Ar;rf=1,Object.defineProperty(Ar,"__esModule",{value:!0}),Ar.invokeService=void 0;const e=gg(),t=r=>(0,e._invokeEndpointFn)(e.InvokeType.SERVICE)(r);return Ar.invokeService=t,Ar}var nf;function m0(){return nf||(nf=1,function(e){Object.defineProperty(e,"__esModule",{value:!0});const t=me;t.__exportStar(v0(),e),t.__exportStar(g0(),e)}(Sl)),Sl}var kl={},Br={},qr={},of;function y0(){if(of)return qr;of=1,Object.defineProperty(qr,"__esModule",{value:!0}),qr.submit=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=async i=>{if(await r("submit",i)===!1)throw new t.BridgeAPIError("this resource's view is not submittable.")};return qr.submit=n,qr}var zr={},lf;function _0(){if(lf)return zr;lf=1,Object.defineProperty(zr,"__esModule",{value:!0}),zr.close=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=async i=>{try{if(await r("close",i)===!1)throw new t.BridgeAPIError("this resource's view is not closable.")}catch{throw new t.BridgeAPIError("this resource's view is not closable.")}};return zr.close=n,zr}var Ur={},uf;function w0(){if(uf)return Ur;uf=1,Object.defineProperty(Ur,"__esModule",{value:!0}),Ur.open=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=async()=>{try{if(await r("open")===!1)throw new t.BridgeAPIError("this resource's view is not openable.")}catch{throw new t.BridgeAPIError("this resource's view is not openable.")}};return Ur.open=n,Ur}var br={},af;function S0(){if(af)return br;af=1,Object.defineProperty(br,"__esModule",{value:!0}),br.refresh=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=async i=>{if(await r("refresh",i)===!1)throw new t.BridgeAPIError("this resource's view is not refreshable.")};return br.refresh=n,br}var Vr={},sf;function E0(){if(sf)return Vr;sf=1,Object.defineProperty(Vr,"__esModule",{value:!0}),Vr.createHistory=void 0;const t=(0,D().getCallBridge)(),r=async()=>{const n=await t("createHistory");return n.listen(i=>{n.location=i}),n};return Vr.createHistory=r,Vr}var Hr={},Cl={},Ge={},cf;function mg(){return cf||(cf=1,Object.defineProperty(Ge,"__esModule",{value:!0}),Ge.FORGE_SUPPORTED_LOCALE_CODES=Ge.I18N_BUNDLE_FOLDER_NAME=Ge.I18N_INFO_FILE_NAME=void 0,Ge.I18N_INFO_FILE_NAME="i18n-info.json",Ge.I18N_BUNDLE_FOLDER_NAME="__LOCALES__",Ge.FORGE_SUPPORTED_LOCALE_CODES=["zh-CN","zh-TW","cs-CZ","da-DK","nl-NL","en-US","en-GB","et-EE","fi-FI","fr-FR","de-DE","hu-HU","is-IS","it-IT","ja-JP","ko-KR","no-NO","pl-PL","pt-BR","pt-PT","ro-RO","ru-RU","sk-SK","tr-TR","es-ES","sv-SE"]),Ge}var Tt={},ff;function k0(){if(ff)return Tt;ff=1,Object.defineProperty(Tt,"__esModule",{value:!0}),Tt.TranslationsGetter=Tt.TranslationGetterError=void 0;const e=(n,i)=>{n.includes(i)||n.push(i)};class t extends Error{constructor(i){super(i),this.name="TranslationGetterError"}}Tt.TranslationGetterError=t;class r{constructor(i){it(this,"resourcesAccessor");it(this,"i18nInfoConfig",null);it(this,"translationResources",new Map);this.resourcesAccessor=i}async getTranslations(i,o={fallback:!0}){const l=await this.getI18nInfoConfig(),{fallback:u}=o;if(!u){let a;return l.locales.includes(i)&&(a=await this.getTranslationResource(i)),{translations:a??null,locale:i}}for(const a of this.getLocaleLookupOrder(i,l)){const s=await this.getTranslationResource(a);if(s)return{translations:s,locale:a}}return{translations:null,locale:i}}async getTranslationsByLocaleLookupOrder(i){const o=await this.getI18nInfoConfig(),l=this.getLocaleLookupOrder(i,o);return await Promise.all(l.map(async u=>{const a=await this.getTranslationResource(u);return{locale:u,translations:a}}))}reset(){this.i18nInfoConfig=null,this.translationResources.clear()}async getTranslationResource(i){let o=this.translationResources.get(i);if(!o)try{o=await this.resourcesAccessor.getTranslationResource(i),this.translationResources.set(i,o)}catch(l){throw l instanceof t?l:new t(`Failed to get translation resource for locale: ${i}`)}return o}async getI18nInfoConfig(){if(!this.i18nInfoConfig)try{this.i18nInfoConfig=await this.resourcesAccessor.getI18nInfoConfig()}catch(i){throw i instanceof t?i:new t("Failed to get i18n info config")}return this.i18nInfoConfig}getLocaleLookupOrder(i,o){const{locales:l,fallback:u}=o,a=[i],s=u[i];return s&&Array.isArray(s)&&s.length>0&&a.push(...s),e(a,o.fallback.default),a.filter(d=>l.includes(d))}}return Tt.TranslationsGetter=r,Tt}var Gr={},Pl={},Rl,df;function Ns(){if(df)return Rl;df=1;var e=Array.isArray;return Rl=e,Rl}var Ol,pf;function C0(){if(pf)return Ol;pf=1;var e=typeof hi=="object"&&hi&&hi.Object===Object&&hi;return Ol=e,Ol}var Tl,hf;function Ls(){if(hf)return Tl;hf=1;var e=C0(),t=typeof self=="object"&&self&&self.Object===Object&&self,r=e||t||Function("return this")();return Tl=r,Tl}var Il,vf;function Ds(){if(vf)return Il;vf=1;var e=Ls(),t=e.Symbol;return Il=t,Il}var xl,gf;function P0(){if(gf)return xl;gf=1;var e=Ds(),t=Object.prototype,r=t.hasOwnProperty,n=t.toString,i=e?e.toStringTag:void 0;function o(l){var u=r.call(l,i),a=l[i];try{l[i]=void 0;var s=!0}catch{}var d=n.call(l);return s&&(u?l[i]=a:delete l[i]),d}return xl=o,xl}var jl,mf;function R0(){if(mf)return jl;mf=1;var e=Object.prototype,t=e.toString;function r(n){return t.call(n)}return jl=r,jl}var Ml,yf;function yg(){if(yf)return Ml;yf=1;var e=Ds(),t=P0(),r=R0(),n="[object Null]",i="[object Undefined]",o=e?e.toStringTag:void 0;function l(u){return u==null?u===void 0?i:n:o&&o in Object(u)?t(u):r(u)}return Ml=l,Ml}var Fl,_f;function O0(){if(_f)return Fl;_f=1;function e(t){return t!=null&&typeof t=="object"}return Fl=e,Fl}var Nl,wf;function As(){if(wf)return Nl;wf=1;var e=yg(),t=O0(),r="[object Symbol]";function n(i){return typeof i=="symbol"||t(i)&&e(i)==r}return Nl=n,Nl}var Ll,Sf;function T0(){if(Sf)return Ll;Sf=1;var e=Ns(),t=As(),r=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,n=/^\w*$/;function i(o,l){if(e(o))return!1;var u=typeof o;return u=="number"||u=="symbol"||u=="boolean"||o==null||t(o)?!0:n.test(o)||!r.test(o)||l!=null&&o in Object(l)}return Ll=i,Ll}var Dl,Ef;function _g(){if(Ef)return Dl;Ef=1;function e(t){var r=typeof t;return t!=null&&(r=="object"||r=="function")}return Dl=e,Dl}var Al,kf;function I0(){if(kf)return Al;kf=1;var e=yg(),t=_g(),r="[object AsyncFunction]",n="[object Function]",i="[object GeneratorFunction]",o="[object Proxy]";function l(u){if(!t(u))return!1;var a=e(u);return a==n||a==i||a==r||a==o}return Al=l,Al}var Bl,Cf;function x0(){if(Cf)return Bl;Cf=1;var e=Ls(),t=e["__core-js_shared__"];return Bl=t,Bl}var ql,Pf;function j0(){if(Pf)return ql;Pf=1;var e=x0(),t=function(){var n=/[^.]+$/.exec(e&&e.keys&&e.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}();function r(n){return!!t&&t in n}return ql=r,ql}var zl,Rf;function M0(){if(Rf)return zl;Rf=1;var e=Function.prototype,t=e.toString;function r(n){if(n!=null){try{return t.call(n)}catch{}try{return n+""}catch{}}return""}return zl=r,zl}var Ul,Of;function F0(){if(Of)return Ul;Of=1;var e=I0(),t=j0(),r=_g(),n=M0(),i=/[\\^$.*+?()[\]{}|]/g,o=/^\[object .+?Constructor\]$/,l=Function.prototype,u=Object.prototype,a=l.toString,s=u.hasOwnProperty,d=RegExp("^"+a.call(s).replace(i,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function g(m){if(!r(m)||t(m))return!1;var h=e(m)?d:o;return h.test(n(m))}return Ul=g,Ul}var bl,Tf;function N0(){if(Tf)return bl;Tf=1;function e(t,r){return t==null?void 0:t[r]}return bl=e,bl}var Vl,If;function wg(){if(If)return Vl;If=1;var e=F0(),t=N0();function r(n,i){var o=t(n,i);return e(o)?o:void 0}return Vl=r,Vl}var Hl,xf;function Ao(){if(xf)return Hl;xf=1;var e=wg(),t=e(Object,"create");return Hl=t,Hl}var Gl,jf;function L0(){if(jf)return Gl;jf=1;var e=Ao();function t(){this.__data__=e?e(null):{},this.size=0}return Gl=t,Gl}var Wl,Mf;function D0(){if(Mf)return Wl;Mf=1;function e(t){var r=this.has(t)&&delete this.__data__[t];return this.size-=r?1:0,r}return Wl=e,Wl}var $l,Ff;function A0(){if(Ff)return $l;Ff=1;var e=Ao(),t="__lodash_hash_undefined__",r=Object.prototype,n=r.hasOwnProperty;function i(o){var l=this.__data__;if(e){var u=l[o];return u===t?void 0:u}return n.call(l,o)?l[o]:void 0}return $l=i,$l}var Kl,Nf;function B0(){if(Nf)return Kl;Nf=1;var e=Ao(),t=Object.prototype,r=t.hasOwnProperty;function n(i){var o=this.__data__;return e?o[i]!==void 0:r.call(o,i)}return Kl=n,Kl}var Ql,Lf;function q0(){if(Lf)return Ql;Lf=1;var e=Ao(),t="__lodash_hash_undefined__";function r(n,i){var o=this.__data__;return this.size+=this.has(n)?0:1,o[n]=e&&i===void 0?t:i,this}return Ql=r,Ql}var Yl,Df;function z0(){if(Df)return Yl;Df=1;var e=L0(),t=D0(),r=A0(),n=B0(),i=q0();function o(l){var u=-1,a=l==null?0:l.length;for(this.clear();++u-1}return ru=t,ru}var nu,Vf;function W0(){if(Vf)return nu;Vf=1;var e=Bo();function t(r,n){var i=this.__data__,o=e(i,r);return o<0?(++this.size,i.push([r,n])):i[o][1]=n,this}return nu=t,nu}var iu,Hf;function $0(){if(Hf)return iu;Hf=1;var e=U0(),t=V0(),r=H0(),n=G0(),i=W0();function o(l){var u=-1,a=l==null?0:l.length;for(this.clear();++u{const a=o[u];return a?(0,e.getTranslationValueFromContent)(a,l):null};e.getTranslationValue=n;const i=(o,l)=>{let u=o[l];if(!u){const a=l.split(".");a.length>1&&(u=(0,r.default)(o,a,null))}return typeof u=="string"?u:null};e.getTranslationValueFromContent=i}(Pl)),Pl}var fd;function d1(){if(fd)return Gr;fd=1,Object.defineProperty(Gr,"__esModule",{value:!0}),Gr.Translator=void 0;const e=Sg();class t{constructor(n,i){it(this,"locale");it(this,"translationsGetter");it(this,"localeLookupOrderedTranslations",null);it(this,"cache",new Map);this.locale=n,this.translationsGetter=i}async init(){this.localeLookupOrderedTranslations=await this.translationsGetter.getTranslationsByLocaleLookupOrder(this.locale)}translate(n){if(!this.localeLookupOrderedTranslations)throw new Error("TranslationLookup not initialized");let i=this.cache.get(n);if(i===void 0){for(const{translations:o}of this.localeLookupOrderedTranslations){const l=(0,e.getTranslationValueFromContent)(o,n);if(l!==null){i=l;break}}i=i??null,this.cache.set(n,i)}return i}}return Gr.Translator=t,Gr}var Wr={},dd;function p1(){if(dd)return Wr;dd=1,Object.defineProperty(Wr,"__esModule",{value:!0}),Wr.ensureLocale=void 0;const e=mg(),t=new Set(e.FORGE_SUPPORTED_LOCALE_CODES),r={"en-UK":"en-GB","nb-NO":"no-NO"},n=e.FORGE_SUPPORTED_LOCALE_CODES.reduce((o,l)=>{const[u]=l.split("-");return o[u]||(o[u]=l),o},{nb:"no-NO",pt:"pt-PT"}),i=o=>{const l=o.replace("_","-");return t.has(l)?l:n[l]??r[l]??null};return Wr.ensureLocale=i,Wr}var Cu={},pd;function h1(){return pd||(pd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.extractI18nPropertiesFromModules=e.extractI18nKeysFromModules=e.getI18nSupportedModuleEntries=void 0;const t=s=>typeof s=="object"&&s!==null&&!Array.isArray(s),r=s=>typeof(s==null?void 0:s.i18n)=="string",n=s=>s.startsWith("connect-"),i=s=>s.startsWith("core:"),o=s=>{const d=new Set,g=(m,h)=>!t(m)||d.has(m)?[]:(d.add(m),Object.entries(m).flatMap(([y,v])=>{const _=[...h,y];return r(v)?[{propertyPath:_,key:v.i18n}]:Array.isArray(v)?v.flatMap(f=>g(f,_)):g(v,_)}));return g(s,[])},l=s=>Object.entries(s).flatMap(([d,g])=>!n(d)&&!i(d)&&g&&Array.isArray(g)&&g.length>0?g.map(m=>[m,d]):[]);e.getI18nSupportedModuleEntries=l;const u=s=>{const d=new Set;for(const g of(0,e.getI18nSupportedModuleEntries)(s)){const m=o(g[0]);for(const{key:h}of m)d.add(h)}return d.size>0?Array.from(d):[]};e.extractI18nKeysFromModules=u;const a=s=>{const d=[];for(const g of(0,e.getI18nSupportedModuleEntries)(s)){const m=o(g[0]);for(const h of m)d.push({moduleName:g[1],...h})}return d};e.extractI18nPropertiesFromModules=a}(Cu)),Cu}var Pu={},hd;function v1(){return hd||(hd=1,Object.defineProperty(Pu,"__esModule",{value:!0})),Pu}var vd;function Eg(){return vd||(vd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.getI18nSupportedModuleEntries=e.extractI18nPropertiesFromModules=e.extractI18nKeysFromModules=e.getTranslationValue=void 0;const t=me;t.__exportStar(mg(),e),t.__exportStar(k0(),e),t.__exportStar(d1(),e),t.__exportStar(p1(),e);var r=Sg();Object.defineProperty(e,"getTranslationValue",{enumerable:!0,get:function(){return r.getTranslationValue}});var n=h1();Object.defineProperty(e,"extractI18nKeysFromModules",{enumerable:!0,get:function(){return n.extractI18nKeysFromModules}}),Object.defineProperty(e,"extractI18nPropertiesFromModules",{enumerable:!0,get:function(){return n.extractI18nPropertiesFromModules}}),Object.defineProperty(e,"getI18nSupportedModuleEntries",{enumerable:!0,get:function(){return n.getI18nSupportedModuleEntries}}),t.__exportStar(v1(),e)}(Cl)),Cl}var gd;function g1(){if(gd)return Hr;gd=1,Object.defineProperty(Hr,"__esModule",{value:!0}),Hr.getContext=void 0;const e=D(),t=Eg(),r=(0,e.getCallBridge)(),n=async()=>{var i;const o=await r("getContext"),l=o==null?void 0:o.locale;return l&&(o.locale=(i=(0,t.ensureLocale)(l))!==null&&i!==void 0?i:l),o};return Hr.getContext=n,Hr}var $r={},md;function m1(){if(md)return $r;md=1,Object.defineProperty($r,"__esModule",{value:!0}),$r.changeWindowTitle=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=async i=>{try{await r("changeWindowTitle",i)}catch{throw new t.BridgeAPIError("the window title wasn't changed due to error.")}};return $r.changeWindowTitle=n,$r}var Kr={},yd;function y1(){if(yd)return Kr;yd=1,Object.defineProperty(Kr,"__esModule",{value:!0}),Kr.theme=void 0;const t=(0,D().getCallBridge)();return Kr.theme={enable:()=>t("enableTheming")},Kr}var Qr={},Yr={},Ru={},It={},_d;function kg(){if(_d)return It;_d=1,Object.defineProperty(It,"__esModule",{value:!0}),It.blobToBase64=It.base64ToBlob=void 0;const e=(r,n)=>{if(!r)return null;const i=r.includes(";base64")?r.split(",")[1]:r,o=atob(i),l=new Array(o.length);for(let a=0;anew Promise((n,i)=>{const o=new FileReader;o.onloadend=()=>{n(o.result)},o.onerror=i,o.readAsDataURL(r)});return It.blobToBase64=t,It}var wd;function _1(){return wd||(wd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.containsSerialisedBlobs=e.containsBlobs=e.deserialiseBlobsInPayload=e.serialiseBlobsInPayload=void 0;const t=kg(),r=s=>{if(typeof s!="object"||s===null||Object.prototype.toString.call(s)!=="[object Object]")return!1;const d=Object.getPrototypeOf(s);if(d===null)return!0;const g=Object.prototype.hasOwnProperty.call(d,"constructor")&&d.constructor;return typeof g=="function"&&g instanceof g&&Function.prototype.call(g)===Function.prototype.call(s)},n=async s=>({data:await(0,t.blobToBase64)(s),type:s.type}),i=s=>(0,t.base64ToBlob)(s.data,s.type),o=async s=>{if(s instanceof Blob)return{...await n(s),__isBlobData:!0};if(Array.isArray(s))return Promise.all(s.map(d=>(0,e.serialiseBlobsInPayload)(d)));if(s&&r(s)){const d=await Promise.all(Object.entries(s).map(async([g,m])=>[g,await(0,e.serialiseBlobsInPayload)(m)]));return Object.fromEntries(d)}return s};e.serialiseBlobsInPayload=o;const l=s=>{if(s&&r(s)&&"__isBlobData"in s){const d=s;return i({data:d.data,type:d.type})}if(Array.isArray(s))return s.map(d=>(0,e.deserialiseBlobsInPayload)(d));if(s&&r(s)){const d={};for(const[g,m]of Object.entries(s))d[g]=(0,e.deserialiseBlobsInPayload)(m);return d}return s};e.deserialiseBlobsInPayload=l;const u=s=>s instanceof Blob?!0:Array.isArray(s)?s.some(d=>(0,e.containsBlobs)(d)):s&&r(s)?Object.values(s).some(d=>(0,e.containsBlobs)(d)):!1;e.containsBlobs=u;const a=s=>s&&r(s)&&"__isBlobData"in s?!0:Array.isArray(s)?s.some(d=>(0,e.containsSerialisedBlobs)(d)):s&&r(s)?Object.values(s).some(d=>(0,e.containsSerialisedBlobs)(d)):!1;e.containsSerialisedBlobs=a}(Ru)),Ru}var Sd;function Cg(){if(Sd)return Yr;Sd=1,Object.defineProperty(Yr,"__esModule",{value:!0}),Yr.events=void 0;const e=D(),t=_1(),r=(0,e.getCallBridge)(),n=a=>s=>{let d=s;return(0,t.containsSerialisedBlobs)(s)&&(d=(0,t.deserialiseBlobsInPayload)(s)),a(d)},i=async(a,s)=>{let d=s;return(0,t.containsBlobs)(s)&&(d=await(0,t.serialiseBlobsInPayload)(s)),r("emit",{event:a,payload:d})},o=(a,s)=>r("on",{event:a,callback:n(s)}),l=async(a,s)=>{let d=s;return(0,t.containsBlobs)(s)&&(d=await(0,t.serialiseBlobsInPayload)(s)),r("emitPublic",{event:a,payload:d})},u=(a,s)=>r("onPublic",{event:a,callback:n(s)});return Yr.events={emit:i,on:o,emitPublic:l,onPublic:u},Yr}var Ed;function w1(){if(Ed)return Qr;Ed=1,Object.defineProperty(Qr,"__esModule",{value:!0}),Qr.emitReadyEvent=void 0;const e=Cg(),t=Tg(),n=(0,D().getCallBridge)(),i="EXTENSION_READY",o=async()=>{const l=await t.view.getContext();await e.events.emit(i,{localId:l.localId});try{await n("emitReadyEvent")}catch{}};return Qr.emitReadyEvent=o,Qr}const S1="modulepreload",E1=function(e,t){return new URL(e,t).href},kd={},k1=function(t,r,n){let i=Promise.resolve();if(r&&r.length>0){const l=document.getElementsByTagName("link"),u=document.querySelector("meta[property=csp-nonce]"),a=(u==null?void 0:u.nonce)||(u==null?void 0:u.getAttribute("nonce"));i=Promise.allSettled(r.map(s=>{if(s=E1(s,n),s in kd)return;kd[s]=!0;const d=s.endsWith(".css"),g=d?'[rel="stylesheet"]':"";if(!!n)for(let y=l.length-1;y>=0;y--){const v=l[y];if(v.href===s&&(!d||v.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${s}"]${g}`))return;const h=document.createElement("link");if(h.rel=d?"stylesheet":S1,d||(h.as="script"),h.crossOrigin="",h.href=s,a&&h.setAttribute("nonce",a),document.head.appendChild(h),d)return new Promise((y,v)=>{h.addEventListener("load",y),h.addEventListener("error",()=>v(new Error(`Unable to preload CSS for ${s}`)))})}))}function o(l){const u=new Event("vite:preloadError",{cancelable:!0});if(u.payload=l,window.dispatchEvent(u),!u.defaultPrevented)throw l}return i.then(l=>{for(const u of l||[])u.status==="rejected"&&o(u.reason);return t().catch(o)})};var Xr={},Ou={},Jr={},Mi={},Cd;function Pg(){if(Cd)return Mi;Cd=1,Object.defineProperty(Mi,"__esModule",{value:!0}),Mi.default=r;let e;const t=new Uint8Array(16);function r(){if(!e&&(e=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!e))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return e(t)}return Mi}var $t={},Zr={},en={},Pd;function C1(){if(Pd)return en;Pd=1,Object.defineProperty(en,"__esModule",{value:!0}),en.default=void 0;var e=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;return en.default=e,en}var Rd;function zo(){if(Rd)return Zr;Rd=1,Object.defineProperty(Zr,"__esModule",{value:!0}),Zr.default=void 0;var e=t(C1());function t(i){return i&&i.__esModule?i:{default:i}}function r(i){return typeof i=="string"&&e.default.test(i)}var n=r;return Zr.default=n,Zr}var Od;function Uo(){if(Od)return $t;Od=1,Object.defineProperty($t,"__esModule",{value:!0}),$t.default=void 0,$t.unsafeStringify=n;var e=t(zo());function t(l){return l&&l.__esModule?l:{default:l}}const r=[];for(let l=0;l<256;++l)r.push((l+256).toString(16).slice(1));function n(l,u=0){return r[l[u+0]]+r[l[u+1]]+r[l[u+2]]+r[l[u+3]]+"-"+r[l[u+4]]+r[l[u+5]]+"-"+r[l[u+6]]+r[l[u+7]]+"-"+r[l[u+8]]+r[l[u+9]]+"-"+r[l[u+10]]+r[l[u+11]]+r[l[u+12]]+r[l[u+13]]+r[l[u+14]]+r[l[u+15]]}function i(l,u=0){const a=n(l,u);if(!(0,e.default)(a))throw TypeError("Stringified UUID is invalid");return a}var o=i;return $t.default=o,$t}var Td;function P1(){if(Td)return Jr;Td=1,Object.defineProperty(Jr,"__esModule",{value:!0}),Jr.default=void 0;var e=r(Pg()),t=Uo();function r(s){return s&&s.__esModule?s:{default:s}}let n,i,o=0,l=0;function u(s,d,g){let m=d&&g||0;const h=d||new Array(16);s=s||{};let y=s.node||n,v=s.clockseq!==void 0?s.clockseq:i;if(y==null||v==null){const S=s.random||(s.rng||e.default)();y==null&&(y=n=[S[0]|1,S[1],S[2],S[3],S[4],S[5]]),v==null&&(v=i=(S[6]<<8|S[7])&16383)}let _=s.msecs!==void 0?s.msecs:Date.now(),f=s.nsecs!==void 0?s.nsecs:l+1;const c=_-o+(f-l)/1e4;if(c<0&&s.clockseq===void 0&&(v=v+1&16383),(c<0||_>o)&&s.nsecs===void 0&&(f=0),f>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");o=_,l=f,i=v,_+=122192928e5;const p=((_&268435455)*1e4+f)%4294967296;h[m++]=p>>>24&255,h[m++]=p>>>16&255,h[m++]=p>>>8&255,h[m++]=p&255;const w=_/4294967296*1e4&268435455;h[m++]=w>>>8&255,h[m++]=w&255,h[m++]=w>>>24&15|16,h[m++]=w>>>16&255,h[m++]=v>>>8|128,h[m++]=v&255;for(let S=0;S<6;++S)h[m+S]=y[S];return d||(0,t.unsafeStringify)(h)}var a=u;return Jr.default=a,Jr}var tn={},lt={},rn={},Id;function Rg(){if(Id)return rn;Id=1,Object.defineProperty(rn,"__esModule",{value:!0}),rn.default=void 0;var e=t(zo());function t(i){return i&&i.__esModule?i:{default:i}}function r(i){if(!(0,e.default)(i))throw TypeError("Invalid UUID");let o;const l=new Uint8Array(16);return l[0]=(o=parseInt(i.slice(0,8),16))>>>24,l[1]=o>>>16&255,l[2]=o>>>8&255,l[3]=o&255,l[4]=(o=parseInt(i.slice(9,13),16))>>>8,l[5]=o&255,l[6]=(o=parseInt(i.slice(14,18),16))>>>8,l[7]=o&255,l[8]=(o=parseInt(i.slice(19,23),16))>>>8,l[9]=o&255,l[10]=(o=parseInt(i.slice(24,36),16))/1099511627776&255,l[11]=o/4294967296&255,l[12]=o>>>24&255,l[13]=o>>>16&255,l[14]=o>>>8&255,l[15]=o&255,l}var n=r;return rn.default=n,rn}var xd;function Og(){if(xd)return lt;xd=1,Object.defineProperty(lt,"__esModule",{value:!0}),lt.URL=lt.DNS=void 0,lt.default=l;var e=Uo(),t=r(Rg());function r(u){return u&&u.__esModule?u:{default:u}}function n(u){u=unescape(encodeURIComponent(u));const a=[];for(let s=0;s>5]>>>f%32&255,p=parseInt(_.charAt(c>>>4&15)+_.charAt(c&15),16);y.push(p)}return y}function r(h){return(h+64>>>9<<4)+14+1}function n(h,y){h[y>>5]|=128<>5]|=(h[_/8]&255)<<_%32;return v}function o(h,y){const v=(h&65535)+(y&65535);return(h>>16)+(y>>16)+(v>>16)<<16|v&65535}function l(h,y){return h<>>32-y}function u(h,y,v,_,f,c){return o(l(o(o(y,h),o(_,c)),f),v)}function a(h,y,v,_,f,c,p){return u(y&v|~y&_,h,y,f,c,p)}function s(h,y,v,_,f,c,p){return u(y&_|v&~_,h,y,f,c,p)}function d(h,y,v,_,f,c,p){return u(y^v^_,h,y,f,c,p)}function g(h,y,v,_,f,c,p){return u(v^(y|~_),h,y,f,c,p)}var m=e;return nn.default=m,nn}var Md;function O1(){if(Md)return tn;Md=1,Object.defineProperty(tn,"__esModule",{value:!0}),tn.default=void 0;var e=r(Og()),t=r(R1());function r(o){return o&&o.__esModule?o:{default:o}}var i=(0,e.default)("v3",48,t.default);return tn.default=i,tn}var on={},ln={},Fd;function T1(){if(Fd)return ln;Fd=1,Object.defineProperty(ln,"__esModule",{value:!0}),ln.default=void 0;var t={randomUUID:typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto)};return ln.default=t,ln}var Nd;function I1(){if(Nd)return on;Nd=1,Object.defineProperty(on,"__esModule",{value:!0}),on.default=void 0;var e=n(T1()),t=n(Pg()),r=Uo();function n(l){return l&&l.__esModule?l:{default:l}}function i(l,u,a){if(e.default.randomUUID&&!u&&!l)return e.default.randomUUID();l=l||{};const s=l.random||(l.rng||t.default)();if(s[6]=s[6]&15|64,s[8]=s[8]&63|128,u){a=a||0;for(let d=0;d<16;++d)u[a+d]=s[d];return u}return(0,r.unsafeStringify)(s)}var o=i;return on.default=o,on}var un={},an={},Ld;function x1(){if(Ld)return an;Ld=1,Object.defineProperty(an,"__esModule",{value:!0}),an.default=void 0;function e(i,o,l,u){switch(i){case 0:return o&l^~o&u;case 1:return o^l^u;case 2:return o&l^o&u^l&u;case 3:return o^l^u}}function t(i,o){return i<>>32-o}function r(i){const o=[1518500249,1859775393,2400959708,3395469782],l=[1732584193,4023233417,2562383102,271733878,3285377520];if(typeof i=="string"){const d=unescape(encodeURIComponent(i));i=[];for(let g=0;g>>0;_=v,v=y,y=t(h,30)>>>0,h=m,m=p}l[0]=l[0]+m>>>0,l[1]=l[1]+h>>>0,l[2]=l[2]+y>>>0,l[3]=l[3]+v>>>0,l[4]=l[4]+_>>>0}return[l[0]>>24&255,l[0]>>16&255,l[0]>>8&255,l[0]&255,l[1]>>24&255,l[1]>>16&255,l[1]>>8&255,l[1]&255,l[2]>>24&255,l[2]>>16&255,l[2]>>8&255,l[2]&255,l[3]>>24&255,l[3]>>16&255,l[3]>>8&255,l[3]&255,l[4]>>24&255,l[4]>>16&255,l[4]>>8&255,l[4]&255]}var n=r;return an.default=n,an}var Dd;function j1(){if(Dd)return un;Dd=1,Object.defineProperty(un,"__esModule",{value:!0}),un.default=void 0;var e=r(Og()),t=r(x1());function r(o){return o&&o.__esModule?o:{default:o}}var i=(0,e.default)("v5",80,t.default);return un.default=i,un}var sn={},Ad;function M1(){if(Ad)return sn;Ad=1,Object.defineProperty(sn,"__esModule",{value:!0}),sn.default=void 0;var e="00000000-0000-0000-0000-000000000000";return sn.default=e,sn}var cn={},Bd;function F1(){if(Bd)return cn;Bd=1,Object.defineProperty(cn,"__esModule",{value:!0}),cn.default=void 0;var e=t(zo());function t(i){return i&&i.__esModule?i:{default:i}}function r(i){if(!(0,e.default)(i))throw TypeError("Invalid UUID");return parseInt(i.slice(14,15),16)}var n=r;return cn.default=n,cn}var qd;function N1(){return qd||(qd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"NIL",{enumerable:!0,get:function(){return o.default}}),Object.defineProperty(e,"parse",{enumerable:!0,get:function(){return s.default}}),Object.defineProperty(e,"stringify",{enumerable:!0,get:function(){return a.default}}),Object.defineProperty(e,"v1",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"v3",{enumerable:!0,get:function(){return r.default}}),Object.defineProperty(e,"v4",{enumerable:!0,get:function(){return n.default}}),Object.defineProperty(e,"v5",{enumerable:!0,get:function(){return i.default}}),Object.defineProperty(e,"validate",{enumerable:!0,get:function(){return u.default}}),Object.defineProperty(e,"version",{enumerable:!0,get:function(){return l.default}});var t=d(P1()),r=d(O1()),n=d(I1()),i=d(j1()),o=d(M1()),l=d(F1()),u=d(zo()),a=d(Uo()),s=d(Rg());function d(g){return g&&g.__esModule?g:{default:g}}}(Ou)),Ou}var zd;function L1(){if(zd)return Xr;zd=1,Object.defineProperty(Xr,"__esModule",{value:!0}),Xr.createAdfRendererIframeProps=void 0;const e=N1(),t=async(r,n)=>{const i=await k1(()=>import("./index-BLip8HpJ.js").then(d=>d.i),[],import.meta.url),o=i.default||i,l=new URL(document.referrer).origin,u=`${l}/forge-apps/adf-renderer`,a=n||`forge-adf-renderer-iframe-${(0,e.v4)()}`,s=()=>{var d,g,m,h,y,v;const _=document.getElementById(a),f={type:"adf-document",document:(d=r.extension.macro)===null||d===void 0?void 0:d.body,timestamp:Date.now(),source:"forge-adf-renderer",localId:r.localId,isEditing:(m=(g=r.extension)===null||g===void 0?void 0:g.isEditing)!==null&&m!==void 0?m:!1,contentId:(y=(h=r.extension)===null||h===void 0?void 0:h.content)===null||y===void 0?void 0:y.id};o.iframeResizer({heightCalculationMethod:"taggedElement",widthCalculationMethod:"bodyScroll",initCallback:c=>{var p;(p=c==null?void 0:c.iFrameResizer)===null||p===void 0||p.resize()}},_||""),(v=_==null?void 0:_.contentWindow)===null||v===void 0||v.postMessage(f,l)};return setTimeout(()=>{document.documentElement.style.height="auto",document.body.style.height="auto"},200),{id:a,src:u,onLoad:s}};return Xr.createAdfRendererIframeProps=t,Xr}var fn={},Ud;function D1(){if(Ud)return fn;Ud=1,Object.defineProperty(fn,"__esModule",{value:!0}),fn.onClose=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=async i=>{try{if(await r("onClose",i)===!1)throw new t.BridgeAPIError("`onClose` call has failed.")}catch{throw new t.BridgeAPIError("`onClose` failed because this resource's view is not closable.")}};return fn.onClose=n,fn}var bd;function Tg(){if(bd)return Br;bd=1,Object.defineProperty(Br,"__esModule",{value:!0}),Br.view=void 0;const e=y0(),t=_0(),r=w0(),n=S0(),i=E0(),o=g1(),l=m1(),u=y1(),a=w1(),s=L1(),d=D1();return Br.view={submit:e.submit,close:t.close,onClose:d.onClose,open:r.open,refresh:n.refresh,createHistory:i.createHistory,getContext:o.getContext,theme:u.theme,changeWindowTitle:l.changeWindowTitle,emitReadyEvent:a.emitReadyEvent,createAdfRendererIframeProps:s.createAdfRendererIframeProps},Br}var Vd;function bo(){return Vd||(Vd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),me.__exportStar(Tg(),e)}(kl)),kl}var Tu={},dn={},Hd;function A1(){if(Hd)return dn;Hd=1,Object.defineProperty(dn,"__esModule",{value:!0}),dn.router=void 0;const t=(0,D().getCallBridge)(),r=async l=>{if(!(l!=null&&l.target))throw new Error("target is required for getUrl");const u=await t("getUrl",l);if(!u)throw new Error("Failed to get URL");try{return new URL(u)}catch(a){throw new Error(`Failed to parse URL: ${u} (${a})`)}},n=l=>{if(typeof l=="string")return t("navigate",{url:l,type:"same-tab"});if(!(l!=null&&l.target))throw new Error("target is required for navigation");return t("navigate",{...l,type:"same-tab"})},i=l=>{if(typeof l=="string")return t("navigate",{url:l,type:"new-tab"});if(!(l!=null&&l.target))throw new Error("target is required for navigation");return t("navigate",{...l,type:"new-tab"})},o=async()=>t("reload");return dn.router={getUrl:r,navigate:n,open:i,reload:o},dn}var Gd;function B1(){return Gd||(Gd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),me.__exportStar(A1(),e)}(Tu)),Tu}var Iu={},pn={},Wd;function q1(){if(Wd)return pn;Wd=1,Object.defineProperty(pn,"__esModule",{value:!0}),pn.Modal=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=()=>{};class i{constructor(l){var u,a;this.resource=(l==null?void 0:l.resource)||null,this.onClose=(l==null?void 0:l.onClose)||n,this.size=(l==null?void 0:l.size)||"medium",this.context=(l==null?void 0:l.context)||{},this.closeOnEscape=(u=l==null?void 0:l.closeOnEscape)!==null&&u!==void 0?u:!0,this.closeOnOverlayClick=(a=l==null?void 0:l.closeOnOverlayClick)!==null&&a!==void 0?a:!0,this.title=(l==null?void 0:l.title)||"",this.icon=(l==null?void 0:l.icon)||""}async open(){try{if(await r("openModal",{resource:this.resource,onClose:this.onClose,size:this.size,context:this.context,closeOnEscape:this.closeOnEscape,closeOnOverlayClick:this.closeOnOverlayClick,title:this.title,icon:this.icon})===!1)throw new t.BridgeAPIError("Unable to open modal.")}catch{throw new t.BridgeAPIError("Unable to open modal.")}}}return pn.Modal=i,pn}var $d;function z1(){return $d||($d=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),me.__exportStar(q1(),e)}(Iu)),Iu}var Me={},xt={},Kd;function U1(){if(Kd)return xt;Kd=1,Object.defineProperty(xt,"__esModule",{value:!0}),xt.productFetchApi=xt.remoteFetchApi=void 0;const e=kg(),t=async(l,u=!1)=>{const a={};for(const[s,d]of l.entries())if(u?s.startsWith("file"):s==="file"){const m=d.name,h=d.type;a[s]=await(0,e.blobToBase64)(d),a[`__${s}Name`]=m,a[`__${s}Type`]=h}else a[s]=d;return JSON.stringify(a)},r=l=>{if(!l)return l;if("signal"in l){const{signal:u,...a}=l;return console.error("Signal is not supported in @forge/bridge and was removed from fetch options. Please use the fetch method from @forge/api for signal support."),a}return l},n=async(l,u)=>{const a=(u==null?void 0:u.body)instanceof FormData,s=a?await t(u==null?void 0:u.body,l==="remote"):u==null?void 0:u.body,d=new Request("",{body:s,method:u==null?void 0:u.method,headers:u==null?void 0:u.headers}),g=Object.fromEntries(d.headers.entries());return{body:d.method!=="GET"?await d.text():null,headers:new Headers(g),isMultipartFormData:a}},i=l=>{const u=async(a,s)=>{const d=r(s),{body:g,headers:m,isMultipartFormData:h}=await n("remote",d),y={remoteKey:a,fetchRequestInit:{...d,body:g,headers:[...m.entries()]},isMultipartFormData:h},{body:v,headers:_,statusText:f,status:c,isAttachment:p}=await l("fetchRemote",y),w=p?(0,e.base64ToBlob)(v,_["content-type"]):v;return new Response(w||null,{headers:_,status:c,statusText:f})};return{requestRemote:(a,s)=>u(a,s)}};xt.remoteFetchApi=i;const o=l=>{const u=async(a,s,d)=>{const g=r(d),{body:m,headers:h,isMultipartFormData:y}=await n("product",g);h.has("X-Atlassian-Token")||h.set("X-Atlassian-Token","no-check");const v={product:a,restPath:s,fetchRequestInit:{...g,body:m,headers:[...h.entries()]},isMultipartFormData:y},{body:_,headers:f,statusText:c,status:p,isAttachment:w}=await l("fetchProduct",v),S=w?(0,e.base64ToBlob)(_,f["content-type"]):_;return new Response(S||null,{headers:f,status:p,statusText:c})};return{requestConfluence:(a,s)=>u("confluence",a,s),requestJira:(a,s)=>u("jira",a,s),requestBitbucket:(a,s)=>u("bitbucket",a,s)}};return xt.productFetchApi=o,xt}var Qd;function b1(){if(Qd)return Me;Qd=1;var e;Object.defineProperty(Me,"__esModule",{value:!0}),Me.requestRemote=Me.requestBitbucket=Me.requestJira=Me.requestConfluence=void 0;const t=D(),r=U1();return e=(0,r.productFetchApi)((0,t.getCallBridge)()),Me.requestConfluence=e.requestConfluence,Me.requestJira=e.requestJira,Me.requestBitbucket=e.requestBitbucket,Me.requestRemote=(0,r.remoteFetchApi)((0,t.getCallBridge)()).requestRemote,Me}var xu={},hn={},Yd;function V1(){if(Yd)return hn;Yd=1,Object.defineProperty(hn,"__esModule",{value:!0}),hn.showFlag=void 0;const e=D(),t=Q(),r=(0,e.getCallBridge)(),n=i=>{var o;if(!i.id)throw new t.BridgeAPIError('"id" must be defined in flag options');const l=r("showFlag",{...i,type:(o=i.type)!==null&&o!==void 0?o:"info"});return{close:async()=>(await l,r("closeFlag",{id:i.id}))}};return hn.showFlag=n,hn}var Xd;function H1(){return Xd||(Xd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.showFlag=void 0;var t=V1();Object.defineProperty(e,"showFlag",{enumerable:!0,get:function(){return t.showFlag}})}(xu)),xu}var ju={},Jd;function G1(){return Jd||(Jd=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),me.__exportStar(Cg(),e)}(ju)),ju}var Mu={},vn={},Zd;function W1(){if(Zd)return vn;Zd=1,Object.defineProperty(vn,"__esModule",{value:!0}),vn.realtime=void 0;const t=(0,D().getCallBridge)(),r=(l,u,a)=>t("publishRealtimeChannel",{channelName:l,eventPayload:u,options:a}),n=(l,u,a)=>t("subscribeRealtimeChannel",{channelName:l,onEvent:u,options:a}),i=(l,u,a)=>t("publishRealtimeChannel",{channelName:l,eventPayload:u,options:a,isGlobal:!0}),o=(l,u,a)=>t("subscribeRealtimeChannel",{channelName:l,onEvent:u,options:a,isGlobal:!0});return vn.realtime={publish:r,subscribe:n,publishGlobal:i,subscribeGlobal:o},vn}var Fu={},ep;function $1(){return ep||(ep=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.Bitbucket=e.Confluence=e.Jira=void 0,function(t){t.Board="board",t.Issue="issue",t.Project="project"}(e.Jira||(e.Jira={})),function(t){t.Content="content",t.Space="space"}(e.Confluence||(e.Confluence={})),function(t){t.Repository="repository",t.PullRequest="pullRequest"}(e.Bitbucket||(e.Bitbucket={}))}(Fu)),Fu}var tp;function K1(){return tp||(tp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.Bitbucket=e.Confluence=e.Jira=e.realtime=void 0;var t=W1();Object.defineProperty(e,"realtime",{enumerable:!0,get:function(){return t.realtime}});var r=$1();Object.defineProperty(e,"Jira",{enumerable:!0,get:function(){return r.Jira}}),Object.defineProperty(e,"Confluence",{enumerable:!0,get:function(){return r.Confluence}}),Object.defineProperty(e,"Bitbucket",{enumerable:!0,get:function(){return r.Bitbucket}})}(Mu)),Mu}var Nu={},gn={},Lu={},rp;function Q1(){return rp||(rp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.open=e.OPEN_ROVO_BRIDGE_ERROR_MESSAGE=void 0;const t=D(),r=Q(),n=30,i=(0,t.getCallBridge)();e.OPEN_ROVO_BRIDGE_ERROR_MESSAGE="Unable to open Rovo Chat due to usage in an unsupported product. Only Confluence, Jira and some Jira Service Management modules are supported at this point. See https://developer.atlassian.com/platform/forge/apis-reference/ui-api-bridge/rovo/";const o=u=>{switch(u.type){case"forge":return{agentName:u.agentName,agentKey:u.agentKey,prompt:u.prompt};case"atlassian":return{agentName:u.agentName,prompt:u.prompt};default:return{prompt:u.prompt}}},l=async u=>{if(u.type==="forge"){if(u.agentName.length>n)throw new Error("rovo agent name too long");if(u.agentKey.length>n)throw new Error("rovo agent key too long")}const a=o(u);if(await i("openRovo",a)===!1)throw new r.BridgeAPIError(e.OPEN_ROVO_BRIDGE_ERROR_MESSAGE)};e.open=l}(Lu)),Lu}var mn={},np;function Y1(){if(np)return mn;np=1,Object.defineProperty(mn,"__esModule",{value:!0}),mn.isEnabled=void 0;const t=(0,D().getCallBridge)(),r=()=>t("isRovoEnabled");return mn.isEnabled=r,mn}var ip;function X1(){if(ip)return gn;ip=1,Object.defineProperty(gn,"__esModule",{value:!0}),gn.rovo=void 0;const e=Q1(),t=Y1();return gn.rovo={open:e.open,isEnabled:t.isEnabled},gn}var op;function J1(){return op||(op=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),me.__exportStar(X1(),e)}(Nu)),Nu}var We={},lp;function Z1(){if(lp)return We;lp=1,Object.defineProperty(We,"__esModule",{value:!0}),We.createTranslationFunction=We.getTranslations=We.resetTranslationsCache=void 0;const e=Eg(),t=bo(),r={getI18nInfoConfig:async()=>{const u=await fetch(`./${e.I18N_BUNDLE_FOLDER_NAME}/${e.I18N_INFO_FILE_NAME}`);if(!u.ok)throw new Error("Failed to get i18n info config: "+u.statusText);return(await u.json()).config},getTranslationResource:async u=>{const a=await fetch(`./${e.I18N_BUNDLE_FOLDER_NAME}/${u}.json`);if(!a.ok)throw new Error(`Failed to get translation resource for locale: ${u}`);return a.json()}},n=new e.TranslationsGetter(r),i=()=>{n.reset()};We.resetTranslationsCache=i;const o=async(u=null,a={fallback:!0})=>{let s=u;return s||(s=(await t.view.getContext()).locale),await n.getTranslations(s,a)};We.getTranslations=o;const l=async(u=null)=>{let a=u;a||(a=(await t.view.getContext()).locale);const s=new e.Translator(a,n);return await s.init(),(d,g)=>{var m,h;return(h=(m=s.translate(d))!==null&&m!==void 0?m:g)!==null&&h!==void 0?h:d}};return We.createTranslationFunction=l,We}var Du={},yn={},up;function e_(){if(up)return yn;up=1,Object.defineProperty(yn,"__esModule",{value:!0}),yn.permissions=void 0;const t=(0,D().getCallBridge)(),r=async a=>t("__permission__egressGet",a),n=async a=>t("__permission__egressSet",a),i=async a=>t("__permission__egressDeleteDomain",a),o=async a=>t("__permission__egressDeleteGroup",a),l=async a=>t("__permission__remoteGet",a),u=async a=>t("__permission__remoteSet",a);return yn.permissions={egress:{get:r,set:n,deleteDomain:i,deleteGroup:o},remote:{get:l,set:u}},yn}var jt={},Au={},Bu={},_n={},wn={},ap;function Bs(){if(ap)return wn;ap=1,Object.defineProperty(wn,"__esModule",{value:!0}),wn.parseUrl=void 0;function e(t){var r,n;const i=(n=(r=t.match(/^(.*?:)/))===null||r===void 0?void 0:r[0])!==null&&n!==void 0?n:"https:",o=t.replace(i,"").replace(/^\/*/,"").replace(/^\\*/,"").split("?")[0].split("#")[0],l=o.split("/")[0],u=o.slice(l.length)||"/";return{protocol:i,hostname:l,pathname:u}}return wn.parseUrl=e,wn}var qu={},sp;function Ig(){return sp||(sp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.getEgressesBasedOnToggles=e.sortAndGroupEgressPermissionsByDomain=e.EgressCategory=e.EgressType=e.globToRegex=void 0;const t=Bs();function r(l){const a=l.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${a}$`)}e.globToRegex=r;const n=l=>{if((l==null?void 0:l.length)===0)return[];const u=/^(.*?:\/\/)/,a=new Set,s=[];return l.forEach(d=>{const g=u.test(d)?d:`https://${d}`,m=(0,t.parseUrl)(g);m.hostname.startsWith("*")?(a.add(m.hostname.substring(2)),s.push(r(m.hostname))):a.add(m.hostname)}),[...a].sort().reduce((d,g)=>(s.some(m=>m.test(g))||d.push(g),d),[])};e.sortAndGroupEgressPermissionsByDomain=n,function(l){l.FetchBackendSide="FETCH_BACKEND_SIDE",l.FetchClientSide="FETCH_CLIENT_SIDE",l.Fonts="FONTS",l.Frames="FRAMES",l.Images="IMAGES",l.Media="MEDIA",l.Navigation="NAVIGATION",l.Scripts="SCRIPTS",l.Styles="STYLES"}(e.EgressType||(e.EgressType={}));var i;(function(l){l.ANALYTICS="ANALYTICS"})(i=e.EgressCategory||(e.EgressCategory={}));const o=l=>{const u=l.egress.filter(s=>{var d;if(((d=s.category)===null||d===void 0?void 0:d.toUpperCase())===i.ANALYTICS)if(l.installationConfig){const g=l.installationConfig.find(m=>m.key.toUpperCase()==="ALLOW_EGRESS_ANALYTICS");return(g==null?void 0:g.value)!==!1}else return l.overrides.ALLOW_EGRESS_ANALYTICS!==!1;return!0}),a=new Map;for(const s of u)a.has(s.type)||a.set(s.type,s.addresses),a.set(s.type,[...a.get(s.type),...s.addresses]);return[...a.entries()].map(([s,d])=>({type:s,addresses:[...new Set(d)]}))};e.getEgressesBasedOnToggles=o}(qu)),qu}var cp;function t_(){if(cp)return _n;cp=1,Object.defineProperty(_n,"__esModule",{value:!0}),_n.EgressFilteringService=void 0;const e=Bs(),t=Ig();class r{constructor(i){this.URLs=i.filter(o=>!o.startsWith("*")).map(o=>this.parseUrl(o)),this.wildcardDomains=i.filter(o=>o!=="*").map(o=>this.parseUrl(o)).filter(o=>decodeURIComponent(o.hostname).startsWith("*")).map(o=>({...o,regex:(0,t.globToRegex)(decodeURIComponent(o.hostname))})),this.allowsEverything=i.includes("*")}parseUrl(i){return(0,e.parseUrl)(i)}containsWildCardEgress(){return this.allowsEverything}isValidUrl(i){if(this.allowsEverything)return!0;const o=this.parseUrl(i);return this.allowedDomainExact(o,this.URLs)||this.allowedDomainPattern(o,this.wildcardDomains)}isValidUrlCSP(i){if(this.allowsEverything)return!0;const o=this.parseUrl(i);return this.allowedDomainExactAndPath(o,this.URLs)||this.allowedDomainPatternAndPath(o,this.wildcardDomains)}allowedDomainExact(i,o){return o.filter(l=>l.protocol===i.protocol).some(l=>l.hostname===i.hostname)}allowedDomainExactAndPath(i,o){return o.filter(l=>this.protocolMatchesCSP(l.protocol,i.protocol)).filter(l=>l.hostname===i.hostname).some(l=>this.pathMatches(l.pathname,i.pathname))}allowedDomainPattern(i,o){return o.filter(l=>l.protocol===i.protocol).some(l=>l.regex.test(i.hostname))}allowedDomainPatternAndPath(i,o){return o.filter(l=>this.protocolMatchesCSP(l.protocol,i.protocol)).filter(l=>l.regex.test(i.hostname)).some(l=>this.pathMatches(l.pathname,i.pathname))}protocolMatchesCSP(i,o){return i===o||i==="http:"&&o==="https:"||i==="ws:"&&o==="wss:"}pathMatches(i,o){return i==="/"?!0:i.endsWith("/")?o.startsWith(i):o===i}}return _n.EgressFilteringService=r,_n}var fp;function r_(){return fp||(fp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0});const t=me;t.__exportStar(t_(),e),t.__exportStar(Bs(),e),t.__exportStar(Ig(),e)}(Bu)),Bu}var dp;function n_(){return dp||(dp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),me.__exportStar(r_(),e)}(Au)),Au}var pp;function i_(){if(pp)return jt;pp=1,Object.defineProperty(jt,"__esModule",{value:!0}),jt.checkPermissions=jt.createPermissionUtils=void 0;const e=n_(),t=bo();function r(y){return typeof y=="string"?y:"address"in y&&y.address?y.address:y.remote||""}const n=["fonts","styles","frames","images","media","scripts"],i=["backend","client"];function o(y){if(!y)return null;const{scopes:v,external:_={}}=y,f=Array.isArray(v)?v:Object.keys(v||{});return{hasScope:c=>f.includes(c),canFetchFrom:(c,p)=>{var w;const S=(w=_.fetch)===null||w===void 0?void 0:w[c];if(!(S!=null&&S.length))return!1;const k=S.map(r).filter(M=>M.length>0);if(k.length===0)return!1;const C=new e.EgressFilteringService(k);return c==="client"?C.isValidUrlCSP(p):C.isValidUrl(p)},canLoadResource:(c,p)=>{const w=_[c];if(!(w!=null&&w.length))return!1;const S=w.map(r).filter(O=>O.length>0);return S.length===0?!1:new e.EgressFilteringService(S).isValidUrlCSP(p)},getScopes:()=>f,getExternalPermissions:()=>_,hasAnyPermissions:()=>f.length>0||Object.keys(_).length>0}}jt.createPermissionUtils=o;function l(y,v){if(!(y!=null&&y.length))return;const _=y.filter(f=>!v.hasScope(f));return _.length>0?_:void 0}function u(y,v){if(!(y!=null&&y.fetch))return;const _={};return i.forEach(f=>{var c;const p=(c=y.fetch)===null||c===void 0?void 0:c[f];if(p!=null&&p.length){const w=p.filter(S=>!v.canFetchFrom(f,S));w.length>0&&(_[f]=w)}}),Object.keys(_).length>0?_:void 0}function a(y,v){const _={};return n.forEach(f=>{const c=y==null?void 0:y[f];if(c!=null&&c.length){const p=c.filter(w=>!v.canLoadResource(f,w));p.length>0&&(_[f]=p)}}),Object.keys(_).length>0?_:void 0}function s(y,v){if(!y)return;const _=u(y,v),f=a(y,v);if(!_&&!f)return;const c={};return _&&(c.fetch=_),f&&Object.assign(c,f),c}function d(y,v){if(y!==void 0&&(typeof y!="object"||y===null||Array.isArray(y)))throw new TypeError(`${v} should be an object, not ${Array.isArray(y)?"an array":`a ${typeof y}`}`)}function g(y,v){if(y!==void 0&&!Array.isArray(y))throw new TypeError(`${v} should be an array, not a ${typeof y}`)}function m(y){g(y.scopes,"scopes");const v=y.external;if(v!==void 0){if(d(v,"external"),v.fetch!==void 0){d(v.fetch,"external.fetch");for(const _ of i)g(v.fetch[_],`external.fetch.${_}`)}for(const _ of n)g(v[_],`external.${_}`)}}async function h(y,v){var _;if(!y)return{granted:!1,missing:null};if(m(y),!(!((_=y.scopes)===null||_===void 0)&&_.length)&&!y.external)return{granted:!0,missing:null};let f=v;f||(f=(await t.view.getContext()).permissions);const c=o(f);if(!c)return{granted:!1,missing:null};const p={};let w=!0;const S=l(y.scopes,c);S&&(p.scopes=S,w=!1);const k=s(y.external,c);return k&&(p.external=k,w=!1),{granted:w,missing:w?null:p}}return jt.checkPermissions=h,jt}var hp;function o_(){return hp||(hp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0});const t=me;t.__exportStar(e_(),e),t.__exportStar(i_(),e)}(Du)),Du}var zu={},Uu={},bu={},Sn={},En={},vp;function xg(){return vp||(vp=1,Object.defineProperty(En,"__esModule",{value:!0}),En.BRIDGE_OBJECT_STORE_RESTRICTED_ENVIRONMENT_ERROR=void 0,En.BRIDGE_OBJECT_STORE_RESTRICTED_ENVIRONMENT_ERROR="Object Store bridge methods are restricted to Forge apps in a non-production environment. For more information please see https://developer.atlassian.com/platform/forge/cli-reference/environments/ for reference on Forge app environments."),En}var gp;function Vo(){if(gp)return Sn;gp=1,Object.defineProperty(Sn,"__esModule",{value:!0}),Sn.checkRestrictedEnvironment=void 0;const e=Q(),t=bo(),r=xg(),n=async()=>{const{environmentType:i}=await t.view.getContext();if(i==="PRODUCTION")throw new e.BridgeAPIError(r.BRIDGE_OBJECT_STORE_RESTRICTED_ENVIRONMENT_ERROR)};return Sn.checkRestrictedEnvironment=n,Sn}var mp;function l_(){return mp||(mp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.upload=e.createUploadPromises=void 0;const t=fi(),r=Q(),n=Vo(),o=(0,D().getCallBridge)(),l=(d,g)=>{const m=atob(d),h=new Array(m.length);for(let v=0;v{const g=d.size,m=await d.arrayBuffer(),h=await crypto.subtle.digest("SHA-256",m),y=new Uint8Array(h),v=btoa(String.fromCharCode(...y));return{length:g,checksum:v,checksumType:"SHA256"}},a=async({functionKey:d,objects:g})=>{if(!d||d.length===0)throw new r.BridgeAPIError("functionKey is required to filter and generate presigned URLs");if(!Array.isArray(g)||g.length===0)throw new r.BridgeAPIError("objects array is required and must not be empty");const m=g.map((c,p)=>{if(c instanceof Blob)return c;if(!(c&&typeof c=="object"&&"data"in c&&typeof c.data=="string"))throw new r.BridgeAPIError(`Invalid object type at index ${p}. Only Blob or Base64Object (with data string and optional mimeType) are accepted.`);try{return l(c.data,c.mimeType)}catch{throw new r.BridgeAPIError(`Invalid base64 data at index ${p}. The data string must be valid base64 encoded.`)}}),h=await Promise.all(m.map(c=>u(c))),y=await(0,t.invoke)(d,{allObjectMetadata:h});if(!y||typeof y!="object")throw new r.BridgeAPIError("Invalid response from functionKey");const v=new Map,_=new Map;return m.forEach((c,p)=>{const w=h[p];v.set(w.checksum,c),_.set(w.checksum,p)}),Object.entries(y).map(([c,p])=>{const{key:w,checksum:S}=p,k=v.get(S),C=_.get(S);return C===void 0?{promise:Promise.resolve({success:!1,key:w,error:`Index not found for checksum ${S}`}),index:-1}:k?{promise:(async()=>{try{const M=await fetch(c,{method:"PUT",body:k,headers:{"Content-Type":k.type||"application/octet-stream","Content-Length":k.size.toString()}});return{success:M.ok,key:w,status:M.status,error:M.ok?void 0:`Upload failed with status ${M.status}`}}catch(M){return{success:!1,key:w,status:503,error:M instanceof Error?M.message:"Upload failed"}}})(),index:C,objectType:k.type,objectSize:k.size}:{promise:Promise.resolve({success:!1,key:w,error:`Blob not found for checksum ${S}`}),index:C}})};e.createUploadPromises=a;const s=async({functionKey:d,objects:g})=>{await(0,n.checkRestrictedEnvironment)(),o("trackObjectStoreAction",{action:"upload"});const m=await(0,e.createUploadPromises)({functionKey:d,objects:g});return await Promise.all(m.map(y=>y.promise))};e.upload=s}(bu)),bu}var kn={},yp;function u_(){if(yp)return kn;yp=1,Object.defineProperty(kn,"__esModule",{value:!0}),kn.deleteObjects=void 0;const e=fi(),t=Q(),r=Vo(),i=(0,D().getCallBridge)(),o=async({functionKey:l,keys:u})=>{if(await(0,r.checkRestrictedEnvironment)(),i("trackObjectStoreAction",{action:"delete"}),!l||l.length===0)throw new t.BridgeAPIError("functionKey is required to delete objects");if(!Array.isArray(u)||u.length===0)throw new t.BridgeAPIError("keys array is required and must not be empty");await Promise.all(u.map(async a=>{await(0,e.invoke)(l,{key:a})}))};return kn.deleteObjects=o,kn}var Cn={},_p;function a_(){if(_p)return Cn;_p=1,Object.defineProperty(Cn,"__esModule",{value:!0}),Cn.download=void 0;const e=fi(),t=Q(),r=Vo(),i=(0,D().getCallBridge)(),o=async({functionKey:l,keys:u})=>{if(await(0,r.checkRestrictedEnvironment)(),i("trackObjectStoreAction",{action:"download"}),!l||l.length===0)throw new t.BridgeAPIError("functionKey is required to filter and generate download URLs");if(!Array.isArray(u)||u.length===0)throw new t.BridgeAPIError("keys array is required and must not be empty");const a=await(0,e.invoke)(l,{keys:u});if(!a||typeof a!="object")throw new t.BridgeAPIError("Invalid response from functionKey");const s=Object.entries(a).map(async([g,m])=>{try{const h=await fetch(g,{method:"GET"});if(!h.ok)return{success:!1,key:m,status:h.status,error:`Download failed with status ${h.status}`};const y=await h.blob();return{success:!0,key:m,blob:y,status:h.status}}catch(h){return{success:!1,key:m,status:503,error:h instanceof Error?h.message:"Download failed"}}});return await Promise.all(s)};return Cn.download=o,Cn}var Pn={},wp;function s_(){if(wp)return Pn;wp=1,Object.defineProperty(Pn,"__esModule",{value:!0}),Pn.getMetadata=void 0;const e=fi(),t=Q(),r=Vo(),i=(0,D().getCallBridge)(),o=async({functionKey:l,keys:u})=>{if(await(0,r.checkRestrictedEnvironment)(),i("trackObjectStoreAction",{action:"getMetadata"}),!l||l.length===0)throw new t.BridgeAPIError("functionKey is required to filter and generate object metadata");if(!Array.isArray(u)||u.length===0)throw new t.BridgeAPIError("keys array is required and must not be empty");return await Promise.all(u.map(async s=>{const d=await(0,e.invoke)(l,{key:s});return!d||typeof d!="object"?{key:s,error:"Invalid response from functionKey"}:d}))};return Pn.getMetadata=o,Pn}var Sp;function c_(){return Sp||(Sp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.createUploadPromises=e.objectStore=void 0;const t=l_();Object.defineProperty(e,"createUploadPromises",{enumerable:!0,get:function(){return t.createUploadPromises}});const r=u_(),n=a_(),i=s_();e.objectStore={upload:t.upload,download:n.download,getMetadata:i.getMetadata,delete:r.deleteObjects}}(Uu)),Uu}var Ep;function f_(){return Ep||(Ep=1,function(e){Object.defineProperty(e,"__esModule",{value:!0});const t=me;t.__exportStar(c_(),e),t.__exportStar(xg(),e)}(zu)),zu}var Vu={},Rn={},On={},kp;function d_(){if(kp)return On;kp=1,Object.defineProperty(On,"__esModule",{value:!0}),On.Evaluator=void 0;class e{constructor(r){this.results=r}checkFlag(r,n){if(!this.results||!this.results.feature_flags)return n;const i=this.results.feature_flags;let o="";try{o=this.getHashedValue(r)}catch(u){return console.error("Unexpected error occurred while evaluating flag ",u),n}if(!o)return n;const l=i[o];return l?l.disabled?!1:l.value:n}shutDown(){this.results=void 0}getHashedValue(r){if(typeof r!="string")return"";const n=r.trim();if(n.length===0)return"";let i=5381;for(let o=0;o>>0).toString()}}return On.Evaluator=e,On}var Tn={},Hu={},Cp;function jg(){return Cp||(Cp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.FeatureFlagEventType=void 0,function(t){t.CHECKFLAG="checkFlag"}(e.FeatureFlagEventType||(e.FeatureFlagEventType={}))}(Hu)),Hu}var Pp;function p_(){if(Pp)return Tn;Pp=1,Object.defineProperty(Tn,"__esModule",{value:!0}),Tn.trackFeatureFlagEvent=void 0;const e=D(),t=Q(),r=Do(),n=jg(),i=500,o=1e3*25,l=(0,e.getCallBridge)(),u=s=>{if(!s||!s.type||!s.properties)throw new t.BridgeAPIError("Missing required parameters. Parameter type, and properties are required in the payload.");if(!(s.type.toUpperCase()in n.FeatureFlagEventType))throw new t.BridgeAPIError("Event type is not supported");if(Object.values(s).some(d=>typeof d=="function"))throw new t.BridgeAPIError("Passing functions as part of the payload is not supported!")},a=s=>(u(s),l("trackFeatureFlagEvent",s));return Tn.trackFeatureFlagEvent=(0,r.withRateLimiter)(a,i,o,`Feature flags calls are rate limited at ${i}req/${o/1e3}s`),Tn}var In={},Rp;function h_(){if(Rp)return In;Rp=1,Object.defineProperty(In,"__esModule",{value:!0}),In.initFeatureFlags=void 0;const e=D(),t=Q(),r=Do(),n=500,i=1e3*25,o=(0,e.getCallBridge)(),l=a=>{if(!a||!a.user||!a.config)throw new t.BridgeAPIError("Missing required parameters. Parameter user is required in the payload.");if(Object.values(a).some(s=>typeof s=="function"))throw new t.BridgeAPIError("Passing functions as part of the payload is not supported!")},u=a=>(l(a),o("initFeatureFlags",{user:a.user,config:a.config}));return In.initFeatureFlags=(0,r.withRateLimiter)(u,n,i,`Feature flags initialisation calls are rate limited at ${n}req/${i/1e3}s`),In}var Op;function v_(){if(Op)return Rn;Op=1,Object.defineProperty(Rn,"__esModule",{value:!0}),Rn.FeatureFlags=void 0;const e=d_(),t=p_(),r=h_(),n=jg();class i{constructor(){this.initialized=!1,this.eventProps={}}async initialize(l,u={environment:"development"}){if(this.isInitialized())return;this.eventProps.environment=u.environment;const a=await(0,r.initFeatureFlags)({user:l,config:u});this.initialized=!0,this.evaluator=new e.Evaluator(a)}checkFlag(l,u=!1){if(!this.isInitialized()||!this.evaluator)throw this.sendCheckFlagEvent(l,!1),new Error("FeatureFlags not initialized. Call initialize() first.");return this.sendCheckFlagEvent(l,!0),this.evaluator.checkFlag(l,u)}shutdown(){this.isInitialized()&&(this.initialized=!1,this.evaluator.shutDown())}isInitialized(){return this.initialized}sendCheckFlagEvent(l,u){const a={type:n.FeatureFlagEventType.CHECKFLAG,properties:{...this.eventProps,environment:this.eventProps.environment||"development",name:l,success:u}};(0,t.trackFeatureFlagEvent)(a)}}return Rn.FeatureFlags=i,Rn}var Tp;function g_(){return Tp||(Tp=1,function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.FeatureFlags=void 0;var t=v_();Object.defineProperty(e,"FeatureFlags",{enumerable:!0,get:function(){return t.FeatureFlags}})}(Vu)),Vu}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.i18n=e.NavigationTarget=void 0;const t=me;var r=Lo;Object.defineProperty(e,"NavigationTarget",{enumerable:!0,get:function(){return r.NavigationTarget}}),t.__exportStar(fi(),e),t.__exportStar(m0(),e),t.__exportStar(bo(),e),t.__exportStar(B1(),e),t.__exportStar(z1(),e),t.__exportStar(b1(),e),t.__exportStar(H1(),e),t.__exportStar(G1(),e),t.__exportStar(K1(),e),t.__exportStar(J1(),e),e.i18n=t.__importStar(Z1()),t.__exportStar(o_(),e),t.__exportStar(f_(),e),t.__exportStar(g_(),e)})($e);const Ip={repo:"",branch:"main",domainPath:"",height:"1200",githubUrl:""},m_=[{value:"600",label:"Small (600px)"},{value:"800",label:"Medium (800px)"},{value:"1200",label:"Large (1200px)"},{value:"1600",label:"Extra Large (1600px)"},{value:"2000",label:"Full Screen (2000px)"}];function y_(e){const t=e.trim(),r=t.match(/github\.com\/([^/]+\/[^/]+)\/blob\/([^/]+)\/(.+)/);if(r)return{repo:r[1],branch:r[2],domainPath:r[3]};const n=t.match(/github\.com\/([^/]+\/[^/]+)\/tree\/([^/]+)\/(.+)/);return n?{repo:n[1],branch:n[2],domainPath:n[3]}:null}function __(){var f,c;const[e,t]=Fe.useState(Ip),[r,n]=Fe.useState(null),[i,o]=Fe.useState(!1),[l,u]=Fe.useState(null),[a,s]=Fe.useState(null),[d,g]=Fe.useState(!0);Fe.useEffect(()=>{async function p(){try{const w=await $e.invoke("getAuthStatus");s(w)}catch{s({authenticated:!1})}finally{g(!1)}}p()},[]),Fe.useEffect(()=>{async function p(){var C;const w=await $e.view.getContext(),S=(C=w==null?void 0:w.extension)==null?void 0:C.config;if(S&&S.repo){const{githubToken:O,...M}=S;t({...Ip,...M}),u({repo:M.repo,branch:M.branch||"main",domainPath:M.domainPath});return}const k=await $e.invoke("getConfig");k&&k.repo&&(t(k),u({repo:k.repo,branch:k.branch||"main",domainPath:k.domainPath}))}p()},[]);const m=p=>{t(S=>({...S,githubUrl:p})),n(null);const w=y_(p);w?(u(w),t(S=>({...S,repo:w.repo,branch:w.branch,domainPath:w.domainPath}))):p.trim()&&u(null)},h=async()=>{var p,w;if(!e.repo||!e.domainPath){n("Please paste a valid GitHub URL to a domain JSON file.");return}o(!0),n(null);try{const S=await $e.invoke("getDomain",e);if(S.error)n(`Error: ${S.error}`);else{const k=((p=S.models)==null?void 0:p.length)??0,C=((w=S.relationships)==null?void 0:w.length)??0;n(`Connected! Found ${k} models and ${C} relationships.`);const O=await $e.invoke("getAuthStatus");s(O)}}catch(S){n(`Error: ${S.message}`)}finally{o(!1)}},y=async()=>{if(!e.repo||!e.domainPath){n("Please paste a valid GitHub URL to a domain JSON file.");return}try{await $e.invoke("saveConfig",e)}catch(p){n(`Save failed: ${p.message}`);return}try{await $e.view.submit(e);return}catch{}try{await $e.view.close();return}catch{}n("__DONE__")};if(r==="__DONE__")return x.jsx("div",{style:z.container,children:x.jsxs("div",{style:{padding:"24px",textAlign:"center"},children:[x.jsx("div",{style:{fontSize:"24px",marginBottom:"8px"},children:"✓"}),x.jsx("div",{style:{fontSize:"14px",fontWeight:600,color:"#006644",marginBottom:"4px"},children:"Configuration saved"}),x.jsx("div",{style:{fontSize:"13px",color:"#6b778c"},children:"Publish the page to see your ERD diagram."})]})});const v=(r==null?void 0:r.startsWith("Connected"))||(r==null?void 0:r.startsWith("Saved")),_=(a==null?void 0:a.authenticated)===!0;return x.jsxs("div",{style:z.container,children:[x.jsx("h3",{style:z.title,children:"ERD Studio Configuration"}),x.jsx("p",{style:z.subtitle,children:"Paste a GitHub link to your domain JSON file. GitHub authentication is handled automatically via OAuth when you test the connection."}),x.jsxs("div",{style:{...z.field,borderBottom:"1px solid #dfe1e6",paddingBottom:"12px",marginBottom:"16px"},children:[x.jsx("label",{style:z.label,children:"GitHub Account"}),d?x.jsx("div",{style:z.authBox,children:x.jsx("span",{style:{fontSize:"13px",color:"#6b778c"},children:"Checking..."})}):_?x.jsx("div",{style:{...z.authBox,backgroundColor:"#e3fcef",borderColor:"#006644"},children:x.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px"},children:[((f=a==null?void 0:a.user)==null?void 0:f.avatarUrl)&&x.jsx("img",{src:a.user.avatarUrl,alt:"",style:{width:"20px",height:"20px",borderRadius:"50%"}}),x.jsxs("span",{style:{fontSize:"13px",color:"#006644",fontWeight:600},children:["Connected",(c=a==null?void 0:a.user)!=null&&c.displayName?` as ${a.user.displayName}`:""]})]})}):x.jsx("div",{style:z.authBox,children:x.jsx("span",{style:{fontSize:"13px",color:"#6b778c"},children:"Not connected — click Test Connection to authenticate via OAuth."})})]}),x.jsxs("div",{style:z.field,children:[x.jsx("label",{style:z.label,children:"GitHub URL"}),x.jsx("input",{style:z.input,type:"text",placeholder:"https://github.com/owner/repo/blob/main/.erd-studio/silver/domain.json",value:e.githubUrl,onChange:p=>m(p.target.value)}),l&&x.jsxs("div",{style:z.parsedInfo,children:[x.jsx("span",{style:z.parsedLabel,children:"Repo:"})," ",l.repo,x.jsx("span",{style:{...z.parsedLabel,marginLeft:"12px"},children:"Branch:"})," ",l.branch,x.jsx("br",{}),x.jsx("span",{style:z.parsedLabel,children:"Path:"})," ",l.domainPath]}),e.githubUrl&&!l&&x.jsx("span",{style:{...z.hint,color:"#de350b"},children:"Could not parse URL. Expected format: github.com/owner/repo/blob/branch/path/to/file.json"})]}),x.jsxs("div",{style:{...z.field,borderTop:"1px solid #dfe1e6",paddingTop:"12px",marginTop:"16px"},children:[x.jsx("label",{style:z.label,children:"Diagram Height"}),x.jsx("select",{style:{...z.input,cursor:"pointer"},value:e.height,onChange:p=>{t(w=>({...w,height:p.target.value})),n(null)},children:m_.map(p=>x.jsx("option",{value:p.value,children:p.label},p.value))})]}),r&&x.jsx("div",{style:{...z.status,color:v?"#006644":"#de350b",backgroundColor:v?"#e3fcef":"#ffebe6"},children:r}),x.jsxs("div",{style:z.buttons,children:[x.jsx("button",{style:{...z.testButton,opacity:l?1:.5},onClick:h,disabled:i||!l,children:i?"Testing...":"Test Connection"}),x.jsx("button",{style:{...z.saveButton,opacity:l?1:.5},onClick:y,disabled:!l,children:"Save"})]})]})}const z={container:{fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',padding:"16px",maxWidth:"520px"},title:{margin:"0 0 4px 0",fontSize:"16px",fontWeight:600,color:"#172b4d"},subtitle:{margin:"0 0 16px 0",fontSize:"13px",color:"#6b778c"},field:{marginBottom:"12px"},label:{display:"block",fontSize:"12px",fontWeight:600,color:"#172b4d",marginBottom:"4px"},input:{width:"100%",padding:"6px 8px",fontSize:"13px",border:"1px solid #dfe1e6",borderRadius:"3px",backgroundColor:"#fafbfc",color:"#172b4d",boxSizing:"border-box"},hint:{display:"block",fontSize:"11px",color:"#97a0af",marginTop:"2px"},parsedInfo:{marginTop:"6px",padding:"6px 8px",backgroundColor:"#f4f5f7",borderRadius:"3px",fontSize:"11px",color:"#172b4d",lineHeight:"1.6"},parsedLabel:{fontWeight:600,color:"#6b778c"},status:{padding:"8px 12px",borderRadius:"3px",fontSize:"13px",marginBottom:"12px"},buttons:{display:"flex",gap:"8px",marginTop:"16px"},testButton:{padding:"6px 12px",fontSize:"13px",border:"1px solid #dfe1e6",borderRadius:"3px",backgroundColor:"#ffffff",color:"#172b4d",cursor:"pointer"},saveButton:{padding:"6px 16px",fontSize:"13px",border:"none",borderRadius:"3px",backgroundColor:"#0052cc",color:"#ffffff",cursor:"pointer",fontWeight:600},authBox:{padding:"8px 12px",borderRadius:"3px",border:"1px solid #dfe1e6",backgroundColor:"#f4f5f7"}},w_=bv(document.getElementById("root"));w_.render(x.jsx(Jg.StrictMode,{children:x.jsx(__,{})}));export{Lg as g}; diff --git a/forge-app/static/config/src/ConfigPanel.tsx b/forge-app/static/config/src/ConfigPanel.tsx index b4fe437..5daf81d 100644 --- a/forge-app/static/config/src/ConfigPanel.tsx +++ b/forge-app/static/config/src/ConfigPanel.tsx @@ -210,7 +210,7 @@ export default function ConfigPanel() { onUrlChange(e.target.value)} /> diff --git a/forge-app/static/frontend/src/App.tsx b/forge-app/static/frontend/src/App.tsx index e3d4109..77d2753 100644 --- a/forge-app/static/frontend/src/App.tsx +++ b/forge-app/static/frontend/src/App.tsx @@ -94,7 +94,7 @@ function InlineConfig({ onSaved }: { onSaved: () => void }) { { setUrl(e.target.value); setStatus(null); }} /> diff --git a/mcp-server/README.md b/mcp-server/README.md index 3788074..23aed8f 100644 --- a/mcp-server/README.md +++ b/mcp-server/README.md @@ -58,18 +58,18 @@ These editors support MCP via their respective config files. Use the same `comma ## Tools -All tools take a `project_path` argument: the **absolute path** to the dbt project root (the directory containing `dbt_project.yml`). The project should also contain an `erd-studio/` directory created by the [ERD Studio VS Code extension](https://marketplace.visualstudio.com/items?itemName=liamwynne.erd-studio). +All tools take a `project_path` argument: the **absolute path** to the dbt project root (the directory containing `dbt_project.yml`). The project should also contain a `.erd-studio/` directory created by the [ERD Studio VS Code extension](https://marketplace.visualstudio.com/items?itemName=liamwynne.erd-studio). | Tool | Returns | |---|---| | `list_domains` | All ERDs grouped by layer. Filter optional by `layer`. | | `read_domain` | Full domain: models + columns + relationships + cardinality + rationale. | -| `list_models` | All logical model definitions from `erd-studio/logical-models/*.yml`. | +| `list_models` | All logical model definitions from `.erd-studio/logical-models/*.yml`. | | `read_model` | Single logical model with column-level metadata, grain, SCD types, rationale. | | `list_manifest_models` | Models from `target/manifest.json` (what dbt actually built), with unique/relationship test coverage. Filter optional by `name_contains`. | | `get_editor_setup` | Returns install instructions for the ERD Studio VS Code extension. Use this when the user wants to edit, design, or build (this MCP server is read-only). | -All tools are read-only. If the project hasn't been initialized with an `erd-studio/` directory yet, list-tools return empty results with a `tip` field pointing to the install path; read-tools throw a friendly error doing the same. Either way the AI naturally surfaces the extension install path to the user. +All tools are read-only. If the project hasn't been initialized with a `.erd-studio/` directory yet, list-tools return empty results with a `tip` field pointing to the install path; read-tools throw a friendly error doing the same. Either way the AI naturally surfaces the extension install path to the user. ## What the AI gets @@ -91,7 +91,7 @@ So when you ask the AI *"propose a column to add to `dim_customer`"*, it sees no ## Without ERD Studio yet -If your dbt project doesn't have an `erd-studio/` directory yet: +If your dbt project doesn't have a `.erd-studio/` directory yet: 1. Install the [VS Code extension](https://marketplace.visualstudio.com/items?itemName=liamwynne.erd-studio) 2. In VS Code: Command Palette → `dbt: Set Up Semantic Domains Directory` diff --git a/mcp-server/src/index.ts b/mcp-server/src/index.ts index a444546..080f388 100644 --- a/mcp-server/src/index.ts +++ b/mcp-server/src/index.ts @@ -33,8 +33,8 @@ Install: https://marketplace.visualstudio.com/items?itemName=liamwynne.erd-studi Or call the \`get_editor_setup\` tool for canonical install instructions. Every tool takes \`project_path\`: the absolute path to the dbt project root (the -directory containing dbt_project.yml). If the project hasn't been initialized with an -erd-studio/ directory yet, list-tools return empty results with a \`tip\` field pointing +directory containing dbt_project.yml). If the project hasn't been initialized with a +.erd-studio/ directory yet, list-tools return empty results with a \`tip\` field pointing to the install path; read-tools throw a friendly error doing the same. Typical inspection workflow: diff --git a/mcp-server/src/lib/setup.ts b/mcp-server/src/lib/setup.ts index 1237411..4fddf04 100644 --- a/mcp-server/src/lib/setup.ts +++ b/mcp-server/src/lib/setup.ts @@ -11,7 +11,7 @@ export const EXTENSION_REPO_URL = 'https://github.com/liam-machine/erd-studio'; * surfaces the install path to the user. */ export const NOT_INITIALIZED_TIP = - "This project doesn't have an erd-studio/ directory yet. To start designing ERDs, " + + "This project doesn't have a .erd-studio/ directory yet. To start designing ERDs, " + `install the ERD Studio VS Code extension: ${EXTENSION_MARKETPLACE_URL} ` + "Then run Command Palette → 'dbt: Set Up Semantic Domains Directory'. " + "The extension also installs an AI coding skill (.claude/skills/erd-studio/SKILL.md) " + @@ -19,7 +19,7 @@ export const NOT_INITIALIZED_TIP = "by design and complements the skill for AI clients other than Claude Code."; /** - * Returns true if the project has an erd-studio/ directory. + * Returns true if the project has a .erd-studio/ directory. */ export function isInitialized(projectPath: string, semanticDir: string): boolean { return fs.existsSync(path.join(projectPath, semanticDir)); diff --git a/mcp-server/src/services.ts b/mcp-server/src/services.ts index e29ebb7..e6747b8 100644 --- a/mcp-server/src/services.ts +++ b/mcp-server/src/services.ts @@ -15,7 +15,7 @@ export interface Services { manifestService: ManifestService; } -const SEMANTIC_DIR = 'erd-studio'; +const SEMANTIC_DIR = '.erd-studio'; export function resolveProjectPath(input: string): string { const resolved = path.resolve(input); diff --git a/mcp-server/src/tools/get_editor_setup.ts b/mcp-server/src/tools/get_editor_setup.ts index 26530ad..e70ba90 100644 --- a/mcp-server/src/tools/get_editor_setup.ts +++ b/mcp-server/src/tools/get_editor_setup.ts @@ -42,7 +42,7 @@ export const get_editor_setup = { 'dbt: Set Up Semantic Domains Directory', '```', '', - 'This creates `erd-studio/` with `layers.json`, `logical-models/`, and `templates/`.', + 'This creates `.erd-studio/` with `layers.json`, `logical-models/`, and `templates/`.', '', '## 3. Install the AI coding harness (writes the skill file)', '', diff --git a/mcp-server/src/tools/list_models.ts b/mcp-server/src/tools/list_models.ts index d382e20..28a802d 100644 --- a/mcp-server/src/tools/list_models.ts +++ b/mcp-server/src/tools/list_models.ts @@ -7,7 +7,7 @@ export const list_models = { config: { title: 'List logical models', description: - 'List all logical model definitions in erd-studio/logical-models/. ' + + 'List all logical model definitions in .erd-studio/logical-models/. ' + 'Each model is one table (dimension, fact, bridge, etc.) reusable across domains. ' + 'Returns model names + light metadata. Call read_model for full column-level detail.', inputSchema: { diff --git a/mcp-server/test-smoke.mjs b/mcp-server/test-smoke.mjs index fae0251..901d032 100644 --- a/mcp-server/test-smoke.mjs +++ b/mcp-server/test-smoke.mjs @@ -11,7 +11,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)); const PROJECT_PATH = path.resolve(__dirname, '../test/fixtures/dbt-project'); const SERVER = path.resolve(__dirname, 'dist/index.js'); -// Build a temporary "uninitialized" project — has dbt_project.yml but no erd-studio/ +// Build a temporary "uninitialized" project — has dbt_project.yml but no .erd-studio/ const UNINIT_PATH = fs.mkdtempSync(path.join(os.tmpdir(), 'erd-mcp-uninit-')); fs.writeFileSync(path.join(UNINIT_PATH, 'dbt_project.yml'), "name: 'test_uninit'\nversion: '1.0.0'\n"); diff --git a/package.json b/package.json index b8bfd37..38ddd8e 100644 --- a/package.json +++ b/package.json @@ -185,11 +185,11 @@ "viewsWelcome": [ { "view": "dbtSemantic.domainTree", - "contents": "No ERD domains found.\n\nERD Studio lets you design your data warehouse visually across two stages:\n\n**Logical** — columns, data types, FK keys, and design rationale\n**Physical** — read-only view of what's built in dbt\n\n[Set Up ERD Studio](command:dbtSemantic.setupSemanticDirectory)\n\nCreates the erd-studio directory structure and your first domain.\n\n[Install AI Coding Harness](command:dbtSemantic.installCodingHarness)\n\nAdd ERD Studio schema reference to Claude, Copilot, Gemini, or Codex." + "contents": "No ERD domains found.\n\nERD Studio lets you design your data warehouse visually across two stages:\n\n**Logical** — columns, data types, FK keys, and design rationale\n**Physical** — read-only view of what's built in dbt\n\n[Set Up ERD Studio](command:dbtSemantic.setupSemanticDirectory)\n\nCreates the .erd-studio directory structure and your first domain.\n\n[Install AI Coding Harness](command:dbtSemantic.installCodingHarness)\n\nAdd ERD Studio schema reference to Claude, Copilot, Gemini, or Codex." }, { "view": "dbtSemantic.modelLibrary", - "contents": "No logical models found.\n\nModels are stored as YAML files in erd-studio/logical-models/.\n\nAdd models to a domain using the ERD editor to create them here." + "contents": "No logical models found.\n\nModels are stored as YAML files in .erd-studio/logical-models/.\n\nAdd models to a domain using the ERD editor to create them here." } ], "customEditors": [ @@ -197,6 +197,9 @@ "viewType": "dbtSemantic.domainEditor", "displayName": "Semantic Domain Editor", "selector": [ + { + "filenamePattern": "**/.erd-studio/*/*.json" + }, { "filenamePattern": "**/erd-studio/*/*.json" } @@ -260,7 +263,7 @@ }, "dbtSemantic.semanticDir": { "type": "string", - "default": "erd-studio", + "default": ".erd-studio", "description": "Relative path to ERD domain files within the project" } } diff --git a/src/extension.ts b/src/extension.ts index 43310f3..eb35936 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -184,7 +184,7 @@ export async function activate(context: vscode.ExtensionContext): Promise console.log(`ERD Studio: Found dbt project at ${workspaceRoot}`); const config = vscode.workspace.getConfiguration('dbtSemantic'); - const semanticDir = config.get('semanticDir', 'erd-studio'); + const semanticDir = config.get('semanticDir', '.erd-studio'); const layerService = new LayerService(workspaceRoot, semanticDir); const domainService = new DomainService(layerService); @@ -296,7 +296,7 @@ export async function activate(context: vscode.ExtensionContext): Promise // ------------------------------------------------------------------------- // File watchers // ------------------------------------------------------------------------- - const fileWatcherService = new FileWatcherService(workspaceRoot); + const fileWatcherService = new FileWatcherService(workspaceRoot, semanticDir); // Manifest changed → refresh open editors let manifestRetryTimeout: ReturnType | undefined; @@ -781,7 +781,7 @@ export async function activate(context: vscode.ExtensionContext): Promise const v4Count = migrationService.findV4Domains().length; const confirm = await vscode.window.showWarningMessage( `Found ${v4Count} domain file(s) using the legacy inline model format. ` + - 'Migration will extract models to erd-studio/logical-models/ and convert domain files to use name references. ' + + 'Migration will extract models to .erd-studio/logical-models/ and convert domain files to use name references. ' + 'This cannot be undone automatically.', 'Migrate Now', 'Cancel', diff --git a/src/providers/DomainTreeProvider.ts b/src/providers/DomainTreeProvider.ts index 1757a4e..b40744f 100644 --- a/src/providers/DomainTreeProvider.ts +++ b/src/providers/DomainTreeProvider.ts @@ -49,7 +49,7 @@ export type TreeElement = LayerNode | DomainNode | NewDomainNode; // --------------------------------------------------------------------------- /** Default semantic directory relative to project root. */ -const DEFAULT_SEMANTIC_DIR = 'erd-studio'; +const DEFAULT_SEMANTIC_DIR = '.erd-studio'; export class DomainTreeProvider implements vscode.TreeDataProvider, vscode.TreeDragAndDropController { diff --git a/src/providers/ModelLibraryTreeProvider.ts b/src/providers/ModelLibraryTreeProvider.ts index 4f27f3b..02680c0 100644 --- a/src/providers/ModelLibraryTreeProvider.ts +++ b/src/providers/ModelLibraryTreeProvider.ts @@ -1,7 +1,7 @@ /** * ModelLibraryTreeProvider — VS Code TreeDataProvider for the Model Library sidebar. * - * Shows all model YAML files in erd-studio/logical-models/ as a flat + * Shows all model YAML files in .erd-studio/logical-models/ as a flat * alphabetical list. Orphaned models (not referenced by any domain) are * flagged with a warning icon and "(unused)" description. Referenced models * show their domain count and list domain names in the tooltip. diff --git a/src/providers/SemanticEditorProvider.ts b/src/providers/SemanticEditorProvider.ts index 4d829ae..4220f99 100644 --- a/src/providers/SemanticEditorProvider.ts +++ b/src/providers/SemanticEditorProvider.ts @@ -2760,7 +2760,7 @@ export class SemanticEditorProvider implements vscode.CustomTextEditorProvider { const ymlData = await this.ymlParserService.loadYmlData(this.workspaceRoot, undefined); const semanticDir = vscode.workspace .getConfiguration('dbtSemantic') - .get('semanticDir', 'erd-studio'); + .get('semanticDir', '.erd-studio'); // Build resolutions from selections const models: ModelResolution[] = []; @@ -2950,7 +2950,7 @@ export class SemanticEditorProvider implements vscode.CustomTextEditorProvider { private async handleLaunchClaudeSync(): Promise { const semanticDir = vscode.workspace .getConfiguration('dbtSemantic') - .get('semanticDir', 'erd-studio'); + .get('semanticDir', '.erd-studio'); const planPath = `${semanticDir}/.sync-plan.json`; const prompt = `Execute the erd-studio sync plan at ${planPath} using the erd-studio skill. Read .claude/skills/erd-studio/SYNC.md for the action reference and follow the execution steps.`; diff --git a/src/providers/SemanticFileDecorationProvider.ts b/src/providers/SemanticFileDecorationProvider.ts index 76f0c1c..82ec9b7 100644 --- a/src/providers/SemanticFileDecorationProvider.ts +++ b/src/providers/SemanticFileDecorationProvider.ts @@ -9,14 +9,15 @@ import type { LayerService } from '../services/layerService'; * inside the ERD Studio sidebar tree via LayerDecorationProvider. */ export class SemanticFileDecorationProvider implements vscode.FileDecorationProvider { - private static readonly SEMANTIC_PATH_PATTERN = /[/\\]erd-studio[/\\]/; + // Matches the .erd-studio data directory (and the legacy non-dotted erd-studio name) + private static readonly SEMANTIC_PATH_PATTERN = /[/\\]\.?erd-studio[/\\]/; private readonly _onDidChangeFileDecorations = new vscode.EventEmitter(); readonly onDidChangeFileDecorations = this._onDidChangeFileDecorations.event; constructor( private readonly layerService: LayerService, - private readonly semanticDir: string = 'erd-studio', + private readonly semanticDir: string = '.erd-studio', ) {} provideFileDecoration(uri: vscode.Uri): vscode.FileDecoration | undefined { diff --git a/src/services/domainService.ts b/src/services/domainService.ts index 59c0de0..4981ab1 100644 --- a/src/services/domainService.ts +++ b/src/services/domainService.ts @@ -1,7 +1,7 @@ /** * DomainService — reads semantic domain JSON files from disk. * - * Domain files live at {dbt_project}/erd-studio/{layer}/{domain}.json + * Domain files live at {dbt_project}/.erd-studio/{layer}/{domain}.json * Each file is a UnifiedDomain containing logical stage data. * * Physical domains are not stored on disk — they are derived at runtime @@ -32,7 +32,7 @@ interface RelationshipTest { toColumn: string; } -const DEFAULT_SEMANTIC_DIR = 'erd-studio'; +const DEFAULT_SEMANTIC_DIR = '.erd-studio'; export class DomainService { private logicalModelService: LogicalModelService | null = null; @@ -49,11 +49,11 @@ export class DomainService { } /** - * Discover all semantic domain JSON files under erd-studio/, + * Discover all semantic domain JSON files under .erd-studio/, * grouped by layer. Returns lightweight summaries (no full parse). * * Directory structure: - * erd-studio/{layer}/*.json + * .erd-studio/{layer}/*.json */ listDomains(projectPath: string, semanticDir = DEFAULT_SEMANTIC_DIR): DomainSummary[] { const basePath = path.join(projectPath, semanticDir); diff --git a/src/services/harnessService.ts b/src/services/harnessService.ts index 5942c00..8a0cf86 100644 --- a/src/services/harnessService.ts +++ b/src/services/harnessService.ts @@ -19,7 +19,7 @@ import * as path from 'path'; // --------------------------------------------------------------------------- /** Version of the harness content. Bump when SCHEMA_CONTENT or generators change. */ -export const HARNESS_VERSION = '14'; +export const HARNESS_VERSION = '15'; const VERSION_MARKER_PREFIX = ''; @@ -102,12 +102,12 @@ export const HARNESS_TARGETS: HarnessTarget[] = [ const SCHEMA_CONTENT = `# ERD Studio — AI Data Modeling Guide -ERD Studio uses a **central model store** architecture. Model definitions are YAML files in \`erd-studio/logical-models/\`. Domain JSON files reference models by name and define relationships and layout. +ERD Studio uses a **central model store** architecture. Model definitions are YAML files in \`.erd-studio/logical-models/\`. Domain JSON files reference models by name and define relationships and layout. ## Architecture Overview \`\`\` -erd-studio/ +.erd-studio/ ├── logical-models/ ← Central model definitions (YAML, one per model) │ ├── dim_customer.yml │ ├── dim_project.yml @@ -132,7 +132,7 @@ The **Model Library** panel in the ERD Studio sidebar shows all YAML files in \` ## Domain File Structure -**File:** \`erd-studio/{layer}/{domain}.json\` +**File:** \`.erd-studio/{layer}/{domain}.json\` \`\`\`json { @@ -199,9 +199,9 @@ Annotations are temporary build notes — visible on the canvas while constructi ## Models -Model definitions live in \`erd-studio/logical-models/{model_name}.yml\`. Create/edit these YAML files to define models. Then reference them by name in domain files. +Model definitions live in \`.erd-studio/logical-models/{model_name}.yml\`. Create/edit these YAML files to define models. Then reference them by name in domain files. -**File:** \`erd-studio/logical-models/dim_customer.yml\` +**File:** \`.erd-studio/logical-models/dim_customer.yml\` \`\`\`yaml name: dim_customer @@ -272,7 +272,7 @@ Optional \`rationale\` object — all fields are optional strings. Omit the enti When the user asks you to create a new model — or materially add columns to an existing one — from an external source (planning doc, DDL, staging SQL, CSV, notebook, or another YAML), follow this protocol. It exists to prevent silent column truncation. -**Does NOT apply to:** renaming a column, changing a single flag, or executing an \`erd-studio/.sync-plan.json\` (see SYNC.md for that workflow). +**Does NOT apply to:** renaming a column, changing a single flag, or executing an \`.erd-studio/.sync-plan.json\` (see SYNC.md for that workflow). ### Step 1 — Read the source fully, then enumerate Before listing anything, confirm you have read the source **in full**. For files longer than 2000 lines, page through with \`Read\` using \`offset\`/\`limit\` until you reach the end of the file. A partial read is a silent-truncation trap before you even start — the columns you never saw cannot appear in your output. @@ -298,7 +298,7 @@ State which of those columns you intend to build, in plain English. Proceed straight to step 3 — do not wait for confirmation. The user will correct you if the scope is wrong. ### Step 3 — Build -Write the \`erd-studio/logical-models/{name}.yml\` file. +Write the \`.erd-studio/logical-models/{name}.yml\` file. ### Step 4 — Reconcile via set-difference Re-read the YAML file you just wrote. Compute the set-difference between source columns and YAML columns — do not rely on a total count alone, because counts can coincidentally match while columns still differ. @@ -405,10 +405,10 @@ Recognized test types: \`relationships\`, \`relationships_where\`, and any test ## Sync Reconciliation -When asked to execute a sync plan, or when \`erd-studio/.sync-plan.json\` exists: +When asked to execute a sync plan, or when \`.erd-studio/.sync-plan.json\` exists: 1. Read \`SYNC.md\` in the same directory as this skill file for the full action reference and execution guide -2. Read \`erd-studio/.sync-plan.json\` for the specific actions to execute +2. Read \`.erd-studio/.sync-plan.json\` for the specific actions to execute 3. Follow the execution steps in SYNC.md to reconcile logical and physical models`; // --------------------------------------------------------------------------- @@ -423,7 +423,7 @@ The sync plan reconciles differences between the **logical** (user-defined) and ## When to Use -When \`erd-studio/.sync-plan.json\` exists in the project, the user has reviewed +When \`.erd-studio/.sync-plan.json\` exists in the project, the user has reviewed logical-vs-physical discrepancies in ERD Studio and chosen which side is "ground truth" for each difference. Your job is to execute those choices. @@ -439,7 +439,7 @@ for each difference. Your job is to execute those choices. "modelContext": { "dim_customer": { "modelName": "dim_customer", - "logicalModelPath": "erd-studio/logical-models/dim_customer.yml", + "logicalModelPath": ".erd-studio/logical-models/dim_customer.yml", "dbtSqlPath": "models/silver/dim_customer.sql", "dbtSchemaPath": "models/silver/dim_customer.yml" } @@ -510,14 +510,14 @@ models: ## Execution Steps -1. **Read** \`erd-studio/.sync-plan.json\` +1. **Read** \`.erd-studio/.sync-plan.json\` 2. **Execute each action** in order: - For logical-side actions: edit files at \`modelContext[modelName].logicalModelPath\` and/or the domain JSON - For physical-side actions: edit files at \`modelContext[modelName].dbtSqlPath\` and \`dbtSchemaPath\` - For destructive actions (\`remove-*\`): confirm with the user before proceeding 3. **Compile** if \`requiresCompile\` is \`true\`: run \`dbt compile\` to regenerate the manifest 4. **Verify**: Re-open the domain in ERD Studio and run the diff comparison to confirm discrepancies are resolved -5. **Clean up**: Delete \`erd-studio/.sync-plan.json\` on success +5. **Clean up**: Delete \`.erd-studio/.sync-plan.json\` on success ## Important Notes @@ -534,10 +534,10 @@ function generateClaudeSkill(): string { return `--- name: erd-studio description: >- - Schema rules for ERD Studio data model files — the erd-studio/ directory + Schema rules for ERD Studio data model files — the .erd-studio/ directory uses a two-file system (YAML model definitions + JSON domain diagrams) with strict format rules you must read before editing. Use this skill - whenever the task touches files in erd-studio/ (domain JSON, logical-models + whenever the task touches files in .erd-studio/ (domain JSON, logical-models YAML, or .sync-plan.json), asks to add/edit/remove models, columns, relationships, or cardinality in a data model or ERD diagram, mentions dim_/fct_/ref_/brg_ prefixed tables in an erd-studio context, or involves @@ -556,11 +556,11 @@ function generateEnforceSkillHook(): string { return [ '#!/usr/bin/env bash', '# ERD Studio — PreToolUse hook for Edit and Write tools.', - '# Blocks the first erd-studio file edit per Claude Code session to ensure the', + '# Blocks the first .erd-studio file edit per Claude Code session to ensure the', '# /erd-studio skill is loaded before any changes are made. Subsequent edits', '# in the same session are allowed (flag keyed on session_id from stdin JSON).', '', - 'deny=\'{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"You must load the /erd-studio skill before editing erd-studio files. It contains the two-file editing rules (YAML models vs JSON domains). Run: /erd-studio — then retry."}}\'', + 'deny=\'{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"You must load the /erd-studio skill before editing .erd-studio files. It contains the two-file editing rules (YAML models vs JSON domains). Run: /erd-studio — then retry."}}\'', 'allow=\'{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":""}}\'', '', '# Read all stdin (Claude sends hook input JSON via stdin)', @@ -570,9 +570,9 @@ function generateEnforceSkillHook(): string { 'file_path="$(echo "$input" | grep -o \'"file_path" *: *"[^"]*"\' | head -1 | sed \'s/.*: *"//;s/"$//\')"', 'session_id="$(echo "$input" | grep -o \'"session_id" *: *"[^"]*"\' | head -1 | sed \'s/.*: *"//;s/"$//\')"', '', - '# Only act on files inside erd-studio/ directories', + '# Only act on files inside .erd-studio/ directories', 'case "$file_path" in', - ' */erd-studio/*)', + ' */.erd-studio/*)', ' flag="/tmp/.erd-studio-skill-${session_id}"', ' if [ ! -f "$flag" ]; then', ' touch "$flag"', @@ -597,7 +597,7 @@ function generateCopilotInstructions(): string { return `--- name: 'ERD Studio' description: 'Data modeling guide for ERD Studio — domain JSON format, dbt YAML tests for physical model, naming conventions' -applyTo: '**/erd-studio/**/*.json' +applyTo: '**/.erd-studio/**/*.json' --- ${SCHEMA_CONTENT} @@ -611,7 +611,7 @@ function generateGeminiStyleguide(): string { ## Code Review Rules -### ERD Studio Domain Files (\`erd-studio/**/*.json\`) +### ERD Studio Domain Files (\`.erd-studio/**/*.json\`) 1. **Schema version** must be \`5\` 2. **Required sections**: \`logical\` and \`viewConfig\` must both be present at root level @@ -715,7 +715,7 @@ export class HarnessService { const syncPath = path.join(dir, 'SYNC.md'); fs.writeFileSync(syncPath, generateSyncGuide(), 'utf-8'); - // enforce-skill.sh — PreToolUse hook that blocks first erd-studio edit + // enforce-skill.sh — PreToolUse hook that blocks first .erd-studio edit // per session so Claude loads the /erd-studio skill before making changes const hookPath = path.join(dir, 'enforce-skill.sh'); fs.writeFileSync(hookPath, generateEnforceSkillHook(), { mode: 0o755 }); diff --git a/src/services/layerService.ts b/src/services/layerService.ts index 6d3994a..25dbf6e 100644 --- a/src/services/layerService.ts +++ b/src/services/layerService.ts @@ -2,7 +2,7 @@ * LayerService — manages layer configuration for the semantic domain system. * * Responsibilities: - * 1. Load layer config from erd-studio/layers.json + * 1. Load layer config from .erd-studio/layers.json * 2. Auto-detect existing layer directories on first run * 3. Validate layer configuration structure * 4. Provide layer lookup and metadata access @@ -32,7 +32,7 @@ export class LayerService { private readonly configPath: string; private readonly semanticPath: string; - constructor(projectPath: string, semanticDir: string = 'erd-studio') { + constructor(projectPath: string, semanticDir: string = '.erd-studio') { this.semanticPath = path.join(projectPath, semanticDir); this.configPath = path.join(this.semanticPath, LAYERS_CONFIG_FILE); } diff --git a/src/services/logicalModelService.ts b/src/services/logicalModelService.ts index a5617e6..69b5e8a 100644 --- a/src/services/logicalModelService.ts +++ b/src/services/logicalModelService.ts @@ -1,6 +1,6 @@ /** * LogicalModelService — reads and writes canonical model definitions - * stored as YAML files in erd-studio/logical-models/. + * stored as YAML files in .erd-studio/logical-models/. * * Each model is a single YAML file: logical-models/{model_name}.yml. * Domain JSON files reference models by name (string[]) instead of @@ -52,7 +52,7 @@ interface YamlColumn { export class LogicalModelService { private readonly modelsDir: string; - constructor(workspaceRoot: string, semanticDir = 'erd-studio') { + constructor(workspaceRoot: string, semanticDir = '.erd-studio') { this.modelsDir = path.join(workspaceRoot, semanticDir, 'logical-models'); } diff --git a/src/services/migrationService.ts b/src/services/migrationService.ts index 09ce268..5559a46 100644 --- a/src/services/migrationService.ts +++ b/src/services/migrationService.ts @@ -3,7 +3,7 @@ * * v4 → v5 migration: * - Extracts inline model objects from domain files - * - Creates YAML model files in erd-studio/logical-models/ + * - Creates YAML model files in .erd-studio/logical-models/ * - Converts domain logical.models from SemanticModel[] to string[] * - Bumps schemaVersion to 5 * @@ -65,7 +65,7 @@ export class MigrationService { * Scan all domain files and return paths of those with schemaVersion < 5. */ findV4Domains(): string[] { - const semanticDir = path.join(this.workspaceRoot, 'erd-studio'); + const semanticDir = path.join(this.workspaceRoot, '.erd-studio'); if (!fs.existsSync(semanticDir)) { return []; } diff --git a/src/services/templateService.ts b/src/services/templateService.ts index 86c9c8c..44ed5e3 100644 --- a/src/services/templateService.ts +++ b/src/services/templateService.ts @@ -1,7 +1,7 @@ /** * TemplateService — reads model template JSON files from disk. * - * Templates live at {dbt_project}/erd-studio/templates/*.json + * Templates live at {dbt_project}/.erd-studio/templates/*.json * and define preset columns and metadata for common model patterns. * * Falls back to built-in templates if no template files are found. @@ -12,7 +12,7 @@ import * as path from 'path'; import type { ColumnDef, ModelTemplate } from '../types/semantic'; -const DEFAULT_SEMANTIC_DIR = 'erd-studio'; +const DEFAULT_SEMANTIC_DIR = '.erd-studio'; const TEMPLATES_DIR = 'templates'; /** @@ -96,7 +96,7 @@ export class TemplateService { /** * Load all model templates from the templates directory. * - * Returns templates from {projectPath}/erd-studio/templates/*.json + * Returns templates from {projectPath}/.erd-studio/templates/*.json * if any exist, otherwise returns built-in fallback templates. * * Templates are sorted by: dimension, fact, bridge, scd2, blank, then diff --git a/src/types/display.ts b/src/types/display.ts index f0cf342..e9dc1fe 100644 --- a/src/types/display.ts +++ b/src/types/display.ts @@ -30,7 +30,7 @@ export interface ManifestModelPreview { * Enhanced model preview for the "Add Existing Model" dialog. * Extends ManifestModelPreview with source information. * - * - 'logical': model has a YAML definition in erd-studio/logical-models/ (Library) + * - 'logical': model has a YAML definition in .erd-studio/logical-models/ (Library) * - 'yml': model defined in a dbt .yml schema file (dbt) * - 'manifest': model exists in compiled manifest only, no .yml file (Compiled) */ diff --git a/src/types/layer.ts b/src/types/layer.ts index 0db88a9..f5b1c13 100644 --- a/src/types/layer.ts +++ b/src/types/layer.ts @@ -2,7 +2,7 @@ * Layer configuration types for dynamic layer management. * * Layers define the medallion architecture levels for semantic domains. - * Configuration is stored in erd-studio/layers.json and controls: + * Configuration is stored in .erd-studio/layers.json and controls: * - Layer metadata (label, abbreviation, description) * - UI appearance (color) * - Behavior flags (creatable, order) @@ -45,7 +45,7 @@ export interface LayerConfig { /** * Full layer configuration file schema. - * Stored at erd-studio/layers.json. + * Stored at .erd-studio/layers.json. */ export interface LayersConfigFile { /** Schema version for future compatibility. */ diff --git a/src/types/semantic.ts b/src/types/semantic.ts index f204b86..582126b 100644 --- a/src/types/semantic.ts +++ b/src/types/semantic.ts @@ -1,7 +1,7 @@ /** * Types for semantic domain JSON files. * - * Domain files live at {dbt_project}/erd-studio/{layer}/{domain}.json + * Domain files live at {dbt_project}/.erd-studio/{layer}/{domain}.json * and describe FK-based relationships between dbt models within a business * domain at a particular design stage (logical or physical). */ @@ -230,7 +230,7 @@ export interface SemanticDomain { /** * Unified domain file format (v4). * - * A single JSON file at erd-studio/{layer}/{domain}.json containing + * A single JSON file at .erd-studio/{layer}/{domain}.json containing * logical stage data. Physical stage is derived at runtime from * the logical models projected through the dbt manifest. */ @@ -270,7 +270,7 @@ export interface StageDataV5 { * * Same as v4 but `logical.models` contains model name strings instead of * inline SemanticModel objects. Models are stored centrally in - * erd-studio/logical-models/{name}.yml. + * .erd-studio/logical-models/{name}.yml. */ export interface UnifiedDomainV5 { schemaVersion: number; diff --git a/src/types/syncPlan.ts b/src/types/syncPlan.ts index d35bcd5..f2572fd 100644 --- a/src/types/syncPlan.ts +++ b/src/types/syncPlan.ts @@ -103,7 +103,7 @@ export interface RelationshipResolution { export interface ModelContext { modelName: string; - /** Relative path to the logical model YAML (e.g. erd-studio/logical-models/dim_customer.yml). */ + /** Relative path to the logical model YAML (e.g. .erd-studio/logical-models/dim_customer.yml). */ logicalModelPath: string; /** Relative path to the dbt SQL file (from manifest originalFilePath). Null if not in manifest. */ dbtSqlPath: string | null; @@ -112,7 +112,7 @@ export interface ModelContext { } // --------------------------------------------------------------------------- -// The sync plan (written to erd-studio/.sync-plan.json) +// The sync plan (written to .erd-studio/.sync-plan.json) // --------------------------------------------------------------------------- export interface SyncPlan { diff --git a/src/watchers/FileWatcherService.ts b/src/watchers/FileWatcherService.ts index 1360026..515c82e 100644 --- a/src/watchers/FileWatcherService.ts +++ b/src/watchers/FileWatcherService.ts @@ -3,7 +3,7 @@ * * Watches: * - target/manifest.json (dbt compile output) → triggers manifest cache invalidation - * - erd-studio/**\/*.json (semantic domain files) → triggers tree and editor refresh + * - {semanticDir}/**\/*.json (semantic domain files, default .erd-studio) → triggers tree and editor refresh * - dbt_project.yml (project configuration) → reload prompt only when path config changes * * All change events are debounced by 300ms to prevent rapid-fire triggers @@ -41,7 +41,7 @@ export class FileWatcherService implements vscode.Disposable { readonly onManifestChanged = this._onManifestChanged.event; readonly onSemanticFileChanged = this._onSemanticFileChanged.event; readonly onSemanticFileDeleted = this._onSemanticFileDeleted.event; - /** Fires when a YAML model file in erd-studio/logical-models/ changes. */ + /** Fires when a YAML model file in {semanticDir}/logical-models/ changes. */ readonly onLogicalModelChanged = this._onLogicalModelChanged.event; /** Fires when any dbt schema .yml/.yaml file under models/ changes. */ readonly onDbtYmlChanged = this._onDbtYmlChanged.event; @@ -51,7 +51,10 @@ export class FileWatcherService implements vscode.Disposable { /** Snapshot of path-related keys from dbt_project.yml at startup. */ private lastProjectPaths: string; - constructor(private readonly workspaceRoot: string) { + constructor( + private readonly workspaceRoot: string, + private readonly semanticDir: string = '.erd-studio', + ) { this.lastProjectPaths = this.readProjectPaths(); this.setupManifestWatcher(); this.setupSemanticWatcher(); @@ -87,13 +90,13 @@ export class FileWatcherService implements vscode.Disposable { } /** - * Watch erd-studio/**\/*.json for changes. + * Watch {semanticDir}/**\/*.json for changes. * Fires when domain files are created, modified, or deleted externally. */ private setupSemanticWatcher(): void { const pattern = new vscode.RelativePattern( this.workspaceRoot, - 'erd-studio/**/*.json', + `${this.semanticDir}/**/*.json`, ); const watcher = vscode.workspace.createFileSystemWatcher(pattern); @@ -182,14 +185,14 @@ export class FileWatcherService implements vscode.Disposable { } /** - * Watch erd-studio/logical-models/*.yml for changes. + * Watch {semanticDir}/logical-models/*.yml for changes. * Fires when model definition files are created, modified, or deleted. * Used to refresh open domain editors that reference the changed model. */ private setupLogicalModelWatcher(): void { const pattern = new vscode.RelativePattern( this.workspaceRoot, - 'erd-studio/logical-models/*.yml', + `${this.semanticDir}/logical-models/*.yml`, ); const watcher = vscode.workspace.createFileSystemWatcher(pattern); diff --git a/test/fixtures/dbt-project-malformed/erd-studio/silver/broken.json b/test/fixtures/dbt-project-malformed/.erd-studio/silver/broken.json similarity index 100% rename from test/fixtures/dbt-project-malformed/erd-studio/silver/broken.json rename to test/fixtures/dbt-project-malformed/.erd-studio/silver/broken.json diff --git a/test/fixtures/dbt-project-sparse/erd-studio/silver/future-version.json b/test/fixtures/dbt-project-sparse/.erd-studio/silver/future-version.json similarity index 100% rename from test/fixtures/dbt-project-sparse/erd-studio/silver/future-version.json rename to test/fixtures/dbt-project-sparse/.erd-studio/silver/future-version.json diff --git a/test/fixtures/dbt-project-sparse/erd-studio/silver/minimal.json b/test/fixtures/dbt-project-sparse/.erd-studio/silver/minimal.json similarity index 100% rename from test/fixtures/dbt-project-sparse/erd-studio/silver/minimal.json rename to test/fixtures/dbt-project-sparse/.erd-studio/silver/minimal.json diff --git a/test/fixtures/dbt-project-sparse/erd-studio/silver/no-schema-version.json b/test/fixtures/dbt-project-sparse/.erd-studio/silver/no-schema-version.json similarity index 100% rename from test/fixtures/dbt-project-sparse/erd-studio/silver/no-schema-version.json rename to test/fixtures/dbt-project-sparse/.erd-studio/silver/no-schema-version.json diff --git a/test/fixtures/dbt-project/.claude/skills/erd-studio/SKILL.md b/test/fixtures/dbt-project/.claude/skills/erd-studio/SKILL.md index 9024e6d..915ba22 100644 --- a/test/fixtures/dbt-project/.claude/skills/erd-studio/SKILL.md +++ b/test/fixtures/dbt-project/.claude/skills/erd-studio/SKILL.md @@ -1,10 +1,10 @@ --- name: erd-studio description: >- - Schema rules for ERD Studio data model files — the erd-studio/ directory + Schema rules for ERD Studio data model files — the .erd-studio/ directory uses a two-file system (YAML model definitions + JSON domain diagrams) with strict format rules you must read before editing. Use this skill - whenever the task touches files in erd-studio/ (domain JSON, logical-models + whenever the task touches files in .erd-studio/ (domain JSON, logical-models YAML, or .sync-plan.json), asks to add/edit/remove models, columns, relationships, or cardinality in a data model or ERD diagram, mentions dim_/fct_/ref_/brg_ prefixed tables in an erd-studio context, or involves @@ -15,12 +15,12 @@ description: >- # ERD Studio — AI Data Modeling Guide -ERD Studio uses a **central model store** architecture. Model definitions are YAML files in `erd-studio/logical-models/`. Domain JSON files reference models by name and define relationships and layout. +ERD Studio uses a **central model store** architecture. Model definitions are YAML files in `.erd-studio/logical-models/`. Domain JSON files reference models by name and define relationships and layout. ## Architecture Overview ``` -erd-studio/ +.erd-studio/ ├── logical-models/ ← Central model definitions (YAML, one per model) │ ├── dim_customer.yml │ ├── dim_project.yml @@ -45,7 +45,7 @@ The **Model Library** panel in the ERD Studio sidebar shows all YAML files in `l ## Domain File Structure -**File:** `erd-studio/{layer}/{domain}.json` +**File:** `.erd-studio/{layer}/{domain}.json` ```json { @@ -112,9 +112,9 @@ Annotations are temporary build notes — visible on the canvas while constructi ## Models -Model definitions live in `erd-studio/logical-models/{model_name}.yml`. Create/edit these YAML files to define models. Then reference them by name in domain files. +Model definitions live in `.erd-studio/logical-models/{model_name}.yml`. Create/edit these YAML files to define models. Then reference them by name in domain files. -**File:** `erd-studio/logical-models/dim_customer.yml` +**File:** `.erd-studio/logical-models/dim_customer.yml` ```yaml name: dim_customer @@ -185,7 +185,7 @@ Optional `rationale` object — all fields are optional strings. Omit the entire When the user asks you to create a new model — or materially add columns to an existing one — from an external source (planning doc, DDL, staging SQL, CSV, notebook, or another YAML), follow this protocol. It exists to prevent silent column truncation. -**Does NOT apply to:** renaming a column, changing a single flag, or executing an `erd-studio/.sync-plan.json` (see SYNC.md for that workflow). +**Does NOT apply to:** renaming a column, changing a single flag, or executing an `.erd-studio/.sync-plan.json` (see SYNC.md for that workflow). ### Step 1 — Read the source fully, then enumerate Before listing anything, confirm you have read the source **in full**. For files longer than 2000 lines, page through with `Read` using `offset`/`limit` until you reach the end of the file. A partial read is a silent-truncation trap before you even start — the columns you never saw cannot appear in your output. @@ -211,7 +211,7 @@ State which of those columns you intend to build, in plain English. Proceed straight to step 3 — do not wait for confirmation. The user will correct you if the scope is wrong. ### Step 3 — Build -Write the `erd-studio/logical-models/{name}.yml` file. +Write the `.erd-studio/logical-models/{name}.yml` file. ### Step 4 — Reconcile via set-difference Re-read the YAML file you just wrote. Compute the set-difference between source columns and YAML columns — do not rely on a total count alone, because counts can coincidentally match while columns still differ. @@ -318,10 +318,10 @@ Recognized test types: `relationships`, `relationships_where`, and any test whos ## Sync Reconciliation -When asked to execute a sync plan, or when `erd-studio/.sync-plan.json` exists: +When asked to execute a sync plan, or when `.erd-studio/.sync-plan.json` exists: 1. Read `SYNC.md` in the same directory as this skill file for the full action reference and execution guide -2. Read `erd-studio/.sync-plan.json` for the specific actions to execute +2. Read `.erd-studio/.sync-plan.json` for the specific actions to execute 3. Follow the execution steps in SYNC.md to reconcile logical and physical models - + diff --git a/test/fixtures/dbt-project/.claude/skills/erd-studio/SYNC.md b/test/fixtures/dbt-project/.claude/skills/erd-studio/SYNC.md index a68f077..087ef0f 100644 --- a/test/fixtures/dbt-project/.claude/skills/erd-studio/SYNC.md +++ b/test/fixtures/dbt-project/.claude/skills/erd-studio/SYNC.md @@ -6,7 +6,7 @@ The sync plan reconciles differences between the **logical** (user-defined) and ## When to Use -When `erd-studio/.sync-plan.json` exists in the project, the user has reviewed +When `.erd-studio/.sync-plan.json` exists in the project, the user has reviewed logical-vs-physical discrepancies in ERD Studio and chosen which side is "ground truth" for each difference. Your job is to execute those choices. @@ -22,7 +22,7 @@ for each difference. Your job is to execute those choices. "modelContext": { "dim_customer": { "modelName": "dim_customer", - "logicalModelPath": "erd-studio/logical-models/dim_customer.yml", + "logicalModelPath": ".erd-studio/logical-models/dim_customer.yml", "dbtSqlPath": "models/silver/dim_customer.sql", "dbtSchemaPath": "models/silver/dim_customer.yml" } @@ -93,14 +93,14 @@ models: ## Execution Steps -1. **Read** `erd-studio/.sync-plan.json` +1. **Read** `.erd-studio/.sync-plan.json` 2. **Execute each action** in order: - For logical-side actions: edit files at `modelContext[modelName].logicalModelPath` and/or the domain JSON - For physical-side actions: edit files at `modelContext[modelName].dbtSqlPath` and `dbtSchemaPath` - For destructive actions (`remove-*`): confirm with the user before proceeding 3. **Compile** if `requiresCompile` is `true`: run `dbt compile` to regenerate the manifest 4. **Verify**: Re-open the domain in ERD Studio and run the diff comparison to confirm discrepancies are resolved -5. **Clean up**: Delete `erd-studio/.sync-plan.json` on success +5. **Clean up**: Delete `.erd-studio/.sync-plan.json` on success ## Important Notes @@ -109,4 +109,4 @@ models: - **Cascade deletions**: When removing a model from logical, also remove any relationships referencing it - **Column ordering**: When adding columns to logical-models YAML, append to the end of the columns array - + diff --git a/test/fixtures/dbt-project/.claude/skills/erd-studio/enforce-skill.sh b/test/fixtures/dbt-project/.claude/skills/erd-studio/enforce-skill.sh index cb345dc..5a350f7 100755 --- a/test/fixtures/dbt-project/.claude/skills/erd-studio/enforce-skill.sh +++ b/test/fixtures/dbt-project/.claude/skills/erd-studio/enforce-skill.sh @@ -1,10 +1,10 @@ #!/usr/bin/env bash # ERD Studio — PreToolUse hook for Edit and Write tools. -# Blocks the first erd-studio file edit per Claude Code session to ensure the +# Blocks the first .erd-studio file edit per Claude Code session to ensure the # /erd-studio skill is loaded before any changes are made. Subsequent edits # in the same session are allowed (flag keyed on session_id from stdin JSON). -deny='{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"You must load the /erd-studio skill before editing erd-studio files. It contains the two-file editing rules (YAML models vs JSON domains). Run: /erd-studio — then retry."}}' +deny='{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"You must load the /erd-studio skill before editing .erd-studio files. It contains the two-file editing rules (YAML models vs JSON domains). Run: /erd-studio — then retry."}}' allow='{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":""}}' # Read all stdin (Claude sends hook input JSON via stdin) @@ -14,9 +14,9 @@ input="$(cat)" file_path="$(echo "$input" | grep -o '"file_path" *: *"[^"]*"' | head -1 | sed 's/.*: *"//;s/"$//')" session_id="$(echo "$input" | grep -o '"session_id" *: *"[^"]*"' | head -1 | sed 's/.*: *"//;s/"$//')" -# Only act on files inside erd-studio/ directories +# Only act on files inside .erd-studio/ directories case "$file_path" in - */erd-studio/*) + */.erd-studio/*) flag="/tmp/.erd-studio-skill-${session_id}" if [ ! -f "$flag" ]; then touch "$flag" diff --git a/test/fixtures/dbt-project/erd-studio/.sync-plan.json b/test/fixtures/dbt-project/.erd-studio/.sync-plan.json similarity index 99% rename from test/fixtures/dbt-project/erd-studio/.sync-plan.json rename to test/fixtures/dbt-project/.erd-studio/.sync-plan.json index 4b543dd..261b812 100644 --- a/test/fixtures/dbt-project/erd-studio/.sync-plan.json +++ b/test/fixtures/dbt-project/.erd-studio/.sync-plan.json @@ -7,7 +7,7 @@ "modelContext": { "fct_large_table": { "modelName": "fct_large_table", - "logicalModelPath": "erd-studio/logical-models/fct_large_table.yml", + "logicalModelPath": ".erd-studio/logical-models/fct_large_table.yml", "dbtSqlPath": null, "dbtSchemaPath": null } diff --git a/test/fixtures/dbt-project/erd-studio/gold/finance.json b/test/fixtures/dbt-project/.erd-studio/gold/finance.json similarity index 100% rename from test/fixtures/dbt-project/erd-studio/gold/finance.json rename to test/fixtures/dbt-project/.erd-studio/gold/finance.json diff --git a/test/fixtures/dbt-project/erd-studio/layers.json b/test/fixtures/dbt-project/.erd-studio/layers.json similarity index 100% rename from test/fixtures/dbt-project/erd-studio/layers.json rename to test/fixtures/dbt-project/.erd-studio/layers.json diff --git a/test/fixtures/dbt-project/erd-studio/logical-models/dim_customer.yml b/test/fixtures/dbt-project/.erd-studio/logical-models/dim_customer.yml similarity index 100% rename from test/fixtures/dbt-project/erd-studio/logical-models/dim_customer.yml rename to test/fixtures/dbt-project/.erd-studio/logical-models/dim_customer.yml diff --git a/test/fixtures/dbt-project/erd-studio/logical-models/dim_date.yml b/test/fixtures/dbt-project/.erd-studio/logical-models/dim_date.yml similarity index 100% rename from test/fixtures/dbt-project/erd-studio/logical-models/dim_date.yml rename to test/fixtures/dbt-project/.erd-studio/logical-models/dim_date.yml diff --git a/test/fixtures/dbt-project/erd-studio/logical-models/dim_location.yml b/test/fixtures/dbt-project/.erd-studio/logical-models/dim_location.yml similarity index 100% rename from test/fixtures/dbt-project/erd-studio/logical-models/dim_location.yml rename to test/fixtures/dbt-project/.erd-studio/logical-models/dim_location.yml diff --git a/test/fixtures/dbt-project/erd-studio/logical-models/dim_project.yml b/test/fixtures/dbt-project/.erd-studio/logical-models/dim_project.yml similarity index 100% rename from test/fixtures/dbt-project/erd-studio/logical-models/dim_project.yml rename to test/fixtures/dbt-project/.erd-studio/logical-models/dim_project.yml diff --git a/test/fixtures/dbt-project/erd-studio/logical-models/dim_task.yml b/test/fixtures/dbt-project/.erd-studio/logical-models/dim_task.yml similarity index 100% rename from test/fixtures/dbt-project/erd-studio/logical-models/dim_task.yml rename to test/fixtures/dbt-project/.erd-studio/logical-models/dim_task.yml diff --git a/test/fixtures/dbt-project/erd-studio/logical-models/fct_large_table.yml b/test/fixtures/dbt-project/.erd-studio/logical-models/fct_large_table.yml similarity index 100% rename from test/fixtures/dbt-project/erd-studio/logical-models/fct_large_table.yml rename to test/fixtures/dbt-project/.erd-studio/logical-models/fct_large_table.yml diff --git a/test/fixtures/dbt-project/erd-studio/logical-models/fct_order.yml b/test/fixtures/dbt-project/.erd-studio/logical-models/fct_order.yml similarity index 100% rename from test/fixtures/dbt-project/erd-studio/logical-models/fct_order.yml rename to test/fixtures/dbt-project/.erd-studio/logical-models/fct_order.yml diff --git a/test/fixtures/dbt-project/erd-studio/logical-models/fct_sale.yml b/test/fixtures/dbt-project/.erd-studio/logical-models/fct_sale.yml similarity index 100% rename from test/fixtures/dbt-project/erd-studio/logical-models/fct_sale.yml rename to test/fixtures/dbt-project/.erd-studio/logical-models/fct_sale.yml diff --git a/test/fixtures/dbt-project/erd-studio/logical-models/fct_task_event.yml b/test/fixtures/dbt-project/.erd-studio/logical-models/fct_task_event.yml similarity index 100% rename from test/fixtures/dbt-project/erd-studio/logical-models/fct_task_event.yml rename to test/fixtures/dbt-project/.erd-studio/logical-models/fct_task_event.yml diff --git a/test/fixtures/dbt-project/erd-studio/silver/bob.json b/test/fixtures/dbt-project/.erd-studio/silver/bob.json similarity index 100% rename from test/fixtures/dbt-project/erd-studio/silver/bob.json rename to test/fixtures/dbt-project/.erd-studio/silver/bob.json diff --git a/test/fixtures/dbt-project/erd-studio/silver/ncr.json b/test/fixtures/dbt-project/.erd-studio/silver/ncr.json similarity index 100% rename from test/fixtures/dbt-project/erd-studio/silver/ncr.json rename to test/fixtures/dbt-project/.erd-studio/silver/ncr.json diff --git a/test/fixtures/dbt-project/erd-studio/silver/scroll-test.json b/test/fixtures/dbt-project/.erd-studio/silver/scroll-test.json similarity index 100% rename from test/fixtures/dbt-project/erd-studio/silver/scroll-test.json rename to test/fixtures/dbt-project/.erd-studio/silver/scroll-test.json diff --git a/test/fixtures/dbt-project/erd-studio/silver/sdd.json b/test/fixtures/dbt-project/.erd-studio/silver/sdd.json similarity index 100% rename from test/fixtures/dbt-project/erd-studio/silver/sdd.json rename to test/fixtures/dbt-project/.erd-studio/silver/sdd.json diff --git a/test/fixtures/dbt-project/erd-studio/silver/showcase.json b/test/fixtures/dbt-project/.erd-studio/silver/showcase.json similarity index 100% rename from test/fixtures/dbt-project/erd-studio/silver/showcase.json rename to test/fixtures/dbt-project/.erd-studio/silver/showcase.json diff --git a/test/fixtures/dbt-project/erd-studio/silver/ttt.json b/test/fixtures/dbt-project/.erd-studio/silver/ttt.json similarity index 100% rename from test/fixtures/dbt-project/erd-studio/silver/ttt.json rename to test/fixtures/dbt-project/.erd-studio/silver/ttt.json diff --git a/test/fixtures/dbt-project/erd-studio/templates/blank.json b/test/fixtures/dbt-project/.erd-studio/templates/blank.json similarity index 100% rename from test/fixtures/dbt-project/erd-studio/templates/blank.json rename to test/fixtures/dbt-project/.erd-studio/templates/blank.json diff --git a/test/fixtures/dbt-project/erd-studio/templates/bridge.json b/test/fixtures/dbt-project/.erd-studio/templates/bridge.json similarity index 100% rename from test/fixtures/dbt-project/erd-studio/templates/bridge.json rename to test/fixtures/dbt-project/.erd-studio/templates/bridge.json diff --git a/test/fixtures/dbt-project/erd-studio/templates/dimension.json b/test/fixtures/dbt-project/.erd-studio/templates/dimension.json similarity index 100% rename from test/fixtures/dbt-project/erd-studio/templates/dimension.json rename to test/fixtures/dbt-project/.erd-studio/templates/dimension.json diff --git a/test/fixtures/dbt-project/erd-studio/templates/fact.json b/test/fixtures/dbt-project/.erd-studio/templates/fact.json similarity index 100% rename from test/fixtures/dbt-project/erd-studio/templates/fact.json rename to test/fixtures/dbt-project/.erd-studio/templates/fact.json diff --git a/test/fixtures/dbt-project/erd-studio/templates/scd2.json b/test/fixtures/dbt-project/.erd-studio/templates/scd2.json similarity index 100% rename from test/fixtures/dbt-project/erd-studio/templates/scd2.json rename to test/fixtures/dbt-project/.erd-studio/templates/scd2.json diff --git a/test/unit/domainService.test.ts b/test/unit/domainService.test.ts index fa19ec1..1f2ec4c 100644 --- a/test/unit/domainService.test.ts +++ b/test/unit/domainService.test.ts @@ -51,7 +51,7 @@ describe('DomainService', () => { }); describe('listDomains', () => { - it('discovers all .json files under erd-studio/{layer}/', () => { + it('discovers all .json files under .erd-studio/{layer}/', () => { const domains = service.listDomains(FIXTURE_PROJECT_PATH); const silverDomains = domains.filter((d) => d.layer === 'silver'); @@ -76,11 +76,11 @@ describe('DomainService', () => { expect(finance).toBeDefined(); expect(finance!.filePath).toBe( - path.join(FIXTURE_PROJECT_PATH, 'erd-studio', 'gold', 'finance.json') + path.join(FIXTURE_PROJECT_PATH, '.erd-studio', 'gold', 'finance.json') ); }); - it('returns empty array when erd-studio directory does not exist', () => { + it('returns empty array when .erd-studio directory does not exist', () => { const domains = service.listDomains('/nonexistent/path'); expect(domains).toEqual([]); }); @@ -92,7 +92,7 @@ describe('DomainService', () => { }); it('supports custom semantic directory', () => { - const domains = service.listDomains(FIXTURE_PROJECT_PATH, 'erd-studio'); + const domains = service.listDomains(FIXTURE_PROJECT_PATH, '.erd-studio'); expect(domains.length).toBeGreaterThan(0); }); @@ -110,7 +110,7 @@ describe('DomainService', () => { describe('getDomain', () => { it('reads and parses a valid domain file into a UnifiedDomain', () => { const filePath = path.join( - FIXTURE_PROJECT_PATH, 'erd-studio', 'gold', 'finance.json' + FIXTURE_PROJECT_PATH, '.erd-studio', 'gold', 'finance.json' ); const domain = service.getDomain(filePath); @@ -122,7 +122,7 @@ describe('DomainService', () => { it('returns logical stage section', () => { const filePath = path.join( - FIXTURE_PROJECT_PATH, 'erd-studio', 'gold', 'finance.json' + FIXTURE_PROJECT_PATH, '.erd-studio', 'gold', 'finance.json' ); const domain = service.getDomain(filePath); @@ -132,7 +132,7 @@ describe('DomainService', () => { it('parses viewConfig correctly from top-level', () => { const filePath = path.join( - FIXTURE_PROJECT_PATH, 'erd-studio', 'gold', 'finance.json' + FIXTURE_PROJECT_PATH, '.erd-studio', 'gold', 'finance.json' ); const domain = service.getDomain(filePath); @@ -149,28 +149,28 @@ describe('DomainService', () => { it('handles invalid JSON with descriptive error', () => { const filePath = path.join( - MALFORMED_PROJECT_PATH, 'erd-studio', 'silver', 'broken.json' + MALFORMED_PROJECT_PATH, '.erd-studio', 'silver', 'broken.json' ); expect(() => service.getDomain(filePath)).toThrow('Invalid JSON'); }); it('throws when schemaVersion is missing', () => { const filePath = path.join( - SPARSE_PROJECT_PATH, 'erd-studio', 'silver', 'no-schema-version.json' + SPARSE_PROJECT_PATH, '.erd-studio', 'silver', 'no-schema-version.json' ); expect(() => service.getDomain(filePath)).toThrow('schemaVersion'); }); it('throws when schemaVersion is from the future', () => { const filePath = path.join( - SPARSE_PROJECT_PATH, 'erd-studio', 'silver', 'future-version.json' + SPARSE_PROJECT_PATH, '.erd-studio', 'silver', 'future-version.json' ); expect(() => service.getDomain(filePath)).toThrow('update the extension'); }); it('applies defaults for missing optional fields', () => { const filePath = path.join( - SPARSE_PROJECT_PATH, 'erd-studio', 'silver', 'minimal.json' + SPARSE_PROJECT_PATH, '.erd-studio', 'silver', 'minimal.json' ); const domain = service.getDomain(filePath); @@ -186,7 +186,7 @@ describe('DomainService', () => { describe('getDomainStage', () => { it('extracts logical stage from unified domain', () => { const filePath = path.join( - FIXTURE_PROJECT_PATH, 'erd-studio', 'gold', 'finance.json' + FIXTURE_PROJECT_PATH, '.erd-studio', 'gold', 'finance.json' ); const stage = service.getDomainStage(filePath); @@ -197,7 +197,7 @@ describe('DomainService', () => { it('includes shared metadata in extracted stage', () => { const filePath = path.join( - FIXTURE_PROJECT_PATH, 'erd-studio', 'silver', 'ncr.json' + FIXTURE_PROJECT_PATH, '.erd-studio', 'silver', 'ncr.json' ); const stage = service.getDomainStage(filePath); diff --git a/test/unit/domainTreeProvider.test.ts b/test/unit/domainTreeProvider.test.ts index ad9a55b..8d45156 100644 --- a/test/unit/domainTreeProvider.test.ts +++ b/test/unit/domainTreeProvider.test.ts @@ -12,7 +12,7 @@ vi.mock('fs', async () => { return { ...actual, existsSync: vi.fn((p: string) => { - if (typeof p === 'string' && p.includes('test-project') && p.includes('erd-studio')) return true; + if (typeof p === 'string' && p.includes('test-project') && p.includes('.erd-studio')) return true; return actual.existsSync(p as any); }), }; @@ -74,19 +74,19 @@ function createMockDomainService( // --------------------------------------------------------------------------- const SILVER_DOMAINS: DomainSummary[] = [ - { domain: 'customer-360', layer: 'silver', filePath: '/project/erd-studio/silver/customer-360.json' }, - { domain: 'orders', layer: 'silver', filePath: '/project/erd-studio/silver/orders.json' }, + { domain: 'customer-360', layer: 'silver', filePath: '/project/.erd-studio/silver/customer-360.json' }, + { domain: 'orders', layer: 'silver', filePath: '/project/.erd-studio/silver/orders.json' }, ]; const GOLD_DOMAINS: DomainSummary[] = [ - { domain: 'reporting', layer: 'gold', filePath: '/project/erd-studio/gold/reporting.json' }, + { domain: 'reporting', layer: 'gold', filePath: '/project/.erd-studio/gold/reporting.json' }, ]; const ALL_SUMMARIES = [...SILVER_DOMAINS, ...GOLD_DOMAINS]; function buildDomainMap(): Map { const map = new Map(); - map.set('/project/erd-studio/silver/customer-360.json', makeUnifiedDomain({ + map.set('/project/.erd-studio/silver/customer-360.json', makeUnifiedDomain({ domain: 'customer-360', layer: 'silver', logical: { @@ -94,7 +94,7 @@ function buildDomainMap(): Map { relationships: [], }, })); - map.set('/project/erd-studio/silver/orders.json', makeUnifiedDomain({ + map.set('/project/.erd-studio/silver/orders.json', makeUnifiedDomain({ domain: 'orders', layer: 'silver', logical: { @@ -102,7 +102,7 @@ function buildDomainMap(): Map { relationships: [], }, })); - map.set('/project/erd-studio/gold/reporting.json', makeUnifiedDomain({ + map.set('/project/.erd-studio/gold/reporting.json', makeUnifiedDomain({ domain: 'reporting', layer: 'gold', logical: { diff --git a/test/unit/fileWatcherService.test.ts b/test/unit/fileWatcherService.test.ts index 0c6f17e..98937c8 100644 --- a/test/unit/fileWatcherService.test.ts +++ b/test/unit/fileWatcherService.test.ts @@ -105,7 +105,7 @@ describe('FileWatcherService', () => { service.onSemanticFileChanged(listener); const semanticWatcher = _mockFileWatchers[1]; - const uri = vscode.Uri.file('/test/workspace/erd-studio/silver/orders.json'); + const uri = vscode.Uri.file('/test/workspace/.erd-studio/silver/orders.json'); semanticWatcher._simulateChange(uri); vi.advanceTimersByTime(300); @@ -117,7 +117,7 @@ describe('FileWatcherService', () => { service.onSemanticFileChanged(listener); const semanticWatcher = _mockFileWatchers[1]; - const uri = vscode.Uri.file('/test/workspace/erd-studio/gold/new-domain.json'); + const uri = vscode.Uri.file('/test/workspace/.erd-studio/gold/new-domain.json'); semanticWatcher._simulateCreate(uri); vi.advanceTimersByTime(300); @@ -129,7 +129,7 @@ describe('FileWatcherService', () => { service.onSemanticFileDeleted(listener); const semanticWatcher = _mockFileWatchers[1]; - const uri = vscode.Uri.file('/test/workspace/erd-studio/silver/deleted.json'); + const uri = vscode.Uri.file('/test/workspace/.erd-studio/silver/deleted.json'); semanticWatcher._simulateDelete(uri); vi.advanceTimersByTime(300); @@ -141,7 +141,7 @@ describe('FileWatcherService', () => { service.onSemanticFileChanged(listener); const semanticWatcher = _mockFileWatchers[1]; - const uri = vscode.Uri.file('/test/workspace/erd-studio/silver/deleted.json'); + const uri = vscode.Uri.file('/test/workspace/.erd-studio/silver/deleted.json'); semanticWatcher._simulateDelete(uri); vi.advanceTimersByTime(300); @@ -153,8 +153,8 @@ describe('FileWatcherService', () => { service.onSemanticFileChanged(listener); const semanticWatcher = _mockFileWatchers[1]; - const uri1 = vscode.Uri.file('/test/workspace/erd-studio/silver/file1.json'); - const uri2 = vscode.Uri.file('/test/workspace/erd-studio/silver/file2.json'); + const uri1 = vscode.Uri.file('/test/workspace/.erd-studio/silver/file1.json'); + const uri2 = vscode.Uri.file('/test/workspace/.erd-studio/silver/file2.json'); // Change file1 multiple times semanticWatcher._simulateChange(uri1); diff --git a/test/unit/harnessService.test.ts b/test/unit/harnessService.test.ts index 77d5eb5..b1f0f4f 100644 --- a/test/unit/harnessService.test.ts +++ b/test/unit/harnessService.test.ts @@ -39,7 +39,7 @@ describe('HarnessService', () => { it('generates Copilot instructions with applyTo glob', () => { const content = service.generateContent('copilot'); - expect(content).toContain("applyTo: '**/erd-studio/**/*.json'"); + expect(content).toContain("applyTo: '**/.erd-studio/**/*.json'"); expect(content).toContain("name: 'ERD Studio'"); expect(content).toContain('# ERD Studio'); }); @@ -63,7 +63,7 @@ describe('HarnessService', () => { expect(content).toContain('schemaVersion'); expect(content).toContain('viewConfig'); expect(content).toContain('logical'); - expect(content).toContain('erd-studio/{layer}/{domain}.json'); + expect(content).toContain('.erd-studio/{layer}/{domain}.json'); } }); diff --git a/test/unit/logicalModelService.test.ts b/test/unit/logicalModelService.test.ts index e60394c..61d40eb 100644 --- a/test/unit/logicalModelService.test.ts +++ b/test/unit/logicalModelService.test.ts @@ -1,5 +1,5 @@ /** - * Tests for LogicalModelService — YAML model file I/O for erd-studio/logical-models/. + * Tests for LogicalModelService — YAML model file I/O for .erd-studio/logical-models/. */ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; diff --git a/test/unit/modelLibraryTreeProvider.test.ts b/test/unit/modelLibraryTreeProvider.test.ts index b72b73a..4a7e016 100644 --- a/test/unit/modelLibraryTreeProvider.test.ts +++ b/test/unit/modelLibraryTreeProvider.test.ts @@ -21,7 +21,7 @@ vi.mock('fs', async () => { function createMockLogicalModelService( modelNames: string[] = [], - modelsDir = '/project/erd-studio/logical-models', + modelsDir = '/project/.erd-studio/logical-models', ): LogicalModelService { return { dirExists: vi.fn(() => modelNames.length > 0), @@ -67,8 +67,8 @@ function v4DomainJson(modelNames: string[]): string { // --------------------------------------------------------------------------- const SUMMARIES: DomainSummary[] = [ - { domain: 'customer-360', layer: 'silver', filePath: '/project/erd-studio/silver/customer-360.json' }, - { domain: 'reporting', layer: 'gold', filePath: '/project/erd-studio/gold/reporting.json' }, + { domain: 'customer-360', layer: 'silver', filePath: '/project/.erd-studio/silver/customer-360.json' }, + { domain: 'reporting', layer: 'gold', filePath: '/project/.erd-studio/gold/reporting.json' }, ]; // --------------------------------------------------------------------------- @@ -103,7 +103,7 @@ describe('ModelLibraryTreeProvider', () => { mockLogicalModelService, mockDomainService, '/project', - 'erd-studio', + '.erd-studio', ); }); @@ -129,7 +129,7 @@ describe('ModelLibraryTreeProvider', () => { mockLogicalModelService, mockDomainService, '/project', - 'erd-studio', + '.erd-studio', ); expect(provider.getChildren()).toEqual([]); }); @@ -174,8 +174,8 @@ describe('ModelLibraryTreeProvider', () => { it('sets correct filePath on each node', () => { const children = provider.getChildren()!; - expect(children[0].filePath).toBe('/project/erd-studio/logical-models/dim_customer.yml'); - expect(children[1].filePath).toBe('/project/erd-studio/logical-models/dim_date.yml'); + expect(children[0].filePath).toBe('/project/.erd-studio/logical-models/dim_customer.yml'); + expect(children[1].filePath).toBe('/project/.erd-studio/logical-models/dim_date.yml'); }); }); @@ -188,7 +188,7 @@ describe('ModelLibraryTreeProvider', () => { const node: ModelLibraryNode = { type: 'model', name: 'dim_date', - filePath: '/project/erd-studio/logical-models/dim_date.yml', + filePath: '/project/.erd-studio/logical-models/dim_date.yml', referencingDomains: [], }; @@ -205,7 +205,7 @@ describe('ModelLibraryTreeProvider', () => { const node: ModelLibraryNode = { type: 'model', name: 'dim_customer', - filePath: '/project/erd-studio/logical-models/dim_customer.yml', + filePath: '/project/.erd-studio/logical-models/dim_customer.yml', referencingDomains: ['customer-360', 'reporting'], }; @@ -222,7 +222,7 @@ describe('ModelLibraryTreeProvider', () => { const node: ModelLibraryNode = { type: 'model', name: 'fct_orders', - filePath: '/project/erd-studio/logical-models/fct_orders.yml', + filePath: '/project/.erd-studio/logical-models/fct_orders.yml', referencingDomains: ['customer-360'], }; @@ -234,7 +234,7 @@ describe('ModelLibraryTreeProvider', () => { const node: ModelLibraryNode = { type: 'model', name: 'dim_customer', - filePath: '/project/erd-studio/logical-models/dim_customer.yml', + filePath: '/project/.erd-studio/logical-models/dim_customer.yml', referencingDomains: [], }; diff --git a/test/unit/selectorsService.test.ts b/test/unit/selectorsService.test.ts index 18c1132..ede4348 100644 --- a/test/unit/selectorsService.test.ts +++ b/test/unit/selectorsService.test.ts @@ -82,7 +82,7 @@ describe('SelectorsService', () => { }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); const result = svc.regenerate(); @@ -119,7 +119,7 @@ describe('SelectorsService', () => { }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); svc.regenerate(); @@ -138,7 +138,7 @@ describe('SelectorsService', () => { { domain: 'real', layer: 'silver', filePath: '/dummy/silver/real.json', models: ['dim_real'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); const result = svc.regenerate(); @@ -155,7 +155,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['m1'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); svc.regenerate(); const raw = fs.readFileSync(path.join(tmpDir, 'selectors.yml'), 'utf-8'); @@ -174,7 +174,7 @@ describe('SelectorsService', () => { }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); svc.regenerate(); @@ -193,7 +193,7 @@ describe('SelectorsService', () => { { domain: 'new', layer: 'silver', filePath: '/x/silver/new.json', models: ['dim_new'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); svc.regenerate(); @@ -225,7 +225,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); svc.regenerate(); @@ -257,7 +257,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); svc.regenerate(); @@ -286,7 +286,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); svc.regenerate(); @@ -314,7 +314,7 @@ describe('SelectorsService', () => { { domain: 'new', layer: 'silver', filePath: '/x/silver/new.json', models: ['dim_new'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); svc.regenerate(); @@ -345,7 +345,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); svc.regenerate(); const first = fs.readFileSync(path.join(tmpDir, 'selectors.yml'), 'utf-8'); @@ -372,7 +372,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); svc.regenerate(); @@ -401,7 +401,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); svc.regenerate(); @@ -431,7 +431,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); expect(() => svc.regenerate()).not.toThrow(); @@ -452,7 +452,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['m1'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); const result = svc.regenerate(); expect(result.status).toBe('written'); @@ -466,7 +466,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['m1'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); const result = svc.regenerate(); expect(result.status).toBe('written'); @@ -491,7 +491,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); svc.regenerate(); @@ -516,7 +516,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', ); svc.regenerate(); @@ -543,7 +543,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', { onSkipped, onWritten }, ); const result = svc.regenerate(); @@ -575,7 +575,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', { onSkipped }, ); const result = svc.regenerate(); @@ -598,7 +598,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', { onSkipped }, ); const result = svc.regenerate(); @@ -628,7 +628,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', { isFileDirtyInEditor, onSkipped, onWritten }, ); const before = fs.readFileSync(path.join(tmpDir, 'selectors.yml'), 'utf-8'); @@ -660,7 +660,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', { isFileDirtyInEditor, onSkipped, onWritten }, ); const result = svc.regenerate(); @@ -678,7 +678,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', { onSkipped, onWritten }, ); svc.regenerate(); @@ -700,7 +700,7 @@ describe('SelectorsService', () => { { domain: 'd', layer: 'silver', filePath: '/x/silver/d.json', models: ['dim_d'] }, ]), tmpDir, - 'erd-studio', + '.erd-studio', { onSkipped, onWritten }, ); diff --git a/webview/components/AddExistingModelDialog/AddExistingModelDialog.tsx b/webview/components/AddExistingModelDialog/AddExistingModelDialog.tsx index 80f3fc2..3a7d94b 100644 --- a/webview/components/AddExistingModelDialog/AddExistingModelDialog.tsx +++ b/webview/components/AddExistingModelDialog/AddExistingModelDialog.tsx @@ -2,7 +2,7 @@ * AddExistingModelDialog — dialog for adding existing models to a domain. * * Displays a searchable, filterable list of models from three sources: - * - Library: models with YAML definitions in erd-studio/logical-models/ + * - Library: models with YAML definitions in .erd-studio/logical-models/ * - dbt: models defined in dbt .yml schema files * - Compiled: models only in compiled manifest (no .yml file) * @@ -158,7 +158,7 @@ export function AddExistingModelDialog() { ) : ( <> - Add .yml schema files to your dbt project, create models in erd-studio/logical-models/, or run dbt compile. + Add .yml schema files to your dbt project, create models in .erd-studio/logical-models/, or run dbt compile. )}