@fayz-ai/core 0.9.0 → 0.10.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.
Files changed (170) hide show
  1. package/README.md +2 -2
  2. package/dist/access/index.js.map +1 -1
  3. package/dist/{chunk-L4TLMYGC.js → chunk-6RBW2Y5K.js} +3 -3
  4. package/dist/chunk-6RBW2Y5K.js.map +1 -0
  5. package/dist/chunk-732GZEUI.js +1592 -0
  6. package/dist/chunk-732GZEUI.js.map +1 -0
  7. package/dist/{chunk-X5THHG6T.js → chunk-CPMHCTX3.js} +3 -3
  8. package/dist/chunk-CPMHCTX3.js.map +1 -0
  9. package/dist/{chunk-V2MSAUHO.js → chunk-JO7Z2AOE.js} +2 -2
  10. package/dist/chunk-JO7Z2AOE.js.map +1 -0
  11. package/dist/{chunk-5RJVUC6J.js → chunk-M27JPX3K.js} +12 -3
  12. package/dist/chunk-M27JPX3K.js.map +1 -0
  13. package/dist/chunk-OXQGRJZT.js +125 -0
  14. package/dist/chunk-OXQGRJZT.js.map +1 -0
  15. package/dist/data/backend-env.d.ts +38 -0
  16. package/dist/data/backend-env.d.ts.map +1 -0
  17. package/dist/data/index.js +1 -1
  18. package/dist/entity/events.d.ts +14 -0
  19. package/dist/entity/events.d.ts.map +1 -0
  20. package/dist/events/envelope.d.ts +31 -0
  21. package/dist/events/envelope.d.ts.map +1 -0
  22. package/dist/events/index.d.ts +4 -0
  23. package/dist/events/index.d.ts.map +1 -1
  24. package/dist/events/log.d.ts +44 -0
  25. package/dist/events/log.d.ts.map +1 -0
  26. package/dist/events/types.d.ts +40 -0
  27. package/dist/events/types.d.ts.map +1 -0
  28. package/dist/i18n/index.d.ts +10 -0
  29. package/dist/i18n/index.d.ts.map +1 -1
  30. package/dist/i18n/index.js +1 -1
  31. package/dist/index.d.ts +27 -17
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +388 -52
  34. package/dist/index.js.map +1 -1
  35. package/dist/integrations/index.js +1 -1
  36. package/dist/{integrations/index.d.ts → integrations.d.ts} +2 -2
  37. package/dist/integrations.d.ts.map +1 -0
  38. package/dist/{address/index.d.ts → lib/address.d.ts} +1 -1
  39. package/dist/{address/index.d.ts.map → lib/address.d.ts.map} +1 -1
  40. package/dist/{phone/index.d.ts → lib/phone.d.ts} +1 -1
  41. package/dist/lib/phone.d.ts.map +1 -0
  42. package/dist/{seo/index.d.ts → lib/seo.d.ts} +18 -1
  43. package/dist/lib/seo.d.ts.map +1 -0
  44. package/dist/{tenant/index.d.ts → lib/tenant.d.ts} +1 -1
  45. package/dist/lib/tenant.d.ts.map +1 -0
  46. package/dist/manifest/index.d.ts +1 -1
  47. package/dist/manifest/index.d.ts.map +1 -1
  48. package/dist/messaging/index.d.ts +3 -0
  49. package/dist/messaging/index.d.ts.map +1 -0
  50. package/dist/messaging/registry.d.ts +35 -0
  51. package/dist/messaging/registry.d.ts.map +1 -0
  52. package/dist/messaging/types.d.ts +67 -0
  53. package/dist/messaging/types.d.ts.map +1 -0
  54. package/dist/plugin/index.js +2 -1
  55. package/dist/plugin/runtime.d.ts +17 -0
  56. package/dist/plugin/runtime.d.ts.map +1 -1
  57. package/dist/registry/block-catalog.d.ts +78 -0
  58. package/dist/registry/block-catalog.d.ts.map +1 -0
  59. package/dist/registry/block-constraints.d.ts +64 -0
  60. package/dist/registry/block-constraints.d.ts.map +1 -0
  61. package/dist/registry/block-schema.d.ts +69 -0
  62. package/dist/registry/block-schema.d.ts.map +1 -0
  63. package/dist/registry/blocks.d.ts +84 -0
  64. package/dist/registry/blocks.d.ts.map +1 -0
  65. package/dist/registry/entities.d.ts +153 -0
  66. package/dist/registry/entities.d.ts.map +1 -0
  67. package/dist/registry/extension-points.d.ts +117 -0
  68. package/dist/registry/extension-points.d.ts.map +1 -0
  69. package/dist/registry/handles.d.ts +41 -0
  70. package/dist/registry/handles.d.ts.map +1 -0
  71. package/dist/registry/index.d.ts +41 -41
  72. package/dist/registry/index.d.ts.map +1 -1
  73. package/dist/registry/loaders.d.ts +55 -0
  74. package/dist/registry/loaders.d.ts.map +1 -0
  75. package/dist/registry/registry-class.d.ts +157 -0
  76. package/dist/registry/registry-class.d.ts.map +1 -0
  77. package/dist/registry/schema-check.d.ts +14 -0
  78. package/dist/registry/schema-check.d.ts.map +1 -0
  79. package/dist/router/index.d.ts +78 -1
  80. package/dist/router/index.d.ts.map +1 -1
  81. package/dist/router/index.js +1 -1
  82. package/dist/testing/index.js +1 -1
  83. package/dist/{testing/index.d.ts → testing.d.ts} +3 -3
  84. package/dist/testing.d.ts.map +1 -0
  85. package/dist/types/analytics.d.ts +196 -0
  86. package/dist/types/analytics.d.ts.map +1 -0
  87. package/dist/types/crud.d.ts +22 -2
  88. package/dist/types/crud.d.ts.map +1 -1
  89. package/dist/types/plugins.d.ts +55 -1
  90. package/dist/types/plugins.d.ts.map +1 -1
  91. package/package.json +6 -18
  92. package/dist/blocks/index.d.ts +0 -25
  93. package/dist/blocks/index.d.ts.map +0 -1
  94. package/dist/chunk-5RJVUC6J.js.map +0 -1
  95. package/dist/chunk-L4TLMYGC.js.map +0 -1
  96. package/dist/chunk-V2MSAUHO.js.map +0 -1
  97. package/dist/chunk-X5THHG6T.js.map +0 -1
  98. package/dist/chunk-Y2C2FBQP.js +0 -35
  99. package/dist/chunk-Y2C2FBQP.js.map +0 -1
  100. package/dist/chunk-YH25Y4FW.js +0 -311
  101. package/dist/chunk-YH25Y4FW.js.map +0 -1
  102. package/dist/integrations/index.d.ts.map +0 -1
  103. package/dist/phone/index.d.ts.map +0 -1
  104. package/dist/seo/index.d.ts.map +0 -1
  105. package/dist/tenant/index.d.ts.map +0 -1
  106. package/dist/testing/index.d.ts.map +0 -1
  107. package/src/access/denial.ts +0 -33
  108. package/src/access/engine.test.ts +0 -48
  109. package/src/access/engine.ts +0 -136
  110. package/src/access/index.ts +0 -14
  111. package/src/access/limits.ts +0 -18
  112. package/src/address/index.ts +0 -188
  113. package/src/app/render.tsx +0 -69
  114. package/src/blocks/index.tsx +0 -68
  115. package/src/data/archetype.ts +0 -255
  116. package/src/data/bulk.ts +0 -35
  117. package/src/data/cached.ts +0 -55
  118. package/src/data/count.test.ts +0 -152
  119. package/src/data/count.ts +0 -131
  120. package/src/data/filters.test.ts +0 -70
  121. package/src/data/filters.ts +0 -90
  122. package/src/data/index.ts +0 -11
  123. package/src/data/mock.ts +0 -90
  124. package/src/data/platform-api.ts +0 -209
  125. package/src/data/refresh.ts +0 -115
  126. package/src/data/resolve.ts +0 -126
  127. package/src/data/supabase.ts +0 -230
  128. package/src/data/types.ts +0 -50
  129. package/src/entity/index.ts +0 -2
  130. package/src/entity/registry.ts +0 -49
  131. package/src/events/index.tsx +0 -82
  132. package/src/i18n/index.ts +0 -476
  133. package/src/i18n/shell-translations.en.ts +0 -875
  134. package/src/i18n/shell-translations.pt-br.ts +0 -873
  135. package/src/index.ts +0 -217
  136. package/src/integrations/index.ts +0 -237
  137. package/src/lib/cache.ts +0 -118
  138. package/src/lib/csv.ts +0 -54
  139. package/src/lib/format.ts +0 -58
  140. package/src/manifest/app-manifest.schema.json +0 -676
  141. package/src/manifest/index.ts +0 -518
  142. package/src/manifest/serialize.ts +0 -52
  143. package/src/phone/index.ts +0 -85
  144. package/src/plugin/createSafeDataProvider.ts +0 -30
  145. package/src/plugin/index.ts +0 -1
  146. package/src/plugin/runtime.ts +0 -331
  147. package/src/registry/index.ts +0 -163
  148. package/src/router/history.ts +0 -86
  149. package/src/router/index.ts +0 -29
  150. package/src/runtime/index.ts +0 -15
  151. package/src/runtime/oauth.ts +0 -219
  152. package/src/search/engine.ts +0 -559
  153. package/src/search/index.ts +0 -25
  154. package/src/search/text.ts +0 -206
  155. package/src/search/types.ts +0 -75
  156. package/src/seo/index.ts +0 -128
  157. package/src/tenant/index.ts +0 -38
  158. package/src/testing/index.ts +0 -116
  159. package/src/types/auth.ts +0 -41
  160. package/src/types/billing.ts +0 -39
  161. package/src/types/crud.ts +0 -184
  162. package/src/types/entities.ts +0 -142
  163. package/src/types/entitlements.ts +0 -45
  164. package/src/types/i18n.ts +0 -7
  165. package/src/types/index.ts +0 -11
  166. package/src/types/org.ts +0 -137
  167. package/src/types/payment.ts +0 -44
  168. package/src/types/permissions.ts +0 -32
  169. package/src/types/plugins.ts +0 -480
  170. package/src/types/theme.ts +0 -8
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
- export { connectorDirection, connectorPlanes, preferredPlane, withAfterHooks } from './chunk-L4TLMYGC.js';
2
- export { PluginContractError, assertConnectorContract, assertPluginManifestContract } from './chunk-X5THHG6T.js';
3
- import { getActiveTenantId, globalCache, getSupabaseClientOptional, resolveDataProvider } from './chunk-V2MSAUHO.js';
4
- export { applyRangeToQuery, bulkCreate, clearGlobalCache, countByTenant, createArchetypeProvider, createCacheStore, createFayzApiProvider, createMockProvider, createSupabaseProvider, getActiveTenantId, getSupabaseClientOptional, globalCache, invalidateCount, isFilterObject, matchesRange, parseRangeFilter, resolveDataProvider, setActiveTenantId, setGlobalSupabaseClient, stableKey, subscribeActiveTenant, useActiveTenantId, withCache } from './chunk-V2MSAUHO.js';
1
+ export { connectorDirection, connectorPlanes, preferredPlane, withAfterHooks } from './chunk-6RBW2Y5K.js';
2
+ export { PluginContractError, assertConnectorContract, assertPluginManifestContract } from './chunk-CPMHCTX3.js';
3
+ import { getActiveTenantId, globalCache, getSupabaseClientOptional, resolveDataProvider } from './chunk-JO7Z2AOE.js';
4
+ export { applyRangeToQuery, bulkCreate, clearGlobalCache, countByTenant, createArchetypeProvider, createCacheStore, createFayzApiProvider, createMockProvider, createSupabaseProvider, getActiveTenantId, getSupabaseClientOptional, globalCache, invalidateCount, isFilterObject, matchesRange, parseRangeFilter, resolveDataProvider, setActiveTenantId, setGlobalSupabaseClient, stableKey, subscribeActiveTenant, useActiveTenantId, withCache } from './chunk-JO7Z2AOE.js';
5
+ import { getBlock, checkNodePlacement, getScaffold } from './chunk-732GZEUI.js';
6
+ export { BLOCK_SETTING_TYPES, ENTITY_FIELD_TYPES, GENERIC_ENTITY_TABLE, PLUGIN_API_VERSION, PluginRuntimeProvider, RESERVED_ENTITY_FIELDS, Registry, SIDECAR_REFERENCES, auditBlocks, blockRegistry, buildEntityDomainEvents, checkAgainstSchema, checkBlockConstraints, checkBlockContext, checkNodePlacement, clearEntityDeclarations, clearExtensionPoints, clearHandles, clearLoaders, clearSidecarDeclarations, componentRegistry, dataNeedKey, defaultPropsFromSettings, defineBlock, defineEntity, defineExtensionPoint, defineLoader, definePlugin, defineSidecarFields, describeBlock, describeBlocks, describeEntities, describeExtensionPoints, describeLoaders, entityAdminForm, entityDeclarationRegistry, entityEventKey, entityRecordSchema, extensionAfterHooks, extensionPointRegistry, formatSchemaIssues, getAnalyticsCards, getBlock, getBlockMeta, getComponent, getDashboardWidgets, getHandle, getMetric, getPage, getPlugin, getPluginFactory, getScaffold, getWidgetsForZone, handleNameFor, handleRegistry, hasEntityDeclaration, hasExtensionPoint, hasHandle, hasLoader, hasSidecarDeclaration, isBlockEnabledOn, isCustomId, isLoaderParamRef, isLoaderPropRef, listBlocks, listEntityDeclarations, listExtensionHandlers, listExtensionPoints, listHandles, listLoaders, listMetrics, listPluginFactories, listPlugins, loaderRegistry, metricRegistry, pageRegistry, pluginFactoryRegistry, pluginRegistry, registerBlock, registerComponent, registerExtensionHandler, registerHandle, registerMetric, registerPage, registerPlugin, registerPluginFactory, registerScaffold, repairBlockTree, resolveEntityDeclaration, resolveHandle, resolveLoader, resolvePluginComponent, resolvePluginRuntime, resolveSidecarDeclaration, runEscapeValve, runExtensionPoint, scaffoldRegistry, settingsToJsonSchema, sidecarDeclarationRegistry, summarizeBlockAudit, unregisterExtensionHandler, useConnectorsForPlugin, usePluginRuntime, usePluginRuntimeOptional, validateEntityRecordData } from './chunk-732GZEUI.js';
5
7
  export { clearEntityRegistry, deriveEntityKey, getAllEntities, getEntityByKey, registerEntity } from './chunk-CU64QI4A.js';
