Skip to content

feat: use new read/load assembly functions everywhere #3600

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 51 commits into from
Jun 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
0068b7f
new module for jsii utility functions
kaizencc Jun 2, 2022
74bd29c
update readme and package.json
kaizencc Jun 2, 2022
5bd3929
prove that new module works
kaizencc Jun 2, 2022
759b7d7
move spec file names to @jsii/spec and re-export in @jsii/utils
kaizencc Jun 3, 2022
ca54f78
update project structure for out-of-source building
kaizencc Jun 3, 2022
c802eb2
getAssemblyFile returns path to SPEC_FILE_NAME, and loadAssemblyFromP…
kaizencc Jun 3, 2022
7d75f79
add tests on error messages
kaizencc Jun 3, 2022
b6abc5d
fix formatting for writing assembly
kaizencc Jun 3, 2022
b820c0d
add command line option compressAssembly
kaizencc Jun 8, 2022
8f0f909
jsii-reflect change wip
kaizencc Jun 8, 2022
f60a57a
add validation prop to load assembly
kaizencc Jun 8, 2022
83081c7
Merge branch 'conroy/jsiiutils' of https://github.com/aws/jsii into c…
kaizencc Jun 8, 2022
ded1036
more progress
kaizencc Jun 8, 2022
7742e78
add validate to loadfrompath
kaizencc Jun 8, 2022
34a4bf0
Merge branch 'conroy/jsiiutils' of https://github.com/aws/jsii into c…
kaizencc Jun 8, 2022
7f31887
fix type-system.ts
kaizencc Jun 8, 2022
7827f02
changes to jsii
kaizencc Jun 9, 2022
45ad28c
changes to rosetta, one test failing
kaizencc Jun 9, 2022
1b105bd
jsii-rosetta uses centralized assembly helper functions
kaizencc Jun 13, 2022
9b42e8d
minor improvements
kaizencc Jun 13, 2022
af821cd
standardize spec_file_name
kaizencc Jun 13, 2022
e33bed0
remove all .jsii usage
kaizencc Jun 13, 2022
3deb6f9
Merge branch 'main' into conroy/jsiiutils
kaizencc Jun 13, 2022
cac5532
move compress into a property bag
kaizencc Jun 13, 2022
417df72
refactor schema validation error message
kaizencc Jun 13, 2022
c7c8adf
merge upstream
kaizencc Jun 13, 2022
8f7504f
update kernel
kaizencc Jun 13, 2022
fc9ec85
npmignore
kaizencc Jun 13, 2022
a0ac235
update for new writeassembly function sig
kaizencc Jun 13, 2022
df48779
remove debugging logic
kaizencc Jun 14, 2022
f06ca4a
fix test
kaizencc Jun 14, 2022
2ac427d
Merge branch 'conroy/jsiiutils' of https://github.com/aws/jsii into c…
kaizencc Jun 14, 2022
fc154f6
Merge branch 'main' into conroy/jsiiutils
kaizencc Jun 27, 2022
550282a
more @jsii/utils to @jsii/spec
kaizencc Jun 27, 2022
97e080f
update example usage
kaizencc Jun 27, 2022
013d3d2
export functions from @jsii/spec
kaizencc Jun 27, 2022
f7f60a4
remove @jsii/utils
kaizencc Jun 27, 2022
ae4ad42
merge
kaizencc Jun 27, 2022
8d38040
update kernel
kaizencc Jun 27, 2022
d657866
update kernel
kaizencc Jun 27, 2022
d9af12d
update jsii-reflect
kaizencc Jun 27, 2022
e7bfd19
reupdate kernel and runtime
kaizencc Jun 27, 2022
35c4e0a
update jsii-rosetta
kaizencc Jun 27, 2022
c4dce18
more rosetta
kaizencc Jun 27, 2022
ded9455
update jsii
kaizencc Jun 27, 2022
925bf7b
npmignore
kaizencc Jun 27, 2022
af24858
more npmignores
kaizencc Jun 27, 2022
29eeb8c
Merge branch 'main' into conroy/jsiiutils-extension
RomainMuller Jun 28, 2022
329c153
add error message to blind catch
kaizencc Jun 28, 2022
a6f9fb9
merge conflict
kaizencc Jun 28, 2022
5daf3af
Merge branch 'conroy/jsiiutils-extension' of https://github.com/aws/j…
kaizencc Jun 28, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions packages/@jsii/kernel/src/kernel.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as spec from '@jsii/spec';
import { loadAssemblyFromPath } from '@jsii/spec';
import * as cp from 'child_process';
import * as fs from 'fs-extra';
import * as os from 'os';
Expand Down Expand Up @@ -114,13 +115,12 @@ export class Kernel {
}

