@voyantjs/legal 0.3.0 → 0.4.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.
@@ -0,0 +1,244 @@
1
+ import { renderPdfDocument } from "@voyantjs/utils/pdf-renderer";
2
+ import { desc, eq } from "drizzle-orm";
3
+ import { contractAttachments, contracts, contractTemplateVersions } from "./schema.js";
4
+ import { contractRecordsService } from "./service-contracts.js";
5
+ import { renderTemplate } from "./service-shared.js";
6
+ function normalizeAttachmentInput(input, fallbackKind) {
7
+ return {
8
+ kind: input.kind ?? fallbackKind,
9
+ name: input.name,
10
+ mimeType: input.mimeType ?? null,
11
+ fileSize: input.fileSize ?? null,
12
+ storageKey: input.storageKey ?? null,
13
+ checksum: input.checksum ?? null,
14
+ metadata: input.metadata ?? null,
15
+ };
16
+ }
17
+ function defaultContractDocumentExtension(format) {
18
+ switch (format) {
19
+ case "html":
20
+ return "html";
21
+ case "lexical_json":
22
+ return "json";
23
+ default:
24
+ return "md";
25
+ }
26
+ }
27
+ function defaultContractDocumentMimeType(format) {
28
+ switch (format) {
29
+ case "html":
30
+ return "text/html; charset=utf-8";
31
+ case "lexical_json":
32
+ return "application/json; charset=utf-8";
33
+ default:
34
+ return "text/markdown; charset=utf-8";
35
+ }
36
+ }
37
+ function encodeStringBody(value) {
38
+ return new TextEncoder().encode(value);
39
+ }
40
+ function getBodySize(body) {
41
+ if (body instanceof Uint8Array)
42
+ return body.byteLength;
43
+ if (body instanceof ArrayBuffer)
44
+ return body.byteLength;
45
+ return body.size;
46
+ }
47
+ function toUploadMetadata(metadata) {
48
+ const entries = Object.entries(metadata ?? {}).filter(([, value]) => ["string", "number", "boolean"].includes(typeof value));
49
+ return entries.length > 0
50
+ ? Object.fromEntries(entries.map(([key, value]) => [key, String(value)]))
51
+ : undefined;
52
+ }
53
+ export function defaultStorageBackedContractDocumentSerializer(context) {
54
+ const extension = defaultContractDocumentExtension(context.renderedBodyFormat);
55
+ return {
56
+ body: encodeStringBody(context.renderedBody),
57
+ name: `contract-${context.contract.id}.${extension}`,
58
+ mimeType: defaultContractDocumentMimeType(context.renderedBodyFormat),
59
+ metadata: {
60
+ renderedBodyFormat: context.renderedBodyFormat,
61
+ },
62
+ };
63
+ }
64
+ export async function defaultPdfContractDocumentSerializer(context) {
65
+ const body = await renderPdfDocument({
66
+ title: `Contract ${context.contract.id}`,
67
+ content: context.renderedBody,
68
+ format: context.renderedBodyFormat === "lexical_json"
69
+ ? "lexical_json"
70
+ : context.renderedBodyFormat === "html"
71
+ ? "html"
72
+ : "markdown",
73
+ metadataLines: [`Contract ID: ${context.contract.id}`, `Status: ${context.contract.status}`],
74
+ });
75
+ return {
76
+ body,
77
+ name: `contract-${context.contract.id}.pdf`,
78
+ mimeType: "application/pdf",
79
+ metadata: {
80
+ renderedBodyFormat: context.renderedBodyFormat,
81
+ renderer: "voyant-basic-pdf",
82
+ },
83
+ };
84
+ }
85
+ export function createStorageBackedContractDocumentGenerator(options) {
86
+ const serializer = options.serializer ?? defaultStorageBackedContractDocumentSerializer;
87
+ return async (context) => {
88
+ const upload = await serializer(context);
89
+ const keyPrefix = typeof options.keyPrefix === "function"
90
+ ? await options.keyPrefix(context)
91
+ : (options.keyPrefix ?? `contracts/${context.contract.id}`);
92
+ const normalizedName = upload.name?.trim() ||
93
+ `contract-${context.contract.id}.${defaultContractDocumentExtension(context.renderedBodyFormat)}`;
94
+ const normalizedKey = upload.key?.trim() || `${keyPrefix.replace(/\/$/, "")}/${normalizedName}`;
95
+ const uploaded = await options.storage.upload(upload.body, {
96
+ key: normalizedKey,
97
+ contentType: upload.mimeType ?? defaultContractDocumentMimeType(context.renderedBodyFormat),
98
+ metadata: toUploadMetadata(upload.metadata),
99
+ });
100
+ const downloadUrl = uploaded.url ||
101
+ (options.signedUrlExpiresIn
102
+ ? await options.storage.signedUrl(uploaded.key, options.signedUrlExpiresIn)
103
+ : "");
104
+ return {
105
+ kind: upload.kind ?? "document",
106
+ name: normalizedName,
107
+ mimeType: upload.mimeType ?? defaultContractDocumentMimeType(context.renderedBodyFormat),
108
+ fileSize: getBodySize(upload.body),
109
+ storageKey: uploaded.key,
110
+ metadata: {
111
+ ...(upload.metadata ?? {}),
112
+ storageProvider: options.storage.name,
113
+ ...(uploaded.url ? { url: uploaded.url } : {}),
114
+ ...(downloadUrl ? { downloadUrl } : {}),
115
+ },
116
+ };
117
+ };
118
+ }
119
+ export function createPdfContractDocumentGenerator(options) {
120
+ return createStorageBackedContractDocumentGenerator({
121
+ ...options,
122
+ serializer: defaultPdfContractDocumentSerializer,
123
+ });
124
+ }
125
+ async function loadTemplateVersion(db, templateVersionId) {
126
+ if (!templateVersionId) {
127
+ return null;
128
+ }
129
+ const [version] = await db
130
+ .select()
131
+ .from(contractTemplateVersions)
132
+ .where(eq(contractTemplateVersions.id, templateVersionId))
133
+ .limit(1);
134
+ return version ?? null;
135
+ }
136
+ async function ensureRenderedContract(db, contractId, issueIfDraft) {
137
+ let contract = await contractRecordsService.getContractById(db, contractId);
138
+ if (!contract) {
139
+ return { status: "not_found" };
140
+ }
141
+ if (contract.status === "draft" && issueIfDraft) {
142
+ const issued = await contractRecordsService.issueContract(db, contractId);
143
+ if (issued.status !== "issued" || !issued.contract) {
144
+ if (issued.status === "not_found") {
145
+ return { status: "not_found" };
146
+ }
147
+ return { status: "not_draft", contract: null };
148
+ }
149
+ contract = issued.contract;
150
+ }
151
+ const templateVersion = await loadTemplateVersion(db, contract.templateVersionId ?? null);
152
+ let renderedBody = contract.renderedBody;
153
+ let renderedBodyFormat = contract.renderedBodyFormat;
154
+ if ((!renderedBody || !renderedBodyFormat) && templateVersion) {
155
+ const variables = contract.variables ?? {};
156
+ renderedBody = renderTemplate(templateVersion.body, templateVersion.bodyFormat, variables);
157
+ renderedBodyFormat = templateVersion.bodyFormat;
158
+ const [updated] = await db
159
+ .update(contracts)
160
+ .set({
161
+ renderedBody,
162
+ renderedBodyFormat,
163
+ updatedAt: new Date(),
164
+ })
165
+ .where(eq(contracts.id, contractId))
166
+ .returning();
167
+ contract = updated ?? contract;
168
+ }
169
+ if (!renderedBody || !renderedBodyFormat) {
170
+ return { status: "render_unavailable", contract, templateVersion };
171
+ }
172
+ return {
173
+ status: "ready",
174
+ contract,
175
+ templateVersion,
176
+ renderedBody,
177
+ renderedBodyFormat,
178
+ };
179
+ }
180
+ export const contractDocumentsService = {
181
+ async generateContractDocument(db, contractId, input, runtime) {
182
+ const prepared = await ensureRenderedContract(db, contractId, input.issueIfDraft);
183
+ if (prepared.status === "not_found") {
184
+ return { status: "not_found" };
185
+ }
186
+ if (prepared.status === "not_draft") {
187
+ return { status: "not_draft" };
188
+ }
189
+ if (prepared.status === "render_unavailable") {
190
+ return { status: "render_unavailable" };
191
+ }
192
+ let artifact;
193
+ try {
194
+ artifact = await runtime.generator({
195
+ db,
196
+ contract: prepared.contract,
197
+ templateVersion: prepared.templateVersion,
198
+ renderedBody: prepared.renderedBody,
199
+ renderedBodyFormat: prepared.renderedBodyFormat,
200
+ variables: prepared.contract.variables ?? {},
201
+ bindings: runtime.bindings ?? {},
202
+ });
203
+ }
204
+ catch {
205
+ return { status: "generator_failed" };
206
+ }
207
+ if (input.replaceExisting) {
208
+ const existing = await db
209
+ .select({ id: contractAttachments.id })
210
+ .from(contractAttachments)
211
+ .where(eq(contractAttachments.contractId, contractId))
212
+ .orderBy(desc(contractAttachments.createdAt));
213
+ for (const attachment of existing) {
214
+ const row = await db
215
+ .select({ id: contractAttachments.id, kind: contractAttachments.kind })
216
+ .from(contractAttachments)
217
+ .where(eq(contractAttachments.id, attachment.id))
218
+ .limit(1)
219
+ .then((rows) => rows[0] ?? null);
220
+ if (row?.kind === (artifact.kind ?? input.kind)) {
221
+ await contractRecordsService.deleteAttachment(db, attachment.id);
222
+ }
223
+ }
224
+ }
225
+ const attachment = await contractRecordsService.createAttachment(db, contractId, normalizeAttachmentInput(artifact, input.kind));
226
+ if (!attachment) {
227
+ return { status: "not_found" };
228
+ }
229
+ return {
230
+ status: "generated",
231
+ contractId: prepared.contract.id,
232
+ contractStatus: prepared.contract.status,
233
+ renderedBodyFormat: prepared.renderedBodyFormat,
234
+ renderedBody: prepared.renderedBody,
235
+ attachment,
236
+ };
237
+ },
238
+ async regenerateContractDocument(db, contractId, input, runtime) {
239
+ return this.generateContractDocument(db, contractId, {
240
+ ...input,
241
+ issueIfDraft: input.issueIfDraft,
242
+ }, runtime);
243
+ },
244
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"service-shared.d.ts","sourceRoot":"","sources":["../../src/contracts/service-shared.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAG5B,OAAO,KAAK,EACV,uBAAuB,EACvB,+BAA+B,EAC/B,8BAA8B,EAC9B,gCAAgC,EAChC,oBAAoB,EACpB,6BAA6B,EAC7B,4BAA4B,EAC5B,mCAAmC,EACnC,yBAAyB,EACzB,8BAA8B,EAC9B,gCAAgC,EAChC,oBAAoB,EACpB,4BAA4B,EAC7B,MAAM,iBAAiB,CAAA;AAExB,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AACvE,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAA;AACvF,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA;AACtF,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA;AACtF,MAAM,MAAM,kCAAkC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAA;AACpG,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAA;AAC9F,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAA;AAC9F,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACtE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACtE,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAA;AACxF,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAA;AAC1F,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAA;AAC1F,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAE3E,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAE9D;AA8DD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,UAAU,GAAG,MAAM,GAAG,cAAc,EAChD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,MAAM,CAkBR;AAED,wBAAgB,yBAAyB,CACvC,cAAc,EAAE,OAAO,EACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,EAAE,CAYV;AAkBD,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,kBAAkB,EACtB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAmCtD;AAED,wBAAsB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAC7C,SAAS,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,EACvB,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,EAC7C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM;;;;;GAIf"}
1
+ {"version":3,"file":"service-shared.d.ts","sourceRoot":"","sources":["../../src/contracts/service-shared.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAG5B,OAAO,KAAK,EACV,uBAAuB,EACvB,+BAA+B,EAC/B,8BAA8B,EAC9B,gCAAgC,EAChC,oBAAoB,EACpB,6BAA6B,EAC7B,4BAA4B,EAC5B,mCAAmC,EACnC,yBAAyB,EACzB,8BAA8B,EAC9B,gCAAgC,EAChC,oBAAoB,EACpB,4BAA4B,EAC7B,MAAM,iBAAiB,CAAA;AAExB,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AACvE,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAA;AACvF,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA;AACtF,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA;AACtF,MAAM,MAAM,kCAAkC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAA;AACpG,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAA;AAC9F,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAA;AAC9F,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACtE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACtE,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAA;AACxF,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAA;AAC1F,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAA;AAC1F,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAE3E,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAE9D;AA4BD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,UAAU,GAAG,MAAM,GAAG,cAAc,EAChD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,MAAM,CAER;AAED,wBAAgB,yBAAyB,CACvC,cAAc,EAAE,OAAO,EACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,EAAE,CAYV;AAkBD,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,kBAAkB,EACtB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAmCtD;AAED,wBAAsB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAC7C,SAAS,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,EACvB,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,EAC7C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM;;;;;GAIf"}
@@ -1,3 +1,4 @@
1
+ import { renderStructuredTemplate } from "@voyantjs/utils/template-renderer";
1
2
  import { sql } from "drizzle-orm";
2
3
  import { contractNumberSeries } from "./schema.js";
3
4
  export function toTimestamp(value) {
@@ -36,51 +37,8 @@ function resolvePath(obj, path) {
36
37
  }
37
38
  return current;
38
39
  }
39
- function stringifyValue(value) {
40
- if (value === null || value === undefined)
41
- return "";
42
- if (typeof value === "string")
43
- return value;
44
- if (typeof value === "number" || typeof value === "boolean")
45
- return String(value);
46
- return JSON.stringify(value);
47
- }
48
- const MUSTACHE_RE = /\{\{\s*([^}]+?)\s*\}\}/g;
49
- function renderMustache(body, variables) {
50
- return body.replace(MUSTACHE_RE, (_, path) => {
51
- const resolved = resolvePath(variables, path.trim());
52
- return stringifyValue(resolved);
53
- });
54
- }
55
- function walkLexical(node, variables) {
56
- const next = { ...node };
57
- if (typeof next.text === "string") {
58
- next.text = renderMustache(next.text, variables);
59
- }
60
- if (Array.isArray(next.children)) {
61
- next.children = next.children.map((child) => walkLexical(child, variables));
62
- }
63
- return next;
64
- }
65
40
  export function renderTemplate(body, bodyFormat, variables) {
66
- if (bodyFormat === "lexical_json") {
67
- try {
68
- const parsed = JSON.parse(body);
69
- if (parsed && typeof parsed === "object") {
70
- const obj = parsed;
71
- if (obj.root && typeof obj.root === "object") {
72
- const result = { ...obj, root: walkLexical(obj.root, variables) };
73
- return JSON.stringify(result);
74
- }
75
- return JSON.stringify(walkLexical(obj, variables));
76
- }
77
- return body;
78
- }
79
- catch {
80
- return renderMustache(body, variables);
81
- }
82
- }
83
- return renderMustache(body, variables);
41
+ return renderStructuredTemplate(body, bodyFormat, variables);
84
42
  }
85
43
  export function validateTemplateVariables(variableSchema, values) {
86
44
  const issues = [];
@@ -36,6 +36,25 @@ export declare const contractTemplatesService: {
36
36
  createdAt: Date;
37
37
  updatedAt: Date;
38
38
  } | null>;
39
+ getDefaultTemplate(db: PostgresJsDatabase, query: {
40
+ scope: "customer" | "supplier" | "partner" | "channel" | "other";
41
+ language?: string;
42
+ fallbackLanguages?: string[];
43
+ }): Promise<{
44
+ id: string;
45
+ name: string;
46
+ slug: string;
47
+ scope: "customer" | "partner" | "supplier" | "other" | "channel";
48
+ language: string;
49
+ description: string | null;
50
+ bodyFormat: "markdown" | "html" | "lexical_json";
51
+ body: string;
52
+ variableSchema: unknown;
53
+ currentVersionId: string | null;
54
+ active: boolean;
55
+ createdAt: Date;
56
+ updatedAt: Date;
57
+ } | null>;
39
58
  createTemplate(db: PostgresJsDatabase, data: CreateContractTemplateInput): Promise<{
40
59
  id: string;
41
60
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"service-templates.d.ts","sourceRoot":"","sources":["../../src/contracts/service-templates.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EAChC,KAAK,kCAAkC,EAEvC,KAAK,mBAAmB,EAExB,KAAK,2BAA2B,EACjC,MAAM,qBAAqB,CAAA;AAE5B,eAAO,MAAM,wBAAwB;sBACX,kBAAkB,SAAS,yBAAyB;;;;;;;;;;;;;;;;;;;;wBA6BlD,kBAAkB,MAAM,MAAM;;;;;;;;;;;;;;;uBAQ/B,kBAAkB,QAAQ,2BAA2B;;;;;;;;;;;;;;;uBAIrD,kBAAkB,MAAM,MAAM,QAAQ,2BAA2B;;;;;;;;;;;;;;;uBAQjE,kBAAkB,MAAM,MAAM;;;6BAO9B,kBAAkB,cAAc,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+BAO9B,kBAAkB,MAAM,MAAM;;;;;;;;;;;8BASzD,kBAAkB,cACV,MAAM,QACZ,kCAAkC;;;;;;;;;;;yBAmCrB,mBAAmB,GAAG,MAAM;CAKlD,CAAA"}
1
+ {"version":3,"file":"service-templates.d.ts","sourceRoot":"","sources":["../../src/contracts/service-templates.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EAChC,KAAK,kCAAkC,EAEvC,KAAK,mBAAmB,EAExB,KAAK,2BAA2B,EACjC,MAAM,qBAAqB,CAAA;AAE5B,eAAO,MAAM,wBAAwB;sBACX,kBAAkB,SAAS,yBAAyB;;;;;;;;;;;;;;;;;;;;wBA6BlD,kBAAkB,MAAM,MAAM;;;;;;;;;;;;;;;2BASlD,kBAAkB,SACf;QACL,KAAK,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAA;QAChE,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;KAC7B;;;;;;;;;;;;;;;uBAgCsB,kBAAkB,QAAQ,2BAA2B;;;;;;;;;;;;;;;uBAIrD,kBAAkB,MAAM,MAAM,QAAQ,2BAA2B;;;;;;;;;;;;;;;uBAQjE,kBAAkB,MAAM,MAAM;;;6BAO9B,kBAAkB,cAAc,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+BAO9B,kBAAkB,MAAM,MAAM;;;;;;;;;;;8BASzD,kBAAkB,cACV,MAAM,QACZ,kCAAkC;;;;;;;;;;;yBAmCrB,mBAAmB,GAAG,MAAM;CAKlD,CAAA"}
@@ -31,6 +31,30 @@ export const contractTemplatesService = {
31
31
  .limit(1);
32
32
  return row ?? null;
33
33
  },
34
+ async getDefaultTemplate(db, query) {
35
+ const rows = await db
36
+ .select()
37
+ .from(contractTemplates)
38
+ .where(and(eq(contractTemplates.scope, query.scope), eq(contractTemplates.active, true)))
39
+ .orderBy(desc(contractTemplates.updatedAt));
40
+ if (rows.length === 0) {
41
+ return null;
42
+ }
43
+ const preferredLanguages = [
44
+ query.language?.trim().toLowerCase(),
45
+ ...(query.fallbackLanguages ?? []).map((value) => value.trim().toLowerCase()),
46
+ ].filter((value, index, values) => Boolean(value) && values.indexOf(value) === index);
47
+ if (preferredLanguages.length === 0) {
48
+ return rows[0] ?? null;
49
+ }
50
+ for (const language of preferredLanguages) {
51
+ const match = rows.find((row) => row.language.trim().toLowerCase() === language);
52
+ if (match) {
53
+ return match;
54
+ }
55
+ }
56
+ return rows[0] ?? null;
57
+ },
34
58
  async createTemplate(db, data) {
35
59
  const [row] = await db.insert(contractTemplates).values(data).returning();
36
60
  return row ?? null;
@@ -1,6 +1,16 @@
1
1
  import { allocateContractNumber, renderTemplate, validateTemplateVariables } from "./service-shared.js";
2
2
  export { allocateContractNumber, renderTemplate, validateTemplateVariables };
3
3
  export declare const contractsService: {
4
+ generateContractDocument(db: import("drizzle-orm/postgres-js").PostgresJsDatabase, contractId: string, input: import("./validation.js").GenerateContractDocumentInput, runtime: import("./service-documents.js").ContractDocumentRuntimeOptions): Promise<{
5
+ status: "not_found" | "not_draft" | "render_unavailable" | "generator_failed";
6
+ } | ({
7
+ status: "generated";
8
+ } & import("./service-documents.js").GeneratedContractDocumentRecord)>;
9
+ regenerateContractDocument(db: import("drizzle-orm/postgres-js").PostgresJsDatabase, contractId: string, input: import("./validation.js").GenerateContractDocumentInput, runtime: import("./service-documents.js").ContractDocumentRuntimeOptions): Promise<{
10
+ status: "not_found" | "not_draft" | "render_unavailable" | "generator_failed";
11
+ } | ({
12
+ status: "generated";
13
+ } & import("./service-documents.js").GeneratedContractDocumentRecord)>;
4
14
  listContracts(db: import("drizzle-orm/postgres-js").PostgresJsDatabase, query: import("./service-shared.js").ContractListQuery): Promise<{
5
15
  data: {
6
16
  id: string;
@@ -1328,6 +1338,25 @@ export declare const contractsService: {
1328
1338
  createdAt: Date;
1329
1339
  updatedAt: Date;
1330
1340
  } | null>;
1341
+ getDefaultTemplate(db: import("drizzle-orm/postgres-js").PostgresJsDatabase, query: {
1342
+ scope: "customer" | "supplier" | "partner" | "channel" | "other";
1343
+ language?: string;
1344
+ fallbackLanguages?: string[];
1345
+ }): Promise<{
1346
+ id: string;
1347
+ name: string;
1348
+ slug: string;
1349
+ scope: "customer" | "partner" | "supplier" | "other" | "channel";
1350
+ language: string;
1351
+ description: string | null;
1352
+ bodyFormat: "markdown" | "html" | "lexical_json";
1353
+ body: string;
1354
+ variableSchema: unknown;
1355
+ currentVersionId: string | null;
1356
+ active: boolean;
1357
+ createdAt: Date;
1358
+ updatedAt: Date;
1359
+ } | null>;
1331
1360
  createTemplate(db: import("drizzle-orm/postgres-js").PostgresJsDatabase, data: import("./service-shared.js").CreateContractTemplateInput): Promise<{
1332
1361
  id: string;
1333
1362
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/contracts/service.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,yBAAyB,EAC1B,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,yBAAyB,EAAE,CAAA;AAE5E,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAI5B,CAAA"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/contracts/service.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,yBAAyB,EAC1B,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,yBAAyB,EAAE,CAAA;AAE5E,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAMwxC,CAAC;yBAAgC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CADt1C,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import { contractRecordsService } from "./service-contracts.js";
2
+ import { contractDocumentsService } from "./service-documents.js";
2
3
  import { contractSeriesService } from "./service-series.js";
3
4
  import { allocateContractNumber, renderTemplate, validateTemplateVariables, } from "./service-shared.js";
4
5
  import { contractTemplatesService } from "./service-templates.js";
@@ -7,4 +8,5 @@ export const contractsService = {
7
8
  ...contractTemplatesService,
8
9
  ...contractSeriesService,
9
10
  ...contractRecordsService,
11
+ ...contractDocumentsService,
10
12
  };
@@ -87,6 +87,17 @@ export declare const contractTemplateListQuerySchema: z.ZodObject<{
87
87
  active: z.ZodOptional<z.ZodCoercedBoolean<unknown>>;
88
88
  search: z.ZodOptional<z.ZodString>;
89
89
  }, z.core.$strip>;
90
+ export declare const contractTemplateDefaultQuerySchema: z.ZodObject<{
91
+ scope: z.ZodDefault<z.ZodEnum<{
92
+ customer: "customer";
93
+ partner: "partner";
94
+ supplier: "supplier";
95
+ other: "other";
96
+ channel: "channel";
97
+ }>>;
98
+ language: z.ZodOptional<z.ZodString>;
99
+ fallbackLanguages: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string[], string | undefined>>;
100
+ }, z.core.$strip>;
90
101
  export declare const insertContractTemplateVersionSchema: z.ZodObject<{
91
102
  bodyFormat: z.ZodDefault<z.ZodEnum<{
92
103
  markdown: "markdown";
@@ -235,6 +246,56 @@ export declare const renderTemplateInputSchema: z.ZodObject<{
235
246
  }>>;
236
247
  body: z.ZodOptional<z.ZodString>;
237
248
  }, z.core.$strip>;
249
+ export declare const publicRenderTemplatePreviewInputSchema: z.ZodObject<{
250
+ variables: z.ZodRecord<z.ZodString, z.ZodUnknown>;
251
+ }, z.core.$strip>;
252
+ export declare const generateContractDocumentInputSchema: z.ZodObject<{
253
+ kind: z.ZodDefault<z.ZodString>;
254
+ replaceExisting: z.ZodDefault<z.ZodBoolean>;
255
+ issueIfDraft: z.ZodDefault<z.ZodBoolean>;
256
+ }, z.core.$strip>;
257
+ export declare const generatedContractDocumentAttachmentSchema: z.ZodObject<{
258
+ id: z.ZodString;
259
+ contractId: z.ZodString;
260
+ kind: z.ZodString;
261
+ name: z.ZodString;
262
+ mimeType: z.ZodNullable<z.ZodString>;
263
+ fileSize: z.ZodNullable<z.ZodNumber>;
264
+ storageKey: z.ZodNullable<z.ZodString>;
265
+ checksum: z.ZodNullable<z.ZodString>;
266
+ metadata: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
267
+ createdAt: z.ZodString;
268
+ }, z.core.$strip>;
269
+ export declare const generatedContractDocumentResultSchema: z.ZodObject<{
270
+ contractId: z.ZodString;
271
+ contractStatus: z.ZodEnum<{
272
+ draft: "draft";
273
+ sent: "sent";
274
+ expired: "expired";
275
+ issued: "issued";
276
+ signed: "signed";
277
+ executed: "executed";
278
+ void: "void";
279
+ }>;
280
+ renderedBodyFormat: z.ZodEnum<{
281
+ markdown: "markdown";
282
+ html: "html";
283
+ lexical_json: "lexical_json";
284
+ }>;
285
+ renderedBody: z.ZodString;
286
+ attachment: z.ZodObject<{
287
+ id: z.ZodString;
288
+ contractId: z.ZodString;
289
+ kind: z.ZodString;
290
+ name: z.ZodString;
291
+ mimeType: z.ZodNullable<z.ZodString>;
292
+ fileSize: z.ZodNullable<z.ZodNumber>;
293
+ storageKey: z.ZodNullable<z.ZodString>;
294
+ checksum: z.ZodNullable<z.ZodString>;
295
+ metadata: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
296
+ createdAt: z.ZodString;
297
+ }, z.core.$strip>;
298
+ }, z.core.$strip>;
238
299
  export declare const insertContractSignatureSchema: z.ZodObject<{
239
300
  signerName: z.ZodString;
240
301
  signerEmail: z.ZodNullable<z.ZodOptional<z.ZodString>>;
@@ -271,4 +332,5 @@ export declare const updateContractAttachmentSchema: z.ZodObject<{
271
332
  checksum: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodString>>>;
272
333
  metadata: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>>;
273
334
  }, z.core.$strip>;
335
+ export type GenerateContractDocumentInput = z.infer<typeof generateContractDocumentInputSchema>;
274
336
  //# sourceMappingURL=validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/contracts/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,mBAAmB;;;;;;EAAkE,CAAA;AAElG,eAAO,MAAM,oBAAoB;;;;;;;;EAQ/B,CAAA;AAEF,eAAO,MAAM,6BAA6B;;;;;EAAwD,CAAA;AAElG,eAAO,MAAM,iCAAiC;;;;EAAyC,CAAA;AAEvF,eAAO,MAAM,wBAAwB;;;;EAA+C,CAAA;AAyBpF,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;iBAA6B,CAAA;AACtE,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;iBAAuC,CAAA;AAEhF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;iBAK1C,CAAA;AAIF,eAAO,MAAM,mCAAmC;;;;;;;;;;iBAM9C,CAAA;AAeF,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;iBAAiC,CAAA;AAC9E,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;iBAA2C,CAAA;AAsBxF,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAqB,CAAA;AACtD,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA+B,CAAA;AAEhE,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;iBASlC,CAAA;AAEF,eAAO,MAAM,yBAAyB;;;;;;;;iBAIpC,CAAA;AAkBF,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;iBAA8B,CAAA;AAcxE,eAAO,MAAM,8BAA8B;;;;;;;;iBAA+B,CAAA;AAC1E,eAAO,MAAM,8BAA8B;;;;;;;;iBAAyC,CAAA"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/contracts/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,mBAAmB;;;;;;EAAkE,CAAA;AAElG,eAAO,MAAM,oBAAoB;;;;;;;;EAQ/B,CAAA;AAEF,eAAO,MAAM,6BAA6B;;;;;EAAwD,CAAA;AAElG,eAAO,MAAM,iCAAiC;;;;EAAyC,CAAA;AAEvF,eAAO,MAAM,wBAAwB;;;;EAA+C,CAAA;AAyBpF,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;iBAA6B,CAAA;AACtE,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;iBAAuC,CAAA;AAEhF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;iBAK1C,CAAA;AAEF,eAAO,MAAM,kCAAkC;;;;;;;;;;iBAc7C,CAAA;AAIF,eAAO,MAAM,mCAAmC;;;;;;;;;;iBAM9C,CAAA;AAeF,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;iBAAiC,CAAA;AAC9E,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;iBAA2C,CAAA;AAsBxF,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAqB,CAAA;AACtD,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA+B,CAAA;AAEhE,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;iBASlC,CAAA;AAEF,eAAO,MAAM,yBAAyB;;;;;;;;iBAIpC,CAAA;AAEF,eAAO,MAAM,sCAAsC;;iBAEjD,CAAA;AAEF,eAAO,MAAM,mCAAmC;;;;iBAI9C,CAAA;AAEF,eAAO,MAAM,yCAAyC;;;;;;;;;;;iBAWpD,CAAA;AAEF,eAAO,MAAM,qCAAqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMhD,CAAA;AAkBF,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;iBAA8B,CAAA;AAcxE,eAAO,MAAM,8BAA8B;;;;;;;;iBAA+B,CAAA;AAC1E,eAAO,MAAM,8BAA8B;;;;;;;;iBAAyC,CAAA;AAEpF,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAA"}
@@ -40,6 +40,19 @@ export const contractTemplateListQuerySchema = paginationSchema.extend({
40
40
  active: z.coerce.boolean().optional(),
41
41
  search: z.string().optional(),
42
42
  });
43
+ export const contractTemplateDefaultQuerySchema = z.object({
44
+ scope: contractScopeSchema.default("customer"),
45
+ language: z.string().min(2).max(10).optional(),
46
+ fallbackLanguages: z
47
+ .string()
48
+ .optional()
49
+ .transform((value) => value
50
+ ? value
51
+ .split(",")
52
+ .map((item) => item.trim())
53
+ .filter(Boolean)
54
+ : []),
55
+ });
43
56
  // ---------- contract template versions ----------
44
57
  export const insertContractTemplateVersionSchema = z.object({
45
58
  bodyFormat: contractBodyFormatSchema.default("markdown"),
@@ -96,6 +109,33 @@ export const renderTemplateInputSchema = z.object({
96
109
  bodyFormat: contractBodyFormatSchema.optional(),
97
110
  body: z.string().optional(),
98
111
  });
112
+ export const publicRenderTemplatePreviewInputSchema = z.object({
113
+ variables: z.record(z.string(), z.unknown()),
114
+ });
115
+ export const generateContractDocumentInputSchema = z.object({
116
+ kind: z.string().min(1).max(50).default("document"),
117
+ replaceExisting: z.boolean().default(true),
118
+ issueIfDraft: z.boolean().default(true),
119
+ });
120
+ export const generatedContractDocumentAttachmentSchema = z.object({
121
+ id: z.string(),
122
+ contractId: z.string(),
123
+ kind: z.string(),
124
+ name: z.string(),
125
+ mimeType: z.string().nullable(),
126
+ fileSize: z.number().int().nullable(),
127
+ storageKey: z.string().nullable(),
128
+ checksum: z.string().nullable(),
129
+ metadata: z.record(z.string(), z.unknown()).nullable(),
130
+ createdAt: z.string(),
131
+ });
132
+ export const generatedContractDocumentResultSchema = z.object({
133
+ contractId: z.string(),
134
+ contractStatus: contractStatusSchema,
135
+ renderedBodyFormat: contractBodyFormatSchema,
136
+ renderedBody: z.string(),
137
+ attachment: generatedContractDocumentAttachmentSchema,
138
+ });
99
139
  // ---------- contract signatures ----------
100
140
  const contractSignatureCoreSchema = z.object({
101
141
  signerName: z.string().min(1).max(255),
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { Module } from "@voyantjs/core";
2
2
  import type { HonoModule } from "@voyantjs/hono/module";
3
+ import { type ContractsRouteOptions } from "./contracts/routes.js";
3
4
  export declare const legalLinkable: {
4
5
  policy: import("@voyantjs/core").LinkableDefinition;
5
6
  policyVersion: import("@voyantjs/core").LinkableDefinition;
@@ -8,7 +9,9 @@ export declare const legalLinkable: {
8
9
  contractTemplate: import("@voyantjs/core").LinkableDefinition;
9
10
  };
10
11
  export declare const legalModule: Module;
12
+ export declare function createLegalHonoModule(options?: ContractsRouteOptions): HonoModule;
11
13
  export declare const legalHonoModule: HonoModule;
12
14
  export * from "./contracts/index.js";
15
+ export type { ContractsRouteOptions } from "./contracts/routes.js";
13
16
  export * from "./policies/index.js";
14
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAOvD,eAAO,MAAM,aAAa;;;;;;CAGzB,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,MAGzB,CAAA;AAUD,eAAO,MAAM,eAAe,EAAE,UAI7B,CAAA;AAED,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAGvD,OAAO,EACL,KAAK,qBAAqB,EAG3B,MAAM,uBAAuB,CAAA;AAI9B,eAAO,MAAM,aAAa;;;;;;CAGzB,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,MAGzB,CAAA;AAED,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,qBAA0B,GAAG,UAAU,CAcrF;AAED,eAAO,MAAM,eAAe,EAAE,UAAoC,CAAA;AAElE,cAAc,sBAAsB,CAAA;AACpC,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAClE,cAAc,qBAAqB,CAAA"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Hono } from "hono";
2
2
  import { contractsLinkable } from "./contracts/index.js";
3
- import { contractsAdminRoutes, contractsPublicRoutes } from "./contracts/routes.js";
3
+ import { createContractsAdminRoutes, createContractsPublicRoutes, } from "./contracts/routes.js";
4
4
  import { policiesLinkable } from "./policies/index.js";
5
5
  import { policiesAdminRoutes, policiesPublicRoutes } from "./policies/routes.js";
6
6
  export const legalLinkable = {
@@ -11,16 +11,19 @@ export const legalModule = {
11
11
  name: "legal",
12
12
  linkable: legalLinkable,
13
13
  };
14
- const legalAdminRoutes = new Hono()
15
- .route("/contracts", contractsAdminRoutes)
16
- .route("/policies", policiesAdminRoutes);
17
- const legalPublicRoutes = new Hono()
18
- .route("/contracts", contractsPublicRoutes)
19
- .route("/policies", policiesPublicRoutes);
20
- export const legalHonoModule = {
21
- module: legalModule,
22
- adminRoutes: legalAdminRoutes,
23
- publicRoutes: legalPublicRoutes,
24
- };
14
+ export function createLegalHonoModule(options = {}) {
15
+ const legalAdminRoutes = new Hono()
16
+ .route("/contracts", createContractsAdminRoutes(options))
17
+ .route("/policies", policiesAdminRoutes);
18
+ const legalPublicRoutes = new Hono()
19
+ .route("/contracts", createContractsPublicRoutes())
20
+ .route("/policies", policiesPublicRoutes);
21
+ return {
22
+ module: legalModule,
23
+ adminRoutes: legalAdminRoutes,
24
+ publicRoutes: legalPublicRoutes,
25
+ };
26
+ }
27
+ export const legalHonoModule = createLegalHonoModule();
25
28
  export * from "./contracts/index.js";
26
29
  export * from "./policies/index.js";