@truto/truto-jsonata 1.0.43 → 1.0.45

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/esm/index.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  flattenDeep as flattenDeep3,
14
14
  flattenDepth,
15
15
  groupBy as groupBy3,
16
- join as join2,
16
+ join as join3,
17
17
  keyBy,
18
18
  omit as omit2,
19
19
  orderBy,
@@ -2193,7 +2193,7 @@ var convertMarkdownToSlack = (text) => {
2193
2193
  var convertMarkdownToSlack_default = convertMarkdownToSlack;
2194
2194
 
2195
2195
  // src/functions/convertNotionToMarkdown.ts
2196
- import { castArray as castArray3, flatten, map as map3, reject, repeat } from "lodash-es";
2196
+ import { castArray as castArray3, flatten, join as join2, map as map3, reject, repeat } from "lodash-es";
2197
2197
  var formatPlainText = (x) => {
2198
2198
  if (x) {
2199
2199
  if (x.href) {
@@ -2223,7 +2223,7 @@ var formatPlainText = (x) => {
2223
2223
  return textToReturn;
2224
2224
  }
2225
2225
  };
2226
- var convertNotionToMd = function(block, level = 1) {
2226
+ var convertNotionToMd = function(block, level = 1, linkChildPages = false) {
2227
2227
  const n = `
2228
2228
 
2229
2229
  `;
@@ -2235,16 +2235,16 @@ var convertNotionToMd = function(block, level = 1) {
2235
2235
  case "bookmark":
2236
2236
  return `[${data.url}](data.url)${n}`;
2237
2237
  case "bulleted_list_item":
2238
- childData = map3(block.children, (child) => convertNotionToMd(child, level + 1)).join(repeat("\t", level));
2239
- return `- ${plainText.join("")}
2238
+ childData = join2(map3(block.children, (child) => convertNotionToMd(child, level + 1, linkChildPages)), repeat("\t", level));
2239
+ return `- ${join2(plainText, "")}
2240
2240
  ` + (childData ? `${repeat("\t", level)}${childData}` : "");
2241
2241
  case "numbered_list_item":
2242
- childData = map3(block.children, (child) => convertNotionToMd(child, level + 1)).join(repeat("\t", level));
2243
- return `${block.number}. ${plainText.join("")}
2242
+ childData = join2(map3(block.children, (child) => convertNotionToMd(child, level + 1, linkChildPages)), repeat("\t", level));
2243
+ return `${block.number}. ${join2(plainText, "")}
2244
2244
  ` + (childData ? `${repeat("\t", level)}${childData}` : "");
2245
2245
  case "quote":
2246
2246
  case "callout":
2247
- return `> ${plainText.join("")}${n}`;
2247
+ return `> ${join2(plainText, "")}${n}`;
2248
2248
  case "code":
2249
2249
  return `\`\`\`${data.language}
2250
2250
  ${plainText}
@@ -2256,51 +2256,60 @@ ${plainText}
2256
2256
  case "equation":
2257
2257
  return data.expression;
2258
2258
  case "paragraph":
2259
- return plainText.join("") + n;
2259
+ return join2(plainText, "") + n;
2260
2260
  case "video":
2261
2261
  case "pdf":
2262
2262
  case "file":
2263
2263
  return `[${caption.length ? caption : "File"}](${data.file ? data.file.url : data.external ? data.external.url : ""})${n}`;
2264
2264
  case "heading_1":
2265
- return `# ${plainText.join("")}${n}`;
2265
+ return `# ${join2(plainText, "")}${n}`;
2266
2266
  case "heading_2":
2267
- return `## ${plainText.join("")}${n}`;
2267
+ return `## ${join2(plainText, "")}${n}`;
2268
2268
  case "heading_3":
2269
- return `### ${plainText.join("")}${n}`;
2269
+ return `### ${join2(plainText, "")}${n}`;
2270
2270
  case "heading_4":
2271
- return `#### ${plainText.join("")}${n}`;
2271
+ return `#### ${join2(plainText, "")}${n}`;
2272
2272
  case "heading_5":
2273
- return `##### ${plainText.join("")}${n}`;
2273
+ return `##### ${join2(plainText, "")}${n}`;
2274
2274
  case "heading_6":
2275
- return `###### ${plainText.join("")}${n}`;
2275
+ return `###### ${join2(plainText, "")}${n}`;
2276
2276
  case "image":
2277
2277
  return `![${caption.length ? caption : "Image"}](${data.file ? data.file.url : data.external ? data.external.url : ""})${n}`;
2278
+ case "child_page":
2279
+ if (linkChildPages) {
2280
+ const pageTitle = data.title || "Untitled Page";
2281
+ const pageUrl = `https://www.notion.so/${block.id.replace(/-/g, "")}`;
2282
+ return `[${pageTitle}](${pageUrl})${n}`;
2283
+ } else {
2284
+ childData = join2(map3(block.children, (child) => convertNotionToMd(child, level, linkChildPages)), "");
2285
+ return (data.title || "Untitled Page") + n + childData;
2286
+ }
2278
2287
  case "table":
2279
2288
  if (block.children) {
2280
2289
  const firstChild = block.children[0];
2281
2290
  const remainingChildren = block.children.slice(1);
2282
- const header = `| ${firstChild.table_row.cells.map((x) => x.map((y) => formatPlainText(y)).join("")).join(" | ")} |
2291
+ const header = `| ${join2(firstChild.table_row.cells.map((x) => join2(x.map((y) => formatPlainText(y)), "")), " | ")} |
2283
2292
  `;
2284
2293
  const divider = `|${repeat("---|", data.table_width)}
2285
2294
  `;
2286
- const rows = remainingChildren.map((row) => {
2287
- return `| ${row.table_row.cells.map((x) => x.map((y) => formatPlainText(y)).join("")).join(" | ")} |`;
2288
- }).join(`
2295
+ const rows = join2(remainingChildren.map((row) => {
2296
+ return `| ${join2(row.table_row.cells.map((x) => join2(x.map((y) => formatPlainText(y)), "")), " | ")} |`;
2297
+ }), `
2289
2298
  `);
2290
2299
  return `${header}${divider}${rows}${n}`;
2291
2300
  }
2292
2301
  return `Table as CSV
2293
2302
  `;
2294
2303
  case "table_row":
2295
- return `| ${data.cells.map((x) => x.map((y) => formatPlainText(y)).join("")).join(" | ")} |
2304
+ return `| ${join2(data.cells.map((x) => join2(x.map((y) => formatPlainText(y)), "")), " | ")} |
2296
2305
  `;
2297
2306
  case "to_do":
2298
- childData = map3(block.children, (child) => convertNotionToMd(child, level + 1)).join(repeat("\t", level));
2299
- return `- [${data.checked ? "X" : " "}] ${plainText.join("")}
2307
+ childData = join2(map3(block.children, (child) => convertNotionToMd(child, level + 1, linkChildPages)), repeat("\t", level));
2308
+ return `- [${data.checked ? "X" : " "}] ${join2(plainText, "")}
2300
2309
  ` + (childData ? `${repeat("\t", level)}${childData}` : "");
2301
2310
  default:
2302
- childData = map3(block.children, (child) => convertNotionToMd(child)).join("");
2303
- return plainText.join("") + n + childData;
2311
+ childData = join2(map3(block.children, (child) => convertNotionToMd(child, level, linkChildPages)), "");
2312
+ return join2(plainText, "") + n + childData;
2304
2313
  }
2305
2314
  };
2306
2315
  var resolveChildren = function(block, blocks) {
@@ -2350,13 +2359,13 @@ var insertNewLinesBetweenLists = function(blocks) {
2350
2359
  return block;
2351
2360
  }));
2352
2361
  };
2353
- var convertNotionToMarkdown = function(blocks) {
2362
+ var convertNotionToMarkdown = function(blocks, linkChildPages = false) {
2354
2363
  const arrayBlocks = insertNewLinesBetweenLists(castArray3(blocks));
2355
2364
  const parentBlocks = reject(arrayBlocks, (block) => block.parent?.type === "block_id");
2356
2365
  const blocksWithChildren = numberOrderedLists(parentBlocks.map((block) => {
2357
2366
  return resolveChildren(block, arrayBlocks);
2358
2367
  }));
2359
- return blocksWithChildren.map((block) => convertNotionToMd(block)).join("");
2368
+ return join2(blocksWithChildren.map((block) => convertNotionToMd(block, 1, linkChildPages)), "");
2360
2369
  };
2361
2370
  var convertNotionToMarkdown_default = convertNotionToMarkdown;
2362
2371
 
@@ -2932,17 +2941,45 @@ var removeEmptyItems_default = removeEmptyItems;
2932
2941
 
2933
2942
  // src/functions/sign.ts
2934
2943
  var sign = async (text, algorithm = "SHA-256", secret, outputFormat = "hex") => {
2935
- const key = await crypto.subtle.importKey("raw", new TextEncoder().encode(secret), { name: "HMAC", hash: algorithm }, false, ["sign"]);
2944
+ const upperAlg = String(algorithm ?? "").trim().toUpperCase();
2936
2945
  const encoder = new TextEncoder;
2937
2946
  const data = encoder.encode(text);
2938
- const hashBuffer = await crypto.subtle.sign("HMAC", key, data);
2947
+ let signatureBuffer;
2948
+ if (upperAlg === "RS256") {
2949
+ const pemKey = secret?.includes("\\n") ? secret.replace(/\\n/g, `
2950
+ `) : secret;
2951
+ if (!pemKey || !/-----BEGIN PRIVATE KEY-----/.test(pemKey)) {
2952
+ throw new Error("RS256 requires a PKCS#8 PEM private key (BEGIN PRIVATE KEY)");
2953
+ }
2954
+ const keyDataBase64 = pemKey.replace(/-----BEGIN PRIVATE KEY-----/, "").replace(/-----END PRIVATE KEY-----/, "").replace(/\s/g, "");
2955
+ const binaryKey = Uint8Array.from(atob(keyDataBase64), (c) => c.charCodeAt(0));
2956
+ const rsaAlgorithm = {
2957
+ name: "RSASSA-PKCS1-v1_5",
2958
+ hash: { name: "SHA-256" }
2959
+ };
2960
+ let key;
2961
+ try {
2962
+ key = await crypto.subtle.importKey("pkcs8", binaryKey, rsaAlgorithm, false, ["sign"]);
2963
+ } catch (e) {
2964
+ throw new Error(`RS256 key import failed. Ensure an unencrypted PKCS#8 PEM (BEGIN PRIVATE KEY). Underlying: ${e?.message || e}`);
2965
+ }
2966
+ try {
2967
+ signatureBuffer = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", key, data);
2968
+ } catch (e) {
2969
+ throw new Error(`RS256 signing failed. Ensure the key matches RSASSA-PKCS1-v1_5 and data is correctly encoded. Underlying: ${e?.message || e}`);
2970
+ }
2971
+ } else {
2972
+ const hmacHash = upperAlg || "SHA-256";
2973
+ const key = await crypto.subtle.importKey("raw", new TextEncoder().encode(secret), { name: "HMAC", hash: { name: hmacHash } }, false, ["sign"]);
2974
+ signatureBuffer = await crypto.subtle.sign("HMAC", key, data);
2975
+ }
2939
2976
  if (outputFormat === "hex") {
2940
- const hashArray = Array.from(new Uint8Array(hashBuffer));
2941
- return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
2977
+ const bytes = Array.from(new Uint8Array(signatureBuffer));
2978
+ return bytes.map((b) => b.toString(16).padStart(2, "0")).join("");
2942
2979
  } else if (outputFormat === "base64") {
2943
- return arrayBufferToBase64(hashBuffer);
2980
+ return arrayBufferToBase64(signatureBuffer);
2944
2981
  } else if (outputFormat === "base64-urlSafe") {
2945
- return arrayBufferToBase64(hashBuffer, true);
2982
+ return arrayBufferToBase64(signatureBuffer, true);
2946
2983
  }
2947
2984
  };
2948
2985
  var sign_default = sign;
@@ -3031,40 +3068,95 @@ function zipSqlResponse(columns, data, key) {
3031
3068
  }
3032
3069
  var zipSqlResponse_default = zipSqlResponse;
3033
3070
 
3034
- // src/functions/signJwt.ts
3035
- import { SignJWT, importPKCS8 } from "jose";
3036
- import { isPlainObject as isPlainObject3, isNull, isString as isString4, includes, replace } from "lodash-es";
3037
- function assertObjectPayload(payload) {
3038
- if (!isPlainObject3(payload) || isNull(payload)) {
3039
- throw new Error("Payload must be a non-null object");
3071
+ // src/functions/convertMdToPdf.ts
3072
+ import pRetry3, { AbortError as AbortError3 } from "p-retry";
3073
+ import { includes, split, trim } from "lodash-es";
3074
+ function getFilenameFromHeaders(resp, fallback) {
3075
+ const cd = resp.headers.get("content-disposition") || "";
3076
+ const matchStar = cd.match(/filename\*=([^;]+)/i);
3077
+ if (matchStar) {
3078
+ const value = trim(matchStar[1]);
3079
+ const parts = split(value, "''");
3080
+ if (parts.length === 2) {
3081
+ try {
3082
+ return decodeURIComponent(parts[1]);
3083
+ } catch {
3084
+ return parts[1];
3085
+ }
3086
+ }
3087
+ return trim(value, `'"`);
3040
3088
  }
3089
+ const match = cd.match(/filename="?([^";]+)"?/i);
3090
+ if (match)
3091
+ return match[1];
3092
+ return fallback || "document.pdf";
3041
3093
  }
3042
- var signJwt = async (payload, key, protectHeaders = {}, signOptions) => {
3043
- assertObjectPayload(payload);
3044
- try {
3045
- let signingKey;
3046
- const alg = protectHeaders.alg;
3047
- if (!alg) {
3048
- throw new Error("Algorithm (alg) must be provided in protectHeaders");
3049
- }
3050
- const isAsymmetric = alg.startsWith("RS") || alg.startsWith("ES") || alg.startsWith("PS");
3051
- if (isAsymmetric) {
3052
- if (!isString4(key)) {
3053
- throw new Error("For asymmetric algorithms, key must be a PEM string");
3094
+ async function convertMdToPdf(markdown, options = {}, assetHeaders = {}) {
3095
+ const documentParserApiUrl = this.environment.lookup("documentParserApiUrl");
3096
+ const documentParserApiKey = this.environment.lookup("documentParserApiKey");
3097
+ if (!documentParserApiKey) {
3098
+ throw new Error("Document parser API key not found in environment");
3099
+ }
3100
+ if (!documentParserApiUrl) {
3101
+ throw new Error("Document parser API URL not found in environment");
3102
+ }
3103
+ if (!markdown || typeof markdown !== "string") {
3104
+ throw new AbortError3("Markdown content is required and must be a string");
3105
+ }
3106
+ const requestBody = {
3107
+ markdown,
3108
+ options,
3109
+ assetHeaders
3110
+ };
3111
+ return await pRetry3(async () => {
3112
+ const response = await fetch(`${documentParserApiUrl}/md-to-pdf`, {
3113
+ method: "POST",
3114
+ headers: {
3115
+ Authorization: `Bearer ${documentParserApiKey}`,
3116
+ "Content-Type": "application/json",
3117
+ Accept: "application/pdf",
3118
+ "User-Agent": "truto"
3119
+ },
3120
+ body: JSON.stringify(requestBody)
3121
+ });
3122
+ if (!response.ok) {
3123
+ if (response.status === 429) {
3124
+ throw new Error("Rate limit exceeded");
3054
3125
  }
3055
- const pemKey = includes(key, "\\n") ? replace(key, /\\n/g, `
3056
- `) : key;
3057
- signingKey = await importPKCS8(pemKey, alg);
3058
- } else {
3059
- signingKey = isString4(key) ? new TextEncoder().encode(key) : key;
3126
+ if (response.status >= 500) {
3127
+ throw new Error(`Server error: ${response.status}`);
3128
+ }
3129
+ const errorText = await response.text();
3130
+ let errorMessage = `PDF conversion failed (${response.status})`;
3131
+ try {
3132
+ const errorData = JSON.parse(errorText);
3133
+ errorMessage = errorData.error || errorMessage;
3134
+ if (errorData.details) {
3135
+ errorMessage += `: ${errorData.details}`;
3136
+ }
3137
+ } catch {
3138
+ errorMessage += `: ${errorText}`;
3139
+ }
3140
+ throw new AbortError3(errorMessage);
3060
3141
  }
3061
- const jwtBuilder = new SignJWT(payload).setProtectedHeader({ ...protectHeaders, typ: "JWT" });
3062
- return await jwtBuilder.sign(signingKey, signOptions);
3063
- } catch (error) {
3064
- throw new Error(`JWT signing failed: ${error?.message || String(error)}`);
3065
- }
3066
- };
3067
- var signJwt_default = signJwt;
3142
+ const contentType = response.headers.get("content-type");
3143
+ if (!contentType || !includes(contentType, "application/pdf")) {
3144
+ throw new AbortError3(`Expected PDF but received: ${contentType}`);
3145
+ }
3146
+ const arrayBuffer = await response.arrayBuffer();
3147
+ const filename = getFilenameFromHeaders(response, options.filename);
3148
+ const blob2 = new Blob([arrayBuffer], { type: "application/pdf" });
3149
+ blob2.name = filename;
3150
+ return blob2;
3151
+ }, {
3152
+ retries: 5,
3153
+ maxTimeout: 30000,
3154
+ minTimeout: 2500,
3155
+ onFailedAttempt: (error) => {
3156
+ console.warn(`PDF conversion attempt ${error.attemptNumber} failed:`, error.message);
3157
+ }
3158
+ });
3159
+ }
3068
3160
 
3069
3161
  // src/registerJsonataExtensions.ts
3070
3162
  function registerJsonataExtensions(expression) {
@@ -3091,6 +3183,7 @@ function registerJsonataExtensions(expression) {
3091
3183
  expression.registerFunction("difference", function(arr1, arr2) {
3092
3184
  return difference(arr1, arr2);
3093
3185
  });
3186
+ expression.registerFunction("convertMdToPdf", convertMdToPdf);
3094
3187
  expression.registerFunction("toNumber", toNumber_default);
3095
3188
  expression.registerFunction("jsonParse", jsonParse_default);
3096
3189
  expression.registerFunction("getMimeType", getMimeType_default);
@@ -3103,7 +3196,6 @@ function registerJsonataExtensions(expression) {
3103
3196
  expression.registerFunction("convertMarkdownToHtml", convertMarkdownToHtml_default);
3104
3197
  expression.registerFunction("digest", digest_default);
3105
3198
  expression.registerFunction("sign", sign_default);
3106
- expression.registerFunction("signJwt", signJwt_default);
3107
3199
  expression.registerFunction("xmlToJs", xmlToJs);
3108
3200
  expression.registerFunction("jsToXml", jsToXml_default);
3109
3201
  expression.registerFunction("generateEmbeddingsCohere", generateEmbeddingsCohere_default);
@@ -3123,7 +3215,7 @@ function registerJsonataExtensions(expression) {
3123
3215
  return compact2(castArray5(arr));
3124
3216
  });
3125
3217
  expression.registerFunction("join", function(arr, separator) {
3126
- return join2(castArray5(arr), separator);
3218
+ return join3(castArray5(arr), separator);
3127
3219
  });
3128
3220
  expression.registerFunction("orderBy", function(arr, attr, order) {
3129
3221
  return orderBy(castArray5(arr), attr, order);
@@ -3141,7 +3233,7 @@ function registerJsonataExtensions(expression) {
3141
3233
  return chunk2(castArray5(arr), size);
3142
3234
  });
3143
3235
  expression.registerFunction("wrap", function(value, wrapper, endWrapper) {
3144
- return join2([wrapper, value, endWrapper || wrapper], "");
3236
+ return join3([wrapper, value, endWrapper || wrapper], "");
3145
3237
  });
3146
3238
  expression.registerFunction("parseDocument", parseDocument_default);
3147
3239
  expression.registerFunction("recursiveCharacterTextSplitter", recursiveCharacterTextSplitter);
@@ -3170,4 +3262,4 @@ export {
3170
3262
  trutoJsonata as default
3171
3263
  };
3172
3264
 
3173
- //# debugId=AF69BFF9BD4A50C064756E2164756E21
3265
+ //# debugId=CD61DB122C61553664756E2164756E21