covara 0.7.1 → 0.8.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 (204) hide show
  1. package/README.md +64 -16
  2. package/dist/cli/args.d.ts +14 -0
  3. package/dist/cli/args.d.ts.map +1 -0
  4. package/dist/cli/args.js +78 -0
  5. package/dist/cli/args.js.map +1 -0
  6. package/dist/cli/commands/data.d.ts +2 -0
  7. package/dist/cli/commands/data.d.ts.map +1 -0
  8. package/dist/cli/commands/data.js +31 -0
  9. package/dist/cli/commands/data.js.map +1 -0
  10. package/dist/cli/commands/db.d.ts +2 -0
  11. package/dist/cli/commands/db.d.ts.map +1 -0
  12. package/dist/cli/commands/db.js +100 -0
  13. package/dist/cli/commands/db.js.map +1 -0
  14. package/dist/cli/commands/dev.d.ts +2 -0
  15. package/dist/cli/commands/dev.d.ts.map +1 -0
  16. package/dist/cli/commands/dev.js +125 -0
  17. package/dist/cli/commands/dev.js.map +1 -0
  18. package/dist/cli/commands/env.d.ts +2 -0
  19. package/dist/cli/commands/env.d.ts.map +1 -0
  20. package/dist/cli/commands/env.js +94 -0
  21. package/dist/cli/commands/env.js.map +1 -0
  22. package/dist/cli/commands/import-export.d.ts +3 -0
  23. package/dist/cli/commands/import-export.d.ts.map +1 -0
  24. package/dist/cli/commands/import-export.js +156 -0
  25. package/dist/cli/commands/import-export.js.map +1 -0
  26. package/dist/cli/commands/migrate.d.ts +2 -0
  27. package/dist/cli/commands/migrate.d.ts.map +1 -0
  28. package/dist/cli/commands/migrate.js +12 -0
  29. package/dist/cli/commands/migrate.js.map +1 -0
  30. package/dist/cli/commands/push.d.ts +2 -0
  31. package/dist/cli/commands/push.d.ts.map +1 -0
  32. package/dist/cli/commands/push.js +45 -0
  33. package/dist/cli/commands/push.js.map +1 -0
  34. package/dist/cli/commands/run.d.ts +2 -0
  35. package/dist/cli/commands/run.d.ts.map +1 -0
  36. package/dist/cli/commands/run.js +54 -0
  37. package/dist/cli/commands/run.js.map +1 -0
  38. package/dist/cli/commands/seed.d.ts +2 -0
  39. package/dist/cli/commands/seed.d.ts.map +1 -0
  40. package/dist/cli/commands/seed.js +32 -0
  41. package/dist/cli/commands/seed.js.map +1 -0
  42. package/dist/cli/commands/studio.d.ts +2 -0
  43. package/dist/cli/commands/studio.d.ts.map +1 -0
  44. package/dist/cli/commands/studio.js +22 -0
  45. package/dist/cli/commands/studio.js.map +1 -0
  46. package/dist/cli/commands/types.d.ts +2 -0
  47. package/dist/cli/commands/types.d.ts.map +1 -0
  48. package/dist/cli/commands/types.js +28 -0
  49. package/dist/cli/commands/types.js.map +1 -0
  50. package/dist/cli/config.d.ts +28 -0
  51. package/dist/cli/config.d.ts.map +1 -0
  52. package/dist/cli/config.js +81 -0
  53. package/dist/cli/config.js.map +1 -0
  54. package/dist/cli/drizzle-bridge.d.ts +29 -0
  55. package/dist/cli/drizzle-bridge.d.ts.map +1 -0
  56. package/dist/cli/drizzle-bridge.js +85 -0
  57. package/dist/cli/drizzle-bridge.js.map +1 -0
  58. package/dist/cli/index.d.ts +2 -1
  59. package/dist/cli/index.d.ts.map +1 -1
  60. package/dist/cli/index.js +74 -20
  61. package/dist/cli/index.js.map +1 -1
  62. package/dist/cli/prompt.d.ts +2 -0
  63. package/dist/cli/prompt.d.ts.map +1 -0
  64. package/dist/cli/prompt.js +16 -0
  65. package/dist/cli/prompt.js.map +1 -0
  66. package/dist/cli/templates/package-json.js +1 -1
  67. package/dist/cli/worker.d.ts +2 -0
  68. package/dist/cli/worker.d.ts.map +1 -0
  69. package/dist/cli/worker.js +120 -0
  70. package/dist/cli/worker.js.map +1 -0
  71. package/dist/client/file-upload.d.ts +2 -1
  72. package/dist/client/file-upload.d.ts.map +1 -1
  73. package/dist/client/file-upload.js +5 -5
  74. package/dist/client/file-upload.js.map +1 -1
  75. package/dist/client/live-store.d.ts.map +1 -1
  76. package/dist/client/live-store.js +12 -6
  77. package/dist/client/live-store.js.map +1 -1
  78. package/dist/client/react-files.js +1 -1
  79. package/dist/client/react-files.js.map +1 -1
  80. package/dist/client/subscription-manager.d.ts.map +1 -1
  81. package/dist/client/subscription-manager.js +7 -0
  82. package/dist/client/subscription-manager.js.map +1 -1
  83. package/dist/htmx/client/runtime.d.ts +2 -0
  84. package/dist/htmx/client/runtime.d.ts.map +1 -0
  85. package/dist/htmx/client/runtime.js +195 -0
  86. package/dist/htmx/client/runtime.js.map +1 -0
  87. package/dist/htmx/context.d.ts +16 -0
  88. package/dist/htmx/context.d.ts.map +1 -0
  89. package/dist/htmx/context.js +52 -0
  90. package/dist/htmx/context.js.map +1 -0
  91. package/dist/htmx/forms.d.ts +3 -0
  92. package/dist/htmx/forms.d.ts.map +1 -0
  93. package/dist/htmx/forms.js +32 -0
  94. package/dist/htmx/forms.js.map +1 -0
  95. package/dist/htmx/ids.d.ts +11 -0
  96. package/dist/htmx/ids.d.ts.map +1 -0
  97. package/dist/htmx/ids.js +27 -0
  98. package/dist/htmx/ids.js.map +1 -0
  99. package/dist/htmx/index.d.ts +11 -0
  100. package/dist/htmx/index.d.ts.map +1 -0
  101. package/dist/htmx/index.js +15 -0
  102. package/dist/htmx/index.js.map +1 -0
  103. package/dist/htmx/live.d.ts +39 -0
  104. package/dist/htmx/live.d.ts.map +1 -0
  105. package/dist/htmx/live.js +37 -0
  106. package/dist/htmx/live.js.map +1 -0
  107. package/dist/htmx/page.d.ts +14 -0
  108. package/dist/htmx/page.d.ts.map +1 -0
  109. package/dist/htmx/page.js +59 -0
  110. package/dist/htmx/page.js.map +1 -0
  111. package/dist/htmx/render-util.d.ts +2 -0
  112. package/dist/htmx/render-util.d.ts.map +1 -0
  113. package/dist/htmx/render-util.js +15 -0
  114. package/dist/htmx/render-util.js.map +1 -0
  115. package/dist/htmx/server.d.ts +21 -0
  116. package/dist/htmx/server.d.ts.map +1 -0
  117. package/dist/htmx/server.js +286 -0
  118. package/dist/htmx/server.js.map +1 -0
  119. package/dist/htmx/sse-render.d.ts +10 -0
  120. package/dist/htmx/sse-render.d.ts.map +1 -0
  121. package/dist/htmx/sse-render.js +40 -0
  122. package/dist/htmx/sse-render.js.map +1 -0
  123. package/dist/htmx/template-gen.d.ts +7 -0
  124. package/dist/htmx/template-gen.d.ts.map +1 -0
  125. package/dist/htmx/template-gen.js +38 -0
  126. package/dist/htmx/template-gen.js.map +1 -0
  127. package/dist/resource/hook.d.ts.map +1 -1
  128. package/dist/resource/hook.js +101 -24
  129. package/dist/resource/hook.js.map +1 -1
  130. package/dist/resource/relations.d.ts +15 -4
  131. package/dist/resource/relations.d.ts.map +1 -1
  132. package/dist/resource/relations.js +146 -26
  133. package/dist/resource/relations.js.map +1 -1
  134. package/dist/resource/subscription.d.ts +15 -2
  135. package/dist/resource/subscription.d.ts.map +1 -1
  136. package/dist/resource/subscription.js +184 -3
  137. package/dist/resource/subscription.js.map +1 -1
  138. package/dist/resource/track-mutations.d.ts.map +1 -1
  139. package/dist/resource/track-mutations.js +11 -1
  140. package/dist/resource/track-mutations.js.map +1 -1
  141. package/dist/resource/types.d.ts +8 -0
  142. package/dist/resource/types.d.ts.map +1 -1
  143. package/dist/server/admin-bypass.d.ts +7 -0
  144. package/dist/server/admin-bypass.d.ts.map +1 -0
  145. package/dist/server/admin-bypass.js +22 -0
  146. package/dist/server/admin-bypass.js.map +1 -0
  147. package/dist/server/app.d.ts +9 -0
  148. package/dist/server/app.d.ts.map +1 -1
  149. package/dist/server/app.js +101 -1
  150. package/dist/server/app.js.map +1 -1
  151. package/dist/server/impersonation.d.ts +18 -0
  152. package/dist/server/impersonation.d.ts.map +1 -0
  153. package/dist/server/impersonation.js +53 -0
  154. package/dist/server/impersonation.js.map +1 -0
  155. package/dist/shared/escape.d.ts +3 -0
  156. package/dist/shared/escape.d.ts.map +1 -0
  157. package/dist/shared/escape.js +12 -0
  158. package/dist/shared/escape.js.map +1 -0
  159. package/dist/storage/local.d.ts +4 -0
  160. package/dist/storage/local.d.ts.map +1 -1
  161. package/dist/storage/local.js +5 -0
  162. package/dist/storage/local.js.map +1 -1
  163. package/dist/storage/resource.d.ts +5 -11
  164. package/dist/storage/resource.d.ts.map +1 -1
  165. package/dist/storage/resource.js +156 -194
  166. package/dist/storage/resource.js.map +1 -1
  167. package/dist/ui/admin-auth.d.ts +6 -0
  168. package/dist/ui/admin-auth.d.ts.map +1 -1
  169. package/dist/ui/admin-auth.js +59 -1
  170. package/dist/ui/admin-auth.js.map +1 -1
  171. package/dist/ui/data-explorer.d.ts.map +1 -1
  172. package/dist/ui/data-explorer.js +91 -4
  173. package/dist/ui/data-explorer.js.map +1 -1
  174. package/dist/ui/html/client/data-explorer-app.d.ts.map +1 -1
  175. package/dist/ui/html/client/data-explorer-app.js +20 -7
  176. package/dist/ui/html/client/data-explorer-app.js.map +1 -1
  177. package/dist/ui/html/client/runtime.d.ts.map +1 -1
  178. package/dist/ui/html/client/runtime.js +70 -2
  179. package/dist/ui/html/client/runtime.js.map +1 -1
  180. package/dist/ui/html/icons.d.ts.map +1 -1
  181. package/dist/ui/html/icons.js +2 -0
  182. package/dist/ui/html/icons.js.map +1 -1
  183. package/dist/ui/html/layout.d.ts +1 -0
  184. package/dist/ui/html/layout.d.ts.map +1 -1
  185. package/dist/ui/html/layout.js +274 -146
  186. package/dist/ui/html/layout.js.map +1 -1
  187. package/dist/ui/html/pages/filter-tester.d.ts.map +1 -1
  188. package/dist/ui/html/pages/filter-tester.js +15 -0
  189. package/dist/ui/html/pages/filter-tester.js.map +1 -1
  190. package/dist/ui/html/pages/users.d.ts.map +1 -1
  191. package/dist/ui/html/pages/users.js +8 -1
  192. package/dist/ui/html/pages/users.js.map +1 -1
  193. package/dist/ui/index.d.ts +1 -1
  194. package/dist/ui/index.d.ts.map +1 -1
  195. package/dist/ui/index.js +1 -1
  196. package/dist/ui/index.js.map +1 -1
  197. package/dist/ui/middleware.d.ts.map +1 -1
  198. package/dist/ui/middleware.js +121 -5
  199. package/dist/ui/middleware.js.map +1 -1
  200. package/dist/ui/schema-registry.d.ts +5 -0
  201. package/dist/ui/schema-registry.d.ts.map +1 -1
  202. package/dist/ui/schema-registry.js +14 -0
  203. package/dist/ui/schema-registry.js.map +1 -1
  204. package/package.json +5 -1
