@reproapp/node-sdk 0.0.18 → 0.0.19
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reproapp/node-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.19",
|
|
4
4
|
"description": "Repro Nest SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
"build": "tsc -p tsconfig.json",
|
|
13
13
|
"dev": "tsc -p tsconfig.json --watch --preserveWatchOutput",
|
|
14
14
|
"prepublishOnly": "npm run build",
|
|
15
|
-
"test": "npm run build && node test/unawaited.test.js && node test/integration-unawaited.js && node test/request-flush-timing.test.js && node test/request-manifest-priority.test.js && node test/runtime-no-double-invoke.test.js && node test/express-trace-http-args.test.js && node test/trace-batch-size.test.js && node test/sdk-background-priority.test.js && node test/ingest-queue-retention.test.js && node test/ingest-timeout.test.js && node -r ./tracer/register test/promise-map.test.js && node test/disable-subtree.test.js && node test/circular-capture.test.js && node test/wrap-plugin-arrow-args.test.js && node test/privacy-runtime-policy.test.js && node test/runtime-privacy-materialization.test.js && node test/kafka-runtime-privacy-policy.test.js",
|
|
16
|
-
"test:containers": "npm run build && node test/runtime-no-double-invoke.testcontainers.test.js"
|
|
15
|
+
"test": "npm run build && node test/unawaited.test.js && node test/integration-unawaited.js && node test/request-flush-timing.test.js && node test/request-manifest-priority.test.js && node test/runtime-no-double-invoke.test.js && node test/express-trace-http-args.test.js && node test/trace-batch-size.test.js && node test/sdk-background-priority.test.js && node test/ingest-queue-retention.test.js && node test/ingest-timeout.test.js && node -r ./tracer/register test/promise-map.test.js && node test/disable-subtree.test.js && node test/circular-capture.test.js && node test/wrap-plugin-arrow-args.test.js && node test/wrap-plugin-super-call.test.js && node test/privacy-runtime-policy.test.js && node test/runtime-privacy-materialization.test.js && node test/kafka-runtime-privacy-policy.test.js",
|
|
16
|
+
"test:containers": "npm run build && node test/runtime-no-double-invoke.testcontainers.test.js && node test/wrap-plugin-super-call.testcontainers.test.js"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
19
|
"express": "^5.1.0",
|
|
@@ -7,7 +7,7 @@ const { trace } = require('../tracer/runtime');
|
|
|
7
7
|
async function startMongo() {
|
|
8
8
|
return new GenericContainer('mongo:7')
|
|
9
9
|
.withExposedPorts(27017)
|
|
10
|
-
.withTmpFs({ '/data/db': 'rw,noexec,nosuid,size=
|
|
10
|
+
.withTmpFs({ '/data/db': 'rw,noexec,nosuid,size=1g' })
|
|
11
11
|
.withCommand(['mongod', '--bind_ip_all', '--setParameter', 'diagnosticDataCollectionEnabled=false'])
|
|
12
12
|
.withWaitStrategy(Wait.forListeningPorts())
|
|
13
13
|
.start();
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const assert = require('assert');
|
|
2
|
+
const vm = require('vm');
|
|
3
|
+
const babel = require('@babel/core');
|
|
4
|
+
const makeWrapPlugin = require('../tracer/wrap-plugin');
|
|
5
|
+
require('../tracer/runtime');
|
|
6
|
+
|
|
7
|
+
function transform(source, filename) {
|
|
8
|
+
return babel.transformSync(source, {
|
|
9
|
+
filename,
|
|
10
|
+
plugins: [makeWrapPlugin(filename, {})],
|
|
11
|
+
parserOpts: { sourceType: 'script', plugins: ['typescript'] },
|
|
12
|
+
generatorOpts: { retainLines: true },
|
|
13
|
+
}).code;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function loadInstrumentedModule(source, filename) {
|
|
17
|
+
const code = transform(source, filename);
|
|
18
|
+
const module = { exports: {} };
|
|
19
|
+
const context = {
|
|
20
|
+
module,
|
|
21
|
+
exports: module.exports,
|
|
22
|
+
require,
|
|
23
|
+
console,
|
|
24
|
+
__trace: global.__trace,
|
|
25
|
+
__repro_call: global.__repro_call,
|
|
26
|
+
Promise,
|
|
27
|
+
Buffer,
|
|
28
|
+
setTimeout,
|
|
29
|
+
clearTimeout,
|
|
30
|
+
setImmediate,
|
|
31
|
+
clearImmediate,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
vm.runInNewContext(code, context, { filename });
|
|
35
|
+
return { exports: module.exports, code };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function toPlainJson(value) {
|
|
39
|
+
return JSON.parse(JSON.stringify(value));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function main() {
|
|
43
|
+
const filename = '/tmp/wrap-plugin-super-call.fixture.js';
|
|
44
|
+
const { exports: mod, code } = loadInstrumentedModule(`
|
|
45
|
+
class BaseNotificationGenerator {
|
|
46
|
+
async resolveNotificationConfig(params) {
|
|
47
|
+
return { source: 'base', params };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
class SubjectNotificationGenerator extends BaseNotificationGenerator {
|
|
52
|
+
async resolveNotificationConfig(params, preloaded) {
|
|
53
|
+
return preloaded
|
|
54
|
+
? Promise.resolve(preloaded)
|
|
55
|
+
: super.resolveNotificationConfig(params);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = { SubjectNotificationGenerator };
|
|
60
|
+
`, filename);
|
|
61
|
+
|
|
62
|
+
assert(!code.includes('= super'), `transformed code must not assign super into a temp:\n${code}`);
|
|
63
|
+
|
|
64
|
+
const generator = new mod.SubjectNotificationGenerator();
|
|
65
|
+
assert.deepStrictEqual(
|
|
66
|
+
toPlainJson(await generator.resolveNotificationConfig({ id: 'S_1' }, null)),
|
|
67
|
+
{ source: 'base', params: { id: 'S_1' } },
|
|
68
|
+
);
|
|
69
|
+
assert.deepStrictEqual(
|
|
70
|
+
toPlainJson(await generator.resolveNotificationConfig({ id: 'S_2' }, { source: 'preloaded' })),
|
|
71
|
+
{ source: 'preloaded' },
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
console.log('wrap-plugin super call OK');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
main().catch((error) => {
|
|
78
|
+
console.error(error);
|
|
79
|
+
process.exitCode = 1;
|
|
80
|
+
});
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const assert = require('assert');
|
|
2
|
+
const vm = require('vm');
|
|
3
|
+
const babel = require('@babel/core');
|
|
4
|
+
const mongoose = require('mongoose');
|
|
5
|
+
const { GenericContainer, Wait } = require('testcontainers');
|
|
6
|
+
|
|
7
|
+
const makeWrapPlugin = require('../tracer/wrap-plugin');
|
|
8
|
+
require('../tracer/runtime');
|
|
9
|
+
|
|
10
|
+
function transform(source, filename) {
|
|
11
|
+
return babel.transformSync(source, {
|
|
12
|
+
filename,
|
|
13
|
+
plugins: [makeWrapPlugin(filename, {})],
|
|
14
|
+
parserOpts: { sourceType: 'script', plugins: ['typescript'] },
|
|
15
|
+
generatorOpts: { retainLines: true },
|
|
16
|
+
}).code;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function loadInstrumentedModule(source, filename) {
|
|
20
|
+
const code = transform(source, filename);
|
|
21
|
+
const module = { exports: {} };
|
|
22
|
+
const context = {
|
|
23
|
+
module,
|
|
24
|
+
exports: module.exports,
|
|
25
|
+
require,
|
|
26
|
+
console,
|
|
27
|
+
__trace: global.__trace,
|
|
28
|
+
__repro_call: global.__repro_call,
|
|
29
|
+
Promise,
|
|
30
|
+
Buffer,
|
|
31
|
+
setTimeout,
|
|
32
|
+
clearTimeout,
|
|
33
|
+
setImmediate,
|
|
34
|
+
clearImmediate,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
vm.runInNewContext(code, context, { filename });
|
|
38
|
+
return module.exports;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function toPlainJson(value) {
|
|
42
|
+
return JSON.parse(JSON.stringify(value));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function startMongo() {
|
|
46
|
+
return new GenericContainer('mongo:7')
|
|
47
|
+
.withExposedPorts(27017)
|
|
48
|
+
.withTmpFs({ '/data/db': 'rw,noexec,nosuid,size=1g' })
|
|
49
|
+
.withCommand(['mongod', '--bind_ip_all', '--setParameter', 'diagnosticDataCollectionEnabled=false'])
|
|
50
|
+
.withWaitStrategy(Wait.forListeningPorts())
|
|
51
|
+
.start();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function main() {
|
|
55
|
+
let container;
|
|
56
|
+
let connection;
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
container = await startMongo();
|
|
60
|
+
const uri = `mongodb://${container.getHost()}:${container.getMappedPort(27017)}/repro_node_sdk_super_test`;
|
|
61
|
+
connection = await mongoose.createConnection(uri).asPromise();
|
|
62
|
+
const Notification = connection.model('Notification', new mongoose.Schema({
|
|
63
|
+
name: { type: String, required: true },
|
|
64
|
+
}));
|
|
65
|
+
|
|
66
|
+
const { SubjectNotificationGenerator } = loadInstrumentedModule(`
|
|
67
|
+
class BaseNotificationGenerator {
|
|
68
|
+
constructor(model) {
|
|
69
|
+
this.model = model;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async resolveNotificationConfig(params) {
|
|
73
|
+
await this.model.create({ name: params.name });
|
|
74
|
+
return { source: 'base', name: params.name };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
class SubjectNotificationGenerator extends BaseNotificationGenerator {
|
|
79
|
+
async resolveNotificationConfig(params, preloaded) {
|
|
80
|
+
return preloaded
|
|
81
|
+
? Promise.resolve(preloaded)
|
|
82
|
+
: super.resolveNotificationConfig(params);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
module.exports = { SubjectNotificationGenerator };
|
|
87
|
+
`, '/tmp/wrap-plugin-super-call-container.fixture.js');
|
|
88
|
+
|
|
89
|
+
const generator = new SubjectNotificationGenerator(Notification);
|
|
90
|
+
assert.deepStrictEqual(
|
|
91
|
+
toPlainJson(await generator.resolveNotificationConfig({ name: 'created-through-super' }, null)),
|
|
92
|
+
{ source: 'base', name: 'created-through-super' },
|
|
93
|
+
);
|
|
94
|
+
assert.deepStrictEqual(
|
|
95
|
+
toPlainJson(await generator.resolveNotificationConfig({ name: 'not-created' }, { source: 'preloaded' })),
|
|
96
|
+
{ source: 'preloaded' },
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
assert.strictEqual(await Notification.countDocuments({ name: 'created-through-super' }), 1);
|
|
100
|
+
assert.strictEqual(await Notification.countDocuments({ name: 'not-created' }), 0);
|
|
101
|
+
|
|
102
|
+
console.log('wrap-plugin super call testcontainers OK');
|
|
103
|
+
} finally {
|
|
104
|
+
if (connection) {
|
|
105
|
+
await connection.close().catch(() => {});
|
|
106
|
+
}
|
|
107
|
+
if (container) {
|
|
108
|
+
await container.stop().catch(() => {});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
main().catch((error) => {
|
|
114
|
+
console.error(error);
|
|
115
|
+
process.exitCode = 1;
|
|
116
|
+
});
|
package/tracer/wrap-plugin.js
CHANGED
|
@@ -49,6 +49,13 @@ module.exports = function makeWrapPlugin(filenameForMeta, opts = {}) {
|
|
|
49
49
|
return '';
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
function isSuperMemberCall(callee) {
|
|
53
|
+
if (!callee) return false;
|
|
54
|
+
if (t.isMemberExpression(callee) && t.isSuper(callee.object)) return true;
|
|
55
|
+
if (t.isOptionalMemberExpression && t.isOptionalMemberExpression(callee) && t.isSuper(callee.object)) return true;
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
52
59
|
const obj = kv => t.objectExpression(
|
|
53
60
|
Object.entries(kv)
|
|
54
61
|
.filter(([, v]) => v != null)
|
|
@@ -451,6 +458,7 @@ module.exports = function makeWrapPlugin(filenameForMeta, opts = {}) {
|
|
|
451
458
|
if (t.isIdentifier(n.callee, { name: '__awaiter' })) return;
|
|
452
459
|
if (t.isIdentifier(n.callee, { name: '__generator' })) return;
|
|
453
460
|
if (t.isSuper(n.callee)) return;
|
|
461
|
+
if (isSuperMemberCall(n.callee)) return;
|
|
454
462
|
if (t.isImport(n.callee)) return;
|
|
455
463
|
|
|
456
464
|
if (t.isMemberExpression(n.callee) && t.isIdentifier(n.callee.object, { name: '__trace' })) {
|
|
@@ -559,6 +567,7 @@ module.exports = function makeWrapPlugin(filenameForMeta, opts = {}) {
|
|
|
559
567
|
if (t.isIdentifier(n.callee, { name: '__awaiter' })) return;
|
|
560
568
|
if (t.isIdentifier(n.callee, { name: '__generator' })) return;
|
|
561
569
|
if (t.isSuper(n.callee)) return;
|
|
570
|
+
if (isSuperMemberCall(n.callee)) return;
|
|
562
571
|
if (t.isImport(n.callee)) return;
|
|
563
572
|
|
|
564
573
|
const loc = n.loc?.start || null;
|