Skip to content

Commit 766de96

Browse files
campionfellinElad Ben-Israel
andauthored
fix: Package name collisions (#22)
* fix: Package name collisions Fixes: cdk8s-team/cdk8s#273 Signed-off-by: campionfellin <campionfellin@gmail.com> * chore: Update jsii version to 1.6 Signed-off-by: campionfellin <campionfellin@gmail.com> * fix: fallback to hash for default packageName and fix hyphens in python package names Signed-off-by: campionfellin <campionfellin@gmail.com> * fix: hypens to underscores for python package names Signed-off-by: campionfellin <campionfellin@gmail.com> * chore: sync up dependencies with projen Signed-off-by: campionfellin <campionfellin@gmail.com> * chore: clean up snapshots Signed-off-by: campionfellin <campionfellin@gmail.com> * Revert "chore: sync up dependencies with projen" This reverts commit 58e1784. * Revert "chore: Update jsii version to 1.6" This reverts commit 824bb84. * fix: remove weird characters from snapshot Signed-off-by: campionfellin <campionfellin@gmail.com> * fix: back to yarn.lock from mainline Signed-off-by: campionfellin <campionfellin@gmail.com> * fix: Respond to comments Signed-off-by: campionfellin <campionfellin@gmail.com> * fix: Update test utils to ignore all jsii.tgz binary files Signed-off-by: campionfellin <campionfellin@gmail.com> * fix: update snapshots Signed-off-by: campionfellin <campionfellin@gmail.com> * fix: snapshots Signed-off-by: campionfellin <campionfellin@gmail.com> * fix: snapshots Signed-off-by: campionfellin <campionfellin@gmail.com> * fix: snapshots Signed-off-by: campionfellin <campionfellin@gmail.com> * fix: validate input options for python module name and java package Signed-off-by: campionfellin <campionfellin@gmail.com> Co-authored-by: Elad Ben-Israel <benisrae@amazon.com>
1 parent 6b1f015 commit 766de96

9 files changed

Lines changed: 115 additions & 48 deletions

File tree

src/compile.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import * as fs from 'fs-extra';
22
import * as path from 'path';
3-
import { exec } from './util';
3+
import { exec, validateOptions } from './util';
44
import { Options } from './options';
5+
import * as crypto from 'crypto';
56

67
const compilerModule = require.resolve('jsii/bin/jsii');
78

89
/**
910
* Compiles the source files in `workdir` with jsii.
1011
*/
1112
export async function compile(workdir: string, options: Options) {
13+
validateOptions(options);
14+
1215
const args = [ '--silence-warnings', 'reserved-word' ];
1316
const entrypoint = options.entrypoint ?? 'index.ts';
1417

@@ -23,6 +26,8 @@ export async function compile(workdir: string, options: Options) {
2326
// path to entrypoint without extension
2427
const basepath = path.join(path.dirname(entrypoint), path.basename(entrypoint, '.ts'));
2528

29+
const moduleKey = options.moduleKey?.replace(/\./g, '').replace(/\//g, '') ?? crypto.createHash('sha256').update(basepath, 'utf8').digest('hex');
30+
2631
// jsii modules to include
2732
const moduleDirs = options.deps ?? [];
2833

@@ -46,9 +51,8 @@ export async function compile(workdir: string, options: Options) {
4651
}
4752
}
4853

49-
5054
const pkg = {
51-
name: 'generated',
55+
name: moduleKey,
5256
version: '0.0.0',
5357
author: 'generated@generated.com',
5458
main: `${basepath}.js`,

src/options.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ export interface Options {
1818
*/
1919
jsii?: JsiiOutputOptions;
2020

21+
/**
22+
* Key for the module to prevent JSII collisions.
23+
*
24+
* Use your own if it's project-unique, otherwise use default.
25+
*
26+
* @default - hash of the basepath to the module
27+
*/
28+
moduleKey?: string
29+
2130
/**
2231
* Produce python code.
2332
* @default - python is not generated
@@ -47,6 +56,9 @@ export interface PythonOutputOptions {
4756

4857
/**
4958
* The name of the the python module to generate.
59+
*
60+
* This must follow the standard Python module name conventions.
61+
* For example, it cannot include a hyphen ('-')
5062
*/
5163
moduleName: string;
5264
}
@@ -59,6 +71,9 @@ export interface JavaOutputOptions {
5971

6072
/**
6173
* The name of the java package to generate
74+
*
75+
* This must follow standard Java package conventions.
76+
* For example, it cannot include a hyphen ('-')
6277
*/
6378
package: string;
6479
}

src/util.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as fs from 'fs-extra';
22
import * as path from 'path';
33
import * as os from 'os';
44
import { spawn, SpawnOptions } from 'child_process';
5+
import { Options } from './options';
56

67
export async function mkdtemp(closure: (dir: string) => Promise<void>) {
78
const workdir = await fs.mkdtemp(path.join(os.tmpdir(), 'temp-'));
@@ -55,3 +56,20 @@ export async function exec(moduleName: string, args: string[] = [], options: Spa
5556
});
5657
});
5758
}
59+
60+
/**
61+
* This validates that the Python module name and Java package name
62+
* conform to language-specific constraints.
63+
*
64+
* @param options Options set by the consumer
65+
* @throws error if options do not conform
66+
*/
67+
export function validateOptions(options: Options) {
68+
if (options.python?.moduleName.includes('-')) {
69+
throw new Error(`Python moduleName [${options.python.moduleName}] may not contain "-"`);
70+
}
71+
72+
if (options.java?.package.includes('-')) {
73+
throw new Error(`Java package [${options.java.package}] may not contain "-"`);
74+
}
75+
}

test/__snapshots__/cli.test.ts.snap

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public final class $Module extends JsiiModule {
4545
private final Map<String, Class<?>> cache = new HashMap<>();
4646
4747
public $Module() {
48-
super(\\"generated\\", \\"0.0.0\\", $Module.class, \\"generated@0.0.0.jsii.tgz\\");
48+
super(\\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060\\", \\"0.0.0\\", $Module.class, \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060@0.0.0.jsii.tgz\\");
4949
}
5050
5151
@Override
@@ -76,7 +76,7 @@ public final class $Module extends JsiiModule {
7676
* A sophisticaed multi-language calculator.
7777
*/
7878
79-
@software.amazon.jsii.Jsii(module = mypackage.$Module.class, fqn = \\"generated.Calculator\\")
79+
@software.amazon.jsii.Jsii(module = mypackage.$Module.class, fqn = \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Calculator\\")
8080
public class Calculator extends software.amazon.jsii.JsiiObject {
8181
8282
protected Calculator(final software.amazon.jsii.JsiiObjectRef objRef) {
@@ -126,7 +126,7 @@ public class Calculator extends software.amazon.jsii.JsiiObject {
126126
* Math operands.
127127
*/
128128
129-
@software.amazon.jsii.Jsii(module = mypackage.$Module.class, fqn = \\"generated.Operands\\")
129+
@software.amazon.jsii.Jsii(module = mypackage.$Module.class, fqn = \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Operands\\")
130130
@software.amazon.jsii.Jsii.Proxy(Operands.Jsii$Proxy.class)
131131
public interface Operands extends software.amazon.jsii.JsiiSerializable {
132132
@@ -229,7 +229,7 @@ public interface Operands extends software.amazon.jsii.JsiiSerializable {
229229
data.set(\\"rhs\\", om.valueToTree(this.getRhs()));
230230
231231
final com.fasterxml.jackson.databind.node.ObjectNode struct = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode();
232-
struct.set(\\"fqn\\", om.valueToTree(\\"generated.Operands\\"));
232+
struct.set(\\"fqn\\", om.valueToTree(\\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Operands\\"));
233233
struct.set(\\"data\\", data);
234234
235235
final com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode();
@@ -258,8 +258,8 @@ public interface Operands extends software.amazon.jsii.JsiiSerializable {
258258
}
259259
}
260260
",
261-
"src/main/resources/mypackage/$Module.txt": "generated.Calculator=mypackage.Calculator
262-
generated.Operands=mypackage.Operands
261+
"src/main/resources/mypackage/$Module.txt": "4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Calculator=mypackage.Calculator
262+
4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Operands=mypackage.Operands
263263
",
264264
}
265265
`;
@@ -272,29 +272,29 @@ Object {
272272
"author",
273273
],
274274
},
275-
"description": "generated",
276-
"fingerprint": "+fSgo9PQwFAKmX2JcaRILwTXE/p1H1bq+QKuOREAfuE=",
275+
"description": "4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060",
276+
"fingerprint": "64TWv4C2KsEvkRVfUjD1gQTbNC2rsTlISDNv4F9JUw0=",
277277
"homepage": "http://generated",
278278
"jsiiVersion": "1.6.0 (build 248e75b)",
279279
"license": "Apache-2.0",
280-
"name": "generated",
280+
"name": "4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060",
281281
"repository": Object {
282282
"type": "git",
283283
"url": "http://generated",
284284
},
285285
"schema": "jsii/0.10.0",
286286
"targets": Object {
287287
"js": Object {
288-
"npm": "generated",
288+
"npm": "4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060",
289289
},
290290
},
291291
"types": Object {
292-
"generated.Calculator": Object {
293-
"assembly": "generated",
292+
"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Calculator": Object {
293+
"assembly": "4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060",
294294
"docs": Object {
295295
"summary": "A sophisticaed multi-language calculator.",
296296
},
297-
"fqn": "generated.Calculator",
297+
"fqn": "4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Calculator",
298298
"initializer": Object {},
299299
"kind": "class",
300300
"locationInModule": Object {
@@ -318,7 +318,7 @@ Object {
318318
},
319319
"name": "ops",
320320
"type": Object {
321-
"fqn": "generated.Operands",
321+
"fqn": "4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Operands",
322322
},
323323
},
324324
],
@@ -344,7 +344,7 @@ Object {
344344
},
345345
"name": "ops",
346346
"type": Object {
347-
"fqn": "generated.Operands",
347+
"fqn": "4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Operands",
348348
},
349349
},
350350
],
@@ -370,7 +370,7 @@ Object {
370370
},
371371
"name": "ops",
372372
"type": Object {
373-
"fqn": "generated.Operands",
373+
"fqn": "4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Operands",
374374
},
375375
},
376376
],
@@ -383,13 +383,13 @@ Object {
383383
],
384384
"name": "Calculator",
385385
},
386-
"generated.Operands": Object {
387-
"assembly": "generated",
386+
"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Operands": Object {
387+
"assembly": "4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060",
388388
"datatype": true,
389389
"docs": Object {
390390
"summary": "Math operands.",
391391
},
392-
"fqn": "generated.Operands",
392+
"fqn": "4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Operands",
393393
"kind": "interface",
394394
"locationInModule": Object {
395395
"filename": "lib/main.ts",
@@ -449,7 +449,7 @@ import publication
449449
from ._jsii import *
450450
451451
452-
class Calculator(metaclass=jsii.JSIIMeta, jsii_type=\\"generated.Calculator\\"):
452+
class Calculator(metaclass=jsii.JSIIMeta, jsii_type=\\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Calculator\\"):
453453
\\"\\"\\"A sophisticaed multi-language calculator.\\"\\"\\"
454454
def __init__(self) -> None:
455455
jsii.create(Calculator, self, [])
@@ -488,7 +488,7 @@ class Calculator(metaclass=jsii.JSIIMeta, jsii_type=\\"generated.Calculator\\"):
488488
return jsii.invoke(self, \\"sub\\", [ops])
489489
490490
491-
@jsii.data_type(jsii_type=\\"generated.Operands\\", jsii_struct_bases=[], name_mapping={'lhs': 'lhs', 'rhs': 'rhs'})
491+
@jsii.data_type(jsii_type=\\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Operands\\", jsii_struct_bases=[], name_mapping={'lhs': 'lhs', 'rhs': 'rhs'})
492492
class Operands():
493493
def __init__(self, *, lhs: jsii.Number, rhs: jsii.Number) -> None:
494494
\\"\\"\\"Math operands.
@@ -538,7 +538,7 @@ import jsii
538538
import jsii.compat
539539
import publication
540540
541-
__jsii_assembly__ = jsii.JSIIAssembly.load(\\"generated\\", \\"0.0.0\\", __name__[0:-6], \\"generated@0.0.0.jsii.tgz\\")
541+
__jsii_assembly__ = jsii.JSIIAssembly.load(\\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060\\", \\"0.0.0\\", __name__[0:-6], \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060@0.0.0.jsii.tgz\\")
542542
543543
__all__ = [
544544
\\"__jsii_assembly__\\",

test/__snapshots__/srcmak.test.ts.snap

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public final class $Module extends JsiiModule {
4545
private final Map<String, Class<?>> cache = new HashMap<>();
4646
4747
public $Module() {
48-
super(\\"generated\\", \\"0.0.0\\", $Module.class, \\"generated@0.0.0.jsii.tgz\\");
48+
super(\\"javapackage\\", \\"0.0.0\\", $Module.class, \\"javapackage@0.0.0.jsii.tgz\\");
4949
}
5050
5151
@Override
@@ -73,7 +73,7 @@ public final class $Module extends JsiiModule {
7373
"src/main/java/hello/world/Hello.java": "package hello.world;
7474
7575
76-
@software.amazon.jsii.Jsii(module = hello.world.$Module.class, fqn = \\"generated.Hello\\")
76+
@software.amazon.jsii.Jsii(module = hello.world.$Module.class, fqn = \\"javapackage.Hello\\")
7777
public class Hello extends software.amazon.jsii.JsiiObject {
7878
7979
protected Hello(final software.amazon.jsii.JsiiObjectRef objRef) {
@@ -97,7 +97,7 @@ public class Hello extends software.amazon.jsii.JsiiObject {
9797
"src/main/java/hello/world/Operands.java": "package hello.world;
9898
9999
100-
@software.amazon.jsii.Jsii(module = hello.world.$Module.class, fqn = \\"generated.Operands\\")
100+
@software.amazon.jsii.Jsii(module = hello.world.$Module.class, fqn = \\"javapackage.Operands\\")
101101
@software.amazon.jsii.Jsii.Proxy(Operands.Jsii$Proxy.class)
102102
public interface Operands extends software.amazon.jsii.JsiiSerializable {
103103
@@ -194,7 +194,7 @@ public interface Operands extends software.amazon.jsii.JsiiSerializable {
194194
data.set(\\"rhs\\", om.valueToTree(this.getRhs()));
195195
196196
final com.fasterxml.jackson.databind.node.ObjectNode struct = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode();
197-
struct.set(\\"fqn\\", om.valueToTree(\\"generated.Operands\\"));
197+
struct.set(\\"fqn\\", om.valueToTree(\\"javapackage.Operands\\"));
198198
struct.set(\\"data\\", data);
199199
200200
final com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode();
@@ -223,8 +223,8 @@ public interface Operands extends software.amazon.jsii.JsiiSerializable {
223223
}
224224
}
225225
",
226-
"src/main/resources/hello/world/$Module.txt": "generated.Hello=hello.world.Hello
227-
generated.Operands=hello.world.Operands
226+
"src/main/resources/hello/world/$Module.txt": "javapackage.Hello=hello.world.Hello
227+
javapackage.Operands=hello.world.Operands
228228
",
229229
}
230230
`;
@@ -237,26 +237,26 @@ Object {
237237
"author",
238238
],
239239
},
240-
"description": "generated",
241-
"fingerprint": "cNtb65kyZQOiBulmzr+bs6dCGdv4uhea1tFTkbRGJTw=",
240+
"description": "1bc04b5291c26a46d918139138b992d2de976d6851d0893b0476b85bfbdfc6e6",
241+
"fingerprint": "i19np+HVFMpwiHENNJeGk6AC3MVvpkkG7VtDtf9ouXs=",
242242
"homepage": "http://generated",
243243
"jsiiVersion": "1.6.0 (build 248e75b)",
244244
"license": "Apache-2.0",
245-
"name": "generated",
245+
"name": "1bc04b5291c26a46d918139138b992d2de976d6851d0893b0476b85bfbdfc6e6",
246246
"repository": Object {
247247
"type": "git",
248248
"url": "http://generated",
249249
},
250250
"schema": "jsii/0.10.0",
251251
"targets": Object {
252252
"js": Object {
253-
"npm": "generated",
253+
"npm": "1bc04b5291c26a46d918139138b992d2de976d6851d0893b0476b85bfbdfc6e6",
254254
},
255255
},
256256
"types": Object {
257-
"generated.Foo": Object {
258-
"assembly": "generated",
259-
"fqn": "generated.Foo",
257+
"1bc04b5291c26a46d918139138b992d2de976d6851d0893b0476b85bfbdfc6e6.Foo": Object {
258+
"assembly": "1bc04b5291c26a46d918139138b992d2de976d6851d0893b0476b85bfbdfc6e6",
259+
"fqn": "1bc04b5291c26a46d918139138b992d2de976d6851d0893b0476b85bfbdfc6e6.Foo",
260260
"initializer": Object {},
261261
"kind": "class",
262262
"locationInModule": Object {
@@ -300,7 +300,7 @@ import publication
300300
from ._jsii import *
301301
302302
303-
class Hello(metaclass=jsii.JSIIMeta, jsii_type=\\"generated.Hello\\"):
303+
class Hello(metaclass=jsii.JSIIMeta, jsii_type=\\"pythonpackage.Hello\\"):
304304
def __init__(self) -> None:
305305
jsii.create(Hello, self, [])
306306
@@ -315,7 +315,7 @@ class Hello(metaclass=jsii.JSIIMeta, jsii_type=\\"generated.Hello\\"):
315315
return jsii.invoke(self, \\"add\\", [ops])
316316
317317
318-
@jsii.data_type(jsii_type=\\"generated.Operands\\", jsii_struct_bases=[], name_mapping={'lhs': 'lhs', 'rhs': 'rhs'})
318+
@jsii.data_type(jsii_type=\\"pythonpackage.Operands\\", jsii_struct_bases=[], name_mapping={'lhs': 'lhs', 'rhs': 'rhs'})
319319
class Operands():
320320
def __init__(self, *, lhs: jsii.Number, rhs: jsii.Number) -> None:
321321
\\"\\"\\"
@@ -362,7 +362,7 @@ import jsii
362362
import jsii.compat
363363
import publication
364364
365-
__jsii_assembly__ = jsii.JSIIAssembly.load(\\"generated\\", \\"0.0.0\\", __name__[0:-6], \\"generated@0.0.0.jsii.tgz\\")
365+
__jsii_assembly__ = jsii.JSIIAssembly.load(\\"pythonpackage\\", \\"0.0.0\\", __name__[0:-6], \\"pythonpackage@0.0.0.jsii.tgz\\")
366366
367367
__all__ = [
368368
\\"__jsii_assembly__\\",

test/cli.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ test('python output', async () => {
7474
);
7575

7676
expect(await snapshotDirectory(outdir, {
77-
excludeFiles: [ 'generated@0.0.0.jsii.tgz' ],
77+
excludeFiles: [ '@0.0.0.jsii.tgz' ],
7878
})).toMatchSnapshot();
7979
});
8080
});
@@ -92,7 +92,7 @@ test('java output', async () => {
9292

9393
expect(await snapshotDirectory(outdir, {
9494
excludeLines: [ /.*@javax.annotation.Generated.*/ ],
95-
excludeFiles: [ 'generated@0.0.0.jsii.tgz' ],
95+
excludeFiles: [ '@0.0.0.jsii.tgz' ],
9696
})).toMatchSnapshot();
9797
});
9898
});

0 commit comments

Comments
 (0)