@antiphony/shared 0.1.0 → 0.3.0
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/cjs/api-codecs.cjs +26 -650
- package/dist/cjs/api-codecs.d.cts +15 -233
- package/dist/cjs/index.cjs +29 -761
- package/dist/cjs/index.d.cts +4 -4
- package/dist/cjs/nsid.cjs +3 -10
- package/dist/cjs/nsid.d.cts +1 -9
- package/dist/cjs/types/api.cjs +11 -571
- package/dist/cjs/types/api.d.cts +13 -265
- package/dist/cjs/types/audio.cjs +26 -547
- package/dist/cjs/types/audio.d.cts +93 -52
- package/dist/cjs/types/records.cjs +3 -328
- package/dist/cjs/types/records.d.cts +7 -729
- package/dist/cjs/types/views.cjs +8 -649
- package/dist/cjs/types/views.d.cts +43 -9123
- package/dist/esm/api-codecs.d.ts +46 -264
- package/dist/esm/api-codecs.js +5 -5
- package/dist/esm/{chunk-ORMEWXMH.js → chunk-5JBD5THX.js} +1 -16
- package/dist/esm/{chunk-XDBKR6LW.js → chunk-6LROFBKK.js} +3 -10
- package/dist/esm/{chunk-F2CANZZ7.js → chunk-BNNLHRH7.js} +1 -1
- package/dist/esm/{chunk-BUNMR4ZO.js → chunk-F7IHVM34.js} +20 -3
- package/dist/esm/chunk-FDM5FDN4.js +46 -0
- package/dist/esm/chunk-IHIBHQBJ.js +78 -0
- package/dist/esm/chunk-R6SBR3IG.js +97 -0
- package/dist/esm/chunk-Y6HNNRVD.js +12 -0
- package/dist/esm/errors/index.js +1 -1
- package/dist/esm/index.d.ts +4 -4
- package/dist/esm/index.js +8 -8
- package/dist/esm/nsid.d.ts +1 -9
- package/dist/esm/nsid.js +2 -2
- package/dist/esm/observability/index.js +2 -2
- package/dist/esm/observability/report-error.js +2 -2
- package/dist/esm/types/api.d.ts +15 -267
- package/dist/esm/types/api.js +4 -5
- package/dist/esm/types/audio.d.ts +170 -129
- package/dist/esm/types/audio.js +4 -4
- package/dist/esm/types/blob.js +1 -1
- package/dist/esm/types/records.d.ts +10 -732
- package/dist/esm/types/records.js +2 -3
- package/dist/esm/types/views.d.ts +51 -9131
- package/dist/esm/types/views.js +3 -4
- package/dist/esm/utils/index.js +1 -1
- package/package.json +1 -1
- package/dist/cjs/types/channels.cjs +0 -170
- package/dist/cjs/types/channels.d.cts +0 -262
- package/dist/cjs/types/storage.cjs +0 -414
- package/dist/cjs/types/storage.d.cts +0 -197
- package/dist/esm/chunk-3WZJXJNU.js +0 -378
- package/dist/esm/chunk-7V44CPRR.js +0 -132
- package/dist/esm/chunk-EA4OONDV.js +0 -380
- package/dist/esm/chunk-TIZRJORN.js +0 -24
- package/dist/esm/types/channels.d.ts +0 -262
- package/dist/esm/types/channels.js +0 -162
- package/dist/esm/types/storage.d.ts +0 -197
- package/dist/esm/types/storage.js +0 -26
package/dist/cjs/types/views.cjs
CHANGED
|
@@ -2,49 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var zod = require('zod');
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
var __defProps = Object.defineProperties;
|
|
7
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
8
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
9
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
11
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
12
|
-
var __spreadValues = (a, b) => {
|
|
13
|
-
for (var prop in b || (b = {}))
|
|
14
|
-
if (__hasOwnProp.call(b, prop))
|
|
15
|
-
__defNormalProp(a, prop, b[prop]);
|
|
16
|
-
if (__getOwnPropSymbols)
|
|
17
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
18
|
-
if (__propIsEnum.call(b, prop))
|
|
19
|
-
__defNormalProp(a, prop, b[prop]);
|
|
20
|
-
}
|
|
21
|
-
return a;
|
|
22
|
-
};
|
|
23
|
-
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
24
|
-
var __objRest = (source, exclude) => {
|
|
25
|
-
var target = {};
|
|
26
|
-
for (var prop in source)
|
|
27
|
-
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
28
|
-
target[prop] = source[prop];
|
|
29
|
-
if (source != null && __getOwnPropSymbols)
|
|
30
|
-
for (var prop of __getOwnPropSymbols(source)) {
|
|
31
|
-
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
32
|
-
target[prop] = source[prop];
|
|
33
|
-
}
|
|
34
|
-
return target;
|
|
35
|
-
};
|
|
36
|
-
var BlobRefSchema = zod.z.object({
|
|
37
|
-
/** Discriminator for AT Protocol type system */
|
|
38
|
-
$type: zod.z.literal("blob"),
|
|
39
|
-
/** Content Identifier (CID) or URL pointing to the blob */
|
|
40
|
-
ref: zod.z.string(),
|
|
41
|
-
/** MIME type of the blob (e.g., 'audio/webm') */
|
|
42
|
-
mimeType: zod.z.string(),
|
|
43
|
-
/** Size of the blob in bytes */
|
|
44
|
-
size: zod.z.number()
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
// types/records.ts
|
|
5
|
+
// types/views.ts
|
|
48
6
|
function httpsUrl() {
|
|
49
7
|
return zod.z.string().trim().url().refine((u) => /^https?:\/\//i.test(u), {
|
|
50
8
|
message: "URL must use the http or https scheme"
|
|
@@ -87,11 +45,8 @@ zod.z.object({
|
|
|
87
45
|
handle: zod.z.string().min(3).max(20).regex(/^[a-zA-Z0-9_]+$/).nullable().optional(),
|
|
88
46
|
/** User stated intent (e.g. "Podcaster", "Listener") */
|
|
89
47
|
usageIntent: zod.z.string().nullable().optional(),
|
|
90
|
-
/**
|
|
91
|
-
|
|
92
|
-
* Defaults to 'voxpop.com'.
|
|
93
|
-
*/
|
|
94
|
-
domain: zod.z.string().default("voxpop.com"),
|
|
48
|
+
/** Domain for federated handle support. */
|
|
49
|
+
domain: zod.z.string().default("antiphony.dev"),
|
|
95
50
|
/**
|
|
96
51
|
* Display Name (e.g. "Brad Thorson"). Nullable: Firestore stores `null`
|
|
97
52
|
* when the user clears this field via the settings form, and the schema
|
|
@@ -119,304 +74,7 @@ zod.z.object({
|
|
|
119
74
|
/** Account status. Deactivated accounts retain data but are excluded from lookups. */
|
|
120
75
|
status: zod.z.enum(["active", "deactivated"]).default("active"),
|
|
121
76
|
/** Timestamp when the account was deactivated (soft deleted) */
|
|
122
|
-
deactivatedAt: FirestoreTimestampSchema.optional()
|
|
123
|
-
/**
|
|
124
|
-
* Denormalized org memberships — { orgId: role } for fast lookup.
|
|
125
|
-
* Source of truth is organizations/{orgId}/members/{userId}.
|
|
126
|
-
* Kept in sync by Cloud Function trigger.
|
|
127
|
-
*/
|
|
128
|
-
orgMemberships: zod.z.record(zod.z.string(), zod.z.enum(["owner", "admin", "member"])).optional()
|
|
129
|
-
});
|
|
130
|
-
var PromptRecordSchema = zod.z.object({
|
|
131
|
-
/** Unique Prompt ID */
|
|
132
|
-
id: zod.z.string(),
|
|
133
|
-
/** ID of the User who created this prompt. Always a user ID, never an org ID. @see UserRecord */
|
|
134
|
-
authorId: zod.z.string(),
|
|
135
|
-
/** Organization context this prompt belongs to (null = personal/no org) */
|
|
136
|
-
orgId: zod.z.string().nullable().optional(),
|
|
137
|
-
/** The main text of the question/prompt */
|
|
138
|
-
title: zod.z.string().min(3),
|
|
139
|
-
/** Optional extra context */
|
|
140
|
-
description: zod.z.string().nullable().optional(),
|
|
141
|
-
/** User who created this prompt (differs from authorId when org-owned) */
|
|
142
|
-
createdBy: zod.z.string().optional(),
|
|
143
|
-
/** URL to the recorded audio file (GCS) */
|
|
144
|
-
audioUrl: zod.z.string().url().or(zod.z.literal("")),
|
|
145
|
-
/** AT Protocol blob reference (future replacement for audioUrl) */
|
|
146
|
-
audio: BlobRefSchema.optional(),
|
|
147
|
-
/**
|
|
148
|
-
* AT Protocol URI returned by the publisher after a successful
|
|
149
|
-
* `repo.putRecord` against the author's PDS — e.g.
|
|
150
|
-
* `at://did:plc:abc123/com.voxpop.audio.prompt/3kj4...`. Optional,
|
|
151
|
-
* no migration: existing rows leave it unset. Format-validated so
|
|
152
|
-
* malformed strings surface at the schema-parse boundary rather than
|
|
153
|
-
* being silently stored.
|
|
154
|
-
*/
|
|
155
|
-
atprotoUri: zod.z.string().regex(/^at:\/\/.+/).optional(),
|
|
156
|
-
/** Server timestamp of creation */
|
|
157
|
-
createdAt: FirestoreTimestampSchema,
|
|
158
|
-
/**
|
|
159
|
-
* Life-cycle status.
|
|
160
|
-
* - `live`: Visible and accepting replies.
|
|
161
|
-
* - `archived`: Visible but closed for new replies.
|
|
162
|
-
* - `deleted`: Soft deleted.
|
|
163
|
-
*/
|
|
164
|
-
status: zod.z.enum(["live", "archived", "deleted"]).default("live"),
|
|
165
|
-
/** AI Enrichment Fields */
|
|
166
|
-
aiStatus: zod.z.enum(["pending", "complete", "error"]).optional(),
|
|
167
|
-
aiError: zod.z.string().optional(),
|
|
168
|
-
aiSummary: zod.z.string().optional(),
|
|
169
|
-
aiLabels: zod.z.array(zod.z.string()).optional(),
|
|
170
|
-
transcription: zod.z.string().optional(),
|
|
171
|
-
/** Pre-computed waveform peaks (normalized 0–1) for instant audio visualization */
|
|
172
|
-
waveformPeaks: zod.z.array(zod.z.number()).optional(),
|
|
173
|
-
/** Social Share Video Fields */
|
|
174
|
-
socialVideoUrl: zod.z.string().url().optional(),
|
|
175
|
-
socialVideoStoragePath: zod.z.string().optional(),
|
|
176
|
-
socialVideoStatus: zod.z.enum(["pending", "complete", "error"]).optional(),
|
|
177
|
-
socialVideoError: zod.z.string().optional(),
|
|
178
|
-
/** The audio URL/path used to generate the current video (for cache invalidation) */
|
|
179
|
-
socialVideoSourceAudio: zod.z.string().optional()
|
|
180
|
-
});
|
|
181
|
-
var ReplyRecordSchema = zod.z.object({
|
|
182
|
-
/** Unique Reply ID */
|
|
183
|
-
id: zod.z.string(),
|
|
184
|
-
/** The Prompt being replied to. @see PromptRecord */
|
|
185
|
-
promptId: zod.z.string(),
|
|
186
|
-
/** The User who replied. @see UserRecord */
|
|
187
|
-
authorId: zod.z.string(),
|
|
188
|
-
/** URL to the recorded audio file (GCS) */
|
|
189
|
-
audioUrl: zod.z.string().url(),
|
|
190
|
-
/** AT Protocol blob reference (future replacement for audioUrl) */
|
|
191
|
-
audio: BlobRefSchema.optional(),
|
|
192
|
-
/** Server timestamp of creation */
|
|
193
|
-
createdAt: FirestoreTimestampSchema,
|
|
194
|
-
/**
|
|
195
|
-
* Life-cycle status.
|
|
196
|
-
* - `live`: Visible and accepting replies.
|
|
197
|
-
* - `archived`: Visible but closed for new replies.
|
|
198
|
-
* - `deleted`: Soft deleted.
|
|
199
|
-
*/
|
|
200
|
-
status: zod.z.enum(["live", "archived", "deleted"]).default("live"),
|
|
201
|
-
/**
|
|
202
|
-
* Pre-computed waveform peaks (normalized 0–1) for instant audio
|
|
203
|
-
* visualization. **Stays on canonical** (does NOT move to the
|
|
204
|
-
* enrichment doc) — produced by a plain ffmpeg pass at ingestion,
|
|
205
|
-
* not an AI step; a self-hoster without paid-tier AI still needs
|
|
206
|
-
* this on every reply for the audio player. See
|
|
207
|
-
* `specs/ai-enrichment-split.md` § 5.
|
|
208
|
-
*/
|
|
209
|
-
waveformPeaks: zod.z.array(zod.z.number()).optional(),
|
|
210
|
-
/**
|
|
211
|
-
* Duration of the audio in seconds, computed server-side from
|
|
212
|
-
* ffmpeg. **Stays on canonical** (same reasoning as `waveformPeaks`
|
|
213
|
-
* above — ingestion ffmpeg output, not an AI enrichment). See
|
|
214
|
-
* `specs/ai-enrichment-split.md` § 5.
|
|
215
|
-
*/
|
|
216
|
-
audioDurationSec: zod.z.number().optional()
|
|
217
|
-
});
|
|
218
|
-
zod.z.object({
|
|
219
|
-
id: zod.z.string(),
|
|
220
|
-
/** Private notes by the prompt author about this reply. */
|
|
221
|
-
notes: zod.z.string().optional(),
|
|
222
|
-
// === AI-enrichment fields (sole source of truth post Stage 4) ===
|
|
223
|
-
//
|
|
224
|
-
// These lifted off canonical in Stage 4 of `specs/ai-enrichment-split.md`.
|
|
225
|
-
// Writers (`functions/`) route AI updates here via the split-write
|
|
226
|
-
// helper in `functions/src/services/replyEnrichmentDualWrite.ts`;
|
|
227
|
-
// readers source them via the hydrator's enrichment branch (see
|
|
228
|
-
// `packages/core/services/hydration.ts`).
|
|
229
|
-
// --- AI core (Gemini-generated) ---
|
|
230
|
-
aiStatus: zod.z.enum(["pending", "complete", "error", "skipped_too_short"]).optional(),
|
|
231
|
-
aiError: zod.z.string().optional(),
|
|
232
|
-
aiSummary: zod.z.string().optional(),
|
|
233
|
-
aiLabels: zod.z.array(zod.z.string()).optional(),
|
|
234
|
-
transcription: zod.z.string().optional(),
|
|
235
|
-
sentiment: zod.z.enum(["Positive", "Negative", "Neutral"]).optional(),
|
|
236
|
-
/** Must match the widened enum in `ReplyRecordSchema.energyLevel`. */
|
|
237
|
-
energyLevel: zod.z.enum(["High", "Low", "Neutral"]).optional(),
|
|
238
|
-
engagementScore: zod.z.number().min(1).max(10).optional(),
|
|
239
|
-
// --- Voice isolation (ElevenLabs, paid tier) ---
|
|
240
|
-
/** Noise-reduced audio URL — replaces `audioUrl` for downstream players when present. PUBLIC. */
|
|
241
|
-
enhancedAudioUrl: zod.z.string().url().optional(),
|
|
242
|
-
/** Storage path companion to `enhancedAudioUrl` — private. */
|
|
243
|
-
enhancedStoragePath: zod.z.string().optional(),
|
|
244
|
-
// --- Social-share video (paid tier) ---
|
|
245
|
-
//
|
|
246
|
-
// All `socialVideo*` fields are creator-only. The URL points at the
|
|
247
|
-
// generated artifact (a video file the creator can download and post
|
|
248
|
-
// to social media); the reply detail page does NOT render it.
|
|
249
|
-
socialVideoUrl: zod.z.string().url().optional(),
|
|
250
|
-
socialVideoStoragePath: zod.z.string().optional(),
|
|
251
|
-
socialVideoStatus: zod.z.enum(["pending", "complete", "error"]).optional(),
|
|
252
|
-
socialVideoError: zod.z.string().optional(),
|
|
253
|
-
/** The audio URL/path used to generate the current video (for cache invalidation). */
|
|
254
|
-
socialVideoSourceAudio: zod.z.string().optional()
|
|
255
|
-
});
|
|
256
|
-
zod.z.object({
|
|
257
|
-
/** Composite key `${viewerUid}_${targetUid}`. */
|
|
258
|
-
id: zod.z.string(),
|
|
259
|
-
/** Per-viewer CRM notes about the target. */
|
|
260
|
-
notes: zod.z.string().optional(),
|
|
261
|
-
/** Per-viewer freeform tags about the target. */
|
|
262
|
-
tags: zod.z.array(zod.z.string()).optional(),
|
|
263
|
-
// === Identity-merge: alias set ===
|
|
264
|
-
//
|
|
265
|
-
// Other identifiers the viewer has declared to be the SAME person as
|
|
266
|
-
// this entry's `targetUid`. vCard/URI-aligned: each entry is a
|
|
267
|
-
// scheme-prefixed identifier, so one field generalizes across networks
|
|
268
|
-
// AND across the future contact-sync import (which carries phone/email):
|
|
269
|
-
// "uid:<firebaseUid>" | "did:plc:…" | "handle:bob.bsky.social"
|
|
270
|
-
// | "tel:+15551234567" | "mailto:x@example.com"
|
|
271
|
-
// Mirrors vCard 4.0's `UID` + `CLIENTPIDMAP`/`PID` source-tracking
|
|
272
|
-
// (RFC 6350) — the standard answer to "the same person from multiple
|
|
273
|
-
// sources". See `specs/people-lexicon-prior-art.md`. The People
|
|
274
|
-
// read-path collapses any replier whose "uid:<uid>" appears here into
|
|
275
|
-
// this primary entry. Empty until the merge feature is used.
|
|
276
|
-
aliases: zod.z.array(zod.z.string()).optional(),
|
|
277
|
-
lastUpdated: FirestoreTimestampSchema.optional()
|
|
278
|
-
});
|
|
279
|
-
zod.z.object({
|
|
280
|
-
sipUri: zod.z.string(),
|
|
281
|
-
sipUsername: zod.z.string(),
|
|
282
|
-
sipSecret: zod.z.string(),
|
|
283
|
-
provider: zod.z.enum(["twilio", "plivo", "internal"])
|
|
284
|
-
});
|
|
285
|
-
zod.z.object({
|
|
286
|
-
/** User's personal phone number (E.164) */
|
|
287
|
-
phoneNumber: zod.z.string(),
|
|
288
|
-
/** Line type from Twilio Lookup v2 */
|
|
289
|
-
lineType: zod.z.string().nullable(),
|
|
290
|
-
/** Carrier name from Twilio Lookup v2 */
|
|
291
|
-
carrier: zod.z.string().nullable(),
|
|
292
|
-
/** free = shared Twilio number (ForwardedFrom routing), paid = dedicated number */
|
|
293
|
-
tier: zod.z.enum(["free", "paid"]),
|
|
294
|
-
/** The VoxPop Twilio number calls forward to (E.164) */
|
|
295
|
-
voxpopNumber: zod.z.string(),
|
|
296
|
-
/** Twilio Phone Number SID (paid tier only) */
|
|
297
|
-
twilioNumberSid: zod.z.string().nullable().optional(),
|
|
298
|
-
/** Forwarding verification state */
|
|
299
|
-
verificationStatus: zod.z.enum(["pending", "verifying", "verified", "failed"]).default("pending"),
|
|
300
|
-
/** Last verification attempt timestamp */
|
|
301
|
-
lastVerificationAt: FirestoreTimestampSchema.optional(),
|
|
302
|
-
/** Number of verification attempts */
|
|
303
|
-
verificationAttempts: zod.z.number().default(0),
|
|
304
|
-
/** Reason for verification failure */
|
|
305
|
-
failureReason: zod.z.string().nullable().optional(),
|
|
306
|
-
/** Whether call forwarding is active */
|
|
307
|
-
enabled: zod.z.boolean().default(false),
|
|
308
|
-
createdAt: FirestoreTimestampSchema,
|
|
309
|
-
updatedAt: FirestoreTimestampSchema
|
|
310
|
-
});
|
|
311
|
-
var ConnectorTypeSchema = zod.z.enum(["telephony"]);
|
|
312
|
-
var ConnectorStatusSchema = zod.z.object({
|
|
313
|
-
/** Coarse, generic lifecycle the control-plane UI can render without
|
|
314
|
-
* connector-specific knowledge. */
|
|
315
|
-
state: zod.z.enum(["unconfigured", "pending", "active", "error", "disabled"]).default("unconfigured"),
|
|
316
|
-
detail: zod.z.string().nullable().optional(),
|
|
317
|
-
/** Opaque, connector-specific status detail (e.g. telephony's
|
|
318
|
-
* `{ verificationStatus, verificationAttempts, failureReason }`). Connector-
|
|
319
|
-
* owned like the rest of `status` — never user-writable. Nullable so a doc
|
|
320
|
-
* that stored `data: null` round-trips without a parse error. */
|
|
321
|
-
data: zod.z.record(zod.z.unknown()).nullable().optional(),
|
|
322
|
-
updatedAt: FirestoreTimestampSchema.optional()
|
|
323
|
-
});
|
|
324
|
-
zod.z.object({
|
|
325
|
-
connectorType: ConnectorTypeSchema,
|
|
326
|
-
/** The owning user. Org-scoping (ownerId as an orgId) is a later step. */
|
|
327
|
-
ownerId: zod.z.string(),
|
|
328
|
-
/** Opaque, connector-specific blob. Core does not interpret this. */
|
|
329
|
-
settings: zod.z.record(zod.z.unknown()).default({}),
|
|
330
|
-
/** Reference into a secret store (e.g. Secret Manager key). Never a raw secret. */
|
|
331
|
-
secretRef: zod.z.string().nullable().optional(),
|
|
332
|
-
enabled: zod.z.boolean().default(false),
|
|
333
|
-
status: ConnectorStatusSchema.default({ state: "unconfigured" }),
|
|
334
|
-
createdAt: FirestoreTimestampSchema,
|
|
335
|
-
updatedAt: FirestoreTimestampSchema
|
|
336
|
-
});
|
|
337
|
-
zod.z.object({
|
|
338
|
-
id: zod.z.string(),
|
|
339
|
-
ownerId: zod.z.string(),
|
|
340
|
-
/** The caller number this rule matches (E.164). Format-enforced at the
|
|
341
|
-
* record level so any writer (API, future contact-sync/callback) can't
|
|
342
|
-
* persist a malformed number. */
|
|
343
|
-
e164: zod.z.string().regex(/^\+[1-9]\d{6,14}$/, "Must be an E.164 phone number"),
|
|
344
|
-
/** Display label, e.g. "Mom" / "Delta Airlines". null = unlabeled. */
|
|
345
|
-
label: zod.z.string().nullable().optional(),
|
|
346
|
-
/** `allow` = ring through; `screen` = async voicemail. */
|
|
347
|
-
action: zod.z.enum(["allow", "screen"]),
|
|
348
|
-
/** Provenance. `manual` = user-created; the others are future writers. */
|
|
349
|
-
source: zod.z.enum(["manual", "contact-sync", "callback"]),
|
|
350
|
-
/** null = permanent; a date = self-expiring exception. */
|
|
351
|
-
expiresAt: FirestoreTimestampSchema.nullable().optional(),
|
|
352
|
-
createdAt: FirestoreTimestampSchema
|
|
353
|
-
});
|
|
354
|
-
var OrganizationRecordSchema = zod.z.object({
|
|
355
|
-
id: zod.z.string(),
|
|
356
|
-
/** Display name of the organization */
|
|
357
|
-
name: zod.z.string().min(3).max(50),
|
|
358
|
-
/**
|
|
359
|
-
* Unique handle for the organization (e.g. voxpop.com/@mypodcast).
|
|
360
|
-
* Used for public URLs.
|
|
361
|
-
*/
|
|
362
|
-
slug: zod.z.string().min(3).max(30).regex(/^[a-z0-9-]+$/),
|
|
363
|
-
/** URL to avatar/logo */
|
|
364
|
-
avatarUrl: zod.z.string().url().optional(),
|
|
365
|
-
/** URL to the podcast RSS feed */
|
|
366
|
-
rssFeedUrl: zod.z.string().url().optional(),
|
|
367
|
-
/** External website URL */
|
|
368
|
-
websiteUrl: httpsUrl().optional(),
|
|
369
|
-
/** Description or tagline */
|
|
370
|
-
description: zod.z.string().optional(),
|
|
371
|
-
/** Owner ID (User ID) */
|
|
372
|
-
ownerId: zod.z.string(),
|
|
373
|
-
/** Server timestamp of creation */
|
|
374
|
-
createdAt: FirestoreTimestampSchema,
|
|
375
|
-
/** Verified domain (e.g., "acme.com") — enables auto-join, enterprise features */
|
|
376
|
-
domain: zod.z.string().nullable().optional(),
|
|
377
|
-
/** Whether the domain has been verified via DNS TXT record */
|
|
378
|
-
domainVerified: zod.z.boolean().default(false),
|
|
379
|
-
/** DNS verification token (stored server-side until verification completes) */
|
|
380
|
-
domainVerificationToken: zod.z.string().optional(),
|
|
381
|
-
/** Billing email — required for paid orgs, where invoices go */
|
|
382
|
-
billingEmail: zod.z.string().email().nullable().optional(),
|
|
383
|
-
/**
|
|
384
|
-
* Tier determines isolation and feature set. Orgs are meant to be paid
|
|
385
|
-
* (business or enterprise); free/pro exist on the enum for the individual track.
|
|
386
|
-
* Default is provisionally `business` (the entry paid tier) — it's assigned at
|
|
387
|
-
* creation with no subscription behind it yet, so it stays provisional until billing
|
|
388
|
-
* promotes/reconciles the org. See docs/tech-debt.md "Org tier billing reconciliation".
|
|
389
|
-
*/
|
|
390
|
-
tier: zod.z.enum(["free", "pro", "business", "enterprise"]).default("business"),
|
|
391
|
-
/** Stripe Customer ID */
|
|
392
|
-
stripeCustomerId: zod.z.string().optional(),
|
|
393
|
-
/** Subscription Status */
|
|
394
|
-
subscriptionStatus: zod.z.enum(["active", "trialing", "past_due", "canceled", "unpaid"]).optional()
|
|
395
|
-
});
|
|
396
|
-
var OrganizationMemberRecordSchema = zod.z.object({
|
|
397
|
-
orgId: zod.z.string(),
|
|
398
|
-
userId: zod.z.string(),
|
|
399
|
-
/** Role in the organization */
|
|
400
|
-
role: zod.z.enum(["owner", "admin", "member"]),
|
|
401
|
-
/** Server timestamp of joining */
|
|
402
|
-
joinedAt: FirestoreTimestampSchema,
|
|
403
|
-
invitedBy: zod.z.string().optional()
|
|
404
|
-
});
|
|
405
|
-
var OrgInviteRecordSchema = zod.z.object({
|
|
406
|
-
id: zod.z.string(),
|
|
407
|
-
orgId: zod.z.string(),
|
|
408
|
-
/** Email the invite was sent to */
|
|
409
|
-
email: zod.z.string().email(),
|
|
410
|
-
/** Role to assign on acceptance */
|
|
411
|
-
role: zod.z.enum(["admin", "member"]),
|
|
412
|
-
/** User ID of who sent the invite */
|
|
413
|
-
invitedBy: zod.z.string(),
|
|
414
|
-
/** Invite lifecycle status */
|
|
415
|
-
status: zod.z.enum(["pending", "accepted", "expired", "revoked"]).default("pending"),
|
|
416
|
-
/** Server timestamp of creation */
|
|
417
|
-
createdAt: FirestoreTimestampSchema,
|
|
418
|
-
/** When this invite expires */
|
|
419
|
-
expiresAt: FirestoreTimestampSchema
|
|
77
|
+
deactivatedAt: FirestoreTimestampSchema.optional()
|
|
420
78
|
});
|
|
421
79
|
|
|
422
80
|
// types/views.ts
|
|
@@ -425,9 +83,7 @@ var ProfileViewBasicSchema = zod.z.object({
|
|
|
425
83
|
handle: zod.z.string().nullable().optional(),
|
|
426
84
|
// `displayName` and `bio` are `.nullable()` — Firestore stores `null` for
|
|
427
85
|
// empty values on these fields (see users-dependencies.ts), and Zod's
|
|
428
|
-
// `.optional()` alone rejects `null`.
|
|
429
|
-
// Phase 3.1 HTTP cutover, when transport-layer Zod validation started
|
|
430
|
-
// actually exercising the wire shape. Consumers already use truthy
|
|
86
|
+
// `.optional()` alone rejects `null`. Consumers already use truthy
|
|
431
87
|
// checks / `??` / `||`, so widening the type to include `null` is safe.
|
|
432
88
|
displayName: zod.z.string().nullable().optional(),
|
|
433
89
|
avatarUrl: zod.z.string().nullable().optional(),
|
|
@@ -480,24 +136,7 @@ var ProfileViewDetailedSchema = ProfileViewBasicSchema.extend({
|
|
|
480
136
|
handle: zod.z.string(),
|
|
481
137
|
did: zod.z.string()
|
|
482
138
|
}).optional(),
|
|
483
|
-
usageIntent: zod.z.string().nullable().optional()
|
|
484
|
-
/** Hydrated RSS Data (fetched from sub-collection) */
|
|
485
|
-
rssSummary: zod.z.object({
|
|
486
|
-
title: zod.z.string().optional(),
|
|
487
|
-
description: zod.z.string().optional(),
|
|
488
|
-
items: zod.z.array(zod.z.object({
|
|
489
|
-
title: zod.z.string().optional(),
|
|
490
|
-
link: zod.z.string().optional(),
|
|
491
|
-
content: zod.z.string().optional(),
|
|
492
|
-
pubDate: zod.z.string().optional()
|
|
493
|
-
})).optional(),
|
|
494
|
-
lastFetchedAt: FirestoreTimestampSchema.optional()
|
|
495
|
-
}).optional(),
|
|
496
|
-
promptAudioUrl: zod.z.string().optional(),
|
|
497
|
-
/** @deprecated Use stats.prompts from ProfileViewBasic instead */
|
|
498
|
-
totalPrompts: zod.z.number().optional(),
|
|
499
|
-
totalReplies: zod.z.number().optional(),
|
|
500
|
-
favoritePromptId: zod.z.string().optional()
|
|
139
|
+
usageIntent: zod.z.string().nullable().optional()
|
|
501
140
|
});
|
|
502
141
|
var ProfileViewSelfSchema = ProfileViewDetailedSchema.extend({
|
|
503
142
|
phoneNumber: zod.z.string().nullable().optional(),
|
|
@@ -508,9 +147,8 @@ var ProfileViewSelfSchema = ProfileViewDetailedSchema.extend({
|
|
|
508
147
|
newReplierCount: zod.z.number().default(0),
|
|
509
148
|
/**
|
|
510
149
|
* Account tier from UserRecord — surfaced on the self profile so the
|
|
511
|
-
* client can gate paid features
|
|
512
|
-
*
|
|
513
|
-
* missing as `'free'`.
|
|
150
|
+
* client can gate paid features. Optional for legacy docs without the
|
|
151
|
+
* field; consumers should treat missing as `'free'`.
|
|
514
152
|
*/
|
|
515
153
|
tier: zod.z.enum(["free", "creator_pro"]).optional(),
|
|
516
154
|
/**
|
|
@@ -532,289 +170,10 @@ var ProfileViewAdminSchema = ProfileViewSelfSchema.extend({
|
|
|
532
170
|
isBanned: zod.z.boolean().optional()
|
|
533
171
|
});
|
|
534
172
|
var ProfileViewSchema = ProfileViewAdminSchema;
|
|
535
|
-
var PromptViewSchema = zod.z.object({
|
|
536
|
-
/** AT Protocol URI (e.g. at://did:plc.../app.../123) */
|
|
537
|
-
uri: zod.z.string().optional(),
|
|
538
|
-
/** IPFS Content ID */
|
|
539
|
-
cid: zod.z.string().optional(),
|
|
540
|
-
/** The raw prompt data */
|
|
541
|
-
record: PromptRecordSchema,
|
|
542
|
-
/** The hydrated author profile */
|
|
543
|
-
author: ProfileViewSchema,
|
|
544
|
-
/** Total number of replies */
|
|
545
|
-
replyCount: zod.z.number().default(0),
|
|
546
|
-
likeCount: zod.z.number().default(0),
|
|
547
|
-
updatedAt: FirestoreTimestampSchema.optional(),
|
|
548
|
-
lastReplyAt: FirestoreTimestampSchema.optional(),
|
|
549
|
-
tags: zod.z.array(zod.z.string()).optional(),
|
|
550
|
-
visibility: zod.z.enum(["public", "private", "unlisted", "archived"]).default("public"),
|
|
551
|
-
analytics: zod.z.object({
|
|
552
|
-
views: zod.z.number().default(0),
|
|
553
|
-
listens: zod.z.number().default(0),
|
|
554
|
-
/**
|
|
555
|
-
* Mean engagementScore (1–10) across this prompt's `status: 'live'`
|
|
556
|
-
* replies that completed AI enrichment. `null` when no such replies
|
|
557
|
-
* exist (0 would alias a valid bottom-of-range score). Derived in
|
|
558
|
-
* hydration from the prompt doc's `engagementScoreSum / Count`.
|
|
559
|
-
*/
|
|
560
|
-
avgEngagementScore: zod.z.number().nullable().optional(),
|
|
561
|
-
/**
|
|
562
|
-
* Counts of `status: 'live'` AI-enriched replies grouped by sentiment.
|
|
563
|
-
* Keys lowercase by convention; source enum
|
|
564
|
-
* (`Positive | Neutral | Negative`) is mapped at the write site.
|
|
565
|
-
*/
|
|
566
|
-
sentimentBreakdown: zod.z.object({
|
|
567
|
-
positive: zod.z.number(),
|
|
568
|
-
neutral: zod.z.number(),
|
|
569
|
-
negative: zod.z.number()
|
|
570
|
-
}).optional()
|
|
571
|
-
}).optional(),
|
|
572
|
-
moderation: zod.z.object({
|
|
573
|
-
flagged: zod.z.boolean().default(false),
|
|
574
|
-
reason: zod.z.string().optional()
|
|
575
|
-
}).optional(),
|
|
576
|
-
// AI Enrichment Fields (Hydrated from Record but hidden from Record Schema)
|
|
577
|
-
aiLabels: zod.z.array(zod.z.string()).optional(),
|
|
578
|
-
aiSummary: zod.z.string().optional(),
|
|
579
|
-
aiStatus: zod.z.enum(["pending", "complete", "error"]).optional(),
|
|
580
|
-
aiError: zod.z.string().optional(),
|
|
581
|
-
transcription: zod.z.string().optional()
|
|
582
|
-
});
|
|
583
|
-
var PromptViewPublicSchema = PromptViewSchema.omit({
|
|
584
|
-
analytics: true,
|
|
585
|
-
moderation: true,
|
|
586
|
-
aiLabels: true,
|
|
587
|
-
aiSummary: true,
|
|
588
|
-
aiStatus: true,
|
|
589
|
-
aiError: true,
|
|
590
|
-
transcription: true
|
|
591
|
-
}).extend({
|
|
592
|
-
author: ProfileViewBasicSchema
|
|
593
|
-
});
|
|
594
|
-
function toPromptViewPublic(prompt) {
|
|
595
|
-
const _a = prompt, { analytics, moderation, aiLabels, aiSummary, aiStatus, aiError, transcription } = _a, rest = __objRest(_a, ["analytics", "moderation", "aiLabels", "aiSummary", "aiStatus", "aiError", "transcription"]);
|
|
596
|
-
return __spreadProps(__spreadValues({}, rest), {
|
|
597
|
-
author: toProfileViewBasic(rest.author)
|
|
598
|
-
});
|
|
599
|
-
}
|
|
600
|
-
var ReplyViewSchema = zod.z.object({
|
|
601
|
-
record: ReplyRecordSchema,
|
|
602
|
-
author: ProfileViewSchema,
|
|
603
|
-
recipient: ProfileViewSchema,
|
|
604
|
-
/** GCS Storage Path for audio file */
|
|
605
|
-
storagePath: zod.z.string().optional(),
|
|
606
|
-
duration: zod.z.number().optional(),
|
|
607
|
-
updatedAt: FirestoreTimestampSchema.optional(),
|
|
608
|
-
isRead: zod.z.boolean(),
|
|
609
|
-
readBy: zod.z.array(zod.z.string()).default([]),
|
|
610
|
-
isDeleted: zod.z.boolean().default(false),
|
|
611
|
-
reactions: zod.z.record(zod.z.string(), zod.z.number()).optional(),
|
|
612
|
-
moderation: zod.z.object({
|
|
613
|
-
flagged: zod.z.boolean().default(false),
|
|
614
|
-
reason: zod.z.string().optional()
|
|
615
|
-
}).optional(),
|
|
616
|
-
// AI Enrichment Fields (Hydrated from Record but hidden from Record Schema)
|
|
617
|
-
aiLabels: zod.z.array(zod.z.string()).optional(),
|
|
618
|
-
aiSummary: zod.z.string().optional(),
|
|
619
|
-
aiStatus: zod.z.enum(["pending", "complete", "error", "skipped_too_short"]).optional(),
|
|
620
|
-
aiError: zod.z.string().optional(),
|
|
621
|
-
transcription: zod.z.string().optional(),
|
|
622
|
-
sentiment: zod.z.enum(["Positive", "Negative", "Neutral"]).optional(),
|
|
623
|
-
/** Must match the widened enum in `ReplyRecordSchema.energyLevel`. */
|
|
624
|
-
energyLevel: zod.z.enum(["High", "Low", "Neutral"]).optional(),
|
|
625
|
-
engagementScore: zod.z.number().min(1).max(10).optional(),
|
|
626
|
-
// === Voice-isolation enrichment (lifted; see specs/ai-enrichment-split.md) ===
|
|
627
|
-
//
|
|
628
|
-
// `enhancedAudioUrl` is the only one of these the public view keeps —
|
|
629
|
-
// it replaces `audioUrl` for downstream players when present.
|
|
630
|
-
// `enhancedStoragePath` is private (storage paths are server-side
|
|
631
|
-
// bookkeeping).
|
|
632
|
-
enhancedAudioUrl: zod.z.string().url().optional(),
|
|
633
|
-
enhancedStoragePath: zod.z.string().optional(),
|
|
634
|
-
// === Social-share video enrichment (lifted; creator-only) ===
|
|
635
|
-
//
|
|
636
|
-
// All `socialVideo*` fields are stripped by `toReplyViewPublic` —
|
|
637
|
-
// the URL points at a generated artifact the creator may share to
|
|
638
|
-
// social media, NOT at content the reply page should render. Status /
|
|
639
|
-
// error / source-audio are job-tracking state.
|
|
640
|
-
socialVideoUrl: zod.z.string().url().optional(),
|
|
641
|
-
socialVideoStoragePath: zod.z.string().optional(),
|
|
642
|
-
socialVideoStatus: zod.z.enum(["pending", "complete", "error"]).optional(),
|
|
643
|
-
socialVideoError: zod.z.string().optional(),
|
|
644
|
-
socialVideoSourceAudio: zod.z.string().optional(),
|
|
645
|
-
/** @private Confirmed listener phone number (never exposed publicly) */
|
|
646
|
-
listenerPhoneNumber: zod.z.string().regex(/^\+[1-9]\d{1,14}$/).optional(),
|
|
647
|
-
/**
|
|
648
|
-
* @private Per-viewer private notes about this reply (CRM enrichment).
|
|
649
|
-
* Lifted into the view from `enrichments/replies/{id}.notes` by the
|
|
650
|
-
* hydrator when the viewer is the prompt author. Never populated for
|
|
651
|
-
* non-author viewers; defensively stripped by `toReplyViewPublic`.
|
|
652
|
-
*/
|
|
653
|
-
notes: zod.z.string().optional()
|
|
654
|
-
});
|
|
655
|
-
var ReplyViewPublicSchema = ReplyViewSchema.omit({
|
|
656
|
-
listenerPhoneNumber: true,
|
|
657
|
-
notes: true,
|
|
658
|
-
// AI cluster — only `transcription` survives.
|
|
659
|
-
aiStatus: true,
|
|
660
|
-
aiError: true,
|
|
661
|
-
aiSummary: true,
|
|
662
|
-
aiLabels: true,
|
|
663
|
-
sentiment: true,
|
|
664
|
-
energyLevel: true,
|
|
665
|
-
engagementScore: true,
|
|
666
|
-
// Voice isolation — keep enhancedAudioUrl, strip the path.
|
|
667
|
-
enhancedStoragePath: true,
|
|
668
|
-
// Social-video — entire cluster is creator-only.
|
|
669
|
-
socialVideoUrl: true,
|
|
670
|
-
socialVideoStoragePath: true,
|
|
671
|
-
socialVideoStatus: true,
|
|
672
|
-
socialVideoError: true,
|
|
673
|
-
socialVideoSourceAudio: true
|
|
674
|
-
});
|
|
675
|
-
function toReplyViewPublic(reply) {
|
|
676
|
-
const _a = reply, {
|
|
677
|
-
listenerPhoneNumber,
|
|
678
|
-
notes,
|
|
679
|
-
aiStatus: aiStatus,
|
|
680
|
-
aiError,
|
|
681
|
-
aiSummary,
|
|
682
|
-
aiLabels,
|
|
683
|
-
sentiment,
|
|
684
|
-
energyLevel,
|
|
685
|
-
engagementScore,
|
|
686
|
-
enhancedStoragePath: enhancedStoragePath,
|
|
687
|
-
socialVideoUrl: socialVideoUrl,
|
|
688
|
-
socialVideoStoragePath,
|
|
689
|
-
socialVideoStatus,
|
|
690
|
-
socialVideoError,
|
|
691
|
-
socialVideoSourceAudio
|
|
692
|
-
} = _a, publicReply = __objRest(_a, [
|
|
693
|
-
"listenerPhoneNumber",
|
|
694
|
-
"notes",
|
|
695
|
-
// AI cluster (only transcription stays public)
|
|
696
|
-
"aiStatus",
|
|
697
|
-
"aiError",
|
|
698
|
-
"aiSummary",
|
|
699
|
-
"aiLabels",
|
|
700
|
-
"sentiment",
|
|
701
|
-
"energyLevel",
|
|
702
|
-
"engagementScore",
|
|
703
|
-
// Voice isolation (only enhancedAudioUrl stays public)
|
|
704
|
-
"enhancedStoragePath",
|
|
705
|
-
// Social-video (entire cluster is creator-only)
|
|
706
|
-
"socialVideoUrl",
|
|
707
|
-
"socialVideoStoragePath",
|
|
708
|
-
"socialVideoStatus",
|
|
709
|
-
"socialVideoError",
|
|
710
|
-
"socialVideoSourceAudio"
|
|
711
|
-
]);
|
|
712
|
-
return publicReply;
|
|
713
|
-
}
|
|
714
|
-
var OrganizationViewSchema = zod.z.object({
|
|
715
|
-
record: OrganizationRecordSchema,
|
|
716
|
-
memberCount: zod.z.number().default(1),
|
|
717
|
-
currentUserRole: zod.z.enum(["owner", "admin", "member"]).optional()
|
|
718
|
-
});
|
|
719
|
-
var OrganizationMemberViewSchema = zod.z.object({
|
|
720
|
-
record: OrganizationMemberRecordSchema,
|
|
721
|
-
profile: ProfileViewBasicSchema
|
|
722
|
-
});
|
|
723
|
-
var OrgInviteViewSchema = zod.z.object({
|
|
724
|
-
record: OrgInviteRecordSchema,
|
|
725
|
-
/** Display name of the user who sent the invite */
|
|
726
|
-
inviterName: zod.z.string().optional(),
|
|
727
|
-
/** Name of the organization */
|
|
728
|
-
orgName: zod.z.string()
|
|
729
|
-
});
|
|
730
|
-
var PromptRepliersSchema = zod.z.object({
|
|
731
|
-
promptId: zod.z.string(),
|
|
732
|
-
repliers: zod.z.record(zod.z.string(), zod.z.object({
|
|
733
|
-
firstReplyAt: FirestoreTimestampSchema,
|
|
734
|
-
lastReplyAt: FirestoreTimestampSchema,
|
|
735
|
-
replyCount: zod.z.number()
|
|
736
|
-
}))
|
|
737
|
-
});
|
|
738
|
-
var PromptWithRepliesSchema = PromptViewSchema.extend({
|
|
739
|
-
replies: zod.z.array(ReplyViewSchema)
|
|
740
|
-
});
|
|
741
|
-
var ReplierSchema = zod.z.object({
|
|
742
|
-
handle: zod.z.string(),
|
|
743
|
-
/** ISO date string */
|
|
744
|
-
lastReplyDate: zod.z.string(),
|
|
745
|
-
/** ISO date string */
|
|
746
|
-
firstReplyAt: zod.z.string(),
|
|
747
|
-
totalReplies: zod.z.number()
|
|
748
|
-
});
|
|
749
|
-
var HandleResolutionSchema = zod.z.discriminatedUnion("type", [
|
|
750
|
-
// Public endpoint (`GET /resolve/:handle`) — project to the basic shape so
|
|
751
|
-
// PII/admin fields (email, phoneNumber, settings, blockedUsers, …) never
|
|
752
|
-
// cross the public API boundary. See `toProfileViewBasic`.
|
|
753
|
-
zod.z.object({ type: zod.z.literal("user"), profile: ProfileViewBasicSchema }),
|
|
754
|
-
zod.z.object({ type: zod.z.literal("org"), org: OrganizationViewSchema })
|
|
755
|
-
]);
|
|
756
|
-
var UserProfileDataSchema = zod.z.object({
|
|
757
|
-
// Public endpoint (`GET /users/:handle/profile`) — basic shape only, so the
|
|
758
|
-
// owner's PII/admin fields never serialize to anonymous callers.
|
|
759
|
-
profileUser: ProfileViewBasicSchema,
|
|
760
|
-
// Each prompt's nested `author` is the profile owner, hydrated from the
|
|
761
|
-
// wide admin profile (`getPromptsForUser` prefetches via getUserDataByUid).
|
|
762
|
-
// Use the PUBLIC prompt/reply shapes so that nested author PII (email,
|
|
763
|
-
// phoneNumber, settings, …) and owner-only prompt enrichment never leak.
|
|
764
|
-
allPromptsWithReplies: zod.z.array(PromptViewPublicSchema.extend({
|
|
765
|
-
replies: zod.z.array(ReplyViewPublicSchema)
|
|
766
|
-
})),
|
|
767
|
-
repliers: zod.z.array(ReplierSchema)
|
|
768
|
-
});
|
|
769
|
-
var RssSummarySchema = zod.z.object({
|
|
770
|
-
title: zod.z.string().optional(),
|
|
771
|
-
description: zod.z.string().optional(),
|
|
772
|
-
image: zod.z.string().optional(),
|
|
773
|
-
link: zod.z.string().optional(),
|
|
774
|
-
items: zod.z.array(zod.z.object({
|
|
775
|
-
title: zod.z.string().optional(),
|
|
776
|
-
link: zod.z.string().optional(),
|
|
777
|
-
content: zod.z.string().optional(),
|
|
778
|
-
pubDate: zod.z.string().optional()
|
|
779
|
-
})).optional(),
|
|
780
|
-
lastFetchedAt: FirestoreTimestampSchema.optional()
|
|
781
|
-
});
|
|
782
|
-
var OrgProfileDataSchema = zod.z.object({
|
|
783
|
-
org: OrganizationViewSchema,
|
|
784
|
-
prompts: zod.z.array(PromptViewSchema),
|
|
785
|
-
rssSummary: RssSummarySchema.nullable()
|
|
786
|
-
});
|
|
787
|
-
var EnrichedReplierSchema = zod.z.object({
|
|
788
|
-
profile: ProfileViewBasicSchema,
|
|
789
|
-
totalReplies: zod.z.number(),
|
|
790
|
-
/** ISO date string */
|
|
791
|
-
lastReplyDate: zod.z.string(),
|
|
792
|
-
/** ISO date string */
|
|
793
|
-
firstReplyAt: zod.z.string(),
|
|
794
|
-
/** Phone number for anonymous repliers (from Firebase Auth, only visible to prompt author) */
|
|
795
|
-
phoneNumber: zod.z.string().optional()
|
|
796
|
-
});
|
|
797
173
|
|
|
798
|
-
exports.EnrichedReplierSchema = EnrichedReplierSchema;
|
|
799
|
-
exports.HandleResolutionSchema = HandleResolutionSchema;
|
|
800
|
-
exports.OrgInviteViewSchema = OrgInviteViewSchema;
|
|
801
|
-
exports.OrgProfileDataSchema = OrgProfileDataSchema;
|
|
802
|
-
exports.OrganizationMemberViewSchema = OrganizationMemberViewSchema;
|
|
803
|
-
exports.OrganizationViewSchema = OrganizationViewSchema;
|
|
804
174
|
exports.ProfileViewAdminSchema = ProfileViewAdminSchema;
|
|
805
175
|
exports.ProfileViewBasicSchema = ProfileViewBasicSchema;
|
|
806
176
|
exports.ProfileViewDetailedSchema = ProfileViewDetailedSchema;
|
|
807
177
|
exports.ProfileViewSchema = ProfileViewSchema;
|
|
808
178
|
exports.ProfileViewSelfSchema = ProfileViewSelfSchema;
|
|
809
|
-
exports.PromptRepliersSchema = PromptRepliersSchema;
|
|
810
|
-
exports.PromptViewPublicSchema = PromptViewPublicSchema;
|
|
811
|
-
exports.PromptViewSchema = PromptViewSchema;
|
|
812
|
-
exports.PromptWithRepliesSchema = PromptWithRepliesSchema;
|
|
813
|
-
exports.ReplierSchema = ReplierSchema;
|
|
814
|
-
exports.ReplyViewPublicSchema = ReplyViewPublicSchema;
|
|
815
|
-
exports.ReplyViewSchema = ReplyViewSchema;
|
|
816
|
-
exports.RssSummarySchema = RssSummarySchema;
|
|
817
|
-
exports.UserProfileDataSchema = UserProfileDataSchema;
|
|
818
179
|
exports.toProfileViewBasic = toProfileViewBasic;
|
|
819
|
-
exports.toPromptViewPublic = toPromptViewPublic;
|
|
820
|
-
exports.toReplyViewPublic = toReplyViewPublic;
|