@voyantjs/legal 0.46.0 → 0.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -50,6 +50,24 @@ and fallback languages in order, prefers channel-specific defaults over global
50
50
  defaults, ignores inactive templates, and falls back to the newest active
51
51
  matching template only when no explicit default exists for that selector.
52
52
 
53
+ ## Contract Document Operations
54
+
55
+ The contracts route surface exposes stable operations for storefront previews
56
+ and stored document handling:
57
+
58
+ - `POST /v1/public/legal/contracts/templates/:id/render-preview`
59
+ - `POST /v1/public/legal/contracts/templates/by-slug/:slug/render-preview`
60
+ - `POST /v1/admin/legal/contracts/templates/:id/render-preview`
61
+ - `POST /v1/admin/legal/contracts/:id/attach-document`
62
+ - `POST /v1/admin/legal/contracts/:id/regenerate-pdf`
63
+
64
+ Preview routes accept `{ variables }` and return only the rendered text. Public
65
+ preview routes require the template to be active. `attach-document` expects a
66
+ multipart `file` field plus optional `name` and `kind`, uploads through the
67
+ configured `documentStorage`, and persists a contract attachment. `regenerate-pdf`
68
+ uses the configured contract document generator and replaces the canonical
69
+ generated document artifact.
70
+
53
71
  ### Policies
54
72
 
55
73
  - **Policies** (`pol`) — policy definitions by kind (cancellation, payment, T&C, etc.)
@@ -258,6 +258,48 @@ export declare function createContractsAdminRoutes(options?: ContractsRouteOptio
258
258
  status: 404;
259
259
  };
260
260
  };
