isthmus-cli 0.6.0 → 0.7.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.
- package/README.ko.md +135 -31
- package/README.md +134 -16
- package/Skills/isthmus/SKILL.md +17 -7
- package/compatibility.json +10 -0
- package/dist/cli/check-command.d.ts +2 -2
- package/dist/cli/check-command.js +22 -9
- package/dist/cli/check-command.js.map +1 -1
- package/dist/cli/command-support.d.ts +19 -1
- package/dist/cli/command-support.js +37 -8
- package/dist/cli/command-support.js.map +1 -1
- package/dist/cli/diff-command.js +4 -3
- package/dist/cli/diff-command.js.map +1 -1
- package/dist/cli/doctor-command.d.ts +11 -0
- package/dist/cli/doctor-command.js +128 -0
- package/dist/cli/doctor-command.js.map +1 -0
- package/dist/cli/extract-js-command.d.ts +33 -0
- package/dist/cli/extract-js-command.js +233 -0
- package/dist/cli/extract-js-command.js.map +1 -0
- package/dist/cli/graph-command.js +13 -6
- package/dist/cli/graph-command.js.map +1 -1
- package/dist/cli/init-command.d.ts +11 -0
- package/dist/cli/init-command.js +115 -0
- package/dist/cli/init-command.js.map +1 -0
- package/dist/cli/main.js +52 -1
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/mcp-server.d.ts +16 -0
- package/dist/cli/mcp-server.js +534 -0
- package/dist/cli/mcp-server.js.map +1 -0
- package/dist/cli/query-command.js +13 -6
- package/dist/cli/query-command.js.map +1 -1
- package/dist/cli/retentions-command.js +14 -7
- package/dist/cli/retentions-command.js.map +1 -1
- package/dist/cli/serve-command.d.ts +13 -0
- package/dist/cli/serve-command.js +43 -0
- package/dist/cli/serve-command.js.map +1 -0
- package/dist/exchange/capture-config.d.ts +18 -0
- package/dist/exchange/capture-config.js +100 -0
- package/dist/exchange/capture-config.js.map +1 -0
- package/dist/exchange/messages.d.ts +9 -24
- package/dist/exchange/messages.js +25 -55
- package/dist/exchange/messages.js.map +1 -1
- package/dist/exchange/parse.d.ts +61 -0
- package/dist/exchange/parse.js +115 -12
- package/dist/exchange/parse.js.map +1 -1
- package/dist/extract/js-document.d.ts +22 -0
- package/dist/extract/js-document.js +230 -0
- package/dist/extract/js-document.js.map +1 -0
- package/dist/extract/js-scan.d.ts +93 -0
- package/dist/extract/js-scan.js +1205 -0
- package/dist/extract/js-scan.js.map +1 -0
- package/dist/extract/lexer.d.ts +26 -0
- package/dist/extract/lexer.js +316 -0
- package/dist/extract/lexer.js.map +1 -0
- package/dist/join/join.d.ts +66 -1
- package/dist/join/join.js +171 -1
- package/dist/join/join.js.map +1 -1
- package/dist/join/messages.d.ts +7 -4
- package/dist/join/messages.js +15 -8
- package/dist/join/messages.js.map +1 -1
- package/dist/report/check-report.d.ts +20 -3
- package/dist/report/check-report.js +240 -8
- package/dist/report/check-report.js.map +1 -1
- package/dist/report/codequality.d.ts +45 -0
- package/dist/report/codequality.js +74 -0
- package/dist/report/codequality.js.map +1 -0
- package/dist/report/diff.d.ts +25 -3
- package/dist/report/diff.js +91 -11
- package/dist/report/diff.js.map +1 -1
- package/dist/report/graph.d.ts +10 -4
- package/dist/report/graph.js +60 -6
- package/dist/report/graph.js.map +1 -1
- package/dist/report/preflight-view.js +28 -1
- package/dist/report/preflight-view.js.map +1 -1
- package/dist/report/preflight.d.ts +4 -4
- package/dist/report/preflight.js +81 -46
- package/dist/report/preflight.js.map +1 -1
- package/dist/report/query.d.ts +11 -4
- package/dist/report/query.js +84 -17
- package/dist/report/query.js.map +1 -1
- package/dist/report/retentions.d.ts +17 -5
- package/dist/report/retentions.js +85 -8
- package/dist/report/retentions.js.map +1 -1
- package/dist/report/rules.d.ts +16 -0
- package/dist/report/rules.js +30 -0
- package/dist/report/rules.js.map +1 -0
- package/dist/report/sarif.d.ts +2 -8
- package/dist/report/sarif.js +2 -10
- package/dist/report/sarif.js.map +1 -1
- package/docs/BRIDGE-EVENTS.md +87 -0
- package/docs/BRIDGE-MESSAGES.md +23 -8
- package/docs/GRAPH-EXCHANGE.md +141 -14
- package/docs/IMPACT.md +1 -1
- package/docs/MCP.md +62 -0
- package/docs/PREFLIGHT.md +24 -8
- package/docs/RUNTIME.md +2 -2
- package/docs/TOOLCHAIN.md +5 -5
- package/package.json +5 -2
- package/scripts/capture-preflight.mjs +32 -44
- package/scripts/run-child.mjs +1 -0
package/dist/join/join.d.ts
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
|
-
import type { BridgeFactsDocument, BridgeLocation, BridgePlatform, BridgeSymbol, BridgeSourceLanguage, BridgeTarget } from '../exchange/parse.ts';
|
|
1
|
+
import type { BridgeFactsDocument, BridgeHandlerDependency, BridgeHandlerScope, BridgeLocation, BridgeMechanism, BridgePlatform, BridgeSymbol, BridgeSourceLanguage, BridgeTarget } from '../exchange/parse.ts';
|
|
2
2
|
/** 한 언어 문서가 제공한 브리지 증거 위치다. */
|
|
3
3
|
export interface BridgeEndpoint {
|
|
4
4
|
readonly platform: BridgePlatform;
|
|
5
5
|
readonly location: BridgeLocation;
|
|
6
6
|
readonly symbol?: BridgeSymbol;
|
|
7
7
|
readonly sourceLanguage?: BridgeSourceLanguage;
|
|
8
|
+
/**
|
|
9
|
+
* 이름 경계 증거가 속한 해석 경로다. `react-native` 사실만 가질 수 있고
|
|
10
|
+
* 생략은 `core`다. mechanism이 다른 호출·수신 쌍의 불일치 판정 근거다.
|
|
11
|
+
*/
|
|
12
|
+
readonly mechanism?: BridgeMechanism;
|
|
13
|
+
/**
|
|
14
|
+
* 호출 API가 모듈 부재를 허용한다는 호출 측 증거다.
|
|
15
|
+
* `module-import`에만 온다 — 부재 시 크래시가 아니라 `null` 반환이다.
|
|
16
|
+
*/
|
|
17
|
+
readonly optional?: boolean;
|
|
18
|
+
/** method-handle 분기 근거다. v2 handler 사실과 같은 형태를 공유한다. */
|
|
19
|
+
readonly handlerScope?: BridgeHandlerScope;
|
|
20
|
+
readonly dependencies?: readonly BridgeHandlerDependency[];
|
|
8
21
|
}
|
|
9
22
|
/** 논리 채널 하나에 모인 양쪽 생성·등록 증거다. */
|
|
10
23
|
export interface MatchedChannel {
|
|
@@ -47,6 +60,44 @@ export interface HandlerWithoutInvocation {
|
|
|
47
60
|
readonly method: string;
|
|
48
61
|
readonly handlers: readonly BridgeEndpoint[];
|
|
49
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* 논리 모듈·컴포넌트 이름 하나에 모인 호출 측·수신 측 증거다.
|
|
65
|
+
*
|
|
66
|
+
* 호출 측은 `module-import`·`component-require`, 수신 측은 `module-export`·
|
|
67
|
+
* `component-export` 사실이다. `channel` 필드에는 RN 모듈·컴포넌트 이름이 든다.
|
|
68
|
+
*/
|
|
69
|
+
export interface MatchedBoundaryName {
|
|
70
|
+
readonly target: BridgeTarget;
|
|
71
|
+
readonly channel: string;
|
|
72
|
+
readonly callers: readonly BridgeEndpoint[];
|
|
73
|
+
readonly receivers: readonly BridgeEndpoint[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 수신 측 export를 찾지 못한 논리 이름과 모든 호출 측 증거다.
|
|
77
|
+
*
|
|
78
|
+
* `incompatibleReceivers`는 같은 이름으로 관찰됐지만 mechanism이 달라
|
|
79
|
+
* 이 호출들에게 도달할 수 없는 수신 측 증거다. 이름이 아예 없는 경우와
|
|
80
|
+
* 구분해 보고 층이 불일치 경고로 내린다.
|
|
81
|
+
*/
|
|
82
|
+
export interface UnexportedBoundaryName {
|
|
83
|
+
readonly target: BridgeTarget;
|
|
84
|
+
readonly channel: string;
|
|
85
|
+
readonly callers: readonly BridgeEndpoint[];
|
|
86
|
+
readonly incompatibleReceivers?: readonly BridgeEndpoint[];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 호출 측 import·require를 찾지 못한 논리 이름과 모든 수신 측 증거다.
|
|
90
|
+
*
|
|
91
|
+
* `incompatibleCallers`는 같은 이름으로 관찰됐지만 mechanism이 달라
|
|
92
|
+
* 이 수신들에게 도달할 수 없는 호출 측 증거다. 호출이 아예 없는 경우와
|
|
93
|
+
* 구분해 보고 층이 불일치 경고로 내린다.
|
|
94
|
+
*/
|
|
95
|
+
export interface UnrequiredBoundaryName {
|
|
96
|
+
readonly target: BridgeTarget;
|
|
97
|
+
readonly channel: string;
|
|
98
|
+
readonly receivers: readonly BridgeEndpoint[];
|
|
99
|
+
readonly incompatibleCallers?: readonly BridgeEndpoint[];
|
|
100
|
+
}
|
|
50
101
|
/**
|
|
51
102
|
* 생산 문서가 밝힌 분석 한계와 출처다.
|
|
52
103
|
*
|
|
@@ -75,6 +126,12 @@ export interface BridgeJoinResult {
|
|
|
75
126
|
readonly matchedMethods: readonly MatchedMethod[];
|
|
76
127
|
readonly unhandledInvocations: readonly UnhandledInvocation[];
|
|
77
128
|
readonly handlersWithoutInvocations: readonly HandlerWithoutInvocation[];
|
|
129
|
+
readonly matchedModules: readonly MatchedBoundaryName[];
|
|
130
|
+
readonly moduleImportsWithoutExports: readonly UnexportedBoundaryName[];
|
|
131
|
+
readonly moduleExportsWithoutImports: readonly UnrequiredBoundaryName[];
|
|
132
|
+
readonly matchedComponents: readonly MatchedBoundaryName[];
|
|
133
|
+
readonly componentRequiresWithoutExports: readonly UnexportedBoundaryName[];
|
|
134
|
+
readonly componentExportsWithoutRequires: readonly UnrequiredBoundaryName[];
|
|
78
135
|
readonly limitations: readonly JoinLimitation[];
|
|
79
136
|
}
|
|
80
137
|
/** 한 번의 조인에서 허용하는 최대 생산 문서 수다. */
|
|
@@ -88,3 +145,11 @@ export declare class BridgeJoinValidationError extends Error {
|
|
|
88
145
|
export declare function joinBridgeDocuments(documents: readonly BridgeFactsDocument[]): BridgeJoinResult;
|
|
89
146
|
/** 입력 한계 때문에 조인 전체가 보류된 결과인지 확인한다. */
|
|
90
147
|
export declare function isBridgeJoinDeferred(joined: BridgeJoinResult): boolean;
|
|
148
|
+
/**
|
|
149
|
+
* v1 사실이 없는 입력에서 v2 전용 보고를 만들 때 쓰는 빈 결과다.
|
|
150
|
+
*
|
|
151
|
+
* 조인을 보류하지 않는다 — 사실이 아예 없었을 뿐이므로 보류와 구분한다.
|
|
152
|
+
*/
|
|
153
|
+
export declare function emptyBridgeJoinResult(): BridgeJoinResult;
|
|
154
|
+
/** limitation을 플랫폼·target·도구·문장 순으로 고정한다. */
|
|
155
|
+
export declare function compareLimitations(left: JoinLimitation, right: JoinLimitation): number;
|
package/dist/join/join.js
CHANGED
|
@@ -60,6 +60,10 @@ export function joinBridgeDocuments(documents) {
|
|
|
60
60
|
handlers,
|
|
61
61
|
}))
|
|
62
62
|
.sort(compareMethodKeys);
|
|
63
|
+
const moduleGroups = collectNameGroups(documents, 'module-import', 'module-export');
|
|
64
|
+
const componentGroups = collectNameGroups(documents, 'component-require', 'component-export');
|
|
65
|
+
const moduleNames = classifyNameGroups(moduleGroups, 'module-import');
|
|
66
|
+
const componentNames = classifyNameGroups(componentGroups, 'component-require');
|
|
63
67
|
return {
|
|
64
68
|
deferred: false,
|
|
65
69
|
observedFacts,
|
|
@@ -69,6 +73,12 @@ export function joinBridgeDocuments(documents) {
|
|
|
69
73
|
matchedMethods,
|
|
70
74
|
unhandledInvocations,
|
|
71
75
|
handlersWithoutInvocations,
|
|
76
|
+
matchedModules: moduleNames.matched,
|
|
77
|
+
moduleImportsWithoutExports: moduleNames.unexported,
|
|
78
|
+
moduleExportsWithoutImports: moduleNames.unrequired,
|
|
79
|
+
matchedComponents: componentNames.matched,
|
|
80
|
+
componentRequiresWithoutExports: componentNames.unexported,
|
|
81
|
+
componentExportsWithoutRequires: componentNames.unrequired,
|
|
72
82
|
limitations,
|
|
73
83
|
};
|
|
74
84
|
}
|
|
@@ -110,6 +120,30 @@ const mixedTargetToken = /(?<![\w-])mixed-targets(?![\w-])/i;
|
|
|
110
120
|
function limitationTarget(document) {
|
|
111
121
|
return hasMixedTargets(document) ? null : document.target;
|
|
112
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* v1 사실이 없는 입력에서 v2 전용 보고를 만들 때 쓰는 빈 결과다.
|
|
125
|
+
*
|
|
126
|
+
* 조인을 보류하지 않는다 — 사실이 아예 없었을 뿐이므로 보류와 구분한다.
|
|
127
|
+
*/
|
|
128
|
+
export function emptyBridgeJoinResult() {
|
|
129
|
+
return {
|
|
130
|
+
deferred: false,
|
|
131
|
+
observedFacts: 0,
|
|
132
|
+
matchedChannels: [],
|
|
133
|
+
unregisteredChannelCreations: [],
|
|
134
|
+
registrationsWithoutCreations: [],
|
|
135
|
+
matchedMethods: [],
|
|
136
|
+
unhandledInvocations: [],
|
|
137
|
+
handlersWithoutInvocations: [],
|
|
138
|
+
matchedModules: [],
|
|
139
|
+
moduleImportsWithoutExports: [],
|
|
140
|
+
moduleExportsWithoutImports: [],
|
|
141
|
+
matchedComponents: [],
|
|
142
|
+
componentRequiresWithoutExports: [],
|
|
143
|
+
componentExportsWithoutRequires: [],
|
|
144
|
+
limitations: [],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
113
147
|
/** 안전하게 조인을 보류하면서 입력 한계만 전달한다. 관찰량은 보존한다. */
|
|
114
148
|
function emptyJoinResult(limitations, observedFacts) {
|
|
115
149
|
return {
|
|
@@ -121,6 +155,12 @@ function emptyJoinResult(limitations, observedFacts) {
|
|
|
121
155
|
matchedMethods: [],
|
|
122
156
|
unhandledInvocations: [],
|
|
123
157
|
handlersWithoutInvocations: [],
|
|
158
|
+
matchedModules: [],
|
|
159
|
+
moduleImportsWithoutExports: [],
|
|
160
|
+
moduleExportsWithoutImports: [],
|
|
161
|
+
matchedComponents: [],
|
|
162
|
+
componentRequiresWithoutExports: [],
|
|
163
|
+
componentExportsWithoutRequires: [],
|
|
124
164
|
limitations,
|
|
125
165
|
};
|
|
126
166
|
}
|
|
@@ -158,6 +198,8 @@ function unjoinedFactLimitations(documents) {
|
|
|
158
198
|
...unjoinedLimitations(documents, isUnjoinedDynamicChannel, 'unjoined-dynamic-channels', 'channel facts with a non-literal name'),
|
|
159
199
|
...unjoinedLimitations(documents, isUnjoinedDynamicMethod, 'unjoined-dynamic-methods', 'method facts with a non-literal name'),
|
|
160
200
|
...unjoinedLimitations(documents, isUnattributedHandler, 'unjoined-unattributed-handlers', 'method handler facts without a channel'),
|
|
201
|
+
...unjoinedLimitations(documents, isUnjoinedDynamicImport, 'unjoined-dynamic-imports', 'module import or component require facts with a non-literal name'),
|
|
202
|
+
...unjoinedLimitations(documents, isUnjoinedDynamicExport, 'unjoined-dynamic-exports', 'module or component export facts with a non-literal name'),
|
|
161
203
|
];
|
|
162
204
|
}
|
|
163
205
|
/** 조건에 맞는 사실 수를 플랫폼·target별로 세어 한계 문장으로 바꾼다. */
|
|
@@ -239,6 +281,16 @@ function isUnjoinedDynamicMethod(fact) {
|
|
|
239
281
|
function isUnattributedHandler(fact) {
|
|
240
282
|
return fact.kind === 'method-handle' && fact.channel === null && !fact.dynamic;
|
|
241
283
|
}
|
|
284
|
+
/** 이름이 리터럴이 아니어서 조인하지 못한 모듈 import·컴포넌트 require 사실인지 확인한다. */
|
|
285
|
+
function isUnjoinedDynamicImport(fact) {
|
|
286
|
+
return (fact.dynamic &&
|
|
287
|
+
(fact.kind === 'module-import' || fact.kind === 'component-require'));
|
|
288
|
+
}
|
|
289
|
+
/** 이름이 리터럴이 아니어서 조인하지 못한 모듈·컴포넌트 export 사실인지 확인한다. */
|
|
290
|
+
function isUnjoinedDynamicExport(fact) {
|
|
291
|
+
return (fact.dynamic &&
|
|
292
|
+
(fact.kind === 'module-export' || fact.kind === 'component-export'));
|
|
293
|
+
}
|
|
242
294
|
/** 생성 시각 차이가 하루를 넘을 때 교차 입력 한계를 만든다. */
|
|
243
295
|
function freshnessLimitation(documents) {
|
|
244
296
|
if (documents.length < 2)
|
|
@@ -263,7 +315,7 @@ function freshnessLimitation(documents) {
|
|
|
263
315
|
};
|
|
264
316
|
}
|
|
265
317
|
/** limitation을 플랫폼·target·도구·문장 순으로 고정한다. */
|
|
266
|
-
function compareLimitations(left, right) {
|
|
318
|
+
export function compareLimitations(left, right) {
|
|
267
319
|
return (compareStrings(left.platform, right.platform) ||
|
|
268
320
|
compareTargets(left.target, right.target) ||
|
|
269
321
|
compareStrings(left.tool, right.tool) ||
|
|
@@ -396,12 +448,130 @@ function isStaticChannelFact(fact) {
|
|
|
396
448
|
function createChannelGroup(target, channel) {
|
|
397
449
|
return { target, channel, creations: [], registrations: [] };
|
|
398
450
|
}
|
|
451
|
+
/**
|
|
452
|
+
* 모듈·컴포넌트 이름 키별로 호출 측·수신 측 증거를 모은다.
|
|
453
|
+
*
|
|
454
|
+
* RN의 `module-import`↔`module-export`와 `component-require`↔`component-export`는
|
|
455
|
+
* 같은 (target, channel=모듈·컴포넌트 이름) 조인 규칙을 공유하므로 수집기를
|
|
456
|
+
* 재사용한다. dynamic 사실은 조인하지 않고 소비자 계수 한계로 넘긴다.
|
|
457
|
+
*/
|
|
458
|
+
function collectNameGroups(documents, callerKind, receiverKind) {
|
|
459
|
+
const groups = new Map();
|
|
460
|
+
for (const document of documents) {
|
|
461
|
+
if (document.target === null)
|
|
462
|
+
continue;
|
|
463
|
+
for (const fact of document.facts) {
|
|
464
|
+
if (fact.dynamic || fact.channel === null)
|
|
465
|
+
continue;
|
|
466
|
+
if (fact.kind !== callerKind && fact.kind !== receiverKind)
|
|
467
|
+
continue;
|
|
468
|
+
const key = `${document.target}\u0000${fact.channel}`;
|
|
469
|
+
const group = groups.get(key) ?? {
|
|
470
|
+
target: document.target,
|
|
471
|
+
channel: fact.channel,
|
|
472
|
+
callers: [],
|
|
473
|
+
receivers: [],
|
|
474
|
+
};
|
|
475
|
+
const endpoints = fact.kind === callerKind ? group.callers : group.receivers;
|
|
476
|
+
endpoints.push(toEndpoint(document.platform, fact));
|
|
477
|
+
groups.set(key, group);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
for (const group of groups.values()) {
|
|
481
|
+
sortUniqueEndpoints(group.callers);
|
|
482
|
+
sortUniqueEndpoints(group.receivers);
|
|
483
|
+
}
|
|
484
|
+
return groups;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* 이름 그룹을 mechanism 규칙으로 매치·미수출·미호출로 나눈다.
|
|
488
|
+
*
|
|
489
|
+
* 한 이름 아래 호출자·수신자가 mechanism이 섞여 있을 수 있으므로 그룹
|
|
490
|
+
* 전체가 아니라 증거 쌍 단위로 판정한다. 만족한 호출자·도달한 수신자만
|
|
491
|
+
* 매치로 고정하고, 나머지는 각각 미수출·미호출 증거로 남긴다 — 한 이름이
|
|
492
|
+
* 두 컬렉션에 동시에 나타날 수 있다.
|
|
493
|
+
*/
|
|
494
|
+
function classifyNameGroups(groups, callerKind) {
|
|
495
|
+
const compatible = (caller, receiver) => boundaryCompatible(callerKind, caller, receiver);
|
|
496
|
+
const matched = [];
|
|
497
|
+
const unexported = [];
|
|
498
|
+
const unrequired = [];
|
|
499
|
+
for (const group of groups.values()) {
|
|
500
|
+
const satisfied = group.callers.filter((caller) => group.receivers.some((receiver) => compatible(caller, receiver)));
|
|
501
|
+
const unsatisfied = group.callers.filter((caller) => !group.receivers.some((receiver) => compatible(caller, receiver)));
|
|
502
|
+
const reached = group.receivers.filter((receiver) => group.callers.some((caller) => compatible(caller, receiver)));
|
|
503
|
+
const unreached = group.receivers.filter((receiver) => !group.callers.some((caller) => compatible(caller, receiver)));
|
|
504
|
+
// 만족한 호출자가 있으면 그와 호환되는 수신자가 존재하므로 도달한
|
|
505
|
+
// 수신자도 비어 있지 않다.
|
|
506
|
+
if (satisfied.length > 0) {
|
|
507
|
+
matched.push({
|
|
508
|
+
target: group.target,
|
|
509
|
+
channel: group.channel,
|
|
510
|
+
callers: satisfied,
|
|
511
|
+
receivers: reached,
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
if (unsatisfied.length > 0) {
|
|
515
|
+
// unsatisfied 호출자에게는 이 그룹의 수신자가 모두 도달 불가다 —
|
|
516
|
+
// 호환되는 수신자가 하나라도 있었다면 그 호출자는 만족했을 것이다.
|
|
517
|
+
// mechanism이 두 값뿐이라 미만족 호출자는 항상 한 mechanism으로
|
|
518
|
+
// 모인다(비어 있지 않은 수신자가 한 mechanism이면 그 mechanism의
|
|
519
|
+
// 호출자는 만족한다) — 호출자 mechanism 구성은 엔트리 증거에 남고
|
|
520
|
+
// 보고 층이 Expo의 폴백 없는 require(error)와 코어 require의 미해결
|
|
521
|
+
// 상호운용(warning)을 구분한다.
|
|
522
|
+
unexported.push({
|
|
523
|
+
target: group.target,
|
|
524
|
+
channel: group.channel,
|
|
525
|
+
callers: unsatisfied,
|
|
526
|
+
...(group.receivers.length === 0
|
|
527
|
+
? {}
|
|
528
|
+
: { incompatibleReceivers: group.receivers }),
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
if (unreached.length > 0) {
|
|
532
|
+
// 도달 못한 수신자에게는 모든 호출자가 비호환이다 — 호환 호출자가
|
|
533
|
+
// 있었다면 도달했을 것이다. 호출자가 있으면 mechanism 불일치 증거다.
|
|
534
|
+
unrequired.push({
|
|
535
|
+
target: group.target,
|
|
536
|
+
channel: group.channel,
|
|
537
|
+
receivers: unreached,
|
|
538
|
+
...(group.callers.length === 0
|
|
539
|
+
? {}
|
|
540
|
+
: { incompatibleCallers: group.callers }),
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
matched.sort(compareChannels);
|
|
545
|
+
unexported.sort(compareChannels);
|
|
546
|
+
unrequired.sort(compareChannels);
|
|
547
|
+
return { matched, unexported, unrequired };
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* mechanism이 다른 호출·수신 쌍이 실제로 연결되는지 판정한다.
|
|
551
|
+
*
|
|
552
|
+
* `module-import`: Expo의 `requireNativeModule`·`requireOptionalNativeModule`은
|
|
553
|
+
* `TurboModuleRegistry` 폴백이 있어 `expo` 호출자는 어느 mechanism의 export도
|
|
554
|
+
* 만족시킨다. 코어 호출자는 코어 export만 도달한다.
|
|
555
|
+
* `component-require`: `requireNativeViewManager`에는 그런 폴백이 없어
|
|
556
|
+
* 같은 mechanism끼리만 잇는다. 생략된 mechanism은 `core`로 읽는다.
|
|
557
|
+
*/
|
|
558
|
+
function boundaryCompatible(callerKind, caller, receiver) {
|
|
559
|
+
const callerMechanism = caller.mechanism ?? 'core';
|
|
560
|
+
const receiverMechanism = receiver.mechanism ?? 'core';
|
|
561
|
+
if (callerKind === 'module-import') {
|
|
562
|
+
return callerMechanism === 'expo' || receiverMechanism === 'core';
|
|
563
|
+
}
|
|
564
|
+
return callerMechanism === receiverMechanism;
|
|
565
|
+
}
|
|
399
566
|
/** 사실을 플랫폼이 포함된 증거 위치로 바꾼다. */
|
|
400
567
|
function toEndpoint(platform, fact) {
|
|
401
568
|
return {
|
|
402
569
|
platform, location: fact.location,
|
|
403
570
|
...(fact.symbol === undefined ? {} : { symbol: fact.symbol }),
|
|
571
|
+
...(fact.mechanism === undefined ? {} : { mechanism: fact.mechanism }),
|
|
572
|
+
...(fact.optional === undefined ? {} : { optional: fact.optional }),
|
|
404
573
|
...(fact.sourceLanguage === undefined ? {} : { sourceLanguage: fact.sourceLanguage }),
|
|
574
|
+
...(fact.handlerScope === undefined ? {} : { handlerScope: fact.handlerScope, dependencies: fact.dependencies }),
|
|
405
575
|
};
|
|
406
576
|
}
|
|
407
577
|
/** 채널 결과를 target과 이름 순으로 고정한다. */
|
package/dist/join/join.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"join.js","sourceRoot":"","sources":["../../src/join/join.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n BridgeFact,\n BridgeFactsDocument,\n BridgeLocation,\n BridgePlatform,\n BridgeSymbol,\n BridgeSourceLanguage,\n BridgeTarget,\n} from '../exchange/parse.ts';\nimport { compareStrings } from '../compare.ts';\nimport { isCallerPlatform, isReceiverPlatform } from '../exchange/parse.ts';\n\n/** 한 언어 문서가 제공한 브리지 증거 위치다. */\nexport interface BridgeEndpoint {\n readonly platform: BridgePlatform;\n readonly location: BridgeLocation;\n readonly symbol?: BridgeSymbol;\n readonly sourceLanguage?: BridgeSourceLanguage;\n}\n\n/** 논리 채널 하나에 모인 양쪽 생성·등록 증거다. */\nexport interface MatchedChannel {\n readonly target: BridgeTarget;\n readonly channel: string;\n readonly creations: readonly BridgeEndpoint[];\n readonly registrations: readonly BridgeEndpoint[];\n}\n\n/** 등록을 찾지 못한 논리 채널과 모든 생성 증거다. */\nexport interface UnregisteredChannelCreation {\n readonly target: BridgeTarget;\n readonly channel: string;\n readonly creations: readonly BridgeEndpoint[];\n}\n\n/** 생성을 찾지 못한 논리 채널과 모든 등록 증거다. */\nexport interface RegistrationWithoutCreation {\n readonly target: BridgeTarget;\n readonly channel: string;\n readonly registrations: readonly BridgeEndpoint[];\n}\n\n/** 논리 메서드 하나에 모인 양쪽 호출·핸들러 증거다. */\nexport interface MatchedMethod {\n readonly target: BridgeTarget;\n readonly channel: string;\n readonly method: string;\n readonly invocations: readonly BridgeEndpoint[];\n readonly handlers: readonly BridgeEndpoint[];\n}\n\n/** 핸들러를 찾지 못한 논리 호출과 모든 호출 증거다. */\nexport interface UnhandledInvocation {\n readonly target: BridgeTarget;\n readonly channel: string;\n readonly method: string;\n readonly invocations: readonly BridgeEndpoint[];\n}\n\n/** 호출자를 찾지 못한 논리 핸들러와 모든 네이티브 증거다. */\nexport interface HandlerWithoutInvocation {\n readonly target: BridgeTarget;\n readonly channel: string;\n readonly method: string;\n readonly handlers: readonly BridgeEndpoint[];\n}\n\n/**\n * 생산 문서가 밝힌 분석 한계와 출처다.\n *\n * `target`은 이 한계를 신고한 문서의 브리지 메커니즘이다. 사실은 target별로만\n * 조인되므로, 보고서는 이 값으로 한계를 해당 target의 진단에만 귀속시킨다.\n * 사실이 없는 문서의 한계, 선언한 target을 신뢰할 수 없는 mixed-targets 문서의\n * 한계, 교차 입력 한계는 어느 target이 가려졌는지 특정할 수 없어 `null`이다.\n */\nexport interface JoinLimitation {\n readonly platform: BridgePlatform | 'cross-platform';\n readonly target: BridgeTarget | null;\n readonly tool: string;\n readonly message: string;\n readonly channels?: readonly string[];\n /** 소비자가 직접 센 한계에만 부여하며 생산 문서에서는 복사하지 않는다. */\n readonly origin?: 'consumer';\n}\n\n/** 검증된 교환 문서들의 논리 조인 결과다. */\nexport interface BridgeJoinResult {\n readonly deferred: boolean;\n /** 입력 문서 전체가 관찰한 fact 수다. 조인 여부와 무관한 관찰량이다. */\n readonly observedFacts: number;\n readonly matchedChannels: readonly MatchedChannel[];\n readonly unregisteredChannelCreations: readonly UnregisteredChannelCreation[];\n readonly registrationsWithoutCreations: readonly RegistrationWithoutCreation[];\n readonly matchedMethods: readonly MatchedMethod[];\n readonly unhandledInvocations: readonly UnhandledInvocation[];\n readonly handlersWithoutInvocations: readonly HandlerWithoutInvocation[];\n readonly limitations: readonly JoinLimitation[];\n}\n\n/** 한 번의 조인에서 허용하는 최대 생산 문서 수다. */\nexport const MAX_DOCUMENTS_PER_JOIN = 256;\n\n/** 함께 조인할 입력 문서 집합이 논리 계약을 위반했음을 나타낸다. */\nexport class BridgeJoinValidationError extends Error {\n /** 입력 경로를 노출하지 않는 안전한 메시지를 보존한다. */\n constructor(message: string) {\n super(message);\n this.name = 'BridgeJoinValidationError';\n }\n}\n\n/** 위치가 아니라 문자열 키로 검증된 교환 문서를 조인한다. */\nexport function joinBridgeDocuments(\n documents: readonly BridgeFactsDocument[],\n): BridgeJoinResult {\n if (documents.length > MAX_DOCUMENTS_PER_JOIN) {\n throw new BridgeJoinValidationError(\n `Bridge join exceeds the ${MAX_DOCUMENTS_PER_JOIN} document limit.`,\n );\n }\n validateProjects(documents);\n validatePlatformComposition(documents);\n const limitations = collectLimitations(documents);\n const observedFacts = documents.reduce(\n (total, document) => total + document.facts.length,\n 0,\n );\n if (documents.some(hasMixedTargets)) {\n return emptyJoinResult(limitations, observedFacts);\n }\n const groups = collectChannelGroups(documents);\n const matchedChannels = [...groups.values()]\n .filter((group) => group.creations.length > 0 && group.registrations.length > 0)\n .sort(compareChannels);\n const unregisteredChannelCreations = [...groups.values()]\n .filter((group) => group.creations.length > 0 && group.registrations.length === 0)\n .map(({ target, channel, creations }) => ({ target, channel, creations }))\n .sort(compareChannels);\n const registrationsWithoutCreations = [...groups.values()]\n .filter((group) => group.registrations.length > 0 && group.creations.length === 0)\n .map(({ target, channel, registrations }) => ({\n target,\n channel,\n registrations,\n }))\n .sort(compareChannels);\n const methodGroups = collectMethodGroups(documents);\n const matchedMethods = [...methodGroups.values()]\n .filter((group) => group.invocations.length > 0 && group.handlers.length > 0)\n .sort(compareMethodKeys);\n const unhandledInvocations = [...methodGroups.values()]\n .filter((group) => group.invocations.length > 0 && group.handlers.length === 0)\n .map(({ target, channel, method, invocations }) => ({\n target,\n channel,\n method,\n invocations,\n }))\n .sort(compareMethodKeys);\n const handlersWithoutInvocations = [...methodGroups.values()]\n .filter((group) => group.handlers.length > 0 && group.invocations.length === 0)\n .map(({ target, channel, method, handlers }) => ({\n target,\n channel,\n method,\n handlers,\n }))\n .sort(compareMethodKeys);\n return {\n deferred: false,\n observedFacts,\n matchedChannels,\n unregisteredChannelCreations,\n registrationsWithoutCreations,\n matchedMethods,\n unhandledInvocations,\n handlersWithoutInvocations,\n limitations,\n };\n}\n\n/** 입력 한계 때문에 조인 전체가 보류된 결과인지 확인한다. */\nexport function isBridgeJoinDeferred(joined: BridgeJoinResult): boolean {\n return joined.deferred;\n}\n\n/** 한 번의 조인 입력이 정확히 하나의 project를 기술하는지 검증한다. */\nfunction validateProjects(documents: readonly BridgeFactsDocument[]): void {\n if (new Set(documents.map(({ project }) => project)).size > 1) {\n throw new BridgeJoinValidationError(\n 'Bridge documents must describe the same project; regenerate them from one project root.',\n );\n }\n}\n\n/** 호출 측·수신 측 문서가 모두 있어야 경계 사실로 조인할 수 있다. */\nfunction validatePlatformComposition(\n documents: readonly BridgeFactsDocument[],\n): void {\n const hasCaller = documents.some(({ platform }) => isCallerPlatform(platform));\n const hasReceiver = documents.some(({ platform }) =>\n isReceiverPlatform(platform),\n );\n if (!hasCaller || !hasReceiver) {\n throw new BridgeJoinValidationError(\n 'Bridge documents must include at least one caller platform (dart, js) document '\n + 'and one receiver platform (swift, kotlin) document; run a producer for the missing side.',\n );\n }\n}\n\n/** 사실별 target이 없는 혼합 문서인지 확인한다. */\nfunction hasMixedTargets(document: BridgeFactsDocument): boolean {\n // 단어 경계로 판정한다. 낱말 안에 붙은 표기(\"non-mixed-targets workspaces\",\n // \"mixed-targets-like\")는 문구 변형이 아니라 다른 낱말이라 보류의 근거가 못 된다.\n // 앞 공백·대소문자·콜론 누락 변형은 계속 보수적으로 인정한다.\n return document.limitations.some((message) =>\n mixedTargetToken.test(message),\n );\n}\n\n/** 문구 변형을 인정하는 mixed-targets 토큰 경계다. */\nconst mixedTargetToken = /(?<![\\w-])mixed-targets(?![\\w-])/i;\n\n/**\n * 한계를 귀속시킬 target을 결정한다.\n *\n * mixed-targets 문서의 선언 target은 대표값일 뿐 사실별 메커니즘을 복원할 수\n * 없으므로, 그 문서의 한계와 조인 제외 사실 계수는 귀속 없이(null) 남긴다.\n * 귀속을 잃어도 관찰 자체는 보존해야 한다.\n */\nfunction limitationTarget(document: BridgeFactsDocument): BridgeTarget | null {\n return hasMixedTargets(document) ? null : document.target;\n}\n\n/** 안전하게 조인을 보류하면서 입력 한계만 전달한다. 관찰량은 보존한다. */\nfunction emptyJoinResult(\n limitations: readonly JoinLimitation[],\n observedFacts: number,\n): BridgeJoinResult {\n return {\n deferred: true,\n observedFacts,\n matchedChannels: [],\n unregisteredChannelCreations: [],\n registrationsWithoutCreations: [],\n matchedMethods: [],\n unhandledInvocations: [],\n handlersWithoutInvocations: [],\n limitations,\n };\n}\n\n/** 입력 limitation에 생산 플랫폼과 도구 이름을 붙이고 조인하지 못한 사실을 함께 센다. */\nfunction collectLimitations(\n documents: readonly BridgeFactsDocument[],\n): JoinLimitation[] {\n const limitations: JoinLimitation[] = documents.flatMap((document) => {\n const scopes = new Map(document.limitationScopes?.map((scope) => [scope.limitationIndex, scope.channels]));\n return document.limitations.map((message, index) => {\n const channels = scopes.get(index);\n return {\n platform: document.platform,\n target: limitationTarget(document),\n tool: document.tool.name,\n message,\n ...(channels === undefined ? {} : { channels }),\n };\n });\n });\n limitations.push(...unjoinedFactLimitations(documents));\n const freshness = freshnessLimitation(documents);\n if (freshness !== undefined) limitations.push(freshness);\n return limitations.sort(compareLimitations);\n}\n\n/**\n * 조인에서 제외한 사실을 isthmus 자신의 관찰 한계로 남긴다.\n *\n * 생산자가 같은 사실을 limitation으로 신고하지 않아도, 또는 신고한 개수가 실제와\n * 달라도 관찰 공백이 보고서에서 사라지지 않아야 한다. 교환 계약은 이 사실들을\n * 세도록 요구하지만 문서의 limitation 문자열은 생산자의 자발적인 신고라\n * 소비자가 신뢰의 근거로 삼을 수 없다.\n */\nfunction unjoinedFactLimitations(\n documents: readonly BridgeFactsDocument[],\n): JoinLimitation[] {\n return [\n ...unjoinedLimitations(\n documents,\n isUnjoinedDynamicChannel,\n 'unjoined-dynamic-channels',\n 'channel facts with a non-literal name',\n ),\n ...unjoinedLimitations(\n documents,\n isUnjoinedDynamicMethod,\n 'unjoined-dynamic-methods',\n 'method facts with a non-literal name',\n ),\n ...unjoinedLimitations(\n documents,\n isUnattributedHandler,\n 'unjoined-unattributed-handlers',\n 'method handler facts without a channel',\n ),\n ];\n}\n\n/** 조건에 맞는 사실 수를 플랫폼·target별로 세어 한계 문장으로 바꾼다. */\nfunction unjoinedLimitations(\n documents: readonly BridgeFactsDocument[],\n matchesFact: (fact: BridgeFact) => boolean,\n prefix: string,\n subject: string,\n): JoinLimitation[] {\n return countFactsByPlatformTarget(documents, matchesFact).map(\n ({ platform, target, count }) => ({\n platform,\n target,\n tool: 'isthmus',\n origin: 'consumer',\n message: `${prefix}: ${count} ${subject} were not joined`,\n }),\n );\n}\n\n/**\n * 주어진 조건의 서로 다른 사실 수를 생산 플랫폼·target별로 모은다.\n *\n * 사실은 target별로만 조인되므로 다른 target의 사실을 한 한계로 합산하면\n * 관찰 공백의 귀속이 사라진다. mixed-targets 문서의 사실은 귀속 없이(null)\n * 센다. 사실이 없는 문서는 교환 계약상 target이 null이고 사실도 없으므로\n * 여기에서 자연스럽게 제외된다.\n */\nfunction countFactsByPlatformTarget(\n documents: readonly BridgeFactsDocument[],\n matchesFact: (fact: BridgeFact) => boolean,\n): Array<{\n platform: BridgePlatform;\n target: BridgeTarget | null;\n count: number;\n}> {\n const distinctFacts = new Map<\n string,\n {\n platform: BridgePlatform;\n target: BridgeTarget | null;\n keys: Set<string>;\n }\n >();\n for (const document of documents) {\n const target = limitationTarget(document);\n // BridgeTarget은 닫힌 어휘라 문자열화된 null과 충돌하지 않는다.\n const groupKey = `${document.platform}\\u0000${target}`;\n for (const fact of document.facts) {\n if (!matchesFact(fact)) continue;\n const group = distinctFacts.get(groupKey) ?? {\n platform: document.platform,\n target,\n keys: new Set<string>(),\n };\n group.keys.add(unjoinedFactKey(fact));\n distinctFacts.set(groupKey, group);\n }\n }\n return [...distinctFacts.values()].map(({ platform, target, keys }) => ({\n platform,\n target,\n count: keys.size,\n }));\n}\n\n/**\n * 같은 위치의 중복 사실을 한 번만 세는 키를 만든다.\n *\n * 위치 기준은 증거 dedup과 같지만 symbol은 비교하지 않아, 같은 위치의 서로\n * 다른 symbol은 하나로 센다. `channel`은 null일 수 있어 구분자 결합 대신\n * JSON으로 만든다. 그래야 미귀속 핸들러와 이름이 `null`인 채널의 사실이\n * 같은 키로 합쳐지지 않는다.\n */\nfunction unjoinedFactKey(fact: BridgeFact): string {\n const { path, line, column } = fact.location;\n return JSON.stringify([\n fact.kind,\n fact.channel,\n fact.method ?? null,\n path,\n line,\n column,\n ]);\n}\n\n/** 이름이 리터럴이 아니어서 조인하지 못한 채널 사실인지 확인한다. */\nfunction isUnjoinedDynamicChannel(fact: BridgeFact): boolean {\n return (\n fact.dynamic &&\n (fact.kind === 'channel-create' || fact.kind === 'channel-register')\n );\n}\n\n/** 이름이 리터럴이 아니어서 조인하지 못한 메서드 사실인지 확인한다. */\nfunction isUnjoinedDynamicMethod(fact: BridgeFact): boolean {\n return (\n fact.dynamic &&\n (fact.kind === 'method-invoke' || fact.kind === 'method-handle')\n );\n}\n\n/**\n * 어느 채널에 속하는지 몰라 조인하지 못한 핸들러 사실인지 확인한다.\n *\n * dynamic 사실은 위에서 이미 세므로 여기서 다시 세지 않는다.\n */\nfunction isUnattributedHandler(fact: BridgeFact): boolean {\n return fact.kind === 'method-handle' && fact.channel === null && !fact.dynamic;\n}\n\n/** 생성 시각 차이가 하루를 넘을 때 교차 입력 한계를 만든다. */\nfunction freshnessLimitation(\n documents: readonly BridgeFactsDocument[],\n): JoinLimitation | undefined {\n if (documents.length < 2) return undefined;\n let earliest = Number.POSITIVE_INFINITY;\n let latest = Number.NEGATIVE_INFINITY;\n for (const document of documents) {\n const timestamp = Date.parse(document.generatedAt);\n earliest = Math.min(earliest, timestamp);\n latest = Math.max(latest, timestamp);\n }\n const difference = latest - earliest;\n if (difference <= millisecondsPerDay) return undefined;\n const hours = Math.round(difference / millisecondsPerHour);\n return {\n platform: 'cross-platform',\n target: null,\n tool: 'isthmus',\n origin: 'consumer',\n message: `input-freshness: bridge documents differ by ${hours} hours`,\n };\n}\n\n/** limitation을 플랫폼·target·도구·문장 순으로 고정한다. */\nfunction compareLimitations(left: JoinLimitation, right: JoinLimitation): number {\n return (\n compareStrings(left.platform, right.platform) ||\n compareTargets(left.target, right.target) ||\n compareStrings(left.tool, right.tool) ||\n compareStrings(left.message, right.message) ||\n compareOptionalStrings(left.origin, right.origin) ||\n compareStrings(JSON.stringify(left.channels ?? null), JSON.stringify(right.channels ?? null))\n );\n}\n\n/** target을 문자열 순으로 고정하고 귀속이 없는(null) 한계를 뒤에 둔다. */\nfunction compareTargets(\n left: BridgeTarget | null,\n right: BridgeTarget | null,\n): number {\n if (left === right) return 0;\n if (left === null) return 1;\n if (right === null) return -1;\n return compareStrings(left, right);\n}\n\n/** 메서드 키별로 호출과 핸들러 증거를 모은다. */\nfunction collectMethodGroups(\n documents: readonly BridgeFactsDocument[],\n): Map<string, MutableMethodGroup> {\n const groups = new Map<string, MutableMethodGroup>();\n for (const document of documents) collectDocumentMethods(document, groups);\n for (const group of groups.values()) {\n sortUniqueEndpoints(group.invocations);\n sortUniqueEndpoints(group.handlers);\n }\n return groups;\n}\n\n/** 증거 위치와 심볼을 정렬하고 같은 증거를 한 번만 남긴다. */\nfunction sortUniqueEndpoints(endpoints: BridgeEndpoint[]): void {\n endpoints.sort(compareEndpoints);\n if (endpoints.length < 2) return;\n let writeIndex = 1;\n for (let readIndex = 1; readIndex < endpoints.length; readIndex++) {\n const previous = endpoints[writeIndex - 1];\n const current = endpoints[readIndex];\n if (\n previous !== undefined &&\n current !== undefined &&\n compareEndpoints(previous, current) !== 0\n ) {\n endpoints[writeIndex] = current;\n writeIndex++;\n }\n }\n endpoints.length = writeIndex;\n}\n\n/** 증거 위치와 선택 심볼을 완전한 결정 순서로 비교한다. */\nfunction compareEndpoints(left: BridgeEndpoint, right: BridgeEndpoint): number {\n const locationOrder =\n compareStrings(left.platform, right.platform) ||\n compareStrings(left.location.path, right.location.path) ||\n left.location.line - right.location.line ||\n left.location.column - right.location.column;\n if (locationOrder !== 0) return locationOrder;\n const languageOrder = compareOptionalStrings(left.sourceLanguage, right.sourceLanguage);\n if (languageOrder !== 0) return languageOrder;\n if (left.symbol === undefined) return right.symbol === undefined ? 0 : 1;\n if (right.symbol === undefined) return -1;\n return (\n compareStrings(left.symbol.qualifiedName, right.symbol.qualifiedName) ||\n compareOptionalStrings(left.symbol.usr, right.symbol.usr)\n );\n}\n\n/** 존재하는 선택 문자열을 없는 값보다 먼저 두고 비교한다. */\nfunction compareOptionalStrings(\n left: string | undefined,\n right: string | undefined,\n): number {\n if (left === undefined) return right === undefined ? 0 : 1;\n if (right === undefined) return -1;\n return compareStrings(left, right);\n}\n\n/** 문서 하나의 정적 메서드 사실을 그룹에 추가한다. */\nfunction collectDocumentMethods(\n document: BridgeFactsDocument,\n groups: Map<string, MutableMethodGroup>,\n): void {\n if (document.target === null) return;\n for (const fact of document.facts) {\n if (!isStaticMethodFact(fact)) continue;\n const key = `${document.target}\\u0000${fact.channel}\\u0000${fact.method}`;\n const group = groups.get(key) ?? createMethodGroup(document.target, fact.channel, fact.method);\n const endpoints = fact.kind === 'method-invoke' ? group.invocations : group.handlers;\n endpoints.push(toEndpoint(document.platform, fact));\n groups.set(key, group);\n }\n}\n\n/** 조인 가능한 정적 메서드 호출·핸들러 사실인지 확인한다. */\nfunction isStaticMethodFact(\n fact: BridgeFactsDocument['facts'][number],\n): fact is BridgeFactsDocument['facts'][number] & {\n channel: string;\n method: string;\n} {\n return (\n (fact.kind === 'method-invoke' || fact.kind === 'method-handle') &&\n !fact.dynamic &&\n fact.channel !== null &&\n fact.method !== undefined\n );\n}\n\n/** 빈 메서드 그룹을 만든다. */\nfunction createMethodGroup(\n target: BridgeTarget,\n channel: string,\n method: string,\n): MutableMethodGroup {\n return { target, channel, method, invocations: [], handlers: [] };\n}\n\n/** 채널 키별로 생성과 등록 증거를 모은다. */\nfunction collectChannelGroups(\n documents: readonly BridgeFactsDocument[],\n): Map<string, MutableChannelGroup> {\n const groups = new Map<string, MutableChannelGroup>();\n for (const document of documents) collectDocumentChannels(document, groups);\n for (const group of groups.values()) {\n sortUniqueEndpoints(group.creations);\n sortUniqueEndpoints(group.registrations);\n }\n return groups;\n}\n\n/** 문서 하나의 정적 채널 사실을 그룹에 추가한다. */\nfunction collectDocumentChannels(\n document: BridgeFactsDocument,\n groups: Map<string, MutableChannelGroup>,\n): void {\n if (document.target === null) return;\n for (const fact of document.facts) {\n if (!isStaticChannelFact(fact)) continue;\n const key = `${document.target}\\u0000${fact.channel}`;\n const group = groups.get(key) ?? createChannelGroup(document.target, fact.channel);\n const endpoints = fact.kind === 'channel-create' ? group.creations : group.registrations;\n endpoints.push(toEndpoint(document.platform, fact));\n groups.set(key, group);\n }\n}\n\n/** 조인 가능한 정적 채널 생성·등록 사실인지 확인한다. */\nfunction isStaticChannelFact(\n fact: BridgeFactsDocument['facts'][number],\n): fact is BridgeFactsDocument['facts'][number] & { channel: string } {\n return (\n (fact.kind === 'channel-create' || fact.kind === 'channel-register') &&\n !fact.dynamic &&\n fact.channel !== null\n );\n}\n\n/** 빈 채널 그룹을 만든다. */\nfunction createChannelGroup(\n target: BridgeTarget,\n channel: string,\n): MutableChannelGroup {\n return { target, channel, creations: [], registrations: [] };\n}\n\n/** 사실을 플랫폼이 포함된 증거 위치로 바꾼다. */\nfunction toEndpoint(\n platform: BridgePlatform,\n fact: BridgeFactsDocument['facts'][number],\n): BridgeEndpoint {\n return {\n platform, location: fact.location,\n ...(fact.symbol === undefined ? {} : { symbol: fact.symbol }),\n ...(fact.sourceLanguage === undefined ? {} : { sourceLanguage: fact.sourceLanguage }),\n };\n}\n\n/** 채널 결과를 target과 이름 순으로 고정한다. */\nfunction compareChannels(left: ChannelKey, right: ChannelKey): number {\n return (\n compareStrings(left.target, right.target) ||\n compareStrings(left.channel, right.channel)\n );\n}\n\n/** 결정적 정렬에 필요한 논리 채널 키다. */\ntype ChannelKey = Pick<MatchedChannel, 'target' | 'channel'>;\n\n/** 메서드 결과를 target·채널·메서드 순으로 고정한다. */\nfunction compareMethodKeys(left: MethodKey, right: MethodKey): number {\n return (\n compareStrings(left.target, right.target) ||\n compareStrings(left.channel, right.channel) ||\n compareStrings(left.method, right.method)\n );\n}\n\n/** 결정적 정렬에 필요한 논리 메서드 키다. */\ntype MethodKey = Pick<MatchedMethod, 'target' | 'channel' | 'method'>;\n\n/** 조립 중인 채널 증거 그룹이다. */\ninterface MutableChannelGroup extends MatchedChannel {\n readonly creations: BridgeEndpoint[];\n readonly registrations: BridgeEndpoint[];\n}\n\n/** 조립 중인 메서드 증거 그룹이다. */\ninterface MutableMethodGroup extends MatchedMethod {\n readonly invocations: BridgeEndpoint[];\n readonly handlers: BridgeEndpoint[];\n}\n\nconst millisecondsPerHour = 60 * 60 * 1_000;\nconst millisecondsPerDay = 24 * millisecondsPerHour;\n"]}
|
|
1
|
+
{"version":3,"file":"join.js","sourceRoot":"","sources":["../../src/join/join.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n BridgeFact,\n BridgeFactsDocument,\n BridgeHandlerDependency,\n BridgeHandlerScope,\n BridgeLocation,\n BridgeMechanism,\n BridgePlatform,\n BridgeSymbol,\n BridgeSourceLanguage,\n BridgeTarget,\n} from '../exchange/parse.ts';\nimport { compareStrings } from '../compare.ts';\nimport { isCallerPlatform, isReceiverPlatform } from '../exchange/parse.ts';\n\n/** 한 언어 문서가 제공한 브리지 증거 위치다. */\nexport interface BridgeEndpoint {\n readonly platform: BridgePlatform;\n readonly location: BridgeLocation;\n readonly symbol?: BridgeSymbol;\n readonly sourceLanguage?: BridgeSourceLanguage;\n /**\n * 이름 경계 증거가 속한 해석 경로다. `react-native` 사실만 가질 수 있고\n * 생략은 `core`다. mechanism이 다른 호출·수신 쌍의 불일치 판정 근거다.\n */\n readonly mechanism?: BridgeMechanism;\n /**\n * 호출 API가 모듈 부재를 허용한다는 호출 측 증거다.\n * `module-import`에만 온다 — 부재 시 크래시가 아니라 `null` 반환이다.\n */\n readonly optional?: boolean;\n /** method-handle 분기 근거다. v2 handler 사실과 같은 형태를 공유한다. */\n readonly handlerScope?: BridgeHandlerScope;\n readonly dependencies?: readonly BridgeHandlerDependency[];\n}\n\n/** 논리 채널 하나에 모인 양쪽 생성·등록 증거다. */\nexport interface MatchedChannel {\n readonly target: BridgeTarget;\n readonly channel: string;\n readonly creations: readonly BridgeEndpoint[];\n readonly registrations: readonly BridgeEndpoint[];\n}\n\n/** 등록을 찾지 못한 논리 채널과 모든 생성 증거다. */\nexport interface UnregisteredChannelCreation {\n readonly target: BridgeTarget;\n readonly channel: string;\n readonly creations: readonly BridgeEndpoint[];\n}\n\n/** 생성을 찾지 못한 논리 채널과 모든 등록 증거다. */\nexport interface RegistrationWithoutCreation {\n readonly target: BridgeTarget;\n readonly channel: string;\n readonly registrations: readonly BridgeEndpoint[];\n}\n\n/** 논리 메서드 하나에 모인 양쪽 호출·핸들러 증거다. */\nexport interface MatchedMethod {\n readonly target: BridgeTarget;\n readonly channel: string;\n readonly method: string;\n readonly invocations: readonly BridgeEndpoint[];\n readonly handlers: readonly BridgeEndpoint[];\n}\n\n/** 핸들러를 찾지 못한 논리 호출과 모든 호출 증거다. */\nexport interface UnhandledInvocation {\n readonly target: BridgeTarget;\n readonly channel: string;\n readonly method: string;\n readonly invocations: readonly BridgeEndpoint[];\n}\n\n/** 호출자를 찾지 못한 논리 핸들러와 모든 네이티브 증거다. */\nexport interface HandlerWithoutInvocation {\n readonly target: BridgeTarget;\n readonly channel: string;\n readonly method: string;\n readonly handlers: readonly BridgeEndpoint[];\n}\n\n/**\n * 논리 모듈·컴포넌트 이름 하나에 모인 호출 측·수신 측 증거다.\n *\n * 호출 측은 `module-import`·`component-require`, 수신 측은 `module-export`·\n * `component-export` 사실이다. `channel` 필드에는 RN 모듈·컴포넌트 이름이 든다.\n */\nexport interface MatchedBoundaryName {\n readonly target: BridgeTarget;\n readonly channel: string;\n readonly callers: readonly BridgeEndpoint[];\n readonly receivers: readonly BridgeEndpoint[];\n}\n\n/**\n * 수신 측 export를 찾지 못한 논리 이름과 모든 호출 측 증거다.\n *\n * `incompatibleReceivers`는 같은 이름으로 관찰됐지만 mechanism이 달라\n * 이 호출들에게 도달할 수 없는 수신 측 증거다. 이름이 아예 없는 경우와\n * 구분해 보고 층이 불일치 경고로 내린다.\n */\nexport interface UnexportedBoundaryName {\n readonly target: BridgeTarget;\n readonly channel: string;\n readonly callers: readonly BridgeEndpoint[];\n readonly incompatibleReceivers?: readonly BridgeEndpoint[];\n}\n\n/**\n * 호출 측 import·require를 찾지 못한 논리 이름과 모든 수신 측 증거다.\n *\n * `incompatibleCallers`는 같은 이름으로 관찰됐지만 mechanism이 달라\n * 이 수신들에게 도달할 수 없는 호출 측 증거다. 호출이 아예 없는 경우와\n * 구분해 보고 층이 불일치 경고로 내린다.\n */\nexport interface UnrequiredBoundaryName {\n readonly target: BridgeTarget;\n readonly channel: string;\n readonly receivers: readonly BridgeEndpoint[];\n readonly incompatibleCallers?: readonly BridgeEndpoint[];\n}\n\n/**\n * 생산 문서가 밝힌 분석 한계와 출처다.\n *\n * `target`은 이 한계를 신고한 문서의 브리지 메커니즘이다. 사실은 target별로만\n * 조인되므로, 보고서는 이 값으로 한계를 해당 target의 진단에만 귀속시킨다.\n * 사실이 없는 문서의 한계, 선언한 target을 신뢰할 수 없는 mixed-targets 문서의\n * 한계, 교차 입력 한계는 어느 target이 가려졌는지 특정할 수 없어 `null`이다.\n */\nexport interface JoinLimitation {\n readonly platform: BridgePlatform | 'cross-platform';\n readonly target: BridgeTarget | null;\n readonly tool: string;\n readonly message: string;\n readonly channels?: readonly string[];\n /** 소비자가 직접 센 한계에만 부여하며 생산 문서에서는 복사하지 않는다. */\n readonly origin?: 'consumer';\n}\n\n/** 검증된 교환 문서들의 논리 조인 결과다. */\nexport interface BridgeJoinResult {\n readonly deferred: boolean;\n /** 입력 문서 전체가 관찰한 fact 수다. 조인 여부와 무관한 관찰량이다. */\n readonly observedFacts: number;\n readonly matchedChannels: readonly MatchedChannel[];\n readonly unregisteredChannelCreations: readonly UnregisteredChannelCreation[];\n readonly registrationsWithoutCreations: readonly RegistrationWithoutCreation[];\n readonly matchedMethods: readonly MatchedMethod[];\n readonly unhandledInvocations: readonly UnhandledInvocation[];\n readonly handlersWithoutInvocations: readonly HandlerWithoutInvocation[];\n readonly matchedModules: readonly MatchedBoundaryName[];\n readonly moduleImportsWithoutExports: readonly UnexportedBoundaryName[];\n readonly moduleExportsWithoutImports: readonly UnrequiredBoundaryName[];\n readonly matchedComponents: readonly MatchedBoundaryName[];\n readonly componentRequiresWithoutExports: readonly UnexportedBoundaryName[];\n readonly componentExportsWithoutRequires: readonly UnrequiredBoundaryName[];\n readonly limitations: readonly JoinLimitation[];\n}\n\n/** 한 번의 조인에서 허용하는 최대 생산 문서 수다. */\nexport const MAX_DOCUMENTS_PER_JOIN = 256;\n\n/** 함께 조인할 입력 문서 집합이 논리 계약을 위반했음을 나타낸다. */\nexport class BridgeJoinValidationError extends Error {\n /** 입력 경로를 노출하지 않는 안전한 메시지를 보존한다. */\n constructor(message: string) {\n super(message);\n this.name = 'BridgeJoinValidationError';\n }\n}\n\n/** 위치가 아니라 문자열 키로 검증된 교환 문서를 조인한다. */\nexport function joinBridgeDocuments(\n documents: readonly BridgeFactsDocument[],\n): BridgeJoinResult {\n if (documents.length > MAX_DOCUMENTS_PER_JOIN) {\n throw new BridgeJoinValidationError(\n `Bridge join exceeds the ${MAX_DOCUMENTS_PER_JOIN} document limit.`,\n );\n }\n validateProjects(documents);\n validatePlatformComposition(documents);\n const limitations = collectLimitations(documents);\n const observedFacts = documents.reduce(\n (total, document) => total + document.facts.length,\n 0,\n );\n if (documents.some(hasMixedTargets)) {\n return emptyJoinResult(limitations, observedFacts);\n }\n const groups = collectChannelGroups(documents);\n const matchedChannels = [...groups.values()]\n .filter((group) => group.creations.length > 0 && group.registrations.length > 0)\n .sort(compareChannels);\n const unregisteredChannelCreations = [...groups.values()]\n .filter((group) => group.creations.length > 0 && group.registrations.length === 0)\n .map(({ target, channel, creations }) => ({ target, channel, creations }))\n .sort(compareChannels);\n const registrationsWithoutCreations = [...groups.values()]\n .filter((group) => group.registrations.length > 0 && group.creations.length === 0)\n .map(({ target, channel, registrations }) => ({\n target,\n channel,\n registrations,\n }))\n .sort(compareChannels);\n const methodGroups = collectMethodGroups(documents);\n const matchedMethods = [...methodGroups.values()]\n .filter((group) => group.invocations.length > 0 && group.handlers.length > 0)\n .sort(compareMethodKeys);\n const unhandledInvocations = [...methodGroups.values()]\n .filter((group) => group.invocations.length > 0 && group.handlers.length === 0)\n .map(({ target, channel, method, invocations }) => ({\n target,\n channel,\n method,\n invocations,\n }))\n .sort(compareMethodKeys);\n const handlersWithoutInvocations = [...methodGroups.values()]\n .filter((group) => group.handlers.length > 0 && group.invocations.length === 0)\n .map(({ target, channel, method, handlers }) => ({\n target,\n channel,\n method,\n handlers,\n }))\n .sort(compareMethodKeys);\n const moduleGroups = collectNameGroups(documents, 'module-import', 'module-export');\n const componentGroups = collectNameGroups(documents, 'component-require', 'component-export');\n const moduleNames = classifyNameGroups(moduleGroups, 'module-import');\n const componentNames = classifyNameGroups(componentGroups, 'component-require');\n return {\n deferred: false,\n observedFacts,\n matchedChannels,\n unregisteredChannelCreations,\n registrationsWithoutCreations,\n matchedMethods,\n unhandledInvocations,\n handlersWithoutInvocations,\n matchedModules: moduleNames.matched,\n moduleImportsWithoutExports: moduleNames.unexported,\n moduleExportsWithoutImports: moduleNames.unrequired,\n matchedComponents: componentNames.matched,\n componentRequiresWithoutExports: componentNames.unexported,\n componentExportsWithoutRequires: componentNames.unrequired,\n limitations,\n };\n}\n\n/** 입력 한계 때문에 조인 전체가 보류된 결과인지 확인한다. */\nexport function isBridgeJoinDeferred(joined: BridgeJoinResult): boolean {\n return joined.deferred;\n}\n\n/** 한 번의 조인 입력이 정확히 하나의 project를 기술하는지 검증한다. */\nfunction validateProjects(documents: readonly BridgeFactsDocument[]): void {\n if (new Set(documents.map(({ project }) => project)).size > 1) {\n throw new BridgeJoinValidationError(\n 'Bridge documents must describe the same project; regenerate them from one project root.',\n );\n }\n}\n\n/** 호출 측·수신 측 문서가 모두 있어야 경계 사실로 조인할 수 있다. */\nfunction validatePlatformComposition(\n documents: readonly BridgeFactsDocument[],\n): void {\n const hasCaller = documents.some(({ platform }) => isCallerPlatform(platform));\n const hasReceiver = documents.some(({ platform }) =>\n isReceiverPlatform(platform),\n );\n if (!hasCaller || !hasReceiver) {\n throw new BridgeJoinValidationError(\n 'Bridge documents must include at least one caller platform (dart, js) document '\n + 'and one receiver platform (swift, kotlin) document; run a producer for the missing side.',\n );\n }\n}\n\n/** 사실별 target이 없는 혼합 문서인지 확인한다. */\nfunction hasMixedTargets(document: BridgeFactsDocument): boolean {\n // 단어 경계로 판정한다. 낱말 안에 붙은 표기(\"non-mixed-targets workspaces\",\n // \"mixed-targets-like\")는 문구 변형이 아니라 다른 낱말이라 보류의 근거가 못 된다.\n // 앞 공백·대소문자·콜론 누락 변형은 계속 보수적으로 인정한다.\n return document.limitations.some((message) =>\n mixedTargetToken.test(message),\n );\n}\n\n/** 문구 변형을 인정하는 mixed-targets 토큰 경계다. */\nconst mixedTargetToken = /(?<![\\w-])mixed-targets(?![\\w-])/i;\n\n/**\n * 한계를 귀속시킬 target을 결정한다.\n *\n * mixed-targets 문서의 선언 target은 대표값일 뿐 사실별 메커니즘을 복원할 수\n * 없으므로, 그 문서의 한계와 조인 제외 사실 계수는 귀속 없이(null) 남긴다.\n * 귀속을 잃어도 관찰 자체는 보존해야 한다.\n */\nfunction limitationTarget(document: BridgeFactsDocument): BridgeTarget | null {\n return hasMixedTargets(document) ? null : document.target;\n}\n\n/**\n * v1 사실이 없는 입력에서 v2 전용 보고를 만들 때 쓰는 빈 결과다.\n *\n * 조인을 보류하지 않는다 — 사실이 아예 없었을 뿐이므로 보류와 구분한다.\n */\nexport function emptyBridgeJoinResult(): BridgeJoinResult {\n return {\n deferred: false,\n observedFacts: 0,\n matchedChannels: [],\n unregisteredChannelCreations: [],\n registrationsWithoutCreations: [],\n matchedMethods: [],\n unhandledInvocations: [],\n handlersWithoutInvocations: [],\n matchedModules: [],\n moduleImportsWithoutExports: [],\n moduleExportsWithoutImports: [],\n matchedComponents: [],\n componentRequiresWithoutExports: [],\n componentExportsWithoutRequires: [],\n limitations: [],\n };\n}\n\n/** 안전하게 조인을 보류하면서 입력 한계만 전달한다. 관찰량은 보존한다. */\nfunction emptyJoinResult(\n limitations: readonly JoinLimitation[],\n observedFacts: number,\n): BridgeJoinResult {\n return {\n deferred: true,\n observedFacts,\n matchedChannels: [],\n unregisteredChannelCreations: [],\n registrationsWithoutCreations: [],\n matchedMethods: [],\n unhandledInvocations: [],\n handlersWithoutInvocations: [],\n matchedModules: [],\n moduleImportsWithoutExports: [],\n moduleExportsWithoutImports: [],\n matchedComponents: [],\n componentRequiresWithoutExports: [],\n componentExportsWithoutRequires: [],\n limitations,\n };\n}\n\n/** 입력 limitation에 생산 플랫폼과 도구 이름을 붙이고 조인하지 못한 사실을 함께 센다. */\nfunction collectLimitations(\n documents: readonly BridgeFactsDocument[],\n): JoinLimitation[] {\n const limitations: JoinLimitation[] = documents.flatMap((document) => {\n const scopes = new Map(document.limitationScopes?.map((scope) => [scope.limitationIndex, scope.channels]));\n return document.limitations.map((message, index) => {\n const channels = scopes.get(index);\n return {\n platform: document.platform,\n target: limitationTarget(document),\n tool: document.tool.name,\n message,\n ...(channels === undefined ? {} : { channels }),\n };\n });\n });\n limitations.push(...unjoinedFactLimitations(documents));\n const freshness = freshnessLimitation(documents);\n if (freshness !== undefined) limitations.push(freshness);\n return limitations.sort(compareLimitations);\n}\n\n/**\n * 조인에서 제외한 사실을 isthmus 자신의 관찰 한계로 남긴다.\n *\n * 생산자가 같은 사실을 limitation으로 신고하지 않아도, 또는 신고한 개수가 실제와\n * 달라도 관찰 공백이 보고서에서 사라지지 않아야 한다. 교환 계약은 이 사실들을\n * 세도록 요구하지만 문서의 limitation 문자열은 생산자의 자발적인 신고라\n * 소비자가 신뢰의 근거로 삼을 수 없다.\n */\nfunction unjoinedFactLimitations(\n documents: readonly BridgeFactsDocument[],\n): JoinLimitation[] {\n return [\n ...unjoinedLimitations(\n documents,\n isUnjoinedDynamicChannel,\n 'unjoined-dynamic-channels',\n 'channel facts with a non-literal name',\n ),\n ...unjoinedLimitations(\n documents,\n isUnjoinedDynamicMethod,\n 'unjoined-dynamic-methods',\n 'method facts with a non-literal name',\n ),\n ...unjoinedLimitations(\n documents,\n isUnattributedHandler,\n 'unjoined-unattributed-handlers',\n 'method handler facts without a channel',\n ),\n ...unjoinedLimitations(\n documents,\n isUnjoinedDynamicImport,\n 'unjoined-dynamic-imports',\n 'module import or component require facts with a non-literal name',\n ),\n ...unjoinedLimitations(\n documents,\n isUnjoinedDynamicExport,\n 'unjoined-dynamic-exports',\n 'module or component export facts with a non-literal name',\n ),\n ];\n}\n\n/** 조건에 맞는 사실 수를 플랫폼·target별로 세어 한계 문장으로 바꾼다. */\nfunction unjoinedLimitations(\n documents: readonly BridgeFactsDocument[],\n matchesFact: (fact: BridgeFact) => boolean,\n prefix: string,\n subject: string,\n): JoinLimitation[] {\n return countFactsByPlatformTarget(documents, matchesFact).map(\n ({ platform, target, count }) => ({\n platform,\n target,\n tool: 'isthmus',\n origin: 'consumer',\n message: `${prefix}: ${count} ${subject} were not joined`,\n }),\n );\n}\n\n/**\n * 주어진 조건의 서로 다른 사실 수를 생산 플랫폼·target별로 모은다.\n *\n * 사실은 target별로만 조인되므로 다른 target의 사실을 한 한계로 합산하면\n * 관찰 공백의 귀속이 사라진다. mixed-targets 문서의 사실은 귀속 없이(null)\n * 센다. 사실이 없는 문서는 교환 계약상 target이 null이고 사실도 없으므로\n * 여기에서 자연스럽게 제외된다.\n */\nfunction countFactsByPlatformTarget(\n documents: readonly BridgeFactsDocument[],\n matchesFact: (fact: BridgeFact) => boolean,\n): Array<{\n platform: BridgePlatform;\n target: BridgeTarget | null;\n count: number;\n}> {\n const distinctFacts = new Map<\n string,\n {\n platform: BridgePlatform;\n target: BridgeTarget | null;\n keys: Set<string>;\n }\n >();\n for (const document of documents) {\n const target = limitationTarget(document);\n // BridgeTarget은 닫힌 어휘라 문자열화된 null과 충돌하지 않는다.\n const groupKey = `${document.platform}\\u0000${target}`;\n for (const fact of document.facts) {\n if (!matchesFact(fact)) continue;\n const group = distinctFacts.get(groupKey) ?? {\n platform: document.platform,\n target,\n keys: new Set<string>(),\n };\n group.keys.add(unjoinedFactKey(fact));\n distinctFacts.set(groupKey, group);\n }\n }\n return [...distinctFacts.values()].map(({ platform, target, keys }) => ({\n platform,\n target,\n count: keys.size,\n }));\n}\n\n/**\n * 같은 위치의 중복 사실을 한 번만 세는 키를 만든다.\n *\n * 위치 기준은 증거 dedup과 같지만 symbol은 비교하지 않아, 같은 위치의 서로\n * 다른 symbol은 하나로 센다. `channel`은 null일 수 있어 구분자 결합 대신\n * JSON으로 만든다. 그래야 미귀속 핸들러와 이름이 `null`인 채널의 사실이\n * 같은 키로 합쳐지지 않는다.\n */\nfunction unjoinedFactKey(fact: BridgeFact): string {\n const { path, line, column } = fact.location;\n return JSON.stringify([\n fact.kind,\n fact.channel,\n fact.method ?? null,\n path,\n line,\n column,\n ]);\n}\n\n/** 이름이 리터럴이 아니어서 조인하지 못한 채널 사실인지 확인한다. */\nfunction isUnjoinedDynamicChannel(fact: BridgeFact): boolean {\n return (\n fact.dynamic &&\n (fact.kind === 'channel-create' || fact.kind === 'channel-register')\n );\n}\n\n/** 이름이 리터럴이 아니어서 조인하지 못한 메서드 사실인지 확인한다. */\nfunction isUnjoinedDynamicMethod(fact: BridgeFact): boolean {\n return (\n fact.dynamic &&\n (fact.kind === 'method-invoke' || fact.kind === 'method-handle')\n );\n}\n\n/**\n * 어느 채널에 속하는지 몰라 조인하지 못한 핸들러 사실인지 확인한다.\n *\n * dynamic 사실은 위에서 이미 세므로 여기서 다시 세지 않는다.\n */\nfunction isUnattributedHandler(fact: BridgeFact): boolean {\n return fact.kind === 'method-handle' && fact.channel === null && !fact.dynamic;\n}\n\n/** 이름이 리터럴이 아니어서 조인하지 못한 모듈 import·컴포넌트 require 사실인지 확인한다. */\nfunction isUnjoinedDynamicImport(fact: BridgeFact): boolean {\n return (\n fact.dynamic &&\n (fact.kind === 'module-import' || fact.kind === 'component-require')\n );\n}\n\n/** 이름이 리터럴이 아니어서 조인하지 못한 모듈·컴포넌트 export 사실인지 확인한다. */\nfunction isUnjoinedDynamicExport(fact: BridgeFact): boolean {\n return (\n fact.dynamic &&\n (fact.kind === 'module-export' || fact.kind === 'component-export')\n );\n}\n\n/** 생성 시각 차이가 하루를 넘을 때 교차 입력 한계를 만든다. */\nfunction freshnessLimitation(\n documents: readonly BridgeFactsDocument[],\n): JoinLimitation | undefined {\n if (documents.length < 2) return undefined;\n let earliest = Number.POSITIVE_INFINITY;\n let latest = Number.NEGATIVE_INFINITY;\n for (const document of documents) {\n const timestamp = Date.parse(document.generatedAt);\n earliest = Math.min(earliest, timestamp);\n latest = Math.max(latest, timestamp);\n }\n const difference = latest - earliest;\n if (difference <= millisecondsPerDay) return undefined;\n const hours = Math.round(difference / millisecondsPerHour);\n return {\n platform: 'cross-platform',\n target: null,\n tool: 'isthmus',\n origin: 'consumer',\n message: `input-freshness: bridge documents differ by ${hours} hours`,\n };\n}\n\n/** limitation을 플랫폼·target·도구·문장 순으로 고정한다. */\nexport function compareLimitations(left: JoinLimitation, right: JoinLimitation): number {\n return (\n compareStrings(left.platform, right.platform) ||\n compareTargets(left.target, right.target) ||\n compareStrings(left.tool, right.tool) ||\n compareStrings(left.message, right.message) ||\n compareOptionalStrings(left.origin, right.origin) ||\n compareStrings(JSON.stringify(left.channels ?? null), JSON.stringify(right.channels ?? null))\n );\n}\n\n/** target을 문자열 순으로 고정하고 귀속이 없는(null) 한계를 뒤에 둔다. */\nfunction compareTargets(\n left: BridgeTarget | null,\n right: BridgeTarget | null,\n): number {\n if (left === right) return 0;\n if (left === null) return 1;\n if (right === null) return -1;\n return compareStrings(left, right);\n}\n\n/** 메서드 키별로 호출과 핸들러 증거를 모은다. */\nfunction collectMethodGroups(\n documents: readonly BridgeFactsDocument[],\n): Map<string, MutableMethodGroup> {\n const groups = new Map<string, MutableMethodGroup>();\n for (const document of documents) collectDocumentMethods(document, groups);\n for (const group of groups.values()) {\n sortUniqueEndpoints(group.invocations);\n sortUniqueEndpoints(group.handlers);\n }\n return groups;\n}\n\n/** 증거 위치와 심볼을 정렬하고 같은 증거를 한 번만 남긴다. */\nfunction sortUniqueEndpoints(endpoints: BridgeEndpoint[]): void {\n endpoints.sort(compareEndpoints);\n if (endpoints.length < 2) return;\n let writeIndex = 1;\n for (let readIndex = 1; readIndex < endpoints.length; readIndex++) {\n const previous = endpoints[writeIndex - 1];\n const current = endpoints[readIndex];\n if (\n previous !== undefined &&\n current !== undefined &&\n compareEndpoints(previous, current) !== 0\n ) {\n endpoints[writeIndex] = current;\n writeIndex++;\n }\n }\n endpoints.length = writeIndex;\n}\n\n/** 증거 위치와 선택 심볼을 완전한 결정 순서로 비교한다. */\nfunction compareEndpoints(left: BridgeEndpoint, right: BridgeEndpoint): number {\n const locationOrder =\n compareStrings(left.platform, right.platform) ||\n compareStrings(left.location.path, right.location.path) ||\n left.location.line - right.location.line ||\n left.location.column - right.location.column;\n if (locationOrder !== 0) return locationOrder;\n const languageOrder = compareOptionalStrings(left.sourceLanguage, right.sourceLanguage);\n if (languageOrder !== 0) return languageOrder;\n if (left.symbol === undefined) return right.symbol === undefined ? 0 : 1;\n if (right.symbol === undefined) return -1;\n return (\n compareStrings(left.symbol.qualifiedName, right.symbol.qualifiedName) ||\n compareOptionalStrings(left.symbol.usr, right.symbol.usr)\n );\n}\n\n/** 존재하는 선택 문자열을 없는 값보다 먼저 두고 비교한다. */\nfunction compareOptionalStrings(\n left: string | undefined,\n right: string | undefined,\n): number {\n if (left === undefined) return right === undefined ? 0 : 1;\n if (right === undefined) return -1;\n return compareStrings(left, right);\n}\n\n/** 문서 하나의 정적 메서드 사실을 그룹에 추가한다. */\nfunction collectDocumentMethods(\n document: BridgeFactsDocument,\n groups: Map<string, MutableMethodGroup>,\n): void {\n if (document.target === null) return;\n for (const fact of document.facts) {\n if (!isStaticMethodFact(fact)) continue;\n const key = `${document.target}\\u0000${fact.channel}\\u0000${fact.method}`;\n const group = groups.get(key) ?? createMethodGroup(document.target, fact.channel, fact.method);\n const endpoints = fact.kind === 'method-invoke' ? group.invocations : group.handlers;\n endpoints.push(toEndpoint(document.platform, fact));\n groups.set(key, group);\n }\n}\n\n/** 조인 가능한 정적 메서드 호출·핸들러 사실인지 확인한다. */\nfunction isStaticMethodFact(\n fact: BridgeFactsDocument['facts'][number],\n): fact is BridgeFactsDocument['facts'][number] & {\n channel: string;\n method: string;\n} {\n return (\n (fact.kind === 'method-invoke' || fact.kind === 'method-handle') &&\n !fact.dynamic &&\n fact.channel !== null &&\n fact.method !== undefined\n );\n}\n\n/** 빈 메서드 그룹을 만든다. */\nfunction createMethodGroup(\n target: BridgeTarget,\n channel: string,\n method: string,\n): MutableMethodGroup {\n return { target, channel, method, invocations: [], handlers: [] };\n}\n\n/** 채널 키별로 생성과 등록 증거를 모은다. */\nfunction collectChannelGroups(\n documents: readonly BridgeFactsDocument[],\n): Map<string, MutableChannelGroup> {\n const groups = new Map<string, MutableChannelGroup>();\n for (const document of documents) collectDocumentChannels(document, groups);\n for (const group of groups.values()) {\n sortUniqueEndpoints(group.creations);\n sortUniqueEndpoints(group.registrations);\n }\n return groups;\n}\n\n/** 문서 하나의 정적 채널 사실을 그룹에 추가한다. */\nfunction collectDocumentChannels(\n document: BridgeFactsDocument,\n groups: Map<string, MutableChannelGroup>,\n): void {\n if (document.target === null) return;\n for (const fact of document.facts) {\n if (!isStaticChannelFact(fact)) continue;\n const key = `${document.target}\\u0000${fact.channel}`;\n const group = groups.get(key) ?? createChannelGroup(document.target, fact.channel);\n const endpoints = fact.kind === 'channel-create' ? group.creations : group.registrations;\n endpoints.push(toEndpoint(document.platform, fact));\n groups.set(key, group);\n }\n}\n\n/** 조인 가능한 정적 채널 생성·등록 사실인지 확인한다. */\nfunction isStaticChannelFact(\n fact: BridgeFactsDocument['facts'][number],\n): fact is BridgeFactsDocument['facts'][number] & { channel: string } {\n return (\n (fact.kind === 'channel-create' || fact.kind === 'channel-register') &&\n !fact.dynamic &&\n fact.channel !== null\n );\n}\n\n/** 빈 채널 그룹을 만든다. */\nfunction createChannelGroup(\n target: BridgeTarget,\n channel: string,\n): MutableChannelGroup {\n return { target, channel, creations: [], registrations: [] };\n}\n\n/**\n * 모듈·컴포넌트 이름 키별로 호출 측·수신 측 증거를 모은다.\n *\n * RN의 `module-import`↔`module-export`와 `component-require`↔`component-export`는\n * 같은 (target, channel=모듈·컴포넌트 이름) 조인 규칙을 공유하므로 수집기를\n * 재사용한다. dynamic 사실은 조인하지 않고 소비자 계수 한계로 넘긴다.\n */\nfunction collectNameGroups(\n documents: readonly BridgeFactsDocument[],\n callerKind: BridgeFact['kind'],\n receiverKind: BridgeFact['kind'],\n): Map<string, MutableNameGroup> {\n const groups = new Map<string, MutableNameGroup>();\n for (const document of documents) {\n if (document.target === null) continue;\n for (const fact of document.facts) {\n if (fact.dynamic || fact.channel === null) continue;\n if (fact.kind !== callerKind && fact.kind !== receiverKind) continue;\n const key = `${document.target}\\u0000${fact.channel}`;\n const group = groups.get(key) ?? {\n target: document.target,\n channel: fact.channel,\n callers: [],\n receivers: [],\n };\n const endpoints = fact.kind === callerKind ? group.callers : group.receivers;\n endpoints.push(toEndpoint(document.platform, fact));\n groups.set(key, group);\n }\n }\n for (const group of groups.values()) {\n sortUniqueEndpoints(group.callers);\n sortUniqueEndpoints(group.receivers);\n }\n return groups;\n}\n\n/** 이름 그룹 하나의 mechanism-aware 분류 결과다. */\ninterface NameClassification {\n readonly matched: MatchedBoundaryName[];\n readonly unexported: UnexportedBoundaryName[];\n readonly unrequired: UnrequiredBoundaryName[];\n}\n\n/**\n * 이름 그룹을 mechanism 규칙으로 매치·미수출·미호출로 나눈다.\n *\n * 한 이름 아래 호출자·수신자가 mechanism이 섞여 있을 수 있으므로 그룹\n * 전체가 아니라 증거 쌍 단위로 판정한다. 만족한 호출자·도달한 수신자만\n * 매치로 고정하고, 나머지는 각각 미수출·미호출 증거로 남긴다 — 한 이름이\n * 두 컬렉션에 동시에 나타날 수 있다.\n */\nfunction classifyNameGroups(\n groups: Map<string, MutableNameGroup>,\n callerKind: 'module-import' | 'component-require',\n): NameClassification {\n const compatible = (caller: BridgeEndpoint, receiver: BridgeEndpoint) =>\n boundaryCompatible(callerKind, caller, receiver);\n const matched: MatchedBoundaryName[] = [];\n const unexported: UnexportedBoundaryName[] = [];\n const unrequired: UnrequiredBoundaryName[] = [];\n for (const group of groups.values()) {\n const satisfied = group.callers.filter((caller) =>\n group.receivers.some((receiver) => compatible(caller, receiver)));\n const unsatisfied = group.callers.filter((caller) =>\n !group.receivers.some((receiver) => compatible(caller, receiver)));\n const reached = group.receivers.filter((receiver) =>\n group.callers.some((caller) => compatible(caller, receiver)));\n const unreached = group.receivers.filter((receiver) =>\n !group.callers.some((caller) => compatible(caller, receiver)));\n // 만족한 호출자가 있으면 그와 호환되는 수신자가 존재하므로 도달한\n // 수신자도 비어 있지 않다.\n if (satisfied.length > 0) {\n matched.push({\n target: group.target,\n channel: group.channel,\n callers: satisfied,\n receivers: reached,\n });\n }\n if (unsatisfied.length > 0) {\n // unsatisfied 호출자에게는 이 그룹의 수신자가 모두 도달 불가다 —\n // 호환되는 수신자가 하나라도 있었다면 그 호출자는 만족했을 것이다.\n // mechanism이 두 값뿐이라 미만족 호출자는 항상 한 mechanism으로\n // 모인다(비어 있지 않은 수신자가 한 mechanism이면 그 mechanism의\n // 호출자는 만족한다) — 호출자 mechanism 구성은 엔트리 증거에 남고\n // 보고 층이 Expo의 폴백 없는 require(error)와 코어 require의 미해결\n // 상호운용(warning)을 구분한다.\n unexported.push({\n target: group.target,\n channel: group.channel,\n callers: unsatisfied,\n ...(group.receivers.length === 0\n ? {}\n : { incompatibleReceivers: group.receivers }),\n });\n }\n if (unreached.length > 0) {\n // 도달 못한 수신자에게는 모든 호출자가 비호환이다 — 호환 호출자가\n // 있었다면 도달했을 것이다. 호출자가 있으면 mechanism 불일치 증거다.\n unrequired.push({\n target: group.target,\n channel: group.channel,\n receivers: unreached,\n ...(group.callers.length === 0\n ? {}\n : { incompatibleCallers: group.callers }),\n });\n }\n }\n matched.sort(compareChannels);\n unexported.sort(compareChannels);\n unrequired.sort(compareChannels);\n return { matched, unexported, unrequired };\n}\n\n/**\n * mechanism이 다른 호출·수신 쌍이 실제로 연결되는지 판정한다.\n *\n * `module-import`: Expo의 `requireNativeModule`·`requireOptionalNativeModule`은\n * `TurboModuleRegistry` 폴백이 있어 `expo` 호출자는 어느 mechanism의 export도\n * 만족시킨다. 코어 호출자는 코어 export만 도달한다.\n * `component-require`: `requireNativeViewManager`에는 그런 폴백이 없어\n * 같은 mechanism끼리만 잇는다. 생략된 mechanism은 `core`로 읽는다.\n */\nfunction boundaryCompatible(\n callerKind: 'module-import' | 'component-require',\n caller: BridgeEndpoint,\n receiver: BridgeEndpoint,\n): boolean {\n const callerMechanism = caller.mechanism ?? 'core';\n const receiverMechanism = receiver.mechanism ?? 'core';\n if (callerKind === 'module-import') {\n return callerMechanism === 'expo' || receiverMechanism === 'core';\n }\n return callerMechanism === receiverMechanism;\n}\n\n/** 사실을 플랫폼이 포함된 증거 위치로 바꾼다. */\nfunction toEndpoint(\n platform: BridgePlatform,\n fact: BridgeFactsDocument['facts'][number],\n): BridgeEndpoint {\n return {\n platform, location: fact.location,\n ...(fact.symbol === undefined ? {} : { symbol: fact.symbol }),\n ...(fact.mechanism === undefined ? {} : { mechanism: fact.mechanism }),\n ...(fact.optional === undefined ? {} : { optional: fact.optional }),\n ...(fact.sourceLanguage === undefined ? {} : { sourceLanguage: fact.sourceLanguage }),\n ...(fact.handlerScope === undefined ? {} : { handlerScope: fact.handlerScope, dependencies: fact.dependencies! }),\n };\n}\n\n/** 채널 결과를 target과 이름 순으로 고정한다. */\nfunction compareChannels(left: ChannelKey, right: ChannelKey): number {\n return (\n compareStrings(left.target, right.target) ||\n compareStrings(left.channel, right.channel)\n );\n}\n\n/** 결정적 정렬에 필요한 논리 채널 키다. */\ntype ChannelKey = Pick<MatchedChannel, 'target' | 'channel'>;\n\n/** 메서드 결과를 target·채널·메서드 순으로 고정한다. */\nfunction compareMethodKeys(left: MethodKey, right: MethodKey): number {\n return (\n compareStrings(left.target, right.target) ||\n compareStrings(left.channel, right.channel) ||\n compareStrings(left.method, right.method)\n );\n}\n\n/** 결정적 정렬에 필요한 논리 메서드 키다. */\ntype MethodKey = Pick<MatchedMethod, 'target' | 'channel' | 'method'>;\n\n/** 조립 중인 채널 증거 그룹이다. */\ninterface MutableChannelGroup extends MatchedChannel {\n readonly creations: BridgeEndpoint[];\n readonly registrations: BridgeEndpoint[];\n}\n\n/** 조립 중인 메서드 증거 그룹이다. */\ninterface MutableMethodGroup extends MatchedMethod {\n readonly invocations: BridgeEndpoint[];\n readonly handlers: BridgeEndpoint[];\n}\n\n/** 조립 중인 모듈·컴포넌트 이름 증거 그룹이다. */\ninterface MutableNameGroup extends MatchedBoundaryName {\n readonly callers: BridgeEndpoint[];\n readonly receivers: BridgeEndpoint[];\n}\n\nconst millisecondsPerHour = 60 * 60 * 1_000;\nconst millisecondsPerDay = 24 * millisecondsPerHour;\n"]}
|
package/dist/join/messages.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BridgeHandlerDependency, BridgeHandlerScope, BridgeMessageDocument } from '../exchange/messages.ts';
|
|
1
|
+
import type { BridgeHandlerDependency, BridgeHandlerScope, BridgeMessageDocument, BridgeMessageTransport } from '../exchange/messages.ts';
|
|
2
2
|
import type { BridgeEndpoint, JoinLimitation } from './join.ts';
|
|
3
3
|
/** 동적 접두사의 원래 표현식도 근거에 보존한다. */
|
|
4
4
|
export interface MessageEndpoint extends BridgeEndpoint {
|
|
@@ -6,18 +6,21 @@ export interface MessageEndpoint extends BridgeEndpoint {
|
|
|
6
6
|
readonly handlerScope?: BridgeHandlerScope;
|
|
7
7
|
readonly dependencies?: readonly BridgeHandlerDependency[];
|
|
8
8
|
}
|
|
9
|
-
/** literal 주소와 prefix 후보를 다른 키로 연결한다. */
|
|
9
|
+
/** literal 주소와 prefix 후보를 다른 키로 연결한다. transport는 같은 주소라도 섞지 않는다. */
|
|
10
10
|
export interface MessageBridgeRoute {
|
|
11
|
+
readonly transport: BridgeMessageTransport;
|
|
11
12
|
readonly channel: string;
|
|
12
13
|
readonly matching: 'literal' | 'prefix';
|
|
13
14
|
readonly senders: readonly MessageEndpoint[];
|
|
14
15
|
readonly handlers: readonly MessageEndpoint[];
|
|
15
16
|
}
|
|
16
|
-
/**
|
|
17
|
+
/** v2 transport 범위에서 관찰한 경계와 끝내 연결하지 못한 사실이다. */
|
|
17
18
|
export interface MessageBridgeJoin {
|
|
18
19
|
readonly routes: readonly MessageBridgeRoute[];
|
|
19
20
|
readonly unresolved: readonly MessageEndpoint[];
|
|
20
21
|
readonly limitations: readonly JoinLimitation[];
|
|
22
|
+
/** 입력 v2 문서 전체가 관찰한 fact 수다. 조인 여부와 무관한 관찰량이다. */
|
|
23
|
+
readonly observedFacts: number;
|
|
21
24
|
}
|
|
22
|
-
/** 서로 같은 project의 양쪽
|
|
25
|
+
/** 서로 같은 project의 양쪽 v2 문서만 조인하며 transport와 MethodChannel 키 공간을 분리한다. */
|
|
23
26
|
export declare function joinMessageBridges(documents: readonly BridgeMessageDocument[], project: string): MessageBridgeJoin;
|