@apifuse/provider-sdk 2.2.0-beta.47 → 2.2.0-beta.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/AUTHORING.md +91 -36
  2. package/CHANGELOG.md +8 -0
  3. package/README.md +11 -9
  4. package/SUBMISSION.md +1 -1
  5. package/bin/apifuse-dev.ts +24 -13
  6. package/bin/apifuse-migrate-operation-declaration.ts +55 -0
  7. package/bin/apifuse-pack-smoke.ts +1 -1
  8. package/bin/apifuse-pack-types.ts +2 -1
  9. package/bin/apifuse-record.ts +30 -16
  10. package/bin/apifuse-submit-check.ts +20 -35
  11. package/dist/cli/commands.d.ts +1 -1
  12. package/dist/cli/commands.js +11 -0
  13. package/dist/cli/migrate-operation-declaration.d.ts +59 -0
  14. package/dist/cli/migrate-operation-declaration.js +1178 -0
  15. package/dist/cli/templates/provider/README.md.tpl +3 -3
  16. package/dist/cli/templates/provider/operations/ping.ts.tpl +2 -0
  17. package/dist/config/loader.d.ts +2 -0
  18. package/dist/config/loader.js +18 -7
  19. package/dist/contract-types.d.ts +11 -5
  20. package/dist/contract.js +21 -10
  21. package/dist/define.d.ts +25 -22
  22. package/dist/define.js +49 -75
  23. package/dist/dev.d.ts +3 -0
  24. package/dist/dev.js +1 -1
  25. package/dist/engine.d.ts +78 -0
  26. package/dist/engine.js +133 -0
  27. package/dist/index.d.ts +3 -2
  28. package/dist/index.js +2 -1
  29. package/dist/lint.d.ts +7 -15
  30. package/dist/lint.js +45 -70
  31. package/dist/provider.d.ts +3 -1
  32. package/dist/provider.js +1 -0
  33. package/dist/runtime/chrome149-header-order.d.ts +58 -0
  34. package/dist/runtime/chrome149-header-order.js +289 -0
  35. package/dist/runtime/env.js +12 -0
  36. package/dist/runtime/executor.d.ts +2 -1
  37. package/dist/runtime/executor.js +3 -36
  38. package/dist/runtime/insights.js +2 -2
  39. package/dist/runtime/otlp.d.ts +71 -2
  40. package/dist/runtime/otlp.js +397 -16
  41. package/dist/runtime/resolver-public.d.ts +1 -1
  42. package/dist/runtime/resolver-public.js +1 -1
  43. package/dist/runtime/resolver-vendors/capsolver.js +9 -3
  44. package/dist/runtime/resolver-vendors/twocaptcha.js +1 -0
  45. package/dist/runtime/resolver.d.ts +12 -0
  46. package/dist/runtime/resolver.js +45 -11
  47. package/dist/runtime/stealth.d.ts +13 -4
  48. package/dist/runtime/stealth.js +362 -85
  49. package/dist/runtime/trace-config.js +2 -1
  50. package/dist/runtime/trace.d.ts +5 -0
  51. package/dist/runtime/trace.js +43 -10
  52. package/dist/server/self-test.d.ts +1 -3
  53. package/dist/server/self-test.js +2 -12
  54. package/dist/server/serve-implementation.d.ts +6 -1
  55. package/dist/server/serve-implementation.js +55 -40
  56. package/dist/server/trace-output.d.ts +3 -1
  57. package/dist/server/trace-output.js +61 -2
  58. package/dist/stealth/profiles.d.ts +9 -8
  59. package/dist/stealth/profiles.js +123 -286
  60. package/dist/types.d.ts +116 -108
  61. package/package.json +2 -1
  62. package/src/cli/__tests__/fixtures/migrate-operation-declaration/approval-override.ts.txt +6 -0
  63. package/src/cli/__tests__/fixtures/migrate-operation-declaration/codemod-syntax.ts.txt +3 -0
  64. package/src/cli/__tests__/fixtures/migrate-operation-declaration/connection-precedence.ts.txt +10 -0
  65. package/src/cli/__tests__/fixtures/migrate-operation-declaration/docs-conflict.ts.txt +8 -0
  66. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-map.ts.txt +5 -0
  67. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-operation.ts.txt +16 -0
  68. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-map.ts.txt +3 -0
  69. package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoist-all.ts.txt +31 -0
  70. package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoisted-const.ts.txt +11 -0
  71. package/src/cli/__tests__/fixtures/migrate-operation-declaration/imported-spread.ts.txt +11 -0
  72. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-map.ts.txt +11 -0
  73. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-cast-tail.ts.txt +21 -0
  74. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-ekitan.ts.txt +11 -0
  75. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-override.ts.txt +14 -0
  76. package/src/cli/__tests__/fixtures/migrate-operation-declaration/missing-english-locale.ts.txt +7 -0
  77. package/src/cli/__tests__/fixtures/migrate-operation-declaration/no-safety.ts.txt +6 -0
  78. package/src/cli/__tests__/fixtures/migrate-operation-declaration/non-literal.ts.txt +7 -0
  79. package/src/cli/__tests__/fixtures/migrate-operation-declaration/redundant-approval.ts.txt +6 -0
  80. package/src/cli/__tests__/fixtures/migrate-operation-declaration/safety-conflict.ts.txt +7 -0
  81. package/src/cli/__tests__/fixtures/migrate-operation-declaration/stream.ts.txt +7 -0
  82. package/src/cli/__tests__/fixtures/migrate-operation-declaration/tool-router-spread.ts.txt +15 -0
  83. package/src/cli/__tests__/fixtures/migrate-operation-declaration/unparseable.ts.txt +4 -0
  84. package/src/cli/__tests__/fixtures/migrate-operation-declaration/verbatim-template.ts.txt +12 -0
  85. package/src/cli/commands.ts +13 -0
  86. package/src/cli/migrate-operation-declaration.ts +1654 -0
  87. package/src/cli/templates/provider/README.md.tpl +3 -3
  88. package/src/cli/templates/provider/operations/ping.ts.tpl +2 -0
  89. package/src/config/loader.ts +31 -6
  90. package/src/contract-types.ts +11 -5
  91. package/src/contract.ts +21 -10
  92. package/src/define.ts +107 -119
  93. package/src/dev.ts +4 -1
  94. package/src/engine.ts +279 -0
  95. package/src/index.ts +13 -5
  96. package/src/lint.ts +58 -92
  97. package/src/provider.ts +25 -3
  98. package/src/runtime/chrome149-header-order.ts +330 -0
  99. package/src/runtime/env.ts +13 -0
  100. package/src/runtime/executor.ts +7 -40
  101. package/src/runtime/insights.ts +2 -2
  102. package/src/runtime/otlp.ts +467 -21
  103. package/src/runtime/resolver-public.ts +3 -0
  104. package/src/runtime/resolver-vendors/capsolver.ts +12 -4
  105. package/src/runtime/resolver-vendors/twocaptcha.ts +1 -0
  106. package/src/runtime/resolver.ts +68 -19
  107. package/src/runtime/stealth.ts +435 -103
  108. package/src/runtime/trace-config.ts +3 -2
  109. package/src/runtime/trace.ts +57 -17
  110. package/src/server/self-test.ts +2 -9
  111. package/src/server/serve-implementation.ts +89 -72
  112. package/src/server/trace-output.ts +99 -2
  113. package/src/stealth/profiles.ts +169 -327
  114. package/src/types.ts +114 -137
