@playcraft/iframe-bridge 0.0.1-alpha.100 → 0.0.1-alpha.101

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.md CHANGED
@@ -142,6 +142,7 @@ const { bridge, whenChildReady } = setupParentBridge({
142
142
  iframe,
143
143
  childOrigin: new URL(childUrl).origin,
144
144
  init: { params: { theme: 'dark' } }, // 收到 child.ready 后自动 emit host.init
145
+ autoDetectChildReady: true, // iframe load / document complete 也视为 ready
145
146
  debug: true,
146
147
  });
147
148
 
@@ -323,10 +324,10 @@ bridgeMethod('form', 'get'); // 'form.get'
323
324
 
324
325
  **Request** `AiGenerateImagePayload`
325
326
 
326
- | 字段 | 类型 | 必填 | 说明 |
327
- | ---------------------- | ----------- | ---- | -------------------------------------- |
328
- | `prompt` | `string` | | 生成提示词 |
329
- | `referenceImageBase64` | `string[]` | | 参考图 base64 列表(无 `data:` 前缀) |
327
+ | 字段 | 类型 | 必填 | 说明 |
328
+ | ---------------------- | ---------- | ---- | ------------------------------------- |
329
+ | `prompt` | `string` | | 生成提示词 |
330
+ | `referenceImageBase64` | `string[]` | | 参考图 base64 列表(无 `data:` 前缀) |
330
331
 
331
332
  **Response** `{ paths: PathEntry[] }`
332
333
 
@@ -356,6 +357,8 @@ bridgeMethod('form', 'get'); // 'form.get'
356
357
 
357
358
  Child 侧 `whenParentReady()` / Parent 侧 `whenChildReady()` 在握手完成后 resolve。
358
359
 
360
+ 若对端未集成 SDK,默认在 `DEFAULT_HANDSHAKE_TIMEOUT_MS`(10s)后仍 resolve 空 payload,并在控制台 `console.warn` 提示;可通过 `handshakeTimeout` 调整等待时间。
361
+
359
362
  ---
360
363
 
361
364
  ### `dialog.close`
package/dist/index.d.ts CHANGED
@@ -202,6 +202,8 @@ type SetupChildBridgeOptions = {
202
202
  readyEvent?: ChildBridgeDefaultEvents['readyEvent'];
203
203
  /** Child → parent event announcing bridge readiness. */
204
204
  announceEvent?: ChildBridgeDefaultEvents['announceEvent'];
205
+ /** Max wait for host.init before resolving with fallback and console.warn. */
206
+ handshakeTimeout?: number;
205
207
  debug?: boolean | DebugLogger;
206
208
  };
