Skip to content

Commit 1634eac

Browse files
authored
chore(release): 1.119.0 (#4979)
See [CHANGELOG](https://github.com/aws/jsii/blob/bump/1.119.0/CHANGELOG.md)
2 parents 02eec31 + 04abbd2 commit 1634eac

File tree

20 files changed

+672
-248
lines changed

20 files changed

+672
-248
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22

33
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
44

5+
## [1.119.0](https://github.com/aws/jsii/compare/v1.118.0...v1.119.0) (2025-11-10)
6+
7+
8+
### Features
9+
10+
* **jsii-diff:** remap old to new FQNs ([#4976](https://github.com/aws/jsii/issues/4976)) ([d7c083d](https://github.com/aws/jsii/commit/d7c083d9a958ddb6205ae0237d032c818668d471))
11+
* **jsii-reflect:** can jqii-query on `fqn` field ([#4975](https://github.com/aws/jsii/issues/4975)) ([86995e5](https://github.com/aws/jsii/commit/86995e544528d19f91631e7acff1d744a2383ae1))
12+
13+
14+
### Bug Fixes
15+
16+
* **jsii-pacmak:** Python interfaces sometimes violate MRO ([#4973](https://github.com/aws/jsii/issues/4973)) ([cfb6580](https://github.com/aws/jsii/commit/cfb658077b8f3f7e464a50f5d17f5594a77e9029))
17+
* **jsii-reflect:** advertise `jsii-query` via `bin` entry of `package.json` ([#4974](https://github.com/aws/jsii/issues/4974)) ([b6c0a35](https://github.com/aws/jsii/commit/b6c0a3511705bc6e021ce23ea1d480552a7cdfaa))
18+
519
## [1.118.0](https://github.com/aws/jsii/compare/v1.117.0...v1.118.0) (2025-10-29)
620

721

gh-pages/content/user-guides/lib-author/configuration/targets/.pages.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ nav:
55
- Go: go.md
66
- Java: java.md
77
- Python: python.md
8+
- Submodules: submodules.md
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Submodules
2+
3+
jsii allows the use of submodules. These make it possible for classes with the
4+
same name to live in different namespaces in the jsii type system, so that they
5+
don't conflict.
6+
7+
For example, "cluster" is a very popular name; in the AWS ecosystem RDS has
8+
Clusters, ECS has Clusters, EKS has Clusters, and so on. We want multiple
9+
classes named `Cluster` in a single code library, but in order to make sure
10+
the names don't conflict, every class is placed in a different submodule.
11+
12+
## Defining submodules
13+
14+
A submodule is declared by using an aliased TypeScript `export *` statement, in
15+
any file reachable from the library's entry point, in the following form:
16+
17+
```ts
18+
export * as my_module from `./my-module`;
19+
// ^^^ ^^^
20+
// Submodule name Submodule source
21+
```
22+
23+
All types reachable from `./my-module` will be in the submodule named
24+
`my_module.` `./my-module` can either point directly to a source file, or to a
25+
directory with an `index.ts` file in it.
26+
27+
A TypeScript *consumer* accesses the classes inside the submodule by importing
28+
the submodule symbol from the library's entry point and then accessing
29+
properties off of that, OR by importing the target file directly:
30+
31+
```ts
32+
// Normal access via library entry point
33+
import { my_module } from '@my-jsii/library';
34+
new my_module.ClassInSubmodule(...);
35+
36+
// -------------------------------------------------------------------------
37+
// Direct access of source file
38+
39+
// This is outside of the purview of jsii and is subject to the files that
40+
// are being declared `export`ed in your `package.json`.
41+
import { ClassInSubmodule } from '@my-jsii/library/my-module';
42+
new ClassInSubmodule(...);
43+
```
44+
45+
Consumers in jsii client languages use a regular namespaced import:
46+
47+
```py
48+
from my_jsii_library.my_module import ClassInModule
49+
```
50+
51+
```java
52+
import com.library.jsii.my.my_module.ClassInmodule;
53+
```
54+
55+
...etc.
56+
57+
## Configuring submodule attributes
58+
59+
If unconfigured, a namespace name will automatically be derived by `jsii-pacmak`
60+
based on the exported name of the submodule. If you want to explicitly configure
61+
the namespace you can put a `.jsiirc.json` file in the right location:
62+
63+
If your submodule export is a `directory/index.ts`, place a `.jsiirc.json` file
64+
in the directory:
65+
66+
```js
67+
/*
68+
.
69+
├── index.ts
70+
├── package.json // <- namespaces for the library root here
71+
└── my-submodule
72+
   ├── .jsiirc.json // <- namespaces for the submodule here
73+
   └── index.ts
74+
*/
75+
76+
{
77+
"targets": {
78+
"java": {
79+
"package": "com.my_company.my_jsii_library.fancy_submodule"
80+
},
81+
"dotnet": {
82+
"namespace": "MyCompany.MyJsiiLibrary.FancySubmodule"
83+
},
84+
"python": {
85+
"module": "my_jsii_library.fancy_submodule"
86+
},
87+
"go": {
88+
"packageName": "fancy_submodule"
89+
}
90+
}
91+
}
92+
```
93+
94+
If your submodule export is a file, name your rc-file `.<base-name>.jsiirc.json`:
95+
96+
```js
97+
/*
98+
.
99+
├── index.ts
100+
├── package.json // <- namespaces for the library root here
101+
├── my-submodule.ts
102+
└── .my-submodule.jsiirc.json // <- namespaces for the submodule here
103+
*/
104+
105+
{
106+
"targets": {
107+
/* ... */
108+
}
109+
}
110+
```

gh-pages/requirements-dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
mkdocs~=1.6.1
22
mkdocs-awesome-pages-plugin~=2.10.1
3-
mkdocs-material~=9.6.22
3+
mkdocs-material~=9.6.23
44
mkdocs-git-revision-date-plugin~=0.3.2

lerna.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212
"rejectCycles": true
1313
}
1414
},
15-
"version": "1.118.0",
15+
"version": "1.119.0",
1616
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
1717
}

packages/@jsii/python-runtime/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
black~=25.9
1+
black~=25.11
22
mypy==1.18.2
33
pip~=25.3
44
pytest~=8.4

packages/jsii-diff/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,45 @@ abstract members yet.
126126
for subclassing, but treating them as such would limit the evolvability of
127127
libraries too much.
128128

129+
## Accepting breaking changes
130+
131+
Sometimes you want to move forward with a change, even if it would technically
132+
be a breaking change to your API. In order to do that, run `jsii-diff`
133+
with the flag `--keys`. It will then print an identifier for every violation
134+
between square brackets, for example:
135+
136+
```
137+
$ jsii-diff <old> --keys
138+
IFACE pkg.MyStruct: formerly required property 'prop' is optional: returned from pkg.IConsumer.someMethod [weakened:pkg.MyStruct]
139+
```
140+
141+
To accept a breaking finding, put the key (in this example `weakened:pkg.MyStruct`)
142+
into a text file, for example `allowed-breaking-changes.txt`, and pass it to
143+
`jsii-diff` as an ignore file:
144+
145+
```
146+
$ jsii-diff <old> --keys --ignore-file allowed-breaking-changes.txt
147+
(no error)
148+
```
149+
150+
### Moving/renaming API elements
151+
152+
If you've moved API elements around between versions of your library, you can
153+
put a special ignore marker starting with `move:` into your `--ignore-file`. To
154+
separate the old and new class names, you can use `:`, `,` or whitespace.
155+
156+
For example:
157+
158+
```
159+
move:package.OldClassName package.NewClassName
160+
move:package.OldClassName:package.NewClassName
161+
move:package.OldClassName, package.NewClassName
162+
```
163+
164+
Moving API elements is always breaking, but using this feature you can confirm
165+
that you at least didn't break anything in the API surface of the moved classes
166+
themselves.
167+
129168
## Help! jsii-diff is marking my changes as breaking
130169

131170
See [BREAKING_CHANGES.md](./BREAKING_CHANGES.md) for more information.

packages/jsii-diff/bin/jsii-diff.ts

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,15 @@ async function main(): Promise<number> {
124124
);
125125
}
126126

127+
const allowedBreakingChanges = await loadFilter(argv['ignore-file']);
128+
const fqnRemapping: Record<string, string> = extractFqnRemappings(
129+
allowedBreakingChanges,
130+
);
131+
127132
LOG.info('Starting analysis');
128133
const mismatches = compareAssemblies(original, updated, {
129134
defaultExperimental: argv['default-stability'] === 'experimental',
135+
fqnRemapping,
130136
});
131137

132138
LOG.info(`Found ${mismatches.count} issues`);
@@ -135,7 +141,7 @@ async function main(): Promise<number> {
135141
const diags = classifyDiagnostics(
136142
mismatches,
137143
treatAsError(argv['error-on'] as ErrorClass, argv['experimental-errors']),
138-
await loadFilter(argv['ignore-file']),
144+
allowedBreakingChanges,
139145
);
140146

141147
process.stderr.write(
@@ -155,6 +161,43 @@ async function main(): Promise<number> {
155161
return 0;
156162
}
157163

164+
/**
165+
* Extract all lines that start with `move:` from the given string set
166+
*
167+
* Interpret them as `move:OLDFQN <sep> NEWFQN`, mapping moved FQNs.
168+
*
169+
* Separator can be any of `:`, comma or whitespace.
170+
*
171+
* Modifies the input set in-place.
172+
*/
173+
function extractFqnRemappings(
174+
allowedBreakingChanges: Set<string>,
175+
): Record<string, string> {
176+
const ret: Record<string, string> = {};
177+
178+
for (const line of Array.from(allowedBreakingChanges)) {
179+
const prefix = 'move:';
180+
if (!line.startsWith(prefix)) {
181+
continue;
182+
}
183+
184+
const parts = line
185+
.slice(prefix.length)
186+
.trim()
187+
.split(/[:, \t]+/g);
188+
if (parts.length !== 2) {
189+
throw new Error(
190+
`Invalid moved FQN declaration: ${line}. Expected format is 'move:old:new'`,
191+
);
192+
}
193+
const [oldFqn, newFqn] = parts;
194+
ret[oldFqn] = newFqn;
195+
allowedBreakingChanges.delete(line);
196+
}
197+
198+
return ret;
199+
}
200+
158201
// Allow both npm:<package> (legacy) and npm://<package> (looks better)
159202
const NPM_REGEX = /^npm:(\/\/)?/;
160203

@@ -311,7 +354,7 @@ async function loadFilter(filterFilename?: string): Promise<Set<string>> {
311354
(await fs.readFile(filterFilename, { encoding: 'utf-8' }))
312355
.split('\n')
313356
.map((x) => x.trim())
314-
.filter((x) => !x.startsWith('#')),
357+
.filter((x) => x && !x.startsWith('#')),
315358
);
316359
} catch (e: any) {
317360
if (e.code !== 'ENOENT') {

0 commit comments

Comments
 (0)