your-ai-workflow-firebase-os 1.14.68 → 1.14.69
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/components/Lightbox.d.ts +5 -2
- package/dist/lib/recordArgs.d.ts +9 -0
- package/dist/pages/PagesAdmin.d.ts +6 -47
- package/dist/server.cjs.js +1 -1
- package/dist/server.es.js +1 -1
- package/dist/{validate-DHdK7h-c.js → validate-BTbvTYP_.js} +360 -330
- package/dist/validate-tte4piFl.cjs +103 -0
- package/dist/vite/validate.d.ts +9 -0
- package/dist/vite.cjs.js +1 -1
- package/dist/vite.es.js +1 -1
- package/dist/your-ai-workflow-firebase-os.cjs.js +42 -42
- package/dist/your-ai-workflow-firebase-os.css +1 -1
- package/dist/your-ai-workflow-firebase-os.es.js +9760 -9707
- package/package.json +1 -1
- package/dist/validate-HJOgqul9.cjs +0 -103
|
@@ -16,8 +16,11 @@ export interface LightboxProps {
|
|
|
16
16
|
onIndex: (index: number) => void;
|
|
17
17
|
onClose: () => void;
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* The page calls this press "zoom": the picture is here to be seen closer,
|
|
20
|
+
* not only bigger. It opens WHOLE either way now — a press, the button or
|
|
21
|
+
* a pinch magnifies the spot it was made on — and the word stays because
|
|
22
|
+
* it is what a page says about its picture, and what the build looks for
|
|
23
|
+
* on a set shown as something to zoom (validate.ts, zoom-is-a-gallery).
|
|
21
24
|
*/
|
|
22
25
|
zoom?: boolean;
|
|
23
26
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** The record to save, whether or not the collection was passed in front of it. */
|
|
2
|
+
export declare function recordPassed(first: unknown, second?: unknown): Record<string, any>;
|
|
3
|
+
/** The id and the change, whether or not the collection was passed in front of them. */
|
|
4
|
+
export declare function changePassed(first: unknown, second?: unknown, third?: unknown): {
|
|
5
|
+
id: string;
|
|
6
|
+
data: Record<string, any>;
|
|
7
|
+
};
|
|
8
|
+
/** The id to delete, whether or not the collection was passed in front of it. */
|
|
9
|
+
export declare function idPassed(first: unknown, second?: unknown): string;
|
|
@@ -79,49 +79,6 @@ export declare const audienceRoleOptions: (roles?: CustomRole[]) => {
|
|
|
79
79
|
* two have to agree to the letter.
|
|
80
80
|
*/
|
|
81
81
|
export declare const caseEntriesCollection: (config: any, prefix?: string) => string;
|
|
82
|
-
/**
|
|
83
|
-
* The audience's two lines in the sentence: WHO can open the page, and how
|
|
84
|
-
* its data works — shared by all of them, each person's own, an entry at a
|
|
85
|
-
* time sent to the people it belongs to, or a thing each person publishes.
|
|
86
|
-
*
|
|
87
|
-
* Both are the app's decisions, made on the page's row, and neither can be
|
|
88
|
-
* guessed from the words. A page born on this screen has no config file for
|
|
89
|
-
* the assistant to read: nothing else in the sentence says whether it is the
|
|
90
|
-
* team's page or a client's, and nothing at all used to say which collections
|
|
91
|
-
* it should reach for. An assistant left to guess reached for `user_` on a
|
|
92
|
-
* team page and for a role's shared space on a client portal — the second of
|
|
93
|
-
* those puts every client's records, and every file they upload, in one place
|
|
94
|
-
* all of them can open.
|
|
95
|
-
*
|
|
96
|
-
* SHARED names the one space the people on the list have — `mem_` for the
|
|
97
|
-
* team, `admin_` for the admins, `role_<id>_` for a single role — and says
|
|
98
|
-
* plainly that everybody on the page reads and writes the same records there.
|
|
99
|
-
* It also names `user_` beside it, because even a shared page has things that
|
|
100
|
-
* belong to one person: a client portal holds one price list and each
|
|
101
|
-
* client's own invoices, and an assistant told only about the shared space
|
|
102
|
-
* puts the invoices there too.
|
|
103
|
-
*
|
|
104
|
-
* PRIVATE is `user_` and nothing else, whatever the page is for. The rules
|
|
105
|
-
* hand each person their own documents and their own uploads and nobody
|
|
106
|
-
* else's, so the keeping is the database's, not the code's — the line says
|
|
107
|
-
* never to build a shared list here at all, because a shared list plus a
|
|
108
|
-
* filter is a curtain: it hides the other people's records on screen and
|
|
109
|
-
* keeps them from nobody.
|
|
110
|
-
*
|
|
111
|
-
* SENT is `case_`, and it is neither of the others: one collection everybody
|
|
112
|
-
* on the page writes into, where each record carries the two lists that say
|
|
113
|
-
* who may see it and who may change it. Its lines are in caseLines above,
|
|
114
|
-
* and they are the longest in the sentence for a reason — nothing about this
|
|
115
|
-
* shape can be guessed from the page's words, and every part of it that is
|
|
116
|
-
* guessed wrong fails as a permission error on somebody else's screen rather
|
|
117
|
-
* than as a mistake the owner can see.
|
|
118
|
-
*
|
|
119
|
-
* A page whose ticks leave no space they could all read — Members with
|
|
120
|
-
* anybody, two roles, a role beside the team — cannot be shared. It has two
|
|
121
|
-
* answers rather than one now, and the line for whichever the owner picked
|
|
122
|
-
* says what it means rather than letting the assistant discover it as a
|
|
123
|
-
* permission error.
|
|
124
|
-
*/
|
|
125
82
|
export declare const audienceLines: (config: any) => string[];
|
|
126
83
|
/** Which groups a piece of the owner's words names, each counted once. */
|
|
127
84
|
export declare const groupsNamed: (text: string, roles?: CustomRole[]) => string[];
|
|
@@ -862,11 +819,13 @@ export declare const ZOOM_WORDS: RegExp;
|
|
|
862
819
|
* in `<Lightbox>`, and `<Lightbox>` was a gallery: the same photo a little
|
|
863
820
|
* bigger with arrows through the others. Now `<Lightbox>` magnifies, and the
|
|
864
821
|
* line says which press is which: the small pictures of a listing swap its
|
|
865
|
-
* big one IN PLACE (viewing), and pressing the big one is the zoom
|
|
866
|
-
*
|
|
867
|
-
*
|
|
822
|
+
* big one IN PLACE (viewing), and pressing the big one is the zoom. What it
|
|
823
|
+
* opens is the picture WHOLE — a press inside it magnifies that spot. It
|
|
824
|
+
* opened already close up until the owner used it: "it has to start zoomed
|
|
825
|
+
* out not zoomed in so user can decide where to zoom themselves"
|
|
826
|
+
* (2026-09-23).
|
|
868
827
|
*/
|
|
869
|
-
export declare const LIGHTBOX_LINE = "Viewing and zooming are two things. Wherever a set of pictures is shown \u2014 a listing, its preview, the pop-up a card opens \u2014 it is VIEWED on the page itself: one big picture with the rest small beside or under it, and pressing a small one swaps the big one in place. Pressing the BIG one is ZOOMING, to see its details closer: it opens my app's own <Lightbox pictures={pictures} index={at} onIndex={setAt} onClose={() => setAt(null)} zoom /> from 'your-ai-workflow-firebase-os', with const [at, setAt] = useState<number | null>(null), which opens that picture
|
|
828
|
+
export declare const LIGHTBOX_LINE = "Viewing and zooming are two things. Wherever a set of pictures is shown \u2014 a listing, its preview, the pop-up a card opens \u2014 it is VIEWED on the page itself: one big picture with the rest small beside or under it, and pressing a small one swaps the big one in place. Pressing the BIG one is ZOOMING, to see its details closer: it opens my app's own <Lightbox pictures={pictures} index={at} onIndex={setAt} onClose={() => setAt(null)} zoom /> from 'your-ai-workflow-firebase-os', with const [at, setAt] = useState<number | null>(null), which opens that picture WHOLE and magnifies the spot pressed in it \u2014 the close-up then follows the mouse exactly, a finger drags and pinches it, one more press shows it whole again \u2014 and its arrows and a swipe move on through the set. It never opens already magnified: which part of a picture somebody wants closer is theirs to choose. A grid of pictures with no big one (a gallery) opens a pressed tile the same way without zoom, whole, and a press there zooms in. Never a viewer or a magnifier of your own, never a 'zoom' that only shows the picture a little bigger, and never a picture that is only looked at.";
|
|
870
829
|
/** Is the owner talking about the app's menu bar? */
|
|
871
830
|
export declare const mentionsMenu: (text: string) => boolean;
|
|
872
831
|
/**
|
package/dist/server.cjs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./chunk-CiTBaPhY.cjs`),t=require(`./verifiedAccount-D3OeaOBo.cjs`),n=require(`./aiModels-BIhoTNH0.cjs`),r=require(`./validate-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./chunk-CiTBaPhY.cjs`),t=require(`./verifiedAccount-D3OeaOBo.cjs`),n=require(`./aiModels-BIhoTNH0.cjs`),r=require(`./validate-tte4piFl.cjs`);let i=require(`node:fs`);i=e.a(i,1);let a=require(`express`);a=e.a(a,1);let o=require(`node:crypto`),s=require(`stripe`);s=e.a(s,1);var c=`https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com`,l=60;function u(e,t,n,r=Math.floor(Date.now()/1e3)){return n?e.alg===`RS256`?e.kid?t.aud===n?t.iss===`https://securetoken.google.com/${n}`?t.sub?t.sub.length>128?`Token subject is not a valid uid.`:typeof t.exp!=`number`||t.exp<=r?`Token has expired.`:typeof t.iat!=`number`||t.iat>r+l?`Token was issued in the future.`:null:`Token has no subject.`:`Token has the wrong issuer.`:`Token was issued for a different Firebase project.`:`Token has no key id.`:`Token is not signed with RS256.`:`The server does not know its Firebase project id.`}function d(e){return Buffer.from(e.replace(/-/g,`+`).replace(/_/g,`/`),`base64`)}function f(e){let t=String(e||``).split(`.`);if(t.length!==3)return null;try{return{header:JSON.parse(d(t[0]).toString(`utf8`)),claims:JSON.parse(d(t[1]).toString(`utf8`)),signed:`${t[0]}.${t[1]}`,signature:d(t[2])}}catch{return null}}var p=null;async function m(){if(p&&p.expiresAt>Date.now())return p.keys;let e=await fetch(c);if(!e.ok)throw Error(`Could not fetch Google signing keys (${e.status}).`);let t=await e.json(),n=/max-age=(\d+)/.exec(e.headers.get(`cache-control`)||``);return p={keys:t,expiresAt:Date.now()+(n?Number(n[1]):3600)*1e3},t}async function h(e,t){let n=f(e);if(!n)throw Error(`That is not a valid sign-in token.`);let r=u(n.header,n.claims,t);if(r)throw Error(r);let i=(await m())[n.header.kid];if(!i)throw Error(`Token was signed with a key Google no longer publishes.`);let a=(0,o.createVerify)(`RSA-SHA256`);if(a.update(n.signed),a.end(),!a.verify(i,n.signature))throw Error(`Token signature does not check out.`);return{uid:n.claims.sub,email:n.claims.email||null,emailVerified:!!n.claims.email_verified,signInProvider:n.claims.firebase?.sign_in_provider||null}}function g(){return(process.env.VITE_FIREBASE_PROJECT_ID||process.env.FIREBASE_PROJECT_ID||``).trim()}var _=`https://firestore.googleapis.com/v1`;function v(e){return e==null?null:`stringValue`in e?e.stringValue:`integerValue`in e?Number(e.integerValue):`doubleValue`in e?e.doubleValue:`booleanValue`in e?e.booleanValue:`timestampValue`in e?e.timestampValue:`nullValue`in e?null:`mapValue`in e?y(e.mapValue?.fields||{}):`arrayValue`in e?(e.arrayValue?.values||[]).map(v):null}function y(e){let t={};for(let[n,r]of Object.entries(e||{}))t[n]=v(r);return t}function ee(e,t){let n=`${e}/${t}`.split(`/`);if(n.length%2!=0)return`That is not a document path.`;for(let e of n)if(!e||e===`.`||e===`..`||!/^[A-Za-z0-9_.@~+-]+$/.test(e))return`That is not a document path.`;return null}async function b(e,t,n,r){let i=ee(t,n);if(i)throw Error(i);let a=`${_}/projects/${e}/databases/(default)/documents/${t}/${n}`,o=await fetch(a,{headers:r?{Authorization:`Bearer ${r}`}:{}});if(o.status===404)return null;if(o.status===403)throw Error(`You do not have permission to read that record.`);if(!o.ok)throw Error(`Firestore refused the read (${o.status}).`);return y((await o.json()).fields||{})}async function te(e,t,n){if(!/^[A-Za-z0-9_.@~+-]+$/.test(t)||t===`.`||t===`..`)throw Error(`That is not a collection.`);let r=`${_}/projects/${e}/databases/(default)/documents/${t}?pageSize=300`,i=await fetch(r,{headers:n?{Authorization:`Bearer ${n}`}:{}});if(i.status===403)throw Error(`You do not have permission to read those records.`);if(!i.ok)throw Error(`Firestore refused the read (${i.status}).`);return((await i.json()).documents||[]).map(e=>({id:String(e.name||``).split(`/`).pop()||``,data:y(e.fields||{})}))}var ne=[`email`,`Email`,`emailAddress`,`email_address`,`userEmail`,`contactEmail`,`submitterEmail`];function re(e){for(let t of ne){let n=e[t];if(typeof n==`string`&&n.includes(`@`))return n.trim()}return null}var ie=4320*60*1e3,ae=new Set([`user`,`users`,`free`,`guest`,`guests`,`internal`,`admin`,`admins`,`public`,`owner`,`team`,`member`,`members`,`none`,`role`,`roles`]),oe=e=>typeof e==`string`&&/^[a-z][a-z0-9]{1,23}$/.test(e)&&!ae.has(e),se=e=>(0,o.createHmac)(`sha256`,e).update(`your-ai-firebase plan roles v1`).digest(`hex`),ce=(e,t,n,r)=>(0,o.createHash)(`sha256`).update(`${e}:${t}:${n}:${r}`).digest(`hex`);function le(e){let t=new Map;for(let n of e){let e=Array.isArray(n?.plans)?n.plans:[];for(let n of e){let e=String(n?.roleId||``);if(oe(e))for(let r of[n?.monthly,n?.yearly])for(let n of[r?.priceId,r?.livePriceId]){let r=String(n||``).trim();r&&t.set(r,e)}}}return t}var ue=e=>le(e).size>0;function de(e,t,n){let r=null;for(let i of e){if(!i.active||!i.priceId)continue;let e=t.get(i.priceId);if(!e)continue;let a=typeof i.currentPeriodEnd==`number`?i.currentPeriodEnd*1e3:n,o=Math.round(Math.max(a,n)+ie);(!r||o>r.until)&&(r={role:e,until:o})}return r}var fe=`https://api.resend.com/emails`;function pe(){return(process.env.RESEND_API_KEY||``).trim()}function x(){return(process.env.EMAIL_FROM||``).trim()||`onboarding@resend.dev`}function me(){return(process.env.EMAIL_REPLY_TO||``).trim()||void 0}function S(){return(process.env.VITE_ADMIN_EMAILS||process.env.ADMIN_EMAILS||``).split(/[,\s]+/).map(e=>e.trim().toLowerCase()).filter(e=>e.includes(`@`))}var he={appName:``,logoUrl:``,appUrl:``,accent:`#7c3aed`,foreground:`#1e1b4b`,buttonText:``,buttonGradient:[],panelBg:``,panelBorder:``};function C(e,t){let n=String(e??``).trim();return/^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(n)?n:t}function ge(e){let t=String(e??``).trim();return t.length>2e3||/[\s"'<>]/.test(t)?``:/^https?:\/\/[^/]+/i.test(t)?t:``}function _e(e){return String(e??``).replace(/[\r\n\t<>]/g,` `).replace(/\s+/g,` `).trim().slice(0,60)}function ve(e){let t=e&&typeof e==`object`?e:{},n=Array.isArray(t.buttonGradient)?t.buttonGradient.map(e=>C(e,``)).filter(Boolean).slice(0,2):[];return{appName:_e(t.appName),logoUrl:ge(t.logoUrl),appUrl:ge(t.appUrl),accent:C(t.accent,he.accent),foreground:C(t.foreground,he.foreground),buttonText:C(t.buttonText,``),buttonGradient:n,panelBg:C(t.panelBg,``),panelBorder:C(t.panelBorder,``)}}function ye(e){let t=e.replace(`#`,``);if(t.length===3&&(t=t.split(``).map(e=>e+e).join(``)),t.length<6)return null;let n=parseInt(t.slice(0,6),16);return Number.isNaN(n)?null:[n>>16&255,n>>8&255,n&255]}function be(e,t,n=[255,255,255]){let r=ye(e);return r?`#`+r.map((e,r)=>Math.round(e+(n[r]-e)*t)).map(e=>e.toString(16).padStart(2,`0`)).join(``):e}function xe(e){let t=ye(e);return t?(.299*t[0]+.587*t[1]+.114*t[2])/255:1}function Se(e,t=`#1f2937`,n=`#ffffff`){return xe(e)>.6?t:n}function Ce(e){let t=e.accent,n=xe(e.foreground)>.55?he.foreground:e.foreground,r=e.buttonGradient[0]||be(t,.22,[0,0,0]),i=e.buttonGradient[1]||(e.buttonGradient[0]?e.buttonGradient[0]:t),a=e.panelBg||be(t,.94);return{accent:t,text:n,muted:`#6b7280`,faint:`#9ca3af`,g0:r,g1:i,btnFg:e.buttonText||Se(r),panelBg:a,panelBorder:e.panelBorder||(e.panelBg?be(e.panelBg,.12,[0,0,0]):be(t,.84)),hr:be(t,.88)}}var w={test:{audience:`admins`,look:`notification`,kicker:`Test`,subject:`Test email from {{appName}}`,title:`{{appName}} can send email`,opener:`{{appName}} can send email`,body:`This is a test. If you are reading it, the connection works and every email your app sends will look like this one.
|
|
2
2
|
|
|
3
3
|
Sent {{now}}.`,button:{label:`Open the app`},description:`Proves the connection works. Goes to the admin addresses.`},new_submission:{audience:`admins`,look:`notification`,kicker:`New form entry`,subject:`New {{formName}} submission`,title:`Someone filled in {{formName}}`,opener:`Someone filled in {{formName}}`,body:`{{summary}}`,facts:[[`Name`,`{{name}}`],[`Email`,`{{email}}`]],button:{label:`Open the inbox`,path:`/inbox`},description:`Lets you know someone filled in a form.`},submission_received:{audience:`record`,look:`text`,kicker:`Received`,subject:`We got your message`,title:`We got your message`,greeting:`Hi {{name}},`,body:`Thanks for getting in touch — we have your message and will come back to you shortly.
|
|
4
4
|
|
package/dist/server.es.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { S as e, c as t, h as n, t as r, u as i, w as a } from "./verifiedAccount-C1iCxopN.js";
|
|
2
2
|
import { a as o, c as s, i as c, l, m as u, n as d, o as f, r as p, s as m, t as h, u as g } from "./aiModels-BHlEfuRJ.js";
|
|
3
|
-
import { _, a as v, i as ee, p as te } from "./validate-
|
|
3
|
+
import { _, a as v, i as ee, p as te } from "./validate-BTbvTYP_.js";
|
|
4
4
|
import * as ne from "node:fs";
|
|
5
5
|
import y from "express";
|
|
6
6
|
import { createHash as re, createHmac as ie, createVerify as ae } from "node:crypto";
|