@chidchanun/bcp 0.3.0 → 0.3.2
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/README.md +135 -111
- package/docs/README.md +53 -78
- package/docs/api-freeze-snapshot.json +24 -2
- package/docs/api-manifest.json +29 -13
- package/docs/api-reference.md +195 -197
- package/docs/application-platform.md +141 -171
- package/docs/docs-web-manifest.json +9 -5
- package/docs/migration-0.3.md +189 -68
- package/docs/module-system-v2.md +386 -0
- package/docs/platform-contract.md +53 -37
- package/docs/platform-manifest.json +36 -4
- package/docs/releases/0.3.1.md +116 -0
- package/docs/releases/0.3.2.md +125 -0
- package/docs/service-container.md +333 -0
- package/package.json +13 -1
- package/packages/bundler/src/client-boundary.ts +2 -0
- package/packages/client/src/application.mjs +1004 -34
- package/packages/client/src/container.mjs +573 -0
- package/packages/client/src/container.ts +24 -0
- package/packages/client/src/modules.mjs +392 -0
- package/packages/client/src/modules.ts +17 -0
- package/packages/server/src/application.ts +171 -11
- package/packages/server/src/container.ts +970 -0
- package/packages/server/src/modules.ts +682 -0
package/docs/migration-0.3.md
CHANGED
|
@@ -1,142 +1,263 @@
|
|
|
1
|
-
# Migrating to BCP Framework 0.3.
|
|
1
|
+
# Migrating to BCP Framework 0.3.x
|
|
2
2
|
|
|
3
|
-
BCP Framework `0.3.0`
|
|
3
|
+
BCP Framework `0.3.0` established the Application Platform baseline. `0.3.1` extends it additively with typed dependency injection through `bcp/container`.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Compatibility
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Current target:
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
```text
|
|
10
|
+
0.3.1 — Dependency Injection & Service Container
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Previous baseline:
|
|
10
14
|
|
|
11
15
|
```text
|
|
12
|
-
|
|
16
|
+
0.3.0
|
|
13
17
|
```
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
Intentional breaking changes:
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
```text
|
|
22
|
+
false
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Existing `0.3.0` applications do not have to adopt dependency injection immediately.
|
|
18
26
|
|
|
19
|
-
|
|
27
|
+
## Upgrade to 0.3.1
|
|
28
|
+
|
|
29
|
+
After publication:
|
|
20
30
|
|
|
21
31
|
```powershell
|
|
22
32
|
npm exec -- bcp-framework update --check
|
|
23
|
-
npm run update -- 0.3.
|
|
33
|
+
npm run update -- 0.3.1
|
|
24
34
|
```
|
|
25
35
|
|
|
26
|
-
Then
|
|
36
|
+
Then validate the application:
|
|
27
37
|
|
|
28
38
|
```powershell
|
|
29
39
|
npm run typecheck
|
|
30
40
|
npm run build
|
|
41
|
+
npm exec -- bcp-framework routes
|
|
31
42
|
npm exec -- bcp-framework doctor
|
|
32
43
|
```
|
|
33
44
|
|
|
34
|
-
|
|
45
|
+
## Existing Application Platform code remains valid
|
|
35
46
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
These imports remain public:
|
|
47
|
+
This remains supported:
|
|
39
48
|
|
|
40
49
|
```ts
|
|
41
|
-
import {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
import {
|
|
51
|
+
createApp,
|
|
52
|
+
} from "bcp/application";
|
|
53
|
+
|
|
54
|
+
const app =
|
|
55
|
+
createApp({
|
|
56
|
+
name: "my-app",
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
app.provide(
|
|
60
|
+
"database",
|
|
61
|
+
database
|
|
62
|
+
);
|
|
51
63
|
```
|
|
52
64
|
|
|
53
|
-
|
|
65
|
+
`app.services` and `context.services` continue to use the Plugin Platform registry.
|
|
54
66
|
|
|
55
|
-
## Optional migration to
|
|
67
|
+
## Optional migration to typed DI
|
|
56
68
|
|
|
57
|
-
New
|
|
69
|
+
New typed dependencies can use `bcp/container`:
|
|
58
70
|
|
|
59
71
|
```ts
|
|
60
72
|
import {
|
|
61
|
-
|
|
62
|
-
|
|
73
|
+
createServiceToken,
|
|
74
|
+
provideValue,
|
|
75
|
+
} from "bcp/container";
|
|
63
76
|
|
|
64
|
-
|
|
77
|
+
const databaseToken =
|
|
78
|
+
createServiceToken<typeof database>(
|
|
79
|
+
"database"
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const app =
|
|
65
83
|
createApp({
|
|
66
84
|
name: "my-app",
|
|
67
|
-
|
|
85
|
+
providers: [
|
|
86
|
+
provideValue(
|
|
87
|
+
databaseToken,
|
|
88
|
+
database
|
|
89
|
+
),
|
|
90
|
+
],
|
|
68
91
|
});
|
|
69
92
|
```
|
|
70
93
|
|
|
71
|
-
|
|
94
|
+
Then resolve from application hooks or server composition code:
|
|
72
95
|
|
|
73
96
|
```ts
|
|
74
|
-
|
|
75
|
-
app.
|
|
76
|
-
|
|
97
|
+
const database =
|
|
98
|
+
await app.container.resolve(
|
|
99
|
+
databaseToken
|
|
100
|
+
);
|
|
77
101
|
```
|
|
78
102
|
|
|
79
|
-
|
|
103
|
+
You do not need to migrate every plugin service at once.
|
|
104
|
+
|
|
105
|
+
## Factory dependencies
|
|
106
|
+
|
|
107
|
+
Replace manual service construction:
|
|
80
108
|
|
|
81
109
|
```ts
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
110
|
+
const repository =
|
|
111
|
+
createRepository(
|
|
112
|
+
database,
|
|
113
|
+
logger
|
|
114
|
+
);
|
|
87
115
|
```
|
|
88
116
|
|
|
89
|
-
|
|
117
|
+
with explicit typed provider dependencies when useful:
|
|
90
118
|
|
|
91
119
|
```ts
|
|
92
|
-
|
|
120
|
+
const repositoryProvider =
|
|
121
|
+
provideFactory(
|
|
122
|
+
repositoryToken,
|
|
123
|
+
[
|
|
124
|
+
databaseToken,
|
|
125
|
+
loggerToken,
|
|
126
|
+
] as const,
|
|
127
|
+
(
|
|
128
|
+
_context,
|
|
129
|
+
[database, logger]
|
|
130
|
+
) =>
|
|
131
|
+
createRepository(
|
|
132
|
+
database,
|
|
133
|
+
logger
|
|
134
|
+
)
|
|
135
|
+
);
|
|
93
136
|
```
|
|
94
137
|
|
|
95
|
-
|
|
138
|
+
No decorators or reflection metadata are required.
|
|
139
|
+
|
|
140
|
+
## Request/job/test scopes
|
|
96
141
|
|
|
97
|
-
|
|
142
|
+
Use child scopes for dependencies that should not be application singletons:
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
const requestScope =
|
|
146
|
+
app.createScope({
|
|
147
|
+
name: `request:${requestId}`,
|
|
148
|
+
});
|
|
98
149
|
|
|
99
|
-
|
|
150
|
+
try {
|
|
151
|
+
const service =
|
|
152
|
+
await requestScope.resolve(
|
|
153
|
+
requestServiceToken
|
|
154
|
+
);
|
|
155
|
+
} finally {
|
|
156
|
+
await requestScope.dispose();
|
|
157
|
+
}
|
|
158
|
+
```
|
|
100
159
|
|
|
101
|
-
|
|
160
|
+
Testing overrides:
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
const testScope =
|
|
164
|
+
app.createScope({
|
|
165
|
+
name: "test",
|
|
166
|
+
overrides: [
|
|
167
|
+
provideValue(
|
|
168
|
+
mailerToken,
|
|
169
|
+
fakeMailer
|
|
170
|
+
),
|
|
171
|
+
],
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Lifetimes
|
|
176
|
+
|
|
177
|
+
Provider lifetimes are:
|
|
102
178
|
|
|
103
179
|
```text
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
180
|
+
singleton
|
|
181
|
+
scoped
|
|
182
|
+
transient
|
|
107
183
|
```
|
|
108
184
|
|
|
109
|
-
|
|
185
|
+
The default is `singleton`.
|
|
186
|
+
|
|
187
|
+
A common mapping is:
|
|
188
|
+
|
|
189
|
+
```text
|
|
190
|
+
database pool singleton
|
|
191
|
+
cache client singleton
|
|
192
|
+
repository scoped or singleton depending on state
|
|
193
|
+
request context scoped
|
|
194
|
+
small stateless factory output transient when required
|
|
195
|
+
```
|
|
110
196
|
|
|
111
|
-
##
|
|
197
|
+
## Disposal ownership
|
|
112
198
|
|
|
113
|
-
|
|
199
|
+
If the DI container owns a resource through a provider `dispose()` callback, avoid also registering an independent shutdown owner for the same instance unless the cleanup operation is explicitly idempotent.
|
|
200
|
+
|
|
201
|
+
Example:
|
|
114
202
|
|
|
115
203
|
```ts
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
204
|
+
provideFactory(
|
|
205
|
+
databaseToken,
|
|
206
|
+
[] as const,
|
|
207
|
+
createDatabase,
|
|
208
|
+
{
|
|
209
|
+
dispose(database) {
|
|
210
|
+
return database.close();
|
|
211
|
+
},
|
|
212
|
+
}
|
|
213
|
+
);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The Application Platform keeps the container alive until application resources/plugins stop, then disposes injected services in reverse creation order.
|
|
217
|
+
|
|
218
|
+
## Application resource lifecycle
|
|
219
|
+
|
|
220
|
+
Long-running components can still use `app.addResource()`:
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
app.addResource({
|
|
224
|
+
name: "worker",
|
|
225
|
+
start: () => worker.start(),
|
|
226
|
+
stop: () => worker.stop(),
|
|
227
|
+
});
|
|
123
228
|
```
|
|
124
229
|
|
|
125
|
-
|
|
230
|
+
DI and Deployment resources solve different concerns:
|
|
231
|
+
|
|
232
|
+
```text
|
|
233
|
+
container provider -> construct/resolve/dispose dependencies
|
|
234
|
+
application resource -> start/readiness/stop long-running runtime components
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
A provider may construct the worker while an application resource starts/stops it.
|
|
126
238
|
|
|
127
239
|
## Server-only boundary
|
|
128
240
|
|
|
129
|
-
|
|
241
|
+
Both entrypoints are server-only:
|
|
242
|
+
|
|
243
|
+
```text
|
|
244
|
+
bcp/container
|
|
245
|
+
bcp/application
|
|
246
|
+
```
|
|
130
247
|
|
|
131
|
-
|
|
248
|
+
Do not import them into React client pages/islands.
|
|
132
249
|
|
|
133
250
|
## API baseline
|
|
134
251
|
|
|
135
|
-
`0.
|
|
252
|
+
`0.3.1` adds one public entrypoint over `0.3.0`:
|
|
253
|
+
|
|
254
|
+
```text
|
|
255
|
+
bcp/container
|
|
256
|
+
```
|
|
136
257
|
|
|
137
|
-
|
|
258
|
+
The reviewed API snapshot records the new `container.mjs` prepared runtime and browser poison boundary.
|
|
138
259
|
|
|
139
|
-
|
|
260
|
+
## Framework validation checklist
|
|
140
261
|
|
|
141
262
|
```powershell
|
|
142
263
|
npm run typecheck
|
|
@@ -149,7 +270,7 @@ npm run release:readiness
|
|
|
149
270
|
npm run rc:check
|
|
150
271
|
```
|
|
151
272
|
|
|
152
|
-
For
|
|
273
|
+
For application upgrades:
|
|
153
274
|
|
|
154
275
|
```powershell
|
|
155
276
|
npm run typecheck
|