Skip to content

Commit c098960

Browse files
authored
feat: export common functions as a submodule (#187)
The `symbolIdentifier` function is a base jsii feature that other tools can depend on without having to depend on the rest of jsii. Currently a dependant package has to import all of the jsii code just to get `symbolIdentifier`. This can have performance implications, as well as producing larger bundles. This change exports `symbolIdentifier` as part of a new `jsii/common` submodule to allow a direct import. --- By submitting this pull request, I confirm that my contribution is made under the terms of the [Apache 2.0 license]. [Apache 2.0 license]: https://www.apache.org/licenses/LICENSE-2.0
1 parent fe54c27 commit c098960

12 files changed

+83
-70
lines changed

.projenrc.ts

+1
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ project.package.addField('exports', {
150150
'.': `./${project.package.entrypoint}`,
151151
'./bin/jsii': './bin/jsii',
152152
'./package.json': './package.json',
153+
'./common': './lib/common/index.js',
153154
});
154155

155156
// Remove TypeScript devDependency (it's a direct/normal dependency here)

package.json

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/assembler.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import * as log4js from 'log4js';
99
import * as ts from 'typescript';
1010

1111
import * as Case from './case';
12+
import { symbolIdentifier } from './common/symbol-id';
1213
import { Directives } from './directives';
1314
import { getReferencedDocParams, parseSymbolDocumentation, TypeSystemHints } from './docs';
1415
import { Emitter } from './emitter';
@@ -17,7 +18,6 @@ import * as literate from './literate';
1718
import * as bindings from './node-bindings';
1819
import { ProjectInfo } from './project-info';
1920
import { isReservedName } from './reserved-words';
20-
import { symbolIdentifier } from './symbol-id';
2121
import { DeprecatedRemover } from './transforms/deprecated-remover';
2222
import { DeprecationWarningsInjector } from './transforms/deprecation-warnings';
2323
import { RuntimeTypeInfoInjector } from './transforms/runtime-info';

src/common/README.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# jsii/common
2+
3+
jsii has some features that other packages might need to depend on, without needing the whole of jsii.
4+
5+
This submodule is addressing this need by exporting *small, self-contained* functions.s
6+
7+
Anything in here MUST NOT depend on any other code in jsii.
8+
It SHOULD be kept very lightweight and mostly depend on TypeScript and Node built-ins.

src/common/find-utils.ts

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import * as fs from 'node:fs';
2+
import * as path from 'node:path';
3+
4+
/**
5+
* Find a directory up the tree from a starting directory matching a condition
6+
*
7+
* Will return `undefined` if no directory matches
8+
*
9+
* (This code is duplicated among jsii/jsii-pacmak/jsii-reflect. Changes should be done in all
10+
* 3 locations, and we should unify these at some point: https://github.com/aws/jsii/issues/3236)
11+
*/
12+
export function findUp(directory: string, pred: (dir: string) => boolean): string | undefined {
13+
const result = pred(directory);
14+
15+
if (result) {
16+
return directory;
17+
}
18+
19+
const parent = path.dirname(directory);
20+
if (parent === directory) {
21+
return undefined;
22+
}
23+
24+
return findUp(parent, pred);
25+
}
26+
27+
/**
28+
* Find the package.json for a given package upwards from the given directory
29+
*
30+
* (This code is duplicated among jsii/jsii-pacmak/jsii-reflect. Changes should be done in all
31+
* 3 locations, and we should unify these at some point: https://github.com/aws/jsii/issues/3236)
32+
*/
33+
export function findPackageJsonUp(packageName: string, directory: string) {
34+
return findUp(directory, (dir) => {
35+
const pjFile = path.join(dir, 'package.json');
36+
return fs.existsSync(pjFile) && JSON.parse(fs.readFileSync(pjFile, 'utf-8')).name === packageName;
37+
});
38+
}
39+
40+
/**
41+
* Find the directory that contains a given dependency, identified by its 'package.json', from a starting search directory
42+
*
43+
* (This code is duplicated among jsii/jsii-pacmak/jsii-reflect. Changes should be done in all
44+
* 3 locations, and we should unify these at some point: https://github.com/aws/jsii/issues/3236)
45+
*/
46+
export function findDependencyDirectory(dependencyName: string, searchStart: string) {
47+
// Explicitly do not use 'require("dep/package.json")' because that will fail if the
48+
// package does not export that particular file.
49+
const entryPoint = require.resolve(dependencyName, {
50+
paths: [searchStart],
51+
});
52+
53+
// Search up from the given directory, looking for a package.json that matches
54+
// the dependency name (so we don't accidentally find stray 'package.jsons').
55+
const depPkgJsonPath = findPackageJsonUp(dependencyName, path.dirname(entryPoint));
56+
57+
if (!depPkgJsonPath) {
58+
throw new Error(`Could not find dependency '${dependencyName}' from '${searchStart}'`);
59+
}
60+
61+
return depPkgJsonPath;
62+
}

src/common/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { symbolIdentifier } from './symbol-id';

src/symbol-id.ts src/common/symbol-id.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import * as fs from 'node:fs';
22
import * as path from 'node:path';
3-
import { Assembly } from '@jsii/spec';
3+
import type { Assembly } from '@jsii/spec';
44
import * as ts from 'typescript';
55

6-
import { findUp } from './utils';
6+
import { findUp } from './find-utils';
77

88
/**
99
* Additional options that may be provided to the symbolIdentifier.

src/compiler.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as ts from 'typescript';
66

77
import { Assembler } from './assembler';
88
import * as Case from './case';
9+
import { findDependencyDirectory } from './common/find-utils';
910
import { emitDownleveledDeclarations, TYPES_COMPAT } from './downlevel-dts';
1011
import { Emitter } from './emitter';
1112
import { JsiiDiagnostic } from './jsii-diagnostic';
@@ -495,7 +496,7 @@ export class Compiler implements Emitter {
495496
}
496497

497498
try {
498-
const depDir = utils.findDependencyDirectory(depName, this.options.projectInfo.projectRoot);
499+
const depDir = findDependencyDirectory(depName, this.options.projectInfo.projectRoot);
499500

500501
const dep = path.join(depDir, 'tsconfig.json');
501502
if (!fs.existsSync(dep)) {

src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export * from './jsii-diagnostic';
2-
export * from './symbol-id';
2+
export * from './common/symbol-id';
33
export * from './helpers';

src/project-info.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ import * as log4js from 'log4js';
66
import * as semver from 'semver';
77
import * as ts from 'typescript';
88

9+
import { findDependencyDirectory } from './common/find-utils';
910
import { JsiiDiagnostic } from './jsii-diagnostic';
10-
import { parsePerson, parseRepository, findDependencyDirectory } from './utils';
11+
import { parsePerson, parseRepository } from './utils';
1112

1213
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
1314
const spdx: Set<string> = require('spdx-license-list/simple');

src/transforms/deprecation-warnings.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import * as spec from '@jsii/spec';
44
import { Assembly } from '@jsii/spec';
55
import * as ts from 'typescript';
66

7+
import { symbolIdentifier } from '../common/symbol-id';
78
import { ProjectInfo } from '../project-info';
8-
import { symbolIdentifier } from '../symbol-id';
99

1010
export const WARNINGSCODE_FILE_NAME = '.warnings.jsii.js';
1111
const WARNING_FUNCTION_NAME = 'print';

src/utils.ts

-62
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import * as fs from 'node:fs';
2-
import * as path from 'node:path';
31
import * as log4js from 'log4js';
42
import * as ts from 'typescript';
53

@@ -153,66 +151,6 @@ export function parseRepository(value: string): { url: string } {
153151
}
154152
}
155153

156-
/**
157-
* Find the directory that contains a given dependency, identified by its 'package.json', from a starting search directory
158-
*
159-
* (This code is duplicated among jsii/jsii-pacmak/jsii-reflect. Changes should be done in all
160-
* 3 locations, and we should unify these at some point: https://github.com/aws/jsii/issues/3236)
161-
*/
162-
export function findDependencyDirectory(dependencyName: string, searchStart: string) {
163-
// Explicitly do not use 'require("dep/package.json")' because that will fail if the
164-
// package does not export that particular file.
165-
const entryPoint = require.resolve(dependencyName, {
166-
paths: [searchStart],
167-
});
168-
169-
// Search up from the given directory, looking for a package.json that matches
170-
// the dependency name (so we don't accidentally find stray 'package.jsons').
171-
const depPkgJsonPath = findPackageJsonUp(dependencyName, path.dirname(entryPoint));
172-
173-
if (!depPkgJsonPath) {
174-
throw new Error(`Could not find dependency '${dependencyName}' from '${searchStart}'`);
175-
}
176-
177-
return depPkgJsonPath;
178-
}
179-
180-
/**
181-
* Find the package.json for a given package upwards from the given directory
182-
*
183-
* (This code is duplicated among jsii/jsii-pacmak/jsii-reflect. Changes should be done in all
184-
* 3 locations, and we should unify these at some point: https://github.com/aws/jsii/issues/3236)
185-
*/
186-
export function findPackageJsonUp(packageName: string, directory: string) {
187-
return findUp(directory, (dir) => {
188-
const pjFile = path.join(dir, 'package.json');
189-
return fs.existsSync(pjFile) && JSON.parse(fs.readFileSync(pjFile, 'utf-8')).name === packageName;
190-
});
191-
}
192-
193-
/**
194-
* Find a directory up the tree from a starting directory matching a condition
195-
*
196-
* Will return `undefined` if no directory matches
197-
*
198-
* (This code is duplicated among jsii/jsii-pacmak/jsii-reflect. Changes should be done in all
199-
* 3 locations, and we should unify these at some point: https://github.com/aws/jsii/issues/3236)
200-
*/
201-
export function findUp(directory: string, pred: (dir: string) => boolean): string | undefined {
202-
const result = pred(directory);
203-
204-
if (result) {
205-
return directory;
206-
}
207-
208-
const parent = path.dirname(directory);
209-
if (parent === directory) {
210-
return undefined;
211-
}
212-
213-
return findUp(parent, pred);
214-
}
215-
216154
const ANSI_REGEX =
217155
// eslint-disable-next-line no-control-regex
218156
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;

0 commit comments

Comments
 (0)