@allstak/angular 0.1.0

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.
@@ -0,0 +1,32 @@
1
+ import { AllStak } from '@allstak/js';
2
+ import { SDK_NAME, SDK_VERSION } from './version';
3
+ /**
4
+ * Initialize the AllStak SDK for an Angular application.
5
+ *
6
+ * This is a thin shim over `AllStak.init` from `@allstak/js` that stamps the
7
+ * wrapper identity (`sdkName: 'allstak-angular'`, `sdkVersion`) so the backend
8
+ * can tell Angular traffic apart from plain JS traffic. Everything else —
9
+ * buffering, sampling, session health, offline queue, PII scrubbing — is
10
+ * delegated to the underlying core client.
11
+ *
12
+ * Call this once at app boot in `main.ts`, BEFORE `bootstrapApplication(...)`
13
+ * (standalone) or `platformBrowserDynamic().bootstrapModule(...)` (NgModule),
14
+ * so the global `ErrorHandler` and router instrumentation see a live client:
15
+ *
16
+ * import { init } from '@allstak/angular';
17
+ *
18
+ * init({
19
+ * apiKey: environment.allstakApiKey,
20
+ * environment: environment.production ? 'production' : 'development',
21
+ * });
22
+ *
23
+ * bootstrapApplication(AppComponent, appConfig);
24
+ */
25
+ export function init(config) {
26
+ return AllStak.init({
27
+ ...config,
28
+ sdkName: config.sdkName ?? SDK_NAME,
29
+ sdkVersion: config.sdkVersion ?? SDK_VERSION,
30
+ });
31
+ }
32
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5pdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9pbml0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFdEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFVbEQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXFCRztBQUNILE1BQU0sVUFBVSxJQUFJLENBQUMsTUFBcUI7SUFDeEMsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDO1FBQ2xCLEdBQUcsTUFBTTtRQUNULE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxJQUFJLFFBQVE7UUFDbkMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxVQUFVLElBQUksV0FBVztLQUM3QyxDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWxsU3RhayB9IGZyb20gJ0BhbGxzdGFrL2pzJztcbmltcG9ydCB0eXBlIHsgQWxsU3Rha0NvbmZpZyB9IGZyb20gJ0BhbGxzdGFrL2pzJztcbmltcG9ydCB7IFNES19OQU1FLCBTREtfVkVSU0lPTiB9IGZyb20gJy4vdmVyc2lvbic7XG5cbi8qKlxuICogVGhlIGNvcmUgY2xpZW50IGluc3RhbmNlIHJldHVybmVkIGJ5IGBBbGxTdGFrLmluaXRgLiBgQGFsbHN0YWsvanNgIGRvZXNcbiAqIG5vdCBleHBvcnQgdGhlIGBBbGxTdGFrQ2xpZW50YCBjbGFzcyBieSBuYW1lLCBzbyB3ZSBkZXJpdmUgdGhlIHR5cGUgZnJvbVxuICogdGhlIHZhbHVlLiBUaGlzIGtlZXBzIHRoZSBlbWl0dGVkIGRlY2xhcmF0aW9uIHJlZmVyZW50aWFsIChubyBpbmxpbmluZyBvZlxuICogdGhlIGNvcmUgY2xhc3MncyBwcml2YXRlIG1lbWJlcnMsIHdoaWNoIHdvdWxkIHRyaXAgVFM0MDk0KS5cbiAqL1xuZXhwb3J0IHR5cGUgQWxsU3Rha0NsaWVudEluc3RhbmNlID0gUmV0dXJuVHlwZTx0eXBlb2YgQWxsU3Rhay5pbml0PjtcblxuLyoqXG4gKiBJbml0aWFsaXplIHRoZSBBbGxTdGFrIFNESyBmb3IgYW4gQW5ndWxhciBhcHBsaWNhdGlvbi5cbiAqXG4gKiBUaGlzIGlzIGEgdGhpbiBzaGltIG92ZXIgYEFsbFN0YWsuaW5pdGAgZnJvbSBgQGFsbHN0YWsvanNgIHRoYXQgc3RhbXBzIHRoZVxuICogd3JhcHBlciBpZGVudGl0eSAoYHNka05hbWU6ICdhbGxzdGFrLWFuZ3VsYXInYCwgYHNka1ZlcnNpb25gKSBzbyB0aGUgYmFja2VuZFxuICogY2FuIHRlbGwgQW5ndWxhciB0cmFmZmljIGFwYXJ0IGZyb20gcGxhaW4gSlMgdHJhZmZpYy4gRXZlcnl0aGluZyBlbHNlIOKAlFxuICogYnVmZmVyaW5nLCBzYW1wbGluZywgc2Vzc2lvbiBoZWFsdGgsIG9mZmxpbmUgcXVldWUsIFBJSSBzY3J1YmJpbmcg4oCUIGlzXG4gKiBkZWxlZ2F0ZWQgdG8gdGhlIHVuZGVybHlpbmcgY29yZSBjbGllbnQuXG4gKlxuICogQ2FsbCB0aGlzIG9uY2UgYXQgYXBwIGJvb3QgaW4gYG1haW4udHNgLCBCRUZPUkUgYGJvb3RzdHJhcEFwcGxpY2F0aW9uKC4uLilgXG4gKiAoc3RhbmRhbG9uZSkgb3IgYHBsYXRmb3JtQnJvd3NlckR5bmFtaWMoKS5ib290c3RyYXBNb2R1bGUoLi4uKWAgKE5nTW9kdWxlKSxcbiAqIHNvIHRoZSBnbG9iYWwgYEVycm9ySGFuZGxlcmAgYW5kIHJvdXRlciBpbnN0cnVtZW50YXRpb24gc2VlIGEgbGl2ZSBjbGllbnQ6XG4gKlxuICogICBpbXBvcnQgeyBpbml0IH0gZnJvbSAnQGFsbHN0YWsvYW5ndWxhcic7XG4gKlxuICogICBpbml0KHtcbiAqICAgICBhcGlLZXk6IGVudmlyb25tZW50LmFsbHN0YWtBcGlLZXksXG4gKiAgICAgZW52aXJvbm1lbnQ6IGVudmlyb25tZW50LnByb2R1Y3Rpb24gPyAncHJvZHVjdGlvbicgOiAnZGV2ZWxvcG1lbnQnLFxuICogICB9KTtcbiAqXG4gKiAgIGJvb3RzdHJhcEFwcGxpY2F0aW9uKEFwcENvbXBvbmVudCwgYXBwQ29uZmlnKTtcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXQoY29uZmlnOiBBbGxTdGFrQ29uZmlnKTogQWxsU3Rha0NsaWVudEluc3RhbmNlIHtcbiAgcmV0dXJuIEFsbFN0YWsuaW5pdCh7XG4gICAgLi4uY29uZmlnLFxuICAgIHNka05hbWU6IGNvbmZpZy5zZGtOYW1lID8/IFNES19OQU1FLFxuICAgIHNka1ZlcnNpb246IGNvbmZpZy5zZGtWZXJzaW9uID8/IFNES19WRVJTSU9OLFxuICB9KTtcbn1cbiJdfQ==
@@ -0,0 +1,102 @@
1
+ import { APP_INITIALIZER, ErrorHandler, InjectionToken, NgModule, Optional, } from '@angular/core';
2
+ import { init } from './init';
3
+ import { createErrorHandler } from './error-handler';
4
+ import { TraceService } from './trace-service';
5
+ import { TraceDirective } from './trace-directive';
6
+ import * as i0 from "@angular/core";
7
+ import * as i1 from "./trace-service";
8
+ /** DI token carrying the config passed to {@link AllStakModule.forRoot}. */
9
+ export const ALLSTAK_CONFIG = new InjectionToken('ALLSTAK_CONFIG');
10
+ /**
11
+ * NgModule that exposes {@link TraceDirective} for module-based apps (or
12
+ * standalone components that prefer NgModule-style `imports`):
13
+ *
14
+ * @NgModule({ imports: [AllStakTraceModule] })
15
+ * export class AppModule {}
16
+ *
17
+ * <app-checkout trace="checkout"></app-checkout>
18
+ *
19
+ * `TraceDirective` is a standalone directive, so it is imported (not declared)
20
+ * and re-exported.
21
+ */
22
+ export class AllStakTraceModule {
23
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AllStakTraceModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
24
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: AllStakTraceModule, imports: [TraceDirective], exports: [TraceDirective] });
25
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AllStakTraceModule });
26
+ }
27
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AllStakTraceModule, decorators: [{
28
+ type: NgModule,
29
+ args: [{
30
+ imports: [TraceDirective],
31
+ exports: [TraceDirective],
32
+ }]
33
+ }] });
34
+ /**
35
+ * Root NgModule for module-based Angular apps.
36
+ *
37
+ * import { AllStakModule } from '@allstak/angular';
38
+ *
39
+ * @NgModule({
40
+ * imports: [
41
+ * BrowserModule,
42
+ * AllStakModule.forRoot({ apiKey: environment.allstakApiKey }),
43
+ * ],
44
+ * })
45
+ * export class AppModule {}
46
+ *
47
+ * `forRoot(config)`:
48
+ * - calls {@link init} during bootstrap (via `APP_INITIALIZER`);
49
+ * - overrides the global `ErrorHandler` with the AllStak handler;
50
+ * - force-instantiates {@link TraceService} so router navigation spans open;
51
+ * - exposes {@link TraceDirective} via {@link AllStakTraceModule}.
52
+ *
53
+ * Call `forRoot` exactly once, in your root module. Feature modules that only
54
+ * need the `[trace]` directive can import {@link AllStakTraceModule} directly.
55
+ */
56
+ export class AllStakModule {
57
+ // Inject TraceService here so importing the module force-instantiates it and
58
+ // its Router subscription runs. `@Optional` keeps router-less apps working.
59
+ constructor(_trace) { }
60
+ static forRoot(config) {
61
+ return {
62
+ ngModule: AllStakModule,
63
+ providers: [
64
+ { provide: ALLSTAK_CONFIG, useValue: config },
65
+ { provide: ErrorHandler, useValue: createErrorHandler() },
66
+ TraceService,
67
+ {
68
+ provide: APP_INITIALIZER,
69
+ multi: true,
70
+ useFactory: appInitializerFactory,
71
+ deps: [ALLSTAK_CONFIG, TraceService],
72
+ },
73
+ ],
74
+ };
75
+ }
76
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AllStakModule, deps: [{ token: i1.TraceService, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
77
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: AllStakModule, imports: [AllStakTraceModule], exports: [AllStakTraceModule] });
78
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AllStakModule, imports: [AllStakTraceModule, AllStakTraceModule] });
79
+ }
80
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AllStakModule, decorators: [{
81
+ type: NgModule,
82
+ args: [{
83
+ imports: [AllStakTraceModule],
84
+ exports: [AllStakTraceModule],
85
+ }]
86
+ }], ctorParameters: () => [{ type: i1.TraceService, decorators: [{
87
+ type: Optional
88
+ }] }] });
89
+ /**
90
+ * `APP_INITIALIZER` factory: initialises the SDK from the injected config and
91
+ * touches `TraceService` so it is constructed (its constructor wires the
92
+ * Router subscription). Declared as a named function so ng-packagr's partial
93
+ * compiler can statically reference it (no arrow-in-decorator-metadata error).
94
+ */
95
+ export function appInitializerFactory(config,
96
+ // TraceService is injected via `deps` purely to force its construction.
97
+ _trace) {
98
+ return () => {
99
+ init(config);
100
+ };
101
+ }
102
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kdWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL21vZHVsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsZUFBZSxFQUNmLFlBQVksRUFDWixjQUFjLEVBQ2QsUUFBUSxFQUNSLFFBQVEsR0FDVCxNQUFNLGVBQWUsQ0FBQztBQUd2QixPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQzlCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7OztBQUVuRCw0RUFBNEU7QUFDNUUsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFHLElBQUksY0FBYyxDQUFnQixnQkFBZ0IsQ0FBQyxDQUFDO0FBRWxGOzs7Ozs7Ozs7OztHQVdHO0FBS0gsTUFBTSxPQUFPLGtCQUFrQjt3R0FBbEIsa0JBQWtCO3lHQUFsQixrQkFBa0IsWUFIbkIsY0FBYyxhQUNkLGNBQWM7eUdBRWIsa0JBQWtCOzs0RkFBbEIsa0JBQWtCO2tCQUo5QixRQUFRO21CQUFDO29CQUNSLE9BQU8sRUFBRSxDQUFDLGNBQWMsQ0FBQztvQkFDekIsT0FBTyxFQUFFLENBQUMsY0FBYyxDQUFDO2lCQUMxQjs7QUFHRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUJHO0FBS0gsTUFBTSxPQUFPLGFBQWE7SUFDeEIsNkVBQTZFO0lBQzdFLDRFQUE0RTtJQUM1RSxZQUF3QixNQUEyQixJQUFHLENBQUM7SUFFdkQsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFxQjtRQUNsQyxPQUFPO1lBQ0wsUUFBUSxFQUFFLGFBQWE7WUFDdkIsU0FBUyxFQUFFO2dCQUNULEVBQUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFO2dCQUM3QyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLGtCQUFrQixFQUFFLEVBQUU7Z0JBQ3pELFlBQVk7Z0JBQ1o7b0JBQ0UsT0FBTyxFQUFFLGVBQWU7b0JBQ3hCLEtBQUssRUFBRSxJQUFJO29CQUNYLFVBQVUsRUFBRSxxQkFBcUI7b0JBQ2pDLElBQUksRUFBRSxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUM7aUJBQ3JDO2FBQ0Y7U0FDRixDQUFDO0lBQ0osQ0FBQzt3R0FwQlUsYUFBYTt5R0FBYixhQUFhLFlBNUJiLGtCQUFrQixhQUFsQixrQkFBa0I7eUdBNEJsQixhQUFhLFlBSGQsa0JBQWtCLEVBekJqQixrQkFBa0I7OzRGQTRCbEIsYUFBYTtrQkFKekIsUUFBUTttQkFBQztvQkFDUixPQUFPLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQztvQkFDN0IsT0FBTyxFQUFFLENBQUMsa0JBQWtCLENBQUM7aUJBQzlCOzswQkFJYyxRQUFROztBQW9CdkI7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUscUJBQXFCLENBQ25DLE1BQXFCO0FBQ3JCLHdFQUF3RTtBQUN4RSxNQUFvQjtJQUVwQixPQUFPLEdBQUcsRUFBRTtRQUNWLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNmLENBQUMsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBUFBfSU5JVElBTElaRVIsXG4gIEVycm9ySGFuZGxlcixcbiAgSW5qZWN0aW9uVG9rZW4sXG4gIE5nTW9kdWxlLFxuICBPcHRpb25hbCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgdHlwZSB7IE1vZHVsZVdpdGhQcm92aWRlcnMgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB0eXBlIHsgQWxsU3Rha0NvbmZpZyB9IGZyb20gJ0BhbGxzdGFrL2pzJztcbmltcG9ydCB7IGluaXQgfSBmcm9tICcuL2luaXQnO1xuaW1wb3J0IHsgY3JlYXRlRXJyb3JIYW5kbGVyIH0gZnJvbSAnLi9lcnJvci1oYW5kbGVyJztcbmltcG9ydCB7IFRyYWNlU2VydmljZSB9IGZyb20gJy4vdHJhY2Utc2VydmljZSc7XG5pbXBvcnQgeyBUcmFjZURpcmVjdGl2ZSB9IGZyb20gJy4vdHJhY2UtZGlyZWN0aXZlJztcblxuLyoqIERJIHRva2VuIGNhcnJ5aW5nIHRoZSBjb25maWcgcGFzc2VkIHRvIHtAbGluayBBbGxTdGFrTW9kdWxlLmZvclJvb3R9LiAqL1xuZXhwb3J0IGNvbnN0IEFMTFNUQUtfQ09ORklHID0gbmV3IEluamVjdGlvblRva2VuPEFsbFN0YWtDb25maWc+KCdBTExTVEFLX0NPTkZJRycpO1xuXG4vKipcbiAqIE5nTW9kdWxlIHRoYXQgZXhwb3NlcyB7QGxpbmsgVHJhY2VEaXJlY3RpdmV9IGZvciBtb2R1bGUtYmFzZWQgYXBwcyAob3JcbiAqIHN0YW5kYWxvbmUgY29tcG9uZW50cyB0aGF0IHByZWZlciBOZ01vZHVsZS1zdHlsZSBgaW1wb3J0c2ApOlxuICpcbiAqICAgQE5nTW9kdWxlKHsgaW1wb3J0czogW0FsbFN0YWtUcmFjZU1vZHVsZV0gfSlcbiAqICAgZXhwb3J0IGNsYXNzIEFwcE1vZHVsZSB7fVxuICpcbiAqICAgPGFwcC1jaGVja291dCB0cmFjZT1cImNoZWNrb3V0XCI+PC9hcHAtY2hlY2tvdXQ+XG4gKlxuICogYFRyYWNlRGlyZWN0aXZlYCBpcyBhIHN0YW5kYWxvbmUgZGlyZWN0aXZlLCBzbyBpdCBpcyBpbXBvcnRlZCAobm90IGRlY2xhcmVkKVxuICogYW5kIHJlLWV4cG9ydGVkLlxuICovXG5ATmdNb2R1bGUoe1xuICBpbXBvcnRzOiBbVHJhY2VEaXJlY3RpdmVdLFxuICBleHBvcnRzOiBbVHJhY2VEaXJlY3RpdmVdLFxufSlcbmV4cG9ydCBjbGFzcyBBbGxTdGFrVHJhY2VNb2R1bGUge31cblxuLyoqXG4gKiBSb290IE5nTW9kdWxlIGZvciBtb2R1bGUtYmFzZWQgQW5ndWxhciBhcHBzLlxuICpcbiAqICAgaW1wb3J0IHsgQWxsU3Rha01vZHVsZSB9IGZyb20gJ0BhbGxzdGFrL2FuZ3VsYXInO1xuICpcbiAqICAgQE5nTW9kdWxlKHtcbiAqICAgICBpbXBvcnRzOiBbXG4gKiAgICAgICBCcm93c2VyTW9kdWxlLFxuICogICAgICAgQWxsU3Rha01vZHVsZS5mb3JSb290KHsgYXBpS2V5OiBlbnZpcm9ubWVudC5hbGxzdGFrQXBpS2V5IH0pLFxuICogICAgIF0sXG4gKiAgIH0pXG4gKiAgIGV4cG9ydCBjbGFzcyBBcHBNb2R1bGUge31cbiAqXG4gKiBgZm9yUm9vdChjb25maWcpYDpcbiAqICAgLSBjYWxscyB7QGxpbmsgaW5pdH0gZHVyaW5nIGJvb3RzdHJhcCAodmlhIGBBUFBfSU5JVElBTElaRVJgKTtcbiAqICAgLSBvdmVycmlkZXMgdGhlIGdsb2JhbCBgRXJyb3JIYW5kbGVyYCB3aXRoIHRoZSBBbGxTdGFrIGhhbmRsZXI7XG4gKiAgIC0gZm9yY2UtaW5zdGFudGlhdGVzIHtAbGluayBUcmFjZVNlcnZpY2V9IHNvIHJvdXRlciBuYXZpZ2F0aW9uIHNwYW5zIG9wZW47XG4gKiAgIC0gZXhwb3NlcyB7QGxpbmsgVHJhY2VEaXJlY3RpdmV9IHZpYSB7QGxpbmsgQWxsU3Rha1RyYWNlTW9kdWxlfS5cbiAqXG4gKiBDYWxsIGBmb3JSb290YCBleGFjdGx5IG9uY2UsIGluIHlvdXIgcm9vdCBtb2R1bGUuIEZlYXR1cmUgbW9kdWxlcyB0aGF0IG9ubHlcbiAqIG5lZWQgdGhlIGBbdHJhY2VdYCBkaXJlY3RpdmUgY2FuIGltcG9ydCB7QGxpbmsgQWxsU3Rha1RyYWNlTW9kdWxlfSBkaXJlY3RseS5cbiAqL1xuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW0FsbFN0YWtUcmFjZU1vZHVsZV0sXG4gIGV4cG9ydHM6IFtBbGxTdGFrVHJhY2VNb2R1bGVdLFxufSlcbmV4cG9ydCBjbGFzcyBBbGxTdGFrTW9kdWxlIHtcbiAgLy8gSW5qZWN0IFRyYWNlU2VydmljZSBoZXJlIHNvIGltcG9ydGluZyB0aGUgbW9kdWxlIGZvcmNlLWluc3RhbnRpYXRlcyBpdCBhbmRcbiAgLy8gaXRzIFJvdXRlciBzdWJzY3JpcHRpb24gcnVucy4gYEBPcHRpb25hbGAga2VlcHMgcm91dGVyLWxlc3MgYXBwcyB3b3JraW5nLlxuICBjb25zdHJ1Y3RvcihAT3B0aW9uYWwoKSBfdHJhY2U6IFRyYWNlU2VydmljZSB8IG51bGwpIHt9XG5cbiAgc3RhdGljIGZvclJvb3QoY29uZmlnOiBBbGxTdGFrQ29uZmlnKTogTW9kdWxlV2l0aFByb3ZpZGVyczxBbGxTdGFrTW9kdWxlPiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5nTW9kdWxlOiBBbGxTdGFrTW9kdWxlLFxuICAgICAgcHJvdmlkZXJzOiBbXG4gICAgICAgIHsgcHJvdmlkZTogQUxMU1RBS19DT05GSUcsIHVzZVZhbHVlOiBjb25maWcgfSxcbiAgICAgICAgeyBwcm92aWRlOiBFcnJvckhhbmRsZXIsIHVzZVZhbHVlOiBjcmVhdGVFcnJvckhhbmRsZXIoKSB9LFxuICAgICAgICBUcmFjZVNlcnZpY2UsXG4gICAgICAgIHtcbiAgICAgICAgICBwcm92aWRlOiBBUFBfSU5JVElBTElaRVIsXG4gICAgICAgICAgbXVsdGk6IHRydWUsXG4gICAgICAgICAgdXNlRmFjdG9yeTogYXBwSW5pdGlhbGl6ZXJGYWN0b3J5LFxuICAgICAgICAgIGRlcHM6IFtBTExTVEFLX0NPTkZJRywgVHJhY2VTZXJ2aWNlXSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxufVxuXG4vKipcbiAqIGBBUFBfSU5JVElBTElaRVJgIGZhY3Rvcnk6IGluaXRpYWxpc2VzIHRoZSBTREsgZnJvbSB0aGUgaW5qZWN0ZWQgY29uZmlnIGFuZFxuICogdG91Y2hlcyBgVHJhY2VTZXJ2aWNlYCBzbyBpdCBpcyBjb25zdHJ1Y3RlZCAoaXRzIGNvbnN0cnVjdG9yIHdpcmVzIHRoZVxuICogUm91dGVyIHN1YnNjcmlwdGlvbikuIERlY2xhcmVkIGFzIGEgbmFtZWQgZnVuY3Rpb24gc28gbmctcGFja2FncidzIHBhcnRpYWxcbiAqIGNvbXBpbGVyIGNhbiBzdGF0aWNhbGx5IHJlZmVyZW5jZSBpdCAobm8gYXJyb3ctaW4tZGVjb3JhdG9yLW1ldGFkYXRhIGVycm9yKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcEluaXRpYWxpemVyRmFjdG9yeShcbiAgY29uZmlnOiBBbGxTdGFrQ29uZmlnLFxuICAvLyBUcmFjZVNlcnZpY2UgaXMgaW5qZWN0ZWQgdmlhIGBkZXBzYCBwdXJlbHkgdG8gZm9yY2UgaXRzIGNvbnN0cnVjdGlvbi5cbiAgX3RyYWNlOiBUcmFjZVNlcnZpY2UsXG4pOiAoKSA9PiB2b2lkIHtcbiAgcmV0dXJuICgpID0+IHtcbiAgICBpbml0KGNvbmZpZyk7XG4gIH07XG59XG4iXX0=
@@ -0,0 +1,68 @@
1
+ import { APP_INITIALIZER, ENVIRONMENT_INITIALIZER, ErrorHandler, inject, makeEnvironmentProviders, } from '@angular/core';
2
+ import { init } from './init';
3
+ import { createErrorHandler } from './error-handler';
4
+ import { TraceService } from './trace-service';
5
+ /**
6
+ * Bootstrap the AllStak SDK from a standalone app's `appConfig.providers`.
7
+ *
8
+ * import { provideAllStak } from '@allstak/angular';
9
+ *
10
+ * export const appConfig: ApplicationConfig = {
11
+ * providers: [
12
+ * provideAllStak({ apiKey: environment.allstakApiKey }),
13
+ * ],
14
+ * };
15
+ *
16
+ * This calls {@link init} during DI bootstrap. For the global `ErrorHandler`
17
+ * to catch errors thrown *during bootstrap itself*, prefer calling `init(...)`
18
+ * directly in `main.ts` before `bootstrapApplication`; this provider is the
19
+ * convenient alternative for apps that initialise inside the DI graph.
20
+ */
21
+ export function provideAllStak(config) {
22
+ return makeEnvironmentProviders([
23
+ {
24
+ provide: ENVIRONMENT_INITIALIZER,
25
+ multi: true,
26
+ useValue: () => {
27
+ init(config);
28
+ },
29
+ },
30
+ ]);
31
+ }
32
+ /**
33
+ * Provide the AllStak `ErrorHandler` (overriding Angular's default) so every
34
+ * error routed through Angular's global error handling is captured.
35
+ *
36
+ * providers: [provideAllStakErrorHandler()]
37
+ *
38
+ * Equivalent to `{ provide: ErrorHandler, useValue: createErrorHandler() }`.
39
+ */
40
+ export function provideAllStakErrorHandler(options) {
41
+ return { provide: ErrorHandler, useValue: createErrorHandler(options) };
42
+ }
43
+ /**
44
+ * Register and force-instantiate {@link TraceService} so its Router
45
+ * subscription runs and a navigation span opens per route change.
46
+ *
47
+ * providers: [provideRouter(routes), provideAllStakRouterInstrumentation()]
48
+ *
49
+ * `TraceService` is `providedIn: 'root'`, but Angular only constructs a
50
+ * service when something injects it. The `APP_INITIALIZER` below injects it
51
+ * during bootstrap, guaranteeing the subscription is live before the first
52
+ * navigation completes.
53
+ */
54
+ export function provideAllStakRouterInstrumentation() {
55
+ return makeEnvironmentProviders([
56
+ TraceService,
57
+ {
58
+ provide: APP_INITIALIZER,
59
+ multi: true,
60
+ useFactory: () => {
61
+ // Force-instantiate the service; the factory itself is a no-op.
62
+ inject(TraceService);
63
+ return () => undefined;
64
+ },
65
+ },
66
+ ]);
67
+ }
68
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3Byb3ZpZGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsZUFBZSxFQUNmLHVCQUF1QixFQUN2QixZQUFZLEVBQ1osTUFBTSxFQUNOLHdCQUF3QixHQUN6QixNQUFNLGVBQWUsQ0FBQztBQUd2QixPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQzlCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXJELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUUvQzs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCxNQUFNLFVBQVUsY0FBYyxDQUFDLE1BQXFCO0lBQ2xELE9BQU8sd0JBQXdCLENBQUM7UUFDOUI7WUFDRSxPQUFPLEVBQUUsdUJBQXVCO1lBQ2hDLEtBQUssRUFBRSxJQUFJO1lBQ1gsUUFBUSxFQUFFLEdBQUcsRUFBRTtnQkFDYixJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDZixDQUFDO1NBQ0Y7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0sVUFBVSwwQkFBMEIsQ0FDeEMsT0FBNkI7SUFFN0IsT0FBTyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7QUFDMUUsQ0FBQztBQUVEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLFVBQVUsbUNBQW1DO0lBQ2pELE9BQU8sd0JBQXdCLENBQUM7UUFDOUIsWUFBWTtRQUNaO1lBQ0UsT0FBTyxFQUFFLGVBQWU7WUFDeEIsS0FBSyxFQUFFLElBQUk7WUFDWCxVQUFVLEVBQUUsR0FBRyxFQUFFO2dCQUNmLGdFQUFnRTtnQkFDaEUsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUNyQixPQUFPLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQztZQUN6QixDQUFDO1NBQ0Y7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQVBQX0lOSVRJQUxJWkVSLFxuICBFTlZJUk9OTUVOVF9JTklUSUFMSVpFUixcbiAgRXJyb3JIYW5kbGVyLFxuICBpbmplY3QsXG4gIG1ha2VFbnZpcm9ubWVudFByb3ZpZGVycyxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgdHlwZSB7IEVudmlyb25tZW50UHJvdmlkZXJzLCBQcm92aWRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHR5cGUgeyBBbGxTdGFrQ29uZmlnIH0gZnJvbSAnQGFsbHN0YWsvanMnO1xuaW1wb3J0IHsgaW5pdCB9IGZyb20gJy4vaW5pdCc7XG5pbXBvcnQgeyBjcmVhdGVFcnJvckhhbmRsZXIgfSBmcm9tICcuL2Vycm9yLWhhbmRsZXInO1xuaW1wb3J0IHR5cGUgeyBFcnJvckhhbmRsZXJPcHRpb25zIH0gZnJvbSAnLi9lcnJvci1oYW5kbGVyJztcbmltcG9ydCB7IFRyYWNlU2VydmljZSB9IGZyb20gJy4vdHJhY2Utc2VydmljZSc7XG5cbi8qKlxuICogQm9vdHN0cmFwIHRoZSBBbGxTdGFrIFNESyBmcm9tIGEgc3RhbmRhbG9uZSBhcHAncyBgYXBwQ29uZmlnLnByb3ZpZGVyc2AuXG4gKlxuICogICBpbXBvcnQgeyBwcm92aWRlQWxsU3RhayB9IGZyb20gJ0BhbGxzdGFrL2FuZ3VsYXInO1xuICpcbiAqICAgZXhwb3J0IGNvbnN0IGFwcENvbmZpZzogQXBwbGljYXRpb25Db25maWcgPSB7XG4gKiAgICAgcHJvdmlkZXJzOiBbXG4gKiAgICAgICBwcm92aWRlQWxsU3Rhayh7IGFwaUtleTogZW52aXJvbm1lbnQuYWxsc3Rha0FwaUtleSB9KSxcbiAqICAgICBdLFxuICogICB9O1xuICpcbiAqIFRoaXMgY2FsbHMge0BsaW5rIGluaXR9IGR1cmluZyBESSBib290c3RyYXAuIEZvciB0aGUgZ2xvYmFsIGBFcnJvckhhbmRsZXJgXG4gKiB0byBjYXRjaCBlcnJvcnMgdGhyb3duICpkdXJpbmcgYm9vdHN0cmFwIGl0c2VsZiosIHByZWZlciBjYWxsaW5nIGBpbml0KC4uLilgXG4gKiBkaXJlY3RseSBpbiBgbWFpbi50c2AgYmVmb3JlIGBib290c3RyYXBBcHBsaWNhdGlvbmA7IHRoaXMgcHJvdmlkZXIgaXMgdGhlXG4gKiBjb252ZW5pZW50IGFsdGVybmF0aXZlIGZvciBhcHBzIHRoYXQgaW5pdGlhbGlzZSBpbnNpZGUgdGhlIERJIGdyYXBoLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvdmlkZUFsbFN0YWsoY29uZmlnOiBBbGxTdGFrQ29uZmlnKTogRW52aXJvbm1lbnRQcm92aWRlcnMge1xuICByZXR1cm4gbWFrZUVudmlyb25tZW50UHJvdmlkZXJzKFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBFTlZJUk9OTUVOVF9JTklUSUFMSVpFUixcbiAgICAgIG11bHRpOiB0cnVlLFxuICAgICAgdXNlVmFsdWU6ICgpID0+IHtcbiAgICAgICAgaW5pdChjb25maWcpO1xuICAgICAgfSxcbiAgICB9LFxuICBdKTtcbn1cblxuLyoqXG4gKiBQcm92aWRlIHRoZSBBbGxTdGFrIGBFcnJvckhhbmRsZXJgIChvdmVycmlkaW5nIEFuZ3VsYXIncyBkZWZhdWx0KSBzbyBldmVyeVxuICogZXJyb3Igcm91dGVkIHRocm91Z2ggQW5ndWxhcidzIGdsb2JhbCBlcnJvciBoYW5kbGluZyBpcyBjYXB0dXJlZC5cbiAqXG4gKiAgIHByb3ZpZGVyczogW3Byb3ZpZGVBbGxTdGFrRXJyb3JIYW5kbGVyKCldXG4gKlxuICogRXF1aXZhbGVudCB0byBgeyBwcm92aWRlOiBFcnJvckhhbmRsZXIsIHVzZVZhbHVlOiBjcmVhdGVFcnJvckhhbmRsZXIoKSB9YC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb3ZpZGVBbGxTdGFrRXJyb3JIYW5kbGVyKFxuICBvcHRpb25zPzogRXJyb3JIYW5kbGVyT3B0aW9ucyxcbik6IFByb3ZpZGVyIHtcbiAgcmV0dXJuIHsgcHJvdmlkZTogRXJyb3JIYW5kbGVyLCB1c2VWYWx1ZTogY3JlYXRlRXJyb3JIYW5kbGVyKG9wdGlvbnMpIH07XG59XG5cbi8qKlxuICogUmVnaXN0ZXIgYW5kIGZvcmNlLWluc3RhbnRpYXRlIHtAbGluayBUcmFjZVNlcnZpY2V9IHNvIGl0cyBSb3V0ZXJcbiAqIHN1YnNjcmlwdGlvbiBydW5zIGFuZCBhIG5hdmlnYXRpb24gc3BhbiBvcGVucyBwZXIgcm91dGUgY2hhbmdlLlxuICpcbiAqICAgcHJvdmlkZXJzOiBbcHJvdmlkZVJvdXRlcihyb3V0ZXMpLCBwcm92aWRlQWxsU3Rha1JvdXRlckluc3RydW1lbnRhdGlvbigpXVxuICpcbiAqIGBUcmFjZVNlcnZpY2VgIGlzIGBwcm92aWRlZEluOiAncm9vdCdgLCBidXQgQW5ndWxhciBvbmx5IGNvbnN0cnVjdHMgYVxuICogc2VydmljZSB3aGVuIHNvbWV0aGluZyBpbmplY3RzIGl0LiBUaGUgYEFQUF9JTklUSUFMSVpFUmAgYmVsb3cgaW5qZWN0cyBpdFxuICogZHVyaW5nIGJvb3RzdHJhcCwgZ3VhcmFudGVlaW5nIHRoZSBzdWJzY3JpcHRpb24gaXMgbGl2ZSBiZWZvcmUgdGhlIGZpcnN0XG4gKiBuYXZpZ2F0aW9uIGNvbXBsZXRlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb3ZpZGVBbGxTdGFrUm91dGVySW5zdHJ1bWVudGF0aW9uKCk6IEVudmlyb25tZW50UHJvdmlkZXJzIHtcbiAgcmV0dXJuIG1ha2VFbnZpcm9ubWVudFByb3ZpZGVycyhbXG4gICAgVHJhY2VTZXJ2aWNlLFxuICAgIHtcbiAgICAgIHByb3ZpZGU6IEFQUF9JTklUSUFMSVpFUixcbiAgICAgIG11bHRpOiB0cnVlLFxuICAgICAgdXNlRmFjdG9yeTogKCkgPT4ge1xuICAgICAgICAvLyBGb3JjZS1pbnN0YW50aWF0ZSB0aGUgc2VydmljZTsgdGhlIGZhY3RvcnkgaXRzZWxmIGlzIGEgbm8tb3AuXG4gICAgICAgIGluamVjdChUcmFjZVNlcnZpY2UpO1xuICAgICAgICByZXR1cm4gKCkgPT4gdW5kZWZpbmVkO1xuICAgICAgfSxcbiAgICB9LFxuICBdKTtcbn1cbiJdfQ==
@@ -0,0 +1,96 @@
1
+ import { AllStak } from '@allstak/js';
2
+ /**
3
+ * Class decorator that instruments a component's init lifecycle. Wraps
4
+ * `ngOnInit` so a `ui.angular.init` span is opened on init and finished on
5
+ * `ngAfterViewInit` (or immediately after `ngOnInit` if the component has no
6
+ * `ngAfterViewInit`).
7
+ *
8
+ * @TraceClassDecorator({ name: 'CheckoutComponent' })
9
+ * @Component({ ... })
10
+ * export class CheckoutComponent implements OnInit {}
11
+ */
12
+ export function TraceClassDecorator(options) {
13
+ return function (target) {
14
+ const proto = target.prototype;
15
+ const SPAN_KEY = '__allstak_trace_class_span__';
16
+ const originalOnInit = proto.ngOnInit;
17
+ const originalAfterViewInit = proto.ngAfterViewInit;
18
+ proto.ngOnInit = function () {
19
+ try {
20
+ this[SPAN_KEY] = AllStak.startSpan('ui.angular.init', {
21
+ op: 'ui.angular.init',
22
+ description: options.name,
23
+ attributes: {
24
+ 'allstak.origin': 'auto.ui.angular',
25
+ 'angular.component': options.name,
26
+ },
27
+ });
28
+ }
29
+ catch {
30
+ // ignore
31
+ }
32
+ originalOnInit?.call(this);
33
+ // If there is no ngAfterViewInit, close the span right after init.
34
+ if (!originalAfterViewInit && !proto.ngAfterViewInit) {
35
+ finishSpan(this[SPAN_KEY]);
36
+ this[SPAN_KEY] = undefined;
37
+ }
38
+ };
39
+ proto.ngAfterViewInit = function () {
40
+ originalAfterViewInit?.call(this);
41
+ finishSpan(this[SPAN_KEY]);
42
+ this[SPAN_KEY] = undefined;
43
+ };
44
+ return target;
45
+ };
46
+ }
47
+ /** Alias for the alternate naming. */
48
+ export const TraceClass = TraceClassDecorator;
49
+ /**
50
+ * Method decorator emitting a point-in-time `ui.angular.[hook]` span around a
51
+ * single lifecycle method (e.g. `ngOnInit`, `ngOnChanges`, `ngAfterViewInit`).
52
+ *
53
+ * class Foo {
54
+ * @TraceMethodDecorator({ name: 'Foo.ngOnInit' })
55
+ * ngOnInit() {}
56
+ * }
57
+ */
58
+ export function TraceMethodDecorator(options) {
59
+ return function (_target, propertyKey, descriptor) {
60
+ const original = descriptor.value;
61
+ descriptor.value = function (...args) {
62
+ let span = null;
63
+ try {
64
+ span = AllStak.startSpan(`ui.angular.${propertyKey}`, {
65
+ op: `ui.angular.${propertyKey}`,
66
+ description: options.name,
67
+ attributes: {
68
+ 'allstak.origin': 'auto.ui.angular',
69
+ 'angular.hook': propertyKey,
70
+ },
71
+ });
72
+ }
73
+ catch {
74
+ // ignore
75
+ }
76
+ try {
77
+ return original?.apply(this, args);
78
+ }
79
+ finally {
80
+ finishSpan(span ?? undefined);
81
+ }
82
+ };
83
+ return descriptor;
84
+ };
85
+ }
86
+ /** Alias for the alternate naming. */
87
+ export const TraceMethod = TraceMethodDecorator;
88
+ function finishSpan(span) {
89
+ try {
90
+ span?.finish('ok');
91
+ }
92
+ catch {
93
+ // ignore — span may already be finished
94
+ }
95
+ }
96
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2UtZGVjb3JhdG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90cmFjZS1kZWNvcmF0b3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFhdEM7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUFDLE9BQThCO0lBQ2hFLE9BQU8sVUFBc0QsTUFBUztRQUNwRSxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsU0FHcEIsQ0FBQztRQUNGLE1BQU0sUUFBUSxHQUFHLDhCQUE4QixDQUFDO1FBQ2hELE1BQU0sY0FBYyxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUM7UUFDdEMsTUFBTSxxQkFBcUIsR0FBRyxLQUFLLENBQUMsZUFBZSxDQUFDO1FBRXBELEtBQUssQ0FBQyxRQUFRLEdBQUc7WUFDZixJQUFJLENBQUM7Z0JBQ0gsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsaUJBQWlCLEVBQUU7b0JBQ3BELEVBQUUsRUFBRSxpQkFBaUI7b0JBQ3JCLFdBQVcsRUFBRSxPQUFPLENBQUMsSUFBSTtvQkFDekIsVUFBVSxFQUFFO3dCQUNWLGdCQUFnQixFQUFFLGlCQUFpQjt3QkFDbkMsbUJBQW1CLEVBQUUsT0FBTyxDQUFDLElBQUk7cUJBQ2xDO2lCQUNGLENBQUMsQ0FBQztZQUNMLENBQUM7WUFBQyxNQUFNLENBQUM7Z0JBQ1AsU0FBUztZQUNYLENBQUM7WUFDRCxjQUFjLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzNCLG1FQUFtRTtZQUNuRSxJQUFJLENBQUMscUJBQXFCLElBQUksQ0FBQyxLQUFLLENBQUMsZUFBZSxFQUFFLENBQUM7Z0JBQ3JELFVBQVUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztnQkFDM0IsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLFNBQVMsQ0FBQztZQUM3QixDQUFDO1FBQ0gsQ0FBQyxDQUFDO1FBRUYsS0FBSyxDQUFDLGVBQWUsR0FBRztZQUN0QixxQkFBcUIsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbEMsVUFBVSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1lBQzNCLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxTQUFTLENBQUM7UUFDN0IsQ0FBQyxDQUFDO1FBRUYsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQUVELHNDQUFzQztBQUN0QyxNQUFNLENBQUMsTUFBTSxVQUFVLEdBQUcsbUJBQW1CLENBQUM7QUFFOUM7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLFVBQVUsb0JBQW9CLENBQUMsT0FBOEI7SUFDakUsT0FBTyxVQUNMLE9BQWUsRUFDZixXQUFtQixFQUNuQixVQUE4QjtRQUU5QixNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsS0FBc0QsQ0FBQztRQUNuRixVQUFVLENBQUMsS0FBSyxHQUFHLFVBQXlCLEdBQUcsSUFBZTtZQUM1RCxJQUFJLElBQUksR0FBZ0IsSUFBSSxDQUFDO1lBQzdCLElBQUksQ0FBQztnQkFDSCxJQUFJLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxjQUFjLFdBQVcsRUFBRSxFQUFFO29CQUNwRCxFQUFFLEVBQUUsY0FBYyxXQUFXLEVBQUU7b0JBQy9CLFdBQVcsRUFBRSxPQUFPLENBQUMsSUFBSTtvQkFDekIsVUFBVSxFQUFFO3dCQUNWLGdCQUFnQixFQUFFLGlCQUFpQjt3QkFDbkMsY0FBYyxFQUFFLFdBQVc7cUJBQzVCO2lCQUNGLENBQUMsQ0FBQztZQUNMLENBQUM7WUFBQyxNQUFNLENBQUM7Z0JBQ1AsU0FBUztZQUNYLENBQUM7WUFDRCxJQUFJLENBQUM7Z0JBQ0gsT0FBTyxRQUFRLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNyQyxDQUFDO29CQUFTLENBQUM7Z0JBQ1QsVUFBVSxDQUFDLElBQUksSUFBSSxTQUFTLENBQUMsQ0FBQztZQUNoQyxDQUFDO1FBQ0gsQ0FBQyxDQUFDO1FBQ0YsT0FBTyxVQUFVLENBQUM7SUFDcEIsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQUVELHNDQUFzQztBQUN0QyxNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUcsb0JBQW9CLENBQUM7QUFFaEQsU0FBUyxVQUFVLENBQUMsSUFBYTtJQUMvQixJQUFJLENBQUM7UUFDRixJQUF5QixFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1Asd0NBQXdDO0lBQzFDLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWxsU3RhayB9IGZyb20gJ0BhbGxzdGFrL2pzJztcbmltcG9ydCB0eXBlIHsgU3BhbiB9IGZyb20gJ0BhbGxzdGFrL2pzJztcblxuLyoqXG4gKiBPcHRpb25zIGZvciB7QGxpbmsgVHJhY2VDbGFzc0RlY29yYXRvcn0gLyB7QGxpbmsgVHJhY2VNZXRob2REZWNvcmF0b3J9LlxuICpcbiAqIGBuYW1lYCBpcyByZXF1aXJlZCBiZWNhdXNlIEFuZ3VsYXIgY29tcG9uZW50L2NsYXNzIG5hbWVzIGFyZSBtYW5nbGVkIGluXG4gKiBtaW5pZmllZCBwcm9kdWN0aW9uIGJ1aWxkcyDigJQgdGhlIHNwYW4gd291bGQgb3RoZXJ3aXNlIGJlIHVuaWRlbnRpZmlhYmxlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRyYWNlRGVjb3JhdG9yT3B0aW9ucyB7XG4gIG5hbWU6IHN0cmluZztcbn1cblxuLyoqXG4gKiBDbGFzcyBkZWNvcmF0b3IgdGhhdCBpbnN0cnVtZW50cyBhIGNvbXBvbmVudCdzIGluaXQgbGlmZWN5Y2xlLiBXcmFwc1xuICogYG5nT25Jbml0YCBzbyBhIGB1aS5hbmd1bGFyLmluaXRgIHNwYW4gaXMgb3BlbmVkIG9uIGluaXQgYW5kIGZpbmlzaGVkIG9uXG4gKiBgbmdBZnRlclZpZXdJbml0YCAob3IgaW1tZWRpYXRlbHkgYWZ0ZXIgYG5nT25Jbml0YCBpZiB0aGUgY29tcG9uZW50IGhhcyBub1xuICogYG5nQWZ0ZXJWaWV3SW5pdGApLlxuICpcbiAqICAgQFRyYWNlQ2xhc3NEZWNvcmF0b3IoeyBuYW1lOiAnQ2hlY2tvdXRDb21wb25lbnQnIH0pXG4gKiAgIEBDb21wb25lbnQoeyAuLi4gfSlcbiAqICAgZXhwb3J0IGNsYXNzIENoZWNrb3V0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHt9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBUcmFjZUNsYXNzRGVjb3JhdG9yKG9wdGlvbnM6IFRyYWNlRGVjb3JhdG9yT3B0aW9ucykge1xuICByZXR1cm4gZnVuY3Rpb24gPFQgZXh0ZW5kcyB7IG5ldyAoLi4uYXJnczogYW55W10pOiBvYmplY3QgfT4odGFyZ2V0OiBUKTogVCB7XG4gICAgY29uc3QgcHJvdG8gPSB0YXJnZXQucHJvdG90eXBlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ICYge1xuICAgICAgbmdPbkluaXQ/OiAoKSA9PiB2b2lkO1xuICAgICAgbmdBZnRlclZpZXdJbml0PzogKCkgPT4gdm9pZDtcbiAgICB9O1xuICAgIGNvbnN0IFNQQU5fS0VZID0gJ19fYWxsc3Rha190cmFjZV9jbGFzc19zcGFuX18nO1xuICAgIGNvbnN0IG9yaWdpbmFsT25Jbml0ID0gcHJvdG8ubmdPbkluaXQ7XG4gICAgY29uc3Qgb3JpZ2luYWxBZnRlclZpZXdJbml0ID0gcHJvdG8ubmdBZnRlclZpZXdJbml0O1xuXG4gICAgcHJvdG8ubmdPbkluaXQgPSBmdW5jdGlvbiAodGhpczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXNbU1BBTl9LRVldID0gQWxsU3Rhay5zdGFydFNwYW4oJ3VpLmFuZ3VsYXIuaW5pdCcsIHtcbiAgICAgICAgICBvcDogJ3VpLmFuZ3VsYXIuaW5pdCcsXG4gICAgICAgICAgZGVzY3JpcHRpb246IG9wdGlvbnMubmFtZSxcbiAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICAnYWxsc3Rhay5vcmlnaW4nOiAnYXV0by51aS5hbmd1bGFyJyxcbiAgICAgICAgICAgICdhbmd1bGFyLmNvbXBvbmVudCc6IG9wdGlvbnMubmFtZSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBpZ25vcmVcbiAgICAgIH1cbiAgICAgIG9yaWdpbmFsT25Jbml0Py5jYWxsKHRoaXMpO1xuICAgICAgLy8gSWYgdGhlcmUgaXMgbm8gbmdBZnRlclZpZXdJbml0LCBjbG9zZSB0aGUgc3BhbiByaWdodCBhZnRlciBpbml0LlxuICAgICAgaWYgKCFvcmlnaW5hbEFmdGVyVmlld0luaXQgJiYgIXByb3RvLm5nQWZ0ZXJWaWV3SW5pdCkge1xuICAgICAgICBmaW5pc2hTcGFuKHRoaXNbU1BBTl9LRVldKTtcbiAgICAgICAgdGhpc1tTUEFOX0tFWV0gPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHByb3RvLm5nQWZ0ZXJWaWV3SW5pdCA9IGZ1bmN0aW9uICh0aGlzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikge1xuICAgICAgb3JpZ2luYWxBZnRlclZpZXdJbml0Py5jYWxsKHRoaXMpO1xuICAgICAgZmluaXNoU3Bhbih0aGlzW1NQQU5fS0VZXSk7XG4gICAgICB0aGlzW1NQQU5fS0VZXSA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRhcmdldDtcbiAgfTtcbn1cblxuLyoqIEFsaWFzIGZvciB0aGUgYWx0ZXJuYXRlIG5hbWluZy4gKi9cbmV4cG9ydCBjb25zdCBUcmFjZUNsYXNzID0gVHJhY2VDbGFzc0RlY29yYXRvcjtcblxuLyoqXG4gKiBNZXRob2QgZGVjb3JhdG9yIGVtaXR0aW5nIGEgcG9pbnQtaW4tdGltZSBgdWkuYW5ndWxhci5baG9va11gIHNwYW4gYXJvdW5kIGFcbiAqIHNpbmdsZSBsaWZlY3ljbGUgbWV0aG9kIChlLmcuIGBuZ09uSW5pdGAsIGBuZ09uQ2hhbmdlc2AsIGBuZ0FmdGVyVmlld0luaXRgKS5cbiAqXG4gKiAgIGNsYXNzIEZvbyB7XG4gKiAgICAgQFRyYWNlTWV0aG9kRGVjb3JhdG9yKHsgbmFtZTogJ0Zvby5uZ09uSW5pdCcgfSlcbiAqICAgICBuZ09uSW5pdCgpIHt9XG4gKiAgIH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFRyYWNlTWV0aG9kRGVjb3JhdG9yKG9wdGlvbnM6IFRyYWNlRGVjb3JhdG9yT3B0aW9ucykge1xuICByZXR1cm4gZnVuY3Rpb24gKFxuICAgIF90YXJnZXQ6IG9iamVjdCxcbiAgICBwcm9wZXJ0eUtleTogc3RyaW5nLFxuICAgIGRlc2NyaXB0b3I6IFByb3BlcnR5RGVzY3JpcHRvcixcbiAgKTogUHJvcGVydHlEZXNjcmlwdG9yIHtcbiAgICBjb25zdCBvcmlnaW5hbCA9IGRlc2NyaXB0b3IudmFsdWUgYXMgKCguLi5hcmdzOiB1bmtub3duW10pID0+IHVua25vd24pIHwgdW5kZWZpbmVkO1xuICAgIGRlc2NyaXB0b3IudmFsdWUgPSBmdW5jdGlvbiAodGhpczogdW5rbm93biwgLi4uYXJnczogdW5rbm93bltdKSB7XG4gICAgICBsZXQgc3BhbjogU3BhbiB8IG51bGwgPSBudWxsO1xuICAgICAgdHJ5IHtcbiAgICAgICAgc3BhbiA9IEFsbFN0YWsuc3RhcnRTcGFuKGB1aS5hbmd1bGFyLiR7cHJvcGVydHlLZXl9YCwge1xuICAgICAgICAgIG9wOiBgdWkuYW5ndWxhci4ke3Byb3BlcnR5S2V5fWAsXG4gICAgICAgICAgZGVzY3JpcHRpb246IG9wdGlvbnMubmFtZSxcbiAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICAnYWxsc3Rhay5vcmlnaW4nOiAnYXV0by51aS5hbmd1bGFyJyxcbiAgICAgICAgICAgICdhbmd1bGFyLmhvb2snOiBwcm9wZXJ0eUtleSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBpZ25vcmVcbiAgICAgIH1cbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBvcmlnaW5hbD8uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBmaW5pc2hTcGFuKHNwYW4gPz8gdW5kZWZpbmVkKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBkZXNjcmlwdG9yO1xuICB9O1xufVxuXG4vKiogQWxpYXMgZm9yIHRoZSBhbHRlcm5hdGUgbmFtaW5nLiAqL1xuZXhwb3J0IGNvbnN0IFRyYWNlTWV0aG9kID0gVHJhY2VNZXRob2REZWNvcmF0b3I7XG5cbmZ1bmN0aW9uIGZpbmlzaFNwYW4oc3BhbjogdW5rbm93bik6IHZvaWQge1xuICB0cnkge1xuICAgIChzcGFuIGFzIFNwYW4gfCB1bmRlZmluZWQpPy5maW5pc2goJ29rJyk7XG4gIH0gY2F0Y2gge1xuICAgIC8vIGlnbm9yZSDigJQgc3BhbiBtYXkgYWxyZWFkeSBiZSBmaW5pc2hlZFxuICB9XG59XG4iXX0=
@@ -0,0 +1,65 @@
1
+ import { Directive, Input, } from '@angular/core';
2
+ import { AllStak } from '@allstak/js';
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * `[trace]` template directive for component render timing.
6
+ *
7
+ * <app-checkout trace="checkout"></app-checkout>
8
+ *
9
+ * Opens a `ui.angular.init` span when the host component initialises
10
+ * (`ngOnInit`) and finishes it once the component's view has been fully
11
+ * initialised (`ngAfterViewInit`). The span is named after the directive's
12
+ * `trace` value — required, because component class names are not reliable in
13
+ * minified production builds.
14
+ *
15
+ * Standalone components import the directive directly; module-based apps get
16
+ * it via {@link AllStakTraceModule}.
17
+ */
18
+ export class TraceDirective {
19
+ /**
20
+ * Human-readable name for the traced component. Used as the span
21
+ * description. Required so spans stay meaningful after minification.
22
+ */
23
+ componentName = '';
24
+ span = null;
25
+ ngOnInit() {
26
+ const name = this.componentName || 'unnamed';
27
+ try {
28
+ this.span = AllStak.startSpan('ui.angular.init', {
29
+ op: 'ui.angular.init',
30
+ description: name,
31
+ attributes: {
32
+ 'allstak.origin': 'auto.ui.angular',
33
+ 'angular.component': name,
34
+ },
35
+ });
36
+ }
37
+ catch {
38
+ // Never let render tracing break a component.
39
+ }
40
+ }
41
+ ngAfterViewInit() {
42
+ try {
43
+ this.span?.finish('ok');
44
+ }
45
+ catch {
46
+ // ignore — span may already be finished
47
+ }
48
+ finally {
49
+ this.span = null;
50
+ }
51
+ }
52
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TraceDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
53
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: TraceDirective, isStandalone: true, selector: "[trace]", inputs: { componentName: ["trace", "componentName"] }, ngImport: i0 });
54
+ }
55
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TraceDirective, decorators: [{
56
+ type: Directive,
57
+ args: [{
58
+ selector: '[trace]',
59
+ standalone: true,
60
+ }]
61
+ }], propDecorators: { componentName: [{
62
+ type: Input,
63
+ args: ['trace']
64
+ }] } });
65
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2UtZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RyYWNlLWRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULEtBQUssR0FHTixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sYUFBYSxDQUFDOztBQUd0Qzs7Ozs7Ozs7Ozs7OztHQWFHO0FBS0gsTUFBTSxPQUFPLGNBQWM7SUFDekI7OztPQUdHO0lBQ2EsYUFBYSxHQUFHLEVBQUUsQ0FBQztJQUUzQixJQUFJLEdBQWdCLElBQUksQ0FBQztJQUVqQyxRQUFRO1FBQ04sTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGFBQWEsSUFBSSxTQUFTLENBQUM7UUFDN0MsSUFBSSxDQUFDO1lBQ0gsSUFBSSxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLGlCQUFpQixFQUFFO2dCQUMvQyxFQUFFLEVBQUUsaUJBQWlCO2dCQUNyQixXQUFXLEVBQUUsSUFBSTtnQkFDakIsVUFBVSxFQUFFO29CQUNWLGdCQUFnQixFQUFFLGlCQUFpQjtvQkFDbkMsbUJBQW1CLEVBQUUsSUFBSTtpQkFDMUI7YUFDRixDQUFDLENBQUM7UUFDTCxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsOENBQThDO1FBQ2hELENBQUM7SUFDSCxDQUFDO0lBRUQsZUFBZTtRQUNiLElBQUksQ0FBQztZQUNILElBQUksQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzFCLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCx3Q0FBd0M7UUFDMUMsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDbkIsQ0FBQztJQUNILENBQUM7d0dBakNVLGNBQWM7NEZBQWQsY0FBYzs7NEZBQWQsY0FBYztrQkFKMUIsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsU0FBUztvQkFDbkIsVUFBVSxFQUFFLElBQUk7aUJBQ2pCOzhCQU1pQixhQUFhO3NCQUE1QixLQUFLO3VCQUFDLE9BQU8iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBEaXJlY3RpdmUsXG4gIElucHV0LFxuICBPbkluaXQsXG4gIEFmdGVyVmlld0luaXQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWxsU3RhayB9IGZyb20gJ0BhbGxzdGFrL2pzJztcbmltcG9ydCB0eXBlIHsgU3BhbiB9IGZyb20gJ0BhbGxzdGFrL2pzJztcblxuLyoqXG4gKiBgW3RyYWNlXWAgdGVtcGxhdGUgZGlyZWN0aXZlIGZvciBjb21wb25lbnQgcmVuZGVyIHRpbWluZy5cbiAqXG4gKiAgIDxhcHAtY2hlY2tvdXQgdHJhY2U9XCJjaGVja291dFwiPjwvYXBwLWNoZWNrb3V0PlxuICpcbiAqIE9wZW5zIGEgYHVpLmFuZ3VsYXIuaW5pdGAgc3BhbiB3aGVuIHRoZSBob3N0IGNvbXBvbmVudCBpbml0aWFsaXNlc1xuICogKGBuZ09uSW5pdGApIGFuZCBmaW5pc2hlcyBpdCBvbmNlIHRoZSBjb21wb25lbnQncyB2aWV3IGhhcyBiZWVuIGZ1bGx5XG4gKiBpbml0aWFsaXNlZCAoYG5nQWZ0ZXJWaWV3SW5pdGApLiBUaGUgc3BhbiBpcyBuYW1lZCBhZnRlciB0aGUgZGlyZWN0aXZlJ3NcbiAqIGB0cmFjZWAgdmFsdWUg4oCUIHJlcXVpcmVkLCBiZWNhdXNlIGNvbXBvbmVudCBjbGFzcyBuYW1lcyBhcmUgbm90IHJlbGlhYmxlIGluXG4gKiBtaW5pZmllZCBwcm9kdWN0aW9uIGJ1aWxkcy5cbiAqXG4gKiBTdGFuZGFsb25lIGNvbXBvbmVudHMgaW1wb3J0IHRoZSBkaXJlY3RpdmUgZGlyZWN0bHk7IG1vZHVsZS1iYXNlZCBhcHBzIGdldFxuICogaXQgdmlhIHtAbGluayBBbGxTdGFrVHJhY2VNb2R1bGV9LlxuICovXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdbdHJhY2VdJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbn0pXG5leHBvcnQgY2xhc3MgVHJhY2VEaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQge1xuICAvKipcbiAgICogSHVtYW4tcmVhZGFibGUgbmFtZSBmb3IgdGhlIHRyYWNlZCBjb21wb25lbnQuIFVzZWQgYXMgdGhlIHNwYW5cbiAgICogZGVzY3JpcHRpb24uIFJlcXVpcmVkIHNvIHNwYW5zIHN0YXkgbWVhbmluZ2Z1bCBhZnRlciBtaW5pZmljYXRpb24uXG4gICAqL1xuICBASW5wdXQoJ3RyYWNlJykgY29tcG9uZW50TmFtZSA9ICcnO1xuXG4gIHByaXZhdGUgc3BhbjogU3BhbiB8IG51bGwgPSBudWxsO1xuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGNvbnN0IG5hbWUgPSB0aGlzLmNvbXBvbmVudE5hbWUgfHwgJ3VubmFtZWQnO1xuICAgIHRyeSB7XG4gICAgICB0aGlzLnNwYW4gPSBBbGxTdGFrLnN0YXJ0U3BhbigndWkuYW5ndWxhci5pbml0Jywge1xuICAgICAgICBvcDogJ3VpLmFuZ3VsYXIuaW5pdCcsXG4gICAgICAgIGRlc2NyaXB0aW9uOiBuYW1lLFxuICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgJ2FsbHN0YWsub3JpZ2luJzogJ2F1dG8udWkuYW5ndWxhcicsXG4gICAgICAgICAgJ2FuZ3VsYXIuY29tcG9uZW50JzogbmFtZSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gTmV2ZXIgbGV0IHJlbmRlciB0cmFjaW5nIGJyZWFrIGEgY29tcG9uZW50LlxuICAgIH1cbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5zcGFuPy5maW5pc2goJ29rJyk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBpZ25vcmUg4oCUIHNwYW4gbWF5IGFscmVhZHkgYmUgZmluaXNoZWRcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5zcGFuID0gbnVsbDtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,101 @@
1
+ import { Injectable, Optional } from '@angular/core';
2
+ import { NavigationStart, NavigationEnd, NavigationCancel, NavigationError, } from '@angular/router';
3
+ import { AllStak } from '@allstak/js';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@angular/router";
6
+ /**
7
+ * Router-aware navigation instrumentation.
8
+ *
9
+ * `TraceService` subscribes to Angular `Router` events and opens a
10
+ * `navigation` span per route change — `NavigationStart` opens it,
11
+ * `NavigationEnd` finishes it `ok`, and `NavigationCancel` / `NavigationError`
12
+ * finish it `error`. A navigation breadcrumb is recorded alongside each span.
13
+ *
14
+ * Because Angular only constructs a service when something injects it, the
15
+ * service must be *force-instantiated* for its Router subscription to run.
16
+ * Use {@link provideAllStakRouterInstrumentation} (standalone) or inject it in
17
+ * your `AppComponent` constructor (NgModule) — see those helpers for wiring.
18
+ *
19
+ * `Router` is `@Optional()` so apps without `@angular/router` (which is an
20
+ * optional peer dependency) can still construct the service without error; it
21
+ * simply becomes a no-op.
22
+ */
23
+ export class TraceService {
24
+ router;
25
+ activeNavSpan = null;
26
+ subscription = null;
27
+ constructor(router) {
28
+ this.router = router;
29
+ if (!this.router)
30
+ return;
31
+ this.subscription = this.router.events.subscribe((event) => {
32
+ this.handleEvent(event);
33
+ });
34
+ }
35
+ handleEvent(event) {
36
+ try {
37
+ if (event instanceof NavigationStart) {
38
+ this.onNavigationStart(event.url);
39
+ }
40
+ else if (event instanceof NavigationEnd) {
41
+ this.finishActive('ok');
42
+ }
43
+ else if (event instanceof NavigationCancel ||
44
+ event instanceof NavigationError) {
45
+ this.finishActive('error');
46
+ if (event instanceof NavigationError) {
47
+ AllStak.captureException(event.error instanceof Error
48
+ ? event.error
49
+ : new Error(String(event.error)), { framework: 'angular', source: '@angular/router' });
50
+ }
51
+ }
52
+ }
53
+ catch {
54
+ // ignore — never block navigation on observability errors
55
+ }
56
+ }
57
+ onNavigationStart(url) {
58
+ // A new navigation supersedes any span still open from a redirect chain.
59
+ this.finishActive('ok');
60
+ AllStak.addBreadcrumb({
61
+ type: 'navigation',
62
+ message: url,
63
+ level: 'info',
64
+ data: { url },
65
+ });
66
+ this.activeNavSpan = AllStak.startSpan('navigation', {
67
+ op: 'navigation',
68
+ description: url,
69
+ attributes: {
70
+ 'allstak.origin': 'auto.navigation.angular',
71
+ 'route.url': url,
72
+ },
73
+ });
74
+ }
75
+ finishActive(status) {
76
+ if (!this.activeNavSpan)
77
+ return;
78
+ try {
79
+ this.activeNavSpan.finish(status);
80
+ }
81
+ catch {
82
+ // ignore — span may already be finished
83
+ }
84
+ finally {
85
+ this.activeNavSpan = null;
86
+ }
87
+ }
88
+ ngOnDestroy() {
89
+ this.subscription?.unsubscribe();
90
+ this.finishActive('ok');
91
+ }
92
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TraceService, deps: [{ token: i1.Router, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
93
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TraceService, providedIn: 'root' });
94
+ }
95
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TraceService, decorators: [{
96
+ type: Injectable,
97
+ args: [{ providedIn: 'root' }]
98
+ }], ctorParameters: () => [{ type: i1.Router, decorators: [{
99
+ type: Optional
100
+ }] }] });
101
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2Utc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90cmFjZS1zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQWEsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2hFLE9BQU8sRUFFTCxlQUFlLEVBQ2YsYUFBYSxFQUNiLGdCQUFnQixFQUNoQixlQUFlLEdBQ2hCLE1BQU0saUJBQWlCLENBQUM7QUFHekIsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGFBQWEsQ0FBQzs7O0FBR3RDOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBRUgsTUFBTSxPQUFPLFlBQVk7SUFJa0I7SUFIakMsYUFBYSxHQUFnQixJQUFJLENBQUM7SUFDekIsWUFBWSxHQUF3QixJQUFJLENBQUM7SUFFMUQsWUFBeUMsTUFBcUI7UUFBckIsV0FBTSxHQUFOLE1BQU0sQ0FBZTtRQUM1RCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPO1FBQ3pCLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsS0FBa0IsRUFBRSxFQUFFO1lBQ3RFLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDMUIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sV0FBVyxDQUFDLEtBQWtCO1FBQ3BDLElBQUksQ0FBQztZQUNILElBQUksS0FBSyxZQUFZLGVBQWUsRUFBRSxDQUFDO2dCQUNyQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3BDLENBQUM7aUJBQU0sSUFBSSxLQUFLLFlBQVksYUFBYSxFQUFFLENBQUM7Z0JBQzFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDMUIsQ0FBQztpQkFBTSxJQUNMLEtBQUssWUFBWSxnQkFBZ0I7Z0JBQ2pDLEtBQUssWUFBWSxlQUFlLEVBQ2hDLENBQUM7Z0JBQ0QsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDM0IsSUFBSSxLQUFLLFlBQVksZUFBZSxFQUFFLENBQUM7b0JBQ3JDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FDdEIsS0FBSyxDQUFDLEtBQUssWUFBWSxLQUFLO3dCQUMxQixDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUs7d0JBQ2IsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsRUFDbEMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxpQkFBaUIsRUFBRSxDQUNwRCxDQUFDO2dCQUNKLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLDBEQUEwRDtRQUM1RCxDQUFDO0lBQ0gsQ0FBQztJQUVPLGlCQUFpQixDQUFDLEdBQVc7UUFDbkMseUVBQXlFO1FBQ3pFLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFeEIsT0FBTyxDQUFDLGFBQWEsQ0FBQztZQUNwQixJQUFJLEVBQUUsWUFBWTtZQUNsQixPQUFPLEVBQUUsR0FBRztZQUNaLEtBQUssRUFBRSxNQUFNO1lBQ2IsSUFBSSxFQUFFLEVBQUUsR0FBRyxFQUFFO1NBQ2QsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLGFBQWEsR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLFlBQVksRUFBRTtZQUNuRCxFQUFFLEVBQUUsWUFBWTtZQUNoQixXQUFXLEVBQUUsR0FBRztZQUNoQixVQUFVLEVBQUU7Z0JBQ1YsZ0JBQWdCLEVBQUUseUJBQXlCO2dCQUMzQyxXQUFXLEVBQUUsR0FBRzthQUNqQjtTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxZQUFZLENBQUMsTUFBc0I7UUFDekMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhO1lBQUUsT0FBTztRQUNoQyxJQUFJLENBQUM7WUFDSCxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNwQyxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1Asd0NBQXdDO1FBQzFDLENBQUM7Z0JBQVMsQ0FBQztZQUNULElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDO1FBQzVCLENBQUM7SUFDSCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxZQUFZLEVBQUUsV0FBVyxFQUFFLENBQUM7UUFDakMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMxQixDQUFDO3dHQXZFVSxZQUFZOzRHQUFaLFlBQVksY0FEQyxNQUFNOzs0RkFDbkIsWUFBWTtrQkFEeEIsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUU7OzBCQUtuQixRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgT25EZXN0cm95LCBPcHRpb25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgUm91dGVyLFxuICBOYXZpZ2F0aW9uU3RhcnQsXG4gIE5hdmlnYXRpb25FbmQsXG4gIE5hdmlnYXRpb25DYW5jZWwsXG4gIE5hdmlnYXRpb25FcnJvcixcbn0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB0eXBlIHsgRXZlbnQgYXMgUm91dGVyRXZlbnQgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHR5cGUgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEFsbFN0YWsgfSBmcm9tICdAYWxsc3Rhay9qcyc7XG5pbXBvcnQgdHlwZSB7IFNwYW4gfSBmcm9tICdAYWxsc3Rhay9qcyc7XG5cbi8qKlxuICogUm91dGVyLWF3YXJlIG5hdmlnYXRpb24gaW5zdHJ1bWVudGF0aW9uLlxuICpcbiAqIGBUcmFjZVNlcnZpY2VgIHN1YnNjcmliZXMgdG8gQW5ndWxhciBgUm91dGVyYCBldmVudHMgYW5kIG9wZW5zIGFcbiAqIGBuYXZpZ2F0aW9uYCBzcGFuIHBlciByb3V0ZSBjaGFuZ2Ug4oCUIGBOYXZpZ2F0aW9uU3RhcnRgIG9wZW5zIGl0LFxuICogYE5hdmlnYXRpb25FbmRgIGZpbmlzaGVzIGl0IGBva2AsIGFuZCBgTmF2aWdhdGlvbkNhbmNlbGAgLyBgTmF2aWdhdGlvbkVycm9yYFxuICogZmluaXNoIGl0IGBlcnJvcmAuIEEgbmF2aWdhdGlvbiBicmVhZGNydW1iIGlzIHJlY29yZGVkIGFsb25nc2lkZSBlYWNoIHNwYW4uXG4gKlxuICogQmVjYXVzZSBBbmd1bGFyIG9ubHkgY29uc3RydWN0cyBhIHNlcnZpY2Ugd2hlbiBzb21ldGhpbmcgaW5qZWN0cyBpdCwgdGhlXG4gKiBzZXJ2aWNlIG11c3QgYmUgKmZvcmNlLWluc3RhbnRpYXRlZCogZm9yIGl0cyBSb3V0ZXIgc3Vic2NyaXB0aW9uIHRvIHJ1bi5cbiAqIFVzZSB7QGxpbmsgcHJvdmlkZUFsbFN0YWtSb3V0ZXJJbnN0cnVtZW50YXRpb259IChzdGFuZGFsb25lKSBvciBpbmplY3QgaXQgaW5cbiAqIHlvdXIgYEFwcENvbXBvbmVudGAgY29uc3RydWN0b3IgKE5nTW9kdWxlKSDigJQgc2VlIHRob3NlIGhlbHBlcnMgZm9yIHdpcmluZy5cbiAqXG4gKiBgUm91dGVyYCBpcyBgQE9wdGlvbmFsKClgIHNvIGFwcHMgd2l0aG91dCBgQGFuZ3VsYXIvcm91dGVyYCAod2hpY2ggaXMgYW5cbiAqIG9wdGlvbmFsIHBlZXIgZGVwZW5kZW5jeSkgY2FuIHN0aWxsIGNvbnN0cnVjdCB0aGUgc2VydmljZSB3aXRob3V0IGVycm9yOyBpdFxuICogc2ltcGx5IGJlY29tZXMgYSBuby1vcC5cbiAqL1xuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcbmV4cG9ydCBjbGFzcyBUcmFjZVNlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBwcml2YXRlIGFjdGl2ZU5hdlNwYW46IFNwYW4gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSByZWFkb25seSBzdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbiB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKEBPcHRpb25hbCgpIHByaXZhdGUgcmVhZG9ubHkgcm91dGVyOiBSb3V0ZXIgfCBudWxsKSB7XG4gICAgaWYgKCF0aGlzLnJvdXRlcikgcmV0dXJuO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uID0gdGhpcy5yb3V0ZXIuZXZlbnRzLnN1YnNjcmliZSgoZXZlbnQ6IFJvdXRlckV2ZW50KSA9PiB7XG4gICAgICB0aGlzLmhhbmRsZUV2ZW50KGV2ZW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlRXZlbnQoZXZlbnQ6IFJvdXRlckV2ZW50KTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIGlmIChldmVudCBpbnN0YW5jZW9mIE5hdmlnYXRpb25TdGFydCkge1xuICAgICAgICB0aGlzLm9uTmF2aWdhdGlvblN0YXJ0KGV2ZW50LnVybCk7XG4gICAgICB9IGVsc2UgaWYgKGV2ZW50IGluc3RhbmNlb2YgTmF2aWdhdGlvbkVuZCkge1xuICAgICAgICB0aGlzLmZpbmlzaEFjdGl2ZSgnb2snKTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGV2ZW50IGluc3RhbmNlb2YgTmF2aWdhdGlvbkNhbmNlbCB8fFxuICAgICAgICBldmVudCBpbnN0YW5jZW9mIE5hdmlnYXRpb25FcnJvclxuICAgICAgKSB7XG4gICAgICAgIHRoaXMuZmluaXNoQWN0aXZlKCdlcnJvcicpO1xuICAgICAgICBpZiAoZXZlbnQgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uRXJyb3IpIHtcbiAgICAgICAgICBBbGxTdGFrLmNhcHR1cmVFeGNlcHRpb24oXG4gICAgICAgICAgICBldmVudC5lcnJvciBpbnN0YW5jZW9mIEVycm9yXG4gICAgICAgICAgICAgID8gZXZlbnQuZXJyb3JcbiAgICAgICAgICAgICAgOiBuZXcgRXJyb3IoU3RyaW5nKGV2ZW50LmVycm9yKSksXG4gICAgICAgICAgICB7IGZyYW1ld29yazogJ2FuZ3VsYXInLCBzb3VyY2U6ICdAYW5ndWxhci9yb3V0ZXInIH0sXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gaWdub3JlIOKAlCBuZXZlciBibG9jayBuYXZpZ2F0aW9uIG9uIG9ic2VydmFiaWxpdHkgZXJyb3JzXG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBvbk5hdmlnYXRpb25TdGFydCh1cmw6IHN0cmluZyk6IHZvaWQge1xuICAgIC8vIEEgbmV3IG5hdmlnYXRpb24gc3VwZXJzZWRlcyBhbnkgc3BhbiBzdGlsbCBvcGVuIGZyb20gYSByZWRpcmVjdCBjaGFpbi5cbiAgICB0aGlzLmZpbmlzaEFjdGl2ZSgnb2snKTtcblxuICAgIEFsbFN0YWsuYWRkQnJlYWRjcnVtYih7XG4gICAgICB0eXBlOiAnbmF2aWdhdGlvbicsXG4gICAgICBtZXNzYWdlOiB1cmwsXG4gICAgICBsZXZlbDogJ2luZm8nLFxuICAgICAgZGF0YTogeyB1cmwgfSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWN0aXZlTmF2U3BhbiA9IEFsbFN0YWsuc3RhcnRTcGFuKCduYXZpZ2F0aW9uJywge1xuICAgICAgb3A6ICduYXZpZ2F0aW9uJyxcbiAgICAgIGRlc2NyaXB0aW9uOiB1cmwsXG4gICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICdhbGxzdGFrLm9yaWdpbic6ICdhdXRvLm5hdmlnYXRpb24uYW5ndWxhcicsXG4gICAgICAgICdyb3V0ZS51cmwnOiB1cmwsXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBmaW5pc2hBY3RpdmUoc3RhdHVzOiAnb2snIHwgJ2Vycm9yJyk6IHZvaWQge1xuICAgIGlmICghdGhpcy5hY3RpdmVOYXZTcGFuKSByZXR1cm47XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuYWN0aXZlTmF2U3Bhbi5maW5pc2goc3RhdHVzKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIGlnbm9yZSDigJQgc3BhbiBtYXkgYWxyZWFkeSBiZSBmaW5pc2hlZFxuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLmFjdGl2ZU5hdlNwYW4gPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuZmluaXNoQWN0aXZlKCdvaycpO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,4 @@
1
+ // AUTO-GENERATED by scripts/gen-version.mjs — do not edit by hand.
2
+ export const SDK_NAME = 'allstak-angular';
3
+ export const SDK_VERSION = "0.1.0";
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy92ZXJzaW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLG1FQUFtRTtBQUNuRSxNQUFNLENBQUMsTUFBTSxRQUFRLEdBQUcsaUJBQWlCLENBQUM7QUFDMUMsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEFVVE8tR0VORVJBVEVEIGJ5IHNjcmlwdHMvZ2VuLXZlcnNpb24ubWpzIOKAlCBkbyBub3QgZWRpdCBieSBoYW5kLlxuZXhwb3J0IGNvbnN0IFNES19OQU1FID0gJ2FsbHN0YWstYW5ndWxhcic7XG5leHBvcnQgY29uc3QgU0RLX1ZFUlNJT04gPSBcIjAuMS4wXCI7XG4iXX0=