@pikku/core 0.12.107 → 0.12.111
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 +344 -0
- package/dist/analytics/analytics.d.ts +6 -0
- package/dist/analytics/analytics.js +58 -0
- package/dist/analytics/analytics.types.d.ts +156 -0
- package/dist/analytics/analytics.types.js +1 -0
- package/dist/analytics/anonymous-analytics-identity.d.ts +23 -0
- package/dist/analytics/anonymous-analytics-identity.js +27 -0
- package/dist/analytics/compose-analytics-identity.d.ts +14 -0
- package/dist/analytics/compose-analytics-identity.js +33 -0
- package/dist/analytics/cookie-analytics-identity.d.ts +24 -0
- package/dist/analytics/cookie-analytics-identity.js +37 -0
- package/dist/analytics/define-analytics-events.d.ts +22 -0
- package/dist/analytics/define-analytics-events.js +9 -0
- package/dist/analytics/fan-out-analytics.d.ts +15 -0
- package/dist/analytics/fan-out-analytics.js +36 -0
- package/dist/analytics/index.d.ts +13 -0
- package/dist/analytics/index.js +8 -0
- package/dist/analytics/logger-analytics-service.d.ts +14 -0
- package/dist/analytics/logger-analytics-service.js +23 -0
- package/dist/analytics/mint-cookie.d.ts +44 -0
- package/dist/analytics/mint-cookie.js +55 -0
- package/dist/errors/errors.d.ts +7 -0
- package/dist/errors/errors.js +17 -0
- package/dist/function/function-meta.types.d.ts +2 -0
- package/dist/function/function-runner.js +29 -0
- package/dist/function/functions.types.d.ts +22 -3
- package/dist/middleware/auth-apikey.d.ts +1 -1
- package/dist/pikku-state.d.ts +1 -1
- package/dist/scopes.d.ts +11 -0
- package/dist/scopes.js +17 -0
- package/dist/services/credential-wire-service.d.ts +1 -1
- package/dist/services/feature-flag-service.d.ts +100 -0
- package/dist/services/feature-flag-service.js +1 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/services/meta-service.d.ts +16 -0
- package/dist/services/meta-service.js +19 -0
- package/dist/services/webhook-service.d.ts +7 -2
- package/dist/services/webhook-service.js +11 -6
- package/dist/testing/service-tests/agent-run-service-tests.d.ts +2 -2
- package/dist/testing/service-tests/agent-storage-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/channel-store-tests.d.ts +1 -1
- package/dist/testing/service-tests/credential-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/deployment-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/event-hub-store-tests.d.ts +1 -1
- package/dist/testing/service-tests/secret-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/session-store-tests.d.ts +1 -1
- package/dist/testing/service-tests/workflow-run-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/workflow-service-tests.d.ts +1 -1
- package/dist/types/core.types.d.ts +23 -0
- package/dist/wirings/agent/agent-rpc.d.ts +1 -1
- package/dist/wirings/agent/agent-turn.d.ts +1 -1
- package/dist/wirings/agent-scorer/agent-scorer-live.d.ts +1 -1
- package/dist/wirings/channel/channel-common.d.ts +1 -1
- package/dist/wirings/channel/channel-rpc-validators.d.ts +2 -2
- package/dist/wirings/channel/channel-runner.d.ts +1 -1
- package/dist/wirings/channel/local/local-channel-runner.d.ts +1 -1
- package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +1 -1
- package/dist/wirings/cli/channel/cli-approval.d.ts +2 -2
- package/dist/wirings/flag/assert-feature-available.d.ts +15 -0
- package/dist/wirings/flag/assert-feature-available.js +23 -0
- package/dist/wirings/flag/cached-flag-source.d.ts +73 -0
- package/dist/wirings/flag/cached-flag-source.js +96 -0
- package/dist/wirings/flag/define-feature-flags.d.ts +33 -0
- package/dist/wirings/flag/define-feature-flags.js +32 -0
- package/dist/wirings/flag/flag.types.d.ts +97 -0
- package/dist/wirings/flag/flag.types.js +1 -0
- package/dist/wirings/flag/index.d.ts +7 -0
- package/dist/wirings/flag/index.js +5 -0
- package/dist/wirings/flag/resolve-flag.d.ts +52 -0
- package/dist/wirings/flag/resolve-flag.js +90 -0
- package/dist/wirings/flag/validate-flag-definitions.d.ts +26 -0
- package/dist/wirings/flag/validate-flag-definitions.js +103 -0
- package/dist/wirings/virtual-user/virtual-user-scaffold.d.ts +8 -8
- package/dist/wirings/virtual-user/virtual-user-schedule.d.ts +1 -1
- package/dist/wirings/workflow/workflow-queue-routing.d.ts +1 -1
- package/package.json +11 -5
- package/run-tests.sh +17 -9
- package/src/public-surface.json +26 -0
- package/src/agent-naming.test.ts +0 -68
- package/src/api-report.test.ts +0 -138
- package/src/app-alias-surface.test.ts +0 -179
- package/src/app-leaf-surface.test.ts +0 -222
- package/src/bootstrap-compat/root.ts +0 -20
- package/src/classification/column-form.test.ts +0 -97
- package/src/classification/column-form.ts +0 -55
- package/src/classification/data-classification.ts +0 -73
- package/src/classification/index.ts +0 -40
- package/src/classification/key-ids.ts +0 -2
- package/src/classification/secret-value.test.ts +0 -204
- package/src/classification/secret-value.ts +0 -106
- package/src/crypto-utils.test.ts +0 -668
- package/src/crypto-utils.ts +0 -460
- package/src/dev/hot-reload.test.ts +0 -587
- package/src/dev/hot-reload.ts +0 -225
- package/src/dev/module-runner.test.ts +0 -235
- package/src/dev/module-runner.ts +0 -138
- package/src/dev/reload-meta.test.ts +0 -183
- package/src/dev/reload-meta.ts +0 -144
- package/src/ecosystem-tier-removed.test.ts +0 -72
- package/src/env.ts +0 -1
- package/src/errors/error-handler.ts +0 -77
- package/src/errors/error.test.ts +0 -229
- package/src/errors/errors.ts +0 -393
- package/src/errors/index.ts +0 -11
- package/src/errors/serialized-error.ts +0 -12
- package/src/factory-functions.test.ts +0 -111
- package/src/function/abort-scope.test.ts +0 -97
- package/src/function/abort-scope.ts +0 -80
- package/src/function/function-meta.types.ts +0 -151
- package/src/function/function-runner.test.ts +0 -1619
- package/src/function/function-runner.ts +0 -499
- package/src/function/functions.types.ts +0 -319
- package/src/function/index.ts +0 -40
- package/src/function/list.types.test.ts +0 -100
- package/src/function/list.types.ts +0 -69
- package/src/function/pikku-request.test.ts +0 -35
- package/src/function/pikku-request.ts +0 -17
- package/src/gopass-secrets-removed.test.ts +0 -51
- package/src/handle-error.test.ts +0 -532
- package/src/handle-error.ts +0 -64
- package/src/middleware/auth-apikey.test.ts +0 -362
- package/src/middleware/auth-apikey.ts +0 -39
- package/src/middleware/auth-bearer.test.ts +0 -566
- package/src/middleware/auth-bearer.ts +0 -83
- package/src/middleware/auth-cookie.test.ts +0 -572
- package/src/middleware/auth-cookie.ts +0 -107
- package/src/middleware/cors.test.ts +0 -579
- package/src/middleware/cors.ts +0 -103
- package/src/middleware/index.ts +0 -30
- package/src/middleware/middleware-factories.ts +0 -76
- package/src/middleware/middleware.types.ts +0 -61
- package/src/middleware/remote-auth.test.ts +0 -547
- package/src/middleware/remote-auth.ts +0 -95
- package/src/middleware/remote-jobs-secret.ts +0 -35
- package/src/middleware/require-origin.test.ts +0 -115
- package/src/middleware/require-origin.ts +0 -79
- package/src/middleware/telemetry.ts +0 -83
- package/src/middleware-runner.test.ts +0 -578
- package/src/middleware-runner.ts +0 -232
- package/src/no-any-casts.test.ts +0 -57
- package/src/no-root-barrel.test.ts +0 -122
- package/src/permissions.test.ts +0 -256
- package/src/permissions.ts +0 -217
- package/src/pikku-state.test.ts +0 -198
- package/src/pikku-state.ts +0 -206
- package/src/production-barrels-stay-lean.test.ts +0 -110
- package/src/public-surface.test.ts +0 -133
- package/src/remote.test.ts +0 -173
- package/src/remote.ts +0 -56
- package/src/removed-legacy-exports.test.ts +0 -66
- package/src/run-tests-script.test.ts +0 -67
- package/src/schema.test.ts +0 -430
- package/src/schema.ts +0 -204
- package/src/scopes.test.ts +0 -203
- package/src/scopes.ts +0 -67
- package/src/services/agent-run-state-service.ts +0 -37
- package/src/services/agent-runner-service.ts +0 -238
- package/src/services/agent-storage-service.ts +0 -39
- package/src/services/ai-embedding-service.ts +0 -9
- package/src/services/audit-service.test.ts +0 -44
- package/src/services/audit-service.ts +0 -280
- package/src/services/content-service.ts +0 -65
- package/src/services/credential-service.ts +0 -20
- package/src/services/credential-wire-service.test.ts +0 -235
- package/src/services/credential-wire-service.ts +0 -120
- package/src/services/deployment-service.ts +0 -32
- package/src/services/email-service.test.ts +0 -100
- package/src/services/email-service.ts +0 -60
- package/src/services/email-template.test.ts +0 -311
- package/src/services/email-template.ts +0 -254
- package/src/services/file-scenario-run-store.test.ts +0 -349
- package/src/services/file-scenario-run-store.ts +0 -282
- package/src/services/gateway-service.ts +0 -5
- package/src/services/http-personas-converse.test.ts +0 -274
- package/src/services/http-personas.test.ts +0 -379
- package/src/services/http-personas.ts +0 -508
- package/src/services/in-memory-agent-run-state-service.ts +0 -87
- package/src/services/in-memory-queue-service.test.ts +0 -162
- package/src/services/in-memory-queue-service.ts +0 -78
- package/src/services/in-memory-session-store.test.ts +0 -58
- package/src/services/in-memory-session-store.ts +0 -20
- package/src/services/in-memory-trigger-service.ts +0 -47
- package/src/services/in-memory-workflow-service.test.ts +0 -430
- package/src/services/in-memory-workflow-service.ts +0 -595
- package/src/services/index.ts +0 -192
- package/src/services/istanbul-coverage-service.test.ts +0 -66
- package/src/services/istanbul-coverage-service.ts +0 -59
- package/src/services/jwt-service.ts +0 -15
- package/src/services/local-content-request-handler.test.ts +0 -240
- package/src/services/local-content-request-handler.ts +0 -295
- package/src/services/local-content.test.ts +0 -186
- package/src/services/local-content.ts +0 -242
- package/src/services/local-credential-service.ts +0 -63
- package/src/services/local-email-service.test.ts +0 -182
- package/src/services/local-email-service.ts +0 -43
- package/src/services/local-gateway-service.ts +0 -51
- package/src/services/local-secrets.test.ts +0 -95
- package/src/services/local-secrets.ts +0 -71
- package/src/services/local-variables.test.ts +0 -61
- package/src/services/local-variables.ts +0 -45
- package/src/services/logger-console.test.ts +0 -117
- package/src/services/logger-console.ts +0 -174
- package/src/services/logger.ts +0 -48
- package/src/services/meta-service.test.ts +0 -75
- package/src/services/meta-service.ts +0 -767
- package/src/services/persona-actor-secret.test.ts +0 -68
- package/src/services/persona-actor-secret.ts +0 -70
- package/src/services/persona-sign-in.test.ts +0 -219
- package/src/services/persona-sign-in.ts +0 -238
- package/src/services/personas-service.ts +0 -191
- package/src/services/pikku-user-id.test.ts +0 -62
- package/src/services/pikku-user-id.ts +0 -13
- package/src/services/queue-webhook-service.test.ts +0 -409
- package/src/services/queue-webhook-service.ts +0 -150
- package/src/services/remote-jobs.test.ts +0 -106
- package/src/services/remote-jobs.ts +0 -92
- package/src/services/scheduler-service.ts +0 -37
- package/src/services/schema-service.ts +0 -10
- package/src/services/scope-service.ts +0 -91
- package/src/services/scoped-credential-service.test.ts +0 -86
- package/src/services/scoped-credential-service.ts +0 -63
- package/src/services/scoped-secret-service.test.ts +0 -93
- package/src/services/scoped-secret-service.ts +0 -40
- package/src/services/secret-host-binding.test.ts +0 -138
- package/src/services/secret-host-binding.ts +0 -51
- package/src/services/secret-service.ts +0 -25
- package/src/services/secretless.test.ts +0 -54
- package/src/services/secretless.ts +0 -29
- package/src/services/session-store.ts +0 -9
- package/src/services/stub-tracker.test.ts +0 -104
- package/src/services/stub-tracker.ts +0 -175
- package/src/services/system-role-guard.test.ts +0 -96
- package/src/services/system-role-guard.ts +0 -71
- package/src/services/temporary-file-service.ts +0 -76
- package/src/services/trigger-service.ts +0 -5
- package/src/services/typed-credential-service.ts +0 -83
- package/src/services/typed-secret-service.test.ts +0 -204
- package/src/services/typed-secret-service.ts +0 -132
- package/src/services/typed-variables-service.test.ts +0 -166
- package/src/services/typed-variables-service.ts +0 -166
- package/src/services/user-session-service.test.ts +0 -147
- package/src/services/user-session-service.ts +0 -85
- package/src/services/v8-coverage-service.test.ts +0 -69
- package/src/services/v8-coverage-service.ts +0 -163
- package/src/services/variables-service.ts +0 -13
- package/src/services/webhook-service.ts +0 -147
- package/src/services/workflow-service.ts +0 -120
- package/src/side-effects-are-declared.test.ts +0 -84
- package/src/source-files-stay-composable.test.ts +0 -41
- package/src/template-alias-surface.test.ts +0 -240
- package/src/test-utils.ts +0 -38
- package/src/testing/index.ts +0 -3
- package/src/testing/service-tests/agent-run-service-tests.ts +0 -98
- package/src/testing/service-tests/agent-storage-service-tests.ts +0 -379
- package/src/testing/service-tests/channel-store-tests.ts +0 -98
- package/src/testing/service-tests/credential-service-tests.ts +0 -143
- package/src/testing/service-tests/deployment-service-tests.ts +0 -33
- package/src/testing/service-tests/event-hub-store-tests.ts +0 -48
- package/src/testing/service-tests/secret-service-tests.ts +0 -105
- package/src/testing/service-tests/session-store-tests.ts +0 -62
- package/src/testing/service-tests/workflow-run-service-tests.ts +0 -59
- package/src/testing/service-tests/workflow-service-tests.ts +0 -308
- package/src/testing/service-tests.ts +0 -95
- package/src/time-utils.test.ts +0 -56
- package/src/time-utils.ts +0 -89
- package/src/types/core.types.ts +0 -446
- package/src/types/index.ts +0 -25
- package/src/types/state.types.ts +0 -226
- package/src/types/typed-credentials.test.ts +0 -72
- package/src/utils/hash.test.ts +0 -68
- package/src/utils/hash.ts +0 -26
- package/src/utils/hmac.ts +0 -21
- package/src/utils/node-host-resolver.ts +0 -20
- package/src/utils/safe-fetch.test.ts +0 -515
- package/src/utils/safe-fetch.ts +0 -347
- package/src/utils.test.ts +0 -359
- package/src/utils.ts +0 -165
- package/src/version.test.ts +0 -80
- package/src/version.ts +0 -25
- package/src/wirings/actor-flow/actor-flow.types.ts +0 -40
- package/src/wirings/actor-flow/index.ts +0 -10
- package/src/wirings/actor-flow/run-conversation.test.ts +0 -187
- package/src/wirings/actor-flow/run-conversation.ts +0 -280
- package/src/wirings/addon/addon-auth-tags.test.ts +0 -219
- package/src/wirings/addon/addon-runner.ts +0 -236
- package/src/wirings/addon/addon-scopes.test.ts +0 -225
- package/src/wirings/addon/addon-secrets.test.ts +0 -391
- package/src/wirings/addon/index.ts +0 -12
- package/src/wirings/addon/remote-addon-auth.ts +0 -65
- package/src/wirings/addon/wire-addon.test.ts +0 -102
- package/src/wirings/addon/wire-addon.ts +0 -202
- package/src/wirings/addon/wire-remote-addon.ts +0 -41
- package/src/wirings/agent/agent-agui.test.ts +0 -1213
- package/src/wirings/agent/agent-agui.ts +0 -405
- package/src/wirings/agent/agent-authorization.test.ts +0 -208
- package/src/wirings/agent/agent-finalize.test.ts +0 -187
- package/src/wirings/agent/agent-finalize.ts +0 -197
- package/src/wirings/agent/agent-helpers.test.ts +0 -215
- package/src/wirings/agent/agent-helpers.ts +0 -96
- package/src/wirings/agent/agent-interrupt.test.ts +0 -833
- package/src/wirings/agent/agent-interrupt.ts +0 -400
- package/src/wirings/agent/agent-memory.test.ts +0 -397
- package/src/wirings/agent/agent-memory.ts +0 -496
- package/src/wirings/agent/agent-middleware.types.test.ts +0 -41
- package/src/wirings/agent/agent-model-config.test.ts +0 -103
- package/src/wirings/agent/agent-model-config.ts +0 -59
- package/src/wirings/agent/agent-prepare.test.ts +0 -977
- package/src/wirings/agent/agent-prepare.ts +0 -1083
- package/src/wirings/agent/agent-registry.test.ts +0 -455
- package/src/wirings/agent/agent-registry.ts +0 -99
- package/src/wirings/agent/agent-resume-authorization.test.ts +0 -206
- package/src/wirings/agent/agent-rpc.ts +0 -116
- package/src/wirings/agent/agent-runner.test.ts +0 -1229
- package/src/wirings/agent/agent-runner.ts +0 -858
- package/src/wirings/agent/agent-stream-delegate.test.ts +0 -381
- package/src/wirings/agent/agent-stream-output-hooks.test.ts +0 -353
- package/src/wirings/agent/agent-stream.test.ts +0 -1800
- package/src/wirings/agent/agent-stream.ts +0 -1639
- package/src/wirings/agent/agent-thread-ownership.test.ts +0 -297
- package/src/wirings/agent/agent-turn.test.ts +0 -65
- package/src/wirings/agent/agent-turn.ts +0 -122
- package/src/wirings/agent/agent-utils.ts +0 -20
- package/src/wirings/agent/agent.types.ts +0 -676
- package/src/wirings/agent/index.ts +0 -58
- package/src/wirings/agent/voice-input.test.ts +0 -220
- package/src/wirings/agent/voice-input.ts +0 -180
- package/src/wirings/agent/voice-output.test.ts +0 -510
- package/src/wirings/agent/voice-output.ts +0 -311
- package/src/wirings/agent-scorer/agent-scorer-grade.test.ts +0 -106
- package/src/wirings/agent-scorer/agent-scorer-grade.ts +0 -55
- package/src/wirings/agent-scorer/agent-scorer-judge.test.ts +0 -285
- package/src/wirings/agent-scorer/agent-scorer-judge.ts +0 -180
- package/src/wirings/agent-scorer/agent-scorer-live.test.ts +0 -174
- package/src/wirings/agent-scorer/agent-scorer-live.ts +0 -56
- package/src/wirings/agent-scorer/agent-scorer-registry.ts +0 -66
- package/src/wirings/agent-scorer/agent-scorer-sampling.test.ts +0 -34
- package/src/wirings/agent-scorer/agent-scorer-sampling.ts +0 -36
- package/src/wirings/agent-scorer/agent-scorer-snapshots.test.ts +0 -49
- package/src/wirings/agent-scorer/agent-scorer-snapshots.ts +0 -46
- package/src/wirings/agent-scorer/agent-scorer-worker.test.ts +0 -122
- package/src/wirings/agent-scorer/agent-scorer-worker.ts +0 -71
- package/src/wirings/agent-scorer/agent-scorer.ts +0 -102
- package/src/wirings/agent-scorer/agent-scorer.types.ts +0 -128
- package/src/wirings/agent-scorer/index.ts +0 -23
- package/src/wirings/channel/channel-common.ts +0 -102
- package/src/wirings/channel/channel-handler-shapes.test.ts +0 -72
- package/src/wirings/channel/channel-handler.test.ts +0 -322
- package/src/wirings/channel/channel-handler.ts +0 -259
- package/src/wirings/channel/channel-host-rpc.test.ts +0 -150
- package/src/wirings/channel/channel-host-rpc.ts +0 -69
- package/src/wirings/channel/channel-middleware-runner.test.ts +0 -188
- package/src/wirings/channel/channel-middleware-runner.ts +0 -126
- package/src/wirings/channel/channel-rpc-registry.ts +0 -116
- package/src/wirings/channel/channel-rpc-responder.ts +0 -117
- package/src/wirings/channel/channel-rpc-service.ts +0 -132
- package/src/wirings/channel/channel-rpc-validators.ts +0 -65
- package/src/wirings/channel/channel-rpc.test.ts +0 -841
- package/src/wirings/channel/channel-rpc.ts +0 -5
- package/src/wirings/channel/channel-rpc.types.ts +0 -160
- package/src/wirings/channel/channel-runner.ts +0 -164
- package/src/wirings/channel/channel-store.ts +0 -35
- package/src/wirings/channel/channel.types.ts +0 -193
- package/src/wirings/channel/define-channel-routes.ts +0 -5
- package/src/wirings/channel/eventhub-service.ts +0 -16
- package/src/wirings/channel/eventhub-store.ts +0 -13
- package/src/wirings/channel/index.ts +0 -40
- package/src/wirings/channel/local/index.ts +0 -3
- package/src/wirings/channel/local/local-channel-handler.ts +0 -98
- package/src/wirings/channel/local/local-channel-runner.test.ts +0 -339
- package/src/wirings/channel/local/local-channel-runner.ts +0 -271
- package/src/wirings/channel/local/local-eventhub-service.test.ts +0 -77
- package/src/wirings/channel/local/local-eventhub-service.ts +0 -69
- package/src/wirings/channel/log-channels.ts +0 -16
- package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +0 -135
- package/src/wirings/channel/pikku-abstract-channel-handler.ts +0 -60
- package/src/wirings/channel/serverless/index.ts +0 -6
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +0 -328
- package/src/wirings/cli/channel/cli-approval.test.ts +0 -177
- package/src/wirings/cli/channel/cli-approval.ts +0 -135
- package/src/wirings/cli/channel/cli-channel-runner.ts +0 -118
- package/src/wirings/cli/channel/cli-raw-channel-runner.test.ts +0 -192
- package/src/wirings/cli/channel/cli-raw-channel-runner.ts +0 -148
- package/src/wirings/cli/channel/cli-raw-client-runner.test.ts +0 -480
- package/src/wirings/cli/channel/cli-raw-client-runner.ts +0 -188
- package/src/wirings/cli/channel/index.ts +0 -6
- package/src/wirings/cli/cli-runner.test.ts +0 -969
- package/src/wirings/cli/cli-runner.ts +0 -538
- package/src/wirings/cli/cli.types.ts +0 -388
- package/src/wirings/cli/command-parser.test.ts +0 -1120
- package/src/wirings/cli/command-parser.ts +0 -713
- package/src/wirings/cli/define-cli-commands.ts +0 -13
- package/src/wirings/cli/format-cli-error.test.ts +0 -91
- package/src/wirings/cli/format-cli-error.ts +0 -96
- package/src/wirings/cli/index.ts +0 -19
- package/src/wirings/credential/credential.types.ts +0 -37
- package/src/wirings/credential/define-credential.ts +0 -49
- package/src/wirings/credential/index.ts +0 -7
- package/src/wirings/credential/validate-credential-definitions.ts +0 -63
- package/src/wirings/gateway/gateway-authorization.test.ts +0 -575
- package/src/wirings/gateway/gateway-channel-meta.test.ts +0 -44
- package/src/wirings/gateway/gateway-runner.test.ts +0 -581
- package/src/wirings/gateway/gateway-runner.ts +0 -411
- package/src/wirings/gateway/gateway.types.ts +0 -137
- package/src/wirings/gateway/index.ts +0 -15
- package/src/wirings/http/http-routes.test.ts +0 -318
- package/src/wirings/http/http-routes.ts +0 -111
- package/src/wirings/http/http-runner-addon-ref.test.ts +0 -238
- package/src/wirings/http/http-runner.test.ts +0 -503
- package/src/wirings/http/http-runner.ts +0 -462
- package/src/wirings/http/http.types.ts +0 -307
- package/src/wirings/http/index.ts +0 -27
- package/src/wirings/http/log-http-routes.ts +0 -18
- package/src/wirings/http/pikku-fetch-http-request.test.ts +0 -318
- package/src/wirings/http/pikku-fetch-http-request.ts +0 -260
- package/src/wirings/http/pikku-fetch-http-response.test.ts +0 -123
- package/src/wirings/http/pikku-fetch-http-response.ts +0 -149
- package/src/wirings/http/routers/http-router.ts +0 -13
- package/src/wirings/http/routers/path-to-regex.test.ts +0 -306
- package/src/wirings/http/routers/path-to-regex.ts +0 -115
- package/src/wirings/http/web-request.test.ts +0 -382
- package/src/wirings/http/web-request.ts +0 -162
- package/src/wirings/mcp/index.ts +0 -26
- package/src/wirings/mcp/mcp-endpoint-registry.test.ts +0 -388
- package/src/wirings/mcp/mcp-endpoint-registry.ts +0 -159
- package/src/wirings/mcp/mcp-runner.test.ts +0 -588
- package/src/wirings/mcp/mcp-runner.ts +0 -330
- package/src/wirings/mcp/mcp.types.ts +0 -199
- package/src/wirings/node/index.ts +0 -2
- package/src/wirings/node/node.types.ts +0 -23
- package/src/wirings/oauth2/index.ts +0 -1
- package/src/wirings/oauth2/oauth2.types.ts +0 -12
- package/src/wirings/persona/define-personas.ts +0 -33
- package/src/wirings/persona/index.ts +0 -75
- package/src/wirings/persona/persona-app-scopes.test.ts +0 -47
- package/src/wirings/persona/persona-app-scopes.ts +0 -74
- package/src/wirings/persona/persona-email.ts +0 -87
- package/src/wirings/persona/persona-environments.test.ts +0 -194
- package/src/wirings/persona/persona-environments.ts +0 -138
- package/src/wirings/persona/persona-mailbox.ts +0 -156
- package/src/wirings/persona/persona.test.ts +0 -230
- package/src/wirings/persona/persona.types.ts +0 -156
- package/src/wirings/persona/validate-personas.ts +0 -137
- package/src/wirings/queue/index.ts +0 -29
- package/src/wirings/queue/queue-identity.test.ts +0 -454
- package/src/wirings/queue/queue-identity.ts +0 -176
- package/src/wirings/queue/queue-runner.test.ts +0 -705
- package/src/wirings/queue/queue-runner.ts +0 -181
- package/src/wirings/queue/queue.types.ts +0 -161
- package/src/wirings/queue/register-queue-helper.ts +0 -46
- package/src/wirings/queue/signed-queue-service.ts +0 -60
- package/src/wirings/queue/validate-worker-config.test.ts +0 -108
- package/src/wirings/queue/validate-worker-config.ts +0 -90
- package/src/wirings/role/define-system-role.ts +0 -33
- package/src/wirings/role/index.ts +0 -13
- package/src/wirings/role/role.test.ts +0 -104
- package/src/wirings/role/role.types.ts +0 -47
- package/src/wirings/role/validate-role-definitions.ts +0 -93
- package/src/wirings/rpc/index.ts +0 -8
- package/src/wirings/rpc/rpc-runner.test.ts +0 -1130
- package/src/wirings/rpc/rpc-runner.ts +0 -569
- package/src/wirings/rpc/rpc-types.ts +0 -87
- package/src/wirings/scheduler/index.ts +0 -11
- package/src/wirings/scheduler/log-schedulers.ts +0 -16
- package/src/wirings/scheduler/scheduler-runner.test.ts +0 -835
- package/src/wirings/scheduler/scheduler-runner.ts +0 -138
- package/src/wirings/scheduler/scheduler.types.ts +0 -42
- package/src/wirings/scope/define-scope.ts +0 -33
- package/src/wirings/scope/index.ts +0 -15
- package/src/wirings/scope/scope.test.ts +0 -159
- package/src/wirings/scope/scope.types.ts +0 -42
- package/src/wirings/scope/validate-scope-definitions.ts +0 -107
- package/src/wirings/secret/index.ts +0 -9
- package/src/wirings/secret/secret.types.ts +0 -70
- package/src/wirings/secret/validate-secret-definitions.test.ts +0 -232
- package/src/wirings/secret/validate-secret-definitions.ts +0 -88
- package/src/wirings/trigger/index.ts +0 -9
- package/src/wirings/trigger/pikku-trigger-service.ts +0 -107
- package/src/wirings/trigger/trigger-runner.test.ts +0 -78
- package/src/wirings/trigger/trigger-runner.ts +0 -113
- package/src/wirings/trigger/trigger.types.ts +0 -100
- package/src/wirings/variable/index.ts +0 -8
- package/src/wirings/variable/validate-variable-definitions.test.ts +0 -115
- package/src/wirings/variable/validate-variable-definitions.ts +0 -71
- package/src/wirings/variable/variable.types.ts +0 -40
- package/src/wirings/virtual-user/index.ts +0 -107
- package/src/wirings/virtual-user/prepare-virtual-user-run.test.ts +0 -115
- package/src/wirings/virtual-user/prepare-virtual-user-run.ts +0 -95
- package/src/wirings/virtual-user/run-virtual-user.test.ts +0 -774
- package/src/wirings/virtual-user/run-virtual-user.ts +0 -684
- package/src/wirings/virtual-user/virtual-user-agents.test.ts +0 -72
- package/src/wirings/virtual-user/virtual-user-agents.ts +0 -62
- package/src/wirings/virtual-user/virtual-user-catalogue.test.ts +0 -215
- package/src/wirings/virtual-user/virtual-user-catalogue.ts +0 -184
- package/src/wirings/virtual-user/virtual-user-derive.test.ts +0 -426
- package/src/wirings/virtual-user/virtual-user-derive.ts +0 -161
- package/src/wirings/virtual-user/virtual-user-dispositions.test.ts +0 -68
- package/src/wirings/virtual-user/virtual-user-dispositions.ts +0 -210
- package/src/wirings/virtual-user/virtual-user-intents.test.ts +0 -218
- package/src/wirings/virtual-user/virtual-user-intents.ts +0 -185
- package/src/wirings/virtual-user/virtual-user-rng.test.ts +0 -72
- package/src/wirings/virtual-user/virtual-user-rng.ts +0 -50
- package/src/wirings/virtual-user/virtual-user-run-store.ts +0 -131
- package/src/wirings/virtual-user/virtual-user-scaffold.test.ts +0 -854
- package/src/wirings/virtual-user/virtual-user-scaffold.ts +0 -664
- package/src/wirings/virtual-user/virtual-user-schedule-store.ts +0 -93
- package/src/wirings/virtual-user/virtual-user-schedule.test.ts +0 -280
- package/src/wirings/virtual-user/virtual-user-schedule.ts +0 -156
- package/src/wirings/virtual-user/virtual-user-target.ts +0 -47
- package/src/wirings/virtual-user/virtual-user.types.ts +0 -215
- package/src/wirings/workflow/dsl/workflow-dsl.types.ts +0 -709
- package/src/wirings/workflow/dsl/workflow-runner.ts +0 -25
- package/src/wirings/workflow/feature.test.ts +0 -131
- package/src/wirings/workflow/feature.ts +0 -59
- package/src/wirings/workflow/graph/graph-foreach-queued.test.ts +0 -569
- package/src/wirings/workflow/graph/graph-foreach.test.ts +0 -626
- package/src/wirings/workflow/graph/graph-node.ts +0 -115
- package/src/wirings/workflow/graph/graph-runner.test.ts +0 -1049
- package/src/wirings/workflow/graph/graph-runner.ts +0 -1376
- package/src/wirings/workflow/graph/graph-validation.test.ts +0 -27
- package/src/wirings/workflow/graph/graph-validation.ts +0 -41
- package/src/wirings/workflow/graph/template.test.ts +0 -49
- package/src/wirings/workflow/graph/template.ts +0 -42
- package/src/wirings/workflow/graph/wire-workflow-graph.ts +0 -39
- package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -75
- package/src/wirings/workflow/index.ts +0 -107
- package/src/wirings/workflow/pikku-scenario-service.ts +0 -1013
- package/src/wirings/workflow/pikku-workflow-service.test.ts +0 -963
- package/src/wirings/workflow/pikku-workflow-service.ts +0 -1993
- package/src/wirings/workflow/run-timeline.test.ts +0 -199
- package/src/wirings/workflow/run-timeline.ts +0 -185
- package/src/wirings/workflow/scenario-cookie-jar.test.ts +0 -107
- package/src/wirings/workflow/scenario-cookie-jar.ts +0 -57
- package/src/wirings/workflow/scenario-expectations.test.ts +0 -238
- package/src/wirings/workflow/scenario-hooks.test.ts +0 -259
- package/src/wirings/workflow/scenario-poll.test.ts +0 -64
- package/src/wirings/workflow/scenario-poll.ts +0 -27
- package/src/wirings/workflow/scenario-prose.test.ts +0 -275
- package/src/wirings/workflow/scenario-prose.ts +0 -86
- package/src/wirings/workflow/scenario-run.types.ts +0 -193
- package/src/wirings/workflow/scenario-service.test.ts +0 -147
- package/src/wirings/workflow/scenario-step-guards.ts +0 -23
- package/src/wirings/workflow/scenario-step.test.ts +0 -800
- package/src/wirings/workflow/scenario-step.types.ts +0 -262
- package/src/wirings/workflow/scenario-surface.test.ts +0 -146
- package/src/wirings/workflow/scenario-surface.ts +0 -71
- package/src/wirings/workflow/scenario.types.ts +0 -63
- package/src/wirings/workflow/workflow-approval-audit.ts +0 -47
- package/src/wirings/workflow/workflow-approval-policy.test.ts +0 -594
- package/src/wirings/workflow/workflow-approval-policy.ts +0 -68
- package/src/wirings/workflow/workflow-approval.ts +0 -290
- package/src/wirings/workflow/workflow-child-run-session.test.ts +0 -168
- package/src/wirings/workflow/workflow-constants.ts +0 -66
- package/src/wirings/workflow/workflow-dispatch-durability.test.ts +0 -116
- package/src/wirings/workflow/workflow-dispatch-payload.test.ts +0 -55
- package/src/wirings/workflow/workflow-dispatch-relay.test.ts +0 -128
- package/src/wirings/workflow/workflow-errors.ts +0 -132
- package/src/wirings/workflow/workflow-inline-authority.test.ts +0 -175
- package/src/wirings/workflow/workflow-invocation-id.test.ts +0 -51
- package/src/wirings/workflow/workflow-invocation-id.ts +0 -28
- package/src/wirings/workflow/workflow-meta-resolver.ts +0 -45
- package/src/wirings/workflow/workflow-mirror.test.ts +0 -171
- package/src/wirings/workflow/workflow-missing-meta.test.ts +0 -92
- package/src/wirings/workflow/workflow-on-error.test.ts +0 -145
- package/src/wirings/workflow/workflow-queue-routing.ts +0 -129
- package/src/wirings/workflow/workflow-queue-wiring.ts +0 -149
- package/src/wirings/workflow/workflow-queue-workers.test.ts +0 -131
- package/src/wirings/workflow/workflow-queue-workers.ts +0 -66
- package/src/wirings/workflow/workflow-recovery.ts +0 -192
- package/src/wirings/workflow/workflow-replay-snapshot.test.ts +0 -140
- package/src/wirings/workflow/workflow-retry-policy.test.ts +0 -113
- package/src/wirings/workflow/workflow-run-authority.test.ts +0 -212
- package/src/wirings/workflow/workflow-run-context.test.ts +0 -172
- package/src/wirings/workflow/workflow-run-engine.types.ts +0 -92
- package/src/wirings/workflow/workflow-run-ownership.ts +0 -37
- package/src/wirings/workflow/workflow-run-polling.test.ts +0 -127
- package/src/wirings/workflow/workflow-stalled-recovery.test.ts +0 -152
- package/src/wirings/workflow/workflow-status-stream.test.ts +0 -354
- package/src/wirings/workflow/workflow-status-stream.ts +0 -144
- package/src/wirings/workflow/workflow-step-claim.ts +0 -46
- package/src/wirings/workflow/workflow-step-ordinal.test.ts +0 -94
- package/src/wirings/workflow/workflow-step-session.test.ts +0 -87
- package/src/wirings/workflow/workflow-suspend.ts +0 -61
- package/src/wirings/workflow/workflow-terminal-run-guard.test.ts +0 -105
- package/src/wirings/workflow/workflow.types.ts +0 -268
- package/src/wirings-stay-decoupled.test.ts +0 -130
- package/tsconfig.json +0 -14
- package/tsconfig.tsbuildinfo +0 -1
- package/tsconfig.type-tests.json +0 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,347 @@
|
|
|
1
|
+
## 0.12.111
|
|
2
|
+
|
|
3
|
+
### Patch Changes
|
|
4
|
+
|
|
5
|
+
- 78237ac: The console shows feature flags as a launch board, and analytics events as a
|
|
6
|
+
declared catalog.
|
|
7
|
+
|
|
8
|
+
A flag's state is four fields — `enabled`, `rolloutPercent`, `declared`,
|
|
9
|
+
`backed` — and none of them is the question an operator actually asks, which is
|
|
10
|
+
how far this has got. The board answers that directly: every declared flag sits
|
|
11
|
+
in the lane its rollout has reached, `dark` → `rolling` → `live`, with
|
|
12
|
+
`attention` for the flags that are not resolving in a way anybody chose.
|
|
13
|
+
|
|
14
|
+
Attention is evaluated before every other reading, and that ordering is the
|
|
15
|
+
whole point rather than an implementation detail. A flag declared in code with
|
|
16
|
+
no row in the store fails open, and it reports `enabled: true` with no rollout
|
|
17
|
+
limit — byte-identical to a deliberate full launch. Read the fields in the
|
|
18
|
+
obvious order and the one production-severity state on the board renders as the
|
|
19
|
+
healthiest one. `groupFlagsByLane` also returns all four lanes whether or not
|
|
20
|
+
they hold anything, because a board read by shape must not rearrange itself the
|
|
21
|
+
moment a lane empties.
|
|
22
|
+
|
|
23
|
+
Selecting a flag opens its controls beside the board rather than over it: the
|
|
24
|
+
switch, the rollout bucket, and the subjects pinned on or off past that bucket.
|
|
25
|
+
They share one surface because they are read together — "off for everyone except
|
|
26
|
+
these three" is a switch and an override row, and an operator who has to leave
|
|
27
|
+
one screen to see the other is the operator who turns a flag on for everybody by
|
|
28
|
+
mistake. The panel tracks the open flag by name and re-reads it from the list, so
|
|
29
|
+
committing a rollout moves the card and the panel together instead of leaving the
|
|
30
|
+
panel describing the flag as it was before the operator changed it.
|
|
31
|
+
|
|
32
|
+
A board whose flags come from a `FeatureFlagSource` — a provider Pikku reads but
|
|
33
|
+
does not own — says so and offers no controls, rather than offering controls that
|
|
34
|
+
would fail.
|
|
35
|
+
|
|
36
|
+
The analytics screen is a catalog of what the code declares, read from build-time
|
|
37
|
+
meta: the events a client may emit and the props each carries, with every prop
|
|
38
|
+
rendered as the schema source text the declaration wrote. It is deliberately not
|
|
39
|
+
a volume report — nothing here counts what was emitted — and saying which of the
|
|
40
|
+
two it is turned out to be the only design question the screen had.
|
|
41
|
+
|
|
42
|
+
Turning a flag on while it carries no rollout limit now asks first. That press
|
|
43
|
+
is the one irreversible thing the board can do — with no bucket left to hold
|
|
44
|
+
anybody back it admits everyone the flag's capabilities allow — and it used to
|
|
45
|
+
be a single click on a switch. The panel also reports what a mutation is doing
|
|
46
|
+
and what it refused to do: the controls it is waiting on go into a pending
|
|
47
|
+
state, and a failed write raises an inline `<Alert>` rather than reverting in
|
|
48
|
+
silence. The console mounts no notification provider, so the feedback is inline
|
|
49
|
+
where the action is, which is the idiom the rest of the console already uses.
|
|
50
|
+
|
|
51
|
+
`@pikku/mantine`'s theme gains four aliases, and they close a contrast defect
|
|
52
|
+
that predates this board:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
'--mantine-color-orange-light': 'var(--app-surface-warning)',
|
|
56
|
+
'--mantine-color-orange-light-color': 'var(--app-amber)',
|
|
57
|
+
'--mantine-color-teal-light': 'var(--app-surface-success)',
|
|
58
|
+
'--mantine-color-teal-light-color': 'var(--app-green)',
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The theme already documents two colour tiers — TEXT must clear AA, GRAPHIC only
|
|
62
|
+
3:1 — and already pulls Mantine's own variables into that contract rather than
|
|
63
|
+
linting call sites. What it had not covered was Mantine's _light variants_:
|
|
64
|
+
`<Alert color="orange">` renders #d9480f on #ffe8cc at 3.62:1, and
|
|
65
|
+
`<Badge variant="light" color="teal">` at 4.33:1, neither reachable from an
|
|
66
|
+
`--app-*` token because the component never asks for one. The ramp itself is
|
|
67
|
+
deliberately untouched: Mantine conflates `--mantine-color-orange-filled`
|
|
68
|
+
between `c="orange"` text and a `variant="filled"` background, so darkening it
|
|
69
|
+
for light-mode text would make an existing filled badge unreadable in dark mode.
|
|
70
|
+
Eight pre-existing `c="orange"` call sites moved onto the amber TEXT tier in the
|
|
71
|
+
same pass.
|
|
72
|
+
|
|
73
|
+
The analytics catalog is grouped by the file that declares each event, and its
|
|
74
|
+
rows are real buttons rather than table cells carrying a tabindex.
|
|
75
|
+
|
|
76
|
+
`ShellHeaderAction` gains `loading` and `testId`, and `ActionCluster` gains a
|
|
77
|
+
`measurement` flag. `ShellHeader` sizes its actions by rendering them a second
|
|
78
|
+
time off-screen, and that measuring copy was carrying the same `data-testid` and
|
|
79
|
+
`data-help` as the real one — so every action on a page with a collapsing header
|
|
80
|
+
resolved to two elements. The flags board also moved its two header actions from
|
|
81
|
+
`actionsNode` (documented as the non-collapsing escape hatch) onto the structured
|
|
82
|
+
`actions` array, which is what stopped them clipping off the right edge at 400px.
|
|
83
|
+
|
|
84
|
+
- add56d2: Reading webhook deliveries no longer throws when nothing persists them.
|
|
85
|
+
|
|
86
|
+
`WebhookService.listDeliveries` and `getDelivery` return `[]`/`null` instead of `NotImplementedError`, so the console's webhooks page shows an empty list on an app whose service only delivers. `recordAttempt` still throws — a write that goes nowhere loses the caller's data.
|
|
87
|
+
|
|
88
|
+
## 0.12.110
|
|
89
|
+
|
|
90
|
+
### Patch Changes
|
|
91
|
+
|
|
92
|
+
- 1c9a55a: Analytics can fan out to several destinations, and carry the identity an ad
|
|
93
|
+
platform needs.
|
|
94
|
+
|
|
95
|
+
`fanOutAnalytics` composes any number of destinations into one
|
|
96
|
+
`AnalyticsService`, so a single-destination app never meets it and a sink is the
|
|
97
|
+
same class whether it runs alone or beside three others. Destinations are
|
|
98
|
+
settled rather than awaited in sequence: `flush()` runs inside the invocation,
|
|
99
|
+
so a slow vendor must not add its latency to the request and a vendor that is
|
|
100
|
+
down must not cost the others their events.
|
|
101
|
+
|
|
102
|
+
Each destination takes an optional `accepts` predicate. Which events a
|
|
103
|
+
destination receives is the app's policy — a product-analytics tool wants
|
|
104
|
+
everything, an ad platform wants three conversions — while what an event should
|
|
105
|
+
look like once it arrives is the sink's, and belongs in its mapper rather than
|
|
106
|
+
in a central mapping table that would push vendor trivia into every app.
|
|
107
|
+
|
|
108
|
+
`AnalyticsIdentity` gains `vendorIds` and `consent`. GA4 keys on a `client_id`
|
|
109
|
+
from the `_ga` cookie and Meta on `fbp`/`fbc`; neither is derivable from a user
|
|
110
|
+
id, so a server-side sink without them does not degrade, it sends nothing
|
|
111
|
+
usable. Both are resolved server-side through an `analyticsIdentity` resolver on
|
|
112
|
+
singleton services, never read from the event body — the same rule the rest of
|
|
113
|
+
the identity already follows, so a crafted client call cannot attribute an event
|
|
114
|
+
to someone else. `cookieAnalyticsIdentity` covers the common first-party-cookie
|
|
115
|
+
case; a consent tool that packs every purpose into one encoded blob writes its
|
|
116
|
+
own resolver, which is why the resolver is a function.
|
|
117
|
+
|
|
118
|
+
A resolver returns nothing off a wire with no browser behind it, so a cron task
|
|
119
|
+
and a queue worker never invent a vendor id.
|
|
120
|
+
|
|
121
|
+
The analytics leaf re-exports the runtime, so an app reaches the whole surface
|
|
122
|
+
through `#pikku/analytics` — wiring where events go sits next to declaring them,
|
|
123
|
+
and splitting that across two specifiers splits one concern across two names.
|
|
124
|
+
|
|
125
|
+
Identity the browser owns is resolved server-side, and can now be created there
|
|
126
|
+
too. `cookieAnalyticsIdentity` reads GA4's `client_id` and Meta's `fbp`/`fbc`
|
|
127
|
+
off first-party cookies; `mintCookie` writes one that is not there yet, which is
|
|
128
|
+
what lets an app collect nothing on the page at all. Both formats are public and
|
|
129
|
+
server-side minting is documented by the vendors — it is the mechanism behind
|
|
130
|
+
server-side tagging, offered here as a wired resolver rather than a second
|
|
131
|
+
container to operate.
|
|
132
|
+
|
|
133
|
+
Minting is gated on consent, because writing the cookie is itself the act
|
|
134
|
+
consent governs — a minter that runs before the banner is answered has already
|
|
135
|
+
done the thing the send gate was meant to prevent. `composeAnalyticsIdentity`
|
|
136
|
+
exists to make that expressible: resolvers run in order and each sees what the
|
|
137
|
+
ones before it produced, so the reader that finds consent necessarily precedes
|
|
138
|
+
the minter that needs it. Every required purpose must be granted, not any.
|
|
139
|
+
|
|
140
|
+
`anonymousAnalyticsIdentity` fills the gap that made anonymous product analytics
|
|
141
|
+
dishonest. `pikkuUserId` is derived from a session and so is absent for exactly
|
|
142
|
+
the visitor it would need to identify, which left a sink choosing between
|
|
143
|
+
collapsing every anonymous visitor into one shared literal and dropping the
|
|
144
|
+
pre-signup funnel entirely. The id is `httpOnly` by default: no browser script
|
|
145
|
+
needs it, and a cookie scripts cannot touch is not subject to the seven-day cap
|
|
146
|
+
browsers place on script-set ones.
|
|
147
|
+
|
|
148
|
+
On the client, `createAnalytics` takes an `enabled` predicate checked at each
|
|
149
|
+
flush. A boolean would be captured before anyone had answered the banner, so
|
|
150
|
+
accepting mid-session would never start and withdrawing would never stop.
|
|
151
|
+
Refused events are discarded rather than held, so changing your mind does not
|
|
152
|
+
release a backlog.
|
|
153
|
+
|
|
154
|
+
- 1c9a55a: Review fixes across the feature-flag and analytics primitives:
|
|
155
|
+
|
|
156
|
+
- An addon function's `featureFlag:` gate now reads the consuming application's
|
|
157
|
+
flag source rather than the package's own services, which never carry one.
|
|
158
|
+
- A flag named `__proto__`, `constructor` or `prototype` is rejected instead of
|
|
159
|
+
being silently dropped from the generated metadata.
|
|
160
|
+
- Two declarations of one flag with different descriptions are a hard error,
|
|
161
|
+
rather than the inspector's traversal order deciding what operators read.
|
|
162
|
+
- `subjectIdOf` falls through an empty organization id to the user, instead of
|
|
163
|
+
resolving to no subject and skipping every override and rollout bucket.
|
|
164
|
+
- `CachedFlagSource.invalidate()` retires the in-flight read, so a webhook that
|
|
165
|
+
lands mid-fetch is not answered by the pre-webhook snapshot for another TTL.
|
|
166
|
+
- The generated `/feature-flags` wire resolves against the compiled fallback
|
|
167
|
+
when no source is wired, so a scope-gated flag is not reported to a caller
|
|
168
|
+
who cannot hold it.
|
|
169
|
+
- `pruneFlags()` rechecks `declared = false` in the delete and reports only
|
|
170
|
+
what it removed, so a redeclaration between the two keeps its overrides.
|
|
171
|
+
- A destination's `accepts` throwing no longer costs every later sink its batch.
|
|
172
|
+
- The React analytics client drops events at collection time when analytics is
|
|
173
|
+
disabled, so a later consent grant cannot send what was gathered before it.
|
|
174
|
+
- The React flag client keeps its map when the wire answers a non-object.
|
|
175
|
+
- `KyselyAnalyticsService` mints event ids from `crypto` rather than a
|
|
176
|
+
timestamp with a short random tail.
|
|
177
|
+
|
|
178
|
+
- 1c9a55a: Feature flags, declared in source and resolved from two independent booleans.
|
|
179
|
+
|
|
180
|
+
`defineFeatureFlags` declares a flag the way `defineScopes` declares a scope —
|
|
181
|
+
the inspector collects it, the CLI emits a `FeatureFlagName` union, and a
|
|
182
|
+
misspelled `featureFlag:` is a type error rather than a gate that silently fails
|
|
183
|
+
open.
|
|
184
|
+
|
|
185
|
+
A flag answers two questions that are not the same question. `capable` comes
|
|
186
|
+
from the session's scopes and is per-user, advisory, and protects nothing — it
|
|
187
|
+
hides UI. `available` comes from one global config snapshot, is caller-blind,
|
|
188
|
+
and is the only half the runner enforces: `override(subject) ?? (enabled AND
|
|
189
|
+
bucket)`, so "off for everyone except these three organizations" is one row, and
|
|
190
|
+
a kill is one write rather than a fan-out. Authorization stays where it was, in
|
|
191
|
+
the function's own `scopes:` — enforcing capability would make a flag a second
|
|
192
|
+
authorization path OR-ing against them. An unavailable feature throws 503, not
|
|
193
|
+
403, because the caller was allowed; the feature was not on.
|
|
194
|
+
|
|
195
|
+
`featureFlag:` is deliberately available on sessionless functions too. It reads
|
|
196
|
+
the config, not the session, so the kill switch reaches a cron task, a queue
|
|
197
|
+
worker and a webhook — which is where it matters most, since nobody is watching
|
|
198
|
+
a UI to notice the feature is off.
|
|
199
|
+
|
|
200
|
+
Refresh is pull-on-demand, so the TTL is the kill-switch latency. Where that is
|
|
201
|
+
too long, `invalidate()` is public: a provider's change webhook lands on an HTTP
|
|
202
|
+
wiring, drops the cache, and the next request does the read. It deliberately
|
|
203
|
+
does not fetch — a burst of webhooks would be N round trips, and on a serverless
|
|
204
|
+
runtime the isolate that took the signal may be gone before anything reads the
|
|
205
|
+
result.
|
|
206
|
+
|
|
207
|
+
Availability fails open through three layers: a fresh read, then the last good
|
|
208
|
+
cached read, then the compiled declaration. The middle layer is load-bearing —
|
|
209
|
+
dropping straight to the compiled fallback on a blip would switch on every flag
|
|
210
|
+
that was deliberately dark.
|
|
211
|
+
|
|
212
|
+
Backing stores split along what they can honestly do. `FeatureFlagSource` is
|
|
213
|
+
read-only (`snapshot()`) and is what a third-party provider implements;
|
|
214
|
+
`FeatureFlagStore` adds the write half and is for stores Pikku owns.
|
|
215
|
+
`@pikku/kysely` ships the store, with declarations synced additively — a removed
|
|
216
|
+
declaration is marked undeclared, never revoked, and a sync never re-enables a
|
|
217
|
+
killed flag. Third-party providers implement the read-only half in the addons
|
|
218
|
+
repository, over plain `fetch` rather than a vendor SDK — those poll on a timer
|
|
219
|
+
belonging to a long-lived process, which a serverless isolate cannot hold
|
|
220
|
+
between requests.
|
|
221
|
+
|
|
222
|
+
A client asks for its flags once per session rather than per flag:
|
|
223
|
+
`scaffold.featureFlags` generates a `GET /feature-flags` returning every
|
|
224
|
+
declared flag resolved for the caller, keyed by this app's `FeatureFlagName`.
|
|
225
|
+
Generated into the app rather than shipped in an addon precisely for that union
|
|
226
|
+
— an addon never sees the host's, and could only answer
|
|
227
|
+
`Record<string, boolean>`. It returns `show` alone: sending `available` apart
|
|
228
|
+
from `capable` would tell every visitor which features exist but are dark.
|
|
229
|
+
|
|
230
|
+
The write half is the operator's, and lives in `@pikku/addon-admin` beside the
|
|
231
|
+
scope RPCs, under a new `admin:flags` scope. `flagList` reports `writable:
|
|
232
|
+
false` rather than failing when flags come from a provider, because a provider's
|
|
233
|
+
own UI is its operator surface and a console full of buttons that 500 is worse
|
|
234
|
+
than a read-only tab. It still lists the flags: a source may report its declared
|
|
235
|
+
set through `declaredFlags()`, and each row carries `backed`, false where the
|
|
236
|
+
provider has never heard of a declared flag. That row is the one worth seeing —
|
|
237
|
+
an absent row fails open, so a dark launch nobody created in PostHog is already
|
|
238
|
+
live for everyone, and a store pikku owns can reconcile that on deploy where a
|
|
239
|
+
provider cannot.
|
|
240
|
+
|
|
241
|
+
On the client, `createFeatureFlags` fetches that map once and `useFeatureFlag`
|
|
242
|
+
reads it synchronously after, through the same provider the analytics client
|
|
243
|
+
hangs off. It takes a `bootstrap` map so a server-rendered page hydrates onto
|
|
244
|
+
the answer it already computed: without one there is a gap in which neither
|
|
245
|
+
default is right, since false hides a feature the user has and true flashes one
|
|
246
|
+
they do not. A failed refresh keeps the map already on screen rather than
|
|
247
|
+
relabelling every flag on a blip.
|
|
248
|
+
|
|
249
|
+
## 0.12.109
|
|
250
|
+
|
|
251
|
+
### Patch Changes
|
|
252
|
+
|
|
253
|
+
- 54138b1: Product analytics moves into core behind a `scaffold.analytics` generator.
|
|
254
|
+
|
|
255
|
+
An app declares what it measures, and nothing else:
|
|
256
|
+
|
|
257
|
+
```ts
|
|
258
|
+
import { defineAnalyticsEvents } from '#pikku/analytics'
|
|
259
|
+
|
|
260
|
+
export const analyticsEvents = defineAnalyticsEvents({
|
|
261
|
+
page_viewed: z.object({ path: z.string() }),
|
|
262
|
+
todo_created: z.object({ priority: z.enum(['low', 'medium', 'high']) }),
|
|
263
|
+
})
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
The definer reaches an app through the generated `#pikku/analytics` leaf, the
|
|
267
|
+
way `defineFeatureFlags` reaches it through `#pikku/scopes` — an app declares
|
|
268
|
+
what it measures without importing out of core. The leaf is written on every
|
|
269
|
+
run, whatever `scaffold.analytics` says: the declaration is how a project names
|
|
270
|
+
what it measures, and the scaffold only decides whether an ingest wire is
|
|
271
|
+
generated for it. Its path is `analyticsTypesFile`, defaulting to
|
|
272
|
+
`<outDir>/analytics/pikku-analytics-types.gen.ts`. It carries the sink surface
|
|
273
|
+
as well as the definer — `AnalyticsService`, `AnalyticsRecord`,
|
|
274
|
+
`AnalyticsIdentity`, `AnalyticsClientContext`, `AnalyticsLog`,
|
|
275
|
+
`LoggerAnalyticsService` — because writing the destination events go to is the
|
|
276
|
+
other half of the same job, and both halves should come through one door.
|
|
277
|
+
|
|
278
|
+
The name is the key, so it is never repeated as a `z.literal` inside the
|
|
279
|
+
schema. Declare in as many modules as suits the project — a feature declares
|
|
280
|
+
its events beside its functions — and the CLI unions them into the generated
|
|
281
|
+
`/analytics` ingest and its schemas. The inspector finds the declarations the
|
|
282
|
+
way it finds every other wiring, so there is no path to configure.
|
|
283
|
+
|
|
284
|
+
Where events go is not part of the declaration. `services.analytics` is the
|
|
285
|
+
request-scoped buffer a function records into, typed against the declared
|
|
286
|
+
names:
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
await analytics.record({ name: 'todo_created', priority: 'high' })
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
It stamps identity, trace and wire fields from the invocation, buffers for the
|
|
293
|
+
length of the call and flushes once when it ends. Identity is always
|
|
294
|
+
server-side and never read from a request body, which is what makes the
|
|
295
|
+
unauthenticated ingest safe to expose.
|
|
296
|
+
|
|
297
|
+
The transport behind it is an `AnalyticsService` on singleton services — the
|
|
298
|
+
one swappable slot. With none wired the runner installs
|
|
299
|
+
`LoggerAnalyticsService`, so an app that turns the scaffold on can watch events
|
|
300
|
+
arrive without first choosing a store; a platform injects its own through
|
|
301
|
+
singleton services, and an app that wants neither sets `analyticsService` in
|
|
302
|
+
its own `services.ts`, which runs last and wins. There is no process-global
|
|
303
|
+
sink registry and no noop: events are never silently dropped.
|
|
304
|
+
|
|
305
|
+
The generated wire is added to the set of scaffolds the inspector reads.
|
|
306
|
+
Nothing imports it — it is a wiring, not a module anyone calls — so without
|
|
307
|
+
that the route was written and never registered: no HTTP wiring, no entry in
|
|
308
|
+
the fetch client, an endpoint that 404s.
|
|
309
|
+
|
|
310
|
+
No middleware is emitted with the wire: an origin lock rejects every native
|
|
311
|
+
client and is forgeable anyway, so guarding the route is the project's call.
|
|
312
|
+
|
|
313
|
+
`name` belongs to the event, not to its props. The generated union rebuilds
|
|
314
|
+
each member from the declared schema's shape and attaches the literal name
|
|
315
|
+
last, so a declaration that happens to carry a `name` prop of its own cannot
|
|
316
|
+
displace the discriminator the union is built on. Props schemas are typed to
|
|
317
|
+
require that shape, so a schema that has none — a union, a primitive — is
|
|
318
|
+
refused at the declaration rather than in generated code.
|
|
319
|
+
|
|
320
|
+
## 0.12.108
|
|
321
|
+
|
|
322
|
+
### Patch Changes
|
|
323
|
+
|
|
324
|
+
- 4c7a1b5: Run the monorepo's own scripts through bun instead of yarn. What moves is the
|
|
325
|
+
package manager each package's `prepublishOnly` and build scripts invoke, plus
|
|
326
|
+
the two manifest fixes bun needs to resolve the tree: `uWebSockets.js` is
|
|
327
|
+
declared with an explicit `github:` specifier, and `@pikku/uws-handler` marks
|
|
328
|
+
its `uWebSockets.js` peer optional so a bun install of a consumer that brings
|
|
329
|
+
its own uWS app does not try to fetch it from the registry.
|
|
330
|
+
|
|
331
|
+
Three published behaviours change, all of them cases where an isolated
|
|
332
|
+
`node_modules` or bun as the runtime had been papered over by yarn's hoisting:
|
|
333
|
+
|
|
334
|
+
- `@pikku/migrator-sql` turns foreign keys on when it opens a sqlite database
|
|
335
|
+
through bun. `node:sqlite` enforces them by default and `bun:sqlite` does not,
|
|
336
|
+
which silently turned every `ON DELETE CASCADE` into a no-op under
|
|
337
|
+
`bunx --bun pikku`.
|
|
338
|
+
- `@pikku/cli` resolves a deploy provider against the project being deployed
|
|
339
|
+
rather than against wherever the CLI itself is installed, which is what its
|
|
340
|
+
own "is not installed" error asks the user to arrange.
|
|
341
|
+
- `@pikku/cli` treats a specifier a runtime hands straight back — bun does this
|
|
342
|
+
for the modules it implements itself — as not resolved from the project, so
|
|
343
|
+
it falls back rather than loading the runtime's own copy.
|
|
344
|
+
|
|
1
345
|
## 0.12.107
|
|
2
346
|
|
|
3
347
|
### Patch Changes
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CoreUserSession, PikkuWire } from '../types/core.types.js';
|
|
2
|
+
import type { Logger } from '../services/logger.js';
|
|
3
|
+
import type { AnalyticsEventBase, AnalyticsEventInput, AnalyticsIdentityResolver, AnalyticsLog, AnalyticsService } from './analytics.types.js';
|
|
4
|
+
/** Removes the discriminator, so `props` is free of the series key. */
|
|
5
|
+
export declare const flattenAnalyticsEvent: (event: AnalyticsEventBase, at?: number) => AnalyticsEventInput;
|
|
6
|
+
export declare const createInvocationAnalytics: (service: AnalyticsService, wire: PikkuWire<any, any, any, CoreUserSession>, logger?: Logger, resolveIdentity?: AnalyticsIdentityResolver) => AnalyticsLog;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** Removes the discriminator, so `props` is free of the series key. */
|
|
2
|
+
export const flattenAnalyticsEvent = (event, at) => {
|
|
3
|
+
const { name, ...props } = event;
|
|
4
|
+
return { name, props, ...(at === undefined ? {} : { at }) };
|
|
5
|
+
};
|
|
6
|
+
class InvocationAnalyticsLog {
|
|
7
|
+
service;
|
|
8
|
+
wire;
|
|
9
|
+
logger;
|
|
10
|
+
resolveIdentity;
|
|
11
|
+
buffer = [];
|
|
12
|
+
constructor(service, wire, logger, resolveIdentity) {
|
|
13
|
+
this.service = service;
|
|
14
|
+
this.wire = wire;
|
|
15
|
+
this.logger = logger;
|
|
16
|
+
this.resolveIdentity = resolveIdentity;
|
|
17
|
+
}
|
|
18
|
+
async record(event, client) {
|
|
19
|
+
this.buffer.push(this.resolveEvent(event, client));
|
|
20
|
+
}
|
|
21
|
+
async flush() {
|
|
22
|
+
if (this.buffer.length === 0)
|
|
23
|
+
return;
|
|
24
|
+
const batch = this.buffer.splice(0, this.buffer.length);
|
|
25
|
+
try {
|
|
26
|
+
await this.service.write(batch);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
const logger = this.wire.logger ?? this.logger;
|
|
30
|
+
logger?.warn?.('analytics flush failed', error);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async close() {
|
|
34
|
+
await this.flush();
|
|
35
|
+
}
|
|
36
|
+
resolveEvent(event, client) {
|
|
37
|
+
const session = this.wire.session;
|
|
38
|
+
const { name, props } = flattenAnalyticsEvent(event);
|
|
39
|
+
const resolved = this.resolveIdentity?.(this.wire);
|
|
40
|
+
return {
|
|
41
|
+
name,
|
|
42
|
+
props,
|
|
43
|
+
occurredAt: new Date().toISOString(),
|
|
44
|
+
...(client?.at === undefined ? {} : { at: client.at }),
|
|
45
|
+
userIdentity: {
|
|
46
|
+
userId: session?.userId ?? null,
|
|
47
|
+
orgId: session?.orgId,
|
|
48
|
+
pikkuUserId: this.wire.pikkuUserId,
|
|
49
|
+
...resolved,
|
|
50
|
+
},
|
|
51
|
+
traceId: this.wire.traceId,
|
|
52
|
+
functionId: this.wire.functionId,
|
|
53
|
+
wireType: this.wire.wireType,
|
|
54
|
+
source: client === undefined ? 'server' : 'client',
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export const createInvocationAnalytics = (service, wire, logger, resolveIdentity) => new InvocationAnalyticsLog(service, wire, logger, resolveIdentity);
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import type { CoreUserSession, PikkuWire, PikkuWiringTypes } from '../types/core.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The constraint a project's declared event union is checked against.
|
|
4
|
+
*
|
|
5
|
+
* Only `name` is fixed, because the name is the whole of what pikku itself
|
|
6
|
+
* reads — everything else on an event belongs to the app and to the sinks it
|
|
7
|
+
* wires, and narrowing it here would make the generic useless for anyone whose
|
|
8
|
+
* events carry more than a fixed set of props.
|
|
9
|
+
*/
|
|
10
|
+
export type AnalyticsEventBase = {
|
|
11
|
+
name: string;
|
|
12
|
+
} & Record<string, unknown>;
|
|
13
|
+
export interface AnalyticsEventInput {
|
|
14
|
+
name: string;
|
|
15
|
+
props?: Record<string, unknown>;
|
|
16
|
+
at?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Stamped server-side from the session and never read from the request body,
|
|
20
|
+
* which is what makes an unauthenticated ingest safe to expose.
|
|
21
|
+
*/
|
|
22
|
+
export interface AnalyticsIdentity {
|
|
23
|
+
userId: string | null;
|
|
24
|
+
orgId?: string;
|
|
25
|
+
pikkuUserId?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Identifiers a destination keys on that pikku does not mint — GA4's
|
|
28
|
+
* `client_id`, Meta's `fbp` and `fbc`, a vendor's own device id. All of them
|
|
29
|
+
* originate in the browser, and a sink that cannot produce one does not
|
|
30
|
+
* degrade, it sends nothing usable.
|
|
31
|
+
*
|
|
32
|
+
* Resolved server-side from first-party cookies on the request, never read
|
|
33
|
+
* from the event body, on the same reasoning as the rest of this object: a
|
|
34
|
+
* crafted client call must not be able to attribute an event to someone else.
|
|
35
|
+
*/
|
|
36
|
+
vendorIds?: Record<string, string>;
|
|
37
|
+
/**
|
|
38
|
+
* A device-scoped id for a visitor with no session, minted by pikku rather
|
|
39
|
+
* than by a vendor.
|
|
40
|
+
*
|
|
41
|
+
* Distinct from `pikkuUserId`, which is derived from a session and is
|
|
42
|
+
* therefore absent for exactly the visitor this identifies. Without it a
|
|
43
|
+
* product-analytics sink has no honest option for anonymous traffic: keying
|
|
44
|
+
* on a shared literal collapses every visitor into one person, and dropping
|
|
45
|
+
* the event loses the whole pre-signup funnel.
|
|
46
|
+
*/
|
|
47
|
+
anonymousId?: string;
|
|
48
|
+
/**
|
|
49
|
+
* What the visitor agreed to, keyed by purpose. A sink gated on a purpose
|
|
50
|
+
* absent here does not send.
|
|
51
|
+
*
|
|
52
|
+
* Open-ended rather than a fixed pair, because the purposes are the consent
|
|
53
|
+
* tool's vocabulary and jurisdictions do not agree on them. Undefined means
|
|
54
|
+
* the app wired no consent resolver, not that consent was refused — the gate
|
|
55
|
+
* belongs to the sink, which is where the app decides what absence means.
|
|
56
|
+
*/
|
|
57
|
+
consent?: Record<string, boolean>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Resolves the half of the identity pikku cannot know, from the wire.
|
|
61
|
+
*
|
|
62
|
+
* A function rather than a cookie-name map because consent tools do not store
|
|
63
|
+
* one boolean per cookie — a single encoded blob is more common — and a map
|
|
64
|
+
* could only express the easy case. {@link cookieAnalyticsIdentity} covers that
|
|
65
|
+
* easy case.
|
|
66
|
+
*/
|
|
67
|
+
export type AnalyticsIdentityResolver = (wire: PikkuWire<any, any, any, CoreUserSession>,
|
|
68
|
+
/**
|
|
69
|
+
* What the resolvers before this one produced, when composed. A minter needs
|
|
70
|
+
* it: whether it may write a cookie at all depends on consent another
|
|
71
|
+
* resolver read, and ordering is the only thing that can express that.
|
|
72
|
+
*/
|
|
73
|
+
resolved?: Pick<AnalyticsIdentity, 'vendorIds' | 'consent' | 'anonymousId'>) => Pick<AnalyticsIdentity, 'vendorIds' | 'consent' | 'anonymousId'> | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* What an event becomes once pikku has accepted it, and the only shape an
|
|
76
|
+
* {@link AnalyticsService} is ever handed.
|
|
77
|
+
*
|
|
78
|
+
* Distinct from {@link AnalyticsEventInput}, which is what a caller submits:
|
|
79
|
+
* the identity, the trace and the origin are stamped server-side on the way
|
|
80
|
+
* through, so a sink never has to trust — or re-derive — any of them.
|
|
81
|
+
*/
|
|
82
|
+
export interface AnalyticsRecord {
|
|
83
|
+
name: string;
|
|
84
|
+
props?: Record<string, unknown>;
|
|
85
|
+
occurredAt: string;
|
|
86
|
+
at?: number;
|
|
87
|
+
userIdentity: AnalyticsIdentity;
|
|
88
|
+
traceId?: string;
|
|
89
|
+
functionId?: string;
|
|
90
|
+
wireType?: PikkuWiringTypes;
|
|
91
|
+
source: 'server' | 'client';
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Where accepted events go. Pikku validates, identifies and batches them; it
|
|
95
|
+
* does not store them.
|
|
96
|
+
*
|
|
97
|
+
* One method, taking a batch, because a batch is what a destination is always
|
|
98
|
+
* handed: the invocation buffers and flushes once, and a lone event is a batch
|
|
99
|
+
* of one. A single-event method beside it would be a second path every sink had
|
|
100
|
+
* to implement and every caller had to choose between.
|
|
101
|
+
*/
|
|
102
|
+
export interface AnalyticsService {
|
|
103
|
+
write(batch: AnalyticsRecord[]): Promise<void>;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* One destination in a fan-out, with the events it is allowed to receive.
|
|
107
|
+
*
|
|
108
|
+
* `accepts` is the app's, not the sink's: which events a destination should get
|
|
109
|
+
* is policy — a product-analytics tool wants everything, an ad platform wants
|
|
110
|
+
* three conversions, and a consent gate reads the same way. What each event
|
|
111
|
+
* should look like once it gets there is the sink's, and lives in its mapper.
|
|
112
|
+
*/
|
|
113
|
+
export interface AnalyticsSink {
|
|
114
|
+
service: AnalyticsService;
|
|
115
|
+
accepts?: (record: AnalyticsRecord) => boolean;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Its presence, not `at`, is what marks a record as relayed from a browser — a
|
|
119
|
+
* beacon is free to omit `at`.
|
|
120
|
+
*/
|
|
121
|
+
export interface AnalyticsClientContext {
|
|
122
|
+
at?: number;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* `services.analytics`: buffered for the invocation, flushed when it ends,
|
|
126
|
+
* always best-effort. `record` is a method rather than a property so an app can
|
|
127
|
+
* narrow `Events` in its own `SingletonServices`.
|
|
128
|
+
*/
|
|
129
|
+
export interface AnalyticsLog<Events extends AnalyticsEventBase = AnalyticsEventBase> {
|
|
130
|
+
record(event: Events, client?: AnalyticsClientContext): Promise<void>;
|
|
131
|
+
flush(): Promise<void>;
|
|
132
|
+
close(): Promise<void>;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* One declared event, as an administration surface sees it.
|
|
136
|
+
*
|
|
137
|
+
* Read off the declaration at build time rather than from a record: the catalog
|
|
138
|
+
* has to list an event nobody has fired yet, which is exactly the event someone
|
|
139
|
+
* is looking for when they open it.
|
|
140
|
+
*/
|
|
141
|
+
export interface AnalyticsEventMeta {
|
|
142
|
+
/** The event name a client emits, exactly as the declaration spells it. */
|
|
143
|
+
name: string;
|
|
144
|
+
/** The module holding the `defineAnalyticsEvents` call that declares it. */
|
|
145
|
+
file: string;
|
|
146
|
+
/** The name that module exports the declaration under. */
|
|
147
|
+
variable: string;
|
|
148
|
+
/**
|
|
149
|
+
* The event's props, keyed by name, valued with the schema's own source text
|
|
150
|
+
* (`z.string()`). Absent where the shape is not an object literal the
|
|
151
|
+
* inspector can read — a shared const, a union, a non-zod vendor.
|
|
152
|
+
*/
|
|
153
|
+
props?: Record<string, string>;
|
|
154
|
+
}
|
|
155
|
+
/** Declared analytics events, keyed by event name. */
|
|
156
|
+
export type AnalyticsEventsMeta = Record<string, AnalyticsEventMeta>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SerializeOptions } from 'cookie';
|
|
2
|
+
import type { AnalyticsIdentityResolver } from './analytics.types.js';
|
|
3
|
+
export interface AnonymousAnalyticsIdentityOptions {
|
|
4
|
+
/** Cookie name. Defaults to `pikku_aid`. */
|
|
5
|
+
name?: string;
|
|
6
|
+
/**
|
|
7
|
+
* Consent purposes required before the cookie is written. Storing an
|
|
8
|
+
* analytics id on someone's device is the act consent governs, so this is
|
|
9
|
+
* usually set — and left unset only where the deployment meets a regulator's
|
|
10
|
+
* exemption for strictly necessary audience measurement.
|
|
11
|
+
*/
|
|
12
|
+
requires?: string[];
|
|
13
|
+
cookie?: SerializeOptions;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Mints a device-scoped id for visitors who have no session yet.
|
|
17
|
+
*
|
|
18
|
+
* `httpOnly` by default, which is the honest reading of what this is for: no
|
|
19
|
+
* browser script needs it, and a cookie scripts cannot touch is both harder to
|
|
20
|
+
* misuse and not subject to the seven-day cap browsers place on script-set
|
|
21
|
+
* ones. An app that wants a vendor SDK to read it must opt out deliberately.
|
|
22
|
+
*/
|
|
23
|
+
export declare const anonymousAnalyticsIdentity: (options?: AnonymousAnalyticsIdentityOptions) => AnalyticsIdentityResolver;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { mintCookie } from './mint-cookie.js';
|
|
2
|
+
const TWO_YEARS_SECONDS = 63_072_000;
|
|
3
|
+
const DEFAULT_COOKIE = {
|
|
4
|
+
path: '/',
|
|
5
|
+
maxAge: TWO_YEARS_SECONDS,
|
|
6
|
+
sameSite: 'lax',
|
|
7
|
+
httpOnly: true,
|
|
8
|
+
secure: true,
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Mints a device-scoped id for visitors who have no session yet.
|
|
12
|
+
*
|
|
13
|
+
* `httpOnly` by default, which is the honest reading of what this is for: no
|
|
14
|
+
* browser script needs it, and a cookie scripts cannot touch is both harder to
|
|
15
|
+
* misuse and not subject to the seven-day cap browsers place on script-set
|
|
16
|
+
* ones. An app that wants a vendor SDK to read it must opt out deliberately.
|
|
17
|
+
*/
|
|
18
|
+
export const anonymousAnalyticsIdentity = (options = {}) => {
|
|
19
|
+
return (wire, resolved) => {
|
|
20
|
+
const anonymousId = mintCookie(wire, options.name ?? 'pikku_aid', {
|
|
21
|
+
cookie: { ...DEFAULT_COOKIE, ...options.cookie },
|
|
22
|
+
requires: options.requires,
|
|
23
|
+
consent: resolved?.consent,
|
|
24
|
+
}, () => crypto.randomUUID());
|
|
25
|
+
return anonymousId === undefined ? undefined : { anonymousId };
|
|
26
|
+
};
|
|
27
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AnalyticsIdentityResolver } from './analytics.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Runs resolvers in order, each seeing what the ones before it produced.
|
|
4
|
+
*
|
|
5
|
+
* Order is meaningful rather than incidental: a resolver that mints a cookie
|
|
6
|
+
* may only do so once consent has been read, so the resolver reading consent
|
|
7
|
+
* has to come first. Put the other way round, the minter sees no consent, mints
|
|
8
|
+
* nothing, and the app collects nothing — silently, which is why this threads
|
|
9
|
+
* state through instead of merging independent results.
|
|
10
|
+
*
|
|
11
|
+
* A later resolver wins a key it sets, so a minter's freshly created id
|
|
12
|
+
* replaces the absent one the cookie reader could not find.
|
|
13
|
+
*/
|
|
14
|
+
export declare const composeAnalyticsIdentity: (...resolvers: AnalyticsIdentityResolver[]) => AnalyticsIdentityResolver;
|