your-ai-workflow-firebase-os 1.2.53 → 1.2.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/vite.cjs.js CHANGED
@@ -173,4 +173,4 @@ if (typeof window !== 'undefined') {
173
173
  export const pagesRegistry = pages;
174
174
  export const formsRegistry = forms;
175
175
  export const microcomponentRegistry = microcomponents;
176
- `}var ne=e=>D(S(e)),O=e=>e.split(`/`).pop()||e,k=e=>/\/configs\/[^/]+$/.test(e),A=e=>/\/microcomponents\/[^/]+\.tsx$/.test(e),j=e=>e.replace(/\/\*[\s\S]*?\*\//g,``).replace(/(^|[^:\\'"`])\/\/.*$/gm,`$1`),M=(e,t)=>{let n=RegExp(`(?:^|[\\s,{])${t}\\s*:\\s*([^,\\n}]+)`,`g`),r=[],i;for(;i=n.exec(e);)r.push(i[1].trim());return r},N=e=>{let t=e.match(/^(['"`])([^'"`]*)\1$/);return t?t[2]:null},P=e=>/export\s+(?:const|let|var|function|class)\s+\w*Config\b/.test(e)||/export\s*\{[^}]*\b\w*Config\b[^}]*\}/.test(e),F=e=>/export\s+default\b/.test(e),I=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,`_`).replace(/^_|_$/g,``),L=[`board`,`table`,`calendar`,`drive`],R={board:{call:`actions.openInlineEditor(categoryId)`,token:`openInlineEditor`},table:{call:`actions.addRow()`,token:`addRow`},calendar:{call:`actions.openAddModal()`,token:`openAddModal`},drive:{call:`the openUploadModal() prop`,token:`openUploadModal`}},z=/(?:copy (?:this|the sentence|it) (?:in)?to|paste (?:this|it) (?:in)?to|copy for (?:your |the )?(?:ai|assistant)|ask your assistant|your assistant.{0,3}s chat|copy this to change)[^\n]{0,40}/i,B=e=>{let t=M(e,`route`);return{first:t[0],count:t.length}};function V(e){let t=[],n=[],r=new Map,i=new Set;for(let{file:t}of e)if(A(t))for(let e of g(O(t)))i.add(e);let a=new Map;for(let{file:t,source:n}of e){if(!k(t))continue;let e=O(t),r=v(e);if(r!==`tab`&&r!==`page`)continue;let i=j(n),o=M(i,`template`)[0],s=o===void 0?null:N(o);if(!s||!L.includes(s))continue;let c=M(i,r===`tab`?`tabName`:`pageName`)[0],l=c===void 0?null:N(c),u=[r===`tab`?p(e):m(e),...l?[I(l),I(l).replace(/_/g,``)]:[]];for(let e of u)a.set(e,s)}for(let{file:o,source:s}of e){let e=O(o),c=j(s);if(k(o)){let n=v(e);if(n===`shipped`)continue;if(n===`other`){t.push(`${o}: rename it to somethingTab.config.ts (a dashboard page), somethingPage.config.ts (a page for anyone) or somethingForm.config.ts (a form).`);continue}if(!P(c)&&!F(c)&&t.push(`${o}: export one const named ${_(e)}Config.`),n===`tab`||n===`page`){let{first:a,count:s}=B(c),l=a===void 0?null:N(a);if(s===0||l===null||!l.startsWith(`/`))t.push(`${o}: route must be one string starting with /, e.g. route: '/onboarding'. A page has exactly one web address.`);else{let e=r.get(l);e?t.push(`${o}: route '${l}' is already used by ${e}. One page, one file, one address.`):r.set(l,o)}let u=M(c,`template`)[0],d=u===void 0?null:N(u);if(!d||![`board`,`table`,`calendar`,`drive`,`inline_form`,`popup_form`].includes(d)){let r=n===`tab`?p(e):m(e),a=M(c,n===`tab`?`tabName`:`pageName`)[0],s=a===void 0?null:N(a),l=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,`_`).replace(/^_|_$/g,``);if(![r,...s?[l(s),l(s).replace(/_/g,``)]:[]].some(e=>i.has(e))){let n=_(e).replace(/(Tab|Page)$/,``),r=(s||n).split(/[^a-zA-Z0-9]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``);t.push(`${o}: no content file matches this page, so it renders empty — create src/your-ai-workflow-firebase-os/microcomponents/${r}Content.tsx with export default.`)}}}if(n===`tab`){let e=M(c,`pageType`)[0],n=e===void 0?null:N(e);n!==`user`&&n!==`internal`&&n!==`admin`&&t.push(`${o}: pageType must be 'user', 'internal' or 'admin'. A dashboard page is never public.`)}if(n===`form`){let n=h(e),r=M(c,`systemName`)[0];r!==void 0&&N(r)!==n&&t.push(`${o}: systemName must be '${n}'.`)}continue}if(A(o)){F(c)||t.push(`${o}: add export default.`);let r=g(e).map(e=>a.get(e)).find(Boolean),i=/<form\b/.test(c)||/\bonSubmit\b/.test(c);if(i&&r){let e=R[r];c.includes(e.token)||n.push(`${o}: this page is a ${r} and already has its own add and edit dialog, themed for light and dark — open it with ${e.call} instead of building a form here.`)}else i&&!/ContactPopup/.test(c)&&n.push(`${o}: forms are *Form.config.ts files shown with <ContactPopup formId="…" />; a hand-written form never reaches the Inbox.`);/<style[\s>]/.test(c)&&t.push(`${o}: a <style> tag is global CSS and restyles every page of the app — delete it and style with theme classes (bg-background, text-foreground, glass-panel, btn-primary).`);let s=c.match(/(?<![\w-])(?:h|max-h)-(?:screen|dvh|svh|lvh|\[(?:100|9\d|8\d)(?:vh|dvh|svh|lvh)\])/);s&&n.push(`${o}: ${s[0]} makes the page exactly one screen tall and strands everything below it on a phone — the page is already inside a panel that scrolls, so let it be as long as it needs and drop the height and any overflow-hidden around it.`);let l=c.match(z);l&&n.push(`${o}: "${l[0]}" is wording off the owner's admin screens — the page is for its visitors, not for the owner or for you. Delete it and any prompt or copy-this box on the page.`);let u=c.match(/\b(?:bg-(?:white|black)|(?:bg|text|border)-(?:gray|slate|zinc|neutral|stone)-\d+)\b/);u&&n.push(`${o}: ${u[0]} is a hard-coded colour that ignores the owner's theme and stays wrong in light or dark mode — use bg-background, text-foreground, border-[var(--panel-border)], glass-panel or btn-primary.`)}}return{errors:t,warnings:n}}var H=(e,t)=>{let n=[],r=t.replace(/\/\*[\s\S]*?\*\//g,``);for(let[,t,i]of r.matchAll(/([^{}]+)\{([^{}]*)\}/g)){let r=t.trim(),a=/(?:^|[\s;])(?:font-size|line-height|font)\s*:/.test(i);if(/\.page-title\b/.test(r)){n.push(`${e}: the rule for \`${r.replace(/\s+/g,` `)}\` styles the app's page title, which is the library's chrome and not this file's to restyle — delete the rule; a page heading you want to size is one you write yourself inside a content file.`);continue}if(/(?:^|[\s;])font-family\s*:/.test(i)){n.push(`${e}: the rule for \`${r.replace(/\s+/g,` `)}\` sets a \`font-family\`, and the app has one typeface — Inter, everywhere, with no setting for it. Delete the \`font-family\` line; the rest of the rule can stay.`);continue}let o=r.split(`,`).map(e=>e.trim()).filter(e=>/^h[1-3]$/.test(e));o.length&&a&&n.push(`${e}: this rule sets a size on \`${o.join(`, `)}\`, which changes every page title in the app — delete the size (font-weight here is fine) and size the headings you write inside your own content file instead.`)}return n},U=[`panelBg`,`panelBorder`,`buttonGradient`,`buttonHoverGradient`,`secondaryButton`,`glowColor`,`notificationIconColor`,`textGradient`,`selectionBg`,`selectionText`],re=(e,t)=>{let n=j(t),r=U.filter(e=>RegExp(`(?:^|[\\s,{])${e}\\s*:`).test(n));return r.length===0?[]:[`${e}: ${r.join(`, `)} ${r.length===1?`is`:`are`} ignored — the app derives every other colour from background, backgroundSecondary, foreground, accent and buttonText, so delete ${r.length===1?`that key`:`those keys`} and put the owner's colours into those five; never copy gradient or panel colours from another theme.`]};function W(e,t){return V(e.map(e=>({file:e.file,source:t(e.abs)})))}var G=i,K=`\0`+G,q=[{rel:`src/App.tsx`,source:a},{rel:`src/main.tsx`,source:s}],J=e=>`${e} is owned by Your AI Firebase; your edit was discarded.`,ie=e=>e.replace(/[?#].*$/,``),Y=e=>n.normalize(e).split(n.sep).join(`/`),X={info:e=>console.log(e),warn:e=>console.warn(e),error:e=>console.error(e)};function Z(e,r=X){let i=[];for(let{rel:a,source:o}of q){let s=n.join(e,a),c=null;try{c=t.readFileSync(s,`utf8`)}catch{c=null}c!==o&&(t.mkdirSync(n.dirname(s),{recursive:!0}),t.writeFileSync(s,o),i.push(a),c!==null&&r.warn(J(a)))}return i}function Q(e){let r=n.join(e,u,`registry.ts`);return t.existsSync(r)?!1:(t.mkdirSync(n.dirname(r),{recursive:!0}),t.writeFileSync(r,o),!0)}var $=(e,t)=>{let r=Y(ie(t));for(let{rel:t,source:i}of q)if(r===Y(n.join(e,t)))return i;return null};function ae(){let e=process.cwd(),r=!1,i=`build`,a=X,o=()=>{let r=W(S(e),e=>t.readFileSync(e,`utf8`)),i=n.join(e,`src`,`your-ai-workflow-firebase-os`,`theme.css`),a=t.existsSync(i)?H(`src/your-ai-workflow-firebase-os/theme.css`,t.readFileSync(i,`utf8`)):[],o=n.join(e,`src`,`your-ai-workflow-firebase-os`,`configs`,`theme.config.ts`),s=t.existsSync(o)?re(`src/your-ai-workflow-firebase-os/configs/theme.config.ts`,t.readFileSync(o,`utf8`)):[];return{errors:[...r.errors,...te(e),...a],warnings:[...r.warnings,...s]}};return{name:`your-ai-firebase`,enforce:`pre`,config:()=>({resolve:{dedupe:[`firebase`,`react`,`react-dom`,`react-router-dom`]}}),configResolved(t){e=t.root,i=t.command,a=t.logger,r=b(e),r&&(Z(e,a),Q(e))},resolveId(e){return e===G?K:null},buildStart(){if(!r)return;let{errors:e,warnings:t}=o();for(let e of t)this.warn(e);if(e.length!==0)if(i===`build`)this.error(e[0]);else for(let t of e)a.error(t)},load(t){if(!r)return null;if(t===K){let t=S(e),{errors:n}=o();return n.length&&this.error(n[0]),D(t)}return $(e,t)},configureServer(t){if(!r)return;let n=()=>{let e=t.moduleGraph.getModuleById(K);e&&t.moduleGraph.invalidateModule(e),t.ws.send({type:`full-reload`,path:`*`})},i=r=>{let i=Y(r);if($(e,i)!==null){Z(e,t.config.logger);return}if(!x(e,i)&&!T(i))return;n();let{errors:a,warnings:s}=o();for(let e of s)t.config.logger.warn(e);for(let e of a)t.config.logger.error(e)};t.watcher.on(`add`,i),t.watcher.on(`unlink`,i),t.watcher.on(`change`,i)}}}exports.CANONICAL_APP_TSX=a,exports.CANONICAL_MAIN_TSX=s,exports.CONFIGS_DIR=l,exports.CONSUMER_DIR=c,exports.CONSUMER_REGISTRY_TS=o,exports.MICROCOMPONENTS_DIR=u,exports.OWNED_BANNER=r,exports.RESOLVED_VIRTUAL_ID=K,exports.SHIPPED_CONFIG_FILES=d,exports.VIRTUAL_ID=G,exports.VIRTUAL_REGISTRIES_ID=i,exports.classifyConfigFile=v,exports.discover=S,exports.ensureConsumerRegistry=Q,exports.fileIdFromConfigFile=_,exports.formIdFromFile=h,exports.isConsumerRoot=b,exports.isDiscoveredPath=x,exports.microcomponentKeysFromFile=g,exports.ownedMessage=J,exports.pageIdFromFile=m,exports.registrable=C,exports.restoreOwnedFiles=Z,exports.stripComments=j,exports.tabIdFromFile=p,exports.validate=V,exports.validateDiscovered=W,exports.virtualModuleSource=ne,exports.virtualModuleSourceFor=D,exports.yourAiFirebase=ae;
176
+ `}var ne=e=>D(S(e)),O=e=>e.split(`/`).pop()||e,k=e=>/\/configs\/[^/]+$/.test(e),A=e=>/\/microcomponents\/[^/]+\.tsx$/.test(e),j=e=>e.replace(/\/\*[\s\S]*?\*\//g,``).replace(/(^|[^:\\'"`])\/\/.*$/gm,`$1`),M=(e,t)=>{let n=RegExp(`(?:^|[\\s,{])${t}\\s*:\\s*([^,\\n}]+)`,`g`),r=[],i;for(;i=n.exec(e);)r.push(i[1].trim());return r},N=e=>{let t=e.match(/^(['"`])([^'"`]*)\1$/);return t?t[2]:null},P=e=>/export\s+(?:const|let|var|function|class)\s+\w*Config\b/.test(e)||/export\s*\{[^}]*\b\w*Config\b[^}]*\}/.test(e),F=e=>/export\s+default\b/.test(e),I=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,`_`).replace(/^_|_$/g,``),L=[`board`,`table`,`calendar`,`drive`],R={board:{call:`actions.openInlineEditor(categoryId)`,token:`openInlineEditor`},table:{call:`actions.addRow()`,token:`addRow`},calendar:{call:`actions.openAddModal()`,token:`openAddModal`},drive:{call:`the openUploadModal() prop`,token:`openUploadModal`}},z=/(?:copy (?:this|the sentence|it) (?:in)?to|paste (?:this|it) (?:in)?to|copy for (?:your |the )?(?:ai|assistant)|ask your assistant|your assistant.{0,3}s chat|copy this to change)[^\n]{0,40}/i,B=e=>{let t=M(e,`route`);return{first:t[0],count:t.length}};function V(e){let t=[],n=[],r=new Map,i=new Set;for(let{file:t}of e)if(A(t))for(let e of g(O(t)))i.add(e);let a=new Map;for(let{file:t,source:n}of e){if(!k(t))continue;let e=O(t),r=v(e);if(r!==`tab`&&r!==`page`)continue;let i=j(n),o=M(i,`template`)[0],s=o===void 0?null:N(o);if(!s||!L.includes(s))continue;let c=M(i,r===`tab`?`tabName`:`pageName`)[0],l=c===void 0?null:N(c),u=[r===`tab`?p(e):m(e),...l?[I(l),I(l).replace(/_/g,``)]:[]];for(let e of u)a.set(e,s)}for(let{file:o,source:s}of e){let e=O(o),c=j(s);if(k(o)){let n=v(e);if(n===`shipped`)continue;if(n===`other`){t.push(`${o}: rename it to somethingTab.config.ts (a dashboard page), somethingPage.config.ts (a page for anyone) or somethingForm.config.ts (a form).`);continue}if(!P(c)&&!F(c)&&t.push(`${o}: export one const named ${_(e)}Config.`),n===`tab`||n===`page`){let{first:a,count:s}=B(c),l=a===void 0?null:N(a);if(s===0||l===null||!l.startsWith(`/`))t.push(`${o}: route must be one string starting with /, e.g. route: '/onboarding'. A page has exactly one web address.`);else{let e=r.get(l);e?t.push(`${o}: route '${l}' is already used by ${e}. One page, one file, one address.`):r.set(l,o)}let u=M(c,`template`)[0],d=u===void 0?null:N(u);if(!d||![`board`,`table`,`calendar`,`drive`,`inline_form`,`popup_form`].includes(d)){let r=n===`tab`?p(e):m(e),a=M(c,n===`tab`?`tabName`:`pageName`)[0],s=a===void 0?null:N(a),l=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,`_`).replace(/^_|_$/g,``);if(![r,...s?[l(s),l(s).replace(/_/g,``)]:[]].some(e=>i.has(e))){let n=_(e).replace(/(Tab|Page)$/,``),r=(s||n).split(/[^a-zA-Z0-9]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``);t.push(`${o}: no content file matches this page, so it renders empty — create src/your-ai-workflow-firebase-os/microcomponents/${r}Content.tsx with export default.`)}}}if(n===`tab`){let e=M(c,`pageType`)[0],n=e===void 0?null:N(e);n!==`user`&&n!==`internal`&&n!==`admin`&&t.push(`${o}: pageType must be 'user', 'internal' or 'admin'. A dashboard page is never public.`)}if(n===`form`){let n=h(e),r=M(c,`systemName`)[0];r!==void 0&&N(r)!==n&&t.push(`${o}: systemName must be '${n}'.`)}continue}if(A(o)){F(c)||t.push(`${o}: add export default.`);let r=g(e).map(e=>a.get(e)).find(Boolean),i=/<form\b/.test(c)||/\bonSubmit\b/.test(c);if(i&&r){let e=R[r];c.includes(e.token)||n.push(`${o}: this page is a ${r} and already has its own add and edit dialog, themed for light and dark — open it with ${e.call} instead of building a form here.`)}else i&&!/ContactPopup/.test(c)&&n.push(`${o}: forms are *Form.config.ts files shown with <ContactPopup formId="…" />; a hand-written form never reaches the Inbox.`);/<style[\s>]/.test(c)&&t.push(`${o}: a <style> tag is global CSS and restyles every page of the app — delete it and style with theme classes (bg-background, text-foreground, glass-panel, btn-primary).`);let s=c.match(/(?<![\w-])(?:h|max-h)-(?:screen|dvh|svh|lvh|\[(?:100|9\d|8\d)(?:vh|dvh|svh|lvh)\])/);s&&n.push(`${o}: ${s[0]} makes the page exactly one screen tall and strands everything below it on a phone — the page is already inside a panel that scrolls, so let it be as long as it needs and drop the height and any overflow-hidden around it.`);let l=c.match(z);l&&n.push(`${o}: "${l[0]}" is wording off the owner's admin screens — the page is for its visitors, not for the owner or for you. Delete it and any prompt or copy-this box on the page.`);let u=c.match(/\b(?:bg-(?:white|black)|(?:bg|text|border)-(?:gray|slate|zinc|neutral|stone)-\d+)\b/);u&&n.push(`${o}: ${u[0]} is a hard-coded colour that ignores the owner's theme and stays wrong in light or dark mode — use bg-background, text-foreground, border-[var(--panel-border)], glass-panel or btn-primary.`)}}return{errors:t,warnings:n}}var H=[`--bg-color`,`--bg-secondary-color`,`--fg-color`,`--accent-color`,`--panel-bg`,`--panel-border`,`--button-bg`,`--button-fg`,`--button-hover-bg`,`--btn-sec-bg`,`--btn-sec-border`,`--btn-sec-text`,`--text-gradient`,`--glow-color`,`--notification-icon-color`,`--selection-bg`,`--selection-text`],U=(e,t)=>{let n=[],r=t.replace(/\/\*[\s\S]*?\*\//g,``);for(let[,t,i]of r.matchAll(/([^{}]+)\{([^{}]*)\}/g)){let r=t.trim(),a=H.filter(e=>RegExp(`${e}\\s*:[^;}]*!important`).test(i));if(a.length){n.push(`${e}: \`${a[0]}\` is set with \`!important\` here, and the app writes that colour itself from the owner's theme — forcing it freezes it, so their Theme screen stops working. Delete the \`!important\` and set the colour in configs/theme.config.ts instead, in background, backgroundSecondary, foreground, accent or buttonText; every other colour is derived from those five.`);continue}let o=/(?:^|[\s;])(?:font-size|line-height|font)\s*:/.test(i);if(/\.page-title\b/.test(r)){n.push(`${e}: the rule for \`${r.replace(/\s+/g,` `)}\` styles the app's page title, which is the library's chrome and not this file's to restyle — delete the rule; a page heading you want to size is one you write yourself inside a content file.`);continue}let s=i.match(/(?:^|[\s;])font-family\s*:\s*([^;}]+)/);if(s&&!/^\s*['"]?Inter['"]?\s*(?:,|$)/i.test(s[1])){n.push(`${e}: the rule for \`${r.replace(/\s+/g,` `)}\` sets a \`font-family\`, and the app has one typeface — Inter, everywhere, with no setting for it. Delete the \`font-family\` line; the rest of the rule can stay.`);continue}let c=r.split(`,`).map(e=>e.trim()).filter(e=>/^h[1-3]$/.test(e));c.length&&o&&n.push(`${e}: this rule sets a size on \`${c.join(`, `)}\`, which changes every page title in the app — delete the size (font-weight here is fine) and size the headings you write inside your own content file instead.`)}return n},re=[`panelBg`,`panelBorder`,`buttonGradient`,`buttonHoverGradient`,`secondaryButton`,`glowColor`,`notificationIconColor`,`textGradient`,`selectionBg`,`selectionText`],ie=(e,t)=>{let n=j(t),r=re.filter(e=>RegExp(`(?:^|[\\s,{])${e}\\s*:`).test(n));return r.length===0?[]:[`${e}: ${r.join(`, `)} ${r.length===1?`is`:`are`} ignored — the app derives every other colour from background, backgroundSecondary, foreground, accent and buttonText, so delete ${r.length===1?`that key`:`those keys`} and put the owner's colours into those five; never copy gradient or panel colours from another theme.`]};function W(e,t){return V(e.map(e=>({file:e.file,source:t(e.abs)})))}var G=i,K=`\0`+G,q=[{rel:`src/App.tsx`,source:a},{rel:`src/main.tsx`,source:s}],J=e=>`${e} is owned by Your AI Firebase; your edit was discarded.`,ae=e=>e.replace(/[?#].*$/,``),Y=e=>n.normalize(e).split(n.sep).join(`/`),X={info:e=>console.log(e),warn:e=>console.warn(e),error:e=>console.error(e)};function Z(e,r=X){let i=[];for(let{rel:a,source:o}of q){let s=n.join(e,a),c=null;try{c=t.readFileSync(s,`utf8`)}catch{c=null}c!==o&&(t.mkdirSync(n.dirname(s),{recursive:!0}),t.writeFileSync(s,o),i.push(a),c!==null&&r.warn(J(a)))}return i}function Q(e){let r=n.join(e,u,`registry.ts`);return t.existsSync(r)?!1:(t.mkdirSync(n.dirname(r),{recursive:!0}),t.writeFileSync(r,o),!0)}var $=(e,t)=>{let r=Y(ae(t));for(let{rel:t,source:i}of q)if(r===Y(n.join(e,t)))return i;return null};function oe(){let e=process.cwd(),r=!1,i=`build`,a=X,o=()=>{let r=W(S(e),e=>t.readFileSync(e,`utf8`)),i=n.join(e,`src`,`your-ai-workflow-firebase-os`,`theme.css`),a=t.existsSync(i)?U(`src/your-ai-workflow-firebase-os/theme.css`,t.readFileSync(i,`utf8`)):[],o=n.join(e,`src`,`your-ai-workflow-firebase-os`,`configs`,`theme.config.ts`),s=t.existsSync(o)?ie(`src/your-ai-workflow-firebase-os/configs/theme.config.ts`,t.readFileSync(o,`utf8`)):[];return{errors:[...r.errors,...te(e),...a],warnings:[...r.warnings,...s]}};return{name:`your-ai-firebase`,enforce:`pre`,config:()=>({resolve:{dedupe:[`firebase`,`react`,`react-dom`,`react-router-dom`]}}),configResolved(t){e=t.root,i=t.command,a=t.logger,r=b(e),r&&(Z(e,a),Q(e))},resolveId(e){return e===G?K:null},buildStart(){if(!r)return;let{errors:e,warnings:t}=o();for(let e of t)this.warn(e);if(e.length!==0)if(i===`build`)this.error(e[0]);else for(let t of e)a.error(t)},load(t){if(!r)return null;if(t===K){let t=S(e),{errors:n}=o();return n.length&&this.error(n[0]),D(t)}return $(e,t)},configureServer(t){if(!r)return;let n=()=>{let e=t.moduleGraph.getModuleById(K);e&&t.moduleGraph.invalidateModule(e),t.ws.send({type:`full-reload`,path:`*`})},i=r=>{let i=Y(r);if($(e,i)!==null){Z(e,t.config.logger);return}if(!x(e,i)&&!T(i))return;n();let{errors:a,warnings:s}=o();for(let e of s)t.config.logger.warn(e);for(let e of a)t.config.logger.error(e)};t.watcher.on(`add`,i),t.watcher.on(`unlink`,i),t.watcher.on(`change`,i)}}}exports.CANONICAL_APP_TSX=a,exports.CANONICAL_MAIN_TSX=s,exports.CONFIGS_DIR=l,exports.CONSUMER_DIR=c,exports.CONSUMER_REGISTRY_TS=o,exports.MICROCOMPONENTS_DIR=u,exports.OWNED_BANNER=r,exports.RESOLVED_VIRTUAL_ID=K,exports.SHIPPED_CONFIG_FILES=d,exports.VIRTUAL_ID=G,exports.VIRTUAL_REGISTRIES_ID=i,exports.classifyConfigFile=v,exports.discover=S,exports.ensureConsumerRegistry=Q,exports.fileIdFromConfigFile=_,exports.formIdFromFile=h,exports.isConsumerRoot=b,exports.isDiscoveredPath=x,exports.microcomponentKeysFromFile=g,exports.ownedMessage=J,exports.pageIdFromFile=m,exports.registrable=C,exports.restoreOwnedFiles=Z,exports.stripComments=j,exports.tabIdFromFile=p,exports.validate=V,exports.validateDiscovered=W,exports.virtualModuleSource=ne,exports.virtualModuleSourceFor=D,exports.yourAiFirebase=oe;
package/dist/vite.es.js CHANGED
@@ -146,7 +146,7 @@ var S = (e) => e.filter((e) => e.kind !== "other"), C = [{
146
146
  "dist",
147
147
  "build"
148
148
  ]);
149
- function T(n) {
149
+ function ee(n) {
150
150
  let r = [], i = t.join(n, "src"), a = (i, o) => {
151
151
  if (!(o > 6 || !e.existsSync(i))) for (let s of e.readdirSync(i, { withFileTypes: !0 })) {
152
152
  let e = t.join(i, s.name), u = d(t.relative(n, e));
@@ -164,18 +164,18 @@ function T(n) {
164
164
  };
165
165
  return a(i, 0), r.sort();
166
166
  }
167
- var E = (e) => {
167
+ var te = (e) => {
168
168
  let n = t.basename(e);
169
169
  return C.some((e) => e.test(n));
170
- }, D = (e) => JSON.stringify(e);
171
- function O(e) {
170
+ }, T = (e) => JSON.stringify(e);
171
+ function E(e) {
172
172
  let t = [], n = [], r = [], i = [];
173
173
  return S(e).forEach((e, a) => {
174
174
  let o = `m${a}`;
175
- if (t.push(`import * as ${o} from ${D(d(e.abs))};`), e.kind === "tab") n.push(`{
175
+ if (t.push(`import * as ${o} from ${T(d(e.abs))};`), e.kind === "tab") n.push(`{
176
176
  const configVal = pickConfig(${o});
177
177
  if (configVal) {
178
- const tabId = ${D(e.id)};
178
+ const tabId = ${T(e.id)};
179
179
  const finalTab = {
180
180
  config: {
181
181
  ...configVal,
@@ -194,7 +194,7 @@ function O(e) {
194
194
  else if (e.kind === "page") n.push(`{
195
195
  const configVal = pickConfig(${o});
196
196
  if (configVal) {
197
- const pageId = ${D(e.id)};
197
+ const pageId = ${T(e.id)};
198
198
  const finalPage = {
199
199
  config: {
200
200
  ...configVal,
@@ -213,7 +213,7 @@ function O(e) {
213
213
  else if (e.kind === "form") r.push(`{
214
214
  const configVal = pickConfig(${o});
215
215
  if (configVal) {
216
- const formId = ${D(e.id)};
216
+ const formId = ${T(e.id)};
217
217
  // The form's id is its file name; systemName always follows the file.
218
218
  const finalConfig = { ...configVal, systemName: formId };
219
219
  forms[formId] = finalConfig;
@@ -224,11 +224,11 @@ function O(e) {
224
224
  else if (e.kind === "microcomponent") {
225
225
  let [t, n] = h(e.name);
226
226
  i.push(`if (${o} && ${o}.default) {
227
- microcomponents[${D(t)}] = ${o}.default;
227
+ microcomponents[${T(t)}] = ${o}.default;
228
228
  // Also answer to the squashed form ("mobile_apps" -> "mobileapps"): a page id
229
229
  // derived from a file name (mobileAppsPage.config.ts -> "mobileapps") has no
230
230
  // underscores, and the page must still find MobileAppsContent.tsx.
231
- microcomponents[${D(n)}] = ${o}.default;
231
+ microcomponents[${T(n)}] = ${o}.default;
232
232
  }`);
233
233
  }
234
234
  }), `// Generated by Your AI Firebase from the files in ${s}/.
@@ -269,19 +269,19 @@ export const formsRegistry = forms;
269
269
  export const microcomponentRegistry = microcomponents;
270
270
  `;
271
271
  }
272
- var ee = (e) => O(x(e)), k = (e) => e.split("/").pop() || e, A = (e) => /\/configs\/[^/]+$/.test(e), j = (e) => /\/microcomponents\/[^/]+\.tsx$/.test(e), M = (e) => e.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:\\'"`])\/\/.*$/gm, "$1"), N = (e, t) => {
272
+ var ne = (e) => E(x(e)), D = (e) => e.split("/").pop() || e, O = (e) => /\/configs\/[^/]+$/.test(e), k = (e) => /\/microcomponents\/[^/]+\.tsx$/.test(e), A = (e) => e.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:\\'"`])\/\/.*$/gm, "$1"), j = (e, t) => {
273
273
  let n = RegExp(`(?:^|[\\s,{])${t}\\s*:\\s*([^,\\n}]+)`, "g"), r = [], i;
274
274
  for (; i = n.exec(e);) r.push(i[1].trim());
275
275
  return r;
276
- }, P = (e) => {
276
+ }, M = (e) => {
277
277
  let t = e.match(/^(['"`])([^'"`]*)\1$/);
278
278
  return t ? t[2] : null;
279
- }, F = (e) => /export\s+(?:const|let|var|function|class)\s+\w*Config\b/.test(e) || /export\s*\{[^}]*\b\w*Config\b[^}]*\}/.test(e), I = (e) => /export\s+default\b/.test(e), L = (e) => e.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, ""), R = [
279
+ }, N = (e) => /export\s+(?:const|let|var|function|class)\s+\w*Config\b/.test(e) || /export\s*\{[^}]*\b\w*Config\b[^}]*\}/.test(e), P = (e) => /export\s+default\b/.test(e), F = (e) => e.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, ""), I = [
280
280
  "board",
281
281
  "table",
282
282
  "calendar",
283
283
  "drive"
284
- ], z = {
284
+ ], L = {
285
285
  board: {
286
286
  call: "actions.openInlineEditor(categoryId)",
287
287
  token: "openInlineEditor"
@@ -298,43 +298,43 @@ var ee = (e) => O(x(e)), k = (e) => e.split("/").pop() || e, A = (e) => /\/confi
298
298
  call: "the openUploadModal() prop",
299
299
  token: "openUploadModal"
300
300
  }
301
- }, B = /(?:copy (?:this|the sentence|it) (?:in)?to|paste (?:this|it) (?:in)?to|copy for (?:your |the )?(?:ai|assistant)|ask your assistant|your assistant.{0,3}s chat|copy this to change)[^\n]{0,40}/i, V = (e) => {
302
- let t = N(e, "route");
301
+ }, R = /(?:copy (?:this|the sentence|it) (?:in)?to|paste (?:this|it) (?:in)?to|copy for (?:your |the )?(?:ai|assistant)|ask your assistant|your assistant.{0,3}s chat|copy this to change)[^\n]{0,40}/i, z = (e) => {
302
+ let t = j(e, "route");
303
303
  return {
304
304
  first: t[0],
305
305
  count: t.length
306
306
  };
307
307
  };
308
- function H(e) {
308
+ function B(e) {
309
309
  let t = [], n = [], r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Set();
310
- for (let { file: t } of e) if (j(t)) for (let e of h(k(t))) i.add(e);
310
+ for (let { file: t } of e) if (k(t)) for (let e of h(D(t))) i.add(e);
311
311
  let a = /* @__PURE__ */ new Map();
312
312
  for (let { file: t, source: n } of e) {
313
- if (!A(t)) continue;
314
- let e = k(t), r = _(e);
313
+ if (!O(t)) continue;
314
+ let e = D(t), r = _(e);
315
315
  if (r !== "tab" && r !== "page") continue;
316
- let i = M(n), o = N(i, "template")[0], s = o === void 0 ? null : P(o);
317
- if (!s || !R.includes(s)) continue;
318
- let c = N(i, r === "tab" ? "tabName" : "pageName")[0], l = c === void 0 ? null : P(c), u = [r === "tab" ? f(e) : p(e), ...l ? [L(l), L(l).replace(/_/g, "")] : []];
316
+ let i = A(n), o = j(i, "template")[0], s = o === void 0 ? null : M(o);
317
+ if (!s || !I.includes(s)) continue;
318
+ let c = j(i, r === "tab" ? "tabName" : "pageName")[0], l = c === void 0 ? null : M(c), u = [r === "tab" ? f(e) : p(e), ...l ? [F(l), F(l).replace(/_/g, "")] : []];
319
319
  for (let e of u) a.set(e, s);
320
320
  }
321
321
  for (let { file: o, source: s } of e) {
322
- let e = k(o), c = M(s);
323
- if (A(o)) {
322
+ let e = D(o), c = A(s);
323
+ if (O(o)) {
324
324
  let n = _(e);
325
325
  if (n === "shipped") continue;
326
326
  if (n === "other") {
327
327
  t.push(`${o}: rename it to somethingTab.config.ts (a dashboard page), somethingPage.config.ts (a page for anyone) or somethingForm.config.ts (a form).`);
328
328
  continue;
329
329
  }
330
- if (!F(c) && !I(c) && t.push(`${o}: export one const named ${g(e)}Config.`), n === "tab" || n === "page") {
331
- let { first: a, count: s } = V(c), l = a === void 0 ? null : P(a);
330
+ if (!N(c) && !P(c) && t.push(`${o}: export one const named ${g(e)}Config.`), n === "tab" || n === "page") {
331
+ let { first: a, count: s } = z(c), l = a === void 0 ? null : M(a);
332
332
  if (s === 0 || l === null || !l.startsWith("/")) t.push(`${o}: route must be one string starting with /, e.g. route: '/onboarding'. A page has exactly one web address.`);
333
333
  else {
334
334
  let e = r.get(l);
335
335
  e ? t.push(`${o}: route '${l}' is already used by ${e}. One page, one file, one address.`) : r.set(l, o);
336
336
  }
337
- let u = N(c, "template")[0], d = u === void 0 ? null : P(u);
337
+ let u = j(c, "template")[0], d = u === void 0 ? null : M(u);
338
338
  if (!d || ![
339
339
  "board",
340
340
  "table",
@@ -343,7 +343,7 @@ function H(e) {
343
343
  "inline_form",
344
344
  "popup_form"
345
345
  ].includes(d)) {
346
- let r = n === "tab" ? f(e) : p(e), a = N(c, n === "tab" ? "tabName" : "pageName")[0], s = a === void 0 ? null : P(a), l = (e) => e.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
346
+ let r = n === "tab" ? f(e) : p(e), a = j(c, n === "tab" ? "tabName" : "pageName")[0], s = a === void 0 ? null : M(a), l = (e) => e.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
347
347
  if (![r, ...s ? [l(s), l(s).replace(/_/g, "")] : []].some((e) => i.has(e))) {
348
348
  let n = g(e).replace(/(Tab|Page)$/, ""), r = (s || n).split(/[^a-zA-Z0-9]+/).filter(Boolean).map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join("");
349
349
  t.push(`${o}: no content file matches this page, so it renders empty — create src/your-ai-workflow-firebase-os/microcomponents/${r}Content.tsx with export default.`);
@@ -351,26 +351,26 @@ function H(e) {
351
351
  }
352
352
  }
353
353
  if (n === "tab") {
354
- let e = N(c, "pageType")[0], n = e === void 0 ? null : P(e);
354
+ let e = j(c, "pageType")[0], n = e === void 0 ? null : M(e);
355
355
  n !== "user" && n !== "internal" && n !== "admin" && t.push(`${o}: pageType must be 'user', 'internal' or 'admin'. A dashboard page is never public.`);
356
356
  }
357
357
  if (n === "form") {
358
- let n = m(e), r = N(c, "systemName")[0];
359
- r !== void 0 && P(r) !== n && t.push(`${o}: systemName must be '${n}'.`);
358
+ let n = m(e), r = j(c, "systemName")[0];
359
+ r !== void 0 && M(r) !== n && t.push(`${o}: systemName must be '${n}'.`);
360
360
  }
361
361
  continue;
362
362
  }
363
- if (j(o)) {
364
- I(c) || t.push(`${o}: add export default.`);
363
+ if (k(o)) {
364
+ P(c) || t.push(`${o}: add export default.`);
365
365
  let r = h(e).map((e) => a.get(e)).find(Boolean), i = /<form\b/.test(c) || /\bonSubmit\b/.test(c);
366
366
  if (i && r) {
367
- let e = z[r];
367
+ let e = L[r];
368
368
  c.includes(e.token) || n.push(`${o}: this page is a ${r} and already has its own add and edit dialog, themed for light and dark — open it with ${e.call} instead of building a form here.`);
369
369
  } else i && !/ContactPopup/.test(c) && n.push(`${o}: forms are *Form.config.ts files shown with <ContactPopup formId="…" />; a hand-written form never reaches the Inbox.`);
370
370
  /<style[\s>]/.test(c) && t.push(`${o}: a <style> tag is global CSS and restyles every page of the app — delete it and style with theme classes (bg-background, text-foreground, glass-panel, btn-primary).`);
371
371
  let s = c.match(/(?<![\w-])(?:h|max-h)-(?:screen|dvh|svh|lvh|\[(?:100|9\d|8\d)(?:vh|dvh|svh|lvh)\])/);
372
372
  s && n.push(`${o}: ${s[0]} makes the page exactly one screen tall and strands everything below it on a phone — the page is already inside a panel that scrolls, so let it be as long as it needs and drop the height and any overflow-hidden around it.`);
373
- let l = c.match(B);
373
+ let l = c.match(R);
374
374
  l && n.push(`${o}: "${l[0]}" is wording off the owner's admin screens — the page is for its visitors, not for the owner or for you. Delete it and any prompt or copy-this box on the page.`);
375
375
  let u = c.match(/\b(?:bg-(?:white|black)|(?:bg|text|border)-(?:gray|slate|zinc|neutral|stone)-\d+)\b/);
376
376
  u && n.push(`${o}: ${u[0]} is a hard-coded colour that ignores the owner's theme and stays wrong in light or dark mode — use bg-background, text-foreground, border-[var(--panel-border)], glass-panel or btn-primary.`);
@@ -381,23 +381,47 @@ function H(e) {
381
381
  warnings: n
382
382
  };
383
383
  }
384
- var U = (e, t) => {
384
+ var V = [
385
+ "--bg-color",
386
+ "--bg-secondary-color",
387
+ "--fg-color",
388
+ "--accent-color",
389
+ "--panel-bg",
390
+ "--panel-border",
391
+ "--button-bg",
392
+ "--button-fg",
393
+ "--button-hover-bg",
394
+ "--btn-sec-bg",
395
+ "--btn-sec-border",
396
+ "--btn-sec-text",
397
+ "--text-gradient",
398
+ "--glow-color",
399
+ "--notification-icon-color",
400
+ "--selection-bg",
401
+ "--selection-text"
402
+ ], H = (e, t) => {
385
403
  let n = [], r = t.replace(/\/\*[\s\S]*?\*\//g, "");
386
404
  for (let [, t, i] of r.matchAll(/([^{}]+)\{([^{}]*)\}/g)) {
387
- let r = t.trim(), a = /(?:^|[\s;])(?:font-size|line-height|font)\s*:/.test(i);
405
+ let r = t.trim(), a = V.filter((e) => RegExp(`${e}\\s*:[^;}]*!important`).test(i));
406
+ if (a.length) {
407
+ n.push(`${e}: \`${a[0]}\` is set with \`!important\` here, and the app writes that colour itself from the owner's theme — forcing it freezes it, so their Theme screen stops working. Delete the \`!important\` and set the colour in configs/theme.config.ts instead, in background, backgroundSecondary, foreground, accent or buttonText; every other colour is derived from those five.`);
408
+ continue;
409
+ }
410
+ let o = /(?:^|[\s;])(?:font-size|line-height|font)\s*:/.test(i);
388
411
  if (/\.page-title\b/.test(r)) {
389
412
  n.push(`${e}: the rule for \`${r.replace(/\s+/g, " ")}\` styles the app's page title, which is the library's chrome and not this file's to restyle — delete the rule; a page heading you want to size is one you write yourself inside a content file.`);
390
413
  continue;
391
414
  }
392
- if (/(?:^|[\s;])font-family\s*:/.test(i)) {
415
+ let s = i.match(/(?:^|[\s;])font-family\s*:\s*([^;}]+)/);
416
+ if (s && !/^\s*['"]?Inter['"]?\s*(?:,|$)/i.test(s[1])) {
393
417
  n.push(`${e}: the rule for \`${r.replace(/\s+/g, " ")}\` sets a \`font-family\`, and the app has one typeface — Inter, everywhere, with no setting for it. Delete the \`font-family\` line; the rest of the rule can stay.`);
394
418
  continue;
395
419
  }
396
- let o = r.split(",").map((e) => e.trim()).filter((e) => /^h[1-3]$/.test(e));
397
- o.length && a && n.push(`${e}: this rule sets a size on \`${o.join(", ")}\`, which changes every page title in the app — delete the size (font-weight here is fine) and size the headings you write inside your own content file instead.`);
420
+ let c = r.split(",").map((e) => e.trim()).filter((e) => /^h[1-3]$/.test(e));
421
+ c.length && o && n.push(`${e}: this rule sets a size on \`${c.join(", ")}\`, which changes every page title in the app — delete the size (font-weight here is fine) and size the headings you write inside your own content file instead.`);
398
422
  }
399
423
  return n;
400
- }, te = [
424
+ }, U = [
401
425
  "panelBg",
402
426
  "panelBorder",
403
427
  "buttonGradient",
@@ -408,12 +432,12 @@ var U = (e, t) => {
408
432
  "textGradient",
409
433
  "selectionBg",
410
434
  "selectionText"
411
- ], ne = (e, t) => {
412
- let n = M(t), r = te.filter((e) => RegExp(`(?:^|[\\s,{])${e}\\s*:`).test(n));
435
+ ], re = (e, t) => {
436
+ let n = A(t), r = U.filter((e) => RegExp(`(?:^|[\\s,{])${e}\\s*:`).test(n));
413
437
  return r.length === 0 ? [] : [`${e}: ${r.join(", ")} ${r.length === 1 ? "is" : "are"} ignored — the app derives every other colour from background, backgroundSecondary, foreground, accent and buttonText, so delete ${r.length === 1 ? "that key" : "those keys"} and put the owner's colours into those five; never copy gradient or panel colours from another theme.`];
414
438
  };
415
439
  function W(e, t) {
416
- return H(e.map((e) => ({
440
+ return B(e.map((e) => ({
417
441
  file: e.file,
418
442
  source: t(e.abs)
419
443
  })));
@@ -426,7 +450,7 @@ var G = r, K = "\0" + G, q = [{
426
450
  }, {
427
451
  rel: "src/main.tsx",
428
452
  source: o
429
- }], J = (e) => `${e} is owned by Your AI Firebase; your edit was discarded.`, re = (e) => e.replace(/[?#].*$/, ""), Y = (e) => t.normalize(e).split(t.sep).join("/"), X = {
453
+ }], J = (e) => `${e} is owned by Your AI Firebase; your edit was discarded.`, ie = (e) => e.replace(/[?#].*$/, ""), Y = (e) => t.normalize(e).split(t.sep).join("/"), X = {
430
454
  info: (e) => console.log(e),
431
455
  warn: (e) => console.warn(e),
432
456
  error: (e) => console.error(e)
@@ -449,17 +473,17 @@ function Q(n) {
449
473
  return e.existsSync(r) ? !1 : (e.mkdirSync(t.dirname(r), { recursive: !0 }), e.writeFileSync(r, a), !0);
450
474
  }
451
475
  var $ = (e, n) => {
452
- let r = Y(re(n));
476
+ let r = Y(ie(n));
453
477
  for (let { rel: n, source: i } of q) if (r === Y(t.join(e, n))) return i;
454
478
  return null;
455
479
  };
456
- function ie() {
480
+ function ae() {
457
481
  let n = process.cwd(), r = !1, i = "build", a = X, o = () => {
458
- let r = W(x(n), (t) => e.readFileSync(t, "utf8")), i = t.join(n, "src", "your-ai-workflow-firebase-os", "theme.css"), a = e.existsSync(i) ? U("src/your-ai-workflow-firebase-os/theme.css", e.readFileSync(i, "utf8")) : [], o = t.join(n, "src", "your-ai-workflow-firebase-os", "configs", "theme.config.ts"), s = e.existsSync(o) ? ne("src/your-ai-workflow-firebase-os/configs/theme.config.ts", e.readFileSync(o, "utf8")) : [];
482
+ let r = W(x(n), (t) => e.readFileSync(t, "utf8")), i = t.join(n, "src", "your-ai-workflow-firebase-os", "theme.css"), a = e.existsSync(i) ? H("src/your-ai-workflow-firebase-os/theme.css", e.readFileSync(i, "utf8")) : [], o = t.join(n, "src", "your-ai-workflow-firebase-os", "configs", "theme.config.ts"), s = e.existsSync(o) ? re("src/your-ai-workflow-firebase-os/configs/theme.config.ts", e.readFileSync(o, "utf8")) : [];
459
483
  return {
460
484
  errors: [
461
485
  ...r.errors,
462
- ...T(n),
486
+ ...ee(n),
463
487
  ...a
464
488
  ],
465
489
  warnings: [...r.warnings, ...s]
@@ -491,7 +515,7 @@ function ie() {
491
515
  if (!r) return null;
492
516
  if (e === K) {
493
517
  let e = x(n), { errors: t } = o();
494
- return t.length && this.error(t[0]), O(e);
518
+ return t.length && this.error(t[0]), E(e);
495
519
  }
496
520
  return $(n, e);
497
521
  },
@@ -509,7 +533,7 @@ function ie() {
509
533
  Z(n, e.config.logger);
510
534
  return;
511
535
  }
512
- if (!b(n, i) && !E(i)) return;
536
+ if (!b(n, i) && !te(i)) return;
513
537
  t();
514
538
  let { errors: a, warnings: s } = o();
515
539
  for (let t of s) e.config.logger.warn(t);
@@ -520,4 +544,4 @@ function ie() {
520
544
  };
521
545
  }
522
546
  //#endregion
523
- export { i as CANONICAL_APP_TSX, o as CANONICAL_MAIN_TSX, c as CONFIGS_DIR, s as CONSUMER_DIR, a as CONSUMER_REGISTRY_TS, l as MICROCOMPONENTS_DIR, n as OWNED_BANNER, K as RESOLVED_VIRTUAL_ID, u as SHIPPED_CONFIG_FILES, G as VIRTUAL_ID, r as VIRTUAL_REGISTRIES_ID, _ as classifyConfigFile, x as discover, Q as ensureConsumerRegistry, g as fileIdFromConfigFile, m as formIdFromFile, y as isConsumerRoot, b as isDiscoveredPath, h as microcomponentKeysFromFile, J as ownedMessage, p as pageIdFromFile, S as registrable, Z as restoreOwnedFiles, M as stripComments, f as tabIdFromFile, H as validate, W as validateDiscovered, ee as virtualModuleSource, O as virtualModuleSourceFor, ie as yourAiFirebase };
547
+ export { i as CANONICAL_APP_TSX, o as CANONICAL_MAIN_TSX, c as CONFIGS_DIR, s as CONSUMER_DIR, a as CONSUMER_REGISTRY_TS, l as MICROCOMPONENTS_DIR, n as OWNED_BANNER, K as RESOLVED_VIRTUAL_ID, u as SHIPPED_CONFIG_FILES, G as VIRTUAL_ID, r as VIRTUAL_REGISTRIES_ID, _ as classifyConfigFile, x as discover, Q as ensureConsumerRegistry, g as fileIdFromConfigFile, m as formIdFromFile, y as isConsumerRoot, b as isDiscoveredPath, h as microcomponentKeysFromFile, J as ownedMessage, p as pageIdFromFile, S as registrable, Z as restoreOwnedFiles, A as stripComments, f as tabIdFromFile, B as validate, W as validateDiscovered, ne as virtualModuleSource, E as virtualModuleSourceFor, ae as yourAiFirebase };