90dc-core 1.13.4 → 1.13.5

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.
@@ -12,5 +12,6 @@ export declare class WorkoutSession extends Model<WorkoutSession> {
12
12
  status: SessionStatus;
13
13
  startedAt: Date;
14
14
  completedAt: Date | null;
15
+ progressSnapshot: any[] | null;
15
16
  }
16
17
  //# sourceMappingURL=WorkoutSession.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkoutSession.d.ts","sourceRoot":"","sources":["../../../../src/lib/dbmodels/program/WorkoutSession.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,KAAK,EAOR,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,oBAAY,aAAa;IACrB,MAAM,WAAW;IACjB,SAAS,cAAc;CAC1B;AAED,qBAYa,cAAe,SAAQ,KAAK,CAAC,cAAc,CAAC;IAQ7C,IAAI,EAAE,MAAM,CAAC;IAIb,QAAQ,EAAE,MAAM,CAAC;IAKjB,WAAW,EAAE,MAAM,CAAC;IAGpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAOlB,MAAM,EAAE,aAAa,CAAC;IAGtB,SAAS,EAAE,IAAI,CAAC;IAGhB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;CACpC"}
1
+ {"version":3,"file":"WorkoutSession.d.ts","sourceRoot":"","sources":["../../../../src/lib/dbmodels/program/WorkoutSession.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,KAAK,EAOR,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,oBAAY,aAAa;IACrB,MAAM,WAAW;IACjB,SAAS,cAAc;CAC1B;AAED,qBAYa,cAAe,SAAQ,KAAK,CAAC,cAAc,CAAC;IAQ7C,IAAI,EAAE,MAAM,CAAC;IAIb,QAAQ,EAAE,MAAM,CAAC;IAKjB,WAAW,EAAE,MAAM,CAAC;IAGpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAOlB,MAAM,EAAE,aAAa,CAAC;IAGtB,SAAS,EAAE,IAAI,CAAC;IAGhB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IAOzB,gBAAgB,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;CAC1C"}
@@ -63,6 +63,13 @@ _ts_decorate([
63
63
  allowNull: true
64
64
  })
65
65
  ], WorkoutSession.prototype, "completedAt", void 0);