@@ -51,7 +51,7 @@ import {
51
51
  APIFUSE__RESOLVER__TIMEOUT_MS,
52
52
  DEFAULT_RESOLVER_TIMEOUT_MS,
53
53
  } from "./resolver-config.js";
54
- import { DEFAULT_PROFILE } from "./stealth.js";
54
+ import { DEFAULT_STEALTH_PROFILE } from "./stealth.js";
55
55
  import type { TraceRecorder } from "./trace.js";
56
56
 
57
57
  export {
@@ -143,11 +143,21 @@ type ResolverCacheIndex = {
143
143
  }[];
144
144
  };
145
145
 
146
+ export type ResolverSolutionSource = "cache" | "vendor";
147
+
148
+ type ResolverSolutionInvalidationOutcome =
149
+ | "cache_disabled"
150
+ | "entry_deleted"
151
+ | "index_entry_deleted"
152
+ | "not_cookie_solution"
153
+ | "solution_not_cached";
154
+
146
155
  const RESOLVER_SOLUTION_CACHE_NAMESPACE = "resolver-solution";
147
156
  const RESOLVER_SOLUTION_INDEX_CACHE_NAMESPACE = "resolver-solution-index";
148
157
  const MIN_RESOLVER_CACHE_TTL_MS = 1_000;
