-
Notifications
You must be signed in to change notification settings - Fork 132
/
GridFileV1_1.ts
154 lines (145 loc) · 4.92 KB
/
GridFileV1_1.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import z from 'zod';
import { GridFileV1 } from './GridFileV1';
import { DEFAULT_FILE_NAME } from '../constants/app';
import { generateUUID } from '../helpers/generateUUID';
// Shared schemas
const ArrayOutputSchema = z.array(z.union([z.string(), z.number(), z.boolean()]));
const BorderDirectionSchema = z.object({
color: z.string().optional(),
type: z.enum(['line1', 'line2', 'line3', 'dotted', 'dashed', 'double']).optional(),
});
const CoordinateSchema = z.object({
x: z.number(),
y: z.number(),
});
const HeadingSchema = z.object({
id: z.number(),
size: z.number().optional(),
});
// File schema
export const GridFileSchemaV1_1 = z.object({
borders: z
.object({
x: z.number(),
y: z.number(),
horizontal: BorderDirectionSchema.optional(),
vertical: BorderDirectionSchema.optional(),
})
.array(),
cells: z
.object({
x: z.number(),
y: z.number(),
type: z.enum(['TEXT', 'FORMULA', 'JAVASCRIPT', 'PYTHON', 'SQL', 'COMPUTED', 'AI']),
value: z.string(),
array_cells: z.tuple([z.number(), z.number()]).array().optional(), // list of output array cells created by this cell
dependent_cells: z.tuple([z.number(), z.number()]).array().optional(),
evaluation_result: z
.object({
success: z.boolean(),
std_out: z.string().optional(),
std_err: z.string().optional(),
output_value: z.string().or(z.null()).or(z.undefined()),
cells_accessed: z.tuple([z.number(), z.number()]).array(),
array_output: z.union([ArrayOutputSchema, z.array(ArrayOutputSchema)]).optional(), // 1 or 2d array
formatted_code: z.string(),
error_span: z.tuple([z.number(), z.number()]).or(z.null()),
})
.optional(),
formula_code: z.string().optional(),
last_modified: z.string().optional(),
ai_prompt: z.string().optional(),
python_code: z.string().optional(),
})
.array(),
cell_dependency: z.string(),
columns: HeadingSchema.array(),
created: z.number(),
// Note: this is used inside the app, but is overridden when a file is
// imported by either the file's name on disk or the name in the URL
filename: z.string(),
formats: z
.object({
x: z.number(),
y: z.number(),
alignment: z.enum(['right', 'center']).optional(), // default is left
bold: z.boolean().optional(),
fillColor: z.string().optional(),
italic: z.boolean().optional(),
textColor: z.string().optional(),
textFormat: z
.union([
z.object({
type: z.literal('NUMBER'),
decimalPlaces: z.number().optional(),
}),
z.object({
display: z.literal('CURRENCY'),
type: z.literal('CURRENCY'),
symbol: z.string().optional(),
decimalPlaces: z.number().optional(),
}),
z.object({
type: z.literal('PERCENTAGE'),
decimalPlaces: z.number().optional(),
}),
z.object({
type: z.literal('EXPONENTIAL'),
decimalPlaces: z.number().optional(),
}),
])
.optional(),
wrapping: z.enum(['wrap', 'clip']).optional(), // default is overflow
})
.array(),
id: z.string().uuid(),
modified: z.number(),
render_dependency: z
.object({
location: CoordinateSchema,
needToRender: CoordinateSchema.array(), // these are cells that must be rendered when drawing this cell
renderThisCell: CoordinateSchema.array(), // these are cells that render this cell when drawing
})
.array(),
rows: HeadingSchema.array(),
version: z.literal('1.1'),
});
export type GridFileV1_1 = z.infer<typeof GridFileSchemaV1_1>;
/**
* Given a v1 file, update it to a v1_1 file
*/
export function upgradeV1toV1_1(file: GridFileV1): GridFileV1_1 {
const date = Date.now();
// The previous enums for borders were integers but now we use strings
// So we have to change them all, e.g. from "3" to "dotted"
// https://github.com/quadratichq/quadratic/pull/308/files#diff-fb2ecd77a7c43aa1f68a862e8866d079391f51b6ae9665059d523221fdf5256fL44-R41
const enumMapping = {
0: 'line1',
1: 'line2',
2: 'line3',
3: 'dotted',
4: 'dashed',
5: 'double',
};
return {
...file,
borders: file.borders.map((oldBorder) => {
// Make a deep copy, modify as necessary, and return it
const border = JSON.parse(JSON.stringify(oldBorder));
if (typeof border?.horizontal?.type === 'number') {
// @ts-expect-error we know it exists
border.horizontal.type = enumMapping[border.horizontal.type];
}
if (typeof border?.vertical?.type === 'number') {
// @ts-expect-error we know it exists
border.vertical.type = enumMapping[border.vertical.type];
}
return border;
}),
version: '1.1',
modified: date,
created: date,
id: generateUUID(),
filename: DEFAULT_FILE_NAME,
} as GridFileV1_1;
}