@chidchanun/bcp 0.1.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/LICENSE +21 -0
  3. package/README.md +241 -0
  4. package/docs/caching.md +76 -0
  5. package/docs/configuration.md +97 -0
  6. package/docs/deployment.md +74 -0
  7. package/docs/getting-started.md +82 -0
  8. package/docs/middleware.md +58 -0
  9. package/docs/releasing.md +299 -0
  10. package/docs/routing.md +103 -0
  11. package/docs/security.md +57 -0
  12. package/package.json +68 -0
  13. package/packages/bundler/src/client-islands.ts +1457 -0
  14. package/packages/bundler/src/incremental-context.ts +206 -0
  15. package/packages/bundler/src/index.ts +1991 -0
  16. package/packages/bundler/src/module-graph.ts +317 -0
  17. package/packages/bundler/src/partial-hydration.ts +414 -0
  18. package/packages/bundler/src/production.ts +974 -0
  19. package/packages/bundler/src/server-production-middleware.ts +447 -0
  20. package/packages/bundler/src/server-production.ts +1193 -0
  21. package/packages/bundler/src/special-files.ts +131 -0
  22. package/packages/cache/src/index.ts +761 -0
  23. package/packages/cli/bin/bcp.mjs +93 -0
  24. package/packages/cli/src/args.ts +305 -0
  25. package/packages/cli/src/bootstrap.ts +514 -0
  26. package/packages/cli/src/index.ts +504 -0
  27. package/packages/cli/src/version.ts +45 -0
  28. package/packages/client/src/cache.ts +11 -0
  29. package/packages/client/src/config.ts +18 -0
  30. package/packages/client/src/error-boundary.tsx +149 -0
  31. package/packages/client/src/hydration.ts +3 -0
  32. package/packages/client/src/index.tsx +57 -0
  33. package/packages/client/src/islands.tsx +315 -0
  34. package/packages/client/src/metadata.ts +281 -0
  35. package/packages/client/src/navigation-loading.ts +52 -0
  36. package/packages/client/src/navigation-state.ts +80 -0
  37. package/packages/client/src/not-found.ts +34 -0
  38. package/packages/client/src/persistent-layout-runtime.ts +273 -0
  39. package/packages/client/src/router-v2.tsx +969 -0
  40. package/packages/client/src/router.tsx +1 -0
  41. package/packages/config/src/index.ts +1038 -0
  42. package/packages/env/src/index.ts +593 -0
  43. package/packages/router/src/advanced-router.ts +1032 -0
  44. package/packages/router/src/index.ts +1 -0
  45. package/packages/server/src/compression.ts +249 -0
  46. package/packages/server/src/dev-document-metadata.ts +154 -0
  47. package/packages/server/src/dev-hmr.ts +225 -0
  48. package/packages/server/src/index.ts +2265 -0
  49. package/packages/server/src/metadata.ts +478 -0
  50. package/packages/server/src/middleware-dev-server.ts +260 -0
  51. package/packages/server/src/middleware-loader.ts +140 -0
  52. package/packages/server/src/middleware-proxy.ts +516 -0
  53. package/packages/server/src/middleware.ts +704 -0
  54. package/packages/server/src/navigation-payload.ts +471 -0
  55. package/packages/server/src/production-server.ts +1746 -0
  56. package/packages/server/src/response-cache-proxy.ts +828 -0
  57. package/packages/server/src/security-proxy.ts +406 -0
  58. package/packages/server/src/security.ts +451 -0
  59. package/packages/server/src/standalone-production-runtime-v2.ts +2047 -0
  60. package/packages/server/src/standalone-production-runtime-v3.ts +250 -0
  61. package/packages/server/src/standalone-production-runtime-v4.ts +289 -0
  62. package/packages/server/src/standalone-production-runtime-v5.ts +289 -0
  63. package/packages/server/src/standalone-production-runtime.ts +1951 -0
  64. package/packages/server/src/standalone-production-server.ts +6 -0
  65. package/packages/server/src/static-assets.ts +262 -0
  66. package/packages/server/src/static-dev-server.ts +854 -0
