your-ai-workflow-firebase-os 1.2.39 → 1.2.40

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.
@@ -1,4 +1,4 @@
1
- import { Ht as e } from "./ContactPopup-Bm3DZkEB.js";
1
+ import { Bt as e } from "./ContactPopup-kZk-JP-d.js";
2
2
  import t, { forwardRef as n, useCallback as r, useEffect as i, useImperativeHandle as a, useMemo as o, useRef as s, useState as c } from "react";
3
3
  import { jsx as l, jsxs as u } from "react/jsx-runtime";
4
4
  //#region node_modules/react-international-phone/dist/index.mjs
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./chunk-DYteiM-1.cjs`);const e=require(`./ContactPopup-DY0VLjCP.cjs`);exports.ContactPopup=e.t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./chunk-DYteiM-1.cjs`);const e=require(`./ContactPopup-D7dmsL5K.cjs`);exports.ContactPopup=e.t;
@@ -1,2 +1,2 @@
1
- import { t as e } from "./ContactPopup-Bm3DZkEB.js";
1
+ import { t as e } from "./ContactPopup-kZk-JP-d.js";
2
2
  export { e as ContactPopup };
package/dist/vite.cjs.js CHANGED
@@ -65,10 +65,10 @@ createRoot(document.getElementById('root')!).render(
65
65
  <App />
66
66
  </StrictMode>,
67
67
  )
