@flue/sdk 0.3.3 → 0.3.5

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 (2) hide show
  1. package/dist/index.mjs +31 -13
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -396,9 +396,6 @@ var CloudflarePlugin = class {
396
396
  }`;
397
397
  }).join("\n\n");
398
398
  const { config: userConfig } = await this.getUserConfig(ctx.outputDir);
399
- const sandboxClassNames = detectSandboxBindings(userConfig);
400
- const sandboxReExports = sandboxClassNames.map((name) => `export { Sandbox as ${name} } from '@cloudflare/sandbox';`).join("\n");
401
- const sandboxClassImport = sandboxClassNames.length > 0 ? `import { Sandbox as __FlueCfSandbox } from '@cloudflare/sandbox';` : "";
402
399
  return `
403
400
  // Auto-generated by @flue/sdk build (cloudflare)
404
401
  import { Agent, routeAgentRequest } from 'agents';
@@ -410,7 +407,7 @@ import {
410
407
  resolveModel,
411
408
  } from '@flue/sdk/internal';
412
409
  import { runWithCloudflareContext, cfSandboxToSessionEnv } from '@flue/sdk/cloudflare';
413
- ${sandboxClassImport ? "\n" + sandboxClassImport : ""}
410
+
414
411
  ${agentImports}
415
412
 
416
413
  // ─── Config ─────────────────────────────────────────────────────────────────
@@ -454,19 +451,40 @@ async function createLocalEnv() {
454
451
 
455
452
  /**
456
453
  * Detect and wrap external sandbox instances (e.g. from @cloudflare/sandbox's
457
- * getSandbox()). Returns SessionEnv if the value is a @cloudflare/sandbox
454
+ * getSandbox()). Returns SessionEnv if the value looks like a Durable Object
458
455
  * RPC stub, null otherwise.
459
456
  *
460
- * NOTE: We must use \`instanceof\` here, not structural duck-typing. The value
461
- * returned by \`getSandbox()\` is a workerd RPC Proxy that returns \`true\` for
462
- * any \`in\` check and \`'function'\` for \`typeof <anything>\`, so structural
463
- * checks (positive or negative) are unreliable against it. \`instanceof\` walks
464
- * the prototype chain via the runtime, which the proxy can't fake.
457
+ * NOTE on detection: The value returned by \`getSandbox()\` is a workerd RPC
458
+ * Proxy. None of the obvious detection strategies work:
459
+ *
460
+ * - Structural duck-typing (\`'X' in stub\`, \`typeof stub.X === 'function'\`):
461
+ * the proxy lies positively for any property name, so any check returns
462
+ * \`true\` regardless of what's actually on the remote.
463
+ * - \`instanceof <UserSandboxClass>\` (e.g. \`Sandbox\` from
464
+ * \`@cloudflare/sandbox\`): the user's class only exists on the in-DO
465
+ * side; over RPC the caller gets a generic stub.
466
+ * - \`instanceof DurableObject\` (imported from \`cloudflare:workers\`): the
467
+ * stub's prototype chain has a class *named* \`DurableObject\`, but it's a
468
+ * workerd-internal class with a different identity than the importable
469
+ * one. \`instanceof\` checks identity, not name, so it returns \`false\`.
470
+ *
471
+ * The one signal that does work — verified by runtime probe — is the string
472
+ * name of the prototype's constructor. Workerd's internal RPC stub class is
473
+ * named \`DurableObject\`, and \`Object.getPrototypeOf(stub).constructor.name\`
474
+ * returns that string. This is a heuristic (it relies on a workerd-internal
475
+ * naming convention, not a contractual API), but it's empirically correct
476
+ * today and will misroute only if a user passes some other DO stub to
477
+ * \`init({ sandbox })\` — in which case \`cfSandboxToSessionEnv\` will fail
478
+ * loudly on first method call.
465
479
  */
466
480
  function resolveSandbox(sandbox) {
467
- ${sandboxClassNames.length > 0 ? `if (sandbox instanceof __FlueCfSandbox) {
481
+ if (
482
+ sandbox &&
483
+ typeof sandbox === 'object' &&
484
+ Object.getPrototypeOf(sandbox)?.constructor?.name === 'DurableObject'
485
+ ) {
468
486
  return cfSandboxToSessionEnv(sandbox);
469
- }` : "/* no @cloudflare/sandbox bindings declared in wrangler config */"}
487
+ }
470
488
  return null;
471
489
  }
472
490
 
@@ -696,7 +714,7 @@ ${agentClasses}
696
714
  // \`@cloudflare/sandbox\` so each user-chosen class_name resolves at the
697
715
  // bundle's top level. The binding + container image configuration is owned
698
716
  // by the user's wrangler.jsonc.
699
- ${sandboxReExports}
717
+ ${detectSandboxBindings(userConfig).map((name) => `export { Sandbox as ${name} } from '@cloudflare/sandbox';`).join("\n")}
700
718
 
701
719
  // ─── Worker Fetch Handler ───────────────────────────────────────────────────
702
720
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flue/sdk",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "exports": {