// read .jsii metadata from the root of the package
const jsiiMetadataFile = path.join(packageDir, spec.SPEC_FILE_NAME);
if (!fs.pathExistsSync(jsiiMetadataFile)) {
throw new Error(
`Package tarball ${req.tarball} must have a file named ${spec.SPEC_FILE_NAME} at the root`,
);
let assmSpec;
try {
assmSpec = loadAssemblyFromPath(packageDir);
} catch (e: any) {
throw new Error(`Error for package tarball ${req.tarball}: ${e.message}`);
Comment on lines +121 to +122
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, @RomainMuller, is this better?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yap

}
const assmSpec = fs.readJsonSync(jsiiMetadataFile) as spec.Assembly;

// load the module and capture it's closure
const closure = this._execute(
Expand Down
8 changes: 3 additions & 5 deletions packages/@jsii/runtime/test/kernel-host.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { api } from '@jsii/kernel';
import * as spec from '@jsii/spec';
import { loadAssemblyFromPath } from '@jsii/spec';
import * as child from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
Expand Down Expand Up @@ -86,12 +87,9 @@ function loadRequest(library: string): api.LoadRequest {
};

function loadAssembly(): spec.Assembly {
const assemblyFile = path.resolve(
require.resolve(`${library}/package.json`),
'..',
'.jsii',
return loadAssemblyFromPath(
path.resolve(require.resolve(`${library}/package.json`), '..'),
);
return JSON.parse(fs.readFileSync(assemblyFile, { encoding: 'utf-8' }));
}

function packageLibrary(target: string): void {
Expand Down
3 changes: 2 additions & 1 deletion packages/@scope/jsii-calc-base-of-base/.npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
*.tgz


# Include .jsii
# Include .jsii and .jsii.gz
!.jsii
!.jsii.gz


# Exclude jsii outdir
Expand Down
3 changes: 2 additions & 1 deletion packages/@scope/jsii-calc-base/.npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
*.tgz


# Include .jsii
# Include .jsii and .jsii.gz
!.jsii
!.jsii.gz


# Exclude jsii outdir
Expand Down
3 changes: 2 additions & 1 deletion packages/@scope/jsii-calc-lib/.npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
*.tgz


# Include .jsii
# Include .jsii and .jsii.gz
!.jsii
!.jsii.gz


# Exclude jsii outdir
Expand Down
3 changes: 2 additions & 1 deletion packages/jsii-calc/.npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
!*.d.ts
*.tgz

# Include .jsii
# Include .jsii and .jsii.gz
!.jsii
!.jsii.gz


# Exclude jsii outdir
Expand Down
2 changes: 1 addition & 1 deletion packages/jsii-diff/bin/jsii-diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ type LoadAssemblyResult = { requested: string; resolved: string } & (
async function loadPackageNameFromAssembly(
options: LoadOptions,
): Promise<string> {
const JSII_ASSEMBLY_FILE = '.jsii';
const JSII_ASSEMBLY_FILE = spec.SPEC_FILE_NAME;
if (!(await fs.pathExists(JSII_ASSEMBLY_FILE))) {
throw new Error(
`No NPM package name given and no ${JSII_ASSEMBLY_FILE} file in the current directory. Please specify a package name.`,
Expand Down
6 changes: 5 additions & 1 deletion packages/jsii-pacmak/lib/npm-modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,11 @@ async function updateNpmIgnore(
);
}

includePattern('Include .jsii', spec.SPEC_FILE_NAME);
includePattern(
'Include .jsii and .jsii.gz',
spec.SPEC_FILE_NAME,
spec.SPEC_FILE_NAME_COMPRESSED,
);

if (modified) {
await fs.writeFile(npmIgnorePath, `${lines.join('\n')}\n`);
Expand Down
20 changes: 7 additions & 13 deletions packages/jsii-reflect/lib/type-system.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as jsii from '@jsii/spec';
import { getAssemblyFile, loadAssemblyFromFile } from '@jsii/spec';
import * as fs from 'fs-extra';
import * as path from 'path';

Expand Down Expand Up @@ -109,10 +109,7 @@ export class TypeSystem {
// Load the assembly, but don't recurse if we already have an assembly with the same name.
// Validation is not an insignificant time sink, and loading IS insignificant, so do a
// load without validation first. This saves about 2/3rds of processing time.
const asm = await this.loadAssembly(
path.join(moduleDirectory, '.jsii'),
false,
);
const asm = this.loadAssembly(getAssemblyFile(moduleDirectory), false);
if (this.includesAssembly(asm.name)) {
const existing = this.findAssembly(asm.name);
if (existing.version !== asm.version) {
Expand Down Expand Up @@ -154,11 +151,11 @@ export class TypeSystem {
}
}

public async loadFile(
public loadFile(
file: string,
options: { isRoot?: boolean; validate?: boolean } = {},
) {
const assembly = await this.loadAssembly(file, options.validate !== false);
const assembly = this.loadAssembly(file, options.validate !== false);
return this.addAssembly(assembly, options);
}

Expand Down Expand Up @@ -308,12 +305,9 @@ export class TypeSystem {
* @param file Assembly file to load
* @param validate Whether to validate the assembly or just assume it matches the schema
*/
private async loadAssembly(file: string, validate = true) {
const spec = JSON.parse(await fs.readFile(file, { encoding: 'utf-8' }));
const ass = validate
? jsii.validateAssembly(spec)
: (spec as jsii.Assembly);
return new Assembly(this, ass);
private loadAssembly(file: string, validate = true) {
const contents = loadAssemblyFromFile(file, validate);
return new Assembly(this, contents);
}

private addRoot(asm: Assembly) {
Expand Down
2 changes: 1 addition & 1 deletion packages/jsii-rosetta/lib/commands/coverage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { formatLocation } from '../snippet';

export async function checkCoverage(assemblyLocations: readonly string[]): Promise<void> {
logging.info(`Loading ${assemblyLocations.length} assemblies`);
const assemblies = await loadAssemblies(assemblyLocations, false);
const assemblies = loadAssemblies(assemblyLocations, false);

const snippets = Array.from(await allTypeScriptSnippets(assemblies, true));

Expand Down
4 changes: 2 additions & 2 deletions packages/jsii-rosetta/lib/commands/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export async function extractSnippets(
const only = options.only ?? [];

logging.info(`Loading ${assemblyLocations.length} assemblies`);
const assemblies = await loadAssemblies(assemblyLocations, options.validateAssemblies ?? false);
const assemblies = loadAssemblies(assemblyLocations, options.validateAssemblies ?? false);

let snippets = Array.from(await allTypeScriptSnippets(assemblies, options.loose));
if (only.length > 0) {
Expand Down Expand Up @@ -170,7 +170,7 @@ export async function extractSnippets(
const output = options.trimCache
? new LanguageTablet()
: await LanguageTablet.fromOptionalFile(options.cacheToFile);
output.addTablet(translator.tablet);
output.addTablets(translator.tablet);
await output.save(options.cacheToFile);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/jsii-rosetta/lib/commands/infuse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export async function infuse(assemblyLocations: string[], options?: InfuseOption
}

// Load tablet file and assemblies
const assemblies = await loadAssemblies(assemblyLocations, false);
const assemblies = loadAssemblies(assemblyLocations, false);
const defaultTablets = await loadAllDefaultTablets(assemblies);

const availableTranslations = new LanguageTablet();
Expand Down
13 changes: 6 additions & 7 deletions packages/jsii-rosetta/lib/commands/transliterate.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Assembly, Docs, SPEC_FILE_NAME, Type, TypeKind } from '@jsii/spec';
import { readJson, writeJson } from 'fs-extra';
import { Assembly, Docs, SPEC_FILE_NAME, Type, TypeKind, loadAssemblyFromPath } from '@jsii/spec';
import { writeJson } from 'fs-extra';
import { resolve } from 'path';

import { TargetLanguage } from '../languages';
Expand Down Expand Up @@ -98,8 +98,7 @@ export async function transliterateAssembly(
for (const [location, loadAssembly] of assemblies.entries()) {
for (const language of targetLanguages) {
const now = new Date().getTime();
// eslint-disable-next-line no-await-in-loop
const result = await loadAssembly();
const result = loadAssembly();

if (result.targets?.[targetName(language)] == null) {
// This language is not supported by the assembly, so we skip it...
Expand Down Expand Up @@ -149,16 +148,16 @@ async function loadAssemblies(
const result = new Map<string, AssemblyLoader>();

for (const directory of directories) {
const loader = () => readJson(resolve(directory, SPEC_FILE_NAME));
const loader = () => loadAssemblyFromPath(directory);
// eslint-disable-next-line no-await-in-loop
await rosetta.addAssembly(await loader(), directory);
await rosetta.addAssembly(loader(), directory);
result.set(directory, loader);
}

return result;
}

type AssemblyLoader = () => Promise<Mutable<Assembly>>;
type AssemblyLoader = () => Mutable<Assembly>;

function transliterateType(type: Type, rosetta: RosettaTabletReader, language: TargetLanguage): void {
transliterateDocs({ api: 'type', fqn: type.fqn }, type.docs);
Expand Down
2 changes: 1 addition & 1 deletion packages/jsii-rosetta/lib/commands/trim-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export interface TrimCacheOptions {

export async function trimCache(options: TrimCacheOptions): Promise<void> {
logging.info(`Loading ${options.assemblyLocations.length} assemblies`);
const assemblies = await loadAssemblies(options.assemblyLocations, false);
const assemblies = loadAssemblies(options.assemblyLocations, false);

const snippets = Array.from(await allTypeScriptSnippets(assemblies));

Expand Down
67 changes: 30 additions & 37 deletions packages/jsii-rosetta/lib/jsii/assemblies.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as spec from '@jsii/spec';
import { loadAssemblyFromFile, loadAssemblyFromPath, getAssemblyFile, writeAssembly } from '@jsii/spec';
import * as crypto from 'crypto';
import * as fs from 'fs-extra';
import * as path from 'path';
Expand Down Expand Up @@ -55,35 +56,28 @@ export interface LoadedAssembly {
/**
* Load assemblies by filename or directory
*/
export async function loadAssemblies(
export function loadAssemblies(
assemblyLocations: readonly string[],
validateAssemblies: boolean,
): Promise<readonly LoadedAssembly[]> {
return Promise.all(assemblyLocations.map(loadAssembly));
): readonly LoadedAssembly[] {
return assemblyLocations.map(loadAssembly);

async function loadAssembly(location: string): Promise<LoadedAssembly> {
const stat = await fs.stat(location);
function loadAssembly(location: string): LoadedAssembly {
const stat = fs.statSync(location);
if (stat.isDirectory()) {
return loadAssembly(path.join(location, '.jsii'));
return loadAssembly(getAssemblyFile(location));
}

const directory = path.dirname(location);
const pjLocation = path.join(directory, 'package.json');

const [assembly, packageJson] = await Promise.all([
loadAssemblyFromFile(location, validateAssemblies),
(await fs.pathExists(pjLocation)) ? fs.readJSON(pjLocation, { encoding: 'utf-8' }) : Promise.resolve(undefined),
]);
const assembly = loadAssemblyFromFile(location, validateAssemblies);
const packageJson = fs.pathExistsSync(pjLocation) ? fs.readJSONSync(pjLocation, { encoding: 'utf-8' }) : undefined;

return { assembly, directory, packageJson };
}
}

async function loadAssemblyFromFile(filename: string, validate: boolean): Promise<spec.Assembly> {
const contents = await fs.readJSON(filename, { encoding: 'utf-8' });
return validate ? spec.validateAssembly(contents) : (contents as spec.Assembly);
}

/**
* Load the default tablets for every assembly, if available
*
Expand Down Expand Up @@ -236,12 +230,12 @@ export async function allTypeScriptSnippets(
* Replaces the file where the original assembly file *should* be found with a new assembly file.
* Recalculates the fingerprint of the assembly to avoid tampering detection.
*/
export async function replaceAssembly(assembly: spec.Assembly, directory: string): Promise<void> {
const fileName = path.join(directory, '.jsii');
await fs.writeJson(fileName, _fingerprint(assembly), {
encoding: 'utf8',
spaces: 2,
});
export function replaceAssembly(
assembly: spec.Assembly,
directory: string,
{ compress = false }: { compress?: boolean } = {},
) {
writeAssembly(directory, _fingerprint(assembly), { compress });
}

/**
Expand Down Expand Up @@ -296,24 +290,23 @@ export function findTypeLookupAssembly(startingDirectory: string): TypeLookupAss
}

function loadLookupAssembly(directory: string): TypeLookupAssembly | undefined {
const assemblyFile = path.join(directory, '.jsii');
if (!fs.pathExistsSync(assemblyFile)) {
try {
const packageJson = fs.readJSONSync(path.join(directory, 'package.json'), { encoding: 'utf-8' });
const assembly: spec.Assembly = loadAssemblyFromPath(directory);
const symbolIdMap = mkDict([
...Object.values(assembly.types ?? {}).map((type) => [type.symbolId ?? '', type.fqn] as const),
...Object.entries(assembly.submodules ?? {}).map(([fqn, mod]) => [mod.symbolId ?? '', fqn] as const),
]);

return {
packageJson,
assembly,
directory,
symbolIdMap,
};
} catch {
return undefined;
}

const packageJson = fs.readJSONSync(path.join(directory, 'package.json'), { encoding: 'utf-8' });
const assembly: spec.Assembly = fs.readJSONSync(assemblyFile, { encoding: 'utf-8' });
const symbolIdMap = mkDict([
...Object.values(assembly.types ?? {}).map((type) => [type.symbolId ?? '', type.fqn] as const),
...Object.entries(assembly.submodules ?? {}).map(([fqn, mod]) => [mod.symbolId ?? '', fqn] as const),
]);

return {
packageJson,
assembly,
directory,
symbolIdMap,
};
}

function findPackageJsonLocation(currentPath: string): string | undefined {
Expand Down
Loading