@declarion/react 0.1.65 → 0.1.67

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 (55) hide show
  1. package/README.md +32 -0
  2. package/dist-lib/api/agents.d.ts +18 -3
  3. package/dist-lib/api/auth-redirect.d.ts +3 -0
  4. package/dist-lib/api/auth.d.ts +14 -0
  5. package/dist-lib/api/client.d.ts +13 -0
  6. package/dist-lib/api/events.d.ts +17 -0
  7. package/dist-lib/components/agents/AgentChatPanel.d.ts +2 -1
  8. package/dist-lib/components/fields/RichTextField.d.ts +2 -0
  9. package/dist-lib/components/fields/index.d.ts +1 -0
  10. package/dist-lib/components/file-widgets/CircleImage.d.ts +2 -0
  11. package/dist-lib/components/file-widgets/DocumentCard.d.ts +2 -0
  12. package/dist-lib/components/file-widgets/FileList.d.ts +2 -0
  13. package/dist-lib/components/file-widgets/Grid.d.ts +2 -0
  14. package/dist-lib/components/file-widgets/ImageWidget.d.ts +12 -0
  15. package/dist-lib/components/file-widgets/LabeledSlots.d.ts +2 -0
  16. package/dist-lib/components/file-widgets/SquareImage.d.ts +2 -0
  17. package/dist-lib/components/file-widgets/WideBanner.d.ts +2 -0
  18. package/dist-lib/components/file-widgets/builtins.d.ts +1 -0
  19. package/dist-lib/components/file-widgets/cropper.d.ts +14 -0
  20. package/dist-lib/components/file-widgets/draft-scope.d.ts +22 -0
  21. package/dist-lib/components/file-widgets/helpers.d.ts +12 -0
  22. package/dist-lib/components/file-widgets/host.d.ts +19 -0
  23. package/dist-lib/components/file-widgets/index.d.ts +16 -0
  24. package/dist-lib/components/file-widgets/payload.d.ts +21 -0
  25. package/dist-lib/components/file-widgets/registry.d.ts +5 -0
  26. package/dist-lib/components/file-widgets/types.d.ts +15 -0
  27. package/dist-lib/components/file-widgets/upload.d.ts +25 -0
  28. package/dist-lib/components/file-widgets/value.d.ts +4 -0
  29. package/dist-lib/components/layout/ImpersonationBanner.d.ts +11 -0
  30. package/dist-lib/components/layout/ImpersonationFrame.d.ts +11 -0
  31. package/dist-lib/components/layout/ImpersonationStartModal.d.ts +22 -0
  32. package/dist-lib/components/layout/TenantChip.d.ts +9 -1
  33. package/dist-lib/components/list/QuickPeek.d.ts +13 -6
  34. package/dist-lib/components/pages/SmartDetailPage.d.ts +1 -1
  35. package/dist-lib/components/pages/SmartListPage.d.ts +1 -1
  36. package/dist-lib/components/primitives/Fields.d.ts +3 -3
  37. package/dist-lib/components/primitives/MenuItem.d.ts +2 -1
  38. package/dist-lib/components/shell/CommandPalette.d.ts +2 -1
  39. package/dist-lib/declarion-react.css +1 -1
  40. package/dist-lib/hooks/useAgentConversation.d.ts +9 -1
  41. package/dist-lib/hooks/useImpersonation.d.ts +23 -0
  42. package/dist-lib/hooks/useVersionWatcher.d.ts +30 -0
  43. package/dist-lib/index.d.ts +6 -0
  44. package/dist-lib/index.js +6653 -3255
  45. package/dist-lib/index.js.map +1 -1
  46. package/dist-lib/lib/rich-text.d.ts +14 -0
  47. package/dist-lib/lib/versionTracker.d.ts +66 -0
  48. package/dist-lib/types/api.d.ts +20 -0
  49. package/dist-lib/types/files.d.ts +76 -0
  50. package/dist-lib/types/schema.d.ts +11 -0
  51. package/dist-lib/vite/fingerprint-plugin.d.ts +45 -0
  52. package/dist-lib/vite/index.d.ts +21 -0
  53. package/dist-lib/vite/index.js +52 -0
  54. package/dist-lib/vite/index.js.map +1 -0
  55. package/package.json +11 -3
