@dgpholdings/greatoak-shared 1.2.90 → 1.2.92

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -47,6 +47,20 @@ export interface TAiUserInjury {
47
47
  }
48
48
  export declare const AI_ENERGY_LEVEL_OPTIONS: readonly ["fresh", "normal", "tired", "exhausted"];
49
49
  export type TAiEnergyLevel = (typeof AI_ENERGY_LEVEL_OPTIONS)[number];
50
+ /**
51
+ * HARDCODED_INTENTS - Single source of truth for workout intent types.
52
+ *
53
+ * Used by:
54
+ * - Frontend: IntentInput chip values
55
+ * - Backend: Intent classification, exercise selection
56
+ * - Shared: TSessionIntent type derivation
57
+ *
58
+ * When adding new intents:
59
+ * 1. Add here
60
+ * 2. Add mapping in goldenExercise/constants.ts WORKOUT_TYPE_GROUPS
61
+ * 3. Add warmup/cooldown mappings if needed
62
+ * 4. Add INTENT_DISPLAY entry in goalJourney.ts (optional, for UI)
63
+ */
50
64
  export declare const HARDCODED_INTENTS: readonly ["push", "pull", "legs", "core", "upper", "lower", "arms", "back", "full-body", "cardio", "strength", "mobility", "fatburn", "unstructured"];
51
65
  export type TWorkoutIntent = (typeof HARDCODED_INTENTS)[number];
52
66
  export {};
@@ -212,6 +212,20 @@ exports.AI_ENERGY_LEVEL_OPTIONS = [
212
212
  "tired",
213
213
  "exhausted",
214
214
  ];
