@zntc/react-native 0.1.1 → 0.1.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/dist/dev-server/bun-http-adapter.d.ts +10 -0
- package/dist/dev-server/hmr-bridge.d.ts +16 -1
- package/dist/dev-server/http-server.d.ts +1 -0
- package/dist/dev-server/index.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +198 -46
- package/dist/preset.d.ts +11 -0
- package/package.json +3 -3
- package/runtime/zntc-hmr-client.cjs +22 -10
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Middleware } from './types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* 미들웨어 체인(node req/res 기반)을 Bun `Request` 에 대해 실행하고 단일
|
|
4
|
+
* `Response` 로 변환. terminal next() / next(err) 도 node 경로(chainToHandler)와
|
|
5
|
+
* 동일하게 404 / 500 으로 매핑한다.
|
|
6
|
+
*
|
|
7
|
+
* route handler 가 비동기로 res.end() 를 호출하는 경우(.catch(next) 패턴)도
|
|
8
|
+
* Promise 가 end / next 둘 중 먼저 오는 쪽에서 resolve 되도록 한다.
|
|
9
|
+
*/
|
|
10
|
+
export declare function runMiddlewareForBun(middleware: Middleware, req: Request): Promise<Response>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { IncomingMessage } from 'node:http';
|
|
2
2
|
import type { Socket } from 'node:net';
|
|
3
|
+
import type { BunHmrClient } from '@zntc/server';
|
|
3
4
|
import { type MetroHmrAdapter } from '../metro-hmr-adapter.ts';
|
|
4
5
|
import type { PlatformStateCallbacks } from './platform-state.ts';
|
|
5
6
|
export interface HmrBridgeOptions {
|
|
@@ -14,8 +15,22 @@ export interface HmrBridge {
|
|
|
14
15
|
readonly adapter: MetroHmrAdapter;
|
|
15
16
|
readonly callbacks: PlatformStateCallbacks;
|
|
16
17
|
readonly path: string;
|
|
17
|
-
/** http upgrade chain 안에서 호출 — channel.accept + initial greeting. */
|
|
18
|
+
/** http upgrade chain 안에서 호출 (Node) — channel.accept + initial greeting. */
|
|
18
19
|
acceptUpgrade(req: IncomingMessage, socket: Socket): void;
|
|
20
|
+
/**
|
|
21
|
+
* Bun.serve websocket `open(ws)` 에서 호출 — Bun client 등록 + initial greeting.
|
|
22
|
+
* Node 의 `acceptUpgrade` 와 대칭이지만 raw socket 핸드셰이크가 없다 (Bun.serve
|
|
23
|
+
* 의 `server.upgrade(req)` 가 RFC6455 핸드셰이크를 native 로 처리하므로).
|
|
24
|
+
*/
|
|
25
|
+
acceptBun(ws: BunHmrClient): void;
|
|
26
|
+
/** Bun.serve websocket `close(ws)` 에서 호출 — Bun client 정리. */
|
|
27
|
+
removeBun(ws: BunHmrClient): void;
|
|
28
|
+
/**
|
|
29
|
+
* Bun.serve websocket `message(ws, msg)` 에서 호출 — client → server text 를
|
|
30
|
+
* incoming 핸들러(register-entrypoints ACK / log forwarding)로 dispatch.
|
|
31
|
+
* Node 경로는 `channel.accept` 의 `socket.on('data')` 가 같은 역할.
|
|
32
|
+
*/
|
|
33
|
+
handleBunMessage(ws: BunHmrClient, text: string): void;
|
|
19
34
|
/** RN runtime console.log forwarding 출력 표시 toggle. 새 상태 반환. */
|
|
20
35
|
toggleLogs(): boolean;
|
|
21
36
|
}
|
|
@@ -30,3 +30,4 @@ export interface DevHttpServerHandle {
|
|
|
30
30
|
*/
|
|
31
31
|
export declare function createBaseMiddleware(options: RnDevServerOptions, deps: DevHttpServerDeps): Middleware;
|
|
32
32
|
export declare function createDevHttpServer(options: RnDevServerOptions, deps: DevHttpServerDeps): Promise<DevHttpServerHandle>;
|
|
33
|
+
export declare function createBunDevHttpServer(options: RnDevServerOptions, deps: DevHttpServerDeps): Promise<DevHttpServerHandle>;
|
|
@@ -2,7 +2,7 @@ export { createHmrBridge, type HmrBridge, type HmrBridgeOptions } from './hmr-br
|
|
|
2
2
|
export { type RnDevServerHandle, serveRn, type ServeRnExtras } from './serve.ts';
|
|
3
3
|
export { type CliServerApi, type CliWebsocketEndpoint, loadCliServerApi, type LoadCliServerApiOptions, } from './middleware/cli-server-api.ts';
|
|
4
4
|
export { type DevMiddleware, loadDevMiddleware, type LoadDevMiddlewareOptions, } from './middleware/dev-middleware.ts';
|
|
5
|
-
export { createBaseMiddleware, createDevHttpServer, type DevHttpServerDeps, type DevHttpServerHandle, } from './http-server.ts';
|
|
5
|
+
export { createBaseMiddleware, createBunDevHttpServer, createDevHttpServer, type DevHttpServerDeps, type DevHttpServerHandle, } from './http-server.ts';
|
|
6
6
|
export { parseRequestUrl, readJsonBody, sendJson, sendText } from './http-utils.ts';
|
|
7
7
|
export type { CustomizeFrame, RnDevServerOptions, RnDevServerOptionsInput } from './options.ts';
|
|
8
8
|
export { buildRnDevServerOptions } from './options.ts';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { HMR_RN_MSG, type HmrRnErrorMessage, type HmrRnLogMessage, type HmrRnMessage, type HmrRnMessageType, type HmrRnReloadMessage, type HmrRnUpdateDoneMessage, type HmrRnUpdateMessage, type HmrRnUpdateModule, type HmrRnUpdateStartMessage, } from '@zntc/server';
|
|
2
|
-
export { type AssetResolverOptions, type Broadcast, buildRnDevServerOptions, createBaseMiddleware, createDevHttpServer, createHmrBridge, createPlatformState, type CliServerApi, type CliWebsocketEndpoint, type DevMiddleware, loadCliServerApi, loadDevMiddleware, type LoadCliServerApiOptions, type LoadDevMiddlewareOptions, createPlatformStateRegistry, type CustomizeFrame, type DevHttpServerDeps, type DevHttpServerHandle, type FrameInfo, getCachedSourceMap, type HmrBridge, type HmrBridgeOptions, applyCustomizeFrame, createSourceMapConsumer, extractCodeFrame, handleAssetRequest, handleBundleRequest, handleHmrMapRequest, handleIndexPage, handleMapRequest, handleSymbolicateRequest, isIndexRoute, isAssetRoute, isBundleRoute, isHmrMapRoute, isMapRoute, isSymbolicateRoute, normalizeFrame, symbolicateFrame, type SymbolicateCodeFrame, type SymbolicateRequest, type SymbolicateResponse, type Middleware, type MiddlewareEnhanceContext, type PlatformState, type PlatformStateCallbacks, type PlatformStateRegistry, colors, formatLogBadge, logBundle, logError, logInfo, logWarn, postProcessSourceMap, type SourcemapPathOptions, printZntcRnBanner, resolveAssetPath, type ServeRnExtras, serveRn, setupTerminalActions, type TerminalActionsCallbacks, type TerminalActionsOptions, type RnDevServerHandle, type RnDevServerOptions, type RnDevServerOptionsInput, waitForBuild, } from './dev-server/index.ts';
|
|
2
|
+
export { type AssetResolverOptions, type Broadcast, buildRnDevServerOptions, createBaseMiddleware, createBunDevHttpServer, createDevHttpServer, createHmrBridge, createPlatformState, type CliServerApi, type CliWebsocketEndpoint, type DevMiddleware, loadCliServerApi, loadDevMiddleware, type LoadCliServerApiOptions, type LoadDevMiddlewareOptions, createPlatformStateRegistry, type CustomizeFrame, type DevHttpServerDeps, type DevHttpServerHandle, type FrameInfo, getCachedSourceMap, type HmrBridge, type HmrBridgeOptions, applyCustomizeFrame, createSourceMapConsumer, extractCodeFrame, handleAssetRequest, handleBundleRequest, handleHmrMapRequest, handleIndexPage, handleMapRequest, handleSymbolicateRequest, isIndexRoute, isAssetRoute, isBundleRoute, isHmrMapRoute, isMapRoute, isSymbolicateRoute, normalizeFrame, symbolicateFrame, type SymbolicateCodeFrame, type SymbolicateRequest, type SymbolicateResponse, type Middleware, type MiddlewareEnhanceContext, type PlatformState, type PlatformStateCallbacks, type PlatformStateRegistry, colors, formatLogBadge, logBundle, logError, logInfo, logWarn, postProcessSourceMap, type SourcemapPathOptions, printZntcRnBanner, resolveAssetPath, type ServeRnExtras, serveRn, setupTerminalActions, type TerminalActionsCallbacks, type TerminalActionsOptions, type RnDevServerHandle, type RnDevServerOptions, type RnDevServerOptionsInput, waitForBuild, } from './dev-server/index.ts';
|
|
3
3
|
export { createMetroHmrAdapter, type MetroHmrAdapter } from './metro-hmr-adapter.ts';
|
|
4
4
|
export type { CustomResolver, MetroPlatform, Resolution, ResolutionContext, } from './metro-resolver-types.ts';
|
|
5
5
|
export { createAssetPlugin } from './plugins/asset.ts';
|
package/dist/index.js
CHANGED
|
@@ -87,7 +87,7 @@ const URI_REGEX = /^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
|
|
|
87
87
|
if (parsedUrl.path.indexOf("//&") === -1) {
|
|
88
88
|
return urlToNormalize;
|
|
89
89
|
}
|
|
90
|
-
return
|
|
90
|
+
return parsedUrl.schemeAndAuthority + parsedUrl.path.replace("//&", "?") + (parsedUrl.queryWithoutQuestionMark.length > 0 ? "&" + parsedUrl.queryWithoutQuestionMark : "") + parsedUrl.fragmentWithHash;
|
|
91
91
|
}
|
|
92
92
|
function toJscSafeUrl(urlToConvert) {
|
|
93
93
|
if (!_rfc3986Parse(urlToConvert).hasQueryPart) {
|
|
@@ -97,7 +97,7 @@ const URI_REGEX = /^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
|
|
|
97
97
|
if (parsedUrl.queryWithoutQuestionMark.length > 0 && (parsedUrl.path === "" || parsedUrl.path === "/")) {
|
|
98
98
|
throw new Error(`The given URL "${urlToConvert}" has an empty path and cannot be converted to a JSC-safe format.`);
|
|
99
99
|
}
|
|
100
|
-
return
|
|
100
|
+
return parsedUrl.schemeAndAuthority + parsedUrl.path + (parsedUrl.queryWithoutQuestionMark.length > 0 ? "//&" + parsedUrl.queryWithoutQuestionMark.replace(/\?/g, "%3F") : "") + parsedUrl.fragmentWithHash;
|
|
101
101
|
}
|
|
102
102
|
module.exports = { isJscSafeUrl, toNormalUrl, toJscSafeUrl };
|
|
103
103
|
|
|
@@ -110,15 +110,6 @@ var require__disabled__url = __commonJS({
|
|
|
110
110
|
}
|
|
111
111
|
});
|
|
112
112
|
//#endregion
|
|
113
|
-
//#region (optional-missing):
|
|
114
|
-
var require__optional_missing__ = __commonJS({
|
|
115
|
-
"(optional-missing):"(exports, module) {
|
|
116
|
-
var e = new Error("Cannot find module \"" + "" + "\"");
|
|
117
|
-
e.code = "MODULE_NOT_FOUND";
|
|
118
|
-
throw e;
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
//#endregion
|
|
122
113
|
//#region array-set.js
|
|
123
114
|
var require_source_map_lib_array_set = __commonJS({
|
|
124
115
|
"array-set.js"(exports, module) {
|
|
@@ -260,7 +251,7 @@ var require_source_map_lib_mapping_list = __commonJS({
|
|
|
260
251
|
const util = require_source_map_lib_util();
|
|
261
252
|
function generatedPositionAfter(mappingA,mappingB) {
|
|
262
253
|
const lineA = mappingA.generatedLine,lineB = mappingB.generatedLine,columnA = mappingA.generatedColumn,columnB = mappingB.generatedColumn;
|
|
263
|
-
return
|
|
254
|
+
return lineB > lineA || lineB == lineA && columnB >= columnA || util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0;
|
|
264
255
|
}
|
|
265
256
|
class MappingList {
|
|
266
257
|
constructor() {
|
|
@@ -525,7 +516,7 @@ const util = require_source_map_lib_util(),binarySearch = require_source_map_lib
|
|
|
525
516
|
bias = SourceMapConsumer.GREATEST_LOWER_BOUND;
|
|
526
517
|
}
|
|
527
518
|
let mapping;
|
|
528
|
-
this._wasm.withMappingCallback((m) =>
|
|
519
|
+
this._wasm.withMappingCallback((m) => mapping = m, () => {
|
|
529
520
|
this._wasm.exports.original_location_for(this._getMappingsPtr(), needle.generatedLine - 1, needle.generatedColumn, bias);
|
|
530
521
|
});
|
|
531
522
|
if (mapping) {
|
|
@@ -547,9 +538,9 @@ const util = require_source_map_lib_util(),binarySearch = require_source_map_lib
|
|
|
547
538
|
if (!this.sourcesContent) {
|
|
548
539
|
return false;
|
|
549
540
|
}
|
|
550
|
-
return
|
|
541
|
+
return this.sourcesContent.length >= this._sources.size() && !this.sourcesContent.some(function(sc) {
|
|
551
542
|
return sc == null;
|
|
552
|
-
})
|
|
543
|
+
});
|
|
553
544
|
}
|
|
554
545
|
sourceContentFor(aSource,nullOnMissing) {
|
|
555
546
|
if (!this.sourcesContent) {
|
|
@@ -582,7 +573,7 @@ const util = require_source_map_lib_util(),binarySearch = require_source_map_lib
|
|
|
582
573
|
bias = SourceMapConsumer.GREATEST_LOWER_BOUND;
|
|
583
574
|
}
|
|
584
575
|
let mapping;
|
|
585
|
-
this._wasm.withMappingCallback((m) =>
|
|
576
|
+
this._wasm.withMappingCallback((m) => mapping = m, () => {
|
|
586
577
|
this._wasm.exports.generated_location_for(this._getMappingsPtr(), needle.source, needle.originalLine - 1, needle.originalColumn, bias);
|
|
587
578
|
});
|
|
588
579
|
if (mapping) {
|
|
@@ -616,7 +607,7 @@ const util = require_source_map_lib_util(),binarySearch = require_source_map_lib
|
|
|
616
607
|
throw new Error("Support for url field in sections not implemented.");
|
|
617
608
|
}
|
|
618
609
|
const offset = util.getArg(s, "offset"),offsetLine = util.getArg(offset, "line"),offsetColumn = util.getArg(offset, "column");
|
|
619
|
-
if (offsetLine < lastOffset.line ||
|
|
610
|
+
if (offsetLine < lastOffset.line || offsetLine === lastOffset.line && offsetColumn < lastOffset.column) {
|
|
620
611
|
throw new Error("Section offsets must be ordered and non-overlapping.");
|
|
621
612
|
}
|
|
622
613
|
lastOffset = offset;
|
|
@@ -645,7 +636,7 @@ const util = require_source_map_lib_util(),binarySearch = require_source_map_lib
|
|
|
645
636
|
if (cmp) {
|
|
646
637
|
return cmp;
|
|
647
638
|
}
|
|
648
|
-
return
|
|
639
|
+
return aNeedle.generatedColumn - (section.generatedOffset.generatedColumn - 1);
|
|
649
640
|
}),section = this._sections[sectionIndex];
|
|
650
641
|
if (!section) {
|
|
651
642
|
return { source: null, line: null, column: null, name: null };
|
|
@@ -1511,13 +1502,13 @@ exports.SourceMapGenerator = require_source_map_lib_source_map_generator().Sourc
|
|
|
1511
1502
|
});
|
|
1512
1503
|
//#endregion
|
|
1513
1504
|
//#region protocol.ts
|
|
1514
|
-
const HMR_MSG = Object.freeze({ Connected: "connected", CssUpdate: "css-update", ClearError: "clear-error", Error: "error", FullReload: "full-reload" }),HMR_WS_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
|
1505
|
+
const HMR_MSG = Object.freeze({ Connected: "connected", CssUpdate: "css-update", ClearError: "clear-error", Error: "error", FullReload: "full-reload", UpdateStart: "update-start", Update: "update", UpdateDone: "update-done" }),HMR_WS_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
|
1515
1506
|
function normalizeHmrErrors(errors) {
|
|
1516
1507
|
if (!Array.isArray(errors) || errors.length === 0) {
|
|
1517
1508
|
return [{ file: "", message: "Unknown build error" }];
|
|
1518
1509
|
}
|
|
1519
1510
|
return errors.map((error) => {
|
|
1520
|
-
const e =
|
|
1511
|
+
const e = error ?? {},file = typeof e.location?.file == "string" ? e.location.file : "",message = String(e.text ?? e.message ?? error);
|
|
1521
1512
|
return { file, message };
|
|
1522
1513
|
});
|
|
1523
1514
|
}
|
|
@@ -1585,8 +1576,8 @@ function parseTextFrame(buffer) {
|
|
|
1585
1576
|
//#endregion
|
|
1586
1577
|
//#region hmr-channel.ts
|
|
1587
1578
|
function extractErrorText(error) {
|
|
1588
|
-
const e =
|
|
1589
|
-
return
|
|
1579
|
+
const e = error ?? {};
|
|
1580
|
+
return typeof e.stack == "string" && e.stack || typeof e.message == "string" && e.message || String(error);
|
|
1590
1581
|
}
|
|
1591
1582
|
function createHmrChannel() {
|
|
1592
1583
|
const nodeSockets = new Set(),bunClients = new Set(),incomingHandlers = [],connectedText = JSON.stringify({ type: HMR_MSG.Connected });
|
|
@@ -1614,14 +1605,15 @@ function createHmrChannel() {
|
|
|
1614
1605
|
let recvBuffer = Buffer.alloc(0);
|
|
1615
1606
|
socket.on("data", (chunk) => {
|
|
1616
1607
|
if (incomingHandlers.length === 0)return;
|
|
1617
|
-
recvBuffer =
|
|
1608
|
+
recvBuffer = recvBuffer.length === 0 ? chunk : Buffer.concat([recvBuffer, chunk]);
|
|
1609
|
+
const reply = (text) => writeTextFrame(socket, text);
|
|
1618
1610
|
while (recvBuffer.length > 0) {
|
|
1619
1611
|
const parsed = parseTextFrame(recvBuffer);
|
|
1620
1612
|
if (!parsed)break;
|
|
1621
1613
|
recvBuffer = recvBuffer.subarray(parsed.consumed);
|
|
1622
1614
|
for (const handler of incomingHandlers) {
|
|
1623
1615
|
try {
|
|
1624
|
-
handler(parsed.text,
|
|
1616
|
+
handler(parsed.text, reply);
|
|
1625
1617
|
} catch {
|
|
1626
1618
|
}
|
|
1627
1619
|
}
|
|
@@ -1635,6 +1627,15 @@ function createHmrChannel() {
|
|
|
1635
1627
|
greetBun(ws);
|
|
1636
1628
|
}, removeBunClient(ws) {
|
|
1637
1629
|
bunClients.delete(ws);
|
|
1630
|
+
}, dispatchBunIncoming(ws,text) {
|
|
1631
|
+
if (incomingHandlers.length === 0)return;
|
|
1632
|
+
const reply = (out) => ws.send(out);
|
|
1633
|
+
for (const handler of incomingHandlers) {
|
|
1634
|
+
try {
|
|
1635
|
+
handler(text, reply);
|
|
1636
|
+
} catch {
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1638
1639
|
}, onIncoming(handler) {
|
|
1639
1640
|
incomingHandlers.push(handler);
|
|
1640
1641
|
}, broadcast(message) {
|
|
@@ -1698,7 +1699,7 @@ const BANNER_WIDTH = 59;
|
|
|
1698
1699
|
function bannerLine(content) {
|
|
1699
1700
|
const visibleLen = content.replace(/\x1b\[[0-9;]*m/g, "").length,padding = Math.max(0, BANNER_WIDTH - visibleLen),left = Math.floor(padding / 2);
|
|
1700
1701
|
;
|
|
1701
|
-
return `${colors.cyan} ║${colors.reset}${" ".repeat(left)}${content}${" ".repeat(
|
|
1702
|
+
return `${colors.cyan} ║${colors.reset}${" ".repeat(left)}${content}${" ".repeat(padding - left)}${colors.cyan}║${colors.reset}`;
|
|
1702
1703
|
}
|
|
1703
1704
|
const ZNTC_ASCII = ["▀▀▀▀▀▀▀▀", "▀▀▀▀▀▀▀▀▀▀▀▀", "▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀", "▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀", "▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀"],ZNTC_GRADIENT = [colors.brightYellow, colors.brightYellow, colors.yellow, colors.brightRed, colors.brightRed];
|
|
1704
1705
|
if (ZNTC_ASCII.length !== ZNTC_GRADIENT.length) {
|
|
@@ -1736,7 +1737,8 @@ function buildOnRebuild(adapter,opts={}) {
|
|
|
1736
1737
|
const annotated = annotateUpdates(event.updates, state.platform);
|
|
1737
1738
|
adapter.sendUpdate(annotated);
|
|
1738
1739
|
if (!opts.silent) {
|
|
1739
|
-
|
|
1740
|
+
const profileOn = process.env.ZNTC_PROFILE != null && process.env.ZNTC_PROFILE !== "",pd = profileOn ? event.phaseDurations : undefined,r = (n) => n == null ? "-" : n.toFixed(0),bd = pd ? ` ${colors.dim}[det=${r(pd.detect)} grph=${r(pd.graph)} lnk=${r(pd.link)} shk=${r(pd.shake)} emt=${r(pd.emit)} dlt=${r(pd.delta)} | gDisc=${r(pd.graphDiscover)} gBld=${r(pd.graphBuild)} eOut=${r(pd.emitOutput)} eMod=${r(pd.emitModulePass)} eCat=${r(pd.emitConcat)}]${colors.reset}` : "";
|
|
1741
|
+
logInfo(`HMR update ${colors.dim}[${state.platform}] ${event.updates.length} module(s) (${ms}ms)${colors.reset}${bd}`);
|
|
1740
1742
|
}
|
|
1741
1743
|
return;
|
|
1742
1744
|
}
|
|
@@ -1746,7 +1748,7 @@ function buildOnRebuild(adapter,opts={}) {
|
|
|
1746
1748
|
};
|
|
1747
1749
|
}
|
|
1748
1750
|
function buildIncomingHandler(adapter,getLogsEnabled) {
|
|
1749
|
-
return (text,
|
|
1751
|
+
return (text, reply) => {
|
|
1750
1752
|
let msg = null;
|
|
1751
1753
|
try {
|
|
1752
1754
|
msg = JSON.parse(text);
|
|
@@ -1755,7 +1757,7 @@ function buildIncomingHandler(adapter,getLogsEnabled) {
|
|
|
1755
1757
|
}
|
|
1756
1758
|
if (!msg || typeof msg.type != "string")return;
|
|
1757
1759
|
if (msg.type === "register-entrypoints") {
|
|
1758
|
-
|
|
1760
|
+
reply(ACK_TEXT);
|
|
1759
1761
|
return;
|
|
1760
1762
|
}
|
|
1761
1763
|
if (msg.type === "log") {
|
|
@@ -1776,10 +1778,6 @@ function buildIncomingHandler(adapter,getLogsEnabled) {
|
|
|
1776
1778
|
};
|
|
1777
1779
|
}
|
|
1778
1780
|
const ACK_TEXT = JSON.stringify({ type: "bundle-registered" });
|
|
1779
|
-
function buildAckFrame() {
|
|
1780
|
-
const payload = Buffer.from(ACK_TEXT);
|
|
1781
|
-
return Buffer.concat([Buffer.from([0x81, payload.length]), payload]);
|
|
1782
|
-
}
|
|
1783
1781
|
function createHmrBridge(options) {
|
|
1784
1782
|
const adapter = createMetroHmrAdapter(),onRebuild = buildOnRebuild(adapter, { silent: options.silent });
|
|
1785
1783
|
let logsEnabled = options.forwardClientLogs !== false;
|
|
@@ -1787,12 +1785,118 @@ function createHmrBridge(options) {
|
|
|
1787
1785
|
return { adapter, callbacks: { onRebuild }, path: options.path, acceptUpgrade(req,socket) {
|
|
1788
1786
|
adapter.channel.accept(req, socket);
|
|
1789
1787
|
adapter.sendInitialGreeting();
|
|
1788
|
+
}, acceptBun(ws) {
|
|
1789
|
+
adapter.channel.addBunClient(ws);
|
|
1790
|
+
adapter.sendInitialGreeting();
|
|
1791
|
+
}, removeBun(ws) {
|
|
1792
|
+
adapter.channel.removeBunClient(ws);
|
|
1793
|
+
}, handleBunMessage(ws,text) {
|
|
1794
|
+
adapter.channel.dispatchBunIncoming(ws, text);
|
|
1790
1795
|
}, toggleLogs() {
|
|
1791
1796
|
logsEnabled = !logsEnabled;
|
|
1792
1797
|
return logsEnabled;
|
|
1793
1798
|
} };
|
|
1794
1799
|
}
|
|
1795
1800
|
//#endregion
|
|
1801
|
+
//#region bun-http-adapter.ts
|
|
1802
|
+
function createResponseShim(done) {
|
|
1803
|
+
const captured = { statusCode: 200, headers: {}, chunks: [] };
|
|
1804
|
+
let ended = false,headersSent = false;
|
|
1805
|
+
const applyHeaders = (headers) => {
|
|
1806
|
+
if (!headers)return;
|
|
1807
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
1808
|
+
captured.headers[k.toLowerCase()] = Array.isArray(v) ? v.join(", ") : String(v);
|
|
1809
|
+
}
|
|
1810
|
+
},shim = { get statusCode() {
|
|
1811
|
+
return captured.statusCode;
|
|
1812
|
+
}, set statusCode(code) {
|
|
1813
|
+
captured.statusCode = code;
|
|
1814
|
+
}, get headersSent() {
|
|
1815
|
+
return headersSent;
|
|
1816
|
+
}, get writableEnded() {
|
|
1817
|
+
return ended;
|
|
1818
|
+
}, setHeader(name,value) {
|
|
1819
|
+
captured.headers[String(name).toLowerCase()] = Array.isArray(value) ? value.join(", ") : String(value);
|
|
1820
|
+
}, getHeader(name) {
|
|
1821
|
+
return captured.headers[String(name).toLowerCase()];
|
|
1822
|
+
}, writeHead(statusCode,headersOrReason,maybeHeaders) {
|
|
1823
|
+
captured.statusCode = statusCode;
|
|
1824
|
+
const headers = headersOrReason && typeof headersOrReason == "object" ? headersOrReason : maybeHeaders ?? undefined;
|
|
1825
|
+
applyHeaders(headers);
|
|
1826
|
+
headersSent = true;
|
|
1827
|
+
return shim;
|
|
1828
|
+
}, write(chunk) {
|
|
1829
|
+
if (chunk != null) {
|
|
1830
|
+
captured.chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
|
|
1831
|
+
}
|
|
1832
|
+
headersSent = true;
|
|
1833
|
+
return true;
|
|
1834
|
+
}, end(chunk) {
|
|
1835
|
+
if (ended)return shim;
|
|
1836
|
+
if (chunk != null) {
|
|
1837
|
+
captured.chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
|
|
1838
|
+
}
|
|
1839
|
+
ended = true;
|
|
1840
|
+
headersSent = true;
|
|
1841
|
+
done(captured);
|
|
1842
|
+
return shim;
|
|
1843
|
+
} };
|
|
1844
|
+
return { res: shim, captured };
|
|
1845
|
+
}
|
|
1846
|
+
function createRequestShim(req,rawBody) {
|
|
1847
|
+
const u = new URL(req.url),headers = {};
|
|
1848
|
+
req.headers.forEach((value, key) => {
|
|
1849
|
+
headers[key.toLowerCase()] = value;
|
|
1850
|
+
});
|
|
1851
|
+
const shim = { url: u.pathname + u.search, method: req.method, headers, complete: true, readable: false, rawBody, on() {
|
|
1852
|
+
return shim;
|
|
1853
|
+
} };
|
|
1854
|
+
return shim;
|
|
1855
|
+
}
|
|
1856
|
+
async function runMiddlewareForBun(middleware,req) {
|
|
1857
|
+
let rawBody = null;
|
|
1858
|
+
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
1859
|
+
try {
|
|
1860
|
+
rawBody = await req.text();
|
|
1861
|
+
} catch {
|
|
1862
|
+
rawBody = null;
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
const reqShim = createRequestShim(req, rawBody);
|
|
1866
|
+
return new Promise((resolve) => {
|
|
1867
|
+
let settled = false;
|
|
1868
|
+
const toResponse = (c) => {
|
|
1869
|
+
const body = c.chunks.length === 0 ? null : new Uint8Array(Buffer.concat(c.chunks));
|
|
1870
|
+
return new Response(body, { status: c.statusCode, headers: c.headers });
|
|
1871
|
+
},{ res:res } = createResponseShim((captured) => {
|
|
1872
|
+
if (settled)return;
|
|
1873
|
+
settled = true;
|
|
1874
|
+
resolve(toResponse(captured));
|
|
1875
|
+
});
|
|
1876
|
+
try {
|
|
1877
|
+
middleware(reqShim, res, (err) => {
|
|
1878
|
+
if (settled)return;
|
|
1879
|
+
settled = true;
|
|
1880
|
+
if (err) {
|
|
1881
|
+
const msg = err?.message ?? String(err);
|
|
1882
|
+
resolve(new Response(`Internal Server Error: ${msg}`, { status: 500 }));
|
|
1883
|
+
return;
|
|
1884
|
+
}
|
|
1885
|
+
if (!res.headersSent && !res.writableEnded) {
|
|
1886
|
+
resolve(new Response("Not Found", { status: 404 }));
|
|
1887
|
+
return;
|
|
1888
|
+
}
|
|
1889
|
+
resolve(new Response(null, { status: res.statusCode }));
|
|
1890
|
+
});
|
|
1891
|
+
} catch (err) {
|
|
1892
|
+
if (settled)return;
|
|
1893
|
+
settled = true;
|
|
1894
|
+
const msg = err?.message ?? String(err);
|
|
1895
|
+
resolve(new Response(`Internal Server Error: ${msg}`, { status: 500 }));
|
|
1896
|
+
}
|
|
1897
|
+
});
|
|
1898
|
+
}
|
|
1899
|
+
//#endregion
|
|
1796
1900
|
//#region http-utils.ts
|
|
1797
1901
|
function sendText(res,statusCode,text,contentType="text/plain") {
|
|
1798
1902
|
res.writeHead(statusCode, { "Content-Type": contentType, "Content-Length": Buffer.byteLength(text) });
|
|
@@ -1979,7 +2083,7 @@ function resolveAssetPath(urlPathname,opts) {
|
|
|
1979
2083
|
}
|
|
1980
2084
|
if (normalizedPath.startsWith("node_modules")) {
|
|
1981
2085
|
try {
|
|
1982
|
-
const modulePath = normalizedPath.replace(/^node_modules[/\\]/, ""),packageName = modulePath.startsWith("@") ?
|
|
2086
|
+
const modulePath = normalizedPath.replace(/^node_modules[/\\]/, ""),packageName = modulePath.startsWith("@") ? modulePath.match(/^(@[^/\\]+[/\\][^/\\]+)/)?.[1] ?? modulePath.split(sep)[0] : modulePath.split(sep)[0];
|
|
1983
2087
|
if (!packageName)return null;
|
|
1984
2088
|
const packageRelativePath = modulePath.slice(packageName.length + 1);
|
|
1985
2089
|
let packageJsonPath;
|
|
@@ -2024,7 +2128,7 @@ async function handleAssetRequest(_req,res,url,opts) {
|
|
|
2024
2128
|
const ext = extname(resolved).toLowerCase();
|
|
2025
2129
|
;
|
|
2026
2130
|
const content = await readFile(resolved);
|
|
2027
|
-
res.writeHead(200, { "Content-Type":
|
|
2131
|
+
res.writeHead(200, { "Content-Type": CONTENT_TYPE_MAP[ext] ?? "application/octet-stream", "Cache-Control": "public, max-age=31536000", "Content-Length": content.length });
|
|
2028
2132
|
res.end(content);
|
|
2029
2133
|
} catch {
|
|
2030
2134
|
sendText(res, 500, "Internal Server Error");
|
|
@@ -2276,7 +2380,7 @@ function deepMerge(base,override) {
|
|
|
2276
2380
|
return result;
|
|
2277
2381
|
}
|
|
2278
2382
|
function buildRnBundleOptions(input) {
|
|
2279
|
-
const { entry:entry, projectRoot:projectRoot, rnPlatform:rnPlatform, dev:dev, sourcemap:sourcemap, minify:minify, dropConsole:dropConsole, dropDebugger:dropDebugger, extra:extra } = input;
|
|
2383
|
+
const { entry:entry, projectRoot:projectRoot, rnPlatform:rnPlatform, dev:dev, sourcemap:sourcemap, minify:minify, watchDelay:watchDelay, dropConsole:dropConsole, dropDebugger:dropDebugger, extra:extra } = input;
|
|
2280
2384
|
if (extra?.platforms && !extra.platforms.includes(rnPlatform)) {
|
|
2281
2385
|
throw new Error(`extra.platforms (${JSON.stringify(extra.platforms)}) does not include the active rnPlatform '${rnPlatform}'`);
|
|
2282
2386
|
}
|
|
@@ -2299,7 +2403,7 @@ function buildRnBundleOptions(input) {
|
|
|
2299
2403
|
if (extra?.prelude && extra.prelude.length > 0) {
|
|
2300
2404
|
for (const p of extra.prelude)runBeforeMain.push(resolve$4(projectRoot, p));
|
|
2301
2405
|
}
|
|
2302
|
-
const define = { global: "__ZNTC_RN_GLOBAL__", __DEV__: String(dev), "process.env.NODE_ENV": `"${dev ? "development" : "production"}"`, "process.env.EXPO_ROUTER_APP_ROOT": JSON.stringify(resolve$4(projectRoot, "app")), "process.env.EXPO_ROUTER_IMPORT_MODE": "\"sync\"", "process.env.EXPO_OS": `"${rnPlatform}"` },baseLoader = buildAssetLoaders(assetExts),preset = { entryPoints: [resolve$4(projectRoot, entry)], platform: "react-native", sourcemap: sourcemap ?? dev, minify: minify ?? false, dropConsole: dropConsole ?? false, dropDebugger: dropDebugger ?? false, plugins, emitDiskSourcemap: !dev, target: "es5", flow: true, jsxInJs: true, configurableExports: true, strictExecutionOrder: true, inlineDynamicImports: true, workletTransform: true, codegenTransform: true, resolveExtensions: buildResolveExtensions(rnPlatform, sourceExts), mainFields: ["react-native", "browser", "main"], loader: baseLoader, alias: buildRnSingletonAliases(projectRoot), preserveSymlinks: true, resolveSymlinkSiblings: true, define, banner: buildPrelude(input), globalIdentifiers: [...RN_GLOBAL_IDENTIFIERS] };
|
|
2406
|
+
const define = { global: "__ZNTC_RN_GLOBAL__", __DEV__: String(dev), "process.env.NODE_ENV": `"${dev ? "development" : "production"}"`, "process.env.EXPO_ROUTER_APP_ROOT": JSON.stringify(resolve$4(projectRoot, "app")), "process.env.EXPO_ROUTER_IMPORT_MODE": "\"sync\"", "process.env.EXPO_OS": `"${rnPlatform}"` },baseLoader = buildAssetLoaders(assetExts),preset = { entryPoints: [resolve$4(projectRoot, entry)], platform: "react-native", sourcemap: sourcemap ?? dev, minify: minify ?? false, ...watchDelay !== undefined ? { watchDelay } : {}, dropConsole: dropConsole ?? false, dropDebugger: dropDebugger ?? false, plugins, emitDiskSourcemap: !dev, target: "es5", flow: true, jsxInJs: true, configurableExports: true, strictExecutionOrder: true, inlineDynamicImports: true, workletTransform: true, codegenTransform: true, preserveSafePlugins: extra?.preserveSafePlugins ?? !(extra?.additionalPlugins && extra.additionalPlugins.length > 0 || extra?.metroResolveRequest || extra?.babelTransformerPath), resolveExtensions: buildResolveExtensions(rnPlatform, sourceExts), mainFields: ["react-native", "browser", "main"], loader: baseLoader, alias: buildRnSingletonAliases(projectRoot), preserveSymlinks: true, resolveSymlinkSiblings: true, define, banner: buildPrelude(input), globalIdentifiers: [...RN_GLOBAL_IDENTIFIERS] };
|
|
2303
2407
|
if (polyfills.length > 0)preset.polyfills = polyfills;
|
|
2304
2408
|
if (runBeforeMain.length > 0)preset.runBeforeMain = runBeforeMain;
|
|
2305
2409
|
const workletVersion = resolveWorkletPluginVersion(projectRoot, input.workletPluginVersion);
|
|
@@ -2366,7 +2470,7 @@ function isVirtualSource(stripped) {
|
|
|
2366
2470
|
function isFrameworkSource(src) {
|
|
2367
2471
|
if (typeof src != "string")return false;
|
|
2368
2472
|
const stripped = stripVirtualPrefix(src);
|
|
2369
|
-
return
|
|
2473
|
+
return stripped === "__prelude__" || stripped.includes("?ctx=") || /(?:^|[/\\])node_modules[/\\]/.test(stripped) || stripped.startsWith("zntc:");
|
|
2370
2474
|
}
|
|
2371
2475
|
function postProcessSourceMap(rawJson,pathOpts) {
|
|
2372
2476
|
try {
|
|
@@ -2376,7 +2480,7 @@ function postProcessSourceMap(rawJson,pathOpts) {
|
|
|
2376
2480
|
if (pathOpts?.sourceRoot === undefined && map.sourceRoot === "") {
|
|
2377
2481
|
delete map.sourceRoot;
|
|
2378
2482
|
}
|
|
2379
|
-
const existing = new Set([...
|
|
2483
|
+
const existing = new Set([...Array.isArray(map.x_google_ignoreList) ? map.x_google_ignoreList : [], ...Array.isArray(map.ignoreList) ? map.ignoreList : []].filter((v) => Number.isInteger(v) && v >= 0));
|
|
2380
2484
|
for (let i = 0; i < map.sources.length; i++) {
|
|
2381
2485
|
if (isFrameworkSource(map.sources[i]))existing.add(i);
|
|
2382
2486
|
}
|
|
@@ -2527,7 +2631,7 @@ function createPlatformStateRegistry(options,callbacks) {
|
|
|
2527
2631
|
function resolvePlatform(url,registry,defaultPlatform) {
|
|
2528
2632
|
const param = url.searchParams.get("platform");
|
|
2529
2633
|
;
|
|
2530
|
-
return registry.getOrCreate(
|
|
2634
|
+
return registry.getOrCreate(param === "ios" || param === "android" ? param : defaultPlatform);
|
|
2531
2635
|
}
|
|
2532
2636
|
//#endregion
|
|
2533
2637
|
//#region bundle.ts
|
|
@@ -2706,7 +2810,7 @@ async function createSourceMapConsumer(sourceMapJson) {
|
|
|
2706
2810
|
return null;
|
|
2707
2811
|
}
|
|
2708
2812
|
try {
|
|
2709
|
-
const mod =
|
|
2813
|
+
const mod = await Promise.resolve().then(()=>require_source_map_source_map());
|
|
2710
2814
|
return await new mod.SourceMapConsumer(parsed);
|
|
2711
2815
|
} catch {
|
|
2712
2816
|
return null;
|
|
@@ -2914,7 +3018,53 @@ async function createDevHttpServer(options,deps) {
|
|
|
2914
3018
|
return { server, url: `http://${options.host}:${options.port}`, port: options.port, stop: () => new Promise((resolve, reject) => {
|
|
2915
3019
|
server.removeListener("request", requestHandler);
|
|
2916
3020
|
if (upgradeHandler)server.removeListener("upgrade", upgradeHandler);
|
|
2917
|
-
server.close((err) =>
|
|
3021
|
+
server.close((err) => err ? reject(err) : resolve());
|
|
3022
|
+
}) };
|
|
3023
|
+
}
|
|
3024
|
+
function createBunHttpServerShim() {
|
|
3025
|
+
let warned = false;
|
|
3026
|
+
const shim = { on(event) {
|
|
3027
|
+
if (event === "upgrade" && !warned) {
|
|
3028
|
+
warned = true;
|
|
3029
|
+
process.stderr.write(`[zntc:rn-dev] Bun runtime: enhanceMiddleware 의 httpServer.on('upgrade') 는 ` + `Bun.serve 에서 지원되지 않습니다(raw socket 미노출). HMR(/hot)은 정상 동작하나 ` + `WebSocket upgrade 에 의존하는 enhanceMiddleware 기능(Rozenite 등)은 제한됩니다.\n`);
|
|
3030
|
+
}
|
|
3031
|
+
return shim;
|
|
3032
|
+
}, once() {
|
|
3033
|
+
return shim;
|
|
3034
|
+
}, removeListener() {
|
|
3035
|
+
return shim;
|
|
3036
|
+
}, off() {
|
|
3037
|
+
return shim;
|
|
3038
|
+
}, address() {
|
|
3039
|
+
return { port: 0 };
|
|
3040
|
+
} };
|
|
3041
|
+
return shim;
|
|
3042
|
+
}
|
|
3043
|
+
async function createBunDevHttpServer(options,deps) {
|
|
3044
|
+
const Bun = globalThis.Bun;
|
|
3045
|
+
if (!Bun)throw new Error("createBunDevHttpServer는 Bun runtime에서만 호출 가능합니다.");
|
|
3046
|
+
const baseMiddleware = createBaseMiddleware(options, deps),enhanced = options.enhanceMiddleware ? options.enhanceMiddleware(baseMiddleware, { httpServer: createBunHttpServerShim() }) : baseMiddleware,hmr = deps.hmrBridge,serveOpts = { port: options.port, hostname: options.host, async fetch(req,server) {
|
|
3047
|
+
const url = new URL(req.url);
|
|
3048
|
+
if (hmr && (url.pathname === hmr.path || url.pathname.startsWith(`${hmr.path}?`))) {
|
|
3049
|
+
if (server.upgrade(req))return undefined;
|
|
3050
|
+
return new Response("Upgrade required", { status: 426 });
|
|
3051
|
+
}
|
|
3052
|
+
return runMiddlewareForBun(enhanced, req);
|
|
3053
|
+
} };
|
|
3054
|
+
if (hmr) {
|
|
3055
|
+
serveOpts.websocket = { open(ws) {
|
|
3056
|
+
hmr.acceptBun(ws);
|
|
3057
|
+
}, message(ws,message) {
|
|
3058
|
+
const text = typeof message == "string" ? message : message.toString("utf-8");
|
|
3059
|
+
hmr.handleBunMessage(ws, text);
|
|
3060
|
+
}, close(ws) {
|
|
3061
|
+
hmr.removeBun(ws);
|
|
3062
|
+
} };
|
|
3063
|
+
}
|
|
3064
|
+
const server = Bun.serve(serveOpts);
|
|
3065
|
+
return { server: server, url: `http://${options.host}:${server.port}`, port: server.port, stop: () => new Promise((resolve) => {
|
|
3066
|
+
server.stop(true);
|
|
3067
|
+
resolve();
|
|
2918
3068
|
}) };
|
|
2919
3069
|
}
|
|
2920
3070
|
//#endregion
|
|
@@ -2937,7 +3087,7 @@ function resolveCliServerApiPath(projectRoot) {
|
|
|
2937
3087
|
}
|
|
2938
3088
|
async function loadCliServerApi(options) {
|
|
2939
3089
|
try {
|
|
2940
|
-
const resolvedPath = resolveCliServerApiPath(options.projectRoot),mod =
|
|
3090
|
+
const resolvedPath = resolveCliServerApiPath(options.projectRoot),mod = await import(resolvedPath),result = mod.createDevServerMiddleware({ port: options.port, host: options.host, watchFolders: [] });
|
|
2941
3091
|
return { websocketEndpoints: result.websocketEndpoints, broadcast: result.messageSocketEndpoint.broadcast };
|
|
2942
3092
|
} catch (err) {
|
|
2943
3093
|
if (process.env.ZNTC_DEBUG_TERMINAL === "1") {
|
|
@@ -3130,7 +3280,9 @@ async function serveRn(options,extras={}) {
|
|
|
3130
3280
|
process.stderr.write(`[zntc:rn-dev:debug] cli-server-api: ${cliServerApi ? "loaded" : "null (peer 미설치 또는 load 실패)"}\n`);
|
|
3131
3281
|
process.stderr.write(`[zntc:rn-dev:debug] dev-middleware: ${devMiddleware ? "loaded" : "null (peer 미설치)"}\n`);
|
|
3132
3282
|
}
|
|
3133
|
-
const hmrBridge = options.hmr ? createHmrBridge({ path: HMR_PATH, silent: extras.silent, forwardClientLogs: options.bundle.extra?.forwardClientLogs }) : undefined,platforms = createPlatformStateRegistry(options, hmrBridge?.callbacks),
|
|
3283
|
+
const hmrBridge = options.hmr ? createHmrBridge({ path: HMR_PATH, silent: extras.silent, forwardClientLogs: options.bundle.extra?.forwardClientLogs }) : undefined,platforms = createPlatformStateRegistry(options, hmrBridge?.callbacks),isBun = typeof globalThis.Bun < "u";
|
|
3284
|
+
;
|
|
3285
|
+
const httpHandle = await (isBun ? createBunDevHttpServer : createDevHttpServer)(options, { broadcast, platforms, hmrBridge, devMiddleware: devMiddleware ?? undefined, cliServerApi: cliServerApi ?? undefined }),buildStart = Date.now(),firstState = platforms.getOrCreate(options.bundle.rnPlatform);
|
|
3134
3286
|
await waitForBuild(firstState);
|
|
3135
3287
|
if (!extras.silent) {
|
|
3136
3288
|
if (firstState.buildError) {
|
|
@@ -3238,7 +3390,7 @@ function parserPluginsFor(filename) {
|
|
|
3238
3390
|
}
|
|
3239
3391
|
function isRootImportPluginName(name) {
|
|
3240
3392
|
const normalized = name.replace(/\\/g, "/");
|
|
3241
|
-
return
|
|
3393
|
+
return normalized === "root-import" || normalized === "babel-plugin-root-import" || normalized.endsWith("/babel-plugin-root-import") || normalized.includes("/babel-plugin-root-import/");
|
|
3242
3394
|
}
|
|
3243
3395
|
function injectRootImportRootOption(options,projectRoot) {
|
|
3244
3396
|
const next = options ? { ...options } : {},paths = next.paths;
|
|
@@ -3463,9 +3615,9 @@ function withExpo(config) {
|
|
|
3463
3615
|
if (winter)expoModules.push(winter);
|
|
3464
3616
|
if (metroRuntime)expoModules.push(metroRuntime);
|
|
3465
3617
|
const existingAssetExts = config.resolver?.assetExts ?? [],existingNormalized = new Set(existingAssetExts.map(normalizeExt));
|
|
3466
|
-
return { ...config, resolver: { ...config.resolver, assetExts: [...existingAssetExts, ...EXPO_ASSET_EXTS.filter((ext) => !existingNormalized.has(ext))], blockList: [...
|
|
3618
|
+
return { ...config, resolver: { ...config.resolver, assetExts: [...existingAssetExts, ...EXPO_ASSET_EXTS.filter((ext) => !existingNormalized.has(ext))], blockList: [...config.resolver?.blockList ?? [], ...EXPO_BLOCK_LIST] }, serializer: { ...config.serializer, prelude: [...config.serializer?.prelude ?? [], ...expoModules] }, server: { ...config.server, silentConsoleErrorPatterns: [...config.server?.silentConsoleErrorPatterns ?? [], WINTER_POLYFILL_WARNING_PATTERN] } };
|
|
3467
3619
|
}
|
|
3468
3620
|
//#endregion
|
|
3469
3621
|
//#region index.ts
|
|
3470
|
-
export { HMR_RN_MSG, buildRnDevServerOptions, createBaseMiddleware, createDevHttpServer, createHmrBridge, createPlatformState, loadCliServerApi, loadDevMiddleware, createPlatformStateRegistry, getCachedSourceMap, applyCustomizeFrame, createSourceMapConsumer, extractCodeFrame, handleAssetRequest, handleBundleRequest, handleHmrMapRequest, handleIndexPage, handleMapRequest, handleSymbolicateRequest, isIndexRoute, isAssetRoute, isBundleRoute, isHmrMapRoute, isMapRoute, isSymbolicateRoute, normalizeFrame, symbolicateFrame, colors, formatLogBadge, logBundle, logError, logInfo, logWarn, postProcessSourceMap, printZntcRnBanner, resolveAssetPath, serveRn, setupTerminalActions, waitForBuild, createMetroHmrAdapter, createAssetPlugin, createBabelPlugin, createBabelTransformer, detectCustomPlugins, isZntcNativePlugin, ZNTC_NATIVE_PLUGIN_PATTERNS, CODEGEN_NATIVE_COMPONENT_MARKER, createCodegenPlugin, createCodegenTransformer, escapeRegex, createMetroResolveRequestPlugin, createRequireContextPlugin, createStyledComponentsNativePlugin, disableStyledComponentsNativeDomProbe, STYLED_COMPONENTS_NATIVE_PATH_RE, buildRnBundleOptions, bundleRn, DEFAULT_ASSET_EXTS, watchRn, resolveRnPolyfills, RN_GLOBAL_IDENTIFIERS, tryResolve, HMR_CLIENT_SUFFIX, ZNTC_HMR_CLIENT_CODE, detectExpo, WINTER_POLYFILL_WARNING_PATTERN, withExpo };
|
|
3622
|
+
export { HMR_RN_MSG, buildRnDevServerOptions, createBaseMiddleware, createBunDevHttpServer, createDevHttpServer, createHmrBridge, createPlatformState, loadCliServerApi, loadDevMiddleware, createPlatformStateRegistry, getCachedSourceMap, applyCustomizeFrame, createSourceMapConsumer, extractCodeFrame, handleAssetRequest, handleBundleRequest, handleHmrMapRequest, handleIndexPage, handleMapRequest, handleSymbolicateRequest, isIndexRoute, isAssetRoute, isBundleRoute, isHmrMapRoute, isMapRoute, isSymbolicateRoute, normalizeFrame, symbolicateFrame, colors, formatLogBadge, logBundle, logError, logInfo, logWarn, postProcessSourceMap, printZntcRnBanner, resolveAssetPath, serveRn, setupTerminalActions, waitForBuild, createMetroHmrAdapter, createAssetPlugin, createBabelPlugin, createBabelTransformer, detectCustomPlugins, isZntcNativePlugin, ZNTC_NATIVE_PLUGIN_PATTERNS, CODEGEN_NATIVE_COMPONENT_MARKER, createCodegenPlugin, createCodegenTransformer, escapeRegex, createMetroResolveRequestPlugin, createRequireContextPlugin, createStyledComponentsNativePlugin, disableStyledComponentsNativeDomProbe, STYLED_COMPONENTS_NATIVE_PATH_RE, buildRnBundleOptions, bundleRn, DEFAULT_ASSET_EXTS, watchRn, resolveRnPolyfills, RN_GLOBAL_IDENTIFIERS, tryResolve, HMR_CLIENT_SUFFIX, ZNTC_HMR_CLIENT_CODE, detectExpo, WINTER_POLYFILL_WARNING_PATTERN, withExpo };
|
|
3471
3623
|
//#endregion
|
package/dist/preset.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export interface RnBundleInput {
|
|
|
12
12
|
dev: boolean;
|
|
13
13
|
/** sourcemap emit. dev 시 inline 권장. */
|
|
14
14
|
sourcemap?: boolean;
|
|
15
|
+
/** watch 디바운스(ms) — dev server watch 의 첫 이벤트 후 idle 병합 윈도우. 기본 16(native). */
|
|
16
|
+
watchDelay?: number;
|
|
15
17
|
/** prod build 의 minify. */
|
|
16
18
|
minify?: boolean;
|
|
17
19
|
/** console.* 호출 제거. Metro production Babel plugin 과 같은 정책을 원하는 release 경로에서 사용. */
|
|
@@ -49,6 +51,15 @@ export interface RnBundleInput {
|
|
|
49
51
|
metroResolveRequest?: CustomResolver;
|
|
50
52
|
/** Metro 호환 babel transformer path (svg-transformer 등). */
|
|
51
53
|
babelTransformerPath?: string;
|
|
54
|
+
/**
|
|
55
|
+
* HMR 위상 보존 plugin 게이트 명시 override. 미지정(undefined)이면 preset 이 보수적으로
|
|
56
|
+
* 판정한다 — 내장 plugin 만이면 true, additionalPlugins/metroResolveRequest/
|
|
57
|
+
* babelTransformerPath 중 하나라도 있으면 false. 사용자가 "내 resolver/transformer 가
|
|
58
|
+
* 결정적·모듈별 순수(같은 입력→같은 출력, 전역 상태 무의존)"임을 보장할 수 있으면 true 로
|
|
59
|
+
* 명시해 보존을 강제(=HMR rebuild 가속)할 수 있다. 비결정이면 stale 번들 위험은 사용자 책임.
|
|
60
|
+
* false 명시로 강제 비활성도 가능.
|
|
61
|
+
*/
|
|
62
|
+
preserveSafePlugins?: boolean;
|
|
52
63
|
/** RN sourceExts override (default RN preset). */
|
|
53
64
|
sourceExts?: string[];
|
|
54
65
|
/** RN assetExts override (default RN preset). */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zntc/react-native",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "ZNTC React Native platform — Metro HMR adapter + RN preset (buildRnBundleOptions) + plugin factories + RN runtime",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bundler",
|
|
@@ -48,13 +48,13 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@react-native-community/cli-server-api": "^15.0.0",
|
|
51
|
-
"@zntc/core": "0.1.
|
|
51
|
+
"@zntc/core": "0.1.2",
|
|
52
52
|
"jsc-safe-url": "^0.2.4",
|
|
53
53
|
"source-map": "^0.7.4"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/node": "^25.5.2",
|
|
57
|
-
"@zntc/server": "0.1.
|
|
57
|
+
"@zntc/server": "0.1.2"
|
|
58
58
|
},
|
|
59
59
|
"optionalDependencies": {
|
|
60
60
|
"@babel/core": "^7.26.0",
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
var
|
|
8
|
+
// JSI 는 색상을 uint32 로 기대 — 음수(-1)는 HostFunction throw 위험. unsigned hex 사용.
|
|
9
|
+
var REFRESH_TEXT_COLOR = 0xffffffff; // #ffffff
|
|
10
|
+
var REFRESH_BACKGROUND_COLOR = 0xff2584e8; // #2584e8
|
|
10
11
|
var BUFFER_LIMIT = 1024 * 1024;
|
|
11
12
|
var prettyFormat = require('pretty-format');
|
|
12
13
|
var prettyFormatImpl = prettyFormat && (prettyFormat.default || prettyFormat);
|
|
@@ -68,13 +69,10 @@ function getDirectNativeDevLoadingView() {
|
|
|
68
69
|
|
|
69
70
|
function wrapNativeDevLoadingView(nativeDevLoadingView) {
|
|
70
71
|
return {
|
|
71
|
-
showMessage: function (message, _type,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
REFRESH_BACKGROUND_COLOR,
|
|
76
|
-
!!(options && options.dismissButton),
|
|
77
|
-
);
|
|
72
|
+
showMessage: function (message, _type, _options) {
|
|
73
|
+
// native DevLoadingView.showMessage 시그니처는 (message, color, backgroundColor) 3개.
|
|
74
|
+
// 4번째 인자를 넘기면 JSI HostFunction 이 arg-count mismatch 로 throw → 배너 미표시.
|
|
75
|
+
nativeDevLoadingView.showMessage(message, REFRESH_TEXT_COLOR, REFRESH_BACKGROUND_COLOR);
|
|
78
76
|
},
|
|
79
77
|
hide: function () {
|
|
80
78
|
nativeDevLoadingView.hide();
|
|
@@ -136,11 +134,25 @@ var HMRClient = {
|
|
|
136
134
|
},
|
|
137
135
|
|
|
138
136
|
_showRefreshing: function () {
|
|
137
|
+
this._showTime = Date.now();
|
|
139
138
|
this._safeCallDlv('showMessage', ['Refreshing...', 'refresh']);
|
|
140
139
|
},
|
|
141
140
|
|
|
141
|
+
// ZNTC 의 HMR apply 는 동기라 update-start→update-done 이 거의 즉시 일어난다.
|
|
142
|
+
// 그대로 hide 하면 'Refreshing...' 배너가 한 프레임도 못 그려지고 사라진다.
|
|
143
|
+
// 최소 표시 시간(MIN_SHOW_MS)을 보장해 Metro 와 체감을 맞춘다. 그 사이 새 update 가
|
|
144
|
+
// 시작되면(_pendingUpdates>0) hide 를 건너뛰어 배너를 유지한다.
|
|
142
145
|
_hideRefreshing: function () {
|
|
143
|
-
this
|
|
146
|
+
var self = this;
|
|
147
|
+
var MIN_SHOW_MS = 300;
|
|
148
|
+
var elapsed = Date.now() - (self._showTime || 0);
|
|
149
|
+
if (elapsed >= MIN_SHOW_MS) {
|
|
150
|
+
self._safeCallDlv('hide', []);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
setTimeout(function () {
|
|
154
|
+
if (self._pendingUpdates === 0) self._safeCallDlv('hide', []);
|
|
155
|
+
}, MIN_SHOW_MS - elapsed);
|
|
144
156
|
},
|
|
145
157
|
|
|
146
158
|
enable: function () {
|