6
- import { getBlock, getScaffold } from './chunk-YH25Y4FW.js';
7
- export { PLUGIN_API_VERSION, PluginRuntimeProvider, Registry, blockRegistry, componentRegistry, definePlugin, getBlock, getComponent, getDashboardWidgets, getMetric, getPage, getPlugin, getPluginFactory, getScaffold, getWidgetsForZone, isCustomId, listBlocks, listMetrics, listPluginFactories, listPlugins, metricRegistry, pageRegistry, pluginFactoryRegistry, pluginRegistry, registerBlock, registerComponent, registerMetric, registerPage, registerPlugin, registerPluginFactory, registerScaffold, resolvePluginComponent, resolvePluginRuntime, scaffoldRegistry, useConnectorsForPlugin, usePluginRuntime, usePluginRuntimeOptional } from './chunk-YH25Y4FW.js';
8
- import { getCurrentLocale } from './chunk-5RJVUC6J.js';
9
- export { I18nProvider, coreTranslations, getCurrentLocale, mergeTranslations, preloadLocale, registerTranslations, setCurrentLocale, setLocaleStore, useI18nConfig, useTranslation } from './chunk-5RJVUC6J.js';
10
- export { hashRouterAdapter, windowRouterAdapter } from './chunk-Y2C2FBQP.js';
8
+ import { getCurrentLocale } from './chunk-M27JPX3K.js';
9
+ export { I18nProvider, coreTranslations, getCurrentLocale, mergeTranslations, preloadLocale, registerTranslations, setCurrentLocale, setLocaleStore, tl, useI18nConfig, useTranslation } from './chunk-M27JPX3K.js';
10
+ export { defaultRouterAdapter, hashRouterAdapter, historyRouterAdapter, hostRouterAdapter, staticRouterAdapter, windowRouterAdapter } from './chunk-OXQGRJZT.js';
11
11
  export { FayzRuntimeError, createFayzRuntimeClient } from './chunk-7RTUHSKY.js';
