@cbjk_iris/schema 0.0.0-stage → 0.0.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/index.mjs ADDED
@@ -0,0 +1,587 @@
1
+ import { A as slugSchema, C as serviceSchema, D as imageSrc, E as httpsUrl, M as urlProblem, O as ptBRError, S as serviceContentSchema, T as hostnameSchema, _ as catalogItemBase, a as SECTION_TYPES, b as productContentSchema, c as sectionSchema, d as fieldAsk, f as fieldMeta, g as PLATFORM_HOSTS, h as siteLinkSchema, i as pageSlugSchema, j as uniqueItems, k as siteHref, l as sectionsOfModule, m as sectionBase, n as homeSchema, o as getSectionDefinition, p as fieldMetaSchema, r as pageSchema, s as sectionDefinitions, t as RESERVED_PAGE_SLUGS, u as defineSection, v as installmentSchema, w as cssValue, x as productSchema, y as platformUrl } from "./page-DxWfFiUO.mjs";
2
+ import { a as PURCHASE_PLATFORMS, c as completeButtonOrder, n as COLOR_TOKENS, o as SECTION_ICONS, r as DEFAULT_BUTTON_ORDER, s as SOCIAL_NETWORKS, t as COLOR_MODES } from "./constants-C4TYxqGV.mjs";
3
+ import { a as MODULES, i as DEFAULT_MODULES, n as DEFAULT_TEXTS, o as MODULE_IDS, r as resolveTexts, t as applySiteConfigDefaults } from "./defaults-BTUKcxLp.mjs";
4
+ import { z } from "zod";
5
+ //#region src/issues.ts
6
+ function formatIssuePath(path) {
7
+ if (!path.length) return "(raiz)";
8
+ return path.map((key, i) => typeof key === "number" ? `[${key}]` : `${i === 0 ? "" : "."}${String(key)}`).join("");
9
+ }
10
+ //#endregion
11
+ //#region src/texts.ts
12
+ const t = () => z.string();
13
+ const platformTexts = () => z.strictObject(Object.fromEntries(PURCHASE_PLATFORMS.map((p) => [p, t()])));
14
+ /** Todas as chaves de texto, com o tipo completo. Fonte única da lista de chaves. */
15
+ const siteTextsSchema = z.strictObject({
16
+ headerCta: t(),
17
+ products: z.strictObject({
18
+ title: t(),
19
+ /** {count} */
20
+ count: t(),
21
+ notFound: t(),
22
+ /** rótulo curto do card ("Comprar agora") */
23
+ buy: t(),
24
+ /** {business} */
25
+ whatsappNotice: t(),
26
+ onSale: t(),
27
+ madeToOrder: t(),
28
+ /** {count} {value} */
29
+ installment: t(),
30
+ interestFree: t(),
31
+ paymentMethods: t(),
32
+ noImage: t(),
33
+ /** rótulo longo de cada botão de compra, no detalhe */
34
+ buttons: platformTexts(),
35
+ /** nome acessível do botão do card: {buy} {platform} */
36
+ cardLabel: t(),
37
+ /** nome de cada plataforma, usado em cardLabel */
38
+ platforms: platformTexts()
39
+ }),
40
+ services: z.strictObject({
41
+ title: t(),
42
+ /** {count} */
43
+ count: t(),
44
+ notFound: t(),
45
+ quote: t(),
46
+ /** {business} */
47
+ whatsappNotice: t(),
48
+ cardLink: t()
49
+ }),
50
+ detail: z.strictObject({
51
+ description: t(),
52
+ specs: t()
53
+ }),
54
+ gallery: z.strictObject({
55
+ title: t(),
56
+ /** exibido quando não há fotos */
57
+ empty: t()
58
+ }),
59
+ sections: z.strictObject({
60
+ seeAll: t(),
61
+ contact: z.strictObject({
62
+ phone: t(),
63
+ email: t(),
64
+ address: t(),
65
+ hours: t(),
66
+ whatsapp: t(),
67
+ mapTitle: t()
68
+ })
69
+ }),
70
+ leadForm: z.strictObject({
71
+ name: t(),
72
+ phone: t(),
73
+ email: t(),
74
+ message: t(),
75
+ submit: t(),
76
+ sending: t(),
77
+ /** confirmação após enviar para um endpoint */
78
+ success: t(),
79
+ error: t(),
80
+ /** linha de abertura da mensagem quando o destino é o WhatsApp */
81
+ whatsappIntro: t()
82
+ }),
83
+ footer: z.strictObject({
84
+ menu: t(),
85
+ contact: t(),
86
+ /** {year} {name} */
87
+ copyright: t()
88
+ })
89
+ });
90
+ function deepPartialSchema(schema) {
91
+ if (schema instanceof z.ZodObject) {
92
+ const shape = Object.fromEntries(Object.entries(schema.shape).map(([k, v]) => [k, deepPartialSchema(v).optional()]));
93
+ return z.strictObject(shape);
94
+ }
95
+ return schema;
96
+ }
97
+ /**
98
+ * Entrada de siteConfig.texts: qualquer subconjunto das chaves, mais a obsoleta
99
+ * products.buyOnWhatsapp (vale como products.buttons.whatsapp quando este falta).
100
+ */
101
+ const siteTextsInputSchema = deepPartialSchema(siteTextsSchema.extend({ products: siteTextsSchema.shape.products.extend({ buyOnWhatsapp: t() }) }));
102
+ //#endregion
103
+ //#region src/theme/tokens.ts
104
+ const CASE = ["uppercase", "none"];
105
+ const SHAPE_TOKENS = [
106
+ {
107
+ name: "--radius",
108
+ kind: "length",
109
+ min: "0",
110
+ max: "2rem",
111
+ sera: "0.625rem"
112
+ },
113
+ {
114
+ name: "--radius-control",
115
+ kind: "length",
116
+ min: "0",
117
+ max: "9999px",
118
+ sera: "0px"
119
+ },
120
+ {
121
+ name: "--radius-card",
122
+ kind: "length",
123
+ min: "0",
124
+ max: "3rem",
125
+ sera: "0px"
126
+ },
127
+ {
128
+ name: "--radius-media",
129
+ kind: "length",
130
+ min: "0",
131
+ max: "3rem",
132
+ sera: "0px"
133
+ },
134
+ {
135
+ name: "--radius-surface",
136
+ kind: "length",
137
+ min: "0",
138
+ max: "3rem",
139
+ sera: "var(--radius)"
140
+ },
141
+ {
142
+ name: "--radius-field",
143
+ kind: "length",
144
+ min: "0",
145
+ max: "9999px",
146
+ sera: "calc(var(--radius) * 0.8)"
147
+ },
148
+ {
149
+ name: "--radius-card-compact",
150
+ kind: "length",
151
+ min: "0",
152
+ max: "3rem",
153
+ sera: "0.125rem"
154
+ },
155
+ {
156
+ name: "--border-width",
157
+ kind: "length",
158
+ min: "0",
159
+ max: "4px",
160
+ sera: "1px"
161
+ },
162
+ {
163
+ name: "--surface-border-width",
164
+ kind: "length",
165
+ min: "0",
166
+ max: "4px",
167
+ sera: "1px"
168
+ },
169
+ {
170
+ name: "--card-ring-width",
171
+ kind: "length",
172
+ min: "0",
173
+ max: "4px",
174
+ sera: "1px"
175
+ },
176
+ {
177
+ name: "--card-ring-color",
178
+ kind: "color",
179
+ sera: "color-mix(in oklab, var(--foreground) 5%, transparent)"
180
+ },
181
+ {
182
+ name: "--popover-ring-color",
183
+ kind: "color",
184
+ sera: "color-mix(in oklab, var(--foreground) 10%, transparent)"
185
+ },
186
+ {
187
+ name: "--shadow-card",
188
+ kind: "shadow",
189
+ sera: "var(--shadow-sm)"
190
+ },
191
+ {
192
+ name: "--shadow-card-hover",
193
+ kind: "shadow",
194
+ sera: "var(--shadow-md)"
195
+ },
196
+ {
197
+ name: "--shadow-overlay",
198
+ kind: "shadow",
199
+ sera: "var(--shadow-md)"
200
+ },
201
+ {
202
+ name: "--shadow-control",
203
+ kind: "shadow",
204
+ sera: "var(--shadow-xs)"
205
+ },
206
+ {
207
+ name: "--surface-alpha",
208
+ kind: "percentage",
209
+ min: 0,
210
+ max: 100,
211
+ sera: "100%"
212
+ },
213
+ {
214
+ name: "--blur",
215
+ kind: "length",
216
+ min: "0",
217
+ max: "24px",
218
+ sera: "0px"
219
+ },
220
+ {
221
+ name: "--header-alpha",
222
+ kind: "percentage",
223
+ min: 0,
224
+ max: 100,
225
+ sera: "86%"
226
+ },
227
+ {
228
+ name: "--header-blur",
229
+ kind: "length",
230
+ min: "0",
231
+ max: "40px",
232
+ sera: "40px"
233
+ },
234
+ {
235
+ name: "--overlay-alpha",
236
+ kind: "percentage",
237
+ min: 0,
238
+ max: 100,
239
+ sera: "20%"
240
+ },
241
+ {
242
+ name: "--overlay-blur",
243
+ kind: "length",
244
+ min: "0",
245
+ max: "24px",
246
+ sera: "8px"
247
+ },
248
+ {
249
+ name: "--density",
250
+ kind: "number",
251
+ min: .75,
252
+ max: 1.25,
253
+ sera: "1"
254
+ },
255
+ {
256
+ name: "--control-case",
257
+ kind: "keyword",
258
+ values: CASE,
259
+ sera: "uppercase"
260
+ },
261
+ {
262
+ name: "--control-tracking",
263
+ kind: "length",
264
+ min: "0em",
265
+ max: "0.2em",
266
+ units: ["em"],
267
+ sera: "0.1em"
268
+ },
269
+ {
270
+ name: "--control-weight",
271
+ kind: "number",
272
+ min: 400,
273
+ max: 800,
274
+ sera: "600"
275
+ },
276
+ {
277
+ name: "--title-case",
278
+ kind: "keyword",
279
+ values: CASE,
280
+ sera: "uppercase"
281
+ },
282
+ {
283
+ name: "--title-tracking",
284
+ kind: "length",
285
+ min: "0em",
286
+ max: "0.2em",
287
+ units: ["em"],
288
+ sera: "0.05em"
289
+ },
290
+ {
291
+ name: "--label-case",
292
+ kind: "keyword",
293
+ values: CASE,
294
+ sera: "uppercase"
295
+ },
296
+ {
297
+ name: "--label-tracking",
298
+ kind: "length",
299
+ min: "0em",
300
+ max: "0.2em",
301
+ units: ["em"],
302
+ sera: "0.025em"
303
+ },
304
+ {
305
+ name: "--ring-width",
306
+ kind: "length",
307
+ min: "1px",
308
+ max: "4px",
309
+ sera: "2px"
310
+ }
311
+ ];
312
+ const SHAPE_TOKEN_KEYS = SHAPE_TOKENS.map((t) => t.name.slice(2));
313
+ /** Estilos embutidos (Q-09). */
314
+ const STYLE_IDS = [
315
+ "sera",
316
+ "soft",
317
+ "glass",
318
+ "flat"
319
+ ];
320
+ const DEFAULT_STYLE_ID = "sera";
321
+ /** Variável do tema que diz o estilo preferido dele (no :root). */
322
+ const IRIS_STYLE_VAR = "--iris-style";
323
+ /**
324
+ * Utilitários congelados do §5.4, definidos no iris.css do core. Mesma lista do "utilities"
325
+ * de docs/spec/style-inventory.json (um teste confere).
326
+ */
327
+ const FROZEN_UTILITIES = [
328
+ "rounded-control",
329
+ "rounded-card",
330
+ "rounded-media",
331
+ "rounded-surface",
332
+ "rounded-surface-lg",
333
+ "rounded-field",
334
+ "rounded-card-compact",
335
+ "shadow-card",
336
+ "shadow-card-hover",
337
+ "shadow-overlay",
338
+ "shadow-control",
339
+ "surface-card",
340
+ "surface-popover",
341
+ "surface-header",
342
+ "surface-overlay",
343
+ "border-control",
344
+ "border-surface",
345
+ "border-selected",
346
+ "divider-t",
347
+ "divider-b",
348
+ "divider-l",
349
+ "divider-r",
350
+ "divider-between-y",
351
+ "ring-focus",
352
+ "py-section",
353
+ "p-card",
354
+ "gap-density",
355
+ "weight-control",
356
+ "case-control",
357
+ "case-control-compact",
358
+ "case-title",
359
+ "case-label"
360
+ ];
361
+ //#endregion
362
+ //#region src/site-config.ts
363
+ const menuItemSchema = z.strictObject({
364
+ title: z.string().min(1),
365
+ path: siteHref.optional(),
366
+ get children() {
367
+ return z.array(menuItemSchema).optional();
368
+ }
369
+ });
370
+ const siteLogoSchema = z.strictObject({
371
+ src: imageSrc,
372
+ alt: z.string().min(1),
373
+ /** dimensões originais, usadas para a proporção */
374
+ width: z.number().positive(),
375
+ height: z.number().positive(),
376
+ /** SVG de uma cor só: herda a cor do texto e acompanha o modo escuro */
377
+ monochrome: z.boolean().optional()
378
+ });
379
+ const googleFontName = z.string().regex(/^[A-Za-z0-9 ]+$/, { error: "use o nome exato do Google Fonts, ex.: \"Playfair Display\"" });
380
+ const fontPath = z.string().refine((p) => !p.startsWith("/") && !/^[A-Za-z]:/.test(p) && !p.includes("\\") && !p.split("/").includes("..") && /^[\w./ -]+\.(?:woff2?|ttf|otf)$/.test(p), { error: "caminho relativo à raiz do projeto, sem .., terminando em .woff2, .woff, .ttf ou .otf (ex.: fonts/marca.woff2)" });
381
+ /** Fonte do Google (nome exato, ex.: "Playfair Display") ou arquivos locais. */
382
+ const brandFontSchema = z.union([z.strictObject({
383
+ google: googleFontName,
384
+ weights: z.array(z.string().regex(/^(?:\d{3}|variable)$/)).optional()
385
+ }), z.strictObject({ local: z.array(z.strictObject({
386
+ path: fontPath,
387
+ weight: z.string().regex(/^\d{3}(?: \d{3})?$/, { error: "use \"400\" ou uma faixa \"100 900\"" }),
388
+ style: z.enum(["normal", "italic"]).optional()
389
+ })).min(1) })]);
390
+ const colorOverrides = z.partialRecord(z.enum(COLOR_TOKENS), cssValue);
391
+ const brandSchema = z.strictObject({
392
+ logo: siteLogoSchema.optional(),
393
+ /** texto ao lado do logo; sem logo e sem texto, usa o name */
394
+ logoText: z.string().min(1).optional(),
395
+ /** cores da marca, por cima do tema; em branco = cor do tema. Qualquer cor CSS */
396
+ colors: z.strictObject({
397
+ /** cor principal (botões padrão, links de destaque) */
398
+ primary: cssValue.optional(),
399
+ /** botões de ação, como o WhatsApp; em branco = primary */
400
+ cta: cssValue.optional(),
401
+ /** badges de oferta e destaques pontuais; em branco = destructive do tema */
402
+ highlight: cssValue.optional()
403
+ }),
404
+ /** arredondamento base, ex.: "0.625rem"; atalho de shape.radius; em branco = o do tema */
405
+ radius: cssValue.optional(),
406
+ /** tokens de forma (SHAPE_TOKENS), sem o "--": { "radius-control": "9999px" } */
407
+ shape: z.partialRecord(z.enum(SHAPE_TOKEN_KEYS), cssValue).optional(),
408
+ /** em branco = fonte do tema (--font-sans do arquivo em themes/) */
409
+ fonts: z.strictObject({
410
+ sans: brandFontSchema.optional(),
411
+ heading: brandFontSchema.optional()
412
+ }).optional(),
413
+ /** sobrescreve qualquer variável final de cor, por modo (ex.: colar trechos do tweakcn) */
414
+ overrides: z.strictObject({
415
+ light: colorOverrides.optional(),
416
+ dark: colorOverrides.optional()
417
+ }).optional()
418
+ });
419
+ /**
420
+ * src do iframe do mapa: só o Google Maps incorporado. Passa por urlProblem (valor cru, https,
421
+ * sem credencial nem porta), host exato www.google.com, e caminho /maps/embed (qualquer query)
422
+ * ou /maps com output=embed na query.
423
+ */
424
+ const mapEmbedUrlSchema = z.string().refine((v) => {
425
+ if (urlProblem(v) !== null) return false;
426
+ const url = new URL(v);
427
+ if (url.hostname !== "www.google.com") return false;
428
+ return url.pathname === "/maps/embed" || url.pathname === "/maps" && url.searchParams.get("output") === "embed";
429
+ }, { error: "use o link de incorporar do mapa do Google (Google Maps → Compartilhar → Incorporar um mapa): https://www.google.com/maps/embed?pb=..." });
430
+ const contactSchema = z.strictObject({
431
+ phone: z.string().min(1).optional(),
432
+ email: z.email({ error: "use um e-mail válido, ex.: contato@loja.com.br" }).optional(),
433
+ address: z.string().min(1).optional(),
434
+ /** linhas de horário, ex.: ["Seg a sex: 8h às 18h", "Sáb: 8h às 12h"] */
435
+ hours: z.array(z.string().min(1)).optional(),
436
+ /** URL de "Incorporar um mapa" do Google Maps (src do iframe) */
437
+ mapEmbedUrl: mapEmbedUrlSchema.optional(),
438
+ social: z.partialRecord(z.enum(SOCIAL_NETWORKS), httpsUrl).optional()
439
+ });
440
+ /**
441
+ * Para onde vão os dados do formulário de lead:
442
+ * - "whatsapp": abre uma conversa com os dados preenchidos (não precisa de conta)
443
+ * - "endpoint": POST em JSON para um serviço de formulários (Formspree, Web3Forms...)
444
+ * - "backend": reservado para o template de backend (ainda não implementado)
445
+ */
446
+ const leadsSchema = z.discriminatedUnion("provider", [
447
+ z.strictObject({
448
+ provider: z.literal("whatsapp"),
449
+ intro: z.string().min(1).optional()
450
+ }),
451
+ z.strictObject({
452
+ provider: z.literal("endpoint"),
453
+ /** URL que recebe o POST, ex.: "https://formspree.io/f/abcd1234" */
454
+ endpoint: httpsUrl,
455
+ /** campos fixos enviados junto (ex.: access_key do Web3Forms, que é pública por design) */
456
+ extraFields: z.record(z.string(), z.string()).optional()
457
+ }),
458
+ z.strictObject({ provider: z.literal("backend") })
459
+ ]);
460
+ const footerSchema = z.strictObject({
461
+ /** frase curta abaixo do logo */
462
+ text: z.string().min(1).optional(),
463
+ /** colunas de links; em branco = links do menu principal */
464
+ columns: z.array(z.strictObject({
465
+ title: z.string().min(1),
466
+ links: z.array(siteLinkSchema)
467
+ })).optional()
468
+ });
469
+ const buttonOrderSchema = z.array(z.enum(PURCHASE_PLATFORMS)).superRefine(uniqueItems("plataforma"));
470
+ const siteConfigSchema = z.strictObject({
471
+ name: z.string().min(1),
472
+ locale: z.string().regex(/^[a-z]{2,3}(?:-[A-Z]{2})?$/, { error: "use um código de idioma, ex.: \"pt-BR\"" }),
473
+ /** código ISO 4217, ex.: BRL, USD */
474
+ currency: z.string().regex(/^[A-Z]{3}$/, { error: "use o código ISO 4217, ex.: \"BRL\"" }),
475
+ brand: brandSchema,
476
+ seo: z.strictObject({
477
+ title: z.string().min(1),
478
+ titleTemplate: z.string().includes("%s", { error: "precisa ter %s no lugar do título da página, ex.: \"%s | Loja\"" }),
479
+ description: z.string().min(1).optional()
480
+ }),
481
+ whatsapp: z.strictObject({
482
+ /** formato internacional, só dígitos (ex.: 5551999999999) */
483
+ phone: z.string().regex(/^\d{10,15}$/, { error: "use o formato internacional, só dígitos (ex.: 5511999999999)" }),
484
+ /** modelos de mensagem; {name} e {price} são substituídos */
485
+ messages: z.strictObject({
486
+ general: z.string().min(1),
487
+ product: z.string().min(1),
488
+ service: z.string().min(1)
489
+ })
490
+ }),
491
+ images: z.strictObject({
492
+ /** hosts externos liberados para next/image (vira remotePatterns). Só o host exato */
493
+ remoteHosts: z.array(hostnameSchema) }),
494
+ theme: z.strictObject({
495
+ /** arquivo em themes/ (sem .css) */
496
+ name: slugSchema,
497
+ colorMode: z.enum(COLOR_MODES),
498
+ /** estilo (forma dos componentes); ausente = o --iris-style do tema, ou "sera" */
499
+ style: z.enum(STYLE_IDS).optional()
500
+ }),
501
+ menu: z.array(menuItemSchema),
502
+ /** dados de contato usados pela seção "contact" e pelo rodapé */
503
+ contact: contactSchema.optional(),
504
+ footer: footerSchema.optional(),
505
+ /** destino do formulário de lead (seção "lead-form") */
506
+ leads: leadsSchema.optional(),
507
+ /** módulos ativos; ausente = os três */
508
+ modules: z.array(z.enum(MODULE_IDS)).superRefine(uniqueItems("módulo")).optional().transform((m) => m ?? [...MODULE_IDS]),
509
+ /** botões de compra; buttonOrder ausente = DEFAULT_BUTTON_ORDER, e o que faltar vai para o fim */
510
+ commerce: z.strictObject({ buttonOrder: buttonOrderSchema.optional() }).optional().transform((c) => ({
511
+ ...c,
512
+ buttonOrder: completeButtonOrder(c?.buttonOrder)
513
+ })),
514
+ /** textos da interface; parcial, mesclado com DEFAULT_TEXTS */
515
+ texts: siteTextsInputSchema.optional().transform((t) => resolveTexts(t))
516
+ });
517
+ /** Config inválido: a mensagem lista cada erro com o caminho do campo. */
518
+ var SiteConfigError = class extends Error {
519
+ issues;
520
+ constructor(issues, file = "site.config.ts") {
521
+ super(`${file} tem erros:\n${issues.map((i) => ` - ${formatIssuePath(i.path)}: ${i.message}`).join("\n")}`);
522
+ this.name = "SiteConfigError";
523
+ this.issues = issues;
524
+ }
525
+ };
526
+ /** Valida e preenche os padrões. Lança SiteConfigError, com mensagens em pt-BR. Roda no Node. */
527
+ function resolveSiteConfig(input) {
528
+ const result = siteConfigSchema.safeParse(input, { error: ptBRError });
529
+ if (!result.success) throw new SiteConfigError(result.error.issues);
530
+ return result.data;
531
+ }
532
+ //#endregion
533
+ //#region src/cli.ts
534
+ const EXIT_CODES = {
535
+ INTERNAL: 1,
536
+ USAGE: 2,
537
+ MISSING_REQUIRED: 3,
538
+ VALIDATION: 4,
539
+ CONFLICT: 5,
540
+ ENVIRONMENT: 6,
541
+ CONFIG_NOT_EDITABLE: 7,
542
+ CANCELLED: 130
543
+ };
544
+ const diagnosticSchema = z.strictObject({
545
+ level: z.enum(["error", "warning"]),
546
+ file: z.string(),
547
+ path: z.string().optional(),
548
+ message: z.string(),
549
+ hint: z.string().optional()
550
+ });
551
+ const fileChangeSchema = z.strictObject({
552
+ path: z.string(),
553
+ action: z.enum([
554
+ "create",
555
+ "update",
556
+ "delete"
557
+ ])
558
+ });
559
+ const cliErrorSchema = z.strictObject({
560
+ code: z.enum(Object.keys(EXIT_CODES)),
561
+ exitCode: z.number().int(),
562
+ message: z.string().min(1),
563
+ hint: z.string().optional(),
564
+ missing: z.array(z.string()).optional()
565
+ }).refine((e) => EXIT_CODES[e.code] === e.exitCode, {
566
+ error: "exitCode não corresponde ao code",
567
+ path: ["exitCode"]
568
+ });
569
+ const base = {
570
+ schemaVersion: z.literal(1),
571
+ command: z.string(),
572
+ changes: z.array(fileChangeSchema),
573
+ warnings: z.array(diagnosticSchema)
574
+ };
575
+ /** Valida um envelope --json em runtime (usado pelos testes de não travamento da CLI). */
576
+ const cliResultSchema = z.discriminatedUnion("ok", [z.strictObject({
577
+ ...base,
578
+ ok: z.literal(true),
579
+ data: z.unknown()
580
+ }), z.strictObject({
581
+ ...base,
582
+ ok: z.literal(false),
583
+ data: z.null(),
584
+ error: cliErrorSchema
585
+ })]);
586
+ //#endregion
587
+ export { COLOR_TOKENS, DEFAULT_BUTTON_ORDER, DEFAULT_MODULES, DEFAULT_STYLE_ID, DEFAULT_TEXTS, EXIT_CODES, FROZEN_UTILITIES, IRIS_STYLE_VAR, MODULES, MODULE_IDS, PLATFORM_HOSTS, PURCHASE_PLATFORMS, RESERVED_PAGE_SLUGS, SECTION_ICONS, SECTION_TYPES, SHAPE_TOKENS, SHAPE_TOKEN_KEYS, STYLE_IDS, SiteConfigError, applySiteConfigDefaults, catalogItemBase, cliResultSchema, cssValue, defineSection, fieldAsk, fieldMeta, fieldMetaSchema, formatIssuePath, getSectionDefinition, homeSchema, httpsUrl, installmentSchema, pageSchema, pageSlugSchema, platformUrl, productContentSchema, productSchema, ptBRError, resolveSiteConfig, resolveTexts, sectionBase, sectionDefinitions, sectionSchema, sectionsOfModule, serviceContentSchema, serviceSchema, siteConfigSchema, slugSchema };
@@ -0,0 +1,6 @@
1
+ //#region src/json-schema.d.ts
2
+ type JsonObject = Record<string, unknown>;
3
+ /** Nome do arquivo → JSON Schema. Gerado com io: "input" (campo com padrão não é obrigatório). */
4
+ export declare function buildJsonSchemas(): Record<string, JsonObject>;
5
+ //#endregion
6
+ export {};
@@ -0,0 +1,45 @@
1
+ import { S as serviceContentSchema, b as productContentSchema, c as sectionSchema, n as homeSchema, r as pageSchema } from "./page-DxWfFiUO.mjs";
2
+ import { z } from "zod";
3
+ //#region src/json-schema.ts
4
+ function override(ctx) {
5
+ const js = ctx.jsonSchema;
6
+ if (typeof js.label === "string" && js.title === void 0) js.title = js.label;
7
+ if (typeof js.example === "string") js.examples = [js.example];
8
+ for (const key of [
9
+ "label",
10
+ "example",
11
+ "ask",
12
+ "input",
13
+ "order"
14
+ ]) if (typeof js[key] !== "object") delete js[key];
15
+ }
16
+ function toJson(schema, withSchemaKey) {
17
+ const js = z.toJSONSchema(schema, {
18
+ io: "input",
19
+ override
20
+ });
21
+ if (!withSchemaKey) return js;
22
+ const properties = {
23
+ $schema: {
24
+ type: "string",
25
+ description: "Caminho do JSON Schema (autocomplete no editor)"
26
+ },
27
+ ...js.properties
28
+ };
29
+ return {
30
+ ...js,
31
+ properties
32
+ };
33
+ }
34
+ /** Nome do arquivo → JSON Schema. Gerado com io: "input" (campo com padrão não é obrigatório). */
35
+ function buildJsonSchemas() {
36
+ return {
37
+ "section.schema.json": toJson(sectionSchema, false),
38
+ "home.schema.json": toJson(homeSchema, true),
39
+ "page.schema.json": toJson(pageSchema, true),
40
+ "product.schema.json": toJson(productContentSchema, true),
41
+ "service.schema.json": toJson(serviceContentSchema, true)
42
+ };
43
+ }
44
+ //#endregion
45
+ export { buildJsonSchemas };