149
158
  const resolverCaches = new WeakMap<object, ProviderCache | null>();
150
159
  const solutionIssuerDigests = new WeakMap<object, string>();
160
+ const resolverSolutionSources = new WeakMap<object, ResolverSolutionSource>();
151
161
  const SAFE_CAUSE_MESSAGE_WORDS: ReadonlySet<string> = new Set([
152
162
  "abort",
153
163
  "aborted",
@@ -244,7 +254,7 @@ export function swapResolverAdapterFactoryForTests(
244
254
  }
245
255
 
246
256
  let resolveDefaultResolverUserAgent: () => string | undefined = () =>
247
- getStealthProfile(DEFAULT_PROFILE).userAgent;
257
+ getStealthProfile(DEFAULT_STEALTH_PROFILE).userAgent;
248
258
 
249
259
  /** Internal test seam; deliberately not re-exported from the package root. */
250
260
  export function swapResolverDefaultUserAgentForTests(
@@ -252,7 +262,7 @@ export function swapResolverDefaultUserAgentForTests(
252
262
  ): () => void {
253
263
  const original = resolveDefaultResolverUserAgent;
254
264
  resolveDefaultResolverUserAgent =
255
- resolver ?? (() => getStealthProfile(DEFAULT_PROFILE).userAgent);
265
+ resolver ?? (() => getStealthProfile(DEFAULT_STEALTH_PROFILE).userAgent);
256
266
  let restored = false;
257
267
  return () => {
258
268
  if (restored) return;
@@ -597,7 +607,7 @@ function isResolverCacheIndex(value: unknown): value is ResolverCacheIndex {
597
607
 
598
608
  function solutionExpiryMs(solution: ChallengeSolution): number | undefined {
599
609
  if (solution.form !== "cookies") return undefined;
600
- const expires = solution.expires;
610
+ const expires = solution.expires ?? solution.sdkEstimatedExpires;
601
611
  if (typeof expires !== "number" || !Number.isFinite(expires)) return undefined;
602
612
  return expires * 1_000;
603
613
  }
@@ -608,6 +618,22 @@ function rememberSolutionIssuer(solution: ChallengeSolution, issuerDigest: strin
608
618
  }
609
619
  }
610
620
 
621
+ function rememberSolutionSource(solution: ChallengeSolution, source: ResolverSolutionSource): void {
622
+ if (typeof solution === "object" && solution !== null) {
623
+ resolverSolutionSources.set(solution, source);
624
+ }
625
+ }
626
+
627
+ /**
628
+ * Identify whether this exact SDK-returned solution object came from the cache
629
+ * or a vendor solve. Returns undefined for copied or caller-created objects.
630
+ */
631
+ export function getResolverSolutionSource(
632
+ solution: ChallengeSolution,
633
+ ): ResolverSolutionSource | undefined {
634
+ return resolverSolutionSources.get(solution);
635
+ }
636
+
611
637
  async function readCachedSolution(
612
638
  cache: ProviderCache,
613
639
  challenge: ProviderChallenge,
@@ -618,8 +644,14 @@ async function readCachedSolution(
618
644
  if (!cached || !isCachedResolverSolution(cached.value)) return undefined;
619
645
  if (cached.value.issuerDigest !== issuerDigest || cached.value.expiresAtMs <= now)
620
646
  return undefined;
621
- rememberSolutionIssuer(cached.value.solution, issuerDigest);
622
- return cached.value.solution;
647
+ if (cached.value.solution.form !== "cookies") return undefined;
648
+ const solution = {
649
+ ...cached.value.solution,
650
+ cookies: { ...cached.value.solution.cookies },
651
+ };
652
+ rememberSolutionIssuer(solution, issuerDigest);
653
+ rememberSolutionSource(solution, "cache");
654
+ return solution;
623
655
  }
624
656
 
625
657
  async function findCachedSolution(
@@ -720,25 +752,18 @@ async function cacheResolverSolution(
720
752
  );
721
753
  }
722
754
 
723
- /** Remove the cached entry for the exact solution object returned by this resolver. */
724
- export async function invalidateResolverSolution(
755
+ async function invalidateResolverSolutionWithOutcome(
725
756
  resolver: ResolverContext,
726
757
  challenge: ProviderChallenge,
727
758
  solution: ChallengeSolution,
728
- ): Promise<void> {
759
+ ): Promise<ResolverSolutionInvalidationOutcome> {
729
760
  const metadata = (
730
761
  resolver as ResolverContext & {
731
762
  readonly [RESOLVER_INSTRUMENTATION_METADATA]?: ResolverInstrumentationMetadata;
732
763
  }
733
764
  )[RESOLVER_INSTRUMENTATION_METADATA];
734
765
  const cacheOwner = metadata?.target ?? resolver;
735
- const invalidate = async (): Promise<
736
- | "cache_disabled"
737
- | "entry_deleted"
738
- | "index_entry_deleted"
739
- | "not_cookie_solution"
740
- | "solution_not_cached"
741
- > => {
766
+ const invalidate = async (): Promise<ResolverSolutionInvalidationOutcome> => {
742
767
  if (solution.form !== "cookies") return "not_cookie_solution";
743
768
  if (!resolverCaches.has(cacheOwner)) {
744
769
  throw new Error("Resolver cache registration lookup failed during solution invalidation");
@@ -764,15 +789,38 @@ export async function invalidateResolverSolution(
764
789
  };
765
790
 
766
791
  if (!metadata) {
767
- await invalidate();
768
- return;
792
+ return await invalidate();
769
793
  }
770
- await metadata.traceRecorder.runSpan("resolver.cache.invalidate", invalidate, {
794
+ return await metadata.traceRecorder.runSpan("resolver.cache.invalidate", invalidate, {
771
795
  attributes: { challenge_kind: challenge.kind },
772
796
  onSuccess: (outcome) => ({ outcome }),
773
797
  });
774
798
  }
775
799
 
800
+ /** Remove the cached entry for the exact solution object returned by this resolver. */
801
+ export async function invalidateResolverSolution(
802
+ resolver: ResolverContext,
803
+ challenge: ProviderChallenge,
804
+ solution: ChallengeSolution,
805
+ ): Promise<void> {
806
+ await invalidateResolverSolutionWithOutcome(resolver, challenge, solution);
807
+ }
808
+
809
+ /**
810
+ * Remove a solution only when it was returned from the resolver cache. Providers
811
+ * should call this when an upstream serves the same challenge after a cached
812
+ * solution was applied, so the next `solve()` mints a fresh solution.
813
+ */
814
+ export async function invalidateCachedResolverSolution(
815
+ resolver: ResolverContext,
816
+ challenge: ProviderChallenge,
817
+ solution: ChallengeSolution,
818
+ ): Promise<boolean> {
819
+ if (getResolverSolutionSource(solution) !== "cache") return false;
820
+ const outcome = await invalidateResolverSolutionWithOutcome(resolver, challenge, solution);
821
+ return outcome === "entry_deleted" || outcome === "index_entry_deleted";
822
+ }
823
+
776
824
  async function resolveResolverIdentity(
777
825
  proxyIntent: NonNullable<ResolverRuntimeOptions["proxyIntent"]>,
778
826
  ): Promise<{
@@ -938,6 +986,7 @@ function createResolverChainClient(options: {
938
986
  );
939
987
  }
940
988
  }
989
+ rememberSolutionSource(solution, "vendor");
941
990
  return solution;
942
991
  } catch (error) {
943
992
  signal.throwIfAborted();