66
+ _ts_decorate([
67
+ Column({
68
+ type: DataType.JSONB,
69
+ allowNull: true,
70
+ comment: 'Stores current workout progress: exercises completed, sets, reps, weight, etc.'
71
+ })
72
+ ], WorkoutSession.prototype, "progressSnapshot", void 0);
66
73
  WorkoutSession = _ts_decorate([
67
74
  Table({
68
75
  tableName: 'WorkoutSessions',
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/dbmodels/program/WorkoutSession.ts"],"sourcesContent":["import {\n Table,\n Model,\n Column,\n DataType,\n Default,\n ForeignKey,\n BelongsTo,\n Index,\n} from 'sequelize-typescript';\nimport { Workout } from './Workout.js';\n\nexport enum SessionStatus {\n ACTIVE = 'active',\n COMPLETED = 'completed',\n}\n\n@Table({\n tableName: 'WorkoutSessions',\n timestamps: true,\n indexes: [\n {\n unique: true,\n fields: ['workoutUuid', 'status'],\n where: { status: 'active' },\n name: 'unique_active_session_per_workout'\n }\n ]\n})\nexport class WorkoutSession extends Model<WorkoutSession> {\n @Default(DataType.UUIDV4)\n @Column({\n type: DataType.UUID,\n defaultValue: DataType.UUIDV4,\n allowNull: false,\n primaryKey: true,\n })\n declare uuid: string;\n\n @Index\n @Column({ type: DataType.UUID, allowNull: false })\n declare userUuid: string;\n\n @ForeignKey(() => Workout)\n @Index\n @Column({ type: DataType.UUID, allowNull: false })\n declare workoutUuid: string;\n\n @BelongsTo(() => Workout, { foreignKey: 'workoutUuid', onDelete: 'CASCADE' })\n declare workout?: Workout;\n\n @Column({\n type: DataType.ENUM(...Object.values(SessionStatus)),\n allowNull: false,\n defaultValue: SessionStatus.ACTIVE,\n })\n declare status: SessionStatus;\n\n @Column({ type: DataType.DATE, allowNull: false, defaultValue: DataType.NOW })\n declare startedAt: Date;\n\n @Column({ type: DataType.DATE, allowNull: true })\n declare completedAt: Date | null;\n}"],"names":["Table","Model","Column","DataType","Default","ForeignKey","BelongsTo","Index","Workout","SessionStatus","WorkoutSession","UUIDV4","type","UUID","defaultValue","allowNull","primaryKey","foreignKey","onDelete","ENUM","Object","values","DATE","NOW","tableName","timestamps","indexes","unique","fields","where","status","name"],"mappings":";;;;;;AAAA,SACIA,KAAK,EACLC,KAAK,EACLC,MAAM,EACNC,QAAQ,EACRC,OAAO,EACPC,UAAU,EACVC,SAAS,EACTC,KAAK,QACF,uBAAuB;AAC9B,SAASC,OAAO,QAAQ,eAAe;AAEvC,OAAO,IAAA,AAAKC,uCAAAA;;;WAAAA;MAGX;AAcD,OAAO,MAAMC,uBAAuBT;AAkCpC;;qBAjCsBU;;QAEdC,MAAMT,SAASU,IAAI;QACnBC,cAAcX,SAASQ,MAAM;QAC7BI,WAAW;QACXC,YAAY;;;;;;QAKNJ,MAAMT,SAASU,IAAI;QAAEE,WAAW;;;;mBAGxBP;;;QAERI,MAAMT,SAASU,IAAI;QAAEE,WAAW;;;;kBAGzBP;QAAWS,YAAY;QAAeC,UAAU;;;;;QAI7DN,MAAMT,SAASgB,IAAI,IAAIC,OAAOC,MAAM,CAACZ;QACrCM,WAAW;QACXD,YAAY;;;;;QAINF,MAAMT,SAASmB,IAAI;QAAEP,WAAW;QAAOD,cAAcX,SAASoB,GAAG;;;;;QAGjEX,MAAMT,SAASmB,IAAI;QAAEP,WAAW;;;;;QA3C1CS,WAAW;QACXC,YAAY;QACZC,SAAS;YACL;gBACIC,QAAQ;gBACRC,QAAQ;oBAAC;oBAAe;iBAAS;gBACjCC,OAAO;oBAAEC,QAAQ;gBAAS;gBAC1BC,MAAM;YACV;SACH"}
1
+ {"version":3,"sources":["../../../../src/lib/dbmodels/program/WorkoutSession.ts"],"sourcesContent":["import {\n Table,\n Model,\n Column,\n DataType,\n Default,\n ForeignKey,\n BelongsTo,\n Index,\n} from 'sequelize-typescript';\nimport { Workout } from './Workout.js';\n\nexport enum SessionStatus {\n ACTIVE = 'active',\n COMPLETED = 'completed',\n}\n\n@Table({\n tableName: 'WorkoutSessions',\n timestamps: true,\n indexes: [\n {\n unique: true,\n fields: ['workoutUuid', 'status'],\n where: { status: 'active' },\n name: 'unique_active_session_per_workout'\n }\n ]\n})\nexport class WorkoutSession extends Model<WorkoutSession> {\n @Default(DataType.UUIDV4)\n @Column({\n type: DataType.UUID,\n defaultValue: DataType.UUIDV4,\n allowNull: false,\n primaryKey: true,\n })\n declare uuid: string;\n\n @Index\n @Column({ type: DataType.UUID, allowNull: false })\n declare userUuid: string;\n\n @ForeignKey(() => Workout)\n @Index\n @Column({ type: DataType.UUID, allowNull: false })\n declare workoutUuid: string;\n\n @BelongsTo(() => Workout, { foreignKey: 'workoutUuid', onDelete: 'CASCADE' })\n declare workout?: Workout;\n\n @Column({\n type: DataType.ENUM(...Object.values(SessionStatus)),\n allowNull: false,\n defaultValue: SessionStatus.ACTIVE,\n })\n declare status: SessionStatus;\n\n @Column({ type: DataType.DATE, allowNull: false, defaultValue: DataType.NOW })\n declare startedAt: Date;\n\n @Column({ type: DataType.DATE, allowNull: true })\n declare completedAt: Date | null;\n\n @Column({\n type: DataType.JSONB,\n allowNull: true,\n comment: 'Stores current workout progress: exercises completed, sets, reps, weight, etc.'\n })\n declare progressSnapshot: any[] | null;\n}"],"names":["Table","Model","Column","DataType","Default","ForeignKey","BelongsTo","Index","Workout","SessionStatus","WorkoutSession","UUIDV4","type","UUID","defaultValue","allowNull","primaryKey","foreignKey","onDelete","ENUM","Object","values","DATE","NOW","JSONB","comment","tableName","timestamps","indexes","unique","fields","where","status","name"],"mappings":";;;;;;AAAA,SACIA,KAAK,EACLC,KAAK,EACLC,MAAM,EACNC,QAAQ,EACRC,OAAO,EACPC,UAAU,EACVC,SAAS,EACTC,KAAK,QACF,uBAAuB;AAC9B,SAASC,OAAO,QAAQ,eAAe;AAEvC,OAAO,IAAA,AAAKC,uCAAAA;;;WAAAA;MAGX;AAcD,OAAO,MAAMC,uBAAuBT;AAyCpC;;qBAxCsBU;;QAEdC,MAAMT,SAASU,IAAI;QACnBC,cAAcX,SAASQ,MAAM;QAC7BI,WAAW;QACXC,YAAY;;;;;;QAKNJ,MAAMT,SAASU,IAAI;QAAEE,WAAW;;;;mBAGxBP;;;QAERI,MAAMT,SAASU,IAAI;QAAEE,WAAW;;;;kBAGzBP;QAAWS,YAAY;QAAeC,UAAU;;;;;QAI7DN,MAAMT,SAASgB,IAAI,IAAIC,OAAOC,MAAM,CAACZ;QACrCM,WAAW;QACXD,YAAY;;;;;QAINF,MAAMT,SAASmB,IAAI;QAAEP,WAAW;QAAOD,cAAcX,SAASoB,GAAG;;;;;QAGjEX,MAAMT,SAASmB,IAAI;QAAEP,WAAW;;;;;QAItCH,MAAMT,SAASqB,KAAK;QACpBT,WAAW;QACXU,SAAS;;;;;QAjDbC,WAAW;QACXC,YAAY;QACZC,SAAS;YACL;gBACIC,QAAQ;gBACRC,QAAQ;oBAAC;oBAAe;iBAAS;gBACjCC,OAAO;oBAAEC,QAAQ;gBAAS;gBAC1BC,MAAM;YACV;SACH"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Migration: Add Partial Unique Constraint on WorkoutSessions
3
+ * Ensures only one ACTIVE session exists per workout, while allowing multiple COMPLETED sessions
4
+ *
5
+ * This is critical for circular programs where workouts repeat across cycles.
6
+ * Each cycle can have its own session history, but only one can be active at a time.
7
+ *
8
+ * Before: No constraint, relied on application logic (findOne)
9
+ * After: Database-level constraint prevents duplicate active sessions
10
+ */ 'use strict';
11
+ module.exports = {
12
+ async up (queryInterface, Sequelize) {
13
+ console.log('🔄 Creating partial unique constraint on WorkoutSessions...');
14
+ // Check if index already exists to make migration idempotent
15
+ const [results] = await queryInterface.sequelize.query(`
16
+ SELECT indexname
17
+ FROM pg_indexes
18
+ WHERE tablename = 'WorkoutSessions'
19
+ AND indexname = 'unique_active_session_per_workout';
20
+ `);
21
+ if (results.length > 0) {
22
+ console.log('✅ Constraint unique_active_session_per_workout already exists, skipping...');
23
+ return;
24
+ }
25
+ // Add partial unique index: only one active session per workout
26
+ await queryInterface.addIndex('WorkoutSessions', [
27
+ 'workoutUuid',
28
+ 'status'
29
+ ], {
30
+ unique: true,
31
+ name: 'unique_active_session_per_workout',
32
+ where: {
33
+ status: 'active'
34
+ }
35
+ });
36
+ console.log('✅ Partial unique constraint on WorkoutSessions created successfully');
37
+ },
38
+ async down (queryInterface, Sequelize) {
39
+ console.log('🔄 Dropping partial unique constraint on WorkoutSessions...');
40
+ await queryInterface.removeIndex('WorkoutSessions', 'unique_active_session_per_workout');
41
+ console.log('✅ Constraint on WorkoutSessions dropped');
42
+ }
43
+ };
44
+
45
+ //# sourceMappingURL=20260115000000-add-workout-session-unique-constraint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/lib/scripts/migrations/20260115000000-add-workout-session-unique-constraint.js"],"sourcesContent":["/**\n * Migration: Add Partial Unique Constraint on WorkoutSessions\n * Ensures only one ACTIVE session exists per workout, while allowing multiple COMPLETED sessions\n *\n * This is critical for circular programs where workouts repeat across cycles.\n * Each cycle can have its own session history, but only one can be active at a time.\n *\n * Before: No constraint, relied on application logic (findOne)\n * After: Database-level constraint prevents duplicate active sessions\n */\n\n'use strict';\n\nmodule.exports = {\n async up(queryInterface, Sequelize) {\n console.log('🔄 Creating partial unique constraint on WorkoutSessions...');\n\n // Check if index already exists to make migration idempotent\n const [results] = await queryInterface.sequelize.query(`\n SELECT indexname\n FROM pg_indexes\n WHERE tablename = 'WorkoutSessions'\n AND indexname = 'unique_active_session_per_workout';\n `);\n\n if (results.length > 0) {\n console.log('✅ Constraint unique_active_session_per_workout already exists, skipping...');\n return;\n }\n\n // Add partial unique index: only one active session per workout\n await queryInterface.addIndex('WorkoutSessions', ['workoutUuid', 'status'], {\n unique: true,\n name: 'unique_active_session_per_workout',\n where: {\n status: 'active'\n }\n });\n\n console.log('✅ Partial unique constraint on WorkoutSessions created successfully');\n },\n\n async down(queryInterface, Sequelize) {\n console.log('🔄 Dropping partial unique constraint on WorkoutSessions...');\n\n await queryInterface.removeIndex('WorkoutSessions', 'unique_active_session_per_workout');\n\n console.log('✅ Constraint on WorkoutSessions dropped');\n }\n};\n"],"names":["module","exports","up","queryInterface","Sequelize","console","log","results","sequelize","query","length","addIndex","unique","name","where","status","down","removeIndex"],"mappings":"AAAA;;;;;;;;;CASC,GAED;AAEAA,OAAOC,OAAO,GAAG;IACf,MAAMC,IAAGC,cAAc,EAAEC,SAAS;QAChCC,QAAQC,GAAG,CAAC;QAEZ,6DAA6D;QAC7D,MAAM,CAACC,QAAQ,GAAG,MAAMJ,eAAeK,SAAS,CAACC,KAAK,CAAC,CAAC;;;;;IAKxD,CAAC;QAED,IAAIF,QAAQG,MAAM,GAAG,GAAG;YACtBL,QAAQC,GAAG,CAAC;YACZ;QACF;QAEA,gEAAgE;QAChE,MAAMH,eAAeQ,QAAQ,CAAC,mBAAmB;YAAC;YAAe;SAAS,EAAE;YAC1EC,QAAQ;YACRC,MAAM;YACNC,OAAO;gBACLC,QAAQ;YACV;QACF;QAEAV,QAAQC,GAAG,CAAC;IACd;IAEA,MAAMU,MAAKb,cAAc,EAAEC,SAAS;QAClCC,QAAQC,GAAG,CAAC;QAEZ,MAAMH,eAAec,WAAW,CAAC,mBAAmB;QAEpDZ,QAAQC,GAAG,CAAC;IACd;AACF"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Migration: Add progressSnapshot field to WorkoutSessions
3
+ *
4
+ * Allows tracking of in-progress workout data (exercises completed, sets, reps, weight, etc.)
5
+ * during an active workout session. This is especially useful for:
6
+ * - Auto-save functionality during workout
7
+ * - Resume workout capability
8
+ * - Circular programs where same template is reused
9
+ *
10
+ * Data flow:
11
+ * 1. During workout: progressSnapshot stores current state
12
+ * 2. On finish: progressSnapshot data moves to WorkoutCompletion.exercisesSnapshot
13
+ * 3. Session status becomes 'completed'
14
+ */ 'use strict';
15
+ module.exports = {
16
+ async up (queryInterface, Sequelize) {
17
+ console.log('🔄 Adding progressSnapshot column to WorkoutSessions...');
18
+ // Check if column already exists to make migration idempotent
19
+ const [results] = await queryInterface.sequelize.query(`
20
+ SELECT column_name
21
+ FROM information_schema.columns
22
+ WHERE table_name = 'WorkoutSessions'
23
+ AND column_name = 'progressSnapshot';
24
+ `);
25
+ if (results.length > 0) {
26
+ console.log('✅ Column progressSnapshot already exists, skipping...');
27
+ return;
28
+ }
29
+ // Add progressSnapshot column
30
+ await queryInterface.addColumn('WorkoutSessions', 'progressSnapshot', {
31
+ type: Sequelize.JSONB,
32
+ allowNull: true,
33
+ defaultValue: null,
34
+ comment: 'Stores current workout progress: exercises completed, sets, reps, weight, etc.'
35
+ });
36
+ console.log('✅ progressSnapshot column added successfully');
37
+ },
38
+ async down (queryInterface, Sequelize) {
39
+ console.log('🔄 Dropping progressSnapshot column from WorkoutSessions...');
40
+ await queryInterface.removeColumn('WorkoutSessions', 'progressSnapshot');
41
+ console.log('✅ progressSnapshot column dropped');
42
+ }
43
+ };
44
+
45
+ //# sourceMappingURL=20260116000000-add-workout-session-progress-snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/lib/scripts/migrations/20260116000000-add-workout-session-progress-snapshot.js"],"sourcesContent":["/**\n * Migration: Add progressSnapshot field to WorkoutSessions\n *\n * Allows tracking of in-progress workout data (exercises completed, sets, reps, weight, etc.)\n * during an active workout session. This is especially useful for:\n * - Auto-save functionality during workout\n * - Resume workout capability\n * - Circular programs where same template is reused\n *\n * Data flow:\n * 1. During workout: progressSnapshot stores current state\n * 2. On finish: progressSnapshot data moves to WorkoutCompletion.exercisesSnapshot\n * 3. Session status becomes 'completed'\n */\n\n'use strict';\n\nmodule.exports = {\n async up(queryInterface, Sequelize) {\n console.log('🔄 Adding progressSnapshot column to WorkoutSessions...');\n\n // Check if column already exists to make migration idempotent\n const [results] = await queryInterface.sequelize.query(`\n SELECT column_name\n FROM information_schema.columns\n WHERE table_name = 'WorkoutSessions'\n AND column_name = 'progressSnapshot';\n `);\n\n if (results.length > 0) {\n console.log('✅ Column progressSnapshot already exists, skipping...');\n return;\n }\n\n // Add progressSnapshot column\n await queryInterface.addColumn('WorkoutSessions', 'progressSnapshot', {\n type: Sequelize.JSONB,\n allowNull: true,\n defaultValue: null,\n comment: 'Stores current workout progress: exercises completed, sets, reps, weight, etc.'\n });\n\n console.log('✅ progressSnapshot column added successfully');\n },\n\n async down(queryInterface, Sequelize) {\n console.log('🔄 Dropping progressSnapshot column from WorkoutSessions...');\n\n await queryInterface.removeColumn('WorkoutSessions', 'progressSnapshot');\n\n console.log('✅ progressSnapshot column dropped');\n }\n};\n"],"names":["module","exports","up","queryInterface","Sequelize","console","log","results","sequelize","query","length","addColumn","type","JSONB","allowNull","defaultValue","comment","down","removeColumn"],"mappings":"AAAA;;;;;;;;;;;;;CAaC,GAED;AAEAA,OAAOC,OAAO,GAAG;IACf,MAAMC,IAAGC,cAAc,EAAEC,SAAS;QAChCC,QAAQC,GAAG,CAAC;QAEZ,8DAA8D;QAC9D,MAAM,CAACC,QAAQ,GAAG,MAAMJ,eAAeK,SAAS,CAACC,KAAK,CAAC,CAAC;;;;;IAKxD,CAAC;QAED,IAAIF,QAAQG,MAAM,GAAG,GAAG;YACtBL,QAAQC,GAAG,CAAC;YACZ;QACF;QAEA,8BAA8B;QAC9B,MAAMH,eAAeQ,SAAS,CAAC,mBAAmB,oBAAoB;YACpEC,MAAMR,UAAUS,KAAK;YACrBC,WAAW;YACXC,cAAc;YACdC,SAAS;QACX;QAEAX,QAAQC,GAAG,CAAC;IACd;IAEA,MAAMW,MAAKd,cAAc,EAAEC,SAAS;QAClCC,QAAQC,GAAG,CAAC;QAEZ,MAAMH,eAAee,YAAY,CAAC,mBAAmB;QAErDb,QAAQC,GAAG,CAAC;IACd;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "90dc-core",
3
- "version": "1.13.4",
3
+ "version": "1.13.5",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",