jsii 5.9.6-dev.0 → 5.9.7-dev.0
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/lib/assembler.d.ts +24 -1
- package/lib/assembler.js +258 -38
- package/lib/assembler.js.map +1 -1
- package/lib/helpers.d.ts +37 -3
- package/lib/helpers.js +27 -6
- package/lib/helpers.js.map +1 -1
- package/lib/jsii-diagnostic.d.ts +5 -0
- package/lib/jsii-diagnostic.js +25 -0
- package/lib/jsii-diagnostic.js.map +1 -1
- package/lib/project-info.js +2 -1
- package/lib/project-info.js.map +1 -1
- package/lib/sets.d.ts +16 -0
- package/lib/sets.js +41 -0
- package/lib/sets.js.map +1 -0
- package/lib/type-reference.d.ts +10 -0
- package/lib/type-reference.js +52 -0
- package/lib/type-reference.js.map +1 -0
- package/lib/type-visitor.d.ts +19 -0
- package/lib/type-visitor.js +51 -0
- package/lib/type-visitor.js.map +1 -0
- package/lib/version.d.ts +2 -2
- package/lib/version.js +2 -2
- package/lib/version.js.map +1 -1
- package/package.json +2 -2
- package/testspee/.eslintrc.js +3 -0
- package/testspee/LICENSE +201 -0
- package/testspee/NOTICE +406 -0
- package/testspee/README.md +1305 -0
- package/testspee/scripts/minify-sources.sh +26 -0
- package/testspee/scripts/verify-imports-resolve-same.ts +142 -0
- package/testspee/scripts/verify-imports-shielded.ts +57 -0
- package/testspee/scripts/verify-stripped-exp.ts +158 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
###
|
4
|
+
# Uses esbuild to minify the built aws-cdk-lib Javascript files to reduce module size
|
5
|
+
# and speed up loading times.
|
6
|
+
#
|
7
|
+
# In local testing, this changed the average time for loading `aws-cdk-lib` from
|
8
|
+
# 1112ms to 832ms (25% reduction).
|
9
|
+
#
|
10
|
+
# There are potentially even more savings available if we were to bundle each submodule
|
11
|
+
# into a single file; however, experiments with this (so far) have not worked due to circular
|
12
|
+
# dependencies in imports that lead to errors like "... is not a constructor". There are also
|
13
|
+
# potentially concerns with relative file usage (e.g., `__dirname`) in source. For now, this helps a bit.
|
14
|
+
###
|
15
|
+
|
16
|
+
scriptdir=$(cd $(dirname $0) && pwd)
|
17
|
+
cd ${scriptdir}/..
|
18
|
+
|
19
|
+
find . -name '*.js' ! -name '.eslintrc.js' ! -path '*node_modules*' | xargs npx esbuild \
|
20
|
+
--platform=node \
|
21
|
+
--format=cjs \
|
22
|
+
--minify-whitespace \
|
23
|
+
--minify-syntax \
|
24
|
+
--tsconfig=tsconfig.json \
|
25
|
+
--allow-overwrite \
|
26
|
+
--outdir=.
|
@@ -0,0 +1,142 @@
|
|
1
|
+
/* eslint-disable no-console */
|
2
|
+
/**
|
3
|
+
* Verify that the two styles of imports we support:
|
4
|
+
*
|
5
|
+
* import { aws_ec2 } from 'aws-cdk-lib';
|
6
|
+
* import * as aws_ec2 from 'aws-cdk-lib/aws-ec2';
|
7
|
+
*
|
8
|
+
* Resolve to the same source file when analyzed using the TypeScript compiler.
|
9
|
+
*
|
10
|
+
* This is necessary for Rosetta's analysis and translation of examples: we need
|
11
|
+
* to know what submodule we're importing here, and we need to be able to deal
|
12
|
+
* with both styles since both are used interchangeably.
|
13
|
+
*/
|
14
|
+
import * as os from 'os';
|
15
|
+
import * as path from 'path';
|
16
|
+
import * as fs from 'fs-extra';
|
17
|
+
|
18
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
19
|
+
import * as ts from 'typescript';
|
20
|
+
|
21
|
+
async function main() {
|
22
|
+
// First make a tempdir and symlink `aws-cdk-lib` into it so we can refer to it
|
23
|
+
// as if it was an installed module.
|
24
|
+
await withTemporaryDirectory(async (tmpDir) => {
|
25
|
+
await fs.mkdirp(path.join(tmpDir, 'node_modules'));
|
26
|
+
await fs.symlink(path.resolve(__dirname, '..'), path.join(tmpDir, 'node_modules', 'aws-cdk-lib'));
|
27
|
+
|
28
|
+
const import1 = 'import { aws_ec2 } from "aws-cdk-lib";';
|
29
|
+
const import2 = 'import * as aws_ec2 from "aws-cdk-lib/aws-ec2";';
|
30
|
+
|
31
|
+
const src1 = await compileAndResolve(path.join(tmpDir, 'program1.ts'), import1, 'aws_ec2');
|
32
|
+
const src2 = await compileAndResolve(path.join(tmpDir, 'program2.ts'), import2, 'aws_ec2');
|
33
|
+
|
34
|
+
if (src1 !== src2) {
|
35
|
+
console.error('Import mismatch!');
|
36
|
+
console.error('\n ', import1, '\n');
|
37
|
+
console.error('resolves to', src1);
|
38
|
+
console.error('\n ', import2, '\n');
|
39
|
+
console.error('resolves to', src2);
|
40
|
+
process.exitCode = 1;
|
41
|
+
}
|
42
|
+
});
|
43
|
+
}
|
44
|
+
|
45
|
+
async function compileAndResolve(fileName: string, contents: string, symbolName: string) {
|
46
|
+
await fs.writeFile(fileName, contents + `\n\nconsole.log(${symbolName});`, { encoding: 'utf-8' });
|
47
|
+
const program = ts.createProgram({ rootNames: [fileName], options: STANDARD_COMPILER_OPTIONS });
|
48
|
+
|
49
|
+
const sourceFile = program.getSourceFile(fileName);
|
50
|
+
if (!sourceFile) {
|
51
|
+
throw new Error(`Could not find sourcefile back: ${fileName}`);
|
52
|
+
}
|
53
|
+
|
54
|
+
const diags = [
|
55
|
+
...program.getGlobalDiagnostics(),
|
56
|
+
...program.getDeclarationDiagnostics(sourceFile),
|
57
|
+
...program.getSyntacticDiagnostics(sourceFile),
|
58
|
+
...program.getSemanticDiagnostics(sourceFile),
|
59
|
+
];
|
60
|
+
if (diags.length > 0) {
|
61
|
+
console.error(ts.formatDiagnostics(diags, {
|
62
|
+
getNewLine: () => '\n',
|
63
|
+
getCurrentDirectory: () => path.dirname(fileName),
|
64
|
+
getCanonicalFileName: (f) => path.resolve(f),
|
65
|
+
}));
|
66
|
+
throw new Error('Compilation failed');
|
67
|
+
}
|
68
|
+
|
69
|
+
// Find the 'console.log()' back and resolve the symbol inside
|
70
|
+
const logStmt = assertNode(sourceFile.statements[1], ts.isExpressionStatement);
|
71
|
+
const logCall = assertNode(logStmt.expression, ts.isCallExpression);
|
72
|
+
const ident = assertNode(logCall.arguments[0], ts.isIdentifier);
|
73
|
+
|
74
|
+
let sym = program.getTypeChecker().getSymbolAtLocation(ident);
|
75
|
+
|
76
|
+
// Resolve alias if applicable
|
77
|
+
// eslint-disable-next-line no-bitwise
|
78
|
+
while (sym && ((sym.flags & ts.SymbolFlags.Alias) !== 0)) {
|
79
|
+
sym = program.getTypeChecker().getAliasedSymbol(sym);
|
80
|
+
}
|
81
|
+
|
82
|
+
if (!sym) {
|
83
|
+
throw new Error(`Could not resolve: ${symbolName} in '${contents}'`);
|
84
|
+
}
|
85
|
+
|
86
|
+
// Return the filename
|
87
|
+
const srcFile = sym.declarations?.[0].getSourceFile().fileName.replace(/[.](ts|js|d\.ts)$/, '');
|
88
|
+
if (!srcFile) {
|
89
|
+
console.log(sym);
|
90
|
+
throw new Error(`Symbol ${symbolName} in '${contents}' does not resolve to a source location`);
|
91
|
+
}
|
92
|
+
return srcFile;
|
93
|
+
}
|
94
|
+
|
95
|
+
export async function withTemporaryDirectory<T>(callback: (dir: string) => Promise<T>): Promise<T> {
|
96
|
+
const tmpdir = await fs.mkdtemp(path.join(os.tmpdir(), path.basename(__filename)));
|
97
|
+
try {
|
98
|
+
return await callback(tmpdir);
|
99
|
+
} finally {
|
100
|
+
await fs.remove(tmpdir);
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
function assertNode<A extends ts.Node>(x: ts.Node, assert: (x: ts.Node) => x is A): A {
|
105
|
+
if (!assert(x)) {
|
106
|
+
throw new Error(`Not the right type of node, expecting ${assert.name}, got ${ts.SyntaxKind[x.kind]}`);
|
107
|
+
}
|
108
|
+
return x;
|
109
|
+
}
|
110
|
+
|
111
|
+
export const STANDARD_COMPILER_OPTIONS: ts.CompilerOptions = {
|
112
|
+
alwaysStrict: true,
|
113
|
+
charset: 'utf8',
|
114
|
+
declaration: true,
|
115
|
+
experimentalDecorators: true,
|
116
|
+
inlineSourceMap: true,
|
117
|
+
inlineSources: true,
|
118
|
+
lib: ['lib.es2016.d.ts', 'lib.es2017.object.d.ts', 'lib.es2017.string.d.ts'],
|
119
|
+
module: ts.ModuleKind.CommonJS,
|
120
|
+
noEmitOnError: true,
|
121
|
+
noFallthroughCasesInSwitch: true,
|
122
|
+
noImplicitAny: true,
|
123
|
+
noImplicitReturns: true,
|
124
|
+
noImplicitThis: true,
|
125
|
+
noUnusedLocals: false, // Important, becomes super annoying without this
|
126
|
+
noUnusedParameters: false, // Important, becomes super annoying without this
|
127
|
+
resolveJsonModule: true,
|
128
|
+
strict: true,
|
129
|
+
strictNullChecks: true,
|
130
|
+
strictPropertyInitialization: true,
|
131
|
+
stripInternal: true,
|
132
|
+
target: ts.ScriptTarget.ES2019,
|
133
|
+
// Incremental builds
|
134
|
+
incremental: true,
|
135
|
+
tsBuildInfoFile: '.tsbuildinfo',
|
136
|
+
};
|
137
|
+
|
138
|
+
main().catch((e) => {
|
139
|
+
// eslint-disable-next-line no-console
|
140
|
+
console.error(e);
|
141
|
+
process.exitCode = 1;
|
142
|
+
});
|
@@ -0,0 +1,57 @@
|
|
1
|
+
/**
|
2
|
+
* Check that the imports from 'aws-cdk-lib' we expect to work, work, and those we have shielded off don't work.
|
3
|
+
*/
|
4
|
+
import * as os from 'os';
|
5
|
+
import * as path from 'path';
|
6
|
+
import * as fs from 'fs-extra';
|
7
|
+
|
8
|
+
async function main() {
|
9
|
+
// First make a tempdir and symlink `aws-cdk-lib` into it so we can refer to it
|
10
|
+
// as if it was an installed module.
|
11
|
+
await withTemporaryDirectory(async (tmpDir) => {
|
12
|
+
await fs.mkdirp(path.join(tmpDir, 'node_modules'));
|
13
|
+
await fs.symlink(path.resolve(__dirname, '..'), path.join(tmpDir, 'node_modules', 'aws-cdk-lib'));
|
14
|
+
|
15
|
+
assertImportSucceeds('aws-cdk-lib');
|
16
|
+
assertImportFails('aws-cdk-lib/LICENSE', 'ERR_PACKAGE_PATH_NOT_EXPORTED');
|
17
|
+
assertImportFails('aws-cdk-lib/aws-s3/lib/bucket', 'ERR_PACKAGE_PATH_NOT_EXPORTED');
|
18
|
+
assertImportSucceeds('aws-cdk-lib/aws-s3');
|
19
|
+
|
20
|
+
function assertImportSucceeds(name: string) {
|
21
|
+
require.resolve(name, { paths: [tmpDir] });
|
22
|
+
}
|
23
|
+
|
24
|
+
function assertImportFails(name: string, code: string) {
|
25
|
+
try {
|
26
|
+
require.resolve(name, { paths: [tmpDir] });
|
27
|
+
|
28
|
+
// eslint-disable-next-line no-console
|
29
|
+
console.error(`Import of '${name}' should have produced an error, but didn't.`);
|
30
|
+
process.exitCode = 1;
|
31
|
+
} catch (e: any) {
|
32
|
+
if (e.code !== code) {
|
33
|
+
// eslint-disable-next-line no-console
|
34
|
+
console.error(`Import of '${name}' should have produced error ${code}, but got ${(e as any).code}.`);
|
35
|
+
process.exitCode = 1;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
});
|
40
|
+
}
|
41
|
+
|
42
|
+
|
43
|
+
export async function withTemporaryDirectory<T>(callback: (dir: string) => Promise<T>): Promise<T> {
|
44
|
+
const tmpdir = await fs.mkdtemp(path.join(os.tmpdir(), path.basename(__filename)));
|
45
|
+
try {
|
46
|
+
return await callback(tmpdir);
|
47
|
+
} finally {
|
48
|
+
await fs.remove(tmpdir);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
|
53
|
+
main().catch((e) => {
|
54
|
+
// eslint-disable-next-line no-console
|
55
|
+
console.error(e);
|
56
|
+
process.exitCode = 1;
|
57
|
+
});
|
@@ -0,0 +1,158 @@
|
|
1
|
+
// +------------------------------------------------------------------------------------------------
|
2
|
+
// | this script is executed post packaging to verify that experimental modules in aws-cdk-lib includes **only** L1 autogenerated files.
|
3
|
+
// | The purpose is to avoid publishing L2 of experimental modules with aws-cdk-lib
|
4
|
+
// |
|
5
|
+
import { spawnSync } from 'child_process';
|
6
|
+
import * as console from 'console';
|
7
|
+
import * as os from 'os';
|
8
|
+
import * as path from 'path';
|
9
|
+
import * as fs from 'fs-extra';
|
10
|
+
|
11
|
+
async function main(tempDir: string) {
|
12
|
+
console.log('🧐 Verifying all experimental modules includes only L1s files...');
|
13
|
+
const cwd = process.cwd();
|
14
|
+
const awsCdkModulesRepoPath = path.join(findWorkspacePath(), 'packages', '@aws-cdk');
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
16
|
+
const version = require('./../package.json').version;
|
17
|
+
const tarFullPath = path.join(cwd, 'dist', 'js', `aws-cdk-lib@${version}.jsii.tgz`);
|
18
|
+
|
19
|
+
const invalidCfnModules = new Map<string, Array<String>>();
|
20
|
+
const invalidModules = new Array<string>();
|
21
|
+
|
22
|
+
// install the tarball in a temp directory
|
23
|
+
console.log(`installing aws-cdk-lib from dist/js into ${tempDir}`);
|
24
|
+
exec('npm', ['install', '--prefix', tempDir, tarFullPath]);
|
25
|
+
const installedAwsCdkLibPath = path.join(tempDir, 'node_modules', 'aws-cdk-lib', 'lib');
|
26
|
+
|
27
|
+
for (const module of fs.readdirSync(awsCdkModulesRepoPath)) {
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
29
|
+
const pkgJson = require(path.join(awsCdkModulesRepoPath, module, 'package.json'));
|
30
|
+
if (pkgJson.stability !== 'experimental') {
|
31
|
+
continue;
|
32
|
+
}
|
33
|
+
if (pkgJson['cdk-build']?.cloudformation) {
|
34
|
+
// if a cfn module, verify only the allowed files exists
|
35
|
+
const files = await listAllFiles(path.join(installedAwsCdkLibPath, module));
|
36
|
+
const invalidFiles = new Array();
|
37
|
+
files.forEach(file => {
|
38
|
+
if (!isAllowedFile(file)) {
|
39
|
+
invalidFiles.push(file);
|
40
|
+
}
|
41
|
+
});
|
42
|
+
if (invalidFiles.length > 0) {
|
43
|
+
invalidCfnModules.set(module, invalidFiles);
|
44
|
+
}
|
45
|
+
} else {
|
46
|
+
// not a cfn module, verify it was entirely removed
|
47
|
+
if (fs.existsSync(path.join(installedAwsCdkLibPath, module))) {
|
48
|
+
invalidModules.push(module);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
if (invalidCfnModules.size > 0 || invalidModules.length > 0) {
|
54
|
+
if (invalidCfnModules.size > 0 ) {
|
55
|
+
console.log('cfn module with invalid files:');
|
56
|
+
for (let [module, files] of invalidCfnModules.entries()) {
|
57
|
+
console.log(`${module}:`);
|
58
|
+
files.forEach(file => console.log(`\t ${file}`));
|
59
|
+
}
|
60
|
+
}
|
61
|
+
console.log('---------------------------------------------');
|
62
|
+
if (invalidModules.length > 0) {
|
63
|
+
console.log('non-cfn experimental modules:');
|
64
|
+
invalidModules.forEach(m => console.log(`\t ${m}`));
|
65
|
+
}
|
66
|
+
throw new Error('Verification Error');
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
const tempDir = fs.mkdtempSync(os.tmpdir());
|
71
|
+
|
72
|
+
main(tempDir).then(
|
73
|
+
() => {
|
74
|
+
fs.removeSync(tempDir);
|
75
|
+
console.log('✅ All experimental modules includes only L1s files!');
|
76
|
+
process.exit(0);
|
77
|
+
},
|
78
|
+
(err) => {
|
79
|
+
process.stderr.write(`${err}\n`);
|
80
|
+
process.stderr.write(`❌ Verification failed, Some experimental modules includes non L1 files, see details above. Inspect working directory: '${tempDir}'`);
|
81
|
+
process.exit(1);
|
82
|
+
},
|
83
|
+
);
|
84
|
+
|
85
|
+
|
86
|
+
/**
|
87
|
+
* Spawn sync with error handling
|
88
|
+
*/
|
89
|
+
function exec(cmd: string, args: string[]) {
|
90
|
+
const proc = spawnSync(cmd, args);
|
91
|
+
|
92
|
+
if (proc.error) {
|
93
|
+
throw proc.error;
|
94
|
+
}
|
95
|
+
|
96
|
+
if (proc.status !== 0) {
|
97
|
+
if (proc.stdout || proc.stderr) {
|
98
|
+
throw new Error(`${cmd} exited with status ${proc.status}; stdout: ${proc.stdout?.toString().trim()}\n\n\nstderr: ${proc.stderr?.toString().trim()}`);
|
99
|
+
}
|
100
|
+
throw new Error(`${cmd} exited with status ${proc.status}`);
|
101
|
+
}
|
102
|
+
|
103
|
+
return proc;
|
104
|
+
}
|
105
|
+
|
106
|
+
const GENERATED_SUFFIX_REGEX = new RegExp(/generated\.(js|d\.ts)$/);
|
107
|
+
const ALLOWED_FILES = ['.jsiirc.json', 'index.ts', 'index.js', 'index.d.ts'];
|
108
|
+
|
109
|
+
/**
|
110
|
+
* Recursively collect all files in dir
|
111
|
+
*/
|
112
|
+
async function listAllFiles(dir: string) {
|
113
|
+
const ret = new Array();
|
114
|
+
|
115
|
+
async function recurse(part: string) {
|
116
|
+
const files = await fs.readdir(part);
|
117
|
+
for (const file of files) {
|
118
|
+
const fullPath = path.join(part, file);
|
119
|
+
if ((await fs.stat(fullPath)).isDirectory()) {
|
120
|
+
await recurse(fullPath);
|
121
|
+
} else {
|
122
|
+
ret.push(file);
|
123
|
+
}
|
124
|
+
}
|
125
|
+
}
|
126
|
+
await recurse(dir);
|
127
|
+
return ret;
|
128
|
+
}
|
129
|
+
|
130
|
+
/**
|
131
|
+
* Find the workspace root path. Walk up the directory tree until you find lerna.json
|
132
|
+
*/
|
133
|
+
function findWorkspacePath() {
|
134
|
+
|
135
|
+
return _findRootPath(process.cwd());
|
136
|
+
|
137
|
+
function _findRootPath(part: string): string {
|
138
|
+
if (part === path.resolve(part, '..')) {
|
139
|
+
throw new Error('couldn\'t find a \'lerna.json\' file when walking up the directory tree, are you in a aws-cdk project?');
|
140
|
+
}
|
141
|
+
|
142
|
+
if (fs.existsSync(path.resolve(part, 'lerna.json'))) {
|
143
|
+
return part;
|
144
|
+
}
|
145
|
+
return _findRootPath(path.resolve(part, '..'));
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
/**
|
150
|
+
* @param file
|
151
|
+
* @returns true if the file allowed in an L1 only modules, otherwise false
|
152
|
+
*/
|
153
|
+
function isAllowedFile(file: string) {
|
154
|
+
if (GENERATED_SUFFIX_REGEX.test(file)) {
|
155
|
+
return true;
|
156
|
+
}
|
157
|
+
return ALLOWED_FILES.includes(file);
|
158
|
+
}
|