@ofocus/sdk 0.1.0 → 0.3.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/LICENSE +21 -0
- package/api-report/ofocus-sdk.api.md +496 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/commands/archive.d.ts +48 -0
- package/dist/commands/archive.d.ts.map +1 -0
- package/dist/commands/archive.js +132 -0
- package/dist/commands/archive.js.map +1 -0
- package/dist/commands/attachments.d.ts +67 -0
- package/dist/commands/attachments.d.ts.map +1 -0
- package/dist/commands/attachments.js +160 -0
- package/dist/commands/attachments.js.map +1 -0
- package/dist/commands/defer.d.ts +37 -0
- package/dist/commands/defer.d.ts.map +1 -0
- package/dist/commands/defer.js +198 -0
- package/dist/commands/defer.js.map +1 -0
- package/dist/commands/deferred.d.ts +18 -0
- package/dist/commands/deferred.d.ts.map +1 -0
- package/dist/commands/deferred.js +146 -0
- package/dist/commands/deferred.js.map +1 -0
- package/dist/commands/duplicate.d.ts +15 -0
- package/dist/commands/duplicate.d.ts.map +1 -0
- package/dist/commands/duplicate.js +49 -0
- package/dist/commands/duplicate.js.map +1 -0
- package/dist/commands/focus.d.ts +26 -0
- package/dist/commands/focus.d.ts.map +1 -0
- package/dist/commands/focus.js +182 -0
- package/dist/commands/focus.js.map +1 -0
- package/dist/commands/folders-crud.d.ts +18 -0
- package/dist/commands/folders-crud.d.ts.map +1 -0
- package/dist/commands/folders-crud.js +117 -0
- package/dist/commands/folders-crud.js.map +1 -0
- package/dist/commands/forecast.d.ts +20 -0
- package/dist/commands/forecast.d.ts.map +1 -0
- package/dist/commands/forecast.js +145 -0
- package/dist/commands/forecast.js.map +1 -0
- package/dist/commands/open.d.ts +17 -0
- package/dist/commands/open.d.ts.map +1 -0
- package/dist/commands/open.js +88 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/projects-crud.d.ts +30 -0
- package/dist/commands/projects-crud.d.ts.map +1 -0
- package/dist/commands/projects-crud.js +209 -0
- package/dist/commands/projects-crud.js.map +1 -0
- package/dist/commands/quick.d.ts +41 -0
- package/dist/commands/quick.d.ts.map +1 -0
- package/dist/commands/quick.js +257 -0
- package/dist/commands/quick.js.map +1 -0
- package/dist/commands/review.d.ts +18 -0
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +87 -1
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/stats.d.ts +48 -0
- package/dist/commands/stats.d.ts.map +1 -0
- package/dist/commands/stats.js +212 -0
- package/dist/commands/stats.js.map +1 -0
- package/dist/commands/sync.d.ts +32 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +63 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/taskpaper.d.ts +46 -0
- package/dist/commands/taskpaper.d.ts.map +1 -0
- package/dist/commands/taskpaper.js +359 -0
- package/dist/commands/taskpaper.js.map +1 -0
- package/dist/commands/templates.d.ts +134 -0
- package/dist/commands/templates.d.ts.map +1 -0
- package/dist/commands/templates.js +252 -0
- package/dist/commands/templates.js.map +1 -0
- package/dist/commands/url.d.ts +16 -0
- package/dist/commands/url.d.ts.map +1 -0
- package/dist/commands/url.js +96 -0
- package/dist/commands/url.js.map +1 -0
- package/dist/index.d.ts +38 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -3
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +27 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/validation.d.ts +1 -1
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +3 -1
- package/dist/validation.js.map +1 -1
- package/package.json +12 -12
- package/dist/ofocus-sdk.d.ts +0 -608
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { CliOutput } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Result from focus operations.
|
|
4
|
+
*/
|
|
5
|
+
export interface FocusResult {
|
|
6
|
+
focused: boolean;
|
|
7
|
+
targetId: string | null;
|
|
8
|
+
targetName: string | null;
|
|
9
|
+
targetType: "project" | "folder" | null;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Focus on a specific project or folder in OmniFocus.
|
|
13
|
+
* This matches the OmniFocus UI focus feature.
|
|
14
|
+
*/
|
|
15
|
+
export declare function focus(target: string, options?: {
|
|
16
|
+
byId?: boolean | undefined;
|
|
17
|
+
}): Promise<CliOutput<FocusResult>>;
|
|
18
|
+
/**
|
|
19
|
+
* Clear focus in OmniFocus (show all items).
|
|
20
|
+
*/
|
|
21
|
+
export declare function unfocus(): Promise<CliOutput<FocusResult>>;
|
|
22
|
+
/**
|
|
23
|
+
* Get the current focus state in OmniFocus.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getFocused(): Promise<CliOutput<FocusResult>>;
|
|
26
|
+
//# sourceMappingURL=focus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focus.d.ts","sourceRoot":"","sources":["../../src/commands/focus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAO7C;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,SAAS,GAAG,QAAQ,GAAG,IAAI,CAAC;CACzC;AAsBD;;;GAGG;AACH,wBAAsB,KAAK,CACzB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAO,GAC3C,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CA4FjC;AAED;;GAEG;AACH,wBAAsB,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CA6B/D;AAED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAkDlE"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { success, failure } from "../result.js";
|
|
2
|
+
import { ErrorCode, createError } from "../errors.js";
|
|
3
|
+
import { validateProjectName } from "../validation.js";
|
|
4
|
+
import { escapeAppleScript } from "../escape.js";
|
|
5
|
+
import { runAppleScript, omniFocusScriptWithHelpers } from "../applescript.js";
|
|
6
|
+
/**
|
|
7
|
+
* Validate an ID for focus operations (can be project or folder).
|
|
8
|
+
*/
|
|
9
|
+
function validateFocusId(id) {
|
|
10
|
+
if (!id || id.trim() === "") {
|
|
11
|
+
return { code: "INVALID_ID_FORMAT", message: "ID cannot be empty" };
|
|
12
|
+
}
|
|
13
|
+
// IDs should be alphanumeric with possible dashes/underscores
|
|
14
|
+
const idPattern = /^[a-zA-Z0-9_-]+$/;
|
|
15
|
+
if (!idPattern.test(id)) {
|
|
16
|
+
return {
|
|
17
|
+
code: "INVALID_ID_FORMAT",
|
|
18
|
+
message: `Invalid ID format: ${id}`,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Focus on a specific project or folder in OmniFocus.
|
|
25
|
+
* This matches the OmniFocus UI focus feature.
|
|
26
|
+
*/
|
|
27
|
+
export async function focus(target, options = {}) {
|
|
28
|
+
// Validate input
|
|
29
|
+
if (options.byId) {
|
|
30
|
+
const error = validateFocusId(target);
|
|
31
|
+
if (error) {
|
|
32
|
+
return failure(createError(ErrorCode.INVALID_ID_FORMAT, error.message));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
const error = validateProjectName(target);
|
|
37
|
+
if (error)
|
|
38
|
+
return failure(error);
|
|
39
|
+
}
|
|
40
|
+
const escapedTarget = escapeAppleScript(target);
|
|
41
|
+
const findScript = options.byId
|
|
42
|
+
? `
|
|
43
|
+
-- Try to find by ID (could be project or folder)
|
|
44
|
+
set targetItem to missing value
|
|
45
|
+
set targetType to ""
|
|
46
|
+
|
|
47
|
+
try
|
|
48
|
+
set targetItem to first flattened project whose id is "${escapedTarget}"
|
|
49
|
+
set targetType to "project"
|
|
50
|
+
end try
|
|
51
|
+
|
|
52
|
+
if targetItem is missing value then
|
|
53
|
+
try
|
|
54
|
+
set targetItem to first flattened folder whose id is "${escapedTarget}"
|
|
55
|
+
set targetType to "folder"
|
|
56
|
+
end try
|
|
57
|
+
end if
|
|
58
|
+
|
|
59
|
+
if targetItem is missing value then
|
|
60
|
+
error "Target not found with ID: ${escapedTarget}"
|
|
61
|
+
end if
|
|
62
|
+
`
|
|
63
|
+
: `
|
|
64
|
+
-- Try to find by name (project first, then folder)
|
|
65
|
+
set targetItem to missing value
|
|
66
|
+
set targetType to ""
|
|
67
|
+
|
|
68
|
+
try
|
|
69
|
+
set targetItem to first flattened project whose name is "${escapedTarget}"
|
|
70
|
+
set targetType to "project"
|
|
71
|
+
end try
|
|
72
|
+
|
|
73
|
+
if targetItem is missing value then
|
|
74
|
+
try
|
|
75
|
+
set targetItem to first flattened folder whose name is "${escapedTarget}"
|
|
76
|
+
set targetType to "folder"
|
|
77
|
+
end try
|
|
78
|
+
end if
|
|
79
|
+
|
|
80
|
+
if targetItem is missing value then
|
|
81
|
+
error "Target not found: ${escapedTarget}"
|
|
82
|
+
end if
|
|
83
|
+
`;
|
|
84
|
+
const script = `
|
|
85
|
+
${findScript}
|
|
86
|
+
|
|
87
|
+
-- Set focus
|
|
88
|
+
set focused of document window 1 to {targetItem}
|
|
89
|
+
|
|
90
|
+
-- Return result
|
|
91
|
+
set targetId to id of targetItem
|
|
92
|
+
set targetName to name of targetItem
|
|
93
|
+
|
|
94
|
+
return "{" & ¬
|
|
95
|
+
"\\"focused\\": true," & ¬
|
|
96
|
+
"\\"targetId\\": \\"" & targetId & "\\"," & ¬
|
|
97
|
+
"\\"targetName\\": \\"" & (my escapeJson(targetName)) & "\\"," & ¬
|
|
98
|
+
"\\"targetType\\": \\"" & targetType & "\\"" & ¬
|
|
99
|
+
"}"
|
|
100
|
+
`;
|
|
101
|
+
const result = await runAppleScript(omniFocusScriptWithHelpers(script));
|
|
102
|
+
if (!result.success) {
|
|
103
|
+
return failure(result.error ??
|
|
104
|
+
createError(ErrorCode.UNKNOWN_ERROR, "Failed to focus on target"));
|
|
105
|
+
}
|
|
106
|
+
if (result.data === undefined) {
|
|
107
|
+
return failure(createError(ErrorCode.UNKNOWN_ERROR, "No result returned"));
|
|
108
|
+
}
|
|
109
|
+
return success(result.data);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Clear focus in OmniFocus (show all items).
|
|
113
|
+
*/
|
|
114
|
+
export async function unfocus() {
|
|
115
|
+
const script = `
|
|
116
|
+
-- Clear focus by setting to empty list
|
|
117
|
+
set focused of document window 1 to {}
|
|
118
|
+
|
|
119
|
+
return "{" & ¬
|
|
120
|
+
"\\"focused\\": false," & ¬
|
|
121
|
+
"\\"targetId\\": null," & ¬
|
|
122
|
+
"\\"targetName\\": null," & ¬
|
|
123
|
+
"\\"targetType\\": null" & ¬
|
|
124
|
+
"}"
|
|
125
|
+
`;
|
|
126
|
+
const result = await runAppleScript(omniFocusScriptWithHelpers(script));
|
|
127
|
+
if (!result.success) {
|
|
128
|
+
return failure(result.error ??
|
|
129
|
+
createError(ErrorCode.UNKNOWN_ERROR, "Failed to clear focus"));
|
|
130
|
+
}
|
|
131
|
+
if (result.data === undefined) {
|
|
132
|
+
return failure(createError(ErrorCode.UNKNOWN_ERROR, "No result returned"));
|
|
133
|
+
}
|
|
134
|
+
return success(result.data);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get the current focus state in OmniFocus.
|
|
138
|
+
*/
|
|
139
|
+
export async function getFocused() {
|
|
140
|
+
const script = `
|
|
141
|
+
set focusedItems to focused of document window 1
|
|
142
|
+
|
|
143
|
+
if (count of focusedItems) is 0 then
|
|
144
|
+
return "{" & ¬
|
|
145
|
+
"\\"focused\\": false," & ¬
|
|
146
|
+
"\\"targetId\\": null," & ¬
|
|
147
|
+
"\\"targetName\\": null," & ¬
|
|
148
|
+
"\\"targetType\\": null" & ¬
|
|
149
|
+
"}"
|
|
150
|
+
end if
|
|
151
|
+
|
|
152
|
+
-- Get first focused item (typically only one)
|
|
153
|
+
set focusedItem to item 1 of focusedItems
|
|
154
|
+
|
|
155
|
+
set targetId to id of focusedItem
|
|
156
|
+
set targetName to name of focusedItem
|
|
157
|
+
|
|
158
|
+
-- Determine type
|
|
159
|
+
set targetType to "folder"
|
|
160
|
+
try
|
|
161
|
+
set testStatus to status of focusedItem
|
|
162
|
+
set targetType to "project"
|
|
163
|
+
end try
|
|
164
|
+
|
|
165
|
+
return "{" & ¬
|
|
166
|
+
"\\"focused\\": true," & ¬
|
|
167
|
+
"\\"targetId\\": \\"" & targetId & "\\"," & ¬
|
|
168
|
+
"\\"targetName\\": \\"" & (my escapeJson(targetName)) & "\\"," & ¬
|
|
169
|
+
"\\"targetType\\": \\"" & targetType & "\\"" & ¬
|
|
170
|
+
"}"
|
|
171
|
+
`;
|
|
172
|
+
const result = await runAppleScript(omniFocusScriptWithHelpers(script));
|
|
173
|
+
if (!result.success) {
|
|
174
|
+
return failure(result.error ??
|
|
175
|
+
createError(ErrorCode.UNKNOWN_ERROR, "Failed to get focus state"));
|
|
176
|
+
}
|
|
177
|
+
if (result.data === undefined) {
|
|
178
|
+
return failure(createError(ErrorCode.UNKNOWN_ERROR, "No result returned"));
|
|
179
|
+
}
|
|
180
|
+
return success(result.data);
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=focus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focus.js","sourceRoot":"","sources":["../../src/commands/focus.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CliOutput, OFFolder, UpdateFolderOptions } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Result from deleting a folder.
|
|
4
|
+
*/
|
|
5
|
+
export interface DeleteFolderResult {
|
|
6
|
+
folderId: string;
|
|
7
|
+
deleted: true;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Update an existing folder in OmniFocus.
|
|
11
|
+
*/
|
|
12
|
+
export declare function updateFolder(folderId: string, options: UpdateFolderOptions): Promise<CliOutput<OFFolder>>;
|
|
13
|
+
/**
|
|
14
|
+
* Delete a folder permanently from OmniFocus.
|
|
15
|
+
* Note: This cannot be undone.
|
|
16
|
+
*/
|
|
17
|
+
export declare function deleteFolder(folderId: string): Promise<CliOutput<DeleteFolderResult>>;
|
|
18
|
+
//# sourceMappingURL=folders-crud.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"folders-crud.d.ts","sourceRoot":"","sources":["../../src/commands/folders-crud.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAO5E;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,IAAI,CAAC;CACf;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAiG9B;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CA4BxC"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { success, failure } from "../result.js";
|
|
2
|
+
import { ErrorCode, createError } from "../errors.js";
|
|
3
|
+
import { validateId, validateFolderName } from "../validation.js";
|
|
4
|
+
import { escapeAppleScript } from "../escape.js";
|
|
5
|
+
import { runAppleScript, omniFocusScriptWithHelpers } from "../applescript.js";
|
|
6
|
+
/**
|
|
7
|
+
* Update an existing folder in OmniFocus.
|
|
8
|
+
*/
|
|
9
|
+
export async function updateFolder(folderId, options) {
|
|
10
|
+
// Validate folder ID
|
|
11
|
+
const idError = validateId(folderId, "folder");
|
|
12
|
+
if (idError)
|
|
13
|
+
return failure(idError);
|
|
14
|
+
// Validate optional inputs
|
|
15
|
+
if (options.name !== undefined) {
|
|
16
|
+
const nameError = validateFolderName(options.name);
|
|
17
|
+
if (nameError)
|
|
18
|
+
return failure(nameError);
|
|
19
|
+
}
|
|
20
|
+
if (options.parentFolderId !== undefined) {
|
|
21
|
+
const parentIdError = validateId(options.parentFolderId, "folder");
|
|
22
|
+
if (parentIdError)
|
|
23
|
+
return failure(parentIdError);
|
|
24
|
+
}
|
|
25
|
+
if (options.parentFolderName !== undefined) {
|
|
26
|
+
const parentNameError = validateFolderName(options.parentFolderName);
|
|
27
|
+
if (parentNameError)
|
|
28
|
+
return failure(parentNameError);
|
|
29
|
+
}
|
|
30
|
+
// Build the update statements
|
|
31
|
+
const updates = [];
|
|
32
|
+
if (options.name !== undefined) {
|
|
33
|
+
updates.push(`set name of theFolder to "${escapeAppleScript(options.name)}"`);
|
|
34
|
+
}
|
|
35
|
+
// Handle reparenting
|
|
36
|
+
let reparentScript = "";
|
|
37
|
+
if (options.parentFolderId !== undefined) {
|
|
38
|
+
reparentScript = `
|
|
39
|
+
set newParent to first flattened folder whose id is "${escapeAppleScript(options.parentFolderId)}"
|
|
40
|
+
move theFolder to end of folders of newParent
|
|
41
|
+
`;
|
|
42
|
+
}
|
|
43
|
+
else if (options.parentFolderName !== undefined) {
|
|
44
|
+
reparentScript = `
|
|
45
|
+
set newParent to first flattened folder whose name is "${escapeAppleScript(options.parentFolderName)}"
|
|
46
|
+
move theFolder to end of folders of newParent
|
|
47
|
+
`;
|
|
48
|
+
}
|
|
49
|
+
const updateScript = updates.join("\n ");
|
|
50
|
+
const script = `
|
|
51
|
+
set theFolder to first flattened folder whose id is "${escapeAppleScript(folderId)}"
|
|
52
|
+
|
|
53
|
+
${updateScript}
|
|
54
|
+
${reparentScript}
|
|
55
|
+
|
|
56
|
+
-- Return updated folder info
|
|
57
|
+
set folderId to id of theFolder
|
|
58
|
+
set folderName to name of theFolder
|
|
59
|
+
|
|
60
|
+
set parentId to ""
|
|
61
|
+
set parentName to ""
|
|
62
|
+
try
|
|
63
|
+
set p to container of theFolder
|
|
64
|
+
if class of p is folder then
|
|
65
|
+
set parentId to id of p
|
|
66
|
+
set parentName to name of p
|
|
67
|
+
end if
|
|
68
|
+
end try
|
|
69
|
+
|
|
70
|
+
set projCount to count of projects of theFolder
|
|
71
|
+
set subFolderCount to count of folders of theFolder
|
|
72
|
+
|
|
73
|
+
return "{" & ¬
|
|
74
|
+
"\\"id\\": \\"" & folderId & "\\"," & ¬
|
|
75
|
+
"\\"name\\": \\"" & (my escapeJson(folderName)) & "\\"," & ¬
|
|
76
|
+
"\\"parentId\\": " & (my jsonString(parentId)) & "," & ¬
|
|
77
|
+
"\\"parentName\\": " & (my jsonString(parentName)) & "," & ¬
|
|
78
|
+
"\\"projectCount\\": " & projCount & "," & ¬
|
|
79
|
+
"\\"folderCount\\": " & subFolderCount & ¬
|
|
80
|
+
"}"
|
|
81
|
+
`;
|
|
82
|
+
const result = await runAppleScript(omniFocusScriptWithHelpers(script));
|
|
83
|
+
if (!result.success) {
|
|
84
|
+
return failure(result.error ??
|
|
85
|
+
createError(ErrorCode.UNKNOWN_ERROR, "Failed to update folder"));
|
|
86
|
+
}
|
|
87
|
+
if (result.data === undefined) {
|
|
88
|
+
return failure(createError(ErrorCode.UNKNOWN_ERROR, "No folder data returned"));
|
|
89
|
+
}
|
|
90
|
+
return success(result.data);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Delete a folder permanently from OmniFocus.
|
|
94
|
+
* Note: This cannot be undone.
|
|
95
|
+
*/
|
|
96
|
+
export async function deleteFolder(folderId) {
|
|
97
|
+
// Validate folder ID
|
|
98
|
+
const idError = validateId(folderId, "folder");
|
|
99
|
+
if (idError)
|
|
100
|
+
return failure(idError);
|
|
101
|
+
const script = `
|
|
102
|
+
set theFolder to first flattened folder whose id is "${escapeAppleScript(folderId)}"
|
|
103
|
+
delete theFolder
|
|
104
|
+
|
|
105
|
+
return "{\\"folderId\\": \\"${escapeAppleScript(folderId)}\\", \\"deleted\\": true}"
|
|
106
|
+
`;
|
|
107
|
+
const result = await runAppleScript(omniFocusScriptWithHelpers(script));
|
|
108
|
+
if (!result.success) {
|
|
109
|
+
return failure(result.error ??
|
|
110
|
+
createError(ErrorCode.UNKNOWN_ERROR, "Failed to delete folder"));
|
|
111
|
+
}
|
|
112
|
+
if (result.data === undefined) {
|
|
113
|
+
return failure(createError(ErrorCode.UNKNOWN_ERROR, "No result returned"));
|
|
114
|
+
}
|
|
115
|
+
return success(result.data);
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=folders-crud.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"folders-crud.js","sourceRoot":"","sources":["../../src/commands/folders-crud.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CliOutput, OFTask } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Options for querying forecast tasks.
|
|
4
|
+
*/
|
|
5
|
+
export interface ForecastOptions {
|
|
6
|
+
/** Start date for the forecast range (defaults to today) */
|
|
7
|
+
start?: string | undefined;
|
|
8
|
+
/** End date for the forecast range */
|
|
9
|
+
end?: string | undefined;
|
|
10
|
+
/** Number of days from start to include (alternative to end) */
|
|
11
|
+
days?: number | undefined;
|
|
12
|
+
/** Include tasks with no due date but deferred to the range */
|
|
13
|
+
includeDeferred?: boolean | undefined;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Query tasks by date range, similar to OmniFocus Forecast view.
|
|
17
|
+
* Returns tasks that are due or deferred within the specified date range.
|
|
18
|
+
*/
|
|
19
|
+
export declare function queryForecast(options?: ForecastOptions): Promise<CliOutput<OFTask[]>>;
|
|
20
|
+
//# sourceMappingURL=forecast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forecast.d.ts","sourceRoot":"","sources":["../../src/commands/forecast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAMrD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,+DAA+D;IAC/D,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACvC;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAqJ9B"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { success, failure } from "../result.js";
|
|
2
|
+
import { ErrorCode, createError } from "../errors.js";
|
|
3
|
+
import { validateDateString } from "../validation.js";
|
|
4
|
+
import { runAppleScript, omniFocusScriptWithHelpers } from "../applescript.js";
|
|
5
|
+
/**
|
|
6
|
+
* Query tasks by date range, similar to OmniFocus Forecast view.
|
|
7
|
+
* Returns tasks that are due or deferred within the specified date range.
|
|
8
|
+
*/
|
|
9
|
+
export async function queryForecast(options = {}) {
|
|
10
|
+
// Validate date inputs
|
|
11
|
+
if (options.start !== undefined) {
|
|
12
|
+
const error = validateDateString(options.start);
|
|
13
|
+
if (error)
|
|
14
|
+
return failure(error);
|
|
15
|
+
}
|
|
16
|
+
if (options.end !== undefined) {
|
|
17
|
+
const error = validateDateString(options.end);
|
|
18
|
+
if (error)
|
|
19
|
+
return failure(error);
|
|
20
|
+
}
|
|
21
|
+
// Validate days option
|
|
22
|
+
if (options.days !== undefined &&
|
|
23
|
+
(options.days < 1 || !Number.isInteger(options.days))) {
|
|
24
|
+
return failure(createError(ErrorCode.VALIDATION_ERROR, "Days must be a positive integer"));
|
|
25
|
+
}
|
|
26
|
+
// Build date range logic in AppleScript
|
|
27
|
+
const startDate = options.start ?? "today";
|
|
28
|
+
const includeDeferred = options.includeDeferred === true;
|
|
29
|
+
// Calculate end date based on days or explicit end
|
|
30
|
+
let endDateLogic;
|
|
31
|
+
if (options.end !== undefined) {
|
|
32
|
+
endDateLogic = `set endDate to date "${options.end}"`;
|
|
33
|
+
}
|
|
34
|
+
else if (options.days !== undefined) {
|
|
35
|
+
endDateLogic = `set endDate to startDate + (${String(options.days)} * days)`;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
// Default to 7 days
|
|
39
|
+
endDateLogic = `set endDate to startDate + (7 * days)`;
|
|
40
|
+
}
|
|
41
|
+
const script = `
|
|
42
|
+
set startDate to date "${startDate}"
|
|
43
|
+
${endDateLogic}
|
|
44
|
+
|
|
45
|
+
set output to "["
|
|
46
|
+
set isFirst to true
|
|
47
|
+
|
|
48
|
+
set allTasks to flattened tasks where completed is false and effectively dropped is false
|
|
49
|
+
|
|
50
|
+
repeat with t in allTasks
|
|
51
|
+
set shouldInclude to false
|
|
52
|
+
|
|
53
|
+
-- Check due date
|
|
54
|
+
try
|
|
55
|
+
set taskDue to due date of t
|
|
56
|
+
if taskDue >= startDate and taskDue <= endDate then
|
|
57
|
+
set shouldInclude to true
|
|
58
|
+
end if
|
|
59
|
+
end try
|
|
60
|
+
|
|
61
|
+
${includeDeferred
|
|
62
|
+
? `
|
|
63
|
+
-- Check defer date
|
|
64
|
+
if not shouldInclude then
|
|
65
|
+
try
|
|
66
|
+
set taskDefer to defer date of t
|
|
67
|
+
if taskDefer >= startDate and taskDefer <= endDate then
|
|
68
|
+
set shouldInclude to true
|
|
69
|
+
end if
|
|
70
|
+
end try
|
|
71
|
+
end if
|
|
72
|
+
`
|
|
73
|
+
: ""}
|
|
74
|
+
|
|
75
|
+
if shouldInclude then
|
|
76
|
+
if not isFirst then set output to output & ","
|
|
77
|
+
set isFirst to false
|
|
78
|
+
|
|
79
|
+
set taskId to id of t
|
|
80
|
+
set taskName to name of t
|
|
81
|
+
set taskNote to note of t
|
|
82
|
+
set taskFlagged to flagged of t
|
|
83
|
+
set taskCompleted to completed of t
|
|
84
|
+
|
|
85
|
+
set dueStr to ""
|
|
86
|
+
try
|
|
87
|
+
set dueStr to (due date of t) as string
|
|
88
|
+
end try
|
|
89
|
+
|
|
90
|
+
set deferStr to ""
|
|
91
|
+
try
|
|
92
|
+
set deferStr to (defer date of t) as string
|
|
93
|
+
end try
|
|
94
|
+
|
|
95
|
+
set completionStr to ""
|
|
96
|
+
try
|
|
97
|
+
set completionStr to (completion date of t) as string
|
|
98
|
+
end try
|
|
99
|
+
|
|
100
|
+
set projId to ""
|
|
101
|
+
set projName to ""
|
|
102
|
+
try
|
|
103
|
+
set proj to containing project of t
|
|
104
|
+
set projId to id of proj
|
|
105
|
+
set projName to name of proj
|
|
106
|
+
end try
|
|
107
|
+
|
|
108
|
+
set tagNames to {}
|
|
109
|
+
repeat with tg in tags of t
|
|
110
|
+
set end of tagNames to name of tg
|
|
111
|
+
end repeat
|
|
112
|
+
|
|
113
|
+
set estMinutes to 0
|
|
114
|
+
try
|
|
115
|
+
set estMinutes to estimated minutes of t
|
|
116
|
+
if estMinutes is missing value then set estMinutes to 0
|
|
117
|
+
end try
|
|
118
|
+
|
|
119
|
+
set output to output & "{" & ¬
|
|
120
|
+
"\\"id\\": \\"" & taskId & "\\"," & ¬
|
|
121
|
+
"\\"name\\": \\"" & (my escapeJson(taskName)) & "\\"," & ¬
|
|
122
|
+
"\\"note\\": " & (my jsonString(taskNote)) & "," & ¬
|
|
123
|
+
"\\"flagged\\": " & taskFlagged & "," & ¬
|
|
124
|
+
"\\"completed\\": " & taskCompleted & "," & ¬
|
|
125
|
+
"\\"dueDate\\": " & (my jsonString(dueStr)) & "," & ¬
|
|
126
|
+
"\\"deferDate\\": " & (my jsonString(deferStr)) & "," & ¬
|
|
127
|
+
"\\"completionDate\\": " & (my jsonString(completionStr)) & "," & ¬
|
|
128
|
+
"\\"projectId\\": " & (my jsonString(projId)) & "," & ¬
|
|
129
|
+
"\\"projectName\\": " & (my jsonString(projName)) & "," & ¬
|
|
130
|
+
"\\"tags\\": " & (my jsonArray(tagNames)) & "," & ¬
|
|
131
|
+
"\\"estimatedMinutes\\": " & estMinutes & ¬
|
|
132
|
+
"}"
|
|
133
|
+
end if
|
|
134
|
+
end repeat
|
|
135
|
+
|
|
136
|
+
return output & "]"
|
|
137
|
+
`;
|
|
138
|
+
const result = await runAppleScript(omniFocusScriptWithHelpers(script));
|
|
139
|
+
if (!result.success) {
|
|
140
|
+
return failure(result.error ??
|
|
141
|
+
createError(ErrorCode.UNKNOWN_ERROR, "Failed to query forecast"));
|
|
142
|
+
}
|
|
143
|
+
return success(result.data ?? []);
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=forecast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forecast.js","sourceRoot":"","sources":["../../src/commands/forecast.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAgB/E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,UAA2B,EAAE;IAE7B,uBAAuB;IACvB,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAChD,IAAI,KAAK;YAAE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,KAAK;YAAE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAED,uBAAuB;IACvB,IACE,OAAO,CAAC,IAAI,KAAK,SAAS;QAC1B,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EACrD,CAAC;QACD,OAAO,OAAO,CACZ,WAAW,CAAC,SAAS,CAAC,gBAAgB,EAAE,iCAAiC,CAAC,CAC3E,CAAC;IACJ,CAAC;IAED,wCAAwC;IACxC,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC;IAC3C,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,KAAK,IAAI,CAAC;IAEzD,mDAAmD;IACnD,IAAI,YAAoB,CAAC;IACzB,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC9B,YAAY,GAAG,wBAAwB,OAAO,CAAC,GAAG,GAAG,CAAC;IACxD,CAAC;SAAM,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACtC,YAAY,GAAG,+BAA+B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;IAC/E,CAAC;SAAM,CAAC;QACN,oBAAoB;QACpB,YAAY,GAAG,uCAAuC,CAAC;IACzD,CAAC;IAED,MAAM,MAAM,GAAG;6BACY,SAAS;MAChC,YAAY;;;;;;;;;;;;;;;;;;QAmBV,eAAe;QACb,CAAC,CAAC;;;;;;;;;;OAUL;QACG,CAAC,CAAC,EACN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEH,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,cAAc,CACjC,0BAA0B,CAAC,MAAM,CAAC,CACnC,CAAC;IAEF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,OAAO,CACZ,MAAM,CAAC,KAAK;YACV,WAAW,CAAC,SAAS,CAAC,aAAa,EAAE,0BAA0B,CAAC,CACnE,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CliOutput } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Result from opening an item.
|
|
4
|
+
*/
|
|
5
|
+
export interface OpenResult {
|
|
6
|
+
id: string;
|
|
7
|
+
type: "task" | "project" | "folder" | "tag";
|
|
8
|
+
name: string;
|
|
9
|
+
opened: true;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Open an item in the OmniFocus UI.
|
|
13
|
+
* The item can be a task, project, folder, or tag.
|
|
14
|
+
* Auto-detects the item type based on the ID.
|
|
15
|
+
*/
|
|
16
|
+
export declare function openItem(id: string): Promise<CliOutput<OpenResult>>;
|
|
17
|
+
//# sourceMappingURL=open.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../src/commands/open.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAO7C;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAoFzE"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { success, failure } from "../result.js";
|
|
2
|
+
import { ErrorCode, createError } from "../errors.js";
|
|
3
|
+
import { validateId } from "../validation.js";
|
|
4
|
+
import { escapeAppleScript } from "../escape.js";
|
|
5
|
+
import { runAppleScript, omniFocusScriptWithHelpers } from "../applescript.js";
|
|
6
|
+
/**
|
|
7
|
+
* Open an item in the OmniFocus UI.
|
|
8
|
+
* The item can be a task, project, folder, or tag.
|
|
9
|
+
* Auto-detects the item type based on the ID.
|
|
10
|
+
*/
|
|
11
|
+
export async function openItem(id) {
|
|
12
|
+
// Validate ID
|
|
13
|
+
const idError = validateId(id, "item");
|
|
14
|
+
if (idError)
|
|
15
|
+
return failure(idError);
|
|
16
|
+
// Try to find the item and determine its type, then open it
|
|
17
|
+
const script = `
|
|
18
|
+
set itemId to "${escapeAppleScript(id)}"
|
|
19
|
+
set itemType to ""
|
|
20
|
+
set itemName to ""
|
|
21
|
+
set foundItem to missing value
|
|
22
|
+
|
|
23
|
+
-- Try to find as task first (most common)
|
|
24
|
+
try
|
|
25
|
+
set foundItem to first flattened task whose id is itemId
|
|
26
|
+
set itemType to "task"
|
|
27
|
+
set itemName to name of foundItem
|
|
28
|
+
end try
|
|
29
|
+
|
|
30
|
+
-- Try as project
|
|
31
|
+
if foundItem is missing value then
|
|
32
|
+
try
|
|
33
|
+
set foundItem to first flattened project whose id is itemId
|
|
34
|
+
set itemType to "project"
|
|
35
|
+
set itemName to name of foundItem
|
|
36
|
+
end try
|
|
37
|
+
end if
|
|
38
|
+
|
|
39
|
+
-- Try as folder
|
|
40
|
+
if foundItem is missing value then
|
|
41
|
+
try
|
|
42
|
+
set foundItem to first flattened folder whose id is itemId
|
|
43
|
+
set itemType to "folder"
|
|
44
|
+
set itemName to name of foundItem
|
|
45
|
+
end try
|
|
46
|
+
end if
|
|
47
|
+
|
|
48
|
+
-- Try as tag
|
|
49
|
+
if foundItem is missing value then
|
|
50
|
+
try
|
|
51
|
+
set foundItem to first flattened tag whose id is itemId
|
|
52
|
+
set itemType to "tag"
|
|
53
|
+
set itemName to name of foundItem
|
|
54
|
+
end try
|
|
55
|
+
end if
|
|
56
|
+
|
|
57
|
+
if foundItem is missing value then
|
|
58
|
+
error "Item not found with ID: " & itemId
|
|
59
|
+
end if
|
|
60
|
+
|
|
61
|
+
-- Activate OmniFocus and open the item using URL scheme
|
|
62
|
+
tell application "OmniFocus"
|
|
63
|
+
activate
|
|
64
|
+
end tell
|
|
65
|
+
|
|
66
|
+
-- Use URL scheme to navigate to the item
|
|
67
|
+
-- OmniFocus URL scheme: omnifocus:///task/ID, omnifocus:///project/ID, etc.
|
|
68
|
+
set theUrl to "omnifocus:///" & itemType & "/" & itemId
|
|
69
|
+
do shell script "open " & quoted form of theUrl
|
|
70
|
+
|
|
71
|
+
return "{" & ¬
|
|
72
|
+
"\\"id\\": \\"" & itemId & "\\"," & ¬
|
|
73
|
+
"\\"type\\": \\"" & itemType & "\\"," & ¬
|
|
74
|
+
"\\"name\\": \\"" & (my escapeJson(itemName)) & "\\"," & ¬
|
|
75
|
+
"\\"opened\\": true" & ¬
|
|
76
|
+
"}"
|
|
77
|
+
`;
|
|
78
|
+
const result = await runAppleScript(omniFocusScriptWithHelpers(script));
|
|
79
|
+
if (!result.success) {
|
|
80
|
+
return failure(result.error ??
|
|
81
|
+
createError(ErrorCode.UNKNOWN_ERROR, "Failed to open item"));
|
|
82
|
+
}
|
|
83
|
+
if (result.data === undefined) {
|
|
84
|
+
return failure(createError(ErrorCode.UNKNOWN_ERROR, "No result returned"));
|
|
85
|
+
}
|
|
86
|
+
return success(result.data);
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=open.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/commands/open.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAY/E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,EAAU;IACvC,cAAc;IACd,MAAM,OAAO,GAAG,UAAU,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACvC,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;IAErC,4DAA4D;IAC5D,MAAM,MAAM,GAAG;qBACI,iBAAiB,CAAC,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DvC,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,cAAc,CACjC,0BAA0B,CAAC,MAAM,CAAC,CACnC,CAAC;IAEF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,OAAO,CACZ,MAAM,CAAC,KAAK;YACV,WAAW,CAAC,SAAS,CAAC,aAAa,EAAE,qBAAqB,CAAC,CAC9D,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,aAAa,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC"}
|