215
+ /**
216
+ * HARDCODED_INTENTS - Single source of truth for workout intent types.
217
+ *
218
+ * Used by:
219
+ * - Frontend: IntentInput chip values
220
+ * - Backend: Intent classification, exercise selection
221
+ * - Shared: TSessionIntent type derivation
222
+ *
223
+ * When adding new intents:
224
+ * 1. Add here
225
+ * 2. Add mapping in goldenExercise/constants.ts WORKOUT_TYPE_GROUPS
226
+ * 3. Add warmup/cooldown mappings if needed
227
+ * 4. Add INTENT_DISPLAY entry in goalJourney.ts (optional, for UI)
228
+ */
215
229
  exports.HARDCODED_INTENTS = [
216
230
  "push",
217
231
  "pull",
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // shared/src/constants/__tests__/workoutIntents.test.ts
4
+ const vitest_1 = require("vitest");
5
+ const AiExerciseVocabulary_1 = require("../AiExerciseVocabulary");
6
+ (0, vitest_1.describe)("HARDCODED_INTENTS - Workout Intent Constants", () => {
7
+ (0, vitest_1.it)("should export all expected workout intents", () => {
8
+ const expectedIntents = [
9
+ "push",
10
+ "pull",
11
+ "legs",
12
+ "core",
13
+ "upper",
14
+ "lower",
15
+ "arms",
16
+ "back",
17
+ "full-body",
18
+ "cardio",
19
+ "strength",
20
+ "mobility",
21
+ "fatburn",
22
+ "unstructured",
23
+ ];
24
+ (0, vitest_1.expect)(AiExerciseVocabulary_1.HARDCODED_INTENTS).toEqual(expectedIntents);
25
+ });
26
+ (0, vitest_1.it)("should have 14 total intents", () => {
27
+ (0, vitest_1.expect)(AiExerciseVocabulary_1.HARDCODED_INTENTS).toHaveLength(14);
28
+ });
29
+ (0, vitest_1.it)("should not have duplicate values", () => {
30
+ const uniqueIntents = [...new Set(AiExerciseVocabulary_1.HARDCODED_INTENTS)];
31
+ (0, vitest_1.expect)(uniqueIntents).toHaveLength(AiExerciseVocabulary_1.HARDCODED_INTENTS.length);
32
+ });
33
+ (0, vitest_1.it)("should only contain lowercase strings with hyphens", () => {
34
+ AiExerciseVocabulary_1.HARDCODED_INTENTS.forEach((intent) => {
35
+ (0, vitest_1.expect)(intent).toMatch(/^[a-z-]+$/);
36
+ });
37
+ });
38
+ (0, vitest_1.it)("should have TWorkoutIntent type that matches array values", () => {
39
+ // Type test - this will fail at compile time if types diverge
40
+ const testIntent = "push";
41
+ (0, vitest_1.expect)(AiExerciseVocabulary_1.HARDCODED_INTENTS).toContain(testIntent);
42
+ // @ts-expect-error - "invalid" is not a valid TWorkoutIntent
43
+ const invalidIntent = "invalid";
44
+ });
45
+ (0, vitest_1.it)("should include user-selectable intents", () => {
46
+ const userSelectableIntents = [
47
+ "push",
48
+ "pull",
49
+ "legs",
50
+ "core",
51
+ "upper",
52
+ "lower",
53
+ "full-body",
54
+ "cardio",
55
+ "strength",
56
+ "mobility",
57
+ "fatburn",
58
+ ];
59
+ userSelectableIntents.forEach((intent) => {
60
+ (0, vitest_1.expect)(AiExerciseVocabulary_1.HARDCODED_INTENTS).toContain(intent);
61
+ });
62
+ });
63
+ (0, vitest_1.it)("should include backend-only intents", () => {
64
+ const backendOnlyIntents = ["arms", "back", "unstructured"];
65
+ backendOnlyIntents.forEach((intent) => {
66
+ (0, vitest_1.expect)(AiExerciseVocabulary_1.HARDCODED_INTENTS).toContain(intent);
67
+ });
68
+ });
69
+ (0, vitest_1.it)("should maintain stable order for backward compatibility", () => {
70
+ // First few intents should remain in this order for compatibility
71
+ (0, vitest_1.expect)(AiExerciseVocabulary_1.HARDCODED_INTENTS[0]).toBe("push");
72
+ (0, vitest_1.expect)(AiExerciseVocabulary_1.HARDCODED_INTENTS[1]).toBe("pull");
73
+ (0, vitest_1.expect)(AiExerciseVocabulary_1.HARDCODED_INTENTS[2]).toBe("legs");
74
+ (0, vitest_1.expect)(AiExerciseVocabulary_1.HARDCODED_INTENTS[3]).toBe("core");
75
+ });
76
+ });
@@ -1,8 +1,7 @@
1
- import { TAiFitnessGoal } from "./AiExerciseVocabulary";
2
- import { QUICK_START_CLEAR_INTENTS } from "./quickStartIntents";
1
+ import { TAiFitnessGoal, TWorkoutIntent } from "./AiExerciseVocabulary";
3
2
  export declare const USER_FITNESS_GOALS: readonly ["lose_weight", "build_muscle", "lean_and_toned", "glutes_and_legs", "get_stronger", "boost_endurance", "athletic_performance", "general_fitness", "posture_and_back", "stress_relief", "rehabilitation", "core_strength", "mobility_flexibility"];
4
3
  export type TUserFitnessGoal = (typeof USER_FITNESS_GOALS)[number];
5
- export type TSessionIntent = (typeof QUICK_START_CLEAR_INTENTS)[keyof typeof QUICK_START_CLEAR_INTENTS] | "rest";
4
+ export type TSessionIntent = TWorkoutIntent | "rest";
6
5
  export declare const GOAL_SESSION_INTENTS: Record<TUserFitnessGoal, TWeeklyIntentTemplate>;
7
6
  export declare const GOAL_TO_AI_FITNESS_GOAL: Record<TUserFitnessGoal, TAiFitnessGoal>;
8
7
  export declare const TRAINING_PHASES: readonly [1, 2, 3, 4];
@@ -51,7 +50,7 @@ export type TIntentDisplay = {
51
50
  */
52
51
  emoji: string;
53
52
  };
54
- export declare const INTENT_DISPLAY: Record<TSessionIntent, TIntentDisplay>;
53
+ export declare const INTENT_DISPLAY: Partial<Record<TSessionIntent, TIntentDisplay>>;
55
54
  export type TGoalDisplay = {
56
55
  /** i18n key for the goal name — e.g. "userGoal.loseWeight.name" */
57
56
  nameKey: string;
@@ -1,4 +1,3 @@
1
1
  export * from "./BodyCategories";
2
2
  export * from "./AiExerciseVocabulary";
3
- export * from "./quickStartIntents";
4
3
  export * from "./goalJourney";
@@ -16,5 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./BodyCategories"), exports);
18
18
  __exportStar(require("./AiExerciseVocabulary"), exports);
19
- __exportStar(require("./quickStartIntents"), exports);
20
19
  __exportStar(require("./goalJourney"), exports);
@@ -1,4 +1,6 @@
1
+ import { TWorkoutIntent } from "../constants/AiExerciseVocabulary";
1
2
  import { TRecord } from "./commonTypes";
3
+ import { TTemplate } from "./TApiTemplateData";
2
4
  export type TClientData = {
3
5
  clientId: string;
4
6
  trainerPlanId: string;
@@ -14,7 +16,9 @@ export type TClientSessionData = {
14
16
  records: TRecord[];
15
17
  };
16
18
  export type TApiClientProgressSaveReq = {
17
- planId?: string;
19
+ planId: string | undefined;
20
+ planType: TTemplate["type"];
21
+ intentId: Omit<TWorkoutIntent, "unstructured"> | undefined;
18
22
  sessionRecord: TClientSessionData[];
19
23
  sessionStartTimestamp: string;
20
24
  };
@@ -1,3 +1,4 @@
1
+ import { TWorkoutIntent } from "../constants";
1
2
  import { TTemplateExercise } from "./commonTypes";
2
3
  import { TProPlan } from "./TApiProPlan";
3
4
  export type TTemplateDb = TTemplate & {
@@ -13,6 +14,7 @@ export type TAiPlanContext = {
13
14
  protectedAreas: string[];
14
15
  intendedIntensity: "recovery" | "light" | "moderate" | "vigorous" | "max_effort";
15
16
  adaptationNote?: string;
17
+ intentId: TWorkoutIntent;
16
18
  };
17
19
  export type TTemplate = {
18
20
  name: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dgpholdings/greatoak-shared",
3
- "version": "1.2.90",
3
+ "version": "1.2.92",
4
4
  "description": "Shared TypeScript types and utilities for @dgpholdings projects",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",