@todu/engine 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/change-observer.d.ts +15 -0
- package/dist/change-observer.d.ts.map +1 -0
- package/dist/change-observer.js +64 -0
- package/dist/change-observer.js.map +1 -0
- package/dist/habits.d.ts +6 -0
- package/dist/habits.d.ts.map +1 -0
- package/dist/habits.js +397 -0
- package/dist/habits.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +104 -0
- package/dist/index.js.map +1 -0
- package/dist/labels.d.ts +5 -0
- package/dist/labels.d.ts.map +1 -0
- package/dist/labels.js +113 -0
- package/dist/labels.js.map +1 -0
- package/dist/notes.d.ts +5 -0
- package/dist/notes.d.ts.map +1 -0
- package/dist/notes.js +163 -0
- package/dist/notes.js.map +1 -0
- package/dist/projects.d.ts +5 -0
- package/dist/projects.d.ts.map +1 -0
- package/dist/projects.js +117 -0
- package/dist/projects.js.map +1 -0
- package/dist/recurring.d.ts +23 -0
- package/dist/recurring.d.ts.map +1 -0
- package/dist/recurring.js +372 -0
- package/dist/recurring.js.map +1 -0
- package/dist/schedule.d.ts +38 -0
- package/dist/schedule.d.ts.map +1 -0
- package/dist/schedule.js +330 -0
- package/dist/schedule.js.map +1 -0
- package/dist/scheduling.d.ts +62 -0
- package/dist/scheduling.d.ts.map +1 -0
- package/dist/scheduling.js +58 -0
- package/dist/scheduling.js.map +1 -0
- package/dist/storage.d.ts +34 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +204 -0
- package/dist/storage.js.map +1 -0
- package/dist/sync-client.d.ts +16 -0
- package/dist/sync-client.d.ts.map +1 -0
- package/dist/sync-client.js +54 -0
- package/dist/sync-client.js.map +1 -0
- package/dist/sync-server.d.ts +12 -0
- package/dist/sync-server.d.ts.map +1 -0
- package/dist/sync-server.js +21 -0
- package/dist/sync-server.js.map +1 -0
- package/dist/tasks.d.ts +18 -0
- package/dist/tasks.d.ts.map +1 -0
- package/dist/tasks.js +396 -0
- package/dist/tasks.js.map +1 -0
- package/dist/todu.d.ts +115 -0
- package/dist/todu.d.ts.map +1 -0
- package/dist/todu.js +76 -0
- package/dist/todu.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/labels.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { DocHandle, Repo } from "@automerge/automerge-repo";
|
|
2
|
+
import { type CatalogDocument } from "@todu/core";
|
|
3
|
+
import type { LabelNamespace } from "./todu.js";
|
|
4
|
+
export declare function createLabelNamespace(catalog: DocHandle<CatalogDocument>, repo: Repo): LabelNamespace;
|
|
5
|
+
//# sourceMappingURL=labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAc,IAAI,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EACL,KAAK,eAAe,EAcrB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAMhD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,SAAS,CAAC,eAAe,CAAC,EACnC,IAAI,EAAE,IAAI,GACT,cAAc,CAgHhB"}
|
package/dist/labels.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { createLabelId, err, notFound, ok, validateCreateLabelInput, validateUpdateLabelInput, validationError, } from "@todu/core";
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Label namespace — CRUD operations on catalog document
|
|
5
|
+
// ============================================================================
|
|
6
|
+
export function createLabelNamespace(catalog, repo) {
|
|
7
|
+
return {
|
|
8
|
+
async create(input) {
|
|
9
|
+
const validationErr = validateCreateLabelInput(input);
|
|
10
|
+
if (validationErr)
|
|
11
|
+
return err(validationErr);
|
|
12
|
+
// Check name uniqueness
|
|
13
|
+
const doc = catalog.doc();
|
|
14
|
+
if (doc) {
|
|
15
|
+
const existing = doc.labels.find((l) => l.name.toLowerCase() === input.name.trim().toLowerCase());
|
|
16
|
+
if (existing) {
|
|
17
|
+
return err(validationError("name", `Label "${input.name.trim()}" already exists`));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const now = new Date().toISOString();
|
|
21
|
+
const id = createLabelId(`lbl-${crypto.randomUUID().slice(0, 8)}`);
|
|
22
|
+
const label = {
|
|
23
|
+
id,
|
|
24
|
+
name: input.name.trim(),
|
|
25
|
+
createdAt: now,
|
|
26
|
+
};
|
|
27
|
+
if (input.color !== undefined) {
|
|
28
|
+
label.color = input.color;
|
|
29
|
+
}
|
|
30
|
+
catalog.change((doc) => {
|
|
31
|
+
doc.labels.push(label);
|
|
32
|
+
});
|
|
33
|
+
return ok(label);
|
|
34
|
+
},
|
|
35
|
+
async list() {
|
|
36
|
+
const doc = catalog.doc();
|
|
37
|
+
if (!doc)
|
|
38
|
+
return ok([]);
|
|
39
|
+
return ok(doc.labels.map(cloneLabel));
|
|
40
|
+
},
|
|
41
|
+
async update(id, input) {
|
|
42
|
+
const validationErr = validateUpdateLabelInput(input);
|
|
43
|
+
if (validationErr)
|
|
44
|
+
return err(validationErr);
|
|
45
|
+
const doc = catalog.doc();
|
|
46
|
+
if (!doc)
|
|
47
|
+
return err(notFound("label", id));
|
|
48
|
+
const index = doc.labels.findIndex((l) => l.id === id);
|
|
49
|
+
if (index === -1)
|
|
50
|
+
return err(notFound("label", id));
|
|
51
|
+
// Check name uniqueness if name is changing
|
|
52
|
+
if (input.name !== undefined) {
|
|
53
|
+
const existing = doc.labels.find((l) => l.id !== id && l.name.toLowerCase() === input.name.trim().toLowerCase());
|
|
54
|
+
if (existing) {
|
|
55
|
+
return err(validationError("name", `Label "${input.name.trim()}" already exists`));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catalog.change((doc) => {
|
|
59
|
+
const label = doc.labels[index];
|
|
60
|
+
if (input.name !== undefined)
|
|
61
|
+
label.name = input.name.trim();
|
|
62
|
+
if (input.color !== undefined)
|
|
63
|
+
label.color = input.color;
|
|
64
|
+
});
|
|
65
|
+
const updated = catalog.doc().labels[index];
|
|
66
|
+
return ok(cloneLabel(updated));
|
|
67
|
+
},
|
|
68
|
+
async delete(id) {
|
|
69
|
+
const doc = catalog.doc();
|
|
70
|
+
if (!doc)
|
|
71
|
+
return err(notFound("label", id));
|
|
72
|
+
const index = doc.labels.findIndex((l) => l.id === id);
|
|
73
|
+
if (index === -1)
|
|
74
|
+
return err(notFound("label", id));
|
|
75
|
+
const labelName = doc.labels[index].name;
|
|
76
|
+
// Remove label from all tasks that reference it
|
|
77
|
+
for (const docId of Object.values(doc.taskListDocIds)) {
|
|
78
|
+
const handle = await repo.find(docId);
|
|
79
|
+
const listDoc = handle.doc();
|
|
80
|
+
if (!listDoc)
|
|
81
|
+
continue;
|
|
82
|
+
const tasksWithLabel = listDoc.tasks
|
|
83
|
+
.map((t, i) => ({ index: i, hasLabel: t.labels.includes(labelName) }))
|
|
84
|
+
.filter((t) => t.hasLabel);
|
|
85
|
+
if (tasksWithLabel.length > 0) {
|
|
86
|
+
handle.change((doc) => {
|
|
87
|
+
for (const { index } of tasksWithLabel) {
|
|
88
|
+
const task = doc.tasks[index];
|
|
89
|
+
const labelIdx = task.labels.indexOf(labelName);
|
|
90
|
+
if (labelIdx !== -1) {
|
|
91
|
+
task.labels.splice(labelIdx, 1);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Remove from catalog
|
|
98
|
+
catalog.change((doc) => {
|
|
99
|
+
doc.labels.splice(index, 1);
|
|
100
|
+
});
|
|
101
|
+
return ok(undefined);
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function cloneLabel(l) {
|
|
106
|
+
return {
|
|
107
|
+
id: l.id,
|
|
108
|
+
name: l.name,
|
|
109
|
+
color: l.color,
|
|
110
|
+
createdAt: l.createdAt,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.js","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"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"}
|
package/dist/notes.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { DocHandle, Repo } from "@automerge/automerge-repo";
|
|
2
|
+
import { type CatalogDocument } from "@todu/core";
|
|
3
|
+
import type { NoteNamespace } from "./todu.js";
|
|
4
|
+
export declare function createNoteNamespace(catalog: DocHandle<CatalogDocument>, repo: Repo): NoteNamespace;
|
|
5
|
+
//# sourceMappingURL=notes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notes.d.ts","sourceRoot":"","sources":["../src/notes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAc,IAAI,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EACL,KAAK,eAAe,EAgBrB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAM/C,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,SAAS,CAAC,eAAe,CAAC,EACnC,IAAI,EAAE,IAAI,GACT,aAAa,CA+Jf"}
|
package/dist/notes.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { createNoteId, createNotesDocument, err, notFound, ok, validateCreateNoteInput, validateUpdateNoteInput, } from "@todu/core";
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Note namespace — CRUD on NotesDocument
|
|
5
|
+
// ============================================================================
|
|
6
|
+
export function createNoteNamespace(catalog, repo) {
|
|
7
|
+
/**
|
|
8
|
+
* Get or create the global NotesDocument.
|
|
9
|
+
*/
|
|
10
|
+
async function getOrCreateNotesDoc() {
|
|
11
|
+
const catalogDoc = catalog.doc();
|
|
12
|
+
const existingDocId = catalogDoc?.notesDocId;
|
|
13
|
+
if (existingDocId) {
|
|
14
|
+
return await repo.find(existingDocId);
|
|
15
|
+
}
|
|
16
|
+
const handle = repo.create();
|
|
17
|
+
const template = createNotesDocument();
|
|
18
|
+
handle.change((doc) => {
|
|
19
|
+
doc.notes = template.notes;
|
|
20
|
+
});
|
|
21
|
+
catalog.change((doc) => {
|
|
22
|
+
doc.notesDocId = handle.documentId;
|
|
23
|
+
});
|
|
24
|
+
return handle;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Verify that an entity exists (task or project).
|
|
28
|
+
*/
|
|
29
|
+
async function entityExists(entityType, entityId) {
|
|
30
|
+
const catalogDoc = catalog.doc();
|
|
31
|
+
if (!catalogDoc)
|
|
32
|
+
return false;
|
|
33
|
+
if (entityType === "project") {
|
|
34
|
+
return catalogDoc.projects.some((p) => p.id === entityId);
|
|
35
|
+
}
|
|
36
|
+
if (entityType === "task") {
|
|
37
|
+
for (const docId of Object.values(catalogDoc.taskListDocIds)) {
|
|
38
|
+
const handle = await repo.find(docId);
|
|
39
|
+
const doc = handle.doc();
|
|
40
|
+
if (doc?.tasks.some((t) => t.id === entityId))
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
// Habits will be checked when that slice lands
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
async create(input) {
|
|
50
|
+
const validationErr = validateCreateNoteInput(input);
|
|
51
|
+
if (validationErr)
|
|
52
|
+
return err(validationErr);
|
|
53
|
+
// Verify entity exists if attached
|
|
54
|
+
if (input.entityType && input.entityId) {
|
|
55
|
+
const exists = await entityExists(input.entityType, input.entityId);
|
|
56
|
+
if (!exists) {
|
|
57
|
+
return err(notFound(input.entityType, input.entityId));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const now = new Date().toISOString();
|
|
61
|
+
const id = createNoteId(`note-${crypto.randomUUID().slice(0, 8)}`);
|
|
62
|
+
const note = {
|
|
63
|
+
id,
|
|
64
|
+
content: input.content.trim(),
|
|
65
|
+
author: input.author ?? "user",
|
|
66
|
+
tags: input.tags ?? [],
|
|
67
|
+
createdAt: now,
|
|
68
|
+
};
|
|
69
|
+
if (input.entityType !== undefined)
|
|
70
|
+
note.entityType = input.entityType;
|
|
71
|
+
if (input.entityId !== undefined)
|
|
72
|
+
note.entityId = input.entityId;
|
|
73
|
+
const notesHandle = await getOrCreateNotesDoc();
|
|
74
|
+
notesHandle.change((doc) => {
|
|
75
|
+
doc.notes.push(note);
|
|
76
|
+
});
|
|
77
|
+
return ok(note);
|
|
78
|
+
},
|
|
79
|
+
async list(filter) {
|
|
80
|
+
const catalogDoc = catalog.doc();
|
|
81
|
+
if (!catalogDoc?.notesDocId)
|
|
82
|
+
return ok([]);
|
|
83
|
+
const notesHandle = await repo.find(catalogDoc.notesDocId);
|
|
84
|
+
const notesDoc = notesHandle.doc();
|
|
85
|
+
if (!notesDoc)
|
|
86
|
+
return ok([]);
|
|
87
|
+
let notes = notesDoc.notes.map(cloneNote);
|
|
88
|
+
// Apply filters
|
|
89
|
+
if (filter?.entityType) {
|
|
90
|
+
notes = notes.filter((n) => n.entityType === filter.entityType);
|
|
91
|
+
}
|
|
92
|
+
if (filter?.entityId) {
|
|
93
|
+
notes = notes.filter((n) => n.entityId === filter.entityId);
|
|
94
|
+
}
|
|
95
|
+
if (filter?.tag) {
|
|
96
|
+
notes = notes.filter((n) => n.tags.includes(filter.tag));
|
|
97
|
+
}
|
|
98
|
+
if (filter?.author) {
|
|
99
|
+
notes = notes.filter((n) => n.author === filter.author);
|
|
100
|
+
}
|
|
101
|
+
// Sort by createdAt desc (newest first)
|
|
102
|
+
notes.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
103
|
+
return ok(notes);
|
|
104
|
+
},
|
|
105
|
+
async update(id, input) {
|
|
106
|
+
const validationErr = validateUpdateNoteInput(input);
|
|
107
|
+
if (validationErr)
|
|
108
|
+
return err(validationErr);
|
|
109
|
+
const catalogDoc = catalog.doc();
|
|
110
|
+
if (!catalogDoc?.notesDocId)
|
|
111
|
+
return err(notFound("note", id));
|
|
112
|
+
const notesHandle = await repo.find(catalogDoc.notesDocId);
|
|
113
|
+
const notesDoc = notesHandle.doc();
|
|
114
|
+
if (!notesDoc)
|
|
115
|
+
return err(notFound("note", id));
|
|
116
|
+
const index = notesDoc.notes.findIndex((n) => n.id === id);
|
|
117
|
+
if (index === -1)
|
|
118
|
+
return err(notFound("note", id));
|
|
119
|
+
notesHandle.change((doc) => {
|
|
120
|
+
const note = doc.notes[index];
|
|
121
|
+
if (input.content !== undefined)
|
|
122
|
+
note.content = input.content.trim();
|
|
123
|
+
if (input.tags !== undefined) {
|
|
124
|
+
// Clear and repopulate tags array for Automerge compatibility
|
|
125
|
+
while (note.tags.length > 0)
|
|
126
|
+
note.tags.pop();
|
|
127
|
+
for (const tag of input.tags)
|
|
128
|
+
note.tags.push(tag);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
const updated = notesHandle.doc().notes[index];
|
|
132
|
+
return ok(cloneNote(updated));
|
|
133
|
+
},
|
|
134
|
+
async delete(id) {
|
|
135
|
+
const catalogDoc = catalog.doc();
|
|
136
|
+
if (!catalogDoc?.notesDocId)
|
|
137
|
+
return err(notFound("note", id));
|
|
138
|
+
const notesHandle = await repo.find(catalogDoc.notesDocId);
|
|
139
|
+
const notesDoc = notesHandle.doc();
|
|
140
|
+
if (!notesDoc)
|
|
141
|
+
return err(notFound("note", id));
|
|
142
|
+
const index = notesDoc.notes.findIndex((n) => n.id === id);
|
|
143
|
+
if (index === -1)
|
|
144
|
+
return err(notFound("note", id));
|
|
145
|
+
notesHandle.change((doc) => {
|
|
146
|
+
doc.notes.splice(index, 1);
|
|
147
|
+
});
|
|
148
|
+
return ok(undefined);
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function cloneNote(n) {
|
|
153
|
+
return {
|
|
154
|
+
id: n.id,
|
|
155
|
+
content: n.content,
|
|
156
|
+
author: n.author,
|
|
157
|
+
entityType: n.entityType,
|
|
158
|
+
entityId: n.entityId,
|
|
159
|
+
tags: [...n.tags],
|
|
160
|
+
createdAt: n.createdAt,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=notes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notes.js","sourceRoot":"","sources":["../src/notes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { DocHandle } from "@automerge/automerge-repo";
|
|
2
|
+
import { type CatalogDocument } from "@todu/core";
|
|
3
|
+
import type { ProjectNamespace } from "./todu.js";
|
|
4
|
+
export declare function createProjectNamespace(catalog: DocHandle<CatalogDocument>): ProjectNamespace;
|
|
5
|
+
//# sourceMappingURL=projects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../src/projects.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EACL,KAAK,eAAe,EAarB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAMlD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,SAAS,CAAC,eAAe,CAAC,GAAG,gBAAgB,CAwG5F"}
|
package/dist/projects.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { createProjectId, err, notFound, ok, validateCreateProjectInput, validateUpdateProjectInput, } from "@todu/core";
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Project namespace — CRUD operations on catalog document
|
|
5
|
+
// ============================================================================
|
|
6
|
+
export function createProjectNamespace(catalog) {
|
|
7
|
+
return {
|
|
8
|
+
async create(input) {
|
|
9
|
+
const validationErr = validateCreateProjectInput(input);
|
|
10
|
+
if (validationErr)
|
|
11
|
+
return err(validationErr);
|
|
12
|
+
const now = new Date().toISOString();
|
|
13
|
+
const id = createProjectId(`proj-${crypto.randomUUID().slice(0, 8)}`);
|
|
14
|
+
const project = {
|
|
15
|
+
id,
|
|
16
|
+
name: input.name.trim(),
|
|
17
|
+
status: "active",
|
|
18
|
+
priority: input.priority ?? "medium",
|
|
19
|
+
syncStrategy: "none",
|
|
20
|
+
createdAt: now,
|
|
21
|
+
updatedAt: now,
|
|
22
|
+
};
|
|
23
|
+
// Automerge doesn't allow undefined — only set optional fields if present
|
|
24
|
+
if (input.description !== undefined) {
|
|
25
|
+
project.description = input.description.trim();
|
|
26
|
+
}
|
|
27
|
+
catalog.change((doc) => {
|
|
28
|
+
doc.projects.push(project);
|
|
29
|
+
});
|
|
30
|
+
return ok(project);
|
|
31
|
+
},
|
|
32
|
+
async list(filter) {
|
|
33
|
+
const doc = catalog.doc();
|
|
34
|
+
if (!doc)
|
|
35
|
+
return ok([]);
|
|
36
|
+
let filtered = doc.projects.map(cloneProject);
|
|
37
|
+
if (filter?.status) {
|
|
38
|
+
const statuses = Array.isArray(filter.status) ? filter.status : [filter.status];
|
|
39
|
+
filtered = filtered.filter((p) => statuses.includes(p.status));
|
|
40
|
+
}
|
|
41
|
+
if (filter?.priority) {
|
|
42
|
+
filtered = filtered.filter((p) => p.priority === filter.priority);
|
|
43
|
+
}
|
|
44
|
+
if (filter?.search) {
|
|
45
|
+
const lowerQuery = filter.search.toLowerCase();
|
|
46
|
+
filtered = filtered.filter((p) => p.name.toLowerCase().includes(lowerQuery));
|
|
47
|
+
}
|
|
48
|
+
return ok(filtered);
|
|
49
|
+
},
|
|
50
|
+
async get(id) {
|
|
51
|
+
const doc = catalog.doc();
|
|
52
|
+
if (!doc)
|
|
53
|
+
return err(notFound("project", id));
|
|
54
|
+
const project = doc.projects.find((p) => p.id === id);
|
|
55
|
+
if (!project)
|
|
56
|
+
return err(notFound("project", id));
|
|
57
|
+
return ok(cloneProject(project));
|
|
58
|
+
},
|
|
59
|
+
async update(id, input) {
|
|
60
|
+
const validationErr = validateUpdateProjectInput(input);
|
|
61
|
+
if (validationErr)
|
|
62
|
+
return err(validationErr);
|
|
63
|
+
const doc = catalog.doc();
|
|
64
|
+
if (!doc)
|
|
65
|
+
return err(notFound("project", id));
|
|
66
|
+
const index = doc.projects.findIndex((p) => p.id === id);
|
|
67
|
+
if (index === -1)
|
|
68
|
+
return err(notFound("project", id));
|
|
69
|
+
const now = new Date().toISOString();
|
|
70
|
+
catalog.change((doc) => {
|
|
71
|
+
const project = doc.projects[index];
|
|
72
|
+
if (input.name !== undefined)
|
|
73
|
+
project.name = input.name.trim();
|
|
74
|
+
if (input.description !== undefined)
|
|
75
|
+
project.description = input.description.trim();
|
|
76
|
+
if (input.status !== undefined)
|
|
77
|
+
project.status = input.status;
|
|
78
|
+
if (input.priority !== undefined)
|
|
79
|
+
project.priority = input.priority;
|
|
80
|
+
project.updatedAt = now;
|
|
81
|
+
});
|
|
82
|
+
// Read back the updated project
|
|
83
|
+
const updated = catalog.doc().projects[index];
|
|
84
|
+
return ok(cloneProject(updated));
|
|
85
|
+
},
|
|
86
|
+
async delete(id) {
|
|
87
|
+
const doc = catalog.doc();
|
|
88
|
+
if (!doc)
|
|
89
|
+
return err(notFound("project", id));
|
|
90
|
+
const index = doc.projects.findIndex((p) => p.id === id);
|
|
91
|
+
if (index === -1)
|
|
92
|
+
return err(notFound("project", id));
|
|
93
|
+
// TODO: When tasks slice lands, check for non-empty TaskListDocument
|
|
94
|
+
// For now, allow deletion unconditionally.
|
|
95
|
+
catalog.change((doc) => {
|
|
96
|
+
doc.projects.splice(index, 1);
|
|
97
|
+
});
|
|
98
|
+
return ok(undefined);
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/** Clone a project out of the Automerge proxy */
|
|
103
|
+
function cloneProject(p) {
|
|
104
|
+
return {
|
|
105
|
+
id: p.id,
|
|
106
|
+
name: p.name,
|
|
107
|
+
description: p.description,
|
|
108
|
+
status: p.status,
|
|
109
|
+
priority: p.priority,
|
|
110
|
+
externalId: p.externalId,
|
|
111
|
+
systemId: p.systemId,
|
|
112
|
+
syncStrategy: p.syncStrategy,
|
|
113
|
+
createdAt: p.createdAt,
|
|
114
|
+
updatedAt: p.updatedAt,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=projects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projects.js","sourceRoot":"","sources":["../src/projects.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { DocHandle, Repo } from "@automerge/automerge-repo";
|
|
2
|
+
import { type CatalogDocument, type ProjectId, type RecurringId } from "@todu/core";
|
|
3
|
+
import type { RecurringNamespace } from "./todu.js";
|
|
4
|
+
export declare function createRecurringNamespace(catalog: DocHandle<CatalogDocument>, repo: Repo): RecurringNamespace;
|
|
5
|
+
export interface UpcomingOccurrence {
|
|
6
|
+
templateId: RecurringId;
|
|
7
|
+
title: string;
|
|
8
|
+
date: string;
|
|
9
|
+
projectId: ProjectId;
|
|
10
|
+
priority: string;
|
|
11
|
+
schedule: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Register the recurring template processor with the scheduling framework.
|
|
15
|
+
* Called once during module initialization.
|
|
16
|
+
*/
|
|
17
|
+
export declare function registerRecurringProcessor(catalog: DocHandle<CatalogDocument>, repo: Repo): void;
|
|
18
|
+
/**
|
|
19
|
+
* Add a date to a template's skip list.
|
|
20
|
+
* Called when a generated task is deleted.
|
|
21
|
+
*/
|
|
22
|
+
export declare function addToSkipList(catalog: DocHandle<CatalogDocument>, templateId: string, date: string): void;
|
|
23
|
+
//# sourceMappingURL=recurring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recurring.d.ts","sourceRoot":"","sources":["../src/recurring.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAc,IAAI,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EACL,KAAK,eAAe,EAQpB,KAAK,SAAS,EAEd,KAAK,WAAW,EASjB,MAAM,YAAY,CAAC;AAUpB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAMpD,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,SAAS,CAAC,eAAe,CAAC,EACnC,IAAI,EAAE,IAAI,GACT,kBAAkB,CAiSpB;AAMD,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,WAAW,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAiGD;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,SAAS,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAOhG;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,SAAS,CAAC,eAAe,CAAC,EACnC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GACX,IAAI,CAaN"}
|