@@ -0,0 +1,289 @@
1
+ import fs from "node:fs";
2
+ import * as net from "node:net";
3
+ import path from "node:path";
4
+
5
+ import {
6
+ createSecurityProxy,
7
+ } from "./security-proxy.js";
8
+
9
+ import {
10
+ createStandaloneProductionServer as createBaseStandaloneProductionServer,
11
+ type StandaloneApiRoute,
12
+ type StandalonePageRoute,
13
+ type StandaloneProductionServerOptions as BaseStandaloneProductionServerOptions,
14
+ } from "./standalone-production-runtime-v4.js";
15
+
16
+ export type {
17
+ StandaloneApiRoute,
18
+ StandalonePageRoute,
19
+ };
20
+
21
+ export interface StandaloneProductionServerOptions
22
+ extends BaseStandaloneProductionServerOptions {}
23
+
24
+ export function createStandaloneProductionServer(
25
+ options: StandaloneProductionServerOptions
26
+ ) {
27
+ let baseServer:
28
+ ReturnType<
29
+ typeof createBaseStandaloneProductionServer
30
+ > | null =
31
+ null;
32
+
33
+ let securityProxy:
34
+ ReturnType<
35
+ typeof createSecurityProxy
36
+ > | null =
37
+ null;
38
+
39
+ let started =
40
+ false;
41
+
42
+ async function start(): Promise<void> {
43
+ if (started) {
44
+ return;
45
+ }
46
+
47
+ applyFrozenSecurityConfig(
48
+ options.buildDirectory
49
+ );
50
+
51
+ const internalPort =
52
+ await findFreePort();
53
+
54
+ baseServer =
55
+ createBaseStandaloneProductionServer({
56
+ ...options,
57
+ port:
58
+ internalPort,
59
+ hostname:
60
+ "127.0.0.1",
61
+ });
62
+
63
+ await baseServer.start();
64
+
65
+ securityProxy =
66
+ createSecurityProxy({
67
+ port:
68
+ options.port,
69
+ hostname:
70
+ options.hostname,
71
+ upstreamPort:
72
+ internalPort,
73
+ upstreamHostname:
74
+ "127.0.0.1",
75
+ });
76
+
77
+ try {
78
+ await securityProxy.start();
79
+ } catch (error) {
80
+ await baseServer.stop();
81
+ baseServer =
82
+ null;
83
+ securityProxy =
84
+ null;
85
+ throw error;
86
+ }
87
+
88
+ started =
89
+ true;
90
+
91
+ console.log(
92
+ `[BCP Security] Gateway: http://${options.hostname}:${options.port}`
93
+ );
94
+ console.log("");
95
+ }
96
+
97
+ async function stop(): Promise<void> {
98
+ if (securityProxy) {
99
+ await securityProxy.stop();
100
+ securityProxy =
101
+ null;
102
+ }
103
+
104
+ if (baseServer) {
105
+ await baseServer.stop();
106
+ baseServer =
107
+ null;
108
+ }
109
+
110
+ started =
111
+ false;
112
+ }
113
+
114
+ return {
115
+ start,
116
+ stop,
117
+ };
118
+ }
119
+
120
+ function applyFrozenSecurityConfig(
121
+ buildDirectory: string
122
+ ): void {
123
+ const configFile =
124
+ path.join(
125
+ buildDirectory,
126
+ "server",
127
+ "config.json"
128
+ );
129
+
130
+ if (
131
+ !fs.existsSync(
132
+ configFile
133
+ )
134
+ ) {
135
+ return;
136
+ }
137
+
138
+ try {
139
+ const parsed =
140
+ JSON.parse(
141
+ fs.readFileSync(
142
+ configFile,
143
+ "utf8"
144
+ )
145
+ ) as {
146
+ server?: {
147
+ bodyLimit?: number;
148
+ };
149
+ security?: {
150
+ poweredByHeader?: boolean;
151
+ contentSecurityPolicy?: string | false;
152
+ frameOptions?: "DENY" | "SAMEORIGIN" | false;
153
+ referrerPolicy?: string;
154
+ permissionsPolicy?: string | false;
155
+ };
156
+ };
157
+
158
+ if (
159
+ process.env.BCP_BODY_LIMIT === undefined &&
160
+ Number.isInteger(
161
+ parsed.server?.bodyLimit
162
+ )
163
+ ) {
164
+ process.env.BCP_BODY_LIMIT =
165
+ String(
166
+ parsed.server?.bodyLimit
167
+ );
168
+ }
169
+
170
+ const security =
171
+ parsed.security;
172
+
173
+ if (!security) {
174
+ return;
175
+ }
176
+
177
+ process.env.BCP_POWERED_BY_HEADER ??=
178
+ security.poweredByHeader
179
+ ? "1"
180
+ : "0";
181
+ process.env.BCP_SECURITY_CSP ??=
182
+ security.contentSecurityPolicy === false ||
183
+ security.contentSecurityPolicy === undefined
184
+ ? "0"
185
+ : security.contentSecurityPolicy;
186
+ process.env.BCP_SECURITY_FRAME_OPTIONS ??=
187
+ security.frameOptions === false ||
188
+ security.frameOptions === undefined
189
+ ? "0"
190
+ : security.frameOptions;
191
+ process.env.BCP_SECURITY_REFERRER_POLICY ??=
192
+ security.referrerPolicy ??
193
+ "strict-origin-when-cross-origin";
194
+ process.env.BCP_SECURITY_PERMISSIONS_POLICY ??=
195
+ security.permissionsPolicy === false ||
196
+ security.permissionsPolicy === undefined
197
+ ? "0"
198
+ : security.permissionsPolicy;
199
+ } catch (error) {
200
+ throw new Error(
201
+ `BCP Framework: invalid standalone security config at "${configFile}". ${error instanceof Error ? error.message : String(error)}`
202
+ );
203
+ }
204
+ }
205
+
206
+ async function findFreePort(): Promise<number> {
207
+ const server =
208
+ net.createServer();
209
+
210
+ try {
211
+ await new Promise<void>(
212
+ (
213
+ resolve,
214
+ reject
215
+ ) => {
216
+ const onError =
217
+ (error: Error) => {
218
+ server.off(
219
+ "listening",
220
+ onListening
221
+ );
222
+ reject(
223
+ error
224
+ );
225
+ };
226
+
227
+ const onListening =
228
+ () => {
229
+ server.off(
230
+ "error",
231
+ onError
232
+ );
233
+ resolve();
234
+ };
235
+
236
+ server.once(
237
+ "error",
238
+ onError
239
+ );
240
+ server.once(
241
+ "listening",
242
+ onListening
243
+ );
244
+ server.listen(
245
+ 0,
246
+ "127.0.0.1"
247
+ );
248
+ }
249
+ );
250
+
251
+ const address =
252
+ server.address();
253
+
254
+ if (
255
+ !address ||
256
+ typeof address ===
257
+ "string"
258
+ ) {
259
+ throw new Error(
260
+ "BCP Framework: could not allocate security gateway port."
261
+ );
262
+ }
263
+
264
+ return address.port;
265
+ } finally {
266
+ if (
267
+ server.listening
268
+ ) {
269
+ await new Promise<void>(
270
+ (
271
+ resolve,
272
+ reject
273
+ ) => {
274
+ server.close(
275
+ (error) => {
276
+ if (error) {
277
+ reject(
278
+ error
279
+ );
280
+ return;
281
+ }
282
+ resolve();
283
+ }
284
+ );
285
+ }
286
+ );
287
+ }
288
+ }
289
+ }