{ "cells": [ { "cell_type": "code", "execution_count": 8, "id": "76919cba", "metadata": {}, "outputs": [], "source": [ "import { load } from \"jsr:@std/dotenv\";\n", "\n", "const env = await load({\n", " export: true,\n", "});" ] }, { "cell_type": "code", "execution_count": 1, "id": "20231839", "metadata": {}, "outputs": [], "source": [ "type ListTemplatesParams = {\n", " id?: string;\n", " versionId?: string;\n", " category?: string;\n", " origin?: 0 | 1;\n", " includeVersions?: boolean;\n", " search?: string;\n", " limit?: number;\n", " cursor?: string;\n", "};\n", "\n", "class CarboneClient {\n", " listTemplates(params?: ListTemplatesParams) {}\n", " listCategories() {}\n", " listTags() {}\n", " uploadTemplate(input: {\n", " file?: Buffer;\n", " filename?: string;\n", " template?: string; // base64\n", " versioning?: boolean;\n", " id?: string;\n", " name?: string;\n", " comment?: string;\n", " tags?: string[];\n", " category?: string;\n", " sample?: any[];\n", " deployedAt?: number;\n", " expireAt?: number;\n", " }) {}\n", " patchTemplate(id: string, body: {\n", " name?: string;\n", " comment?: string;\n", " tags?: string[];\n", " category?: string;\n", " deployedAt?: number;\n", " expireAt?: number;\n", " }) {}\n", " deleteTemplate(id: string) {}\n", " downloadTemplate(id: string) {}\n", " render(templateId: string, body: any, opts?: { download?: boolean }) {}\n", " renderFromTemplate(body: any, opts?: { download?: boolean }) {}\n", " downloadRender(renderId: string) {}\n", "}" ] }, { "cell_type": "code", "execution_count": 2, "id": "9950c1f7", "metadata": {}, "outputs": [], "source": [ "const CARBONE_VERSION = \"5\";\n", "\n", "type CarboneSuccess = {\n", " success: true;\n", " data: T;\n", " hasMore?: boolean;\n", " nextCursor?: string;\n", "};\n", "\n", "type CarboneError = {\n", " success: false;\n", " error: string;\n", "};\n", "\n", "type CarboneResponse = CarboneSuccess | CarboneError;\n", "\n", "export class CarboneClient {\n", " constructor(\n", " private baseUrl: string,\n", " private apiToken: string\n", " ) {}\n", "\n", " private buildHeaders(extra?: Record) {\n", " return {\n", " Authorization: `Bearer ${this.apiToken}`,\n", " \"carbone-version\": CARBONE_VERSION,\n", " ...extra,\n", " };\n", " }\n", "\n", " private async parseResponse(res: Response): Promise {\n", " const contentType = res.headers.get(\"content-type\") || \"\";\n", "\n", " if (!res.ok) {\n", " let message = `Carbone request failed: ${res.status}`;\n", " try {\n", " const err = await res.json();\n", " message = err?.error || err?.message || message;\n", " } catch {}\n", " throw new Error(message);\n", " }\n", "\n", " if (contentType.includes(\"application/json\")) {\n", " return res.json() as Promise;\n", " }\n", "\n", " return res as unknown as T;\n", " }\n", "\n", " private toQuery(params?: Record) {\n", " const qs = new URLSearchParams();\n", " if (!params) return \"\";\n", " for (const [key, value] of Object.entries(params)) {\n", " if (value === undefined || value === null) continue;\n", " qs.set(key, String(value));\n", " }\n", " const s = qs.toString();\n", " return s ? `?${s}` : \"\";\n", " }\n", "\n", " async listTemplates(params?: {\n", " id?: string;\n", " versionId?: string;\n", " category?: string;\n", " origin?: 0 | 1;\n", " includeVersions?: boolean;\n", " search?: string;\n", " limit?: number;\n", " cursor?: string;\n", " }) {\n", " const res = await fetch(\n", " `${this.baseUrl}/templates${this.toQuery(params)}`,\n", " {\n", " method: \"GET\",\n", " headers: this.buildHeaders(),\n", " }\n", " );\n", " return this.parseResponse<\n", " CarboneResponse<\n", " Array<{\n", " id: string;\n", " versionId: string;\n", " deployedAt: number;\n", " createdAt: number;\n", " expireAt?: number;\n", " size: number;\n", " type: string;\n", " name?: string;\n", " category?: string;\n", " comment?: string;\n", " tags?: string[];\n", " origin?: number;\n", " }>\n", " >\n", " >(res);\n", " }\n", "\n", " async listCategories() {\n", " const res = await fetch(`${this.baseUrl}/templates/categories`, {\n", " method: \"GET\",\n", " headers: this.buildHeaders(),\n", " });\n", " return this.parseResponse>>(res);\n", " }\n", "\n", " async listTags() {\n", " const res = await fetch(`${this.baseUrl}/templates/tags`, {\n", " method: \"GET\",\n", " headers: this.buildHeaders(),\n", " });\n", " return this.parseResponse>>(res);\n", " }\n", "\n", " async uploadTemplateJson(body: {\n", " template: string;\n", " versioning?: boolean;\n", " id?: string;\n", " name?: string;\n", " comment?: string;\n", " tags?: string[];\n", " category?: string;\n", " sample?: any[];\n", " deployedAt?: number;\n", " expireAt?: number;\n", " }) {\n", " const res = await fetch(`${this.baseUrl}/template`, {\n", " method: \"POST\",\n", " headers: this.buildHeaders({\n", " \"Content-Type\": \"application/json\",\n", " }),\n", " body: JSON.stringify(body),\n", " });\n", " return this.parseResponse<\n", " CarboneResponse<{\n", " id?: string;\n", " versionId?: string;\n", " templateId?: string;\n", " type?: string;\n", " size?: number;\n", " createdAt?: number;\n", " }>\n", " >(res);\n", " }\n", "\n", " async uploadTemplateFile(input: {\n", " file: Blob;\n", " filename: string;\n", " versioning?: boolean;\n", " id?: string;\n", " name?: string;\n", " comment?: string;\n", " tags?: string[];\n", " category?: string;\n", " sample?: any[];\n", " deployedAt?: number;\n", " expireAt?: number;\n", " }) {\n", " const form = new FormData();\n", "\n", " if (input.versioning !== undefined) {\n", " form.append(\"versioning\", String(input.versioning));\n", " }\n", " if (input.id) form.append(\"id\", input.id);\n", " if (input.name) form.append(\"name\", input.name);\n", " if (input.comment) form.append(\"comment\", input.comment);\n", " if (input.category) form.append(\"category\", input.category);\n", " if (input.tags) {\n", " for (const tag of input.tags) form.append(\"tags[]\", tag);\n", " }\n", " if (input.sample) form.append(\"sample\", JSON.stringify(input.sample));\n", " if (input.deployedAt !== undefined) {\n", " form.append(\"deployedAt\", String(input.deployedAt));\n", " }\n", " if (input.expireAt !== undefined) {\n", " form.append(\"expireAt\", String(input.expireAt));\n", " }\n", "\n", " // template should be appended last\n", " form.append(\"template\", input.file, input.filename);\n", "\n", " const res = await fetch(`${this.baseUrl}/template`, {\n", " method: \"POST\",\n", " headers: this.buildHeaders(),\n", " body: form,\n", " });\n", " return this.parseResponse<\n", " CarboneResponse<{\n", " id?: string;\n", " versionId?: string;\n", " templateId?: string;\n", " type?: string;\n", " size?: number;\n", " createdAt?: number;\n", " }>\n", " >(res);\n", " }\n", "\n", " async patchTemplate(\n", " id: string,\n", " body: {\n", " name?: string;\n", " comment?: string;\n", " tags?: string[];\n", " category?: string;\n", " deployedAt?: number;\n", " expireAt?: number;\n", " }\n", " ) {\n", " const res = await fetch(`${this.baseUrl}/template/${id}`, {\n", " method: \"PATCH\",\n", " headers: this.buildHeaders({\n", " \"Content-Type\": \"application/json\",\n", " }),\n", " body: JSON.stringify(body),\n", " });\n", " return this.parseResponse>(res);\n", " }\n", "\n", " async deleteTemplate(id: string) {\n", " const res = await fetch(`${this.baseUrl}/template/${id}`, {\n", " method: \"DELETE\",\n", " headers: this.buildHeaders(),\n", " });\n", " return this.parseResponse>(res);\n", " }\n", "\n", " async downloadTemplate(id: string) {\n", " const res = await fetch(`${this.baseUrl}/template/${id}`, {\n", " method: \"GET\",\n", " headers: this.buildHeaders(),\n", " });\n", "\n", " if (!res.ok) {\n", " const err = await res.json().catch(() => null);\n", " throw new Error(err?.error || `Failed to download template: ${res.status}`);\n", " }\n", "\n", " return {\n", " buffer: Buffer.from(await res.arrayBuffer()),\n", " contentType: res.headers.get(\"content-type\"),\n", " contentDisposition: res.headers.get(\"content-disposition\"),\n", " };\n", " }\n", "\n", " async render(\n", " templateIdOrVersionId: string,\n", " body: Record,\n", " opts?: { download?: boolean }\n", " ) {\n", " const query = opts?.download ? \"?download=true\" : \"\";\n", " const res = await fetch(\n", " `${this.baseUrl}/render/${templateIdOrVersionId}${query}`,\n", " {\n", " method: \"POST\",\n", " headers: this.buildHeaders({\n", " \"Content-Type\": \"application/json\",\n", " }),\n", " body: JSON.stringify(body),\n", " }\n", " );\n", "\n", " if (opts?.download) {\n", " if (!res.ok) {\n", " const err = await res.json().catch(() => null);\n", " throw new Error(err?.error || `Render failed: ${res.status}`);\n", " }\n", " return {\n", " buffer: Buffer.from(await res.arrayBuffer()),\n", " contentType: res.headers.get(\"content-type\"),\n", " contentDisposition: res.headers.get(\"content-disposition\"),\n", " };\n", " }\n", "\n", " return this.parseResponse>(res);\n", " }\n", "\n", " async renderFromTemplate(\n", " body: Record,\n", " opts?: { download?: boolean }\n", " ) {\n", " const query = opts?.download ? \"?download=true\" : \"\";\n", " const res = await fetch(`${this.baseUrl}/render/template${query}`, {\n", " method: \"POST\",\n", " headers: this.buildHeaders({\n", " \"Content-Type\": \"application/json\",\n", " }),\n", " body: JSON.stringify(body),\n", " });\n", "\n", " if (opts?.download) {\n", " if (!res.ok) {\n", " const err = await res.json().catch(() => null);\n", " throw new Error(err?.error || `Render failed: ${res.status}`);\n", " }\n", " return {\n", " buffer: Buffer.from(await res.arrayBuffer()),\n", " contentType: res.headers.get(\"content-type\"),\n", " contentDisposition: res.headers.get(\"content-disposition\"),\n", " };\n", " }\n", "\n", " return this.parseResponse>(res);\n", " }\n", "\n", " async downloadRender(renderId: string) {\n", " const res = await fetch(`${this.baseUrl}/render/${renderId}`, {\n", " method: \"GET\",\n", " });\n", "\n", " if (!res.ok) {\n", " const err = await res.json().catch(() => null);\n", " throw new Error(err?.error || `Failed to download render: ${res.status}`);\n", " }\n", "\n", " return {\n", " buffer: Buffer.from(await res.arrayBuffer()),\n", " contentType: res.headers.get(\"content-type\"),\n", " contentDisposition: res.headers.get(\"content-disposition\"),\n", " };\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": 17, "id": "95b24436", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " success: true,\n", " data: [\n", " {\n", " versionId: \"1990f3351b4313779ae3ef3caeaea14dea51c3a98a691fb90a347dec53f875e6\",\n", " id: \"1373945625988937236\",\n", " deployedAt: 1773246290,\n", " createdAt: 1773246316,\n", " expireAt: 0,\n", " size: 29008,\n", " type: \"docx\",\n", " name: \"Anexo 1\",\n", " category: \"Planes de estudio\",\n", " comment: \"Plantilla de anexo 1 SEP RVOE Acuerdo 17-11-17\",\n", " tags: [],\n", " origin: 1\n", " },\n", " {\n", " versionId: \"caee5a7804647382f6df62ef92cc8f04c822b6a297479c5068e22d08def685d7\",\n", " id: \"1373945108764607184\",\n", " deployedAt: 1773246225,\n", " createdAt: 1773246251,\n", " expireAt: 0,\n", " size: 29642,\n", " type: \"xlsx\",\n", " name: \"Anexo 2\",\n", " category: \"\",\n", " comment: \"\",\n", " tags: [],\n", " origin: 1\n", " },\n", " {\n", " versionId: \"b0ab3c6fe90c73151fcae64d8509e406803381f3966aa88d30d8d30e2b1ffe8f\",\n", " id: \"1373944894291796699\",\n", " deployedAt: 1773246204,\n", " createdAt: 1773246230,\n", " expireAt: 0,\n", " size: 23806,\n", " type: \"docx\",\n", " name: \"Anexo 3\",\n", " category: \"\",\n", " comment: \"\",\n", " tags: [],\n", " origin: 1\n", " }\n", " ],\n", " hasMore: false\n", "}\n", "{ success: true, data: [ { name: \"Planes de estudio\" } ] }\n", "{ success: true, data: [] }\n" ] } ], "source": [ "const carbone = new CarboneClient(\n", " \"https://carbone.lci.ulsa.mx\",\n", " Deno.env.get(\"CARBONE_API_TOKEN\")!\n", ");\n", "\n", "const templates = await carbone.listTemplates({ limit: 20 });\n", "console.log(templates);\n", "\n", "const categories = await carbone.listCategories();\n", "console.log(categories);\n", "\n", "const tags = await carbone.listTags();\n", "console.log(tags);" ] }, { "cell_type": "code", "execution_count": null, "id": "8196fac4", "metadata": {}, "outputs": [], "source": [ "const templateID = \"1373945625988937236\";\n" ] }, { "cell_type": "code", "execution_count": 16, "id": "caf8bc20", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{\n", " success: \u001b[33mtrue\u001b[39m,\n", " data: {\n", " category: \u001b[32m\"Planes de estudio\"\u001b[39m,\n", " comment: \u001b[32m\"Plantilla de anexo 1 SEP RVOE Acuerdo 17-11-17\"\u001b[39m,\n", " versionId: \u001b[32m\"1990f3351b4313779ae3ef3caeaea14dea51c3a98a691fb90a347dec53f875e6\"\u001b[39m\n", " }\n", "}" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "await carbone.patchTemplate(\"1373945625988937236\", {\n", " category: \"Planes de estudio\",\n", " comment: \"Plantilla de anexo 1 SEP RVOE Acuerdo 17-11-17\",\n", "});\n" ] }, { "cell_type": "code", "execution_count": null, "id": "929883b9", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Deno", "language": "typescript", "name": "deno" }, "language_info": { "codemirror_mode": "typescript", "file_extension": ".ts", "mimetype": "text/x.typescript", "name": "typescript", "nbconvert_exporter": "script", "pygments_lexer": "typescript", "version": "5.9.2" } }, "nbformat": 4, "nbformat_minor": 5 }