@@ -0,0 +1,14 @@
1
+ import type { HydratedFile } from "../types/files";
2
+ export interface RichTextValue {
3
+ markdown: string;
4
+ files: Record<string, HydratedFile>;
5
+ }
6
+ export declare function richTextMarkdown(value: unknown): string;
7
+ export declare function richTextFiles(value: unknown): Record<string, HydratedFile>;
8
+ export declare function createRichTextValue(markdownValue: unknown, inlineFilesValue: unknown): RichTextValue;
9
+ export declare function withRichTextFile(value: unknown, file: HydratedFile): RichTextValue;
10
+ export declare function withoutRichTextFiles(value: unknown, removedIds: Iterable<string>): RichTextValue;
11
+ export declare function inlineFilesById(value: unknown): Record<string, HydratedFile>;
12
+ export declare function extractDeclarionFileIds(markdown: string): string[];
13
+ export declare function extractDeclarionFileId(url: string | undefined): string | null;
14
+ export declare function richTextTokenForFile(file: Pick<HydratedFile, "id" | "content_type" | "filename">): string;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * versionTracker — central staleness-detection state for the SPA.
3
+ *
4
+ * Every API response carries `X-Declarion-Version: <combined-fingerprint>`
5
+ * (set by the server's version_header middleware). The FIRST arrival
6
+ * in a bundle's lifetime is captured as the baseline; any later
7
+ * response with a different value triggers drift detection — the SPA
8
+ * either silently invalidates the schema query (if only schema differs)
9
+ * or prompts the user to reload (if assets/binary changed).
10
+ *
11
+ * **State is in-memory only — no sessionStorage / localStorage.** Each
12
+ * bundle load captures its own baseline from its first response. The
13
+ * bundle IS its own version contract; the live server's first answer
14
+ * defines what version the bundle should consider itself. Persisting
15
+ * across reloads is actively harmful: a stale baseline from a previous
16
+ * bundle could override the live answer, producing a "click Reload →
17
+ * page reloads → toast pops again" infinite loop. This is the same
18
+ * lesson behind why `index.html` is `Cache-Control: no-cache` — the
19
+ * bootstrap manifest must always be live, never replayed.
20
+ *
21
+ * Defense in depth runs three sources into the same comparator:
22
+ * 1. observe() — header read on every API response (apiFetch hook).
23
+ * 2. fetchProbe() — explicit GET /api/version (focus / online / 60s).
24
+ * 3. (optional) SSE `version-changed` event from useSSE.
25
+ *
26
+ * Cross-tab coordination via BroadcastChannel('declarion-version') —
27
+ * runtime IPC only, not persistence. When one tab detects drift it
28
+ * fans the decision out so all tabs reload together (avoids the
29
+ * half-old / half-new tab anti-pattern). Each tab still bootstraps
30
+ * its own baseline independently.
31
+ */
32
+ export interface VersionDelta {
33
+ /** Reason the delta was emitted. Lets subscribers decide UX. */
34
+ kind: "schema-only" | "asset-or-binary" | "unknown";
35
+ /** Latest combined fingerprint observed. Drives the next baseline. */
36
+ observed: string;
37
+ /** Per-component breakdown when /api/version was reached. */
38
+ components?: VersionComponents;
39
+ }
40
+ export interface VersionComponents {
41
+ schema: string;
42
+ asset: string;
43
+ binary: string;
44
+ }
45
+ export type VersionDeltaListener = (delta: VersionDelta) => void;
46
+ /**
47
+ * Observe an API response. Captures the first-seen fingerprint and
48
+ * compares subsequent ones. Idempotent — safe to call from every
49
+ * apiFetch round-trip; backward-compatible — no-op when the header
50
+ * is absent (older server).
51
+ */
52
+ export declare function observe(headers: Headers | undefined | null): void;
53
+ /**
54
+ * Hit /api/version with If-None-Match (cheap when nothing changed —
55
+ * 304 with no body). On any change, emit a typed delta.
56
+ */
57
+ export declare function fetchProbe(): Promise<void>;
58
+ /**
59
+ * Subscribe to drift events. Called once from useVersionWatcher; the
60
+ * subscriber renders the UpdatePrompt (toast or silent invalidation).
61
+ */
62
+ export declare function subscribe(cb: VersionDeltaListener): () => void;
63
+ /**
64
+ * Test-only: reset internal state. Not exposed via package exports.
65
+ */
66
+ export declare function __resetForTests(): void;
@@ -1,4 +1,5 @@
1
1
  import type { AccentDef, LocalizedString } from "./schema";
2
+ import type { HydratedFile } from "./files";
2
3
  export interface ListMeta {
3
4
  total: number;
4
5
  page: number;
@@ -47,9 +48,26 @@ export interface AuthUser {
47
48
  roles: string[];
48
49
  permissions?: string[];
49
50
  tenant?: Tenant;
51
+ /** Populated only when the request is acting under an impersonation session. */
52
+ impersonation?: ImpersonationInfo;
50
53
  created_at: string;
51
54
  updated_at: string;
52
55
  }
56
+ /**
57
+ * ImpersonationInfo is the read-side projection of the active session
58
+ * surfaced by auth.me. Drives the banner, topbar chip, viewport frame,
59
+ * and the "Exit impersonation" menu item.
60
+ */
61
+ export interface ImpersonationInfo {
62
+ session_id: string;
63
+ real_user_id: string;
64
+ real_user_email?: string;
65
+ target_user_id: string;
66
+ target_user_email?: string;
67
+ reason: string;
68
+ started_at: string;
69
+ expires_at: string;
70
+ }
53
71
  export interface LoginResponse {
54
72
  expires_at: string;
55
73
  user: AuthUser;
@@ -87,6 +105,7 @@ export interface PublicBranding {
87
105
  app_logo?: string;
88
106
  app_initial?: string;
89
107
  accent_color?: string;
108
+ ai_name?: string;
90
109
  wordmark?: string;
91
110
  version_label?: string;
92
111
  auth_tagline?: LocalizedString;
@@ -199,6 +218,7 @@ export type Units = Record<string, string>;
199
218
  /** A row enriched with $-prefixed sub-resources (as returned by Get or write responses). */
200
219
  export interface EnrichedRow extends Record<string, unknown> {
201
220
  $refs?: Refs;
221
+ $files?: Record<string, HydratedFile | HydratedFile[] | null>;
202
222
  $statuses?: V2StatusInstance[];
203
223
  $properties?: V2PropertyInstance[];
204
224
  $params?: V2ParamInstance[];
@@ -0,0 +1,76 @@
1
+ export type FileFieldMode = "single" | "array" | "named_map" | "rich_text_inline";
2
+ export interface FileFieldDisplay {
3
+ widget: string;
4
+ placeholder?: string;
5
+ crop_on_upload?: boolean;
6
+ aspect_ratio?: string;
7
+ focal_point?: boolean;
8
+ is_listable?: boolean;
9
+ listable_thumbnail?: string;
10
+ reorderable?: boolean;
11
+ bulk_upload?: boolean;
12
+ bulk_download?: boolean;
13
+ lazy_load?: boolean;
14
+ }
15
+ export interface FileNamedSlotDef {
16
+ accepts?: string[];
17
+ max_size_bytes?: number;
18
+ svg_sanitize?: boolean;
19
+ pdf_strip_js?: boolean;
20
+ exif_strip?: boolean;
21
+ aspect_ratio?: string;
22
+ storage_backend?: string;
23
+ }
24
+ export interface FileFieldDef {
25
+ name: string;
26
+ mode: FileFieldMode;
27
+ accepts?: string[];
28
+ max_size_bytes?: number;
29
+ max_count?: number;
30
+ max_total_size_bytes?: number;
31
+ required?: boolean;
32
+ slots?: Record<string, FileNamedSlotDef>;
33
+ display?: FileFieldDisplay;
34
+ }
35
+ export interface HydratedFile {
36
+ id: string;
37
+ filename: string;
38
+ content_type: string;
39
+ size_bytes: number;
40
+ sha256?: string;
41
+ width?: number;
42
+ height?: number;
43
+ page_count?: number;
44
+ uploaded_at?: string;
45
+ uploaded_by?: string;
46
+ url?: string;
47
+ presigned_url?: string;
48
+ derivations?: Record<string, string>;
49
+ metadata?: Record<string, unknown>;
50
+ position?: number;
51
+ slot?: string;
52
+ version?: {
53
+ number?: number;
54
+ is_current?: boolean;
55
+ supersedes_file_id?: string;
56
+ };
57
+ }
58
+ export type NamedFileFieldValue = Record<string, HydratedFile | null>;
59
+ export type FileFieldValue = HydratedFile | HydratedFile[] | NamedFileFieldValue | null;
60
+ export interface UploadProgress {
61
+ loaded: number;
62
+ total: number;
63
+ pct: number;
64
+ }
65
+ export interface UploadedFile {
66
+ id: string;
67
+ filename: string;
68
+ content_type: string;
69
+ size_bytes: number;
70
+ sha256: string;
71
+ dedup?: boolean;
72
+ width?: number;
73
+ height?: number;
74
+ url?: string;
75
+ metadata?: Record<string, unknown>;
76
+ }
@@ -1,4 +1,5 @@
1
1
  import { OrderedMap } from "./ordmap";
2
+ import type { FileFieldDef } from "./files";
2
3
  export { OrderedMap };
3
4
  export type LocalizedString = Record<string, string>;
4
5
  /**
@@ -8,6 +9,12 @@ export type LocalizedString = Record<string, string>;
8
9
  */
9
10
  export declare const DETAIL_SCREEN_NONE = "none";
10
11
  export declare function loc(ls: LocalizedString | undefined, lang?: string): string;
12
+ export declare const DISPLAY_KEY = "$display";
13
+ export declare function getDisplayValue(row: Record<string, unknown> | null | undefined, entity: {
14
+ display?: {
15
+ display_field?: string;
16
+ };
17
+ } | null | undefined): string | undefined;
11
18
  export declare function fieldDisplayName(field: EntityField, fieldName: string, entities?: Record<string, Entity>): string;
12
19
  export interface RefDisplay {
13
20
  field: string;
@@ -53,6 +60,7 @@ export interface EntityField {
53
60
  color?: string;
54
61
  }>;
55
62
  enum?: string;
63
+ files?: FileFieldDef;
56
64
  ref?: RefConfig;
57
65
  structure?: string;
58
66
  array?: boolean;
@@ -183,6 +191,7 @@ export interface Entity {
183
191
  description?: LocalizedString;
184
192
  icon: string;
185
193
  display_field?: string;
194
+ display_template?: string;
186
195
  };
187
196
  fields: OrderedMap<EntityField>;
188
197
  soft_delete?: string;
@@ -194,6 +203,7 @@ export interface Entity {
194
203
  actions?: Record<string, Action>;
195
204
  handlers?: Record<string, HandlerDef>;
196
205
  associations?: Record<string, AssociationDef>;
206
+ files?: OrderedMap<FileFieldDef>;
197
207
  detail_screen?: string;
198
208
  }
199
209
  export declare function getPrimaryKeyFields(entity: Entity): string[];
@@ -469,6 +479,7 @@ export interface Branding {
469
479
  app_logo?: string;
470
480
  app_initial?: string;
471
481
  accent_color?: string;
482
+ ai_name?: string;
472
483
  wordmark?: string;
473
484
  version_label?: string;
474
485
  status_url?: string;
@@ -0,0 +1,45 @@
1
+ import type { Plugin } from "vite";
2
+ export interface DeclarionFingerprintPluginOptions {
3
+ /**
4
+ * Subdirectory of `outDir` to walk. Defaults to "assets" — Vite's
5
+ * standard hashed-output location. Override only if a consumer has
6
+ * customized `build.assetsDir`.
7
+ */
8
+ assetsDir?: string;
9
+ /**
10
+ * Filename of the emitted fingerprint, written next to `index.html`.
11
+ * Defaults to "bundle-fingerprint.txt". Match this on the server
12
+ * side (`apps/server/fingerprint.go:readBundleFingerprint`) if you
13
+ * customize.
14
+ */
15
+ filename?: string;
16
+ }
17
+ /**
18
+ * Vite plugin that emits a single-line `bundle-fingerprint.txt` next
19
+ * to `index.html` after every production build. The fingerprint is a
20
+ * SHA-256 over every file in `assetsDir/` — sorted by name, length-
21
+ * prefixed (`name\x00sha256\x00`) so concatenation is collision-safe.
22
+ *
23
+ * The Declarion server reads this file at boot and folds it into the
24
+ * combined build identity exposed via `X-Declarion-Version` and
25
+ * `/api/version`. When a consumer redeploys the UI bundle (changed
26
+ * JS/CSS/assets) the file changes → server fingerprint changes → SDK
27
+ * detects asset drift → user is prompted to reload to pick up the
28
+ * new code.
29
+ *
30
+ * Why a separate file rather than walking `assetsDir/` from Go at
31
+ * boot:
32
+ * - Eliminates a per-process I/O dependency on bundle layout
33
+ * conventions (Vite could change `assetsDir` defaults; the
34
+ * plugin is the canonical contract).
35
+ * - Computed once at build time, read once at boot — never on the
36
+ * hot path.
37
+ * - Lets the consumer image ship the fingerprint as an immutable
38
+ * artifact rather than re-deriving it at every server start.
39
+ *
40
+ * Backward compatible: if a consumer hasn't adopted the plugin yet,
41
+ * `bundle-fingerprint.txt` is absent at boot, the server logs once
42
+ * and degrades to binary-only drift detection (still correct — the
43
+ * binary fingerprint differs across builds anyway). No errors.
44
+ */
45
+ export declare function declarionFingerprintPlugin(options?: DeclarionFingerprintPluginOptions): Plugin;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @declarion/react/vite — Vite plugin entry point.
3
+ *
4
+ * Separate from the SDK's main React entry (`@declarion/react`) so this
5
+ * Node-only code never accidentally pulls into a browser bundle.
6
+ *
7
+ * Usage in a consumer's `vite.config.ts`:
8
+ *
9
+ * import { declarionFingerprintPlugin } from "@declarion/react/vite";
10
+ *
11
+ * export default defineConfig({
12
+ * plugins: [react(), declarionFingerprintPlugin()],
13
+ * });
14
+ *
15
+ * One line, one plugin — works in every Declarion deployment mode
16
+ * (local-up, prebuilt-declarion, fully-prebuilt prod) because the
17
+ * plugin runs at consumer-build time regardless of where the SDK
18
+ * itself comes from (npm pin / vite alias / link).
19
+ */
20
+ export { declarionFingerprintPlugin } from "./fingerprint-plugin";
21
+ export type { DeclarionFingerprintPluginOptions } from "./fingerprint-plugin";
@@ -0,0 +1,52 @@
1
+ import { createHash as e } from "node:crypto";
2
+ import { readFileSync as t, readdirSync as n, statSync as r, writeFileSync as i } from "node:fs";
3
+ import { join as a } from "node:path";
4
+ //#region src/vite/fingerprint-plugin.ts
5
+ function o(n = {}) {
6
+ let r = n.filename ?? "bundle-fingerprint.txt";
7
+ return {
8
+ name: "declarion-fingerprint",
9
+ apply: "build",
10
+ closeBundle: {
11
+ sequential: !0,
12
+ handler() {
13
+ let o = this.environment.config, c = o.build.outDir, l = a(c, n.assetsDir ?? o.build.assetsDir ?? "assets"), u = s(l);
14
+ u.sort();
15
+ let d = e("sha256");
16
+ for (let n of u) {
17
+ let r = a(l, n), i = e("sha256").update(t(r)).digest("hex");
18
+ d.update(`${n.length}:${n}\n`), d.update(`${i.length}:${i}\n`);
19
+ }
20
+ let f = d.digest("hex");
21
+ i(a(c, r), f + "\n", "utf8");
22
+ }
23
+ }
24
+ };
25
+ }
26
+ function s(e) {
27
+ let t = [], i = [{
28
+ abs: e,
29
+ rel: ""
30
+ }];
31
+ for (; i.length > 0;) {
32
+ let { abs: e, rel: o } = i.pop(), s;
33
+ try {
34
+ s = n(e);
35
+ } catch (e) {
36
+ if (e && typeof e == "object" && "code" in e && e.code === "ENOENT") return [];
37
+ throw e;
38
+ }
39
+ for (let n of s) {
40
+ let s = a(e, n), c = o ? `${o}/${n}` : n;
41
+ r(s).isDirectory() ? i.push({
42
+ abs: s,
43
+ rel: c
44
+ }) : t.push(c);
45
+ }
46
+ }
47
+ return t;
48
+ }
49
+ //#endregion
50
+ export { o as declarionFingerprintPlugin };
51
+
52
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/vite/fingerprint-plugin.ts"],"sourcesContent":["import type { Plugin } from \"vite\";\nimport { createHash } from \"node:crypto\";\nimport {\n readdirSync,\n readFileSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport interface DeclarionFingerprintPluginOptions {\n /**\n * Subdirectory of `outDir` to walk. Defaults to \"assets\" — Vite's\n * standard hashed-output location. Override only if a consumer has\n * customized `build.assetsDir`.\n */\n assetsDir?: string;\n\n /**\n * Filename of the emitted fingerprint, written next to `index.html`.\n * Defaults to \"bundle-fingerprint.txt\". Match this on the server\n * side (`apps/server/fingerprint.go:readBundleFingerprint`) if you\n * customize.\n */\n filename?: string;\n}\n\n/**\n * Vite plugin that emits a single-line `bundle-fingerprint.txt` next\n * to `index.html` after every production build. The fingerprint is a\n * SHA-256 over every file in `assetsDir/` — sorted by name, length-\n * prefixed (`name\\x00sha256\\x00`) so concatenation is collision-safe.\n *\n * The Declarion server reads this file at boot and folds it into the\n * combined build identity exposed via `X-Declarion-Version` and\n * `/api/version`. When a consumer redeploys the UI bundle (changed\n * JS/CSS/assets) the file changes → server fingerprint changes → SDK\n * detects asset drift → user is prompted to reload to pick up the\n * new code.\n *\n * Why a separate file rather than walking `assetsDir/` from Go at\n * boot:\n * - Eliminates a per-process I/O dependency on bundle layout\n * conventions (Vite could change `assetsDir` defaults; the\n * plugin is the canonical contract).\n * - Computed once at build time, read once at boot — never on the\n * hot path.\n * - Lets the consumer image ship the fingerprint as an immutable\n * artifact rather than re-deriving it at every server start.\n *\n * Backward compatible: if a consumer hasn't adopted the plugin yet,\n * `bundle-fingerprint.txt` is absent at boot, the server logs once\n * and degrades to binary-only drift detection (still correct — the\n * binary fingerprint differs across builds anyway). No errors.\n */\nexport function declarionFingerprintPlugin(\n options: DeclarionFingerprintPluginOptions = {},\n): Plugin {\n const filename = options.filename ?? \"bundle-fingerprint.txt\";\n\n return {\n name: \"declarion-fingerprint\",\n apply: \"build\",\n closeBundle: {\n // `sequential: true` is the safe default — run after rollup has\n // finished writing the bundle, before any other closeBundle\n // hooks observe the output dir.\n sequential: true,\n handler() {\n // Read outDir + assetsDir from the resolved Vite config. We\n // don't capture them in a `configResolved` hook because\n // `closeBundle` already runs after config resolution.\n const cfg = this.environment.config;\n const outDir = cfg.build.outDir;\n const assetsDir = options.assetsDir ?? cfg.build.assetsDir ?? \"assets\";\n const assetsRoot = join(outDir, assetsDir);\n\n const files = collectFiles(assetsRoot);\n files.sort(); // deterministic order\n\n const h = createHash(\"sha256\");\n for (const relPath of files) {\n const abs = join(assetsRoot, relPath);\n const fileHash = createHash(\"sha256\")\n .update(readFileSync(abs))\n .digest(\"hex\");\n // Length-prefix discipline — same as the Go side\n // (store/migrations.go:215-282 + apps/server/fingerprint.go).\n // `a`+`bc` and `ab`+`c` must produce different hashes.\n h.update(`${relPath.length}:${relPath}\\n`);\n h.update(`${fileHash.length}:${fileHash}\\n`);\n }\n const combined = h.digest(\"hex\");\n\n writeFileSync(join(outDir, filename), combined + \"\\n\", \"utf8\");\n },\n },\n };\n}\n\n/**\n * Walks `root` recursively and returns POSIX-style relative paths of\n * every regular file. Sorted by the caller. Symlinks are followed\n * since Vite output dirs don't contain them in practice.\n */\nfunction collectFiles(root: string): string[] {\n const out: string[] = [];\n const stack: { abs: string; rel: string }[] = [{ abs: root, rel: \"\" }];\n while (stack.length > 0) {\n const { abs, rel } = stack.pop()!;\n let entries: string[];\n try {\n entries = readdirSync(abs);\n } catch (err) {\n // Missing assetsDir: nothing to fingerprint. Return empty;\n // the plugin still emits the file so the server boot path\n // doesn't have to special-case missing-yet-defined assets.\n if (\n err &&\n typeof err === \"object\" &&\n \"code\" in err &&\n (err as { code: string }).code === \"ENOENT\"\n ) {\n return [];\n }\n throw err;\n }\n for (const name of entries) {\n const childAbs = join(abs, name);\n const childRel = rel ? `${rel}/${name}` : name;\n if (statSync(childAbs).isDirectory()) {\n stack.push({ abs: childAbs, rel: childRel });\n } else {\n out.push(childRel);\n }\n }\n }\n return out;\n}\n"],"mappings":";;;;AAuDA,SAAgB,EACd,IAA6C,EAAE,EACvC;CACR,IAAM,IAAW,EAAQ,YAAY;AAErC,QAAO;EACL,MAAM;EACN,OAAO;EACP,aAAa;GAIX,YAAY;GACZ,UAAU;IAIR,IAAM,IAAM,KAAK,YAAY,QACvB,IAAS,EAAI,MAAM,QAEnB,IAAa,EAAK,GADN,EAAQ,aAAa,EAAI,MAAM,aAAa,SACpB,EAEpC,IAAQ,EAAa,EAAW;AACtC,MAAM,MAAM;IAEZ,IAAM,IAAI,EAAW,SAAS;AAC9B,SAAK,IAAM,KAAW,GAAO;KAC3B,IAAM,IAAM,EAAK,GAAY,EAAQ,EAC/B,IAAW,EAAW,SAAS,CAClC,OAAO,EAAa,EAAI,CAAC,CACzB,OAAO,MAAM;AAKhB,KADA,EAAE,OAAO,GAAG,EAAQ,OAAO,GAAG,EAAQ,IAAI,EAC1C,EAAE,OAAO,GAAG,EAAS,OAAO,GAAG,EAAS,IAAI;;IAE9C,IAAM,IAAW,EAAE,OAAO,MAAM;AAEhC,MAAc,EAAK,GAAQ,EAAS,EAAE,IAAW,MAAM,OAAO;;GAEjE;EACF;;AAQH,SAAS,EAAa,GAAwB;CAC5C,IAAM,IAAgB,EAAE,EAClB,IAAwC,CAAC;EAAE,KAAK;EAAM,KAAK;EAAI,CAAC;AACtE,QAAO,EAAM,SAAS,IAAG;EACvB,IAAM,EAAE,QAAK,WAAQ,EAAM,KAAK,EAC5B;AACJ,MAAI;AACF,OAAU,EAAY,EAAI;WACnB,GAAK;AAIZ,OACE,KACA,OAAO,KAAQ,YACf,UAAU,KACT,EAAyB,SAAS,SAEnC,QAAO,EAAE;AAEX,SAAM;;AAER,OAAK,IAAM,KAAQ,GAAS;GAC1B,IAAM,IAAW,EAAK,GAAK,EAAK,EAC1B,IAAW,IAAM,GAAG,EAAI,GAAG,MAAS;AAC1C,GAAI,EAAS,EAAS,CAAC,aAAa,GAClC,EAAM,KAAK;IAAE,KAAK;IAAU,KAAK;IAAU,CAAC,GAE5C,EAAI,KAAK,EAAS;;;AAIxB,QAAO"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@declarion/react",
3
- "version": "0.1.65",
3
+ "version": "0.1.67",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "description": "React SDK for Declarion, the schema-driven business apps platform.",
@@ -15,6 +15,11 @@
15
15
  "import": "./dist-lib/index.js",
16
16
  "default": "./dist-lib/index.js"
17
17
  },
18
+ "./vite": {
19
+ "types": "./dist-lib/vite/index.d.ts",
20
+ "import": "./dist-lib/vite/index.js",
21
+ "default": "./dist-lib/vite/index.js"
22
+ },
18
23
  "./styles.css": "./dist-lib/declarion-react.css"
19
24
  },
20
25
  "files": [
@@ -67,6 +72,8 @@
67
72
  "@types/react": "^19.0.0",
68
73
  "@types/react-dom": "^19.0.0",
69
74
  "@vitejs/plugin-react": "^6.0.1",
75
+ "eslint": "^10.2.1",
76
+ "eslint-plugin-react-hooks": "^7.1.1",
70
77
  "jsdom": "^29.0.1",
71
78
  "msw": "^2.13.4",
72
79
  "react": "^19.0.0",
@@ -74,14 +81,15 @@
74
81
  "tailwindcss": "^4.2.4",
75
82
  "tsc-alias": "^1.8.16",
76
83
  "typescript": "^6.0.3",
84
+ "typescript-eslint": "^8.59.0",
77
85
  "vite": "^8.0.9",
78
86
  "vitest": "^4.1.5"
79
87
  },
80
88
  "scripts": {
81
89
  "dev": "vite",
82
90
  "build": "tsc --noEmit && vite build",
83
- "build:lib": "vite build --config vite.lib.config.ts && tsc -p tsconfig.lib.json && tsc-alias -p tsconfig.lib.json",
84
- "lint": "tsc --noEmit",
91
+ "build:lib": "vite build --config vite.lib.config.ts && vite build --config vite.plugin.config.ts && tsc -p tsconfig.lib.json && tsc-alias -p tsconfig.lib.json",
92
+ "lint": "tsc --noEmit && eslint src",
85
93
  "test": "vitest run",
86
94
  "preview": "vite preview"
87
95
  }