stitchkit 0.94.0 → 0.94.1
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 +64 -0
- package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-listing.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -1
- package/dist/agent-runtime/contained-darwin.d.ts +38 -0
- package/dist/agent-runtime/contained-darwin.d.ts.map +1 -0
- package/dist/agent-runtime/contained-files.d.ts +11 -26
- package/dist/agent-runtime/contained-files.d.ts.map +1 -1
- package/dist/agent-runtime/contained-scan.d.ts +21 -0
- package/dist/agent-runtime/contained-scan.d.ts.map +1 -0
- package/dist/agent-runtime/contained-write.d.ts +9 -0
- package/dist/agent-runtime/contained-write.d.ts.map +1 -0
- package/dist/agent-runtime/deferred-tool-types.d.ts +3 -2
- package/dist/agent-runtime/deferred-tool-types.d.ts.map +1 -1
- package/dist/agent-runtime/harness-control.d.ts +0 -1
- package/dist/agent-runtime/harness-control.d.ts.map +1 -1
- package/dist/agent-runtime/harness.d.ts +0 -5
- package/dist/agent-runtime/harness.d.ts.map +1 -1
- package/dist/agent-runtime/managed-tools.d.ts +3 -2
- package/dist/agent-runtime/managed-tools.d.ts.map +1 -1
- package/dist/agent-runtime/runtime.d.ts +1 -1
- package/dist/agent-runtime/runtime.d.ts.map +1 -1
- package/dist/agent-runtime/schedule-records.d.ts +34 -0
- package/dist/agent-runtime/schedule-records.d.ts.map +1 -0
- package/dist/agent-runtime/schedules.d.ts +34 -0
- package/dist/agent-runtime/schedules.d.ts.map +1 -1
- package/dist/agent-runtime/store-conformance-lifecycle.d.ts +434 -0
- package/dist/agent-runtime/store-conformance-lifecycle.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance-ordering.d.ts +18 -0
- package/dist/agent-runtime/store-conformance-ordering.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance-support.d.ts +130 -0
- package/dist/agent-runtime/store-conformance-support.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance-terminal.d.ts +12 -0
- package/dist/agent-runtime/store-conformance-terminal.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance.d.ts.map +1 -1
- package/dist/application/admission-rate.d.ts +21 -0
- package/dist/application/admission-rate.d.ts.map +1 -0
- package/dist/application/admission-run.d.ts +8 -0
- package/dist/application/admission-run.d.ts.map +1 -0
- package/dist/application/admission.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-lock.d.ts +9 -34
- package/dist/application/diagnostic-journal-lock.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-manager.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-storage.d.ts.map +1 -1
- package/dist/application/kernel-resource-context.d.ts.map +1 -1
- package/dist/application/notification-outbox.d.ts.map +1 -1
- package/dist/application/schedule.d.ts +0 -1
- package/dist/application/schedule.d.ts.map +1 -1
- package/dist/application/watch-hub-core.d.ts +122 -0
- package/dist/application/watch-hub-core.d.ts.map +1 -0
- package/dist/application/watch-hub.d.ts +2 -2
- package/dist/application/watch-hub.d.ts.map +1 -1
- package/dist/browser/client-executors.d.ts +14 -0
- package/dist/browser/client-executors.d.ts.map +1 -0
- package/dist/browser/client-multipart.d.ts +1 -1
- package/dist/browser/client-multipart.d.ts.map +1 -1
- package/dist/browser/client.d.ts +3 -2
- package/dist/browser/client.d.ts.map +1 -1
- package/dist/browser/http-fetch.d.ts +22 -0
- package/dist/browser/http-fetch.d.ts.map +1 -0
- package/dist/browser/http.d.ts +1 -3
- package/dist/browser/http.d.ts.map +1 -1
- package/dist/browser/live-state-core.d.ts +63 -0
- package/dist/browser/live-state-core.d.ts.map +1 -0
- package/dist/browser/live-state.d.ts.map +1 -1
- package/dist/browser/realtime-client.d.ts +26 -0
- package/dist/browser/realtime-client.d.ts.map +1 -0
- package/dist/browser/socket-io-connection.d.ts +82 -0
- package/dist/browser/socket-io-connection.d.ts.map +1 -0
- package/dist/browser/socket-io-peer.d.ts +20 -0
- package/dist/browser/socket-io-peer.d.ts.map +1 -0
- package/dist/browser/socket-io-trace.d.ts +31 -0
- package/dist/browser/socket-io-trace.d.ts.map +1 -0
- package/dist/browser/socket-io.d.ts +2 -18
- package/dist/browser/socket-io.d.ts.map +1 -1
- package/dist/contract/client-types.d.ts +134 -0
- package/dist/contract/client-types.d.ts.map +1 -0
- package/dist/contract/define-validation.d.ts +30 -0
- package/dist/contract/define-validation.d.ts.map +1 -0
- package/dist/contract/define.d.ts +3 -357
- package/dist/contract/define.d.ts.map +1 -1
- package/dist/contract/runtime-context.d.ts +131 -0
- package/dist/contract/runtime-context.d.ts.map +1 -0
- package/dist/contract/tool-options.d.ts +105 -0
- package/dist/contract/tool-options.d.ts.map +1 -0
- package/dist/contract/tool-view.d.ts +15 -2
- package/dist/contract/tool-view.d.ts.map +1 -1
- package/dist/durability/contract.d.ts +83 -0
- package/dist/durability/contract.d.ts.map +1 -1
- package/dist/durability/effect.d.ts +24 -0
- package/dist/durability/effect.d.ts.map +1 -0
- package/dist/durability/engine.d.ts +2 -2
- package/dist/durability/engine.d.ts.map +1 -1
- package/dist/durability/events.d.ts +2 -0
- package/dist/durability/events.d.ts.map +1 -1
- package/dist/durability/ledger.d.ts +11 -0
- package/dist/durability/ledger.d.ts.map +1 -1
- package/dist/durability/parks.d.ts +22 -0
- package/dist/durability/parks.d.ts.map +1 -0
- package/dist/durability/scheduler.d.ts +1 -0
- package/dist/durability/scheduler.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime/coding-tools.js +4 -4
- package/dist/entrypoints/agent-runtime/harness.js +127 -116
- package/dist/entrypoints/agent-runtime/sandbox.js +4 -4
- package/dist/entrypoints/agent-runtime/sqlite/bun.js +3 -3
- package/dist/entrypoints/agent-runtime/sqlite/node.js +3 -3
- package/dist/entrypoints/agent-runtime/testing.js +246 -214
- package/dist/entrypoints/agent-runtime.js +224 -203
- package/dist/entrypoints/application/diagnostic-journal.js +63 -203
- package/dist/entrypoints/application/opentelemetry.js +1 -1
- package/dist/entrypoints/application.js +361 -324
- package/dist/entrypoints/cli.d.ts +4 -1
- package/dist/entrypoints/cli.d.ts.map +1 -1
- package/dist/entrypoints/cli.js +57 -35
- package/dist/entrypoints/contract.d.ts +5 -2
- package/dist/entrypoints/contract.d.ts.map +1 -1
- package/dist/entrypoints/contract.js +3 -2
- package/dist/entrypoints/files.d.ts +2 -0
- package/dist/entrypoints/files.d.ts.map +1 -1
- package/dist/entrypoints/files.js +98 -2
- package/dist/entrypoints/index.d.ts +4 -2
- package/dist/entrypoints/index.d.ts.map +1 -1
- package/dist/entrypoints/index.js +348 -282
- package/dist/entrypoints/live.js +89 -71
- package/dist/entrypoints/node.d.ts +2 -1
- package/dist/entrypoints/node.d.ts.map +1 -1
- package/dist/entrypoints/node.js +13 -12
- package/dist/entrypoints/react.js +1 -1
- package/dist/entrypoints/remote.js +4 -4
- package/dist/entrypoints/server.d.ts +4 -2
- package/dist/entrypoints/server.d.ts.map +1 -1
- package/dist/entrypoints/server.js +293 -79
- package/dist/entrypoints/testing.d.ts +2 -1
- package/dist/entrypoints/testing.d.ts.map +1 -1
- package/dist/entrypoints/testing.js +288 -281
- package/dist/entrypoints/tools/connections.js +2 -2
- package/dist/entrypoints/tools/invoker.js +4 -4
- package/dist/entrypoints/tools.d.ts +6 -3
- package/dist/entrypoints/tools.d.ts.map +1 -1
- package/dist/entrypoints/tools.js +245 -202
- package/dist/entrypoints/tracking.js +325 -274
- package/dist/files/boundary.d.ts.map +1 -1
- package/dist/files/file-io.d.ts +14 -0
- package/dist/files/file-io.d.ts.map +1 -0
- package/dist/index-1j8pm5t0.js +412 -0
- package/dist/{index-kvj7f4hq.js → index-2bxbyab0.js} +10 -2
- package/dist/{index-xnj9bgxe.js → index-2gxzjvyr.js} +2 -162
- package/dist/index-4gcnakhx.js +82 -0
- package/dist/{index-j05z5gn4.js → index-55hkhm67.js} +136 -119
- package/dist/{index-cq4qfycf.js → index-79z7m7dt.js} +227 -59
- package/dist/{index-97ac4gph.js → index-7f68ghdn.js} +3 -3
- package/dist/{index-r7nmqpsg.js → index-7p1f0vp2.js} +1 -1
- package/dist/{index-dcpdvjsc.js → index-863ea9jb.js} +4 -4
- package/dist/index-8p52kd5p.js +242 -0
- package/dist/{index-2qzskm8h.js → index-dce5wxcq.js} +1 -1
- package/dist/index-e01r054k.js +105 -0
- package/dist/{index-sees8yf8.js → index-ensd0r74.js} +118 -111
- package/dist/{index-1nd48tm9.js → index-gxrt5h6v.js} +2 -1
- package/dist/{index-e87kakm4.js → index-ham5sz8m.js} +112 -110
- package/dist/{index-kj2wbeta.js → index-het2he5g.js} +280 -196
- package/dist/{index-vcvkq30w.js → index-hmp4800j.js} +3 -3
- package/dist/{index-gyr48nzg.js → index-k30h66yd.js} +71 -151
- package/dist/{index-2cr1cqhn.js → index-khtgb21r.js} +2 -2
- package/dist/{index-x4799c19.js → index-ndddxtyx.js} +11 -11
- package/dist/{index-dydjcp8z.js → index-np4m8hd3.js} +38 -36
- package/dist/{index-p81267c2.js → index-p3vsv1fb.js} +621 -357
- package/dist/{index-mp5sn43f.js → index-p9e0w8hs.js} +2 -2
- package/dist/{index-rewkc2hj.js → index-p9sh0xx4.js} +3 -3
- package/dist/{index-70yj2ebz.js → index-paz6sgdp.js} +107 -103
- package/dist/{index-bn2cjajt.js → index-px2gm2jp.js} +26 -102
- package/dist/index-s812ycat.js +65 -0
- package/dist/{index-xsqjkha9.js → index-sp1tzwnb.js} +2 -2
- package/dist/{index-n6hxg8as.js → index-t9rhjr9f.js} +615 -566
- package/dist/{index-zeemqhqx.js → index-v260df89.js} +88 -80
- package/dist/{index-fdp6hdxn.js → index-w906953s.js} +5 -1
- package/dist/{index-mdzh02yc.js → index-wdkt63w3.js} +1 -1
- package/dist/{index-58k4fp34.js → index-wsm5w4ee.js} +1 -1
- package/dist/{index-v38qyerb.js → index-xw3s75nj.js} +1 -1
- package/dist/internal/atomic-file.d.ts +23 -2
- package/dist/internal/atomic-file.d.ts.map +1 -1
- package/dist/internal/exclusive-lock.d.ts +51 -0
- package/dist/internal/exclusive-lock.d.ts.map +1 -0
- package/dist/internal/process-identity.d.ts +47 -0
- package/dist/internal/process-identity.d.ts.map +1 -0
- package/dist/internal/with-exclusive-lock.d.ts +67 -0
- package/dist/internal/with-exclusive-lock.d.ts.map +1 -0
- package/dist/live/watch-client.d.ts.map +1 -1
- package/dist/observability/audit.d.ts +2 -2
- package/dist/observability/audit.d.ts.map +1 -1
- package/dist/observability/event.d.ts +2 -1
- package/dist/observability/event.d.ts.map +1 -1
- package/dist/primitives/export-operation.d.ts +1 -1
- package/dist/primitives/export-operation.d.ts.map +1 -1
- package/dist/realtime/registry.d.ts +0 -5
- package/dist/realtime/registry.d.ts.map +1 -1
- package/dist/server/bun.d.ts +0 -1
- package/dist/server/bun.d.ts.map +1 -1
- package/dist/server/context-contribution.d.ts +1 -1
- package/dist/server/context-contribution.d.ts.map +1 -1
- package/dist/server/context.d.ts +1 -1
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/endpoint-response.d.ts +2 -1
- package/dist/server/endpoint-response.d.ts.map +1 -1
- package/dist/server/error-dispatch.d.ts +1 -1
- package/dist/server/error-dispatch.d.ts.map +1 -1
- package/dist/server/error-hook.d.ts +1 -1
- package/dist/server/error-hook.d.ts.map +1 -1
- package/dist/server/handler-state.d.ts +1 -1
- package/dist/server/handler-state.d.ts.map +1 -1
- package/dist/server/implement-registry.d.ts +54 -0
- package/dist/server/implement-registry.d.ts.map +1 -0
- package/dist/server/implement.d.ts +9 -55
- package/dist/server/implement.d.ts.map +1 -1
- package/dist/server/middleware/auth.d.ts +1 -31
- package/dist/server/middleware/auth.d.ts.map +1 -1
- package/dist/server/middleware/jwt.d.ts +31 -0
- package/dist/server/middleware/jwt.d.ts.map +1 -0
- package/dist/server/multipart-reader.d.ts +22 -0
- package/dist/server/multipart-reader.d.ts.map +1 -0
- package/dist/server/multipart.d.ts +1 -1
- package/dist/server/multipart.d.ts.map +1 -1
- package/dist/server/oauth/cimd.d.ts +88 -0
- package/dist/server/oauth/cimd.d.ts.map +1 -0
- package/dist/server/oauth/endpoints.d.ts +39 -0
- package/dist/server/oauth/endpoints.d.ts.map +1 -0
- package/dist/server/oauth/provider.d.ts +1 -68
- package/dist/server/oauth/provider.d.ts.map +1 -1
- package/dist/server/streaming-pump.d.ts +66 -0
- package/dist/server/streaming-pump.d.ts.map +1 -0
- package/dist/server/streaming-route.d.ts +12 -5
- package/dist/server/streaming-route.d.ts.map +1 -1
- package/dist/server/types.d.ts +4 -1
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/unix-client-bun.d.ts.map +1 -1
- package/dist/server/unix-client-http1.d.ts +76 -0
- package/dist/server/unix-client-http1.d.ts.map +1 -0
- package/dist/server/unix-client.d.ts.map +1 -1
- package/dist/testing/handler-clients.d.ts +2 -1
- package/dist/testing/handler-clients.d.ts.map +1 -1
- package/dist/testing/realtime-probe.d.ts +33 -0
- package/dist/testing/realtime-probe.d.ts.map +1 -0
- package/dist/testing/surface-conformance.d.ts +0 -31
- package/dist/testing/surface-conformance.d.ts.map +1 -1
- package/dist/testing/surface-manifest-digest.d.ts +44 -0
- package/dist/testing/surface-manifest-digest.d.ts.map +1 -0
- package/dist/testing/surface-manifest.d.ts.map +1 -1
- package/dist/tools/agent.d.ts +1 -1
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/cli/args-fields.d.ts +31 -0
- package/dist/tools/cli/args-fields.d.ts.map +1 -0
- package/dist/tools/cli/args-route.d.ts +42 -0
- package/dist/tools/cli/args-route.d.ts.map +1 -0
- package/dist/tools/cli/args-view.d.ts +32 -0
- package/dist/tools/cli/args-view.d.ts.map +1 -0
- package/dist/tools/cli/args.d.ts +2 -65
- package/dist/tools/cli/args.d.ts.map +1 -1
- package/dist/tools/cli/argument-error.d.ts +5 -0
- package/dist/tools/cli/argument-error.d.ts.map +1 -0
- package/dist/tools/cli/checkpoint.d.ts.map +1 -1
- package/dist/tools/cli/command.d.ts +1 -1
- package/dist/tools/cli/command.d.ts.map +1 -1
- package/dist/tools/cli/config.d.ts +1 -1
- package/dist/tools/cli/config.d.ts.map +1 -1
- package/dist/tools/cli/format.d.ts +2 -1
- package/dist/tools/cli/format.d.ts.map +1 -1
- package/dist/tools/cli/invoke.d.ts +2 -1
- package/dist/tools/cli/invoke.d.ts.map +1 -1
- package/dist/tools/cli/managed-surface.d.ts +1 -1
- package/dist/tools/cli/managed-surface.d.ts.map +1 -1
- package/dist/tools/cli/policy.d.ts +1 -1
- package/dist/tools/cli/policy.d.ts.map +1 -1
- package/dist/tools/cli/prepare.d.ts.map +1 -1
- package/dist/tools/cli/run-managed.d.ts.map +1 -1
- package/dist/tools/cli/session.d.ts +1 -1
- package/dist/tools/cli/session.d.ts.map +1 -1
- package/dist/tools/cli/update.d.ts +19 -0
- package/dist/tools/cli/update.d.ts.map +1 -1
- package/dist/tools/cli/view.d.ts +1 -1
- package/dist/tools/cli/view.d.ts.map +1 -1
- package/dist/tools/cli/wait.d.ts +1 -1
- package/dist/tools/cli/wait.d.ts.map +1 -1
- package/dist/tools/connections/runtime.d.ts +1 -1
- package/dist/tools/connections/runtime.d.ts.map +1 -1
- package/dist/tools/execute-args.d.ts +23 -0
- package/dist/tools/execute-args.d.ts.map +1 -0
- package/dist/tools/execute-hooks.d.ts +146 -0
- package/dist/tools/execute-hooks.d.ts.map +1 -0
- package/dist/tools/execute-result.d.ts +40 -0
- package/dist/tools/execute-result.d.ts.map +1 -0
- package/dist/tools/execute.d.ts +4 -193
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/internal/surface-projector.d.ts +2 -1
- package/dist/tools/internal/surface-projector.d.ts.map +1 -1
- package/dist/tools/invoker.d.ts +2 -1
- package/dist/tools/invoker.d.ts.map +1 -1
- package/dist/tools/lifecycle.d.ts +1 -1
- package/dist/tools/lifecycle.d.ts.map +1 -1
- package/dist/tools/mcp/mount.d.ts +1 -1
- package/dist/tools/mcp/mount.d.ts.map +1 -1
- package/dist/tools/mcp/prepare.d.ts +2 -1
- package/dist/tools/mcp/prepare.d.ts.map +1 -1
- package/dist/tools/mcp/progress.d.ts +1 -1
- package/dist/tools/mcp/progress.d.ts.map +1 -1
- package/dist/tools/mcp/register.d.ts +3 -2
- package/dist/tools/mcp/register.d.ts.map +1 -1
- package/dist/tools/mcp/round-context.d.ts +38 -0
- package/dist/tools/mcp/round-context.d.ts.map +1 -0
- package/dist/tools/mcp/round-policy.d.ts +1 -1
- package/dist/tools/mcp/round-policy.d.ts.map +1 -1
- package/dist/tools/mcp/round.d.ts +3 -11
- package/dist/tools/mcp/round.d.ts.map +1 -1
- package/dist/tools/mcp/runtime-tools.d.ts +2 -1
- package/dist/tools/mcp/runtime-tools.d.ts.map +1 -1
- package/dist/tools/mount.d.ts +3 -1
- package/dist/tools/mount.d.ts.map +1 -1
- package/dist/tools/native-definition.d.ts +2 -1
- package/dist/tools/native-definition.d.ts.map +1 -1
- package/dist/tools/operations/async-operation-runtime-tools.d.ts +2 -1
- package/dist/tools/operations/async-operation-runtime-tools.d.ts.map +1 -1
- package/dist/tools/operations/async-operation-runtime-types.d.ts +2 -1
- package/dist/tools/operations/async-operation-runtime-types.d.ts.map +1 -1
- package/dist/tools/remote.d.ts.map +1 -1
- package/dist/tools/runtime-tool.d.ts +3 -1
- package/dist/tools/runtime-tool.d.ts.map +1 -1
- package/dist/tools/tool-logger.d.ts +1 -1
- package/dist/tools/tool-logger.d.ts.map +1 -1
- package/dist/tracking/client-listeners.d.ts +30 -0
- package/dist/tracking/client-listeners.d.ts.map +1 -0
- package/dist/tracking/client-visit.d.ts +61 -0
- package/dist/tracking/client-visit.d.ts.map +1 -0
- package/dist/tracking/client.d.ts +3 -2
- package/dist/tracking/client.d.ts.map +1 -1
- package/llms/application.2.txt +266 -2
- package/llms/application.txt +8 -266
- package/llms/cli.2.txt +80 -0
- package/llms/cli.txt +45 -74
- package/llms/contract.txt +3 -3
- package/llms/files.txt +3 -0
- package/llms/tools.2.txt +88 -279
- package/llms/tools.3.txt +288 -0
- package/llms/tools.txt +27 -65
- package/llms-full.txt +108 -12
- package/llms.txt +5 -5
- package/package.json +1 -1
- package/dist/index-e2z3ahw9.js +0 -325
- package/dist/index-mkm15s49.js +0 -394
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ApiError
|
|
3
|
-
} from "../index-
|
|
3
|
+
} from "../index-v260df89.js";
|
|
4
4
|
import {
|
|
5
5
|
defineContract
|
|
6
|
-
} from "../index-
|
|
6
|
+
} from "../index-k30h66yd.js";
|
|
7
|
+
import"../index-4gcnakhx.js";
|
|
7
8
|
import"../index-zcgf3gqf.js";
|
|
8
9
|
import"../index-kzfs85xp.js";
|
|
9
10
|
import"../index-hffjpmq9.js";
|
|
@@ -258,6 +259,69 @@ function resolveTrackedClick(target, { origin, attributes = {}, isAction = () =>
|
|
|
258
259
|
}
|
|
259
260
|
return result.interaction || result.click || result.outbound ? result : null;
|
|
260
261
|
}
|
|
262
|
+
// src/tracking/client-listeners.ts
|
|
263
|
+
function wireTrackingListeners(deps) {
|
|
264
|
+
const { host, builtin } = deps;
|
|
265
|
+
const unsubscribe = [];
|
|
266
|
+
const renewThenFlush = () => void deps.renewVisit().then(() => deps.flushOutbox());
|
|
267
|
+
unsubscribe.push(host.on("online", renewThenFlush));
|
|
268
|
+
unsubscribe.push(host.interval(() => void deps.flushOutbox(), deps.heartbeatMs));
|
|
269
|
+
let hiddenAt = null;
|
|
270
|
+
let lastLeaveAt = Number.NEGATIVE_INFINITY;
|
|
271
|
+
const onHide = () => {
|
|
272
|
+
const at = host.now();
|
|
273
|
+
if (at - lastLeaveAt < 1000)
|
|
274
|
+
return;
|
|
275
|
+
lastLeaveAt = at;
|
|
276
|
+
deps.sendOnUnload(deps.leaveDraft(deps.currentPage()));
|
|
277
|
+
deps.releaseLease();
|
|
278
|
+
};
|
|
279
|
+
unsubscribe.push(host.on("pagehide", onHide));
|
|
280
|
+
unsubscribe.push(host.on("visibilitychange", () => {
|
|
281
|
+
if (!host.visible()) {
|
|
282
|
+
hiddenAt = host.wallClock();
|
|
283
|
+
onHide();
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
deps.meter.checkpoint();
|
|
287
|
+
if (hiddenAt !== null && host.wallClock() - hiddenAt >= deps.renewAfterHiddenMs) {
|
|
288
|
+
renewThenFlush();
|
|
289
|
+
}
|
|
290
|
+
hiddenAt = null;
|
|
291
|
+
}));
|
|
292
|
+
unsubscribe.push(host.interval(() => {
|
|
293
|
+
deps.send([deps.draft(builtin.heartbeat, { ...deps.meter.heartbeat(host.visible()) })]);
|
|
294
|
+
}, deps.heartbeatMs));
|
|
295
|
+
unsubscribe.push(host.on("scroll", () => deps.scroll.record(host.scrollDepth())));
|
|
296
|
+
unsubscribe.push(host.interval(() => {
|
|
297
|
+
for (const milestone of deps.scroll.observe(host.scrollDepth())) {
|
|
298
|
+
deps.send([deps.draft(builtin.scrollDepth, { maxPercent: milestone })]);
|
|
299
|
+
}
|
|
300
|
+
}, 2000));
|
|
301
|
+
unsubscribe.push(host.onClick((target) => {
|
|
302
|
+
const click = resolveTrackedClick(target, {
|
|
303
|
+
origin: host.page().origin,
|
|
304
|
+
attributes: deps.clickAttributes,
|
|
305
|
+
isAction: deps.isAction
|
|
306
|
+
});
|
|
307
|
+
if (!click)
|
|
308
|
+
return;
|
|
309
|
+
const drafts = [];
|
|
310
|
+
if (click.interaction)
|
|
311
|
+
drafts.push(deps.draft(builtin.interaction, { ...click.interaction }));
|
|
312
|
+
if (click.click)
|
|
313
|
+
drafts.push(deps.draft(builtin.click, { ...click.click }));
|
|
314
|
+
if (click.outbound)
|
|
315
|
+
drafts.push(deps.draft(builtin.outboundClick, { ...click.outbound }));
|
|
316
|
+
if (click.leavesPage)
|
|
317
|
+
for (const item of drafts)
|
|
318
|
+
deps.sendOnUnload(item);
|
|
319
|
+
else
|
|
320
|
+
deps.send(drafts);
|
|
321
|
+
}));
|
|
322
|
+
return unsubscribe;
|
|
323
|
+
}
|
|
324
|
+
|
|
261
325
|
// src/tracking/delivery.ts
|
|
262
326
|
function isRetryable(error) {
|
|
263
327
|
return ApiError.is(error) && (error.status === 0 || error.status >= 500);
|
|
@@ -295,40 +359,6 @@ async function deliverTrackingBatch({
|
|
|
295
359
|
return "failed";
|
|
296
360
|
}
|
|
297
361
|
|
|
298
|
-
// src/tracking/scroll.ts
|
|
299
|
-
function scrollDepthPercent(view) {
|
|
300
|
-
const scrollable = view.scrollHeight - view.innerHeight;
|
|
301
|
-
if (scrollable <= 0)
|
|
302
|
-
return 0;
|
|
303
|
-
return Math.max(0, Math.min(100, Math.round(view.scrollY / scrollable * 100)));
|
|
304
|
-
}
|
|
305
|
-
function createScrollMilestones(milestones = [25, 50, 75, 100]) {
|
|
306
|
-
const sorted = [...milestones].sort((a, b) => a - b);
|
|
307
|
-
let deepest = 0;
|
|
308
|
-
const fired = new Set;
|
|
309
|
-
return {
|
|
310
|
-
record(percent) {
|
|
311
|
-
deepest = Math.max(deepest, percent);
|
|
312
|
-
},
|
|
313
|
-
observe(percent) {
|
|
314
|
-
deepest = Math.max(deepest, percent);
|
|
315
|
-
const reached = [];
|
|
316
|
-
for (const milestone of sorted) {
|
|
317
|
-
if (deepest >= milestone && !fired.has(milestone)) {
|
|
318
|
-
fired.add(milestone);
|
|
319
|
-
reached.push(milestone);
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
return reached;
|
|
323
|
-
},
|
|
324
|
-
max: () => deepest,
|
|
325
|
-
reset() {
|
|
326
|
-
deepest = 0;
|
|
327
|
-
fired.clear();
|
|
328
|
-
}
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
|
|
332
362
|
// src/tracking/sequence-reserve.ts
|
|
333
363
|
function createSequenceReserve(reserve, options = {}) {
|
|
334
364
|
const blockSize = options.blockSize ?? 16;
|
|
@@ -376,6 +406,185 @@ function createSequenceReserve(reserve, options = {}) {
|
|
|
376
406
|
};
|
|
377
407
|
}
|
|
378
408
|
|
|
409
|
+
// src/tracking/client-visit.ts
|
|
410
|
+
function bootstrapTrackingVisit(deps, renew) {
|
|
411
|
+
const { visit, config, host, outbox, sequences, captureAttribution, fail } = deps;
|
|
412
|
+
if (!renew && visit.visitId && visit.browserStreamId)
|
|
413
|
+
return Promise.resolve(visit.visitId);
|
|
414
|
+
if (visit.bootstrapping)
|
|
415
|
+
return visit.bootstrapping;
|
|
416
|
+
const run = (async () => {
|
|
417
|
+
try {
|
|
418
|
+
const health = outbox ? await outbox.health() : { state: "unavailable", queued: 0, dropped: 0 };
|
|
419
|
+
const wasAvailable = visit.outboxAvailable;
|
|
420
|
+
visit.outboxAvailable = health.state === "available";
|
|
421
|
+
if (visit.outboxAvailable && !wasAvailable && !sequences.shared())
|
|
422
|
+
sequences.reset();
|
|
423
|
+
visit.browserStreamId = visit.outboxAvailable && outbox ? await outbox.streamId() : visit.browserStreamId ?? host.randomUUID();
|
|
424
|
+
await sequences.refill();
|
|
425
|
+
const page = host.page();
|
|
426
|
+
const touch = captureAttribution(page.search, page.pathname);
|
|
427
|
+
const response = await config.bootstrap({
|
|
428
|
+
browserStreamId: visit.browserStreamId,
|
|
429
|
+
previousVisitId: visit.visitId ?? undefined,
|
|
430
|
+
origin: page.origin,
|
|
431
|
+
landingPath: page.pathname,
|
|
432
|
+
referrer: page.referrer || undefined,
|
|
433
|
+
utm: touch?.currentTouch.utm?.source ? touch.currentTouch.utm : undefined,
|
|
434
|
+
displayMode: page.displayMode,
|
|
435
|
+
screenWidth: page.screenWidth,
|
|
436
|
+
screenHeight: page.screenHeight,
|
|
437
|
+
buildId: config.buildId,
|
|
438
|
+
outboxState: health.state,
|
|
439
|
+
outboxQueued: health.queued,
|
|
440
|
+
outboxDropped: health.dropped
|
|
441
|
+
});
|
|
442
|
+
visit.visitId = response.visitId;
|
|
443
|
+
config.onVisit?.(visit.visitId);
|
|
444
|
+
return visit.visitId;
|
|
445
|
+
} catch (error) {
|
|
446
|
+
fail("visit bootstrap", error);
|
|
447
|
+
return null;
|
|
448
|
+
} finally {
|
|
449
|
+
visit.bootstrapping = null;
|
|
450
|
+
}
|
|
451
|
+
})();
|
|
452
|
+
visit.bootstrapping = run;
|
|
453
|
+
return run;
|
|
454
|
+
}
|
|
455
|
+
function createOutboxFlusher(deps) {
|
|
456
|
+
const { outbox } = deps;
|
|
457
|
+
let flushing = null;
|
|
458
|
+
let queued = null;
|
|
459
|
+
const flushOutbox = () => {
|
|
460
|
+
if (!outbox || !deps.isAvailable())
|
|
461
|
+
return Promise.resolve();
|
|
462
|
+
if (flushing) {
|
|
463
|
+
queued ??= flushing.then(() => {
|
|
464
|
+
queued = null;
|
|
465
|
+
return flushOutbox();
|
|
466
|
+
});
|
|
467
|
+
return queued;
|
|
468
|
+
}
|
|
469
|
+
flushing = (async () => {
|
|
470
|
+
try {
|
|
471
|
+
if (!await outbox.acquireLease(deps.owner))
|
|
472
|
+
return;
|
|
473
|
+
const batch = await outbox.readBatch(deps.batchSize);
|
|
474
|
+
if (batch.length === 0)
|
|
475
|
+
return;
|
|
476
|
+
const response = await deps.deliver(batch);
|
|
477
|
+
if (response) {
|
|
478
|
+
await outbox.acknowledge(response.dispositions.map((item) => item.eventId));
|
|
479
|
+
}
|
|
480
|
+
} catch (error) {
|
|
481
|
+
deps.fail("outbox flush", error);
|
|
482
|
+
} finally {
|
|
483
|
+
flushing = null;
|
|
484
|
+
}
|
|
485
|
+
})();
|
|
486
|
+
return flushing;
|
|
487
|
+
};
|
|
488
|
+
return flushOutbox;
|
|
489
|
+
}
|
|
490
|
+
function createVisitSequences(outbox, visit, options, fail) {
|
|
491
|
+
return createSequenceReserve((count) => {
|
|
492
|
+
if (!outbox || !visit.outboxAvailable)
|
|
493
|
+
return Promise.reject(new Error("outbox unavailable"));
|
|
494
|
+
return outbox.reserveSequences(count);
|
|
495
|
+
}, {
|
|
496
|
+
...options,
|
|
497
|
+
onUnavailable: outbox ? (error) => {
|
|
498
|
+
visit.outboxAvailable = false;
|
|
499
|
+
fail("sequence reservation", error);
|
|
500
|
+
} : undefined
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
function pageAttribution(host, storage, referrerMap, search, pathname) {
|
|
504
|
+
const page = host.page();
|
|
505
|
+
return resolveAttribution({
|
|
506
|
+
search,
|
|
507
|
+
pathname,
|
|
508
|
+
referrer: page.referrer,
|
|
509
|
+
hostname: page.hostname,
|
|
510
|
+
storage,
|
|
511
|
+
referrerMap,
|
|
512
|
+
now: host.wallClock()
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
function pageViewDraft(host, type, pathname, previous) {
|
|
516
|
+
const page = host.page();
|
|
517
|
+
return {
|
|
518
|
+
type,
|
|
519
|
+
page: pathname,
|
|
520
|
+
metadata: {
|
|
521
|
+
title: page.title,
|
|
522
|
+
screenWidth: page.viewportWidth,
|
|
523
|
+
screenHeight: page.viewportHeight,
|
|
524
|
+
referrer: previous ? undefined : page.referrer || undefined
|
|
525
|
+
},
|
|
526
|
+
clientTimestamp: host.wallClock()
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
async function materializeAll(drafts, materialize, sequences) {
|
|
530
|
+
const events = [];
|
|
531
|
+
for (const draft of drafts) {
|
|
532
|
+
let event = materialize(draft);
|
|
533
|
+
if (!event) {
|
|
534
|
+
await sequences.refill();
|
|
535
|
+
event = materialize(draft);
|
|
536
|
+
}
|
|
537
|
+
if (event)
|
|
538
|
+
events.push(event);
|
|
539
|
+
}
|
|
540
|
+
return events;
|
|
541
|
+
}
|
|
542
|
+
async function deliverTrackedEvents(config, request, fail) {
|
|
543
|
+
let response = null;
|
|
544
|
+
const outcome = await deliverTrackingBatch({
|
|
545
|
+
request: async () => {
|
|
546
|
+
response = await config.deliver(request);
|
|
547
|
+
},
|
|
548
|
+
onUnauthorized: config.onUnauthorized,
|
|
549
|
+
onFailure: (error) => fail("event delivery", error)
|
|
550
|
+
});
|
|
551
|
+
return outcome === "delivered" ? response : null;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// src/tracking/scroll.ts
|
|
555
|
+
function scrollDepthPercent(view) {
|
|
556
|
+
const scrollable = view.scrollHeight - view.innerHeight;
|
|
557
|
+
if (scrollable <= 0)
|
|
558
|
+
return 0;
|
|
559
|
+
return Math.max(0, Math.min(100, Math.round(view.scrollY / scrollable * 100)));
|
|
560
|
+
}
|
|
561
|
+
function createScrollMilestones(milestones = [25, 50, 75, 100]) {
|
|
562
|
+
const sorted = [...milestones].sort((a, b) => a - b);
|
|
563
|
+
let deepest = 0;
|
|
564
|
+
const fired = new Set;
|
|
565
|
+
return {
|
|
566
|
+
record(percent) {
|
|
567
|
+
deepest = Math.max(deepest, percent);
|
|
568
|
+
},
|
|
569
|
+
observe(percent) {
|
|
570
|
+
deepest = Math.max(deepest, percent);
|
|
571
|
+
const reached = [];
|
|
572
|
+
for (const milestone of sorted) {
|
|
573
|
+
if (deepest >= milestone && !fired.has(milestone)) {
|
|
574
|
+
fired.add(milestone);
|
|
575
|
+
reached.push(milestone);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
return reached;
|
|
579
|
+
},
|
|
580
|
+
max: () => deepest,
|
|
581
|
+
reset() {
|
|
582
|
+
deepest = 0;
|
|
583
|
+
fired.clear();
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
|
|
379
588
|
// src/tracking/visible-time.ts
|
|
380
589
|
function createVisibleTimeMeter(options = {}) {
|
|
381
590
|
const now = options.now ?? (() => performance.now());
|
|
@@ -421,154 +630,63 @@ function chunk(items, size) {
|
|
|
421
630
|
chunks.push(items.slice(at, at + size));
|
|
422
631
|
return chunks;
|
|
423
632
|
}
|
|
424
|
-
function
|
|
633
|
+
function unloadBeacon(unloadUrl) {
|
|
634
|
+
return (request) => unloadUrl === undefined ? false : sendUnloadBeacon(unloadUrl, JSON.stringify(request));
|
|
635
|
+
}
|
|
636
|
+
function currentUtmOf(attribution) {
|
|
637
|
+
return attribution?.currentTouch.utm?.source ? attribution.currentTouch.utm : undefined;
|
|
638
|
+
}
|
|
639
|
+
function trackingTimings(config) {
|
|
425
640
|
if (typeof config.buildId !== "string" || config.buildId.length === 0) {
|
|
426
641
|
throw new Error('[stitchkit] tracking client requires a buildId — a git SHA or "dev"');
|
|
427
642
|
}
|
|
643
|
+
return {
|
|
644
|
+
heartbeatMs: config.heartbeatMs ?? 30000,
|
|
645
|
+
renewAfterHiddenMs: config.renewAfterHiddenMs ?? 30 * 60 * 1000,
|
|
646
|
+
pendingLimit: config.pendingLimit ?? 100,
|
|
647
|
+
batchSize: config.batchSize ?? 50
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
function createTrackingClient(config) {
|
|
428
651
|
const { host, builtin, outbox } = config;
|
|
429
|
-
const heartbeatMs = config
|
|
430
|
-
const renewAfterHiddenMs = config.renewAfterHiddenMs ?? 30 * 60 * 1000;
|
|
431
|
-
const pendingLimit = config.pendingLimit ?? 100;
|
|
432
|
-
const batchSize = config.batchSize ?? 50;
|
|
652
|
+
const { heartbeatMs, renewAfterHiddenMs, pendingLimit, batchSize } = trackingTimings(config);
|
|
433
653
|
const fail = config.onFailure ?? (() => {
|
|
434
654
|
return;
|
|
435
655
|
});
|
|
436
656
|
const decorate = config.decorate ?? ((event) => event);
|
|
437
|
-
const unload = config.unload ?? (
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
657
|
+
const unload = config.unload ?? unloadBeacon(config.unloadUrl);
|
|
658
|
+
const visit = {
|
|
659
|
+
browserStreamId: null,
|
|
660
|
+
visitId: null,
|
|
661
|
+
outboxAvailable: outbox !== undefined,
|
|
662
|
+
bootstrapping: null
|
|
663
|
+
};
|
|
442
664
|
let pending = [];
|
|
443
665
|
let currentPage = null;
|
|
444
666
|
let attribution = null;
|
|
445
667
|
let running = 0;
|
|
446
668
|
const flushOwner = host.randomUUID();
|
|
447
|
-
const meter = createVisibleTimeMeter(
|
|
448
|
-
now: () => host.now(),
|
|
449
|
-
wallClock: () => host.wallClock(),
|
|
450
|
-
randomUUID: () => host.randomUUID()
|
|
451
|
-
});
|
|
669
|
+
const meter = createVisibleTimeMeter(host);
|
|
452
670
|
const scroll = createScrollMilestones(config.scrollMilestones);
|
|
453
|
-
const sequences =
|
|
454
|
-
if (!outbox || !outboxAvailable)
|
|
455
|
-
return Promise.reject(new Error("outbox unavailable"));
|
|
456
|
-
return outbox.reserveSequences(count);
|
|
457
|
-
}, {
|
|
458
|
-
...config.sequence,
|
|
459
|
-
onUnavailable: outbox ? (error) => {
|
|
460
|
-
outboxAvailable = false;
|
|
461
|
-
fail("sequence reservation", error);
|
|
462
|
-
} : undefined
|
|
463
|
-
});
|
|
464
|
-
const currentUtm = () => attribution?.currentTouch.utm?.source ? attribution.currentTouch.utm : undefined;
|
|
671
|
+
const sequences = createVisitSequences(outbox, visit, config.sequence, fail);
|
|
465
672
|
const captureAttribution = (search, pathname) => {
|
|
466
673
|
if (!host.storage)
|
|
467
674
|
return null;
|
|
468
|
-
|
|
469
|
-
attribution = resolveAttribution({
|
|
470
|
-
search,
|
|
471
|
-
pathname,
|
|
472
|
-
referrer: page.referrer,
|
|
473
|
-
hostname: page.hostname,
|
|
474
|
-
storage: host.storage,
|
|
475
|
-
referrerMap: config.referrerMap,
|
|
476
|
-
now: host.wallClock()
|
|
477
|
-
});
|
|
675
|
+
attribution = pageAttribution(host, host.storage, config.referrerMap, search, pathname);
|
|
478
676
|
return attribution;
|
|
479
677
|
};
|
|
480
|
-
const bootstrapVisit = (renew = false) => {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
if (outboxAvailable && !wasAvailable && !sequences.shared())
|
|
491
|
-
sequences.reset();
|
|
492
|
-
browserStreamId = outboxAvailable && outbox ? await outbox.streamId() : browserStreamId ?? host.randomUUID();
|
|
493
|
-
await sequences.refill();
|
|
494
|
-
const page = host.page();
|
|
495
|
-
const touch = captureAttribution(page.search, page.pathname);
|
|
496
|
-
const response = await config.bootstrap({
|
|
497
|
-
browserStreamId,
|
|
498
|
-
previousVisitId: visitId ?? undefined,
|
|
499
|
-
origin: page.origin,
|
|
500
|
-
landingPath: page.pathname,
|
|
501
|
-
referrer: page.referrer || undefined,
|
|
502
|
-
utm: touch?.currentTouch.utm?.source ? touch.currentTouch.utm : undefined,
|
|
503
|
-
displayMode: page.displayMode,
|
|
504
|
-
screenWidth: page.screenWidth,
|
|
505
|
-
screenHeight: page.screenHeight,
|
|
506
|
-
buildId: config.buildId,
|
|
507
|
-
outboxState: health.state,
|
|
508
|
-
outboxQueued: health.queued,
|
|
509
|
-
outboxDropped: health.dropped
|
|
510
|
-
});
|
|
511
|
-
visitId = response.visitId;
|
|
512
|
-
config.onVisit?.(visitId);
|
|
513
|
-
return visitId;
|
|
514
|
-
} catch (error) {
|
|
515
|
-
fail("visit bootstrap", error);
|
|
516
|
-
return null;
|
|
517
|
-
} finally {
|
|
518
|
-
bootstrapping = null;
|
|
519
|
-
}
|
|
520
|
-
})();
|
|
521
|
-
bootstrapping = run;
|
|
522
|
-
return run;
|
|
523
|
-
};
|
|
524
|
-
const deliver = async (events) => {
|
|
525
|
-
let response = null;
|
|
526
|
-
const outcome = await deliverTrackingBatch({
|
|
527
|
-
request: async () => {
|
|
528
|
-
response = await config.deliver({
|
|
529
|
-
buildId: config.buildId,
|
|
530
|
-
events,
|
|
531
|
-
utm: currentUtm()
|
|
532
|
-
});
|
|
533
|
-
},
|
|
534
|
-
onUnauthorized: config.onUnauthorized,
|
|
535
|
-
onFailure: (error) => fail("event delivery", error)
|
|
536
|
-
});
|
|
537
|
-
return outcome === "delivered" ? response : null;
|
|
538
|
-
};
|
|
539
|
-
let flushing = null;
|
|
540
|
-
let queued = null;
|
|
541
|
-
const flushOutbox = () => {
|
|
542
|
-
if (!outbox || !outboxAvailable)
|
|
543
|
-
return Promise.resolve();
|
|
544
|
-
if (flushing) {
|
|
545
|
-
queued ??= flushing.then(() => {
|
|
546
|
-
queued = null;
|
|
547
|
-
return flushOutbox();
|
|
548
|
-
});
|
|
549
|
-
return queued;
|
|
550
|
-
}
|
|
551
|
-
flushing = (async () => {
|
|
552
|
-
try {
|
|
553
|
-
if (!await outbox.acquireLease(flushOwner))
|
|
554
|
-
return;
|
|
555
|
-
const batch = await outbox.readBatch(batchSize);
|
|
556
|
-
if (batch.length === 0)
|
|
557
|
-
return;
|
|
558
|
-
const response = await deliver(batch);
|
|
559
|
-
if (response) {
|
|
560
|
-
await outbox.acknowledge(response.dispositions.map((item) => item.eventId));
|
|
561
|
-
}
|
|
562
|
-
} catch (error) {
|
|
563
|
-
fail("outbox flush", error);
|
|
564
|
-
} finally {
|
|
565
|
-
flushing = null;
|
|
566
|
-
}
|
|
567
|
-
})();
|
|
568
|
-
return flushing;
|
|
569
|
-
};
|
|
678
|
+
const bootstrapVisit = (renew = false) => bootstrapTrackingVisit({ visit, config, host, outbox, sequences, captureAttribution, fail }, renew);
|
|
679
|
+
const deliver = (events) => deliverTrackedEvents(config, { buildId: config.buildId, events, utm: currentUtmOf(attribution) }, fail);
|
|
680
|
+
const flushOutbox = createOutboxFlusher({
|
|
681
|
+
outbox,
|
|
682
|
+
isAvailable: () => visit.outboxAvailable,
|
|
683
|
+
owner: flushOwner,
|
|
684
|
+
batchSize,
|
|
685
|
+
deliver,
|
|
686
|
+
fail
|
|
687
|
+
});
|
|
570
688
|
const materialize = (draft2) => {
|
|
571
|
-
if (!visitId || !browserStreamId)
|
|
689
|
+
if (!visit.visitId || !visit.browserStreamId)
|
|
572
690
|
return null;
|
|
573
691
|
const sequence = sequences.take();
|
|
574
692
|
if (sequence === null)
|
|
@@ -576,13 +694,13 @@ function createTrackingClient(config) {
|
|
|
576
694
|
return decorate({
|
|
577
695
|
...draft2,
|
|
578
696
|
eventId: host.randomUUID(),
|
|
579
|
-
visitId,
|
|
580
|
-
browserStreamId,
|
|
697
|
+
visitId: visit.visitId,
|
|
698
|
+
browserStreamId: visit.browserStreamId,
|
|
581
699
|
browserSequence: sequence
|
|
582
700
|
});
|
|
583
701
|
};
|
|
584
702
|
const persistAndFlush = async (events) => {
|
|
585
|
-
if (!outbox || !outboxAvailable) {
|
|
703
|
+
if (!outbox || !visit.outboxAvailable) {
|
|
586
704
|
for (const batch of chunk(events, batchSize))
|
|
587
705
|
await deliver(batch);
|
|
588
706
|
return;
|
|
@@ -601,7 +719,7 @@ function createTrackingClient(config) {
|
|
|
601
719
|
send(drafts);
|
|
602
720
|
};
|
|
603
721
|
const send = (drafts) => {
|
|
604
|
-
if (!visitId || !browserStreamId) {
|
|
722
|
+
if (!visit.visitId || !visit.browserStreamId) {
|
|
605
723
|
pending = [...pending, ...drafts].slice(-pendingLimit);
|
|
606
724
|
bootstrapVisit().then((issued) => {
|
|
607
725
|
if (issued)
|
|
@@ -609,20 +727,10 @@ function createTrackingClient(config) {
|
|
|
609
727
|
});
|
|
610
728
|
return;
|
|
611
729
|
}
|
|
612
|
-
(async () => {
|
|
613
|
-
const events = [];
|
|
614
|
-
for (const draft2 of drafts) {
|
|
615
|
-
let event = materialize(draft2);
|
|
616
|
-
if (!event) {
|
|
617
|
-
await sequences.refill();
|
|
618
|
-
event = materialize(draft2);
|
|
619
|
-
}
|
|
620
|
-
if (event)
|
|
621
|
-
events.push(event);
|
|
622
|
-
}
|
|
730
|
+
materializeAll(drafts, materialize, sequences).then(async (events) => {
|
|
623
731
|
if (events.length > 0)
|
|
624
732
|
await persistAndFlush(events);
|
|
625
|
-
})
|
|
733
|
+
});
|
|
626
734
|
};
|
|
627
735
|
const sendOnUnload = (draft2) => {
|
|
628
736
|
const event = materialize(draft2);
|
|
@@ -630,26 +738,19 @@ function createTrackingClient(config) {
|
|
|
630
738
|
send([draft2]);
|
|
631
739
|
return;
|
|
632
740
|
}
|
|
633
|
-
unload({ buildId: config.buildId, events: [event], utm:
|
|
634
|
-
if (outbox && outboxAvailable)
|
|
741
|
+
unload({ buildId: config.buildId, events: [event], utm: currentUtmOf(attribution) });
|
|
742
|
+
if (outbox && visit.outboxAvailable)
|
|
635
743
|
outbox.enqueue(event).catch((error) => fail("unload event persistence", error));
|
|
636
|
-
}
|
|
637
744
|
};
|
|
638
|
-
const draft = (type, metadata) =>
|
|
639
|
-
|
|
640
|
-
page
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
metadata: { ...meter.cut(), scrollDepthPercent: scroll.max() },
|
|
648
|
-
clientTimestamp: host.wallClock()
|
|
649
|
-
});
|
|
650
|
-
function track(type, metadata) {
|
|
651
|
-
send([draft(type, metadata === undefined ? undefined : asMetadata(metadata))]);
|
|
652
|
-
}
|
|
745
|
+
const draft = (type, metadata) => {
|
|
746
|
+
const page = currentPage ?? host.page().pathname;
|
|
747
|
+
return { type, page, metadata, clientTimestamp: host.wallClock() };
|
|
748
|
+
};
|
|
749
|
+
const leaveDraft = (page) => {
|
|
750
|
+
const metadata = { ...meter.cut(), scrollDepthPercent: scroll.max() };
|
|
751
|
+
return { type: builtin.pageLeave, page, metadata, clientTimestamp: host.wallClock() };
|
|
752
|
+
};
|
|
753
|
+
const track = (type, metadata) => send([draft(type, metadata === undefined ? undefined : asMetadata(metadata))]);
|
|
653
754
|
const onNavigate = (pathname, search) => {
|
|
654
755
|
captureAttribution(search, pathname);
|
|
655
756
|
const previous = currentPage;
|
|
@@ -660,89 +761,39 @@ function createTrackingClient(config) {
|
|
|
660
761
|
currentPage = pathname;
|
|
661
762
|
meter.checkpoint();
|
|
662
763
|
scroll.reset();
|
|
663
|
-
|
|
664
|
-
send([
|
|
665
|
-
{
|
|
666
|
-
type: builtin.pageView,
|
|
667
|
-
page: pathname,
|
|
668
|
-
metadata: {
|
|
669
|
-
title: page.title,
|
|
670
|
-
screenWidth: page.viewportWidth,
|
|
671
|
-
screenHeight: page.viewportHeight,
|
|
672
|
-
referrer: previous ? undefined : page.referrer || undefined
|
|
673
|
-
},
|
|
674
|
-
clientTimestamp: host.wallClock()
|
|
675
|
-
}
|
|
676
|
-
]);
|
|
764
|
+
send([pageViewDraft(host, builtin.pageView, pathname, previous)]);
|
|
677
765
|
};
|
|
678
766
|
const start = () => {
|
|
679
767
|
const generation = ++running;
|
|
680
|
-
const unsubscribe = [];
|
|
681
768
|
bootstrapVisit().then((issued) => {
|
|
682
769
|
if (!issued || generation !== running)
|
|
683
770
|
return;
|
|
684
771
|
drainPending();
|
|
685
772
|
flushOutbox();
|
|
686
773
|
});
|
|
687
|
-
const
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
sendOnUnload
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
meter.checkpoint();
|
|
711
|
-
if (hiddenAt !== null && host.wallClock() - hiddenAt >= renewAfterHiddenMs) {
|
|
712
|
-
renewThenFlush();
|
|
713
|
-
}
|
|
714
|
-
hiddenAt = null;
|
|
715
|
-
}));
|
|
716
|
-
unsubscribe.push(host.interval(() => {
|
|
717
|
-
send([draft(builtin.heartbeat, { ...meter.heartbeat(host.visible()) })]);
|
|
718
|
-
}, heartbeatMs));
|
|
719
|
-
unsubscribe.push(host.on("scroll", () => scroll.record(host.scrollDepth())));
|
|
720
|
-
unsubscribe.push(host.interval(() => {
|
|
721
|
-
for (const milestone of scroll.observe(host.scrollDepth())) {
|
|
722
|
-
send([draft(builtin.scrollDepth, { maxPercent: milestone })]);
|
|
723
|
-
}
|
|
724
|
-
}, 2000));
|
|
725
|
-
unsubscribe.push(host.onClick((target) => {
|
|
726
|
-
const click = resolveTrackedClick(target, {
|
|
727
|
-
origin: host.page().origin,
|
|
728
|
-
attributes: config.clickAttributes,
|
|
729
|
-
isAction: config.isAction
|
|
730
|
-
});
|
|
731
|
-
if (!click)
|
|
732
|
-
return;
|
|
733
|
-
const drafts = [];
|
|
734
|
-
if (click.interaction)
|
|
735
|
-
drafts.push(draft(builtin.interaction, { ...click.interaction }));
|
|
736
|
-
if (click.click)
|
|
737
|
-
drafts.push(draft(builtin.click, { ...click.click }));
|
|
738
|
-
if (click.outbound)
|
|
739
|
-
drafts.push(draft(builtin.outboundClick, { ...click.outbound }));
|
|
740
|
-
if (click.leavesPage)
|
|
741
|
-
for (const item of drafts)
|
|
742
|
-
sendOnUnload(item);
|
|
743
|
-
else
|
|
744
|
-
send(drafts);
|
|
745
|
-
}));
|
|
774
|
+
const unsubscribe = wireTrackingListeners({
|
|
775
|
+
host,
|
|
776
|
+
builtin,
|
|
777
|
+
heartbeatMs,
|
|
778
|
+
renewAfterHiddenMs,
|
|
779
|
+
meter,
|
|
780
|
+
scroll,
|
|
781
|
+
draft,
|
|
782
|
+
leaveDraft,
|
|
783
|
+
send,
|
|
784
|
+
sendOnUnload,
|
|
785
|
+
flushOutbox,
|
|
786
|
+
renewVisit: () => bootstrapVisit(true),
|
|
787
|
+
currentPage: () => currentPage ?? host.page().pathname,
|
|
788
|
+
releaseLease: () => {
|
|
789
|
+
if (outbox && visit.outboxAvailable)
|
|
790
|
+
outbox.releaseLease(flushOwner).catch(() => {
|
|
791
|
+
return;
|
|
792
|
+
});
|
|
793
|
+
},
|
|
794
|
+
clickAttributes: config.clickAttributes,
|
|
795
|
+
isAction: config.isAction
|
|
796
|
+
});
|
|
746
797
|
return () => {
|
|
747
798
|
running += 1;
|
|
748
799
|
for (const off of unsubscribe.splice(0))
|
|
@@ -753,8 +804,8 @@ function createTrackingClient(config) {
|
|
|
753
804
|
track,
|
|
754
805
|
onNavigate,
|
|
755
806
|
start,
|
|
756
|
-
visitId: () => visitId,
|
|
757
|
-
browserStreamId: () => browserStreamId,
|
|
807
|
+
visitId: () => visit.visitId,
|
|
808
|
+
browserStreamId: () => visit.browserStreamId,
|
|
758
809
|
attribution: () => attribution
|
|
759
810
|
};
|
|
760
811
|
}
|