@apifuse/provider-sdk 2.2.0-beta.55 → 2.2.0-beta.57
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/CHANGELOG.md +8 -0
- package/bin/apifuse-pack-types.ts +121 -0
- package/dist/cli/migrate-operation-declaration.d.ts +7 -0
- package/dist/cli/migrate-operation-declaration.js +52 -12
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/runtime/proxy-telemetry.d.ts +53 -2
- package/dist/runtime/proxy-telemetry.js +106 -65
- package/dist/runtime/request-telemetry.d.ts +70 -0
- package/dist/runtime/request-telemetry.js +228 -0
- package/dist/server/index.d.ts +3 -1
- package/dist/server/index.js +1 -0
- package/dist/server/serve-implementation.js +58 -20
- package/package.json +1 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-index.ts.txt +3 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-one.ts.txt +6 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-two.ts.txt +6 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-mixed-index.ts.txt +14 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-registry.ts.txt +3 -0
- package/src/cli/migrate-operation-declaration.ts +75 -10
- package/src/index.ts +13 -0
- package/src/runtime/proxy-telemetry.ts +160 -74
- package/src/runtime/request-telemetry.ts +376 -0
- package/src/server/index.ts +14 -0
- package/src/server/serve-implementation.ts +93 -21
|
@@ -26,6 +26,7 @@ import { getProviderBaseUrl } from "../runtime/provider.js";
|
|
|
26
26
|
import { createOcrClientFromEnv } from "../runtime/ocr.js";
|
|
27
27
|
import { PROXY_AUTH_IP_DENIED_CODE, PROXY_EDGE_AUTH_REJECTED_CODE, PROXY_POOL_EXHAUSTED_CODE, } from "../runtime/proxy-errors.js";
|
|
28
28
|
import { PROVIDER_TELEMETRY_HEADER, ProxyTelemetryCollector, } from "../runtime/proxy-telemetry.js";
|
|
29
|
+
import { closedEnum, RequestTelemetry, tenantOpaqueKeys, } from "../runtime/request-telemetry.js";
|
|
29
30
|
import { createUnsupportedResolverClient, } from "../runtime/resolver-shared.js";
|
|
30
31
|
import { assertRequiredSecretsPresent, listMissingRequiredSecrets, MISSING_SECRET_CODE, } from "../runtime/secrets.js";
|
|
31
32
|
import { createProviderRuntimeStateFromEnv, createUnsupportedProviderRuntimeState, } from "../runtime/state.js";
|
|
@@ -75,6 +76,16 @@ function providerErrorCode(error) {
|
|
|
75
76
|
}
|
|
76
77
|
const AUTH_FLOW_LOCALES = ["en", "ko", "ja"];
|
|
77
78
|
const retryResponseMeta = new WeakMap();
|
|
79
|
+
const RETRY_LAST_ERROR_CODES = [
|
|
80
|
+
"transport_cancelled",
|
|
81
|
+
"transport_timeout",
|
|
82
|
+
"transport_network_error",
|
|
83
|
+
"upstream_http_error",
|
|
84
|
+
"other",
|
|
85
|
+
];
|
|
86
|
+
function tenantRetryLastErrorCode(value) {
|
|
87
|
+
return RETRY_LAST_ERROR_CODES.find((candidate) => candidate === value) ?? "other";
|
|
88
|
+
}
|
|
78
89
|
const STATEFUL_INTERNAL_OPERATIONS_ROUTE = "/__apifuse/stateful/operations";
|
|
79
90
|
const STATEFUL_FORWARDING_SOURCE_POD_HEADER = "x-apifuse-stateful-source-pod";
|
|
80
91
|
const DEFAULT_STATEFUL_FORWARDING_MAX_SKEW_MS = 5 * 60_000;
|
|
@@ -409,7 +420,7 @@ function createProviderContext(provider, request, operationId, options, state =
|
|
|
409
420
|
const proxyClientOptions = {
|
|
410
421
|
upstream: { proxy: provider.proxy },
|
|
411
422
|
affinityKey: resolveProviderProxyAffinityKey(provider, request, operationId),
|
|
412
|
-
telemetry: scope.
|
|
423
|
+
telemetry: scope.telemetry.proxy,
|
|
413
424
|
engineCredentials: engineProxyCredentials,
|
|
414
425
|
};
|
|
415
426
|
const resolverIdentityScope = resolveProviderResolverIdentityScope(provider, proxyClientOptions.affinityKey, request.requestId);
|
|
@@ -417,7 +428,7 @@ function createProviderContext(provider, request, operationId, options, state =
|
|
|
417
428
|
const stealthClientOptions = {
|
|
418
429
|
upstream: proxyClientOptions.upstream,
|
|
419
430
|
affinityKey: proxyClientOptions.affinityKey,
|
|
420
|
-
telemetry: scope.
|
|
431
|
+
telemetry: scope.telemetry.proxy,
|
|
421
432
|
engineCredentials: engineProxyCredentials,
|
|
422
433
|
...(signal ? { signal } : {}),
|
|
423
434
|
...(provider.stealth ? { stealth: provider.stealth } : {}),
|
|
@@ -564,14 +575,14 @@ function createAuthFlowContext(provider, request, options, state, scope, signal)
|
|
|
564
575
|
const proxyClientOptions = {
|
|
565
576
|
upstream: { proxy: provider.proxy },
|
|
566
577
|
affinityKey: resolveAuthFlowProxyAffinityKey(provider, request),
|
|
567
|
-
telemetry: scope.
|
|
578
|
+
telemetry: scope.telemetry.proxy,
|
|
568
579
|
engineCredentials: engineProxyCredentials,
|
|
569
580
|
};
|
|
570
581
|
const resolverIdentityScope = resolveProviderResolverIdentityScope(provider, proxyClientOptions.affinityKey, request.requestId);
|
|
571
582
|
const stealthClientOptions = {
|
|
572
583
|
upstream: proxyClientOptions.upstream,
|
|
573
584
|
affinityKey: proxyClientOptions.affinityKey,
|
|
574
|
-
telemetry: scope.
|
|
585
|
+
telemetry: scope.telemetry.proxy,
|
|
575
586
|
engineCredentials: engineProxyCredentials,
|
|
576
587
|
...(signal ? { signal } : {}),
|
|
577
588
|
...(provider.stealth ? { stealth: provider.stealth } : {}),
|
|
@@ -1014,7 +1025,7 @@ function providerErrorCauseChain(error) {
|
|
|
1014
1025
|
}
|
|
1015
1026
|
return frames.length > 0 ? frames : undefined;
|
|
1016
1027
|
}
|
|
1017
|
-
function logProviderError(logger, provider, kind, route, requestId, error, status, cost, declaredErrorCode,
|
|
1028
|
+
function logProviderError(logger, provider, kind, route, requestId, error, status, cost, declaredErrorCode, telemetry, observabilityDetails, correlation = {}) {
|
|
1018
1029
|
const providerCode = isProviderError(error) ? providerErrorCode(error) : undefined;
|
|
1019
1030
|
const code = isProviderError(error)
|
|
1020
1031
|
? (providerCode ?? "provider_error")
|
|
@@ -1033,7 +1044,7 @@ function logProviderError(logger, provider, kind, route, requestId, error, statu
|
|
|
1033
1044
|
typeof providerCode === "string" &&
|
|
1034
1045
|
!SDK_OWNED_PROVIDER_ERROR_CODES.has(providerCode) &&
|
|
1035
1046
|
declaredErrorCode === undefined;
|
|
1036
|
-
const
|
|
1047
|
+
const telemetryPayload = telemetry?.toLogPayload();
|
|
1037
1048
|
const emit = typeof logger === "function" ? logger : defaultProviderServerLogger;
|
|
1038
1049
|
// The logger is caller-supplied and may mutate the event synchronously.
|
|
1039
1050
|
// Give it an independent snapshot so those mutations cannot corrupt the
|
|
@@ -1058,7 +1069,7 @@ function logProviderError(logger, provider, kind, route, requestId, error, statu
|
|
|
1058
1069
|
: {}),
|
|
1059
1070
|
status,
|
|
1060
1071
|
...cost,
|
|
1061
|
-
...(
|
|
1072
|
+
...(telemetryPayload ?? {}),
|
|
1062
1073
|
code,
|
|
1063
1074
|
errorClass,
|
|
1064
1075
|
message,
|
|
@@ -1093,8 +1104,8 @@ function logProviderCleanupError(logger, provider, kind, operationId, requestId,
|
|
|
1093
1104
|
message,
|
|
1094
1105
|
});
|
|
1095
1106
|
}
|
|
1096
|
-
function logProviderSuccess(logger, provider, kind, route, requestId, status, cost,
|
|
1097
|
-
const
|
|
1107
|
+
function logProviderSuccess(logger, provider, kind, route, requestId, status, cost, telemetry, correlation = {}) {
|
|
1108
|
+
const telemetryPayload = telemetry?.toLogPayload();
|
|
1098
1109
|
const emit = typeof logger === "function" ? logger : defaultProviderServerLogger;
|
|
1099
1110
|
emit({
|
|
1100
1111
|
level: "info",
|
|
@@ -1113,7 +1124,7 @@ function logProviderSuccess(logger, provider, kind, route, requestId, status, co
|
|
|
1113
1124
|
: {}),
|
|
1114
1125
|
status,
|
|
1115
1126
|
...cost,
|
|
1116
|
-
...(
|
|
1127
|
+
...(telemetryPayload ?? {}),
|
|
1117
1128
|
});
|
|
1118
1129
|
}
|
|
1119
1130
|
const STREAM_CLEANUP_TIMEOUT_MS = 100;
|
|
@@ -1165,7 +1176,6 @@ function requestTraceId(headers, requestId) {
|
|
|
1165
1176
|
function createRequestScope(input) {
|
|
1166
1177
|
const requestCost = startRequestCost();
|
|
1167
1178
|
const traceConfig = resolveTraceConfigFromEnv();
|
|
1168
|
-
const proxyTelemetry = new ProxyTelemetryCollector();
|
|
1169
1179
|
const details = {
|
|
1170
1180
|
route: input.route,
|
|
1171
1181
|
requestId: input.requestId,
|
|
@@ -1188,6 +1198,9 @@ function createRequestScope(input) {
|
|
|
1188
1198
|
...(initialTraceId ? { traceId: initialTraceId } : {}),
|
|
1189
1199
|
})
|
|
1190
1200
|
: createTraceContext();
|
|
1201
|
+
const proxyCollector = new ProxyTelemetryCollector();
|
|
1202
|
+
const telemetry = new RequestTelemetry(trace);
|
|
1203
|
+
telemetry.register(proxyCollector);
|
|
1191
1204
|
let rootRunner = (fn) => fn();
|
|
1192
1205
|
let resolveRoot;
|
|
1193
1206
|
const rootTerminal = new Promise((resolve) => {
|
|
@@ -1233,7 +1246,7 @@ function createRequestScope(input) {
|
|
|
1233
1246
|
await Promise.all(streamCleanups.map(runCleanupEntry));
|
|
1234
1247
|
};
|
|
1235
1248
|
const headerSnapshot = (error) => {
|
|
1236
|
-
const providerTelemetryHeader =
|
|
1249
|
+
const providerTelemetryHeader = telemetry.toHeaderValue();
|
|
1237
1250
|
const declaredErrorCode = error === undefined ? undefined : input.declaredErrorCode?.(error);
|
|
1238
1251
|
const errorObservability = error === undefined ? undefined : errorObservabilityDetails(error, declaredErrorCode);
|
|
1239
1252
|
return {
|
|
@@ -1261,7 +1274,7 @@ function createRequestScope(input) {
|
|
|
1261
1274
|
};
|
|
1262
1275
|
const scope = {
|
|
1263
1276
|
trace,
|
|
1264
|
-
|
|
1277
|
+
telemetry,
|
|
1265
1278
|
enrich(enrichment) {
|
|
1266
1279
|
if (terminalOutcome)
|
|
1267
1280
|
return;
|
|
@@ -1334,10 +1347,10 @@ function createRequestScope(input) {
|
|
|
1334
1347
|
const cost = finishRequestCost(requestCost);
|
|
1335
1348
|
try {
|
|
1336
1349
|
if (error === undefined) {
|
|
1337
|
-
logProviderSuccess(input.logger, input.provider, input.kind, details.route, details.requestId, status, cost,
|
|
1350
|
+
logProviderSuccess(input.logger, input.provider, input.kind, details.route, details.requestId, status, cost, telemetry, details.correlation);
|
|
1338
1351
|
}
|
|
1339
1352
|
else {
|
|
1340
|
-
logProviderError(input.logger, input.provider, input.kind, details.route, details.requestId, error, status, cost, declaredErrorCode,
|
|
1353
|
+
logProviderError(input.logger, input.provider, input.kind, details.route, details.requestId, error, status, cost, declaredErrorCode, telemetry, finishedResult.errorObservability, details.correlation);
|
|
1341
1354
|
}
|
|
1342
1355
|
}
|
|
1343
1356
|
catch {
|
|
@@ -1407,18 +1420,43 @@ function toJsonSuccessResponse(result, ctx) {
|
|
|
1407
1420
|
}
|
|
1408
1421
|
const cacheMeta = ctx && "cache" in ctx ? ctx.cache.responseMeta() : undefined;
|
|
1409
1422
|
const retryMeta = ctx ? retryResponseMeta.get(ctx) : undefined;
|
|
1423
|
+
const cache = cacheMeta
|
|
1424
|
+
? {
|
|
1425
|
+
hit: cacheMeta.hit,
|
|
1426
|
+
stale: cacheMeta.stale,
|
|
1427
|
+
// TODO(owner): keep or remove implementation-shaped cache keys from tenant meta.
|
|
1428
|
+
keys: tenantOpaqueKeys(cacheMeta.keys),
|
|
1429
|
+
...(cacheMeta.source ? { source: closedEnum(cacheMeta.source) } : {}),
|
|
1430
|
+
}
|
|
1431
|
+
: undefined;
|
|
1432
|
+
const retry = retryMeta
|
|
1433
|
+
? {
|
|
1434
|
+
attempts: retryMeta.attempts,
|
|
1435
|
+
retries: retryMeta.retries,
|
|
1436
|
+
...(retryMeta.preset ? { preset: closedEnum(retryMeta.preset) } : {}),
|
|
1437
|
+
transport: closedEnum(retryMeta.transport),
|
|
1438
|
+
...(retryMeta.lastErrorCode
|
|
1439
|
+
? {
|
|
1440
|
+
lastErrorCode: closedEnum(tenantRetryLastErrorCode(retryMeta.lastErrorCode)),
|
|
1441
|
+
}
|
|
1442
|
+
: {}),
|
|
1443
|
+
...(retryMeta.lastStatus ? { lastStatus: retryMeta.lastStatus } : {}),
|
|
1444
|
+
}
|
|
1445
|
+
: undefined;
|
|
1410
1446
|
const meta = cacheMeta || retryMeta
|
|
1411
1447
|
? {
|
|
1412
|
-
...(
|
|
1448
|
+
...(cache
|
|
1413
1449
|
? {
|
|
1414
|
-
cached:
|
|
1415
|
-
stale:
|
|
1416
|
-
cache
|
|
1450
|
+
cached: cache.hit,
|
|
1451
|
+
stale: cache.stale,
|
|
1452
|
+
cache,
|
|
1417
1453
|
}
|
|
1418
1454
|
: {}),
|
|
1419
|
-
...(
|
|
1455
|
+
...(retry ? { retry } : {}),
|
|
1420
1456
|
}
|
|
1421
1457
|
: undefined;
|
|
1458
|
+
const _neutralMeta = meta;
|
|
1459
|
+
void _neutralMeta;
|
|
1422
1460
|
return {
|
|
1423
1461
|
data: result,
|
|
1424
1462
|
...(meta ? { meta } : {}),
|
package/package.json
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { makeRegistry } from "./operations/registry";
|
|
2
|
+
|
|
3
|
+
const literalOperation = defineOperation<ProviderContext>()({
|
|
4
|
+
annotations: { readOnly: true },
|
|
5
|
+
input: LiteralInputSchema,
|
|
6
|
+
output: LiteralOutputSchema,
|
|
7
|
+
handler: literalHandler,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const literalProvider = buildProvider({
|
|
11
|
+
operations: { literal: literalOperation },
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export default buildProvider({ operations: makeRegistry({ publicOnly: true }) });
|
|
@@ -141,6 +141,8 @@ type RepositoryMigrationContext = {
|
|
|
141
141
|
readonly operationSites?: ReadonlyMap<number, string>;
|
|
142
142
|
readonly excludedBindings?: ReadonlySet<string>;
|
|
143
143
|
readonly staticObjectResolver?: StaticObjectResolver;
|
|
144
|
+
readonly runtimeComposedInitializers?: ReadonlySet<number>;
|
|
145
|
+
readonly recordDiscoveredSites?: (count: number) => void;
|
|
144
146
|
};
|
|
145
147
|
|
|
146
148
|
type OperationSite = {
|
|
@@ -194,7 +196,9 @@ function migrateOperationDeclarationInternal(
|
|
|
194
196
|
options.operationIds,
|
|
195
197
|
context.operationSites,
|
|
196
198
|
context.excludedBindings,
|
|
199
|
+
context.runtimeComposedInitializers,
|
|
197
200
|
);
|
|
201
|
+
context.recordDiscoveredSites?.(discovery.discoveredCount);
|
|
198
202
|
if (discovery.refusals.length > 0) {
|
|
199
203
|
return { status: "refused", refusals: discovery.refusals };
|
|
200
204
|
}
|
|
@@ -1047,18 +1051,27 @@ function discoverOperationSites(
|
|
|
1047
1051
|
operationIds: ReadonlyMap<string, string> | undefined,
|
|
1048
1052
|
operationSites: ReadonlyMap<number, string> | undefined,
|
|
1049
1053
|
excludedBindings: ReadonlySet<string> | undefined,
|
|
1054
|
+
runtimeComposedInitializers: ReadonlySet<number> | undefined,
|
|
1050
1055
|
): {
|
|
1051
1056
|
readonly sites: OperationSite[];
|
|
1057
|
+
readonly discoveredCount: number;
|
|
1052
1058
|
readonly refusals: OperationDeclarationRefusal[];
|
|
1053
1059
|
} {
|
|
1054
1060
|
const sitesByStart = new Map<number, OperationSite>();
|
|
1061
|
+
const discoveredStarts = new Set<number>();
|
|
1055
1062
|
const localIds = new Map(operationIds ?? []);
|
|
1056
1063
|
const localExcludedBindings = new Set(excludedBindings ?? []);
|
|
1057
1064
|
const refusals: OperationDeclarationRefusal[] = [];
|
|
1058
1065
|
const operationFactories = collectSimpleOperationFactories(source);
|
|
1059
1066
|
const factoryCallIds = new Map<string, Set<string>>();
|
|
1060
1067
|
|
|
1061
|
-
for (const map of collectOperationsMaps(
|
|
1068
|
+
for (const map of collectOperationsMaps(
|
|
1069
|
+
source,
|
|
1070
|
+
constObjects,
|
|
1071
|
+
fileName,
|
|
1072
|
+
refusals,
|
|
1073
|
+
runtimeComposedInitializers,
|
|
1074
|
+
)) {
|
|
1062
1075
|
for (const property of map.properties) {
|
|
1063
1076
|
if (ts.isSpreadAssignment(property)) continue;
|
|
1064
1077
|
const key = staticPropertyName(property.name);
|
|
@@ -1145,12 +1158,15 @@ function discoverOperationSites(
|
|
|
1145
1158
|
if (ts.isCallExpression(node) && isOperationHelperCall(node)) {
|
|
1146
1159
|
const argument = operationArgument(node);
|
|
1147
1160
|
const bindingName = enclosingBindingName(node);
|
|
1161
|
+
const unwrappedArgument = unwrapExpression(argument);
|
|
1162
|
+
if (unwrappedArgument !== undefined && ts.isObjectLiteralExpression(unwrappedArgument)) {
|
|
1163
|
+
discoveredStarts.add(unwrappedArgument.getStart(source));
|
|
1164
|
+
}
|
|
1148
1165
|
if (bindingName !== undefined && localExcludedBindings.has(bindingName)) return;
|
|
1149
1166
|
const operationKey =
|
|
1150
1167
|
(bindingName === undefined ? undefined : localIds.get(bindingName)) ??
|
|
1151
1168
|
bindingName ??
|
|
1152
1169
|
"<anonymous>";
|
|
1153
|
-
const unwrappedArgument = unwrapExpression(argument);
|
|
1154
1170
|
if (unwrappedArgument === undefined || !ts.isObjectLiteralExpression(unwrappedArgument)) {
|
|
1155
1171
|
refusals.push(
|
|
1156
1172
|
refusal(
|
|
@@ -1181,10 +1197,12 @@ function discoverOperationSites(
|
|
|
1181
1197
|
ts.forEachChild(node, visit);
|
|
1182
1198
|
};
|
|
1183
1199
|
visit(source);
|
|
1200
|
+
for (const start of sitesByStart.keys()) discoveredStarts.add(start);
|
|
1184
1201
|
return {
|
|
1185
1202
|
sites: [...sitesByStart.values()].sort(
|
|
1186
1203
|
(left, right) => left.object.getStart(source) - right.object.getStart(source),
|
|
1187
1204
|
),
|
|
1205
|
+
discoveredCount: discoveredStarts.size,
|
|
1188
1206
|
refusals,
|
|
1189
1207
|
};
|
|
1190
1208
|
}
|
|
@@ -1223,6 +1241,7 @@ function collectOperationsMaps(
|
|
|
1223
1241
|
constObjects: ReadonlyMap<string, TS.ObjectLiteralExpression>,
|
|
1224
1242
|
fileName: string,
|
|
1225
1243
|
refusals: OperationDeclarationRefusal[],
|
|
1244
|
+
runtimeComposedInitializers?: ReadonlySet<number>,
|
|
1226
1245
|
): TS.ObjectLiteralExpression[] {
|
|
1227
1246
|
const maps = new Map<number, TS.ObjectLiteralExpression>();
|
|
1228
1247
|
const inspect = (expression: TS.Expression, label: string): void => {
|
|
@@ -1238,6 +1257,7 @@ function collectOperationsMaps(
|
|
|
1238
1257
|
return;
|
|
1239
1258
|
}
|
|
1240
1259
|
if (ts.isCallExpression(unwrapped)) {
|
|
1260
|
+
if (runtimeComposedInitializers?.has(expression.getStart(source)) === true) return;
|
|
1241
1261
|
refusals.push(
|
|
1242
1262
|
refusal(
|
|
1243
1263
|
fileName,
|
|
@@ -1893,6 +1913,7 @@ export type OperationDeclarationRepositoryResult =
|
|
|
1893
1913
|
readonly providerRoot: string;
|
|
1894
1914
|
readonly changedFiles: readonly string[];
|
|
1895
1915
|
readonly operationCount: number;
|
|
1916
|
+
readonly notes: readonly OperationDeclarationNote[];
|
|
1896
1917
|
readonly sidecar?: string;
|
|
1897
1918
|
readonly localeTodoCount: number;
|
|
1898
1919
|
}
|
|
@@ -1902,10 +1923,17 @@ export type OperationDeclarationRepositoryResult =
|
|
|
1902
1923
|
readonly refusals: readonly OperationDeclarationRefusal[];
|
|
1903
1924
|
/** Operations that were independently migratable before repository-atomic refusal. */
|
|
1904
1925
|
readonly operationCount: number;
|
|
1926
|
+
readonly notes: readonly OperationDeclarationNote[];
|
|
1905
1927
|
readonly changedFiles: readonly string[];
|
|
1906
1928
|
readonly localeTodoCount: number;
|
|
1907
1929
|
};
|
|
1908
1930
|
|
|
1931
|
+
export type OperationDeclarationNote = {
|
|
1932
|
+
readonly code: "runtime_composed_registry";
|
|
1933
|
+
readonly path: string;
|
|
1934
|
+
readonly initializer: string;
|
|
1935
|
+
};
|
|
1936
|
+
|
|
1909
1937
|
/** Run the file transform repository-wide, committing writes only if every file is provable. */
|
|
1910
1938
|
export function migrateOperationDeclarationRepository(
|
|
1911
1939
|
providerRootInput: string,
|
|
@@ -1920,6 +1948,7 @@ export function migrateOperationDeclarationRepository(
|
|
|
1920
1948
|
const todos: LocaleTodo[] = [];
|
|
1921
1949
|
const refusals: OperationDeclarationRefusal[] = [...repositoryIndex.refusals];
|
|
1922
1950
|
let operationCount = 0;
|
|
1951
|
+
let repositoryDiscoveredCount = 0;
|
|
1923
1952
|
|
|
1924
1953
|
for (const sourcePath of sourceFiles) {
|
|
1925
1954
|
const relativePath = slash(relative(providerRoot, sourcePath));
|
|
@@ -1934,6 +1963,10 @@ export function migrateOperationDeclarationRepository(
|
|
|
1934
1963
|
operationSites: repositoryIndex.operationSites.get(sourcePath),
|
|
1935
1964
|
excludedBindings: repositoryIndex.excludedBindings.get(sourcePath),
|
|
1936
1965
|
staticObjectResolver: repositoryIndex.staticObjectResolverFor(sourcePath),
|
|
1966
|
+
runtimeComposedInitializers: repositoryIndex.runtimeComposedInitializers.get(sourcePath),
|
|
1967
|
+
recordDiscoveredSites: (count) => {
|
|
1968
|
+
repositoryDiscoveredCount += count;
|
|
1969
|
+
},
|
|
1937
1970
|
},
|
|
1938
1971
|
);
|
|
1939
1972
|
if (result.status === "refused") {
|
|
@@ -1947,7 +1980,21 @@ export function migrateOperationDeclarationRepository(
|
|
|
1947
1980
|
todos.push(...result.localeTodos);
|
|
1948
1981
|
}
|
|
1949
1982
|
}
|
|
1950
|
-
|
|
1983
|
+
const notes: OperationDeclarationNote[] =
|
|
1984
|
+
repositoryDiscoveredCount === 0
|
|
1985
|
+
? []
|
|
1986
|
+
: repositoryIndex.declarations.flatMap((declaration) =>
|
|
1987
|
+
declaration.runtimeInitializer === undefined
|
|
1988
|
+
? []
|
|
1989
|
+
: [
|
|
1990
|
+
{
|
|
1991
|
+
code: "runtime_composed_registry" as const,
|
|
1992
|
+
path: slash(relative(providerRoot, declaration.path)),
|
|
1993
|
+
initializer: declaration.runtimeInitializer,
|
|
1994
|
+
},
|
|
1995
|
+
],
|
|
1996
|
+
);
|
|
1997
|
+
if (repositoryIndex.declarations.length > 0 && repositoryDiscoveredCount === 0) {
|
|
1951
1998
|
for (const declaration of repositoryIndex.declarations) {
|
|
1952
1999
|
refusals.push(
|
|
1953
2000
|
refusal(
|
|
@@ -1970,6 +2017,7 @@ export function migrateOperationDeclarationRepository(
|
|
|
1970
2017
|
providerRoot,
|
|
1971
2018
|
refusals,
|
|
1972
2019
|
operationCount,
|
|
2020
|
+
notes,
|
|
1973
2021
|
changedFiles,
|
|
1974
2022
|
localeTodoCount: todos.length,
|
|
1975
2023
|
};
|
|
@@ -1984,6 +2032,7 @@ export function migrateOperationDeclarationRepository(
|
|
|
1984
2032
|
providerRoot,
|
|
1985
2033
|
changedFiles: [],
|
|
1986
2034
|
operationCount,
|
|
2035
|
+
notes,
|
|
1987
2036
|
localeTodoCount: 0,
|
|
1988
2037
|
};
|
|
1989
2038
|
}
|
|
@@ -2000,6 +2049,7 @@ export function migrateOperationDeclarationRepository(
|
|
|
2000
2049
|
providerRoot,
|
|
2001
2050
|
changedFiles,
|
|
2002
2051
|
operationCount,
|
|
2052
|
+
notes,
|
|
2003
2053
|
sidecar,
|
|
2004
2054
|
localeTodoCount: todos.length,
|
|
2005
2055
|
};
|
|
@@ -2180,15 +2230,16 @@ type ProviderOperationsDeclaration = {
|
|
|
2180
2230
|
readonly path: string;
|
|
2181
2231
|
readonly construct: string;
|
|
2182
2232
|
readonly initializer: TS.Expression;
|
|
2233
|
+
readonly runtimeInitializer?: string;
|
|
2183
2234
|
};
|
|
2184
2235
|
|
|
2185
2236
|
type RepositoryOperationIndex = {
|
|
2186
2237
|
readonly operationIds: Map<string, Map<string, string>>;
|
|
2187
2238
|
readonly operationSites: Map<string, Map<number, string>>;
|
|
2188
2239
|
readonly excludedBindings: Map<string, Set<string>>;
|
|
2240
|
+
readonly runtimeComposedInitializers: Map<string, Set<number>>;
|
|
2189
2241
|
readonly refusals: OperationDeclarationRefusal[];
|
|
2190
2242
|
readonly declarations: ProviderOperationsDeclaration[];
|
|
2191
|
-
readonly discoveredCount: number;
|
|
2192
2243
|
readonly staticObjectResolverFor: (path: string) => StaticObjectResolver;
|
|
2193
2244
|
};
|
|
2194
2245
|
|
|
@@ -2205,12 +2256,12 @@ function buildRepositoryOperationIndex(
|
|
|
2205
2256
|
const operationIds = buildOperationIdIndex(sourceFiles);
|
|
2206
2257
|
const operationSites = new Map<string, Map<number, string>>();
|
|
2207
2258
|
const excludedBindings = new Map<string, Set<string>>();
|
|
2259
|
+
const runtimeComposedInitializers = new Map<string, Set<number>>();
|
|
2208
2260
|
const refusals: OperationDeclarationRefusal[] = [];
|
|
2209
2261
|
const declarations: ProviderOperationsDeclaration[] = [];
|
|
2210
2262
|
const indexedProviderProperties = new Set<string>();
|
|
2211
2263
|
const factoryIds = new Map<string, { path: string; name: string; ids: Set<string> }>();
|
|
2212
2264
|
const bindingCandidates = new Map<string, { path: string; name: string; ids: Set<string> }>();
|
|
2213
|
-
let discoveredCount = 0;
|
|
2214
2265
|
|
|
2215
2266
|
const relativePath = (path: string): string => slash(relative(providerRoot, path));
|
|
2216
2267
|
const resolutionRefusal = (path: string, operationKey: string, detail: string): void => {
|
|
@@ -2489,7 +2540,6 @@ function buildRepositoryOperationIndex(
|
|
|
2489
2540
|
}
|
|
2490
2541
|
sites.set(start, operationId);
|
|
2491
2542
|
operationSites.set(path, sites);
|
|
2492
|
-
discoveredCount += 1;
|
|
2493
2543
|
};
|
|
2494
2544
|
|
|
2495
2545
|
const classifyEntry = (entry: RegistryEntry): void => {
|
|
@@ -2543,7 +2593,6 @@ function buildRepositoryOperationIndex(
|
|
|
2543
2593
|
};
|
|
2544
2594
|
factory.ids.add(entry.operationId);
|
|
2545
2595
|
factoryIds.set(key, factory);
|
|
2546
|
-
discoveredCount += 1;
|
|
2547
2596
|
return;
|
|
2548
2597
|
}
|
|
2549
2598
|
resolutionRefusal(
|
|
@@ -2562,10 +2611,26 @@ function buildRepositoryOperationIndex(
|
|
|
2562
2611
|
const key = `${path}\0${node.getStart(source)}`;
|
|
2563
2612
|
if (indexedProviderProperties.has(key)) return;
|
|
2564
2613
|
indexedProviderProperties.add(key);
|
|
2565
|
-
|
|
2614
|
+
const resolvedInitializer = resolveLocatedExpression(
|
|
2615
|
+
{ path, source, expression: node.initializer },
|
|
2616
|
+
new Set(),
|
|
2617
|
+
);
|
|
2618
|
+
let runtimeInitializer: string | undefined;
|
|
2619
|
+
if (resolvedInitializer.status === "resolved") {
|
|
2620
|
+
const resolvedExpression = unwrapExpression(resolvedInitializer.value.expression);
|
|
2621
|
+
if (resolvedExpression !== undefined && ts.isCallExpression(resolvedExpression)) {
|
|
2622
|
+
runtimeInitializer = resolvedExpression.getText(resolvedInitializer.value.source);
|
|
2623
|
+
const initializers = runtimeComposedInitializers.get(path) ?? new Set<number>();
|
|
2624
|
+
initializers.add(node.initializer.getStart(source));
|
|
2625
|
+
runtimeComposedInitializers.set(path, initializers);
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
declarations.push({ path, construct, initializer: node.initializer, runtimeInitializer });
|
|
2566
2629
|
const flattened = flattenRegistry({ path, source, expression: node.initializer }, new Set());
|
|
2567
2630
|
if ("detail" in flattened) {
|
|
2568
|
-
|
|
2631
|
+
if (runtimeInitializer === undefined) {
|
|
2632
|
+
resolutionRefusal(path, "<operations>", flattened.detail);
|
|
2633
|
+
}
|
|
2569
2634
|
} else {
|
|
2570
2635
|
for (const entry of flattened.entries.values()) classifyEntry(entry);
|
|
2571
2636
|
}
|
|
@@ -2691,9 +2756,9 @@ function buildRepositoryOperationIndex(
|
|
|
2691
2756
|
operationIds,
|
|
2692
2757
|
operationSites,
|
|
2693
2758
|
excludedBindings,
|
|
2759
|
+
runtimeComposedInitializers,
|
|
2694
2760
|
refusals,
|
|
2695
2761
|
declarations,
|
|
2696
|
-
discoveredCount,
|
|
2697
2762
|
staticObjectResolverFor: (currentPath) => (expression, source) =>
|
|
2698
2763
|
resolveStaticObject(expression, sources.has(source.fileName) ? source.fileName : currentPath),
|
|
2699
2764
|
};
|
package/src/index.ts
CHANGED
|
@@ -181,10 +181,23 @@ export {
|
|
|
181
181
|
export type { PrevalidateResult } from "./runtime/prevalidate.js";
|
|
182
182
|
export { getProviderBaseUrl } from "./runtime/provider.js";
|
|
183
183
|
export type {
|
|
184
|
+
ProxyTelemetryHeaderPayload,
|
|
185
|
+
ProxyHash,
|
|
184
186
|
ProxyTelemetryLogPayload,
|
|
185
187
|
ProxyTelemetryResolvedPayload,
|
|
186
188
|
ProxyTelemetryUnresolvedPayload,
|
|
187
189
|
} from "./runtime/proxy-telemetry.js";
|
|
190
|
+
export {
|
|
191
|
+
RequestTelemetry,
|
|
192
|
+
closedEnum,
|
|
193
|
+
type ClosedEnum,
|
|
194
|
+
type GatewayIngestible,
|
|
195
|
+
type RequestTelemetryLogPayload,
|
|
196
|
+
type SpanIndex,
|
|
197
|
+
type TelemetryContributor,
|
|
198
|
+
type TelemetryKey,
|
|
199
|
+
type TenantNeutral,
|
|
200
|
+
} from "./runtime/request-telemetry.js";
|
|
188
201
|
export {
|
|
189
202
|
APIFUSE__CDP_POOL__URL,
|
|
190
203
|
APIFUSE__RESOLVER__2CAPTCHA__API_KEY,
|