Skip to content

Commit 1fd47b1

Browse files
author
Elad Ben-Israel
committed
feat: outputJsii
allows emitting the .jsii file during compilation (for testing purposes mostly).
1 parent 7d694f5 commit 1fd47b1

5 files changed

Lines changed: 130 additions & 27 deletions

File tree

lib/compile.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,29 @@ export async function compile(workdir: string, options: Options) {
2020
const basepath = path.join(path.dirname(entrypoint), path.basename(entrypoint, '.ts'));
2121

2222
// jsii modules to include
23-
const modules = options.modules ?? [];
23+
const moduleDirs = options.moduleDirs ?? [];
2424

2525
const targets: Record<string, any> = { };
2626

2727
const deps: Record<string, string> = { };
28-
for (const mod of modules) {
29-
if (mod.startsWith('@types/')) {
30-
continue;
31-
}
3228

33-
deps[mod] = '*';
29+
for (const dir of moduleDirs) {
30+
// read module metadata
31+
const metadata = await fs.readJson(path.join(dir, 'package.json'));
32+
const moduleName: string = metadata.name;
33+
const moduleVersion: string = metadata.version;
34+
35+
const targetdir = path.join(path.join(workdir, 'node_modules'), moduleName);
36+
await fs.mkdirp(path.dirname(targetdir));
37+
await fs.ensureSymlink(dir, targetdir);
38+
39+
// add to "deps" and "peer deps"
40+
if (!moduleName.startsWith('@types/')) {
41+
deps[moduleName] = moduleVersion;
42+
}
3443
}
3544

45+
3646
const pkg = {
3747
name: 'generated',
3848
version: '0.0.0',
@@ -56,11 +66,6 @@ export async function compile(workdir: string, options: Options) {
5666
};
5767
}
5868

59-
for (const mod of modules) {
60-
const sourcedir = path.dirname(require.resolve(`${mod}/package.json`));
61-
await fs.mkdirp(path.join(workdir, path.join('node_modules', path.dirname(mod))));
62-
await fs.ensureSymlink(sourcedir, path.join(workdir, 'node_modules', mod));
63-
}
6469

6570
await fs.writeFile(path.join(workdir, 'package.json'), JSON.stringify(pkg, undefined, 2));
6671

lib/options.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,29 @@
1-
export interface Options {
1+
export interface CommonOptions {
22
/**
33
* The relative path of the .ts entrypoint within the source directory.
44
* @default "index.ts"
55
*/
66
entrypoint?: string;
77

88
/**
9-
* The name of the the python module to generate. If omitted python will not be generated.
9+
* List of directories that include node modules to symlink into the compiled
10+
* package. For example, if your generated code references some library, you
11+
* should include it's module directory in here.
1012
*/
11-
pythonName?: string;
13+
moduleDirs?: string[];
1214

1315
/**
14-
* List of module names to compile against. These modules must be resolvable
15-
* against the current executable and their version will be the same version.
16+
* Path to output the .jsii file output.
17+
* @default - jsii file is not emitted.
1618
*/
17-
modules?: string[];
19+
outputJsii?: string;
1820
}
21+
22+
export interface PythonOptions extends CommonOptions {
23+
/**
24+
* The name of the the python module to generate. If omitted python will not be generated.
25+
*/
26+
pythonName?: string;
27+
}
28+
29+
export type Options = PythonOptions; /* | JavaOptions | DotNetOptions */

lib/srcmak.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import { Options } from './options';
66

77
const pacmakModule = require.resolve('jsii-pacmak/bin/jsii-pacmak');
88

9-
export async function srcmak(srcdir: string, targetdir: string, options: Options) {
9+
export async function srcmak(srcdir: string, targetdir: string, options: Options = { }) {
1010
srcdir = path.resolve(srcdir);
1111
targetdir = path.resolve(targetdir);
1212

13+
const outputJsii = options.outputJsii ? path.resolve(options.outputJsii) : undefined;
14+
1315
await withTempDir('jsii-codemak', async () => {
1416
// copy sources to temp directory
1517
await fs.copy(srcdir, '.');
@@ -20,6 +22,10 @@ export async function srcmak(srcdir: string, targetdir: string, options: Options
2022
// run pacmak to generate code
2123
await exec(pacmakModule, [ '--code-only' ]);
2224

25+
if (outputJsii) {
26+
await fs.copy('.jsii', outputJsii);
27+
}
28+
2329
// extract code based on selected languages
2430
if (options.pythonName) {
2531
const reldir = options.pythonName.replace(/\./g, '/'); // replace "." with "/"

test/__snapshots__/jsii-srcmak.test.js.snap renamed to test/__snapshots__/srcmak.test.js.snap

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,61 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`outputJsii can be used to look at the jsii file 1`] = `
4+
Object {
5+
"author": Object {
6+
"name": "generated@generated.com",
7+
"roles": Array [
8+
"author",
9+
],
10+
},
11+
"description": "generated",
12+
"fingerprint": "mDN1As+e+zwuytAHqC8o+7gwTrnrzC2d65pSGEUAe1I=",
13+
"homepage": "http://generated",
14+
"jsiiVersion": "1.5.0 (build 46538f8)",
15+
"license": "Apache-2.0",
16+
"name": "generated",
17+
"repository": Object {
18+
"type": "git",
19+
"url": "http://generated",
20+
},
21+
"schema": "jsii/0.10.0",
22+
"targets": Object {
23+
"js": Object {
24+
"npm": "generated",
25+
},
26+
},
27+
"types": Object {
28+
"generated.Foo": Object {
29+
"assembly": "generated",
30+
"fqn": "generated.Foo",
31+
"initializer": Object {},
32+
"kind": "class",
33+
"locationInModule": Object {
34+
"filename": "index.ts",
35+
"line": 2,
36+
},
37+
"methods": Array [
38+
Object {
39+
"locationInModule": Object {
40+
"filename": "index.ts",
41+
"line": 3,
42+
},
43+
"name": "hello",
44+
"returns": Object {
45+
"type": Object {
46+
"primitive": "string",
47+
},
48+
},
49+
"static": true,
50+
},
51+
],
52+
"name": "Foo",
53+
},
54+
},
55+
"version": "0.0.0",
56+
}
57+
`;
58+
359
exports[`python + different entrypoint + submodule 1`] = `
460
Object {
561
"my_python_module/submodule/__init__.py": "import abc
@@ -12,7 +68,7 @@ import jsii
1268
import jsii.compat
1369
import publication
1470
15-
__jsii_assembly__ = jsii.JSIIAssembly.load(\\"generated\\", \\"0.0.0\\", __name__, \\"generated@0.0.0.jsii.tgz\\")
71+
from ._jsii import *
1672
1773
1874
class Hello(metaclass=jsii.JSIIMeta, jsii_type=\\"generated.Hello\\"):
@@ -32,7 +88,7 @@ class Hello(metaclass=jsii.JSIIMeta, jsii_type=\\"generated.Hello\\"):
3288
3389
@jsii.data_type(jsii_type=\\"generated.Operands\\", jsii_struct_bases=[], name_mapping={'lhs': 'lhs', 'rhs': 'rhs'})
3490
class Operands():
35-
def __init__(self, *, lhs: jsii.Number, rhs: jsii.Number):
91+
def __init__(self, *, lhs: jsii.Number, rhs: jsii.Number) -> None:
3692
\\"\\"\\"
3793
:param lhs: -
3894
:param rhs: -
@@ -60,7 +116,10 @@ class Operands():
60116
return 'Operands(%s)' % ', '.join(k + '=' + repr(v) for k, v in self._values.items())
61117
62118
63-
__all__ = [\\"Hello\\", \\"Operands\\", \\"__jsii_assembly__\\"]
119+
__all__ = [
120+
\\"Hello\\",
121+
\\"Operands\\",
122+
]
64123
65124
publication.publish()
66125
",
@@ -73,7 +132,12 @@ import typing
73132
import jsii
74133
import jsii.compat
75134
import publication
76-
__all__ = []
135+
136+
__jsii_assembly__ = jsii.JSIIAssembly.load(\\"generated\\", \\"0.0.0\\", __name__[0:-6], \\"generated@0.0.0.jsii.tgz\\")
137+
138+
__all__ = [
139+
\\"__jsii_assembly__\\",
140+
]
77141
78142
publication.publish()
79143
",
Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ test('just compile', async () => {
2222
`);
2323

2424
await withTempDir('target', async target => {
25-
await srcmak(source, target, { modules: [] });
25+
await srcmak(source, target);
2626
});
2727
});
2828
});
@@ -33,7 +33,7 @@ test('compilation error fails and includes error message', async () => {
3333

3434
await withTempDir('target', async target => {
3535
let error;
36-
try { await srcmak(source, target, { modules: [] }); }
36+
try { await srcmak(source, target); }
3737
catch (e) { error = e; }
3838

3939
expect(error).toBeDefined();
@@ -65,7 +65,6 @@ test('python + different entrypoint + submodule', async () => {
6565
await srcmak(source, target, {
6666
entrypoint: 'different/entry.ts',
6767
pythonName: 'my_python_module.submodule',
68-
modules: [],
6968
});
7069

7170
const dir = await snapshotDirectory(target, [ 'generated@0.0.0.jsii.tgz' ]);
@@ -88,10 +87,28 @@ test('compile against a local jsii dependency', async () => {
8887

8988
await withTempDir('target', async target => {
9089
await srcmak(source, target, {
91-
modules: [
92-
'constructs', // <<---- this is the magic
90+
moduleDirs: [
91+
path.dirname(require.resolve('constructs/package.json')), // <<---- this is the magic
9392
],
9493
});
9594
});
9695
});
9796
});
97+
98+
test('outputJsii can be used to look at the jsii file', async () => {
99+
await withTempDir('source', async source => {
100+
await fs.writeFile('index.ts', `
101+
export class Foo {
102+
public static hello() { return "world"; }
103+
}
104+
`);
105+
106+
await withTempDir('target', async target => {
107+
await srcmak(source, target, {
108+
outputJsii: '.jsii',
109+
});
110+
111+
expect(await fs.readJson('.jsii')).toMatchSnapshot();
112+
});
113+
})
114+
});

0 commit comments

Comments
 (0)