@@ -0,0 +1,39 @@
1
+ import type { HtmlEscapedString } from "hono/utils/html";
2
+ import type { RegionContext } from "./context.js";
3
+ export type Renderable = unknown;
4
+ export interface LiveQuery {
5
+ filter?: string;
6
+ orderBy?: string;
7
+ limit?: number;
8
+ }
9
+ export interface LiveProps<Row extends Record<string, unknown> = Record<string, unknown>> {
10
+ resource: unknown;
11
+ query?: LiveQuery;
12
+ mode?: "live" | "page";
13
+ moreLabel?: string;
14
+ idField?: string;
15
+ create?: (c: RegionContext) => Renderable;
16
+ container?: (rows: Renderable, c: RegionContext) => Renderable;
17
+ render: (row: Row, c: RegionContext) => Renderable;
18
+ empty?: (c: RegionContext) => Renderable;
19
+ }
20
+ export interface LiveAggregateProps {
21
+ resource: unknown;
22
+ query?: LiveQuery;
23
+ groupBy?: string[];
24
+ render: (data: unknown, c: RegionContext) => Renderable;
25
+ }
26
+ export interface CollectedRegion {
27
+ index: number;
28
+ regionId: string;
29
+ kind: "live" | "aggregate";
30
+ token: string;
31
+ props: LiveProps | LiveAggregateProps;
32
+ }
33
+ export declare const collectRegions: (pagePath: string, renderSync: () => string) => {
34
+ html: string;
35
+ regions: CollectedRegion[];
36
+ };
37
+ export declare const Live: <Row extends Record<string, unknown> = Record<string, unknown>>(props: LiveProps<Row>) => HtmlEscapedString;
38
+ export declare const LiveAggregate: (props: LiveAggregateProps) => HtmlEscapedString;
39
+ //# sourceMappingURL=live.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/htmx/live.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAI/C,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC;AAEjC,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS,CAAC,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAGtF,QAAQ,EAAE,OAAO,CAAC;IAIlB,KAAK,CAAC,EAAE,SAAS,CAAC;IAMlB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAEvB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,UAAU,CAAC;IAG1C,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,aAAa,KAAK,UAAU,CAAC;IAE/D,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,aAAa,KAAK,UAAU,CAAC;IAEnD,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,UAAU,CAAC;CAC1C;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,aAAa,KAAK,UAAU,CAAC;CACzD;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,GAAG,kBAAkB,CAAC;CACvC;AAaD,eAAO,MAAM,cAAc,GACzB,UAAU,MAAM,EAChB,YAAY,MAAM,MAAM,KACvB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAU5C,CAAC;AAqBF,eAAO,MAAM,IAAI,GAAI,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChF,OAAO,SAAS,CAAC,GAAG,CAAC,KACpB,iBAA+D,CAAC;AAEnE,eAAO,MAAM,aAAa,GAAI,OAAO,kBAAkB,KAAG,iBACtB,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { raw } from "hono/html";
2
+ import { regionId } from "./ids.js";
3
+ // Render-scoped collector. Safe as a module global because a page render is
4
+ // SYNCHRONOUS: <Live> returns a token string immediately (data fetching happens
5
+ // later, outside JSX), so toString() never yields and no two renders interleave
6
+ // while the collector is set.
7
+ let activeCollector = null;
8
+ export const collectRegions = (pagePath, renderSync) => {
9
+ const collector = { pagePath, regions: [] };
10
+ const previous = activeCollector;
11
+ activeCollector = collector;
12
+ try {
13
+ const html = renderSync();
14
+ return { html, regions: collector.regions };
15
+ }
16
+ finally {
17
+ activeCollector = previous;
18
+ }
19
+ };
20
+ const registerRegion = (kind, props) => {
21
+ const collector = activeCollector;
22
+ if (!collector) {
23
+ // Rendered outside a page render (e.g. a stray <Live> in a fragment); emit
24
+ // nothing rather than throwing.
25
+ return raw("");
26
+ }
27
+ const index = collector.regions.length;
28
+ const rid = regionId(collector.pagePath, index);
29
+ const token = `<!--cv-region:${rid}-->`;
30
+ collector.regions.push({ index, regionId: rid, kind, token, props });
31
+ return raw(token);
32
+ };
33
+ // hono/jsx function components. Returned token is replaced with the region's
34
+ // rendered HTML in the assemble phase (see renderPage).
35
+ export const Live = (props) => registerRegion("live", props);
36
+ export const LiveAggregate = (props) => registerRegion("aggregate", props);
37
+ //# sourceMappingURL=live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/htmx/live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEhC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AA8DjC,4EAA4E;AAC5E,gFAAgF;AAChF,gFAAgF;AAChF,8BAA8B;AAC9B,IAAI,eAAe,GAAqB,IAAI,CAAC;AAE7C,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,QAAgB,EAChB,UAAwB,EACsB,EAAE;IAChD,MAAM,SAAS,GAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACvD,MAAM,QAAQ,GAAG,eAAe,CAAC;IACjC,eAAe,GAAG,SAAS,CAAC;IAC5B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;QAC1B,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC;IAC9C,CAAC;YAAS,CAAC;QACT,eAAe,GAAG,QAAQ,CAAC;IAC7B,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CACrB,IAA6B,EAC7B,KAAqC,EAClB,EAAE;IACrB,MAAM,SAAS,GAAG,eAAe,CAAC;IAClC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,2EAA2E;QAC3E,gCAAgC;QAChC,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IACD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC;IACvC,MAAM,GAAG,GAAG,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,iBAAiB,GAAG,KAAK,CAAC;IACxC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;AACpB,CAAC,CAAC;AAEF,6EAA6E;AAC7E,wDAAwD;AACxD,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,KAAqB,EACF,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,KAAkB,CAAC,CAAC;AAEnE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAyB,EAAqB,EAAE,CAC5E,cAAc,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { type CollectedRegion, type Renderable } from "./live.js";
2
+ export interface PageResult {
3
+ items: Record<string, unknown>[];
4
+ nextCursor?: string | null;
5
+ hasMore?: boolean;
6
+ }
7
+ export interface RenderPageOptions {
8
+ pagePath: string;
9
+ ctx: unknown;
10
+ fetchRows: (region: CollectedRegion) => Promise<PageResult>;
11
+ fetchAggregate?: (region: CollectedRegion) => Promise<unknown>;
12
+ }
13
+ export declare const renderPage: (component: (ctx: any) => Renderable, options: RenderPageOptions) => Promise<string>;
14
+ //# sourceMappingURL=page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../src/htmx/page.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,eAAe,EAGpB,KAAK,UAAU,EAChB,MAAM,QAAQ,CAAC;AAEhB,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,OAAO,CAAC;IAGb,SAAS,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAE5D,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAChE;AAwDD,eAAO,MAAM,UAAU,GACrB,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,UAAU,EACnC,SAAS,iBAAiB,KACzB,OAAO,CAAC,MAAM,CAchB,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { raw } from "hono/html";
2
+ import { attrsToHtml, createRegionContext, loadMoreButtonHtml } from "./context.js";
3
+ import { templateDomId } from "./ids.js";
4
+ import { toHtmlString } from "./render-util.js";
5
+ import { buildRowTemplate } from "./template-gen.js";
6
+ import { collectRegions, } from "./live.js";
7
+ const renderLiveRegion = async (region, options) => {
8
+ const props = region.props;
9
+ const mode = props.mode ?? "live";
10
+ const c = createRegionContext(region.regionId, { mode });
11
+ const { items, nextCursor, hasMore } = await options.fetchRows(region);
12
+ let body = items.length > 0
13
+ ? items.map((row) => toHtmlString(props.render(row, c))).join("")
14
+ : props.empty
15
+ ? toHtmlString(props.empty(c))
16
+ : "";
17
+ // In "page" mode, append the cursor-driven load-more control inside the
18
+ // container so it grows in order and the control advances itself.
19
+ if (mode === "page" && hasMore && nextCursor) {
20
+ body += loadMoreButtonHtml(region.regionId, nextCursor, props.moreLabel);
21
+ }
22
+ const container = props.container
23
+ ? toHtmlString(props.container(raw(body), c))
24
+ : `<div${attrsToHtml(c.container())}>${body}</div>`;
25
+ const create = props.create ? toHtmlString(props.create(c)) : "";
26
+ // Ship the server-derived row template so the client can render optimistic
27
+ // rows that match the server's markup (no ghost). Inert until the runtime
28
+ // uses it; <template> content is not executed by htmx.
29
+ const template = `<template id="${templateDomId(region.regionId)}">${buildRowTemplate({
30
+ regionId: region.regionId,
31
+ props,
32
+ })}</template>`;
33
+ return create + container + template;
34
+ };
35
+ const renderAggregateRegion = async (region, options) => {
36
+ const props = region.props;
37
+ const c = createRegionContext(region.regionId);
38
+ const data = options.fetchAggregate ? await options.fetchAggregate(region) : null;
39
+ // Wrap in a live container: the client connects its SSE and replaces the
40
+ // inner aggregate fragment whenever the resource changes.
41
+ return `<div${attrsToHtml(c.container())}>${toHtmlString(props.render(data, c))}</div>`;
42
+ };
43
+ // Render a registered page: a synchronous collect pass gathers the <Live>
44
+ // regions (each leaves a placeholder token), then an async assemble pass fetches
45
+ // each region's data, renders it via the page's own closures, and substitutes
46
+ // the token. Live updates/optimism use the same closures via the generated
47
+ // endpoints, so the markup has a single source of truth.
48
+ export const renderPage = async (component, options) => {
49
+ const { html, regions } = collectRegions(options.pagePath, () => toHtmlString(component(options.ctx)));
50
+ let output = html;
51
+ for (const region of regions) {
52
+ const replacement = region.kind === "aggregate"
53
+ ? await renderAggregateRegion(region, options)
54
+ : await renderLiveRegion(region, options);
55
+ output = output.replace(region.token, () => replacement);
56
+ }
57
+ return output;
58
+ };
59
+ //# sourceMappingURL=page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.js","sourceRoot":"","sources":["../../src/htmx/page.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const toHtmlString: (value: unknown) => string;
2
+ //# sourceMappingURL=render-util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-util.d.ts","sourceRoot":"","sources":["../../src/htmx/render-util.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,GAAI,OAAO,OAAO,KAAG,MAU7C,CAAC"}
@@ -0,0 +1,15 @@
1
+ // Coerce a closure return value (string / hono-jsx node / anything with a sync
2
+ // toString) into an HTML string. Throws on async shells — page shells must be
3
+ // synchronous; async data fetching is handled per <Live> region.
4
+ export const toHtmlString = (value) => {
5
+ if (value === null || value === undefined || value === false)
6
+ return "";
7
+ if (typeof value === "string")
8
+ return value;
9
+ const out = value.toString();
10
+ if (out instanceof Promise) {
11
+ throw new Error("covara/htmx: page components must render synchronously (no async components in the page shell); data fetching is handled per <Live> region");
12
+ }
13
+ return String(out);
14
+ };
15
+ //# sourceMappingURL=render-util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-util.js","sourceRoot":"","sources":["../../src/htmx/render-util.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,iEAAiE;AACjE,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAc,EAAU,EAAE;IACrD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK;QAAE,OAAO,EAAE,CAAC;IACxE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,GAAG,GAAI,KAAiC,CAAC,QAAQ,EAAE,CAAC;IAC1D,IAAI,GAAG,YAAY,OAAO,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CACb,4IAA4I,CAC7I,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { Hono, type Context } from "hono";
2
+ export interface PageContext {
3
+ user: unknown;
4
+ req: Context["req"];
5
+ c: Context;
6
+ }
7
+ export type PageComponent = (ctx: PageContext) => unknown;
8
+ export interface ResourceInfo {
9
+ mountPath: string;
10
+ idField: string;
11
+ }
12
+ export interface LiveSupport {
13
+ registerResource(tableName: string, info: ResourceInfo): void;
14
+ registerPage(path: string, component: PageComponent): void;
15
+ }
16
+ type AppLike = Hono & {
17
+ request: Hono["request"];
18
+ };
19
+ export declare const installLiveSupport: (app: AppLike) => LiveSupport;
20
+ export {};
21
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/htmx/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AAkB1C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC,EAAE,OAAO,CAAC;CACZ;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC;AAE1D,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9D,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,GAAG,IAAI,CAAC;CAC5D;AAED,KAAK,OAAO,GAAG,IAAI,GAAG;IAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;CAAE,CAAC;AAanD,eAAO,MAAM,kBAAkB,GAAI,KAAK,OAAO,KAAG,WAmQjD,CAAC"}
@@ -0,0 +1,286 @@
1
+ import { Hono } from "hono";
2
+ import { getTableName } from "drizzle-orm";
3
+ import { getUser } from "../server/context.js";
4
+ import { stashRenderer } from "../resource/subscription.js";
5
+ import { createResourceFilter } from "../resource/filter.js";
6
+ import { renderPage } from "./page.js";
7
+ import { collectRegions, } from "./live.js";
8
+ import { createRegionContext, loadMoreButtonHtml } from "./context.js";
9
+ import { toHtmlString } from "./render-util.js";
10
+ import { coerceFormBody } from "./forms.js";
11
+ import { makeInvalidateRenderer, makeRegionEventRenderer } from "./sse-render.js";
12
+ import { LIVE_PREFIX, slugifyPath } from "./ids.js";
13
+ const escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
14
+ export const installLiveSupport = (app) => {
15
+ const resources = new Map();
16
+ const pages = new Map();
17
+ let routesMounted = false;
18
+ const buildCtx = (c) => ({
19
+ user: getUser(c) ?? null,
20
+ req: c.req,
21
+ c,
22
+ });
23
+ const forwardHeaders = (c) => {
24
+ const headers = {};
25
+ const cookie = c.req.header("cookie");
26
+ if (cookie)
27
+ headers.cookie = cookie;
28
+ const auth = c.req.header("authorization");
29
+ if (auth)
30
+ headers.authorization = auth;
31
+ return headers;
32
+ };
33
+ const resolveResourceInfo = (resource) => {
34
+ if (typeof resource === "string") {
35
+ return (resources.get(resource) ?? {
36
+ mountPath: resource.startsWith("/") ? resource : `/${resource}`,
37
+ idField: "id",
38
+ });
39
+ }
40
+ try {
41
+ return resources.get(getTableName(resource));
42
+ }
43
+ catch {
44
+ return undefined;
45
+ }
46
+ };
47
+ const resolveRegion = (regionParam, ctx) => {
48
+ for (const [path, component] of pages) {
49
+ const match = new RegExp(`^${escapeRe(slugifyPath(path))}-(\\d+)$`).exec(regionParam);
50
+ if (!match)
51
+ continue;
52
+ const index = Number(match[1]);
53
+ const { regions } = collectRegions(path, () => toHtmlString(component(ctx)));
54
+ const region = regions[index];
55
+ if (!region || region.regionId !== regionParam)
56
+ continue;
57
+ const props = region.props;
58
+ const info = resolveResourceInfo(props.resource);
59
+ if (!info)
60
+ return undefined;
61
+ return {
62
+ region,
63
+ props,
64
+ info,
65
+ idField: props.idField ?? info.idField ?? "id",
66
+ table: typeof props.resource === "object" ? props.resource : null,
67
+ isAggregate: region.kind === "aggregate",
68
+ };
69
+ }
70
+ return undefined;
71
+ };
72
+ const listQuery = (props, cursor) => {
73
+ const params = new URLSearchParams();
74
+ const q = props.query ?? {};
75
+ if (q.filter)
76
+ params.set("filter", q.filter);
77
+ if (q.orderBy)
78
+ params.set("orderBy", q.orderBy);
79
+ if (q.limit != null)
80
+ params.set("limit", String(q.limit));
81
+ if (cursor)
82
+ params.set("cursor", cursor);
83
+ const s = params.toString();
84
+ return s ? `?${s}` : "";
85
+ };
86
+ const fetchRows = async (c, props, cursor) => {
87
+ const info = resolveResourceInfo(props.resource);
88
+ if (!info)
89
+ return { items: [] };
90
+ const res = await app.request(`${info.mountPath}${listQuery(props, cursor)}`, {
91
+ headers: forwardHeaders(c),
92
+ });
93
+ if (!res.ok)
94
+ return { items: [] };
95
+ const data = (await res.json());
96
+ if (Array.isArray(data))
97
+ return { items: data };
98
+ return { items: data.items ?? [], nextCursor: data.nextCursor, hasMore: data.hasMore };
99
+ };
100
+ const aggregateQuery = (props) => {
101
+ const params = new URLSearchParams();
102
+ if (props.query?.filter)
103
+ params.set("filter", props.query.filter);
104
+ if (props.groupBy?.length)
105
+ params.set("groupBy", props.groupBy.join(","));
106
+ params.set("count", "true");
107
+ return `?${params.toString()}`;
108
+ };
109
+ const fetchAggregate = async (c, props) => {
110
+ const info = resolveResourceInfo(props.resource);
111
+ if (!info)
112
+ return null;
113
+ const res = await app.request(`${info.mountPath}/aggregate${aggregateQuery(props)}`, {
114
+ headers: forwardHeaders(c),
115
+ });
116
+ if (!res.ok)
117
+ return null;
118
+ return res.json();
119
+ };
120
+ const renderRows = (props, regionId, rows) => {
121
+ const rc = createRegionContext(regionId);
122
+ if (rows.length === 0)
123
+ return props.empty ? toHtmlString(props.empty(rc)) : "";
124
+ return rows.map((row) => toHtmlString(props.render(row, rc))).join("");
125
+ };
126
+ const ssrHandler = (path) => async (c) => {
127
+ const component = pages.get(path);
128
+ if (!component)
129
+ return c.notFound();
130
+ const ctx = buildCtx(c);
131
+ const html = await renderPage(component, {
132
+ pagePath: path,
133
+ ctx,
134
+ fetchRows: (region) => fetchRows(c, region.props),
135
+ fetchAggregate: (region) => fetchAggregate(c, region.props),
136
+ });
137
+ return c.html(`${html}\n<script src="${LIVE_PREFIX}/_runtime.js"></script>`);
138
+ };
139
+ const mountRoutes = () => {
140
+ if (routesMounted)
141
+ return;
142
+ routesMounted = true;
143
+ const live = new Hono();
144
+ live.get("/_runtime.js", async (c) => {
145
+ // Loaded on demand so apps that don't serve htmx pages never pull the
146
+ // vendored htmx core string into memory.
147
+ const [{ htmxScript }, { covaraRuntimeScript }] = await Promise.all([
148
+ import("../ui/html/client/htmx-vendor.js"),
149
+ import("./client/runtime.js"),
150
+ ]);
151
+ c.header("Content-Type", "application/javascript; charset=utf-8");
152
+ return c.body(`${htmxScript}\n${covaraRuntimeScript}`);
153
+ });
154
+ // Live SSE: inject an HTML renderer into the resource's own /subscribe via a
155
+ // one-shot token, forward auth, and stream the result straight back.
156
+ live.get("/:region/subscribe", async (c) => {
157
+ const resolved = resolveRegion(c.req.param("region"), buildCtx(c));
158
+ if (!resolved)
159
+ return c.notFound();
160
+ const renderer = resolved.isAggregate
161
+ ? makeInvalidateRenderer()
162
+ : makeRegionEventRenderer({
163
+ regionId: resolved.region.regionId,
164
+ idField: resolved.idField,
165
+ props: resolved.props,
166
+ });
167
+ const token = stashRenderer(renderer);
168
+ const params = new URLSearchParams();
169
+ const filter = resolved.props.query?.filter;
170
+ if (filter)
171
+ params.set("filter", filter);
172
+ params.set("__cvRenderer", token);
173
+ params.set("skipExisting", "true");
174
+ return app.request(`${resolved.info.mountPath}/subscribe?${params.toString()}`, {
175
+ headers: { ...forwardHeaders(c), accept: "text/event-stream" },
176
+ signal: c.req.raw.signal,
177
+ });
178
+ });
179
+ // List / pagination fragment.
180
+ live.get("/:region", async (c) => {
181
+ const resolved = resolveRegion(c.req.param("region"), buildCtx(c));
182
+ if (!resolved)
183
+ return c.notFound();
184
+ const rc = createRegionContext(resolved.region.regionId);
185
+ if (resolved.isAggregate) {
186
+ const props = resolved.props;
187
+ const data = await fetchAggregate(c, props);
188
+ return c.html(toHtmlString(props.render(data, rc)));
189
+ }
190
+ const props = resolved.props;
191
+ const { items, nextCursor, hasMore } = await fetchRows(c, props, c.req.query("cursor"));
192
+ let html = renderRows(props, resolved.region.regionId, items);
193
+ // In "page" mode, append the next load-more control so the button (which
194
+ // swapped itself out) is replaced by the next page + the following button.
195
+ if ((props.mode ?? "live") === "page" && hasMore && nextCursor) {
196
+ html += loadMoreButtonHtml(resolved.region.regionId, nextCursor, props.moreLabel);
197
+ }
198
+ return c.html(html);
199
+ });
200
+ // Create -> render the new row via the region's row closure.
201
+ live.post("/:region", async (c) => {
202
+ const resolved = resolveRegion(c.req.param("region"), buildCtx(c));
203
+ if (!resolved || resolved.isAggregate)
204
+ return c.notFound();
205
+ const props = resolved.props;
206
+ const body = (await c.req.parseBody());
207
+ const payload = resolved.table ? coerceFormBody(body, resolved.table) : body;
208
+ const res = await app.request(resolved.info.mountPath, {
209
+ method: "POST",
210
+ headers: { ...forwardHeaders(c), "content-type": "application/json" },
211
+ body: JSON.stringify(payload),
212
+ });
213
+ if (!res.ok)
214
+ return c.html(await errorFragment(res), res.status);
215
+ const row = (await res.json());
216
+ const rc = createRegionContext(resolved.region.regionId);
217
+ return c.html(toHtmlString(props.render(row, rc)), 201);
218
+ });
219
+ // Update -> render the row, or an empty body (which removes it) when the
220
+ // updated row no longer matches the region's display filter.
221
+ live.patch("/:region/:id", async (c) => {
222
+ const resolved = resolveRegion(c.req.param("region"), buildCtx(c));
223
+ if (!resolved || resolved.isAggregate)
224
+ return c.notFound();
225
+ const props = resolved.props;
226
+ const id = c.req.param("id");
227
+ const body = (await c.req.parseBody());
228
+ const payload = resolved.table ? coerceFormBody(body, resolved.table) : body;
229
+ const res = await app.request(`${resolved.info.mountPath}/${encodeURIComponent(id)}`, {
230
+ method: "PATCH",
231
+ headers: { ...forwardHeaders(c), "content-type": "application/json" },
232
+ body: JSON.stringify(payload),
233
+ });
234
+ if (!res.ok)
235
+ return c.html(await errorFragment(res), res.status);
236
+ const row = (await res.json());
237
+ const filter = props.query?.filter;
238
+ if (filter && resolved.table && !matchesFilter(resolved.table, filter, row)) {
239
+ return c.html("");
240
+ }
241
+ const rc = createRegionContext(resolved.region.regionId);
242
+ return c.html(toHtmlString(props.render(row, rc)));
243
+ });
244
+ // Delete -> empty body (outerHTML swap removes the targeted row).
245
+ live.delete("/:region/:id", async (c) => {
246
+ const resolved = resolveRegion(c.req.param("region"), buildCtx(c));
247
+ if (!resolved)
248
+ return c.notFound();
249
+ const id = c.req.param("id");
250
+ const res = await app.request(`${resolved.info.mountPath}/${encodeURIComponent(id)}`, { method: "DELETE", headers: forwardHeaders(c) });
251
+ return c.html("", (res.ok ? 200 : res.status));
252
+ });
253
+ app.route(LIVE_PREFIX, live);
254
+ };
255
+ return {
256
+ registerResource: (tableName, info) => resources.set(tableName, info),
257
+ registerPage: (path, component) => {
258
+ pages.set(path, component);
259
+ mountRoutes();
260
+ app.get(path, ssrHandler(path));
261
+ },
262
+ };
263
+ };
264
+ const matchesFilter = (table, filter, row) => {
265
+ try {
266
+ return createResourceFilter(table).compile(filter).execute(row);
267
+ }
268
+ catch {
269
+ return true;
270
+ }
271
+ };
272
+ const errorFragment = async (res) => {
273
+ let detail = `Request failed (${res.status})`;
274
+ try {
275
+ const body = (await res.json());
276
+ detail = body.detail ?? body.title ?? detail;
277
+ }
278
+ catch {
279
+ // non-JSON error
280
+ }
281
+ return `<div class="cv-error" role="alert">${detail
282
+ .replace(/&/g, "&amp;")
283
+ .replace(/</g, "&lt;")
284
+ .replace(/>/g, "&gt;")}</div>`;
285
+ };
286
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/htmx/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { EventRenderer } from "../resource/subscription.js";
2
+ import type { LiveProps } from "./live.js";
3
+ export interface RegionRenderTarget {
4
+ regionId: string;
5
+ idField: string;
6
+ props: LiveProps;
7
+ }
8
+ export declare const makeInvalidateRenderer: () => EventRenderer;
9
+ export declare const makeRegionEventRenderer: (region: RegionRenderTarget) => EventRenderer;
10
+ //# sourceMappingURL=sse-render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse-render.d.ts","sourceRoot":"","sources":["../../src/htmx/sse-render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAI7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,SAAS,CAAC;CAClB;AAaD,eAAO,MAAM,sBAAsB,QAAO,aACI,CAAC;AAE/C,eAAO,MAAM,uBAAuB,GAAI,QAAQ,kBAAkB,KAAG,aAwBpE,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { formatSSE } from "../server/sse.js";
2
+ import { createRegionContext } from "./context.js";
3
+ import { rowDomId } from "./ids.js";
4
+ import { toHtmlString } from "./render-util.js";
5
+ // Builds the per-handler renderer that turns subscription events into named SSE
6
+ // frames the covara client runtime applies to the DOM:
7
+ // added/existing -> "added" event, data = the rendered row HTML (upsert by id)
8
+ // changed -> "changed" event, data = the rendered row HTML (replace by id)
9
+ // removed -> "removed" event, data = the row's DOM id (remove)
10
+ // invalidate -> "invalidate" event (client refetches the list)
11
+ // Rows are rendered through the page's own row closure, so the live markup is
12
+ // identical to the SSR markup.
13
+ // For aggregate regions: every row change emits a single "invalidate" so the
14
+ // client refetches the (recomputed) aggregate fragment. Reuses the row
15
+ // subscribe + renderer hook — no aggregate-specific server change needed.
16
+ export const makeInvalidateRenderer = () => () => formatSSE({ event: "invalidate", data: "" });
17
+ export const makeRegionEventRenderer = (region) => {
18
+ const c = createRegionContext(region.regionId);
19
+ const renderRow = (row) => toHtmlString(region.props.render(row, c));
20
+ return (event) => {
21
+ switch (event.type) {
22
+ case "existing":
23
+ case "added":
24
+ return formatSSE({ event: "added", id: event.seq, data: renderRow(event.object) });
25
+ case "changed":
26
+ return formatSSE({ event: "changed", id: event.seq, data: renderRow(event.object) });
27
+ case "removed":
28
+ return formatSSE({
29
+ event: "removed",
30
+ id: event.seq,
31
+ data: rowDomId(region.regionId, event.objectId),
32
+ });
33
+ case "invalidate":
34
+ return formatSSE({ event: "invalidate", data: event.reason ?? "" });
35
+ default:
36
+ return "";
37
+ }
38
+ };
39
+ };
40
+ //# sourceMappingURL=sse-render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse-render.js","sourceRoot":"","sources":["../../src/htmx/sse-render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAS7C,gFAAgF;AAChF,uDAAuD;AACvD,iFAAiF;AACjF,oFAAoF;AACpF,wEAAwE;AACxE,qEAAqE;AACrE,8EAA8E;AAC9E,+BAA+B;AAC/B,6EAA6E;AAC7E,uEAAuE;AACvE,0EAA0E;AAC1E,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAkB,EAAE,CAAC,GAAG,EAAE,CAC9D,SAAS,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;AAE/C,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,MAA0B,EAAiB,EAAE;IACnF,MAAM,CAAC,GAAG,mBAAmB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,CAAC,GAA4B,EAAU,EAAE,CACzD,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IAE5C,OAAO,CAAC,KAAK,EAAE,EAAE;QACf,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,UAAU,CAAC;YAChB,KAAK,OAAO;gBACV,OAAO,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACrF,KAAK,SAAS;gBACZ,OAAO,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACvF,KAAK,SAAS;gBACZ,OAAO,SAAS,CAAC;oBACf,KAAK,EAAE,SAAS;oBAChB,EAAE,EAAE,KAAK,CAAC,GAAG;oBACb,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC;iBAChD,CAAC,CAAC;YACL,KAAK,YAAY;gBACf,OAAO,SAAS,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC;YACtE;gBACE,OAAO,EAAE,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { LiveProps } from "./live.js";
2
+ export declare const buildRowTemplate: (region: {
3
+ regionId: string;
4
+ props: LiveProps;
5
+ }) => string;
6
+ export declare const applyRowTemplate: (template: string, values: Record<string, unknown>) => string;
7
+ //# sourceMappingURL=template-gen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-gen.d.ts","sourceRoot":"","sources":["../../src/htmx/template-gen.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAuBxC,eAAO,MAAM,gBAAgB,GAAI,QAAQ;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,KAAG,MAIjF,CAAC;AAIF,eAAO,MAAM,gBAAgB,GAC3B,UAAU,MAAM,EAChB,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,MAUC,CAAC"}