@meistrari/tela-sdk-js 1.0.1 → 2.0.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/dist/index.cjs CHANGED
@@ -1,7 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  const changeCase = require('change-case');
4
- const micromatch = require('micromatch');
4
+ const minimatch = require('minimatch');
5
+ const z = require('zod');
5
6
 
6
7
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
7
8
 
@@ -18,14 +19,14 @@ function _interopNamespaceCompat(e) {
18
19
  }
19
20
 
20
21
  const changeCase__namespace = /*#__PURE__*/_interopNamespaceCompat(changeCase);
21
- const micromatch__default = /*#__PURE__*/_interopDefaultCompat(micromatch);
22
+ const z__default = /*#__PURE__*/_interopDefaultCompat(z);
22
23
 
23
- const version = "1.0.1";
24
+ const version = "2.0.0";
24
25
 
25
- var __defProp$5 = Object.defineProperty;
26
- var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
27
- var __publicField$5 = (obj, key, value) => {
28
- __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
26
+ var __defProp$7 = Object.defineProperty;
27
+ var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
28
+ var __publicField$7 = (obj, key, value) => {
29
+ __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
29
30
  return value;
30
31
  };
31
32
  class TelaError extends Error {
@@ -51,16 +52,35 @@ class InvalidFileURL extends TelaError {
51
52
  }
52
53
  }
53
54
  class FileUploadError extends TelaError {
55
+ constructor(message, statusCode) {
56
+ super(`Failed to upload file: ${message} (Status code: ${statusCode})`);
57
+ __publicField$7(this, "statusCode");
58
+ this.statusCode = statusCode;
59
+ }
60
+ }
61
+ class ExecutionNotStartedError extends TelaError {
62
+ constructor() {
63
+ super("Execution has not started yet");
64
+ }
65
+ }
66
+ class InvalidExecutionModeError extends TelaError {
54
67
  constructor(message) {
55
- super(`Failed to upload file: ${message}`);
68
+ super(message);
69
+ }
70
+ }
71
+ class ExecutionFailedError extends TelaError {
72
+ constructor(rawOutput) {
73
+ super(`Execution failed: ${JSON.stringify(rawOutput)}`);
74
+ __publicField$7(this, "rawOutput");
75
+ this.rawOutput = rawOutput;
56
76
  }
57
77
  }
58
78
  class APIError extends TelaError {
59
79
  constructor(statusCode, error, _message) {
60
80
  const message = error?.message ? typeof error.message === "string" ? error.message : JSON.stringify(error.message) : error ? JSON.stringify(error) : _message;
61
81
  super(message);
62
- __publicField$5(this, "statusCode");
63
- __publicField$5(this, "error");
82
+ __publicField$7(this, "statusCode");
83
+ __publicField$7(this, "error");
64
84
  this.statusCode = statusCode;
65
85
  this.error = error;
66
86
  }
@@ -102,7 +122,7 @@ class APIError extends TelaError {
102
122
  class UserAbortError extends APIError {
103
123
  constructor({ message } = {}) {
104
124
  super(void 0, void 0, message || "User aborted.");
105
- __publicField$5(this, "statusCode");
125
+ __publicField$7(this, "statusCode");
106
126
  }
107
127
  }
108
128
  class ConnectionError extends APIError {
@@ -111,7 +131,7 @@ class ConnectionError extends APIError {
111
131
  cause
112
132
  }) {
113
133
  super(void 0, void 0, message || "Connection error.");
114
- __publicField$5(this, "statusCode");
134
+ __publicField$7(this, "statusCode");
115
135
  if (cause)
116
136
  this.cause = cause;
117
137
  }
@@ -121,57 +141,57 @@ class ConnectionTimeout extends APIError {
121
141
  message
122
142
  } = {}) {
123
143
  super(void 0, void 0, message || "Request timed out.");
124
- __publicField$5(this, "statusCode");
144
+ __publicField$7(this, "statusCode");
125
145
  }
126
146
  }
127
147
  class BadRequestError extends APIError {
128
148
  constructor() {
129
149
  super(...arguments);
130
- __publicField$5(this, "statusCode", 400);
150
+ __publicField$7(this, "statusCode", 400);
131
151
  }
132
152
  // todo: handle validation errors from zod/typebox
133
153
  }
134
154
  class AuthenticationError extends APIError {
135
155
  constructor() {
136
156
  super(...arguments);
137
- __publicField$5(this, "statusCode", 401);
157
+ __publicField$7(this, "statusCode", 401);
138
158
  }
139
159
  }
140
160
  class AuthorizationError extends APIError {
141
161
  constructor() {
142
162
  super(...arguments);
143
- __publicField$5(this, "statusCode", 403);
163
+ __publicField$7(this, "statusCode", 403);
144
164
  }
145
165
  }
146
166
  class NotFoundError extends APIError {
147
167
  constructor() {
148
168
  super(...arguments);
149
- __publicField$5(this, "statusCode", 404);
169
+ __publicField$7(this, "statusCode", 404);
150
170
  }
151
171
  }
152
172
  class ConflictError extends APIError {
153
173
  constructor() {
154
174
  super(...arguments);
155
- __publicField$5(this, "statusCode", 409);
175
+ __publicField$7(this, "statusCode", 409);
156
176
  }
157
177
  }
158
178
  class UnprocessableEntityError extends APIError {
159
179
  constructor() {
160
180
  super(...arguments);
161
181
  // todo: check if tela returns 400 or 422 for zod errors
162
- __publicField$5(this, "statusCode", 422);
182
+ __publicField$7(this, "statusCode", 422);
163
183
  }
164
184
  }
165
185
  class RateLimitError extends APIError {
166
186
  constructor() {
167
187
  super(...arguments);
168
- __publicField$5(this, "statusCode", 429);
188
+ __publicField$7(this, "statusCode", 429);
169
189
  }
170
190
  }
171
191
  class InternalServerError extends APIError {
172
192
  constructor() {
173
193
  super(...arguments);
174
- __publicField$5(this, "statusCode", 500);
194
+ __publicField$7(this, "statusCode", 500);
175
195
  }
176
196
  }
177
197
  function toError(err) {
@@ -210,8 +230,12 @@ const DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS = [
210
230
 
211
231
  function isExcluded(path, exclusions) {
212
232
  return exclusions.some((pattern) => {
213
- const isMatch = micromatch__default.isMatch(path, pattern);
214
- return isMatch;
233
+ return minimatch.minimatch(path, pattern, {
234
+ dot: true,
235
+ nobrace: false,
236
+ noglobstar: false,
237
+ matchBase: false
238
+ });
215
239
  });
216
240
  }
217
241
  function transformObjectFromCamelCaseToSnakeCase(obj, exclusions = []) {
@@ -279,10 +303,10 @@ function transformObjectFromSnakeCaseToCamelCase(obj, exclusions = []) {
279
303
  return result;
280
304
  }
281
305
 
282
- var __defProp$4 = Object.defineProperty;
283
- var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
284
- var __publicField$4 = (obj, key, value) => {
285
- __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
306
+ var __defProp$6 = Object.defineProperty;
307
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
308
+ var __publicField$6 = (obj, key, value) => {
309
+ __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
286
310
  return value;
287
311
  };
288
312
  class Stream {
@@ -297,7 +321,7 @@ class Stream {
297
321
  /**
298
322
  * The AbortController associated with this stream.
299
323
  */
300
- __publicField$4(this, "controller");
324
+ __publicField$6(this, "controller");
301
325
  this.controller = controller;
302
326
  }
303
327
  /**
@@ -338,6 +362,10 @@ class Stream {
338
362
  if (data && data.error) {
339
363
  throw new APIError(void 0, data.error, void 0);
340
364
  }
365
+ data = data.message.content;
366
+ if (!data) {
367
+ continue;
368
+ }
341
369
  yield data;
342
370
  } else {
343
371
  let data;
@@ -351,6 +379,10 @@ class Stream {
351
379
  if (sse.event === "error") {
352
380
  throw new APIError(void 0, data.error, data.message);
353
381
  }
382
+ data = data.message.content;
383
+ if (!data) {
384
+ continue;
385
+ }
354
386
  yield { event: sse.event, data };
355
387
  }
356
388
  }
@@ -540,9 +572,9 @@ function findDoubleNewlineIndex(buffer) {
540
572
  }
541
573
  class SSEDecoder {
542
574
  constructor() {
543
- __publicField$4(this, "data");
544
- __publicField$4(this, "event");
545
- __publicField$4(this, "chunks");
575
+ __publicField$6(this, "data");
576
+ __publicField$6(this, "event");
577
+ __publicField$6(this, "chunks");
546
578
  this.event = null;
547
579
  this.data = [];
548
580
  this.chunks = [];
@@ -583,9 +615,9 @@ class SSEDecoder {
583
615
  const _LineDecoder = class _LineDecoder {
584
616
  // TextDecoder found in browsers; not typed to avoid pulling in either "dom" or "node" types.
585
617
  constructor() {
586
- __publicField$4(this, "buffer");
587
- __publicField$4(this, "trailingCR");
588
- __publicField$4(this, "textDecoder");
618
+ __publicField$6(this, "buffer");
619
+ __publicField$6(this, "trailingCR");
620
+ __publicField$6(this, "textDecoder");
589
621
  this.buffer = [];
590
622
  this.trailingCR = false;
591
623
  }
@@ -660,8 +692,8 @@ const _LineDecoder = class _LineDecoder {
660
692
  }
661
693
  };
662
694
  // prettier-ignore
663
- __publicField$4(_LineDecoder, "NEWLINE_CHARS", /* @__PURE__ */ new Set(["\n", "\r"]));
664
- __publicField$4(_LineDecoder, "NEWLINE_REGEXP", /\r\n|[\n\r]/g);
695
+ __publicField$6(_LineDecoder, "NEWLINE_CHARS", /* @__PURE__ */ new Set(["\n", "\r"]));
696
+ __publicField$6(_LineDecoder, "NEWLINE_REGEXP", /\r\n|[\n\r]/g);
665
697
  let LineDecoder = _LineDecoder;
666
698
  function partition(str, delimiter) {
667
699
  const index = str.indexOf(delimiter);
@@ -698,10 +730,10 @@ function readableStreamAsyncIterable(stream) {
698
730
  };
699
731
  }
700
732
 
701
- var __defProp$3 = Object.defineProperty;
702
- var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
703
- var __publicField$3 = (obj, key, value) => {
704
- __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
733
+ var __defProp$5 = Object.defineProperty;
734
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
735
+ var __publicField$5 = (obj, key, value) => {
736
+ __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
705
737
  return value;
706
738
  };
707
739
  async function defaultParseResponse(props) {
@@ -726,10 +758,10 @@ async function defaultParseResponse(props) {
726
758
  }
727
759
  class BaseClient {
728
760
  constructor({ baseURL, maxRetries = 5, timeout = 0 }) {
729
- __publicField$3(this, "baseURL");
730
- __publicField$3(this, "maxRetries");
731
- __publicField$3(this, "timeout");
732
- __publicField$3(this, "fetch");
761
+ __publicField$5(this, "baseURL");
762
+ __publicField$5(this, "maxRetries");
763
+ __publicField$5(this, "timeout");
764
+ __publicField$5(this, "fetch");
733
765
  this.baseURL = baseURL;
734
766
  this.maxRetries = validateMaxRetries(maxRetries);
735
767
  this.timeout = validateTimeout(timeout);
@@ -751,9 +783,6 @@ class BaseClient {
751
783
  getUserAgent() {
752
784
  return `tela-sdk-node/${version}`;
753
785
  }
754
- getAuthHeaders() {
755
- return {};
756
- }
757
786
  get(path, opts) {
758
787
  return this.methodRequest("GET", path, opts);
759
788
  }
@@ -1006,12 +1035,15 @@ async function getStreamSize(stream) {
1006
1035
  return size;
1007
1036
  }
1008
1037
 
1009
- var __defProp$2 = Object.defineProperty;
1010
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1011
- var __publicField$2 = (obj, key, value) => {
1012
- __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
1038
+ var __defProp$4 = Object.defineProperty;
1039
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1040
+ var __publicField$4 = (obj, key, value) => {
1041
+ __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
1013
1042
  return value;
1014
1043
  };
1044
+ function TelaFileSchema() {
1045
+ return z__default.custom((value) => value instanceof TelaFile, { message: "Value must be an instance of TelaFile" }).meta({ isTelaFile: true });
1046
+ }
1015
1047
  class TelaFile {
1016
1048
  /**
1017
1049
  * Creates an instance of `TelaFile`.
@@ -1021,14 +1053,31 @@ class TelaFile {
1021
1053
  * @throws {InvalidFileURL} If the provided URL is not valid.
1022
1054
  * @throws {EmptyFileError} If the provided file is empty.
1023
1055
  */
1024
- constructor(file, options) {
1025
- __publicField$2(this, "_file");
1026
- __publicField$2(this, "_options");
1027
- __publicField$2(this, "_size", null);
1056
+ constructor(file, options = {}) {
1057
+ __publicField$4(this, "_file");
1058
+ __publicField$4(this, "_options");
1059
+ __publicField$4(this, "_size", null);
1060
+ __publicField$4(this, "_mimeType");
1061
+ __publicField$4(this, "_name");
1028
1062
  this._file = file;
1063
+ if (file instanceof File || file instanceof Blob) {
1064
+ this._size = file.size;
1065
+ }
1066
+ if (file instanceof File || file instanceof Blob) {
1067
+ this._mimeType = file.type;
1068
+ }
1069
+ if ("name" in options) {
1070
+ this._name = options.name;
1071
+ }
1072
+ if ("mimeType" in options) {
1073
+ this._mimeType = options.mimeType;
1074
+ }
1029
1075
  this._options = options;
1030
1076
  this.validateFile();
1031
1077
  }
1078
+ static create(file, options) {
1079
+ return new TelaFile(file, options);
1080
+ }
1032
1081
  /**
1033
1082
  * Retrieves the options provided during instantiation.
1034
1083
  *
@@ -1043,7 +1092,15 @@ class TelaFile {
1043
1092
  * @returns `true` if the file source is a valid URL string, otherwise `false`.
1044
1093
  */
1045
1094
  get isURL() {
1046
- return typeof this._file === "string" && this.isValidURL(this._file);
1095
+ return this.isValidURL(this._file);
1096
+ }
1097
+ /**
1098
+ * Determines whether the file source is a valid Vault reference.
1099
+ *
1100
+ * @returns `true` if the file source is a valid Vault reference, otherwise `false`.
1101
+ */
1102
+ get isVaultReference() {
1103
+ return this.isValidVaultReference(this._file);
1047
1104
  }
1048
1105
  /**
1049
1106
  * Gets the size of the file in bytes.
@@ -1053,6 +1110,22 @@ class TelaFile {
1053
1110
  get size() {
1054
1111
  return this._size;
1055
1112
  }
1113
+ /**
1114
+ * Gets the name of the file.
1115
+ *
1116
+ * @returns The name of the file if available, otherwise `null`.
1117
+ */
1118
+ get name() {
1119
+ return this._name ?? null;
1120
+ }
1121
+ /**
1122
+ * Gets the type of the file.
1123
+ *
1124
+ * @returns The type of the file if available, otherwise `null`.
1125
+ */
1126
+ get type() {
1127
+ return this._mimeType ?? null;
1128
+ }
1056
1129
  /**
1057
1130
  * Retrieves the content of the file in a format suitable for uploading.
1058
1131
  *
@@ -1063,11 +1136,11 @@ class TelaFile {
1063
1136
  * @returns A promise that resolves to the uploadable content.
1064
1137
  */
1065
1138
  async getUploadableContent() {
1066
- if (this.isURL && typeof this._file === "string") {
1139
+ if (this.isValidURL(this._file) || this.isValidVaultReference(this._file)) {
1067
1140
  return this._file;
1068
1141
  }
1069
1142
  if (this._file instanceof Uint8Array) {
1070
- return new File([this._file], "file", {
1143
+ return new File([this._file.buffer], "file", {
1071
1144
  type: "application/octet-stream"
1072
1145
  });
1073
1146
  }
@@ -1108,6 +1181,9 @@ class TelaFile {
1108
1181
  * @returns `true` if the URL is valid, otherwise `false`.
1109
1182
  */
1110
1183
  isValidURL(url) {
1184
+ if (typeof url !== "string") {
1185
+ return false;
1186
+ }
1111
1187
  try {
1112
1188
  new URL(url);
1113
1189
  return true;
@@ -1115,43 +1191,604 @@ class TelaFile {
1115
1191
  return false;
1116
1192
  }
1117
1193
  }
1194
+ /**
1195
+ * Checks if the provided string is a valid Vault reference.
1196
+ *
1197
+ * @param url - The Vault reference string to validate.
1198
+ * @returns `true` if the Vault reference is valid, otherwise `false`.
1199
+ */
1200
+ isValidVaultReference(url) {
1201
+ if (typeof url !== "string") {
1202
+ return false;
1203
+ }
1204
+ return url.startsWith("vault://");
1205
+ }
1206
+ }
1207
+
1208
+ function compareSchemas(clientSchema, serverSchema, path = "$") {
1209
+ const mismatches = [];
1210
+ if (clientSchema.type !== serverSchema.type) {
1211
+ mismatches.push({
1212
+ path,
1213
+ issue: `Type mismatch: client has "${clientSchema.type}", server has "${serverSchema.type}"`
1214
+ });
1215
+ return mismatches;
1216
+ }
1217
+ if (clientSchema.type === "object") {
1218
+ const clientProps = clientSchema.properties || {};
1219
+ const serverProps = serverSchema.properties || {};
1220
+ const clientRequired = clientSchema.required || [];
1221
+ const serverRequired = serverSchema.required || [];
1222
+ for (const reqProp of serverRequired) {
1223
+ if (!clientProps[reqProp]) {
1224
+ mismatches.push({
1225
+ path: `${path}.${reqProp}`,
1226
+ issue: `Property is required on server but missing on client`
1227
+ });
1228
+ continue;
1229
+ }
1230
+ if (!clientRequired.includes(reqProp)) {
1231
+ mismatches.push({
1232
+ path: `${path}.${reqProp}`,
1233
+ issue: `Property is required on server but optional on client`
1234
+ });
1235
+ }
1236
+ }
1237
+ for (const clientProp of Object.keys(clientProps)) {
1238
+ if (!serverProps[clientProp]) {
1239
+ mismatches.push({
1240
+ path: `${path}.${clientProp}`,
1241
+ issue: `Extra property not expected by server`
1242
+ });
1243
+ }
1244
+ }
1245
+ for (const prop of Object.keys(serverProps)) {
1246
+ if (!clientProps[prop]) {
1247
+ continue;
1248
+ }
1249
+ const nestedMismatches = compareSchemas(
1250
+ clientProps[prop],
1251
+ serverProps[prop],
1252
+ `${path}.${prop}`
1253
+ );
1254
+ mismatches.push(...nestedMismatches);
1255
+ }
1256
+ }
1257
+ if (clientSchema.type === "array") {
1258
+ const clientItems = clientSchema.items;
1259
+ const serverItems = serverSchema.items;
1260
+ if (!clientItems || !serverItems) {
1261
+ if (clientItems !== serverItems) {
1262
+ mismatches.push({
1263
+ path: `${path}[]`,
1264
+ issue: `Array items schema mismatch: one side has items definition, other doesn't`
1265
+ });
1266
+ }
1267
+ return mismatches;
1268
+ }
1269
+ const itemMismatches = compareSchemas(
1270
+ clientItems,
1271
+ serverItems,
1272
+ `${path}[]`
1273
+ );
1274
+ mismatches.push(...itemMismatches);
1275
+ }
1276
+ return mismatches;
1118
1277
  }
1119
- function createTelaFile(file, options) {
1120
- return new TelaFile(file, options);
1278
+ function mapServerTypeToJsonSchemaType(serverType) {
1279
+ const typeMap = {
1280
+ text: "string",
1281
+ number: "number",
1282
+ boolean: "boolean",
1283
+ file: "string",
1284
+ // z.file() generates type: "string" with format: "binary", contentEncoding: "binary"
1285
+ array: "array",
1286
+ object: "object"
1287
+ };
1288
+ return typeMap[serverType.toLowerCase()] || null;
1289
+ }
1290
+ function validateInputSchema(clientSchema, serverVariables) {
1291
+ const mismatches = [];
1292
+ const clientProps = clientSchema.properties || {};
1293
+ const clientRequired = clientSchema.required || [];
1294
+ for (const serverVar of serverVariables) {
1295
+ if (serverVar.required) {
1296
+ if (!clientProps[serverVar.name]) {
1297
+ mismatches.push({
1298
+ path: `$.${serverVar.name}`,
1299
+ issue: `Property is required on server but missing on client`
1300
+ });
1301
+ continue;
1302
+ }
1303
+ if (!clientRequired.includes(serverVar.name)) {
1304
+ mismatches.push({
1305
+ path: `$.${serverVar.name}`,
1306
+ issue: `Variable is required on server but optional on client`
1307
+ });
1308
+ }
1309
+ }
1310
+ if (!clientProps[serverVar.name]) {
1311
+ continue;
1312
+ }
1313
+ {
1314
+ const clientProp = clientProps[serverVar.name];
1315
+ const clientType = clientProp.type;
1316
+ const expectedType = mapServerTypeToJsonSchemaType(serverVar.type);
1317
+ if (serverVar.type.toLowerCase() === "file") {
1318
+ const isFileSchema = clientProp.isTelaFile;
1319
+ if (isFileSchema) {
1320
+ continue;
1321
+ }
1322
+ if (clientProp.format === "binary") {
1323
+ mismatches.push({
1324
+ path: `$.${serverVar.name}`,
1325
+ issue: `Type mismatch: file is expected to be a \`telaFile()\` but is a regular file instead.`
1326
+ });
1327
+ continue;
1328
+ }
1329
+ if (clientType === "string" && !clientProp.format && !clientProp.contentEncoding) {
1330
+ mismatches.push({
1331
+ path: `$.${serverVar.name}`,
1332
+ issue: `Type mismatch: server expects file, client has plain string. Did you mean to use \`telaFile()\`?`
1333
+ });
1334
+ continue;
1335
+ }
1336
+ mismatches.push({
1337
+ path: `$.${serverVar.name}`,
1338
+ issue: `Type mismatch: server expects file, client has "${clientType}"`
1339
+ });
1340
+ continue;
1341
+ }
1342
+ if (expectedType && clientType !== expectedType) {
1343
+ mismatches.push({
1344
+ path: `$.${serverVar.name}`,
1345
+ issue: `Type mismatch: server expects "${serverVar.type}", client has "${clientType}"`
1346
+ });
1347
+ }
1348
+ }
1349
+ }
1350
+ const serverVarNames = serverVariables.map((v) => v.name);
1351
+ for (const clientProp of Object.keys(clientProps)) {
1352
+ if (!serverVarNames.includes(clientProp)) {
1353
+ mismatches.push({
1354
+ path: `$.${clientProp}`,
1355
+ issue: `Extra property not expected by server`
1356
+ });
1357
+ }
1358
+ }
1359
+ return mismatches;
1360
+ }
1361
+ function validateOutputSchema(clientSchema, serverSchema) {
1362
+ return compareSchemas(clientSchema, serverSchema);
1121
1363
  }
1122
1364
 
1123
- var __defProp$1 = Object.defineProperty;
1124
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1125
- var __publicField$1 = (obj, key, value) => {
1126
- __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
1365
+ var __defProp$3 = Object.defineProperty;
1366
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1367
+ var __publicField$3 = (obj, key, value) => {
1368
+ __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
1127
1369
  return value;
1128
1370
  };
1129
- class Resource {
1130
- constructor(client) {
1131
- __publicField$1(this, "_client");
1132
- this._client = client;
1371
+ function timeout(ms, signal) {
1372
+ return new Promise((resolve, reject) => {
1373
+ const timer = setTimeout(resolve, ms);
1374
+ if (signal) {
1375
+ signal.addEventListener("abort", () => {
1376
+ clearTimeout(timer);
1377
+ reject(signal.reason);
1378
+ }, { once: true });
1379
+ }
1380
+ });
1381
+ }
1382
+ class Poller {
1383
+ constructor({ interval, timeout: timeout2, abortSignal }) {
1384
+ __publicField$3(this, "_interval");
1385
+ __publicField$3(this, "_timeout");
1386
+ __publicField$3(this, "_abortSignal");
1387
+ __publicField$3(this, "_internalAbortController");
1388
+ if (interval <= 0) {
1389
+ throw new TelaError("Interval must be greater than 0");
1390
+ }
1391
+ if (timeout2 <= 0) {
1392
+ throw new TelaError("Timeout must be greater than 0");
1393
+ }
1394
+ this._interval = interval;
1395
+ this._timeout = timeout2;
1396
+ this._abortSignal = abortSignal ?? new AbortController().signal;
1397
+ this._internalAbortController = new AbortController();
1398
+ }
1399
+ async startTimeout() {
1400
+ await timeout(this._timeout, this._internalAbortController.signal);
1401
+ throw new ConnectionTimeout({
1402
+ message: `Reached timeout of ${this._timeout}ms when polling`
1403
+ });
1404
+ }
1405
+ /**
1406
+ * Starts the polling operation, repeatedly calling the callback until completion.
1407
+ * The callback is invoked at the configured interval and must return a PollerResult
1408
+ * indicating whether polling should continue or if the final value is ready.
1409
+ *
1410
+ * @param callback - Function called on each polling iteration.
1411
+ * @returns A promise resolving to the final result value.
1412
+ * @throws {Error} If the polling operation times out.
1413
+ * @throws {Error} If the operation is aborted via the AbortSignal.
1414
+ * @throws Any error thrown by the callback function.
1415
+ *
1416
+ * @example
1417
+ * ```typescript
1418
+ * const result = await poller.start(async (signal) => {
1419
+ * const response = await fetch('/api/status', { signal });
1420
+ * const data = await response.json();
1421
+ *
1422
+ * if (data.status === 'completed') {
1423
+ * return { done: true, value: data.result };
1424
+ * }
1425
+ * return { done: false };
1426
+ * });
1427
+ * ```
1428
+ */
1429
+ start(callback) {
1430
+ const resultPromise = async () => {
1431
+ try {
1432
+ while (!this._abortSignal.aborted) {
1433
+ const result = await Promise.try(callback, this._abortSignal);
1434
+ if (result.done) {
1435
+ return result.value;
1436
+ }
1437
+ await timeout(this._interval, this._abortSignal);
1438
+ }
1439
+ throw new UserAbortError({ message: "Polling aborted" });
1440
+ } finally {
1441
+ this._internalAbortController.abort();
1442
+ }
1443
+ };
1444
+ return Promise.race([this.startTimeout(), resultPromise()]);
1133
1445
  }
1134
1446
  }
1135
1447
 
1136
- class ChatCompletions extends Resource {
1137
- async create(body, opts) {
1138
- const processedBody = { ...body };
1139
- if (body.variables) {
1140
- const processedVariables = {};
1141
- for await (const [key, value] of Object.entries(body.variables)) {
1142
- if (value instanceof TelaFile) {
1143
- const fileWithUrl = await this.uploadFile(value);
1144
- processedVariables[key] = fileWithUrl;
1145
- } else {
1146
- processedVariables[key] = value;
1448
+ async function calculateSha256sum(content) {
1449
+ const stream = content instanceof File || content instanceof Blob ? content.stream() : content;
1450
+ const reader = stream.getReader();
1451
+ try {
1452
+ const { createHash } = await import('node:crypto');
1453
+ const hash = createHash("sha256");
1454
+ while (true) {
1455
+ const { done, value } = await reader.read();
1456
+ if (done)
1457
+ break;
1458
+ hash.update(value);
1459
+ }
1460
+ return hash.digest("hex");
1461
+ } catch {
1462
+ const chunks = [];
1463
+ while (true) {
1464
+ const { done, value } = await reader.read();
1465
+ if (done)
1466
+ break;
1467
+ chunks.push(value);
1468
+ }
1469
+ const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
1470
+ const buffer = new Uint8Array(totalLength);
1471
+ let offset = 0;
1472
+ for (const chunk of chunks) {
1473
+ buffer.set(chunk, offset);
1474
+ offset += chunk.length;
1475
+ }
1476
+ const hashBuffer = await crypto.subtle.digest("SHA-256", buffer);
1477
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
1478
+ const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
1479
+ return hashHex;
1480
+ }
1481
+ }
1482
+
1483
+ var __defProp$2 = Object.defineProperty;
1484
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1485
+ var __publicField$2 = (obj, key, value) => {
1486
+ __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
1487
+ return value;
1488
+ };
1489
+ function isTelaFile(obj) {
1490
+ return obj instanceof TelaFile;
1491
+ }
1492
+ function isTelaFileArray(obj) {
1493
+ return Array.isArray(obj) && obj.length > 0 && obj.every(isTelaFile);
1494
+ }
1495
+ class CanvasExecution {
1496
+ /**
1497
+ * Creates a new canvas execution instance.
1498
+ *
1499
+ * @param variables - Input variables to be passed to the canvas template.
1500
+ * @param params - Execution parameters controlling sync/async/stream behavior.
1501
+ * @param outputSchema - Zod schema or object schema for validating/parsing output.
1502
+ * @param client - HTTP client instance for making API requests.
1503
+ */
1504
+ constructor(variables, params = { async: false }, outputSchema, client) {
1505
+ __publicField$2(this, "_id");
1506
+ __publicField$2(this, "_variables");
1507
+ __publicField$2(this, "_params");
1508
+ __publicField$2(this, "_client");
1509
+ __publicField$2(this, "_outputSchema");
1510
+ __publicField$2(this, "_skipResultValidation");
1511
+ __publicField$2(this, "_abortController");
1512
+ __publicField$2(this, "_startPropmise");
1513
+ __publicField$2(this, "_resultPromise");
1514
+ __publicField$2(this, "_stream");
1515
+ this._variables = variables;
1516
+ this._params = params;
1517
+ this._outputSchema = outputSchema;
1518
+ this._skipResultValidation = params.skipResultValidation ?? false;
1519
+ this._client = client;
1520
+ this._abortController = new AbortController();
1521
+ }
1522
+ /**
1523
+ * Gets the unique execution ID assigned by the server.
1524
+ *
1525
+ * @throws {Error} If the execution has not been started yet.
1526
+ * @returns The execution ID.
1527
+ */
1528
+ get id() {
1529
+ if (!this._id) {
1530
+ throw new ExecutionNotStartedError();
1531
+ }
1532
+ return this._id;
1533
+ }
1534
+ /**
1535
+ * Gets the input variables provided to this execution.
1536
+ *
1537
+ * @returns The variables object.
1538
+ */
1539
+ get variables() {
1540
+ return this._variables;
1541
+ }
1542
+ /**
1543
+ * Gets the execution parameters configured for this instance.
1544
+ *
1545
+ * @returns The execution parameters or undefined.
1546
+ */
1547
+ get params() {
1548
+ return this._params;
1549
+ }
1550
+ /**
1551
+ * Checks if this execution is configured for asynchronous processing.
1552
+ *
1553
+ * @returns True if async mode is enabled.
1554
+ */
1555
+ get isAsync() {
1556
+ return this._isAsync(this._params);
1557
+ }
1558
+ /**
1559
+ * Checks if this execution is configured for synchronous processing.
1560
+ *
1561
+ * @returns True if sync mode is enabled (not async).
1562
+ */
1563
+ get isSync() {
1564
+ return !this._isAsync(this._params) && !this.isStream;
1565
+ }
1566
+ /**
1567
+ * Checks if this execution is configured for streaming responses.
1568
+ *
1569
+ * @returns True if stream mode is enabled.
1570
+ */
1571
+ get isStream() {
1572
+ return Boolean(this._params.stream);
1573
+ }
1574
+ /**
1575
+ * Type guard to check if params indicate async execution.
1576
+ *
1577
+ * @param params - Execution parameters to check.
1578
+ * @returns True if params indicate async mode.
1579
+ */
1580
+ _isAsync(params) {
1581
+ return Boolean(params.async);
1582
+ }
1583
+ /**
1584
+ * Starts the execution based on configured parameters.
1585
+ * Routes to the appropriate execution method (sync, async, or stream).
1586
+ *
1587
+ * @returns A promise or async generator depending on execution mode.
1588
+ */
1589
+ start() {
1590
+ if (this._resultPromise || this._stream) {
1591
+ return this._resultPromise ?? this._stream;
1592
+ }
1593
+ if (this._params.stream) {
1594
+ return this.startStream();
1595
+ }
1596
+ if (this.isSync) {
1597
+ return this.startSync();
1598
+ }
1599
+ return this.startAsync();
1600
+ }
1601
+ /**
1602
+ * Gets the execution result. For async executions, automatically starts polling.
1603
+ * For sync executions, returns the result promise. For streams, returns the generator.
1604
+ *
1605
+ * @returns The execution result as a promise or async generator.
1606
+ */
1607
+ get result() {
1608
+ if (this.isSync) {
1609
+ if (!this._resultPromise) {
1610
+ throw new ExecutionNotStartedError();
1611
+ }
1612
+ return this._resultPromise;
1613
+ }
1614
+ if (this.isStream) {
1615
+ if (!this._stream) {
1616
+ throw new ExecutionNotStartedError();
1617
+ }
1618
+ return this._stream;
1619
+ }
1620
+ if (this._resultPromise) {
1621
+ return this._resultPromise;
1622
+ }
1623
+ this._resultPromise = this.startPolling();
1624
+ return this._resultPromise;
1625
+ }
1626
+ /**
1627
+ * Cancels the ongoing execution by aborting all active requests and polling operations.
1628
+ */
1629
+ cancel() {
1630
+ this._abortController.abort();
1631
+ }
1632
+ /**
1633
+ * Builds the base request body shared across all execution types.
1634
+ * Includes messages, overrides, and structured output configuration.
1635
+ *
1636
+ * @returns The base request body object.
1637
+ */
1638
+ get baseBody() {
1639
+ const body = {
1640
+ canvasId: this._params.canvasId,
1641
+ applicationId: this._params.applicationId,
1642
+ versionId: this._params.versionId,
1643
+ messages: this._params.messages
1644
+ };
1645
+ if (this._params.override && this._outputSchema instanceof z__default.ZodType) {
1646
+ return {
1647
+ ...body,
1648
+ override: {
1649
+ ...this._params.override,
1650
+ structured_output: z__default.toJSONSchema(this._outputSchema)
1147
1651
  }
1652
+ };
1653
+ }
1654
+ return body;
1655
+ }
1656
+ /**
1657
+ * Processes variables and uploads any TelaFile instances to the server.
1658
+ * Replaces TelaFile objects with their uploaded URLs while preserving other values.
1659
+ *
1660
+ * @returns A promise resolving to the processed variables object.
1661
+ */
1662
+ async resolveVariables() {
1663
+ const variables = {};
1664
+ for (const [key, value] of Object.entries(this._variables)) {
1665
+ if (isTelaFileArray(value)) {
1666
+ variables[key] = await this.uploadFiles(value);
1667
+ continue;
1668
+ }
1669
+ if (isTelaFile(value)) {
1670
+ variables[key] = await this.uploadFile(value);
1671
+ continue;
1148
1672
  }
1149
- processedBody.variables = processedVariables;
1673
+ variables[key] = value;
1150
1674
  }
1151
- return this._client.post("/v2/chat/completions", {
1152
- body: processedBody,
1153
- ...opts,
1154
- stream: body.stream ?? false
1675
+ return variables;
1676
+ }
1677
+ /**
1678
+ * Initiates a synchronous execution that waits for the complete result.
1679
+ * The result is validated against the output schema if provided.
1680
+ *
1681
+ * @returns A promise resolving to the parsed execution result.
1682
+ */
1683
+ async startSync() {
1684
+ const resolvedVariables = await this.resolveVariables();
1685
+ const body = {
1686
+ async: this._params.async ?? false,
1687
+ stream: false,
1688
+ ...this.baseBody,
1689
+ variables: resolvedVariables
1690
+ };
1691
+ this._resultPromise = this._client.post("/v2/chat/completions", {
1692
+ body,
1693
+ stream: false,
1694
+ signal: this._abortController.signal
1695
+ }).then((response) => {
1696
+ this._id = response.id;
1697
+ return response.choices?.[0]?.message?.content;
1698
+ }).then((content) => {
1699
+ if (this._skipResultValidation || !(this._outputSchema instanceof z__default.ZodType)) {
1700
+ return content;
1701
+ }
1702
+ return this._outputSchema.parse(content);
1703
+ });
1704
+ return this._resultPromise;
1705
+ }
1706
+ /**
1707
+ * Initiates an asynchronous execution that returns immediately with an execution ID.
1708
+ * Results must be retrieved separately via polling using the `result` getter.
1709
+ *
1710
+ * @returns A promise that resolves when the execution is queued.
1711
+ */
1712
+ async startAsync() {
1713
+ const resolvedVariables = await this.resolveVariables();
1714
+ const body = {
1715
+ async: true,
1716
+ stream: false,
1717
+ ...this.baseBody,
1718
+ variables: resolvedVariables
1719
+ };
1720
+ return await this._client.post("/v2/chat/completions", {
1721
+ body,
1722
+ stream: false,
1723
+ signal: this._abortController.signal
1724
+ }).then((response) => {
1725
+ this._id = response.id;
1726
+ return response;
1727
+ });
1728
+ }
1729
+ /**
1730
+ * Initiates a streaming execution that returns results incrementally as they're generated.
1731
+ *
1732
+ * @returns A promise resolving to an async generator yielding result chunks.
1733
+ */
1734
+ async startStream() {
1735
+ const resolvedVariables = await this.resolveVariables();
1736
+ const body = {
1737
+ ...this.baseBody,
1738
+ stream: true,
1739
+ variables: resolvedVariables
1740
+ };
1741
+ this._stream = await this._client.post("/v2/chat/completions", {
1742
+ body,
1743
+ stream: true,
1744
+ signal: this._abortController.signal
1745
+ });
1746
+ return this._stream;
1747
+ }
1748
+ /**
1749
+ * Polls the server for async execution results at regular intervals.
1750
+ * Continues polling until the execution completes or the timeout is reached.
1751
+ *
1752
+ * @throws {Error} If called on a non-async execution.
1753
+ * @throws {Error} If the execution fails on the server.
1754
+ * @throws {Error} If the polling operation times out.
1755
+ * @returns A promise resolving to the final execution result.
1756
+ */
1757
+ async startPolling() {
1758
+ if (!this._isAsync(this._params)) {
1759
+ throw new InvalidExecutionModeError("Polling is only supported for async executions");
1760
+ }
1761
+ return new Poller({
1762
+ interval: this._params.pollingInterval ?? 1e3,
1763
+ // 1 second
1764
+ timeout: this._params.pollingTimeout ?? 6e4,
1765
+ // 1 minute
1766
+ abortSignal: this._abortController.signal
1767
+ }).start(async (signal) => {
1768
+ const response = await this._client.get(
1769
+ `/v2/chat/completions/${this.id}`,
1770
+ {
1771
+ signal
1772
+ }
1773
+ );
1774
+ if (response.status === "failed") {
1775
+ throw new ExecutionFailedError(response.rawOutput);
1776
+ }
1777
+ if (response.status !== "succeeded") {
1778
+ return {
1779
+ done: false,
1780
+ value: void 0
1781
+ };
1782
+ }
1783
+ return {
1784
+ done: response.status === "succeeded",
1785
+ value: response.outputContent.content
1786
+ };
1787
+ }).then((value) => {
1788
+ if (this._skipResultValidation || !(this._outputSchema instanceof z__default.ZodType)) {
1789
+ return value;
1790
+ }
1791
+ return this._outputSchema.parse(value);
1155
1792
  });
1156
1793
  }
1157
1794
  /**
@@ -1167,36 +1804,303 @@ class ChatCompletions extends Resource {
1167
1804
  * ```typescript
1168
1805
  * const file = new TelaFile({ /* file options *\/ });
1169
1806
  * const uploadedFile = await this.uploadFile(file);
1170
- * console.log(uploadedFile.file_url);
1807
+ * console.log(uploadedFile.fileUrl);
1171
1808
  * ```
1172
1809
  */
1173
1810
  async uploadFile(file) {
1174
- const content = await file.getUploadableContent();
1175
- if (file.isURL && typeof content === "string") {
1811
+ let content = await file.getUploadableContent();
1812
+ let sha256sumStream;
1813
+ if (typeof content === "string") {
1176
1814
  return { fileUrl: content, options: file.options };
1177
1815
  }
1178
- const response = await this._client.post(
1179
- "/v2/file"
1180
- );
1181
- const { uploadUrl, downloadUrl } = response;
1182
- let contentType = "application/octet-stream";
1183
- if (content instanceof File || content instanceof Blob) {
1184
- contentType = content.type;
1816
+ const filename = file.name ?? void 0;
1817
+ const fileType = file.type ?? void 0;
1818
+ const contentLength = file.size ?? void 0;
1819
+ if (content instanceof ReadableStream) {
1820
+ const [hashStream, contentStream] = content.tee();
1821
+ content = contentStream;
1822
+ sha256sumStream = hashStream;
1823
+ }
1824
+ const sha256sum = await calculateSha256sum(sha256sumStream ?? content);
1825
+ const { id, uploadUrl } = await this._client.post("/_services/vault/files", {
1826
+ body: {
1827
+ fileName: filename,
1828
+ mimeType: fileType,
1829
+ size: contentLength ?? void 0,
1830
+ sha256sum
1831
+ }
1832
+ });
1833
+ if (content instanceof ReadableStream && typeof Bun !== "undefined") {
1834
+ console.warn(
1835
+ "[Tela SDK - WARNING] Buffering file upload due to Bun fetch implementation. Large files may cause memory issues. Consider using Node.js for streaming uploads.",
1836
+ { fileName: filename, fileSize: contentLength }
1837
+ );
1838
+ const chunks = [];
1839
+ const reader = content.getReader();
1840
+ while (true) {
1841
+ const { done, value } = await reader.read();
1842
+ if (done)
1843
+ break;
1844
+ chunks.push(value);
1845
+ }
1846
+ content = new Blob(chunks, { type: fileType ?? "application/octet-stream" });
1185
1847
  }
1186
- const uploadResponse = await fetch(uploadUrl, {
1848
+ const request = new Request(uploadUrl, {
1187
1849
  method: "PUT",
1188
1850
  body: content,
1189
1851
  headers: {
1190
- "Content-Type": contentType,
1852
+ "Content-Type": fileType ?? "application/octet-stream",
1191
1853
  ...file.size ? { "Content-Length": file.size.toString() } : {}
1192
- },
1193
- // duplex is not supported
1194
- duplex: "half"
1854
+ }
1195
1855
  });
1856
+ const uploadResponse = await fetch(request);
1196
1857
  if (!uploadResponse.ok) {
1197
- throw new FileUploadError(await uploadResponse.text());
1858
+ throw new FileUploadError(await uploadResponse.text(), uploadResponse.status);
1859
+ }
1860
+ return { fileUrl: `vault://${id}`, options: file.options };
1861
+ }
1862
+ /**
1863
+ * Uploads multiple files and returns their URLs and options.
1864
+ *
1865
+ * This is used internally to handle multiple file uploads associated with chat completions.
1866
+ *
1867
+ * @param files - An array of TelaFile instances to be uploaded.
1868
+ * @returns A Promise that resolves to an array of objects containing file URLs and options.
1869
+ * @throws {FileUploadError} If any file upload fails.
1870
+ */
1871
+ async uploadFiles(files) {
1872
+ const uploadPromises = files.map((file) => this.uploadFile(file));
1873
+ return Promise.all(uploadPromises);
1874
+ }
1875
+ }
1876
+
1877
+ var __defProp$1 = Object.defineProperty;
1878
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1879
+ var __publicField$1 = (obj, key, value) => {
1880
+ __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
1881
+ return value;
1882
+ };
1883
+ const zod = {
1884
+ string: z.string,
1885
+ number: z.number,
1886
+ boolean: z.boolean,
1887
+ object: z.object,
1888
+ array: z.array,
1889
+ file: TelaFileSchema,
1890
+ any: z.any,
1891
+ unknown: z.unknown
1892
+ };
1893
+ function fetchById(id, client) {
1894
+ return client.get(`/prompt/${id}/promoted-version`);
1895
+ }
1896
+ function fetchByVersionId(versionId, client) {
1897
+ return client.get(`/prompt-version/${versionId}`);
1898
+ }
1899
+ function fetchByApplicationId(applicationId, client) {
1900
+ return client.get(`/prompt-application/${applicationId}/targetPromptVersion`);
1901
+ }
1902
+ function fetchByAny({ id, versionId, applicationId, client }) {
1903
+ if (applicationId) {
1904
+ return fetchByApplicationId(applicationId, client);
1905
+ }
1906
+ if (versionId) {
1907
+ return fetchByVersionId(versionId, client);
1908
+ }
1909
+ if (id) {
1910
+ return fetchById(id, client);
1911
+ }
1912
+ throw new Error("Either id, versionId, or applicationId must be provided");
1913
+ }
1914
+ function validateSchemas(input, output, promptVersion) {
1915
+ const canvasIdentifier = `${promptVersion.title} (${promptVersion.promptId})`;
1916
+ if (input instanceof z.z.ZodType) {
1917
+ try {
1918
+ const inputSchema = z.z.toJSONSchema(input, { unrepresentable: "any" });
1919
+ const mismatches = validateInputSchema(inputSchema, promptVersion.variables);
1920
+ if (mismatches.length === 0) {
1921
+ return;
1922
+ }
1923
+ console.warn(
1924
+ `[Tela SDK - Canvas Input Validation] Input schema mismatches for canvas "${canvasIdentifier}":`
1925
+ );
1926
+ for (const mismatch of mismatches) {
1927
+ console.warn(` - ${mismatch.path}: ${mismatch.issue}`);
1928
+ }
1929
+ } catch (error) {
1930
+ console.warn(
1931
+ `[Tela SDK - Canvas Input Validation] Failed to validate input schema for canvas "${canvasIdentifier}":`,
1932
+ error
1933
+ );
1934
+ }
1935
+ }
1936
+ if (output instanceof z.z.ZodType) {
1937
+ try {
1938
+ const outputSchema = z.z.toJSONSchema(output);
1939
+ const serverOutput = promptVersion.configuration.structuredOutput;
1940
+ if (!serverOutput.enabled) {
1941
+ console.warn(
1942
+ `[Tela SDK - Canvas Output Validation] Output schema provided for canvas "${canvasIdentifier}", but structured output is not enabled on the server. The schema may not be enforced.`
1943
+ );
1944
+ return;
1945
+ }
1946
+ const mismatches = validateOutputSchema(outputSchema, serverOutput.schema);
1947
+ if (mismatches.length === 0) {
1948
+ return;
1949
+ }
1950
+ console.warn(
1951
+ `[Tela SDK - Canvas Output Validation] Output schema mismatches for canvas "${canvasIdentifier}":`
1952
+ );
1953
+ for (const mismatch of mismatches) {
1954
+ console.warn(` - ${mismatch.path}: ${mismatch.issue}`);
1955
+ }
1956
+ } catch (error) {
1957
+ console.warn(
1958
+ `[Tela SDK - Canvas Output Validation] Failed to validate output schema for canvas "${canvasIdentifier}":`,
1959
+ error
1960
+ );
1198
1961
  }
1199
- return { fileUrl: downloadUrl, options: file.options };
1962
+ }
1963
+ }
1964
+ class Canvas {
1965
+ /**
1966
+ * Creates a new instance of the Canvas class. Usage of this constructor is not recommended.
1967
+ * Use the `tela.getCanvas` method instead.
1968
+ *
1969
+ * @private
1970
+ */
1971
+ constructor({ id, applicationId, name, versionId, input, output, client, variables }) {
1972
+ __publicField$1(this, "_id");
1973
+ __publicField$1(this, "_versionId");
1974
+ __publicField$1(this, "_applicationId");
1975
+ __publicField$1(this, "_name");
1976
+ __publicField$1(this, "_input");
1977
+ __publicField$1(this, "_output");
1978
+ __publicField$1(this, "_client");
1979
+ __publicField$1(this, "_variables");
1980
+ this._id = id;
1981
+ this._applicationId = applicationId;
1982
+ this._name = name;
1983
+ this._versionId = versionId;
1984
+ this._input = input && input(zod);
1985
+ this._output = output && output(zod);
1986
+ this._client = client;
1987
+ this._variables = variables;
1988
+ }
1989
+ /**
1990
+ * Gets a canvas by its ID.
1991
+ *
1992
+ * @param options - The options to use to get the canvas.
1993
+ * @param options.id - The ID of the canvas to get.
1994
+ * @param options.versionId - The version ID of the canvas to get.
1995
+ * @param options.applicationId - The application ID of the canvas to get.
1996
+ * @param options.client - The client to use to make the request.
1997
+ * @param options.input - The input schema of the canvas to get.
1998
+ * @param options.output - The output schema of the canvas to get.
1999
+ * @returns The canvas.
2000
+ */
2001
+ static async get(options) {
2002
+ const { id, versionId, applicationId, client, input, output, skipSchemaValidation = false } = options;
2003
+ const promptVersion = await fetchByAny({ id, versionId, applicationId, client });
2004
+ const inputSchema = input && input(zod);
2005
+ const outputSchema = output && output(zod);
2006
+ if (!skipSchemaValidation) {
2007
+ validateSchemas(inputSchema, outputSchema, promptVersion);
2008
+ }
2009
+ return new Canvas({
2010
+ id: promptVersion.promptId,
2011
+ name: promptVersion.title,
2012
+ versionId: promptVersion.id,
2013
+ input,
2014
+ output,
2015
+ client,
2016
+ variables: promptVersion.variables
2017
+ });
2018
+ }
2019
+ /**
2020
+ * Gets the unique identifier of this canvas.
2021
+ *
2022
+ * @returns The canvas ID.
2023
+ */
2024
+ get id() {
2025
+ if (!this._id) {
2026
+ throw new Error("Canvas ID is not set");
2027
+ }
2028
+ return this._id;
2029
+ }
2030
+ /**
2031
+ * Gets the name of this canvas, if provided.
2032
+ *
2033
+ * @returns The canvas name or undefined.
2034
+ */
2035
+ get name() {
2036
+ if (!this._name) {
2037
+ throw new Error("Canvas name is not set");
2038
+ }
2039
+ return this._name;
2040
+ }
2041
+ /**
2042
+ * Gets the version identifier of this canvas, if specified.
2043
+ * When undefined, the latest promoted version is used.
2044
+ *
2045
+ * @returns The version ID or undefined.
2046
+ */
2047
+ get versionId() {
2048
+ if (!this._versionId) {
2049
+ throw new Error("Canvas version ID is not set");
2050
+ }
2051
+ return this._versionId;
2052
+ }
2053
+ get applicationId() {
2054
+ if (!this._applicationId) {
2055
+ throw new Error("Canvas application ID is not set");
2056
+ }
2057
+ return this._applicationId;
2058
+ }
2059
+ /**
2060
+ * Gets the variables of this canvas.
2061
+ *
2062
+ * @returns The variables of the canvas.
2063
+ */
2064
+ get variables() {
2065
+ return this._variables;
2066
+ }
2067
+ /**
2068
+ * Validates and parses input variables using the canvas input schema.
2069
+ *
2070
+ * @param variables - Raw input variables to validate.
2071
+ * @returns Parsed and validated variables.
2072
+ * @throws {ZodError} If validation fails when a Zod schema is configured.
2073
+ */
2074
+ parseVariables(variables) {
2075
+ try {
2076
+ if (this._input instanceof z.z.ZodType) {
2077
+ return this._input.parse(variables);
2078
+ }
2079
+ return variables;
2080
+ } catch (error) {
2081
+ if (!(error instanceof z.ZodError)) {
2082
+ throw error;
2083
+ }
2084
+ throw new Error(z.z.prettifyError(error));
2085
+ }
2086
+ }
2087
+ execute(variables, params) {
2088
+ const parsedInput = this.parseVariables(variables);
2089
+ const fullParams = {
2090
+ ...params ?? { async: false },
2091
+ versionId: this._versionId,
2092
+ canvasId: this._id,
2093
+ applicationId: this._applicationId
2094
+ };
2095
+ const execution = new CanvasExecution(parsedInput, fullParams, this._output, this._client);
2096
+ return {
2097
+ then(onfulfilled, onrejected) {
2098
+ return Promise.resolve(execution.start()).then(() => onfulfilled?.(execution) ?? execution).catch(onrejected);
2099
+ },
2100
+ get result() {
2101
+ return Promise.resolve(execution.start()).then(() => execution.result);
2102
+ }
2103
+ };
1200
2104
  }
1201
2105
  }
1202
2106
 
@@ -1217,31 +2121,56 @@ const _TelaSDK = class _TelaSDK extends BaseClient {
1217
2121
  __publicField(this, "apiKey");
1218
2122
  __publicField(this, "jwt");
1219
2123
  /**
1220
- * The ChatCompletions resource for interacting with Tela's chat completion API.
2124
+ * Creates a new `TelaFile` instance from the provided file input.
1221
2125
  *
1222
- * Use this to generate chat completions based on provided messages.
2126
+ * @param file - The file input to create a `TelaFile` instance from.
2127
+ * @returns A new `TelaFile` instance.
2128
+ */
2129
+ __publicField(this, "createFile", TelaFile.create.bind(this));
2130
+ /**
2131
+ * Retrieves a canvas by its ID, version ID, or application ID.
2132
+ * Validates input and output schemas if Zod schemas are provided.
2133
+ *
2134
+ * @param options - Options for retrieving the canvas.
2135
+ * @returns A promise resolving to a Canvas instance.
1223
2136
  *
1224
2137
  * @example
1225
2138
  * ```typescript
1226
- * const completion = await tela.completions.create({
1227
- * canvasId: "your-canvas-id",
1228
- * messages: [{ role: "user", content: "Hello!" }],
2139
+ * import { z } from 'zod';
2140
+ *
2141
+ * // Get canvas by ID with schemas
2142
+ * const canvas = await tela.canvas.get({
2143
+ * id: 'canvas-id',
2144
+ * input: z.object({ query: z.string() }),
2145
+ * output: z.object({ response: z.string() })
1229
2146
  * });
1230
- * ```
1231
- */
1232
- __publicField(this, "completions", new ChatCompletions(this));
1233
- /**
1234
- * Creates a new `TelaFile` instance from the provided file input.
1235
2147
  *
1236
- * @param file - The file input to create a `TelaFile` instance from.
1237
- * @returns A new `TelaFile` instance.
2148
+ * // Get canvas by application ID
2149
+ * const canvas = await tela.canvas.get({
2150
+ * applicationId: 'app-id'
2151
+ * });
2152
+ *
2153
+ * // Execute the canvas
2154
+ * const execution = await canvas.execute({ query: 'Hello' });
2155
+ * const result = await execution.result;
2156
+ * ```
1238
2157
  */
1239
- __publicField(this, "createFile", createTelaFile.bind(this));
2158
+ __publicField(this, "canvas", {
2159
+ get: async (options) => {
2160
+ return Canvas.get({
2161
+ ...options,
2162
+ client: this
2163
+ });
2164
+ }
2165
+ });
1240
2166
  this.opts = { baseURL, ...rest };
1241
2167
  this.apiKey = apiKey;
1242
2168
  this.jwt = jwt;
1243
2169
  this.validateAuth();
1244
2170
  }
2171
+ get authToken() {
2172
+ return this.apiKey || this.jwt;
2173
+ }
1245
2174
  validateAuth() {
1246
2175
  if (!this.apiKey && !this.jwt) {
1247
2176
  throw new MissingApiKeyOrJWTError();
@@ -1298,6 +2227,30 @@ function createTelaClient(opts) {
1298
2227
  return new TelaSDK(opts);
1299
2228
  }
1300
2229
 
2230
+ exports.APIError = APIError;
2231
+ exports.AuthenticationError = AuthenticationError;
2232
+ exports.AuthorizationError = AuthorizationError;
2233
+ exports.BadRequestError = BadRequestError;
2234
+ exports.BaseClient = BaseClient;
2235
+ exports.ConflictApiKeyAndJWTError = ConflictApiKeyAndJWTError;
2236
+ exports.ConflictError = ConflictError;
2237
+ exports.ConnectionError = ConnectionError;
2238
+ exports.ConnectionTimeout = ConnectionTimeout;
2239
+ exports.EmptyFileError = EmptyFileError;
2240
+ exports.ExecutionFailedError = ExecutionFailedError;
2241
+ exports.ExecutionNotStartedError = ExecutionNotStartedError;
2242
+ exports.FileUploadError = FileUploadError;
2243
+ exports.InternalServerError = InternalServerError;
2244
+ exports.InvalidExecutionModeError = InvalidExecutionModeError;
2245
+ exports.InvalidFileURL = InvalidFileURL;
2246
+ exports.MissingApiKeyOrJWTError = MissingApiKeyOrJWTError;
2247
+ exports.NotFoundError = NotFoundError;
2248
+ exports.RateLimitError = RateLimitError;
2249
+ exports.TelaError = TelaError;
1301
2250
  exports.TelaFile = TelaFile;
2251
+ exports.TelaFileSchema = TelaFileSchema;
1302
2252
  exports.TelaSDK = TelaSDK;
2253
+ exports.UnprocessableEntityError = UnprocessableEntityError;
2254
+ exports.UserAbortError = UserAbortError;
1303
2255
  exports.createTelaClient = createTelaClient;
2256
+ exports.toError = toError;