instant-cli 0.22.95-experimental.surgical.20386112228.1 → 0.22.95-experimental.surgical.20386732292.1
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/.turbo/turbo-build.log +1 -1
- package/__tests__/__snapshots__/updateSchemaFile.test.ts.snap +244 -0
- package/__tests__/updateSchemaFile.test.ts +295 -64
- package/dist/util/updateSchemaFile.d.ts.map +1 -1
- package/dist/util/updateSchemaFile.js +68 -6
- package/dist/util/updateSchemaFile.js.map +1 -1
- package/package.json +4 -4
- package/src/util/updateSchemaFile.ts +67 -6
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
> instant-cli@0.22.95-experimental.surgical.
|
|
2
|
+
> instant-cli@0.22.95-experimental.surgical.20386732292.1 build /home/runner/work/instant/instant/client/packages/cli
|
|
3
3
|
> rm -rf dist; tsc -p tsconfig.json
|
|
4
4
|
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`adds a link when links object is empty 1`] = `
|
|
4
|
+
"
|
|
5
|
+
import { i } from '@instantdb/core';
|
|
6
|
+
|
|
7
|
+
const _schema = i.schema({
|
|
8
|
+
entities: {
|
|
9
|
+
todos: i.entity({
|
|
10
|
+
title: i.string(),
|
|
11
|
+
}),
|
|
12
|
+
users: i.entity({
|
|
13
|
+
email: i.string(),
|
|
14
|
+
}),
|
|
15
|
+
},
|
|
16
|
+
links: {
|
|
17
|
+
todoOwner: {
|
|
18
|
+
forward: {
|
|
19
|
+
on: 'todos',
|
|
20
|
+
has: 'one',
|
|
21
|
+
label: 'owner',
|
|
22
|
+
},
|
|
23
|
+
reverse: {
|
|
24
|
+
on: 'users',
|
|
25
|
+
has: 'many',
|
|
26
|
+
label: 'todos',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
rooms: {},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export default _schema;
|
|
34
|
+
"
|
|
35
|
+
`;
|
|
36
|
+
|
|
37
|
+
exports[`drops constraints removed by server 1`] = `
|
|
38
|
+
"
|
|
39
|
+
import { i } from '@instantdb/core';
|
|
40
|
+
|
|
41
|
+
const _schema = i.schema({
|
|
42
|
+
entities: {
|
|
43
|
+
todos: i.entity({
|
|
44
|
+
title: i.string(),
|
|
45
|
+
done: i.boolean().optional(),
|
|
46
|
+
}),
|
|
47
|
+
},
|
|
48
|
+
links: {},
|
|
49
|
+
rooms: {},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
export default _schema;
|
|
53
|
+
"
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
exports[`handles quoted keys for entities, attrs, and links 1`] = `
|
|
57
|
+
"
|
|
58
|
+
import { i } from '@instantdb/core';
|
|
59
|
+
|
|
60
|
+
const _schema = i.schema({
|
|
61
|
+
entities: {
|
|
62
|
+
todos: i.entity({
|
|
63
|
+
title: i.string(),
|
|
64
|
+
}),
|
|
65
|
+
users: i.entity({
|
|
66
|
+
email: i.string(),
|
|
67
|
+
}),
|
|
68
|
+
'user-profiles': i.entity({
|
|
69
|
+
'display-name': i.string(),
|
|
70
|
+
'avatar-url': i.string(),
|
|
71
|
+
}),
|
|
72
|
+
},
|
|
73
|
+
links: {
|
|
74
|
+
'todo-owner': {
|
|
75
|
+
forward: {
|
|
76
|
+
on: 'todos',
|
|
77
|
+
has: 'one',
|
|
78
|
+
label: 'owner',
|
|
79
|
+
},
|
|
80
|
+
reverse: {
|
|
81
|
+
on: 'users',
|
|
82
|
+
has: 'many',
|
|
83
|
+
label: 'todos',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
rooms: {},
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
export default _schema;
|
|
91
|
+
"
|
|
92
|
+
`;
|
|
93
|
+
|
|
94
|
+
exports[`inserts attrs into multi-line entities with indentation 1`] = `
|
|
95
|
+
"
|
|
96
|
+
import { i } from '@instantdb/core';
|
|
97
|
+
|
|
98
|
+
const _schema = i.schema({
|
|
99
|
+
entities: {
|
|
100
|
+
todos: i.entity({
|
|
101
|
+
title: i.string(),
|
|
102
|
+
done: i.boolean().optional(),
|
|
103
|
+
priority: i.number(),
|
|
104
|
+
}),
|
|
105
|
+
},
|
|
106
|
+
links: {},
|
|
107
|
+
rooms: {},
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
export default _schema;
|
|
111
|
+
"
|
|
112
|
+
`;
|
|
113
|
+
|
|
114
|
+
exports[`preserves type params across chained calls 1`] = `
|
|
115
|
+
"
|
|
116
|
+
import { i } from '@instantdb/core';
|
|
117
|
+
import { Label } from './types';
|
|
118
|
+
|
|
119
|
+
const _schema = i.schema({
|
|
120
|
+
entities: {
|
|
121
|
+
todos: i.entity({
|
|
122
|
+
title: i.string(),
|
|
123
|
+
status: i.string<'todo' | 'done'>().unique().indexed(),
|
|
124
|
+
labels: i.json<Label[]>(),
|
|
125
|
+
}),
|
|
126
|
+
users: i.entity({
|
|
127
|
+
email: i.string().unique(),
|
|
128
|
+
}),
|
|
129
|
+
},
|
|
130
|
+
links: {},
|
|
131
|
+
rooms: {},
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
export default _schema;
|
|
135
|
+
"
|
|
136
|
+
`;
|
|
137
|
+
|
|
138
|
+
exports[`removes a link with surrounding comments and commas 1`] = `
|
|
139
|
+
"
|
|
140
|
+
import { i } from '@instantdb/core';
|
|
141
|
+
|
|
142
|
+
const _schema = i.schema({
|
|
143
|
+
entities: {
|
|
144
|
+
todos: i.entity({
|
|
145
|
+
title: i.string(),
|
|
146
|
+
}),
|
|
147
|
+
users: i.entity({
|
|
148
|
+
email: i.string(),
|
|
149
|
+
}),
|
|
150
|
+
projects: i.entity({
|
|
151
|
+
name: i.string(),
|
|
152
|
+
}),
|
|
153
|
+
},
|
|
154
|
+
links: {
|
|
155
|
+
// owner link
|
|
156
|
+
/* project link */
|
|
157
|
+
projectTodos: {
|
|
158
|
+
forward: { on: 'projects', has: 'many', label: 'todos' },
|
|
159
|
+
reverse: { on: 'todos', has: 'one', label: 'project' },
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
rooms: {},
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
export default _schema;
|
|
166
|
+
"
|
|
167
|
+
`;
|
|
168
|
+
|
|
169
|
+
exports[`removes the last link cleanly 1`] = `
|
|
170
|
+
"
|
|
171
|
+
import { i } from '@instantdb/core';
|
|
172
|
+
|
|
173
|
+
const _schema = i.schema({
|
|
174
|
+
entities: {
|
|
175
|
+
todos: i.entity({
|
|
176
|
+
title: i.string(),
|
|
177
|
+
}),
|
|
178
|
+
users: i.entity({
|
|
179
|
+
email: i.string(),
|
|
180
|
+
}),
|
|
181
|
+
},
|
|
182
|
+
links: {},
|
|
183
|
+
rooms: {},
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
export default _schema;
|
|
187
|
+
"
|
|
188
|
+
`;
|
|
189
|
+
|
|
190
|
+
exports[`updates link details by forward key 1`] = `
|
|
191
|
+
"
|
|
192
|
+
import { i } from '@instantdb/core';
|
|
193
|
+
|
|
194
|
+
const _schema = i.schema({
|
|
195
|
+
entities: {
|
|
196
|
+
todos: i.entity({
|
|
197
|
+
title: i.string(),
|
|
198
|
+
}),
|
|
199
|
+
users: i.entity({
|
|
200
|
+
email: i.string(),
|
|
201
|
+
}),
|
|
202
|
+
},
|
|
203
|
+
links: {
|
|
204
|
+
todoOwner: {
|
|
205
|
+
forward: {
|
|
206
|
+
on: 'todos',
|
|
207
|
+
has: 'one',
|
|
208
|
+
label: 'owner',
|
|
209
|
+
required: true,
|
|
210
|
+
onDelete: 'cascade',
|
|
211
|
+
},
|
|
212
|
+
reverse: {
|
|
213
|
+
on: 'users',
|
|
214
|
+
has: 'many',
|
|
215
|
+
label: 'todos',
|
|
216
|
+
onDelete: 'cascade',
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
rooms: {},
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
export default _schema;
|
|
224
|
+
"
|
|
225
|
+
`;
|
|
226
|
+
|
|
227
|
+
exports[`updates single-line entity in place 1`] = `
|
|
228
|
+
"
|
|
229
|
+
import { i } from '@instantdb/core';
|
|
230
|
+
|
|
231
|
+
const _schema = i.schema({
|
|
232
|
+
entities: {
|
|
233
|
+
projects: i.entity({ name: i.string(), status: i.string() }),
|
|
234
|
+
todos: i.entity({
|
|
235
|
+
title: i.string(),
|
|
236
|
+
}),
|
|
237
|
+
},
|
|
238
|
+
links: {},
|
|
239
|
+
rooms: {},
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
export default _schema;
|
|
243
|
+
"
|
|
244
|
+
`;
|
|
@@ -2,50 +2,69 @@ import { test, expect } from 'vitest';
|
|
|
2
2
|
import { i, schemaTypescriptFileToInstantSchema } from '@instantdb/platform';
|
|
3
3
|
import { updateSchemaFile } from '../src/util/updateSchemaFile';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
function schemaStr(
|
|
6
|
+
entitiesBlock: string,
|
|
7
|
+
linksBlock: string,
|
|
8
|
+
extraImports = '',
|
|
9
|
+
) {
|
|
10
|
+
const linksSection = linksBlock ? `${linksBlock}\n` : '';
|
|
11
|
+
return `
|
|
7
12
|
import { i } from '@instantdb/core';
|
|
8
|
-
|
|
9
|
-
|
|
13
|
+
${extraImports ? `${extraImports}\n` : ''}
|
|
10
14
|
const _schema = i.schema({
|
|
11
15
|
entities: {
|
|
12
|
-
|
|
13
|
-
title: i.string(),
|
|
14
|
-
status: i.string<'todo' | 'done'>(),
|
|
15
|
-
labels: i.json<Label[]>(),
|
|
16
|
-
}),
|
|
16
|
+
${entitiesBlock}
|
|
17
17
|
},
|
|
18
|
-
links: {
|
|
18
|
+
links: {
|
|
19
|
+
${linksSection} },
|
|
19
20
|
rooms: {},
|
|
20
21
|
});
|
|
21
22
|
|
|
22
23
|
export default _schema;
|
|
23
24
|
`;
|
|
25
|
+
}
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
async function runUpdate(oldFile: string, serverSchema: any) {
|
|
28
|
+
const localSchema = schemaTypescriptFileToInstantSchema(oldFile);
|
|
29
|
+
return updateSchemaFile(oldFile, localSchema, serverSchema);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
test('throws when schema call is missing', async () => {
|
|
33
|
+
const oldFile = `
|
|
34
|
+
import { i } from '@instantdb/core';
|
|
35
|
+
|
|
36
|
+
export const nope = 1;
|
|
37
|
+
`;
|
|
38
|
+
const schema = i.schema({
|
|
39
|
+
entities: { todos: i.entity({ title: i.string() }) },
|
|
36
40
|
links: {},
|
|
37
41
|
});
|
|
42
|
+
await expect(updateSchemaFile(oldFile, schema, schema)).rejects.toThrow(
|
|
43
|
+
'Could not find i.schema',
|
|
44
|
+
);
|
|
45
|
+
});
|
|
38
46
|
|
|
39
|
-
|
|
40
|
-
const
|
|
47
|
+
test('throws when entities object is missing', async () => {
|
|
48
|
+
const oldFile = `
|
|
49
|
+
import { i } from '@instantdb/core';
|
|
41
50
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
expect(result).toContain('projects: i.entity({');
|
|
51
|
+
const _schema = i.schema({
|
|
52
|
+
links: {},
|
|
53
|
+
rooms: {},
|
|
46
54
|
});
|
|
47
55
|
|
|
48
|
-
|
|
56
|
+
export default _schema;
|
|
57
|
+
`;
|
|
58
|
+
const schema = i.schema({
|
|
59
|
+
entities: { todos: i.entity({ title: i.string() }) },
|
|
60
|
+
links: {},
|
|
61
|
+
});
|
|
62
|
+
await expect(updateSchemaFile(oldFile, schema, schema)).rejects.toThrow(
|
|
63
|
+
'entities object',
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('throws when links object is missing', async () => {
|
|
49
68
|
const oldFile = `
|
|
50
69
|
import { i } from '@instantdb/core';
|
|
51
70
|
|
|
@@ -53,67 +72,260 @@ const _schema = i.schema({
|
|
|
53
72
|
entities: {
|
|
54
73
|
todos: i.entity({
|
|
55
74
|
title: i.string(),
|
|
56
|
-
priority: i.number(),
|
|
57
|
-
}),
|
|
58
|
-
oldEntity: i.entity({
|
|
59
|
-
data: i.json(),
|
|
60
75
|
}),
|
|
61
76
|
},
|
|
62
|
-
links: {},
|
|
63
77
|
rooms: {},
|
|
64
78
|
});
|
|
65
79
|
|
|
66
80
|
export default _schema;
|
|
67
81
|
`;
|
|
82
|
+
const schema = i.schema({
|
|
83
|
+
entities: { todos: i.entity({ title: i.string() }) },
|
|
84
|
+
links: {},
|
|
85
|
+
});
|
|
86
|
+
await expect(updateSchemaFile(oldFile, schema, schema)).rejects.toThrow(
|
|
87
|
+
'links object',
|
|
88
|
+
);
|
|
89
|
+
});
|
|
68
90
|
|
|
91
|
+
test('preserves type params across chained calls', async () => {
|
|
92
|
+
const oldFile = schemaStr(
|
|
93
|
+
` todos: i.entity({
|
|
94
|
+
title: i.string(),
|
|
95
|
+
status: i.string<'todo' | 'done'>().optional().indexed(),
|
|
96
|
+
labels: i.json<Label[]>(),
|
|
97
|
+
}),
|
|
98
|
+
users: i.entity({
|
|
99
|
+
email: i.string(),
|
|
100
|
+
}),`,
|
|
101
|
+
'',
|
|
102
|
+
"import { Label } from './types';",
|
|
103
|
+
);
|
|
69
104
|
const serverSchema = i.schema({
|
|
70
105
|
entities: {
|
|
71
106
|
todos: i.entity({
|
|
72
107
|
title: i.string(),
|
|
108
|
+
status: i.string().unique().indexed(),
|
|
109
|
+
labels: i.json(),
|
|
110
|
+
}),
|
|
111
|
+
users: i.entity({
|
|
112
|
+
email: i.string().unique(),
|
|
73
113
|
}),
|
|
74
114
|
},
|
|
75
115
|
links: {},
|
|
76
116
|
});
|
|
77
117
|
|
|
78
|
-
const
|
|
79
|
-
const result = await updateSchemaFile(oldFile, localSchema, serverSchema);
|
|
118
|
+
const result = await runUpdate(oldFile, serverSchema);
|
|
80
119
|
|
|
81
|
-
expect(result).
|
|
82
|
-
expect(result).not.toContain('priority: i.number()');
|
|
83
|
-
expect(result).toContain('title: i.string()');
|
|
120
|
+
expect(result).toMatchSnapshot();
|
|
84
121
|
});
|
|
85
122
|
|
|
86
|
-
test('
|
|
87
|
-
const oldFile =
|
|
88
|
-
|
|
123
|
+
test('drops constraints removed by server', async () => {
|
|
124
|
+
const oldFile = schemaStr(
|
|
125
|
+
` todos: i.entity({
|
|
126
|
+
title: i.string().unique().indexed().optional(),
|
|
127
|
+
done: i.boolean().optional(),
|
|
128
|
+
}),`,
|
|
129
|
+
'',
|
|
130
|
+
);
|
|
131
|
+
const serverSchema = i.schema({
|
|
132
|
+
entities: {
|
|
133
|
+
todos: i.entity({
|
|
134
|
+
title: i.string(),
|
|
135
|
+
done: i.boolean().optional(),
|
|
136
|
+
}),
|
|
137
|
+
},
|
|
138
|
+
links: {},
|
|
139
|
+
});
|
|
89
140
|
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
141
|
+
const result = await runUpdate(oldFile, serverSchema);
|
|
142
|
+
|
|
143
|
+
expect(result).toMatchSnapshot();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test('updates link details by forward key', async () => {
|
|
147
|
+
const oldFile = schemaStr(
|
|
148
|
+
` todos: i.entity({
|
|
93
149
|
title: i.string(),
|
|
94
|
-
status: i.string<'todo' | 'done'>(),
|
|
95
150
|
}),
|
|
96
151
|
users: i.entity({
|
|
97
152
|
email: i.string(),
|
|
153
|
+
}),`,
|
|
154
|
+
` todoOwner: {
|
|
155
|
+
forward: { on: 'todos', has: 'one', label: 'owner' },
|
|
156
|
+
reverse: { on: 'users', has: 'many', label: 'todos' },
|
|
157
|
+
},`,
|
|
158
|
+
);
|
|
159
|
+
const serverSchema = i.schema({
|
|
160
|
+
entities: {
|
|
161
|
+
todos: i.entity({ title: i.string() }),
|
|
162
|
+
users: i.entity({ email: i.string() }),
|
|
163
|
+
},
|
|
164
|
+
links: {
|
|
165
|
+
todoOwner: {
|
|
166
|
+
forward: {
|
|
167
|
+
on: 'todos',
|
|
168
|
+
has: 'one',
|
|
169
|
+
label: 'owner',
|
|
170
|
+
required: true,
|
|
171
|
+
onDelete: 'cascade',
|
|
172
|
+
},
|
|
173
|
+
reverse: {
|
|
174
|
+
on: 'users',
|
|
175
|
+
has: 'many',
|
|
176
|
+
label: 'todos',
|
|
177
|
+
onDelete: 'cascade',
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
const result = await runUpdate(oldFile, serverSchema);
|
|
184
|
+
|
|
185
|
+
expect(result).toMatchSnapshot();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test('removes a link with surrounding comments and commas', async () => {
|
|
189
|
+
const oldFile = schemaStr(
|
|
190
|
+
` todos: i.entity({
|
|
191
|
+
title: i.string(),
|
|
98
192
|
}),
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
193
|
+
users: i.entity({
|
|
194
|
+
email: i.string(),
|
|
195
|
+
}),
|
|
196
|
+
projects: i.entity({
|
|
197
|
+
name: i.string(),
|
|
198
|
+
}),`,
|
|
199
|
+
` // owner link
|
|
200
|
+
todoOwner: {
|
|
201
|
+
forward: { on: 'todos', has: 'one', label: 'owner' },
|
|
202
|
+
reverse: { on: 'users', has: 'many', label: 'todos' },
|
|
203
|
+
},
|
|
204
|
+
/* project link */
|
|
205
|
+
projectTodos: {
|
|
206
|
+
forward: { on: 'projects', has: 'many', label: 'todos' },
|
|
207
|
+
reverse: { on: 'todos', has: 'one', label: 'project' },
|
|
208
|
+
},`,
|
|
209
|
+
);
|
|
210
|
+
const serverSchema = i.schema({
|
|
211
|
+
entities: {
|
|
212
|
+
todos: i.entity({ title: i.string() }),
|
|
213
|
+
users: i.entity({ email: i.string() }),
|
|
214
|
+
projects: i.entity({ name: i.string() }),
|
|
215
|
+
},
|
|
216
|
+
links: {
|
|
217
|
+
projectTodos: {
|
|
218
|
+
forward: { on: 'projects', has: 'many', label: 'todos' },
|
|
219
|
+
reverse: { on: 'todos', has: 'one', label: 'project' },
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
const result = await runUpdate(oldFile, serverSchema);
|
|
225
|
+
|
|
226
|
+
expect(result).toMatchSnapshot();
|
|
102
227
|
});
|
|
103
228
|
|
|
104
|
-
|
|
105
|
-
|
|
229
|
+
test('updates single-line entity in place', async () => {
|
|
230
|
+
const oldFile = schemaStr(
|
|
231
|
+
` projects: i.entity({ name: i.string() }),
|
|
232
|
+
todos: i.entity({
|
|
233
|
+
title: i.string(),
|
|
234
|
+
}),`,
|
|
235
|
+
'',
|
|
236
|
+
);
|
|
237
|
+
const serverSchema = i.schema({
|
|
238
|
+
entities: {
|
|
239
|
+
projects: i.entity({
|
|
240
|
+
name: i.string(),
|
|
241
|
+
status: i.string(),
|
|
242
|
+
}),
|
|
243
|
+
todos: i.entity({
|
|
244
|
+
title: i.string(),
|
|
245
|
+
}),
|
|
246
|
+
},
|
|
247
|
+
links: {},
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
const result = await runUpdate(oldFile, serverSchema);
|
|
251
|
+
|
|
252
|
+
expect(result).toMatchSnapshot();
|
|
253
|
+
});
|
|
106
254
|
|
|
255
|
+
test('inserts attrs into multi-line entities with indentation', async () => {
|
|
256
|
+
const oldFile = schemaStr(
|
|
257
|
+
` todos: i.entity({
|
|
258
|
+
title: i.string(),
|
|
259
|
+
done: i.boolean().optional(),
|
|
260
|
+
}),`,
|
|
261
|
+
'',
|
|
262
|
+
);
|
|
107
263
|
const serverSchema = i.schema({
|
|
108
264
|
entities: {
|
|
109
265
|
todos: i.entity({
|
|
110
|
-
title: i.string()
|
|
111
|
-
|
|
266
|
+
title: i.string(),
|
|
267
|
+
done: i.boolean().optional(),
|
|
268
|
+
priority: i.number(),
|
|
112
269
|
}),
|
|
113
|
-
|
|
114
|
-
|
|
270
|
+
},
|
|
271
|
+
links: {},
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const result = await runUpdate(oldFile, serverSchema);
|
|
275
|
+
|
|
276
|
+
expect(result).toMatchSnapshot();
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
test('handles quoted keys for entities, attrs, and links', async () => {
|
|
280
|
+
const oldFile = schemaStr(
|
|
281
|
+
` todos: i.entity({
|
|
282
|
+
title: i.string(),
|
|
283
|
+
}),
|
|
284
|
+
users: i.entity({
|
|
285
|
+
email: i.string(),
|
|
286
|
+
}),
|
|
287
|
+
'user-profiles': i.entity({
|
|
288
|
+
'display-name': i.string(),
|
|
289
|
+
}),`,
|
|
290
|
+
'',
|
|
291
|
+
);
|
|
292
|
+
const serverSchema = i.schema({
|
|
293
|
+
entities: {
|
|
294
|
+
todos: i.entity({ title: i.string() }),
|
|
295
|
+
users: i.entity({ email: i.string() }),
|
|
296
|
+
'user-profiles': i.entity({
|
|
297
|
+
'display-name': i.string(),
|
|
298
|
+
'avatar-url': i.string(),
|
|
115
299
|
}),
|
|
116
300
|
},
|
|
301
|
+
links: {
|
|
302
|
+
'todo-owner': {
|
|
303
|
+
forward: { on: 'todos', has: 'one', label: 'owner' },
|
|
304
|
+
reverse: { on: 'users', has: 'many', label: 'todos' },
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
const result = await runUpdate(oldFile, serverSchema);
|
|
310
|
+
|
|
311
|
+
expect(result).toMatchSnapshot();
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
test('adds a link when links object is empty', async () => {
|
|
315
|
+
const oldFile = schemaStr(
|
|
316
|
+
` todos: i.entity({
|
|
317
|
+
title: i.string(),
|
|
318
|
+
}),
|
|
319
|
+
users: i.entity({
|
|
320
|
+
email: i.string(),
|
|
321
|
+
}),`,
|
|
322
|
+
'',
|
|
323
|
+
);
|
|
324
|
+
const serverSchema = i.schema({
|
|
325
|
+
entities: {
|
|
326
|
+
todos: i.entity({ title: i.string() }),
|
|
327
|
+
users: i.entity({ email: i.string() }),
|
|
328
|
+
},
|
|
117
329
|
links: {
|
|
118
330
|
todoOwner: {
|
|
119
331
|
forward: { on: 'todos', has: 'one', label: 'owner' },
|
|
@@ -122,14 +334,33 @@ export default _schema;
|
|
|
122
334
|
},
|
|
123
335
|
});
|
|
124
336
|
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
337
|
+
const result = await runUpdate(oldFile, serverSchema);
|
|
338
|
+
|
|
339
|
+
expect(result).toMatchSnapshot();
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
test('removes the last link cleanly', async () => {
|
|
343
|
+
const oldFile = schemaStr(
|
|
344
|
+
` todos: i.entity({
|
|
345
|
+
title: i.string(),
|
|
346
|
+
}),
|
|
347
|
+
users: i.entity({
|
|
348
|
+
email: i.string(),
|
|
349
|
+
}),`,
|
|
350
|
+
` todoOwner: {
|
|
351
|
+
forward: { on: 'todos', has: 'one', label: 'owner' },
|
|
352
|
+
reverse: { on: 'users', has: 'many', label: 'todos' },
|
|
353
|
+
},`,
|
|
354
|
+
);
|
|
355
|
+
const serverSchema = i.schema({
|
|
356
|
+
entities: {
|
|
357
|
+
todos: i.entity({ title: i.string() }),
|
|
358
|
+
users: i.entity({ email: i.string() }),
|
|
359
|
+
},
|
|
360
|
+
links: {},
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
const result = await runUpdate(oldFile, serverSchema);
|
|
364
|
+
|
|
365
|
+
expect(result).toMatchSnapshot();
|
|
135
366
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updateSchemaFile.d.ts","sourceRoot":"","sources":["../../src/util/updateSchemaFile.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAe,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAKrE,wBAAsB,gBAAgB,CACpC,mBAAmB,EAAE,MAAM,EAC3B,WAAW,EAAE,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAC5C,YAAY,EAAE,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAC5C,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"updateSchemaFile.d.ts","sourceRoot":"","sources":["../../src/util/updateSchemaFile.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAe,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAKrE,wBAAsB,gBAAgB,CACpC,mBAAmB,EAAE,MAAM,EAC3B,WAAW,EAAE,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAC5C,YAAY,EAAE,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAC5C,OAAO,CAAC,MAAM,CAAC,CAoDjB"}
|
|
@@ -30,7 +30,8 @@ export function updateSchemaFile(existingFileContent, localSchema, serverSchema)
|
|
|
30
30
|
const edits = [];
|
|
31
31
|
edits.push(...collectEntityEdits(existingFileContent, entitiesObj, entitiesByName, changeBuckets, serverSchema));
|
|
32
32
|
edits.push(...collectLinkEdits(existingFileContent, linksObj, changeBuckets, localLinksByForward, serverLinksByForward));
|
|
33
|
-
|
|
33
|
+
const updated = applyEdits(existingFileContent, edits);
|
|
34
|
+
return normalizeEmptyLinksObject(updated);
|
|
34
35
|
});
|
|
35
36
|
}
|
|
36
37
|
function parseFile(content) {
|
|
@@ -177,10 +178,11 @@ function collectLinkEdits(content, linksObj, changeBuckets, localLinksByForward,
|
|
|
177
178
|
if (!linkProp)
|
|
178
179
|
continue;
|
|
179
180
|
const nextValue = renderLinkValue(serverLink.link);
|
|
181
|
+
const propIndent = getLineIndent(content, linkProp.start);
|
|
180
182
|
edits.push({
|
|
181
183
|
start: linkProp.value.start,
|
|
182
184
|
end: linkProp.value.end,
|
|
183
|
-
text: nextValue,
|
|
185
|
+
text: indentValueAfterFirstLine(nextValue, propIndent),
|
|
184
186
|
});
|
|
185
187
|
}
|
|
186
188
|
return edits;
|
|
@@ -430,6 +432,11 @@ function insertProperty(source, obj, propText, indent) {
|
|
|
430
432
|
const props = obj.properties.filter(isProperty);
|
|
431
433
|
const closingBrace = obj.end - 1;
|
|
432
434
|
const propTextWithIndent = indentLines(propText, indent);
|
|
435
|
+
const propTextSingleLine = propText.trim();
|
|
436
|
+
const innerStart = obj.start + 1;
|
|
437
|
+
const innerEnd = closingBrace;
|
|
438
|
+
const innerContent = source.slice(innerStart, innerEnd);
|
|
439
|
+
const innerWhitespaceOnly = /^[\s]*$/.test(innerContent);
|
|
433
440
|
if (props.length === 0) {
|
|
434
441
|
const objSource = source.slice(obj.start, obj.end);
|
|
435
442
|
const multiline = objSource.includes('\n') || propText.includes('\n');
|
|
@@ -437,10 +444,17 @@ function insertProperty(source, obj, propText, indent) {
|
|
|
437
444
|
return {
|
|
438
445
|
start: closingBrace,
|
|
439
446
|
end: closingBrace,
|
|
440
|
-
text: ` ${
|
|
447
|
+
text: ` ${propTextSingleLine} `,
|
|
441
448
|
};
|
|
442
449
|
}
|
|
443
450
|
const closingIndent = getLineIndent(source, closingBrace);
|
|
451
|
+
if (innerWhitespaceOnly) {
|
|
452
|
+
return {
|
|
453
|
+
start: innerStart,
|
|
454
|
+
end: innerEnd,
|
|
455
|
+
text: `\n${propTextWithIndent},\n${closingIndent}`,
|
|
456
|
+
};
|
|
457
|
+
}
|
|
444
458
|
return {
|
|
445
459
|
start: closingBrace,
|
|
446
460
|
end: closingBrace,
|
|
@@ -448,14 +462,18 @@ function insertProperty(source, obj, propText, indent) {
|
|
|
448
462
|
};
|
|
449
463
|
}
|
|
450
464
|
const lastProp = props[props.length - 1];
|
|
451
|
-
const multiline = source.slice(lastProp.end, closingBrace).includes('\n')
|
|
465
|
+
const multiline = source.slice(lastProp.end, closingBrace).includes('\n') ||
|
|
466
|
+
propText.includes('\n');
|
|
452
467
|
const needsComma = !hasTrailingComma(source, lastProp.end, obj.end);
|
|
453
468
|
if (!multiline) {
|
|
454
|
-
|
|
469
|
+
let insertPos = closingBrace;
|
|
470
|
+
while (insertPos > lastProp.end && /\s/.test(source[insertPos - 1])) {
|
|
471
|
+
insertPos -= 1;
|
|
472
|
+
}
|
|
455
473
|
return {
|
|
456
474
|
start: insertPos,
|
|
457
475
|
end: insertPos,
|
|
458
|
-
text: `${needsComma ? ',' : ''} ${
|
|
476
|
+
text: `${needsComma ? ',' : ''} ${propTextSingleLine}`,
|
|
459
477
|
};
|
|
460
478
|
}
|
|
461
479
|
const lineStart = source.lastIndexOf('\n', closingBrace);
|
|
@@ -468,6 +486,12 @@ function insertProperty(source, obj, propText, indent) {
|
|
|
468
486
|
function removeProperty(source, obj, prop) {
|
|
469
487
|
let start = prop.start;
|
|
470
488
|
let end = prop.end;
|
|
489
|
+
const lineStart = source.lastIndexOf('\n', start - 1) + 1;
|
|
490
|
+
let shouldTrimLineEnd = false;
|
|
491
|
+
if (/^[\t ]*$/.test(source.slice(lineStart, start))) {
|
|
492
|
+
start = lineStart;
|
|
493
|
+
shouldTrimLineEnd = true;
|
|
494
|
+
}
|
|
471
495
|
const after = skipWhitespaceAndComments(source, end, obj.end);
|
|
472
496
|
if (source[after] === ',') {
|
|
473
497
|
end = after + 1;
|
|
@@ -478,8 +502,46 @@ function removeProperty(source, obj, prop) {
|
|
|
478
502
|
start = before;
|
|
479
503
|
}
|
|
480
504
|
}
|
|
505
|
+
if (shouldTrimLineEnd) {
|
|
506
|
+
const lineEnd = source.indexOf('\n', end);
|
|
507
|
+
if (lineEnd !== -1 && /^[\t ]*$/.test(source.slice(end, lineEnd))) {
|
|
508
|
+
end = lineEnd + 1;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
481
511
|
return { start, end, text: '' };
|
|
482
512
|
}
|
|
513
|
+
function indentValueAfterFirstLine(value, indent) {
|
|
514
|
+
const lines = value.split('\n');
|
|
515
|
+
if (lines.length <= 1)
|
|
516
|
+
return value;
|
|
517
|
+
return [
|
|
518
|
+
lines[0],
|
|
519
|
+
...lines.slice(1).map((line) => (line ? indent + line : line)),
|
|
520
|
+
].join('\n');
|
|
521
|
+
}
|
|
522
|
+
function normalizeEmptyLinksObject(content) {
|
|
523
|
+
let ast;
|
|
524
|
+
try {
|
|
525
|
+
ast = parseFile(content);
|
|
526
|
+
}
|
|
527
|
+
catch (_a) {
|
|
528
|
+
return content;
|
|
529
|
+
}
|
|
530
|
+
const schemaObj = findSchemaObject(ast);
|
|
531
|
+
if (!schemaObj)
|
|
532
|
+
return content;
|
|
533
|
+
const linksProp = findObjectProperty(schemaObj, 'links');
|
|
534
|
+
if (!linksProp || !isObjectExpression(linksProp.value))
|
|
535
|
+
return content;
|
|
536
|
+
if (linksProp.value.properties.some(isProperty))
|
|
537
|
+
return content;
|
|
538
|
+
const inner = content.slice(linksProp.value.start + 1, linksProp.value.end - 1);
|
|
539
|
+
if (!/^[\s]*$/.test(inner))
|
|
540
|
+
return content;
|
|
541
|
+
return (content.slice(0, linksProp.value.start) +
|
|
542
|
+
'{}' +
|
|
543
|
+
content.slice(linksProp.value.end));
|
|
544
|
+
}
|
|
483
545
|
function hasTrailingComma(source, afterPos, endPos) {
|
|
484
546
|
const next = skipWhitespaceAndComments(source, afterPos, endPos);
|
|
485
547
|
return source[next] === ',';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updateSchemaFile.js","sourceRoot":"","sources":["../../src/util/updateSchemaFile.ts"],"names":[],"mappings":"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","sourcesContent":["import * as acorn from 'acorn';\nimport { tsPlugin } from 'acorn-typescript';\nimport {\n diffSchemas,\n renderAttrCall,\n renderAttrProperty,\n renderEntityProperty,\n renderLinkProperty,\n renderLinkValue,\n type MigrationTx,\n} from '@instantdb/platform';\nimport type { DataAttrDef, InstantSchemaDef } from '@instantdb/core';\n\nconst parser = (acorn.Parser as any).extend(tsPlugin({ dts: false }) as any);\nconst DEFAULT_INDENT = ' ';\n\nexport async function updateSchemaFile(\n existingFileContent: string,\n localSchema: InstantSchemaDef<any, any, any>,\n serverSchema: InstantSchemaDef<any, any, any>,\n): Promise<string> {\n const ast = parseFile(existingFileContent);\n const schemaObj = findSchemaObject(ast);\n if (!schemaObj) {\n throw new Error('Could not find i.schema(...) in schema file.');\n }\n\n const { entitiesObj, linksObj } = getSchemaSections(schemaObj);\n const diff = await diffSchemas(\n localSchema,\n serverSchema,\n async (created) => created,\n {},\n );\n if (diff.length === 0) {\n return existingFileContent;\n }\n\n const { entitiesByName } = buildEntitiesIndex(entitiesObj);\n\n const { localLinksByForward, serverLinksByForward } = buildLinkMaps(\n localSchema.links || {},\n serverSchema.links || {},\n );\n const changeBuckets = collectChanges(\n diff,\n localLinksByForward,\n serverLinksByForward,\n );\n\n const edits: Edit[] = [];\n edits.push(\n ...collectEntityEdits(\n existingFileContent,\n entitiesObj,\n entitiesByName,\n changeBuckets,\n serverSchema,\n ),\n );\n edits.push(\n ...collectLinkEdits(\n existingFileContent,\n linksObj,\n changeBuckets,\n localLinksByForward,\n serverLinksByForward,\n ),\n );\n\n return applyEdits(existingFileContent, edits);\n}\n\ntype ObjectExpression = {\n type: 'ObjectExpression';\n start: number;\n end: number;\n properties: any[];\n};\n\ntype PropertyNode = {\n type: 'Property';\n start: number;\n end: number;\n key: any;\n value: any;\n};\n\ntype EntityInfo = {\n prop: PropertyNode;\n attrsObj: ObjectExpression;\n attrsByName: Map<string, PropertyNode>;\n};\n\ntype Edit = { start: number; end: number; text: string };\n\ntype ChangeBuckets = {\n createEntities: Set<string>;\n deleteEntities: Set<string>;\n addAttrs: Map<string, Set<string>>;\n deleteAttrs: Map<string, Set<string>>;\n updateAttrs: Map<string, Set<string>>;\n addLinks: Set<string>;\n deleteLinks: Set<string>;\n updateLinks: Set<string>;\n};\n\ntype LinkMap = Map<string, { name: string; link: any }>;\n\nfunction parseFile(content: string) {\n return parser.parse(content, {\n sourceType: 'module',\n ecmaVersion: 'latest',\n });\n}\n\nfunction getSchemaSections(schemaObj: ObjectExpression) {\n const entitiesProp = findObjectProperty(schemaObj, 'entities');\n if (!entitiesProp || !isObjectExpression(entitiesProp.value)) {\n throw new Error('Could not find entities object in schema file.');\n }\n const linksProp = findObjectProperty(schemaObj, 'links');\n if (!linksProp || !isObjectExpression(linksProp.value)) {\n throw new Error('Could not find links object in schema file.');\n }\n\n return {\n entitiesObj: entitiesProp.value,\n linksObj: linksProp.value,\n };\n}\n\nfunction buildEntitiesIndex(entitiesObj: ObjectExpression) {\n const entitiesByName = new Map<string, EntityInfo>();\n\n for (const prop of entitiesObj.properties) {\n if (!isProperty(prop)) continue;\n const name = getPropName(prop);\n if (!name) continue;\n const attrsObj = getEntityAttrsObject(prop.value);\n if (!attrsObj) continue;\n\n const attrsByName = new Map<string, PropertyNode>();\n for (const attrProp of attrsObj.properties) {\n if (!isProperty(attrProp)) continue;\n const attrName = getPropName(attrProp);\n if (!attrName) continue;\n attrsByName.set(attrName, attrProp);\n }\n\n entitiesByName.set(name, { prop, attrsObj, attrsByName });\n }\n\n return { entitiesByName };\n}\n\nfunction buildLinkMaps(\n localLinks: Record<string, any>,\n serverLinks: Record<string, any>,\n) {\n return {\n localLinksByForward: buildLinkForwardMap(localLinks),\n serverLinksByForward: buildLinkForwardMap(serverLinks),\n };\n}\n\nfunction collectEntityEdits(\n content: string,\n entitiesObj: ObjectExpression,\n entitiesByName: Map<string, EntityInfo>,\n changeBuckets: ChangeBuckets,\n serverSchema: InstantSchemaDef<any, any, any>,\n): Edit[] {\n const edits: Edit[] = [];\n\n for (const entityName of changeBuckets.deleteEntities) {\n const entity = entitiesByName.get(entityName);\n if (!entity) continue;\n edits.push(removeProperty(content, entitiesObj, entity.prop));\n }\n\n for (const entityName of changeBuckets.createEntities) {\n if (entitiesByName.has(entityName)) continue;\n const entityDef = serverSchema.entities?.[entityName];\n if (!entityDef) continue;\n const propText = renderEntityProperty(entityName, entityDef.attrs);\n const indent = getObjectPropIndent(content, entitiesObj);\n edits.push(insertProperty(content, entitiesObj, propText, indent));\n }\n\n for (const [entityName, attrs] of changeBuckets.deleteAttrs) {\n const entity = entitiesByName.get(entityName);\n if (!entity) continue;\n for (const attrName of attrs) {\n const attrProp = entity.attrsByName.get(attrName);\n if (!attrProp) continue;\n edits.push(removeProperty(content, entity.attrsObj, attrProp));\n }\n }\n\n for (const [entityName, attrs] of changeBuckets.addAttrs) {\n const entity = entitiesByName.get(entityName);\n if (!entity) continue;\n const entityDef = serverSchema.entities?.[entityName];\n if (!entityDef) continue;\n const indent = getObjectPropIndent(content, entity.attrsObj);\n for (const attrName of attrs) {\n const attrDef = entityDef.attrs?.[attrName];\n if (!attrDef) continue;\n const propText = renderAttrProperty(attrName, attrDef);\n edits.push(insertProperty(content, entity.attrsObj, propText, indent));\n }\n }\n\n for (const [entityName, attrs] of changeBuckets.updateAttrs) {\n const entity = entitiesByName.get(entityName);\n if (!entity) continue;\n const entityDef = serverSchema.entities?.[entityName];\n if (!entityDef) continue;\n for (const attrName of attrs) {\n const attrProp = entity.attrsByName.get(attrName);\n const attrDef = entityDef.attrs?.[attrName];\n if (!attrProp || !attrDef) continue;\n edits.push(updateAttrEdit(content, attrProp, attrDef));\n }\n }\n\n return edits;\n}\n\nfunction collectLinkEdits(\n content: string,\n linksObj: ObjectExpression,\n changeBuckets: ChangeBuckets,\n localLinksByForward: LinkMap,\n serverLinksByForward: LinkMap,\n): Edit[] {\n const edits: Edit[] = [];\n\n for (const forwardKey of changeBuckets.deleteLinks) {\n const localLink = localLinksByForward.get(forwardKey);\n if (!localLink) continue;\n const linkProp = findObjectProperty(linksObj, localLink.name);\n if (!linkProp) continue;\n edits.push(removeProperty(content, linksObj, linkProp));\n }\n\n for (const forwardKey of changeBuckets.addLinks) {\n const serverLink = serverLinksByForward.get(forwardKey);\n if (!serverLink) continue;\n const linkName = serverLink.name;\n if (findObjectProperty(linksObj, linkName)) continue;\n const propText = renderLinkProperty(linkName, serverLink.link);\n const indent = getObjectPropIndent(content, linksObj);\n edits.push(insertProperty(content, linksObj, propText, indent));\n }\n\n for (const forwardKey of changeBuckets.updateLinks) {\n const serverLink = serverLinksByForward.get(forwardKey);\n const localLink = localLinksByForward.get(forwardKey);\n if (!serverLink || !localLink) continue;\n const linkProp = findObjectProperty(linksObj, localLink.name);\n if (!linkProp) continue;\n const nextValue = renderLinkValue(serverLink.link);\n edits.push({\n start: linkProp.value.start,\n end: linkProp.value.end,\n text: nextValue,\n });\n }\n\n return edits;\n}\n\nfunction updateAttrEdit(\n content: string,\n attrProp: PropertyNode,\n attrDef: DataAttrDef<string, boolean, boolean>,\n): Edit {\n const { typeParams } = analyzeChain(attrProp.value);\n const typeParamsText = typeParams\n ? content.slice(typeParams.start, typeParams.end)\n : null;\n const nextValue = renderAttrCall(attrDef, typeParamsText);\n return {\n start: attrProp.value.start,\n end: attrProp.value.end,\n text: nextValue,\n };\n}\n\nfunction applyEdits(content: string, edits: Edit[]) {\n if (edits.length === 0) {\n return content;\n }\n const sorted = [...edits].sort((a, b) => b.start - a.start);\n let output = content;\n for (const edit of sorted) {\n output = output.slice(0, edit.start) + edit.text + output.slice(edit.end);\n }\n return output;\n}\n\nfunction collectChanges(\n steps: MigrationTx[],\n localLinksByForward: LinkMap,\n serverLinksByForward: LinkMap,\n): ChangeBuckets {\n const buckets: ChangeBuckets = {\n createEntities: new Set(),\n deleteEntities: new Set(),\n addAttrs: new Map(),\n deleteAttrs: new Map(),\n updateAttrs: new Map(),\n addLinks: new Set(),\n deleteLinks: new Set(),\n updateLinks: new Set(),\n };\n\n for (const step of steps) {\n const namespace = step.identifier.namespace;\n const attrName = step.identifier.attrName;\n const forwardKey = `${namespace}.${attrName}`;\n\n switch (step.type) {\n case 'add-attr': {\n if (attrName === 'id') {\n buckets.createEntities.add(namespace);\n break;\n }\n if (step['value-type'] === 'ref') {\n buckets.addLinks.add(forwardKey);\n break;\n }\n ensureSet(buckets.addAttrs, namespace).add(attrName);\n break;\n }\n case 'delete-attr': {\n if (attrName === 'id') {\n buckets.deleteEntities.add(namespace);\n break;\n }\n if (localLinksByForward.has(forwardKey)) {\n buckets.deleteLinks.add(forwardKey);\n break;\n }\n ensureSet(buckets.deleteAttrs, namespace).add(attrName);\n break;\n }\n case 'update-attr': {\n if (step.partialAttr?.['value-type'] === 'ref') {\n buckets.updateLinks.add(forwardKey);\n break;\n }\n ensureSet(buckets.updateAttrs, namespace).add(attrName);\n break;\n }\n case 'index':\n case 'remove-index':\n case 'unique':\n case 'remove-unique':\n case 'required':\n case 'remove-required':\n case 'check-data-type':\n case 'remove-data-type': {\n if (serverLinksByForward.has(forwardKey)) {\n buckets.updateLinks.add(forwardKey);\n break;\n }\n ensureSet(buckets.updateAttrs, namespace).add(attrName);\n break;\n }\n default: {\n assertNever(step);\n }\n }\n }\n\n pruneNamespaceBuckets(buckets);\n return buckets;\n}\n\nfunction ensureSet(map: Map<string, Set<string>>, key: string) {\n if (!map.has(key)) map.set(key, new Set());\n return map.get(key)!;\n}\n\nfunction pruneNamespaceBuckets(buckets: ChangeBuckets) {\n const namespaces = new Set<string>([\n ...buckets.createEntities,\n ...buckets.deleteEntities,\n ]);\n\n for (const namespace of namespaces) {\n buckets.addAttrs.delete(namespace);\n buckets.deleteAttrs.delete(namespace);\n buckets.updateAttrs.delete(namespace);\n removeNamespaceLinks(buckets.addLinks, namespace);\n removeNamespaceLinks(buckets.deleteLinks, namespace);\n removeNamespaceLinks(buckets.updateLinks, namespace);\n }\n}\n\nfunction removeNamespaceLinks(set: Set<string>, namespace: string) {\n const prefix = `${namespace}.`;\n for (const key of Array.from(set)) {\n if (key.startsWith(prefix)) {\n set.delete(key);\n }\n }\n}\n\nfunction assertNever(value: never): never {\n throw new Error(`Unhandled migration step: ${JSON.stringify(value)}`);\n}\n\nfunction analyzeChain(node: any): { typeParams: acorn.Node | null } {\n let curr = node;\n let typeParams: acorn.Node | null = null;\n\n while (curr?.type === 'CallExpression') {\n if (curr.typeParameters) {\n typeParams = curr.typeParameters;\n }\n if (curr.callee?.type === 'MemberExpression') {\n curr = curr.callee.object;\n } else {\n break;\n }\n }\n return { typeParams };\n}\n\nfunction findSchemaObject(ast: any): ObjectExpression | null {\n let schemaObj: ObjectExpression | null = null;\n const walk = (node: any) => {\n if (!node || schemaObj) return;\n if (\n node.type === 'CallExpression' &&\n node.callee?.type === 'MemberExpression' &&\n node.callee.object?.type === 'Identifier' &&\n node.callee.object.name === 'i' &&\n node.callee.property?.name === 'schema' &&\n node.arguments?.length > 0\n ) {\n const arg = node.arguments[0];\n if (isObjectExpression(arg)) {\n schemaObj = arg;\n }\n return;\n }\n for (const key in node) {\n if (key === 'loc' || key === 'start' || key === 'end') continue;\n const value = node[key];\n if (!value || typeof value !== 'object') continue;\n if (Array.isArray(value)) {\n value.forEach(walk);\n } else {\n walk(value);\n }\n }\n };\n walk(ast);\n return schemaObj;\n}\n\nfunction findObjectProperty(\n obj: ObjectExpression,\n name: string,\n): PropertyNode | null {\n for (const prop of obj.properties) {\n if (!isProperty(prop)) continue;\n const propName = getPropName(prop);\n if (propName === name) return prop;\n }\n return null;\n}\n\nfunction getEntityAttrsObject(value: any): ObjectExpression | null {\n if (\n value?.type !== 'CallExpression' ||\n value.callee?.type !== 'MemberExpression' ||\n value.callee.object?.type !== 'Identifier' ||\n value.callee.object.name !== 'i' ||\n value.callee.property?.name !== 'entity'\n ) {\n return null;\n }\n const attrsObj = value.arguments?.[0];\n return isObjectExpression(attrsObj) ? attrsObj : null;\n}\n\nfunction buildLinkForwardMap(links: Record<string, any>) {\n const map = new Map<string, { name: string; link: any }>();\n for (const [name, link] of Object.entries(links || {})) {\n map.set(linkForwardKey(link), { name, link });\n }\n return map;\n}\n\nfunction linkForwardKey(link: any) {\n return `${link.forward.on}.${link.forward.label}`;\n}\n\nfunction isObjectExpression(node: any): node is ObjectExpression {\n return node?.type === 'ObjectExpression';\n}\n\nfunction isProperty(node: any): node is PropertyNode {\n return node?.type === 'Property';\n}\n\nfunction getPropName(prop: PropertyNode) {\n if (prop.key.type === 'Identifier') return prop.key.name;\n if (prop.key.type === 'Literal') return String(prop.key.value);\n return null;\n}\n\nfunction indentLines(text: string, indent: string) {\n return text\n .split('\\n')\n .map((line) => (line.length ? indent + line : line))\n .join('\\n');\n}\n\nfunction getObjectPropIndent(source: string, obj: ObjectExpression) {\n const props = obj.properties.filter(isProperty);\n if (props.length > 0) {\n return getLineIndent(source, props[0].start);\n }\n const closingIndent = getLineIndent(source, obj.end - 1);\n return closingIndent + DEFAULT_INDENT;\n}\n\nfunction getLineIndent(source: string, pos: number) {\n const lineStart = source.lastIndexOf('\\n', pos - 1) + 1;\n const match = source.slice(lineStart, pos).match(/^[\\t ]*/);\n return match ? match[0] : '';\n}\n\nfunction insertProperty(\n source: string,\n obj: ObjectExpression,\n propText: string,\n indent: string,\n) {\n const props = obj.properties.filter(isProperty);\n const closingBrace = obj.end - 1;\n const propTextWithIndent = indentLines(propText, indent);\n\n if (props.length === 0) {\n const objSource = source.slice(obj.start, obj.end);\n const multiline = objSource.includes('\\n') || propText.includes('\\n');\n if (!multiline) {\n return {\n start: closingBrace,\n end: closingBrace,\n text: ` ${propTextWithIndent} `,\n };\n }\n const closingIndent = getLineIndent(source, closingBrace);\n return {\n start: closingBrace,\n end: closingBrace,\n text: `\\n${propTextWithIndent},\\n${closingIndent}`,\n };\n }\n\n const lastProp = props[props.length - 1];\n const multiline = source.slice(lastProp.end, closingBrace).includes('\\n');\n const needsComma = !hasTrailingComma(source, lastProp.end, obj.end);\n\n if (!multiline) {\n const insertPos = closingBrace;\n return {\n start: insertPos,\n end: insertPos,\n text: `${needsComma ? ',' : ''} ${propTextWithIndent}`,\n };\n }\n\n const lineStart = source.lastIndexOf('\\n', closingBrace);\n return {\n start: lineStart,\n end: lineStart,\n text: `${needsComma ? ',' : ''}\\n${propTextWithIndent},`,\n };\n}\n\nfunction removeProperty(\n source: string,\n obj: ObjectExpression,\n prop: PropertyNode,\n) {\n let start = prop.start;\n let end = prop.end;\n const after = skipWhitespaceAndComments(source, end, obj.end);\n if (source[after] === ',') {\n end = after + 1;\n } else {\n const before = skipWhitespaceAndCommentsBackward(source, start, obj.start);\n if (source[before] === ',') {\n start = before;\n }\n }\n return { start, end, text: '' };\n}\n\nfunction hasTrailingComma(source: string, afterPos: number, endPos: number) {\n const next = skipWhitespaceAndComments(source, afterPos, endPos);\n return source[next] === ',';\n}\n\nfunction skipWhitespaceAndComments(source: string, start: number, end: number) {\n let i = start;\n while (i < end) {\n const ch = source[i];\n if (/\\s/.test(ch)) {\n i += 1;\n continue;\n }\n if (ch === '/' && source[i + 1] === '/') {\n const nextLine = source.indexOf('\\n', i + 2);\n i = nextLine === -1 ? end : nextLine + 1;\n continue;\n }\n if (ch === '/' && source[i + 1] === '*') {\n const close = source.indexOf('*/', i + 2);\n i = close === -1 ? end : close + 2;\n continue;\n }\n break;\n }\n return i;\n}\n\nfunction skipWhitespaceAndCommentsBackward(\n source: string,\n start: number,\n end: number,\n) {\n let i = start - 1;\n while (i >= end) {\n const ch = source[i];\n if (/\\s/.test(ch)) {\n i -= 1;\n continue;\n }\n if (ch === '/' && source[i - 1] === '/') {\n const prevLine = source.lastIndexOf('\\n', i - 2);\n i = prevLine === -1 ? end - 1 : prevLine - 1;\n continue;\n }\n if (ch === '/' && source[i - 1] === '*') {\n const open = source.lastIndexOf('/*', i - 2);\n i = open === -1 ? end - 1 : open - 1;\n continue;\n }\n break;\n }\n return i;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"updateSchemaFile.js","sourceRoot":"","sources":["../../src/util/updateSchemaFile.ts"],"names":[],"mappings":"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","sourcesContent":["import * as acorn from 'acorn';\nimport { tsPlugin } from 'acorn-typescript';\nimport {\n diffSchemas,\n renderAttrCall,\n renderAttrProperty,\n renderEntityProperty,\n renderLinkProperty,\n renderLinkValue,\n type MigrationTx,\n} from '@instantdb/platform';\nimport type { DataAttrDef, InstantSchemaDef } from '@instantdb/core';\n\nconst parser = (acorn.Parser as any).extend(tsPlugin({ dts: false }) as any);\nconst DEFAULT_INDENT = ' ';\n\nexport async function updateSchemaFile(\n existingFileContent: string,\n localSchema: InstantSchemaDef<any, any, any>,\n serverSchema: InstantSchemaDef<any, any, any>,\n): Promise<string> {\n const ast = parseFile(existingFileContent);\n const schemaObj = findSchemaObject(ast);\n if (!schemaObj) {\n throw new Error('Could not find i.schema(...) in schema file.');\n }\n\n const { entitiesObj, linksObj } = getSchemaSections(schemaObj);\n const diff = await diffSchemas(\n localSchema,\n serverSchema,\n async (created) => created,\n {},\n );\n if (diff.length === 0) {\n return existingFileContent;\n }\n\n const { entitiesByName } = buildEntitiesIndex(entitiesObj);\n\n const { localLinksByForward, serverLinksByForward } = buildLinkMaps(\n localSchema.links || {},\n serverSchema.links || {},\n );\n const changeBuckets = collectChanges(\n diff,\n localLinksByForward,\n serverLinksByForward,\n );\n\n const edits: Edit[] = [];\n edits.push(\n ...collectEntityEdits(\n existingFileContent,\n entitiesObj,\n entitiesByName,\n changeBuckets,\n serverSchema,\n ),\n );\n edits.push(\n ...collectLinkEdits(\n existingFileContent,\n linksObj,\n changeBuckets,\n localLinksByForward,\n serverLinksByForward,\n ),\n );\n\n const updated = applyEdits(existingFileContent, edits);\n return normalizeEmptyLinksObject(updated);\n}\n\ntype ObjectExpression = {\n type: 'ObjectExpression';\n start: number;\n end: number;\n properties: any[];\n};\n\ntype PropertyNode = {\n type: 'Property';\n start: number;\n end: number;\n key: any;\n value: any;\n};\n\ntype EntityInfo = {\n prop: PropertyNode;\n attrsObj: ObjectExpression;\n attrsByName: Map<string, PropertyNode>;\n};\n\ntype Edit = { start: number; end: number; text: string };\n\ntype ChangeBuckets = {\n createEntities: Set<string>;\n deleteEntities: Set<string>;\n addAttrs: Map<string, Set<string>>;\n deleteAttrs: Map<string, Set<string>>;\n updateAttrs: Map<string, Set<string>>;\n addLinks: Set<string>;\n deleteLinks: Set<string>;\n updateLinks: Set<string>;\n};\n\ntype LinkMap = Map<string, { name: string; link: any }>;\n\nfunction parseFile(content: string) {\n return parser.parse(content, {\n sourceType: 'module',\n ecmaVersion: 'latest',\n });\n}\n\nfunction getSchemaSections(schemaObj: ObjectExpression) {\n const entitiesProp = findObjectProperty(schemaObj, 'entities');\n if (!entitiesProp || !isObjectExpression(entitiesProp.value)) {\n throw new Error('Could not find entities object in schema file.');\n }\n const linksProp = findObjectProperty(schemaObj, 'links');\n if (!linksProp || !isObjectExpression(linksProp.value)) {\n throw new Error('Could not find links object in schema file.');\n }\n\n return {\n entitiesObj: entitiesProp.value,\n linksObj: linksProp.value,\n };\n}\n\nfunction buildEntitiesIndex(entitiesObj: ObjectExpression) {\n const entitiesByName = new Map<string, EntityInfo>();\n\n for (const prop of entitiesObj.properties) {\n if (!isProperty(prop)) continue;\n const name = getPropName(prop);\n if (!name) continue;\n const attrsObj = getEntityAttrsObject(prop.value);\n if (!attrsObj) continue;\n\n const attrsByName = new Map<string, PropertyNode>();\n for (const attrProp of attrsObj.properties) {\n if (!isProperty(attrProp)) continue;\n const attrName = getPropName(attrProp);\n if (!attrName) continue;\n attrsByName.set(attrName, attrProp);\n }\n\n entitiesByName.set(name, { prop, attrsObj, attrsByName });\n }\n\n return { entitiesByName };\n}\n\nfunction buildLinkMaps(\n localLinks: Record<string, any>,\n serverLinks: Record<string, any>,\n) {\n return {\n localLinksByForward: buildLinkForwardMap(localLinks),\n serverLinksByForward: buildLinkForwardMap(serverLinks),\n };\n}\n\nfunction collectEntityEdits(\n content: string,\n entitiesObj: ObjectExpression,\n entitiesByName: Map<string, EntityInfo>,\n changeBuckets: ChangeBuckets,\n serverSchema: InstantSchemaDef<any, any, any>,\n): Edit[] {\n const edits: Edit[] = [];\n\n for (const entityName of changeBuckets.deleteEntities) {\n const entity = entitiesByName.get(entityName);\n if (!entity) continue;\n edits.push(removeProperty(content, entitiesObj, entity.prop));\n }\n\n for (const entityName of changeBuckets.createEntities) {\n if (entitiesByName.has(entityName)) continue;\n const entityDef = serverSchema.entities?.[entityName];\n if (!entityDef) continue;\n const propText = renderEntityProperty(entityName, entityDef.attrs);\n const indent = getObjectPropIndent(content, entitiesObj);\n edits.push(insertProperty(content, entitiesObj, propText, indent));\n }\n\n for (const [entityName, attrs] of changeBuckets.deleteAttrs) {\n const entity = entitiesByName.get(entityName);\n if (!entity) continue;\n for (const attrName of attrs) {\n const attrProp = entity.attrsByName.get(attrName);\n if (!attrProp) continue;\n edits.push(removeProperty(content, entity.attrsObj, attrProp));\n }\n }\n\n for (const [entityName, attrs] of changeBuckets.addAttrs) {\n const entity = entitiesByName.get(entityName);\n if (!entity) continue;\n const entityDef = serverSchema.entities?.[entityName];\n if (!entityDef) continue;\n const indent = getObjectPropIndent(content, entity.attrsObj);\n for (const attrName of attrs) {\n const attrDef = entityDef.attrs?.[attrName];\n if (!attrDef) continue;\n const propText = renderAttrProperty(attrName, attrDef);\n edits.push(insertProperty(content, entity.attrsObj, propText, indent));\n }\n }\n\n for (const [entityName, attrs] of changeBuckets.updateAttrs) {\n const entity = entitiesByName.get(entityName);\n if (!entity) continue;\n const entityDef = serverSchema.entities?.[entityName];\n if (!entityDef) continue;\n for (const attrName of attrs) {\n const attrProp = entity.attrsByName.get(attrName);\n const attrDef = entityDef.attrs?.[attrName];\n if (!attrProp || !attrDef) continue;\n edits.push(updateAttrEdit(content, attrProp, attrDef));\n }\n }\n\n return edits;\n}\n\nfunction collectLinkEdits(\n content: string,\n linksObj: ObjectExpression,\n changeBuckets: ChangeBuckets,\n localLinksByForward: LinkMap,\n serverLinksByForward: LinkMap,\n): Edit[] {\n const edits: Edit[] = [];\n\n for (const forwardKey of changeBuckets.deleteLinks) {\n const localLink = localLinksByForward.get(forwardKey);\n if (!localLink) continue;\n const linkProp = findObjectProperty(linksObj, localLink.name);\n if (!linkProp) continue;\n edits.push(removeProperty(content, linksObj, linkProp));\n }\n\n for (const forwardKey of changeBuckets.addLinks) {\n const serverLink = serverLinksByForward.get(forwardKey);\n if (!serverLink) continue;\n const linkName = serverLink.name;\n if (findObjectProperty(linksObj, linkName)) continue;\n const propText = renderLinkProperty(linkName, serverLink.link);\n const indent = getObjectPropIndent(content, linksObj);\n edits.push(insertProperty(content, linksObj, propText, indent));\n }\n\n for (const forwardKey of changeBuckets.updateLinks) {\n const serverLink = serverLinksByForward.get(forwardKey);\n const localLink = localLinksByForward.get(forwardKey);\n if (!serverLink || !localLink) continue;\n const linkProp = findObjectProperty(linksObj, localLink.name);\n if (!linkProp) continue;\n const nextValue = renderLinkValue(serverLink.link);\n const propIndent = getLineIndent(content, linkProp.start);\n edits.push({\n start: linkProp.value.start,\n end: linkProp.value.end,\n text: indentValueAfterFirstLine(nextValue, propIndent),\n });\n }\n\n return edits;\n}\n\nfunction updateAttrEdit(\n content: string,\n attrProp: PropertyNode,\n attrDef: DataAttrDef<string, boolean, boolean>,\n): Edit {\n const { typeParams } = analyzeChain(attrProp.value);\n const typeParamsText = typeParams\n ? content.slice(typeParams.start, typeParams.end)\n : null;\n const nextValue = renderAttrCall(attrDef, typeParamsText);\n return {\n start: attrProp.value.start,\n end: attrProp.value.end,\n text: nextValue,\n };\n}\n\nfunction applyEdits(content: string, edits: Edit[]) {\n if (edits.length === 0) {\n return content;\n }\n const sorted = [...edits].sort((a, b) => b.start - a.start);\n let output = content;\n for (const edit of sorted) {\n output = output.slice(0, edit.start) + edit.text + output.slice(edit.end);\n }\n return output;\n}\n\nfunction collectChanges(\n steps: MigrationTx[],\n localLinksByForward: LinkMap,\n serverLinksByForward: LinkMap,\n): ChangeBuckets {\n const buckets: ChangeBuckets = {\n createEntities: new Set(),\n deleteEntities: new Set(),\n addAttrs: new Map(),\n deleteAttrs: new Map(),\n updateAttrs: new Map(),\n addLinks: new Set(),\n deleteLinks: new Set(),\n updateLinks: new Set(),\n };\n\n for (const step of steps) {\n const namespace = step.identifier.namespace;\n const attrName = step.identifier.attrName;\n const forwardKey = `${namespace}.${attrName}`;\n\n switch (step.type) {\n case 'add-attr': {\n if (attrName === 'id') {\n buckets.createEntities.add(namespace);\n break;\n }\n if (step['value-type'] === 'ref') {\n buckets.addLinks.add(forwardKey);\n break;\n }\n ensureSet(buckets.addAttrs, namespace).add(attrName);\n break;\n }\n case 'delete-attr': {\n if (attrName === 'id') {\n buckets.deleteEntities.add(namespace);\n break;\n }\n if (localLinksByForward.has(forwardKey)) {\n buckets.deleteLinks.add(forwardKey);\n break;\n }\n ensureSet(buckets.deleteAttrs, namespace).add(attrName);\n break;\n }\n case 'update-attr': {\n if (step.partialAttr?.['value-type'] === 'ref') {\n buckets.updateLinks.add(forwardKey);\n break;\n }\n ensureSet(buckets.updateAttrs, namespace).add(attrName);\n break;\n }\n case 'index':\n case 'remove-index':\n case 'unique':\n case 'remove-unique':\n case 'required':\n case 'remove-required':\n case 'check-data-type':\n case 'remove-data-type': {\n if (serverLinksByForward.has(forwardKey)) {\n buckets.updateLinks.add(forwardKey);\n break;\n }\n ensureSet(buckets.updateAttrs, namespace).add(attrName);\n break;\n }\n default: {\n assertNever(step);\n }\n }\n }\n\n pruneNamespaceBuckets(buckets);\n return buckets;\n}\n\nfunction ensureSet(map: Map<string, Set<string>>, key: string) {\n if (!map.has(key)) map.set(key, new Set());\n return map.get(key)!;\n}\n\nfunction pruneNamespaceBuckets(buckets: ChangeBuckets) {\n const namespaces = new Set<string>([\n ...buckets.createEntities,\n ...buckets.deleteEntities,\n ]);\n\n for (const namespace of namespaces) {\n buckets.addAttrs.delete(namespace);\n buckets.deleteAttrs.delete(namespace);\n buckets.updateAttrs.delete(namespace);\n removeNamespaceLinks(buckets.addLinks, namespace);\n removeNamespaceLinks(buckets.deleteLinks, namespace);\n removeNamespaceLinks(buckets.updateLinks, namespace);\n }\n}\n\nfunction removeNamespaceLinks(set: Set<string>, namespace: string) {\n const prefix = `${namespace}.`;\n for (const key of Array.from(set)) {\n if (key.startsWith(prefix)) {\n set.delete(key);\n }\n }\n}\n\nfunction assertNever(value: never): never {\n throw new Error(`Unhandled migration step: ${JSON.stringify(value)}`);\n}\n\nfunction analyzeChain(node: any): { typeParams: acorn.Node | null } {\n let curr = node;\n let typeParams: acorn.Node | null = null;\n\n while (curr?.type === 'CallExpression') {\n if (curr.typeParameters) {\n typeParams = curr.typeParameters;\n }\n if (curr.callee?.type === 'MemberExpression') {\n curr = curr.callee.object;\n } else {\n break;\n }\n }\n return { typeParams };\n}\n\nfunction findSchemaObject(ast: any): ObjectExpression | null {\n let schemaObj: ObjectExpression | null = null;\n const walk = (node: any) => {\n if (!node || schemaObj) return;\n if (\n node.type === 'CallExpression' &&\n node.callee?.type === 'MemberExpression' &&\n node.callee.object?.type === 'Identifier' &&\n node.callee.object.name === 'i' &&\n node.callee.property?.name === 'schema' &&\n node.arguments?.length > 0\n ) {\n const arg = node.arguments[0];\n if (isObjectExpression(arg)) {\n schemaObj = arg;\n }\n return;\n }\n for (const key in node) {\n if (key === 'loc' || key === 'start' || key === 'end') continue;\n const value = node[key];\n if (!value || typeof value !== 'object') continue;\n if (Array.isArray(value)) {\n value.forEach(walk);\n } else {\n walk(value);\n }\n }\n };\n walk(ast);\n return schemaObj;\n}\n\nfunction findObjectProperty(\n obj: ObjectExpression,\n name: string,\n): PropertyNode | null {\n for (const prop of obj.properties) {\n if (!isProperty(prop)) continue;\n const propName = getPropName(prop);\n if (propName === name) return prop;\n }\n return null;\n}\n\nfunction getEntityAttrsObject(value: any): ObjectExpression | null {\n if (\n value?.type !== 'CallExpression' ||\n value.callee?.type !== 'MemberExpression' ||\n value.callee.object?.type !== 'Identifier' ||\n value.callee.object.name !== 'i' ||\n value.callee.property?.name !== 'entity'\n ) {\n return null;\n }\n const attrsObj = value.arguments?.[0];\n return isObjectExpression(attrsObj) ? attrsObj : null;\n}\n\nfunction buildLinkForwardMap(links: Record<string, any>) {\n const map = new Map<string, { name: string; link: any }>();\n for (const [name, link] of Object.entries(links || {})) {\n map.set(linkForwardKey(link), { name, link });\n }\n return map;\n}\n\nfunction linkForwardKey(link: any) {\n return `${link.forward.on}.${link.forward.label}`;\n}\n\nfunction isObjectExpression(node: any): node is ObjectExpression {\n return node?.type === 'ObjectExpression';\n}\n\nfunction isProperty(node: any): node is PropertyNode {\n return node?.type === 'Property';\n}\n\nfunction getPropName(prop: PropertyNode) {\n if (prop.key.type === 'Identifier') return prop.key.name;\n if (prop.key.type === 'Literal') return String(prop.key.value);\n return null;\n}\n\nfunction indentLines(text: string, indent: string) {\n return text\n .split('\\n')\n .map((line) => (line.length ? indent + line : line))\n .join('\\n');\n}\n\nfunction getObjectPropIndent(source: string, obj: ObjectExpression) {\n const props = obj.properties.filter(isProperty);\n if (props.length > 0) {\n return getLineIndent(source, props[0].start);\n }\n const closingIndent = getLineIndent(source, obj.end - 1);\n return closingIndent + DEFAULT_INDENT;\n}\n\nfunction getLineIndent(source: string, pos: number) {\n const lineStart = source.lastIndexOf('\\n', pos - 1) + 1;\n const match = source.slice(lineStart, pos).match(/^[\\t ]*/);\n return match ? match[0] : '';\n}\n\nfunction insertProperty(\n source: string,\n obj: ObjectExpression,\n propText: string,\n indent: string,\n) {\n const props = obj.properties.filter(isProperty);\n const closingBrace = obj.end - 1;\n const propTextWithIndent = indentLines(propText, indent);\n const propTextSingleLine = propText.trim();\n const innerStart = obj.start + 1;\n const innerEnd = closingBrace;\n const innerContent = source.slice(innerStart, innerEnd);\n const innerWhitespaceOnly = /^[\\s]*$/.test(innerContent);\n\n if (props.length === 0) {\n const objSource = source.slice(obj.start, obj.end);\n const multiline = objSource.includes('\\n') || propText.includes('\\n');\n if (!multiline) {\n return {\n start: closingBrace,\n end: closingBrace,\n text: ` ${propTextSingleLine} `,\n };\n }\n const closingIndent = getLineIndent(source, closingBrace);\n if (innerWhitespaceOnly) {\n return {\n start: innerStart,\n end: innerEnd,\n text: `\\n${propTextWithIndent},\\n${closingIndent}`,\n };\n }\n return {\n start: closingBrace,\n end: closingBrace,\n text: `\\n${propTextWithIndent},\\n${closingIndent}`,\n };\n }\n\n const lastProp = props[props.length - 1];\n const multiline =\n source.slice(lastProp.end, closingBrace).includes('\\n') ||\n propText.includes('\\n');\n const needsComma = !hasTrailingComma(source, lastProp.end, obj.end);\n\n if (!multiline) {\n let insertPos = closingBrace;\n while (insertPos > lastProp.end && /\\s/.test(source[insertPos - 1])) {\n insertPos -= 1;\n }\n return {\n start: insertPos,\n end: insertPos,\n text: `${needsComma ? ',' : ''} ${propTextSingleLine}`,\n };\n }\n\n const lineStart = source.lastIndexOf('\\n', closingBrace);\n return {\n start: lineStart,\n end: lineStart,\n text: `${needsComma ? ',' : ''}\\n${propTextWithIndent},`,\n };\n}\n\nfunction removeProperty(\n source: string,\n obj: ObjectExpression,\n prop: PropertyNode,\n) {\n let start = prop.start;\n let end = prop.end;\n const lineStart = source.lastIndexOf('\\n', start - 1) + 1;\n let shouldTrimLineEnd = false;\n if (/^[\\t ]*$/.test(source.slice(lineStart, start))) {\n start = lineStart;\n shouldTrimLineEnd = true;\n }\n const after = skipWhitespaceAndComments(source, end, obj.end);\n if (source[after] === ',') {\n end = after + 1;\n } else {\n const before = skipWhitespaceAndCommentsBackward(source, start, obj.start);\n if (source[before] === ',') {\n start = before;\n }\n }\n if (shouldTrimLineEnd) {\n const lineEnd = source.indexOf('\\n', end);\n if (lineEnd !== -1 && /^[\\t ]*$/.test(source.slice(end, lineEnd))) {\n end = lineEnd + 1;\n }\n }\n return { start, end, text: '' };\n}\n\nfunction indentValueAfterFirstLine(value: string, indent: string) {\n const lines = value.split('\\n');\n if (lines.length <= 1) return value;\n return [\n lines[0],\n ...lines.slice(1).map((line) => (line ? indent + line : line)),\n ].join('\\n');\n}\n\nfunction normalizeEmptyLinksObject(content: string) {\n let ast: any;\n try {\n ast = parseFile(content);\n } catch {\n return content;\n }\n const schemaObj = findSchemaObject(ast);\n if (!schemaObj) return content;\n const linksProp = findObjectProperty(schemaObj, 'links');\n if (!linksProp || !isObjectExpression(linksProp.value)) return content;\n if (linksProp.value.properties.some(isProperty)) return content;\n const inner = content.slice(linksProp.value.start + 1, linksProp.value.end - 1);\n if (!/^[\\s]*$/.test(inner)) return content;\n return (\n content.slice(0, linksProp.value.start) +\n '{}' +\n content.slice(linksProp.value.end)\n );\n}\n\nfunction hasTrailingComma(source: string, afterPos: number, endPos: number) {\n const next = skipWhitespaceAndComments(source, afterPos, endPos);\n return source[next] === ',';\n}\n\nfunction skipWhitespaceAndComments(source: string, start: number, end: number) {\n let i = start;\n while (i < end) {\n const ch = source[i];\n if (/\\s/.test(ch)) {\n i += 1;\n continue;\n }\n if (ch === '/' && source[i + 1] === '/') {\n const nextLine = source.indexOf('\\n', i + 2);\n i = nextLine === -1 ? end : nextLine + 1;\n continue;\n }\n if (ch === '/' && source[i + 1] === '*') {\n const close = source.indexOf('*/', i + 2);\n i = close === -1 ? end : close + 2;\n continue;\n }\n break;\n }\n return i;\n}\n\nfunction skipWhitespaceAndCommentsBackward(\n source: string,\n start: number,\n end: number,\n) {\n let i = start - 1;\n while (i >= end) {\n const ch = source[i];\n if (/\\s/.test(ch)) {\n i -= 1;\n continue;\n }\n if (ch === '/' && source[i - 1] === '/') {\n const prevLine = source.lastIndexOf('\\n', i - 2);\n i = prevLine === -1 ? end - 1 : prevLine - 1;\n continue;\n }\n if (ch === '/' && source[i - 1] === '*') {\n const open = source.lastIndexOf('/*', i - 2);\n i = open === -1 ? end - 1 : open - 1;\n continue;\n }\n break;\n }\n return i;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "instant-cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.22.95-experimental.surgical.
|
|
4
|
+
"version": "0.22.95-experimental.surgical.20386732292.1",
|
|
5
5
|
"description": "Instant's CLI",
|
|
6
6
|
"homepage": "https://github.com/instantdb/instant/tree/main/client/packages/cli",
|
|
7
7
|
"repository": {
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"strip-ansi": "^7.1.2",
|
|
42
42
|
"terminal-link": "^3.0.0",
|
|
43
43
|
"unconfig": "^0.5.5",
|
|
44
|
-
"@instantdb/core": "0.22.95-experimental.surgical.
|
|
45
|
-
"@instantdb/
|
|
46
|
-
"@instantdb/
|
|
44
|
+
"@instantdb/core": "0.22.95-experimental.surgical.20386732292.1",
|
|
45
|
+
"@instantdb/version": "0.22.95-experimental.surgical.20386732292.1",
|
|
46
|
+
"@instantdb/platform": "0.22.95-experimental.surgical.20386732292.1"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@babel/core": "^7.17.9",
|
|
@@ -68,7 +68,8 @@ export async function updateSchemaFile(
|
|
|
68
68
|
),
|
|
69
69
|
);
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
const updated = applyEdits(existingFileContent, edits);
|
|
72
|
+
return normalizeEmptyLinksObject(updated);
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
type ObjectExpression = {
|
|
@@ -262,10 +263,11 @@ function collectLinkEdits(
|
|
|
262
263
|
const linkProp = findObjectProperty(linksObj, localLink.name);
|
|
263
264
|
if (!linkProp) continue;
|
|
264
265
|
const nextValue = renderLinkValue(serverLink.link);
|
|
266
|
+
const propIndent = getLineIndent(content, linkProp.start);
|
|
265
267
|
edits.push({
|
|
266
268
|
start: linkProp.value.start,
|
|
267
269
|
end: linkProp.value.end,
|
|
268
|
-
text: nextValue,
|
|
270
|
+
text: indentValueAfterFirstLine(nextValue, propIndent),
|
|
269
271
|
});
|
|
270
272
|
}
|
|
271
273
|
|
|
@@ -547,6 +549,11 @@ function insertProperty(
|
|
|
547
549
|
const props = obj.properties.filter(isProperty);
|
|
548
550
|
const closingBrace = obj.end - 1;
|
|
549
551
|
const propTextWithIndent = indentLines(propText, indent);
|
|
552
|
+
const propTextSingleLine = propText.trim();
|
|
553
|
+
const innerStart = obj.start + 1;
|
|
554
|
+
const innerEnd = closingBrace;
|
|
555
|
+
const innerContent = source.slice(innerStart, innerEnd);
|
|
556
|
+
const innerWhitespaceOnly = /^[\s]*$/.test(innerContent);
|
|
550
557
|
|
|
551
558
|
if (props.length === 0) {
|
|
552
559
|
const objSource = source.slice(obj.start, obj.end);
|
|
@@ -555,10 +562,17 @@ function insertProperty(
|
|
|
555
562
|
return {
|
|
556
563
|
start: closingBrace,
|
|
557
564
|
end: closingBrace,
|
|
558
|
-
text: ` ${
|
|
565
|
+
text: ` ${propTextSingleLine} `,
|
|
559
566
|
};
|
|
560
567
|
}
|
|
561
568
|
const closingIndent = getLineIndent(source, closingBrace);
|
|
569
|
+
if (innerWhitespaceOnly) {
|
|
570
|
+
return {
|
|
571
|
+
start: innerStart,
|
|
572
|
+
end: innerEnd,
|
|
573
|
+
text: `\n${propTextWithIndent},\n${closingIndent}`,
|
|
574
|
+
};
|
|
575
|
+
}
|
|
562
576
|
return {
|
|
563
577
|
start: closingBrace,
|
|
564
578
|
end: closingBrace,
|
|
@@ -567,15 +581,20 @@ function insertProperty(
|
|
|
567
581
|
}
|
|
568
582
|
|
|
569
583
|
const lastProp = props[props.length - 1];
|
|
570
|
-
const multiline =
|
|
584
|
+
const multiline =
|
|
585
|
+
source.slice(lastProp.end, closingBrace).includes('\n') ||
|
|
586
|
+
propText.includes('\n');
|
|
571
587
|
const needsComma = !hasTrailingComma(source, lastProp.end, obj.end);
|
|
572
588
|
|
|
573
589
|
if (!multiline) {
|
|
574
|
-
|
|
590
|
+
let insertPos = closingBrace;
|
|
591
|
+
while (insertPos > lastProp.end && /\s/.test(source[insertPos - 1])) {
|
|
592
|
+
insertPos -= 1;
|
|
593
|
+
}
|
|
575
594
|
return {
|
|
576
595
|
start: insertPos,
|
|
577
596
|
end: insertPos,
|
|
578
|
-
text: `${needsComma ? ',' : ''} ${
|
|
597
|
+
text: `${needsComma ? ',' : ''} ${propTextSingleLine}`,
|
|
579
598
|
};
|
|
580
599
|
}
|
|
581
600
|
|
|
@@ -594,6 +613,12 @@ function removeProperty(
|
|
|
594
613
|
) {
|
|
595
614
|
let start = prop.start;
|
|
596
615
|
let end = prop.end;
|
|
616
|
+
const lineStart = source.lastIndexOf('\n', start - 1) + 1;
|
|
617
|
+
let shouldTrimLineEnd = false;
|
|
618
|
+
if (/^[\t ]*$/.test(source.slice(lineStart, start))) {
|
|
619
|
+
start = lineStart;
|
|
620
|
+
shouldTrimLineEnd = true;
|
|
621
|
+
}
|
|
597
622
|
const after = skipWhitespaceAndComments(source, end, obj.end);
|
|
598
623
|
if (source[after] === ',') {
|
|
599
624
|
end = after + 1;
|
|
@@ -603,9 +628,45 @@ function removeProperty(
|
|
|
603
628
|
start = before;
|
|
604
629
|
}
|
|
605
630
|
}
|
|
631
|
+
if (shouldTrimLineEnd) {
|
|
632
|
+
const lineEnd = source.indexOf('\n', end);
|
|
633
|
+
if (lineEnd !== -1 && /^[\t ]*$/.test(source.slice(end, lineEnd))) {
|
|
634
|
+
end = lineEnd + 1;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
606
637
|
return { start, end, text: '' };
|
|
607
638
|
}
|
|
608
639
|
|
|
640
|
+
function indentValueAfterFirstLine(value: string, indent: string) {
|
|
641
|
+
const lines = value.split('\n');
|
|
642
|
+
if (lines.length <= 1) return value;
|
|
643
|
+
return [
|
|
644
|
+
lines[0],
|
|
645
|
+
...lines.slice(1).map((line) => (line ? indent + line : line)),
|
|
646
|
+
].join('\n');
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
function normalizeEmptyLinksObject(content: string) {
|
|
650
|
+
let ast: any;
|
|
651
|
+
try {
|
|
652
|
+
ast = parseFile(content);
|
|
653
|
+
} catch {
|
|
654
|
+
return content;
|
|
655
|
+
}
|
|
656
|
+
const schemaObj = findSchemaObject(ast);
|
|
657
|
+
if (!schemaObj) return content;
|
|
658
|
+
const linksProp = findObjectProperty(schemaObj, 'links');
|
|
659
|
+
if (!linksProp || !isObjectExpression(linksProp.value)) return content;
|
|
660
|
+
if (linksProp.value.properties.some(isProperty)) return content;
|
|
661
|
+
const inner = content.slice(linksProp.value.start + 1, linksProp.value.end - 1);
|
|
662
|
+
if (!/^[\s]*$/.test(inner)) return content;
|
|
663
|
+
return (
|
|
664
|
+
content.slice(0, linksProp.value.start) +
|
|
665
|
+
'{}' +
|
|
666
|
+
content.slice(linksProp.value.end)
|
|
667
|
+
);
|
|
668
|
+
}
|
|
669
|
+
|
|
609
670
|
function hasTrailingComma(source: string, afterPos: number, endPos: number) {
|
|
610
671
|
const next = skipWhitespaceAndComments(source, afterPos, endPos);
|
|
611
672
|
return source[next] === ',';
|