@vantageos/convex-doc-forge 0.1.1 → 0.1.3

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/CHANGELOG.md CHANGED
@@ -2,6 +2,38 @@
2
2
 
3
3
  All notable changes to this package follow [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) + [SemVer](https://semver.org/spec/v2.0.0.html).
4
4
 
5
+ ## [0.1.3] - 2026-06-19
6
+
7
+ ### Fixed
8
+
9
+ - **GAP 1 (data)** `input_schema` changed from `v.any()` to `v.string()` in `schema.ts`, `mutations.ts` (arg + handler type), and `queries.ts` (returns validators for both `list_templates` and `get_template`). JSON Schemas containing `$schema`/`$ref`/`$defs` keys (which start with `$`, reserved by Convex) now round-trip correctly — callers `JSON.stringify()` before upsert, `JSON.parse()` after retrieval. No handler logic change; store-as-is.
10
+ - **GAP 2 (BLOCKER)** `render_now` no longer reads `process.env.CONVEX_DOC_FORGE_RENDERER_URL` / `CONVEX_DOC_FORGE_RENDERER_KEY`. Convex components cannot access the host deployment's env vars (`convex env set` has no `--component` flag). Config is now passed as args: `renderer_url: v.string()` + `renderer_key: v.string()`. The host app reads its own env and threads these values when calling `ctx.runAction(components.docForge.actions.render_now, { ..., renderer_url, renderer_key })`.
11
+
12
+ ### Tests
13
+
14
+ - `actions.test.ts`: removed `process.env.*RENDERER*` setup/teardown; all `renderNowHandler` calls now pass `renderer_url`/`renderer_key` as args; guard tests updated accordingly; added `$schema` round-trip test.
15
+ - `mutations.test.ts`: `baseArgs.input_schema` changed to `JSON.stringify(...)` throughout; added `$schema`/`$ref`/`$defs` round-trip test.
16
+
17
+ ### Notes
18
+
19
+ - tsc: 0 errors. V8-pure: zero `"use node"` or `node:*` in src/. `peerDependencies.convex` unchanged (`>=1.17.0`).
20
+ - Breaking change for callers of `render_now`: must now pass `renderer_url` + `renderer_key` as args. See README + `scripts/smoke-render.md` for updated call pattern.
21
+
22
+ ## [0.1.2] - 2026-06-19
23
+
24
+ ### Added
25
+
26
+ - `mutations.ts`: public `generate_upload_url` mutation — enables host apps / consumers to upload a template binary into the component storage namespace, then register it via `upsert_template`. Unblocks `render_now` E2E and template upload (Marie/Iris RH critical path).
27
+ - Takes no args, returns `v.string()` (signed upload URL).
28
+ - Pure addition, no breaking change, `peerDependencies.convex` unchanged (`>=1.17.0`).
29
+ - V8-pure: no `"use node"`, no `node:*` imports (component constraint).
30
+ - `scripts/smoke-render.md`: canonical, reusable fleet smoke harness documenting the full upload→upsert→render CLI sequence.
31
+
32
+ ### Notes
33
+
34
+ - Discovered via consumer-1 dogfood (Omega install on vibrant-ibex-858): `upsert_template` required `asset_storage_id: v.id("_storage")` but there was no public path for a consumer to obtain a storage ID in the component namespace.
35
+ - tsc: 0 errors. Test ratio: 31/31 PASS.
36
+
5
37
  ## [0.1.1] - 2026-06-19
6
38
 
7
39
  ### Fixed
package/README.md CHANGED
@@ -44,7 +44,19 @@ export default app;
44
44
 
45
45
  ---
46
46
 
47
- ## Required env vars (set in Convex dashboard)
47
+ ## Renderer config (passed as args by the host app)
48
+
49
+ `render_now` does **not** read env vars from the Convex dashboard — Convex components cannot access the host deployment's env vars (`convex env set` has no `--component` flag). The host app reads its own env and passes config as args on every call:
50
+
51
+ ```ts
52
+ const result = await ctx.runAction(components.docForge.actions.render_now, {
53
+ // ...
54
+ renderer_url: process.env.CONVEX_DOC_FORGE_RENDERER_URL!,
55
+ renderer_key: process.env.CONVEX_DOC_FORGE_RENDERER_KEY!,
56
+ });
57
+ ```
58
+
59
+ Set these in the **host** deployment's Convex dashboard (not inside the component):
48
60
 
49
61
  | Variable | Description |
50
62
  |---|---|
@@ -64,7 +76,7 @@ export default app;
64
76
  | `tenant_id` | string | Clerk org ID |
65
77
  | `template_type` | `"doc-binary"` | Always `doc-binary` (V1) |
66
78
  | `renderer_kind` | `"docxtpl" \| "python-pptx" \| "jinja2-html"` | Which renderer to use |
67
- | `input_schema` | object | JSON Schema for context validation |
79
+ | `input_schema` | string | JSON Schema serialized as a JSON string (`JSON.stringify(schema)`) — avoids Convex `$`-key rejection |
68
80
  | `asset_storage_id` | Id<"_storage"> | Convex file storage reference to the .docx/.pptx asset |
69
81
  | `output_formats` | string[] | e.g. `["docx", "pdf"]` |
70
82
  | `version` | string | SemVer |
@@ -115,13 +127,79 @@ docForge.mutations.queue_render({ template_id, context, output_format, createdBy
115
127
  docForge.actions.render_now({
116
128
  template_id, context, output_format,
117
129
  actor, // Clerk subject
118
- source? // "manual" | "workflow" | "agent" (default "manual")
130
+ source?, // "manual" | "workflow" | "agent" (default "manual")
131
+ renderer_url, // host app reads from its own env (e.g. process.env.CONVEX_DOC_FORGE_RENDERER_URL)
132
+ renderer_key, // host app reads from its own env (e.g. process.env.CONVEX_DOC_FORGE_RENDERER_KEY)
119
133
  })
120
134
  // → { output_url, render_job_id, duration_ms, pages? }
121
135
  ```
122
136
 
123
137
  ---
124
138
 
139
+ ## Asset ingestion
140
+
141
+ Before calling `upsert_template`, the host app must upload the `.docx`/`.pptx` binary into the component's isolated storage namespace and obtain a `storageId`. The three-step flow:
142
+
143
+ **Step 1 — get a signed upload URL** (from a host app action):
144
+
145
+ ```ts
146
+ // convex/myActions.ts
147
+ import { action } from "./_generated/server";
148
+ import { components } from "./_generated/api";
149
+
150
+ export const getDocForgeUploadUrl = action({
151
+ args: {},
152
+ handler: async (ctx) =>
153
+ await ctx.runMutation(components.docForge.mutations.generate_upload_url, {}),
154
+ });
155
+ ```
156
+
157
+ **Step 2 — POST the raw bytes to the signed URL**:
158
+
159
+ ```bash
160
+ curl -X POST "<uploadUrl>" \
161
+ -H "Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document" \
162
+ --data-binary @template.docx
163
+ # → { "storageId": "kg2abc..." }
164
+ ```
165
+
166
+ **Step 3 — register the asset as a template** and then render:
167
+
168
+ ```ts
169
+ const templateId = await ctx.runMutation(
170
+ components.docForge.mutations.upsert_template,
171
+ {
172
+ name: "proposition-audit",
173
+ team: "iris-rh",
174
+ tenant_id: "org_clerk_abc",
175
+ renderer_kind: "docxtpl",
176
+ // input_schema must be a JSON-stringified string — Convex rejects $-prefixed keys (e.g. $schema, $ref)
177
+ input_schema: JSON.stringify({ type: "object", properties: { client_name: { type: "string" } } }),
178
+ asset_storage_id: storageId, // from step 2
179
+ output_formats: ["pdf", "docx"],
180
+ version: "1.0.0",
181
+ createdBy: "clerk_user_id",
182
+ },
183
+ );
184
+
185
+ // Now render_now works end-to-end:
186
+ // renderer_url + renderer_key are read from the host app's env and passed as args
187
+ const result = await ctx.runAction(components.docForge.actions.render_now, {
188
+ template_id: templateId,
189
+ context: { client_name: "Iris RH" },
190
+ output_format: "pdf",
191
+ actor: "clerk_user_id",
192
+ source: "manual",
193
+ renderer_url: process.env.CONVEX_DOC_FORGE_RENDERER_URL!,
194
+ renderer_key: process.env.CONVEX_DOC_FORGE_RENDERER_KEY!,
195
+ });
196
+ // → { output_url, render_job_id, duration_ms }
197
+ ```
198
+
199
+ See `scripts/smoke-render.md` in this repo for the full copy-paste fleet smoke harness.
200
+
201
+ ---
202
+
125
203
  ## Renderer contract
126
204
 
127
205
  `render_now` calls the sidecar:
package/dist/actions.d.ts CHANGED
@@ -4,6 +4,8 @@ export declare function renderNowHandler(ctx: any, args: {
4
4
  output_format: string;
5
5
  actor: string;
6
6
  source?: "manual" | "workflow" | "agent";
7
+ renderer_url: string;
8
+ renderer_key: string;
7
9
  }): Promise<{
8
10
  output_url: string;
9
11
  render_job_id: string;
@@ -16,5 +18,7 @@ export declare const render_now: import("convex/server").RegisteredAction<"publi
16
18
  context: any;
17
19
  output_format: string;
18
20
  actor: string;
21
+ renderer_url: string;
22
+ renderer_key: string;
19
23
  }, any>;
20
24
  //# sourceMappingURL=actions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAiCA,wBAAsB,gBAAgB,CAEpC,GAAG,EAAE,GAAG,EACR,IAAI,EAAE;IACJ,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;CAC1C,GACA,OAAO,CAAC;IACT,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAoID;AAMD,eAAO,MAAM,UAAU;;;;;;OAsBrB,CAAC"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAiCA,wBAAsB,gBAAgB,CAEpC,GAAG,EAAE,GAAG,EACR,IAAI,EAAE;IACJ,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB,GACA,OAAO,CAAC;IACT,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAoID;AAMD,eAAO,MAAM,UAAU;;;;;;;;OAwBrB,CAAC"}
package/dist/actions.js CHANGED
@@ -18,12 +18,12 @@ const SIGNED_URL_TTL_MS = 7 * 24 * 60 * 60 * 1000;
18
18
  export async function renderNowHandler(
19
19
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
20
  ctx, args) {
21
- const rendererUrl = process.env.CONVEX_DOC_FORGE_RENDERER_URL;
22
- const rendererKey = process.env.CONVEX_DOC_FORGE_RENDERER_KEY;
21
+ const rendererUrl = args.renderer_url;
22
+ const rendererKey = args.renderer_key;
23
23
  if (!rendererUrl)
24
- throw new Error("CONVEX_DOC_FORGE_RENDERER_URL not set");
24
+ throw new Error("renderer_url arg is required");
25
25
  if (!rendererKey)
26
- throw new Error("CONVEX_DOC_FORGE_RENDERER_KEY not set");
26
+ throw new Error("renderer_key arg is required");
27
27
  // 1. Load template
28
28
  const template = await ctx.runQuery(internal.queries.get_template, {
29
29
  template_id: args.template_id,
@@ -149,6 +149,8 @@ export const render_now = action({
149
149
  output_format: v.string(),
150
150
  actor: v.string(),
151
151
  source: v.optional(v.union(v.literal("manual"), v.literal("workflow"), v.literal("agent"))),
152
+ renderer_url: v.string(),
153
+ renderer_key: v.string(),
152
154
  },
153
155
  returns: v.object({
154
156
  output_url: v.string(),
@@ -5,7 +5,7 @@ export declare function upsertTemplateHandler(ctx: AnyCtx, args: {
5
5
  team: string;
6
6
  tenant_id: string;
7
7
  renderer_kind: "docxtpl" | "python-pptx" | "jinja2-html";
8
- input_schema: unknown;
8
+ input_schema: string;
9
9
  asset_storage_id: Id<"_storage">;
10
10
  output_formats: string[];
11
11
  metadata?: Record<string, string>;
@@ -29,6 +29,7 @@ export declare function failRenderJobHandler(ctx: AnyCtx, args: {
29
29
  job_id: Id<"render_jobs">;
30
30
  error: string;
31
31
  }): Promise<null>;
32
+ export declare function generateUploadUrlHandler(ctx: AnyCtx): Promise<string>;
32
33
  export declare function writeAuditHandler(ctx: AnyCtx, args: {
33
34
  render_job_id: Id<"render_jobs">;
34
35
  tenant_id: string;
@@ -40,12 +41,13 @@ export declare function writeAuditHandler(ctx: AnyCtx, args: {
40
41
  actor: string;
41
42
  source: "manual" | "workflow" | "agent";
42
43
  }): Promise<Id<"render_audit">>;
44
+ export declare const generate_upload_url: import("convex/server").RegisteredMutation<"public", {}, Promise<string>>;
43
45
  export declare const upsert_template: import("convex/server").RegisteredMutation<"public", {
44
46
  name: string;
45
47
  team: string;
46
48
  tenant_id: string;
47
49
  renderer_kind: "docxtpl" | "python-pptx" | "jinja2-html";
48
- input_schema: unknown;
50
+ input_schema: string;
49
51
  asset_storage_id: Id<"_storage">;
50
52
  output_formats: string[];
51
53
  metadata?: Record<string, string>;
@@ -1 +1 @@
1
- {"version":3,"file":"mutations.d.ts","sourceRoot":"","sources":["../src/mutations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mutations.d.ts","sourceRoot":"","sources":["../src/mutations.ts"],"names":[],"mappings":"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"}
package/dist/mutations.js CHANGED
@@ -93,6 +93,9 @@ export async function failRenderJobHandler(ctx, args) {
93
93
  });
94
94
  return null;
95
95
  }
96
+ export async function generateUploadUrlHandler(ctx) {
97
+ return await ctx.storage.generateUploadUrl();
98
+ }
96
99
  export async function writeAuditHandler(ctx, args) {
97
100
  return await ctx.db.insert("render_audit", {
98
101
  ...args,
@@ -102,13 +105,18 @@ export async function writeAuditHandler(ctx, args) {
102
105
  // ---------------------------------------------------------------------------
103
106
  // Convex registrations
104
107
  // ---------------------------------------------------------------------------
108
+ export const generate_upload_url = mutation({
109
+ args: {},
110
+ returns: v.string(),
111
+ handler: generateUploadUrlHandler,
112
+ });
105
113
  export const upsert_template = mutation({
106
114
  args: {
107
115
  name: v.string(),
108
116
  team: v.string(),
109
117
  tenant_id: v.string(),
110
118
  renderer_kind: v.union(v.literal("docxtpl"), v.literal("python-pptx"), v.literal("jinja2-html")),
111
- input_schema: v.any(),
119
+ input_schema: v.string(),
112
120
  asset_storage_id: v.id("_storage"),
113
121
  output_formats: v.array(v.string()),
114
122
  metadata: v.optional(v.record(v.string(), v.string())),
package/dist/queries.js CHANGED
@@ -63,7 +63,7 @@ export const list_templates = query({
63
63
  tenant_id: v.string(),
64
64
  template_type: v.literal("doc-binary"),
65
65
  renderer_kind: v.union(v.literal("docxtpl"), v.literal("python-pptx"), v.literal("jinja2-html")),
66
- input_schema: v.any(),
66
+ input_schema: v.string(),
67
67
  asset_storage_id: v.id("_storage"),
68
68
  output_formats: v.array(v.string()),
69
69
  metadata: v.optional(v.record(v.string(), v.string())),
@@ -83,7 +83,7 @@ export const get_template = query({
83
83
  tenant_id: v.string(),
84
84
  template_type: v.literal("doc-binary"),
85
85
  renderer_kind: v.union(v.literal("docxtpl"), v.literal("python-pptx"), v.literal("jinja2-html")),
86
- input_schema: v.any(),
86
+ input_schema: v.string(),
87
87
  asset_storage_id: v.id("_storage"),
88
88
  output_formats: v.array(v.string()),
89
89
  metadata: v.optional(v.record(v.string(), v.string())),
package/dist/schema.d.ts CHANGED
@@ -14,7 +14,7 @@ declare const _default: import("convex/server").SchemaDefinition<{
14
14
  tenant_id: string;
15
15
  template_type: "doc-binary";
16
16
  renderer_kind: "docxtpl" | "python-pptx" | "jinja2-html";
17
- input_schema: any;
17
+ input_schema: string;
18
18
  asset_storage_id: import("convex/values").GenericId<"_storage">;
19
19
  output_formats: string[];
20
20
  version: string;
@@ -26,14 +26,14 @@ declare const _default: import("convex/server").SchemaDefinition<{
26
26
  tenant_id: import("convex/values").VString<string, "required">;
27
27
  template_type: import("convex/values").VLiteral<"doc-binary", "required">;
28
28
  renderer_kind: import("convex/values").VUnion<"docxtpl" | "python-pptx" | "jinja2-html", [import("convex/values").VLiteral<"docxtpl", "required">, import("convex/values").VLiteral<"python-pptx", "required">, import("convex/values").VLiteral<"jinja2-html", "required">], "required", never>;
29
- input_schema: import("convex/values").VAny<any, "required", string>;
29
+ input_schema: import("convex/values").VString<string, "required">;
30
30
  asset_storage_id: import("convex/values").VId<import("convex/values").GenericId<"_storage">, "required">;
31
31
  output_formats: import("convex/values").VArray<string[], import("convex/values").VString<string, "required">, "required">;
32
32
  metadata: import("convex/values").VRecord<Record<string, string> | undefined, import("convex/values").VString<string, "required">, import("convex/values").VString<string, "required">, "optional", string>;
33
33
  version: import("convex/values").VString<string, "required">;
34
34
  createdAt: import("convex/values").VFloat64<number, "required">;
35
35
  updatedAt: import("convex/values").VFloat64<number, "required">;
36
- }, "required", "name" | "team" | "tenant_id" | "template_type" | "renderer_kind" | "input_schema" | "asset_storage_id" | "output_formats" | "metadata" | "version" | "createdAt" | "updatedAt" | `input_schema.${string}` | `metadata.${string}`>, {
36
+ }, "required", "name" | "team" | "tenant_id" | "template_type" | "renderer_kind" | "input_schema" | "asset_storage_id" | "output_formats" | "metadata" | "version" | "createdAt" | "updatedAt" | `metadata.${string}`>, {
37
37
  by_tenant: ["tenant_id", "_creationTime"];
38
38
  by_tenant_team: ["tenant_id", "team", "_creationTime"];
39
39
  by_tenant_type: ["tenant_id", "template_type", "_creationTime"];
package/dist/schema.js CHANGED
@@ -15,7 +15,7 @@ export default defineSchema({
15
15
  tenant_id: v.string(), // Clerk org ID
16
16
  template_type: v.literal("doc-binary"),
17
17
  renderer_kind: v.union(v.literal("docxtpl"), v.literal("python-pptx"), v.literal("jinja2-html")),
18
- input_schema: v.any(), // JSON Schema object validated at runtime
18
+ input_schema: v.string(), // JSON Schema serialized as a JSON string (avoids $-key rejection)
19
19
  asset_storage_id: v.id("_storage"),
20
20
  output_formats: v.array(v.string()),
21
21
  metadata: v.optional(v.record(v.string(), v.string())),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vantageos/convex-doc-forge",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Convex component — data layer for VantageDocForge (templates, render jobs, audit)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",