@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,160 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { success, failure, failureMessage } from "../result.js";
|
|
4
|
+
import { ErrorCode, createError } from "../errors.js";
|
|
5
|
+
import { validateId } from "../validation.js";
|
|
6
|
+
import { escapeAppleScript } from "../escape.js";
|
|
7
|
+
import { runAppleScript, omniFocusScriptWithHelpers } from "../applescript.js";
|
|
8
|
+
/**
|
|
9
|
+
* Add an attachment to a task.
|
|
10
|
+
* @param taskId - Task ID to add attachment to
|
|
11
|
+
* @param filePath - Path to the file to attach
|
|
12
|
+
*/
|
|
13
|
+
export async function addAttachment(taskId, filePath) {
|
|
14
|
+
const idError = validateId(taskId, "task");
|
|
15
|
+
if (idError)
|
|
16
|
+
return failure(idError);
|
|
17
|
+
// Validate file exists
|
|
18
|
+
const absolutePath = path.resolve(filePath);
|
|
19
|
+
if (!fs.existsSync(absolutePath)) {
|
|
20
|
+
return failureMessage(`File not found: ${filePath}`);
|
|
21
|
+
}
|
|
22
|
+
// Get file stats
|
|
23
|
+
const stats = fs.statSync(absolutePath);
|
|
24
|
+
if (!stats.isFile()) {
|
|
25
|
+
return failureMessage(`Not a file: ${filePath}`);
|
|
26
|
+
}
|
|
27
|
+
const fileName = path.basename(absolutePath);
|
|
28
|
+
// OmniFocus AppleScript for adding attachment
|
|
29
|
+
// Note: OmniFocus uses POSIX file paths for attachments
|
|
30
|
+
const script = `
|
|
31
|
+
set theTask to first flattened task whose id is "${escapeAppleScript(taskId)}"
|
|
32
|
+
set taskName to name of theTask
|
|
33
|
+
|
|
34
|
+
-- Add attachment using POSIX file path
|
|
35
|
+
set theFile to POSIX file "${escapeAppleScript(absolutePath)}"
|
|
36
|
+
|
|
37
|
+
tell theTask
|
|
38
|
+
make new attachment with properties {file:theFile}
|
|
39
|
+
end tell
|
|
40
|
+
|
|
41
|
+
return "{" & ¬
|
|
42
|
+
"\\"taskId\\": \\"" & (id of theTask) & "\\"," & ¬
|
|
43
|
+
"\\"taskName\\": \\"" & (my escapeJson(taskName)) & "\\"," & ¬
|
|
44
|
+
"\\"fileName\\": \\"" & "${escapeAppleScript(fileName)}" & "\\"," & ¬
|
|
45
|
+
"\\"attached\\": true" & ¬
|
|
46
|
+
"}"
|
|
47
|
+
`;
|
|
48
|
+
const result = await runAppleScript(omniFocusScriptWithHelpers(script));
|
|
49
|
+
if (!result.success) {
|
|
50
|
+
return failure(result.error ??
|
|
51
|
+
createError(ErrorCode.UNKNOWN_ERROR, "Failed to add attachment"));
|
|
52
|
+
}
|
|
53
|
+
if (result.data === undefined) {
|
|
54
|
+
return failure(createError(ErrorCode.UNKNOWN_ERROR, "No result data returned"));
|
|
55
|
+
}
|
|
56
|
+
return success(result.data);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* List attachments of a task.
|
|
60
|
+
* @param taskId - Task ID to list attachments for
|
|
61
|
+
*/
|
|
62
|
+
export async function listAttachments(taskId) {
|
|
63
|
+
const idError = validateId(taskId, "task");
|
|
64
|
+
if (idError)
|
|
65
|
+
return failure(idError);
|
|
66
|
+
const script = `
|
|
67
|
+
set theTask to first flattened task whose id is "${escapeAppleScript(taskId)}"
|
|
68
|
+
set taskName to name of theTask
|
|
69
|
+
set taskId to id of theTask
|
|
70
|
+
|
|
71
|
+
set output to "{\\"taskId\\": \\"" & taskId & "\\","
|
|
72
|
+
set output to output & "\\"taskName\\": \\"" & (my escapeJson(taskName)) & "\\","
|
|
73
|
+
set output to output & "\\"attachments\\": ["
|
|
74
|
+
|
|
75
|
+
set isFirst to true
|
|
76
|
+
set taskAttachments to attachments of theTask
|
|
77
|
+
|
|
78
|
+
repeat with att in taskAttachments
|
|
79
|
+
if not isFirst then set output to output & ","
|
|
80
|
+
set isFirst to false
|
|
81
|
+
|
|
82
|
+
set attId to id of att
|
|
83
|
+
set attName to name of att
|
|
84
|
+
|
|
85
|
+
set output to output & "{"
|
|
86
|
+
set output to output & "\\"id\\": \\"" & attId & "\\","
|
|
87
|
+
set output to output & "\\"name\\": \\"" & (my escapeJson(attName)) & "\\","
|
|
88
|
+
set output to output & "\\"size\\": null,"
|
|
89
|
+
set output to output & "\\"type\\": null"
|
|
90
|
+
set output to output & "}"
|
|
91
|
+
end repeat
|
|
92
|
+
|
|
93
|
+
set output to output & "]}"
|
|
94
|
+
return output
|
|
95
|
+
`;
|
|
96
|
+
const result = await runAppleScript(omniFocusScriptWithHelpers(script));
|
|
97
|
+
if (!result.success) {
|
|
98
|
+
return failure(result.error ??
|
|
99
|
+
createError(ErrorCode.UNKNOWN_ERROR, "Failed to list attachments"));
|
|
100
|
+
}
|
|
101
|
+
if (result.data === undefined) {
|
|
102
|
+
return failure(createError(ErrorCode.UNKNOWN_ERROR, "No result data returned"));
|
|
103
|
+
}
|
|
104
|
+
return success(result.data);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Remove an attachment from a task.
|
|
108
|
+
* @param taskId - Task ID to remove attachment from
|
|
109
|
+
* @param attachmentIdOrName - Attachment ID or name to remove
|
|
110
|
+
*/
|
|
111
|
+
export async function removeAttachment(taskId, attachmentIdOrName) {
|
|
112
|
+
const idError = validateId(taskId, "task");
|
|
113
|
+
if (idError)
|
|
114
|
+
return failure(idError);
|
|
115
|
+
if (!attachmentIdOrName || attachmentIdOrName.trim() === "") {
|
|
116
|
+
return failureMessage("Attachment ID or name is required");
|
|
117
|
+
}
|
|
118
|
+
const script = `
|
|
119
|
+
set theTask to first flattened task whose id is "${escapeAppleScript(taskId)}"
|
|
120
|
+
set attachmentToRemove to missing value
|
|
121
|
+
set attName to ""
|
|
122
|
+
|
|
123
|
+
-- Try to find attachment by ID first, then by name
|
|
124
|
+
set taskAttachments to attachments of theTask
|
|
125
|
+
|
|
126
|
+
repeat with att in taskAttachments
|
|
127
|
+
if id of att is "${escapeAppleScript(attachmentIdOrName)}" then
|
|
128
|
+
set attachmentToRemove to att
|
|
129
|
+
set attName to name of att
|
|
130
|
+
exit repeat
|
|
131
|
+
else if name of att is "${escapeAppleScript(attachmentIdOrName)}" then
|
|
132
|
+
set attachmentToRemove to att
|
|
133
|
+
set attName to name of att
|
|
134
|
+
exit repeat
|
|
135
|
+
end if
|
|
136
|
+
end repeat
|
|
137
|
+
|
|
138
|
+
if attachmentToRemove is missing value then
|
|
139
|
+
error "Attachment not found: ${escapeAppleScript(attachmentIdOrName)}"
|
|
140
|
+
end if
|
|
141
|
+
|
|
142
|
+
delete attachmentToRemove
|
|
143
|
+
|
|
144
|
+
return "{" & ¬
|
|
145
|
+
"\\"taskId\\": \\"" & (id of theTask) & "\\"," & ¬
|
|
146
|
+
"\\"attachmentName\\": \\"" & (my escapeJson(attName)) & "\\"," & ¬
|
|
147
|
+
"\\"removed\\": true" & ¬
|
|
148
|
+
"}"
|
|
149
|
+
`;
|
|
150
|
+
const result = await runAppleScript(omniFocusScriptWithHelpers(script));
|
|
151
|
+
if (!result.success) {
|
|
152
|
+
return failure(result.error ??
|
|
153
|
+
createError(ErrorCode.UNKNOWN_ERROR, "Failed to remove attachment"));
|
|
154
|
+
}
|
|
155
|
+
if (result.data === undefined) {
|
|
156
|
+
return failure(createError(ErrorCode.UNKNOWN_ERROR, "No result data returned"));
|
|
157
|
+
}
|
|
158
|
+
return success(result.data);
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=attachments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../src/commands/attachments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { CliOutput, BatchResult } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Options for deferring a task.
|
|
4
|
+
*/
|
|
5
|
+
export interface DeferOptions {
|
|
6
|
+
/** Defer for a number of days from today */
|
|
7
|
+
days?: number | undefined;
|
|
8
|
+
/** Defer to a specific date */
|
|
9
|
+
to?: string | undefined;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Result from deferring a task.
|
|
13
|
+
*/
|
|
14
|
+
export interface DeferResult {
|
|
15
|
+
taskId: string;
|
|
16
|
+
taskName: string;
|
|
17
|
+
previousDeferDate: string | null;
|
|
18
|
+
newDeferDate: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Item in batch defer result.
|
|
22
|
+
*/
|
|
23
|
+
export interface BatchDeferItem {
|
|
24
|
+
taskId: string;
|
|
25
|
+
taskName: string;
|
|
26
|
+
previousDeferDate: string | null;
|
|
27
|
+
newDeferDate: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Defer a task by a number of days or to a specific date.
|
|
31
|
+
*/
|
|
32
|
+
export declare function deferTask(taskId: string, options?: DeferOptions): Promise<CliOutput<DeferResult>>;
|
|
33
|
+
/**
|
|
34
|
+
* Defer multiple tasks by a number of days or to a specific date.
|
|
35
|
+
*/
|
|
36
|
+
export declare function deferTasks(taskIds: string[], options?: DeferOptions): Promise<CliOutput<BatchResult<BatchDeferItem>>>;
|
|
37
|
+
//# sourceMappingURL=defer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defer.d.ts","sourceRoot":"","sources":["../../src/commands/defer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1D;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,+BAA+B;IAC/B,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;CACtB;AAID;;GAEG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAiFjC;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CA4IjD"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { success, failure } from "../result.js";
|
|
2
|
+
import { ErrorCode, createError } from "../errors.js";
|
|
3
|
+
import { validateId, validateDateString } from "../validation.js";
|
|
4
|
+
import { escapeAppleScript } from "../escape.js";
|
|
5
|
+
import { runAppleScript, omniFocusScriptWithHelpers } from "../applescript.js";
|
|
6
|
+
const MAX_BATCH_SIZE = 50;
|
|
7
|
+
/**
|
|
8
|
+
* Defer a task by a number of days or to a specific date.
|
|
9
|
+
*/
|
|
10
|
+
export async function deferTask(taskId, options = {}) {
|
|
11
|
+
// Validate task ID
|
|
12
|
+
const idError = validateId(taskId, "task");
|
|
13
|
+
if (idError)
|
|
14
|
+
return failure(idError);
|
|
15
|
+
// Validate that at least one option is provided
|
|
16
|
+
if (options.days === undefined && options.to === undefined) {
|
|
17
|
+
return failure(createError(ErrorCode.VALIDATION_ERROR, "Must specify either --days or --to"));
|
|
18
|
+
}
|
|
19
|
+
// Validate days
|
|
20
|
+
if (options.days !== undefined &&
|
|
21
|
+
(options.days < 1 || !Number.isInteger(options.days))) {
|
|
22
|
+
return failure(createError(ErrorCode.VALIDATION_ERROR, "Days must be a positive integer"));
|
|
23
|
+
}
|
|
24
|
+
// Validate date string if provided
|
|
25
|
+
if (options.to !== undefined) {
|
|
26
|
+
const dateError = validateDateString(options.to);
|
|
27
|
+
if (dateError)
|
|
28
|
+
return failure(dateError);
|
|
29
|
+
}
|
|
30
|
+
// Build the defer date logic
|
|
31
|
+
let deferLogic;
|
|
32
|
+
if (options.days !== undefined) {
|
|
33
|
+
deferLogic = `set newDefer to (current date) + (${String(options.days)} * days)`;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
deferLogic = `set newDefer to date "${escapeAppleScript(options.to ?? "")}"`;
|
|
37
|
+
}
|
|
38
|
+
const script = `
|
|
39
|
+
set theTask to first flattened task whose id is "${escapeAppleScript(taskId)}"
|
|
40
|
+
|
|
41
|
+
-- Get previous defer date
|
|
42
|
+
set prevDefer to ""
|
|
43
|
+
try
|
|
44
|
+
set prevDefer to (defer date of theTask) as string
|
|
45
|
+
end try
|
|
46
|
+
|
|
47
|
+
-- Calculate new defer date
|
|
48
|
+
${deferLogic}
|
|
49
|
+
|
|
50
|
+
-- Set the defer date
|
|
51
|
+
set defer date of theTask to newDefer
|
|
52
|
+
|
|
53
|
+
-- Get the new defer date as string
|
|
54
|
+
set newDeferStr to (defer date of theTask) as string
|
|
55
|
+
|
|
56
|
+
return "{" & ¬
|
|
57
|
+
"\\"taskId\\": \\"${escapeAppleScript(taskId)}\\"," & ¬
|
|
58
|
+
"\\"taskName\\": \\"" & (my escapeJson(name of theTask)) & "\\"," & ¬
|
|
59
|
+
"\\"previousDeferDate\\": " & (my jsonString(prevDefer)) & "," & ¬
|
|
60
|
+
"\\"newDeferDate\\": \\"" & (my escapeJson(newDeferStr)) & "\\"" & ¬
|
|
61
|
+
"}"
|
|
62
|
+
`;
|
|
63
|
+
const result = await runAppleScript(omniFocusScriptWithHelpers(script));
|
|
64
|
+
if (!result.success) {
|
|
65
|
+
return failure(result.error ??
|
|
66
|
+
createError(ErrorCode.UNKNOWN_ERROR, "Failed to defer task"));
|
|
67
|
+
}
|
|
68
|
+
if (result.data === undefined) {
|
|
69
|
+
return failure(createError(ErrorCode.UNKNOWN_ERROR, "No result returned"));
|
|
70
|
+
}
|
|
71
|
+
return success(result.data);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Defer multiple tasks by a number of days or to a specific date.
|
|
75
|
+
*/
|
|
76
|
+
export async function deferTasks(taskIds, options = {}) {
|
|
77
|
+
// Validate all task IDs first
|
|
78
|
+
for (const id of taskIds) {
|
|
79
|
+
const idError = validateId(id, "task");
|
|
80
|
+
if (idError)
|
|
81
|
+
return failure(idError);
|
|
82
|
+
}
|
|
83
|
+
// Validate that at least one option is provided
|
|
84
|
+
if (options.days === undefined && options.to === undefined) {
|
|
85
|
+
return failure(createError(ErrorCode.VALIDATION_ERROR, "Must specify either --days or --to"));
|
|
86
|
+
}
|
|
87
|
+
// Validate days
|
|
88
|
+
if (options.days !== undefined &&
|
|
89
|
+
(options.days < 1 || !Number.isInteger(options.days))) {
|
|
90
|
+
return failure(createError(ErrorCode.VALIDATION_ERROR, "Days must be a positive integer"));
|
|
91
|
+
}
|
|
92
|
+
// Validate date string if provided
|
|
93
|
+
if (options.to !== undefined) {
|
|
94
|
+
const dateError = validateDateString(options.to);
|
|
95
|
+
if (dateError)
|
|
96
|
+
return failure(dateError);
|
|
97
|
+
}
|
|
98
|
+
// Process in chunks
|
|
99
|
+
const chunks = [];
|
|
100
|
+
for (let i = 0; i < taskIds.length; i += MAX_BATCH_SIZE) {
|
|
101
|
+
chunks.push(taskIds.slice(i, i + MAX_BATCH_SIZE));
|
|
102
|
+
}
|
|
103
|
+
const allSucceeded = [];
|
|
104
|
+
const allFailed = [];
|
|
105
|
+
// Build the defer date logic
|
|
106
|
+
let deferLogic;
|
|
107
|
+
if (options.days !== undefined) {
|
|
108
|
+
deferLogic = `set newDefer to rightNow + (${String(options.days)} * days)`;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
deferLogic = `set newDefer to date "${escapeAppleScript(options.to ?? "")}"`;
|
|
112
|
+
}
|
|
113
|
+
for (const chunk of chunks) {
|
|
114
|
+
const idsJson = JSON.stringify(chunk);
|
|
115
|
+
const script = `
|
|
116
|
+
set taskIdList to ${idsJson}
|
|
117
|
+
set succeededList to {}
|
|
118
|
+
set failedList to {}
|
|
119
|
+
set rightNow to current date
|
|
120
|
+
|
|
121
|
+
${deferLogic}
|
|
122
|
+
|
|
123
|
+
repeat with taskIdStr in taskIdList
|
|
124
|
+
try
|
|
125
|
+
set theTask to first flattened task whose id is taskIdStr
|
|
126
|
+
|
|
127
|
+
-- Get previous defer date
|
|
128
|
+
set prevDefer to ""
|
|
129
|
+
try
|
|
130
|
+
set prevDefer to (defer date of theTask) as string
|
|
131
|
+
end try
|
|
132
|
+
|
|
133
|
+
-- Set the defer date
|
|
134
|
+
set defer date of theTask to newDefer
|
|
135
|
+
|
|
136
|
+
-- Get the new defer date as string
|
|
137
|
+
set newDeferStr to (defer date of theTask) as string
|
|
138
|
+
|
|
139
|
+
set end of succeededList to "{" & ¬
|
|
140
|
+
"\\"taskId\\": \\"" & taskIdStr & "\\"," & ¬
|
|
141
|
+
"\\"taskName\\": \\"" & (my escapeJson(name of theTask)) & "\\"," & ¬
|
|
142
|
+
"\\"previousDeferDate\\": " & (my jsonString(prevDefer)) & "," & ¬
|
|
143
|
+
"\\"newDeferDate\\": \\"" & (my escapeJson(newDeferStr)) & "\\"" & ¬
|
|
144
|
+
"}"
|
|
145
|
+
on error errMsg
|
|
146
|
+
set end of failedList to "{" & ¬
|
|
147
|
+
"\\"id\\": \\"" & taskIdStr & "\\"," & ¬
|
|
148
|
+
"\\"error\\": \\"" & (my escapeJson(errMsg)) & "\\"" & ¬
|
|
149
|
+
"}"
|
|
150
|
+
end try
|
|
151
|
+
end repeat
|
|
152
|
+
|
|
153
|
+
set successJson to "["
|
|
154
|
+
set isFirst to true
|
|
155
|
+
repeat with item_ in succeededList
|
|
156
|
+
if not isFirst then set successJson to successJson & ","
|
|
157
|
+
set isFirst to false
|
|
158
|
+
set successJson to successJson & item_
|
|
159
|
+
end repeat
|
|
160
|
+
set successJson to successJson & "]"
|
|
161
|
+
|
|
162
|
+
set failJson to "["
|
|
163
|
+
set isFirst to true
|
|
164
|
+
repeat with item_ in failedList
|
|
165
|
+
if not isFirst then set failJson to failJson & ","
|
|
166
|
+
set isFirst to false
|
|
167
|
+
set failJson to failJson & item_
|
|
168
|
+
end repeat
|
|
169
|
+
set failJson to failJson & "]"
|
|
170
|
+
|
|
171
|
+
return "{" & ¬
|
|
172
|
+
"\\"succeeded\\": " & successJson & "," & ¬
|
|
173
|
+
"\\"failed\\": " & failJson & ¬
|
|
174
|
+
"}"
|
|
175
|
+
`;
|
|
176
|
+
const result = await runAppleScript(omniFocusScriptWithHelpers(script));
|
|
177
|
+
if (result.success && result.data) {
|
|
178
|
+
allSucceeded.push(...result.data.succeeded);
|
|
179
|
+
allFailed.push(...result.data.failed);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
// If the entire chunk failed, mark all as failed
|
|
183
|
+
for (const id of chunk) {
|
|
184
|
+
allFailed.push({
|
|
185
|
+
id,
|
|
186
|
+
error: result.error?.message ?? "Unknown error",
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return success({
|
|
192
|
+
succeeded: allSucceeded,
|
|
193
|
+
failed: allFailed,
|
|
194
|
+
totalSucceeded: allSucceeded.length,
|
|
195
|
+
totalFailed: allFailed.length,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=defer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defer.js","sourceRoot":"","sources":["../../src/commands/defer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CliOutput, OFTask } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Options for querying deferred tasks.
|
|
4
|
+
*/
|
|
5
|
+
export interface DeferredQueryOptions {
|
|
6
|
+
/** Include tasks deferred until after this date */
|
|
7
|
+
deferredAfter?: string | undefined;
|
|
8
|
+
/** Include tasks deferred until before this date */
|
|
9
|
+
deferredBefore?: string | undefined;
|
|
10
|
+
/** Only show tasks that are currently blocked by defer date */
|
|
11
|
+
blockedOnly?: boolean | undefined;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Query all deferred tasks from OmniFocus.
|
|
15
|
+
* Returns tasks that have a defer date set.
|
|
16
|
+
*/
|
|
17
|
+
export declare function queryDeferred(options?: DeferredQueryOptions): Promise<CliOutput<OFTask[]>>;
|
|
18
|
+
//# sourceMappingURL=deferred.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deferred.d.ts","sourceRoot":"","sources":["../../src/commands/deferred.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAOrD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,mDAAmD;IACnD,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,oDAAoD;IACpD,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,+DAA+D;IAC/D,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACnC;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAsJ9B"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { success, failure } from "../result.js";
|
|
2
|
+
import { ErrorCode, createError } from "../errors.js";
|
|
3
|
+
import { runAppleScript, omniFocusScriptWithHelpers } from "../applescript.js";
|
|
4
|
+
import { validateDateString } from "../validation.js";
|
|
5
|
+
import { escapeAppleScript } from "../escape.js";
|
|
6
|
+
/**
|
|
7
|
+
* Query all deferred tasks from OmniFocus.
|
|
8
|
+
* Returns tasks that have a defer date set.
|
|
9
|
+
*/
|
|
10
|
+
export async function queryDeferred(options = {}) {
|
|
11
|
+
// Validate date inputs
|
|
12
|
+
if (options.deferredAfter) {
|
|
13
|
+
const afterError = validateDateString(options.deferredAfter);
|
|
14
|
+
if (afterError) {
|
|
15
|
+
return failure(afterError);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (options.deferredBefore) {
|
|
19
|
+
const beforeError = validateDateString(options.deferredBefore);
|
|
20
|
+
if (beforeError) {
|
|
21
|
+
return failure(beforeError);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const blockedOnly = options.blockedOnly === true;
|
|
25
|
+
const escapedDeferredAfter = options.deferredAfter
|
|
26
|
+
? escapeAppleScript(options.deferredAfter)
|
|
27
|
+
: null;
|
|
28
|
+
const escapedDeferredBefore = options.deferredBefore
|
|
29
|
+
? escapeAppleScript(options.deferredBefore)
|
|
30
|
+
: null;
|
|
31
|
+
const script = `
|
|
32
|
+
set output to "["
|
|
33
|
+
set isFirst to true
|
|
34
|
+
set rightNow to current date
|
|
35
|
+
|
|
36
|
+
set allTasks to flattened tasks where completed is false and effectively dropped is false
|
|
37
|
+
|
|
38
|
+
repeat with t in allTasks
|
|
39
|
+
set shouldInclude to false
|
|
40
|
+
|
|
41
|
+
-- Check if task has defer date
|
|
42
|
+
try
|
|
43
|
+
set taskDefer to defer date of t
|
|
44
|
+
if taskDefer is not missing value then
|
|
45
|
+
set shouldInclude to true
|
|
46
|
+
|
|
47
|
+
${blockedOnly
|
|
48
|
+
? `
|
|
49
|
+
-- Only include if defer date is in the future (currently blocked)
|
|
50
|
+
if taskDefer <= rightNow then
|
|
51
|
+
set shouldInclude to false
|
|
52
|
+
end if
|
|
53
|
+
`
|
|
54
|
+
: ""}
|
|
55
|
+
|
|
56
|
+
${escapedDeferredAfter
|
|
57
|
+
? `
|
|
58
|
+
-- Filter by deferred after
|
|
59
|
+
if shouldInclude and taskDefer < date "${escapedDeferredAfter}" then
|
|
60
|
+
set shouldInclude to false
|
|
61
|
+
end if
|
|
62
|
+
`
|
|
63
|
+
: ""}
|
|
64
|
+
|
|
65
|
+
${escapedDeferredBefore
|
|
66
|
+
? `
|
|
67
|
+
-- Filter by deferred before
|
|
68
|
+
if shouldInclude and taskDefer > date "${escapedDeferredBefore}" then
|
|
69
|
+
set shouldInclude to false
|
|
70
|
+
end if
|
|
71
|
+
`
|
|
72
|
+
: ""}
|
|
73
|
+
end if
|
|
74
|
+
end try
|
|
75
|
+
|
|
76
|
+
if shouldInclude then
|
|
77
|
+
if not isFirst then set output to output & ","
|
|
78
|
+
set isFirst to false
|
|
79
|
+
|
|
80
|
+
set taskId to id of t
|
|
81
|
+
set taskName to name of t
|
|
82
|
+
set taskNote to note of t
|
|
83
|
+
set taskFlagged to flagged of t
|
|
84
|
+
set taskCompleted to completed of t
|
|
85
|
+
|
|
86
|
+
set dueStr to ""
|
|
87
|
+
try
|
|
88
|
+
set dueStr to (due date of t) as string
|
|
89
|
+
end try
|
|
90
|
+
|
|
91
|
+
set deferStr to ""
|
|
92
|
+
try
|
|
93
|
+
set deferStr to (defer date of t) as string
|
|
94
|
+
end try
|
|
95
|
+
|
|
96
|
+
set completionStr to ""
|
|
97
|
+
try
|
|
98
|
+
set completionStr to (completion date of t) as string
|
|
99
|
+
end try
|
|
100
|
+
|
|
101
|
+
set projId to ""
|
|
102
|
+
set projName to ""
|
|
103
|
+
try
|
|
104
|
+
set proj to containing project of t
|
|
105
|
+
set projId to id of proj
|
|
106
|
+
set projName to name of proj
|
|
107
|
+
end try
|
|
108
|
+
|
|
109
|
+
set tagNames to {}
|
|
110
|
+
repeat with tg in tags of t
|
|
111
|
+
set end of tagNames to name of tg
|
|
112
|
+
end repeat
|
|
113
|
+
|
|
114
|
+
set estMinutes to 0
|
|
115
|
+
try
|
|
116
|
+
set estMinutes to estimated minutes of t
|
|
117
|
+
if estMinutes is missing value then set estMinutes to 0
|
|
118
|
+
end try
|
|
119
|
+
|
|
120
|
+
set output to output & "{" & ¬
|
|
121
|
+
"\\"id\\": \\"" & taskId & "\\"," & ¬
|
|
122
|
+
"\\"name\\": \\"" & (my escapeJson(taskName)) & "\\"," & ¬
|
|
123
|
+
"\\"note\\": " & (my jsonString(taskNote)) & "," & ¬
|
|
124
|
+
"\\"flagged\\": " & taskFlagged & "," & ¬
|
|
125
|
+
"\\"completed\\": " & taskCompleted & "," & ¬
|
|
126
|
+
"\\"dueDate\\": " & (my jsonString(dueStr)) & "," & ¬
|
|
127
|
+
"\\"deferDate\\": " & (my jsonString(deferStr)) & "," & ¬
|
|
128
|
+
"\\"completionDate\\": " & (my jsonString(completionStr)) & "," & ¬
|
|
129
|
+
"\\"projectId\\": " & (my jsonString(projId)) & "," & ¬
|
|
130
|
+
"\\"projectName\\": " & (my jsonString(projName)) & "," & ¬
|
|
131
|
+
"\\"tags\\": " & (my jsonArray(tagNames)) & "," & ¬
|
|
132
|
+
"\\"estimatedMinutes\\": " & estMinutes & ¬
|
|
133
|
+
"}"
|
|
134
|
+
end if
|
|
135
|
+
end repeat
|
|
136
|
+
|
|
137
|
+
return output & "]"
|
|
138
|
+
`;
|
|
139
|
+
const result = await runAppleScript(omniFocusScriptWithHelpers(script));
|
|
140
|
+
if (!result.success) {
|
|
141
|
+
return failure(result.error ??
|
|
142
|
+
createError(ErrorCode.UNKNOWN_ERROR, "Failed to query deferred tasks"));
|
|
143
|
+
}
|
|
144
|
+
return success(result.data ?? []);
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=deferred.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deferred.js","sourceRoot":"","sources":["../../src/commands/deferred.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,cAAc,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAcjD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,UAAgC,EAAE;IAElC,uBAAuB;IACvB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,MAAM,UAAU,GAAG,kBAAkB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QAC7D,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAC/D,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,KAAK,IAAI,CAAC;IACjD,MAAM,oBAAoB,GAAG,OAAO,CAAC,aAAa;QAChD,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,aAAa,CAAC;QAC1C,CAAC,CAAC,IAAI,CAAC;IACT,MAAM,qBAAqB,GAAG,OAAO,CAAC,cAAc;QAClD,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,cAAc,CAAC;QAC3C,CAAC,CAAC,IAAI,CAAC;IAET,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;YAiBL,WAAW;QACT,CAAC,CAAC;;;;;WAKL;QACG,CAAC,CAAC,EACN;;YAGE,oBAAoB;QAClB,CAAC,CAAC;;mDAEmC,oBAAoB;;;WAG5D;QACG,CAAC,CAAC,EACN;;YAGE,qBAAqB;QACnB,CAAC,CAAC;;mDAEmC,qBAAqB;;;WAG7D;QACG,CAAC,CAAC,EACN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEP,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,gCAAgC,CAAC,CACzE,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CliOutput, DuplicateTaskOptions } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Result from duplicating a task.
|
|
4
|
+
*/
|
|
5
|
+
export interface DuplicateTaskResult {
|
|
6
|
+
originalTaskId: string;
|
|
7
|
+
newTaskId: string;
|
|
8
|
+
newTaskName: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Duplicate a task in OmniFocus.
|
|
12
|
+
* Creates a copy of the task with all its properties.
|
|
13
|
+
*/
|
|
14
|
+
export declare function duplicateTask(taskId: string, options?: DuplicateTaskOptions): Promise<CliOutput<DuplicateTaskResult>>;
|
|
15
|
+
//# sourceMappingURL=duplicate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplicate.d.ts","sourceRoot":"","sources":["../../src/commands/duplicate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAOnE;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC,CAgDzC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
* Duplicate a task in OmniFocus.
|
|
8
|
+
* Creates a copy of the task with all its properties.
|
|
9
|
+
*/
|
|
10
|
+
export async function duplicateTask(taskId, options = {}) {
|
|
11
|
+
// Validate task ID
|
|
12
|
+
const idError = validateId(taskId, "task");
|
|
13
|
+
if (idError)
|
|
14
|
+
return failure(idError);
|
|
15
|
+
// Default to including subtasks
|
|
16
|
+
const includeSubtasks = options.includeSubtasks !== false;
|
|
17
|
+
// AppleScript's duplicate command includes subtasks by default
|
|
18
|
+
// We need to handle the case where we don't want subtasks
|
|
19
|
+
const duplicateScript = includeSubtasks
|
|
20
|
+
? `set newTask to duplicate theTask`
|
|
21
|
+
: `set newTask to duplicate theTask
|
|
22
|
+
-- Remove subtasks if not including them (iterate in reverse to avoid skipping)
|
|
23
|
+
repeat with i from (count of tasks of newTask) to 1 by -1
|
|
24
|
+
delete task i of newTask
|
|
25
|
+
end repeat`;
|
|
26
|
+
const script = `
|
|
27
|
+
set theTask to first flattened task whose id is "${escapeAppleScript(taskId)}"
|
|
28
|
+
${duplicateScript}
|
|
29
|
+
|
|
30
|
+
set newId to id of newTask
|
|
31
|
+
set newName to name of newTask
|
|
32
|
+
|
|
33
|
+
return "{" & ¬
|
|
34
|
+
"\\"originalTaskId\\": \\"${escapeAppleScript(taskId)}\\"," & ¬
|
|
35
|
+
"\\"newTaskId\\": \\"" & newId & "\\"," & ¬
|
|
36
|
+
"\\"newTaskName\\": \\"" & (my escapeJson(newName)) & "\\"" & ¬
|
|
37
|
+
"}"
|
|
38
|
+
`;
|
|
39
|
+
const result = await runAppleScript(omniFocusScriptWithHelpers(script));
|
|
40
|
+
if (!result.success) {
|
|
41
|
+
return failure(result.error ??
|
|
42
|
+
createError(ErrorCode.UNKNOWN_ERROR, "Failed to duplicate task"));
|
|
43
|
+
}
|
|
44
|
+
if (result.data === undefined) {
|
|
45
|
+
return failure(createError(ErrorCode.UNKNOWN_ERROR, "No result returned"));
|
|
46
|
+
}
|
|
47
|
+
return success(result.data);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=duplicate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplicate.js","sourceRoot":"","sources":["../../src/commands/duplicate.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;AAW/E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAc,EACd,UAAgC,EAAE;IAElC,mBAAmB;IACnB,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;IAErC,gCAAgC;IAChC,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,KAAK,KAAK,CAAC;IAE1D,+DAA+D;IAC/D,0DAA0D;IAC1D,MAAM,eAAe,GAAG,eAAe;QACrC,CAAC,CAAC,kCAAkC;QACpC,CAAC,CAAC;;;;kBAIY,CAAC;IAEjB,MAAM,MAAM,GAAG;uDACsC,iBAAiB,CAAC,MAAM,CAAC;MAC1E,eAAe;;;;;;kCAMa,iBAAiB,CAAC,MAAM,CAAC;;;;GAIxD,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,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"}
|