@critical-path/core 0.33.0 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +1 -1
  3. package/dist/domain/entities.js +17 -17
  4. package/dist/domain/entities.js.map +1 -1
  5. package/dist/domain/events.d.ts +53 -2
  6. package/dist/domain/events.d.ts.map +1 -1
  7. package/dist/domain/events.js +7 -0
  8. package/dist/domain/events.js.map +1 -1
  9. package/dist/engine/entity-events.test.d.ts +2 -0
  10. package/dist/engine/entity-events.test.d.ts.map +1 -0
  11. package/dist/engine/entity-events.test.js +61 -0
  12. package/dist/engine/entity-events.test.js.map +1 -0
  13. package/dist/engine/index.d.ts +2 -0
  14. package/dist/engine/index.d.ts.map +1 -1
  15. package/dist/engine/index.js +106 -39
  16. package/dist/engine/index.js.map +1 -1
  17. package/dist/schemas/index.d.ts +6 -6
  18. package/dist/store/firebase.js +5 -5
  19. package/dist/store/firebase.js.map +1 -1
  20. package/dist/store/index.d.ts +5 -0
  21. package/dist/store/index.d.ts.map +1 -1
  22. package/dist/store/index.js +30 -13
  23. package/dist/store/index.js.map +1 -1
  24. package/dist/store/sqlite.js +13 -13
  25. package/dist/store/sqlite.js.map +1 -1
  26. package/dist/testing/conformance.d.ts.map +1 -1
  27. package/dist/testing/conformance.js +15 -0
  28. package/dist/testing/conformance.js.map +1 -1
  29. package/package.json +1 -1
  30. package/src/domain/entities.ts +17 -17
  31. package/src/domain/events.ts +49 -0
  32. package/src/engine/entity-events.test.ts +67 -0
  33. package/src/engine/index.ts +115 -39
  34. package/src/store/firebase.ts +5 -5
  35. package/src/store/index.ts +30 -13
  36. package/src/store/sqlite.ts +13 -13
  37. package/src/testing/conformance.ts +18 -0
  38. package/tsconfig.tsbuildinfo +1 -1
@@ -373,7 +373,7 @@ export class SQLiteStore implements StorageAdapter {
373
373
  }
374
374
 