12
12
  import * as React3 from 'react';
13
13
  import { useEffect } from 'react';
@@ -25,6 +25,146 @@ var WidgetZone = {
25
25
  SETTINGS_AFTER: "settings.after",
26
26
  FLOATING: "shell.floating"
27
27
  };
28
+
29
+ // src/data/backend-env.ts
30
+ function str(value) {
31
+ return typeof value === "string" && value.length > 0 ? value : void 0;
32
+ }
33
+ function resolveBackendEnv(options = {}) {
34
+ const env = options.env ?? (import.meta.env ?? {});
35
+ const url = str(env.VITE_SUPABASE_URL);
36
+ const key = str(env.VITE_SUPABASE_PUBLISHABLE_KEY) ?? str(env.VITE_SUPABASE_ANON_KEY);
37
+ const flag = env.VITE_SUPABASE_ENABLED;
38
+ const flagSet = flag !== void 0 && flag !== "";
39
+ const enabledByFlag = flag === true || flag === "true";
40
+ let live;
41
+ if (options.force) live = options.force === "live";
42
+ else if (flagSet) live = enabledByFlag && Boolean(url && key);
43
+ else live = Boolean(url && key);
44
+ return {
45
+ live,
46
+ supabaseUrl: live ? url : void 0,
47
+ supabaseAnonKey: live ? key : void 0,
48
+ adapter: live ? "supabase" : "mock"
49
+ };
50
+ }
51
+
52
+ // src/events/envelope.ts
53
+ function emitDomainEvent(key, payload, meta) {
54
+ const event = {
55
+ key,
56
+ payload,
57
+ actorId: meta?.actorId ?? null,
58
+ tenantId: meta?.tenantId ?? null,
59
+ subject: meta?.subject ?? null,
60
+ occurredAt: meta?.occurredAt ?? (/* @__PURE__ */ new Date()).toISOString()
61
+ };
62
+ eventBus.emit(key, event);
63
+ for (const sink of sinks) {
64
+ try {
65
+ sink(event);
66
+ } catch (err) {
67
+ console.warn("[events] sink failed", err);
68
+ }
69
+ }
70
+ return event;
71
+ }
72
+ var sinks = /* @__PURE__ */ new Set();
73
+ function registerEventSink(sink) {
74
+ sinks.add(sink);
75
+ return () => {
76
+ sinks.delete(sink);
77
+ };
78
+ }
79
+ function clearEventSinks() {
80
+ sinks.clear();
81
+ }
82
+ function onDomainEvent(key, handler) {
83
+ return eventBus.on(key, (e) => {
84
+ void handler(e);
85
+ });
86
+ }
87
+ function onDomainEvents(keys, known, handler) {
88
+ const matched = known.filter((k) => keys.some((p) => p === "*" || (p.endsWith(".*") ? k.startsWith(p.slice(0, -1)) : p === k)));
89
+ const offs = matched.map((k) => onDomainEvent(k, handler));
90
+ return () => {
91
+ for (const off of offs) off();
92
+ };
93
+ }
94
+ function sampleEventPayload(fields) {
95
+ const out = {};
96
+ for (const f of fields ?? []) out[f.name] = f.example ?? `{{${f.name}}}`;
97
+ return out;
98
+ }
99
+
100
+ // src/events/log.ts
101
+ var EVENT_LOG_TABLE = "plg_event_log";
102
+ function client() {
103
+ return getSupabaseClientOptional();
104
+ }
105
+ function toRun(row) {
106
+ return {
107
+ id: row.id,
108
+ eventKey: row.event_key,
109
+ status: row.status ?? "recorded",
110
+ payload: row.payload ?? {},
111
+ result: row.result ?? null,
112
+ error: row.error ?? null,
113
+ actorId: row.actor_id ?? null,
114
+ subjectType: row.subject_type ?? null,
115
+ subjectId: row.subject_id ?? null,
116
+ occurredAt: row.occurred_at ?? row.created_at
117
+ };
118
+ }
119
+ function recordEventRun(event, status = "recorded") {
120
+ const db = client();
121
+ if (!db) return;
122
+ const tenantId = event.tenantId ?? getActiveTenantId();
123
+ if (!tenantId) return;
124
+ void (async () => {
125
+ try {
126
+ await db.from(EVENT_LOG_TABLE).insert({
127
+ tenant_id: tenantId,
128
+ event_key: event.key,
129
+ status,
130
+ payload: event.payload ?? {},
131
+ actor_id: event.actorId ?? null,
132
+ subject_type: event.subject?.type ?? null,
133
+ subject_id: event.subject?.id ?? null,
134
+ occurred_at: event.occurredAt
135
+ });
136
+ } catch (err) {
137
+ console.warn("[events] could not record run", err);
138
+ }
139
+ })();
140
+ }
141
+ var started = false;
142
+ function startEventLog() {
143
+ if (started) return () => {
144
+ };
145
+ started = true;
146
+ const off = registerEventSink((event) => recordEventRun(event));
147
+ return () => {
148
+ off();
149
+ started = false;
150
+ };
151
+ }
152
+ async function loadEventRuns(eventKey, options) {
153
+ const db = client();
154
+ if (!db) return [];
155
+ try {
156
+ let q = db.from(EVENT_LOG_TABLE).select("*").eq("event_key", eventKey).order("occurred_at", { ascending: false }).limit(options?.limit ?? 20);
157
+ if (options?.tenantId) q = q.eq("tenant_id", options.tenantId);
158
+ const { data, error } = await q;
159
+ if (error) throw error;
160
+ return (data ?? []).map(toRun);
161
+ } catch (err) {
162
+ console.warn("[events] could not load runs", err);
163
+ return [];
164
+ }
165
+ }
166
+
167
+ // src/events/index.tsx
28
168
  function createEventBus() {
29
169
  const handlers = /* @__PURE__ */ new Map();
30
170
  const bus = {
@@ -134,7 +274,7 @@ function createSafeDataProvider(makeSupabase, makeMock) {
134
274
  });
135
275
  }
