@meteor-vite/plugin-zodern-relay 1.0.5 → 1.0.6
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/README.md +54 -54
- package/dist/Plugin.js +6 -2
- package/dist/Plugin.js.map +1 -1
- package/dist/Plugin.mjs +6 -2
- package/dist/Plugin.mjs.map +1 -1
- package/package.json +1 -1
- package/src/Plugin.ts +127 -121
- package/stubs/babel-plugin.js +444 -444
- package/stubs/relay-client.js +22 -22
package/stubs/babel-plugin.js
CHANGED
|
@@ -1,445 +1,445 @@
|
|
|
1
|
-
const { createHash } = require('crypto');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
|
|
4
|
-
// If has a MemberExpression, returns the first call expression in its callee
|
|
5
|
-
// Otherwise, returns the call expression
|
|
6
|
-
function getFirstCallExpr(call) {
|
|
7
|
-
if (call.node.callee.type !== 'MemberExpression') {
|
|
8
|
-
return call;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (
|
|
13
|
-
call.node.callee.object.type !== 'CallExpression'
|
|
14
|
-
) {
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return call.get('callee.object');
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
module.exports = function (api) {
|
|
22
|
-
let t = api.types;
|
|
23
|
-
|
|
24
|
-
let caller;
|
|
25
|
-
api.caller(function (c) {
|
|
26
|
-
caller = c;
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
function createExport(exportName, callee, name, stub) {
|
|
30
|
-
let args = [
|
|
31
|
-
t.StringLiteral(name)
|
|
32
|
-
];
|
|
33
|
-
|
|
34
|
-
if (stub) {
|
|
35
|
-
if (stub.type === 'ObjectMethod') {
|
|
36
|
-
stub = t.FunctionExpression(
|
|
37
|
-
null,
|
|
38
|
-
stub.node.params || [],
|
|
39
|
-
stub.node.body,
|
|
40
|
-
stub.node.generator,
|
|
41
|
-
stub.node.async
|
|
42
|
-
)
|
|
43
|
-
} else if (stub.type === 'ObjectProperty') {
|
|
44
|
-
stub = stub.node.value;
|
|
45
|
-
}
|
|
46
|
-
args.push(stub);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const declaration = t.CallExpression(
|
|
50
|
-
t.Identifier(callee),
|
|
51
|
-
args
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
if (exportName === null) {
|
|
55
|
-
return t.ExportDefaultDeclaration(
|
|
56
|
-
declaration
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return t.ExportNamedDeclaration(
|
|
61
|
-
t.VariableDeclaration(
|
|
62
|
-
'const',
|
|
63
|
-
[t.VariableDeclarator(
|
|
64
|
-
t.Identifier(exportName),
|
|
65
|
-
declaration
|
|
66
|
-
)]
|
|
67
|
-
)
|
|
68
|
-
)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function getOrAddName(args, { exportName, filePath, isPub }) {
|
|
72
|
-
if (args[0].type !== 'ObjectExpression') {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
let obj = args[0];
|
|
77
|
-
let nameProperty = obj.properties.find((property) => {
|
|
78
|
-
if (property.key.type !== 'Identifier') {
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (property.key.name !== 'name') {
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return property.value.type === 'StringLiteral';
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
if (nameProperty) {
|
|
90
|
-
return nameProperty.value.value;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
let fileHash = 'M' + createHash('sha256')
|
|
94
|
-
.update(filePath)
|
|
95
|
-
.digest('hex')
|
|
96
|
-
.substring(0, 5);
|
|
97
|
-
|
|
98
|
-
let name = exportName;
|
|
99
|
-
|
|
100
|
-
if (name === null) {
|
|
101
|
-
let baseName = path.basename(filePath);
|
|
102
|
-
let lastDotIndex = baseName.lastIndexOf('.');
|
|
103
|
-
name = baseName.substring(0, lastDotIndex);
|
|
104
|
-
} else if (isPub && name.startsWith('subscribe')) {
|
|
105
|
-
name = exportName.substring('subscribe'.length);
|
|
106
|
-
|
|
107
|
-
if (name[0] !== name[0].toLowerCase()) {
|
|
108
|
-
name = `${name[0].toLowerCase()}${name.substring(1)}`
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
name += fileHash;
|
|
113
|
-
|
|
114
|
-
obj.properties.push(t.ObjectProperty(
|
|
115
|
-
t.Identifier('name'),
|
|
116
|
-
t.StringLiteral(name)
|
|
117
|
-
));
|
|
118
|
-
|
|
119
|
-
return name;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// TODO: args should be a path instead of node
|
|
123
|
-
function findStubPropertyIndex(args) {
|
|
124
|
-
let obj = args[0];
|
|
125
|
-
let stubPropIndex = obj.properties.findIndex((property) => {
|
|
126
|
-
if (property.key.type !== 'Identifier') {
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (property.key.name !== 'stub') {
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return true;
|
|
135
|
-
});
|
|
136
|
-
let stub = obj.properties[stubPropIndex];
|
|
137
|
-
|
|
138
|
-
if (!stub) {
|
|
139
|
-
return -1;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (
|
|
143
|
-
stub.type === 'ObjectMethod' ||
|
|
144
|
-
stub.value.type === 'FunctionExpression' ||
|
|
145
|
-
stub.value.type === 'ArrowFunctionExpression'
|
|
146
|
-
) {
|
|
147
|
-
return stubPropIndex;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (stub.value.type !== 'BooleanLiteral') {
|
|
152
|
-
return -1;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (stub.value.value !== true) {
|
|
156
|
-
return -1;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// stub is set to true - use the run function
|
|
160
|
-
return obj.properties.findIndex((property) => {
|
|
161
|
-
if (property.key.type !== 'Identifier') {
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (property.key.name !== 'run') {
|
|
166
|
-
return false;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
return true;
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
let canHaveMethods = false;
|
|
174
|
-
let canHavePublications = false;
|
|
175
|
-
let createMethodName = null;
|
|
176
|
-
let createPublicationName = null;
|
|
177
|
-
let methods = [];
|
|
178
|
-
let publications = [];
|
|
179
|
-
let isServer = false;
|
|
180
|
-
let filePath = ''
|
|
181
|
-
let imports = Object.create(null);
|
|
182
|
-
|
|
183
|
-
return {
|
|
184
|
-
visitor: {
|
|
185
|
-
Program: {
|
|
186
|
-
enter(_, state) {
|
|
187
|
-
createMethodName = null;
|
|
188
|
-
createPublicationName = null;
|
|
189
|
-
methods = [];
|
|
190
|
-
publications = [];
|
|
191
|
-
|
|
192
|
-
let relPath = path
|
|
193
|
-
.relative(state.cwd, state.filename)
|
|
194
|
-
.split(path.sep)
|
|
195
|
-
.join(path.posix.sep);
|
|
196
|
-
filePath = relPath;
|
|
197
|
-
|
|
198
|
-
canHaveMethods = relPath.includes('/methods/') || relPath.startsWith('methods/');
|
|
199
|
-
canHavePublications = relPath.includes('/publications/') || relPath.startsWith('publications/');
|
|
200
|
-
|
|
201
|
-
isServer = caller.arch.startsWith('os.');
|
|
202
|
-
|
|
203
|
-
if (!canHaveMethods && !canHavePublications) {
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
},
|
|
207
|
-
exit(path) {
|
|
208
|
-
if (isServer || !canHaveMethods && !canHavePublications) {
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (methods.length === 0 && publications.length === 0) {
|
|
213
|
-
path.node.body = [];
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
let body = [];
|
|
218
|
-
|
|
219
|
-
let importSpecifiers = [];
|
|
220
|
-
if (methods.length > 0) {
|
|
221
|
-
importSpecifiers.push(
|
|
222
|
-
t.ImportSpecifier(t.Identifier('_createClientMethod'), t.Identifier('_createClientMethod'))
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
if (publications.length > 0) {
|
|
226
|
-
importSpecifiers.push(
|
|
227
|
-
t.ImportSpecifier(t.Identifier('_createClientPublication'), t.Identifier('_createClientPublication'))
|
|
228
|
-
)
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
let importDecl = t.ImportDeclaration(
|
|
232
|
-
importSpecifiers,
|
|
233
|
-
t.StringLiteral('meteor/zodern:relay/client'),
|
|
234
|
-
);
|
|
235
|
-
|
|
236
|
-
body.push(importDecl);
|
|
237
|
-
|
|
238
|
-
methods.forEach(method => {
|
|
239
|
-
if (method.stub) {
|
|
240
|
-
let stubBody = method.stub.get('body').node ?
|
|
241
|
-
method.stub.get('body') : method.stub.get('value.body');
|
|
242
|
-
stubBody.traverse({
|
|
243
|
-
ReferencedIdentifier(subPath) {
|
|
244
|
-
if (stubBody.scope.hasOwnBinding(subPath.node.name)) {
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (subPath.node.name in imports) {
|
|
249
|
-
let importDesc = imports[subPath.node.name];
|
|
250
|
-
|
|
251
|
-
let specifier;
|
|
252
|
-
if (importDesc.type === 'ImportDefaultSpecifier') {
|
|
253
|
-
specifier = t.ImportDefaultSpecifier(t.Identifier(subPath.node.name));
|
|
254
|
-
} else if (importDesc.type === 'ImportNamespaceSpecifier') {
|
|
255
|
-
specifier = t.ImportNamespaceSpecifier(t.Identifier(subPath.node.name));
|
|
256
|
-
} else {
|
|
257
|
-
specifier = t.ImportSpecifier(
|
|
258
|
-
t.Identifier(importDesc.importName),
|
|
259
|
-
t.Identifier(subPath.node.name)
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// TODO: we should preserve the original order of the imports
|
|
264
|
-
body.push(t.ImportDeclaration(
|
|
265
|
-
[ specifier ],
|
|
266
|
-
t.StringLiteral(importDesc.source)
|
|
267
|
-
));
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
body.push(
|
|
274
|
-
createExport(method.export, '_createClientMethod', method.name, method.stub)
|
|
275
|
-
);
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
publications.forEach(publication => {
|
|
279
|
-
body.push(
|
|
280
|
-
createExport(publication.export, '_createClientPublication', publication.name)
|
|
281
|
-
);
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
path.node.body = body;
|
|
285
|
-
|
|
286
|
-
return;
|
|
287
|
-
},
|
|
288
|
-
},
|
|
289
|
-
ImportDeclaration(path) {
|
|
290
|
-
path.node.specifiers.forEach(specifier => {
|
|
291
|
-
let type = specifier.type;
|
|
292
|
-
let hasImportName = type !== 'ImportDefaultSpecifier' &&
|
|
293
|
-
type !== 'ImportNamespaceSpecifier'
|
|
294
|
-
imports[specifier.local.name] = {
|
|
295
|
-
type,
|
|
296
|
-
importName: hasImportName ?
|
|
297
|
-
specifier.imported.name :
|
|
298
|
-
null,
|
|
299
|
-
source: path.node.source.value
|
|
300
|
-
};
|
|
301
|
-
|
|
302
|
-
if (!hasImportName) {
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
if (canHaveMethods && specifier.imported.name === 'createMethod') {
|
|
307
|
-
createMethodName = specifier.local.name;
|
|
308
|
-
}
|
|
309
|
-
if (canHavePublications && specifier.imported.name === 'createPublication') {
|
|
310
|
-
createPublicationName = specifier.local.name;
|
|
311
|
-
}
|
|
312
|
-
});
|
|
313
|
-
},
|
|
314
|
-
ExportDefaultDeclaration(path) {
|
|
315
|
-
if (path.node.declaration.type !== 'CallExpression') {
|
|
316
|
-
return;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
let call = getFirstCallExpr(path.get('declaration'));
|
|
320
|
-
|
|
321
|
-
if (!call) {
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
if (
|
|
326
|
-
call.node.callee.name === createMethodName
|
|
327
|
-
) {
|
|
328
|
-
let name = getOrAddName(call.node.arguments, {
|
|
329
|
-
exportName: null,
|
|
330
|
-
filePath,
|
|
331
|
-
isPub: false
|
|
332
|
-
});
|
|
333
|
-
if (name === undefined) {
|
|
334
|
-
throw new Error('Unable to find name for createMethod');
|
|
335
|
-
}
|
|
336
|
-
let stubPropIndex = findStubPropertyIndex(call.node.arguments);
|
|
337
|
-
let stub;
|
|
338
|
-
if (stubPropIndex > -1) {
|
|
339
|
-
stub = call.get(`arguments.0.properties.${stubPropIndex}`);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
methods.push({
|
|
343
|
-
name: name,
|
|
344
|
-
export: null,
|
|
345
|
-
stub
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
if (
|
|
350
|
-
call.node.callee.name === createPublicationName
|
|
351
|
-
) {
|
|
352
|
-
let name = getOrAddName(call.node.arguments, {
|
|
353
|
-
exportName: null,
|
|
354
|
-
filePath,
|
|
355
|
-
isPub: true
|
|
356
|
-
});
|
|
357
|
-
if (name === undefined) {
|
|
358
|
-
throw new Error('Unable to find name for createMethod');
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
publications.push({
|
|
362
|
-
name: name,
|
|
363
|
-
export: null
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
},
|
|
367
|
-
ExportNamedDeclaration(path) {
|
|
368
|
-
let declaration = path.get('declaration');
|
|
369
|
-
|
|
370
|
-
if (
|
|
371
|
-
// null when the code is something like "export { h };"
|
|
372
|
-
!declaration.node ||
|
|
373
|
-
declaration.isFunctionDeclaration()
|
|
374
|
-
) {
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
if (declaration.type == 'ClassDeclaration') {
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
if (declaration.type !== 'VariableDeclaration') {
|
|
383
|
-
throw new Error(`export declarations of type ${declaration.type} are not supported`);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
declaration.get('declarations').forEach(vDeclaration => {
|
|
387
|
-
if (!vDeclaration.isVariableDeclarator()) {
|
|
388
|
-
throw new Error(`Unsupported declaration type in VariableDeclaration: ${vDeclaration.node.type}`);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
if (!vDeclaration.get('init').isCallExpression()) {
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
let call = getFirstCallExpr(vDeclaration.get('init'));
|
|
396
|
-
|
|
397
|
-
if (!call) {
|
|
398
|
-
return;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
if (
|
|
402
|
-
call.node.callee.name === createMethodName
|
|
403
|
-
) {
|
|
404
|
-
let name = getOrAddName(call.node.arguments, {
|
|
405
|
-
exportName: vDeclaration.node.id.name,
|
|
406
|
-
filePath,
|
|
407
|
-
isPub: false
|
|
408
|
-
});
|
|
409
|
-
if (name === undefined) {
|
|
410
|
-
throw new Error('Unable to find name for createMethod');
|
|
411
|
-
}
|
|
412
|
-
let stubPropIndex = findStubPropertyIndex(call.node.arguments);
|
|
413
|
-
let stub;
|
|
414
|
-
if (stubPropIndex > -1) {
|
|
415
|
-
stub = call.get(`arguments.0.properties.${stubPropIndex}`);
|
|
416
|
-
}
|
|
417
|
-
methods.push({
|
|
418
|
-
name: name,
|
|
419
|
-
export: vDeclaration.node.id.name,
|
|
420
|
-
stub
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
if (
|
|
425
|
-
call.node.callee.name === createPublicationName
|
|
426
|
-
) {
|
|
427
|
-
let name = getOrAddName(call.node.arguments, {
|
|
428
|
-
exportName: vDeclaration.node.id.name,
|
|
429
|
-
filePath,
|
|
430
|
-
isPub: true
|
|
431
|
-
});
|
|
432
|
-
if (name === undefined) {
|
|
433
|
-
throw new Error('Unable to find name for createMethod');
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
publications.push({
|
|
437
|
-
name: name,
|
|
438
|
-
export: vDeclaration.node.id.name
|
|
439
|
-
});
|
|
440
|
-
}
|
|
441
|
-
})
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
};
|
|
1
|
+
const { createHash } = require('crypto');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
// If has a MemberExpression, returns the first call expression in its callee
|
|
5
|
+
// Otherwise, returns the call expression
|
|
6
|
+
function getFirstCallExpr(call) {
|
|
7
|
+
if (call.node.callee.type !== 'MemberExpression') {
|
|
8
|
+
return call;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
if (
|
|
13
|
+
call.node.callee.object.type !== 'CallExpression'
|
|
14
|
+
) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return call.get('callee.object');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = function (api) {
|
|
22
|
+
let t = api.types;
|
|
23
|
+
|
|
24
|
+
let caller;
|
|
25
|
+
api.caller(function (c) {
|
|
26
|
+
caller = c;
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
function createExport(exportName, callee, name, stub) {
|
|
30
|
+
let args = [
|
|
31
|
+
t.StringLiteral(name)
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
if (stub) {
|
|
35
|
+
if (stub.type === 'ObjectMethod') {
|
|
36
|
+
stub = t.FunctionExpression(
|
|
37
|
+
null,
|
|
38
|
+
stub.node.params || [],
|
|
39
|
+
stub.node.body,
|
|
40
|
+
stub.node.generator,
|
|
41
|
+
stub.node.async
|
|
42
|
+
)
|
|
43
|
+
} else if (stub.type === 'ObjectProperty') {
|
|
44
|
+
stub = stub.node.value;
|
|
45
|
+
}
|
|
46
|
+
args.push(stub);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const declaration = t.CallExpression(
|
|
50
|
+
t.Identifier(callee),
|
|
51
|
+
args
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
if (exportName === null) {
|
|
55
|
+
return t.ExportDefaultDeclaration(
|
|
56
|
+
declaration
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return t.ExportNamedDeclaration(
|
|
61
|
+
t.VariableDeclaration(
|
|
62
|
+
'const',
|
|
63
|
+
[t.VariableDeclarator(
|
|
64
|
+
t.Identifier(exportName),
|
|
65
|
+
declaration
|
|
66
|
+
)]
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function getOrAddName(args, { exportName, filePath, isPub }) {
|
|
72
|
+
if (args[0].type !== 'ObjectExpression') {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let obj = args[0];
|
|
77
|
+
let nameProperty = obj.properties.find((property) => {
|
|
78
|
+
if (property.key.type !== 'Identifier') {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (property.key.name !== 'name') {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return property.value.type === 'StringLiteral';
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (nameProperty) {
|
|
90
|
+
return nameProperty.value.value;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
let fileHash = 'M' + createHash('sha256')
|
|
94
|
+
.update(filePath)
|
|
95
|
+
.digest('hex')
|
|
96
|
+
.substring(0, 5);
|
|
97
|
+
|
|
98
|
+
let name = exportName;
|
|
99
|
+
|
|
100
|
+
if (name === null) {
|
|
101
|
+
let baseName = path.basename(filePath);
|
|
102
|
+
let lastDotIndex = baseName.lastIndexOf('.');
|
|
103
|
+
name = baseName.substring(0, lastDotIndex);
|
|
104
|
+
} else if (isPub && name.startsWith('subscribe')) {
|
|
105
|
+
name = exportName.substring('subscribe'.length);
|
|
106
|
+
|
|
107
|
+
if (name[0] !== name[0].toLowerCase()) {
|
|
108
|
+
name = `${name[0].toLowerCase()}${name.substring(1)}`
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
name += fileHash;
|
|
113
|
+
|
|
114
|
+
obj.properties.push(t.ObjectProperty(
|
|
115
|
+
t.Identifier('name'),
|
|
116
|
+
t.StringLiteral(name)
|
|
117
|
+
));
|
|
118
|
+
|
|
119
|
+
return name;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// TODO: args should be a path instead of node
|
|
123
|
+
function findStubPropertyIndex(args) {
|
|
124
|
+
let obj = args[0];
|
|
125
|
+
let stubPropIndex = obj.properties.findIndex((property) => {
|
|
126
|
+
if (property.key.type !== 'Identifier') {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (property.key.name !== 'stub') {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return true;
|
|
135
|
+
});
|
|
136
|
+
let stub = obj.properties[stubPropIndex];
|
|
137
|
+
|
|
138
|
+
if (!stub) {
|
|
139
|
+
return -1;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (
|
|
143
|
+
stub.type === 'ObjectMethod' ||
|
|
144
|
+
stub.value.type === 'FunctionExpression' ||
|
|
145
|
+
stub.value.type === 'ArrowFunctionExpression'
|
|
146
|
+
) {
|
|
147
|
+
return stubPropIndex;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
if (stub.value.type !== 'BooleanLiteral') {
|
|
152
|
+
return -1;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (stub.value.value !== true) {
|
|
156
|
+
return -1;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// stub is set to true - use the run function
|
|
160
|
+
return obj.properties.findIndex((property) => {
|
|
161
|
+
if (property.key.type !== 'Identifier') {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (property.key.name !== 'run') {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return true;
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
let canHaveMethods = false;
|
|
174
|
+
let canHavePublications = false;
|
|
175
|
+
let createMethodName = null;
|
|
176
|
+
let createPublicationName = null;
|
|
177
|
+
let methods = [];
|
|
178
|
+
let publications = [];
|
|
179
|
+
let isServer = false;
|
|
180
|
+
let filePath = ''
|
|
181
|
+
let imports = Object.create(null);
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
visitor: {
|
|
185
|
+
Program: {
|
|
186
|
+
enter(_, state) {
|
|
187
|
+
createMethodName = null;
|
|
188
|
+
createPublicationName = null;
|
|
189
|
+
methods = [];
|
|
190
|
+
publications = [];
|
|
191
|
+
|
|
192
|
+
let relPath = path
|
|
193
|
+
.relative(state.cwd, state.filename)
|
|
194
|
+
.split(path.sep)
|
|
195
|
+
.join(path.posix.sep);
|
|
196
|
+
filePath = relPath;
|
|
197
|
+
|
|
198
|
+
canHaveMethods = relPath.includes('/methods/') || relPath.startsWith('methods/');
|
|
199
|
+
canHavePublications = relPath.includes('/publications/') || relPath.startsWith('publications/');
|
|
200
|
+
|
|
201
|
+
isServer = caller.arch.startsWith('os.');
|
|
202
|
+
|
|
203
|
+
if (!canHaveMethods && !canHavePublications) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
exit(path) {
|
|
208
|
+
if (isServer || !canHaveMethods && !canHavePublications) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (methods.length === 0 && publications.length === 0) {
|
|
213
|
+
path.node.body = [];
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
let body = [];
|
|
218
|
+
|
|
219
|
+
let importSpecifiers = [];
|
|
220
|
+
if (methods.length > 0) {
|
|
221
|
+
importSpecifiers.push(
|
|
222
|
+
t.ImportSpecifier(t.Identifier('_createClientMethod'), t.Identifier('_createClientMethod'))
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
if (publications.length > 0) {
|
|
226
|
+
importSpecifiers.push(
|
|
227
|
+
t.ImportSpecifier(t.Identifier('_createClientPublication'), t.Identifier('_createClientPublication'))
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
let importDecl = t.ImportDeclaration(
|
|
232
|
+
importSpecifiers,
|
|
233
|
+
t.StringLiteral('meteor/zodern:relay/client'),
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
body.push(importDecl);
|
|
237
|
+
|
|
238
|
+
methods.forEach(method => {
|
|
239
|
+
if (method.stub) {
|
|
240
|
+
let stubBody = method.stub.get('body').node ?
|
|
241
|
+
method.stub.get('body') : method.stub.get('value.body');
|
|
242
|
+
stubBody.traverse({
|
|
243
|
+
ReferencedIdentifier(subPath) {
|
|
244
|
+
if (stubBody.scope.hasOwnBinding(subPath.node.name)) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (subPath.node.name in imports) {
|
|
249
|
+
let importDesc = imports[subPath.node.name];
|
|
250
|
+
|
|
251
|
+
let specifier;
|
|
252
|
+
if (importDesc.type === 'ImportDefaultSpecifier') {
|
|
253
|
+
specifier = t.ImportDefaultSpecifier(t.Identifier(subPath.node.name));
|
|
254
|
+
} else if (importDesc.type === 'ImportNamespaceSpecifier') {
|
|
255
|
+
specifier = t.ImportNamespaceSpecifier(t.Identifier(subPath.node.name));
|
|
256
|
+
} else {
|
|
257
|
+
specifier = t.ImportSpecifier(
|
|
258
|
+
t.Identifier(importDesc.importName),
|
|
259
|
+
t.Identifier(subPath.node.name)
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// TODO: we should preserve the original order of the imports
|
|
264
|
+
body.push(t.ImportDeclaration(
|
|
265
|
+
[ specifier ],
|
|
266
|
+
t.StringLiteral(importDesc.source)
|
|
267
|
+
));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
body.push(
|
|
274
|
+
createExport(method.export, '_createClientMethod', method.name, method.stub)
|
|
275
|
+
);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
publications.forEach(publication => {
|
|
279
|
+
body.push(
|
|
280
|
+
createExport(publication.export, '_createClientPublication', publication.name)
|
|
281
|
+
);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
path.node.body = body;
|
|
285
|
+
|
|
286
|
+
return;
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
ImportDeclaration(path) {
|
|
290
|
+
path.node.specifiers.forEach(specifier => {
|
|
291
|
+
let type = specifier.type;
|
|
292
|
+
let hasImportName = type !== 'ImportDefaultSpecifier' &&
|
|
293
|
+
type !== 'ImportNamespaceSpecifier'
|
|
294
|
+
imports[specifier.local.name] = {
|
|
295
|
+
type,
|
|
296
|
+
importName: hasImportName ?
|
|
297
|
+
specifier.imported.name :
|
|
298
|
+
null,
|
|
299
|
+
source: path.node.source.value
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
if (!hasImportName) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (canHaveMethods && specifier.imported.name === 'createMethod') {
|
|
307
|
+
createMethodName = specifier.local.name;
|
|
308
|
+
}
|
|
309
|
+
if (canHavePublications && specifier.imported.name === 'createPublication') {
|
|
310
|
+
createPublicationName = specifier.local.name;
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
},
|
|
314
|
+
ExportDefaultDeclaration(path) {
|
|
315
|
+
if (path.node.declaration.type !== 'CallExpression') {
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
let call = getFirstCallExpr(path.get('declaration'));
|
|
320
|
+
|
|
321
|
+
if (!call) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (
|
|
326
|
+
call.node.callee.name === createMethodName
|
|
327
|
+
) {
|
|
328
|
+
let name = getOrAddName(call.node.arguments, {
|
|
329
|
+
exportName: null,
|
|
330
|
+
filePath,
|
|
331
|
+
isPub: false
|
|
332
|
+
});
|
|
333
|
+
if (name === undefined) {
|
|
334
|
+
throw new Error('Unable to find name for createMethod');
|
|
335
|
+
}
|
|
336
|
+
let stubPropIndex = findStubPropertyIndex(call.node.arguments);
|
|
337
|
+
let stub;
|
|
338
|
+
if (stubPropIndex > -1) {
|
|
339
|
+
stub = call.get(`arguments.0.properties.${stubPropIndex}`);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
methods.push({
|
|
343
|
+
name: name,
|
|
344
|
+
export: null,
|
|
345
|
+
stub
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (
|
|
350
|
+
call.node.callee.name === createPublicationName
|
|
351
|
+
) {
|
|
352
|
+
let name = getOrAddName(call.node.arguments, {
|
|
353
|
+
exportName: null,
|
|
354
|
+
filePath,
|
|
355
|
+
isPub: true
|
|
356
|
+
});
|
|
357
|
+
if (name === undefined) {
|
|
358
|
+
throw new Error('Unable to find name for createMethod');
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
publications.push({
|
|
362
|
+
name: name,
|
|
363
|
+
export: null
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
ExportNamedDeclaration(path) {
|
|
368
|
+
let declaration = path.get('declaration');
|
|
369
|
+
|
|
370
|
+
if (
|
|
371
|
+
// null when the code is something like "export { h };"
|
|
372
|
+
!declaration.node ||
|
|
373
|
+
declaration.isFunctionDeclaration()
|
|
374
|
+
) {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (declaration.type == 'ClassDeclaration') {
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (declaration.type !== 'VariableDeclaration') {
|
|
383
|
+
throw new Error(`export declarations of type ${declaration.type} are not supported`);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
declaration.get('declarations').forEach(vDeclaration => {
|
|
387
|
+
if (!vDeclaration.isVariableDeclarator()) {
|
|
388
|
+
throw new Error(`Unsupported declaration type in VariableDeclaration: ${vDeclaration.node.type}`);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (!vDeclaration.get('init').isCallExpression()) {
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
let call = getFirstCallExpr(vDeclaration.get('init'));
|
|
396
|
+
|
|
397
|
+
if (!call) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (
|
|
402
|
+
call.node.callee.name === createMethodName
|
|
403
|
+
) {
|
|
404
|
+
let name = getOrAddName(call.node.arguments, {
|
|
405
|
+
exportName: vDeclaration.node.id.name,
|
|
406
|
+
filePath,
|
|
407
|
+
isPub: false
|
|
408
|
+
});
|
|
409
|
+
if (name === undefined) {
|
|
410
|
+
throw new Error('Unable to find name for createMethod');
|
|
411
|
+
}
|
|
412
|
+
let stubPropIndex = findStubPropertyIndex(call.node.arguments);
|
|
413
|
+
let stub;
|
|
414
|
+
if (stubPropIndex > -1) {
|
|
415
|
+
stub = call.get(`arguments.0.properties.${stubPropIndex}`);
|
|
416
|
+
}
|
|
417
|
+
methods.push({
|
|
418
|
+
name: name,
|
|
419
|
+
export: vDeclaration.node.id.name,
|
|
420
|
+
stub
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (
|
|
425
|
+
call.node.callee.name === createPublicationName
|
|
426
|
+
) {
|
|
427
|
+
let name = getOrAddName(call.node.arguments, {
|
|
428
|
+
exportName: vDeclaration.node.id.name,
|
|
429
|
+
filePath,
|
|
430
|
+
isPub: true
|
|
431
|
+
});
|
|
432
|
+
if (name === undefined) {
|
|
433
|
+
throw new Error('Unable to find name for createMethod');
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
publications.push({
|
|
437
|
+
name: name,
|
|
438
|
+
export: vDeclaration.node.id.name
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
})
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
445
|
}
|