375
375
  async createProject(project: Omit<Project, 'id' | 'createdAt' | 'updatedAt'>): Promise<Project> {
376
- const id = `proj_${Math.random().toString(36).substring(2, 9)}`;
376
+ const id = `proj_${crypto.randomUUID()}`;
377
377
  const now = new Date().toISOString();
378
378
  const key = project.key || generateProjectKey(project.name);
379
379
  const newProj: Project = { ...project, key, id, createdAt: now, updatedAt: now };
@@ -451,7 +451,7 @@ export class SQLiteStore implements StorageAdapter {
451
451
  }
452
452
 
453
453
  async createWorkflow(workflow: Omit<Workflow, 'id' | 'createdAt' | 'updatedAt'>): Promise<Workflow> {
454
- const id = `wf_${Math.random().toString(36).substring(2, 9)}`;
454
+ const id = `wf_${crypto.randomUUID()}`;
455
455
  const now = new Date().toISOString();
456
456
  const newWf: Workflow = { ...workflow, id, createdAt: now, updatedAt: now };
457
457
 
@@ -529,7 +529,7 @@ export class SQLiteStore implements StorageAdapter {
529
529
  }
530
530
 
531
531
  async createTeam(team: Omit<Team, 'id' | 'createdAt' | 'updatedAt'>): Promise<Team> {
532
- const id = `team_${Math.random().toString(36).substring(2, 9)}`;
532
+ const id = `team_${crypto.randomUUID()}`;
533
533
  const now = new Date().toISOString();
534
534
  const newTeam: Team = { ...team, id, createdAt: now, updatedAt: now };
535
535
 
@@ -592,7 +592,7 @@ export class SQLiteStore implements StorageAdapter {
592
592
  }
593
593
 
594
594
  async createContainer(container: Omit<TaskContainer, 'id' | 'createdAt' | 'updatedAt'>): Promise<TaskContainer> {
595
- const id = `cnt_${Math.random().toString(36).substring(2, 9)}`;
595
+ const id = `cnt_${crypto.randomUUID()}`;
596
596
  const now = new Date().toISOString();
597
597
  const newContainer: TaskContainer = { ...container, id, createdAt: now, updatedAt: now };
598
598
 
@@ -655,7 +655,7 @@ export class SQLiteStore implements StorageAdapter {
655
655
  }
656
656
 
657
657
  async createDeliverable(deliverable: CreateDeliverableInput): Promise<Deliverable> {
658
- const id = `deliv_${Math.random().toString(36).substring(2, 9)}`;
658
+ const id = `deliv_${crypto.randomUUID()}`;
659
659
  const now = new Date().toISOString();
660
660
  const newDeliverable: Deliverable = {
661
661
  ...deliverable,
@@ -802,7 +802,7 @@ export class SQLiteStore implements StorageAdapter {
802
802
  }
803
803
 
804
804
  async createTask(task: Omit<Task, 'id' | 'createdAt' | 'updatedAt'>): Promise<Task> {
805
- const id = `task_${Math.random().toString(36).substring(2, 9)}`;
805
+ const id = `task_${crypto.randomUUID()}`;
806
806
  const now = new Date().toISOString();
807
807
  const newTask: Task = { ...task, id, createdAt: now, updatedAt: now };
808
808
 
@@ -948,7 +948,7 @@ export class SQLiteStore implements StorageAdapter {
948
948
  }
949
949
 
950
950
  async createIteration(iteration: Omit<Iteration, 'id' | 'createdAt'>): Promise<Iteration> {
951
- const id = `iter_${Math.random().toString(36).substring(2, 9)}`;
951
+ const id = `iter_${crypto.randomUUID()}`;
952
952
  const now = new Date().toISOString();
953
953
  const newIteration: Iteration = { ...iteration, id, createdAt: now };
954
954
 
@@ -1029,7 +1029,7 @@ export class SQLiteStore implements StorageAdapter {
1029
1029
  }
1030
1030
 
1031
1031
  async addComment(comment: Omit<Comment, 'id' | 'createdAt' | 'updatedAt'>): Promise<Comment> {
1032
- const id = `cmt_${Math.random().toString(36).substring(2, 9)}`;
1032
+ const id = `cmt_${crypto.randomUUID()}`;
1033
1033
  const now = new Date().toISOString();
1034
1034
  const newComment: Comment = { ...comment, id, createdAt: now, updatedAt: now };
1035
1035
 
@@ -1166,7 +1166,7 @@ export class SQLiteStore implements StorageAdapter {
1166
1166
  }
1167
1167
 
1168
1168
  async createAttachment(attachment: Omit<Attachment, 'id' | 'createdAt' | 'updatedAt'>): Promise<Attachment> {
1169
- const id = `att_${Math.random().toString(36).substring(2, 9)}`;
1169
+ const id = `att_${crypto.randomUUID()}`;
1170
1170
  const now = new Date().toISOString();
1171
1171
  const newAtt: Attachment = {
1172
1172
  ...attachment,
@@ -1267,7 +1267,7 @@ export class SQLiteStore implements StorageAdapter {
1267
1267
  }
1268
1268
 
1269
1269
  async logActivity(activity: Omit<Activity, 'id' | 'createdAt'>): Promise<Activity> {
1270
- const id = `act_${Math.random().toString(36).substring(2, 9)}`;
1270
+ const id = `act_${crypto.randomUUID()}`;
1271
1271
  const now = new Date().toISOString();
1272
1272
  const newAct: Activity = { ...activity, id, createdAt: now };
1273
1273
 
@@ -1295,7 +1295,7 @@ export class SQLiteStore implements StorageAdapter {
1295
1295
  }
1296
1296
 
1297
1297
  async logTime(entry: Omit<TimeEntry, 'id' | 'loggedAt'> & { loggedAt?: string }): Promise<TimeEntry> {
1298
- const id = `time_${Math.random().toString(36).substring(2, 9)}`;
1298
+ const id = `time_${crypto.randomUUID()}`;
1299
1299
  const now = entry.loggedAt || new Date().toISOString();
1300
1300
  const newEntry: TimeEntry = { ...entry, id, loggedAt: now };
1301
1301
 
@@ -1322,7 +1322,7 @@ export class SQLiteStore implements StorageAdapter {
1322
1322
  }
1323
1323
 
1324
1324
  async addDependency(dep: Omit<TaskDependency, 'id'>): Promise<TaskDependency> {
1325
- const id = `dep_${Math.random().toString(36).substring(2, 9)}`;
1325
+ const id = `dep_${crypto.randomUUID()}`;
1326
1326
  const newDep: TaskDependency = { ...dep, id };
1327
1327
 
1328
1328
  const stmt = this.db.prepare(`
@@ -1395,7 +1395,7 @@ export class SQLiteStore implements StorageAdapter {
1395
1395
  }
1396
1396
 
1397
1397
  async addWebhook(webhook: Omit<Webhook, 'id' | 'createdAt'>): Promise<Webhook> {
1398
- const id = `wh_${Math.random().toString(36).substring(2, 9)}`;
1398
+ const id = `wh_${crypto.randomUUID()}`;
1399
1399
  const now = new Date().toISOString();
1400
1400
  const newWh: Webhook = { ...webhook, id, createdAt: now };
1401
1401
 
@@ -140,6 +140,24 @@ export function runStorageAdapterConformance({ name, createStore, describe, it,
140
140
  expect(updated.parentId === null).toBe(false);
141
141
  });
142
142
 
143
+ it('returns copies, so mutating results or reused inputs does not change stored records', async () => {
144
+ const store = await createStore();
145
+ const project = await store.createProject({ name: 'P' });
146
+ const input = { projectId: project.id, title: 'Original', status: 'todo', priority: 'medium', tags: ['a'] };
147
+ const created = await store.createTask(input);
148
+
149
+ input.tags.push('mutated-input');
150
+ input.title = 'Mutated input';
151
+ const fetched = (await store.getTask(created.id))!;
152
+ fetched.tags!.push('mutated-result');
153
+ fetched.title = 'Mutated result';
154
+ (await store.getTasks(project.id))[0].title = 'Mutated list';
155
+
156
+ const stored = await store.getTask(created.id);
157
+ expect(stored?.title).toBe('Original');
158
+ expect(stored?.tags).toEqual(['a']);
159
+ });
160
+
143
161
  it('follows the not-found contract', async () => {
144
162
  const store = await createStore();
145
163
  expect(await store.getProject('missing')).toBeNull();
@@ -1 +1 @@
1
- {"root":["./src/deliverables.test.ts","./src/index.test.ts","./src/index.ts","./src/status.test.ts","./src/task-state.test.ts","./src/use-case-validation.test.ts","./src/domain/authorization.ts","./src/domain/calendar.test.ts","./src/domain/calendar.ts","./src/domain/cpm.test.ts","./src/domain/cpm.ts","./src/domain/custom-fields.ts","./src/domain/ddd.test.ts","./src/domain/entities.ts","./src/domain/errors.ts","./src/domain/events.ts","./src/domain/graph.ts","./src/domain/index.ts","./src/domain/ladder.test.ts","./src/domain/ladder.ts","./src/domain/metrics.test.ts","./src/domain/metrics.ts","./src/domain/task-duration.test.ts","./src/domain/workload.test.ts","./src/domain/workload.ts","./src/engine/actor.test.ts","./src/engine/authorization.test.ts","./src/engine/cascade.test.ts","./src/engine/config.test.ts","./src/engine/index.ts","./src/plugins/index.ts","./src/plugins/plugins.test.ts","./src/schemas/index.ts","./src/schemas/schemas.test.ts","./src/storage/file-storage.ts","./src/storage/firebase-storage.ts","./src/storage/index.ts","./src/storage/s3.ts","./src/storage/storage.test.ts","./src/store/conformance.test.ts","./src/store/firebase.test.ts","./src/store/firebase.ts","./src/store/index.ts","./src/store/query.test.ts","./src/store/query.ts","./src/store/sqlite.test.ts","./src/store/sqlite.ts","./src/testing/conformance.ts","./src/testing/index.ts","./src/types/index.ts","./src/utils/fractional-index.test.ts","./src/utils/fractional-index.ts","./src/utils/index.ts","./src/utils/key.test.ts","./src/utils/key.ts","./src/utils/mentions.test.ts","./src/utils/mentions.ts","./src/utils/status.ts","./src/utils/workflow.ts","./src/webhooks/dispatcher.ts","./src/webhooks/index.ts","./src/webhooks/signature.ts","./src/webhooks/webhooks.test.ts"],"version":"5.9.3"}
1
+ {"root":["./src/deliverables.test.ts","./src/index.test.ts","./src/index.ts","./src/status.test.ts","./src/task-state.test.ts","./src/use-case-validation.test.ts","./src/domain/authorization.ts","./src/domain/calendar.test.ts","./src/domain/calendar.ts","./src/domain/cpm.test.ts","./src/domain/cpm.ts","./src/domain/custom-fields.ts","./src/domain/ddd.test.ts","./src/domain/entities.ts","./src/domain/errors.ts","./src/domain/events.ts","./src/domain/graph.ts","./src/domain/index.ts","./src/domain/ladder.test.ts","./src/domain/ladder.ts","./src/domain/metrics.test.ts","./src/domain/metrics.ts","./src/domain/task-duration.test.ts","./src/domain/workload.test.ts","./src/domain/workload.ts","./src/engine/actor.test.ts","./src/engine/authorization.test.ts","./src/engine/cascade.test.ts","./src/engine/config.test.ts","./src/engine/entity-events.test.ts","./src/engine/index.ts","./src/plugins/index.ts","./src/plugins/plugins.test.ts","./src/schemas/index.ts","./src/schemas/schemas.test.ts","./src/storage/file-storage.ts","./src/storage/firebase-storage.ts","./src/storage/index.ts","./src/storage/s3.ts","./src/storage/storage.test.ts","./src/store/conformance.test.ts","./src/store/firebase.test.ts","./src/store/firebase.ts","./src/store/index.ts","./src/store/query.test.ts","./src/store/query.ts","./src/store/sqlite.test.ts","./src/store/sqlite.ts","./src/testing/conformance.ts","./src/testing/index.ts","./src/types/index.ts","./src/utils/fractional-index.test.ts","./src/utils/fractional-index.ts","./src/utils/index.ts","./src/utils/key.test.ts","./src/utils/key.ts","./src/utils/mentions.test.ts","./src/utils/mentions.ts","./src/utils/status.ts","./src/utils/workflow.ts","./src/webhooks/dispatcher.ts","./src/webhooks/index.ts","./src/webhooks/signature.ts","./src/webhooks/webhooks.test.ts"],"version":"5.9.3"}