261
+ } & {
262
+ "/templates/:id/render-preview": {
263
+ $post: {
264
+ input: {
265
+ param: {
266
+ id: string;
267
+ };
268
+ };
269
+ output: {
270
+ error: string;
271
+ issues: {
272
+ message: string;
273
+ }[];
274
+ };
275
+ outputFormat: "json";
276
+ status: 400;
277
+ } | {
278
+ input: {
279
+ param: {
280
+ id: string;
281
+ };
282
+ };
283
+ output: {
284
+ data: {
285
+ rendered: string;
286
+ };
287
+ };
288
+ outputFormat: "json";
289
+ status: import("hono/utils/http-status").ContentfulStatusCode;
290
+ } | {
291
+ input: {
292
+ param: {
293
+ id: string;
294
+ };
295
+ };
296
+ output: {
297
+ error: string;
298
+ };
299
+ outputFormat: "json";
300
+ status: 404;
301
+ };
302
+ };
261
303
  } & {
262
304
  "/templates/:id/versions": {
263
305
  $get: {
@@ -1260,6 +1302,85 @@ export declare function createContractsAdminRoutes(options?: ContractsRouteOptio
1260
1302
  status: import("hono/utils/http-status").ContentfulStatusCode;
1261
1303
  };
1262
1304
  };
1305
+ } & {
1306
+ "/:id/regenerate-pdf": {
1307
+ $post: {
1308
+ input: {
1309
+ param: {
1310
+ id: string;
1311
+ };
1312
+ };
1313
+ output: {
1314
+ error: string;
1315
+ };
1316
+ outputFormat: "json";
1317
+ status: 501;
1318
+ } | {
1319
+ input: {
1320
+ param: {
1321
+ id: string;
1322
+ };
1323
+ };
1324
+ output: {
1325
+ error: string;
1326
+ };
1327
+ outputFormat: "json";
1328
+ status: 404;
1329
+ } | {
1330
+ input: {
1331
+ param: {
1332
+ id: string;
1333
+ };
1334
+ };
1335
+ output: {
1336
+ error: string;
1337
+ };
1338
+ outputFormat: "json";
1339
+ status: 409;
1340
+ } | {
1341
+ input: {
1342
+ param: {
1343
+ id: string;
1344
+ };
1345
+ };
1346
+ output: {
1347
+ error: string;
1348
+ };
1349
+ outputFormat: "json";
1350
+ status: 502;
1351
+ } | {
1352
+ input: {
1353
+ param: {
1354
+ id: string;
1355
+ };
1356
+ };
1357
+ output: {
1358
+ data: {
1359
+ status: "not_found" | "not_draft" | "render_unavailable" | "generator_failed";
1360
+ } | {
1361
+ status: "generated";
1362
+ contractId: string;
1363
+ contractStatus: "executed" | "void" | "draft" | "issued" | "sent" | "signed" | "expired";
1364
+ renderedBodyFormat: "markdown" | "html" | "lexical_json";
1365
+ renderedBody: string;
1366
+ attachment: {
1367
+ metadata: import("hono/utils/types").JSONValue;
1368
+ name: string;
1369
+ id: string;
1370
+ createdAt: string;
1371
+ kind: string;
1372
+ mimeType: string | null;
1373
+ fileSize: number | null;
1374
+ storageKey: string | null;
1375
+ checksum: string | null;
1376
+ contractId: string;
1377
+ };
1378
+ };
1379
+ };
1380
+ outputFormat: "json";
1381
+ status: import("hono/utils/http-status").ContentfulStatusCode;
1382
+ };
1383
+ };
1263
1384
  } & {
1264
1385
  "/:id/signatures": {
1265
1386
  $get: {
@@ -1385,6 +1506,37 @@ export declare function createContractsAdminRoutes(options?: ContractsRouteOptio
1385
1506
  status: import("hono/utils/http-status").StatusCode;
1386
1507
  };
1387
1508
  };
1509
+ } & {
1510
+ "/:id/attach-document": {
1511
+ $post: {
1512
+ input: {
1513
+ param: {
1514
+ id: string;
1515
+ };
1516
+ };
1517
+ output: Promise<void>;
1518
+ outputFormat: "json";
1519
+ status: import("hono/utils/http-status").StatusCode;
1520
+ } | {
1521
+ input: {
1522
+ param: {
1523
+ id: string;
1524
+ };
1525
+ };
1526
+ output: {};
1527
+ outputFormat: string;
1528
+ status: import("hono/utils/http-status").StatusCode;
1529
+ } | {
1530
+ input: {
1531
+ param: {
1532
+ id: string;
1533
+ };
1534
+ };
1535
+ output: {};
1536
+ outputFormat: string;
1537
+ status: import("hono/utils/http-status").StatusCode;
1538
+ };
1539
+ };
1388
1540
  } & {
1389
1541
  "/attachments/:attachmentId": {
1390
1542
  $patch: {
@@ -1753,6 +1905,48 @@ export declare const contractsAdminRoutes: import("hono/hono-base").HonoBase<Env
1753
1905
  status: 404;
1754
1906
  };
1755
1907
  };
1908
+ } & {
1909
+ "/templates/:id/render-preview": {
1910
+ $post: {
1911
+ input: {
1912
+ param: {
1913
+ id: string;
1914
+ };
1915
+ };
1916
+ output: {
1917
+ error: string;
1918
+ issues: {
1919
+ message: string;
1920
+ }[];
1921
+ };
1922
+ outputFormat: "json";
1923
+ status: 400;
1924
+ } | {
1925
+ input: {
1926
+ param: {
1927
+ id: string;
1928
+ };
1929
+ };
1930
+ output: {
1931
+ data: {
1932
+ rendered: string;
1933
+ };
1934
+ };
1935
+ outputFormat: "json";
1936
+ status: import("hono/utils/http-status").ContentfulStatusCode;
1937
+ } | {
1938
+ input: {
1939
+ param: {
1940
+ id: string;
1941
+ };
1942
+ };
1943
+ output: {
1944
+ error: string;
1945
+ };
1946
+ outputFormat: "json";
1947
+ status: 404;
1948
+ };
1949
+ };
1756
1950
  } & {
1757
1951
  "/templates/:id/versions": {
1758
1952
  $get: {
@@ -2755,6 +2949,85 @@ export declare const contractsAdminRoutes: import("hono/hono-base").HonoBase<Env
2755
2949
  status: import("hono/utils/http-status").ContentfulStatusCode;
2756
2950
  };
2757
2951
  };
2952
+ } & {
2953
+ "/:id/regenerate-pdf": {
2954
+ $post: {
2955
+ input: {
2956
+ param: {
2957
+ id: string;
2958
+ };
2959
+ };
2960
+ output: {
2961
+ error: string;
2962
+ };
2963
+ outputFormat: "json";
2964
+ status: 501;
2965
+ } | {
2966
+ input: {
2967
+ param: {
2968
+ id: string;
2969
+ };
2970
+ };
2971
+ output: {
2972
+ error: string;
2973
+ };
2974
+ outputFormat: "json";
2975
+ status: 404;
2976
+ } | {
2977
+ input: {
2978
+ param: {
2979
+ id: string;
2980
+ };
2981
+ };
2982
+ output: {
2983
+ error: string;
2984
+ };
2985
+ outputFormat: "json";
2986
+ status: 409;
2987
+ } | {
2988
+ input: {
2989
+ param: {
2990
+ id: string;
2991
+ };
2992
+ };
2993
+ output: {
2994
+ error: string;
2995
+ };
2996
+ outputFormat: "json";
2997
+ status: 502;
2998
+ } | {
2999
+ input: {
3000
+ param: {
3001
+ id: string;
3002
+ };
3003
+ };
3004
+ output: {
3005
+ data: {
3006
+ status: "not_found" | "not_draft" | "render_unavailable" | "generator_failed";
3007
+ } | {
3008
+ status: "generated";
3009
+ contractId: string;
3010
+ contractStatus: "executed" | "void" | "draft" | "issued" | "sent" | "signed" | "expired";
3011
+ renderedBodyFormat: "markdown" | "html" | "lexical_json";
3012
+ renderedBody: string;
3013
+ attachment: {
3014
+ metadata: import("hono/utils/types").JSONValue;
3015
+ name: string;
3016
+ id: string;
3017
+ createdAt: string;
3018
+ kind: string;
3019
+ mimeType: string | null;
3020
+ fileSize: number | null;
3021
+ storageKey: string | null;
3022
+ checksum: string | null;
3023
+ contractId: string;
3024
+ };
3025
+ };
3026
+ };
3027
+ outputFormat: "json";
3028
+ status: import("hono/utils/http-status").ContentfulStatusCode;
3029
+ };
3030
+ };
2758
3031
  } & {
2759
3032
  "/:id/signatures": {
2760
3033
  $get: {
@@ -2880,6 +3153,37 @@ export declare const contractsAdminRoutes: import("hono/hono-base").HonoBase<Env
2880
3153
  status: import("hono/utils/http-status").StatusCode;
2881
3154
  };
2882
3155
  };
3156
+ } & {
3157
+ "/:id/attach-document": {
3158
+ $post: {
3159
+ input: {
3160
+ param: {
3161
+ id: string;
3162
+ };
3163
+ };
3164
+ output: Promise<void>;
3165
+ outputFormat: "json";
3166
+ status: import("hono/utils/http-status").StatusCode;
3167
+ } | {
3168
+ input: {
3169
+ param: {
3170
+ id: string;
3171
+ };
3172
+ };
3173
+ output: {};
3174
+ outputFormat: string;
3175
+ status: import("hono/utils/http-status").StatusCode;
3176
+ } | {
3177
+ input: {
3178
+ param: {
3179
+ id: string;
3180
+ };
3181
+ };
3182
+ output: {};
3183
+ outputFormat: string;
3184
+ status: import("hono/utils/http-status").StatusCode;
3185
+ };
3186
+ };
2883
3187
  } & {
2884
3188
  "/attachments/:attachmentId": {
2885
3189
  $patch: {
@@ -3085,6 +3389,48 @@ export declare function createContractsPublicRoutes(): import("hono/hono-base").
3085
3389
  status: 404;
3086
3390
  };
3087
3391
  };
3392
+ } & {
3393
+ "/templates/:id/render-preview": {
3394
+ $post: {
3395
+ input: {
3396
+ param: {
3397
+ id: string;
3398
+ };
3399
+ };
3400
+ output: {
3401
+ error: string;
3402
+ issues: {
3403
+ message: string;
3404
+ }[];
3405
+ };
3406
+ outputFormat: "json";
3407
+ status: 400;
3408
+ } | {
3409
+ input: {
3410
+ param: {
3411
+ id: string;
3412
+ };
3413
+ };
3414
+ output: {
3415
+ data: {
3416
+ rendered: string;
3417
+ };
3418
+ };
3419
+ outputFormat: "json";
3420
+ status: import("hono/utils/http-status").ContentfulStatusCode;
3421
+ } | {
3422
+ input: {
3423
+ param: {
3424
+ id: string;
3425
+ };
3426
+ };
3427
+ output: {
3428
+ error: string;
3429
+ };
3430
+ outputFormat: "json";
3431
+ status: 404;
3432
+ };
3433
+ };
3088
3434
  } & {
3089
3435
  "/templates/by-slug/:slug/preview": {
3090
3436
  $post: {
@@ -3127,6 +3473,48 @@ export declare function createContractsPublicRoutes(): import("hono/hono-base").
3127
3473
  status: 404;
3128
3474
  };
3129
3475
  };
3476
+ } & {
3477
+ "/templates/by-slug/:slug/render-preview": {
3478
+ $post: {
3479
+ input: {
3480
+ param: {
3481
+ slug: string;
3482
+ };
3483
+ };
3484
+ output: {
3485
+ error: string;
3486
+ issues: {
3487
+ message: string;
3488
+ }[];
3489
+ };
3490
+ outputFormat: "json";
3491
+ status: 400;
3492
+ } | {
3493
+ input: {
3494
+ param: {
3495
+ slug: string;
3496
+ };
3497
+ };
3498
+ output: {
3499
+ data: {
3500
+ rendered: string;
3501
+ };
3502
+ };
3503
+ outputFormat: "json";
3504
+ status: import("hono/utils/http-status").ContentfulStatusCode;
3505
+ } | {
3506
+ input: {
3507
+ param: {
3508
+ slug: string;
3509
+ };
3510
+ };
3511
+ output: {
3512
+ error: string;
3513
+ };
3514
+ outputFormat: "json";
3515
+ status: 404;
3516
+ };
3517
+ };
3130
3518
  } & {
3131
3519
  "/:id": {
3132
3520
  $get: {
@@ -3309,6 +3697,48 @@ export declare const contractsPublicRoutes: import("hono/hono-base").HonoBase<En
3309
3697
  status: 404;
3310
3698
  };
3311
3699
  };
3700
+ } & {
3701
+ "/templates/:id/render-preview": {
3702
+ $post: {
3703
+ input: {
3704
+ param: {
3705
+ id: string;
3706
+ };
3707
+ };
3708
+ output: {
3709
+ error: string;
3710
+ issues: {
3711
+ message: string;
3712
+ }[];
3713
+ };
3714
+ outputFormat: "json";
3715
+ status: 400;
3716
+ } | {
3717
+ input: {
3718
+ param: {
3719
+ id: string;
3720
+ };
3721
+ };
3722
+ output: {
3723
+ data: {
3724
+ rendered: string;
3725
+ };
3726
+ };
3727
+ outputFormat: "json";
3728
+ status: import("hono/utils/http-status").ContentfulStatusCode;
3729
+ } | {
3730
+ input: {
3731
+ param: {
3732
+ id: string;
3733
+ };
3734
+ };
3735
+ output: {
3736
+ error: string;
3737
+ };
3738
+ outputFormat: "json";
3739
+ status: 404;
3740
+ };
3741
+ };
3312
3742
  } & {
3313
3743
  "/templates/by-slug/:slug/preview": {
3314
3744
  $post: {
@@ -3351,6 +3781,48 @@ export declare const contractsPublicRoutes: import("hono/hono-base").HonoBase<En
3351
3781
  status: 404;
3352
3782
  };
3353
3783
  };
3784
+ } & {
3785
+ "/templates/by-slug/:slug/render-preview": {
3786
+ $post: {
3787
+ input: {
3788
+ param: {
3789
+ slug: string;
3790
+ };
3791
+ };
3792
+ output: {
3793
+ error: string;
3794
+ issues: {
3795
+ message: string;
3796
+ }[];
3797
+ };
3798
+ outputFormat: "json";
3799
+ status: 400;
3800
+ } | {
3801
+ input: {
3802
+ param: {
3803
+ slug: string;
3804
+ };
3805
+ };
3806
+ output: {
3807
+ data: {
3808
+ rendered: string;
3809
+ };
3810
+ };
3811
+ outputFormat: "json";
3812
+ status: import("hono/utils/http-status").ContentfulStatusCode;
3813
+ } | {
3814
+ input: {
3815
+ param: {
3816
+ slug: string;
3817
+ };
3818
+ };
3819
+ output: {
3820
+ error: string;
3821
+ };
3822
+ outputFormat: "json";
3823
+ status: 404;
3824
+ };
3825
+ };
3354
3826
  } & {
3355
3827
  "/:id": {
3356
3828
  $get: {
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/contracts/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAE/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAUjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAoB/C,KAAK,GAAG,GAAG;IACT,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,SAAS,EAAE;QACT,SAAS,EAAE,eAAe,CAAA;QAC1B,EAAE,EAAE,kBAAkB,CAAA;QACtB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG,UAAU,CAChD,OAAO,gBAAgB,CAAC,wBAAwB,CACjD,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAA;AAEjB,MAAM,WAAW,qBAAqB;IACpC,iBAAiB,CAAC,EAAE,yBAAyB,CAAA;IAC7C,wBAAwB,CAAC,EAAE,CACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,yBAAyB,GAAG,SAAS,CAAA;IAC1C,0BAA0B,CAAC,EAAE,CAC3B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,UAAU,EAAE,MAAM,KACf,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAA;IAC3C,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;IACxC,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,eAAe,GAAG,IAAI,GAAG,SAAS,CAAA;IAClG,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,QAAQ,GAAG,SAAS,CAAA;CAC9E;AAkHD,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,qBAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sCA6V7E;AAED,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCAA+B,CAAA;AAEhE,wBAAgB,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA6D1C;AAED,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAAgC,CAAA;AAElE,MAAM,MAAM,oBAAoB,GAAG,OAAO,oBAAoB,CAAA;AAC9D,MAAM,MAAM,qBAAqB,GAAG,OAAO,qBAAqB,CAAA"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/contracts/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAE/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAUjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAoB/C,KAAK,GAAG,GAAG;IACT,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,SAAS,EAAE;QACT,SAAS,EAAE,eAAe,CAAA;QAC1B,EAAE,EAAE,kBAAkB,CAAA;QACtB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG,UAAU,CAChD,OAAO,gBAAgB,CAAC,wBAAwB,CACjD,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAA;AAEjB,MAAM,WAAW,qBAAqB;IACpC,iBAAiB,CAAC,EAAE,yBAAyB,CAAA;IAC7C,wBAAwB,CAAC,EAAE,CACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,yBAAyB,GAAG,SAAS,CAAA;IAC1C,0BAA0B,CAAC,EAAE,CAC3B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,UAAU,EAAE,MAAM,KACf,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAA;IAC3C,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;IACxC,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,eAAe,GAAG,IAAI,GAAG,SAAS,CAAA;IAClG,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,QAAQ,GAAG,SAAS,CAAA;CAC9E;AA+ND,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,qBAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sCA+S7E;AAED,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCAA+B,CAAA;AAEhE,wBAAgB,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAmC1C;AAED,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAAgC,CAAA;AAElE,MAAM,MAAM,oBAAoB,GAAG,OAAO,oBAAoB,CAAA;AAC9D,MAAM,MAAM,qBAAqB,GAAG,OAAO,qBAAqB,CAAA"}
@@ -87,6 +87,93 @@ async function parseAttachmentUploadRequest(c) {
87
87
  }
88
88
  return { form, file };
89
89
  }
90
+ async function renderAdminTemplatePreview(c) {
91
+ const id = c.req.param("id");
92
+ if (!id)
93
+ return c.json({ error: "Template not found" }, 404);
94
+ const input = await parseJsonBody(c, renderTemplateInputSchema);
95
+ const template = await contractsService.getTemplateById(c.get("db"), id);
96
+ if (!template)
97
+ return c.json({ error: "Template not found" }, 404);
98
+ const body = input.body ?? template.body;
99
+ return renderPreviewResponse(c, { ...input, body });
100
+ }
101
+ async function renderPublicTemplatePreview(c) {
102
+ const id = c.req.param("id");
103
+ if (!id)
104
+ return c.json({ error: "Template not found" }, 404);
105
+ const input = await parseJsonBody(c, publicRenderTemplatePreviewInputSchema);
106
+ const template = await contractsService.getTemplateById(c.get("db"), id);
107
+ if (!template?.active)
108
+ return c.json({ error: "Template not found" }, 404);
109
+ return renderPreviewResponse(c, {
110
+ variables: input.variables,
111
+ body: template.body,
112
+ });
113
+ }
114
+ async function renderPublicTemplatePreviewBySlug(c) {
115
+ const slug = c.req.param("slug");
116
+ if (!slug)
117
+ return c.json({ error: "Template not found" }, 404);
118
+ const input = await parseJsonBody(c, publicRenderTemplatePreviewInputSchema);
119
+ const template = await contractsService.findTemplateBySlug(c.get("db"), slug);
120
+ if (!template?.active)
121
+ return c.json({ error: "Template not found" }, 404);
122
+ return renderPreviewResponse(c, {
123
+ variables: input.variables,
124
+ body: template.body,
125
+ }, {
126
+ template: {
127
+ id: template.id,
128
+ slug: template.slug,
129
+ name: template.name,
130
+ language: template.language,
131
+ scope: template.scope,
132
+ },
133
+ });
134
+ }
135
+ async function uploadContractAttachment(c, options, contractId) {
136
+ const runtime = getRuntime(options, c.env, (key) => c.var.container?.resolve(key));
137
+ const storage = runtime.documentStorage;
138
+ if (!storage) {
139
+ return c.json({ error: "Contract document storage is not configured" }, 501);
140
+ }
141
+ const contract = await contractsService.getContractById(c.get("db"), contractId);
142
+ if (!contract)
143
+ return c.json({ error: "Contract not found" }, 404);
144
+ const parsed = await parseAttachmentUploadRequest(c);
145
+ if ("error" in parsed)
146
+ return parsed.error;
147
+ const row = await contractsService.createAttachment(c.get("db"), contractId, await buildUploadedAttachmentInput({
148
+ storage,
149
+ contractId,
150
+ form: parsed.form,
151
+ file: parsed.file,
152
+ }));
153
+ if (!row)
154
+ return c.json({ error: "Contract not found" }, 404);
155
+ return c.json({ data: row }, 201);
156
+ }
157
+ async function regenerateContractDocument(c, options, contractId) {
158
+ const runtime = getRuntime(options, c.env, (key) => c.var.container?.resolve(key));
159
+ const generator = runtime.documentGenerator;
160
+ if (!generator) {
161
+ return c.json({ error: "Contract document generator is not configured" }, 501);
162
+ }
163
+ const result = await contractsService.regenerateContractDocument(c.get("db"), contractId, await parseOptionalJsonBody(c, generateContractDocumentInputSchema), { generator, bindings: c.env, eventBus: runtime.eventBus });
164
+ if (result.status === "not_found")
165
+ return c.json({ error: "Contract not found" }, 404);
166
+ if (result.status === "not_draft") {
167
+ return c.json({ error: "Only draft contracts can be auto-issued for document generation" }, 409);
168
+ }
169
+ if (result.status === "render_unavailable") {
170
+ return c.json({ error: "Contract has no renderable body or template version" }, 409);
171
+ }
172
+ if (result.status === "generator_failed") {
173
+ return c.json({ error: "Contract document generation failed" }, 502);
174
+ }
175
+ return c.json({ data: result });
176
+ }
90
177
  export function createContractsAdminRoutes(options = {}) {
91
178
  return new Hono()
92
179
  .get("/templates", async (c) => {
@@ -122,14 +209,8 @@ export function createContractsAdminRoutes(options = {}) {
122
209
  return c.json({ error: "Template not found" }, 404);
123
210
  return c.json({ success: true });
124
211
  })
125
- .post("/templates/:id/preview", async (c) => {
126
- const input = await parseJsonBody(c, renderTemplateInputSchema);
127
- const template = await contractsService.getTemplateById(c.get("db"), c.req.param("id"));
128
- if (!template)
129
- return c.json({ error: "Template not found" }, 404);
130
- const body = input.body ?? template.body;
131
- return renderPreviewResponse(c, { ...input, body });
132
- })
212
+ .post("/templates/:id/preview", renderAdminTemplatePreview)
213
+ .post("/templates/:id/render-preview", renderAdminTemplatePreview)
133
214
  .get("/templates/:id/versions", async (c) => {
134
215
  const rows = await contractsService.listTemplateVersions(c.get("db"), c.req.param("id"));
135
216
  return c.json({ data: rows });
@@ -275,24 +356,10 @@ export function createContractsAdminRoutes(options = {}) {
275
356
  return c.json({ data: result }, 201);
276
357
  })
277
358
  .post("/:id/regenerate-document", async (c) => {
278
- const runtime = getRuntime(options, c.env, (key) => c.var.container?.resolve(key));
279
- const generator = runtime.documentGenerator;
280
- if (!generator) {
281
- return c.json({ error: "Contract document generator is not configured" }, 501);
282
- }
283
- const result = await contractsService.regenerateContractDocument(c.get("db"), c.req.param("id"), await parseOptionalJsonBody(c, generateContractDocumentInputSchema), { generator, bindings: c.env, eventBus: runtime.eventBus });
284
- if (result.status === "not_found")
285
- return c.json({ error: "Contract not found" }, 404);
286
- if (result.status === "not_draft") {
287
- return c.json({ error: "Only draft contracts can be auto-issued for document generation" }, 409);
288
- }
289
- if (result.status === "render_unavailable") {
290
- return c.json({ error: "Contract has no renderable body or template version" }, 409);
291
- }
292
- if (result.status === "generator_failed") {
293
- return c.json({ error: "Contract document generation failed" }, 502);
294
- }
295
- return c.json({ data: result });
359
+ return regenerateContractDocument(c, options, c.req.param("id"));
360
+ })
361
+ .post("/:id/regenerate-pdf", async (c) => {
362
+ return regenerateContractDocument(c, options, c.req.param("id"));
296
363
  })
297
364
  .get("/:id/signatures", async (c) => {
298
365
  const rows = await contractsService.listSignatures(c.get("db"), c.req.param("id"));
@@ -309,23 +376,10 @@ export function createContractsAdminRoutes(options = {}) {
309
376
  return c.json({ data: row }, 201);
310
377
  })
311
378
  .post("/:id/attachments/upload", async (c) => {
312
- const runtime = getRuntime(options, c.env, (key) => c.var.container?.resolve(key));
313
- const storage = runtime.documentStorage;
314
- if (!storage) {
315
- return c.json({ error: "Contract document storage is not configured" }, 501);
316
- }
317
- const parsed = await parseAttachmentUploadRequest(c);
318
- if ("error" in parsed)
319
- return parsed.error;
320
- const row = await contractsService.createAttachment(c.get("db"), c.req.param("id"), await buildUploadedAttachmentInput({
321
- storage,
322
- contractId: c.req.param("id"),
323
- form: parsed.form,
324
- file: parsed.file,
325
- }));
326
- if (!row)
327
- return c.json({ error: "Contract not found" }, 404);
328
- return c.json({ data: row }, 201);
379
+ return uploadContractAttachment(c, options, c.req.param("id"));
380
+ })
381
+ .post("/:id/attach-document", async (c) => {
382
+ return uploadContractAttachment(c, options, c.req.param("id"));
329
383
  })
330
384
  .patch("/attachments/:attachmentId", async (c) => {
331
385
  const row = await contractsService.updateAttachment(c.get("db"), c.req.param("attachmentId"), await parseJsonBody(c, updateContractAttachmentSchema));
@@ -397,40 +451,16 @@ export function createContractsPublicRoutes() {
397
451
  return c.json({ error: "Template not found" }, 404);
398
452
  return c.json({ data: row });
399
453
  })
400
- .post("/templates/:id/preview", async (c) => {
401
- const input = await parseJsonBody(c, publicRenderTemplatePreviewInputSchema);
402
- const template = await contractsService.getTemplateById(c.get("db"), c.req.param("id"));
403
- if (!template?.active)
404
- return c.json({ error: "Template not found" }, 404);
405
- return renderPreviewResponse(c, {
406
- variables: input.variables,
407
- body: template.body,
408
- });
409
- })
454
+ .post("/templates/:id/preview", renderPublicTemplatePreview)
455
+ .post("/templates/:id/render-preview", renderPublicTemplatePreview)
410
456
  /**
411
457
  * Slug-based variant — storefronts wire products to a contract
412
458
  * template via slug at config time, not id, so they can render the
413
459
  * preview in the booking journey before any contract row exists.
414
460
  * The dialog at /shop/book/... POSTs here with the draft variables.
415
461
  */
416
- .post("/templates/by-slug/:slug/preview", async (c) => {
417
- const input = await parseJsonBody(c, publicRenderTemplatePreviewInputSchema);
418
- const template = await contractsService.findTemplateBySlug(c.get("db"), c.req.param("slug"));
419
- if (!template?.active)
420
- return c.json({ error: "Template not found" }, 404);
421
- return renderPreviewResponse(c, {
422
- variables: input.variables,
423
- body: template.body,
424
- }, {
425
- template: {
426
- id: template.id,
427
- slug: template.slug,
428
- name: template.name,
429
- language: template.language,
430
- scope: template.scope,
431
- },
432
- });
433
- })
462
+ .post("/templates/by-slug/:slug/preview", renderPublicTemplatePreviewBySlug)
463
+ .post("/templates/by-slug/:slug/render-preview", renderPublicTemplatePreviewBySlug)
434
464
  .get("/:id", async (c) => {
435
465
  const row = await contractsService.getContractById(c.get("db"), c.req.param("id"));
436
466
  if (!row)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyantjs/legal",
3
- "version": "0.46.0",
3
+ "version": "0.47.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -59,14 +59,14 @@
59
59
  "drizzle-orm": "^0.45.2",
60
60
  "hono": "^4.12.10",
61
61
  "zod": "^4.3.6",
62
- "@voyantjs/bookings": "0.46.0",
63
- "@voyantjs/core": "0.46.0",
64
- "@voyantjs/crm": "0.46.0",
65
- "@voyantjs/db": "0.46.0",
66
- "@voyantjs/hono": "0.46.0",
67
- "@voyantjs/suppliers": "0.46.0",
68
- "@voyantjs/utils": "0.46.0",
69
- "@voyantjs/storage": "0.46.0"
62
+ "@voyantjs/bookings": "0.47.0",
63
+ "@voyantjs/core": "0.47.0",
64
+ "@voyantjs/crm": "0.47.0",
65
+ "@voyantjs/db": "0.47.0",
66
+ "@voyantjs/hono": "0.47.0",
67
+ "@voyantjs/suppliers": "0.47.0",
68
+ "@voyantjs/utils": "0.47.0",
69
+ "@voyantjs/storage": "0.47.0"
70
70
  },
71
71
  "devDependencies": {
72
72
  "typescript": "^6.0.2",