@kaiord/core
Advanced tools
| {"version":3,"file":"index.d.ts","names":[],"sources":["../src/domain/schemas/length-unit.ts","../src/domain/converters/length-unit.converter.ts","../src/domain/schemas/krd/event.ts","../src/domain/schemas/krd/lap.ts","../src/domain/schemas/krd/metadata.ts","../src/domain/schemas/krd/record.ts","../src/domain/schemas/krd/session.ts","../src/domain/schemas/krd/index.ts","../src/domain/converters/workout-to-krd.converter.ts","../src/domain/hash/canonical-hash.ts","../src/domain/ingest/derive-external-id.ts","../src/domain/managed-data-type-registry.ts","../src/domain/managed-data-type.ts","../src/domain/schemas/workout-step.ts","../src/domain/schemas/workout.ts","../src/domain/schemas/planned-session.ts","../src/domain/schemas/activity.ts","../src/domain/schemas/training-zones.ts","../src/domain/schemas/duration-type.ts","../src/domain/schemas/duration.ts","../src/domain/schemas/target-type.ts","../src/domain/schemas/target-values/cadence.ts","../src/domain/schemas/target-values/heart-rate.ts","../src/domain/schemas/target-values/pace.ts","../src/domain/schemas/target-values/power.ts","../src/domain/schemas/target-values/stroke-type.ts","../src/domain/schemas/target-values/unit.ts","../src/domain/schemas/target.ts","../src/domain/schemas/equipment.ts","../src/domain/schemas/intensity.ts","../src/domain/schemas/sport.ts","../src/domain/schemas/sport-category.ts","../src/domain/schemas/sub-sport.ts","../src/domain/schemas/swim-stroke.ts","../src/domain/schemas/file-type.ts","../src/domain/schemas/health/body-composition.ts","../src/domain/schemas/health/daily.ts","../src/domain/schemas/health/energy-balance.ts","../src/domain/schemas/health/energy-goal.ts","../src/domain/schemas/health/heart-rate-series.ts","../src/domain/schemas/health/hrv.ts","../src/domain/schemas/health/nutrition.ts","../src/domain/schemas/health/sleep.ts","../src/domain/schemas/health/strain.ts","../src/domain/schemas/health/stress.ts","../src/domain/schemas/health/tolerances.ts","../src/domain/schemas/health/vitals.ts","../src/domain/schemas/health/weight.ts","../src/domain/schemas/health/index.ts","../src/domain/type-guards.ts","../src/domain/types/error-types.ts","../src/domain/types/shared-errors.ts","../src/domain/types/fit-errors.ts","../src/domain/types/garmin-errors.ts","../src/domain/types/krd-errors.ts","../src/domain/types/service-errors.ts","../src/domain/types/tcx-errors.ts","../src/domain/types/tolerance-errors.ts","../src/domain/types/unsupported-krd-type-error.ts","../src/domain/types/zwift-errors.ts","../src/domain/validation/extract-workout.ts","../src/domain/validation/schema-validator.ts","../src/domain/validation/tolerance-checker.ts","../src/domain/validation/validate-krd.ts","../src/domain/zones/power-zones.ts","../src/ports/analytics.ts","../src/adapters/analytics/noop-analytics.ts","../src/ports/logger.ts","../src/adapters/logger/console-logger.ts","../src/ports/auth-provider.ts","../src/ports/format-strategy.ts","../src/ports/token-store.ts","../src/ports/workout-service.ts","../src/application/from-format.ts","../src/application/to-format.ts","../src/application/energy/activity-factor.ts","../src/application/energy/adaptive-tdee.ts","../src/application/energy/aggregate-energy-balance.ts","../src/application/energy/bmr.ts","../src/application/energy/day-balance.ts","../src/application/energy/ema.ts","../src/application/energy/expected-activity-kcal.ts","../src/application/energy/expenditure.ts","../src/application/energy/goal-cap.ts","../src/application/energy/goal-delta.ts","../src/application/energy/macro-targets.ts","../src/application/energy/met-table.ts","../src/application/energy/periodized-target.ts","../src/application/round-trip/validate-round-trip.ts","../src/protocol/profile-snapshot.ts","../src/domain/lab/lab-flag.ts","../src/domain/lab/lab-parameter.ts","../src/domain/lab/lab-parameter-catalog.ts","../src/domain/lab/lab-provenance.ts","../src/domain/lab/lab-report.ts","../src/domain/lab/lab-value.ts","../src/domain/lab/ref-text.ts","../src/domain/lab/unit-conversion.ts"],"mappings":";;cAEa,kBAAgB,EAAA;;;;KAEjB,aAAa,EAAE,aAAa;;;cCF3B,wBAAqB,gBAClB,MACR;;;;;;;;;;;;;;;;;;;cCcK,gBAAc,EAAA;;;;;;;;;;;;;;;;;GAiBzB,EAAA,KAAA;;;;;;KAOU,WAAW,EAAE,aAAa;;;;;;cCjCzB,qBAAmB,EAAA;;;;;;;;KASpB,gBAAgB,EAAE,aAAa;;;;;;cAO9B,cAAY,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CvB,EAAA,KAAA;;;;KAKU,SAAS,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;cCjDvB,mBAAiB,EAAA;;;;;;;GAgB5B,EAAA,KAAA;;;;;;KAOU,cAAc,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;cC5B5B,iBAAe,EAAA;;;;;;;;;;;;;;;;GA4B1B,EAAA,KAAA;;;;;;KAOU,YAAY,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;;cClC1B,kBAAgB,EAAA;;;;;;;;;;;;;;;;;;;;;GAuC3B,EAAA,KAAA;;;;;;KAOU,aAAa,EAAE,aAAa;;;;;;;;;;;;;;;;;cC7B3B,qBAAmB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkBR,EAAA,KAAA,UAAA,EAAA;KAEZ,gBAAgB,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAgC9B,WAAS,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BlB,EAAA,KAAA;;;;;;KAOQ,MAAM,EAAE,aAAa;;;KC1H5B;EACH;;;;;;;;;;;;;cAcW,mBAAgB,kBACX,UACN,4BACT;;;cCQU,gBAAa,OAAW;;;;;;;;;;;cCrBxB,mBAAgB;EAC3B,SAAS;EACT;;;;cCeW,uBAAuB,OAClC,iBACA;;;cCrBW;KAgBD,0BAA0B;;KAG1B;;KAGA,eAAe,MAAM,SAAS,MAAM;KAEpC;EACV;EACA,QAAQ,EAAE;EACV;IAAgB;IAAiB;;EACjC,iBAAiB;;;;;;;;;;cCrBN,mBAAiB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsB1B,EAAA,KAAA;;;;;;KAOQ,cAAc,EAAE,aAAa;;;;;;;;cC9B5B,uBAAqB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAIhC,EAAA,KAAA;;;;;;;;;;;;;;;;;;;;;cAsBW,eAAa,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiBxB,EAAA,KAAA;;;;;;KAOU,kBAAkB,EAAE,aAAa;;;;;;KAOjC,UAAU,EAAE,aAAa;;;;;;;cCjExB,4BAA0B,EAAA;;;;;KAM3B,uBAAuB,EAAE,aAAa;;;;;;;;;;;;cAarC,sBAAoB,EAAA;;;;;;;;;;;;;;;;;GAqB/B,EAAA,KAAA;KAEU,iBAAiB,EAAE,aAAa;;;;;;;;;cCtC/B,uBAAqB,EAAA;;;;;;;;;;;;GAqBhC,EAAA,KAAA;KAEU,kBAAkB,EAAE,aAAa;;;;;;;;cAShC,gBAAc,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAKzB,EAAA,KAAA;KAEU,WAAW,EAAE,aAAa;;;;cC9CzB,wBAAsB,EAAA;;;;;GAQjC,EAAA,KAAA;KAEU,mBAAmB,EAAE,aAAa;;cAGjC,uBAAqB,EAAA;;;;;;;;;;;;;GAKhC,EAAA,KAAA;KAEU,kBAAkB,EAAE,aAAa;;;;;;;cAQhC,qBAAmB,EAAA;;;;;;;;;;;;;;;;;;GAM9B,EAAA,KAAA;KAEU,gBAAgB,EAAE,aAAa;;;;;;;;;;;;;;;;;;cCtB9B,oBAAkB,EAAA;;;;;;;;;;;;;;;;;;;;;KAsBnB,eAAe,EAAE,aAAa;;;;;;;;;;;;;;;;cCnB7B,gBAAc,EAAA,uBAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEzB,EAAA,KAAA;;;;;;KAOU,WAAW,EAAE,aAAa;;;;;;;;;;;;;;;;;;cC3EzB,kBAAgB,EAAA;;;;;;;;;;;;;KAcjB,aAAa,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;cCJ3B,oBAAkB,EAAA,uBAAA,EAAA;;;;;;;GAgB7B,EAAA,KAAA;;;;;;KAOU,eAAe,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;cCvB7B,sBAAoB,EAAA,uBAAA,EAAA;;;;;;;;;;;;;GAwB/B,EAAA,KAAA;;;;;;KAOU,iBAAiB,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;cC/B/B,iBAAe,EAAA,uBAAA,EAAA;;;;;;;;;;GAoB1B,EAAA,KAAA;;;;;;KAOU,YAAY,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;cCvB1B,kBAAgB,EAAA,uBAAA,EAAA;;;;;;;;;;;;;GAwB3B,EAAA,KAAA;;;;;;KAOU,aAAa,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;cCxC3B,uBAAqB,EAAA;;;GAGhC,EAAA,KAAA;;;;;;KAOU,kBAAkB,EAAE,aAAa;;;;;;;;;;;;;;;;;cChBhC,kBAAgB,EAAA;;;;;;;;;;;;;;;;KAiBjB,aAAa,EAAE,aAAa;;;;;;;;;cCb3B,cAAY,EAAA,uBAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsBvB,EAAA,KAAA;;;;;;KAOU,SAAS,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;;;cC3BvB,iBAAe,EAAA;;;;;;;;;;;;;KAchB,YAAY,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;;;cCd1B,iBAAe,EAAA;;;;;;;;;;;;;;KAehB,YAAY,EAAE,aAAa;;;;;;;;;;cC5B1B,aAAW,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAuFZ,QAAQ,EAAE,aAAa;;;;;;;;;;KCvFvB;;;;;cAgBC,gBAAa,OAAW,UAAQ;;;;;;;;;;;;;;;;;;;;;;;;cCFhC,gBAAc,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAqEf,WAAW,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;;;cCtEzB,kBAAgB,EAAA;;;;;;;;;;;;;;KAejB,aAAa,EAAE,aAAa;;;;;;;;;;;;;cAc3B;WACA;WACC;WACE;WACH;WACJ;WACA;WACH;;;;;;;;;;;;;;cAeO,oBAAoB,eAAe;;;;;;;;;;;;;cC7DnC,gBAAc,EAAA;;;;;;;;;;;KAYf,WAAW,EAAE,aAAa;;;;cAKzB;;;;;cAUA;KASD,yBAAyB;cAExB,mBAAgB,OAAW,aAAW,SAAS;;;;;;;;;;;;cCrC/C,uBAAqB,EAAA;;;;;;;;;;;;;;GAgC9B,EAAA,KAAA;KAEQ,kBAAkB,EAAE,aAAa;;;;;;;;;;;;cClChC,qBAAmB,EAAA;;;;;;;;;;;;;;;GAe9B,EAAA,KAAA;KAEU,gBAAgB,EAAE,aAAa;;;;;;;;cCrB9B,yBAAuB,EAAA;;;;;KAMxB,oBAAoB,EAAE,aAAa;;;;;;;;;;;cAYlC,wBAAsB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAWjC,EAAA,KAAA;KAEU,mBAAmB,EAAE,aAAa;;;;;;;;;;cC/BjC,gBAAc,EAAA;;;;;KAEf,WAAW,EAAE,aAAa;cAEzB,kBAAgB,EAAA;;;;;;;;;GAK3B,EAAA,KAAA;KAEU,aAAa,EAAE,aAAa;;;;;;;;;;;;;;cCL3B,uBAAqB,EAAA;;;;;;;;;GAqB9B,EAAA,KAAA;KAEQ,kBAAkB,EAAE,aAAa;;;;;;;;cC7BhC,kBAAgB,EAAA;;;;;;;;;;;;;GAU3B,EAAA,KAAA;KAEU,aAAa,EAAE,aAAa;;;;;;;;;;;cCX3B,sBAAoB,EAAA;;;;;GAK/B,EAAA,KAAA;KAEU,iBAAiB,EAAE,aAAa;;;;;;cAO/B,gBAAc,EAAA;;;;;;KAEf,WAAW,EAAE,aAAa;;;;;;;;;;;cCbzB,kBAAgB,EAAA;;;;;;;;;GAI3B,EAAA,KAAA;KAEU,aAAa,EAAE,aAAa;;;;;;;;;cAU3B,mBAAiB,EAAA;;;;;;;;;;;;;;;;;;;;;GA2B1B,EAAA,KAAA;KAEQ,cAAc,EAAE,aAAa;;;;;;;;;;;;cC7C5B,qBAAmB,EAAA;;;;;;;;;;;GA0B5B,EAAA,KAAA;KAEQ,gBAAgB,EAAE,aAAa;;;;;;;;cChC9B,qBAAmB,EAAA;;;;;;;;;;GA6B5B,EAAA,KAAA;KAEQ,gBAAgB,EAAE,aAAa;;;;;;;;;cCjC9B;cACA;cACA;cACA;cACA;cACA;cACA;cACA;cAIA;cACA;cACA;cACA;cAGA;;;;;;;;;cCdA,qBAAmB,EAAA;;;;;;;;;;;GA0B5B,EAAA,KAAA;KAEQ,gBAAgB,EAAE,aAAa;;;;;;;;;;cC3B9B,yBAAuB,EAAA;;;;;;;;GAQlC,EAAA,KAAA;KAEU,oBAAoB,EAAE,aAAa;;;;;;;;;;;;cCAlC,8BAA4B,EAAA,uBAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAUvC,EAAA,KAAA;KAEU,yBAAyB,EAAE,aAC9B;;;;;;;;;cC1BI,oBAAiB,MACtB,cAAc,oBACnB,QAAQ;;;;;;;;;;;;;;;;;;KCKC;;EAEV;;EAEA;;;;;;;EAOA;;EAEA;;EAEA;;;;;;;;;;;;;;;;;;KAmBU;;EAEV;;EAEA;;EAEA;;EAEA;;EAEA;;;;;;;;;;;uBClDoB,2BAA2B;WAG7B;EAFlB,YACE,iBACgB;;;;;;uBAaE,8BAA8B;WAGhC,QAAQ,MAAM;EAFhC,YACE,iBACgB,QAAQ,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;cCJrB,wBAAwB;WACV;;;;;;;;;;;;;;;;;;cAmBd,wBAAqB,iBACjB,oBAEd;;;;;;cC1CU,2BAA2B;WACb;;cAGd,2BAAwB,iBACpB,oBAEd;;;;;;;;;;;;;;;;;;;;;;;;;cCaU,2BAA2B;WACb;;;;;;;;;;;;;;;;;;;;;cAsBd,2BAAwB,iBACpB,QACP,MAAM,qBACb;;;;;;cChDU,yBAAyB;WAKlB;WAJO;EAEzB,YACE,iBACgB;;cASP,yBAAsB,iBAClB,oBAEd;;;;cAKU,wBAAwB;WAKjB;WACA;WALO;EAEzB,YACE,iBACgB,iCACA;;cASP,wBAAqB,iBACjB,qBACI,oBAElB;;;;;;;;;;;;;;;;;;;;;;;;cCpBU,wBAAwB;WACV;;;;;;;;;cAUd,wBAAqB,iBACjB,oBAEd;;;;;;;;;;;;;;;;;;;;;cAsBU,2BAA2B;WACb;;;;;;;;;cAUd,2BAAwB,iBACpB,QACP,MAAM,qBACb;;;;;;;;;;;;;;;;;;;;;;;;;;;;cC/CU,+BAA+B;WAKxB,YAAY,MAAM;WAJX;EAEzB,YACE,iBACgB,YAAY,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;cCNzB,gCAAgC;WAIzB,SAAS;WACT;WAJO;EAEzB,YACkB,SAAS,UACT;;;;;;;;cAiBP,gCAA6B,SAC/B,UAAQ,wBAEhB;;;;;;;;;;;;;;;;;;;;;;;;cC3BU,0BAA0B;WACZ;;;;;;;;;cAUd,0BAAuB,iBACnB,oBAEd;;;;;;;;;;;;;;;;;;;;;cAsBU,6BAA6B;WACf;;;;;;;;;cAUd,6BAA0B,iBACtB,QACP,MAAM,qBACb;;;;;;;;;;;;;cC1DU,iBAAc,KAAS,QAAM;;;KCb9B;EACV,WAAW,iBAAiB,MAAM;;cAGvB,6BAA4B;;;cCL5B,uBAAqB,EAAA;;;;;;;;GAQhC,EAAA,KAAA;KAEU,kBAAkB,EAAE,aAAa;cAEhC,oBAAoB;cAUpB,0BAAwB,EAAA;;;;;;GAMnC,EAAA,KAAA;KAEU,uBAAqB,EAAE,aAAa;KAEpC;EACV,YAAY,kBAAkB,mBAAmB;EACjD,gBACE,kBACA,mBACG;EACL,aAAa,kBAAkB,mBAAmB;EAClD,iBACE,kBACA,mBACG;EACL,eAAe,kBAAkB,mBAAmB;EACpD,YAAY,kBAAkB,mBAAmB;;cAetC,yBAAsB,SACzB,oBACP;;;;;;;;;;cCnDU,cAAW,iBAAmB;;;;;;;;;;;;;;;;;;;KCK/B;cAEC,sBAAsB;cAEtB,wBAAwB,SAAS,OAAO;;;;cAgBxC,cAAW,kBAAoB,SAAS;;;;;;;;;cAaxC,mBAAgB;;;;;;;;;;;;;;cAsBhB,mBAAgB,oBAAsB;;;KCxEvC,iBAAiB;KAEjB;EACV,WAAW;EACX,QAAQ,cAAc,QAAQ;;;;cCFnB,2BAA0B;;;KCF3B;KAEA;EACV,QAAQ,iBAAiB,UAAU;EACnC,OAAO,iBAAiB,UAAU;EAClC,OAAO,iBAAiB,UAAU;EAClC,QAAQ,iBAAiB,UAAU;;;;cCJxB,2BAA0B;;;;;;KCC3B,YAAY;;;;KAKZ;EACV,QAAQ,kBAAkB,qBAAqB;EAC/C;EACA,qBAAqB,QAAQ;EAC7B,iBAAiB,QAAQ,cAAc;EACvC,cAAc;;;;;;;KCRJ,gBAAgB,QAAQ,eAAe,QAAQ;;;;KAK/C,cAAc,iBAAiB,QAAQ;;;;KAKvC,gBAAgB,KAAK,QAAQ,QAAQ;;;;KAKrC,cAAc,KAAK,QAAQ;;;;;;KCf3B;EACV,OAAO,QAAQ,cAAc;EAC7B,YAAY,QAAQ;EACpB,aAAa;;;;;;;KCHH;EACV;EACA;EACA;EACA;EACA;;;;;KAMU;EAAe;EAAY;EAAc;;;;;KAKzC;EAAgB;EAAiB;;;;;KAKjC;EACV,OAAO,KAAK,QAAQ,QAAQ;EAC5B,OAAO,sBAAsB,QAAQ;EACrC,OAAO,UAAU,gBAAgB,QAAQ;EACzC,SAAS,sBAAsB;;;;;;;;;;;;;;;cCdpB,aAAU,QACb,YAAU,QACV,cAAY,SACX,WACR,QAAQ;;;;;;;;;;;;cAmBE,WAAQ,cACP,QACJ,YAAU,SACT,WACR,QAAQ;;;;;;;;;;;;;;cC3BE,WAAQ,KACd,KAAG,QACA,cAAY,SACX,WACR,QAAQ;;;;;;;;;;;;cAmBE,SAAM,KACZ,KAAG,QACA,YAAU,SACT,WACR;;;;;;;;;;;;;;;;KC7BS;;cAIC;;cAGA,aAAa,OAAO;;;;;cAYpB,6BAA0B,QAC7B;;;;;;;;;;;;;;;;;;;;;;;;;cCXG;;cAGA;KAED;;EAEV;;EAEA;;EAEA;;EAEA;;KAGU;;EAEV;;EAEA;;EAEA;;;;;;;;cAwBW,sBAAmB,OACvB,6BACN;;;KClDS;EACV;EACA;EACA;EACA;EACA;EACA;EACA;;;;;;cAmCW,yBAAsB,MAC3B,cAAc,sBACnB;;;;;;;;;;KCzDS;KAEA;KAEA;EACV;EACA;EACA;EACA,KAAK;;EAEL;;KAGU;EACV;EACA,SAAS;;;;;;;;cAgDE,aAAU,OAAW,aAAW;;;;KClDjC;EACV;EACA;EACA;EACA,QAAQ;;KAGE;;EAEV;;EAEA,aAAa;;EAEb;;EAEA;;EAEA,eAAe;;EAEf,eAAe;;;;;;;;cAcJ,2BAAwB,OAC5B,kCACN;;;;;;;;;;;;;;;;;;;;;;KCpCS;;EAEV;EACA;;KAGU;;EAEV;;KAGU;EACV;EACA;;;;;;;;;cA0BW,2BAAwB,QAC3B,cAAc,WAAS,SACtB,eACR;;;KCtCS;EACV,OAAO;EACP;EACA;EACA;EACA;;;;;;;;;cAoDW,+BAA4B,OAChC;;;;KCrEG;EACV;EACA;;KAGU;;EAEV,WAAW;;EAEX;;EAEA;;;;;EAKA;;KAGU;EACV;EACA;EACA;EACA,QAAQ;;;;;;cAiEG,wBAAqB,OACzB,wBACN;;;;;;;;;;KC/FS;EACV;EACA;EACA;;EAEA;;;;;cCaW;;cAEA;KAID;EACV,UAAU;EACV;EACA;;EAEA;;EAEA;EACA;;;;;EAKA;;;;;;;;cAyEW,oBAAiB,OACrB,2BACN;;;KC1FS;EACV;EACA;EACA,UAAU;;;;;;;cAsBC,sBAAmB,OACvB,6BACN;;;;cCtCU;;;;;cAMA,WAAW,QAAQ,OAAO;;;;;cAgD1B,cAAW,OAAW;;;;;;;;;;;;;;;KC1DvB;EACV;;EAEA;;EAEA;;EAEA;;;;;;;;cAuBW,0BAAuB,OAC3B;;;;;;;;KC5BG,oBAAoB,kBAAkB;;;;;;;;;;;;;;;;cAiBrC,oBAAiB,cACd,cAAY,cACZ,cAAY,kBACR,kBAAgB,QAC1B;EASiC,0BAAA;IACvC,gBAAgB;QACd,QAAQ,MAAM;EAGoB,uBAAA;IACpC,aAAa;QACX,QAAQ,MAAM;;EAOgB,wBAAA;IAAE,aAAa;QAAY;;;;;;;;EAG3B,wBAAA;IAAE,aAAa;QAAK;;;;;;;;;;cCW3C,uBAAqB,EAAA,QAAA,EAAA,YAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiBd,EAAA,KAAA;KAER,kBAAkB,EAAE,aAAa;;;;;;;;cAShC;cAsBA,sBAAmB,mBACb,UACP;;;;cC3HC,eAAa,EAAA;;;;;;KACd,UAAU,EAAE,aAAa;KAEzB;KAEP;EAAW;EAAc;;;KAGlB,kBAAkB;EAC5B;IAAU,MAAM;IAAQ,QAAQ;;;KAGtB;EACV;EACA;EACA;EACA;EACA,kBAAkB;EAClB,MAAM;;;;;;;;iBASQ,YAAY,OAAO,mBAAmB;;;;cC7BzC,mBAAiB,EAAA;;;GAG5B,EAAA,KAAA;KACU,cAAc,EAAE,aAAa;;cAG5B,iBAAe,EAAA;;;;GAI1B,EAAA,KAAA;KACU,YAAY,EAAE,aAAa;;cAG1B,gBAAc,EAAA;;;;;;;;;;;;KAYf,WAAW,EAAE,aAAa;;cAGzB,oBAAkB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAW7B,EAAA,KAAA;KACU,eAAe,EAAE,aAAa;;;;;;;;;cC3B7B,gCAAgC;;iBAkB7B,gBAAgB,cAAc;cAIjC;;iBAGG,mBAAmB;;iBAKnB,qBAAqB;;;;;;;;;cCxCxB,qBAAmB,EAAA;;;;;;;;GAI9B,EAAA,KAAA;KAEU,gBAAgB,EAAE,aAAa;;;;;;;;;cCJ9B,iBAAe,EAAA;;;;;;;;;;;;;;;;;GAU1B,EAAA,KAAA;KAEU,YAAY,EAAE,aAAa;;;;cChB1B,oBAAkB,EAAA;;;;;KACnB,eAAe,EAAE,aAAa;;;;;;;;cAS7B,gBAAc,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkBzB,EAAA,KAAA;KAEU,WAAW,EAAE,aAAa;;;KCpCjC;EAAW;EAAc;;;;;;;;iBAed,mBAAmB,kBAAkB;;;KCbzC;EACV;EACA;;;iBAIc,iBAAiB,kBAAkB,MAAM;;iBAKzC,mBACd,wBACA,MAAM;;;;;;iBAYQ,kBACd,OAAO,0BACP,kBACC;KAaS;EACV;EACA;;;iBAIc,mBACd,OAAO,0BACP,kBACA,kBACC;;iBAYa,aACd,OAAO,0BACP,2BACA"} |
| {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/domain/schemas/krd/index.ts","../../src/test-utils/fixtures.ts","../../src/ports/logger.ts","../../src/tests/helpers/test-utils.ts","../../src/tests/fixtures/krd/krd.fixtures.ts","../../src/tests/fixtures/krd/metadata.fixtures.ts","../../src/tests/fixtures/krd/event.fixtures.ts","../../src/tests/fixtures/krd/lap.fixtures.ts","../../src/tests/fixtures/krd/record.fixtures.ts","../../src/tests/fixtures/krd/session.fixtures.ts","../../src/tests/fixtures/workout/workout-step.fixtures.ts","../../src/tests/fixtures/workout/workout.fixtures.ts","../../src/tests/fixtures/workout/duration.fixtures.ts","../../src/tests/fixtures/workout/target.fixtures.ts","../../src/protocol/profile-snapshot.ts","../../src/test-utils/profile-snapshot-fixtures.ts","../../src/test-utils/tolerance-constants.ts","../../src/test-utils/round-trip-fixtures.ts"],"mappings":"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"} |
| {"version":3,"file":"index.js","names":[],"sources":["../../src/test-utils/fixtures.ts","../../src/tests/helpers/test-utils.ts","../../src/tests/fixtures/krd/event.fixtures.ts","../../src/tests/fixtures/krd/lap.fixtures.ts","../../src/test-utils/tolerance-constants.ts","../../src/tests/fixtures/krd/metadata.fixtures.ts","../../src/tests/fixtures/krd/record.fixtures.ts","../../src/tests/fixtures/krd/session.fixtures.ts","../../src/tests/fixtures/krd/krd.fixtures.ts","../../src/tests/fixtures/workout/workout-step.fixtures.ts","../../src/tests/fixtures/workout/repetition-block.fixtures.ts","../../src/tests/fixtures/workout/workout.fixtures.ts","../../src/tests/fixtures/workout/duration.fixtures.ts","../../src/tests/fixtures/workout/target.fixtures.ts","../../src/test-utils/profile-snapshot-fixtures.ts","../../src/test-utils/round-trip-fixtures.ts"],"sourcesContent":["/**\n * Test Fixture Helpers\n *\n * Utilities for loading shared test fixtures across packages.\n */\n\nimport { readFileSync } from \"fs\";\nimport { join } from \"path\";\nimport type { KRD } from \"../domain/schemas/krd\";\n\n/**\n * Base path to fixtures directory\n * Points to shared test-fixtures at monorepo root\n * From packages/core/src/test-utils/ or packages/core/dist/test-utils/\n * Goes up 4 levels to reach monorepo root, then into test-fixtures/\n */\nconst FIXTURES_DIR = join(__dirname, \"../../../../test-fixtures\");\n\n/**\n * Load a FIT file fixture as a buffer\n *\n * @param filename - Name of the FIT file (e.g., \"WorkoutIndividualSteps.fit\")\n * @returns Buffer containing the FIT file data\n *\n * @example\n * ```typescript\n * const fitBuffer = loadFitFixture(\"WorkoutIndividualSteps.fit\");\n * const krd = await fitReader.readToKRD(fitBuffer);\n * ```\n */\nexport const loadFitFixture = (filename: string): Uint8Array => {\n const path = join(FIXTURES_DIR, \"fit\", filename);\n return readFileSync(path);\n};\n\n/**\n * Load a KRD file fixture as a parsed object\n *\n * @param filename - Name of the KRD file (e.g., \"WorkoutIndividualSteps.krd\")\n * @returns Parsed KRD object\n *\n * @example\n * ```typescript\n * const krd = loadKrdFixture(\"WorkoutIndividualSteps.krd\");\n * expect(krd.version).toBe(\"1.0\");\n * ```\n */\nexport const loadKrdFixture = (filename: string): KRD => {\n const path = join(FIXTURES_DIR, \"krd\", filename);\n const json = readFileSync(path, \"utf-8\");\n return JSON.parse(json) as KRD;\n};\n\n/**\n * Load a KRD file fixture as raw JSON string\n *\n * @param filename - Name of the KRD file (e.g., \"WorkoutIndividualSteps.krd\")\n * @returns Raw JSON string\n *\n * @example\n * ```typescript\n * const jsonString = loadKrdFixtureRaw(\"WorkoutIndividualSteps.krd\");\n * const krd = JSON.parse(jsonString);\n * ```\n */\nexport const loadKrdFixtureRaw = (filename: string): string => {\n const path = join(FIXTURES_DIR, \"krd\", filename);\n return readFileSync(path, \"utf-8\");\n};\n\n/**\n * Load a TCX file fixture as a string\n *\n * @param filename - Name of the TCX file (e.g., \"WorkoutHeartRateTargets.tcx\")\n * @returns TCX XML string\n *\n * @example\n * ```typescript\n * const tcxString = loadTcxFixture(\"WorkoutHeartRateTargets.tcx\");\n * const krd = await tcxReader.readToKRD(tcxString);\n * ```\n */\nexport const loadTcxFixture = (filename: string): string => {\n const path = join(FIXTURES_DIR, \"tcx\", filename);\n return readFileSync(path, \"utf-8\");\n};\n\n/**\n * Load a ZWO file fixture as a string\n *\n * @param filename - Name of the ZWO file (e.g., \"WorkoutIndividualSteps.zwo\")\n * @returns ZWO XML string\n *\n * @example\n * ```typescript\n * const zwoString = loadZwoFixture(\"WorkoutIndividualSteps.zwo\");\n * const krd = await zwoReader.readToKRD(zwoString);\n * ```\n */\nexport const loadZwoFixture = (filename: string): string => {\n const path = join(FIXTURES_DIR, \"zwo\", filename);\n return readFileSync(path, \"utf-8\");\n};\n\n/**\n * Get the full path to a fixture file\n *\n * @param type - Type of fixture (\"fit\", \"krd\", \"tcx\", or \"zwo\")\n * @param filename - Name of the file\n * @returns Full path to the fixture file\n *\n * @example\n * ```typescript\n * const path = getFixturePath(\"fit\", \"WorkoutIndividualSteps.fit\");\n * const buffer = readFileSync(path);\n * ```\n */\nexport const getFixturePath = (\n type: \"fit\" | \"krd\" | \"tcx\" | \"zwo\",\n filename: string\n): string => {\n return join(FIXTURES_DIR, type, filename);\n};\n\n/**\n * Available fixture names (without extension)\n */\nexport const FIXTURE_NAMES = {\n INDIVIDUAL_STEPS: \"WorkoutIndividualSteps\",\n REPEAT_STEPS: \"WorkoutRepeatSteps\",\n CUSTOM_TARGET_VALUES: \"WorkoutCustomTargetValues\",\n REPEAT_GREATER_THAN: \"WorkoutRepeatGreaterThanStep\",\n} as const;\n\n/**\n * Load a fixture pair (FIT + KRD) for round-trip testing\n *\n * @param baseName - Base name without extension (e.g., \"WorkoutIndividualSteps\")\n * @returns Object with both FIT buffer and KRD object\n *\n * @example\n * ```typescript\n * const { fit, krd } = loadFixturePair(\"WorkoutIndividualSteps\");\n * const converted = await fitReader.readToKRD(fit);\n * expect(converted).toEqual(krd);\n * ```\n */\nexport const loadFixturePair = (\n baseName: string\n): { fit: Uint8Array; krd: KRD } => {\n return {\n fit: loadFitFixture(`${baseName}.fit`),\n krd: loadKrdFixture(`${baseName}.krd`),\n };\n};\n","import type { Logger } from \"../../ports/logger\";\n\nexport const createMockLogger = (): Logger => ({\n debug: (...args: unknown[]) => {\n if (process.env.DEBUG_LOGS) console.log(\"[DEBUG]\", ...args);\n },\n info: (...args: unknown[]) => {\n if (process.env.DEBUG_LOGS) console.log(\"[INFO]\", ...args);\n },\n warn: (...args: unknown[]) => {\n if (process.env.DEBUG_LOGS) console.log(\"[WARN]\", ...args);\n },\n error: (...args: unknown[]) => {\n if (process.env.DEBUG_LOGS) console.error(\"[ERROR]\", ...args);\n },\n});\n","import { faker } from \"@faker-js/faker\";\nimport { Factory } from \"rosie\";\n\nimport type { KRDEvent } from \"../../../domain/schemas/krd\";\n\nexport const buildKRDEvent = new Factory<KRDEvent>()\n .attr(\"timestamp\", () => faker.date.recent().toISOString())\n .attr(\"eventType\", () =>\n faker.helpers.arrayElement([\n \"event_start\",\n \"event_stop\",\n \"event_pause\",\n \"event_resume\",\n \"event_lap\",\n \"event_marker\",\n \"event_timer\",\n ] as const)\n )\n .attr(\"eventGroup\", () => faker.number.int({ max: 10, min: 0 }))\n .attr(\"data\", () => faker.number.int({ max: 255, min: 0 }));\n","import { faker } from \"@faker-js/faker\";\nimport { Factory } from \"rosie\";\n\nimport type { KRDLap } from \"../../../domain/schemas/krd\";\n\nexport const buildKRDLap = new Factory<KRDLap>()\n .attr(\"startTime\", () => faker.date.recent().toISOString())\n .attr(\"totalElapsedTime\", () => faker.number.int({ max: 1800, min: 30 }))\n .attr(\"totalDistance\", () => faker.number.int({ max: 10000, min: 100 }))\n .attr(\"avgHeartRate\", () => faker.number.int({ max: 200, min: 60 }))\n .attr(\"maxHeartRate\", () => faker.number.int({ max: 220, min: 100 }))\n .attr(\"avgCadence\", () => faker.number.int({ max: 120, min: 60 }))\n .attr(\"avgPower\", () => faker.number.int({ max: 400, min: 100 }));\n","/**\n * Round-trip tolerance constants.\n *\n * These values mirror the documented tolerances from CLAUDE.md:\n * time ±1s, power ±1W or ±1%FTP, HR ±1bpm, cadence ±1rpm.\n *\n * Distance and pace tolerances are derived from the same domain\n * conventions used by the round-trip validator.\n *\n * Centralised so test files can reference named values instead of\n * sprinkling magic numbers across assertions.\n */\n\nexport const TOLERANCE_TIME_SEC = 1 as const;\nexport const TOLERANCE_POWER_WATTS = 1 as const;\nexport const TOLERANCE_HR_BPM = 1 as const;\nexport const TOLERANCE_CADENCE_RPM = 1 as const;\nexport const TOLERANCE_DISTANCE_M = 1 as const;\nexport const TOLERANCE_PACE_SEC_PER_M = 0.01 as const;\n\n// === Buffer / arbitrary numeric literals used in tests ===\nexport const SAMPLE_BUFFER_LENGTH = 3 as const;\nexport const SAMPLE_BUFFER_BYTES = [1, 2, 3] as const;\n\n// === Length-unit converter samples (yards <-> meters) ===\nexport const LENGTH_UNIT_YARDS_25_AS_METERS = 22.86 as const;\nexport const LENGTH_UNIT_YARDS_50_AS_METERS = 45.72 as const;\nexport const LENGTH_UNIT_YARDS_27_5_AS_METERS = 25.146 as const;\nexport const LENGTH_DECIMAL_METERS = 33.33 as const;\n\n// === Pool length samples ===\nexport const POOL_LENGTH_25 = 25 as const;\nexport const POOL_LENGTH_50 = 50 as const;\n\n// === Pace-tolerance edge values (used in tolerance-checker test) ===\nexport const PACE_EXPECTED_3_5 = 3.5 as const;\nexport const PACE_ACTUAL_3_52 = 3.52 as const;\nexport const PACE_DEVIATION_0_02 = 0.02 as const;\nexport const PACE_DEVIATION_PRECISION = 10 as const;\nexport const PACE_TOLERANCE_DEFAULT = 0.01 as const;\n\n// === Faker numeric-string lengths ===\nexport const FAKER_SERIAL_NUMBER_DIGITS = 10 as const;\n\n// === Target generator boundary widths ===\nexport const TARGET_RANGE_WIDTH_10 = 10 as const;\nexport const TARGET_PACE_RANGE_GAP_0_5 = 0.5 as const;\n\n// === Profile snapshot constants ===\nexport const PROFILE_STALE_SNAPSHOT_DAYS = 7 as const;\nexport const PROFILE_SAMPLE_LTHR_RUNNING = 170 as const;\nexport const PROFILE_OVERSIZED_PAYLOAD_REPEAT = 9000 as const;\n\n// === Workout step notes max length (KRD spec) ===\nexport const WORKOUT_STEP_NOTES_MAX_LENGTH = 256 as const;\n","import { faker } from \"@faker-js/faker\";\nimport { Factory } from \"rosie\";\n\nimport type { KRDMetadata } from \"../../../domain/schemas/krd\";\nimport { FAKER_SERIAL_NUMBER_DIGITS } from \"../../../test-utils/tolerance-constants\";\n\nexport const buildKRDMetadata = new Factory<KRDMetadata>()\n .attr(\"created\", () => faker.date.recent().toISOString())\n .attr(\"manufacturer\", () =>\n faker.helpers.arrayElement([\"garmin\", \"wahoo\", \"polar\", \"suunto\"])\n )\n .attr(\"product\", () =>\n faker.helpers.arrayElement([\"fenix7\", \"edge530\", \"forerunner945\", \"elemnt\"])\n )\n .attr(\"serialNumber\", () => faker.string.numeric(FAKER_SERIAL_NUMBER_DIGITS))\n .attr(\"sport\", () =>\n faker.helpers.arrayElement([\"running\", \"cycling\", \"swimming\"])\n )\n .attr(\"subSport\", () =>\n faker.helpers.arrayElement([\"trail\", \"road\", \"track\", \"indoor\"])\n );\n","import { faker } from \"@faker-js/faker\";\nimport { Factory } from \"rosie\";\n\nimport type { KRDRecord } from \"../../../domain/schemas/krd\";\n\nexport const buildKRDRecord = new Factory<KRDRecord>()\n .attr(\"timestamp\", () => faker.date.recent().toISOString())\n .attr(\"position\", () => ({\n lat: faker.location.latitude(),\n lon: faker.location.longitude(),\n }))\n .attr(\"altitude\", () => faker.number.float({ max: 3000, min: 0 }))\n .attr(\"heartRate\", () => faker.number.int({ max: 200, min: 60 }))\n .attr(\"cadence\", () => faker.number.int({ max: 120, min: 60 }))\n .attr(\"power\", () => faker.number.int({ max: 500, min: 0 }))\n .attr(\"speed\", () =>\n faker.number.float({ fractionDigits: 2, max: 15, min: 0 })\n )\n .attr(\"distance\", () => faker.number.int({ max: 50000, min: 0 }));\n","import { faker } from \"@faker-js/faker\";\nimport { Factory } from \"rosie\";\n\nimport type { KRDSession } from \"../../../domain/schemas/krd\";\n\nexport const buildKRDSession = new Factory<KRDSession>()\n .attr(\"startTime\", () => faker.date.recent().toISOString())\n .attr(\"totalElapsedTime\", () => faker.number.int({ max: 7200, min: 60 }))\n .attr(\"totalTimerTime\", () => faker.number.int({ max: 7200, min: 60 }))\n .attr(\"totalDistance\", () => faker.number.int({ max: 50000, min: 1000 }))\n .attr(\"sport\", () =>\n faker.helpers.arrayElement([\"running\", \"cycling\", \"swimming\"])\n )\n .attr(\"subSport\", () =>\n faker.helpers.arrayElement([\"trail\", \"road\", \"track\", \"indoor\"])\n )\n .attr(\"avgHeartRate\", () => faker.number.int({ max: 200, min: 60 }))\n .attr(\"maxHeartRate\", () => faker.number.int({ max: 220, min: 100 }))\n .attr(\"avgCadence\", () => faker.number.int({ max: 120, min: 60 }))\n .attr(\"avgPower\", () => faker.number.int({ max: 400, min: 100 }))\n .attr(\"totalCalories\", () => faker.number.int({ max: 2000, min: 100 }));\n","import { faker } from \"@faker-js/faker\";\nimport { Factory } from \"rosie\";\n\nimport type { KRD } from \"../../../domain/schemas/krd\";\nimport { buildKRDEvent } from \"./event.fixtures\";\nimport { buildKRDLap } from \"./lap.fixtures\";\nimport { buildKRDMetadata } from \"./metadata.fixtures\";\nimport { buildKRDRecord } from \"./record.fixtures\";\nimport { buildKRDSession } from \"./session.fixtures\";\n\nexport const buildKRD = new Factory<KRD>()\n .attr(\"version\", () => \"1.0\")\n .attr(\"type\", () =>\n faker.helpers.arrayElement([\n \"structured_workout\",\n \"recorded_activity\",\n \"course\",\n ] as const)\n )\n .attr(\"metadata\", () => buildKRDMetadata.build())\n .attr(\"sessions\", () => [buildKRDSession.build()])\n .attr(\"laps\", () => [buildKRDLap.build(), buildKRDLap.build()])\n .attr(\"records\", () => [\n buildKRDRecord.build(),\n buildKRDRecord.build(),\n buildKRDRecord.build(),\n ])\n .attr(\"events\", () => [buildKRDEvent.build()])\n .attr(\"extensions\", () => ({\n fit: {\n developerFields: [],\n },\n }));\n","import { faker } from \"@faker-js/faker\";\nimport { Factory } from \"rosie\";\n\nimport type { WorkoutStep } from \"../../../domain/schemas/workout\";\nimport { WORKOUT_STEP_NOTES_MAX_LENGTH } from \"../../../test-utils/tolerance-constants\";\n\nexport const buildWorkoutStep = new Factory<WorkoutStep>()\n .attr(\"stepIndex\", () => faker.number.int({ max: 50, min: 0 }))\n .attr(\"name\", () => faker.lorem.words({ max: 3, min: 1 }))\n .attr(\"durationType\", () =>\n faker.helpers.arrayElement([\"time\", \"distance\", \"open\"] as const)\n )\n .attr(\"duration\", [\"durationType\"], (durationType: string) => {\n if (durationType === \"time\") {\n return {\n type: \"time\" as const,\n seconds: faker.number.int({ max: 3600, min: 30 }),\n };\n } else if (durationType === \"distance\") {\n return {\n type: \"distance\" as const,\n meters: faker.number.int({ max: 10000, min: 100 }),\n };\n } else {\n return { type: \"open\" as const };\n }\n })\n .attr(\"targetType\", () =>\n faker.helpers.arrayElement([\n \"power\",\n \"heart_rate\",\n \"cadence\",\n \"pace\",\n \"open\",\n ] as const)\n )\n .attr(\"target\", [\"targetType\"], (targetType: string) => {\n if (targetType === \"power\") {\n const unit = faker.helpers.arrayElement([\n \"watts\",\n \"percent_ftp\",\n \"zone\",\n \"range\",\n ] as const);\n if (unit === \"watts\") {\n return {\n type: \"power\" as const,\n value: {\n unit: \"watts\" as const,\n value: faker.number.int({ max: 400, min: 100 }),\n },\n };\n } else if (unit === \"percent_ftp\") {\n return {\n type: \"power\" as const,\n value: {\n unit: \"percent_ftp\" as const,\n value: faker.number.int({ max: 150, min: 50 }),\n },\n };\n } else if (unit === \"zone\") {\n return {\n type: \"power\" as const,\n value: {\n unit: \"zone\" as const,\n value: faker.number.int({ max: 7, min: 1 }),\n },\n };\n } else {\n return {\n type: \"power\" as const,\n value: {\n unit: \"range\" as const,\n min: faker.number.int({ max: 200, min: 100 }),\n max: faker.number.int({ max: 400, min: 250 }),\n },\n };\n }\n } else if (targetType === \"heart_rate\") {\n const unit = faker.helpers.arrayElement([\n \"bpm\",\n \"zone\",\n \"percent_max\",\n \"range\",\n ] as const);\n if (unit === \"bpm\") {\n return {\n type: \"heart_rate\" as const,\n value: {\n unit: \"bpm\" as const,\n value: faker.number.int({ max: 200, min: 60 }),\n },\n };\n } else if (unit === \"zone\") {\n return {\n type: \"heart_rate\" as const,\n value: {\n unit: \"zone\" as const,\n value: faker.number.int({ max: 5, min: 1 }),\n },\n };\n } else if (unit === \"percent_max\") {\n return {\n type: \"heart_rate\" as const,\n value: {\n unit: \"percent_max\" as const,\n value: faker.number.int({ max: 100, min: 50 }),\n },\n };\n } else {\n return {\n type: \"heart_rate\" as const,\n value: {\n unit: \"range\" as const,\n min: faker.number.int({ max: 140, min: 100 }),\n max: faker.number.int({ max: 180, min: 150 }),\n },\n };\n }\n } else if (targetType === \"cadence\") {\n const unit = faker.helpers.arrayElement([\"rpm\", \"range\"] as const);\n if (unit === \"rpm\") {\n return {\n type: \"cadence\" as const,\n value: {\n unit: \"rpm\" as const,\n value: faker.number.int({ max: 120, min: 60 }),\n },\n };\n } else {\n return {\n type: \"cadence\" as const,\n value: {\n unit: \"range\" as const,\n min: faker.number.int({ max: 80, min: 60 }),\n max: faker.number.int({ max: 110, min: 90 }),\n },\n };\n }\n } else if (targetType === \"pace\") {\n const unit = faker.helpers.arrayElement([\n \"mps\",\n \"zone\",\n \"range\",\n ] as const);\n if (unit === \"mps\") {\n return {\n type: \"pace\" as const,\n value: {\n unit: \"mps\" as const,\n value: faker.number.float({ fractionDigits: 2, max: 6, min: 2 }),\n },\n };\n } else if (unit === \"zone\") {\n return {\n type: \"pace\" as const,\n value: {\n unit: \"zone\" as const,\n value: faker.number.int({ max: 5, min: 1 }),\n },\n };\n } else {\n return {\n type: \"pace\" as const,\n value: {\n unit: \"range\" as const,\n min: faker.number.float({ fractionDigits: 2, max: 4, min: 2 }),\n max: faker.number.float({ fractionDigits: 2, max: 6, min: 4.5 }),\n },\n };\n }\n } else {\n return { type: \"open\" as const };\n }\n })\n .attr(\"intensity\", () =>\n faker.helpers.arrayElement([\n \"warmup\",\n \"active\",\n \"cooldown\",\n \"rest\",\n \"recovery\",\n \"interval\",\n \"other\",\n ] as const)\n )\n .attr(\"notes\", () =>\n faker.lorem\n .sentence({ max: 20, min: 3 })\n .slice(0, WORKOUT_STEP_NOTES_MAX_LENGTH)\n );\n","import { faker } from \"@faker-js/faker\";\nimport { Factory } from \"rosie\";\n\nimport type { RepetitionBlock } from \"../../../domain/schemas/workout\";\nimport { buildWorkoutStep } from \"./workout-step.fixtures\";\n\nexport const buildRepetitionBlock = new Factory<RepetitionBlock>()\n .attr(\"repeatCount\", () => faker.number.int({ max: 10, min: 2 }))\n .attr(\"steps\", () => [buildWorkoutStep.build(), buildWorkoutStep.build()]);\n","import { faker } from \"@faker-js/faker\";\nimport { Factory } from \"rosie\";\n\nimport type { Sport } from \"../../../domain/schemas/sport\";\nimport type { SubSport } from \"../../../domain/schemas/sub-sport\";\nimport type { Workout } from \"../../../domain/schemas/workout\";\nimport { buildRepetitionBlock } from \"./repetition-block.fixtures\";\nimport { buildWorkoutStep } from \"./workout-step.fixtures\";\n\nconst SUB_SPORTS: Partial<Record<Sport, SubSport[]>> = {\n running: [\"trail\", \"street\", \"track\", \"treadmill\"],\n cycling: [\"road\", \"mountain\", \"gravel_cycling\", \"indoor_cycling\"],\n swimming: [\"lap_swimming\", \"open_water\"],\n generic: [\"generic\"],\n};\n\nexport const buildWorkout = new Factory<Workout>()\n .attr(\"name\", () => faker.lorem.words({ max: 5, min: 1 }))\n .attr(\"sport\", () =>\n faker.helpers.arrayElement([\"running\", \"cycling\", \"swimming\"] as const)\n )\n .attr(\"subSport\", [\"sport\"], (sport: Sport) =>\n faker.helpers.arrayElement(SUB_SPORTS[sport] ?? [\"generic\"])\n )\n .attr(\"steps\", () => [\n buildWorkoutStep.build(),\n buildRepetitionBlock.build(),\n buildWorkoutStep.build(),\n ]);\n","import { faker } from \"@faker-js/faker\";\nimport { Factory } from \"rosie\";\n\nimport type { Duration } from \"../../../domain/schemas/duration\";\n\nconst DURATION_TYPES = [\n \"time\",\n \"distance\",\n \"heart_rate_less_than\",\n \"repeat_until_heart_rate_greater_than\",\n \"calories\",\n \"power_less_than\",\n \"power_greater_than\",\n \"repeat_until_time\",\n \"repeat_until_distance\",\n \"repeat_until_calories\",\n \"repeat_until_heart_rate_less_than\",\n \"repeat_until_power_less_than\",\n \"repeat_until_power_greater_than\",\n \"open\",\n] as const;\n\nconst repeatFrom = () => faker.number.int({ max: 10, min: 0 });\nconst seconds = () => faker.number.int({ max: 3600, min: 30 });\nconst meters = () => faker.number.int({ max: 10000, min: 100 });\nconst bpm = () => faker.number.int({ max: 200, min: 60 });\nconst watts = () => faker.number.int({ max: 400, min: 100 });\nconst calories = () => faker.number.int({ max: 1000, min: 50 });\n\nconst DURATION_BUILDERS: Record<string, () => Duration> = {\n time: () => ({ type: \"time\", seconds: seconds() }),\n distance: () => ({ type: \"distance\", meters: meters() }),\n heart_rate_less_than: () => ({ type: \"heart_rate_less_than\", bpm: bpm() }),\n repeat_until_heart_rate_greater_than: () => ({\n type: \"repeat_until_heart_rate_greater_than\",\n bpm: bpm(),\n repeatFrom: repeatFrom(),\n }),\n calories: () => ({ type: \"calories\", calories: calories() }),\n power_less_than: () => ({ type: \"power_less_than\", watts: watts() }),\n power_greater_than: () => ({ type: \"power_greater_than\", watts: watts() }),\n repeat_until_time: () => ({\n type: \"repeat_until_time\",\n seconds: seconds(),\n repeatFrom: repeatFrom(),\n }),\n repeat_until_distance: () => ({\n type: \"repeat_until_distance\",\n meters: meters(),\n repeatFrom: repeatFrom(),\n }),\n repeat_until_calories: () => ({\n type: \"repeat_until_calories\",\n calories: calories(),\n repeatFrom: repeatFrom(),\n }),\n repeat_until_heart_rate_less_than: () => ({\n type: \"repeat_until_heart_rate_less_than\",\n bpm: bpm(),\n repeatFrom: repeatFrom(),\n }),\n repeat_until_power_less_than: () => ({\n type: \"repeat_until_power_less_than\",\n watts: watts(),\n repeatFrom: repeatFrom(),\n }),\n repeat_until_power_greater_than: () => ({\n type: \"repeat_until_power_greater_than\",\n watts: watts(),\n repeatFrom: repeatFrom(),\n }),\n open: () => ({ type: \"open\" }),\n};\n\nexport const buildDuration = new Factory<Duration>()\n .attr(\"type\", () => faker.helpers.arrayElement([...DURATION_TYPES]))\n .after((duration) => {\n const builder = DURATION_BUILDERS[duration.type]!;\n return Object.assign(duration, builder());\n });\n","import { faker } from \"@faker-js/faker\";\nimport { Factory } from \"rosie\";\n\nimport type { Target } from \"../../../domain/schemas/target\";\n\nconst buildPowerValue = () => {\n const unit = faker.helpers.arrayElement([\n \"watts\",\n \"percent_ftp\",\n \"zone\",\n \"range\",\n ] as const);\n if (unit === \"zone\")\n return { unit, value: faker.number.int({ max: 7, min: 1 }) };\n if (unit === \"range\") {\n return {\n unit,\n min: faker.number.int({ max: 200, min: 100 }),\n max: faker.number.int({ max: 400, min: 250 }),\n };\n }\n if (unit === \"percent_ftp\")\n return { unit, value: faker.number.int({ max: 150, min: 50 }) };\n return { unit, value: faker.number.int({ max: 400, min: 100 }) };\n};\n\nconst buildHeartRateValue = () => {\n const unit = faker.helpers.arrayElement([\n \"bpm\",\n \"zone\",\n \"percent_max\",\n \"range\",\n ] as const);\n if (unit === \"zone\")\n return { unit, value: faker.number.int({ max: 5, min: 1 }) };\n if (unit === \"range\") {\n return {\n unit,\n min: faker.number.int({ max: 140, min: 100 }),\n max: faker.number.int({ max: 180, min: 150 }),\n };\n }\n if (unit === \"percent_max\")\n return { unit, value: faker.number.int({ max: 100, min: 50 }) };\n return { unit, value: faker.number.int({ max: 200, min: 60 }) };\n};\n\nconst buildCadenceValue = () => {\n const unit = faker.helpers.arrayElement([\"rpm\", \"range\"] as const);\n if (unit === \"range\") {\n return {\n unit,\n min: faker.number.int({ max: 80, min: 60 }),\n max: faker.number.int({ max: 110, min: 90 }),\n };\n }\n return { unit, value: faker.number.int({ max: 120, min: 60 }) };\n};\n\nconst buildPaceValue = () => {\n const unit = faker.helpers.arrayElement([\"mps\", \"zone\", \"range\"] as const);\n if (unit === \"zone\")\n return { unit, value: faker.number.int({ max: 5, min: 1 }) };\n if (unit === \"range\") {\n return {\n unit,\n min: faker.number.float({ fractionDigits: 2, max: 4, min: 2 }),\n max: faker.number.float({ fractionDigits: 2, max: 6, min: 4.5 }),\n };\n }\n return {\n unit,\n value: faker.number.float({ fractionDigits: 2, max: 6, min: 2 }),\n };\n};\n\nconst buildStrokeTypeValue = () => ({\n unit: \"swim_stroke\" as const,\n value: faker.number.int({ max: 5, min: 0 }),\n});\n\nconst TARGET_TYPES = [\n \"power\",\n \"heart_rate\",\n \"cadence\",\n \"pace\",\n \"stroke_type\",\n \"open\",\n] as const;\n\nconst TARGET_BUILDERS: Record<string, () => Target> = {\n power: () => ({ type: \"power\", value: buildPowerValue() }),\n heart_rate: () => ({ type: \"heart_rate\", value: buildHeartRateValue() }),\n cadence: () => ({ type: \"cadence\", value: buildCadenceValue() }),\n pace: () => ({ type: \"pace\", value: buildPaceValue() }),\n stroke_type: () => ({ type: \"stroke_type\", value: buildStrokeTypeValue() }),\n open: () => ({ type: \"open\" }),\n};\n\nexport const buildTarget = new Factory<Target>()\n .attr(\"type\", () => faker.helpers.arrayElement([...TARGET_TYPES]))\n .after((target) => {\n const builder = TARGET_BUILDERS[target.type]!;\n return Object.assign(target, builder());\n });\n","/**\n * Profile Snapshot Fixtures\n *\n * Shared positive/negative fixture set consumed by:\n * - The SPA's Zod parser tests (in `@kaiord/workout-spa-editor`).\n * - Each bridge's plain-JS structural validator parity test.\n *\n * Both validators MUST agree: positive fixtures parse with deep-equal\n * output; negative fixtures reject without throwing and without mutating\n * `Object.prototype`.\n */\n\nimport type { ProfileSnapshot } from \"../protocol/profile-snapshot\";\n\nconst ISO = \"2026-05-01T08:30:00.000Z\";\n\nexport const baselineSnapshot: ProfileSnapshot = {\n schemaVersion: 1,\n profile: { name: \"Pablo\", bodyWeight: 72 },\n activeSport: \"cycling\",\n thresholds: {\n cycling: { ftp: 270 },\n running: { thresholdPaceSecPerKm: 255, lthr: 168 },\n },\n heartRate: { max: 188, lthr: 168 },\n generatedAt: ISO,\n};\n\nexport const minimalSnapshot: ProfileSnapshot = {\n schemaVersion: 1,\n profile: { name: \"Min\" },\n thresholds: {},\n heartRate: {},\n generatedAt: ISO,\n};\n\nexport const partialZoneSnapshot: ProfileSnapshot = {\n schemaVersion: 1,\n profile: { name: \"Partial\" },\n activeSport: \"running\",\n thresholds: {\n running: { lthr: 170 },\n },\n heartRate: { max: 195 },\n generatedAt: ISO,\n};\n\nexport const positiveSnapshotFixtures: readonly ProfileSnapshot[] = [\n baselineSnapshot,\n minimalSnapshot,\n partialZoneSnapshot,\n];\n\nconst longName = \"x\".repeat(100);\nconst oversizedName = \"x\".repeat(9000);\n\nexport type NegativeSnapshotFixture = {\n readonly name: string;\n readonly value: unknown;\n readonly expectedError: RegExp;\n};\n\nconst buildPrototypePolluted = (): unknown => {\n const obj = JSON.parse(\n `{\"__proto__\":{\"isAdmin\":true},\"schemaVersion\":1,\"profile\":{\"name\":\"P\"},\"thresholds\":{},\"heartRate\":{},\"generatedAt\":\"${ISO}\"}`\n ) as Record<string, unknown>;\n return obj;\n};\n\nconst buildNestedPolluted = (): unknown => {\n const obj = JSON.parse(\n `{\"schemaVersion\":1,\"profile\":{\"__proto__\":{\"isAdmin\":true},\"name\":\"P\"},\"thresholds\":{},\"heartRate\":{},\"generatedAt\":\"${ISO}\"}`\n ) as Record<string, unknown>;\n return obj;\n};\n\nexport const negativeSnapshotFixtures: readonly NegativeSnapshotFixture[] = [\n {\n name: \"missing schemaVersion\",\n value: { profile: { name: \"x\" }, generatedAt: ISO },\n expectedError: /schemaVersion/i,\n },\n {\n name: \"unsupported schemaVersion\",\n value: { schemaVersion: 99, profile: { name: \"x\" }, generatedAt: ISO },\n expectedError: /schemaVersion/i,\n },\n {\n name: \"missing profile.name\",\n value: { schemaVersion: 1, profile: {}, generatedAt: ISO },\n expectedError: /name/i,\n },\n {\n name: \"empty profile.name\",\n value: { schemaVersion: 1, profile: { name: \"\" }, generatedAt: ISO },\n expectedError: /name/i,\n },\n {\n name: \"profile.name too long\",\n value: {\n schemaVersion: 1,\n profile: { name: `${longName}x` },\n generatedAt: ISO,\n },\n expectedError: /name/i,\n },\n {\n name: \"missing generatedAt\",\n value: { schemaVersion: 1, profile: { name: \"x\" } },\n expectedError: /generatedAt/i,\n },\n {\n name: \"non-positive bodyWeight\",\n value: {\n schemaVersion: 1,\n profile: { name: \"x\", bodyWeight: 0 },\n generatedAt: ISO,\n },\n expectedError: /bodyWeight|positive/i,\n },\n {\n name: \"unknown activeSport\",\n value: {\n schemaVersion: 1,\n profile: { name: \"x\" },\n activeSport: \"rowing\",\n generatedAt: ISO,\n },\n expectedError: /activeSport|enum/i,\n },\n {\n name: \"oversized payload\",\n value: {\n schemaVersion: 1,\n profile: { name: oversizedName },\n generatedAt: ISO,\n },\n expectedError: /too large/i,\n },\n {\n name: \"top-level prototype-pollution\",\n value: buildPrototypePolluted(),\n expectedError: /(invalid|payload|__proto__|prototype)/i,\n },\n {\n name: \"nested prototype-pollution\",\n value: buildNestedPolluted(),\n expectedError: /(invalid|payload|__proto__|prototype)/i,\n },\n];\n\nexport const snapshotFixtures = {\n positive: positiveSnapshotFixtures,\n negative: negativeSnapshotFixtures,\n} as const;\n","/**\n * Round-trip test fixtures.\n *\n * Shared sample buffers and named domain constants used by\n * round-trip validation tests. Centralising these values keeps\n * `expect(...)` assertions self-documenting and removes inline\n * magic numbers from the test suite.\n *\n * Tolerance numeric values themselves live in `./tolerance-constants`.\n */\n\n/**\n * Returns a fresh `Uint8Array([1, 2, 3, 4])` per call.\n *\n * Returning a new buffer per invocation prevents cross-test mutation\n * if a future test ever writes to the underlying bytes.\n */\nexport const createFitBufferSample = (): Uint8Array =>\n new Uint8Array([1, 2, 3, 4]);\n\n// Power assertion fixtures (watts)\nexport const POWER_EXPECTED = 250 as const;\nexport const POWER_ACTUAL = 255 as const;\nexport const POWER_ACTUAL_HIGH = 260 as const;\n\n// Heart rate assertion fixtures (bpm)\nexport const HR_EXPECTED = 150 as const;\nexport const HR_ACTUAL = 155 as const;\nexport const HR_ACTUAL_HIGH = 160 as const;\n\n// Cadence assertion fixtures (rpm)\nexport const CADENCE_EXPECTED = 85 as const;\nexport const CADENCE_ACTUAL = 90 as const;\n\n// Session-level time / distance fixtures\nexport const TIME_EXPECTED_SEC = 3600 as const;\nexport const TIME_ACTUAL_SEC = 3602 as const;\nexport const DISTANCE_EXPECTED_M = 10000 as const;\nexport const DISTANCE_ACTUAL_M = 10005 as const;\n\n// Lap-level time / distance fixtures\nexport const LAP_TIME_EXPECTED_SEC = 600 as const;\nexport const LAP_TIME_ACTUAL_SEC = 605 as const;\nexport const LAP_DISTANCE_EXPECTED_M = 1000 as const;\nexport const LAP_DISTANCE_ACTUAL_M = 1010 as const;\n\n// Record-level fixtures\nexport const RECORD_DISTANCE_EXPECTED_M = 100 as const;\nexport const RECORD_DISTANCE_ACTUAL_M = 105 as const;\nexport const RECORD_SPEED_EXPECTED_MPS = 2.78 as const;\nexport const RECORD_SPEED_ACTUAL_MPS = 2.85 as const;\n\n// Violation count assertions\nexport const VIOLATION_COUNT_FULL_SESSION = 5 as const;\nexport const VIOLATION_COUNT_LAP = 3 as const;\nexport const VIOLATION_COUNT_RECORD = 5 as const;\n\n// Deviation values fed to ToleranceChecker mocks\nexport const DEVIATION_POWER_5W = 5 as const;\nexport const DEVIATION_POWER_10W = 10 as const;\nexport const DEVIATION_HR_5BPM = 5 as const;\nexport const DEVIATION_HR_10BPM = 10 as const;\nexport const DEVIATION_CADENCE_5RPM = 5 as const;\nexport const DEVIATION_DISTANCE_5M = 5 as const;\nexport const DEVIATION_DISTANCE_10M = 10 as const;\nexport const DEVIATION_TIME_2SEC = 2 as const;\nexport const DEVIATION_TIME_5SEC = 5 as const;\nexport const DEVIATION_PACE = 0.07 as const;\n"],"mappings":"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"} |
+21
| MIT License | ||
| Copyright (c) 2025 Pablo Albaladejo | ||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the “Software”), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
| The above copyright notice and this permission notice shall be included in | ||
| all copies or substantial portions of the Software. | ||
| THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| THE SOFTWARE. |
+1074
-1086
@@ -1,4 +0,3 @@ | ||
| import { z } from 'zod'; | ||
| import * as rosie from 'rosie'; | ||
| import { z } from "zod"; | ||
| //#region src/domain/schemas/krd/index.d.ts | ||
| /** | ||
@@ -35,355 +34,357 @@ * Zod schema for the complete KRD (Kaiord Representation Definition) format. | ||
| declare const krdSchema: z.ZodObject<{ | ||
| version: z.ZodString; | ||
| type: z.ZodEnum<{ | ||
| structured_workout: "structured_workout"; | ||
| recorded_activity: "recorded_activity"; | ||
| course: "course"; | ||
| sleep_record: "sleep_record"; | ||
| weight_measurement: "weight_measurement"; | ||
| hrv_summary: "hrv_summary"; | ||
| daily_wellness: "daily_wellness"; | ||
| body_composition: "body_composition"; | ||
| stress_episode: "stress_episode"; | ||
| version: z.ZodString; | ||
| type: z.ZodEnum<{ | ||
| body_composition: "body_composition"; | ||
| course: "course"; | ||
| daily_wellness: "daily_wellness"; | ||
| hrv_summary: "hrv_summary"; | ||
| recorded_activity: "recorded_activity"; | ||
| sleep_record: "sleep_record"; | ||
| stress_episode: "stress_episode"; | ||
| structured_workout: "structured_workout"; | ||
| weight_measurement: "weight_measurement"; | ||
| }>; | ||
| metadata: z.ZodObject<{ | ||
| created: z.ZodISODateTime; | ||
| manufacturer: z.ZodOptional<z.ZodString>; | ||
| product: z.ZodOptional<z.ZodString>; | ||
| serialNumber: z.ZodOptional<z.ZodString>; | ||
| sport: z.ZodOptional<z.ZodString>; | ||
| subSport: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>; | ||
| sessions: z.ZodOptional<z.ZodArray<z.ZodObject<{ | ||
| startTime: z.ZodISODateTime; | ||
| totalElapsedTime: z.ZodNumber; | ||
| totalTimerTime: z.ZodOptional<z.ZodNumber>; | ||
| totalDistance: z.ZodOptional<z.ZodNumber>; | ||
| sport: z.ZodString; | ||
| subSport: z.ZodOptional<z.ZodString>; | ||
| avgHeartRate: z.ZodOptional<z.ZodNumber>; | ||
| maxHeartRate: z.ZodOptional<z.ZodNumber>; | ||
| avgCadence: z.ZodOptional<z.ZodNumber>; | ||
| maxCadence: z.ZodOptional<z.ZodNumber>; | ||
| avgPower: z.ZodOptional<z.ZodNumber>; | ||
| maxPower: z.ZodOptional<z.ZodNumber>; | ||
| normalizedPower: z.ZodOptional<z.ZodNumber>; | ||
| trainingStressScore: z.ZodOptional<z.ZodNumber>; | ||
| intensityFactor: z.ZodOptional<z.ZodNumber>; | ||
| totalCalories: z.ZodOptional<z.ZodNumber>; | ||
| totalAscent: z.ZodOptional<z.ZodNumber>; | ||
| totalDescent: z.ZodOptional<z.ZodNumber>; | ||
| avgSpeed: z.ZodOptional<z.ZodNumber>; | ||
| maxSpeed: z.ZodOptional<z.ZodNumber>; | ||
| }, z.core.$strip>>>; | ||
| laps: z.ZodOptional<z.ZodArray<z.ZodObject<{ | ||
| startTime: z.ZodISODateTime; | ||
| totalElapsedTime: z.ZodNumber; | ||
| totalTimerTime: z.ZodOptional<z.ZodNumber>; | ||
| totalDistance: z.ZodOptional<z.ZodNumber>; | ||
| avgHeartRate: z.ZodOptional<z.ZodNumber>; | ||
| maxHeartRate: z.ZodOptional<z.ZodNumber>; | ||
| avgCadence: z.ZodOptional<z.ZodNumber>; | ||
| maxCadence: z.ZodOptional<z.ZodNumber>; | ||
| avgPower: z.ZodOptional<z.ZodNumber>; | ||
| maxPower: z.ZodOptional<z.ZodNumber>; | ||
| normalizedPower: z.ZodOptional<z.ZodNumber>; | ||
| avgSpeed: z.ZodOptional<z.ZodNumber>; | ||
| maxSpeed: z.ZodOptional<z.ZodNumber>; | ||
| totalAscent: z.ZodOptional<z.ZodNumber>; | ||
| totalDescent: z.ZodOptional<z.ZodNumber>; | ||
| totalCalories: z.ZodOptional<z.ZodNumber>; | ||
| trigger: z.ZodOptional<z.ZodEnum<{ | ||
| distance: "distance"; | ||
| fitness_equipment: "fitness_equipment"; | ||
| manual: "manual"; | ||
| position: "position"; | ||
| session_end: "session_end"; | ||
| time: "time"; | ||
| }>>; | ||
| sport: z.ZodOptional<z.ZodEnum<{ | ||
| alpine_skiing: "alpine_skiing"; | ||
| american_football: "american_football"; | ||
| archery: "archery"; | ||
| baseball: "baseball"; | ||
| basketball: "basketball"; | ||
| boating: "boating"; | ||
| boxing: "boxing"; | ||
| canoeing: "canoeing"; | ||
| cricket: "cricket"; | ||
| cross_country_skiing: "cross_country_skiing"; | ||
| cycling: "cycling"; | ||
| dance: "dance"; | ||
| disc_golf: "disc_golf"; | ||
| diving: "diving"; | ||
| driving: "driving"; | ||
| e_biking: "e_biking"; | ||
| fishing: "fishing"; | ||
| fitness_equipment: "fitness_equipment"; | ||
| floor_climbing: "floor_climbing"; | ||
| flying: "flying"; | ||
| generic: "generic"; | ||
| geocaching: "geocaching"; | ||
| golf: "golf"; | ||
| grinding: "grinding"; | ||
| hang_gliding: "hang_gliding"; | ||
| hiit: "hiit"; | ||
| hiking: "hiking"; | ||
| hockey: "hockey"; | ||
| horseback_riding: "horseback_riding"; | ||
| hunting: "hunting"; | ||
| ice_skating: "ice_skating"; | ||
| inline_skating: "inline_skating"; | ||
| jump_rope: "jump_rope"; | ||
| jumpmaster: "jumpmaster"; | ||
| kayaking: "kayaking"; | ||
| kitesurfing: "kitesurfing"; | ||
| lacrosse: "lacrosse"; | ||
| meditation: "meditation"; | ||
| mixed_martial_arts: "mixed_martial_arts"; | ||
| mobility: "mobility"; | ||
| motor_sports: "motor_sports"; | ||
| motorcycling: "motorcycling"; | ||
| mountaineering: "mountaineering"; | ||
| multisport: "multisport"; | ||
| paddling: "paddling"; | ||
| para_sport: "para_sport"; | ||
| pool_apnea: "pool_apnea"; | ||
| racket: "racket"; | ||
| rafting: "rafting"; | ||
| rock_climbing: "rock_climbing"; | ||
| rowing: "rowing"; | ||
| rugby: "rugby"; | ||
| running: "running"; | ||
| sailing: "sailing"; | ||
| shooting: "shooting"; | ||
| sky_diving: "sky_diving"; | ||
| snorkeling: "snorkeling"; | ||
| snowboarding: "snowboarding"; | ||
| snowmobiling: "snowmobiling"; | ||
| snowshoeing: "snowshoeing"; | ||
| soccer: "soccer"; | ||
| stand_up_paddleboarding: "stand_up_paddleboarding"; | ||
| surfing: "surfing"; | ||
| swimming: "swimming"; | ||
| tactical: "tactical"; | ||
| team_sport: "team_sport"; | ||
| tennis: "tennis"; | ||
| training: "training"; | ||
| transition: "transition"; | ||
| video_gaming: "video_gaming"; | ||
| volleyball: "volleyball"; | ||
| wakeboarding: "wakeboarding"; | ||
| wakesurfing: "wakesurfing"; | ||
| walking: "walking"; | ||
| water_skiing: "water_skiing"; | ||
| water_sport: "water_sport"; | ||
| water_tubing: "water_tubing"; | ||
| wheelchair_push_run: "wheelchair_push_run"; | ||
| wheelchair_push_walk: "wheelchair_push_walk"; | ||
| windsurfing: "windsurfing"; | ||
| winter_sport: "winter_sport"; | ||
| }>>; | ||
| subSport: z.ZodOptional<z.ZodEnum<{ | ||
| all: "all"; | ||
| apnea_diving: "apnea_diving"; | ||
| apnea_hunting: "apnea_hunting"; | ||
| atv: "atv"; | ||
| backcountry: "backcountry"; | ||
| bike_to_run_transition: "bike_to_run_transition"; | ||
| bmx: "bmx"; | ||
| cardio_training: "cardio_training"; | ||
| casual_walking: "casual_walking"; | ||
| challenge: "challenge"; | ||
| commuting: "commuting"; | ||
| cyclocross: "cyclocross"; | ||
| downhill: "downhill"; | ||
| e_bike_fitness: "e_bike_fitness"; | ||
| e_bike_mountain: "e_bike_mountain"; | ||
| elliptical: "elliptical"; | ||
| exercise: "exercise"; | ||
| flexibility_training: "flexibility_training"; | ||
| gauge_diving: "gauge_diving"; | ||
| generic: "generic"; | ||
| gravel_cycling: "gravel_cycling"; | ||
| hand_cycling: "hand_cycling"; | ||
| indoor_cycling: "indoor_cycling"; | ||
| indoor_rowing: "indoor_rowing"; | ||
| indoor_running: "indoor_running"; | ||
| indoor_skiing: "indoor_skiing"; | ||
| indoor_walking: "indoor_walking"; | ||
| lap_swimming: "lap_swimming"; | ||
| map: "map"; | ||
| match: "match"; | ||
| mixed_surface: "mixed_surface"; | ||
| motocross: "motocross"; | ||
| mountain: "mountain"; | ||
| multi_gas_diving: "multi_gas_diving"; | ||
| navigate: "navigate"; | ||
| obstacle: "obstacle"; | ||
| open_water: "open_water"; | ||
| pilates: "pilates"; | ||
| rc_drone: "rc_drone"; | ||
| recumbent: "recumbent"; | ||
| resort: "resort"; | ||
| road: "road"; | ||
| run_to_bike_transition: "run_to_bike_transition"; | ||
| single_gas_diving: "single_gas_diving"; | ||
| skate_skiing: "skate_skiing"; | ||
| speed_walking: "speed_walking"; | ||
| spin: "spin"; | ||
| stair_climbing: "stair_climbing"; | ||
| street: "street"; | ||
| strength_training: "strength_training"; | ||
| swim_to_bike_transition: "swim_to_bike_transition"; | ||
| track: "track"; | ||
| track_cycling: "track_cycling"; | ||
| track_me: "track_me"; | ||
| trail: "trail"; | ||
| treadmill: "treadmill"; | ||
| virtual_activity: "virtual_activity"; | ||
| warm_up: "warm_up"; | ||
| whitewater: "whitewater"; | ||
| wingsuit: "wingsuit"; | ||
| yoga: "yoga"; | ||
| }>>; | ||
| workoutStepIndex: z.ZodOptional<z.ZodNumber>; | ||
| numLengths: z.ZodOptional<z.ZodNumber>; | ||
| swimStroke: z.ZodOptional<z.ZodEnum<{ | ||
| backstroke: "backstroke"; | ||
| breaststroke: "breaststroke"; | ||
| butterfly: "butterfly"; | ||
| drill: "drill"; | ||
| freestyle: "freestyle"; | ||
| im: "im"; | ||
| mixed: "mixed"; | ||
| }>>; | ||
| }, z.core.$strip>>>; | ||
| records: z.ZodOptional<z.ZodArray<z.ZodObject<{ | ||
| timestamp: z.ZodISODateTime; | ||
| position: z.ZodOptional<z.ZodObject<{ | ||
| lat: z.ZodNumber; | ||
| lon: z.ZodNumber; | ||
| }, z.core.$strip>>; | ||
| altitude: z.ZodOptional<z.ZodNumber>; | ||
| heartRate: z.ZodOptional<z.ZodNumber>; | ||
| cadence: z.ZodOptional<z.ZodNumber>; | ||
| power: z.ZodOptional<z.ZodNumber>; | ||
| speed: z.ZodOptional<z.ZodNumber>; | ||
| distance: z.ZodOptional<z.ZodNumber>; | ||
| temperature: z.ZodOptional<z.ZodNumber>; | ||
| verticalOscillation: z.ZodOptional<z.ZodNumber>; | ||
| stanceTime: z.ZodOptional<z.ZodNumber>; | ||
| stepLength: z.ZodOptional<z.ZodNumber>; | ||
| }, z.core.$strip>>>; | ||
| events: z.ZodOptional<z.ZodArray<z.ZodObject<{ | ||
| timestamp: z.ZodISODateTime; | ||
| eventType: z.ZodEnum<{ | ||
| event_activity_start: "event_activity_start"; | ||
| event_lap: "event_lap"; | ||
| event_marker: "event_marker"; | ||
| event_pause: "event_pause"; | ||
| event_resume: "event_resume"; | ||
| event_session_start: "event_session_start"; | ||
| event_start: "event_start"; | ||
| event_stop: "event_stop"; | ||
| event_timer: "event_timer"; | ||
| event_workout_step_change: "event_workout_step_change"; | ||
| }>; | ||
| metadata: z.ZodObject<{ | ||
| created: z.ZodISODateTime; | ||
| manufacturer: z.ZodOptional<z.ZodString>; | ||
| product: z.ZodOptional<z.ZodString>; | ||
| serialNumber: z.ZodOptional<z.ZodString>; | ||
| sport: z.ZodOptional<z.ZodString>; | ||
| subSport: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>; | ||
| sessions: z.ZodOptional<z.ZodArray<z.ZodObject<{ | ||
| eventGroup: z.ZodOptional<z.ZodNumber>; | ||
| data: z.ZodOptional<z.ZodNumber>; | ||
| message: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>>>; | ||
| extensions: z.ZodOptional<z.ZodObject<{ | ||
| structured_workout: z.ZodOptional<z.ZodUnknown>; | ||
| fit: z.ZodOptional<z.ZodUnknown>; | ||
| course: z.ZodOptional<z.ZodUnknown>; | ||
| course_points: z.ZodOptional<z.ZodUnknown>; | ||
| health: z.ZodOptional<z.ZodObject<{ | ||
| sleep: z.ZodOptional<z.ZodObject<{ | ||
| kind: z.ZodLiteral<"sleep">; | ||
| version: z.ZodString; | ||
| startTime: z.ZodISODateTime; | ||
| totalElapsedTime: z.ZodNumber; | ||
| totalTimerTime: z.ZodOptional<z.ZodNumber>; | ||
| totalDistance: z.ZodOptional<z.ZodNumber>; | ||
| sport: z.ZodString; | ||
| subSport: z.ZodOptional<z.ZodString>; | ||
| avgHeartRate: z.ZodOptional<z.ZodNumber>; | ||
| maxHeartRate: z.ZodOptional<z.ZodNumber>; | ||
| avgCadence: z.ZodOptional<z.ZodNumber>; | ||
| maxCadence: z.ZodOptional<z.ZodNumber>; | ||
| avgPower: z.ZodOptional<z.ZodNumber>; | ||
| maxPower: z.ZodOptional<z.ZodNumber>; | ||
| normalizedPower: z.ZodOptional<z.ZodNumber>; | ||
| trainingStressScore: z.ZodOptional<z.ZodNumber>; | ||
| intensityFactor: z.ZodOptional<z.ZodNumber>; | ||
| totalCalories: z.ZodOptional<z.ZodNumber>; | ||
| totalAscent: z.ZodOptional<z.ZodNumber>; | ||
| totalDescent: z.ZodOptional<z.ZodNumber>; | ||
| avgSpeed: z.ZodOptional<z.ZodNumber>; | ||
| maxSpeed: z.ZodOptional<z.ZodNumber>; | ||
| }, z.core.$strip>>>; | ||
| laps: z.ZodOptional<z.ZodArray<z.ZodObject<{ | ||
| startTime: z.ZodISODateTime; | ||
| totalElapsedTime: z.ZodNumber; | ||
| totalTimerTime: z.ZodOptional<z.ZodNumber>; | ||
| totalDistance: z.ZodOptional<z.ZodNumber>; | ||
| avgHeartRate: z.ZodOptional<z.ZodNumber>; | ||
| maxHeartRate: z.ZodOptional<z.ZodNumber>; | ||
| avgCadence: z.ZodOptional<z.ZodNumber>; | ||
| maxCadence: z.ZodOptional<z.ZodNumber>; | ||
| avgPower: z.ZodOptional<z.ZodNumber>; | ||
| maxPower: z.ZodOptional<z.ZodNumber>; | ||
| normalizedPower: z.ZodOptional<z.ZodNumber>; | ||
| avgSpeed: z.ZodOptional<z.ZodNumber>; | ||
| maxSpeed: z.ZodOptional<z.ZodNumber>; | ||
| totalAscent: z.ZodOptional<z.ZodNumber>; | ||
| totalDescent: z.ZodOptional<z.ZodNumber>; | ||
| totalCalories: z.ZodOptional<z.ZodNumber>; | ||
| trigger: z.ZodOptional<z.ZodEnum<{ | ||
| time: "time"; | ||
| fitness_equipment: "fitness_equipment"; | ||
| manual: "manual"; | ||
| distance: "distance"; | ||
| position: "position"; | ||
| session_end: "session_end"; | ||
| }>>; | ||
| sport: z.ZodOptional<z.ZodEnum<{ | ||
| generic: "generic"; | ||
| running: "running"; | ||
| cycling: "cycling"; | ||
| transition: "transition"; | ||
| fitness_equipment: "fitness_equipment"; | ||
| swimming: "swimming"; | ||
| basketball: "basketball"; | ||
| soccer: "soccer"; | ||
| tennis: "tennis"; | ||
| american_football: "american_football"; | ||
| training: "training"; | ||
| walking: "walking"; | ||
| cross_country_skiing: "cross_country_skiing"; | ||
| alpine_skiing: "alpine_skiing"; | ||
| snowboarding: "snowboarding"; | ||
| rowing: "rowing"; | ||
| mountaineering: "mountaineering"; | ||
| hiking: "hiking"; | ||
| multisport: "multisport"; | ||
| paddling: "paddling"; | ||
| flying: "flying"; | ||
| e_biking: "e_biking"; | ||
| motorcycling: "motorcycling"; | ||
| boating: "boating"; | ||
| driving: "driving"; | ||
| golf: "golf"; | ||
| hang_gliding: "hang_gliding"; | ||
| horseback_riding: "horseback_riding"; | ||
| hunting: "hunting"; | ||
| fishing: "fishing"; | ||
| inline_skating: "inline_skating"; | ||
| rock_climbing: "rock_climbing"; | ||
| sailing: "sailing"; | ||
| ice_skating: "ice_skating"; | ||
| sky_diving: "sky_diving"; | ||
| snowshoeing: "snowshoeing"; | ||
| snowmobiling: "snowmobiling"; | ||
| stand_up_paddleboarding: "stand_up_paddleboarding"; | ||
| surfing: "surfing"; | ||
| wakeboarding: "wakeboarding"; | ||
| water_skiing: "water_skiing"; | ||
| kayaking: "kayaking"; | ||
| rafting: "rafting"; | ||
| windsurfing: "windsurfing"; | ||
| kitesurfing: "kitesurfing"; | ||
| tactical: "tactical"; | ||
| jumpmaster: "jumpmaster"; | ||
| boxing: "boxing"; | ||
| floor_climbing: "floor_climbing"; | ||
| baseball: "baseball"; | ||
| diving: "diving"; | ||
| shooting: "shooting"; | ||
| winter_sport: "winter_sport"; | ||
| grinding: "grinding"; | ||
| hiit: "hiit"; | ||
| video_gaming: "video_gaming"; | ||
| racket: "racket"; | ||
| wheelchair_push_walk: "wheelchair_push_walk"; | ||
| wheelchair_push_run: "wheelchair_push_run"; | ||
| meditation: "meditation"; | ||
| para_sport: "para_sport"; | ||
| disc_golf: "disc_golf"; | ||
| team_sport: "team_sport"; | ||
| cricket: "cricket"; | ||
| rugby: "rugby"; | ||
| hockey: "hockey"; | ||
| lacrosse: "lacrosse"; | ||
| volleyball: "volleyball"; | ||
| water_tubing: "water_tubing"; | ||
| wakesurfing: "wakesurfing"; | ||
| water_sport: "water_sport"; | ||
| archery: "archery"; | ||
| mixed_martial_arts: "mixed_martial_arts"; | ||
| motor_sports: "motor_sports"; | ||
| snorkeling: "snorkeling"; | ||
| dance: "dance"; | ||
| jump_rope: "jump_rope"; | ||
| pool_apnea: "pool_apnea"; | ||
| mobility: "mobility"; | ||
| geocaching: "geocaching"; | ||
| canoeing: "canoeing"; | ||
| }>>; | ||
| subSport: z.ZodOptional<z.ZodEnum<{ | ||
| match: "match"; | ||
| map: "map"; | ||
| generic: "generic"; | ||
| treadmill: "treadmill"; | ||
| street: "street"; | ||
| trail: "trail"; | ||
| track: "track"; | ||
| spin: "spin"; | ||
| indoor_cycling: "indoor_cycling"; | ||
| road: "road"; | ||
| mountain: "mountain"; | ||
| downhill: "downhill"; | ||
| recumbent: "recumbent"; | ||
| cyclocross: "cyclocross"; | ||
| hand_cycling: "hand_cycling"; | ||
| track_cycling: "track_cycling"; | ||
| indoor_rowing: "indoor_rowing"; | ||
| elliptical: "elliptical"; | ||
| stair_climbing: "stair_climbing"; | ||
| lap_swimming: "lap_swimming"; | ||
| open_water: "open_water"; | ||
| flexibility_training: "flexibility_training"; | ||
| strength_training: "strength_training"; | ||
| warm_up: "warm_up"; | ||
| exercise: "exercise"; | ||
| challenge: "challenge"; | ||
| indoor_skiing: "indoor_skiing"; | ||
| cardio_training: "cardio_training"; | ||
| indoor_walking: "indoor_walking"; | ||
| e_bike_fitness: "e_bike_fitness"; | ||
| bmx: "bmx"; | ||
| casual_walking: "casual_walking"; | ||
| speed_walking: "speed_walking"; | ||
| bike_to_run_transition: "bike_to_run_transition"; | ||
| run_to_bike_transition: "run_to_bike_transition"; | ||
| swim_to_bike_transition: "swim_to_bike_transition"; | ||
| atv: "atv"; | ||
| motocross: "motocross"; | ||
| backcountry: "backcountry"; | ||
| resort: "resort"; | ||
| rc_drone: "rc_drone"; | ||
| wingsuit: "wingsuit"; | ||
| whitewater: "whitewater"; | ||
| skate_skiing: "skate_skiing"; | ||
| yoga: "yoga"; | ||
| pilates: "pilates"; | ||
| indoor_running: "indoor_running"; | ||
| gravel_cycling: "gravel_cycling"; | ||
| e_bike_mountain: "e_bike_mountain"; | ||
| commuting: "commuting"; | ||
| mixed_surface: "mixed_surface"; | ||
| navigate: "navigate"; | ||
| track_me: "track_me"; | ||
| single_gas_diving: "single_gas_diving"; | ||
| multi_gas_diving: "multi_gas_diving"; | ||
| gauge_diving: "gauge_diving"; | ||
| apnea_diving: "apnea_diving"; | ||
| apnea_hunting: "apnea_hunting"; | ||
| virtual_activity: "virtual_activity"; | ||
| obstacle: "obstacle"; | ||
| all: "all"; | ||
| }>>; | ||
| workoutStepIndex: z.ZodOptional<z.ZodNumber>; | ||
| numLengths: z.ZodOptional<z.ZodNumber>; | ||
| swimStroke: z.ZodOptional<z.ZodEnum<{ | ||
| mixed: "mixed"; | ||
| freestyle: "freestyle"; | ||
| backstroke: "backstroke"; | ||
| breaststroke: "breaststroke"; | ||
| butterfly: "butterfly"; | ||
| drill: "drill"; | ||
| im: "im"; | ||
| }>>; | ||
| }, z.core.$strip>>>; | ||
| records: z.ZodOptional<z.ZodArray<z.ZodObject<{ | ||
| timestamp: z.ZodISODateTime; | ||
| position: z.ZodOptional<z.ZodObject<{ | ||
| lat: z.ZodNumber; | ||
| lon: z.ZodNumber; | ||
| endTime: z.ZodISODateTime; | ||
| totalDurationSeconds: z.ZodNumber; | ||
| stages: z.ZodArray<z.ZodObject<{ | ||
| stage: z.ZodEnum<{ | ||
| awake: "awake"; | ||
| deep: "deep"; | ||
| light: "light"; | ||
| rem: "rem"; | ||
| }>; | ||
| startTime: z.ZodISODateTime; | ||
| durationSeconds: z.ZodNumber; | ||
| }, z.core.$strip>>; | ||
| altitude: z.ZodOptional<z.ZodNumber>; | ||
| heartRate: z.ZodOptional<z.ZodNumber>; | ||
| cadence: z.ZodOptional<z.ZodNumber>; | ||
| power: z.ZodOptional<z.ZodNumber>; | ||
| speed: z.ZodOptional<z.ZodNumber>; | ||
| distance: z.ZodOptional<z.ZodNumber>; | ||
| temperature: z.ZodOptional<z.ZodNumber>; | ||
| verticalOscillation: z.ZodOptional<z.ZodNumber>; | ||
| stanceTime: z.ZodOptional<z.ZodNumber>; | ||
| stepLength: z.ZodOptional<z.ZodNumber>; | ||
| }, z.core.$strip>>>; | ||
| events: z.ZodOptional<z.ZodArray<z.ZodObject<{ | ||
| timestamp: z.ZodISODateTime; | ||
| eventType: z.ZodEnum<{ | ||
| event_start: "event_start"; | ||
| event_stop: "event_stop"; | ||
| event_pause: "event_pause"; | ||
| event_resume: "event_resume"; | ||
| event_lap: "event_lap"; | ||
| event_marker: "event_marker"; | ||
| event_timer: "event_timer"; | ||
| event_workout_step_change: "event_workout_step_change"; | ||
| event_session_start: "event_session_start"; | ||
| event_activity_start: "event_activity_start"; | ||
| score: z.ZodOptional<z.ZodNumber>; | ||
| restingHeartRate: z.ZodOptional<z.ZodNumber>; | ||
| kaiordRecordId: z.ZodOptional<z.ZodString>; | ||
| sourceBridgeId: z.ZodOptional<z.ZodString>; | ||
| externalId: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>>; | ||
| weight: z.ZodOptional<z.ZodObject<{ | ||
| kind: z.ZodLiteral<"weight">; | ||
| version: z.ZodString; | ||
| measuredAt: z.ZodISODateTime; | ||
| weightKilograms: z.ZodNumber; | ||
| kaiordRecordId: z.ZodOptional<z.ZodString>; | ||
| sourceBridgeId: z.ZodOptional<z.ZodString>; | ||
| externalId: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>>; | ||
| hrv: z.ZodOptional<z.ZodObject<{ | ||
| kind: z.ZodLiteral<"hrv">; | ||
| version: z.ZodString; | ||
| measuredAt: z.ZodISODateTime; | ||
| rMSSD: z.ZodNumber; | ||
| measurementWindow: z.ZodEnum<{ | ||
| overnight: "overnight"; | ||
| spot: "spot"; | ||
| }>; | ||
| eventGroup: z.ZodOptional<z.ZodNumber>; | ||
| data: z.ZodOptional<z.ZodNumber>; | ||
| message: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>>>; | ||
| extensions: z.ZodOptional<z.ZodObject<{ | ||
| structured_workout: z.ZodOptional<z.ZodUnknown>; | ||
| fit: z.ZodOptional<z.ZodUnknown>; | ||
| course: z.ZodOptional<z.ZodUnknown>; | ||
| course_points: z.ZodOptional<z.ZodUnknown>; | ||
| health: z.ZodOptional<z.ZodObject<{ | ||
| sleep: z.ZodOptional<z.ZodObject<{ | ||
| kind: z.ZodLiteral<"sleep">; | ||
| version: z.ZodString; | ||
| startTime: z.ZodISODateTime; | ||
| endTime: z.ZodISODateTime; | ||
| totalDurationSeconds: z.ZodNumber; | ||
| stages: z.ZodArray<z.ZodObject<{ | ||
| stage: z.ZodEnum<{ | ||
| awake: "awake"; | ||
| light: "light"; | ||
| deep: "deep"; | ||
| rem: "rem"; | ||
| }>; | ||
| startTime: z.ZodISODateTime; | ||
| durationSeconds: z.ZodNumber; | ||
| }, z.core.$strip>>; | ||
| score: z.ZodOptional<z.ZodNumber>; | ||
| restingHeartRate: z.ZodOptional<z.ZodNumber>; | ||
| kaiordRecordId: z.ZodOptional<z.ZodString>; | ||
| sourceBridgeId: z.ZodOptional<z.ZodString>; | ||
| externalId: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>>; | ||
| weight: z.ZodOptional<z.ZodObject<{ | ||
| kind: z.ZodLiteral<"weight">; | ||
| version: z.ZodString; | ||
| measuredAt: z.ZodISODateTime; | ||
| weightKilograms: z.ZodNumber; | ||
| kaiordRecordId: z.ZodOptional<z.ZodString>; | ||
| sourceBridgeId: z.ZodOptional<z.ZodString>; | ||
| externalId: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>>; | ||
| hrv: z.ZodOptional<z.ZodObject<{ | ||
| kind: z.ZodLiteral<"hrv">; | ||
| version: z.ZodString; | ||
| measuredAt: z.ZodISODateTime; | ||
| rMSSD: z.ZodNumber; | ||
| measurementWindow: z.ZodEnum<{ | ||
| overnight: "overnight"; | ||
| spot: "spot"; | ||
| }>; | ||
| score: z.ZodOptional<z.ZodNumber>; | ||
| kaiordRecordId: z.ZodOptional<z.ZodString>; | ||
| sourceBridgeId: z.ZodOptional<z.ZodString>; | ||
| externalId: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>>; | ||
| daily: z.ZodOptional<z.ZodObject<{ | ||
| kind: z.ZodLiteral<"daily">; | ||
| version: z.ZodString; | ||
| date: z.ZodISODate; | ||
| steps: z.ZodNumber; | ||
| activeCalories: z.ZodNumber; | ||
| restingCalories: z.ZodNumber; | ||
| intensityMinutes: z.ZodObject<{ | ||
| moderate: z.ZodNumber; | ||
| vigorous: z.ZodNumber; | ||
| }, z.core.$strip>; | ||
| floorsClimbed: z.ZodOptional<z.ZodNumber>; | ||
| kaiordRecordId: z.ZodOptional<z.ZodString>; | ||
| sourceBridgeId: z.ZodOptional<z.ZodString>; | ||
| externalId: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>>; | ||
| bodyComposition: z.ZodOptional<z.ZodObject<{ | ||
| kind: z.ZodLiteral<"bodyComposition">; | ||
| version: z.ZodString; | ||
| measuredAt: z.ZodISODateTime; | ||
| bodyFatPercent: z.ZodOptional<z.ZodNumber>; | ||
| leanMassKilograms: z.ZodOptional<z.ZodNumber>; | ||
| boneMassKilograms: z.ZodOptional<z.ZodNumber>; | ||
| bodyWaterPercent: z.ZodOptional<z.ZodNumber>; | ||
| bmi: z.ZodOptional<z.ZodNumber>; | ||
| kaiordRecordId: z.ZodOptional<z.ZodString>; | ||
| sourceBridgeId: z.ZodOptional<z.ZodString>; | ||
| externalId: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>>; | ||
| stress: z.ZodOptional<z.ZodObject<{ | ||
| kind: z.ZodLiteral<"stress">; | ||
| version: z.ZodString; | ||
| startTime: z.ZodISODateTime; | ||
| endTime: z.ZodISODateTime; | ||
| averageLevel: z.ZodNumber; | ||
| peakLevel: z.ZodNumber; | ||
| kaiordRecordId: z.ZodOptional<z.ZodString>; | ||
| sourceBridgeId: z.ZodOptional<z.ZodString>; | ||
| externalId: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>>; | ||
| }, z.core.$catchall<z.ZodUnknown>>>; | ||
| score: z.ZodOptional<z.ZodNumber>; | ||
| kaiordRecordId: z.ZodOptional<z.ZodString>; | ||
| sourceBridgeId: z.ZodOptional<z.ZodString>; | ||
| externalId: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>>; | ||
| daily: z.ZodOptional<z.ZodObject<{ | ||
| kind: z.ZodLiteral<"daily">; | ||
| version: z.ZodString; | ||
| date: z.ZodISODate; | ||
| steps: z.ZodNumber; | ||
| activeCalories: z.ZodNumber; | ||
| restingCalories: z.ZodNumber; | ||
| intensityMinutes: z.ZodObject<{ | ||
| moderate: z.ZodNumber; | ||
| vigorous: z.ZodNumber; | ||
| }, z.core.$strip>; | ||
| floorsClimbed: z.ZodOptional<z.ZodNumber>; | ||
| kaiordRecordId: z.ZodOptional<z.ZodString>; | ||
| sourceBridgeId: z.ZodOptional<z.ZodString>; | ||
| externalId: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>>; | ||
| bodyComposition: z.ZodOptional<z.ZodObject<{ | ||
| kind: z.ZodLiteral<"bodyComposition">; | ||
| version: z.ZodString; | ||
| measuredAt: z.ZodISODateTime; | ||
| bodyFatPercent: z.ZodOptional<z.ZodNumber>; | ||
| leanMassKilograms: z.ZodOptional<z.ZodNumber>; | ||
| boneMassKilograms: z.ZodOptional<z.ZodNumber>; | ||
| bodyWaterPercent: z.ZodOptional<z.ZodNumber>; | ||
| bmi: z.ZodOptional<z.ZodNumber>; | ||
| visceralFatRating: z.ZodOptional<z.ZodNumber>; | ||
| basalMetabolicRateKcal: z.ZodOptional<z.ZodNumber>; | ||
| kaiordRecordId: z.ZodOptional<z.ZodString>; | ||
| sourceBridgeId: z.ZodOptional<z.ZodString>; | ||
| externalId: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>>; | ||
| stress: z.ZodOptional<z.ZodObject<{ | ||
| kind: z.ZodLiteral<"stress">; | ||
| version: z.ZodString; | ||
| startTime: z.ZodISODateTime; | ||
| endTime: z.ZodISODateTime; | ||
| averageLevel: z.ZodNumber; | ||
| peakLevel: z.ZodNumber; | ||
| kaiordRecordId: z.ZodOptional<z.ZodString>; | ||
| sourceBridgeId: z.ZodOptional<z.ZodString>; | ||
| externalId: z.ZodOptional<z.ZodString>; | ||
| }, z.core.$strip>>; | ||
| }, z.core.$catchall<z.ZodUnknown>>>; | ||
| }, z.core.$catchall<z.ZodUnknown>>>; | ||
| }, z.core.$strip>; | ||
@@ -396,10 +397,5 @@ /** | ||
| type KRD = z.infer<typeof krdSchema>; | ||
| //#endregion | ||
| //#region src/test-utils/fixtures.d.ts | ||
| /** | ||
| * Test Fixture Helpers | ||
| * | ||
| * Utilities for loading shared test fixtures across packages. | ||
| */ | ||
| /** | ||
| * Load a FIT file fixture as a buffer | ||
@@ -487,6 +483,6 @@ * | ||
| declare const FIXTURE_NAMES: { | ||
| readonly INDIVIDUAL_STEPS: "WorkoutIndividualSteps"; | ||
| readonly REPEAT_STEPS: "WorkoutRepeatSteps"; | ||
| readonly CUSTOM_TARGET_VALUES: "WorkoutCustomTargetValues"; | ||
| readonly REPEAT_GREATER_THAN: "WorkoutRepeatGreaterThanStep"; | ||
| readonly INDIVIDUAL_STEPS: "WorkoutIndividualSteps"; | ||
| readonly REPEAT_STEPS: "WorkoutRepeatSteps"; | ||
| readonly CUSTOM_TARGET_VALUES: "WorkoutCustomTargetValues"; | ||
| readonly REPEAT_GREATER_THAN: "WorkoutRepeatGreaterThanStep"; | ||
| }; | ||
@@ -507,186 +503,22 @@ /** | ||
| declare const loadFixturePair: (baseName: string) => { | ||
| fit: Uint8Array; | ||
| krd: KRD; | ||
| fit: Uint8Array; | ||
| krd: KRD; | ||
| }; | ||
| //#endregion | ||
| //#region src/ports/logger.d.ts | ||
| type Logger = { | ||
| debug: (message: string, context?: Record<string, unknown>) => void; | ||
| info: (message: string, context?: Record<string, unknown>) => void; | ||
| warn: (message: string, context?: Record<string, unknown>) => void; | ||
| error: (message: string, context?: Record<string, unknown>) => void; | ||
| debug: (message: string, context?: Record<string, unknown>) => void; | ||
| info: (message: string, context?: Record<string, unknown>) => void; | ||
| warn: (message: string, context?: Record<string, unknown>) => void; | ||
| error: (message: string, context?: Record<string, unknown>) => void; | ||
| }; | ||
| //#endregion | ||
| //#region src/tests/helpers/test-utils.d.ts | ||
| declare const createMockLogger: () => Logger; | ||
| declare const buildKRD: rosie.IFactory<{ | ||
| version: string; | ||
| type: "structured_workout" | "recorded_activity" | "course" | "sleep_record" | "weight_measurement" | "hrv_summary" | "daily_wellness" | "body_composition" | "stress_episode"; | ||
| metadata: { | ||
| created: string; | ||
| manufacturer?: string | undefined; | ||
| product?: string | undefined; | ||
| serialNumber?: string | undefined; | ||
| sport?: string | undefined; | ||
| subSport?: string | undefined; | ||
| }; | ||
| sessions?: { | ||
| startTime: string; | ||
| totalElapsedTime: number; | ||
| sport: string; | ||
| totalTimerTime?: number | undefined; | ||
| totalDistance?: number | undefined; | ||
| subSport?: string | undefined; | ||
| avgHeartRate?: number | undefined; | ||
| maxHeartRate?: number | undefined; | ||
| avgCadence?: number | undefined; | ||
| maxCadence?: number | undefined; | ||
| avgPower?: number | undefined; | ||
| maxPower?: number | undefined; | ||
| normalizedPower?: number | undefined; | ||
| trainingStressScore?: number | undefined; | ||
| intensityFactor?: number | undefined; | ||
| totalCalories?: number | undefined; | ||
| totalAscent?: number | undefined; | ||
| totalDescent?: number | undefined; | ||
| avgSpeed?: number | undefined; | ||
| maxSpeed?: number | undefined; | ||
| }[] | undefined; | ||
| laps?: { | ||
| startTime: string; | ||
| totalElapsedTime: number; | ||
| totalTimerTime?: number | undefined; | ||
| totalDistance?: number | undefined; | ||
| avgHeartRate?: number | undefined; | ||
| maxHeartRate?: number | undefined; | ||
| avgCadence?: number | undefined; | ||
| maxCadence?: number | undefined; | ||
| avgPower?: number | undefined; | ||
| maxPower?: number | undefined; | ||
| normalizedPower?: number | undefined; | ||
| avgSpeed?: number | undefined; | ||
| maxSpeed?: number | undefined; | ||
| totalAscent?: number | undefined; | ||
| totalDescent?: number | undefined; | ||
| totalCalories?: number | undefined; | ||
| trigger?: "time" | "fitness_equipment" | "manual" | "distance" | "position" | "session_end" | undefined; | ||
| sport?: "generic" | "running" | "cycling" | "transition" | "fitness_equipment" | "swimming" | "basketball" | "soccer" | "tennis" | "american_football" | "training" | "walking" | "cross_country_skiing" | "alpine_skiing" | "snowboarding" | "rowing" | "mountaineering" | "hiking" | "multisport" | "paddling" | "flying" | "e_biking" | "motorcycling" | "boating" | "driving" | "golf" | "hang_gliding" | "horseback_riding" | "hunting" | "fishing" | "inline_skating" | "rock_climbing" | "sailing" | "ice_skating" | "sky_diving" | "snowshoeing" | "snowmobiling" | "stand_up_paddleboarding" | "surfing" | "wakeboarding" | "water_skiing" | "kayaking" | "rafting" | "windsurfing" | "kitesurfing" | "tactical" | "jumpmaster" | "boxing" | "floor_climbing" | "baseball" | "diving" | "shooting" | "winter_sport" | "grinding" | "hiit" | "video_gaming" | "racket" | "wheelchair_push_walk" | "wheelchair_push_run" | "meditation" | "para_sport" | "disc_golf" | "team_sport" | "cricket" | "rugby" | "hockey" | "lacrosse" | "volleyball" | "water_tubing" | "wakesurfing" | "water_sport" | "archery" | "mixed_martial_arts" | "motor_sports" | "snorkeling" | "dance" | "jump_rope" | "pool_apnea" | "mobility" | "geocaching" | "canoeing" | undefined; | ||
| subSport?: "match" | "map" | "generic" | "treadmill" | "street" | "trail" | "track" | "spin" | "indoor_cycling" | "road" | "mountain" | "downhill" | "recumbent" | "cyclocross" | "hand_cycling" | "track_cycling" | "indoor_rowing" | "elliptical" | "stair_climbing" | "lap_swimming" | "open_water" | "flexibility_training" | "strength_training" | "warm_up" | "exercise" | "challenge" | "indoor_skiing" | "cardio_training" | "indoor_walking" | "e_bike_fitness" | "bmx" | "casual_walking" | "speed_walking" | "bike_to_run_transition" | "run_to_bike_transition" | "swim_to_bike_transition" | "atv" | "motocross" | "backcountry" | "resort" | "rc_drone" | "wingsuit" | "whitewater" | "skate_skiing" | "yoga" | "pilates" | "indoor_running" | "gravel_cycling" | "e_bike_mountain" | "commuting" | "mixed_surface" | "navigate" | "track_me" | "single_gas_diving" | "multi_gas_diving" | "gauge_diving" | "apnea_diving" | "apnea_hunting" | "virtual_activity" | "obstacle" | "all" | undefined; | ||
| workoutStepIndex?: number | undefined; | ||
| numLengths?: number | undefined; | ||
| swimStroke?: "mixed" | "freestyle" | "backstroke" | "breaststroke" | "butterfly" | "drill" | "im" | undefined; | ||
| }[] | undefined; | ||
| records?: { | ||
| timestamp: string; | ||
| position?: { | ||
| lat: number; | ||
| lon: number; | ||
| } | undefined; | ||
| altitude?: number | undefined; | ||
| heartRate?: number | undefined; | ||
| cadence?: number | undefined; | ||
| power?: number | undefined; | ||
| speed?: number | undefined; | ||
| distance?: number | undefined; | ||
| temperature?: number | undefined; | ||
| verticalOscillation?: number | undefined; | ||
| stanceTime?: number | undefined; | ||
| stepLength?: number | undefined; | ||
| }[] | undefined; | ||
| events?: { | ||
| timestamp: string; | ||
| eventType: "event_start" | "event_stop" | "event_pause" | "event_resume" | "event_lap" | "event_marker" | "event_timer" | "event_workout_step_change" | "event_session_start" | "event_activity_start"; | ||
| eventGroup?: number | undefined; | ||
| data?: number | undefined; | ||
| message?: string | undefined; | ||
| }[] | undefined; | ||
| extensions?: { | ||
| [x: string]: unknown; | ||
| structured_workout?: unknown; | ||
| fit?: unknown; | ||
| course?: unknown; | ||
| course_points?: unknown; | ||
| health?: { | ||
| [x: string]: unknown; | ||
| sleep?: { | ||
| kind: "sleep"; | ||
| version: string; | ||
| startTime: string; | ||
| endTime: string; | ||
| totalDurationSeconds: number; | ||
| stages: { | ||
| stage: "awake" | "light" | "deep" | "rem"; | ||
| startTime: string; | ||
| durationSeconds: number; | ||
| }[]; | ||
| score?: number | undefined; | ||
| restingHeartRate?: number | undefined; | ||
| kaiordRecordId?: string | undefined; | ||
| sourceBridgeId?: string | undefined; | ||
| externalId?: string | undefined; | ||
| } | undefined; | ||
| weight?: { | ||
| kind: "weight"; | ||
| version: string; | ||
| measuredAt: string; | ||
| weightKilograms: number; | ||
| kaiordRecordId?: string | undefined; | ||
| sourceBridgeId?: string | undefined; | ||
| externalId?: string | undefined; | ||
| } | undefined; | ||
| hrv?: { | ||
| kind: "hrv"; | ||
| version: string; | ||
| measuredAt: string; | ||
| rMSSD: number; | ||
| measurementWindow: "overnight" | "spot"; | ||
| score?: number | undefined; | ||
| kaiordRecordId?: string | undefined; | ||
| sourceBridgeId?: string | undefined; | ||
| externalId?: string | undefined; | ||
| } | undefined; | ||
| daily?: { | ||
| kind: "daily"; | ||
| version: string; | ||
| date: string; | ||
| steps: number; | ||
| activeCalories: number; | ||
| restingCalories: number; | ||
| intensityMinutes: { | ||
| moderate: number; | ||
| vigorous: number; | ||
| }; | ||
| floorsClimbed?: number | undefined; | ||
| kaiordRecordId?: string | undefined; | ||
| sourceBridgeId?: string | undefined; | ||
| externalId?: string | undefined; | ||
| } | undefined; | ||
| bodyComposition?: { | ||
| kind: "bodyComposition"; | ||
| version: string; | ||
| measuredAt: string; | ||
| bodyFatPercent?: number | undefined; | ||
| leanMassKilograms?: number | undefined; | ||
| boneMassKilograms?: number | undefined; | ||
| bodyWaterPercent?: number | undefined; | ||
| bmi?: number | undefined; | ||
| kaiordRecordId?: string | undefined; | ||
| sourceBridgeId?: string | undefined; | ||
| externalId?: string | undefined; | ||
| } | undefined; | ||
| stress?: { | ||
| kind: "stress"; | ||
| version: string; | ||
| startTime: string; | ||
| endTime: string; | ||
| averageLevel: number; | ||
| peakLevel: number; | ||
| kaiordRecordId?: string | undefined; | ||
| sourceBridgeId?: string | undefined; | ||
| externalId?: string | undefined; | ||
| } | undefined; | ||
| } | undefined; | ||
| } | undefined; | ||
| }>; | ||
| declare const buildKRDMetadata: rosie.IFactory<{ | ||
| //#endregion | ||
| //#region src/tests/fixtures/krd/krd.fixtures.d.ts | ||
| declare const buildKRD: import("rosie").IFactory<{ | ||
| version: string; | ||
| type: "body_composition" | "course" | "daily_wellness" | "hrv_summary" | "recorded_activity" | "sleep_record" | "stress_episode" | "structured_workout" | "weight_measurement"; | ||
| metadata: { | ||
| created: string; | ||
@@ -698,13 +530,4 @@ manufacturer?: string | undefined; | ||
| subSport?: string | undefined; | ||
| }>; | ||
| declare const buildKRDEvent: rosie.IFactory<{ | ||
| timestamp: string; | ||
| eventType: "event_start" | "event_stop" | "event_pause" | "event_resume" | "event_lap" | "event_marker" | "event_timer" | "event_workout_step_change" | "event_session_start" | "event_activity_start"; | ||
| eventGroup?: number | undefined; | ||
| data?: number | undefined; | ||
| message?: string | undefined; | ||
| }>; | ||
| declare const buildKRDLap: rosie.IFactory<{ | ||
| }; | ||
| sessions?: { | ||
| startTime: string; | ||
@@ -714,2 +537,4 @@ totalElapsedTime: number; | ||
| totalDistance?: number | undefined; | ||
| sport: string; | ||
| subSport?: string | undefined; | ||
| avgHeartRate?: number | undefined; | ||
@@ -722,20 +547,39 @@ maxHeartRate?: number | undefined; | ||
| normalizedPower?: number | undefined; | ||
| trainingStressScore?: number | undefined; | ||
| intensityFactor?: number | undefined; | ||
| totalCalories?: number | undefined; | ||
| totalAscent?: number | undefined; | ||
| totalDescent?: number | undefined; | ||
| avgSpeed?: number | undefined; | ||
| maxSpeed?: number | undefined; | ||
| }[] | undefined; | ||
| laps?: { | ||
| startTime: string; | ||
| totalElapsedTime: number; | ||
| totalTimerTime?: number | undefined; | ||
| totalDistance?: number | undefined; | ||
| avgHeartRate?: number | undefined; | ||
| maxHeartRate?: number | undefined; | ||
| avgCadence?: number | undefined; | ||
| maxCadence?: number | undefined; | ||
| avgPower?: number | undefined; | ||
| maxPower?: number | undefined; | ||
| normalizedPower?: number | undefined; | ||
| avgSpeed?: number | undefined; | ||
| maxSpeed?: number | undefined; | ||
| totalAscent?: number | undefined; | ||
| totalDescent?: number | undefined; | ||
| totalCalories?: number | undefined; | ||
| trigger?: "time" | "fitness_equipment" | "manual" | "distance" | "position" | "session_end" | undefined; | ||
| sport?: "generic" | "running" | "cycling" | "transition" | "fitness_equipment" | "swimming" | "basketball" | "soccer" | "tennis" | "american_football" | "training" | "walking" | "cross_country_skiing" | "alpine_skiing" | "snowboarding" | "rowing" | "mountaineering" | "hiking" | "multisport" | "paddling" | "flying" | "e_biking" | "motorcycling" | "boating" | "driving" | "golf" | "hang_gliding" | "horseback_riding" | "hunting" | "fishing" | "inline_skating" | "rock_climbing" | "sailing" | "ice_skating" | "sky_diving" | "snowshoeing" | "snowmobiling" | "stand_up_paddleboarding" | "surfing" | "wakeboarding" | "water_skiing" | "kayaking" | "rafting" | "windsurfing" | "kitesurfing" | "tactical" | "jumpmaster" | "boxing" | "floor_climbing" | "baseball" | "diving" | "shooting" | "winter_sport" | "grinding" | "hiit" | "video_gaming" | "racket" | "wheelchair_push_walk" | "wheelchair_push_run" | "meditation" | "para_sport" | "disc_golf" | "team_sport" | "cricket" | "rugby" | "hockey" | "lacrosse" | "volleyball" | "water_tubing" | "wakesurfing" | "water_sport" | "archery" | "mixed_martial_arts" | "motor_sports" | "snorkeling" | "dance" | "jump_rope" | "pool_apnea" | "mobility" | "geocaching" | "canoeing" | undefined; | ||
| subSport?: "match" | "map" | "generic" | "treadmill" | "street" | "trail" | "track" | "spin" | "indoor_cycling" | "road" | "mountain" | "downhill" | "recumbent" | "cyclocross" | "hand_cycling" | "track_cycling" | "indoor_rowing" | "elliptical" | "stair_climbing" | "lap_swimming" | "open_water" | "flexibility_training" | "strength_training" | "warm_up" | "exercise" | "challenge" | "indoor_skiing" | "cardio_training" | "indoor_walking" | "e_bike_fitness" | "bmx" | "casual_walking" | "speed_walking" | "bike_to_run_transition" | "run_to_bike_transition" | "swim_to_bike_transition" | "atv" | "motocross" | "backcountry" | "resort" | "rc_drone" | "wingsuit" | "whitewater" | "skate_skiing" | "yoga" | "pilates" | "indoor_running" | "gravel_cycling" | "e_bike_mountain" | "commuting" | "mixed_surface" | "navigate" | "track_me" | "single_gas_diving" | "multi_gas_diving" | "gauge_diving" | "apnea_diving" | "apnea_hunting" | "virtual_activity" | "obstacle" | "all" | undefined; | ||
| trigger?: "distance" | "fitness_equipment" | "manual" | "position" | "session_end" | "time" | undefined; | ||
| sport?: "alpine_skiing" | "american_football" | "archery" | "baseball" | "basketball" | "boating" | "boxing" | "canoeing" | "cricket" | "cross_country_skiing" | "cycling" | "dance" | "disc_golf" | "diving" | "driving" | "e_biking" | "fishing" | "fitness_equipment" | "floor_climbing" | "flying" | "generic" | "geocaching" | "golf" | "grinding" | "hang_gliding" | "hiit" | "hiking" | "hockey" | "horseback_riding" | "hunting" | "ice_skating" | "inline_skating" | "jump_rope" | "jumpmaster" | "kayaking" | "kitesurfing" | "lacrosse" | "meditation" | "mixed_martial_arts" | "mobility" | "motor_sports" | "motorcycling" | "mountaineering" | "multisport" | "paddling" | "para_sport" | "pool_apnea" | "racket" | "rafting" | "rock_climbing" | "rowing" | "rugby" | "running" | "sailing" | "shooting" | "sky_diving" | "snorkeling" | "snowboarding" | "snowmobiling" | "snowshoeing" | "soccer" | "stand_up_paddleboarding" | "surfing" | "swimming" | "tactical" | "team_sport" | "tennis" | "training" | "transition" | "video_gaming" | "volleyball" | "wakeboarding" | "wakesurfing" | "walking" | "water_skiing" | "water_sport" | "water_tubing" | "wheelchair_push_run" | "wheelchair_push_walk" | "windsurfing" | "winter_sport" | undefined; | ||
| subSport?: "all" | "apnea_diving" | "apnea_hunting" | "atv" | "backcountry" | "bike_to_run_transition" | "bmx" | "cardio_training" | "casual_walking" | "challenge" | "commuting" | "cyclocross" | "downhill" | "e_bike_fitness" | "e_bike_mountain" | "elliptical" | "exercise" | "flexibility_training" | "gauge_diving" | "generic" | "gravel_cycling" | "hand_cycling" | "indoor_cycling" | "indoor_rowing" | "indoor_running" | "indoor_skiing" | "indoor_walking" | "lap_swimming" | "map" | "match" | "mixed_surface" | "motocross" | "mountain" | "multi_gas_diving" | "navigate" | "obstacle" | "open_water" | "pilates" | "rc_drone" | "recumbent" | "resort" | "road" | "run_to_bike_transition" | "single_gas_diving" | "skate_skiing" | "speed_walking" | "spin" | "stair_climbing" | "street" | "strength_training" | "swim_to_bike_transition" | "track" | "track_cycling" | "track_me" | "trail" | "treadmill" | "virtual_activity" | "warm_up" | "whitewater" | "wingsuit" | "yoga" | undefined; | ||
| workoutStepIndex?: number | undefined; | ||
| numLengths?: number | undefined; | ||
| swimStroke?: "mixed" | "freestyle" | "backstroke" | "breaststroke" | "butterfly" | "drill" | "im" | undefined; | ||
| }>; | ||
| declare const buildKRDRecord: rosie.IFactory<{ | ||
| swimStroke?: "backstroke" | "breaststroke" | "butterfly" | "drill" | "freestyle" | "im" | "mixed" | undefined; | ||
| }[] | undefined; | ||
| records?: { | ||
| timestamp: string; | ||
| position?: { | ||
| lat: number; | ||
| lon: number; | ||
| lat: number; | ||
| lon: number; | ||
| } | undefined; | ||
@@ -752,583 +596,724 @@ altitude?: number | undefined; | ||
| stepLength?: number | undefined; | ||
| }[] | undefined; | ||
| events?: { | ||
| timestamp: string; | ||
| eventType: "event_activity_start" | "event_lap" | "event_marker" | "event_pause" | "event_resume" | "event_session_start" | "event_start" | "event_stop" | "event_timer" | "event_workout_step_change"; | ||
| eventGroup?: number | undefined; | ||
| data?: number | undefined; | ||
| message?: string | undefined; | ||
| }[] | undefined; | ||
| extensions?: { | ||
| [x: string]: unknown; | ||
| structured_workout?: unknown; | ||
| fit?: unknown; | ||
| course?: unknown; | ||
| course_points?: unknown; | ||
| health?: { | ||
| [x: string]: unknown; | ||
| sleep?: { | ||
| kind: "sleep"; | ||
| version: string; | ||
| startTime: string; | ||
| endTime: string; | ||
| totalDurationSeconds: number; | ||
| stages: { | ||
| stage: "awake" | "deep" | "light" | "rem"; | ||
| startTime: string; | ||
| durationSeconds: number; | ||
| }[]; | ||
| score?: number | undefined; | ||
| restingHeartRate?: number | undefined; | ||
| kaiordRecordId?: string | undefined; | ||
| sourceBridgeId?: string | undefined; | ||
| externalId?: string | undefined; | ||
| } | undefined; | ||
| weight?: { | ||
| kind: "weight"; | ||
| version: string; | ||
| measuredAt: string; | ||
| weightKilograms: number; | ||
| kaiordRecordId?: string | undefined; | ||
| sourceBridgeId?: string | undefined; | ||
| externalId?: string | undefined; | ||
| } | undefined; | ||
| hrv?: { | ||
| kind: "hrv"; | ||
| version: string; | ||
| measuredAt: string; | ||
| rMSSD: number; | ||
| measurementWindow: "overnight" | "spot"; | ||
| score?: number | undefined; | ||
| kaiordRecordId?: string | undefined; | ||
| sourceBridgeId?: string | undefined; | ||
| externalId?: string | undefined; | ||
| } | undefined; | ||
| daily?: { | ||
| kind: "daily"; | ||
| version: string; | ||
| date: string; | ||
| steps: number; | ||
| activeCalories: number; | ||
| restingCalories: number; | ||
| intensityMinutes: { | ||
| moderate: number; | ||
| vigorous: number; | ||
| }; | ||
| floorsClimbed?: number | undefined; | ||
| kaiordRecordId?: string | undefined; | ||
| sourceBridgeId?: string | undefined; | ||
| externalId?: string | undefined; | ||
| } | undefined; | ||
| bodyComposition?: { | ||
| kind: "bodyComposition"; | ||
| version: string; | ||
| measuredAt: string; | ||
| bodyFatPercent?: number | undefined; | ||
| leanMassKilograms?: number | undefined; | ||
| boneMassKilograms?: number | undefined; | ||
| bodyWaterPercent?: number | undefined; | ||
| bmi?: number | undefined; | ||
| visceralFatRating?: number | undefined; | ||
| basalMetabolicRateKcal?: number | undefined; | ||
| kaiordRecordId?: string | undefined; | ||
| sourceBridgeId?: string | undefined; | ||
| externalId?: string | undefined; | ||
| } | undefined; | ||
| stress?: { | ||
| kind: "stress"; | ||
| version: string; | ||
| startTime: string; | ||
| endTime: string; | ||
| averageLevel: number; | ||
| peakLevel: number; | ||
| kaiordRecordId?: string | undefined; | ||
| sourceBridgeId?: string | undefined; | ||
| externalId?: string | undefined; | ||
| } | undefined; | ||
| } | undefined; | ||
| } | undefined; | ||
| }>; | ||
| declare const buildKRDSession: rosie.IFactory<{ | ||
| startTime: string; | ||
| totalElapsedTime: number; | ||
| sport: string; | ||
| totalTimerTime?: number | undefined; | ||
| totalDistance?: number | undefined; | ||
| subSport?: string | undefined; | ||
| avgHeartRate?: number | undefined; | ||
| maxHeartRate?: number | undefined; | ||
| avgCadence?: number | undefined; | ||
| maxCadence?: number | undefined; | ||
| avgPower?: number | undefined; | ||
| maxPower?: number | undefined; | ||
| normalizedPower?: number | undefined; | ||
| trainingStressScore?: number | undefined; | ||
| intensityFactor?: number | undefined; | ||
| totalCalories?: number | undefined; | ||
| totalAscent?: number | undefined; | ||
| totalDescent?: number | undefined; | ||
| avgSpeed?: number | undefined; | ||
| maxSpeed?: number | undefined; | ||
| //#endregion | ||
| //#region src/tests/fixtures/krd/metadata.fixtures.d.ts | ||
| declare const buildKRDMetadata: import("rosie").IFactory<{ | ||
| created: string; | ||
| manufacturer?: string | undefined; | ||
| product?: string | undefined; | ||
| serialNumber?: string | undefined; | ||
| sport?: string | undefined; | ||
| subSport?: string | undefined; | ||
| }>; | ||
| declare const buildWorkoutStep: rosie.IFactory<{ | ||
| //#endregion | ||
| //#region src/tests/fixtures/krd/event.fixtures.d.ts | ||
| declare const buildKRDEvent: import("rosie").IFactory<{ | ||
| timestamp: string; | ||
| eventType: "event_activity_start" | "event_lap" | "event_marker" | "event_pause" | "event_resume" | "event_session_start" | "event_start" | "event_stop" | "event_timer" | "event_workout_step_change"; | ||
| eventGroup?: number | undefined; | ||
| data?: number | undefined; | ||
| message?: string | undefined; | ||
| }>; | ||
| //#endregion | ||
| //#region src/tests/fixtures/krd/lap.fixtures.d.ts | ||
| declare const buildKRDLap: import("rosie").IFactory<{ | ||
| startTime: string; | ||
| totalElapsedTime: number; | ||
| totalTimerTime?: number | undefined; | ||
| totalDistance?: number | undefined; | ||
| avgHeartRate?: number | undefined; | ||
| maxHeartRate?: number | undefined; | ||
| avgCadence?: number | undefined; | ||
| maxCadence?: number | undefined; | ||
| avgPower?: number | undefined; | ||
| maxPower?: number | undefined; | ||
| normalizedPower?: number | undefined; | ||
| avgSpeed?: number | undefined; | ||
| maxSpeed?: number | undefined; | ||
| totalAscent?: number | undefined; | ||
| totalDescent?: number | undefined; | ||
| totalCalories?: number | undefined; | ||
| trigger?: "distance" | "fitness_equipment" | "manual" | "position" | "session_end" | "time" | undefined; | ||
| sport?: "alpine_skiing" | "american_football" | "archery" | "baseball" | "basketball" | "boating" | "boxing" | "canoeing" | "cricket" | "cross_country_skiing" | "cycling" | "dance" | "disc_golf" | "diving" | "driving" | "e_biking" | "fishing" | "fitness_equipment" | "floor_climbing" | "flying" | "generic" | "geocaching" | "golf" | "grinding" | "hang_gliding" | "hiit" | "hiking" | "hockey" | "horseback_riding" | "hunting" | "ice_skating" | "inline_skating" | "jump_rope" | "jumpmaster" | "kayaking" | "kitesurfing" | "lacrosse" | "meditation" | "mixed_martial_arts" | "mobility" | "motor_sports" | "motorcycling" | "mountaineering" | "multisport" | "paddling" | "para_sport" | "pool_apnea" | "racket" | "rafting" | "rock_climbing" | "rowing" | "rugby" | "running" | "sailing" | "shooting" | "sky_diving" | "snorkeling" | "snowboarding" | "snowmobiling" | "snowshoeing" | "soccer" | "stand_up_paddleboarding" | "surfing" | "swimming" | "tactical" | "team_sport" | "tennis" | "training" | "transition" | "video_gaming" | "volleyball" | "wakeboarding" | "wakesurfing" | "walking" | "water_skiing" | "water_sport" | "water_tubing" | "wheelchair_push_run" | "wheelchair_push_walk" | "windsurfing" | "winter_sport" | undefined; | ||
| subSport?: "all" | "apnea_diving" | "apnea_hunting" | "atv" | "backcountry" | "bike_to_run_transition" | "bmx" | "cardio_training" | "casual_walking" | "challenge" | "commuting" | "cyclocross" | "downhill" | "e_bike_fitness" | "e_bike_mountain" | "elliptical" | "exercise" | "flexibility_training" | "gauge_diving" | "generic" | "gravel_cycling" | "hand_cycling" | "indoor_cycling" | "indoor_rowing" | "indoor_running" | "indoor_skiing" | "indoor_walking" | "lap_swimming" | "map" | "match" | "mixed_surface" | "motocross" | "mountain" | "multi_gas_diving" | "navigate" | "obstacle" | "open_water" | "pilates" | "rc_drone" | "recumbent" | "resort" | "road" | "run_to_bike_transition" | "single_gas_diving" | "skate_skiing" | "speed_walking" | "spin" | "stair_climbing" | "street" | "strength_training" | "swim_to_bike_transition" | "track" | "track_cycling" | "track_me" | "trail" | "treadmill" | "virtual_activity" | "warm_up" | "whitewater" | "wingsuit" | "yoga" | undefined; | ||
| workoutStepIndex?: number | undefined; | ||
| numLengths?: number | undefined; | ||
| swimStroke?: "backstroke" | "breaststroke" | "butterfly" | "drill" | "freestyle" | "im" | "mixed" | undefined; | ||
| }>; | ||
| //#endregion | ||
| //#region src/tests/fixtures/krd/record.fixtures.d.ts | ||
| declare const buildKRDRecord: import("rosie").IFactory<{ | ||
| timestamp: string; | ||
| position?: { | ||
| lat: number; | ||
| lon: number; | ||
| } | undefined; | ||
| altitude?: number | undefined; | ||
| heartRate?: number | undefined; | ||
| cadence?: number | undefined; | ||
| power?: number | undefined; | ||
| speed?: number | undefined; | ||
| distance?: number | undefined; | ||
| temperature?: number | undefined; | ||
| verticalOscillation?: number | undefined; | ||
| stanceTime?: number | undefined; | ||
| stepLength?: number | undefined; | ||
| }>; | ||
| //#endregion | ||
| //#region src/tests/fixtures/krd/session.fixtures.d.ts | ||
| declare const buildKRDSession: import("rosie").IFactory<{ | ||
| startTime: string; | ||
| totalElapsedTime: number; | ||
| totalTimerTime?: number | undefined; | ||
| totalDistance?: number | undefined; | ||
| sport: string; | ||
| subSport?: string | undefined; | ||
| avgHeartRate?: number | undefined; | ||
| maxHeartRate?: number | undefined; | ||
| avgCadence?: number | undefined; | ||
| maxCadence?: number | undefined; | ||
| avgPower?: number | undefined; | ||
| maxPower?: number | undefined; | ||
| normalizedPower?: number | undefined; | ||
| trainingStressScore?: number | undefined; | ||
| intensityFactor?: number | undefined; | ||
| totalCalories?: number | undefined; | ||
| totalAscent?: number | undefined; | ||
| totalDescent?: number | undefined; | ||
| avgSpeed?: number | undefined; | ||
| maxSpeed?: number | undefined; | ||
| }>; | ||
| //#endregion | ||
| //#region src/tests/fixtures/workout/workout-step.fixtures.d.ts | ||
| declare const buildWorkoutStep: import("rosie").IFactory<{ | ||
| stepIndex: number; | ||
| name?: string | undefined; | ||
| durationType: "calories" | "distance" | "heart_rate_less_than" | "open" | "power_greater_than" | "power_less_than" | "repeat_until_calories" | "repeat_until_distance" | "repeat_until_heart_rate_greater_than" | "repeat_until_heart_rate_less_than" | "repeat_until_power_greater_than" | "repeat_until_power_less_than" | "repeat_until_time" | "time"; | ||
| duration: { | ||
| type: "time"; | ||
| seconds: number; | ||
| } | { | ||
| type: "distance"; | ||
| meters: number; | ||
| } | { | ||
| type: "heart_rate_less_than"; | ||
| bpm: number; | ||
| } | { | ||
| type: "repeat_until_heart_rate_greater_than"; | ||
| bpm: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "calories"; | ||
| calories: number; | ||
| } | { | ||
| type: "power_less_than"; | ||
| watts: number; | ||
| } | { | ||
| type: "power_greater_than"; | ||
| watts: number; | ||
| } | { | ||
| type: "repeat_until_time"; | ||
| seconds: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_distance"; | ||
| meters: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_calories"; | ||
| calories: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_heart_rate_less_than"; | ||
| bpm: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_power_less_than"; | ||
| watts: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_power_greater_than"; | ||
| watts: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "open"; | ||
| }; | ||
| targetType: "cadence" | "heart_rate" | "open" | "pace" | "power" | "stroke_type"; | ||
| target: { | ||
| type: "power"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "watts"; | ||
| value: number; | ||
| } | { | ||
| unit: "percent_ftp"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "heart_rate"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "bpm"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| } | { | ||
| unit: "percent_max"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "cadence"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "rpm"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "pace"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "mps"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "stroke_type"; | ||
| value: { | ||
| unit: "swim_stroke"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "open"; | ||
| }; | ||
| intensity?: "active" | "cooldown" | "interval" | "other" | "recovery" | "rest" | "warmup" | undefined; | ||
| notes?: string | undefined; | ||
| equipment?: "none" | "swim_fins" | "swim_kickboard" | "swim_paddles" | "swim_pull_buoy" | "swim_snorkel" | undefined; | ||
| extensions?: Record<string, unknown> | undefined; | ||
| }>; | ||
| //#endregion | ||
| //#region src/tests/fixtures/workout/workout.fixtures.d.ts | ||
| declare const buildWorkout: import("rosie").IFactory<{ | ||
| name?: string | undefined; | ||
| notes?: string | undefined; | ||
| sport: "alpine_skiing" | "american_football" | "archery" | "baseball" | "basketball" | "boating" | "boxing" | "canoeing" | "cricket" | "cross_country_skiing" | "cycling" | "dance" | "disc_golf" | "diving" | "driving" | "e_biking" | "fishing" | "fitness_equipment" | "floor_climbing" | "flying" | "generic" | "geocaching" | "golf" | "grinding" | "hang_gliding" | "hiit" | "hiking" | "hockey" | "horseback_riding" | "hunting" | "ice_skating" | "inline_skating" | "jump_rope" | "jumpmaster" | "kayaking" | "kitesurfing" | "lacrosse" | "meditation" | "mixed_martial_arts" | "mobility" | "motor_sports" | "motorcycling" | "mountaineering" | "multisport" | "paddling" | "para_sport" | "pool_apnea" | "racket" | "rafting" | "rock_climbing" | "rowing" | "rugby" | "running" | "sailing" | "shooting" | "sky_diving" | "snorkeling" | "snowboarding" | "snowmobiling" | "snowshoeing" | "soccer" | "stand_up_paddleboarding" | "surfing" | "swimming" | "tactical" | "team_sport" | "tennis" | "training" | "transition" | "video_gaming" | "volleyball" | "wakeboarding" | "wakesurfing" | "walking" | "water_skiing" | "water_sport" | "water_tubing" | "wheelchair_push_run" | "wheelchair_push_walk" | "windsurfing" | "winter_sport"; | ||
| subSport?: "all" | "apnea_diving" | "apnea_hunting" | "atv" | "backcountry" | "bike_to_run_transition" | "bmx" | "cardio_training" | "casual_walking" | "challenge" | "commuting" | "cyclocross" | "downhill" | "e_bike_fitness" | "e_bike_mountain" | "elliptical" | "exercise" | "flexibility_training" | "gauge_diving" | "generic" | "gravel_cycling" | "hand_cycling" | "indoor_cycling" | "indoor_rowing" | "indoor_running" | "indoor_skiing" | "indoor_walking" | "lap_swimming" | "map" | "match" | "mixed_surface" | "motocross" | "mountain" | "multi_gas_diving" | "navigate" | "obstacle" | "open_water" | "pilates" | "rc_drone" | "recumbent" | "resort" | "road" | "run_to_bike_transition" | "single_gas_diving" | "skate_skiing" | "speed_walking" | "spin" | "stair_climbing" | "street" | "strength_training" | "swim_to_bike_transition" | "track" | "track_cycling" | "track_me" | "trail" | "treadmill" | "virtual_activity" | "warm_up" | "whitewater" | "wingsuit" | "yoga" | undefined; | ||
| poolLength?: number | undefined; | ||
| poolLengthUnit?: "meters" | undefined; | ||
| steps: ({ | ||
| stepIndex: number; | ||
| durationType: "time" | "distance" | "heart_rate_less_than" | "repeat_until_heart_rate_greater_than" | "calories" | "power_less_than" | "power_greater_than" | "repeat_until_time" | "repeat_until_distance" | "repeat_until_calories" | "repeat_until_heart_rate_less_than" | "repeat_until_power_less_than" | "repeat_until_power_greater_than" | "open"; | ||
| name?: string | undefined; | ||
| durationType: "calories" | "distance" | "heart_rate_less_than" | "open" | "power_greater_than" | "power_less_than" | "repeat_until_calories" | "repeat_until_distance" | "repeat_until_heart_rate_greater_than" | "repeat_until_heart_rate_less_than" | "repeat_until_power_greater_than" | "repeat_until_power_less_than" | "repeat_until_time" | "time"; | ||
| duration: { | ||
| type: "time"; | ||
| seconds: number; | ||
| } | { | ||
| type: "distance"; | ||
| meters: number; | ||
| } | { | ||
| type: "heart_rate_less_than"; | ||
| bpm: number; | ||
| } | { | ||
| type: "repeat_until_heart_rate_greater_than"; | ||
| bpm: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "calories"; | ||
| calories: number; | ||
| } | { | ||
| type: "power_less_than"; | ||
| watts: number; | ||
| } | { | ||
| type: "power_greater_than"; | ||
| watts: number; | ||
| } | { | ||
| type: "repeat_until_time"; | ||
| seconds: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_distance"; | ||
| meters: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_calories"; | ||
| calories: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_heart_rate_less_than"; | ||
| bpm: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_power_less_than"; | ||
| watts: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_power_greater_than"; | ||
| watts: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "open"; | ||
| }; | ||
| targetType: "cadence" | "heart_rate" | "open" | "pace" | "power" | "stroke_type"; | ||
| target: { | ||
| type: "power"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "watts"; | ||
| value: number; | ||
| } | { | ||
| unit: "percent_ftp"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "heart_rate"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "bpm"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| } | { | ||
| unit: "percent_max"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "cadence"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "rpm"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "pace"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "mps"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "stroke_type"; | ||
| value: { | ||
| unit: "swim_stroke"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "open"; | ||
| }; | ||
| intensity?: "active" | "cooldown" | "interval" | "other" | "recovery" | "rest" | "warmup" | undefined; | ||
| notes?: string | undefined; | ||
| equipment?: "none" | "swim_fins" | "swim_kickboard" | "swim_paddles" | "swim_pull_buoy" | "swim_snorkel" | undefined; | ||
| extensions?: Record<string, unknown> | undefined; | ||
| } | { | ||
| id?: string | undefined; | ||
| repeatCount: number; | ||
| steps: { | ||
| stepIndex: number; | ||
| name?: string | undefined; | ||
| durationType: "calories" | "distance" | "heart_rate_less_than" | "open" | "power_greater_than" | "power_less_than" | "repeat_until_calories" | "repeat_until_distance" | "repeat_until_heart_rate_greater_than" | "repeat_until_heart_rate_less_than" | "repeat_until_power_greater_than" | "repeat_until_power_less_than" | "repeat_until_time" | "time"; | ||
| duration: { | ||
| type: "time"; | ||
| seconds: number; | ||
| } | { | ||
| } | { | ||
| type: "distance"; | ||
| meters: number; | ||
| } | { | ||
| } | { | ||
| type: "heart_rate_less_than"; | ||
| bpm: number; | ||
| } | { | ||
| } | { | ||
| type: "repeat_until_heart_rate_greater_than"; | ||
| bpm: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| } | { | ||
| type: "calories"; | ||
| calories: number; | ||
| } | { | ||
| } | { | ||
| type: "power_less_than"; | ||
| watts: number; | ||
| } | { | ||
| } | { | ||
| type: "power_greater_than"; | ||
| watts: number; | ||
| } | { | ||
| } | { | ||
| type: "repeat_until_time"; | ||
| seconds: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| } | { | ||
| type: "repeat_until_distance"; | ||
| meters: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| } | { | ||
| type: "repeat_until_calories"; | ||
| calories: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| } | { | ||
| type: "repeat_until_heart_rate_less_than"; | ||
| bpm: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| } | { | ||
| type: "repeat_until_power_less_than"; | ||
| watts: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| } | { | ||
| type: "repeat_until_power_greater_than"; | ||
| watts: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| } | { | ||
| type: "open"; | ||
| }; | ||
| targetType: "cadence" | "power" | "open" | "heart_rate" | "pace" | "stroke_type"; | ||
| target: { | ||
| }; | ||
| targetType: "cadence" | "heart_rate" | "open" | "pace" | "power" | "stroke_type"; | ||
| target: { | ||
| type: "power"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "watts"; | ||
| value: number; | ||
| unit: "watts"; | ||
| value: number; | ||
| } | { | ||
| unit: "percent_ftp"; | ||
| value: number; | ||
| unit: "percent_ftp"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| unit: "zone"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| } | { | ||
| type: "heart_rate"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "bpm"; | ||
| value: number; | ||
| unit: "bpm"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| unit: "zone"; | ||
| value: number; | ||
| } | { | ||
| unit: "percent_max"; | ||
| value: number; | ||
| unit: "percent_max"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| } | { | ||
| type: "cadence"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "rpm"; | ||
| value: number; | ||
| unit: "rpm"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| } | { | ||
| type: "pace"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "mps"; | ||
| value: number; | ||
| unit: "mps"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| unit: "zone"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| } | { | ||
| type: "stroke_type"; | ||
| value: { | ||
| unit: "swim_stroke"; | ||
| value: number; | ||
| unit: "swim_stroke"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| } | { | ||
| type: "open"; | ||
| }; | ||
| name?: string | undefined; | ||
| intensity?: "warmup" | "active" | "cooldown" | "rest" | "recovery" | "interval" | "other" | undefined; | ||
| notes?: string | undefined; | ||
| equipment?: "none" | "swim_fins" | "swim_kickboard" | "swim_paddles" | "swim_pull_buoy" | "swim_snorkel" | undefined; | ||
| extensions?: Record<string, unknown> | undefined; | ||
| }; | ||
| intensity?: "active" | "cooldown" | "interval" | "other" | "recovery" | "rest" | "warmup" | undefined; | ||
| notes?: string | undefined; | ||
| equipment?: "none" | "swim_fins" | "swim_kickboard" | "swim_paddles" | "swim_pull_buoy" | "swim_snorkel" | undefined; | ||
| extensions?: Record<string, unknown> | undefined; | ||
| }[]; | ||
| })[]; | ||
| extensions?: Record<string, unknown> | undefined; | ||
| }>; | ||
| declare const buildWorkout: rosie.IFactory<{ | ||
| sport: "generic" | "running" | "cycling" | "transition" | "fitness_equipment" | "swimming" | "basketball" | "soccer" | "tennis" | "american_football" | "training" | "walking" | "cross_country_skiing" | "alpine_skiing" | "snowboarding" | "rowing" | "mountaineering" | "hiking" | "multisport" | "paddling" | "flying" | "e_biking" | "motorcycling" | "boating" | "driving" | "golf" | "hang_gliding" | "horseback_riding" | "hunting" | "fishing" | "inline_skating" | "rock_climbing" | "sailing" | "ice_skating" | "sky_diving" | "snowshoeing" | "snowmobiling" | "stand_up_paddleboarding" | "surfing" | "wakeboarding" | "water_skiing" | "kayaking" | "rafting" | "windsurfing" | "kitesurfing" | "tactical" | "jumpmaster" | "boxing" | "floor_climbing" | "baseball" | "diving" | "shooting" | "winter_sport" | "grinding" | "hiit" | "video_gaming" | "racket" | "wheelchair_push_walk" | "wheelchair_push_run" | "meditation" | "para_sport" | "disc_golf" | "team_sport" | "cricket" | "rugby" | "hockey" | "lacrosse" | "volleyball" | "water_tubing" | "wakesurfing" | "water_sport" | "archery" | "mixed_martial_arts" | "motor_sports" | "snorkeling" | "dance" | "jump_rope" | "pool_apnea" | "mobility" | "geocaching" | "canoeing"; | ||
| steps: ({ | ||
| stepIndex: number; | ||
| durationType: "time" | "distance" | "heart_rate_less_than" | "repeat_until_heart_rate_greater_than" | "calories" | "power_less_than" | "power_greater_than" | "repeat_until_time" | "repeat_until_distance" | "repeat_until_calories" | "repeat_until_heart_rate_less_than" | "repeat_until_power_less_than" | "repeat_until_power_greater_than" | "open"; | ||
| duration: { | ||
| type: "time"; | ||
| seconds: number; | ||
| } | { | ||
| type: "distance"; | ||
| meters: number; | ||
| } | { | ||
| type: "heart_rate_less_than"; | ||
| bpm: number; | ||
| } | { | ||
| type: "repeat_until_heart_rate_greater_than"; | ||
| bpm: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "calories"; | ||
| calories: number; | ||
| } | { | ||
| type: "power_less_than"; | ||
| watts: number; | ||
| } | { | ||
| type: "power_greater_than"; | ||
| watts: number; | ||
| } | { | ||
| type: "repeat_until_time"; | ||
| seconds: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_distance"; | ||
| meters: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_calories"; | ||
| calories: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_heart_rate_less_than"; | ||
| bpm: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_power_less_than"; | ||
| watts: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_power_greater_than"; | ||
| watts: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "open"; | ||
| }; | ||
| targetType: "cadence" | "power" | "open" | "heart_rate" | "pace" | "stroke_type"; | ||
| target: { | ||
| type: "power"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "watts"; | ||
| value: number; | ||
| } | { | ||
| unit: "percent_ftp"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "heart_rate"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "bpm"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| } | { | ||
| unit: "percent_max"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "cadence"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "rpm"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "pace"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "mps"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "stroke_type"; | ||
| value: { | ||
| unit: "swim_stroke"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "open"; | ||
| }; | ||
| name?: string | undefined; | ||
| intensity?: "warmup" | "active" | "cooldown" | "rest" | "recovery" | "interval" | "other" | undefined; | ||
| notes?: string | undefined; | ||
| equipment?: "none" | "swim_fins" | "swim_kickboard" | "swim_paddles" | "swim_pull_buoy" | "swim_snorkel" | undefined; | ||
| extensions?: Record<string, unknown> | undefined; | ||
| } | { | ||
| repeatCount: number; | ||
| steps: { | ||
| stepIndex: number; | ||
| durationType: "time" | "distance" | "heart_rate_less_than" | "repeat_until_heart_rate_greater_than" | "calories" | "power_less_than" | "power_greater_than" | "repeat_until_time" | "repeat_until_distance" | "repeat_until_calories" | "repeat_until_heart_rate_less_than" | "repeat_until_power_less_than" | "repeat_until_power_greater_than" | "open"; | ||
| duration: { | ||
| type: "time"; | ||
| seconds: number; | ||
| } | { | ||
| type: "distance"; | ||
| meters: number; | ||
| } | { | ||
| type: "heart_rate_less_than"; | ||
| bpm: number; | ||
| } | { | ||
| type: "repeat_until_heart_rate_greater_than"; | ||
| bpm: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "calories"; | ||
| calories: number; | ||
| } | { | ||
| type: "power_less_than"; | ||
| watts: number; | ||
| } | { | ||
| type: "power_greater_than"; | ||
| watts: number; | ||
| } | { | ||
| type: "repeat_until_time"; | ||
| seconds: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_distance"; | ||
| meters: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_calories"; | ||
| calories: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_heart_rate_less_than"; | ||
| bpm: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_power_less_than"; | ||
| watts: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_power_greater_than"; | ||
| watts: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "open"; | ||
| }; | ||
| targetType: "cadence" | "power" | "open" | "heart_rate" | "pace" | "stroke_type"; | ||
| target: { | ||
| type: "power"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "watts"; | ||
| value: number; | ||
| } | { | ||
| unit: "percent_ftp"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "heart_rate"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "bpm"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| } | { | ||
| unit: "percent_max"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "cadence"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "rpm"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "pace"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "mps"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "stroke_type"; | ||
| value: { | ||
| unit: "swim_stroke"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "open"; | ||
| }; | ||
| name?: string | undefined; | ||
| intensity?: "warmup" | "active" | "cooldown" | "rest" | "recovery" | "interval" | "other" | undefined; | ||
| notes?: string | undefined; | ||
| equipment?: "none" | "swim_fins" | "swim_kickboard" | "swim_paddles" | "swim_pull_buoy" | "swim_snorkel" | undefined; | ||
| extensions?: Record<string, unknown> | undefined; | ||
| }[]; | ||
| id?: string | undefined; | ||
| })[]; | ||
| name?: string | undefined; | ||
| notes?: string | undefined; | ||
| subSport?: "match" | "map" | "generic" | "treadmill" | "street" | "trail" | "track" | "spin" | "indoor_cycling" | "road" | "mountain" | "downhill" | "recumbent" | "cyclocross" | "hand_cycling" | "track_cycling" | "indoor_rowing" | "elliptical" | "stair_climbing" | "lap_swimming" | "open_water" | "flexibility_training" | "strength_training" | "warm_up" | "exercise" | "challenge" | "indoor_skiing" | "cardio_training" | "indoor_walking" | "e_bike_fitness" | "bmx" | "casual_walking" | "speed_walking" | "bike_to_run_transition" | "run_to_bike_transition" | "swim_to_bike_transition" | "atv" | "motocross" | "backcountry" | "resort" | "rc_drone" | "wingsuit" | "whitewater" | "skate_skiing" | "yoga" | "pilates" | "indoor_running" | "gravel_cycling" | "e_bike_mountain" | "commuting" | "mixed_surface" | "navigate" | "track_me" | "single_gas_diving" | "multi_gas_diving" | "gauge_diving" | "apnea_diving" | "apnea_hunting" | "virtual_activity" | "obstacle" | "all" | undefined; | ||
| poolLength?: number | undefined; | ||
| poolLengthUnit?: "meters" | undefined; | ||
| extensions?: Record<string, unknown> | undefined; | ||
| }>; | ||
| declare const buildDuration: rosie.IFactory<{ | ||
| type: "time"; | ||
| seconds: number; | ||
| //#endregion | ||
| //#region src/tests/fixtures/workout/duration.fixtures.d.ts | ||
| declare const buildDuration: import("rosie").IFactory<{ | ||
| type: "time"; | ||
| seconds: number; | ||
| } | { | ||
| type: "distance"; | ||
| meters: number; | ||
| type: "distance"; | ||
| meters: number; | ||
| } | { | ||
| type: "heart_rate_less_than"; | ||
| bpm: number; | ||
| type: "heart_rate_less_than"; | ||
| bpm: number; | ||
| } | { | ||
| type: "repeat_until_heart_rate_greater_than"; | ||
| bpm: number; | ||
| repeatFrom: number; | ||
| type: "repeat_until_heart_rate_greater_than"; | ||
| bpm: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "calories"; | ||
| calories: number; | ||
| type: "calories"; | ||
| calories: number; | ||
| } | { | ||
| type: "power_less_than"; | ||
| watts: number; | ||
| type: "power_less_than"; | ||
| watts: number; | ||
| } | { | ||
| type: "power_greater_than"; | ||
| watts: number; | ||
| type: "power_greater_than"; | ||
| watts: number; | ||
| } | { | ||
| type: "repeat_until_time"; | ||
| seconds: number; | ||
| repeatFrom: number; | ||
| type: "repeat_until_time"; | ||
| seconds: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_distance"; | ||
| meters: number; | ||
| repeatFrom: number; | ||
| type: "repeat_until_distance"; | ||
| meters: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_calories"; | ||
| calories: number; | ||
| repeatFrom: number; | ||
| type: "repeat_until_calories"; | ||
| calories: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_heart_rate_less_than"; | ||
| bpm: number; | ||
| repeatFrom: number; | ||
| type: "repeat_until_heart_rate_less_than"; | ||
| bpm: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_power_less_than"; | ||
| watts: number; | ||
| repeatFrom: number; | ||
| type: "repeat_until_power_less_than"; | ||
| watts: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "repeat_until_power_greater_than"; | ||
| watts: number; | ||
| repeatFrom: number; | ||
| type: "repeat_until_power_greater_than"; | ||
| watts: number; | ||
| repeatFrom: number; | ||
| } | { | ||
| type: "open"; | ||
| type: "open"; | ||
| }>; | ||
| declare const buildTarget: rosie.IFactory<{ | ||
| type: "power"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "watts"; | ||
| value: number; | ||
| } | { | ||
| unit: "percent_ftp"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| }; | ||
| //#endregion | ||
| //#region src/tests/fixtures/workout/target.fixtures.d.ts | ||
| declare const buildTarget: import("rosie").IFactory<{ | ||
| type: "power"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "watts"; | ||
| value: number; | ||
| } | { | ||
| unit: "percent_ftp"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "heart_rate"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "bpm"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| } | { | ||
| unit: "percent_max"; | ||
| value: number; | ||
| }; | ||
| type: "heart_rate"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "bpm"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| } | { | ||
| unit: "percent_max"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "cadence"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "rpm"; | ||
| value: number; | ||
| }; | ||
| type: "cadence"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "rpm"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "pace"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "mps"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| }; | ||
| type: "pace"; | ||
| value: { | ||
| unit: "range"; | ||
| min: number; | ||
| max: number; | ||
| } | { | ||
| unit: "mps"; | ||
| value: number; | ||
| } | { | ||
| unit: "zone"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "stroke_type"; | ||
| value: { | ||
| unit: "swim_stroke"; | ||
| value: number; | ||
| }; | ||
| type: "stroke_type"; | ||
| value: { | ||
| unit: "swim_stroke"; | ||
| value: number; | ||
| }; | ||
| } | { | ||
| type: "open"; | ||
| type: "open"; | ||
| }>; | ||
| /** | ||
| * Profile Snapshot — cross-cutting protocol contract | ||
| * | ||
| * Owned by the SPA Bridge Protocol capability. The SPA derives a snapshot | ||
| * from its domain Profile and pushes it to every VERIFIED bridge so the | ||
| * bridge popup can render athlete data without a network call. | ||
| * | ||
| * Why @kaiord/core: same precedent as bridgeManifestSchema — only package | ||
| * both the SPA and any bridge can structurally agree on without a layering | ||
| * inversion. The runtime has no module-loading path between the SPA and | ||
| * a bridge; the schema serves as the source of truth for the SPA's | ||
| * Zod parser AND for each bridge's hand-rolled plain-JS structural | ||
| * validator (parity-tested via shared fixtures). | ||
| */ | ||
| //#endregion | ||
| //#region src/protocol/profile-snapshot.d.ts | ||
| declare const profileSnapshotSchema: z.ZodPipe<z.ZodUnknown, z.ZodObject<{ | ||
| schemaVersion: z.ZodLiteral<1>; | ||
| profile: z.ZodObject<{ | ||
| name: z.ZodString; | ||
| bodyWeight: z.ZodOptional<z.ZodNumber>; | ||
| }, z.core.$strict>; | ||
| activeSport: z.ZodOptional<z.ZodEnum<{ | ||
| running: "running"; | ||
| cycling: "cycling"; | ||
| swimming: "swimming"; | ||
| }>>; | ||
| thresholds: z.ZodDefault<z.ZodObject<{ | ||
| cycling: z.ZodOptional<z.ZodObject<{ | ||
| ftp: z.ZodOptional<z.ZodNumber>; | ||
| }, z.core.$strict>>; | ||
| running: z.ZodOptional<z.ZodObject<{ | ||
| thresholdPaceSecPerKm: z.ZodOptional<z.ZodNumber>; | ||
| lthr: z.ZodOptional<z.ZodNumber>; | ||
| }, z.core.$strict>>; | ||
| swimming: z.ZodOptional<z.ZodObject<{ | ||
| cssPaceSecPer100m: z.ZodOptional<z.ZodNumber>; | ||
| }, z.core.$strict>>; | ||
| schemaVersion: z.ZodLiteral<1>; | ||
| profile: z.ZodObject<{ | ||
| name: z.ZodString; | ||
| bodyWeight: z.ZodOptional<z.ZodNumber>; | ||
| }, z.core.$strict>; | ||
| activeSport: z.ZodOptional<z.ZodEnum<{ | ||
| cycling: "cycling"; | ||
| running: "running"; | ||
| swimming: "swimming"; | ||
| }>>; | ||
| thresholds: z.ZodDefault<z.ZodObject<{ | ||
| cycling: z.ZodOptional<z.ZodObject<{ | ||
| ftp: z.ZodOptional<z.ZodNumber>; | ||
| }, z.core.$strict>>; | ||
| heartRate: z.ZodDefault<z.ZodObject<{ | ||
| max: z.ZodOptional<z.ZodNumber>; | ||
| lthr: z.ZodOptional<z.ZodNumber>; | ||
| running: z.ZodOptional<z.ZodObject<{ | ||
| thresholdPaceSecPerKm: z.ZodOptional<z.ZodNumber>; | ||
| lthr: z.ZodOptional<z.ZodNumber>; | ||
| }, z.core.$strict>>; | ||
| generatedAt: z.ZodISODateTime; | ||
| swimming: z.ZodOptional<z.ZodObject<{ | ||
| cssPaceSecPer100m: z.ZodOptional<z.ZodNumber>; | ||
| }, z.core.$strict>>; | ||
| }, z.core.$strict>>; | ||
| heartRate: z.ZodDefault<z.ZodObject<{ | ||
| max: z.ZodOptional<z.ZodNumber>; | ||
| lthr: z.ZodOptional<z.ZodNumber>; | ||
| }, z.core.$strict>>; | ||
| generatedAt: z.ZodISODateTime; | ||
| }, z.core.$strict>>; | ||
| type ProfileSnapshot = z.infer<typeof profileSnapshotSchema>; | ||
| /** | ||
| * Profile Snapshot Fixtures | ||
| * | ||
| * Shared positive/negative fixture set consumed by: | ||
| * - The SPA's Zod parser tests (in `@kaiord/workout-spa-editor`). | ||
| * - Each bridge's plain-JS structural validator parity test. | ||
| * | ||
| * Both validators MUST agree: positive fixtures parse with deep-equal | ||
| * output; negative fixtures reject without throwing and without mutating | ||
| * `Object.prototype`. | ||
| */ | ||
| //#endregion | ||
| //#region src/test-utils/profile-snapshot-fixtures.d.ts | ||
| declare const baselineSnapshot: ProfileSnapshot; | ||
@@ -1339,36 +1324,37 @@ declare const minimalSnapshot: ProfileSnapshot; | ||
| type NegativeSnapshotFixture = { | ||
| readonly name: string; | ||
| readonly value: unknown; | ||
| readonly expectedError: RegExp; | ||
| readonly name: string; | ||
| readonly value: unknown; | ||
| readonly expectedError: RegExp; | ||
| }; | ||
| declare const negativeSnapshotFixtures: readonly NegativeSnapshotFixture[]; | ||
| declare const snapshotFixtures: { | ||
| readonly positive: readonly { | ||
| schemaVersion: 1; | ||
| profile: { | ||
| name: string; | ||
| bodyWeight?: number | undefined; | ||
| }; | ||
| thresholds: { | ||
| cycling?: { | ||
| ftp?: number | undefined; | ||
| } | undefined; | ||
| running?: { | ||
| thresholdPaceSecPerKm?: number | undefined; | ||
| lthr?: number | undefined; | ||
| } | undefined; | ||
| swimming?: { | ||
| cssPaceSecPer100m?: number | undefined; | ||
| } | undefined; | ||
| }; | ||
| heartRate: { | ||
| max?: number | undefined; | ||
| lthr?: number | undefined; | ||
| }; | ||
| generatedAt: string; | ||
| activeSport?: "running" | "cycling" | "swimming" | undefined; | ||
| }[]; | ||
| readonly negative: readonly NegativeSnapshotFixture[]; | ||
| readonly positive: readonly { | ||
| schemaVersion: 1; | ||
| profile: { | ||
| name: string; | ||
| bodyWeight?: number | undefined; | ||
| }; | ||
| activeSport?: "cycling" | "running" | "swimming" | undefined; | ||
| thresholds: { | ||
| cycling?: { | ||
| ftp?: number | undefined; | ||
| } | undefined; | ||
| running?: { | ||
| thresholdPaceSecPerKm?: number | undefined; | ||
| lthr?: number | undefined; | ||
| } | undefined; | ||
| swimming?: { | ||
| cssPaceSecPer100m?: number | undefined; | ||
| } | undefined; | ||
| }; | ||
| heartRate: { | ||
| max?: number | undefined; | ||
| lthr?: number | undefined; | ||
| }; | ||
| generatedAt: string; | ||
| }[]; | ||
| readonly negative: readonly NegativeSnapshotFixture[]; | ||
| }; | ||
| //#endregion | ||
| //#region src/test-utils/tolerance-constants.d.ts | ||
| /** | ||
@@ -1392,3 +1378,4 @@ * Round-trip tolerance constants. | ||
| declare const TOLERANCE_PACE_SEC_PER_M: 0.01; | ||
| //#endregion | ||
| //#region src/test-utils/round-trip-fixtures.d.ts | ||
| /** | ||
@@ -1444,3 +1431,4 @@ * Round-trip test fixtures. | ||
| declare const DEVIATION_PACE: 0.07; | ||
| //#endregion | ||
| export { CADENCE_ACTUAL, CADENCE_EXPECTED, DEVIATION_CADENCE_5RPM, DEVIATION_DISTANCE_10M, DEVIATION_DISTANCE_5M, DEVIATION_HR_10BPM, DEVIATION_HR_5BPM, DEVIATION_PACE, DEVIATION_POWER_10W, DEVIATION_POWER_5W, DEVIATION_TIME_2SEC, DEVIATION_TIME_5SEC, DISTANCE_ACTUAL_M, DISTANCE_EXPECTED_M, FIXTURE_NAMES, HR_ACTUAL, HR_ACTUAL_HIGH, HR_EXPECTED, LAP_DISTANCE_ACTUAL_M, LAP_DISTANCE_EXPECTED_M, LAP_TIME_ACTUAL_SEC, LAP_TIME_EXPECTED_SEC, type NegativeSnapshotFixture, POWER_ACTUAL, POWER_ACTUAL_HIGH, POWER_EXPECTED, RECORD_DISTANCE_ACTUAL_M, RECORD_DISTANCE_EXPECTED_M, RECORD_SPEED_ACTUAL_MPS, RECORD_SPEED_EXPECTED_MPS, TIME_ACTUAL_SEC, TIME_EXPECTED_SEC, TOLERANCE_CADENCE_RPM, TOLERANCE_DISTANCE_M, TOLERANCE_HR_BPM, TOLERANCE_PACE_SEC_PER_M, TOLERANCE_POWER_WATTS, TOLERANCE_TIME_SEC, VIOLATION_COUNT_FULL_SESSION, VIOLATION_COUNT_LAP, VIOLATION_COUNT_RECORD, baselineSnapshot, buildDuration, buildKRD, buildKRDEvent, buildKRDLap, buildKRDMetadata, buildKRDRecord, buildKRDSession, buildTarget, buildWorkout, buildWorkoutStep, createFitBufferSample, createMockLogger, getFixturePath, loadFitFixture, loadFixturePair, loadKrdFixture, loadKrdFixtureRaw, loadTcxFixture, loadZwoFixture, minimalSnapshot, negativeSnapshotFixtures, partialZoneSnapshot, positiveSnapshotFixtures, snapshotFixtures }; | ||
| //# sourceMappingURL=index.d.ts.map |
+1025
-624
@@ -1,656 +0,1057 @@ | ||
| import { readFileSync } from 'fs'; | ||
| import { join } from 'path'; | ||
| import { faker } from '@faker-js/faker'; | ||
| import { Factory } from 'rosie'; | ||
| // src/test-utils/fixtures.ts | ||
| var FIXTURES_DIR = join(__dirname, "../../../../test-fixtures"); | ||
| var loadFitFixture = (filename) => { | ||
| const path = join(FIXTURES_DIR, "fit", filename); | ||
| return readFileSync(path); | ||
| import { readFileSync } from "fs"; | ||
| import { join } from "path"; | ||
| import { faker } from "@faker-js/faker"; | ||
| import { Factory } from "rosie"; | ||
| //#region src/test-utils/fixtures.ts | ||
| /** | ||
| * Test Fixture Helpers | ||
| * | ||
| * Utilities for loading shared test fixtures across packages. | ||
| */ | ||
| /** | ||
| * Base path to fixtures directory | ||
| * Points to shared test-fixtures at monorepo root | ||
| * From packages/core/src/test-utils/ or packages/core/dist/test-utils/ | ||
| * Goes up 4 levels to reach monorepo root, then into test-fixtures/ | ||
| */ | ||
| const FIXTURES_DIR = join(__dirname, "../../../../test-fixtures"); | ||
| /** | ||
| * Load a FIT file fixture as a buffer | ||
| * | ||
| * @param filename - Name of the FIT file (e.g., "WorkoutIndividualSteps.fit") | ||
| * @returns Buffer containing the FIT file data | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const fitBuffer = loadFitFixture("WorkoutIndividualSteps.fit"); | ||
| * const krd = await fitReader.readToKRD(fitBuffer); | ||
| * ``` | ||
| */ | ||
| const loadFitFixture = (filename) => { | ||
| return readFileSync(join(FIXTURES_DIR, "fit", filename)); | ||
| }; | ||
| var loadKrdFixture = (filename) => { | ||
| const path = join(FIXTURES_DIR, "krd", filename); | ||
| const json = readFileSync(path, "utf-8"); | ||
| return JSON.parse(json); | ||
| /** | ||
| * Load a KRD file fixture as a parsed object | ||
| * | ||
| * @param filename - Name of the KRD file (e.g., "WorkoutIndividualSteps.krd") | ||
| * @returns Parsed KRD object | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const krd = loadKrdFixture("WorkoutIndividualSteps.krd"); | ||
| * expect(krd.version).toBe("1.0"); | ||
| * ``` | ||
| */ | ||
| const loadKrdFixture = (filename) => { | ||
| const json = readFileSync(join(FIXTURES_DIR, "krd", filename), "utf-8"); | ||
| return JSON.parse(json); | ||
| }; | ||
| var loadKrdFixtureRaw = (filename) => { | ||
| const path = join(FIXTURES_DIR, "krd", filename); | ||
| return readFileSync(path, "utf-8"); | ||
| /** | ||
| * Load a KRD file fixture as raw JSON string | ||
| * | ||
| * @param filename - Name of the KRD file (e.g., "WorkoutIndividualSteps.krd") | ||
| * @returns Raw JSON string | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const jsonString = loadKrdFixtureRaw("WorkoutIndividualSteps.krd"); | ||
| * const krd = JSON.parse(jsonString); | ||
| * ``` | ||
| */ | ||
| const loadKrdFixtureRaw = (filename) => { | ||
| return readFileSync(join(FIXTURES_DIR, "krd", filename), "utf-8"); | ||
| }; | ||
| var loadTcxFixture = (filename) => { | ||
| const path = join(FIXTURES_DIR, "tcx", filename); | ||
| return readFileSync(path, "utf-8"); | ||
| /** | ||
| * Load a TCX file fixture as a string | ||
| * | ||
| * @param filename - Name of the TCX file (e.g., "WorkoutHeartRateTargets.tcx") | ||
| * @returns TCX XML string | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const tcxString = loadTcxFixture("WorkoutHeartRateTargets.tcx"); | ||
| * const krd = await tcxReader.readToKRD(tcxString); | ||
| * ``` | ||
| */ | ||
| const loadTcxFixture = (filename) => { | ||
| return readFileSync(join(FIXTURES_DIR, "tcx", filename), "utf-8"); | ||
| }; | ||
| var loadZwoFixture = (filename) => { | ||
| const path = join(FIXTURES_DIR, "zwo", filename); | ||
| return readFileSync(path, "utf-8"); | ||
| /** | ||
| * Load a ZWO file fixture as a string | ||
| * | ||
| * @param filename - Name of the ZWO file (e.g., "WorkoutIndividualSteps.zwo") | ||
| * @returns ZWO XML string | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const zwoString = loadZwoFixture("WorkoutIndividualSteps.zwo"); | ||
| * const krd = await zwoReader.readToKRD(zwoString); | ||
| * ``` | ||
| */ | ||
| const loadZwoFixture = (filename) => { | ||
| return readFileSync(join(FIXTURES_DIR, "zwo", filename), "utf-8"); | ||
| }; | ||
| var getFixturePath = (type, filename) => { | ||
| return join(FIXTURES_DIR, type, filename); | ||
| /** | ||
| * Get the full path to a fixture file | ||
| * | ||
| * @param type - Type of fixture ("fit", "krd", "tcx", or "zwo") | ||
| * @param filename - Name of the file | ||
| * @returns Full path to the fixture file | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const path = getFixturePath("fit", "WorkoutIndividualSteps.fit"); | ||
| * const buffer = readFileSync(path); | ||
| * ``` | ||
| */ | ||
| const getFixturePath = (type, filename) => { | ||
| return join(FIXTURES_DIR, type, filename); | ||
| }; | ||
| var FIXTURE_NAMES = { | ||
| INDIVIDUAL_STEPS: "WorkoutIndividualSteps", | ||
| REPEAT_STEPS: "WorkoutRepeatSteps", | ||
| CUSTOM_TARGET_VALUES: "WorkoutCustomTargetValues", | ||
| REPEAT_GREATER_THAN: "WorkoutRepeatGreaterThanStep" | ||
| /** | ||
| * Available fixture names (without extension) | ||
| */ | ||
| const FIXTURE_NAMES = { | ||
| INDIVIDUAL_STEPS: "WorkoutIndividualSteps", | ||
| REPEAT_STEPS: "WorkoutRepeatSteps", | ||
| CUSTOM_TARGET_VALUES: "WorkoutCustomTargetValues", | ||
| REPEAT_GREATER_THAN: "WorkoutRepeatGreaterThanStep" | ||
| }; | ||
| var loadFixturePair = (baseName) => { | ||
| return { | ||
| fit: loadFitFixture(`${baseName}.fit`), | ||
| krd: loadKrdFixture(`${baseName}.krd`) | ||
| }; | ||
| /** | ||
| * Load a fixture pair (FIT + KRD) for round-trip testing | ||
| * | ||
| * @param baseName - Base name without extension (e.g., "WorkoutIndividualSteps") | ||
| * @returns Object with both FIT buffer and KRD object | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const { fit, krd } = loadFixturePair("WorkoutIndividualSteps"); | ||
| * const converted = await fitReader.readToKRD(fit); | ||
| * expect(converted).toEqual(krd); | ||
| * ``` | ||
| */ | ||
| const loadFixturePair = (baseName) => { | ||
| return { | ||
| fit: loadFitFixture(`${baseName}.fit`), | ||
| krd: loadKrdFixture(`${baseName}.krd`) | ||
| }; | ||
| }; | ||
| // src/tests/helpers/test-utils.ts | ||
| var createMockLogger = () => ({ | ||
| debug: (...args) => { | ||
| if (process.env.DEBUG_LOGS) console.log("[DEBUG]", ...args); | ||
| }, | ||
| info: (...args) => { | ||
| if (process.env.DEBUG_LOGS) console.log("[INFO]", ...args); | ||
| }, | ||
| warn: (...args) => { | ||
| if (process.env.DEBUG_LOGS) console.log("[WARN]", ...args); | ||
| }, | ||
| error: (...args) => { | ||
| if (process.env.DEBUG_LOGS) console.error("[ERROR]", ...args); | ||
| } | ||
| //#endregion | ||
| //#region src/tests/helpers/test-utils.ts | ||
| const createMockLogger = () => ({ | ||
| debug: (...args) => { | ||
| if (process.env.DEBUG_LOGS) console.log("[DEBUG]", ...args); | ||
| }, | ||
| info: (...args) => { | ||
| if (process.env.DEBUG_LOGS) console.log("[INFO]", ...args); | ||
| }, | ||
| warn: (...args) => { | ||
| if (process.env.DEBUG_LOGS) console.log("[WARN]", ...args); | ||
| }, | ||
| error: (...args) => { | ||
| if (process.env.DEBUG_LOGS) console.error("[ERROR]", ...args); | ||
| } | ||
| }); | ||
| var buildKRDEvent = new Factory().attr("timestamp", () => faker.date.recent().toISOString()).attr( | ||
| "eventType", | ||
| () => faker.helpers.arrayElement([ | ||
| "event_start", | ||
| "event_stop", | ||
| "event_pause", | ||
| "event_resume", | ||
| "event_lap", | ||
| "event_marker", | ||
| "event_timer" | ||
| ]) | ||
| ).attr("eventGroup", () => faker.number.int({ max: 10, min: 0 })).attr("data", () => faker.number.int({ max: 255, min: 0 })); | ||
| var buildKRDLap = new Factory().attr("startTime", () => faker.date.recent().toISOString()).attr("totalElapsedTime", () => faker.number.int({ max: 1800, min: 30 })).attr("totalDistance", () => faker.number.int({ max: 1e4, min: 100 })).attr("avgHeartRate", () => faker.number.int({ max: 200, min: 60 })).attr("maxHeartRate", () => faker.number.int({ max: 220, min: 100 })).attr("avgCadence", () => faker.number.int({ max: 120, min: 60 })).attr("avgPower", () => faker.number.int({ max: 400, min: 100 })); | ||
| // src/test-utils/tolerance-constants.ts | ||
| var TOLERANCE_TIME_SEC = 1; | ||
| var TOLERANCE_POWER_WATTS = 1; | ||
| var TOLERANCE_HR_BPM = 1; | ||
| var TOLERANCE_CADENCE_RPM = 1; | ||
| var TOLERANCE_DISTANCE_M = 1; | ||
| var TOLERANCE_PACE_SEC_PER_M = 0.01; | ||
| var FAKER_SERIAL_NUMBER_DIGITS = 10; | ||
| var WORKOUT_STEP_NOTES_MAX_LENGTH = 256; | ||
| // src/tests/fixtures/krd/metadata.fixtures.ts | ||
| var buildKRDMetadata = new Factory().attr("created", () => faker.date.recent().toISOString()).attr( | ||
| "manufacturer", | ||
| () => faker.helpers.arrayElement(["garmin", "wahoo", "polar", "suunto"]) | ||
| ).attr( | ||
| "product", | ||
| () => faker.helpers.arrayElement(["fenix7", "edge530", "forerunner945", "elemnt"]) | ||
| ).attr("serialNumber", () => faker.string.numeric(FAKER_SERIAL_NUMBER_DIGITS)).attr( | ||
| "sport", | ||
| () => faker.helpers.arrayElement(["running", "cycling", "swimming"]) | ||
| ).attr( | ||
| "subSport", | ||
| () => faker.helpers.arrayElement(["trail", "road", "track", "indoor"]) | ||
| ); | ||
| var buildKRDRecord = new Factory().attr("timestamp", () => faker.date.recent().toISOString()).attr("position", () => ({ | ||
| lat: faker.location.latitude(), | ||
| lon: faker.location.longitude() | ||
| })).attr("altitude", () => faker.number.float({ max: 3e3, min: 0 })).attr("heartRate", () => faker.number.int({ max: 200, min: 60 })).attr("cadence", () => faker.number.int({ max: 120, min: 60 })).attr("power", () => faker.number.int({ max: 500, min: 0 })).attr( | ||
| "speed", | ||
| () => faker.number.float({ fractionDigits: 2, max: 15, min: 0 }) | ||
| ).attr("distance", () => faker.number.int({ max: 5e4, min: 0 })); | ||
| var buildKRDSession = new Factory().attr("startTime", () => faker.date.recent().toISOString()).attr("totalElapsedTime", () => faker.number.int({ max: 7200, min: 60 })).attr("totalTimerTime", () => faker.number.int({ max: 7200, min: 60 })).attr("totalDistance", () => faker.number.int({ max: 5e4, min: 1e3 })).attr( | ||
| "sport", | ||
| () => faker.helpers.arrayElement(["running", "cycling", "swimming"]) | ||
| ).attr( | ||
| "subSport", | ||
| () => faker.helpers.arrayElement(["trail", "road", "track", "indoor"]) | ||
| ).attr("avgHeartRate", () => faker.number.int({ max: 200, min: 60 })).attr("maxHeartRate", () => faker.number.int({ max: 220, min: 100 })).attr("avgCadence", () => faker.number.int({ max: 120, min: 60 })).attr("avgPower", () => faker.number.int({ max: 400, min: 100 })).attr("totalCalories", () => faker.number.int({ max: 2e3, min: 100 })); | ||
| // src/tests/fixtures/krd/krd.fixtures.ts | ||
| var buildKRD = new Factory().attr("version", () => "1.0").attr( | ||
| "type", | ||
| () => faker.helpers.arrayElement([ | ||
| "structured_workout", | ||
| "recorded_activity", | ||
| "course" | ||
| ]) | ||
| ).attr("metadata", () => buildKRDMetadata.build()).attr("sessions", () => [buildKRDSession.build()]).attr("laps", () => [buildKRDLap.build(), buildKRDLap.build()]).attr("records", () => [ | ||
| buildKRDRecord.build(), | ||
| buildKRDRecord.build(), | ||
| buildKRDRecord.build() | ||
| ]).attr("events", () => [buildKRDEvent.build()]).attr("extensions", () => ({ | ||
| fit: { | ||
| developerFields: [] | ||
| } | ||
| //#endregion | ||
| //#region src/tests/fixtures/krd/event.fixtures.ts | ||
| const buildKRDEvent = new Factory().attr("timestamp", () => faker.date.recent().toISOString()).attr("eventType", () => faker.helpers.arrayElement([ | ||
| "event_start", | ||
| "event_stop", | ||
| "event_pause", | ||
| "event_resume", | ||
| "event_lap", | ||
| "event_marker", | ||
| "event_timer" | ||
| ])).attr("eventGroup", () => faker.number.int({ | ||
| max: 10, | ||
| min: 0 | ||
| })).attr("data", () => faker.number.int({ | ||
| max: 255, | ||
| min: 0 | ||
| })); | ||
| var buildWorkoutStep = new Factory().attr("stepIndex", () => faker.number.int({ max: 50, min: 0 })).attr("name", () => faker.lorem.words({ max: 3, min: 1 })).attr( | ||
| "durationType", | ||
| () => faker.helpers.arrayElement(["time", "distance", "open"]) | ||
| ).attr("duration", ["durationType"], (durationType) => { | ||
| if (durationType === "time") { | ||
| return { | ||
| type: "time", | ||
| seconds: faker.number.int({ max: 3600, min: 30 }) | ||
| }; | ||
| } else if (durationType === "distance") { | ||
| return { | ||
| type: "distance", | ||
| meters: faker.number.int({ max: 1e4, min: 100 }) | ||
| }; | ||
| } else { | ||
| return { type: "open" }; | ||
| } | ||
| }).attr( | ||
| "targetType", | ||
| () => faker.helpers.arrayElement([ | ||
| "power", | ||
| "heart_rate", | ||
| "cadence", | ||
| "pace", | ||
| "open" | ||
| ]) | ||
| ).attr("target", ["targetType"], (targetType) => { | ||
| if (targetType === "power") { | ||
| const unit = faker.helpers.arrayElement([ | ||
| "watts", | ||
| "percent_ftp", | ||
| "zone", | ||
| "range" | ||
| ]); | ||
| if (unit === "watts") { | ||
| return { | ||
| type: "power", | ||
| value: { | ||
| unit: "watts", | ||
| value: faker.number.int({ max: 400, min: 100 }) | ||
| } | ||
| }; | ||
| } else if (unit === "percent_ftp") { | ||
| return { | ||
| type: "power", | ||
| value: { | ||
| unit: "percent_ftp", | ||
| value: faker.number.int({ max: 150, min: 50 }) | ||
| } | ||
| }; | ||
| } else if (unit === "zone") { | ||
| return { | ||
| type: "power", | ||
| value: { | ||
| unit: "zone", | ||
| value: faker.number.int({ max: 7, min: 1 }) | ||
| } | ||
| }; | ||
| } else { | ||
| return { | ||
| type: "power", | ||
| value: { | ||
| unit: "range", | ||
| min: faker.number.int({ max: 200, min: 100 }), | ||
| max: faker.number.int({ max: 400, min: 250 }) | ||
| } | ||
| }; | ||
| } | ||
| } else if (targetType === "heart_rate") { | ||
| const unit = faker.helpers.arrayElement([ | ||
| "bpm", | ||
| "zone", | ||
| "percent_max", | ||
| "range" | ||
| ]); | ||
| if (unit === "bpm") { | ||
| return { | ||
| type: "heart_rate", | ||
| value: { | ||
| unit: "bpm", | ||
| value: faker.number.int({ max: 200, min: 60 }) | ||
| } | ||
| }; | ||
| } else if (unit === "zone") { | ||
| return { | ||
| type: "heart_rate", | ||
| value: { | ||
| unit: "zone", | ||
| value: faker.number.int({ max: 5, min: 1 }) | ||
| } | ||
| }; | ||
| } else if (unit === "percent_max") { | ||
| return { | ||
| type: "heart_rate", | ||
| value: { | ||
| unit: "percent_max", | ||
| value: faker.number.int({ max: 100, min: 50 }) | ||
| } | ||
| }; | ||
| } else { | ||
| return { | ||
| type: "heart_rate", | ||
| value: { | ||
| unit: "range", | ||
| min: faker.number.int({ max: 140, min: 100 }), | ||
| max: faker.number.int({ max: 180, min: 150 }) | ||
| } | ||
| }; | ||
| } | ||
| } else if (targetType === "cadence") { | ||
| const unit = faker.helpers.arrayElement(["rpm", "range"]); | ||
| if (unit === "rpm") { | ||
| return { | ||
| type: "cadence", | ||
| value: { | ||
| unit: "rpm", | ||
| value: faker.number.int({ max: 120, min: 60 }) | ||
| } | ||
| }; | ||
| } else { | ||
| return { | ||
| type: "cadence", | ||
| value: { | ||
| unit: "range", | ||
| min: faker.number.int({ max: 80, min: 60 }), | ||
| max: faker.number.int({ max: 110, min: 90 }) | ||
| } | ||
| }; | ||
| } | ||
| } else if (targetType === "pace") { | ||
| const unit = faker.helpers.arrayElement([ | ||
| "mps", | ||
| "zone", | ||
| "range" | ||
| ]); | ||
| if (unit === "mps") { | ||
| return { | ||
| type: "pace", | ||
| value: { | ||
| unit: "mps", | ||
| value: faker.number.float({ fractionDigits: 2, max: 6, min: 2 }) | ||
| } | ||
| }; | ||
| } else if (unit === "zone") { | ||
| return { | ||
| type: "pace", | ||
| value: { | ||
| unit: "zone", | ||
| value: faker.number.int({ max: 5, min: 1 }) | ||
| } | ||
| }; | ||
| } else { | ||
| return { | ||
| type: "pace", | ||
| value: { | ||
| unit: "range", | ||
| min: faker.number.float({ fractionDigits: 2, max: 4, min: 2 }), | ||
| max: faker.number.float({ fractionDigits: 2, max: 6, min: 4.5 }) | ||
| } | ||
| }; | ||
| } | ||
| } else { | ||
| return { type: "open" }; | ||
| } | ||
| }).attr( | ||
| "intensity", | ||
| () => faker.helpers.arrayElement([ | ||
| "warmup", | ||
| "active", | ||
| "cooldown", | ||
| "rest", | ||
| "recovery", | ||
| "interval", | ||
| "other" | ||
| ]) | ||
| ).attr( | ||
| "notes", | ||
| () => faker.lorem.sentence({ max: 20, min: 3 }).slice(0, WORKOUT_STEP_NOTES_MAX_LENGTH) | ||
| ); | ||
| var buildRepetitionBlock = new Factory().attr("repeatCount", () => faker.number.int({ max: 10, min: 2 })).attr("steps", () => [buildWorkoutStep.build(), buildWorkoutStep.build()]); | ||
| // src/tests/fixtures/workout/workout.fixtures.ts | ||
| var SUB_SPORTS = { | ||
| running: ["trail", "street", "track", "treadmill"], | ||
| cycling: ["road", "mountain", "gravel_cycling", "indoor_cycling"], | ||
| swimming: ["lap_swimming", "open_water"], | ||
| generic: ["generic"] | ||
| //#endregion | ||
| //#region src/tests/fixtures/krd/lap.fixtures.ts | ||
| const buildKRDLap = new Factory().attr("startTime", () => faker.date.recent().toISOString()).attr("totalElapsedTime", () => faker.number.int({ | ||
| max: 1800, | ||
| min: 30 | ||
| })).attr("totalDistance", () => faker.number.int({ | ||
| max: 1e4, | ||
| min: 100 | ||
| })).attr("avgHeartRate", () => faker.number.int({ | ||
| max: 200, | ||
| min: 60 | ||
| })).attr("maxHeartRate", () => faker.number.int({ | ||
| max: 220, | ||
| min: 100 | ||
| })).attr("avgCadence", () => faker.number.int({ | ||
| max: 120, | ||
| min: 60 | ||
| })).attr("avgPower", () => faker.number.int({ | ||
| max: 400, | ||
| min: 100 | ||
| })); | ||
| //#endregion | ||
| //#region src/test-utils/tolerance-constants.ts | ||
| /** | ||
| * Round-trip tolerance constants. | ||
| * | ||
| * These values mirror the documented tolerances from CLAUDE.md: | ||
| * time ±1s, power ±1W or ±1%FTP, HR ±1bpm, cadence ±1rpm. | ||
| * | ||
| * Distance and pace tolerances are derived from the same domain | ||
| * conventions used by the round-trip validator. | ||
| * | ||
| * Centralised so test files can reference named values instead of | ||
| * sprinkling magic numbers across assertions. | ||
| */ | ||
| const TOLERANCE_TIME_SEC = 1; | ||
| const TOLERANCE_POWER_WATTS = 1; | ||
| const TOLERANCE_HR_BPM = 1; | ||
| const TOLERANCE_CADENCE_RPM = 1; | ||
| const TOLERANCE_DISTANCE_M = 1; | ||
| const TOLERANCE_PACE_SEC_PER_M = .01; | ||
| //#endregion | ||
| //#region src/tests/fixtures/krd/metadata.fixtures.ts | ||
| const buildKRDMetadata = new Factory().attr("created", () => faker.date.recent().toISOString()).attr("manufacturer", () => faker.helpers.arrayElement([ | ||
| "garmin", | ||
| "wahoo", | ||
| "polar", | ||
| "suunto" | ||
| ])).attr("product", () => faker.helpers.arrayElement([ | ||
| "fenix7", | ||
| "edge530", | ||
| "forerunner945", | ||
| "elemnt" | ||
| ])).attr("serialNumber", () => faker.string.numeric(10)).attr("sport", () => faker.helpers.arrayElement([ | ||
| "running", | ||
| "cycling", | ||
| "swimming" | ||
| ])).attr("subSport", () => faker.helpers.arrayElement([ | ||
| "trail", | ||
| "road", | ||
| "track", | ||
| "indoor" | ||
| ])); | ||
| //#endregion | ||
| //#region src/tests/fixtures/krd/record.fixtures.ts | ||
| const buildKRDRecord = new Factory().attr("timestamp", () => faker.date.recent().toISOString()).attr("position", () => ({ | ||
| lat: faker.location.latitude(), | ||
| lon: faker.location.longitude() | ||
| })).attr("altitude", () => faker.number.float({ | ||
| max: 3e3, | ||
| min: 0 | ||
| })).attr("heartRate", () => faker.number.int({ | ||
| max: 200, | ||
| min: 60 | ||
| })).attr("cadence", () => faker.number.int({ | ||
| max: 120, | ||
| min: 60 | ||
| })).attr("power", () => faker.number.int({ | ||
| max: 500, | ||
| min: 0 | ||
| })).attr("speed", () => faker.number.float({ | ||
| fractionDigits: 2, | ||
| max: 15, | ||
| min: 0 | ||
| })).attr("distance", () => faker.number.int({ | ||
| max: 5e4, | ||
| min: 0 | ||
| })); | ||
| //#endregion | ||
| //#region src/tests/fixtures/krd/session.fixtures.ts | ||
| const buildKRDSession = new Factory().attr("startTime", () => faker.date.recent().toISOString()).attr("totalElapsedTime", () => faker.number.int({ | ||
| max: 7200, | ||
| min: 60 | ||
| })).attr("totalTimerTime", () => faker.number.int({ | ||
| max: 7200, | ||
| min: 60 | ||
| })).attr("totalDistance", () => faker.number.int({ | ||
| max: 5e4, | ||
| min: 1e3 | ||
| })).attr("sport", () => faker.helpers.arrayElement([ | ||
| "running", | ||
| "cycling", | ||
| "swimming" | ||
| ])).attr("subSport", () => faker.helpers.arrayElement([ | ||
| "trail", | ||
| "road", | ||
| "track", | ||
| "indoor" | ||
| ])).attr("avgHeartRate", () => faker.number.int({ | ||
| max: 200, | ||
| min: 60 | ||
| })).attr("maxHeartRate", () => faker.number.int({ | ||
| max: 220, | ||
| min: 100 | ||
| })).attr("avgCadence", () => faker.number.int({ | ||
| max: 120, | ||
| min: 60 | ||
| })).attr("avgPower", () => faker.number.int({ | ||
| max: 400, | ||
| min: 100 | ||
| })).attr("totalCalories", () => faker.number.int({ | ||
| max: 2e3, | ||
| min: 100 | ||
| })); | ||
| //#endregion | ||
| //#region src/tests/fixtures/krd/krd.fixtures.ts | ||
| const buildKRD = new Factory().attr("version", () => "1.0").attr("type", () => faker.helpers.arrayElement([ | ||
| "structured_workout", | ||
| "recorded_activity", | ||
| "course" | ||
| ])).attr("metadata", () => buildKRDMetadata.build()).attr("sessions", () => [buildKRDSession.build()]).attr("laps", () => [buildKRDLap.build(), buildKRDLap.build()]).attr("records", () => [ | ||
| buildKRDRecord.build(), | ||
| buildKRDRecord.build(), | ||
| buildKRDRecord.build() | ||
| ]).attr("events", () => [buildKRDEvent.build()]).attr("extensions", () => ({ fit: { developerFields: [] } })); | ||
| //#endregion | ||
| //#region src/tests/fixtures/workout/workout-step.fixtures.ts | ||
| const buildWorkoutStep = new Factory().attr("stepIndex", () => faker.number.int({ | ||
| max: 50, | ||
| min: 0 | ||
| })).attr("name", () => faker.lorem.words({ | ||
| max: 3, | ||
| min: 1 | ||
| })).attr("durationType", () => faker.helpers.arrayElement([ | ||
| "time", | ||
| "distance", | ||
| "open" | ||
| ])).attr("duration", ["durationType"], (durationType) => { | ||
| if (durationType === "time") return { | ||
| type: "time", | ||
| seconds: faker.number.int({ | ||
| max: 3600, | ||
| min: 30 | ||
| }) | ||
| }; | ||
| else if (durationType === "distance") return { | ||
| type: "distance", | ||
| meters: faker.number.int({ | ||
| max: 1e4, | ||
| min: 100 | ||
| }) | ||
| }; | ||
| else return { type: "open" }; | ||
| }).attr("targetType", () => faker.helpers.arrayElement([ | ||
| "power", | ||
| "heart_rate", | ||
| "cadence", | ||
| "pace", | ||
| "open" | ||
| ])).attr("target", ["targetType"], (targetType) => { | ||
| if (targetType === "power") { | ||
| const unit = faker.helpers.arrayElement([ | ||
| "watts", | ||
| "percent_ftp", | ||
| "zone", | ||
| "range" | ||
| ]); | ||
| if (unit === "watts") return { | ||
| type: "power", | ||
| value: { | ||
| unit: "watts", | ||
| value: faker.number.int({ | ||
| max: 400, | ||
| min: 100 | ||
| }) | ||
| } | ||
| }; | ||
| else if (unit === "percent_ftp") return { | ||
| type: "power", | ||
| value: { | ||
| unit: "percent_ftp", | ||
| value: faker.number.int({ | ||
| max: 150, | ||
| min: 50 | ||
| }) | ||
| } | ||
| }; | ||
| else if (unit === "zone") return { | ||
| type: "power", | ||
| value: { | ||
| unit: "zone", | ||
| value: faker.number.int({ | ||
| max: 7, | ||
| min: 1 | ||
| }) | ||
| } | ||
| }; | ||
| else return { | ||
| type: "power", | ||
| value: { | ||
| unit: "range", | ||
| min: faker.number.int({ | ||
| max: 200, | ||
| min: 100 | ||
| }), | ||
| max: faker.number.int({ | ||
| max: 400, | ||
| min: 250 | ||
| }) | ||
| } | ||
| }; | ||
| } else if (targetType === "heart_rate") { | ||
| const unit = faker.helpers.arrayElement([ | ||
| "bpm", | ||
| "zone", | ||
| "percent_max", | ||
| "range" | ||
| ]); | ||
| if (unit === "bpm") return { | ||
| type: "heart_rate", | ||
| value: { | ||
| unit: "bpm", | ||
| value: faker.number.int({ | ||
| max: 200, | ||
| min: 60 | ||
| }) | ||
| } | ||
| }; | ||
| else if (unit === "zone") return { | ||
| type: "heart_rate", | ||
| value: { | ||
| unit: "zone", | ||
| value: faker.number.int({ | ||
| max: 5, | ||
| min: 1 | ||
| }) | ||
| } | ||
| }; | ||
| else if (unit === "percent_max") return { | ||
| type: "heart_rate", | ||
| value: { | ||
| unit: "percent_max", | ||
| value: faker.number.int({ | ||
| max: 100, | ||
| min: 50 | ||
| }) | ||
| } | ||
| }; | ||
| else return { | ||
| type: "heart_rate", | ||
| value: { | ||
| unit: "range", | ||
| min: faker.number.int({ | ||
| max: 140, | ||
| min: 100 | ||
| }), | ||
| max: faker.number.int({ | ||
| max: 180, | ||
| min: 150 | ||
| }) | ||
| } | ||
| }; | ||
| } else if (targetType === "cadence") if (faker.helpers.arrayElement(["rpm", "range"]) === "rpm") return { | ||
| type: "cadence", | ||
| value: { | ||
| unit: "rpm", | ||
| value: faker.number.int({ | ||
| max: 120, | ||
| min: 60 | ||
| }) | ||
| } | ||
| }; | ||
| else return { | ||
| type: "cadence", | ||
| value: { | ||
| unit: "range", | ||
| min: faker.number.int({ | ||
| max: 80, | ||
| min: 60 | ||
| }), | ||
| max: faker.number.int({ | ||
| max: 110, | ||
| min: 90 | ||
| }) | ||
| } | ||
| }; | ||
| else if (targetType === "pace") { | ||
| const unit = faker.helpers.arrayElement([ | ||
| "mps", | ||
| "zone", | ||
| "range" | ||
| ]); | ||
| if (unit === "mps") return { | ||
| type: "pace", | ||
| value: { | ||
| unit: "mps", | ||
| value: faker.number.float({ | ||
| fractionDigits: 2, | ||
| max: 6, | ||
| min: 2 | ||
| }) | ||
| } | ||
| }; | ||
| else if (unit === "zone") return { | ||
| type: "pace", | ||
| value: { | ||
| unit: "zone", | ||
| value: faker.number.int({ | ||
| max: 5, | ||
| min: 1 | ||
| }) | ||
| } | ||
| }; | ||
| else return { | ||
| type: "pace", | ||
| value: { | ||
| unit: "range", | ||
| min: faker.number.float({ | ||
| fractionDigits: 2, | ||
| max: 4, | ||
| min: 2 | ||
| }), | ||
| max: faker.number.float({ | ||
| fractionDigits: 2, | ||
| max: 6, | ||
| min: 4.5 | ||
| }) | ||
| } | ||
| }; | ||
| } else return { type: "open" }; | ||
| }).attr("intensity", () => faker.helpers.arrayElement([ | ||
| "warmup", | ||
| "active", | ||
| "cooldown", | ||
| "rest", | ||
| "recovery", | ||
| "interval", | ||
| "other" | ||
| ])).attr("notes", () => faker.lorem.sentence({ | ||
| max: 20, | ||
| min: 3 | ||
| }).slice(0, 256)); | ||
| //#endregion | ||
| //#region src/tests/fixtures/workout/repetition-block.fixtures.ts | ||
| const buildRepetitionBlock = new Factory().attr("repeatCount", () => faker.number.int({ | ||
| max: 10, | ||
| min: 2 | ||
| })).attr("steps", () => [buildWorkoutStep.build(), buildWorkoutStep.build()]); | ||
| //#endregion | ||
| //#region src/tests/fixtures/workout/workout.fixtures.ts | ||
| const SUB_SPORTS = { | ||
| running: [ | ||
| "trail", | ||
| "street", | ||
| "track", | ||
| "treadmill" | ||
| ], | ||
| cycling: [ | ||
| "road", | ||
| "mountain", | ||
| "gravel_cycling", | ||
| "indoor_cycling" | ||
| ], | ||
| swimming: ["lap_swimming", "open_water"], | ||
| generic: ["generic"] | ||
| }; | ||
| var buildWorkout = new Factory().attr("name", () => faker.lorem.words({ max: 5, min: 1 })).attr( | ||
| "sport", | ||
| () => faker.helpers.arrayElement(["running", "cycling", "swimming"]) | ||
| ).attr( | ||
| "subSport", | ||
| ["sport"], | ||
| (sport) => faker.helpers.arrayElement(SUB_SPORTS[sport] ?? ["generic"]) | ||
| ).attr("steps", () => [ | ||
| buildWorkoutStep.build(), | ||
| buildRepetitionBlock.build(), | ||
| buildWorkoutStep.build() | ||
| const buildWorkout = new Factory().attr("name", () => faker.lorem.words({ | ||
| max: 5, | ||
| min: 1 | ||
| })).attr("sport", () => faker.helpers.arrayElement([ | ||
| "running", | ||
| "cycling", | ||
| "swimming" | ||
| ])).attr("subSport", ["sport"], (sport) => faker.helpers.arrayElement(SUB_SPORTS[sport] ?? ["generic"])).attr("steps", () => [ | ||
| buildWorkoutStep.build(), | ||
| buildRepetitionBlock.build(), | ||
| buildWorkoutStep.build() | ||
| ]); | ||
| var DURATION_TYPES = [ | ||
| "time", | ||
| "distance", | ||
| "heart_rate_less_than", | ||
| "repeat_until_heart_rate_greater_than", | ||
| "calories", | ||
| "power_less_than", | ||
| "power_greater_than", | ||
| "repeat_until_time", | ||
| "repeat_until_distance", | ||
| "repeat_until_calories", | ||
| "repeat_until_heart_rate_less_than", | ||
| "repeat_until_power_less_than", | ||
| "repeat_until_power_greater_than", | ||
| "open" | ||
| //#endregion | ||
| //#region src/tests/fixtures/workout/duration.fixtures.ts | ||
| const DURATION_TYPES = [ | ||
| "time", | ||
| "distance", | ||
| "heart_rate_less_than", | ||
| "repeat_until_heart_rate_greater_than", | ||
| "calories", | ||
| "power_less_than", | ||
| "power_greater_than", | ||
| "repeat_until_time", | ||
| "repeat_until_distance", | ||
| "repeat_until_calories", | ||
| "repeat_until_heart_rate_less_than", | ||
| "repeat_until_power_less_than", | ||
| "repeat_until_power_greater_than", | ||
| "open" | ||
| ]; | ||
| var repeatFrom = () => faker.number.int({ max: 10, min: 0 }); | ||
| var seconds = () => faker.number.int({ max: 3600, min: 30 }); | ||
| var meters = () => faker.number.int({ max: 1e4, min: 100 }); | ||
| var bpm = () => faker.number.int({ max: 200, min: 60 }); | ||
| var watts = () => faker.number.int({ max: 400, min: 100 }); | ||
| var calories = () => faker.number.int({ max: 1e3, min: 50 }); | ||
| var DURATION_BUILDERS = { | ||
| time: () => ({ type: "time", seconds: seconds() }), | ||
| distance: () => ({ type: "distance", meters: meters() }), | ||
| heart_rate_less_than: () => ({ type: "heart_rate_less_than", bpm: bpm() }), | ||
| repeat_until_heart_rate_greater_than: () => ({ | ||
| type: "repeat_until_heart_rate_greater_than", | ||
| bpm: bpm(), | ||
| repeatFrom: repeatFrom() | ||
| }), | ||
| calories: () => ({ type: "calories", calories: calories() }), | ||
| power_less_than: () => ({ type: "power_less_than", watts: watts() }), | ||
| power_greater_than: () => ({ type: "power_greater_than", watts: watts() }), | ||
| repeat_until_time: () => ({ | ||
| type: "repeat_until_time", | ||
| seconds: seconds(), | ||
| repeatFrom: repeatFrom() | ||
| }), | ||
| repeat_until_distance: () => ({ | ||
| type: "repeat_until_distance", | ||
| meters: meters(), | ||
| repeatFrom: repeatFrom() | ||
| }), | ||
| repeat_until_calories: () => ({ | ||
| type: "repeat_until_calories", | ||
| calories: calories(), | ||
| repeatFrom: repeatFrom() | ||
| }), | ||
| repeat_until_heart_rate_less_than: () => ({ | ||
| type: "repeat_until_heart_rate_less_than", | ||
| bpm: bpm(), | ||
| repeatFrom: repeatFrom() | ||
| }), | ||
| repeat_until_power_less_than: () => ({ | ||
| type: "repeat_until_power_less_than", | ||
| watts: watts(), | ||
| repeatFrom: repeatFrom() | ||
| }), | ||
| repeat_until_power_greater_than: () => ({ | ||
| type: "repeat_until_power_greater_than", | ||
| watts: watts(), | ||
| repeatFrom: repeatFrom() | ||
| }), | ||
| open: () => ({ type: "open" }) | ||
| const repeatFrom = () => faker.number.int({ | ||
| max: 10, | ||
| min: 0 | ||
| }); | ||
| const seconds = () => faker.number.int({ | ||
| max: 3600, | ||
| min: 30 | ||
| }); | ||
| const meters = () => faker.number.int({ | ||
| max: 1e4, | ||
| min: 100 | ||
| }); | ||
| const bpm = () => faker.number.int({ | ||
| max: 200, | ||
| min: 60 | ||
| }); | ||
| const watts = () => faker.number.int({ | ||
| max: 400, | ||
| min: 100 | ||
| }); | ||
| const calories = () => faker.number.int({ | ||
| max: 1e3, | ||
| min: 50 | ||
| }); | ||
| const DURATION_BUILDERS = { | ||
| time: () => ({ | ||
| type: "time", | ||
| seconds: seconds() | ||
| }), | ||
| distance: () => ({ | ||
| type: "distance", | ||
| meters: meters() | ||
| }), | ||
| heart_rate_less_than: () => ({ | ||
| type: "heart_rate_less_than", | ||
| bpm: bpm() | ||
| }), | ||
| repeat_until_heart_rate_greater_than: () => ({ | ||
| type: "repeat_until_heart_rate_greater_than", | ||
| bpm: bpm(), | ||
| repeatFrom: repeatFrom() | ||
| }), | ||
| calories: () => ({ | ||
| type: "calories", | ||
| calories: calories() | ||
| }), | ||
| power_less_than: () => ({ | ||
| type: "power_less_than", | ||
| watts: watts() | ||
| }), | ||
| power_greater_than: () => ({ | ||
| type: "power_greater_than", | ||
| watts: watts() | ||
| }), | ||
| repeat_until_time: () => ({ | ||
| type: "repeat_until_time", | ||
| seconds: seconds(), | ||
| repeatFrom: repeatFrom() | ||
| }), | ||
| repeat_until_distance: () => ({ | ||
| type: "repeat_until_distance", | ||
| meters: meters(), | ||
| repeatFrom: repeatFrom() | ||
| }), | ||
| repeat_until_calories: () => ({ | ||
| type: "repeat_until_calories", | ||
| calories: calories(), | ||
| repeatFrom: repeatFrom() | ||
| }), | ||
| repeat_until_heart_rate_less_than: () => ({ | ||
| type: "repeat_until_heart_rate_less_than", | ||
| bpm: bpm(), | ||
| repeatFrom: repeatFrom() | ||
| }), | ||
| repeat_until_power_less_than: () => ({ | ||
| type: "repeat_until_power_less_than", | ||
| watts: watts(), | ||
| repeatFrom: repeatFrom() | ||
| }), | ||
| repeat_until_power_greater_than: () => ({ | ||
| type: "repeat_until_power_greater_than", | ||
| watts: watts(), | ||
| repeatFrom: repeatFrom() | ||
| }), | ||
| open: () => ({ type: "open" }) | ||
| }; | ||
| var buildDuration = new Factory().attr("type", () => faker.helpers.arrayElement([...DURATION_TYPES])).after((duration) => { | ||
| const builder = DURATION_BUILDERS[duration.type]; | ||
| return Object.assign(duration, builder()); | ||
| const buildDuration = new Factory().attr("type", () => faker.helpers.arrayElement([...DURATION_TYPES])).after((duration) => { | ||
| const builder = DURATION_BUILDERS[duration.type]; | ||
| return Object.assign(duration, builder()); | ||
| }); | ||
| var buildPowerValue = () => { | ||
| const unit = faker.helpers.arrayElement([ | ||
| "watts", | ||
| "percent_ftp", | ||
| "zone", | ||
| "range" | ||
| ]); | ||
| if (unit === "zone") | ||
| return { unit, value: faker.number.int({ max: 7, min: 1 }) }; | ||
| if (unit === "range") { | ||
| return { | ||
| unit, | ||
| min: faker.number.int({ max: 200, min: 100 }), | ||
| max: faker.number.int({ max: 400, min: 250 }) | ||
| }; | ||
| } | ||
| if (unit === "percent_ftp") | ||
| return { unit, value: faker.number.int({ max: 150, min: 50 }) }; | ||
| return { unit, value: faker.number.int({ max: 400, min: 100 }) }; | ||
| //#endregion | ||
| //#region src/tests/fixtures/workout/target.fixtures.ts | ||
| const buildPowerValue = () => { | ||
| const unit = faker.helpers.arrayElement([ | ||
| "watts", | ||
| "percent_ftp", | ||
| "zone", | ||
| "range" | ||
| ]); | ||
| if (unit === "zone") return { | ||
| unit, | ||
| value: faker.number.int({ | ||
| max: 7, | ||
| min: 1 | ||
| }) | ||
| }; | ||
| if (unit === "range") return { | ||
| unit, | ||
| min: faker.number.int({ | ||
| max: 200, | ||
| min: 100 | ||
| }), | ||
| max: faker.number.int({ | ||
| max: 400, | ||
| min: 250 | ||
| }) | ||
| }; | ||
| if (unit === "percent_ftp") return { | ||
| unit, | ||
| value: faker.number.int({ | ||
| max: 150, | ||
| min: 50 | ||
| }) | ||
| }; | ||
| return { | ||
| unit, | ||
| value: faker.number.int({ | ||
| max: 400, | ||
| min: 100 | ||
| }) | ||
| }; | ||
| }; | ||
| var buildHeartRateValue = () => { | ||
| const unit = faker.helpers.arrayElement([ | ||
| "bpm", | ||
| "zone", | ||
| "percent_max", | ||
| "range" | ||
| ]); | ||
| if (unit === "zone") | ||
| return { unit, value: faker.number.int({ max: 5, min: 1 }) }; | ||
| if (unit === "range") { | ||
| return { | ||
| unit, | ||
| min: faker.number.int({ max: 140, min: 100 }), | ||
| max: faker.number.int({ max: 180, min: 150 }) | ||
| }; | ||
| } | ||
| if (unit === "percent_max") | ||
| return { unit, value: faker.number.int({ max: 100, min: 50 }) }; | ||
| return { unit, value: faker.number.int({ max: 200, min: 60 }) }; | ||
| const buildHeartRateValue = () => { | ||
| const unit = faker.helpers.arrayElement([ | ||
| "bpm", | ||
| "zone", | ||
| "percent_max", | ||
| "range" | ||
| ]); | ||
| if (unit === "zone") return { | ||
| unit, | ||
| value: faker.number.int({ | ||
| max: 5, | ||
| min: 1 | ||
| }) | ||
| }; | ||
| if (unit === "range") return { | ||
| unit, | ||
| min: faker.number.int({ | ||
| max: 140, | ||
| min: 100 | ||
| }), | ||
| max: faker.number.int({ | ||
| max: 180, | ||
| min: 150 | ||
| }) | ||
| }; | ||
| if (unit === "percent_max") return { | ||
| unit, | ||
| value: faker.number.int({ | ||
| max: 100, | ||
| min: 50 | ||
| }) | ||
| }; | ||
| return { | ||
| unit, | ||
| value: faker.number.int({ | ||
| max: 200, | ||
| min: 60 | ||
| }) | ||
| }; | ||
| }; | ||
| var buildCadenceValue = () => { | ||
| const unit = faker.helpers.arrayElement(["rpm", "range"]); | ||
| if (unit === "range") { | ||
| return { | ||
| unit, | ||
| min: faker.number.int({ max: 80, min: 60 }), | ||
| max: faker.number.int({ max: 110, min: 90 }) | ||
| }; | ||
| } | ||
| return { unit, value: faker.number.int({ max: 120, min: 60 }) }; | ||
| const buildCadenceValue = () => { | ||
| const unit = faker.helpers.arrayElement(["rpm", "range"]); | ||
| if (unit === "range") return { | ||
| unit, | ||
| min: faker.number.int({ | ||
| max: 80, | ||
| min: 60 | ||
| }), | ||
| max: faker.number.int({ | ||
| max: 110, | ||
| min: 90 | ||
| }) | ||
| }; | ||
| return { | ||
| unit, | ||
| value: faker.number.int({ | ||
| max: 120, | ||
| min: 60 | ||
| }) | ||
| }; | ||
| }; | ||
| var buildPaceValue = () => { | ||
| const unit = faker.helpers.arrayElement(["mps", "zone", "range"]); | ||
| if (unit === "zone") | ||
| return { unit, value: faker.number.int({ max: 5, min: 1 }) }; | ||
| if (unit === "range") { | ||
| return { | ||
| unit, | ||
| min: faker.number.float({ fractionDigits: 2, max: 4, min: 2 }), | ||
| max: faker.number.float({ fractionDigits: 2, max: 6, min: 4.5 }) | ||
| }; | ||
| } | ||
| return { | ||
| unit, | ||
| value: faker.number.float({ fractionDigits: 2, max: 6, min: 2 }) | ||
| }; | ||
| const buildPaceValue = () => { | ||
| const unit = faker.helpers.arrayElement([ | ||
| "mps", | ||
| "zone", | ||
| "range" | ||
| ]); | ||
| if (unit === "zone") return { | ||
| unit, | ||
| value: faker.number.int({ | ||
| max: 5, | ||
| min: 1 | ||
| }) | ||
| }; | ||
| if (unit === "range") return { | ||
| unit, | ||
| min: faker.number.float({ | ||
| fractionDigits: 2, | ||
| max: 4, | ||
| min: 2 | ||
| }), | ||
| max: faker.number.float({ | ||
| fractionDigits: 2, | ||
| max: 6, | ||
| min: 4.5 | ||
| }) | ||
| }; | ||
| return { | ||
| unit, | ||
| value: faker.number.float({ | ||
| fractionDigits: 2, | ||
| max: 6, | ||
| min: 2 | ||
| }) | ||
| }; | ||
| }; | ||
| var buildStrokeTypeValue = () => ({ | ||
| unit: "swim_stroke", | ||
| value: faker.number.int({ max: 5, min: 0 }) | ||
| const buildStrokeTypeValue = () => ({ | ||
| unit: "swim_stroke", | ||
| value: faker.number.int({ | ||
| max: 5, | ||
| min: 0 | ||
| }) | ||
| }); | ||
| var TARGET_TYPES = [ | ||
| "power", | ||
| "heart_rate", | ||
| "cadence", | ||
| "pace", | ||
| "stroke_type", | ||
| "open" | ||
| const TARGET_TYPES = [ | ||
| "power", | ||
| "heart_rate", | ||
| "cadence", | ||
| "pace", | ||
| "stroke_type", | ||
| "open" | ||
| ]; | ||
| var TARGET_BUILDERS = { | ||
| power: () => ({ type: "power", value: buildPowerValue() }), | ||
| heart_rate: () => ({ type: "heart_rate", value: buildHeartRateValue() }), | ||
| cadence: () => ({ type: "cadence", value: buildCadenceValue() }), | ||
| pace: () => ({ type: "pace", value: buildPaceValue() }), | ||
| stroke_type: () => ({ type: "stroke_type", value: buildStrokeTypeValue() }), | ||
| open: () => ({ type: "open" }) | ||
| const TARGET_BUILDERS = { | ||
| power: () => ({ | ||
| type: "power", | ||
| value: buildPowerValue() | ||
| }), | ||
| heart_rate: () => ({ | ||
| type: "heart_rate", | ||
| value: buildHeartRateValue() | ||
| }), | ||
| cadence: () => ({ | ||
| type: "cadence", | ||
| value: buildCadenceValue() | ||
| }), | ||
| pace: () => ({ | ||
| type: "pace", | ||
| value: buildPaceValue() | ||
| }), | ||
| stroke_type: () => ({ | ||
| type: "stroke_type", | ||
| value: buildStrokeTypeValue() | ||
| }), | ||
| open: () => ({ type: "open" }) | ||
| }; | ||
| var buildTarget = new Factory().attr("type", () => faker.helpers.arrayElement([...TARGET_TYPES])).after((target) => { | ||
| const builder = TARGET_BUILDERS[target.type]; | ||
| return Object.assign(target, builder()); | ||
| const buildTarget = new Factory().attr("type", () => faker.helpers.arrayElement([...TARGET_TYPES])).after((target) => { | ||
| const builder = TARGET_BUILDERS[target.type]; | ||
| return Object.assign(target, builder()); | ||
| }); | ||
| // src/test-utils/profile-snapshot-fixtures.ts | ||
| var ISO = "2026-05-01T08:30:00.000Z"; | ||
| var baselineSnapshot = { | ||
| schemaVersion: 1, | ||
| profile: { name: "Pablo", bodyWeight: 72 }, | ||
| activeSport: "cycling", | ||
| thresholds: { | ||
| cycling: { ftp: 270 }, | ||
| running: { thresholdPaceSecPerKm: 255, lthr: 168 } | ||
| }, | ||
| heartRate: { max: 188, lthr: 168 }, | ||
| generatedAt: ISO | ||
| //#endregion | ||
| //#region src/test-utils/profile-snapshot-fixtures.ts | ||
| const ISO = "2026-05-01T08:30:00.000Z"; | ||
| const baselineSnapshot = { | ||
| schemaVersion: 1, | ||
| profile: { | ||
| name: "Pablo", | ||
| bodyWeight: 72 | ||
| }, | ||
| activeSport: "cycling", | ||
| thresholds: { | ||
| cycling: { ftp: 270 }, | ||
| running: { | ||
| thresholdPaceSecPerKm: 255, | ||
| lthr: 168 | ||
| } | ||
| }, | ||
| heartRate: { | ||
| max: 188, | ||
| lthr: 168 | ||
| }, | ||
| generatedAt: ISO | ||
| }; | ||
| var minimalSnapshot = { | ||
| schemaVersion: 1, | ||
| profile: { name: "Min" }, | ||
| thresholds: {}, | ||
| heartRate: {}, | ||
| generatedAt: ISO | ||
| const minimalSnapshot = { | ||
| schemaVersion: 1, | ||
| profile: { name: "Min" }, | ||
| thresholds: {}, | ||
| heartRate: {}, | ||
| generatedAt: ISO | ||
| }; | ||
| var partialZoneSnapshot = { | ||
| schemaVersion: 1, | ||
| profile: { name: "Partial" }, | ||
| activeSport: "running", | ||
| thresholds: { | ||
| running: { lthr: 170 } | ||
| }, | ||
| heartRate: { max: 195 }, | ||
| generatedAt: ISO | ||
| const partialZoneSnapshot = { | ||
| schemaVersion: 1, | ||
| profile: { name: "Partial" }, | ||
| activeSport: "running", | ||
| thresholds: { running: { lthr: 170 } }, | ||
| heartRate: { max: 195 }, | ||
| generatedAt: ISO | ||
| }; | ||
| var positiveSnapshotFixtures = [ | ||
| baselineSnapshot, | ||
| minimalSnapshot, | ||
| partialZoneSnapshot | ||
| const positiveSnapshotFixtures = [ | ||
| baselineSnapshot, | ||
| minimalSnapshot, | ||
| partialZoneSnapshot | ||
| ]; | ||
| var longName = "x".repeat(100); | ||
| var oversizedName = "x".repeat(9e3); | ||
| var buildPrototypePolluted = () => { | ||
| const obj = JSON.parse( | ||
| `{"__proto__":{"isAdmin":true},"schemaVersion":1,"profile":{"name":"P"},"thresholds":{},"heartRate":{},"generatedAt":"${ISO}"}` | ||
| ); | ||
| return obj; | ||
| const longName = "x".repeat(100); | ||
| const oversizedName = "x".repeat(9e3); | ||
| const buildPrototypePolluted = () => { | ||
| return JSON.parse(`{"__proto__":{"isAdmin":true},"schemaVersion":1,"profile":{"name":"P"},"thresholds":{},"heartRate":{},"generatedAt":"${ISO}"}`); | ||
| }; | ||
| var buildNestedPolluted = () => { | ||
| const obj = JSON.parse( | ||
| `{"schemaVersion":1,"profile":{"__proto__":{"isAdmin":true},"name":"P"},"thresholds":{},"heartRate":{},"generatedAt":"${ISO}"}` | ||
| ); | ||
| return obj; | ||
| const buildNestedPolluted = () => { | ||
| return JSON.parse(`{"schemaVersion":1,"profile":{"__proto__":{"isAdmin":true},"name":"P"},"thresholds":{},"heartRate":{},"generatedAt":"${ISO}"}`); | ||
| }; | ||
| var negativeSnapshotFixtures = [ | ||
| { | ||
| name: "missing schemaVersion", | ||
| value: { profile: { name: "x" }, generatedAt: ISO }, | ||
| expectedError: /schemaVersion/i | ||
| }, | ||
| { | ||
| name: "unsupported schemaVersion", | ||
| value: { schemaVersion: 99, profile: { name: "x" }, generatedAt: ISO }, | ||
| expectedError: /schemaVersion/i | ||
| }, | ||
| { | ||
| name: "missing profile.name", | ||
| value: { schemaVersion: 1, profile: {}, generatedAt: ISO }, | ||
| expectedError: /name/i | ||
| }, | ||
| { | ||
| name: "empty profile.name", | ||
| value: { schemaVersion: 1, profile: { name: "" }, generatedAt: ISO }, | ||
| expectedError: /name/i | ||
| }, | ||
| { | ||
| name: "profile.name too long", | ||
| value: { | ||
| schemaVersion: 1, | ||
| profile: { name: `${longName}x` }, | ||
| generatedAt: ISO | ||
| }, | ||
| expectedError: /name/i | ||
| }, | ||
| { | ||
| name: "missing generatedAt", | ||
| value: { schemaVersion: 1, profile: { name: "x" } }, | ||
| expectedError: /generatedAt/i | ||
| }, | ||
| { | ||
| name: "non-positive bodyWeight", | ||
| value: { | ||
| schemaVersion: 1, | ||
| profile: { name: "x", bodyWeight: 0 }, | ||
| generatedAt: ISO | ||
| }, | ||
| expectedError: /bodyWeight|positive/i | ||
| }, | ||
| { | ||
| name: "unknown activeSport", | ||
| value: { | ||
| schemaVersion: 1, | ||
| profile: { name: "x" }, | ||
| activeSport: "rowing", | ||
| generatedAt: ISO | ||
| }, | ||
| expectedError: /activeSport|enum/i | ||
| }, | ||
| { | ||
| name: "oversized payload", | ||
| value: { | ||
| schemaVersion: 1, | ||
| profile: { name: oversizedName }, | ||
| generatedAt: ISO | ||
| }, | ||
| expectedError: /too large/i | ||
| }, | ||
| { | ||
| name: "top-level prototype-pollution", | ||
| value: buildPrototypePolluted(), | ||
| expectedError: /(invalid|payload|__proto__|prototype)/i | ||
| }, | ||
| { | ||
| name: "nested prototype-pollution", | ||
| value: buildNestedPolluted(), | ||
| expectedError: /(invalid|payload|__proto__|prototype)/i | ||
| } | ||
| const negativeSnapshotFixtures = [ | ||
| { | ||
| name: "missing schemaVersion", | ||
| value: { | ||
| profile: { name: "x" }, | ||
| generatedAt: ISO | ||
| }, | ||
| expectedError: /schemaVersion/i | ||
| }, | ||
| { | ||
| name: "unsupported schemaVersion", | ||
| value: { | ||
| schemaVersion: 99, | ||
| profile: { name: "x" }, | ||
| generatedAt: ISO | ||
| }, | ||
| expectedError: /schemaVersion/i | ||
| }, | ||
| { | ||
| name: "missing profile.name", | ||
| value: { | ||
| schemaVersion: 1, | ||
| profile: {}, | ||
| generatedAt: ISO | ||
| }, | ||
| expectedError: /name/i | ||
| }, | ||
| { | ||
| name: "empty profile.name", | ||
| value: { | ||
| schemaVersion: 1, | ||
| profile: { name: "" }, | ||
| generatedAt: ISO | ||
| }, | ||
| expectedError: /name/i | ||
| }, | ||
| { | ||
| name: "profile.name too long", | ||
| value: { | ||
| schemaVersion: 1, | ||
| profile: { name: `${longName}x` }, | ||
| generatedAt: ISO | ||
| }, | ||
| expectedError: /name/i | ||
| }, | ||
| { | ||
| name: "missing generatedAt", | ||
| value: { | ||
| schemaVersion: 1, | ||
| profile: { name: "x" } | ||
| }, | ||
| expectedError: /generatedAt/i | ||
| }, | ||
| { | ||
| name: "non-positive bodyWeight", | ||
| value: { | ||
| schemaVersion: 1, | ||
| profile: { | ||
| name: "x", | ||
| bodyWeight: 0 | ||
| }, | ||
| generatedAt: ISO | ||
| }, | ||
| expectedError: /bodyWeight|positive/i | ||
| }, | ||
| { | ||
| name: "unknown activeSport", | ||
| value: { | ||
| schemaVersion: 1, | ||
| profile: { name: "x" }, | ||
| activeSport: "rowing", | ||
| generatedAt: ISO | ||
| }, | ||
| expectedError: /activeSport|enum/i | ||
| }, | ||
| { | ||
| name: "oversized payload", | ||
| value: { | ||
| schemaVersion: 1, | ||
| profile: { name: oversizedName }, | ||
| generatedAt: ISO | ||
| }, | ||
| expectedError: /too large/i | ||
| }, | ||
| { | ||
| name: "top-level prototype-pollution", | ||
| value: buildPrototypePolluted(), | ||
| expectedError: /(invalid|payload|__proto__|prototype)/i | ||
| }, | ||
| { | ||
| name: "nested prototype-pollution", | ||
| value: buildNestedPolluted(), | ||
| expectedError: /(invalid|payload|__proto__|prototype)/i | ||
| } | ||
| ]; | ||
| var snapshotFixtures = { | ||
| positive: positiveSnapshotFixtures, | ||
| negative: negativeSnapshotFixtures | ||
| const snapshotFixtures = { | ||
| positive: positiveSnapshotFixtures, | ||
| negative: negativeSnapshotFixtures | ||
| }; | ||
| //#endregion | ||
| //#region src/test-utils/round-trip-fixtures.ts | ||
| /** | ||
| * Round-trip test fixtures. | ||
| * | ||
| * Shared sample buffers and named domain constants used by | ||
| * round-trip validation tests. Centralising these values keeps | ||
| * `expect(...)` assertions self-documenting and removes inline | ||
| * magic numbers from the test suite. | ||
| * | ||
| * Tolerance numeric values themselves live in `./tolerance-constants`. | ||
| */ | ||
| /** | ||
| * Returns a fresh `Uint8Array([1, 2, 3, 4])` per call. | ||
| * | ||
| * Returning a new buffer per invocation prevents cross-test mutation | ||
| * if a future test ever writes to the underlying bytes. | ||
| */ | ||
| const createFitBufferSample = () => new Uint8Array([ | ||
| 1, | ||
| 2, | ||
| 3, | ||
| 4 | ||
| ]); | ||
| const POWER_EXPECTED = 250; | ||
| const POWER_ACTUAL = 255; | ||
| const POWER_ACTUAL_HIGH = 260; | ||
| const HR_EXPECTED = 150; | ||
| const HR_ACTUAL = 155; | ||
| const HR_ACTUAL_HIGH = 160; | ||
| const CADENCE_EXPECTED = 85; | ||
| const CADENCE_ACTUAL = 90; | ||
| const TIME_EXPECTED_SEC = 3600; | ||
| const TIME_ACTUAL_SEC = 3602; | ||
| const DISTANCE_EXPECTED_M = 1e4; | ||
| const DISTANCE_ACTUAL_M = 10005; | ||
| const LAP_TIME_EXPECTED_SEC = 600; | ||
| const LAP_TIME_ACTUAL_SEC = 605; | ||
| const LAP_DISTANCE_EXPECTED_M = 1e3; | ||
| const LAP_DISTANCE_ACTUAL_M = 1010; | ||
| const RECORD_DISTANCE_EXPECTED_M = 100; | ||
| const RECORD_DISTANCE_ACTUAL_M = 105; | ||
| const RECORD_SPEED_EXPECTED_MPS = 2.78; | ||
| const RECORD_SPEED_ACTUAL_MPS = 2.85; | ||
| const VIOLATION_COUNT_FULL_SESSION = 5; | ||
| const VIOLATION_COUNT_LAP = 3; | ||
| const VIOLATION_COUNT_RECORD = 5; | ||
| const DEVIATION_POWER_5W = 5; | ||
| const DEVIATION_POWER_10W = 10; | ||
| const DEVIATION_HR_5BPM = 5; | ||
| const DEVIATION_HR_10BPM = 10; | ||
| const DEVIATION_CADENCE_5RPM = 5; | ||
| const DEVIATION_DISTANCE_5M = 5; | ||
| const DEVIATION_DISTANCE_10M = 10; | ||
| const DEVIATION_TIME_2SEC = 2; | ||
| const DEVIATION_TIME_5SEC = 5; | ||
| const DEVIATION_PACE = .07; | ||
| //#endregion | ||
| export { CADENCE_ACTUAL, CADENCE_EXPECTED, DEVIATION_CADENCE_5RPM, DEVIATION_DISTANCE_10M, DEVIATION_DISTANCE_5M, DEVIATION_HR_10BPM, DEVIATION_HR_5BPM, DEVIATION_PACE, DEVIATION_POWER_10W, DEVIATION_POWER_5W, DEVIATION_TIME_2SEC, DEVIATION_TIME_5SEC, DISTANCE_ACTUAL_M, DISTANCE_EXPECTED_M, FIXTURE_NAMES, HR_ACTUAL, HR_ACTUAL_HIGH, HR_EXPECTED, LAP_DISTANCE_ACTUAL_M, LAP_DISTANCE_EXPECTED_M, LAP_TIME_ACTUAL_SEC, LAP_TIME_EXPECTED_SEC, POWER_ACTUAL, POWER_ACTUAL_HIGH, POWER_EXPECTED, RECORD_DISTANCE_ACTUAL_M, RECORD_DISTANCE_EXPECTED_M, RECORD_SPEED_ACTUAL_MPS, RECORD_SPEED_EXPECTED_MPS, TIME_ACTUAL_SEC, TIME_EXPECTED_SEC, TOLERANCE_CADENCE_RPM, TOLERANCE_DISTANCE_M, TOLERANCE_HR_BPM, TOLERANCE_PACE_SEC_PER_M, TOLERANCE_POWER_WATTS, TOLERANCE_TIME_SEC, VIOLATION_COUNT_FULL_SESSION, VIOLATION_COUNT_LAP, VIOLATION_COUNT_RECORD, baselineSnapshot, buildDuration, buildKRD, buildKRDEvent, buildKRDLap, buildKRDMetadata, buildKRDRecord, buildKRDSession, buildTarget, buildWorkout, buildWorkoutStep, createFitBufferSample, createMockLogger, getFixturePath, loadFitFixture, loadFixturePair, loadKrdFixture, loadKrdFixtureRaw, loadTcxFixture, loadZwoFixture, minimalSnapshot, negativeSnapshotFixtures, partialZoneSnapshot, positiveSnapshotFixtures, snapshotFixtures }; | ||
| // src/test-utils/round-trip-fixtures.ts | ||
| var createFitBufferSample = () => new Uint8Array([1, 2, 3, 4]); | ||
| var POWER_EXPECTED = 250; | ||
| var POWER_ACTUAL = 255; | ||
| var POWER_ACTUAL_HIGH = 260; | ||
| var HR_EXPECTED = 150; | ||
| var HR_ACTUAL = 155; | ||
| var HR_ACTUAL_HIGH = 160; | ||
| var CADENCE_EXPECTED = 85; | ||
| var CADENCE_ACTUAL = 90; | ||
| var TIME_EXPECTED_SEC = 3600; | ||
| var TIME_ACTUAL_SEC = 3602; | ||
| var DISTANCE_EXPECTED_M = 1e4; | ||
| var DISTANCE_ACTUAL_M = 10005; | ||
| var LAP_TIME_EXPECTED_SEC = 600; | ||
| var LAP_TIME_ACTUAL_SEC = 605; | ||
| var LAP_DISTANCE_EXPECTED_M = 1e3; | ||
| var LAP_DISTANCE_ACTUAL_M = 1010; | ||
| var RECORD_DISTANCE_EXPECTED_M = 100; | ||
| var RECORD_DISTANCE_ACTUAL_M = 105; | ||
| var RECORD_SPEED_EXPECTED_MPS = 2.78; | ||
| var RECORD_SPEED_ACTUAL_MPS = 2.85; | ||
| var VIOLATION_COUNT_FULL_SESSION = 5; | ||
| var VIOLATION_COUNT_LAP = 3; | ||
| var VIOLATION_COUNT_RECORD = 5; | ||
| var DEVIATION_POWER_5W = 5; | ||
| var DEVIATION_POWER_10W = 10; | ||
| var DEVIATION_HR_5BPM = 5; | ||
| var DEVIATION_HR_10BPM = 10; | ||
| var DEVIATION_CADENCE_5RPM = 5; | ||
| var DEVIATION_DISTANCE_5M = 5; | ||
| var DEVIATION_DISTANCE_10M = 10; | ||
| var DEVIATION_TIME_2SEC = 2; | ||
| var DEVIATION_TIME_5SEC = 5; | ||
| var DEVIATION_PACE = 0.07; | ||
| export { CADENCE_ACTUAL, CADENCE_EXPECTED, DEVIATION_CADENCE_5RPM, DEVIATION_DISTANCE_10M, DEVIATION_DISTANCE_5M, DEVIATION_HR_10BPM, DEVIATION_HR_5BPM, DEVIATION_PACE, DEVIATION_POWER_10W, DEVIATION_POWER_5W, DEVIATION_TIME_2SEC, DEVIATION_TIME_5SEC, DISTANCE_ACTUAL_M, DISTANCE_EXPECTED_M, FIXTURE_NAMES, HR_ACTUAL, HR_ACTUAL_HIGH, HR_EXPECTED, LAP_DISTANCE_ACTUAL_M, LAP_DISTANCE_EXPECTED_M, LAP_TIME_ACTUAL_SEC, LAP_TIME_EXPECTED_SEC, POWER_ACTUAL, POWER_ACTUAL_HIGH, POWER_EXPECTED, RECORD_DISTANCE_ACTUAL_M, RECORD_DISTANCE_EXPECTED_M, RECORD_SPEED_ACTUAL_MPS, RECORD_SPEED_EXPECTED_MPS, TIME_ACTUAL_SEC, TIME_EXPECTED_SEC, TOLERANCE_CADENCE_RPM, TOLERANCE_DISTANCE_M, TOLERANCE_HR_BPM, TOLERANCE_PACE_SEC_PER_M, TOLERANCE_POWER_WATTS, TOLERANCE_TIME_SEC, VIOLATION_COUNT_FULL_SESSION, VIOLATION_COUNT_LAP, VIOLATION_COUNT_RECORD, baselineSnapshot, buildDuration, buildKRD, buildKRDEvent, buildKRDLap, buildKRDMetadata, buildKRDRecord, buildKRDSession, buildTarget, buildWorkout, buildWorkoutStep, createFitBufferSample, createMockLogger, getFixturePath, loadFitFixture, loadFixturePair, loadKrdFixture, loadKrdFixtureRaw, loadTcxFixture, loadZwoFixture, minimalSnapshot, negativeSnapshotFixtures, partialZoneSnapshot, positiveSnapshotFixtures, snapshotFixtures }; | ||
| //# sourceMappingURL=index.js.map |
+20
-20
| { | ||
| "name": "@kaiord/core", | ||
| "version": "10.0.0", | ||
| "version": "10.1.0", | ||
| "description": "Core library for the Kaiord health & fitness data framework", | ||
@@ -23,14 +23,2 @@ "type": "module", | ||
| ], | ||
| "scripts": { | ||
| "generate:schema": "tsx scripts/generate-schema.ts", | ||
| "generate:krd-fixtures": "tsx scripts/generate-krd-fixtures.ts", | ||
| "prebuild": "pnpm run generate:schema", | ||
| "build": "pnpm run generate:schema && tsup", | ||
| "test": "vitest --run", | ||
| "test:watch": "vitest", | ||
| "test:coverage": "vitest --run --coverage", | ||
| "lint": "tsc --noEmit && eslint . && prettier --check src scripts", | ||
| "lint:fix": "eslint . --fix && prettier --write src scripts", | ||
| "clean": "rm -rf dist" | ||
| }, | ||
| "dependencies": { | ||
@@ -42,10 +30,10 @@ "@noble/hashes": "^2.2.0", | ||
| "@faker-js/faker": "^10.5.0", | ||
| "@types/node": "^26.1.0", | ||
| "@types/node": "^26.1.2", | ||
| "@types/rosie": "^0.0.45", | ||
| "@vitest/coverage-v8": "^4.1.9", | ||
| "@vitest/coverage-v8": "^4.1.10", | ||
| "rosie": "^2.1.1", | ||
| "tsup": "^8.5.1", | ||
| "tsx": "^4.22.5", | ||
| "typescript": "^6.0.3", | ||
| "vitest": "^4.1.9" | ||
| "tsdown": "^0.22.14", | ||
| "tsx": "^4.23.1", | ||
| "typescript": "^7.0.2", | ||
| "vitest": "^4.1.10" | ||
| }, | ||
@@ -84,3 +72,15 @@ "repository": { | ||
| "node": ">=22.12.0" | ||
| }, | ||
| "scripts": { | ||
| "generate:schema": "tsx scripts/generate-schema.ts", | ||
| "generate:krd-fixtures": "tsx scripts/generate-krd-fixtures.ts", | ||
| "prebuild": "pnpm run generate:schema", | ||
| "build": "pnpm run generate:schema && tsdown --concurrency 1", | ||
| "test": "vitest --run", | ||
| "test:watch": "vitest", | ||
| "test:coverage": "vitest --run --coverage", | ||
| "lint": "tsc --noEmit && eslint . && prettier --check src scripts", | ||
| "lint:fix": "eslint . --fix && prettier --write src scripts", | ||
| "clean": "rm -rf dist" | ||
| } | ||
| } | ||
| } |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
894006
7.88%18
28.57%15691
13.98%