@deepnote/blocks 1.3.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 ADDED
@@ -0,0 +1,598 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+
23
+ //#endregion
24
+ let zod = require("zod");
25
+ zod = __toESM(zod);
26
+ let yaml = require("yaml");
27
+ yaml = __toESM(yaml);
28
+ let ts_dedent = require("ts-dedent");
29
+ ts_dedent = __toESM(ts_dedent);
30
+
31
+ //#region src/deserialize-file/deepnote-file-schema.ts
32
+ const deepnoteBlockSchema = zod.z.object({
33
+ blockGroup: zod.z.string().optional(),
34
+ content: zod.z.string().optional(),
35
+ executionCount: zod.z.number().optional(),
36
+ id: zod.z.string(),
37
+ metadata: zod.z.record(zod.z.any()).optional(),
38
+ outputs: zod.z.array(zod.z.any()).optional(),
39
+ sortingKey: zod.z.string(),
40
+ type: zod.z.string(),
41
+ version: zod.z.number().optional()
42
+ });
43
+ const deepnoteFileSchema = zod.z.object({
44
+ metadata: zod.z.object({
45
+ checksum: zod.z.string().optional(),
46
+ createdAt: zod.z.string(),
47
+ exportedAt: zod.z.string().optional(),
48
+ modifiedAt: zod.z.string().optional()
49
+ }),
50
+ project: zod.z.object({
51
+ id: zod.z.string(),
52
+ initNotebookId: zod.z.string().optional(),
53
+ integrations: zod.z.array(zod.z.object({
54
+ id: zod.z.string(),
55
+ name: zod.z.string(),
56
+ type: zod.z.string()
57
+ })).optional(),
58
+ name: zod.z.string(),
59
+ notebooks: zod.z.array(zod.z.object({
60
+ blocks: zod.z.array(deepnoteBlockSchema),
61
+ executionMode: zod.z.enum(["block", "downstream"]).optional(),
62
+ id: zod.z.string(),
63
+ isModule: zod.z.boolean().optional(),
64
+ name: zod.z.string(),
65
+ workingDirectory: zod.z.string().optional()
66
+ })),
67
+ settings: zod.z.object({
68
+ environment: zod.z.object({
69
+ customImage: zod.z.string().optional(),
70
+ pythonVersion: zod.z.string().optional()
71
+ }).optional(),
72
+ requirements: zod.z.array(zod.z.string()).optional(),
73
+ sqlCacheMaxAge: zod.z.number().optional()
74
+ }).optional()
75
+ }),
76
+ version: zod.z.string()
77
+ });
78
+
79
+ //#endregion
80
+ //#region src/deserialize-file/parse-yaml.ts
81
+ function parseYaml(yamlContent) {
82
+ try {
83
+ return (0, yaml.parse)(yamlContent);
84
+ } catch (error) {
85
+ const message = error instanceof Error ? error.message : String(error);
86
+ throw new Error(`Failed to parse Deepnote file: ${message}`);
87
+ }
88
+ }
89
+
90
+ //#endregion
91
+ //#region src/deserialize-file/deserialize-deepnote-file.ts
92
+ /**
93
+ * Deserialize a YAML string into a DeepnoteFile object.
94
+ */
95
+ function deserializeDeepnoteFile(yamlContent) {
96
+ const parsed = parseYaml(yamlContent);
97
+ const result = deepnoteFileSchema.safeParse(parsed);
98
+ if (!result.success) {
99
+ const issue = result.error.issues[0];
100
+ if (!issue) throw new Error("Invalid Deepnote file.");
101
+ const path = issue.path.join(".");
102
+ const message = path ? `${path}: ${issue.message}` : issue.message;
103
+ throw new Error(`Failed to parse the Deepnote file: ${message}.`);
104
+ }
105
+ return result.data;
106
+ }
107
+
108
+ //#endregion
109
+ //#region src/blocks.ts
110
+ var UnsupportedBlockTypeError = class extends Error {
111
+ constructor(message) {
112
+ super(message);
113
+ this.name = "UnsupportedBlockTypeError";
114
+ }
115
+ };
116
+
117
+ //#endregion
118
+ //#region src/blocks/image-blocks.ts
119
+ function escapeHtmlAttribute(value) {
120
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
121
+ }
122
+ function sanitizeWidth(width) {
123
+ return width.replace(/[^0-9]/g, "") || "";
124
+ }
125
+ function sanitizeAlignment(alignment) {
126
+ return [
127
+ "left",
128
+ "center",
129
+ "right"
130
+ ].includes(alignment.toLowerCase()) ? alignment.toLowerCase() : "";
131
+ }
132
+ function createMarkdownForImageBlock(block) {
133
+ return `<img src="${escapeHtmlAttribute(block.metadata.deepnote_img_src ?? "")}" width="${sanitizeWidth(block.metadata.deepnote_img_width ?? "")}" align="${sanitizeAlignment(block.metadata.deepnote_img_alignment ?? "")}" />`;
134
+ }
135
+ function isImageBlock(block) {
136
+ return block.type === "image";
137
+ }
138
+
139
+ //#endregion
140
+ //#region src/blocks/text-blocks.ts
141
+ function isTextBlock(block) {
142
+ return [
143
+ "text-cell-p",
144
+ "text-cell-h1",
145
+ "text-cell-h2",
146
+ "text-cell-h3",
147
+ "text-cell-bullet",
148
+ "text-cell-todo",
149
+ "text-cell-callout"
150
+ ].includes(block.type.toLowerCase());
151
+ }
152
+ function escapeMarkdown(text) {
153
+ return text.replace(/([\\`*_{}[\]()#+\-.!|>])/g, "\\$1");
154
+ }
155
+ function createMarkdownForTextBlock(block) {
156
+ if (block.type === "text-cell-h1") return `# ${escapeMarkdown(block.content)}`;
157
+ if (block.type === "text-cell-h2") return `## ${escapeMarkdown(block.content)}`;
158
+ if (block.type === "text-cell-h3") return `### ${escapeMarkdown(block.content)}`;
159
+ if (block.type === "text-cell-bullet") return `- ${escapeMarkdown(block.content)}`;
160
+ if (block.type === "text-cell-todo") return `- ${block.metadata.checked ? "[x]" : "[ ]"} ${escapeMarkdown(block.content)}`;
161
+ if (block.type === "text-cell-callout") return `> ${escapeMarkdown(block.content)}`;
162
+ if (block.type === "text-cell-p") return escapeMarkdown(block.content);
163
+ throw new Error("Unhandled block type.");
164
+ }
165
+ function stripMarkdownFromTextBlock(block) {
166
+ if (block.type === "text-cell-h1") return block.content.replace(/^#\s+/, "").trim();
167
+ if (block.type === "text-cell-h2") return block.content.replace(/^##\s+/, "").trim();
168
+ if (block.type === "text-cell-h3") return block.content.replace(/^#{3,6}\s+/, "").trim();
169
+ if (block.type === "text-cell-bullet") return block.content.replace(/^-+\s+/, "").trim();
170
+ if (block.type === "text-cell-todo") return block.content.replace(/^-+\s+\[.\]\s+/, "").trim();
171
+ if (block.type === "text-cell-callout") return block.content.replace(/^>\s+/, "").trim();
172
+ if (block.type === "text-cell-p") return block.content.trim();
173
+ throw new Error("Unhandled block type.");
174
+ }
175
+ function createMarkdownForSeparatorBlock(_block) {
176
+ return "<hr>";
177
+ }
178
+ function isSeparatorBlock(block) {
179
+ return block.type === "separator";
180
+ }
181
+
182
+ //#endregion
183
+ //#region src/markdown.ts
184
+ function createMarkdown(block) {
185
+ if (block.type === "markdown") return block.content ?? "";
186
+ if (isTextBlock(block)) return createMarkdownForTextBlock(block);
187
+ if (isSeparatorBlock(block)) return createMarkdownForSeparatorBlock(block);
188
+ if (isImageBlock(block)) return createMarkdownForImageBlock(block);
189
+ throw new UnsupportedBlockTypeError(`Creating markdown from block type ${block.type} is not supported yet.`);
190
+ }
191
+ function stripMarkdown(block) {
192
+ if (isTextBlock(block)) return stripMarkdownFromTextBlock(block);
193
+ throw new UnsupportedBlockTypeError(`Stripping markdown from block type ${block.type} is not supported yet.`);
194
+ }
195
+
196
+ //#endregion
197
+ //#region src/blocks/python-utils.ts
198
+ function escapePythonString(value) {
199
+ return `'${value.replaceAll("\\", "\\\\").replaceAll("'", "\\'").replaceAll("\n", "\\n")}'`;
200
+ }
201
+ function sanitizePythonVariableName(name, options = {}) {
202
+ let sanitizedVariableName = name.replace(/\s+/g, "_").replace(/[^0-9a-zA-Z_]/g, "").replace(/^[^a-zA-Z_]+/g, "");
203
+ if (sanitizedVariableName === "" && !options.disableEmptyFallback) sanitizedVariableName = "input_1";
204
+ return sanitizedVariableName;
205
+ }
206
+
207
+ //#endregion
208
+ //#region src/python-snippets.ts
209
+ const pythonCode = {
210
+ setVariableContextValue: (variableName, value) => {
211
+ return `${sanitizePythonVariableName(variableName)} = ${value ? "True" : "False"}`;
212
+ },
213
+ executeBigNumber: (titleTemplate, valueVariableName, comparisonTitleTemplate = "", comparisonVariableName = "") => {
214
+ const sanitizedValueVariable = sanitizePythonVariableName(valueVariableName);
215
+ const valuePart = sanitizedValueVariable ? `f"{${sanitizedValueVariable}}"` : `""`;
216
+ if (!(comparisonTitleTemplate || comparisonVariableName)) return `
217
+ def __deepnote_big_number__():
218
+ import json
219
+ import jinja2
220
+ from jinja2 import meta
221
+
222
+ def render_template(template):
223
+ parsed_content = jinja2.Environment().parse(template)
224
+
225
+ required_variables = meta.find_undeclared_variables(parsed_content)
226
+
227
+ context = {
228
+ variable_name: globals().get(variable_name)
229
+ for variable_name in required_variables
230
+ }
231
+
232
+ result = jinja2.Environment().from_string(template).render(context)
233
+
234
+ return result
235
+
236
+ rendered_title = render_template(${escapePythonString(titleTemplate)})
237
+
238
+ return json.dumps({
239
+ "title": rendered_title,
240
+ "value": ${valuePart}
241
+ })
242
+
243
+ __deepnote_big_number__()
244
+ `;
245
+ const sanitizedComparisonVariable = sanitizePythonVariableName(comparisonVariableName);
246
+ const comparisonValuePart = sanitizedComparisonVariable ? `f"{${sanitizedComparisonVariable}}"` : `""`;
247
+ return `
248
+ def __deepnote_big_number__():
249
+ import json
250
+ import jinja2
251
+ from jinja2 import meta
252
+
253
+ def render_template(template):
254
+ parsed_content = jinja2.Environment().parse(template)
255
+
256
+ required_variables = meta.find_undeclared_variables(parsed_content)
257
+
258
+ context = {
259
+ variable_name: globals().get(variable_name)
260
+ for variable_name in required_variables
261
+ }
262
+
263
+ result = jinja2.Environment().from_string(template).render(context)
264
+
265
+ return result
266
+
267
+ rendered_title = render_template(${escapePythonString(titleTemplate)})
268
+ rendered_comparison_title = render_template(${escapePythonString(comparisonTitleTemplate)})
269
+
270
+ return json.dumps({
271
+ "comparisonTitle": rendered_comparison_title,
272
+ "comparisonValue": ${comparisonValuePart},
273
+ "title": rendered_title,
274
+ "value": ${valuePart}
275
+ })
276
+
277
+ __deepnote_big_number__()
278
+ `;
279
+ },
280
+ executeVisualization: (variableName, spec, filters) => {
281
+ return `_dntk.DeepnoteChart(${sanitizePythonVariableName(variableName)}, ${escapePythonString(spec)}, filters=${escapePythonString(filters)})`;
282
+ },
283
+ dateRangePast7days: (name) => {
284
+ return ts_dedent.dedent`
285
+ from datetime import datetime as _deepnote_datetime, timedelta as _deepnote_timedelta
286
+ ${sanitizePythonVariableName(name)} = [_deepnote_datetime.now().date() - _deepnote_timedelta(days=7), _deepnote_datetime.now().date()]
287
+ `;
288
+ },
289
+ dateRangePast14days: (name) => {
290
+ return ts_dedent.dedent`
291
+ from datetime import datetime as _deepnote_datetime, timedelta as _deepnote_timedelta
292
+ ${sanitizePythonVariableName(name)} = [_deepnote_datetime.now().date() - _deepnote_timedelta(days=14), _deepnote_datetime.now().date()]
293
+ `;
294
+ },
295
+ dateRangePastMonth: (name) => {
296
+ return ts_dedent.dedent`
297
+ from datetime import datetime as _deepnote_datetime
298
+ from dateutil.relativedelta import relativedelta
299
+ ${sanitizePythonVariableName(name)} = [_deepnote_datetime.now().date() - relativedelta(months=1), _deepnote_datetime.now().date()]
300
+ `;
301
+ },
302
+ dateRangePast3months: (name) => {
303
+ return ts_dedent.dedent`
304
+ from datetime import datetime as _deepnote_datetime
305
+ from dateutil.relativedelta import relativedelta
306
+ ${sanitizePythonVariableName(name)} = [_deepnote_datetime.now().date() - relativedelta(months=3), _deepnote_datetime.now().date()]
307
+ `;
308
+ },
309
+ dateRangePast6months: (name) => {
310
+ return ts_dedent.dedent`
311
+ from datetime import datetime as _deepnote_datetime
312
+ from dateutil.relativedelta import relativedelta
313
+ ${sanitizePythonVariableName(name)} = [_deepnote_datetime.now().date() - relativedelta(months=6), _deepnote_datetime.now().date()]
314
+ `;
315
+ },
316
+ dateRangePastYear: (name) => {
317
+ return ts_dedent.dedent`
318
+ from datetime import datetime as _deepnote_datetime
319
+ from dateutil.relativedelta import relativedelta
320
+ ${sanitizePythonVariableName(name)} = [_deepnote_datetime.now().date() - relativedelta(years=1), _deepnote_datetime.now().date()]
321
+ `;
322
+ },
323
+ dateRangeCustomDays: (name, days) => {
324
+ return ts_dedent.dedent`
325
+ from datetime import datetime, timedelta
326
+ ${sanitizePythonVariableName(name)} = [datetime.now().date() - timedelta(days=${Math.floor(Number(days)) || 0}), datetime.now().date()]
327
+ `;
328
+ },
329
+ dateRangeAbsolute: (name, startDate, endDate) => {
330
+ const sanitizedName = sanitizePythonVariableName(name);
331
+ const escapedStartDate = escapePythonString(startDate);
332
+ const escapedEndDate = escapePythonString(endDate);
333
+ return ts_dedent.dedent`
334
+ from dateutil.parser import parse as _deepnote_parse
335
+ ${sanitizedName} = [${startDate ? `_deepnote_parse(${escapedStartDate}).date()` : "None"}, ${endDate ? `_deepnote_parse(${escapedEndDate}).date()` : "None"}]
336
+ `;
337
+ }
338
+ };
339
+
340
+ //#endregion
341
+ //#region src/blocks/big-number-blocks.ts
342
+ function createPythonCodeForBigNumberBlock(block) {
343
+ return pythonCode.executeBigNumber(block.metadata.deepnote_big_number_title ?? "", block.metadata.deepnote_big_number_value ?? "", block.metadata.deepnote_big_number_comparison_title, block.metadata.deepnote_big_number_comparison_value);
344
+ }
345
+ function isBigNumberBlock(block) {
346
+ return block.type === "big-number";
347
+ }
348
+
349
+ //#endregion
350
+ //#region src/blocks/button-blocks.ts
351
+ function createPythonCodeForButtonBlock(block, executionContext) {
352
+ if (block.metadata.deepnote_button_behavior === "set_variable" && block.metadata.deepnote_variable_name) {
353
+ const sanitizedPythonVariableName = sanitizePythonVariableName(block.metadata.deepnote_variable_name);
354
+ if (executionContext?.variableContext?.includes(sanitizedPythonVariableName)) return pythonCode.setVariableContextValue(sanitizedPythonVariableName, true);
355
+ return pythonCode.setVariableContextValue(sanitizedPythonVariableName, false);
356
+ }
357
+ return "";
358
+ }
359
+ function isButtonBlock(block) {
360
+ return block.type === "button";
361
+ }
362
+
363
+ //#endregion
364
+ //#region src/blocks/data-frame.ts
365
+ function createDataFrameConfig(block) {
366
+ const tableState = block.metadata.deepnote_table_state ?? {};
367
+ const tableStateAsJson = JSON.stringify(tableState);
368
+ return ts_dedent.dedent`
369
+ if '_dntk' in globals():
370
+ _dntk.dataframe_utils.configure_dataframe_formatter(${escapePythonString(tableStateAsJson)})
371
+ else:
372
+ _deepnote_current_table_attrs = ${escapePythonString(tableStateAsJson)}
373
+ `;
374
+ }
375
+
376
+ //#endregion
377
+ //#region src/blocks/code-blocks.ts
378
+ function createPythonCodeForCodeBlock(block) {
379
+ return ts_dedent.dedent`
380
+ ${createDataFrameConfig(block)}
381
+
382
+ ${block.content}
383
+ `;
384
+ }
385
+ function isCodeBlock(block) {
386
+ return block.type === "code";
387
+ }
388
+
389
+ //#endregion
390
+ //#region src/blocks/input-blocks.ts
391
+ const DATE_RANGE_INPUT_RELATIVE_RANGES = [
392
+ {
393
+ value: "past7days",
394
+ pythonCode: pythonCode.dateRangePast7days
395
+ },
396
+ {
397
+ value: "past14days",
398
+ pythonCode: pythonCode.dateRangePast14days
399
+ },
400
+ {
401
+ value: "pastMonth",
402
+ pythonCode: pythonCode.dateRangePastMonth
403
+ },
404
+ {
405
+ value: "past3months",
406
+ pythonCode: pythonCode.dateRangePast3months
407
+ },
408
+ {
409
+ value: "past6months",
410
+ pythonCode: pythonCode.dateRangePast6months
411
+ },
412
+ {
413
+ value: "pastYear",
414
+ pythonCode: pythonCode.dateRangePastYear
415
+ }
416
+ ];
417
+ function isCustomDateRange(value) {
418
+ if (typeof value !== "string") return false;
419
+ const days = Number.parseInt(value.split("customDays")[1] ?? "0", 10);
420
+ return value.startsWith("customDays") && !Number.isNaN(days) && days >= 0;
421
+ }
422
+ function isValidRelativeDateInterval(value) {
423
+ return typeof value === "string" && DATE_RANGE_INPUT_RELATIVE_RANGES.some((range) => range.value === value);
424
+ }
425
+ function isValidAbsoluteDateRange(value) {
426
+ const YYYY_MM_DD_REGEX = /^\d{4}-\d{2}-\d{2}$/;
427
+ return Array.isArray(value) && value.length === 2 && value.every((v) => typeof v === "string" && (v === "" || YYYY_MM_DD_REGEX.test(v)));
428
+ }
429
+ function createPythonCodeForInputTextBlock(block) {
430
+ return `${sanitizePythonVariableName(block.metadata.deepnote_variable_name)} = ${escapePythonString(block.metadata.deepnote_variable_value)}`;
431
+ }
432
+ function createPythonCodeForInputTextareaBlock(block) {
433
+ return `${sanitizePythonVariableName(block.metadata.deepnote_variable_name)} = ${escapePythonString(block.metadata.deepnote_variable_value)}`;
434
+ }
435
+ function createPythonCodeForInputCheckboxBlock(block) {
436
+ return `${sanitizePythonVariableName(block.metadata.deepnote_variable_name)} = ${block.metadata.deepnote_variable_value ? "True" : "False"}`;
437
+ }
438
+ function createPythonCodeForInputSelectBlock(block) {
439
+ const sanitizedPythonVariableName = sanitizePythonVariableName(block.metadata.deepnote_variable_name);
440
+ if (block.metadata.deepnote_allow_multiple_values || Array.isArray(block.metadata.deepnote_variable_value)) return `${sanitizedPythonVariableName} = [${(Array.isArray(block.metadata.deepnote_variable_value) ? block.metadata.deepnote_variable_value : [block.metadata.deepnote_variable_value]).map((value) => escapePythonString(value)).join(", ")}]`;
441
+ else if (!block.metadata.deepnote_allow_multiple_values && !block.metadata.deepnote_variable_value) return `${sanitizedPythonVariableName} = None`;
442
+ else return `${sanitizedPythonVariableName} = ${escapePythonString(block.metadata.deepnote_variable_value)}`;
443
+ }
444
+ function createPythonCodeForInputSliderBlock(block) {
445
+ const sanitizedPythonVariableName = sanitizePythonVariableName(block.metadata.deepnote_variable_name);
446
+ const value = block.metadata.deepnote_variable_value;
447
+ if (!/^-?\d+\.?\d*$|^-?\d*\.\d+$/.test(value)) throw new Error(`Invalid numeric value for slider input: "${value}". Expected a valid number (integer or float).`);
448
+ const numericValue = Number(value);
449
+ if (!Number.isFinite(numericValue)) throw new Error(`Invalid numeric value for slider input: "${value}". Value must be finite.`);
450
+ return `${sanitizedPythonVariableName} = ${numericValue}`;
451
+ }
452
+ function createPythonCodeForInputFileBlock(block) {
453
+ const sanitizedPythonVariableName = sanitizePythonVariableName(block.metadata.deepnote_variable_name);
454
+ if (block.metadata.deepnote_variable_value === "") return `${sanitizedPythonVariableName} = None`;
455
+ return `${sanitizedPythonVariableName} = ${escapePythonString(block.metadata.deepnote_variable_value)}`;
456
+ }
457
+ function createPythonCodeForInputDateBlock(block) {
458
+ const sanitizedPythonVariableName = sanitizePythonVariableName(block.metadata.deepnote_variable_name);
459
+ const escapedValue = escapePythonString(block.metadata.deepnote_variable_value);
460
+ if (!block.metadata.deepnote_variable_value) return `
461
+ ${sanitizedPythonVariableName} = None
462
+ `;
463
+ if (block.metadata.deepnote_input_date_version === 2) return `
464
+ from dateutil.parser import parse as _deepnote_parse
465
+ ${sanitizedPythonVariableName} = _deepnote_parse(${escapedValue}).date()
466
+ `;
467
+ return `
468
+ from datetime import datetime as _deepnote_datetime
469
+ ${sanitizedPythonVariableName} = _deepnote_datetime.strptime(${escapedValue}, "%Y-%m-%dT%H:%M:%S.%fZ")
470
+ `;
471
+ }
472
+ function createPythonCodeForInputDateRangeBlock(block) {
473
+ const sanitizedPythonVariableName = sanitizePythonVariableName(block.metadata.deepnote_variable_name);
474
+ if (isValidAbsoluteDateRange(block.metadata.deepnote_variable_value)) {
475
+ const startDate = block.metadata.deepnote_variable_value[0];
476
+ const endDate = block.metadata.deepnote_variable_value[1];
477
+ return pythonCode.dateRangeAbsolute(sanitizedPythonVariableName, startDate, endDate);
478
+ } else if (isCustomDateRange(block.metadata.deepnote_variable_value)) {
479
+ const customDays = block.metadata.deepnote_variable_value.replace("customDays", "");
480
+ return pythonCode.dateRangeCustomDays(sanitizedPythonVariableName, Number(customDays));
481
+ } else if (isValidRelativeDateInterval(block.metadata.deepnote_variable_value)) {
482
+ const range = DATE_RANGE_INPUT_RELATIVE_RANGES.find((range$1) => range$1.value === block.metadata.deepnote_variable_value);
483
+ if (!range) throw new Error(`Invalid relative date interval: "${block.metadata.deepnote_variable_value}". Expected one of: ${DATE_RANGE_INPUT_RELATIVE_RANGES.map((r) => r.value).join(", ")}.`);
484
+ return ts_dedent.dedent`
485
+ ${range.pythonCode(sanitizedPythonVariableName)}`;
486
+ } else return ts_dedent.dedent`
487
+ ${sanitizedPythonVariableName} = [None, None]
488
+ `;
489
+ }
490
+ function isInputTextBlock(block) {
491
+ return block.type === "input-text";
492
+ }
493
+ function isInputTextareaBlock(block) {
494
+ return block.type === "input-textarea";
495
+ }
496
+ function isInputCheckboxBlock(block) {
497
+ return block.type === "input-checkbox";
498
+ }
499
+ function isInputSelectBlock(block) {
500
+ return block.type === "input-select";
501
+ }
502
+ function isInputSliderBlock(block) {
503
+ return block.type === "input-slider";
504
+ }
505
+ function isInputFileBlock(block) {
506
+ return block.type === "input-file";
507
+ }
508
+ function isInputDateBlock(block) {
509
+ return block.type === "input-date";
510
+ }
511
+ function isInputDateRangeBlock(block) {
512
+ return block.type === "input-date-range";
513
+ }
514
+
515
+ //#endregion
516
+ //#region src/blocks/sql-utils.ts
517
+ function convertToEnvironmentVariableName(str) {
518
+ return (/^\d/.test(str) ? `_${str}` : str).toUpperCase().replace(/[^\w]/g, "_");
519
+ }
520
+ function getSqlEnvVarName(integrationId) {
521
+ return `SQL_${integrationId}`;
522
+ }
523
+
524
+ //#endregion
525
+ //#region src/blocks/sql-blocks.ts
526
+ function createPythonCodeForSqlBlock(block) {
527
+ const query = block.content;
528
+ const pythonVariableName = block.metadata.deepnote_variable_name;
529
+ const sanitizedPythonVariableName = pythonVariableName !== void 0 ? sanitizePythonVariableName(pythonVariableName) || "input_1" : void 0;
530
+ const returnVariableType = block.metadata.deepnote_return_variable_type ?? "dataframe";
531
+ const integrationId = block.metadata.sql_integration_id;
532
+ const connectionEnvVarName = integrationId ? convertToEnvironmentVariableName(getSqlEnvVarName(integrationId)) : "SQL_ALCHEMY_JSON_ENV_VAR";
533
+ const escapedQuery = escapePythonString(query);
534
+ const dataFrameConfig = createDataFrameConfig(block);
535
+ const executeSqlFunctionCall = ts_dedent.dedent`
536
+ _dntk.execute_sql(
537
+ ${escapedQuery},
538
+ '${connectionEnvVarName}',
539
+ audit_sql_comment='',
540
+ sql_cache_mode='cache_disabled',
541
+ return_variable_type='${returnVariableType}'
542
+ )
543
+ `;
544
+ if (sanitizedPythonVariableName === void 0) return ts_dedent.dedent`
545
+ ${dataFrameConfig}
546
+
547
+ ${executeSqlFunctionCall}
548
+ `;
549
+ return ts_dedent.dedent`
550
+ ${dataFrameConfig}
551
+
552
+ ${sanitizedPythonVariableName} = ${executeSqlFunctionCall}
553
+ ${sanitizedPythonVariableName}
554
+ `;
555
+ }
556
+ function isSqlBlock(block) {
557
+ return block.type === "sql";
558
+ }
559
+
560
+ //#endregion
561
+ //#region src/blocks/visualization-blocks.ts
562
+ function createPythonCodeForVisualizationBlock(block) {
563
+ const variableName = block.metadata.deepnote_variable_name;
564
+ const spec = block.metadata.deepnote_visualization_spec;
565
+ const filters = block.metadata.deepnote_chart_filter?.advancedFilters ?? [];
566
+ if (!variableName || !spec) return "";
567
+ const sanitizedVariableName = sanitizePythonVariableName(variableName);
568
+ return pythonCode.executeVisualization(sanitizedVariableName, JSON.stringify(spec), JSON.stringify(filters));
569
+ }
570
+ function isVisualizationBlock(block) {
571
+ return block.type === "visualization";
572
+ }
573
+
574
+ //#endregion
575
+ //#region src/python-code.ts
576
+ function createPythonCode(block, executionContext) {
577
+ if (isCodeBlock(block)) return createPythonCodeForCodeBlock(block);
578
+ if (isSqlBlock(block)) return createPythonCodeForSqlBlock(block);
579
+ if (isInputTextBlock(block)) return createPythonCodeForInputTextBlock(block);
580
+ if (isInputTextareaBlock(block)) return createPythonCodeForInputTextareaBlock(block);
581
+ if (isInputCheckboxBlock(block)) return createPythonCodeForInputCheckboxBlock(block);
582
+ if (isInputSelectBlock(block)) return createPythonCodeForInputSelectBlock(block);
583
+ if (isInputSliderBlock(block)) return createPythonCodeForInputSliderBlock(block);
584
+ if (isInputFileBlock(block)) return createPythonCodeForInputFileBlock(block);
585
+ if (isInputDateBlock(block)) return createPythonCodeForInputDateBlock(block);
586
+ if (isInputDateRangeBlock(block)) return createPythonCodeForInputDateRangeBlock(block);
587
+ if (isVisualizationBlock(block)) return createPythonCodeForVisualizationBlock(block);
588
+ if (isButtonBlock(block)) return createPythonCodeForButtonBlock(block, executionContext);
589
+ if (isBigNumberBlock(block)) return createPythonCodeForBigNumberBlock(block);
590
+ throw new UnsupportedBlockTypeError(`Creating python code from block type ${block.type} is not supported yet.`);
591
+ }
592
+
593
+ //#endregion
594
+ exports.createMarkdown = createMarkdown;
595
+ exports.createPythonCode = createPythonCode;
596
+ exports.deepnoteBlockSchema = deepnoteBlockSchema;
597
+ exports.deserializeDeepnoteFile = deserializeDeepnoteFile;
598
+ exports.stripMarkdown = stripMarkdown;