136
276
 
137
- // src/phone/index.ts
277
+ // src/lib/phone.ts
138
278
  function flagOf(iso2) {
139
279
  return iso2.toUpperCase().replace(/[^A-Z]/g, "").split("").map((c) => String.fromCodePoint(127462 + c.charCodeAt(0) - 65)).join("");
140
280
  }
@@ -179,7 +319,7 @@ function maskDigitCount(mask) {
179
319
  return n;
180
320
  }
181
321
 
182
- // src/address/index.ts
322
+ // src/lib/address.ts
183
323
  function normalizePostalCode(value) {
184
324
  return (value || "").replace(/\D/g, "");
185
325
  }
@@ -296,23 +436,41 @@ function upsertLink(rel, href) {
296
436
  function clearManaged() {
297
437
  document.head.querySelectorAll(`[${MANAGED}]`).forEach((el) => el.remove());
298
438
  }
439
+ function buildSeoTags(config) {
440
+ const description = config.description ?? "";
441
+ const meta = [
442
+ { name: "description", content: description },
443
+ { property: "og:title", content: config.title },
444
+ { property: "og:description", content: description },
445
+ { property: "og:type", content: config.type ?? "website" },
446
+ { name: "twitter:card", content: config.image ? "summary_large_image" : "summary" },
447
+ { name: "twitter:title", content: config.title },
448
+ { name: "twitter:description", content: description }
449
+ ];
450
+ if (config.canonical) meta.push({ property: "og:url", content: config.canonical });
451
+ if (config.image) {
452
+ meta.push({ property: "og:image", content: config.image });
453
+ meta.push({ name: "twitter:image", content: config.image });
454
+ }
455
+ if (config.siteName) meta.push({ property: "og:site_name", content: config.siteName });
456
+ return {
457
+ title: config.title,
458
+ meta: meta.filter((m) => m.content !== ""),
459
+ links: config.canonical ? [{ rel: "canonical", href: config.canonical }] : [],
460
+ jsonLd: config.jsonLd ?? []
461
+ };
462
+ }
299
463
  function applySeo(config) {
300
464
  if (typeof document === "undefined") return;
465
+ const tags = buildSeoTags(config);
301
466
  clearManaged();
302
- document.title = config.title;
303
- upsertMeta("name", "description", config.description ?? "");
304
- if (config.canonical) upsertLink("canonical", config.canonical);
305
- upsertMeta("property", "og:title", config.title);
306
- upsertMeta("property", "og:description", config.description ?? "");
307
- upsertMeta("property", "og:type", config.type === "article" ? "article" : "website");
308
- if (config.canonical) upsertMeta("property", "og:url", config.canonical);
309
- if (config.image) upsertMeta("property", "og:image", config.image);
310
- if (config.siteName) upsertMeta("property", "og:site_name", config.siteName);
311
- upsertMeta("name", "twitter:card", config.image ? "summary_large_image" : "summary");
312
- upsertMeta("name", "twitter:title", config.title);
313
- upsertMeta("name", "twitter:description", config.description ?? "");
314
- if (config.image) upsertMeta("name", "twitter:image", config.image);
315
- for (const obj of config.jsonLd ?? []) {
467
+ document.title = tags.title;
468
+ for (const tag of tags.meta) {
469
+ if (tag.name) upsertMeta("name", tag.name, tag.content);
470
+ else if (tag.property) upsertMeta("property", tag.property, tag.content);
471
+ }
472
+ for (const link of tags.links) upsertLink(link.rel, link.href);
473
+ for (const obj of tags.jsonLd) {
316
474
  const script = document.createElement("script");
317
475
  script.type = "application/ld+json";
318
476
  script.setAttribute(MANAGED, "");
@@ -395,11 +553,11 @@ function formatDateTime(value) {
395
553
  // src/lib/csv.ts
396
554
  function escapeCSVField(value) {
397
555
  if (value == null) return "";
398
- const str = String(value);
399
- if (str.includes(",") || str.includes('"') || str.includes("\n")) {
400
- return `"${str.replace(/"/g, '""')}"`;
556
+ const str2 = String(value);
557
+ if (str2.includes(",") || str2.includes('"') || str2.includes("\n")) {
558
+ return `"${str2.replace(/"/g, '""')}"`;
401
559
  }
402
- return str;
560
+ return str2;
403
561
  }
404
562
  function buildCSV(columns, rows) {
405
563
  const header = columns.map((c) => escapeCSVField(c.label)).join(",");
@@ -780,11 +938,11 @@ function isMissingFunction(error) {
780
938
  return message.includes(RPC_NAME) && (message.includes("does not exist") || message.includes("not find"));
781
939
  }
782
940
  async function searchViaIndex(query, targets, perTarget, limit) {
783
- const client = getSupabaseClientOptional();
941
+ const client2 = getSupabaseClientOptional();
784
942
  const tenantId = getActiveTenantId();
785
- if (!client || !tenantId) return { hits: [], ok: false };
943
+ if (!client2 || !tenantId) return { hits: [], ok: false };
786
944
  const byKey = new Map(targets.map((t) => [t.key, t]));
787
- const { data, error } = await client.rpc(RPC_NAME, {
945
+ const { data, error } = await client2.rpc(RPC_NAME, {
788
946
  p_query: query.raw,
789
947
  p_tenant_id: tenantId,
790
948
  p_entity_keys: targets.map((t) => t.key),
@@ -895,12 +1053,12 @@ async function searchViaScan(query, targets, perTarget, onProgress) {
895
1053
  return { hits: second.hits, failed: [.../* @__PURE__ */ new Set([...first.failed, ...second.failed])] };
896
1054
  }
897
1055
  async function searchEverything(rawQuery, options) {
898
- const started = Date.now();
1056
+ const started2 = Date.now();
899
1057
  const query = normalizeQuery(rawQuery);
900
1058
  const targets = options.targets;
901
1059
  const limit = options.limit ?? DEFAULT_LIMIT;
902
1060
  const perTarget = options.perTarget ?? DEFAULT_PER_TARGET;
903
- const empty = (via2) => assemble(rawQuery, [], targets, { via: via2, failed: [], elapsedMs: Date.now() - started, perTarget, limit });
1061
+ const empty = (via2) => assemble(rawQuery, [], targets, { via: via2, failed: [], elapsedMs: Date.now() - started2, perTarget, limit });
904
1062
  if (query.folded.length < MIN_QUERY_LENGTH || targets.length === 0) return empty("cache");
905
1063
  const scope = scopeKey(targets);
906
1064
  const exact = cacheGet(scope, query.folded);
@@ -908,7 +1066,7 @@ async function searchEverything(rawQuery, options) {
908
1066
  return assemble(rawQuery, exact.hits, targets, {
909
1067
  via: "cache",
910
1068
  failed: [],
911
- elapsedMs: Date.now() - started,
1069
+ elapsedMs: Date.now() - started2,
912
1070
  perTarget,
913
1071
  limit
914
1072
  });
@@ -927,7 +1085,7 @@ async function searchEverything(rawQuery, options) {
927
1085
  options.onPartial(assemble(rawQuery, rescored, targets, {
928
1086
  via: "cache",
929
1087
  failed: [],
930
- elapsedMs: Date.now() - started,
1088
+ elapsedMs: Date.now() - started2,
931
1089
  perTarget,
932
1090
  limit,
933
1091
  partial: true
@@ -952,7 +1110,7 @@ async function searchEverything(rawQuery, options) {
952
1110
  const scanned = await searchViaScan(query, targets, perTarget, emit ? (running) => emit(assemble(rawQuery, running, targets, {
953
1111
  via: "scan",
954
1112
  failed: [],
955
- elapsedMs: Date.now() - started,
1113
+ elapsedMs: Date.now() - started2,
956
1114
  perTarget,
957
1115
  limit,
958
1116
  partial: true
@@ -964,7 +1122,7 @@ async function searchEverything(rawQuery, options) {
964
1122
  const result = assemble(rawQuery, hits, targets, {
965
1123
  via,
966
1124
  failed,
967
- elapsedMs: Date.now() - started,
1125
+ elapsedMs: Date.now() - started2,
968
1126
  perTarget,
969
1127
  limit
970
1128
  });
@@ -978,37 +1136,142 @@ async function searchEverything(rawQuery, options) {
978
1136
  });
979
1137
  return result;
980
1138
  }
981
- function UnknownBlock({ type }) {
1139
+ var errorVisibility = null;
1140
+ function defaultVisibility() {
1141
+ try {
1142
+ return process.env.NODE_ENV !== "production" ? "visible" : "silent";
1143
+ } catch {
1144
+ return "silent";
1145
+ }
1146
+ }
1147
+ function setBlockErrorVisibility(visibility) {
1148
+ errorVisibility = visibility;
1149
+ }
1150
+ var editorMode = false;
1151
+ function setBlockEditorMode(enabled) {
1152
+ editorMode = enabled;
1153
+ }
1154
+ function blockEditorMode() {
1155
+ return editorMode;
1156
+ }
1157
+ var BLOCK_PATH_ATTRIBUTE = "data-fayz-block";
1158
+ var BLOCK_TYPE_ATTRIBUTE = "data-fayz-block-type";
1159
+ var BlockPathContext = React3.createContext("");
1160
+ function useBlockPath() {
1161
+ return React3.useContext(BlockPathContext);
1162
+ }
1163
+ function getBlockErrorVisibility() {
1164
+ return errorVisibility ?? defaultVisibility();
1165
+ }
1166
+ function BlockErrorCard({ title, detail }) {
982
1167
  return React3.createElement(
983
1168
  "div",
984
1169
  {
1170
+ "data-block-error": title,
985
1171
  style: {
986
- border: "1px dashed #c026d3",
987
- color: "#a21caf",
1172
+ border: "1px dashed #dc2626",
1173
+ color: "#b91c1c",
988
1174
  padding: "8px 12px",
989
1175
  font: "12px ui-monospace, monospace",
990
1176
  borderRadius: 6
991
1177
  }
992
1178
  },
993
- `Unknown block: "${type}"`
1179
+ title,
1180
+ detail ? React3.createElement("div", { style: { opacity: 0.8, marginTop: 4 } }, detail) : null
994
1181
  );
995
1182
  }
996
- function BlockRenderer({ node }) {
1183
+ function UnknownBlock({ type }) {
1184
+ if (getBlockErrorVisibility() === "silent") return null;
1185
+ return React3.createElement(BlockErrorCard, { title: `Unknown block: "${type}"` });
1186
+ }
1187
+ var BlockErrorBoundary = class extends React3.Component {
1188
+ constructor() {
1189
+ super(...arguments);
1190
+ this.state = { error: null };
1191
+ }
1192
+ static getDerivedStateFromError(error) {
1193
+ return { error };
1194
+ }
1195
+ componentDidCatch(error, info) {
1196
+ console.error(`[blocks] block "${this.props.blockType}" crashed while rendering:`, error, info.componentStack);
1197
+ }
1198
+ render() {
1199
+ if (!this.state.error) return this.props.children;
1200
+ if (getBlockErrorVisibility() === "silent") return null;
1201
+ return React3.createElement(BlockErrorCard, {
1202
+ title: `Block "${this.props.blockType}" crashed`,
1203
+ detail: this.state.error.message
1204
+ });
1205
+ }
1206
+ };
1207
+ var BlockAncestryContext = React3.createContext([]);
1208
+ function ConstraintViolation({ detail }) {
1209
+ if (getBlockErrorVisibility() === "silent") return null;
1210
+ return React3.createElement(BlockErrorCard, { title: "Misplaced block", detail });
1211
+ }
1212
+ var warnedViolations = /* @__PURE__ */ new Set();
1213
+ function BlockRenderer({ node, path }) {
1214
+ const ancestry = React3.useContext(BlockAncestryContext);
997
1215
  const Comp = getBlock(node.type);
998
- const childEls = node.children?.length ? node.children.map(
999
- (child, i) => React3.createElement(BlockRenderer, { key: child.id ?? `${child.type}-${i}`, node: child })
1000
- ) : null;
1001
1216
  if (!Comp) return React3.createElement(UnknownBlock, { type: node.type });
1002
- return React3.createElement(Comp, { ...node.props ?? {}, node }, childEls);
1217
+ const violations = checkNodePlacement(node.type, ancestry);
1218
+ if (violations.length > 0) {
1219
+ const message = violations.map((v) => v.detail).join("; ");
1220
+ if (!warnedViolations.has(message)) {
1221
+ warnedViolations.add(message);
1222
+ console.warn(`[blocks] ${message}`);
1223
+ }
1224
+ return React3.createElement(ConstraintViolation, { detail: violations[0].detail });
1225
+ }
1226
+ const childEls = node.children?.length ? renderBlocks(node.children, path ? `${path}.children` : void 0) : null;
1227
+ const rendered = React3.createElement(
1228
+ BlockAncestryContext.Provider,
1229
+ { value: ancestry.length ? [...ancestry, node.type] : [node.type] },
1230
+ React3.createElement(
1231
+ BlockErrorBoundary,
1232
+ { blockType: node.type },
1233
+ React3.createElement(Comp, { ...node.props ?? {}, node }, childEls)
1234
+ )
1235
+ );
1236
+ if (!editorMode || !path) return rendered;
1237
+ return React3.createElement(
1238
+ BlockPathContext.Provider,
1239
+ { value: path },
1240
+ React3.createElement(
1241
+ "div",
1242
+ {
1243
+ [BLOCK_PATH_ATTRIBUTE]: path,
1244
+ [BLOCK_TYPE_ATTRIBUTE]: node.type,
1245
+ style: { display: "contents" }
1246
+ },
1247
+ rendered
1248
+ )
1249
+ );
1003
1250
  }
1004
- function renderBlocks(nodes) {
1251
+ function renderBlocks(nodes, basePath) {
1005
1252
  return nodes.map(
1006
- (node, i) => React3.createElement(BlockRenderer, { key: node.id ?? `${node.type}-${i}`, node })
1253
+ (node, i) => React3.createElement(BlockRenderer, {
1254
+ key: node.id ?? `${node.type}-${i}`,
1255
+ node,
1256
+ // POSITIONAL, deliberately. `[#id]` is the reorder-stable form
1257
+ // store-change supports, and using it here looked obviously better — but
1258
+ // by the time a node reaches this function its `id` has been synthesized
1259
+ // (`${type}-${index}`) for every block the document did not name, and the
1260
+ // renderer cannot tell an authored id from a generated one. Emitting
1261
+ // `[#hero-0]` produced paths that resolve against nothing.
1262
+ //
1263
+ // The cost of positional is that a reorder invalidates an outstanding
1264
+ // path. That is bounded: a path is captured on click and spent on save,
1265
+ // and a document that names its blocks can be addressed by id by whoever
1266
+ // holds the document — which is the editor, not the renderer.
1267
+ path: basePath ? `${basePath}[${i}]` : void 0
1268
+ })
1007
1269
  );
1008
1270
  }
1009
1271
  function BlockChildren({ node }) {
1272
+ const path = useBlockPath();
1010
1273
  if (!node?.children?.length) return null;
1011
- return renderBlocks(node.children);
1274
+ return renderBlocks(node.children, path ? `${path}.children` : void 0);
1012
1275
  }
1013
1276
 
1014
1277
  // src/manifest/index.ts
@@ -2014,7 +2277,7 @@ function renderApp(input, opts = {}) {
2014
2277
  const Scaffold = getScaffold(surface.scaffold);
2015
2278
  if (!Scaffold) {
2016
2279
  throw new Error(
2017
- `Scaffold "${surface.scaffold}" is not registered. Call renderApp from the package that provides it (e.g. @fayz-ai/saas, @fayz-ai/portal, @fayz-ai/storefront) or call its register*Scaffold() first.`
2280
+ `Scaffold "${surface.scaffold}" is not registered. Call renderApp from the package that provides it (e.g. @fayz-ai/admin, @fayz-ai/portal, @fayz-ai/storefront) or call its register*Scaffold() first.`
2018
2281
  );
2019
2282
  }
2020
2283
  return React3.createElement(
@@ -2063,6 +2326,79 @@ function routeModule(path) {
2063
2326
  return path.replace(/^\/+/, "").split("/")[0] ?? "";
2064
2327
  }
2065
2328
 
2066
- export { BlockChildren, BlockRenderer, COUNTRIES, CURRENT_MANIFEST_VERSION, DATA_CHANGED_EVENT, DEFAULT_COUNTRY, MIN_QUERY_LENGTH, WidgetZone, absoluteUrl, app_manifest_schema_default as appManifestSchema, applySeo, breadcrumbJsonLd, buildCSV, clearPostalCache, clearSearchCache, computeContractHash, createEventBus, createSafeDataProvider, createViaCepProvider, defineApp, digitsOf, downloadCSV, emitDataChanged, eventBus, exportCSV, foldText, foldWithMap, formatCurrency, formatDate, formatDateTime, formatPostalCode, getActiveLocale, getCountry, getDefaultCurrency, getPostalLookupProvider, highlightRanges, isSearchIndexAvailable, isValidPostalCode, lookupPostalCode, maskDigitCount, maskPhone, matchesDataChange, migrateManifest, navHistoryBack, normalizePostalCode, normalizeQuery, organizationJsonLd, recordNavigation, registerManifestMigration, renderApp, renderBlocks, routeModule, scoreCandidate, searchEverything, seoOrigin, serializeManifest, serializeManifestWithHash, setDefaultCurrency, setPostalLookupProvider, setSearchIndexAvailable, similarity, unmaskPhone, useDataChanged, useManifest, useNavHistoryStore, useNavReferrer, useOnEvent, useSeo, validateManifest };
2329
+ // src/messaging/registry.ts
2330
+ var defaultsRegistry = /* @__PURE__ */ new Map();
2331
+ function registerMessageDefaults(defs) {
2332
+ for (const def of defs) defaultsRegistry.set(def.eventKey, def);
2333
+ }
2334
+ function getMessageDefaults() {
2335
+ return Array.from(defaultsRegistry.values());
2336
+ }
2337
+ function clearMessageDefaults() {
2338
+ defaultsRegistry.clear();
2339
+ }
2340
+ function renderMessageTemplate(text, values) {
2341
+ return text.replace(/\{\{\s*(\w+)\s*\}\}/g, (whole, key) => values[key] ?? whole);
2342
+ }
2343
+ function resolveMessages(overrides, events) {
2344
+ const byKey = new Map(overrides.map((o) => [`${o.eventKey}:${o.channel}`, o]));
2345
+ const byEvent = new Map(events.map((e) => [e.name, e]));
2346
+ const out = [];
2347
+ for (const def of getMessageDefaults()) {
2348
+ const event = byEvent.get(def.eventKey);
2349
+ if (!event) continue;
2350
+ const placeholders = (event.fields ?? []).map((f) => `{{${f.name}}}`);
2351
+ for (const channel of def.channels) {
2352
+ const fallback = def.defaults[channel];
2353
+ if (!fallback) continue;
2354
+ const override = byKey.get(`${def.eventKey}:${channel}`) ?? null;
2355
+ out.push({
2356
+ event,
2357
+ kind: def.kind,
2358
+ channel,
2359
+ override,
2360
+ enabled: override?.enabled ?? def.defaultEnabled?.[channel] ?? false,
2361
+ subject: override?.subject ?? fallback.subject ?? "",
2362
+ body: override?.body ?? fallback.body,
2363
+ customized: Boolean(override?.subject || override?.body),
2364
+ placeholders
2365
+ });
2366
+ }
2367
+ }
2368
+ return out;
2369
+ }
2370
+ function resolveMessage(eventKey, channel, overrides, events) {
2371
+ return resolveMessages(overrides, events).find((m) => m.event.name === eventKey && m.channel === channel) ?? null;
2372
+ }
2373
+ function getEventsWithoutMessages(events) {
2374
+ return events.filter((e) => !defaultsRegistry.has(e.name));
2375
+ }
2376
+ var MESSAGE_TEMPLATES_TABLE = "plg_automations_templates";
2377
+ async function loadMessageOverrides(tenantId) {
2378
+ const client2 = getSupabaseClientOptional();
2379
+ if (!client2) return [];
2380
+ try {
2381
+ let q = client2.from(MESSAGE_TEMPLATES_TABLE).select("*");
2382
+ if (tenantId) q = q.eq("tenant_id", tenantId);
2383
+ const { data, error } = await q;
2384
+ if (error) throw error;
2385
+ return (data ?? []).map((row) => ({
2386
+ id: row.id,
2387
+ tenantId: row.tenant_id,
2388
+ eventKey: row.event_key,
2389
+ channel: row.channel ?? "email",
2390
+ enabled: row.enabled ?? null,
2391
+ subject: row.subject || null,
2392
+ body: row.body || null,
2393
+ name: row.name || null,
2394
+ updatedAt: row.updated_at ?? row.created_at
2395
+ }));
2396
+ } catch (err) {
2397
+ console.warn("[messaging] could not load overrides; using defaults", err);
2398
+ return [];
2399
+ }
2400
+ }
2401
+
2402
+ export { BLOCK_PATH_ATTRIBUTE, BLOCK_TYPE_ATTRIBUTE, BlockChildren, BlockErrorBoundary, BlockRenderer, COUNTRIES, CURRENT_MANIFEST_VERSION, DATA_CHANGED_EVENT, DEFAULT_COUNTRY, EVENT_LOG_TABLE, MESSAGE_TEMPLATES_TABLE, MIN_QUERY_LENGTH, WidgetZone, absoluteUrl, app_manifest_schema_default as appManifestSchema, applySeo, blockEditorMode, breadcrumbJsonLd, buildCSV, buildSeoTags, clearEventSinks, clearMessageDefaults, clearPostalCache, clearSearchCache, computeContractHash, createEventBus, createSafeDataProvider, createViaCepProvider, defineApp, digitsOf, downloadCSV, emitDataChanged, emitDomainEvent, eventBus, exportCSV, foldText, foldWithMap, formatCurrency, formatDate, formatDateTime, formatPostalCode, getActiveLocale, getBlockErrorVisibility, getCountry, getDefaultCurrency, getEventsWithoutMessages, getMessageDefaults, getPostalLookupProvider, highlightRanges, isSearchIndexAvailable, isValidPostalCode, loadEventRuns, loadMessageOverrides, lookupPostalCode, maskDigitCount, maskPhone, matchesDataChange, migrateManifest, navHistoryBack, normalizePostalCode, normalizeQuery, onDomainEvent, onDomainEvents, organizationJsonLd, recordEventRun, recordNavigation, registerEventSink, registerManifestMigration, registerMessageDefaults, renderApp, renderBlocks, renderMessageTemplate, resolveBackendEnv, resolveMessage, resolveMessages, routeModule, sampleEventPayload, scoreCandidate, searchEverything, seoOrigin, serializeManifest, serializeManifestWithHash, setBlockEditorMode, setBlockErrorVisibility, setDefaultCurrency, setPostalLookupProvider, setSearchIndexAvailable, similarity, startEventLog, unmaskPhone, useBlockPath, useDataChanged, useManifest, useNavHistoryStore, useNavReferrer, useOnEvent, useSeo, validateManifest };
2067
2403
  //# sourceMappingURL=index.js.map
2068
2404
  //# sourceMappingURL=index.js.map