68
- `,s=`src/your-ai-workflow-firebase-os`,c=`${s}/configs`,l=`${s}/microcomponents`,u=[`theme.config.ts`,`contactForm.config.ts`,`supportForm.config.ts`,`registry.ts`,`pagesRegistry.ts`],d=e=>e.split(n.sep).join(`/`),f=e=>n.basename(e).replace(`.config.ts`,``).replace(/Tab$/,``).toLowerCase(),p=e=>n.basename(e).replace(`.config.ts`,``).replace(/Page$/,``).toLowerCase(),m=e=>n.basename(e).replace(`.config.ts`,``).replace(/Form$/,``).toLowerCase(),h=e=>{let t=n.basename(e).replace(/\.tsx$/,``).replace(/Content$/,``).replace(/([a-z0-9])([A-Z])/g,`$1_$2`).toLowerCase();return[t,t.replace(/_/g,``)]},g=e=>n.basename(e).replace(/\.config\.ts$/,``);function _(e){let t=n.basename(e);return u.includes(t)?`shipped`:/Tab\.config\.ts$/.test(t)?`tab`:/Page\.config\.ts$/.test(t)?`page`:/Form\.config\.ts$/.test(t)?`form`:`other`}var v=e=>t.existsSync(e)?t.readdirSync(e,{withFileTypes:!0}).filter(e=>e.isFile()).map(e=>e.name).sort():[],y=e=>t.existsSync(n.join(e,s));function b(e,t){let r=d(n.relative(e,t));return r.startsWith(c+`/`)||r.startsWith(l+`/`)}function x(e){let t=[],r=n.join(e,c);for(let e of v(r)){if(!/\.tsx?$/.test(e))continue;let i=n.join(r,e),a=`${c}/${e}`,o=_(e);o===`tab`?t.push({kind:o,file:a,abs:i,name:e,id:f(e)}):o===`page`?t.push({kind:o,file:a,abs:i,name:e,id:p(e)}):o===`form`||/Form\.config\.ts$/.test(e)?t.push({kind:`form`,file:a,abs:i,name:e,id:m(e)}):t.push({kind:`other`,file:a,abs:i,name:e,id:``})}let i=n.join(e,l);for(let e of v(i))e.endsWith(`.tsx`)&&e.replace(/\.tsx$/,``)!==`registry`&&t.push({kind:`microcomponent`,file:`${l}/${e}`,abs:n.join(i,e),name:e,id:h(e)[0]});return t}var S=e=>e.filter(e=>e.kind!==`other`),C=e=>JSON.stringify(e);function w(e){let t=[],n=[],r=[],i=[];return S(e).forEach((e,a)=>{let o=`m${a}`;if(t.push(`import * as ${o} from ${C(d(e.abs))};`),e.kind===`tab`)n.push(`{
68
+ `,s=`src/your-ai-workflow-firebase-os`,c=`${s}/configs`,l=`${s}/microcomponents`,u=[`theme.config.ts`,`contactForm.config.ts`,`supportForm.config.ts`,`registry.ts`,`pagesRegistry.ts`],d=e=>e.split(n.sep).join(`/`),f=e=>n.basename(e).replace(`.config.ts`,``).replace(/Tab$/,``).toLowerCase(),p=e=>n.basename(e).replace(`.config.ts`,``).replace(/Page$/,``).toLowerCase(),m=e=>n.basename(e).replace(`.config.ts`,``).replace(/Form$/,``).toLowerCase(),h=e=>{let t=n.basename(e).replace(/\.tsx$/,``).replace(/Content$/,``).replace(/([a-z0-9])([A-Z])/g,`$1_$2`).toLowerCase();return[t,t.replace(/_/g,``)]},g=e=>n.basename(e).replace(/\.config\.ts$/,``);function _(e){let t=n.basename(e);return u.includes(t)?`shipped`:/Tab\.config\.ts$/.test(t)?`tab`:/Page\.config\.ts$/.test(t)?`page`:/Form\.config\.ts$/.test(t)?`form`:`other`}var v=e=>t.existsSync(e)?t.readdirSync(e,{withFileTypes:!0}).filter(e=>e.isFile()).map(e=>e.name).sort():[],y=e=>t.existsSync(n.join(e,s));function b(e,t){let r=d(n.relative(e,t));return r.startsWith(c+`/`)||r.startsWith(l+`/`)}function x(e){let t=[],r=n.join(e,c);for(let e of v(r)){if(!/\.tsx?$/.test(e))continue;let i=n.join(r,e),a=`${c}/${e}`,o=_(e);o===`tab`?t.push({kind:o,file:a,abs:i,name:e,id:f(e)}):o===`page`?t.push({kind:o,file:a,abs:i,name:e,id:p(e)}):o===`form`||/Form\.config\.ts$/.test(e)?t.push({kind:`form`,file:a,abs:i,name:e,id:m(e)}):t.push({kind:`other`,file:a,abs:i,name:e,id:``})}let i=n.join(e,l);for(let e of v(i))e.endsWith(`.tsx`)&&e.replace(/\.tsx$/,``)!==`registry`&&t.push({kind:`microcomponent`,file:`${l}/${e}`,abs:n.join(i,e),name:e,id:h(e)[0]});return t}var S=e=>e.filter(e=>e.kind!==`other`),C=[{test:e=>/Content\.tsx$/.test(e),home:l},{test:e=>/(Tab|Page|Form)\.config\.tsx?$/.test(e),home:c}],w=new Set([`node_modules`,`.git`,`dist`,`build`]);function T(e){let r=[],i=n.join(e,`src`),a=(i,o)=>{if(!(o>6||!t.existsSync(i)))for(let s of t.readdirSync(i,{withFileTypes:!0})){let t=n.join(i,s.name),u=d(n.relative(e,t));if(s.isDirectory()){w.has(s.name)||a(t,o+1);continue}if(!(u===`${c}/${s.name}`||u===`${l}/${s.name}`)){for(let{test:e,home:t}of C)if(e(s.name)){r.push(`${u}: files like this are only found directly in ${t}/ — move it to ${t}/${s.name}.`);break}}}};return a(i,0),r.sort()}var E=e=>{let t=n.basename(e);return C.some(e=>e.test(t))},D=e=>JSON.stringify(e);function O(e){let t=[],n=[],r=[],i=[];return S(e).forEach((e,a)=>{let o=`m${a}`;if(t.push(`import * as ${o} from ${D(d(e.abs))};`),e.kind===`tab`)n.push(`{
69
69
  const configVal = pickConfig(${o});
70
70
  if (configVal) {
71
- const tabId = ${C(e.id)};
71
+ const tabId = ${D(e.id)};
72
72
  const finalTab = {
73
73
  config: {
74
74
  ...configVal,
@@ -86,7 +86,7 @@ createRoot(document.getElementById('root')!).render(
86
86
  }`);else if(e.kind===`page`)n.push(`{
87
87
  const configVal = pickConfig(${o});
88
88
  if (configVal) {
89
- const pageId = ${C(e.id)};
89
+ const pageId = ${D(e.id)};
90
90
  const finalPage = {
91
91
  config: {
92
92
  ...configVal,
@@ -104,7 +104,7 @@ createRoot(document.getElementById('root')!).render(
104
104
  }`);else if(e.kind===`form`)r.push(`{
105
105
  const configVal = pickConfig(${o});
106
106
  if (configVal) {
107
- const formId = ${C(e.id)};
107
+ const formId = ${D(e.id)};
108
108
  // The form's id is its file name; systemName always follows the file.
109
109
  const finalConfig = { ...configVal, systemName: formId };
110
110
  forms[formId] = finalConfig;
@@ -112,11 +112,11 @@ createRoot(document.getElementById('root')!).render(
112
112
  forms[finalConfig.systemName.toLowerCase()] = finalConfig;
113
113
  }
114
114
  }`);else if(e.kind===`microcomponent`){let[t,n]=h(e.name);i.push(`if (${o} && ${o}.default) {
115
- microcomponents[${C(t)}] = ${o}.default;
115
+ microcomponents[${D(t)}] = ${o}.default;
116
116
  // Also answer to the squashed form ("mobile_apps" -> "mobileapps"): a page id
117
117
  // derived from a file name (mobileAppsPage.config.ts -> "mobileapps") has no
118
118
  // underscores, and the page must still find MobileAppsContent.tsx.
119
- microcomponents[${C(n)}] = ${o}.default;
119
+ microcomponents[${D(n)}] = ${o}.default;
120
120
  }`)}}),`// Generated by Your AI Firebase from the files in ${s}/.
121
121
  // Never written to disk; never edit. Add or remove a file and it updates itself.
122
122
  ${t.join(`
@@ -157,4 +157,4 @@ if (typeof window !== 'undefined') {
157
157
  export const pagesRegistry = pages;
158
158
  export const formsRegistry = forms;
159
159
  export const microcomponentRegistry = microcomponents;
160
- `}var T=e=>w(x(e)),E=e=>e.split(`/`).pop()||e,D=e=>/\/configs\/[^/]+$/.test(e),O=e=>/\/microcomponents\/[^/]+\.tsx$/.test(e),k=e=>e.replace(/\/\*[\s\S]*?\*\//g,``).replace(/(^|[^:\\'"`])\/\/.*$/gm,`$1`),A=(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},j=e=>{let t=e.match(/^(['"`])([^'"`]*)\1$/);return t?t[2]:null},M=e=>/export\s+(?:const|let|var|function|class)\s+\w*Config\b/.test(e)||/export\s*\{[^}]*\b\w*Config\b[^}]*\}/.test(e),N=e=>/export\s+default\b/.test(e),P=e=>{let t=A(e,`route`);return{first:t[0],count:t.length}};function F(e){let t=[],n=[],r=new Map,i=new Set;for(let{file:t}of e)if(O(t))for(let e of h(E(t)))i.add(e);for(let{file:a,source:o}of e){let e=E(a),s=k(o);if(D(a)){let n=_(e);if(n===`shipped`)continue;if(n===`other`){t.push(`${a}: rename it to somethingTab.config.ts (a dashboard page), somethingPage.config.ts (a page for anyone) or somethingForm.config.ts (a form).`);continue}if(!M(s)&&!N(s)&&t.push(`${a}: export one const named ${g(e)}Config.`),n===`tab`||n===`page`){let{first:o,count:c}=P(s),l=o===void 0?null:j(o);if(c===0||l===null||!l.startsWith(`/`))t.push(`${a}: 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(`${a}: route '${l}' is already used by ${e}. One page, one file, one address.`):r.set(l,a)}let u=A(s,`template`)[0],d=u===void 0?null:j(u);if(!d||![`board`,`table`,`calendar`,`drive`,`inline_form`,`popup_form`].includes(d)){let r=n===`tab`?f(e):p(e),o=A(s,n===`tab`?`tabName`:`pageName`)[0],c=o===void 0?null:j(o),l=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,`_`).replace(/^_|_$/g,``);if(![r,...c?[l(c),l(c).replace(/_/g,``)]:[]].some(e=>i.has(e))){let n=g(e).replace(/(Tab|Page)$/,``),r=(c||n).split(/[^a-zA-Z0-9]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``);t.push(`${a}: 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=A(s,`pageType`)[0],n=e===void 0?null:j(e);n!==`user`&&n!==`internal`&&n!==`admin`&&t.push(`${a}: pageType must be 'user', 'internal' or 'admin'. A dashboard page is never public.`)}if(n===`form`){let n=m(e),r=A(s,`systemName`)[0];r!==void 0&&j(r)!==n&&t.push(`${a}: systemName must be '${n}'.`)}continue}if(O(a)){N(s)||t.push(`${a}: add export default.`),(/<form\b/.test(s)||/\bonSubmit\b/.test(s))&&!/ContactPopup/.test(s)&&n.push(`${a}: forms are *Form.config.ts files shown with <ContactPopup formId="…" />; a hand-written form never reaches the Inbox.`),/<style[\s>]/.test(s)&&t.push(`${a}: 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 e=s.match(/\b(?:bg-(?:white|black)|(?:bg|text|border)-(?:gray|slate|zinc|neutral|stone)-\d+)\b/);e&&n.push(`${a}: ${e[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}}function I(e,t){return F(e.map(e=>({file:e.file,source:t(e.abs)})))}var L=i,R=`\0`+L,z=[{rel:`src/App.tsx`,source:a},{rel:`src/main.tsx`,source:o}],B=e=>`${e} is owned by Your AI Firebase; your edit was discarded.`,V=e=>e.replace(/[?#].*$/,``),H=e=>n.normalize(e).split(n.sep).join(`/`),U={info:e=>console.log(e),warn:e=>console.warn(e),error:e=>console.error(e)};function W(e,r=U){let i=[];for(let{rel:a,source:o}of z){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(B(a)))}return i}var G=(e,t)=>{let r=H(V(t));for(let{rel:t,source:i}of z)if(r===H(n.join(e,t)))return i;return null};function K(){let e=process.cwd(),n=!1,r=`build`,i=U,a=()=>I(x(e),e=>t.readFileSync(e,`utf8`));return{name:`your-ai-firebase`,enforce:`pre`,configResolved(t){e=t.root,r=t.command,i=t.logger,n=y(e),n&&W(e,i)},resolveId(e){return e===L?R:null},buildStart(){if(!n)return;let{errors:e,warnings:t}=a();for(let e of t)this.warn(e);if(e.length!==0)if(r===`build`)this.error(e[0]);else for(let t of e)i.error(t)},load(r){if(!n)return null;if(r===R){let n=x(e),{errors:r}=I(n,e=>t.readFileSync(e,`utf8`));return r.length&&this.error(r[0]),w(n)}return G(e,r)},configureServer(t){if(!n)return;let r=()=>{let e=t.moduleGraph.getModuleById(R);e&&t.moduleGraph.invalidateModule(e),t.ws.send({type:`full-reload`,path:`*`})},i=n=>{let i=H(n);if(G(e,i)!==null){W(e,t.config.logger);return}if(!b(e,i))return;r();let{errors:o,warnings:s}=a();for(let e of s)t.config.logger.warn(e);for(let e of o)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=o,exports.CONFIGS_DIR=c,exports.CONSUMER_DIR=s,exports.MICROCOMPONENTS_DIR=l,exports.OWNED_BANNER=r,exports.RESOLVED_VIRTUAL_ID=R,exports.SHIPPED_CONFIG_FILES=u,exports.VIRTUAL_ID=L,exports.VIRTUAL_REGISTRIES_ID=i,exports.classifyConfigFile=_,exports.discover=x,exports.fileIdFromConfigFile=g,exports.formIdFromFile=m,exports.isConsumerRoot=y,exports.isDiscoveredPath=b,exports.microcomponentKeysFromFile=h,exports.ownedMessage=B,exports.pageIdFromFile=p,exports.registrable=S,exports.restoreOwnedFiles=W,exports.stripComments=k,exports.tabIdFromFile=f,exports.validate=F,exports.validateDiscovered=I,exports.virtualModuleSource=T,exports.virtualModuleSourceFor=w,exports.yourAiFirebase=K;
160
+ `}var k=e=>O(x(e)),A=e=>e.split(`/`).pop()||e,j=e=>/\/configs\/[^/]+$/.test(e),M=e=>/\/microcomponents\/[^/]+\.tsx$/.test(e),N=e=>e.replace(/\/\*[\s\S]*?\*\//g,``).replace(/(^|[^:\\'"`])\/\/.*$/gm,`$1`),P=(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},F=e=>{let t=e.match(/^(['"`])([^'"`]*)\1$/);return t?t[2]:null},I=e=>/export\s+(?:const|let|var|function|class)\s+\w*Config\b/.test(e)||/export\s*\{[^}]*\b\w*Config\b[^}]*\}/.test(e),L=e=>/export\s+default\b/.test(e),R=e=>{let t=P(e,`route`);return{first:t[0],count:t.length}};function z(e){let t=[],n=[],r=new Map,i=new Set;for(let{file:t}of e)if(M(t))for(let e of h(A(t)))i.add(e);for(let{file:a,source:o}of e){let e=A(a),s=N(o);if(j(a)){let n=_(e);if(n===`shipped`)continue;if(n===`other`){t.push(`${a}: rename it to somethingTab.config.ts (a dashboard page), somethingPage.config.ts (a page for anyone) or somethingForm.config.ts (a form).`);continue}if(!I(s)&&!L(s)&&t.push(`${a}: export one const named ${g(e)}Config.`),n===`tab`||n===`page`){let{first:o,count:c}=R(s),l=o===void 0?null:F(o);if(c===0||l===null||!l.startsWith(`/`))t.push(`${a}: 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(`${a}: route '${l}' is already used by ${e}. One page, one file, one address.`):r.set(l,a)}let u=P(s,`template`)[0],d=u===void 0?null:F(u);if(!d||![`board`,`table`,`calendar`,`drive`,`inline_form`,`popup_form`].includes(d)){let r=n===`tab`?f(e):p(e),o=P(s,n===`tab`?`tabName`:`pageName`)[0],c=o===void 0?null:F(o),l=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,`_`).replace(/^_|_$/g,``);if(![r,...c?[l(c),l(c).replace(/_/g,``)]:[]].some(e=>i.has(e))){let n=g(e).replace(/(Tab|Page)$/,``),r=(c||n).split(/[^a-zA-Z0-9]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``);t.push(`${a}: 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=P(s,`pageType`)[0],n=e===void 0?null:F(e);n!==`user`&&n!==`internal`&&n!==`admin`&&t.push(`${a}: pageType must be 'user', 'internal' or 'admin'. A dashboard page is never public.`)}if(n===`form`){let n=m(e),r=P(s,`systemName`)[0];r!==void 0&&F(r)!==n&&t.push(`${a}: systemName must be '${n}'.`)}continue}if(M(a)){L(s)||t.push(`${a}: add export default.`),(/<form\b/.test(s)||/\bonSubmit\b/.test(s))&&!/ContactPopup/.test(s)&&n.push(`${a}: forms are *Form.config.ts files shown with <ContactPopup formId="…" />; a hand-written form never reaches the Inbox.`),/<style[\s>]/.test(s)&&t.push(`${a}: 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 e=s.match(/\b(?:bg-(?:white|black)|(?:bg|text|border)-(?:gray|slate|zinc|neutral|stone)-\d+)\b/);e&&n.push(`${a}: ${e[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}}function B(e,t){return z(e.map(e=>({file:e.file,source:t(e.abs)})))}var V=i,H=`\0`+V,U=[{rel:`src/App.tsx`,source:a},{rel:`src/main.tsx`,source:o}],W=e=>`${e} is owned by Your AI Firebase; your edit was discarded.`,G=e=>e.replace(/[?#].*$/,``),K=e=>n.normalize(e).split(n.sep).join(`/`),q={info:e=>console.log(e),warn:e=>console.warn(e),error:e=>console.error(e)};function J(e,r=q){let i=[];for(let{rel:a,source:o}of U){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(W(a)))}return i}var Y=(e,t)=>{let r=K(G(t));for(let{rel:t,source:i}of U)if(r===K(n.join(e,t)))return i;return null};function X(){let e=process.cwd(),n=!1,r=`build`,i=q,a=()=>{let n=B(x(e),e=>t.readFileSync(e,`utf8`));return{...n,errors:[...n.errors,...T(e)]}};return{name:`your-ai-firebase`,enforce:`pre`,configResolved(t){e=t.root,r=t.command,i=t.logger,n=y(e),n&&J(e,i)},resolveId(e){return e===V?H:null},buildStart(){if(!n)return;let{errors:e,warnings:t}=a();for(let e of t)this.warn(e);if(e.length!==0)if(r===`build`)this.error(e[0]);else for(let t of e)i.error(t)},load(t){if(!n)return null;if(t===H){let t=x(e),{errors:n}=a();return n.length&&this.error(n[0]),O(t)}return Y(e,t)},configureServer(t){if(!n)return;let r=()=>{let e=t.moduleGraph.getModuleById(H);e&&t.moduleGraph.invalidateModule(e),t.ws.send({type:`full-reload`,path:`*`})},i=n=>{let i=K(n);if(Y(e,i)!==null){J(e,t.config.logger);return}if(!b(e,i)&&!E(i))return;r();let{errors:o,warnings:s}=a();for(let e of s)t.config.logger.warn(e);for(let e of o)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=o,exports.CONFIGS_DIR=c,exports.CONSUMER_DIR=s,exports.MICROCOMPONENTS_DIR=l,exports.OWNED_BANNER=r,exports.RESOLVED_VIRTUAL_ID=H,exports.SHIPPED_CONFIG_FILES=u,exports.VIRTUAL_ID=V,exports.VIRTUAL_REGISTRIES_ID=i,exports.classifyConfigFile=_,exports.discover=x,exports.fileIdFromConfigFile=g,exports.formIdFromFile=m,exports.isConsumerRoot=y,exports.isDiscoveredPath=b,exports.microcomponentKeysFromFile=h,exports.ownedMessage=W,exports.pageIdFromFile=p,exports.registrable=S,exports.restoreOwnedFiles=J,exports.stripComments=N,exports.tabIdFromFile=f,exports.validate=z,exports.validateDiscovered=B,exports.virtualModuleSource=k,exports.virtualModuleSourceFor=O,exports.yourAiFirebase=X;
package/dist/vite.es.js CHANGED
@@ -128,15 +128,48 @@ function b(e) {
128
128
  });
129
129
  return n;
130
130
  }
131
- var x = (e) => e.filter((e) => e.kind !== "other"), S = (e) => JSON.stringify(e);
132
- function C(e) {
131
+ var x = (e) => e.filter((e) => e.kind !== "other"), S = [{
132
+ test: (e) => /Content\.tsx$/.test(e),
133
+ home: c
134
+ }, {
135
+ test: (e) => /(Tab|Page|Form)\.config\.tsx?$/.test(e),
136
+ home: s
137
+ }], C = new Set([
138
+ "node_modules",
139
+ ".git",
140
+ "dist",
141
+ "build"
142
+ ]);
143
+ function w(n) {
144
+ let r = [], i = t.join(n, "src"), a = (i, o) => {
145
+ if (!(o > 6 || !e.existsSync(i))) for (let l of e.readdirSync(i, { withFileTypes: !0 })) {
146
+ let e = t.join(i, l.name), d = u(t.relative(n, e));
147
+ if (l.isDirectory()) {
148
+ C.has(l.name) || a(e, o + 1);
149
+ continue;
150
+ }
151
+ if (!(d === `${s}/${l.name}` || d === `${c}/${l.name}`)) {
152
+ for (let { test: e, home: t } of S) if (e(l.name)) {
153
+ r.push(`${d}: files like this are only found directly in ${t}/ — move it to ${t}/${l.name}.`);
154
+ break;
155
+ }
156
+ }
157
+ }
158
+ };
159
+ return a(i, 0), r.sort();
160
+ }
161
+ var T = (e) => {
162
+ let n = t.basename(e);
163
+ return S.some((e) => e.test(n));
164
+ }, E = (e) => JSON.stringify(e);
165
+ function D(e) {
133
166
  let t = [], n = [], r = [], i = [];
134
167
  return x(e).forEach((e, a) => {
135
168
  let o = `m${a}`;
136
- if (t.push(`import * as ${o} from ${S(u(e.abs))};`), e.kind === "tab") n.push(`{
169
+ if (t.push(`import * as ${o} from ${E(u(e.abs))};`), e.kind === "tab") n.push(`{
137
170
  const configVal = pickConfig(${o});
138
171
  if (configVal) {
139
- const tabId = ${S(e.id)};
172
+ const tabId = ${E(e.id)};
140
173
  const finalTab = {
141
174
  config: {
142
175
  ...configVal,
@@ -155,7 +188,7 @@ function C(e) {
155
188
  else if (e.kind === "page") n.push(`{
156
189
  const configVal = pickConfig(${o});
157
190
  if (configVal) {
158
- const pageId = ${S(e.id)};
191
+ const pageId = ${E(e.id)};
159
192
  const finalPage = {
160
193
  config: {
161
194
  ...configVal,
@@ -174,7 +207,7 @@ function C(e) {
174
207
  else if (e.kind === "form") r.push(`{
175
208
  const configVal = pickConfig(${o});
176
209
  if (configVal) {
177
- const formId = ${S(e.id)};
210
+ const formId = ${E(e.id)};
178
211
  // The form's id is its file name; systemName always follows the file.
179
212
  const finalConfig = { ...configVal, systemName: formId };
180
213
  forms[formId] = finalConfig;
@@ -185,11 +218,11 @@ function C(e) {
185
218
  else if (e.kind === "microcomponent") {
186
219
  let [t, n] = m(e.name);
187
220
  i.push(`if (${o} && ${o}.default) {
188
- microcomponents[${S(t)}] = ${o}.default;
221
+ microcomponents[${E(t)}] = ${o}.default;
189
222
  // Also answer to the squashed form ("mobile_apps" -> "mobileapps"): a page id
190
223
  // derived from a file name (mobileAppsPage.config.ts -> "mobileapps") has no
191
224
  // underscores, and the page must still find MobileAppsContent.tsx.
192
- microcomponents[${S(n)}] = ${o}.default;
225
+ microcomponents[${E(n)}] = ${o}.default;
193
226
  }`);
194
227
  }
195
228
  }), `// Generated by Your AI Firebase from the files in ${o}/.
@@ -230,40 +263,40 @@ export const formsRegistry = forms;
230
263
  export const microcomponentRegistry = microcomponents;
231
264
  `;
232
265
  }
233
- var w = (e) => C(b(e)), T = (e) => e.split("/").pop() || e, E = (e) => /\/configs\/[^/]+$/.test(e), D = (e) => /\/microcomponents\/[^/]+\.tsx$/.test(e), O = (e) => e.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:\\'"`])\/\/.*$/gm, "$1"), k = (e, t) => {
266
+ var O = (e) => D(b(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) => {
234
267
  let n = RegExp(`(?:^|[\\s,{])${t}\\s*:\\s*([^,\\n}]+)`, "g"), r = [], i;
235
268
  for (; i = n.exec(e);) r.push(i[1].trim());
236
269
  return r;
237
- }, A = (e) => {
270
+ }, P = (e) => {
238
271
  let t = e.match(/^(['"`])([^'"`]*)\1$/);
239
272
  return t ? t[2] : null;
240
- }, j = (e) => /export\s+(?:const|let|var|function|class)\s+\w*Config\b/.test(e) || /export\s*\{[^}]*\b\w*Config\b[^}]*\}/.test(e), M = (e) => /export\s+default\b/.test(e), N = (e) => {
241
- let t = k(e, "route");
273
+ }, 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) => {
274
+ let t = N(e, "route");
242
275
  return {
243
276
  first: t[0],
244
277
  count: t.length
245
278
  };
246
279
  };
247
- function P(e) {
280
+ function R(e) {
248
281
  let t = [], n = [], r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Set();
249
- for (let { file: t } of e) if (D(t)) for (let e of m(T(t))) i.add(e);
282
+ for (let { file: t } of e) if (j(t)) for (let e of m(k(t))) i.add(e);
250
283
  for (let { file: a, source: o } of e) {
251
- let e = T(a), s = O(o);
252
- if (E(a)) {
284
+ let e = k(a), s = M(o);
285
+ if (A(a)) {
253
286
  let n = g(e);
254
287
  if (n === "shipped") continue;
255
288
  if (n === "other") {
256
289
  t.push(`${a}: rename it to somethingTab.config.ts (a dashboard page), somethingPage.config.ts (a page for anyone) or somethingForm.config.ts (a form).`);
257
290
  continue;
258
291
  }
259
- if (!j(s) && !M(s) && t.push(`${a}: export one const named ${h(e)}Config.`), n === "tab" || n === "page") {
260
- let { first: o, count: c } = N(s), l = o === void 0 ? null : A(o);
292
+ if (!F(s) && !I(s) && t.push(`${a}: export one const named ${h(e)}Config.`), n === "tab" || n === "page") {
293
+ let { first: o, count: c } = L(s), l = o === void 0 ? null : P(o);
261
294
  if (c === 0 || l === null || !l.startsWith("/")) t.push(`${a}: route must be one string starting with /, e.g. route: '/onboarding'. A page has exactly one web address.`);
262
295
  else {
263
296
  let e = r.get(l);
264
297
  e ? t.push(`${a}: route '${l}' is already used by ${e}. One page, one file, one address.`) : r.set(l, a);
265
298
  }
266
- let u = k(s, "template")[0], p = u === void 0 ? null : A(u);
299
+ let u = N(s, "template")[0], p = u === void 0 ? null : P(u);
267
300
  if (!p || ![
268
301
  "board",
269
302
  "table",
@@ -272,7 +305,7 @@ function P(e) {
272
305
  "inline_form",
273
306
  "popup_form"
274
307
  ].includes(p)) {
275
- let r = n === "tab" ? d(e) : f(e), o = k(s, n === "tab" ? "tabName" : "pageName")[0], c = o === void 0 ? null : A(o), l = (e) => e.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
308
+ let r = n === "tab" ? d(e) : f(e), o = N(s, n === "tab" ? "tabName" : "pageName")[0], c = o === void 0 ? null : P(o), l = (e) => e.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
276
309
  if (![r, ...c ? [l(c), l(c).replace(/_/g, "")] : []].some((e) => i.has(e))) {
277
310
  let n = h(e).replace(/(Tab|Page)$/, ""), r = (c || n).split(/[^a-zA-Z0-9]+/).filter(Boolean).map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join("");
278
311
  t.push(`${a}: no content file matches this page, so it renders empty — create src/your-ai-workflow-firebase-os/microcomponents/${r}Content.tsx with export default.`);
@@ -280,17 +313,17 @@ function P(e) {
280
313
  }
281
314
  }
282
315
  if (n === "tab") {
283
- let e = k(s, "pageType")[0], n = e === void 0 ? null : A(e);
316
+ let e = N(s, "pageType")[0], n = e === void 0 ? null : P(e);
284
317
  n !== "user" && n !== "internal" && n !== "admin" && t.push(`${a}: pageType must be 'user', 'internal' or 'admin'. A dashboard page is never public.`);
285
318
  }
286
319
  if (n === "form") {
287
- let n = p(e), r = k(s, "systemName")[0];
288
- r !== void 0 && A(r) !== n && t.push(`${a}: systemName must be '${n}'.`);
320
+ let n = p(e), r = N(s, "systemName")[0];
321
+ r !== void 0 && P(r) !== n && t.push(`${a}: systemName must be '${n}'.`);
289
322
  }
290
323
  continue;
291
324
  }
292
- if (D(a)) {
293
- M(s) || t.push(`${a}: add export default.`), (/<form\b/.test(s) || /\bonSubmit\b/.test(s)) && !/ContactPopup/.test(s) && n.push(`${a}: forms are *Form.config.ts files shown with <ContactPopup formId="…" />; a hand-written form never reaches the Inbox.`), /<style[\s>]/.test(s) && t.push(`${a}: 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).`);
325
+ if (j(a)) {
326
+ I(s) || t.push(`${a}: add export default.`), (/<form\b/.test(s) || /\bonSubmit\b/.test(s)) && !/ContactPopup/.test(s) && n.push(`${a}: forms are *Form.config.ts files shown with <ContactPopup formId="…" />; a hand-written form never reaches the Inbox.`), /<style[\s>]/.test(s) && t.push(`${a}: 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).`);
294
327
  let e = s.match(/\b(?:bg-(?:white|black)|(?:bg|text|border)-(?:gray|slate|zinc|neutral|stone)-\d+)\b/);
295
328
  e && n.push(`${a}: ${e[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.`);
296
329
  }
@@ -300,53 +333,59 @@ function P(e) {
300
333
  warnings: n
301
334
  };
302
335
  }
303
- function F(e, t) {
304
- return P(e.map((e) => ({
336
+ function z(e, t) {
337
+ return R(e.map((e) => ({
305
338
  file: e.file,
306
339
  source: t(e.abs)
307
340
  })));
308
341
  }
309
342
  //#endregion
310
343
  //#region src/vite/plugin.ts
311
- var I = r, L = "\0" + I, R = [{
344
+ var B = r, V = "\0" + B, H = [{
312
345
  rel: "src/App.tsx",
313
346
  source: i
314
347
  }, {
315
348
  rel: "src/main.tsx",
316
349
  source: a
317
- }], z = (e) => `${e} is owned by Your AI Firebase; your edit was discarded.`, B = (e) => e.replace(/[?#].*$/, ""), V = (e) => t.normalize(e).split(t.sep).join("/"), H = {
350
+ }], U = (e) => `${e} is owned by Your AI Firebase; your edit was discarded.`, W = (e) => e.replace(/[?#].*$/, ""), G = (e) => t.normalize(e).split(t.sep).join("/"), K = {
318
351
  info: (e) => console.log(e),
319
352
  warn: (e) => console.warn(e),
320
353
  error: (e) => console.error(e)
321
354
  };
322
- function U(n, r = H) {
355
+ function q(n, r = K) {
323
356
  let i = [];
324
- for (let { rel: a, source: o } of R) {
357
+ for (let { rel: a, source: o } of H) {
325
358
  let s = t.join(n, a), c = null;
326
359
  try {
327
360
  c = e.readFileSync(s, "utf8");
328
361
  } catch {
329
362
  c = null;
330
363
  }
331
- c !== o && (e.mkdirSync(t.dirname(s), { recursive: !0 }), e.writeFileSync(s, o), i.push(a), c !== null && r.warn(z(a)));
364
+ c !== o && (e.mkdirSync(t.dirname(s), { recursive: !0 }), e.writeFileSync(s, o), i.push(a), c !== null && r.warn(U(a)));
332
365
  }
333
366
  return i;
334
367
  }
335
- var W = (e, n) => {
336
- let r = V(B(n));
337
- for (let { rel: n, source: i } of R) if (r === V(t.join(e, n))) return i;
368
+ var J = (e, n) => {
369
+ let r = G(W(n));
370
+ for (let { rel: n, source: i } of H) if (r === G(t.join(e, n))) return i;
338
371
  return null;
339
372
  };
340
- function G() {
341
- let t = process.cwd(), n = !1, r = "build", i = H, a = () => F(b(t), (t) => e.readFileSync(t, "utf8"));
373
+ function Y() {
374
+ let t = process.cwd(), n = !1, r = "build", i = K, a = () => {
375
+ let n = z(b(t), (t) => e.readFileSync(t, "utf8"));
376
+ return {
377
+ ...n,
378
+ errors: [...n.errors, ...w(t)]
379
+ };
380
+ };
342
381
  return {
343
382
  name: "your-ai-firebase",
344
383
  enforce: "pre",
345
384
  configResolved(e) {
346
- t = e.root, r = e.command, i = e.logger, n = v(t), n && U(t, i);
385
+ t = e.root, r = e.command, i = e.logger, n = v(t), n && q(t, i);
347
386
  },
348
387
  resolveId(e) {
349
- return e === I ? L : null;
388
+ return e === B ? V : null;
350
389
  },
351
390
  buildStart() {
352
391
  if (!n) return;
@@ -355,29 +394,29 @@ function G() {
355
394
  if (e.length !== 0) if (r === "build") this.error(e[0]);
356
395
  else for (let t of e) i.error(t);
357
396
  },
358
- load(r) {
397
+ load(e) {
359
398
  if (!n) return null;
360
- if (r === L) {
361
- let n = b(t), { errors: r } = F(n, (t) => e.readFileSync(t, "utf8"));
362
- return r.length && this.error(r[0]), C(n);
399
+ if (e === V) {
400
+ let e = b(t), { errors: n } = a();
401
+ return n.length && this.error(n[0]), D(e);
363
402
  }
364
- return W(t, r);
403
+ return J(t, e);
365
404
  },
366
405
  configureServer(e) {
367
406
  if (!n) return;
368
407
  let r = () => {
369
- let t = e.moduleGraph.getModuleById(L);
408
+ let t = e.moduleGraph.getModuleById(V);
370
409
  t && e.moduleGraph.invalidateModule(t), e.ws.send({
371
410
  type: "full-reload",
372
411
  path: "*"
373
412
  });
374
413
  }, i = (n) => {
375
- let i = V(n);
376
- if (W(t, i) !== null) {
377
- U(t, e.config.logger);
414
+ let i = G(n);
415
+ if (J(t, i) !== null) {
416
+ q(t, e.config.logger);
378
417
  return;
379
418
  }
380
- if (!y(t, i)) return;
419
+ if (!y(t, i) && !T(i)) return;
381
420
  r();
382
421
  let { errors: o, warnings: s } = a();
383
422
  for (let t of s) e.config.logger.warn(t);
@@ -388,4 +427,4 @@ function G() {
388
427
  };
389
428
  }
390
429
  //#endregion
391
- export { i as CANONICAL_APP_TSX, a as CANONICAL_MAIN_TSX, s as CONFIGS_DIR, o as CONSUMER_DIR, c as MICROCOMPONENTS_DIR, n as OWNED_BANNER, L as RESOLVED_VIRTUAL_ID, l as SHIPPED_CONFIG_FILES, I as VIRTUAL_ID, r as VIRTUAL_REGISTRIES_ID, g as classifyConfigFile, b as discover, h as fileIdFromConfigFile, p as formIdFromFile, v as isConsumerRoot, y as isDiscoveredPath, m as microcomponentKeysFromFile, z as ownedMessage, f as pageIdFromFile, x as registrable, U as restoreOwnedFiles, O as stripComments, d as tabIdFromFile, P as validate, F as validateDiscovered, w as virtualModuleSource, C as virtualModuleSourceFor, G as yourAiFirebase };
430
+ export { i as CANONICAL_APP_TSX, a as CANONICAL_MAIN_TSX, s as CONFIGS_DIR, o as CONSUMER_DIR, c as MICROCOMPONENTS_DIR, n as OWNED_BANNER, V as RESOLVED_VIRTUAL_ID, l as SHIPPED_CONFIG_FILES, B as VIRTUAL_ID, r as VIRTUAL_REGISTRIES_ID, g as classifyConfigFile, b as discover, h as fileIdFromConfigFile, p as formIdFromFile, v as isConsumerRoot, y as isDiscoveredPath, m as microcomponentKeysFromFile, U as ownedMessage, f as pageIdFromFile, x as registrable, q as restoreOwnedFiles, M as stripComments, d as tabIdFromFile, R as validate, z as validateDiscovered, O as virtualModuleSource, D as virtualModuleSourceFor, Y as yourAiFirebase };