207
209
  type SetupChildBridgeResult = {
@@ -232,6 +234,13 @@ type SetupParentBridgeOptions = {
232
234
  announceEvent?: ParentBridgeDefaultEvents['announceEvent'];
233
235
  /** Parent → child event sent automatically after announceEvent. */
234
236
  readyEvent?: ParentBridgeDefaultEvents['readyEvent'];
237
+ /** Max wait for child.ready before resolving with fallback and console.warn. */
238
+ handshakeTimeout?: number;
239
+ /**
240
+ * Treat iframe `load` and `contentDocument.readyState === 'complete'` as child ready.
241
+ * Does not emit `host.init` — only the bridge `child.ready` handshake does that.
242
+ */
243
+ autoDetectChildReady?: boolean;
235
244
  debug?: boolean | DebugLogger;
236
245
  };
237
246
  type SetupParentBridgeResult = {
@@ -251,6 +260,8 @@ declare function withParentOrigin(childUrl: string | URL, parentOrigin?: string)
251
260
  /** Protocol marker on every envelope; matches package.json version */
252
261
  declare const PROTOCOL_VERSION: string;
253
262
  declare const DEFAULT_REQUEST_TIMEOUT_MS = 150000;
263
+ /** Max wait for parent ↔ child handshake before resolving with fallback + console.warn. */
264
+ declare const DEFAULT_HANDSHAKE_TIMEOUT_MS = 10000;
254
265
  declare const BridgeErrorCodes: {
255
266
  readonly ABORTED: "ABORTED";
256
267
  readonly DESTROYED: "DESTROYED";
@@ -294,5 +305,5 @@ declare class PlaycraftBridgeError extends Error {
294
305
  /** Normalize thrown/unknown errors to wire-shaped `{ ret, msg }`. */
295
306
  declare function toPlaycraftError(err: unknown): RpcError;
296
307
 
297
- export { BRIDGE_EVENT_NAMES, BRIDGE_RPC_NAMES, Bridge, BridgeErrorCodes, BridgeMethods, ChildBridgeDefaults, DEFAULT_REQUEST_TIMEOUT_MS, PROTOCOL_VERSION, ParentBridgeDefaults, PlaycraftBridgeError, RetCodes, bridgeMethod, createEnvelope, createErrorResponse, createSuccessResponse, emitOne, errorCodeToRet, isDebugFromUrl, isInvokeGroups, isPlaycraftEnvelope, normalizeInvokeCall, retToErrorCode, settleParallel, setupChildBridge, setupParentBridge, toPlaycraftError, withParentOrigin };
308
+ export { BRIDGE_EVENT_NAMES, BRIDGE_RPC_NAMES, Bridge, BridgeErrorCodes, BridgeMethods, ChildBridgeDefaults, DEFAULT_HANDSHAKE_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS, PROTOCOL_VERSION, ParentBridgeDefaults, PlaycraftBridgeError, RetCodes, bridgeMethod, createEnvelope, createErrorResponse, createSuccessResponse, emitOne, errorCodeToRet, isDebugFromUrl, isInvokeGroups, isPlaycraftEnvelope, normalizeInvokeCall, retToErrorCode, settleParallel, setupChildBridge, setupParentBridge, toPlaycraftError, withParentOrigin };
298
309
  export type { AiGenerateImagePayload, AiGenerateImageResult, BridgeErrorCode, BridgeEventName, BridgeMessageEvent, BridgeMethodDomain, BridgeOptions, BridgeRpcName, ChildBridgeDefaultEvents, ChildReadyEvt, DebugLogger, DialogCloseEvt, Envelope, EventMap, EventName, Handler, HostInitEvt, InvokeBatchInput, InvokeBatchOptions, InvokeCall, InvokeGroup, InvokeGroupsInput, InvokeMap, InvokeName, InvokeParallelResult, InvokeTuple, Kind, MethodMap, MethodName, NotifyHandler, ParentBridgeDefaultEvents, PathEntry, PathsGetReq, PathsGetRes, PathsSetReq, PathsSetRes, PendingReq, RequestOptions, RetCode, RpcError, SetupChildBridgeOptions, SetupChildBridgeResult, SetupParentBridgeOptions, SetupParentBridgeResult };
package/dist/index.js CHANGED
@@ -1,9 +1,10 @@
1
- var version = "0.0.1-alpha.100";
1
+ var version = "0.0.1-alpha.101";
2
2
  var pkg = {
3
3
  version: version};
4
4
 
5
5
  /** Protocol marker on every envelope; matches package.json version */ const PROTOCOL_VERSION = pkg.version;
6
6
  const DEFAULT_REQUEST_TIMEOUT_MS = 150_000;
7
+ /** Max wait for parent ↔ child handshake before resolving with fallback + console.warn. */ const DEFAULT_HANDSHAKE_TIMEOUT_MS = 10_000;
7
8
  const BridgeErrorCodes = {
8
9
  ABORTED: 'ABORTED',
9
10
  DESTROYED: 'DESTROYED',
@@ -382,14 +383,26 @@ function parseTruthyDebug(value) {
382
383
  return parseTruthyDebug(params.get('debug'));
383
384
  }
384
385
 
385
- function createReadyGate() {
386
- let resolve;
387
- const promise = new Promise((res)=>{
388
- resolve = res;
386
+ /** Resolves on success or after timeout so callers can always continue. */ function createHandshakeGate(options) {
387
+ let settled = false;
388
+ let resolveValue;
389
+ let timer;
390
+ const promise = new Promise((resolve)=>{
391
+ resolveValue = (value)=>{
392
+ if (settled) return;
393
+ settled = true;
394
+ if (timer !== undefined) clearTimeout(timer);
395
+ resolve(value);
396
+ };
389
397
  });
398
+ timer = setTimeout(()=>{
399
+ if (settled) return;
400
+ options.onTimeout();
401
+ resolveValue(options.fallbackValue);
402
+ }, options.timeoutMs);
390
403
  return {
391
404
  promise,
392
- resolve
405
+ resolve: resolveValue
393
406
  };
394
407
  }
395
408
 
@@ -413,9 +426,15 @@ function createChildBridge(parentOrigin, debug) {
413
426
  });
414
427
  }
415
428
  function setupChildBridge(options) {
416
- const { parentOrigin, readyEvent = ChildBridgeDefaults.readyEvent, announceEvent = ChildBridgeDefaults.announceEvent, debug = isDebugFromUrl() } = normalizeOptions(options);
429
+ const { parentOrigin, readyEvent = ChildBridgeDefaults.readyEvent, announceEvent = ChildBridgeDefaults.announceEvent, handshakeTimeout = DEFAULT_HANDSHAKE_TIMEOUT_MS, debug = isDebugFromUrl() } = normalizeOptions(options);
417
430
  const bridge = createChildBridge(parentOrigin, debug);
418
- const ready = createReadyGate();
431
+ const ready = createHandshakeGate({
432
+ timeoutMs: handshakeTimeout,
433
+ fallbackValue: {},
434
+ onTimeout: ()=>{
435
+ console.warn(`[playcraft] whenParentReady timed out after ${handshakeTimeout}ms — parent may not have integrated iframe-bridge SDK`);
436
+ }
437
+ });
419
438
  bridge.on(readyEvent, (evt)=>ready.resolve(evt));
420
439
  if (window.parent !== window) {
421
440
  void bridge.emit(announceEvent, {});
@@ -426,6 +445,19 @@ function setupChildBridge(options) {
426
445
  };
427
446
  }
428
447
 
448
+ function attachAutoDetectChildReady(iframe, onReady) {
449
+ const handleLoad = ()=>{
450
+ onReady();
451
+ };
452
+ iframe.addEventListener('load', handleLoad);
453
+ if (iframe.src && iframe.contentDocument?.readyState === 'complete') {
454
+ onReady();
455
+ }
456
+ return ()=>{
457
+ iframe.removeEventListener('load', handleLoad);
458
+ };
459
+ }
460
+
429
461
  /** Default one-way events used by the parent-side handshake. */ const ParentBridgeDefaults = {
430
462
  announceEvent: BridgeMethods.child.ready,
431
463
  readyEvent: BridgeMethods.host.init
@@ -441,13 +473,30 @@ function createParentBridge(iframe, childOrigin, debug) {
441
473
  });
442
474
  }
443
475
  function setupParentBridge(options) {
444
- const { iframe, childOrigin, init = {}, announceEvent = ParentBridgeDefaults.announceEvent, readyEvent = ParentBridgeDefaults.readyEvent, debug = isDebugFromUrl() } = options;
476
+ const { iframe, childOrigin, init = {}, announceEvent = ParentBridgeDefaults.announceEvent, readyEvent = ParentBridgeDefaults.readyEvent, handshakeTimeout = DEFAULT_HANDSHAKE_TIMEOUT_MS, autoDetectChildReady = false, debug = isDebugFromUrl() } = options;
445
477
  const bridge = createParentBridge(iframe, childOrigin, debug);
446
- const ready = createReadyGate();
478
+ const ready = createHandshakeGate({
479
+ timeoutMs: handshakeTimeout,
480
+ fallbackValue: {},
481
+ onTimeout: ()=>{
482
+ console.warn(`[playcraft] whenChildReady timed out after ${handshakeTimeout}ms — child may not have integrated iframe-bridge SDK`);
483
+ }
484
+ });
485
+ let detachAutoDetectChildReady;
486
+ if (autoDetectChildReady) {
487
+ detachAutoDetectChildReady = attachAutoDetectChildReady(iframe, ()=>{
488
+ ready.resolve({});
489
+ });
490
+ }
447
491
  bridge.on(announceEvent, (evt)=>{
448
492
  void bridge.emit(readyEvent, init);
449
493
  ready.resolve(evt);
450
494
  });
495
+ const destroyBridge = bridge.destroy.bind(bridge);
496
+ bridge.destroy = ()=>{
497
+ detachAutoDetectChildReady?.();
498
+ destroyBridge();
499
+ };
451
500
  return {
452
501
  bridge,
453
502
  whenChildReady: ()=>ready.promise
@@ -460,4 +509,4 @@ function setupParentBridge(options) {
460
509
  return url;
461
510
  }
462
511
 
463
- export { BRIDGE_EVENT_NAMES, BRIDGE_RPC_NAMES, Bridge, BridgeErrorCodes, BridgeMethods, ChildBridgeDefaults, DEFAULT_REQUEST_TIMEOUT_MS, PROTOCOL_VERSION, ParentBridgeDefaults, PlaycraftBridgeError, RetCodes, bridgeMethod, createEnvelope, createErrorResponse, createSuccessResponse, emitOne, errorCodeToRet, isDebugFromUrl, isInvokeGroups, isPlaycraftEnvelope, normalizeInvokeCall, retToErrorCode, settleParallel, setupChildBridge, setupParentBridge, toPlaycraftError, withParentOrigin };
512
+ export { BRIDGE_EVENT_NAMES, BRIDGE_RPC_NAMES, Bridge, BridgeErrorCodes, BridgeMethods, ChildBridgeDefaults, DEFAULT_HANDSHAKE_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS, PROTOCOL_VERSION, ParentBridgeDefaults, PlaycraftBridgeError, RetCodes, bridgeMethod, createEnvelope, createErrorResponse, createSuccessResponse, emitOne, errorCodeToRet, isDebugFromUrl, isInvokeGroups, isPlaycraftEnvelope, normalizeInvokeCall, retToErrorCode, settleParallel, setupChildBridge, setupParentBridge, toPlaycraftError, withParentOrigin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcraft/iframe-bridge",
3
- "version": "0.0.1-alpha.100",
3
+ "version": "0.0.1-alpha.101",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "PlayCraft iframe postMessage bridge SDK for parent ↔ child communication",