apple-notes-mcp 2.8.34 → 2.8.36
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/README.md +73 -7
- package/build/index.js +1261 -325
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -108,7 +108,7 @@ var require_code = __commonJS({
|
|
|
108
108
|
}
|
|
109
109
|
exports._ = _;
|
|
110
110
|
var plus = new _Code("+");
|
|
111
|
-
function
|
|
111
|
+
function str2(strs, ...args) {
|
|
112
112
|
const expr = [safeStringify(strs[0])];
|
|
113
113
|
let i = 0;
|
|
114
114
|
while (i < args.length) {
|
|
@@ -119,7 +119,7 @@ var require_code = __commonJS({
|
|
|
119
119
|
optimize(expr);
|
|
120
120
|
return new _Code(expr);
|
|
121
121
|
}
|
|
122
|
-
exports.str =
|
|
122
|
+
exports.str = str2;
|
|
123
123
|
function addCodeArg(code, arg) {
|
|
124
124
|
if (arg instanceof _Code)
|
|
125
125
|
code.push(...arg._items);
|
|
@@ -162,7 +162,7 @@ var require_code = __commonJS({
|
|
|
162
162
|
return;
|
|
163
163
|
}
|
|
164
164
|
function strConcat(c1, c2) {
|
|
165
|
-
return c2.emptyStr() ? c1 : c1.emptyStr() ? c2 :
|
|
165
|
+
return c2.emptyStr() ? c1 : c1.emptyStr() ? c2 : str2`${c1}${c2}`;
|
|
166
166
|
}
|
|
167
167
|
exports.strConcat = strConcat;
|
|
168
168
|
function interpolate(x) {
|
|
@@ -417,11 +417,11 @@ var require_codegen = __commonJS({
|
|
|
417
417
|
const rhs = this.rhs === void 0 ? "" : ` = ${this.rhs}`;
|
|
418
418
|
return `${varKind} ${this.name}${rhs};` + _n;
|
|
419
419
|
}
|
|
420
|
-
optimizeNames(names,
|
|
420
|
+
optimizeNames(names, constants5) {
|
|
421
421
|
if (!names[this.name.str])
|
|
422
422
|
return;
|
|
423
423
|
if (this.rhs)
|
|
424
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
424
|
+
this.rhs = optimizeExpr(this.rhs, names, constants5);
|
|
425
425
|
return this;
|
|
426
426
|
}
|
|
427
427
|
get names() {
|
|
@@ -438,10 +438,10 @@ var require_codegen = __commonJS({
|
|
|
438
438
|
render({ _n }) {
|
|
439
439
|
return `${this.lhs} = ${this.rhs};` + _n;
|
|
440
440
|
}
|
|
441
|
-
optimizeNames(names,
|
|
441
|
+
optimizeNames(names, constants5) {
|
|
442
442
|
if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
|
|
443
443
|
return;
|
|
444
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
444
|
+
this.rhs = optimizeExpr(this.rhs, names, constants5);
|
|
445
445
|
return this;
|
|
446
446
|
}
|
|
447
447
|
get names() {
|
|
@@ -502,8 +502,8 @@ var require_codegen = __commonJS({
|
|
|
502
502
|
optimizeNodes() {
|
|
503
503
|
return `${this.code}` ? this : void 0;
|
|
504
504
|
}
|
|
505
|
-
optimizeNames(names,
|
|
506
|
-
this.code = optimizeExpr(this.code, names,
|
|
505
|
+
optimizeNames(names, constants5) {
|
|
506
|
+
this.code = optimizeExpr(this.code, names, constants5);
|
|
507
507
|
return this;
|
|
508
508
|
}
|
|
509
509
|
get names() {
|
|
@@ -532,12 +532,12 @@ var require_codegen = __commonJS({
|
|
|
532
532
|
}
|
|
533
533
|
return nodes.length > 0 ? this : void 0;
|
|
534
534
|
}
|
|
535
|
-
optimizeNames(names,
|
|
535
|
+
optimizeNames(names, constants5) {
|
|
536
536
|
const { nodes } = this;
|
|
537
537
|
let i = nodes.length;
|
|
538
538
|
while (i--) {
|
|
539
539
|
const n = nodes[i];
|
|
540
|
-
if (n.optimizeNames(names,
|
|
540
|
+
if (n.optimizeNames(names, constants5))
|
|
541
541
|
continue;
|
|
542
542
|
subtractNames(names, n.names);
|
|
543
543
|
nodes.splice(i, 1);
|
|
@@ -590,12 +590,12 @@ var require_codegen = __commonJS({
|
|
|
590
590
|
return void 0;
|
|
591
591
|
return this;
|
|
592
592
|
}
|
|
593
|
-
optimizeNames(names,
|
|
593
|
+
optimizeNames(names, constants5) {
|
|
594
594
|
var _a;
|
|
595
|
-
this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names,
|
|
596
|
-
if (!(super.optimizeNames(names,
|
|
595
|
+
this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants5);
|
|
596
|
+
if (!(super.optimizeNames(names, constants5) || this.else))
|
|
597
597
|
return;
|
|
598
|
-
this.condition = optimizeExpr(this.condition, names,
|
|
598
|
+
this.condition = optimizeExpr(this.condition, names, constants5);
|
|
599
599
|
return this;
|
|
600
600
|
}
|
|
601
601
|
get names() {
|
|
@@ -618,10 +618,10 @@ var require_codegen = __commonJS({
|
|
|
618
618
|
render(opts) {
|
|
619
619
|
return `for(${this.iteration})` + super.render(opts);
|
|
620
620
|
}
|
|
621
|
-
optimizeNames(names,
|
|
622
|
-
if (!super.optimizeNames(names,
|
|
621
|
+
optimizeNames(names, constants5) {
|
|
622
|
+
if (!super.optimizeNames(names, constants5))
|
|
623
623
|
return;
|
|
624
|
-
this.iteration = optimizeExpr(this.iteration, names,
|
|
624
|
+
this.iteration = optimizeExpr(this.iteration, names, constants5);
|
|
625
625
|
return this;
|
|
626
626
|
}
|
|
627
627
|
get names() {
|
|
@@ -657,10 +657,10 @@ var require_codegen = __commonJS({
|
|
|
657
657
|
render(opts) {
|
|
658
658
|
return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
|
|
659
659
|
}
|
|
660
|
-
optimizeNames(names,
|
|
661
|
-
if (!super.optimizeNames(names,
|
|
660
|
+
optimizeNames(names, constants5) {
|
|
661
|
+
if (!super.optimizeNames(names, constants5))
|
|
662
662
|
return;
|
|
663
|
-
this.iterable = optimizeExpr(this.iterable, names,
|
|
663
|
+
this.iterable = optimizeExpr(this.iterable, names, constants5);
|
|
664
664
|
return this;
|
|
665
665
|
}
|
|
666
666
|
get names() {
|
|
@@ -702,11 +702,11 @@ var require_codegen = __commonJS({
|
|
|
702
702
|
(_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNodes();
|
|
703
703
|
return this;
|
|
704
704
|
}
|
|
705
|
-
optimizeNames(names,
|
|
705
|
+
optimizeNames(names, constants5) {
|
|
706
706
|
var _a, _b;
|
|
707
|
-
super.optimizeNames(names,
|
|
708
|
-
(_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names,
|
|
709
|
-
(_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names,
|
|
707
|
+
super.optimizeNames(names, constants5);
|
|
708
|
+
(_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants5);
|
|
709
|
+
(_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants5);
|
|
710
710
|
return this;
|
|
711
711
|
}
|
|
712
712
|
get names() {
|
|
@@ -1007,7 +1007,7 @@ var require_codegen = __commonJS({
|
|
|
1007
1007
|
function addExprNames(names, from) {
|
|
1008
1008
|
return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
|
|
1009
1009
|
}
|
|
1010
|
-
function optimizeExpr(expr, names,
|
|
1010
|
+
function optimizeExpr(expr, names, constants5) {
|
|
1011
1011
|
if (expr instanceof code_1.Name)
|
|
1012
1012
|
return replaceName(expr);
|
|
1013
1013
|
if (!canOptimize(expr))
|
|
@@ -1022,14 +1022,14 @@ var require_codegen = __commonJS({
|
|
|
1022
1022
|
return items;
|
|
1023
1023
|
}, []));
|
|
1024
1024
|
function replaceName(n) {
|
|
1025
|
-
const c =
|
|
1025
|
+
const c = constants5[n.str];
|
|
1026
1026
|
if (c === void 0 || names[n.str] !== 1)
|
|
1027
1027
|
return n;
|
|
1028
1028
|
delete names[n.str];
|
|
1029
1029
|
return c;
|
|
1030
1030
|
}
|
|
1031
1031
|
function canOptimize(e) {
|
|
1032
|
-
return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 &&
|
|
1032
|
+
return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants5[c.str] !== void 0);
|
|
1033
1033
|
}
|
|
1034
1034
|
}
|
|
1035
1035
|
function subtractNames(names, from) {
|
|
@@ -1124,22 +1124,22 @@ var require_util = __commonJS({
|
|
|
1124
1124
|
return (0, codegen_1._)`${topSchemaRef}${schemaPath}${(0, codegen_1.getProperty)(keyword)}`;
|
|
1125
1125
|
}
|
|
1126
1126
|
exports.schemaRefOrVal = schemaRefOrVal;
|
|
1127
|
-
function unescapeFragment(
|
|
1128
|
-
return unescapeJsonPointer(decodeURIComponent(
|
|
1127
|
+
function unescapeFragment(str2) {
|
|
1128
|
+
return unescapeJsonPointer(decodeURIComponent(str2));
|
|
1129
1129
|
}
|
|
1130
1130
|
exports.unescapeFragment = unescapeFragment;
|
|
1131
|
-
function escapeFragment(
|
|
1132
|
-
return encodeURIComponent(escapeJsonPointer(
|
|
1131
|
+
function escapeFragment(str2) {
|
|
1132
|
+
return encodeURIComponent(escapeJsonPointer(str2));
|
|
1133
1133
|
}
|
|
1134
1134
|
exports.escapeFragment = escapeFragment;
|
|
1135
|
-
function escapeJsonPointer(
|
|
1136
|
-
if (typeof
|
|
1137
|
-
return `${
|
|
1138
|
-
return
|
|
1135
|
+
function escapeJsonPointer(str2) {
|
|
1136
|
+
if (typeof str2 == "number")
|
|
1137
|
+
return `${str2}`;
|
|
1138
|
+
return str2.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
1139
1139
|
}
|
|
1140
1140
|
exports.escapeJsonPointer = escapeJsonPointer;
|
|
1141
|
-
function unescapeJsonPointer(
|
|
1142
|
-
return
|
|
1141
|
+
function unescapeJsonPointer(str2) {
|
|
1142
|
+
return str2.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
1143
1143
|
}
|
|
1144
1144
|
exports.unescapeJsonPointer = unescapeJsonPointer;
|
|
1145
1145
|
function eachItem(xs, f) {
|
|
@@ -2164,8 +2164,8 @@ var require_json_schema_traverse = __commonJS({
|
|
|
2164
2164
|
post(schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex);
|
|
2165
2165
|
}
|
|
2166
2166
|
}
|
|
2167
|
-
function escapeJsonPtr(
|
|
2168
|
-
return
|
|
2167
|
+
function escapeJsonPtr(str2) {
|
|
2168
|
+
return str2.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
2169
2169
|
}
|
|
2170
2170
|
}
|
|
2171
2171
|
});
|
|
@@ -3261,15 +3261,15 @@ var require_utils = __commonJS({
|
|
|
3261
3261
|
isIPV6: true
|
|
3262
3262
|
};
|
|
3263
3263
|
}
|
|
3264
|
-
function findToken(
|
|
3264
|
+
function findToken(str2, token) {
|
|
3265
3265
|
let ind = 0;
|
|
3266
|
-
for (let i = 0; i <
|
|
3267
|
-
if (
|
|
3266
|
+
for (let i = 0; i < str2.length; i++) {
|
|
3267
|
+
if (str2[i] === token) ind++;
|
|
3268
3268
|
}
|
|
3269
3269
|
return ind;
|
|
3270
3270
|
}
|
|
3271
|
-
function removeDotSegments(
|
|
3272
|
-
let input =
|
|
3271
|
+
function removeDotSegments(path8) {
|
|
3272
|
+
let input = path8;
|
|
3273
3273
|
const output = [];
|
|
3274
3274
|
let nextSlash = -1;
|
|
3275
3275
|
let len = 0;
|
|
@@ -3674,8 +3674,8 @@ var require_schemes = __commonJS({
|
|
|
3674
3674
|
}
|
|
3675
3675
|
if (wsComponent.resourceName) {
|
|
3676
3676
|
const queryIndex = wsComponent.resourceName.indexOf("?");
|
|
3677
|
-
const
|
|
3678
|
-
wsComponent.path =
|
|
3677
|
+
const path8 = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
|
|
3678
|
+
wsComponent.path = path8 && path8 !== "/" ? path8 : void 0;
|
|
3679
3679
|
wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1);
|
|
3680
3680
|
wsComponent.resourceName = void 0;
|
|
3681
3681
|
}
|
|
@@ -4267,7 +4267,7 @@ var require_core = __commonJS({
|
|
|
4267
4267
|
var util_1 = require_util();
|
|
4268
4268
|
var $dataRefSchema = require_data();
|
|
4269
4269
|
var uri_1 = require_uri();
|
|
4270
|
-
var defaultRegExp = (
|
|
4270
|
+
var defaultRegExp = (str2, flags) => new RegExp(str2, flags);
|
|
4271
4271
|
defaultRegExp.code = "new RegExp";
|
|
4272
4272
|
var META_IGNORE_OPTIONS = ["removeAdditional", "useDefaults", "coerceTypes"];
|
|
4273
4273
|
var EXT_SCOPE_NAMES = /* @__PURE__ */ new Set([
|
|
@@ -5062,16 +5062,16 @@ var require_ucs2length = __commonJS({
|
|
|
5062
5062
|
"node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/runtime/ucs2length.js"(exports) {
|
|
5063
5063
|
"use strict";
|
|
5064
5064
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5065
|
-
function ucs2length(
|
|
5066
|
-
const len =
|
|
5065
|
+
function ucs2length(str2) {
|
|
5066
|
+
const len = str2.length;
|
|
5067
5067
|
let length = 0;
|
|
5068
5068
|
let pos = 0;
|
|
5069
5069
|
let value;
|
|
5070
5070
|
while (pos < len) {
|
|
5071
5071
|
length++;
|
|
5072
|
-
value =
|
|
5072
|
+
value = str2.charCodeAt(pos++);
|
|
5073
5073
|
if (value >= 55296 && value <= 56319 && pos < len) {
|
|
5074
|
-
value =
|
|
5074
|
+
value = str2.charCodeAt(pos);
|
|
5075
5075
|
if ((value & 64512) === 56320)
|
|
5076
5076
|
pos++;
|
|
5077
5077
|
}
|
|
@@ -6954,8 +6954,8 @@ var require_formats = __commonJS({
|
|
|
6954
6954
|
}
|
|
6955
6955
|
var DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
|
|
6956
6956
|
var DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
6957
|
-
function date3(
|
|
6958
|
-
const matches = DATE.exec(
|
|
6957
|
+
function date3(str2) {
|
|
6958
|
+
const matches = DATE.exec(str2);
|
|
6959
6959
|
if (!matches)
|
|
6960
6960
|
return false;
|
|
6961
6961
|
const year = +matches[1];
|
|
@@ -6974,8 +6974,8 @@ var require_formats = __commonJS({
|
|
|
6974
6974
|
}
|
|
6975
6975
|
var TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i;
|
|
6976
6976
|
function getTime(strictTimeZone) {
|
|
6977
|
-
return function time3(
|
|
6978
|
-
const matches = TIME.exec(
|
|
6977
|
+
return function time3(str2) {
|
|
6978
|
+
const matches = TIME.exec(str2);
|
|
6979
6979
|
if (!matches)
|
|
6980
6980
|
return false;
|
|
6981
6981
|
const hr = +matches[1];
|
|
@@ -7021,8 +7021,8 @@ var require_formats = __commonJS({
|
|
|
7021
7021
|
var DATE_TIME_SEPARATOR = /t|\s/i;
|
|
7022
7022
|
function getDateTime(strictTimeZone) {
|
|
7023
7023
|
const time3 = getTime(strictTimeZone);
|
|
7024
|
-
return function date_time(
|
|
7025
|
-
const dateTime =
|
|
7024
|
+
return function date_time(str2) {
|
|
7025
|
+
const dateTime = str2.split(DATE_TIME_SEPARATOR);
|
|
7026
7026
|
return dateTime.length === 2 && date3(dateTime[0]) && time3(dateTime[1]);
|
|
7027
7027
|
};
|
|
7028
7028
|
}
|
|
@@ -7047,13 +7047,13 @@ var require_formats = __commonJS({
|
|
|
7047
7047
|
}
|
|
7048
7048
|
var NOT_URI_FRAGMENT = /\/|:/;
|
|
7049
7049
|
var URI = /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
|
|
7050
|
-
function uri(
|
|
7051
|
-
return NOT_URI_FRAGMENT.test(
|
|
7050
|
+
function uri(str2) {
|
|
7051
|
+
return NOT_URI_FRAGMENT.test(str2) && URI.test(str2);
|
|
7052
7052
|
}
|
|
7053
7053
|
var BYTE = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/gm;
|
|
7054
|
-
function byte(
|
|
7054
|
+
function byte(str2) {
|
|
7055
7055
|
BYTE.lastIndex = 0;
|
|
7056
|
-
return BYTE.test(
|
|
7056
|
+
return BYTE.test(str2);
|
|
7057
7057
|
}
|
|
7058
7058
|
var MIN_INT32 = -(2 ** 31);
|
|
7059
7059
|
var MAX_INT32 = 2 ** 31 - 1;
|
|
@@ -7067,11 +7067,11 @@ var require_formats = __commonJS({
|
|
|
7067
7067
|
return true;
|
|
7068
7068
|
}
|
|
7069
7069
|
var Z_ANCHOR = /[^\\]\\Z/;
|
|
7070
|
-
function regex(
|
|
7071
|
-
if (Z_ANCHOR.test(
|
|
7070
|
+
function regex(str2) {
|
|
7071
|
+
if (Z_ANCHOR.test(str2))
|
|
7072
7072
|
return false;
|
|
7073
7073
|
try {
|
|
7074
|
-
new RegExp(
|
|
7074
|
+
new RegExp(str2);
|
|
7075
7075
|
return true;
|
|
7076
7076
|
} catch (e) {
|
|
7077
7077
|
return false;
|
|
@@ -7181,12 +7181,12 @@ var require_dist = __commonJS({
|
|
|
7181
7181
|
throw new Error(`Unknown format "${name}"`);
|
|
7182
7182
|
return f;
|
|
7183
7183
|
};
|
|
7184
|
-
function addFormats(ajv, list,
|
|
7184
|
+
function addFormats(ajv, list, fs8, exportName) {
|
|
7185
7185
|
var _a;
|
|
7186
7186
|
var _b;
|
|
7187
7187
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
7188
7188
|
for (const f of list)
|
|
7189
|
-
ajv.addFormat(f,
|
|
7189
|
+
ajv.addFormat(f, fs8[f]);
|
|
7190
7190
|
}
|
|
7191
7191
|
module.exports = exports = formatsPlugin;
|
|
7192
7192
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -7422,7 +7422,7 @@ var require_DOMException = __commonJS({
|
|
|
7422
7422
|
"INVALID_NODE_TYPE_ERR (24): the supplied node is invalid or has an invalid ancestor for this operation",
|
|
7423
7423
|
"DATA_CLONE_ERR (25): the object can not be cloned."
|
|
7424
7424
|
];
|
|
7425
|
-
var
|
|
7425
|
+
var constants5 = {
|
|
7426
7426
|
INDEX_SIZE_ERR,
|
|
7427
7427
|
DOMSTRING_SIZE_ERR: 2,
|
|
7428
7428
|
// historical
|
|
@@ -7461,8 +7461,8 @@ var require_DOMException = __commonJS({
|
|
|
7461
7461
|
this.name = names[code];
|
|
7462
7462
|
}
|
|
7463
7463
|
DOMException.prototype.__proto__ = Error.prototype;
|
|
7464
|
-
for (c in
|
|
7465
|
-
v = { value:
|
|
7464
|
+
for (c in constants5) {
|
|
7465
|
+
v = { value: constants5[c] };
|
|
7466
7466
|
Object.defineProperty(DOMException, c, v);
|
|
7467
7467
|
Object.defineProperty(DOMException.prototype, c, v);
|
|
7468
7468
|
}
|
|
@@ -9206,12 +9206,12 @@ var require_DOMTokenList = __commonJS({
|
|
|
9206
9206
|
if (strProp === clist._lastStringValue) {
|
|
9207
9207
|
return toArray(clist);
|
|
9208
9208
|
}
|
|
9209
|
-
var
|
|
9210
|
-
if (
|
|
9209
|
+
var str2 = strProp.replace(/(^[ \t\r\n\f]+)|([ \t\r\n\f]+$)/g, "");
|
|
9210
|
+
if (str2 === "") {
|
|
9211
9211
|
return [];
|
|
9212
9212
|
} else {
|
|
9213
9213
|
var seen = /* @__PURE__ */ Object.create(null);
|
|
9214
|
-
return
|
|
9214
|
+
return str2.split(/[ \t\r\n\f]+/g).filter(function(n) {
|
|
9215
9215
|
var key = "$" + n;
|
|
9216
9216
|
if (seen[key]) {
|
|
9217
9217
|
return false;
|
|
@@ -9266,16 +9266,16 @@ var require_select = __commonJS({
|
|
|
9266
9266
|
var nodeType = n.parentNode.nodeType;
|
|
9267
9267
|
return nodeType === 1 || nodeType === 9;
|
|
9268
9268
|
};
|
|
9269
|
-
var unquote = function(
|
|
9270
|
-
if (!
|
|
9271
|
-
var ch =
|
|
9269
|
+
var unquote = function(str2) {
|
|
9270
|
+
if (!str2) return str2;
|
|
9271
|
+
var ch = str2[0];
|
|
9272
9272
|
if (ch === '"' || ch === "'") {
|
|
9273
|
-
if (
|
|
9274
|
-
|
|
9273
|
+
if (str2[str2.length - 1] === ch) {
|
|
9274
|
+
str2 = str2.slice(1, -1);
|
|
9275
9275
|
} else {
|
|
9276
|
-
|
|
9276
|
+
str2 = str2.slice(1);
|
|
9277
9277
|
}
|
|
9278
|
-
return
|
|
9278
|
+
return str2.replace(rules.str_escape, function(s) {
|
|
9279
9279
|
var m = /^\\(?:([0-9A-Fa-f]+)|([\r\n\f]+))/.exec(s);
|
|
9280
9280
|
if (!m) {
|
|
9281
9281
|
return s.slice(1);
|
|
@@ -9289,14 +9289,14 @@ var require_select = __commonJS({
|
|
|
9289
9289
|
String.fromCharCode(cp)
|
|
9290
9290
|
);
|
|
9291
9291
|
});
|
|
9292
|
-
} else if (rules.ident.test(
|
|
9293
|
-
return decodeid(
|
|
9292
|
+
} else if (rules.ident.test(str2)) {
|
|
9293
|
+
return decodeid(str2);
|
|
9294
9294
|
} else {
|
|
9295
|
-
return
|
|
9295
|
+
return str2;
|
|
9296
9296
|
}
|
|
9297
9297
|
};
|
|
9298
|
-
var decodeid = function(
|
|
9299
|
-
return
|
|
9298
|
+
var decodeid = function(str2) {
|
|
9299
|
+
return str2.replace(rules.escape, function(s) {
|
|
9300
9300
|
var m = /^\\([0-9A-Fa-f]+)/.exec(s);
|
|
9301
9301
|
if (!m) {
|
|
9302
9302
|
return s[1];
|
|
@@ -12238,32 +12238,32 @@ var require_URL = __commonJS({
|
|
|
12238
12238
|
else
|
|
12239
12239
|
return basepath.substring(0, lastslash + 1) + refpath;
|
|
12240
12240
|
}
|
|
12241
|
-
function remove_dot_segments(
|
|
12242
|
-
if (!
|
|
12241
|
+
function remove_dot_segments(path8) {
|
|
12242
|
+
if (!path8) return path8;
|
|
12243
12243
|
var output = "";
|
|
12244
|
-
while (
|
|
12245
|
-
if (
|
|
12246
|
-
|
|
12244
|
+
while (path8.length > 0) {
|
|
12245
|
+
if (path8 === "." || path8 === "..") {
|
|
12246
|
+
path8 = "";
|
|
12247
12247
|
break;
|
|
12248
12248
|
}
|
|
12249
|
-
var twochars =
|
|
12250
|
-
var threechars =
|
|
12251
|
-
var fourchars =
|
|
12249
|
+
var twochars = path8.substring(0, 2);
|
|
12250
|
+
var threechars = path8.substring(0, 3);
|
|
12251
|
+
var fourchars = path8.substring(0, 4);
|
|
12252
12252
|
if (threechars === "../") {
|
|
12253
|
-
|
|
12253
|
+
path8 = path8.substring(3);
|
|
12254
12254
|
} else if (twochars === "./") {
|
|
12255
|
-
|
|
12255
|
+
path8 = path8.substring(2);
|
|
12256
12256
|
} else if (threechars === "/./") {
|
|
12257
|
-
|
|
12258
|
-
} else if (twochars === "/." &&
|
|
12259
|
-
|
|
12260
|
-
} else if (fourchars === "/../" || threechars === "/.." &&
|
|
12261
|
-
|
|
12257
|
+
path8 = "/" + path8.substring(3);
|
|
12258
|
+
} else if (twochars === "/." && path8.length === 2) {
|
|
12259
|
+
path8 = "/";
|
|
12260
|
+
} else if (fourchars === "/../" || threechars === "/.." && path8.length === 3) {
|
|
12261
|
+
path8 = "/" + path8.substring(4);
|
|
12262
12262
|
output = output.replace(/\/?[^\/]*$/, "");
|
|
12263
12263
|
} else {
|
|
12264
|
-
var segment =
|
|
12264
|
+
var segment = path8.match(/(\/?([^\/]*))/)[0];
|
|
12265
12265
|
output += segment;
|
|
12266
|
-
|
|
12266
|
+
path8 = path8.substring(segment.length);
|
|
12267
12267
|
}
|
|
12268
12268
|
}
|
|
12269
12269
|
return output;
|
|
@@ -24465,14 +24465,14 @@ var require_turndown_cjs = __commonJS({
|
|
|
24465
24465
|
} else if (node.nodeType === 1) {
|
|
24466
24466
|
replacement = replacementForNode.call(self, node);
|
|
24467
24467
|
}
|
|
24468
|
-
return
|
|
24468
|
+
return join19(output, replacement);
|
|
24469
24469
|
}, "");
|
|
24470
24470
|
}
|
|
24471
24471
|
function postProcess(output) {
|
|
24472
24472
|
var self = this;
|
|
24473
24473
|
this.rules.forEach(function(rule) {
|
|
24474
24474
|
if (typeof rule.append === "function") {
|
|
24475
|
-
output =
|
|
24475
|
+
output = join19(output, rule.append(self.options));
|
|
24476
24476
|
}
|
|
24477
24477
|
});
|
|
24478
24478
|
return output.replace(/^[\t\r\n]+/, "").replace(/[\t\r\n\s]+$/, "");
|
|
@@ -24484,7 +24484,7 @@ var require_turndown_cjs = __commonJS({
|
|
|
24484
24484
|
if (whitespace.leading || whitespace.trailing) content = content.trim();
|
|
24485
24485
|
return whitespace.leading + rule.replacement(content, node, this.options) + whitespace.trailing;
|
|
24486
24486
|
}
|
|
24487
|
-
function
|
|
24487
|
+
function join19(output, replacement) {
|
|
24488
24488
|
var s1 = trimTrailingNewlines(output);
|
|
24489
24489
|
var s2 = trimLeadingNewlines(replacement);
|
|
24490
24490
|
var nls = Math.max(output.length - s1.length, replacement.length - s2.length);
|
|
@@ -24979,8 +24979,8 @@ function getErrorMap() {
|
|
|
24979
24979
|
|
|
24980
24980
|
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
24981
24981
|
var makeIssue = (params) => {
|
|
24982
|
-
const { data, path:
|
|
24983
|
-
const fullPath = [...
|
|
24982
|
+
const { data, path: path8, errorMaps, issueData } = params;
|
|
24983
|
+
const fullPath = [...path8, ...issueData.path || []];
|
|
24984
24984
|
const fullIssue = {
|
|
24985
24985
|
...issueData,
|
|
24986
24986
|
path: fullPath
|
|
@@ -25096,11 +25096,11 @@ var errorUtil;
|
|
|
25096
25096
|
|
|
25097
25097
|
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
25098
25098
|
var ParseInputLazyPath = class {
|
|
25099
|
-
constructor(parent, value,
|
|
25099
|
+
constructor(parent, value, path8, key) {
|
|
25100
25100
|
this._cachedPath = [];
|
|
25101
25101
|
this.parent = parent;
|
|
25102
25102
|
this.data = value;
|
|
25103
|
-
this._path =
|
|
25103
|
+
this._path = path8;
|
|
25104
25104
|
this._key = key;
|
|
25105
25105
|
}
|
|
25106
25106
|
get path() {
|
|
@@ -28667,9 +28667,9 @@ function assertNever(_x) {
|
|
|
28667
28667
|
}
|
|
28668
28668
|
function assert(_) {
|
|
28669
28669
|
}
|
|
28670
|
-
function getEnumValues(
|
|
28671
|
-
const numericValues = Object.values(
|
|
28672
|
-
const values = Object.entries(
|
|
28670
|
+
function getEnumValues(entries2) {
|
|
28671
|
+
const numericValues = Object.values(entries2).filter((v) => typeof v === "number");
|
|
28672
|
+
const values = Object.entries(entries2).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
|
|
28673
28673
|
return values;
|
|
28674
28674
|
}
|
|
28675
28675
|
function joinValues(array2, separator = "|") {
|
|
@@ -28737,10 +28737,10 @@ function assignProp(target, prop, value) {
|
|
|
28737
28737
|
configurable: true
|
|
28738
28738
|
});
|
|
28739
28739
|
}
|
|
28740
|
-
function getElementAtPath(obj,
|
|
28741
|
-
if (!
|
|
28740
|
+
function getElementAtPath(obj, path8) {
|
|
28741
|
+
if (!path8)
|
|
28742
28742
|
return obj;
|
|
28743
|
-
return
|
|
28743
|
+
return path8.reduce((acc, key) => acc?.[key], obj);
|
|
28744
28744
|
}
|
|
28745
28745
|
function promiseAllObject(promisesObj) {
|
|
28746
28746
|
const keys = Object.keys(promisesObj);
|
|
@@ -28755,14 +28755,14 @@ function promiseAllObject(promisesObj) {
|
|
|
28755
28755
|
}
|
|
28756
28756
|
function randomString(length = 10) {
|
|
28757
28757
|
const chars = "abcdefghijklmnopqrstuvwxyz";
|
|
28758
|
-
let
|
|
28758
|
+
let str2 = "";
|
|
28759
28759
|
for (let i = 0; i < length; i++) {
|
|
28760
|
-
|
|
28760
|
+
str2 += chars[Math.floor(Math.random() * chars.length)];
|
|
28761
28761
|
}
|
|
28762
|
-
return
|
|
28762
|
+
return str2;
|
|
28763
28763
|
}
|
|
28764
|
-
function esc(
|
|
28765
|
-
return JSON.stringify(
|
|
28764
|
+
function esc(str2) {
|
|
28765
|
+
return JSON.stringify(str2);
|
|
28766
28766
|
}
|
|
28767
28767
|
var captureStackTrace = Error.captureStackTrace ? Error.captureStackTrace : (..._args) => {
|
|
28768
28768
|
};
|
|
@@ -28850,8 +28850,8 @@ var getParsedType2 = (data) => {
|
|
|
28850
28850
|
};
|
|
28851
28851
|
var propertyKeyTypes = /* @__PURE__ */ new Set(["string", "number", "symbol"]);
|
|
28852
28852
|
var primitiveTypes = /* @__PURE__ */ new Set(["string", "number", "bigint", "boolean", "symbol", "undefined"]);
|
|
28853
|
-
function escapeRegex(
|
|
28854
|
-
return
|
|
28853
|
+
function escapeRegex(str2) {
|
|
28854
|
+
return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
28855
28855
|
}
|
|
28856
28856
|
function clone(inst, def, params) {
|
|
28857
28857
|
const cl = new inst._zod.constr(def ?? inst._zod.def);
|
|
@@ -29060,11 +29060,11 @@ function aborted(x, startIndex = 0) {
|
|
|
29060
29060
|
}
|
|
29061
29061
|
return false;
|
|
29062
29062
|
}
|
|
29063
|
-
function prefixIssues(
|
|
29063
|
+
function prefixIssues(path8, issues) {
|
|
29064
29064
|
return issues.map((iss) => {
|
|
29065
29065
|
var _a;
|
|
29066
29066
|
(_a = iss).path ?? (_a.path = []);
|
|
29067
|
-
iss.path.unshift(
|
|
29067
|
+
iss.path.unshift(path8);
|
|
29068
29068
|
return iss;
|
|
29069
29069
|
});
|
|
29070
29070
|
}
|
|
@@ -32475,11 +32475,11 @@ function normalizeObjectSchema(schema) {
|
|
|
32475
32475
|
}
|
|
32476
32476
|
return void 0;
|
|
32477
32477
|
}
|
|
32478
|
-
function getDotPath(
|
|
32479
|
-
if (
|
|
32478
|
+
function getDotPath(path8) {
|
|
32479
|
+
if (path8.length === 0) {
|
|
32480
32480
|
return "object root";
|
|
32481
32481
|
}
|
|
32482
|
-
return
|
|
32482
|
+
return path8.reduce((acc, seg, index) => {
|
|
32483
32483
|
if (index === 0) {
|
|
32484
32484
|
return String(seg);
|
|
32485
32485
|
}
|
|
@@ -33039,10 +33039,10 @@ var ZodEnum2 = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
|
|
|
33039
33039
|
};
|
|
33040
33040
|
});
|
|
33041
33041
|
function _enum(values, params) {
|
|
33042
|
-
const
|
|
33042
|
+
const entries2 = Array.isArray(values) ? Object.fromEntries(values.map((v) => [v, v])) : values;
|
|
33043
33043
|
return new ZodEnum2({
|
|
33044
33044
|
type: "enum",
|
|
33045
|
-
entries,
|
|
33045
|
+
entries: entries2,
|
|
33046
33046
|
...util_exports.normalizeParams(params)
|
|
33047
33047
|
});
|
|
33048
33048
|
}
|
|
@@ -37774,12 +37774,12 @@ var UriTemplate = class _UriTemplate {
|
|
|
37774
37774
|
* A template expression is a sequence of characters enclosed in curly braces,
|
|
37775
37775
|
* like {foo} or {?bar}.
|
|
37776
37776
|
*/
|
|
37777
|
-
static isTemplate(
|
|
37778
|
-
return /\{[^}\s]+\}/.test(
|
|
37777
|
+
static isTemplate(str2) {
|
|
37778
|
+
return /\{[^}\s]+\}/.test(str2);
|
|
37779
37779
|
}
|
|
37780
|
-
static validateLength(
|
|
37781
|
-
if (
|
|
37782
|
-
throw new Error(`${context} exceeds maximum length of ${max} characters (got ${
|
|
37780
|
+
static validateLength(str2, max, context) {
|
|
37781
|
+
if (str2.length > max) {
|
|
37782
|
+
throw new Error(`${context} exceeds maximum length of ${max} characters (got ${str2.length})`);
|
|
37783
37783
|
}
|
|
37784
37784
|
}
|
|
37785
37785
|
get variableNames() {
|
|
@@ -37908,8 +37908,8 @@ var UriTemplate = class _UriTemplate {
|
|
|
37908
37908
|
}
|
|
37909
37909
|
return result;
|
|
37910
37910
|
}
|
|
37911
|
-
escapeRegExp(
|
|
37912
|
-
return
|
|
37911
|
+
escapeRegExp(str2) {
|
|
37912
|
+
return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
37913
37913
|
}
|
|
37914
37914
|
partToRegExp(part) {
|
|
37915
37915
|
const patterns = [];
|
|
@@ -39962,9 +39962,9 @@ var many = (f, n) => getFields(f, n).map((field) => {
|
|
|
39962
39962
|
});
|
|
39963
39963
|
function parseAudioRecording(data) {
|
|
39964
39964
|
const root = decode(data);
|
|
39965
|
-
const
|
|
39966
|
-
if (
|
|
39967
|
-
if (
|
|
39965
|
+
const entries2 = many(root, 3);
|
|
39966
|
+
if (entries2.length === 0) throw new Error("No mergeable objects");
|
|
39967
|
+
if (entries2.length > 2e6) throw new Error("Recording too large");
|
|
39968
39968
|
const keys = getFields(root, 4).map((f) => stringValue(f) ?? "");
|
|
39969
39969
|
const types = getFields(root, 5).map((f) => stringValue(f) ?? "");
|
|
39970
39970
|
const uuids = getFields(root, 6).map(
|
|
@@ -39975,7 +39975,7 @@ function parseAudioRecording(data) {
|
|
|
39975
39975
|
if (uuid2 && !uuidSlot.has(uuid2)) uuidSlot.set(uuid2, i);
|
|
39976
39976
|
});
|
|
39977
39977
|
const entry = (index) => {
|
|
39978
|
-
const value =
|
|
39978
|
+
const value = entries2[index];
|
|
39979
39979
|
if (!value) throw new Error("Invalid object reference");
|
|
39980
39980
|
return value;
|
|
39981
39981
|
};
|
|
@@ -40017,7 +40017,7 @@ function parseAudioRecording(data) {
|
|
|
40017
40017
|
const text = note && stringValue(getField(note, 2));
|
|
40018
40018
|
return text?.replace(/\n+$/u, "") || void 0;
|
|
40019
40019
|
};
|
|
40020
|
-
const recordings =
|
|
40020
|
+
const recordings = entries2.map((e) => customMap(e)).filter((m) => m?.type === "com.apple.notes.ICTTAudioRecording");
|
|
40021
40021
|
if (recordings.length !== 1) throw new Error("Expected exactly one audio recording object");
|
|
40022
40022
|
const recording = recordings[0];
|
|
40023
40023
|
const fragments = [];
|
|
@@ -40322,15 +40322,15 @@ function parseNoteTableCells(compressed) {
|
|
|
40322
40322
|
}
|
|
40323
40323
|
function decodeTable(compressed, strict) {
|
|
40324
40324
|
const root = decodeMessage(gunzipSync4(compressed, { maxOutputLength: 16 * 1024 * 1024 }));
|
|
40325
|
-
const data = sub2(sub2(root, 2), 3),
|
|
40326
|
-
if (
|
|
40325
|
+
const data = sub2(sub2(root, 2), 3), entries2 = many2(data, 3);
|
|
40326
|
+
if (entries2.length > 1e5) throw new Error("Table too large");
|
|
40327
40327
|
const keys = getFields(data, 4).map(stringValue), types = getFields(data, 5).map(stringValue), uuids = getFields(data, 6).map(hex);
|
|
40328
40328
|
const entry = (index) => {
|
|
40329
|
-
if (!
|
|
40330
|
-
return
|
|
40329
|
+
if (!entries2[index]) throw new Error("Invalid table reference");
|
|
40330
|
+
return entries2[index];
|
|
40331
40331
|
};
|
|
40332
40332
|
const uuidIndex = (index) => num(sub2(many2(sub2(entry(index), 13), 3)[0], 2), 2);
|
|
40333
|
-
const roots =
|
|
40333
|
+
const roots = entries2.filter((e) => {
|
|
40334
40334
|
const map = embeddedMessage(getField(e, 13));
|
|
40335
40335
|
return map && types[num(map, 1)] === "com.apple.notes.ICTable";
|
|
40336
40336
|
});
|
|
@@ -40392,7 +40392,7 @@ function decodeTable(compressed, strict) {
|
|
|
40392
40392
|
values[ri][ci] = text.replace(/\n$/u, "");
|
|
40393
40393
|
}
|
|
40394
40394
|
}
|
|
40395
|
-
const rtl =
|
|
40395
|
+
const rtl = entries2.some((e) => {
|
|
40396
40396
|
const map = embeddedMessage(getField(e, 13));
|
|
40397
40397
|
return map && many2(map, 3).some(
|
|
40398
40398
|
(m) => stringValue(getField(sub2(m, 2), 4)) === "CRTableColumnDirectionRightToLeft"
|
|
@@ -40582,7 +40582,7 @@ var Decoder = class {
|
|
|
40582
40582
|
* positively and negated by the caller.
|
|
40583
40583
|
*/
|
|
40584
40584
|
leaf(key, value, excluded) {
|
|
40585
|
-
const
|
|
40585
|
+
const flag2 = (description, negative) => typeof value === "boolean" ? {
|
|
40586
40586
|
type: key,
|
|
40587
40587
|
value,
|
|
40588
40588
|
...excluded ? { excluded: true } : {},
|
|
@@ -40590,25 +40590,25 @@ var Decoder = class {
|
|
|
40590
40590
|
} : null;
|
|
40591
40591
|
switch (key) {
|
|
40592
40592
|
case "checklist":
|
|
40593
|
-
return
|
|
40593
|
+
return flag2("has a checklist", "has no checklist");
|
|
40594
40594
|
case "checklistInProgress":
|
|
40595
|
-
return
|
|
40595
|
+
return flag2("has an unfinished checklist", "has no unfinished checklist");
|
|
40596
40596
|
case "checklistCompleted":
|
|
40597
|
-
return
|
|
40597
|
+
return flag2("has a completed checklist", "has no completed checklist");
|
|
40598
40598
|
case "attachment":
|
|
40599
|
-
return
|
|
40599
|
+
return flag2("has attachments", "has no attachments");
|
|
40600
40600
|
case "pinned":
|
|
40601
|
-
return
|
|
40601
|
+
return flag2("is pinned", "is not pinned");
|
|
40602
40602
|
case "systemPaper":
|
|
40603
|
-
return
|
|
40603
|
+
return flag2("is a Quick Note", "is not a Quick Note");
|
|
40604
40604
|
case "passwordProtected":
|
|
40605
|
-
return
|
|
40605
|
+
return flag2("is locked", "is not locked");
|
|
40606
40606
|
case "shared":
|
|
40607
|
-
return
|
|
40607
|
+
return flag2("is shared", "is not shared");
|
|
40608
40608
|
case "mention":
|
|
40609
|
-
return
|
|
40609
|
+
return flag2("mentions anyone", "mentions no one");
|
|
40610
40610
|
case "tagged":
|
|
40611
|
-
return
|
|
40611
|
+
return flag2("has any tag", "has no tags");
|
|
40612
40612
|
case "attachmentSection": {
|
|
40613
40613
|
if (typeof value !== "number" || !ATTACHMENT_SECTIONS[value]) return null;
|
|
40614
40614
|
return {
|
|
@@ -40784,7 +40784,7 @@ function buildSmartFolders(output) {
|
|
|
40784
40784
|
if (lines.length < 4) throw new Error("Unexpected smart folder query output");
|
|
40785
40785
|
const [storeUuid, rowsJson, foldersJson, tagsJson] = lines;
|
|
40786
40786
|
if (!/^[0-9A-F-]+$/i.test(storeUuid)) throw new Error("Unexpected Notes store identifier");
|
|
40787
|
-
const coreDataId2 = (
|
|
40787
|
+
const coreDataId2 = (entity3, pk) => `x-coredata://${storeUuid}/${entity3}/p${pk}`;
|
|
40788
40788
|
const rows = JSON.parse(rowsJson);
|
|
40789
40789
|
const folderRows = JSON.parse(foldersJson || "{}");
|
|
40790
40790
|
const tagRows = JSON.parse(tagsJson || "[]");
|
|
@@ -40881,8 +40881,8 @@ function allowedSaveRoots() {
|
|
|
40881
40881
|
"/private/tmp"
|
|
40882
40882
|
];
|
|
40883
40883
|
}
|
|
40884
|
-
function canonicalize(
|
|
40885
|
-
return realpathSync.native(
|
|
40884
|
+
function canonicalize(path8) {
|
|
40885
|
+
return realpathSync.native(path8);
|
|
40886
40886
|
}
|
|
40887
40887
|
function isWithinRoots(candidate, roots) {
|
|
40888
40888
|
return roots.some((root) => {
|
|
@@ -40904,9 +40904,9 @@ function canonicalRoots(roots) {
|
|
|
40904
40904
|
}
|
|
40905
40905
|
return canonical;
|
|
40906
40906
|
}
|
|
40907
|
-
function entryExists(
|
|
40907
|
+
function entryExists(path8) {
|
|
40908
40908
|
try {
|
|
40909
|
-
lstatSync(
|
|
40909
|
+
lstatSync(path8);
|
|
40910
40910
|
return true;
|
|
40911
40911
|
} catch (e) {
|
|
40912
40912
|
const code = e.code;
|
|
@@ -41036,6 +41036,22 @@ function cleanupTempDir(dir) {
|
|
|
41036
41036
|
}
|
|
41037
41037
|
}
|
|
41038
41038
|
|
|
41039
|
+
// src/utils/paperAttachments.ts
|
|
41040
|
+
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
41041
|
+
import {
|
|
41042
|
+
closeSync as closeSync3,
|
|
41043
|
+
constants as constants3,
|
|
41044
|
+
fstatSync as fstatSync3,
|
|
41045
|
+
lstatSync as lstatSync3,
|
|
41046
|
+
mkdirSync as mkdirSync3,
|
|
41047
|
+
openSync as openSync3,
|
|
41048
|
+
readdirSync as readdirSync2,
|
|
41049
|
+
readSync as readSync2,
|
|
41050
|
+
unlinkSync as unlinkSync2,
|
|
41051
|
+
writeSync as writeSync2
|
|
41052
|
+
} from "node:fs";
|
|
41053
|
+
import { basename as basename2, dirname as dirname3, extname as extname2, join as join7 } from "node:path";
|
|
41054
|
+
|
|
41039
41055
|
// src/utils/attachmentAssets.ts
|
|
41040
41056
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
41041
41057
|
import {
|
|
@@ -41120,7 +41136,7 @@ function attachmentCoreDataId(noteId3, pk) {
|
|
|
41120
41136
|
}
|
|
41121
41137
|
function buildAttachmentRowsSql(notePk, columns) {
|
|
41122
41138
|
if (!Number.isSafeInteger(notePk) || notePk < 0) throw new Error("Invalid note primary key");
|
|
41123
|
-
const
|
|
41139
|
+
const col3 = (alias, name) => columns.has(name) ? `${alias}.${name}` : "NULL";
|
|
41124
41140
|
const firstOf = (alias, names) => {
|
|
41125
41141
|
const present = names.filter((n) => columns.has(n)).map((n) => `${alias}.${n}`);
|
|
41126
41142
|
if (present.length === 0) return "NULL";
|
|
@@ -41133,19 +41149,19 @@ function buildAttachmentRowsSql(notePk, columns) {
|
|
|
41133
41149
|
].join(", ");
|
|
41134
41150
|
const account = accountCols.length ? `(SELECT acc.ZIDENTIFIER FROM ZICCLOUDSYNCINGOBJECT acc WHERE acc.Z_ENT = (SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = 'ICAccount') AND acc.Z_PK IN (${accountRefs}) LIMIT 1)` : "NULL";
|
|
41135
41151
|
const noteLink = columns.has("ZNOTE") ? "a.ZNOTE" : "NULL";
|
|
41136
|
-
const parent =
|
|
41152
|
+
const parent = col3("a", "ZPARENTATTACHMENT");
|
|
41137
41153
|
const deleted = columns.has("ZMARKEDFORDELETION") ? " AND COALESCE(a.ZMARKEDFORDELETION, 0) = 0" : "";
|
|
41138
41154
|
const fields = [
|
|
41139
41155
|
`'pk', a.Z_PK`,
|
|
41140
41156
|
`'identifier', a.ZIDENTIFIER`,
|
|
41141
|
-
`'uti', ${
|
|
41157
|
+
`'uti', ${col3("a", "ZTYPEUTI")}`,
|
|
41142
41158
|
`'parentPk', ${parent}`,
|
|
41143
|
-
`'filename', ${
|
|
41159
|
+
`'filename', ${col3("a", "ZFILENAME")}`,
|
|
41144
41160
|
`'mediaIdentifier', m.ZIDENTIFIER`,
|
|
41145
|
-
`'mediaFilename', ${
|
|
41161
|
+
`'mediaFilename', ${col3("m", "ZFILENAME")}`,
|
|
41146
41162
|
`'mediaGeneration', ${firstOf("m", ["ZGENERATION1", "ZGENERATION"])}`,
|
|
41147
|
-
`'fallbackImageGeneration', ${
|
|
41148
|
-
`'fallbackPdfGeneration', ${
|
|
41163
|
+
`'fallbackImageGeneration', ${col3("a", "ZFALLBACKIMAGEGENERATION")}`,
|
|
41164
|
+
`'fallbackPdfGeneration', ${col3("a", "ZFALLBACKPDFGENERATION")}`,
|
|
41149
41165
|
`'accountIdentifier', ${account}`
|
|
41150
41166
|
].join(", ");
|
|
41151
41167
|
const mediaJoin = columns.has("ZMEDIA") ? "LEFT JOIN ZICCLOUDSYNCINGOBJECT m ON m.Z_PK = a.ZMEDIA" : "LEFT JOIN ZICCLOUDSYNCINGOBJECT m ON 0";
|
|
@@ -41258,32 +41274,32 @@ function safeComponent(value) {
|
|
|
41258
41274
|
if (value === "." || value === ".." || value.includes("/") || value.includes("\0")) return null;
|
|
41259
41275
|
return value;
|
|
41260
41276
|
}
|
|
41261
|
-
function realInside(
|
|
41277
|
+
function realInside(path8, rootReal) {
|
|
41262
41278
|
try {
|
|
41263
|
-
const real = realpathSync2.native(
|
|
41279
|
+
const real = realpathSync2.native(path8);
|
|
41264
41280
|
return real === rootReal || real.startsWith(rootReal + sep2) ? real : null;
|
|
41265
41281
|
} catch {
|
|
41266
41282
|
return null;
|
|
41267
41283
|
}
|
|
41268
41284
|
}
|
|
41269
|
-
function isRegularFile(
|
|
41285
|
+
function isRegularFile(path8) {
|
|
41270
41286
|
try {
|
|
41271
|
-
return lstatSync2(
|
|
41287
|
+
return lstatSync2(path8).isFile();
|
|
41272
41288
|
} catch {
|
|
41273
41289
|
return false;
|
|
41274
41290
|
}
|
|
41275
41291
|
}
|
|
41276
|
-
function isDirectory(
|
|
41292
|
+
function isDirectory(path8) {
|
|
41277
41293
|
try {
|
|
41278
|
-
return lstatSync2(
|
|
41294
|
+
return lstatSync2(path8).isDirectory();
|
|
41279
41295
|
} catch {
|
|
41280
41296
|
return false;
|
|
41281
41297
|
}
|
|
41282
41298
|
}
|
|
41283
41299
|
function boundedEntries(dir, limit) {
|
|
41284
41300
|
try {
|
|
41285
|
-
const
|
|
41286
|
-
return
|
|
41301
|
+
const entries2 = readdirSync(dir);
|
|
41302
|
+
return entries2.length > limit ? null : entries2.sort();
|
|
41287
41303
|
} catch {
|
|
41288
41304
|
return null;
|
|
41289
41305
|
}
|
|
@@ -41301,19 +41317,19 @@ function resolveAccountDir(containerDir, accountIdentifier) {
|
|
|
41301
41317
|
const dir = realInside(join6(accountsReal, account), accountsReal);
|
|
41302
41318
|
if (dir && isDirectory(dir)) return dir;
|
|
41303
41319
|
}
|
|
41304
|
-
const
|
|
41320
|
+
const entries2 = (boundedEntries(accountsReal, 64) ?? []).filter(
|
|
41305
41321
|
(e) => isDirectory(join6(accountsReal, e))
|
|
41306
41322
|
);
|
|
41307
|
-
if (
|
|
41308
|
-
return realInside(join6(accountsReal,
|
|
41323
|
+
if (entries2.length !== 1) return null;
|
|
41324
|
+
return realInside(join6(accountsReal, entries2[0]), accountsReal);
|
|
41309
41325
|
}
|
|
41310
41326
|
function generationRank(name) {
|
|
41311
41327
|
const m = /^(\d+)_/.exec(name);
|
|
41312
41328
|
return m ? Number(m[1]) : 0;
|
|
41313
41329
|
}
|
|
41314
41330
|
function generationDirs(base, accountDir) {
|
|
41315
|
-
const
|
|
41316
|
-
return
|
|
41331
|
+
const entries2 = boundedEntries(base, MAX_GENERATION_DIRS) ?? [];
|
|
41332
|
+
return entries2.map((e) => realInside(join6(base, e), accountDir)).filter((p) => p !== null && isDirectory(p)).sort((a, b) => generationRank(basename(b)) - generationRank(basename(a)));
|
|
41317
41333
|
}
|
|
41318
41334
|
function fallbackFiles(accountDir, rootName, identifier, generation, names) {
|
|
41319
41335
|
const base = join6(accountDir, rootName, identifier);
|
|
@@ -41358,11 +41374,11 @@ function previewFileInBundle(bundle, accountDir) {
|
|
|
41358
41374
|
function listPreviewEntries(accountDir) {
|
|
41359
41375
|
return boundedEntries(join6(accountDir, "Previews"), MAX_PREVIEW_DIR_ENTRIES) ?? [];
|
|
41360
41376
|
}
|
|
41361
|
-
function previewPaths(accountDir, identifier,
|
|
41377
|
+
function previewPaths(accountDir, identifier, entries2) {
|
|
41362
41378
|
const id2 = safeComponent(identifier);
|
|
41363
41379
|
if (!id2) return [];
|
|
41364
41380
|
const prefix = `${id2}-`.toLowerCase();
|
|
41365
|
-
const candidates =
|
|
41381
|
+
const candidates = entries2.filter((name) => name.toLowerCase().startsWith(prefix)).filter((name) => {
|
|
41366
41382
|
const ext = extname(name).toLowerCase();
|
|
41367
41383
|
return !ext || PREVIEW_IMAGE_SUFFIXES.has(ext) || /^\.\d+$/.test(ext);
|
|
41368
41384
|
}).sort((a, b) => previewPixelArea(b) - previewPixelArea(a) || a.localeCompare(b));
|
|
@@ -41611,11 +41627,348 @@ function exportAttachmentAssets(assets, exportDir, options = {}) {
|
|
|
41611
41627
|
return { exportDir: dir, results };
|
|
41612
41628
|
}
|
|
41613
41629
|
|
|
41630
|
+
// src/utils/paperAttachments.ts
|
|
41631
|
+
var MAX_AXIS = 32768;
|
|
41632
|
+
var MAX_PREVIEW_DIR_ENTRIES2 = 1e5;
|
|
41633
|
+
var MAX_DIR_ENTRIES = 64;
|
|
41634
|
+
var HEADER_BYTES = 64 * 1024;
|
|
41635
|
+
var PNG_MAGIC = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
|
|
41636
|
+
var IMAGE_SUFFIXES = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg"]);
|
|
41637
|
+
var axisOk = (n) => Number.isInteger(n) && n > 0 && n <= MAX_AXIS;
|
|
41638
|
+
function parseImageHeader(buf) {
|
|
41639
|
+
if (buf.length >= 24 && buf.subarray(0, 8).equals(PNG_MAGIC)) {
|
|
41640
|
+
if (buf.readUInt32BE(8) !== 13 || buf.toString("latin1", 12, 16) !== "IHDR") return null;
|
|
41641
|
+
const width = buf.readUInt32BE(16);
|
|
41642
|
+
const height = buf.readUInt32BE(20);
|
|
41643
|
+
return axisOk(width) && axisOk(height) ? { format: "png", width, height } : null;
|
|
41644
|
+
}
|
|
41645
|
+
if (buf.length >= 4 && buf[0] === 255 && buf[1] === 216 && buf[2] === 255) {
|
|
41646
|
+
let offset = 2;
|
|
41647
|
+
while (offset + 4 <= buf.length) {
|
|
41648
|
+
if (buf[offset] !== 255) return null;
|
|
41649
|
+
const marker = buf[offset + 1];
|
|
41650
|
+
if (marker === 255) {
|
|
41651
|
+
offset++;
|
|
41652
|
+
continue;
|
|
41653
|
+
}
|
|
41654
|
+
const length = buf.readUInt16BE(offset + 2);
|
|
41655
|
+
if (length < 2) return null;
|
|
41656
|
+
const isFrame = marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204;
|
|
41657
|
+
if (isFrame) {
|
|
41658
|
+
if (offset + 9 > buf.length) return null;
|
|
41659
|
+
const height = buf.readUInt16BE(offset + 5);
|
|
41660
|
+
const width = buf.readUInt16BE(offset + 7);
|
|
41661
|
+
return axisOk(width) && axisOk(height) ? { format: "jpeg", width, height } : null;
|
|
41662
|
+
}
|
|
41663
|
+
offset += 2 + length;
|
|
41664
|
+
}
|
|
41665
|
+
}
|
|
41666
|
+
return null;
|
|
41667
|
+
}
|
|
41668
|
+
function readImageInfoFd(fd) {
|
|
41669
|
+
if (!fstatSync3(fd).isFile()) return null;
|
|
41670
|
+
const buf = Buffer.alloc(HEADER_BYTES);
|
|
41671
|
+
const read = readSync2(fd, buf, 0, buf.length, 0);
|
|
41672
|
+
return parseImageHeader(buf.subarray(0, read));
|
|
41673
|
+
}
|
|
41674
|
+
function readImageInfo(path8) {
|
|
41675
|
+
let fd;
|
|
41676
|
+
try {
|
|
41677
|
+
fd = openSync3(path8, constants3.O_RDONLY | constants3.O_NOFOLLOW);
|
|
41678
|
+
} catch {
|
|
41679
|
+
return null;
|
|
41680
|
+
}
|
|
41681
|
+
try {
|
|
41682
|
+
return readImageInfoFd(fd);
|
|
41683
|
+
} finally {
|
|
41684
|
+
closeSync3(fd);
|
|
41685
|
+
}
|
|
41686
|
+
}
|
|
41687
|
+
function buildDrawingRowsSql(notePk, columns) {
|
|
41688
|
+
if (!Number.isSafeInteger(notePk) || notePk < 0) throw new Error("Invalid note primary key");
|
|
41689
|
+
const col3 = (name) => columns.has(name) ? `a.${name}` : "NULL";
|
|
41690
|
+
const accountCols = [...columns].filter((c) => /^ZACCOUNT\d*$/.test(c)).sort();
|
|
41691
|
+
const account = accountCols.length ? `(SELECT acc.ZIDENTIFIER FROM ZICCLOUDSYNCINGOBJECT acc WHERE acc.Z_ENT = (SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = 'ICAccount') AND acc.Z_PK IN (${[
|
|
41692
|
+
...accountCols.map((c) => `a.${c}`),
|
|
41693
|
+
...accountCols.map((c) => `n.${c}`)
|
|
41694
|
+
].join(", ")}) LIMIT 1)` : "NULL";
|
|
41695
|
+
const deleted = columns.has("ZMARKEDFORDELETION") ? " AND COALESCE(a.ZMARKEDFORDELETION, 0) = 0" : "";
|
|
41696
|
+
const fields = [
|
|
41697
|
+
`'pk', a.Z_PK`,
|
|
41698
|
+
`'identifier', a.ZIDENTIFIER`,
|
|
41699
|
+
`'uti', a.ZTYPEUTI`,
|
|
41700
|
+
`'handwritingSummary', ${col3("ZHANDWRITINGSUMMARY")}`,
|
|
41701
|
+
`'fallbackImageGeneration', ${col3("ZFALLBACKIMAGEGENERATION")}`,
|
|
41702
|
+
`'accountIdentifier', ${account}`
|
|
41703
|
+
].join(", ");
|
|
41704
|
+
return [
|
|
41705
|
+
"BEGIN;",
|
|
41706
|
+
`SELECT count(*) FROM ZICCLOUDSYNCINGOBJECT WHERE Z_PK = ${notePk} AND Z_ENT = (SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = 'ICNote');`,
|
|
41707
|
+
`SELECT json_group_array(json_object(${fields})) FROM ZICCLOUDSYNCINGOBJECT a LEFT JOIN ZICCLOUDSYNCINGOBJECT n ON n.Z_PK = a.ZNOTE WHERE a.Z_ENT = (SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = 'ICAttachment') AND a.ZNOTE = ${notePk} AND (a.ZTYPEUTI = 'com.apple.paper' OR a.ZTYPEUTI = 'com.apple.drawing' OR a.ZTYPEUTI LIKE 'com.apple.drawing.%')${deleted};`,
|
|
41708
|
+
"COMMIT;"
|
|
41709
|
+
].join(" ");
|
|
41710
|
+
}
|
|
41711
|
+
function runSqlite4(dbPath2, sql) {
|
|
41712
|
+
try {
|
|
41713
|
+
return execFileSync7("/usr/bin/sqlite3", ["-readonly", dbPath2, sql], {
|
|
41714
|
+
encoding: "utf8",
|
|
41715
|
+
timeout: 1e4,
|
|
41716
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
41717
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
41718
|
+
});
|
|
41719
|
+
} catch (error2) {
|
|
41720
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
41721
|
+
if (/authorization denied|unable to open database/i.test(message)) {
|
|
41722
|
+
throw new AttachmentStoreError(
|
|
41723
|
+
"Full Disk Access is required to read drawing attachments. Grant it to the app that launches this server, then relaunch it (run the doctor tool to verify).",
|
|
41724
|
+
"no_fda"
|
|
41725
|
+
);
|
|
41726
|
+
}
|
|
41727
|
+
throw new AttachmentStoreError(`Failed to read drawing attachments: ${message}`, "query_error");
|
|
41728
|
+
}
|
|
41729
|
+
}
|
|
41730
|
+
var str = (v) => typeof v === "string" && v.length > 0 ? v : null;
|
|
41731
|
+
function parseDrawingRows(json2) {
|
|
41732
|
+
const raw = JSON.parse(json2 || "[]");
|
|
41733
|
+
if (!Array.isArray(raw)) throw new Error("Invalid drawing rows");
|
|
41734
|
+
const rows = [];
|
|
41735
|
+
for (const item of raw) {
|
|
41736
|
+
if (!item || typeof item !== "object") continue;
|
|
41737
|
+
const r = item;
|
|
41738
|
+
const identifier = str(r.identifier);
|
|
41739
|
+
const uti = str(r.uti);
|
|
41740
|
+
if (!Number.isSafeInteger(r.pk) || !identifier || !uti) continue;
|
|
41741
|
+
const summary = str(r.handwritingSummary);
|
|
41742
|
+
rows.push({
|
|
41743
|
+
pk: r.pk,
|
|
41744
|
+
identifier,
|
|
41745
|
+
uti,
|
|
41746
|
+
handwritingSummary: summary && summary.trim() ? summary : null,
|
|
41747
|
+
fallbackImageGeneration: str(r.fallbackImageGeneration),
|
|
41748
|
+
accountIdentifier: str(r.accountIdentifier)
|
|
41749
|
+
});
|
|
41750
|
+
}
|
|
41751
|
+
return rows.sort((a, b) => a.pk - b.pk);
|
|
41752
|
+
}
|
|
41753
|
+
function readDrawingRows(noteId3, dbPath2 = join7(NOTES_CONTAINER_DIR, "NoteStore.sqlite")) {
|
|
41754
|
+
const { pk } = parseNoteId2(noteId3);
|
|
41755
|
+
const columns = new Set(
|
|
41756
|
+
runSqlite4(
|
|
41757
|
+
dbPath2,
|
|
41758
|
+
"SELECT group_concat(name, ',') FROM pragma_table_info('ZICCLOUDSYNCINGOBJECT');"
|
|
41759
|
+
).trim().split(",").filter(Boolean)
|
|
41760
|
+
);
|
|
41761
|
+
if (!columns.has("ZIDENTIFIER") || !columns.has("ZTYPEUTI") || !columns.has("ZNOTE")) {
|
|
41762
|
+
throw new AttachmentStoreError("Unsupported Notes database schema", "query_error");
|
|
41763
|
+
}
|
|
41764
|
+
const lines = runSqlite4(dbPath2, buildDrawingRowsSql(pk, columns)).split("\n");
|
|
41765
|
+
if (lines[0]?.trim() !== "1") {
|
|
41766
|
+
throw new AttachmentStoreError(
|
|
41767
|
+
`No note found in the database for ID "${noteId3}".`,
|
|
41768
|
+
"not_found"
|
|
41769
|
+
);
|
|
41770
|
+
}
|
|
41771
|
+
try {
|
|
41772
|
+
return parseDrawingRows(lines[1] ?? "[]");
|
|
41773
|
+
} catch {
|
|
41774
|
+
throw new AttachmentStoreError("Drawing rows could not be parsed", "query_error");
|
|
41775
|
+
}
|
|
41776
|
+
}
|
|
41777
|
+
function kindOf(path8) {
|
|
41778
|
+
try {
|
|
41779
|
+
const st = lstatSync3(path8);
|
|
41780
|
+
return st.isFile() ? "file" : st.isDirectory() ? "dir" : null;
|
|
41781
|
+
} catch {
|
|
41782
|
+
return null;
|
|
41783
|
+
}
|
|
41784
|
+
}
|
|
41785
|
+
function entries(dir, limit) {
|
|
41786
|
+
try {
|
|
41787
|
+
const list = readdirSync2(dir);
|
|
41788
|
+
return list.length > limit ? [] : list.sort();
|
|
41789
|
+
} catch {
|
|
41790
|
+
return [];
|
|
41791
|
+
}
|
|
41792
|
+
}
|
|
41793
|
+
var byGenerationDesc = (a, b) => generationRank(basename2(b)) - generationRank(basename2(a));
|
|
41794
|
+
function findFallbackImage(accountDir, identifier, generation) {
|
|
41795
|
+
const id2 = safeComponent(identifier);
|
|
41796
|
+
if (!id2) return null;
|
|
41797
|
+
const base = join7(accountDir, "FallbackImages", id2);
|
|
41798
|
+
const names = ["FallbackImage.png", "FallbackImage.jpg"];
|
|
41799
|
+
const candidates = [];
|
|
41800
|
+
const gen = safeComponent(generation);
|
|
41801
|
+
if (gen) for (const n of names) candidates.push(join7(base, gen, n));
|
|
41802
|
+
const gens = entries(base, MAX_DIR_ENTRIES).map((e) => join7(base, e)).sort(byGenerationDesc);
|
|
41803
|
+
for (const g of gens) for (const n of names) candidates.push(join7(g, n));
|
|
41804
|
+
for (const n of names) candidates.push(join7(base, n));
|
|
41805
|
+
candidates.push(join7(accountDir, "FallbackImages", `${id2}.png`));
|
|
41806
|
+
candidates.push(join7(accountDir, "FallbackImages", `${id2}.jpg`));
|
|
41807
|
+
for (const c of candidates) {
|
|
41808
|
+
const real = realInside(c, accountDir);
|
|
41809
|
+
if (real && kindOf(real) === "file") return real;
|
|
41810
|
+
}
|
|
41811
|
+
return null;
|
|
41812
|
+
}
|
|
41813
|
+
function findLargestPreview(accountDir, identifier) {
|
|
41814
|
+
const id2 = safeComponent(identifier);
|
|
41815
|
+
if (!id2) return null;
|
|
41816
|
+
const dir = join7(accountDir, "Previews");
|
|
41817
|
+
const prefix = `${id2}-`.toLowerCase();
|
|
41818
|
+
const names = entries(dir, MAX_PREVIEW_DIR_ENTRIES2).filter((n) => n.toLowerCase().startsWith(prefix)).filter((n) => {
|
|
41819
|
+
const ext = extname2(n).toLowerCase();
|
|
41820
|
+
return !ext || IMAGE_SUFFIXES.has(ext) || /^\.\d+$/.test(ext);
|
|
41821
|
+
}).sort((a, b) => previewPixelArea(b) - previewPixelArea(a) || a.localeCompare(b));
|
|
41822
|
+
for (const name of names) {
|
|
41823
|
+
const real = realInside(join7(dir, name), accountDir);
|
|
41824
|
+
if (!real) continue;
|
|
41825
|
+
const kind = kindOf(real);
|
|
41826
|
+
if (kind === "file") return real;
|
|
41827
|
+
if (kind !== "dir") continue;
|
|
41828
|
+
const gens = entries(real, MAX_DIR_ENTRIES).map((e) => realInside(join7(real, e), accountDir)).filter((p) => p !== null && kindOf(p) === "dir").sort(byGenerationDesc);
|
|
41829
|
+
for (const g of [...gens, real]) {
|
|
41830
|
+
const file = realInside(join7(g, "Preview.png"), accountDir);
|
|
41831
|
+
if (file && kindOf(file) === "file") return file;
|
|
41832
|
+
}
|
|
41833
|
+
}
|
|
41834
|
+
return null;
|
|
41835
|
+
}
|
|
41836
|
+
function describeDrawings(rows, containerDir = NOTES_CONTAINER_DIR) {
|
|
41837
|
+
return rows.map((row) => {
|
|
41838
|
+
const accountDir = resolveAccountDir(containerDir, row.accountIdentifier);
|
|
41839
|
+
const kind = row.uti === "com.apple.paper" ? "paper" : "drawing";
|
|
41840
|
+
const id2 = safeComponent(row.identifier);
|
|
41841
|
+
const fallbackImagePath = accountDir ? findFallbackImage(accountDir, row.identifier, row.fallbackImageGeneration) : null;
|
|
41842
|
+
const previewPath = accountDir ? findLargestPreview(accountDir, row.identifier) : null;
|
|
41843
|
+
const bundle = accountDir && id2 && kind === "paper" ? realInside(join7(accountDir, "Paper", "Bundles", `${id2}.bundle`), accountDir) : null;
|
|
41844
|
+
let raster = null;
|
|
41845
|
+
for (const [path8, source] of [
|
|
41846
|
+
[fallbackImagePath, "fallback"],
|
|
41847
|
+
[previewPath, "preview"]
|
|
41848
|
+
]) {
|
|
41849
|
+
const info = path8 ? readImageInfo(path8) : null;
|
|
41850
|
+
if (path8 && info) {
|
|
41851
|
+
raster = { path: path8, source, ...info };
|
|
41852
|
+
break;
|
|
41853
|
+
}
|
|
41854
|
+
}
|
|
41855
|
+
return {
|
|
41856
|
+
pk: row.pk,
|
|
41857
|
+
identifier: row.identifier,
|
|
41858
|
+
uti: row.uti,
|
|
41859
|
+
kind,
|
|
41860
|
+
handwritingSummary: row.handwritingSummary,
|
|
41861
|
+
bundlePresent: bundle !== null && kindOf(bundle) === "dir",
|
|
41862
|
+
fallbackImagePath,
|
|
41863
|
+
previewPath,
|
|
41864
|
+
raster
|
|
41865
|
+
};
|
|
41866
|
+
});
|
|
41867
|
+
}
|
|
41868
|
+
function verifyWrittenImage(fd, path8, expected) {
|
|
41869
|
+
const check2 = readImageInfoFd(fd);
|
|
41870
|
+
if (!check2 || check2.format !== expected.format || check2.width !== expected.width || check2.height !== expected.height) {
|
|
41871
|
+
unlinkSync2(path8);
|
|
41872
|
+
throw new Error("The exported image failed validation and was removed.");
|
|
41873
|
+
}
|
|
41874
|
+
return check2;
|
|
41875
|
+
}
|
|
41876
|
+
function selectDrawing(drawings, noteId3, attachmentId) {
|
|
41877
|
+
if (attachmentId) {
|
|
41878
|
+
const wanted = attachmentId.toLowerCase();
|
|
41879
|
+
const found = drawings.find(
|
|
41880
|
+
(d) => d.identifier.toLowerCase() === wanted || attachmentCoreDataId(noteId3, d.pk).toLowerCase() === wanted
|
|
41881
|
+
);
|
|
41882
|
+
if (!found) throw new Error(`No Paper or drawing attachment "${attachmentId}" in this note.`);
|
|
41883
|
+
return found;
|
|
41884
|
+
}
|
|
41885
|
+
if (drawings.length === 0) throw new Error("This note has no Paper or drawing attachment.");
|
|
41886
|
+
if (drawings.length > 1) {
|
|
41887
|
+
throw new Error(
|
|
41888
|
+
`This note has ${drawings.length} Paper or drawing attachments; pass attachmentId (from list-paper-attachments) to choose one.`
|
|
41889
|
+
);
|
|
41890
|
+
}
|
|
41891
|
+
return drawings[0];
|
|
41892
|
+
}
|
|
41893
|
+
function exportDrawingRaster(drawing, savePath, containerDir = NOTES_CONTAINER_DIR) {
|
|
41894
|
+
if (!drawing.raster) {
|
|
41895
|
+
throw new Error(
|
|
41896
|
+
"Notes has no rendered image for this drawing on disk yet (open the note in Notes.app to let it render, then retry)."
|
|
41897
|
+
);
|
|
41898
|
+
}
|
|
41899
|
+
const abs = assertSafeSavePath(savePath);
|
|
41900
|
+
if (isInsideNotesContainer(abs, containerDir)) {
|
|
41901
|
+
throw new Error(`Refusing to write inside the Notes data container: "${abs}"`);
|
|
41902
|
+
}
|
|
41903
|
+
const ext = extname2(abs).toLowerCase();
|
|
41904
|
+
const expected = drawing.raster.format === "png" ? [".png"] : [".jpg", ".jpeg"];
|
|
41905
|
+
if (!expected.includes(ext)) {
|
|
41906
|
+
throw new Error(
|
|
41907
|
+
`The rendered image is ${drawing.raster.format.toUpperCase()}; savePath must end in ${expected.join(" or ")}.`
|
|
41908
|
+
);
|
|
41909
|
+
}
|
|
41910
|
+
mkdirSync3(dirname3(abs), { recursive: true });
|
|
41911
|
+
assertSafeSavePath(abs);
|
|
41912
|
+
if (isInsideNotesContainer(abs, containerDir)) {
|
|
41913
|
+
throw new Error(`Refusing to write inside the Notes data container: "${abs}"`);
|
|
41914
|
+
}
|
|
41915
|
+
const input = openSync3(drawing.raster.path, constants3.O_RDONLY | constants3.O_NOFOLLOW);
|
|
41916
|
+
let bytes = 0;
|
|
41917
|
+
try {
|
|
41918
|
+
if (!fstatSync3(input).isFile()) throw new Error("The rendered image is not a regular file");
|
|
41919
|
+
const header = Buffer.alloc(HEADER_BYTES);
|
|
41920
|
+
const headerLength = readSync2(input, header, 0, header.length, 0);
|
|
41921
|
+
const info = parseImageHeader(header.subarray(0, headerLength));
|
|
41922
|
+
if (!info || info.format !== drawing.raster.format) {
|
|
41923
|
+
throw new Error(
|
|
41924
|
+
"The rendered image changed or is not a valid PNG/JPEG; nothing was written."
|
|
41925
|
+
);
|
|
41926
|
+
}
|
|
41927
|
+
let output;
|
|
41928
|
+
try {
|
|
41929
|
+
output = openSync3(
|
|
41930
|
+
abs,
|
|
41931
|
+
constants3.O_RDWR | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW,
|
|
41932
|
+
384
|
|
41933
|
+
);
|
|
41934
|
+
} catch (error2) {
|
|
41935
|
+
if (error2.code === "EEXIST") {
|
|
41936
|
+
throw new Error(`"${abs}" already exists; choose a new savePath.`);
|
|
41937
|
+
}
|
|
41938
|
+
throw error2;
|
|
41939
|
+
}
|
|
41940
|
+
try {
|
|
41941
|
+
const buffer = Buffer.allocUnsafe(1024 * 1024);
|
|
41942
|
+
let position = 0;
|
|
41943
|
+
for (; ; ) {
|
|
41944
|
+
const read = readSync2(input, buffer, 0, buffer.length, position);
|
|
41945
|
+
if (read === 0) break;
|
|
41946
|
+
position += read;
|
|
41947
|
+
let written = 0;
|
|
41948
|
+
while (written < read) written += writeSync2(output, buffer, written, read - written);
|
|
41949
|
+
}
|
|
41950
|
+
bytes = position;
|
|
41951
|
+
const check2 = verifyWrittenImage(output, abs, info);
|
|
41952
|
+
return { savedPath: abs, bytes, source: drawing.raster.source, ...check2 };
|
|
41953
|
+
} catch (error2) {
|
|
41954
|
+
try {
|
|
41955
|
+
unlinkSync2(abs);
|
|
41956
|
+
} catch {
|
|
41957
|
+
}
|
|
41958
|
+
throw error2;
|
|
41959
|
+
} finally {
|
|
41960
|
+
closeSync3(output);
|
|
41961
|
+
}
|
|
41962
|
+
} finally {
|
|
41963
|
+
closeSync3(input);
|
|
41964
|
+
}
|
|
41965
|
+
}
|
|
41966
|
+
|
|
41614
41967
|
// src/services/appleNotesManager.ts
|
|
41615
41968
|
var import_turndown = __toESM(require_turndown_cjs(), 1);
|
|
41616
41969
|
import { existsSync as existsSync4 } from "fs";
|
|
41617
41970
|
import { homedir as homedir7 } from "os";
|
|
41618
|
-
import { join as
|
|
41971
|
+
import { join as join8 } from "path";
|
|
41619
41972
|
var FIELD_SEP = "";
|
|
41620
41973
|
var RECORD_SEP = "";
|
|
41621
41974
|
var AS_FIELD_SEP = "(character id 31)";
|
|
@@ -41843,7 +42196,7 @@ function getNoteLinkFromDB(coreDataId2) {
|
|
|
41843
42196
|
const match = coreDataId2.match(/\/p(\d+)$/);
|
|
41844
42197
|
if (!match) return null;
|
|
41845
42198
|
const pk = parseInt(match[1], 10);
|
|
41846
|
-
const dbPath2 =
|
|
42199
|
+
const dbPath2 = join8(homedir7(), "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite");
|
|
41847
42200
|
if (!existsSync4(dbPath2)) return null;
|
|
41848
42201
|
try {
|
|
41849
42202
|
const { DatabaseSync } = __require("node:sqlite");
|
|
@@ -42840,7 +43193,7 @@ var AppleNotesManager = class {
|
|
|
42840
43193
|
return [];
|
|
42841
43194
|
}
|
|
42842
43195
|
const recordSeparator = result.output.includes(RECORD_SEP) ? RECORD_SEP : "\n";
|
|
42843
|
-
const
|
|
43196
|
+
const entries2 = result.output.split(recordSeparator).map((line) => {
|
|
42844
43197
|
const parts = line.includes(FIELD_SEP) ? line.split(FIELD_SEP) : line.split(" ");
|
|
42845
43198
|
return {
|
|
42846
43199
|
id: (parts[0] || "").trim(),
|
|
@@ -42853,7 +43206,7 @@ var AppleNotesManager = class {
|
|
|
42853
43206
|
account: (parts[4] || "").trim()
|
|
42854
43207
|
};
|
|
42855
43208
|
});
|
|
42856
|
-
const byId = new Map(
|
|
43209
|
+
const byId = new Map(entries2.map((e) => [e.id, e]));
|
|
42857
43210
|
const buildPath = (entry) => {
|
|
42858
43211
|
const safeName = escapeFolderName(entry.name);
|
|
42859
43212
|
if (!entry.parentId) return safeName;
|
|
@@ -42863,7 +43216,7 @@ var AppleNotesManager = class {
|
|
|
42863
43216
|
}
|
|
42864
43217
|
return safeName;
|
|
42865
43218
|
};
|
|
42866
|
-
return
|
|
43219
|
+
return entries2.map((entry) => ({
|
|
42867
43220
|
id: entry.id,
|
|
42868
43221
|
name: buildPath(entry),
|
|
42869
43222
|
account: entry.account || targetAccount || "",
|
|
@@ -43765,6 +44118,24 @@ var AppleNotesManager = class {
|
|
|
43765
44118
|
cleanupTempDir(dir);
|
|
43766
44119
|
}
|
|
43767
44120
|
}
|
|
44121
|
+
/**
|
|
44122
|
+
* Lists a note's Paper (`com.apple.paper`) and classic drawing attachments
|
|
44123
|
+
* with Notes' rendered raster, read-only from NoteStore and the Notes group
|
|
44124
|
+
* container. Requires Full Disk Access.
|
|
44125
|
+
*
|
|
44126
|
+
* @throws PaperStoreError (`no_fda`, `invalid_id`, `not_found`, `query_error`)
|
|
44127
|
+
*/
|
|
44128
|
+
listPaperAttachmentsById(noteId3) {
|
|
44129
|
+
return describeDrawings(readDrawingRows(noteId3));
|
|
44130
|
+
}
|
|
44131
|
+
/**
|
|
44132
|
+
* Copies Notes' rendered raster of one drawing to a new file. `attachmentId`
|
|
44133
|
+
* (identifier or AppleScript id) is required when the note has more than one.
|
|
44134
|
+
*/
|
|
44135
|
+
exportPaperImageById(noteId3, savePath, attachmentId) {
|
|
44136
|
+
const drawing = selectDrawing(this.listPaperAttachmentsById(noteId3), noteId3, attachmentId);
|
|
44137
|
+
return { drawing, ...exportDrawingRaster(drawing, savePath) };
|
|
44138
|
+
}
|
|
43768
44139
|
/**
|
|
43769
44140
|
* Reads one note's attachments with their on-disk asset and preview paths,
|
|
43770
44141
|
* in body order, from the NoteStore database and the Notes group container
|
|
@@ -44209,7 +44580,7 @@ var AppleNotesManager = class {
|
|
|
44209
44580
|
};
|
|
44210
44581
|
|
|
44211
44582
|
// src/utils/syncDetection.ts
|
|
44212
|
-
import { execFileSync as
|
|
44583
|
+
import { execFileSync as execFileSync8 } from "child_process";
|
|
44213
44584
|
import * as fs3 from "fs";
|
|
44214
44585
|
import * as path3 from "path";
|
|
44215
44586
|
import * as os3 from "os";
|
|
@@ -44254,7 +44625,7 @@ function getSyncStatus(useCache = true) {
|
|
|
44254
44625
|
WHERE object.ZCLOUDSTATE = state.Z_PK
|
|
44255
44626
|
);
|
|
44256
44627
|
`;
|
|
44257
|
-
const result =
|
|
44628
|
+
const result = execFileSync8(
|
|
44258
44629
|
"sqlite3",
|
|
44259
44630
|
["-readonly", NOTES_DB_PATH4, query.replace(/\n/g, " ")],
|
|
44260
44631
|
{
|
|
@@ -44313,7 +44684,7 @@ function withSyncAwarenessSync(operation, fn) {
|
|
|
44313
44684
|
}
|
|
44314
44685
|
|
|
44315
44686
|
// src/utils/noteMetadata.ts
|
|
44316
|
-
import { execFileSync as
|
|
44687
|
+
import { execFileSync as execFileSync9 } from "child_process";
|
|
44317
44688
|
import * as fs4 from "fs";
|
|
44318
44689
|
import * as path4 from "path";
|
|
44319
44690
|
import * as os4 from "os";
|
|
@@ -44333,15 +44704,15 @@ var COLUMN_MAP = [
|
|
|
44333
44704
|
{ key: "widgetSnippet", column: "ZWIDGETSNIPPET", type: "text" },
|
|
44334
44705
|
{ key: "smartFolderQuery", column: "ZSMARTFOLDERQUERYJSON", type: "text" }
|
|
44335
44706
|
];
|
|
44336
|
-
function
|
|
44337
|
-
return
|
|
44707
|
+
function runSqlite5(query) {
|
|
44708
|
+
return execFileSync9("sqlite3", ["-readonly", NOTES_DB_PATH5, query], {
|
|
44338
44709
|
encoding: "utf8",
|
|
44339
44710
|
timeout: 5e3,
|
|
44340
44711
|
stdio: ["pipe", "pipe", "pipe"]
|
|
44341
44712
|
}).trim();
|
|
44342
44713
|
}
|
|
44343
44714
|
function presentColumns() {
|
|
44344
|
-
const out =
|
|
44715
|
+
const out = runSqlite5("PRAGMA table_info(ZICCLOUDSYNCINGOBJECT);");
|
|
44345
44716
|
const cols = /* @__PURE__ */ new Set();
|
|
44346
44717
|
for (const line of out.split("\n")) {
|
|
44347
44718
|
const name = line.split("|")[1];
|
|
@@ -44369,7 +44740,7 @@ function getNoteMetadata(noteId3) {
|
|
|
44369
44740
|
return { metadata: {} };
|
|
44370
44741
|
}
|
|
44371
44742
|
const pairs = selected.map((c) => `'${c.key}', ${c.column}`).join(", ");
|
|
44372
|
-
const row =
|
|
44743
|
+
const row = runSqlite5(
|
|
44373
44744
|
`SELECT json_object(${pairs}) FROM ZICCLOUDSYNCINGOBJECT WHERE Z_PK = ${pk};`
|
|
44374
44745
|
);
|
|
44375
44746
|
if (!row) {
|
|
@@ -44401,8 +44772,11 @@ function getNoteMetadata(noteId3) {
|
|
|
44401
44772
|
}
|
|
44402
44773
|
}
|
|
44403
44774
|
|
|
44404
|
-
// src/utils/
|
|
44405
|
-
import {
|
|
44775
|
+
// src/utils/noteListings.ts
|
|
44776
|
+
import { gunzipSync as gunzipSync6 } from "zlib";
|
|
44777
|
+
|
|
44778
|
+
// src/utils/noteStoreSql.ts
|
|
44779
|
+
import { execFileSync as execFileSync10 } from "child_process";
|
|
44406
44780
|
import * as fs5 from "fs";
|
|
44407
44781
|
import * as os5 from "os";
|
|
44408
44782
|
import * as path5 from "path";
|
|
@@ -44410,6 +44784,407 @@ var NOTES_DB_PATH6 = path5.join(
|
|
|
44410
44784
|
os5.homedir(),
|
|
44411
44785
|
"Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
|
|
44412
44786
|
);
|
|
44787
|
+
var CORE_DATA_EPOCH_MS = Date.UTC(2001, 0, 1);
|
|
44788
|
+
var STORE_FDA_MESSAGE = `Full Disk Access is required to read the Notes database. In System Settings > Privacy & Security > Full Disk Access, grant access to the app that launches this server (Claude Desktop / Terminal / iTerm2), then fully quit and relaunch it. Setup guide: ${FULL_DISK_ACCESS_GUIDE_URL} \u2014 run the doctor tool to verify.`;
|
|
44789
|
+
var NoteStoreError = class extends Error {
|
|
44790
|
+
constructor(message, kind) {
|
|
44791
|
+
super(message);
|
|
44792
|
+
this.kind = kind;
|
|
44793
|
+
this.name = "NoteStoreError";
|
|
44794
|
+
}
|
|
44795
|
+
kind;
|
|
44796
|
+
};
|
|
44797
|
+
function doubleToHex(value) {
|
|
44798
|
+
if (!Number.isFinite(value)) throw new NoteStoreError("Not a finite number", "invalid_input");
|
|
44799
|
+
const buffer = Buffer.alloc(8);
|
|
44800
|
+
buffer.writeDoubleBE(value);
|
|
44801
|
+
return buffer.toString("hex");
|
|
44802
|
+
}
|
|
44803
|
+
function hexToDouble(hex3) {
|
|
44804
|
+
if (!/^[0-9a-f]{16}$/i.test(hex3))
|
|
44805
|
+
throw new NoteStoreError("Invalid double bits", "invalid_input");
|
|
44806
|
+
const value = Buffer.from(hex3, "hex").readDoubleBE();
|
|
44807
|
+
if (!Number.isFinite(value)) throw new NoteStoreError("Invalid double bits", "invalid_input");
|
|
44808
|
+
return value;
|
|
44809
|
+
}
|
|
44810
|
+
function renderValue(value) {
|
|
44811
|
+
if ("int" in value) {
|
|
44812
|
+
if (!Number.isSafeInteger(value.int)) {
|
|
44813
|
+
throw new NoteStoreError("Bound integer out of range", "invalid_input");
|
|
44814
|
+
}
|
|
44815
|
+
return String(value.int);
|
|
44816
|
+
}
|
|
44817
|
+
if ("blob" in value) return `x'${Buffer.from(value.blob).toString("hex")}'`;
|
|
44818
|
+
const double = "double" in value ? value.double : hexToDouble(value.doubleBits);
|
|
44819
|
+
return `ieee754_from_blob(x'${doubleToHex(double)}')`;
|
|
44820
|
+
}
|
|
44821
|
+
function runReadOnlySql(dbPath2, sql, params = {}) {
|
|
44822
|
+
if (!fs5.existsSync(dbPath2)) throw new NoteStoreError(STORE_FDA_MESSAGE, "no_fda");
|
|
44823
|
+
const args = ["-readonly"];
|
|
44824
|
+
const names = Object.keys(params);
|
|
44825
|
+
if (names.length) args.push("-cmd", ".parameter init");
|
|
44826
|
+
for (const name of names) {
|
|
44827
|
+
if (!/^[a-z][a-z0-9_]*$/i.test(name)) {
|
|
44828
|
+
throw new NoteStoreError(`Invalid parameter name ${name}`, "invalid_input");
|
|
44829
|
+
}
|
|
44830
|
+
args.push("-cmd", `.parameter set @${name} ${renderValue(params[name])}`);
|
|
44831
|
+
}
|
|
44832
|
+
args.push(dbPath2, sql);
|
|
44833
|
+
try {
|
|
44834
|
+
return execFileSync10("sqlite3", args, {
|
|
44835
|
+
encoding: "utf8",
|
|
44836
|
+
timeout: 3e4,
|
|
44837
|
+
maxBuffer: 512 * 1024 * 1024,
|
|
44838
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
44839
|
+
});
|
|
44840
|
+
} catch (error2) {
|
|
44841
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
44842
|
+
if (/authorization denied|unable to open database/i.test(message)) {
|
|
44843
|
+
throw new NoteStoreError(STORE_FDA_MESSAGE, "no_fda");
|
|
44844
|
+
}
|
|
44845
|
+
console.error(`Notes database query failed: ${message}`);
|
|
44846
|
+
throw new NoteStoreError("Failed to query the Notes database.", "query_error");
|
|
44847
|
+
}
|
|
44848
|
+
}
|
|
44849
|
+
function parseJsonLines(output) {
|
|
44850
|
+
const rows = [];
|
|
44851
|
+
for (const line of output.split("\n")) {
|
|
44852
|
+
if (!line.trim()) continue;
|
|
44853
|
+
try {
|
|
44854
|
+
rows.push(JSON.parse(line));
|
|
44855
|
+
} catch {
|
|
44856
|
+
throw new NoteStoreError("Unexpected Notes database response.", "query_error");
|
|
44857
|
+
}
|
|
44858
|
+
}
|
|
44859
|
+
return rows;
|
|
44860
|
+
}
|
|
44861
|
+
function readColumns(dbPath2) {
|
|
44862
|
+
const out = runReadOnlySql(
|
|
44863
|
+
dbPath2,
|
|
44864
|
+
"SELECT json_object('name', name) FROM pragma_table_info('ZICCLOUDSYNCINGOBJECT');"
|
|
44865
|
+
);
|
|
44866
|
+
return new Set(parseJsonLines(out).map((row) => row.name));
|
|
44867
|
+
}
|
|
44868
|
+
function requireColumns(columns, required2, tool) {
|
|
44869
|
+
const missing = required2.filter((column) => !columns.has(column));
|
|
44870
|
+
if (missing.length) {
|
|
44871
|
+
throw new NoteStoreError(
|
|
44872
|
+
`This macOS version's Notes database lacks columns ${tool} needs (${missing.join(", ")}).`,
|
|
44873
|
+
"schema"
|
|
44874
|
+
);
|
|
44875
|
+
}
|
|
44876
|
+
}
|
|
44877
|
+
function col(columns, alias, name, fallback = "NULL") {
|
|
44878
|
+
return columns.has(name) ? `${alias}.${name}` : fallback;
|
|
44879
|
+
}
|
|
44880
|
+
function entity(name) {
|
|
44881
|
+
return `(SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME='${name}')`;
|
|
44882
|
+
}
|
|
44883
|
+
function accountRef(columns, alias) {
|
|
44884
|
+
const refs = [...columns].filter((name) => /^ZACCOUNT\d*$/.test(name)).sort().map((name) => `${alias}.${name}`);
|
|
44885
|
+
if (!refs.length) return "NULL";
|
|
44886
|
+
return refs.length === 1 ? refs[0] : `COALESCE(${refs.join(", ")})`;
|
|
44887
|
+
}
|
|
44888
|
+
function trashFolderSql(columns, f) {
|
|
44889
|
+
const parts = [];
|
|
44890
|
+
if (columns.has("ZFOLDERTYPE")) parts.push(`COALESCE(${f}.ZFOLDERTYPE, 0) = 1`);
|
|
44891
|
+
if (columns.has("ZIDENTIFIER")) parts.push(`COALESCE(${f}.ZIDENTIFIER, '') LIKE 'TrashFolder%'`);
|
|
44892
|
+
return parts.length ? `(${parts.join(" OR ")})` : "0";
|
|
44893
|
+
}
|
|
44894
|
+
function notTombstonedSql(columns, alias) {
|
|
44895
|
+
return columns.has("ZMARKEDFORDELETION") ? `COALESCE(${alias}.ZMARKEDFORDELETION, 0) = 0` : "1";
|
|
44896
|
+
}
|
|
44897
|
+
function activeNoteSql(columns, n, f) {
|
|
44898
|
+
return [
|
|
44899
|
+
`${n}.ZFOLDER IS NOT NULL`,
|
|
44900
|
+
`${f}.Z_PK IS NOT NULL`,
|
|
44901
|
+
notTombstonedSql(columns, n),
|
|
44902
|
+
notTombstonedSql(columns, f),
|
|
44903
|
+
`NOT ${trashFolderSql(columns, f)}`
|
|
44904
|
+
].join(" AND ");
|
|
44905
|
+
}
|
|
44906
|
+
function coreDataToIso(seconds) {
|
|
44907
|
+
if (typeof seconds !== "number" || !Number.isFinite(seconds)) return null;
|
|
44908
|
+
const date3 = new Date(CORE_DATA_EPOCH_MS + seconds * 1e3);
|
|
44909
|
+
return Number.isNaN(date3.getTime()) ? null : date3.toISOString();
|
|
44910
|
+
}
|
|
44911
|
+
function noteIdFor(storeUuid, pk) {
|
|
44912
|
+
return `x-coredata://${storeUuid}/ICNote/p${pk}`;
|
|
44913
|
+
}
|
|
44914
|
+
function readStoreContext(dbPath2, columns) {
|
|
44915
|
+
const sql = [
|
|
44916
|
+
"BEGIN;",
|
|
44917
|
+
"SELECT json_object('k', 'meta', 'uuid', (SELECT Z_UUID FROM Z_METADATA LIMIT 1));",
|
|
44918
|
+
`SELECT json_object('k', 'account', 'pk', a.Z_PK, 'name', ${col(columns, "a", "ZNAME")}, 'identifier', ${col(columns, "a", "ZIDENTIFIER")}) FROM ZICCLOUDSYNCINGOBJECT a WHERE a.Z_ENT = ${entity("ICAccount")} AND ${notTombstonedSql(columns, "a")};`,
|
|
44919
|
+
`SELECT json_object('k', 'folder', 'pk', f.Z_PK, 'name', ${col(columns, "f", "ZTITLE2")}, 'identifier', ${col(columns, "f", "ZIDENTIFIER")}, 'parent', ${col(columns, "f", "ZPARENT")}, 'account', ${col(columns, "f", "ZOWNER", accountRef(columns, "f"))}, 'folderType', ${col(columns, "f", "ZFOLDERTYPE")}, 'trash', ${trashFolderSql(columns, "f")}, 'tombstoned', NOT ${notTombstonedSql(columns, "f")}) FROM ZICCLOUDSYNCINGOBJECT f WHERE f.Z_ENT = ${entity("ICFolder")};`,
|
|
44920
|
+
"COMMIT;"
|
|
44921
|
+
].join(" ");
|
|
44922
|
+
const rows = parseJsonLines(runReadOnlySql(dbPath2, sql));
|
|
44923
|
+
const meta = rows.find((row) => row.k === "meta");
|
|
44924
|
+
if (typeof meta?.uuid !== "string" || !meta.uuid) {
|
|
44925
|
+
throw new NoteStoreError("The Notes database has no store identifier.", "schema");
|
|
44926
|
+
}
|
|
44927
|
+
return {
|
|
44928
|
+
uuid: meta.uuid,
|
|
44929
|
+
accounts: rows.filter((row) => row.k === "account").map((row) => ({
|
|
44930
|
+
pk: row.pk,
|
|
44931
|
+
name: typeof row.name === "string" ? row.name : "",
|
|
44932
|
+
identifier: row.identifier ?? null
|
|
44933
|
+
})),
|
|
44934
|
+
folders: rows.filter((row) => row.k === "folder").map((row) => ({
|
|
44935
|
+
pk: row.pk,
|
|
44936
|
+
name: row.name ?? null,
|
|
44937
|
+
identifier: row.identifier ?? null,
|
|
44938
|
+
parent: row.parent ?? null,
|
|
44939
|
+
account: row.account ?? null,
|
|
44940
|
+
folderType: row.folderType ?? null,
|
|
44941
|
+
trash: row.trash ? 1 : 0,
|
|
44942
|
+
tombstoned: row.tombstoned ? 1 : 0
|
|
44943
|
+
}))
|
|
44944
|
+
};
|
|
44945
|
+
}
|
|
44946
|
+
function folderPaths(folders) {
|
|
44947
|
+
const byPk = new Map(folders.map((folder) => [folder.pk, folder]));
|
|
44948
|
+
const paths = /* @__PURE__ */ new Map();
|
|
44949
|
+
for (const folder of folders) {
|
|
44950
|
+
const segments = [];
|
|
44951
|
+
const seen = /* @__PURE__ */ new Set();
|
|
44952
|
+
let current = folder;
|
|
44953
|
+
while (current && !seen.has(current.pk)) {
|
|
44954
|
+
seen.add(current.pk);
|
|
44955
|
+
segments.unshift(escapeFolderName(current.name ?? ""));
|
|
44956
|
+
current = current.parent !== null ? byPk.get(current.parent) : void 0;
|
|
44957
|
+
}
|
|
44958
|
+
paths.set(folder.pk, segments.join("/"));
|
|
44959
|
+
}
|
|
44960
|
+
return paths;
|
|
44961
|
+
}
|
|
44962
|
+
function resolveAccountName(accounts, name) {
|
|
44963
|
+
const wanted = name.trim().toLocaleLowerCase();
|
|
44964
|
+
const exact = accounts.filter((account) => account.name.toLocaleLowerCase() === wanted);
|
|
44965
|
+
if (exact.length === 1) return exact[0];
|
|
44966
|
+
const prefix = accounts.filter((account) => account.name.toLocaleLowerCase().startsWith(wanted));
|
|
44967
|
+
if (exact.length === 0 && prefix.length === 1) return prefix[0];
|
|
44968
|
+
const names = accounts.map((account) => account.name).join(", ");
|
|
44969
|
+
throw new NoteStoreError(
|
|
44970
|
+
exact.length > 1 || prefix.length > 1 ? `Account "${name}" is ambiguous. Accounts: ${names}.` : `No account named "${name}". Accounts: ${names}.`,
|
|
44971
|
+
"invalid_input"
|
|
44972
|
+
);
|
|
44973
|
+
}
|
|
44974
|
+
|
|
44975
|
+
// src/utils/noteListings.ts
|
|
44976
|
+
var SPECIAL_LIMIT = { DEFAULT: 100, MAX: 1e3 };
|
|
44977
|
+
var HASHTAG_UTI = "com.apple.notes.inlinetextattachment.hashtag";
|
|
44978
|
+
var KIND_COLUMN = {
|
|
44979
|
+
pinned: ["ZISPINNED"],
|
|
44980
|
+
"quick-notes": ["ZISSYSTEMPAPER"],
|
|
44981
|
+
"recently-deleted": ["ZFOLDERTYPE", "ZIDENTIFIER"],
|
|
44982
|
+
locked: ["ZISPASSWORDPROTECTED"]
|
|
44983
|
+
};
|
|
44984
|
+
function kindSupported(columns, kind) {
|
|
44985
|
+
return KIND_COLUMN[kind].some((name) => columns.has(name));
|
|
44986
|
+
}
|
|
44987
|
+
var flag = (columns, alias, name) => columns.has(name) ? `COALESCE(${alias}.${name}, 0)` : "0";
|
|
44988
|
+
function kindPredicate(columns, kind) {
|
|
44989
|
+
switch (kind) {
|
|
44990
|
+
case "pinned":
|
|
44991
|
+
return `${flag(columns, "n", "ZISPINNED")} = 1 AND ${activeNoteSql(columns, "n", "f")}`;
|
|
44992
|
+
case "quick-notes":
|
|
44993
|
+
return `${flag(columns, "n", "ZISSYSTEMPAPER")} = 1 AND ${activeNoteSql(columns, "n", "f")}`;
|
|
44994
|
+
case "recently-deleted":
|
|
44995
|
+
return `f.Z_PK IS NOT NULL AND ${trashFolderSql(columns, "f")} AND ${notTombstonedSql(columns, "n")}`;
|
|
44996
|
+
case "locked":
|
|
44997
|
+
return `${flag(columns, "n", "ZISPASSWORDPROTECTED")} = 1`;
|
|
44998
|
+
}
|
|
44999
|
+
}
|
|
45000
|
+
function folderAccountJoins(columns) {
|
|
45001
|
+
const owner = col(columns, "f", "ZOWNER");
|
|
45002
|
+
const account = owner === "NULL" ? accountRef(columns, "n") : `COALESCE(${owner}, ${accountRef(columns, "n")})`;
|
|
45003
|
+
return `LEFT JOIN ZICCLOUDSYNCINGOBJECT f ON f.Z_PK = n.ZFOLDER AND f.Z_ENT = ${entity("ICFolder")} LEFT JOIN ZICCLOUDSYNCINGOBJECT a ON a.Z_PK = ${account} AND a.Z_ENT = ${entity("ICAccount")}`;
|
|
45004
|
+
}
|
|
45005
|
+
function noteFrom(columns) {
|
|
45006
|
+
return `FROM ZICCLOUDSYNCINGOBJECT n ${folderAccountJoins(columns)}`;
|
|
45007
|
+
}
|
|
45008
|
+
var REQUIRED = ["Z_PK", "Z_ENT", "ZFOLDER", "ZTITLE1"];
|
|
45009
|
+
function buildSpecialNotesSql(columns, kind, scoped) {
|
|
45010
|
+
requireColumns(columns, REQUIRED, "list-special-notes");
|
|
45011
|
+
const created = ["ZCREATIONDATE3", "ZCREATIONDATE1", "ZCREATIONDATE"].filter((name) => columns.has(name)).map((name) => `n.${name}`).join(", ") || "NULL";
|
|
45012
|
+
const createdExpr = created.includes(",") ? `COALESCE(${created})` : created;
|
|
45013
|
+
const modified = col(columns, "n", "ZMODIFICATIONDATE1");
|
|
45014
|
+
const locked = flag(columns, "n", "ZISPASSWORDPROTECTED");
|
|
45015
|
+
const where = `WHERE n.Z_ENT = ${entity("ICNote")} AND ${kindPredicate(columns, kind)}` + (scoped ? " AND a.Z_PK = @account" : "");
|
|
45016
|
+
const snippet = `CASE WHEN ${locked} = 1 THEN NULL ELSE ${col(columns, "n", "ZSNIPPET")} END`;
|
|
45017
|
+
const hint = kind === "locked" ? col(columns, "n", "ZPASSWORDHINT") : "NULL";
|
|
45018
|
+
const row = `SELECT json_object('k', 'note', 'pk', n.Z_PK, 'identifier', ${col(columns, "n", "ZIDENTIFIER")}, 'title', n.ZTITLE1, 'folder', f.Z_PK, 'account', a.Z_PK, 'created', ${createdExpr}, 'modified', ${modified}, 'pinned', ${flag(columns, "n", "ZISPINNED")}, 'locked', ${locked}, 'quick', ${flag(columns, "n", "ZISSYSTEMPAPER")}, 'trash', f.Z_PK IS NOT NULL AND ${trashFolderSql(columns, "f")}, 'tombstoned', NOT ${notTombstonedSql(columns, "n")}, 'snippet', ${snippet}, 'hint', ${hint}) ${noteFrom(columns)} ${where} ORDER BY ${modified} DESC, n.Z_PK DESC LIMIT @limit;`;
|
|
45019
|
+
return [
|
|
45020
|
+
"BEGIN;",
|
|
45021
|
+
`SELECT json_object('k', 'total', 'n', COUNT(*)) ${noteFrom(columns)} ${where};`,
|
|
45022
|
+
row,
|
|
45023
|
+
"COMMIT;"
|
|
45024
|
+
].join(" ");
|
|
45025
|
+
}
|
|
45026
|
+
function listSpecialNotes(options) {
|
|
45027
|
+
const dbPath2 = options.dbPath ?? NOTES_DB_PATH6;
|
|
45028
|
+
const limit = Math.min(
|
|
45029
|
+
Math.max(1, Math.trunc(options.limit ?? SPECIAL_LIMIT.DEFAULT)),
|
|
45030
|
+
SPECIAL_LIMIT.MAX
|
|
45031
|
+
);
|
|
45032
|
+
const columns = readColumns(dbPath2);
|
|
45033
|
+
const empty = {
|
|
45034
|
+
kind: options.kind,
|
|
45035
|
+
notes: [],
|
|
45036
|
+
count: 0,
|
|
45037
|
+
total: 0,
|
|
45038
|
+
limit,
|
|
45039
|
+
supported: false
|
|
45040
|
+
};
|
|
45041
|
+
if (!kindSupported(columns, options.kind)) return empty;
|
|
45042
|
+
const context = readStoreContext(dbPath2, columns);
|
|
45043
|
+
const scope2 = options.account ? resolveAccountName(context.accounts, options.account) : void 0;
|
|
45044
|
+
const params = { limit: { int: limit } };
|
|
45045
|
+
if (scope2) params.account = { int: scope2.pk };
|
|
45046
|
+
const rows = parseJsonLines(
|
|
45047
|
+
runReadOnlySql(dbPath2, buildSpecialNotesSql(columns, options.kind, Boolean(scope2)), params)
|
|
45048
|
+
);
|
|
45049
|
+
const paths = folderPaths(context.folders);
|
|
45050
|
+
const accountNames = new Map(context.accounts.map((account) => [account.pk, account.name]));
|
|
45051
|
+
const notes = rows.filter((row) => row.k === "note").map((row) => toSpecialRow(row, context.uuid, paths, accountNames, options.kind));
|
|
45052
|
+
return {
|
|
45053
|
+
kind: options.kind,
|
|
45054
|
+
notes,
|
|
45055
|
+
count: notes.length,
|
|
45056
|
+
total: rows.find((row) => row.k === "total")?.n ?? notes.length,
|
|
45057
|
+
limit,
|
|
45058
|
+
supported: true,
|
|
45059
|
+
...scope2 ? { account: scope2.name } : {}
|
|
45060
|
+
};
|
|
45061
|
+
}
|
|
45062
|
+
function toSpecialRow(row, uuid2, paths, accountNames, kind) {
|
|
45063
|
+
const locked = Boolean(row.locked);
|
|
45064
|
+
const note = {
|
|
45065
|
+
id: noteIdFor(uuid2, row.pk),
|
|
45066
|
+
identifier: row.identifier ?? null,
|
|
45067
|
+
title: row.title ?? null,
|
|
45068
|
+
folder: row.folder !== null ? paths.get(row.folder) ?? null : null,
|
|
45069
|
+
account: row.account !== null ? accountNames.get(row.account) ?? null : null,
|
|
45070
|
+
created: coreDataToIso(row.created),
|
|
45071
|
+
modified: coreDataToIso(row.modified),
|
|
45072
|
+
pinned: Boolean(row.pinned),
|
|
45073
|
+
locked,
|
|
45074
|
+
quickNote: Boolean(row.quick),
|
|
45075
|
+
inRecentlyDeleted: Boolean(row.trash),
|
|
45076
|
+
markedForDeletion: Boolean(row.tombstoned)
|
|
45077
|
+
};
|
|
45078
|
+
if (!locked) note.snippet = row.snippet ?? null;
|
|
45079
|
+
if (kind === "locked" && row.hint) note.passwordHint = row.hint;
|
|
45080
|
+
return note;
|
|
45081
|
+
}
|
|
45082
|
+
var TAG_REQUIRED = ["Z_PK", "Z_ENT", "ZFOLDER", "ZNOTE1", "ZTYPEUTI1", "ZALTTEXT", "ZIDENTIFIER"];
|
|
45083
|
+
function buildTagInventorySql(columns, scoped) {
|
|
45084
|
+
requireColumns(columns, TAG_REQUIRED, "list-native-tags");
|
|
45085
|
+
const accountFilter = scoped ? " AND a.Z_PK = @account" : "";
|
|
45086
|
+
const uses = `FROM ZICCLOUDSYNCINGOBJECT i JOIN ZICCLOUDSYNCINGOBJECT n ON n.Z_PK = i.ZNOTE1 AND n.Z_ENT = ${entity("ICNote")} ${folderAccountJoins(columns)} WHERE i.ZTYPEUTI1 = '${HASHTAG_UTI}' AND ${notTombstonedSql(columns, "i")} AND ${activeNoteSql(columns, "n", "f")}${accountFilter}`;
|
|
45087
|
+
const tagAccount = accountRef(columns, "t");
|
|
45088
|
+
const display = ["ZDISPLAYTEXT", "ZSTANDARDIZEDCONTENT", "ZNAME"].filter((name) => columns.has(name)).map((name) => `t.${name}`);
|
|
45089
|
+
const displayExpr = display.length > 1 ? `COALESCE(${display.join(", ")})` : display[0] || "NULL";
|
|
45090
|
+
return [
|
|
45091
|
+
"BEGIN;",
|
|
45092
|
+
`SELECT json_object('k', 'tag', 'text', ${displayExpr}, 'account', ta.Z_PK) FROM ZICCLOUDSYNCINGOBJECT t LEFT JOIN ZICCLOUDSYNCINGOBJECT ta ON ta.Z_PK = ${tagAccount} AND ta.Z_ENT = ${entity("ICAccount")} WHERE t.Z_ENT = ${entity("ICHashtag")} AND ${notTombstonedSql(columns, "t")}${scoped ? " AND ta.Z_PK = @account" : ""};`,
|
|
45093
|
+
`SELECT json_object('k', 'use', 'note', n.Z_PK, 'object', i.ZIDENTIFIER, 'text', i.ZALTTEXT, 'account', a.Z_PK, 'locked', ${flag(columns, "n", "ZISPASSWORDPROTECTED")}) ${uses};`,
|
|
45094
|
+
`SELECT json_object('k', 'body', 'note', b.Z_PK, 'data', (SELECT hex(d.ZDATA) FROM ZICNOTEDATA d WHERE d.ZNOTE = b.Z_PK ORDER BY d.Z_PK DESC LIMIT 1)) FROM ZICCLOUDSYNCINGOBJECT b WHERE b.Z_PK IN (SELECT n.Z_PK ${uses}) AND ${flag(columns, "b", "ZISPASSWORDPROTECTED")} = 0;`,
|
|
45095
|
+
"COMMIT;"
|
|
45096
|
+
].join(" ");
|
|
45097
|
+
}
|
|
45098
|
+
var bareTag = (text) => text.replace(/^#/, "").trim();
|
|
45099
|
+
function referencedObjects(hex3) {
|
|
45100
|
+
if (!hex3 || !/^[0-9a-f]+$/i.test(hex3)) return null;
|
|
45101
|
+
try {
|
|
45102
|
+
const data = gunzipSync6(Buffer.from(hex3, "hex"), { maxOutputLength: 32 * 1024 * 1024 });
|
|
45103
|
+
const wrapper = embeddedMessage(getField(decodeMessage(data), 2));
|
|
45104
|
+
const body = wrapper && embeddedMessage(getField(wrapper, 3));
|
|
45105
|
+
if (!body) return null;
|
|
45106
|
+
const ids = /* @__PURE__ */ new Set();
|
|
45107
|
+
for (const run of getFields(body, 5)) {
|
|
45108
|
+
const attachment = embeddedMessage(getField(embeddedMessage(run) ?? [], 12));
|
|
45109
|
+
const id2 = attachment && stringValue(getField(attachment, 1));
|
|
45110
|
+
if (id2) ids.add(id2);
|
|
45111
|
+
}
|
|
45112
|
+
return ids;
|
|
45113
|
+
} catch {
|
|
45114
|
+
return null;
|
|
45115
|
+
}
|
|
45116
|
+
}
|
|
45117
|
+
function nativeTagInventory(options = {}) {
|
|
45118
|
+
const dbPath2 = options.dbPath ?? NOTES_DB_PATH6;
|
|
45119
|
+
const columns = readColumns(dbPath2);
|
|
45120
|
+
const context = readStoreContext(dbPath2, columns);
|
|
45121
|
+
const scope2 = options.account ? resolveAccountName(context.accounts, options.account) : void 0;
|
|
45122
|
+
const rows = parseJsonLines(
|
|
45123
|
+
runReadOnlySql(
|
|
45124
|
+
dbPath2,
|
|
45125
|
+
buildTagInventorySql(columns, Boolean(scope2)),
|
|
45126
|
+
scope2 ? { account: { int: scope2.pk } } : {}
|
|
45127
|
+
)
|
|
45128
|
+
);
|
|
45129
|
+
return assembleInventory(rows, context.accounts, scope2);
|
|
45130
|
+
}
|
|
45131
|
+
function assembleInventory(rows, accounts, scope2) {
|
|
45132
|
+
const accountNames = new Map(accounts.map((account) => [account.pk, account.name]));
|
|
45133
|
+
const bodies = /* @__PURE__ */ new Map();
|
|
45134
|
+
for (const row of rows) if (row.k === "body") bodies.set(row.note, referencedObjects(row.data));
|
|
45135
|
+
const groups = /* @__PURE__ */ new Map();
|
|
45136
|
+
const group = (text, weight) => {
|
|
45137
|
+
const key = text.toLocaleLowerCase();
|
|
45138
|
+
let found = groups.get(key);
|
|
45139
|
+
if (!found) groups.set(key, found = { spellings: /* @__PURE__ */ new Map(), notes: /* @__PURE__ */ new Map() });
|
|
45140
|
+
found.spellings.set(text, (found.spellings.get(text) ?? 0) + weight);
|
|
45141
|
+
return found;
|
|
45142
|
+
};
|
|
45143
|
+
const unverified = /* @__PURE__ */ new Set();
|
|
45144
|
+
for (const row of rows) {
|
|
45145
|
+
if (row.k === "tag" && row.text && bareTag(row.text)) group(bareTag(row.text), 0);
|
|
45146
|
+
if (row.k !== "use" || !row.text || !bareTag(row.text)) continue;
|
|
45147
|
+
const referenced = row.locked ? null : bodies.get(row.note) ?? null;
|
|
45148
|
+
if (referenced && !(row.object && referenced.has(row.object))) continue;
|
|
45149
|
+
if (!referenced) unverified.add(row.note);
|
|
45150
|
+
group(bareTag(row.text), 1).notes.set(row.note, row.account);
|
|
45151
|
+
}
|
|
45152
|
+
const inventory = [...groups.values()].map((entry) => {
|
|
45153
|
+
const spellings = [...entry.spellings.entries()].sort(
|
|
45154
|
+
(a, b) => b[1] - a[1] || a[0].localeCompare(b[0])
|
|
45155
|
+
);
|
|
45156
|
+
const perAccount = {};
|
|
45157
|
+
for (const accountPk of entry.notes.values()) {
|
|
45158
|
+
const name = accountPk !== null && accountNames.get(accountPk) || "unknown";
|
|
45159
|
+
perAccount[name] = (perAccount[name] ?? 0) + 1;
|
|
45160
|
+
}
|
|
45161
|
+
const result = {
|
|
45162
|
+
tag: spellings[0][0],
|
|
45163
|
+
noteCount: entry.notes.size,
|
|
45164
|
+
accounts: perAccount
|
|
45165
|
+
};
|
|
45166
|
+
if (spellings.length > 1) result.spellings = spellings.slice(1).map(([text]) => text);
|
|
45167
|
+
return result;
|
|
45168
|
+
});
|
|
45169
|
+
inventory.sort((a, b) => b.noteCount - a.noteCount || a.tag.localeCompare(b.tag));
|
|
45170
|
+
return {
|
|
45171
|
+
inventory,
|
|
45172
|
+
tagCount: inventory.length,
|
|
45173
|
+
complete: unverified.size === 0,
|
|
45174
|
+
unverifiedNotes: unverified.size,
|
|
45175
|
+
...scope2 ? { account: scope2.name } : {}
|
|
45176
|
+
};
|
|
45177
|
+
}
|
|
45178
|
+
|
|
45179
|
+
// src/utils/noteIdentifiers.ts
|
|
45180
|
+
import { execFileSync as execFileSync11 } from "child_process";
|
|
45181
|
+
import * as fs6 from "fs";
|
|
45182
|
+
import * as os6 from "os";
|
|
45183
|
+
import * as path6 from "path";
|
|
45184
|
+
var NOTES_DB_PATH7 = path6.join(
|
|
45185
|
+
os6.homedir(),
|
|
45186
|
+
"Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
|
|
45187
|
+
);
|
|
44413
45188
|
var UUID_PATTERN = /^[0-9A-Fa-f]{8}(?:-[0-9A-Fa-f]{4}){3}-[0-9A-Fa-f]{12}$/;
|
|
44414
45189
|
var NUMERIC_KEY_PATTERN = /^\d{1,18}$/;
|
|
44415
45190
|
var NOTE_ID_MESSAGE = "A canonical Apple Note ID is required (x-coredata://.../ICNote/p...), or the note's Notes UUID or numeric key";
|
|
@@ -44443,10 +45218,10 @@ function assertAll(values, pattern, label) {
|
|
|
44443
45218
|
if (!pattern.test(value)) throw new Error(`Refusing to query with an invalid ${label}`);
|
|
44444
45219
|
}
|
|
44445
45220
|
}
|
|
44446
|
-
function entityClause(
|
|
44447
|
-
return `(SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = '${
|
|
45221
|
+
function entityClause(entity3) {
|
|
45222
|
+
return `(SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = '${entity3}')`;
|
|
44448
45223
|
}
|
|
44449
|
-
function buildResolveSql(
|
|
45224
|
+
function buildResolveSql(entity3, keys, uuids) {
|
|
44450
45225
|
assertAll(keys, NUMERIC_KEY_PATTERN, "numeric key");
|
|
44451
45226
|
assertAll(uuids, UUID_PATTERN, "UUID");
|
|
44452
45227
|
const matches = [];
|
|
@@ -44463,28 +45238,28 @@ function buildResolveSql(entity2, keys, uuids) {
|
|
|
44463
45238
|
matches.push(`o.ZIDENTIFIER IN (${[...variants].map((v) => `'${v}'`).join(", ")})`);
|
|
44464
45239
|
}
|
|
44465
45240
|
const where = matches.length > 0 ? matches.join(" OR ") : "0";
|
|
44466
|
-
return `SELECT json_object('store', (SELECT Z_UUID FROM Z_METADATA LIMIT 1), 'rows', (SELECT json_group_array(json_object('pk', o.Z_PK, 'identifier', o.ZIDENTIFIER)) FROM ZICCLOUDSYNCINGOBJECT o WHERE o.Z_ENT = ${entityClause(
|
|
45241
|
+
return `SELECT json_object('store', (SELECT Z_UUID FROM Z_METADATA LIMIT 1), 'rows', (SELECT json_group_array(json_object('pk', o.Z_PK, 'identifier', o.ZIDENTIFIER)) FROM ZICCLOUDSYNCINGOBJECT o WHERE o.Z_ENT = ${entityClause(entity3)} AND (${where})));`;
|
|
44467
45242
|
}
|
|
44468
|
-
function buildLookupSql(
|
|
45243
|
+
function buildLookupSql(entity3, keys) {
|
|
44469
45244
|
assertAll(keys, NUMERIC_KEY_PATTERN, "numeric key");
|
|
44470
45245
|
const pks = [...new Set(keys.map(canonicalKey))];
|
|
44471
45246
|
const inList = pks.length > 0 ? pks.join(", ") : "NULL";
|
|
44472
45247
|
let fields = "'pk', o.Z_PK, 'identifier', o.ZIDENTIFIER";
|
|
44473
45248
|
let joins = "";
|
|
44474
|
-
if (
|
|
45249
|
+
if (entity3 === "ICNote") {
|
|
44475
45250
|
fields += ", 'folderIdentifier', f.ZIDENTIFIER, 'accountIdentifier', a.ZIDENTIFIER";
|
|
44476
45251
|
joins = "LEFT JOIN ZICCLOUDSYNCINGOBJECT f ON f.Z_PK = o.ZFOLDER LEFT JOIN ZICCLOUDSYNCINGOBJECT a ON a.Z_PK = f.ZOWNER ";
|
|
44477
|
-
} else if (
|
|
45252
|
+
} else if (entity3 === "ICFolder") {
|
|
44478
45253
|
fields += ", 'parentIdentifier', p.ZIDENTIFIER, 'accountIdentifier', a.ZIDENTIFIER";
|
|
44479
45254
|
joins = "LEFT JOIN ZICCLOUDSYNCINGOBJECT p ON p.Z_PK = o.ZPARENT LEFT JOIN ZICCLOUDSYNCINGOBJECT a ON a.Z_PK = o.ZOWNER ";
|
|
44480
45255
|
}
|
|
44481
|
-
return `SELECT json_object('store', (SELECT Z_UUID FROM Z_METADATA LIMIT 1), 'rows', (SELECT json_group_array(json_object(${fields})) FROM ZICCLOUDSYNCINGOBJECT o ${joins}WHERE o.Z_ENT = ${entityClause(
|
|
45256
|
+
return `SELECT json_object('store', (SELECT Z_UUID FROM Z_METADATA LIMIT 1), 'rows', (SELECT json_group_array(json_object(${fields})) FROM ZICCLOUDSYNCINGOBJECT o ${joins}WHERE o.Z_ENT = ${entityClause(entity3)} AND o.Z_PK IN (${inList})));`;
|
|
44482
45257
|
}
|
|
44483
45258
|
function runJsonQuery(sql, dbPath2) {
|
|
44484
|
-
if (!
|
|
45259
|
+
if (!fs6.existsSync(dbPath2)) throw new IdentifierResolutionError("no_fda", NO_FDA_MESSAGE);
|
|
44485
45260
|
let out;
|
|
44486
45261
|
try {
|
|
44487
|
-
out =
|
|
45262
|
+
out = execFileSync11("sqlite3", ["-readonly", dbPath2, sql], {
|
|
44488
45263
|
encoding: "utf8",
|
|
44489
45264
|
timeout: 5e3,
|
|
44490
45265
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -44501,10 +45276,10 @@ function runJsonQuery(sql, dbPath2) {
|
|
|
44501
45276
|
const rows = typeof parsed.rows === "string" ? JSON.parse(parsed.rows) : parsed.rows;
|
|
44502
45277
|
return { store: parsed.store ?? null, rows: rows ?? [] };
|
|
44503
45278
|
}
|
|
44504
|
-
function coreDataId(store,
|
|
44505
|
-
return `x-coredata://${store}/${
|
|
45279
|
+
function coreDataId(store, entity3, pk) {
|
|
45280
|
+
return `x-coredata://${store}/${entity3}/p${pk}`;
|
|
44506
45281
|
}
|
|
44507
|
-
function resolveIdentifiers(values,
|
|
45282
|
+
function resolveIdentifiers(values, entity3, dbPath2 = NOTES_DB_PATH7) {
|
|
44508
45283
|
const resolved = /* @__PURE__ */ new Map();
|
|
44509
45284
|
const keys = [];
|
|
44510
45285
|
const uuids = [];
|
|
@@ -44516,7 +45291,7 @@ function resolveIdentifiers(values, entity2, dbPath2 = NOTES_DB_PATH6) {
|
|
|
44516
45291
|
}
|
|
44517
45292
|
if (keys.length === 0 && uuids.length === 0) return resolved;
|
|
44518
45293
|
const { store, rows } = runJsonQuery(
|
|
44519
|
-
buildResolveSql(
|
|
45294
|
+
buildResolveSql(entity3, keys, uuids),
|
|
44520
45295
|
dbPath2
|
|
44521
45296
|
);
|
|
44522
45297
|
if (!store) {
|
|
@@ -44529,16 +45304,16 @@ function resolveIdentifiers(values, entity2, dbPath2 = NOTES_DB_PATH6) {
|
|
|
44529
45304
|
const byUuid = new Map(
|
|
44530
45305
|
rows.filter((row) => row.identifier).map((row) => [String(row.identifier).toUpperCase(), row])
|
|
44531
45306
|
);
|
|
44532
|
-
const label = ENTITY_LABEL[
|
|
45307
|
+
const label = ENTITY_LABEL[entity3];
|
|
44533
45308
|
const missing = [];
|
|
44534
45309
|
for (const key of keys) {
|
|
44535
45310
|
const row = byKey.get(canonicalKey(key));
|
|
44536
|
-
if (row) resolved.set(key, coreDataId(store,
|
|
45311
|
+
if (row) resolved.set(key, coreDataId(store, entity3, row.pk));
|
|
44537
45312
|
else missing.push(`numeric key ${key}`);
|
|
44538
45313
|
}
|
|
44539
45314
|
for (const uuid2 of uuids) {
|
|
44540
45315
|
const row = byUuid.get(uuid2.toUpperCase());
|
|
44541
|
-
if (row) resolved.set(uuid2, coreDataId(store,
|
|
45316
|
+
if (row) resolved.set(uuid2, coreDataId(store, entity3, row.pk));
|
|
44542
45317
|
else missing.push(`identifier ${uuid2}`);
|
|
44543
45318
|
}
|
|
44544
45319
|
if (missing.length > 0) {
|
|
@@ -44550,12 +45325,12 @@ function resolveIdentifiers(values, entity2, dbPath2 = NOTES_DB_PATH6) {
|
|
|
44550
45325
|
return resolved;
|
|
44551
45326
|
}
|
|
44552
45327
|
var COREDATA_PARTS = /^x-coredata:\/\/([0-9A-Fa-f-]+)\/(ICNote|ICFolder|ICAccount)\/p(\d{1,18})$/;
|
|
44553
|
-
function lookupStableIdentifiers(ids,
|
|
45328
|
+
function lookupStableIdentifiers(ids, entity3, dbPath2 = NOTES_DB_PATH7) {
|
|
44554
45329
|
const result = /* @__PURE__ */ new Map();
|
|
44555
45330
|
const wanted = /* @__PURE__ */ new Map();
|
|
44556
45331
|
for (const id2 of ids) {
|
|
44557
45332
|
const match = COREDATA_PARTS.exec(id2);
|
|
44558
|
-
if (!match || match[2] !==
|
|
45333
|
+
if (!match || match[2] !== entity3) continue;
|
|
44559
45334
|
const pk = canonicalKey(match[3]);
|
|
44560
45335
|
const list = wanted.get(pk) ?? [];
|
|
44561
45336
|
list.push({ id: id2, store: match[1] });
|
|
@@ -44564,7 +45339,7 @@ function lookupStableIdentifiers(ids, entity2, dbPath2 = NOTES_DB_PATH6) {
|
|
|
44564
45339
|
if (wanted.size === 0) return result;
|
|
44565
45340
|
let query;
|
|
44566
45341
|
try {
|
|
44567
|
-
query = runJsonQuery(buildLookupSql(
|
|
45342
|
+
query = runJsonQuery(buildLookupSql(entity3, [...wanted.keys()]), dbPath2);
|
|
44568
45343
|
} catch {
|
|
44569
45344
|
return result;
|
|
44570
45345
|
}
|
|
@@ -44586,16 +45361,16 @@ function lookupStableIdentifiers(ids, entity2, dbPath2 = NOTES_DB_PATH6) {
|
|
|
44586
45361
|
}
|
|
44587
45362
|
return result;
|
|
44588
45363
|
}
|
|
44589
|
-
function withStableIdentifiers(items,
|
|
45364
|
+
function withStableIdentifiers(items, entity3, dbPath2 = NOTES_DB_PATH7) {
|
|
44590
45365
|
const ids = items.map((item) => item.id).filter((id2) => typeof id2 === "string");
|
|
44591
45366
|
if (ids.length === 0) return items;
|
|
44592
|
-
const found = lookupStableIdentifiers(ids,
|
|
45367
|
+
const found = lookupStableIdentifiers(ids, entity3, dbPath2);
|
|
44593
45368
|
if (found.size === 0) return items;
|
|
44594
45369
|
return items.map(
|
|
44595
45370
|
(item) => item.id && found.has(item.id) ? { ...item, ...found.get(item.id) } : item
|
|
44596
45371
|
);
|
|
44597
45372
|
}
|
|
44598
|
-
var defaultResolver = (values,
|
|
45373
|
+
var defaultResolver = (values, entity3) => resolveIdentifiers(values, entity3);
|
|
44599
45374
|
var DEFAULT_MAX_ID_LENGTH = 2e3;
|
|
44600
45375
|
function acceptAlternateForms(pattern) {
|
|
44601
45376
|
return new RegExp(
|
|
@@ -44603,10 +45378,10 @@ function acceptAlternateForms(pattern) {
|
|
|
44603
45378
|
pattern.flags
|
|
44604
45379
|
);
|
|
44605
45380
|
}
|
|
44606
|
-
function resolveInSchema(values,
|
|
45381
|
+
function resolveInSchema(values, entity3, ctx, resolver) {
|
|
44607
45382
|
if (!values.some(isAlternateIdentifier)) return new Map(values.map((v) => [v, v]));
|
|
44608
45383
|
try {
|
|
44609
|
-
return resolver(values,
|
|
45384
|
+
return resolver(values, entity3);
|
|
44610
45385
|
} catch (error2) {
|
|
44611
45386
|
ctx.addIssue({
|
|
44612
45387
|
code: external_exports.ZodIssueCode.custom,
|
|
@@ -44615,26 +45390,26 @@ function resolveInSchema(values, entity2, ctx, resolver) {
|
|
|
44615
45390
|
return null;
|
|
44616
45391
|
}
|
|
44617
45392
|
}
|
|
44618
|
-
function exactIdInput(
|
|
45393
|
+
function exactIdInput(entity3, pattern, message, options = {}) {
|
|
44619
45394
|
const resolver = options.resolver ?? defaultResolver;
|
|
44620
45395
|
return external_exports.string().max(options.maxLength ?? DEFAULT_MAX_ID_LENGTH).regex(acceptAlternateForms(pattern), message).transform((value, ctx) => {
|
|
44621
|
-
const map = resolveInSchema([value],
|
|
45396
|
+
const map = resolveInSchema([value], entity3, ctx, resolver);
|
|
44622
45397
|
return map ? map.get(value) ?? value : external_exports.NEVER;
|
|
44623
45398
|
});
|
|
44624
45399
|
}
|
|
44625
|
-
function exactIdArrayInput(
|
|
45400
|
+
function exactIdArrayInput(entity3, pattern, message, options = {}) {
|
|
44626
45401
|
const resolver = options.resolver ?? defaultResolver;
|
|
44627
45402
|
const item = external_exports.string().max(options.maxLength ?? DEFAULT_MAX_ID_LENGTH).regex(acceptAlternateForms(pattern), message);
|
|
44628
45403
|
const array2 = options.maxItems === void 0 ? external_exports.array(item) : external_exports.array(item).max(options.maxItems);
|
|
44629
45404
|
return array2.transform((values, ctx) => {
|
|
44630
|
-
const map = resolveInSchema(values,
|
|
45405
|
+
const map = resolveInSchema(values, entity3, ctx, resolver);
|
|
44631
45406
|
return map ? values.map((value) => map.get(value) ?? value) : external_exports.NEVER;
|
|
44632
45407
|
});
|
|
44633
45408
|
}
|
|
44634
|
-
function looseIdTransform(
|
|
45409
|
+
function looseIdTransform(entity3, resolver = defaultResolver) {
|
|
44635
45410
|
return (value, ctx) => {
|
|
44636
45411
|
if (!isAlternateIdentifier(value)) return value;
|
|
44637
|
-
const map = resolveInSchema([value],
|
|
45412
|
+
const map = resolveInSchema([value], entity3, ctx, resolver);
|
|
44638
45413
|
return map ? map.get(value) ?? value : external_exports.NEVER;
|
|
44639
45414
|
};
|
|
44640
45415
|
}
|
|
@@ -45174,18 +45949,18 @@ function positiveTextTerms(node, negated = false) {
|
|
|
45174
45949
|
}
|
|
45175
45950
|
|
|
45176
45951
|
// src/utils/noteQueryStore.ts
|
|
45177
|
-
import { execFileSync as
|
|
45178
|
-
import * as
|
|
45179
|
-
import * as
|
|
45180
|
-
import * as
|
|
45181
|
-
import { gunzipSync as
|
|
45182
|
-
var
|
|
45183
|
-
|
|
45952
|
+
import { execFileSync as execFileSync12 } from "child_process";
|
|
45953
|
+
import * as fs7 from "fs";
|
|
45954
|
+
import * as os7 from "os";
|
|
45955
|
+
import * as path7 from "path";
|
|
45956
|
+
import { gunzipSync as gunzipSync7 } from "zlib";
|
|
45957
|
+
var NOTES_DB_PATH8 = path7.join(
|
|
45958
|
+
os7.homedir(),
|
|
45184
45959
|
"Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
|
|
45185
45960
|
);
|
|
45186
45961
|
var QUERY_SCAN = { DEFAULT: 500, MAX: 5e3 };
|
|
45187
45962
|
var QUERY_RESULTS = { DEFAULT: 50, MAX: 500 };
|
|
45188
|
-
var
|
|
45963
|
+
var CORE_DATA_EPOCH_MS2 = Date.UTC(2001, 0, 1);
|
|
45189
45964
|
var SNIPPET_BEFORE = 60;
|
|
45190
45965
|
var SNIPPET_LENGTH = 180;
|
|
45191
45966
|
var QUERY_FDA_MESSAGE = `Full Disk Access is required to query notes. In System Settings > Privacy & Security > Full Disk Access, grant access to the app that launches this server (Claude Desktop / Terminal / iTerm2), then fully quit and relaunch it. Setup guide: ${FULL_DISK_ACCESS_GUIDE_URL} \u2014 run the doctor tool to verify.`;
|
|
@@ -45268,10 +46043,10 @@ function countWords(text) {
|
|
|
45268
46043
|
return count;
|
|
45269
46044
|
}
|
|
45270
46045
|
var REQUIRED_COLUMNS3 = ["Z_PK", "Z_ENT", "ZTITLE1", "ZFOLDER", "ZMODIFICATIONDATE1"];
|
|
45271
|
-
function
|
|
46046
|
+
function col2(available, alias, name) {
|
|
45272
46047
|
return available.has(name) ? `${alias}.${name}` : "NULL";
|
|
45273
46048
|
}
|
|
45274
|
-
var
|
|
46049
|
+
var entity2 = (name) => `(SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME='${name}')`;
|
|
45275
46050
|
function buildScanSql(available, options) {
|
|
45276
46051
|
const missing = REQUIRED_COLUMNS3.filter((c) => !available.has(c));
|
|
45277
46052
|
if (missing.length) {
|
|
@@ -45289,21 +46064,21 @@ function buildScanSql(available, options) {
|
|
|
45289
46064
|
const bool = (name) => available.has(name) ? `COALESCE(n.${name}, 0)` : "0";
|
|
45290
46065
|
const notNull = (alias, name) => available.has(name) ? `${alias}.${name} IS NOT NULL` : "0";
|
|
45291
46066
|
const tagsExpr = options.withTags && ["ZNOTE1", "ZTYPEUTI1", "ZALTTEXT", "ZIDENTIFIER"].every((c) => available.has(c)) ? `(SELECT json_group_array(json_array(t.ZIDENTIFIER, t.ZALTTEXT)) FROM ZICCLOUDSYNCINGOBJECT t WHERE t.ZNOTE1 = n.Z_PK AND t.ZTYPEUTI1 = 'com.apple.notes.inlinetextattachment.hashtag')` : "NULL";
|
|
45292
|
-
const where = [`n.Z_ENT = ${
|
|
46067
|
+
const where = [`n.Z_ENT = ${entity2("ICNote")}`];
|
|
45293
46068
|
if (!options.includeDeleted) {
|
|
45294
46069
|
where.push("n.ZFOLDER IS NOT NULL");
|
|
45295
46070
|
if (available.has("ZMARKEDFORDELETION")) where.push("COALESCE(n.ZMARKEDFORDELETION, 0) = 0");
|
|
45296
46071
|
if (available.has("ZFOLDERTYPE")) {
|
|
45297
46072
|
where.push(
|
|
45298
|
-
`n.ZFOLDER NOT IN (SELECT Z_PK FROM ZICCLOUDSYNCINGOBJECT WHERE Z_ENT = ${
|
|
46073
|
+
`n.ZFOLDER NOT IN (SELECT Z_PK FROM ZICCLOUDSYNCINGOBJECT WHERE Z_ENT = ${entity2("ICFolder")} AND ZFOLDERTYPE = 1)`
|
|
45299
46074
|
);
|
|
45300
46075
|
}
|
|
45301
46076
|
}
|
|
45302
46077
|
const whereSql = where.join(" AND ");
|
|
45303
|
-
const folderRow = `SELECT json_object('k', 'folder', 'pk', f.Z_PK, 'name', ${
|
|
45304
|
-
const accountRow = `SELECT json_object('k', 'account', 'pk', a.Z_PK, 'name', ${
|
|
46078
|
+
const folderRow = `SELECT json_object('k', 'folder', 'pk', f.Z_PK, 'name', ${col2(available, "f", "ZTITLE2")}, 'parent', ${col2(available, "f", "ZPARENT")}, 'type', ${col2(available, "f", "ZFOLDERTYPE")}, 'owner', ${col2(available, "f", "ZOWNER")}, 'shared', ${notNull("f", "ZSERVERSHAREDATA")}) FROM ZICCLOUDSYNCINGOBJECT f WHERE f.Z_ENT = ${entity2("ICFolder")};`;
|
|
46079
|
+
const accountRow = `SELECT json_object('k', 'account', 'pk', a.Z_PK, 'name', ${col2(available, "a", "ZNAME")}) FROM ZICCLOUDSYNCINGOBJECT a WHERE a.Z_ENT = ${entity2("ICAccount")};`;
|
|
45305
46080
|
const dataExpr = options.withBodies ? "(SELECT hex(d.ZDATA) FROM ZICNOTEDATA d WHERE d.ZNOTE = n.Z_PK ORDER BY d.Z_PK DESC LIMIT 1)" : "NULL";
|
|
45306
|
-
const noteRow = `SELECT json_object('k', 'note', 'pk', n.Z_PK, 'title', n.ZTITLE1, 'folder', n.ZFOLDER, 'created', ${createdExpr}, 'modified', n.ZMODIFICATIONDATE1, 'pinned', ${bool("ZISPINNED")}, 'locked', ${bool("ZISPASSWORDPROTECTED")}, 'shared', ${notNull("n", "ZSERVERSHAREDATA")}, 'snippet', ${
|
|
46081
|
+
const noteRow = `SELECT json_object('k', 'note', 'pk', n.Z_PK, 'title', n.ZTITLE1, 'folder', n.ZFOLDER, 'created', ${createdExpr}, 'modified', n.ZMODIFICATIONDATE1, 'pinned', ${bool("ZISPINNED")}, 'locked', ${bool("ZISPASSWORDPROTECTED")}, 'shared', ${notNull("n", "ZSERVERSHAREDATA")}, 'snippet', ${col2(available, "n", "ZSNIPPET")}, 'data', ${dataExpr}, 'tags', ${tagsExpr}) FROM ZICCLOUDSYNCINGOBJECT n WHERE ${whereSql} ORDER BY n.ZMODIFICATIONDATE1 DESC, n.Z_PK DESC LIMIT ${scan};`;
|
|
45307
46082
|
return [
|
|
45308
46083
|
"BEGIN;",
|
|
45309
46084
|
"SELECT json_object('k', 'meta', 'uuid', (SELECT Z_UUID FROM Z_METADATA LIMIT 1));",
|
|
@@ -45314,8 +46089,8 @@ function buildScanSql(available, options) {
|
|
|
45314
46089
|
"COMMIT;"
|
|
45315
46090
|
].join(" ");
|
|
45316
46091
|
}
|
|
45317
|
-
function
|
|
45318
|
-
return
|
|
46092
|
+
function runSqlite6(dbPath2, query) {
|
|
46093
|
+
return execFileSync12("sqlite3", ["-readonly", dbPath2, query], {
|
|
45319
46094
|
encoding: "utf8",
|
|
45320
46095
|
timeout: 3e4,
|
|
45321
46096
|
maxBuffer: 512 * 1024 * 1024,
|
|
@@ -45324,7 +46099,7 @@ function runSqlite5(dbPath2, query) {
|
|
|
45324
46099
|
}
|
|
45325
46100
|
function presentColumns2(dbPath2) {
|
|
45326
46101
|
const cols = /* @__PURE__ */ new Set();
|
|
45327
|
-
for (const line of
|
|
46102
|
+
for (const line of runSqlite6(dbPath2, "PRAGMA table_info(ZICCLOUDSYNCINGOBJECT);").split("\n")) {
|
|
45328
46103
|
const name = line.split("|")[1];
|
|
45329
46104
|
if (name) cols.add(name);
|
|
45330
46105
|
}
|
|
@@ -45342,12 +46117,12 @@ function resolveFolders(rows) {
|
|
|
45342
46117
|
seen.add(pk);
|
|
45343
46118
|
const parent = row.parent !== null ? resolve4(row.parent, seen) : void 0;
|
|
45344
46119
|
const name = row.name ?? "";
|
|
45345
|
-
const
|
|
46120
|
+
const path8 = parent ? `${parent.path}/${escapeSegment(name)}` : escapeSegment(name);
|
|
45346
46121
|
const plainPath = parent ? `${parent.plainPath}/${name}` : name;
|
|
45347
46122
|
const info = {
|
|
45348
|
-
path:
|
|
46123
|
+
path: path8,
|
|
45349
46124
|
plainPath,
|
|
45350
|
-
keys: [...new Set([name, plainPath,
|
|
46125
|
+
keys: [...new Set([name, plainPath, path8].map(normalizeForMatch))],
|
|
45351
46126
|
accountPk: row.owner ?? parent?.accountPk ?? null,
|
|
45352
46127
|
shared: Boolean(row.shared) || Boolean(parent?.shared)
|
|
45353
46128
|
};
|
|
@@ -45357,7 +46132,7 @@ function resolveFolders(rows) {
|
|
|
45357
46132
|
for (const row of rows) resolve4(row.pk, /* @__PURE__ */ new Set());
|
|
45358
46133
|
return resolved;
|
|
45359
46134
|
}
|
|
45360
|
-
var coreDataMs = (seconds) => seconds === null || !Number.isFinite(seconds) ? void 0 :
|
|
46135
|
+
var coreDataMs = (seconds) => seconds === null || !Number.isFinite(seconds) ? void 0 : CORE_DATA_EPOCH_MS2 + seconds * 1e3;
|
|
45361
46136
|
function buildSnippet(text, terms) {
|
|
45362
46137
|
const clean = text.replace(/\ufffc/gu, " ");
|
|
45363
46138
|
const firstBreak = clean.indexOf("\n");
|
|
@@ -45379,12 +46154,12 @@ function queryNotes(expression, options = {}) {
|
|
|
45379
46154
|
const includeDeleted = options.includeDeleted ?? false;
|
|
45380
46155
|
const withBodies = needsContent(ast);
|
|
45381
46156
|
const withTags = needsTags(ast);
|
|
45382
|
-
const dbPath2 = options.dbPath ??
|
|
45383
|
-
if (!
|
|
46157
|
+
const dbPath2 = options.dbPath ?? NOTES_DB_PATH8;
|
|
46158
|
+
if (!fs7.existsSync(dbPath2)) throw new NoteQueryStoreError(QUERY_FDA_MESSAGE, "no_fda");
|
|
45384
46159
|
let output;
|
|
45385
46160
|
try {
|
|
45386
46161
|
const available = presentColumns2(dbPath2);
|
|
45387
|
-
output =
|
|
46162
|
+
output = runSqlite6(
|
|
45388
46163
|
dbPath2,
|
|
45389
46164
|
buildScanSql(available, { scanLimit, includeDeleted, withBodies, withTags })
|
|
45390
46165
|
);
|
|
@@ -45440,7 +46215,7 @@ function queryNotes(expression, options = {}) {
|
|
|
45440
46215
|
try {
|
|
45441
46216
|
decoded = decodeNoteBody(
|
|
45442
46217
|
new Uint8Array(
|
|
45443
|
-
|
|
46218
|
+
gunzipSync7(Buffer.from(row.data, "hex"), { maxOutputLength: 32 * 1024 * 1024 })
|
|
45444
46219
|
)
|
|
45445
46220
|
);
|
|
45446
46221
|
} catch {
|
|
@@ -45515,10 +46290,10 @@ function queryNotes(expression, options = {}) {
|
|
|
45515
46290
|
import { spawnSync } from "child_process";
|
|
45516
46291
|
|
|
45517
46292
|
// src/services/nativeTags.ts
|
|
45518
|
-
import { execFileSync as
|
|
46293
|
+
import { execFileSync as execFileSync13 } from "node:child_process";
|
|
45519
46294
|
import { mkdtempSync as mkdtempSync2, writeFileSync, rmSync as rmSync2 } from "node:fs";
|
|
45520
46295
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
45521
|
-
import { join as
|
|
46296
|
+
import { join as join14 } from "node:path";
|
|
45522
46297
|
|
|
45523
46298
|
// src/services/shortcutConsent.ts
|
|
45524
46299
|
function shortcutConsentHint(shortcut) {
|
|
@@ -45594,7 +46369,7 @@ function addNativeTags(request, deps) {
|
|
|
45594
46369
|
};
|
|
45595
46370
|
}
|
|
45596
46371
|
function listInstalledShortcuts() {
|
|
45597
|
-
return
|
|
46372
|
+
return execFileSync13("/usr/bin/shortcuts", ["list", "--show-identifiers"], {
|
|
45598
46373
|
encoding: "utf8",
|
|
45599
46374
|
timeout: 15e3,
|
|
45600
46375
|
maxBuffer: 1024 * 1024,
|
|
@@ -45620,11 +46395,11 @@ function runNativeTagsShortcut(input) {
|
|
|
45620
46395
|
const status = nativeTagsStatus();
|
|
45621
46396
|
if (!status.installed)
|
|
45622
46397
|
throw new Error(`Import the supplied ${status.shortcut}.shortcut in Shortcuts first`);
|
|
45623
|
-
const directory = mkdtempSync2(
|
|
46398
|
+
const directory = mkdtempSync2(join14(tmpdir2(), "apple-notes-native-tags-"));
|
|
45624
46399
|
try {
|
|
45625
|
-
const
|
|
45626
|
-
writeFileSync(
|
|
45627
|
-
|
|
46400
|
+
const path8 = join14(directory, "request.json");
|
|
46401
|
+
writeFileSync(path8, JSON.stringify(input), { mode: 384 });
|
|
46402
|
+
execFileSync13("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", path8], {
|
|
45628
46403
|
encoding: "utf8",
|
|
45629
46404
|
timeout: 6e4,
|
|
45630
46405
|
maxBuffer: 1024 * 1024,
|
|
@@ -45643,10 +46418,10 @@ function runNativeTagsShortcut(input) {
|
|
|
45643
46418
|
}
|
|
45644
46419
|
|
|
45645
46420
|
// src/services/backgroundNotes.ts
|
|
45646
|
-
import { execFileSync as
|
|
46421
|
+
import { execFileSync as execFileSync14 } from "node:child_process";
|
|
45647
46422
|
import { mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync2, rmSync as rmSync3 } from "node:fs";
|
|
45648
46423
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
45649
|
-
import { join as
|
|
46424
|
+
import { join as join15 } from "node:path";
|
|
45650
46425
|
|
|
45651
46426
|
// src/utils/appendMarkdown.ts
|
|
45652
46427
|
var escape2 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
@@ -45971,9 +46746,9 @@ function runBackgroundShortcut(input, status = backgroundStatus()) {
|
|
|
45971
46746
|
throw new Error(
|
|
45972
46747
|
`Install the supplied "${status.shortcut}" Shortcut once; Shortcuts must list it exactly once`
|
|
45973
46748
|
);
|
|
45974
|
-
const directory = mkdtempSync3(
|
|
46749
|
+
const directory = mkdtempSync3(join15(tmpdir3(), "apple-notes-background-"));
|
|
45975
46750
|
try {
|
|
45976
|
-
const file =
|
|
46751
|
+
const file = join15(directory, "request.json");
|
|
45977
46752
|
writeFileSync2(
|
|
45978
46753
|
file,
|
|
45979
46754
|
JSON.stringify({
|
|
@@ -45993,7 +46768,7 @@ function runBackgroundShortcut(input, status = backgroundStatus()) {
|
|
|
45993
46768
|
{ mode: 384 }
|
|
45994
46769
|
);
|
|
45995
46770
|
try {
|
|
45996
|
-
|
|
46771
|
+
execFileSync14("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", file], {
|
|
45997
46772
|
encoding: "utf8",
|
|
45998
46773
|
timeout: callTimeoutMs() ?? 6e4,
|
|
45999
46774
|
maxBuffer: 1024 * 1024,
|
|
@@ -46228,7 +47003,7 @@ function createMarkdownNote(manager, request, run = runBackgroundShortcut) {
|
|
|
46228
47003
|
throw new Error(
|
|
46229
47004
|
`Install the supplied "${status.shortcut}" Shortcut once; Shortcuts must list it exactly once`
|
|
46230
47005
|
);
|
|
46231
|
-
const segments = (
|
|
47006
|
+
const segments = (path8) => JSON.stringify(splitFolderPath(path8).map((part) => part.toLocaleLowerCase()));
|
|
46232
47007
|
if (request.folder) {
|
|
46233
47008
|
const wanted = segments(request.folder);
|
|
46234
47009
|
if (!manager.listAccounts().some(
|
|
@@ -46318,7 +47093,7 @@ ${request.content}`
|
|
|
46318
47093
|
}
|
|
46319
47094
|
|
|
46320
47095
|
// src/services/capabilityMatrix.ts
|
|
46321
|
-
import { execFileSync as
|
|
47096
|
+
import { execFileSync as execFileSync15 } from "node:child_process";
|
|
46322
47097
|
import { release } from "node:os";
|
|
46323
47098
|
var MACOS_SHORTCUTS_CLI = "12.0";
|
|
46324
47099
|
var MACOS_MARKDOWN_IMPORT = "26.0";
|
|
@@ -46525,7 +47300,7 @@ function evaluateFeatures(env, features = FEATURES) {
|
|
|
46525
47300
|
function readMacOSVersion() {
|
|
46526
47301
|
if (process.platform !== "darwin") return null;
|
|
46527
47302
|
try {
|
|
46528
|
-
const out =
|
|
47303
|
+
const out = execFileSync15("/usr/bin/sw_vers", ["-productVersion"], {
|
|
46529
47304
|
encoding: "utf8",
|
|
46530
47305
|
timeout: 3e3,
|
|
46531
47306
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -46558,9 +47333,9 @@ function getCapabilityMatrix(probe = probeCapabilityEnvironment) {
|
|
|
46558
47333
|
return evaluateFeatures(probe());
|
|
46559
47334
|
}
|
|
46560
47335
|
function formatCapabilityMatrix(matrix) {
|
|
46561
|
-
const
|
|
47336
|
+
const os8 = matrix.runtimeOS;
|
|
46562
47337
|
const lines = [
|
|
46563
|
-
`Feature matrix (macOS ${
|
|
47338
|
+
`Feature matrix (macOS ${os8.macOSVersion ?? "unknown"}, Darwin ${os8.darwinRelease}):`
|
|
46564
47339
|
];
|
|
46565
47340
|
for (const [name, status] of Object.entries(matrix.features)) {
|
|
46566
47341
|
lines.push(
|
|
@@ -46678,19 +47453,19 @@ function formatDoctorReport(r) {
|
|
|
46678
47453
|
}
|
|
46679
47454
|
|
|
46680
47455
|
// src/services/fileConfig.ts
|
|
46681
|
-
import { existsSync as
|
|
46682
|
-
import { join as
|
|
46683
|
-
import { homedir as
|
|
47456
|
+
import { existsSync as existsSync10, readFileSync as readFileSync2 } from "fs";
|
|
47457
|
+
import { join as join16 } from "path";
|
|
47458
|
+
import { homedir as homedir13 } from "os";
|
|
46684
47459
|
function fileConfigPath(env = process.env) {
|
|
46685
47460
|
const override = env.APPLE_NOTES_MCP_CONFIG_FILE;
|
|
46686
47461
|
if (override && override.trim()) return override.trim();
|
|
46687
|
-
return
|
|
47462
|
+
return join16(homedir13(), "Library", "Application Support", "apple-notes-mcp", "config.json");
|
|
46688
47463
|
}
|
|
46689
|
-
function loadFileConfig(env = process.env,
|
|
47464
|
+
function loadFileConfig(env = process.env, path8 = fileConfigPath(env)) {
|
|
46690
47465
|
const applied = [];
|
|
46691
47466
|
try {
|
|
46692
|
-
if (!
|
|
46693
|
-
const parsed = JSON.parse(readFileSync2(
|
|
47467
|
+
if (!existsSync10(path8)) return applied;
|
|
47468
|
+
const parsed = JSON.parse(readFileSync2(path8, "utf8"));
|
|
46694
47469
|
if (!parsed || typeof parsed !== "object") return applied;
|
|
46695
47470
|
for (const [k, v] of Object.entries(parsed)) {
|
|
46696
47471
|
if (typeof v !== "string") continue;
|
|
@@ -46700,7 +47475,7 @@ function loadFileConfig(env = process.env, path7 = fileConfigPath(env)) {
|
|
|
46700
47475
|
}
|
|
46701
47476
|
}
|
|
46702
47477
|
} catch (e) {
|
|
46703
|
-
console.error(`Failed to load apple-notes-mcp config file ${
|
|
47478
|
+
console.error(`Failed to load apple-notes-mcp config file ${path8}: ${String(e)}`);
|
|
46704
47479
|
}
|
|
46705
47480
|
return applied;
|
|
46706
47481
|
}
|
|
@@ -46987,11 +47762,11 @@ function createShutdown(stream, exit, timeoutMs = SHUTDOWN_DRAIN_TIMEOUT_MS) {
|
|
|
46987
47762
|
}
|
|
46988
47763
|
|
|
46989
47764
|
// src/utils/noteBlocks.ts
|
|
46990
|
-
import { execFileSync as
|
|
46991
|
-
import { existsSync as
|
|
46992
|
-
import { homedir as
|
|
46993
|
-
import { join as
|
|
46994
|
-
import { gunzipSync as
|
|
47765
|
+
import { execFileSync as execFileSync16 } from "node:child_process";
|
|
47766
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
47767
|
+
import { homedir as homedir14 } from "node:os";
|
|
47768
|
+
import { join as join17 } from "node:path";
|
|
47769
|
+
import { gunzipSync as gunzipSync8 } from "node:zlib";
|
|
46995
47770
|
var NoteBlocksError = class extends Error {
|
|
46996
47771
|
code;
|
|
46997
47772
|
constructor(code, message) {
|
|
@@ -47279,7 +48054,7 @@ function summarize(blocks, attachments) {
|
|
|
47279
48054
|
function decodeCompressedNoteBlocks(compressed) {
|
|
47280
48055
|
let data;
|
|
47281
48056
|
try {
|
|
47282
|
-
data =
|
|
48057
|
+
data = gunzipSync8(compressed, { maxOutputLength: 32 * 1024 * 1024 });
|
|
47283
48058
|
} catch (error2) {
|
|
47284
48059
|
throw new NoteBlocksError(
|
|
47285
48060
|
"decompress-failed",
|
|
@@ -47333,23 +48108,23 @@ function pageNoteBlocks(doc, { offset = 0, limit = 500, maxBytes = blocksMaxResp
|
|
|
47333
48108
|
undecodedFields: doc.undecodedFields
|
|
47334
48109
|
};
|
|
47335
48110
|
}
|
|
47336
|
-
var
|
|
47337
|
-
|
|
48111
|
+
var NOTES_DB_PATH9 = join17(
|
|
48112
|
+
homedir14(),
|
|
47338
48113
|
"Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
|
|
47339
48114
|
);
|
|
47340
|
-
function readNoteBlocks(id2, { dbPath: dbPath2 =
|
|
48115
|
+
function readNoteBlocks(id2, { dbPath: dbPath2 = NOTES_DB_PATH9 } = {}) {
|
|
47341
48116
|
const pk = /^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p([0-9]{1,18})$/i.exec(id2)?.[1];
|
|
47342
48117
|
if (!pk)
|
|
47343
48118
|
throw new NoteBlocksError(
|
|
47344
48119
|
"invalid-id",
|
|
47345
48120
|
`Invalid note ID: expected x-coredata://<store>/ICNote/p<number>`
|
|
47346
48121
|
);
|
|
47347
|
-
if (!
|
|
48122
|
+
if (!existsSync11(dbPath2))
|
|
47348
48123
|
throw new NoteBlocksError("no-full-disk-access", "The Notes database is not readable");
|
|
47349
48124
|
const sql = "SELECT json_object('exists', (SELECT count(*) FROM ZICCLOUDSYNCINGOBJECT WHERE Z_PK = @pk AND Z_ENT = (SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = 'ICNote')), 'data', (SELECT hex(ZDATA) FROM ZICNOTEDATA WHERE ZNOTE = @pk), 'encrypted', (SELECT ZCRYPTOINITIALIZATIONVECTOR IS NOT NULL FROM ZICNOTEDATA WHERE ZNOTE = @pk));";
|
|
47350
48125
|
let output;
|
|
47351
48126
|
try {
|
|
47352
|
-
output =
|
|
48127
|
+
output = execFileSync16(
|
|
47353
48128
|
"/usr/bin/sqlite3",
|
|
47354
48129
|
["-readonly", "-cmd", ".parameter init", "-cmd", `.parameter set @pk ${pk}`, dbPath2, sql],
|
|
47355
48130
|
{
|
|
@@ -47500,17 +48275,17 @@ function insertLink(request, deps) {
|
|
|
47500
48275
|
// src/tools/directOperations.ts
|
|
47501
48276
|
import { createHash as createHash2 } from "node:crypto";
|
|
47502
48277
|
import {
|
|
47503
|
-
closeSync as
|
|
47504
|
-
constants as
|
|
47505
|
-
fstatSync as
|
|
48278
|
+
closeSync as closeSync4,
|
|
48279
|
+
constants as constants4,
|
|
48280
|
+
fstatSync as fstatSync4,
|
|
47506
48281
|
mkdtempSync as mkdtempSync4,
|
|
47507
|
-
openSync as
|
|
48282
|
+
openSync as openSync4,
|
|
47508
48283
|
readFileSync as readFileSync3,
|
|
47509
48284
|
rmSync as rmSync4,
|
|
47510
48285
|
writeFileSync as writeFileSync3
|
|
47511
48286
|
} from "node:fs";
|
|
47512
48287
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
47513
|
-
import { basename as
|
|
48288
|
+
import { basename as basename3, extname as extname3, isAbsolute as isAbsolute3, join as join18 } from "node:path";
|
|
47514
48289
|
var noteId = exactIdInput(
|
|
47515
48290
|
"ICNote",
|
|
47516
48291
|
/^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p\d+$/i,
|
|
@@ -47553,11 +48328,11 @@ function assertExistingContentPreserved(before, after) {
|
|
|
47553
48328
|
throw new Error("Existing native object content or presentation changed");
|
|
47554
48329
|
}
|
|
47555
48330
|
}
|
|
47556
|
-
function localAttachment(
|
|
47557
|
-
if (!isAbsolute3(
|
|
47558
|
-
const descriptor =
|
|
48331
|
+
function localAttachment(path8) {
|
|
48332
|
+
if (!isAbsolute3(path8)) throw new Error("An absolute local file path is required");
|
|
48333
|
+
const descriptor = openSync4(path8, constants4.O_RDONLY | constants4.O_NOFOLLOW);
|
|
47559
48334
|
try {
|
|
47560
|
-
const stat =
|
|
48335
|
+
const stat = fstatSync4(descriptor);
|
|
47561
48336
|
if (!stat.isFile() || stat.size === 0 || stat.size > 64 * 1024 * 1024)
|
|
47562
48337
|
throw new Error("Attachment must be a nonempty regular file of at most 64 MiB");
|
|
47563
48338
|
const bytes = readFileSync3(descriptor);
|
|
@@ -47565,7 +48340,7 @@ function localAttachment(path7) {
|
|
|
47565
48340
|
throw new Error("Attachment changed while it was being read; try again");
|
|
47566
48341
|
return bytes;
|
|
47567
48342
|
} finally {
|
|
47568
|
-
|
|
48343
|
+
closeSync4(descriptor);
|
|
47569
48344
|
}
|
|
47570
48345
|
}
|
|
47571
48346
|
function registerDirectOperations(server2, manager) {
|
|
@@ -47677,8 +48452,8 @@ function registerDirectOperations(server2, manager) {
|
|
|
47677
48452
|
}
|
|
47678
48453
|
);
|
|
47679
48454
|
}
|
|
47680
|
-
function attachmentName(
|
|
47681
|
-
const source =
|
|
48455
|
+
function attachmentName(path8, filename) {
|
|
48456
|
+
const source = basename3(path8);
|
|
47682
48457
|
if (filename === void 0) return source;
|
|
47683
48458
|
if (Buffer.byteLength(filename, "utf8") > 255)
|
|
47684
48459
|
throw new Error("filename must be at most 255 bytes");
|
|
@@ -47686,21 +48461,21 @@ function attachmentName(path7, filename) {
|
|
|
47686
48461
|
throw new Error(
|
|
47687
48462
|
"filename must be one path component with no slash, colon, backslash, control character, leading dot, or surrounding spaces"
|
|
47688
48463
|
);
|
|
47689
|
-
if (
|
|
48464
|
+
if (extname3(filename).toLowerCase() !== extname3(source).toLowerCase())
|
|
47690
48465
|
throw new Error(
|
|
47691
|
-
`filename must keep the source file's extension (${
|
|
48466
|
+
`filename must keep the source file's extension (${extname3(source) || "none"})`
|
|
47692
48467
|
);
|
|
47693
48468
|
return filename;
|
|
47694
48469
|
}
|
|
47695
48470
|
function attachFile(manager, args) {
|
|
47696
|
-
const { id: id2, expectedContentHash, path:
|
|
47697
|
-
const name = attachmentName(
|
|
48471
|
+
const { id: id2, expectedContentHash, path: path8 } = args;
|
|
48472
|
+
const name = attachmentName(path8, args.filename);
|
|
47698
48473
|
const before = readSnapshot(manager, id2);
|
|
47699
48474
|
if (before.hash !== expectedContentHash) throw new Error("Note revision changed");
|
|
47700
|
-
const bytes = localAttachment(
|
|
48475
|
+
const bytes = localAttachment(path8);
|
|
47701
48476
|
const beforeAttachments = manager.listAttachmentsById(id2);
|
|
47702
|
-
const directory = mkdtempSync4(
|
|
47703
|
-
const temporaryFile =
|
|
48477
|
+
const directory = mkdtempSync4(join18(tmpdir4(), "notes-attachment-add-"));
|
|
48478
|
+
const temporaryFile = join18(directory, name);
|
|
47704
48479
|
try {
|
|
47705
48480
|
writeFileSync3(temporaryFile, bytes, { mode: 384 });
|
|
47706
48481
|
if (readSnapshot(manager, id2).hash !== before.hash) throw new Error("Note revision changed");
|
|
@@ -48258,9 +49033,9 @@ function registerNativeOperations(server2, manager) {
|
|
|
48258
49033
|
|
|
48259
49034
|
// src/setupShortcuts.ts
|
|
48260
49035
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
48261
|
-
import { existsSync as
|
|
49036
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
48262
49037
|
import { release as release2 } from "node:os";
|
|
48263
|
-
import { dirname as
|
|
49038
|
+
import { dirname as dirname4, resolve as resolve3 } from "node:path";
|
|
48264
49039
|
import { fileURLToPath } from "node:url";
|
|
48265
49040
|
var OPTIONAL_BRIDGE_NOTE = "(optional \u2014 needed only for create-note format: markdown, macOS 26+)";
|
|
48266
49041
|
var MARKDOWN_MIN_DARWIN_MAJOR = 25;
|
|
@@ -48278,16 +49053,16 @@ var shortcutFiles = [
|
|
|
48278
49053
|
];
|
|
48279
49054
|
function setupShortcuts(checkOnly, dependencies = {}) {
|
|
48280
49055
|
const status = dependencies.status || nativeTagsStatus;
|
|
48281
|
-
const exists = dependencies.exists ||
|
|
48282
|
-
const open = dependencies.open || ((
|
|
48283
|
-
const result = spawnSync2("/usr/bin/open", [
|
|
49056
|
+
const exists = dependencies.exists || existsSync12;
|
|
49057
|
+
const open = dependencies.open || ((path8) => {
|
|
49058
|
+
const result = spawnSync2("/usr/bin/open", [path8], { encoding: "utf8" });
|
|
48284
49059
|
return result.status === 0 ? { ok: true } : { ok: false, error: result.stderr || result.error?.message || "open failed" };
|
|
48285
49060
|
});
|
|
48286
|
-
const baseDirectory = dependencies.baseDirectory || resolve3(
|
|
49061
|
+
const baseDirectory = dependencies.baseDirectory || resolve3(dirname4(fileURLToPath(import.meta.url)), "../shortcuts");
|
|
48287
49062
|
const osRelease = (dependencies.osRelease || release2)();
|
|
48288
49063
|
const darwinMajor = Number.parseInt(osRelease.split(".")[0], 10);
|
|
48289
49064
|
const items = shortcutFiles.map(({ name, file, optional: optional2 }) => {
|
|
48290
|
-
const
|
|
49065
|
+
const path8 = resolve3(baseDirectory, file);
|
|
48291
49066
|
let installed = false;
|
|
48292
49067
|
let identifier;
|
|
48293
49068
|
let error2;
|
|
@@ -48303,9 +49078,9 @@ function setupShortcuts(checkOnly, dependencies = {}) {
|
|
|
48303
49078
|
if (!installed && !checkOnly) {
|
|
48304
49079
|
if (optional2 && !(darwinMajor >= MARKDOWN_MIN_DARWIN_MAJOR))
|
|
48305
49080
|
skipped = `requires macOS 26 or later (this Mac reports Darwin ${osRelease})`;
|
|
48306
|
-
else if (!exists(
|
|
49081
|
+
else if (!exists(path8)) error2 = `Packaged Shortcut is missing: ${path8}`;
|
|
48307
49082
|
else {
|
|
48308
|
-
const result = open(
|
|
49083
|
+
const result = open(path8);
|
|
48309
49084
|
opened = result.ok;
|
|
48310
49085
|
if (!result.ok) error2 = result.error || `Could not open ${file}`;
|
|
48311
49086
|
}
|
|
@@ -48314,7 +49089,7 @@ function setupShortcuts(checkOnly, dependencies = {}) {
|
|
|
48314
49089
|
name,
|
|
48315
49090
|
installed,
|
|
48316
49091
|
identifier,
|
|
48317
|
-
file:
|
|
49092
|
+
file: path8,
|
|
48318
49093
|
opened,
|
|
48319
49094
|
...optional2 ? { optional: optional2 } : {},
|
|
48320
49095
|
...skipped ? { skipped } : {},
|
|
@@ -49245,19 +50020,47 @@ registerTool(
|
|
|
49245
50020
|
registerTool(
|
|
49246
50021
|
"list-native-tags",
|
|
49247
50022
|
{
|
|
49248
|
-
description: "Use when: listing actual native Notes tags
|
|
50023
|
+
description: "Use when: listing actual native Notes tags, either in one folder (pass folder) or as an account-wide inventory with note counts (omit folder; account then optionally narrows it, else every account is counted).\nReturns: folder mode maps each tag to exact matching note IDs, plus completeness and per-note errors; inventory mode returns each tag with noteCount and per-account counts, sorted by count.\nDo not use when: searching textual #hashtags in note bodies (search-notes).\nSafety: read-only; requires Full Disk Access and discloses partial reads.",
|
|
49249
50024
|
inputSchema: {
|
|
49250
|
-
account: external_exports.string().min(1).max(MAX.ACCOUNT)
|
|
49251
|
-
|
|
50025
|
+
account: external_exports.string().min(1).max(MAX.ACCOUNT).optional().describe(
|
|
50026
|
+
"Account name (exact or unique prefix). Folder mode: defaults to Notes.app's default account. Inventory mode: omit to count every account."
|
|
50027
|
+
),
|
|
50028
|
+
folder: external_exports.string().min(1).max(MAX.FOLDER).optional().describe("Folder to list tags in. Omit for the account-wide inventory with counts.")
|
|
49252
50029
|
},
|
|
49253
50030
|
outputSchema: {
|
|
49254
50031
|
tags: external_exports.record(external_exports.array(external_exports.string())).optional(),
|
|
49255
50032
|
complete: external_exports.boolean().optional(),
|
|
49256
|
-
errors: external_exports.record(external_exports.string()).optional()
|
|
50033
|
+
errors: external_exports.record(external_exports.string()).optional(),
|
|
50034
|
+
inventory: external_exports.array(
|
|
50035
|
+
external_exports.object({
|
|
50036
|
+
tag: external_exports.string(),
|
|
50037
|
+
noteCount: external_exports.number(),
|
|
50038
|
+
accounts: external_exports.record(external_exports.number()),
|
|
50039
|
+
spellings: external_exports.array(external_exports.string()).optional()
|
|
50040
|
+
}).passthrough()
|
|
50041
|
+
).optional(),
|
|
50042
|
+
tagCount: external_exports.number().optional(),
|
|
50043
|
+
unverifiedNotes: external_exports.number().optional(),
|
|
50044
|
+
account: external_exports.string().optional()
|
|
49257
50045
|
},
|
|
49258
50046
|
annotations: { readOnlyHint: true }
|
|
49259
50047
|
},
|
|
49260
50048
|
withErrorHandling(({ account, folder }) => {
|
|
50049
|
+
if (!folder) {
|
|
50050
|
+
const result = nativeTagInventory({ account });
|
|
50051
|
+
const scope2 = result.account ? ` in ${result.account}` : " across all accounts";
|
|
50052
|
+
const lines = result.inventory.map(
|
|
50053
|
+
(entry) => ` - ${entry.tag}: ${entry.noteCount} note${entry.noteCount === 1 ? "" : "s"}`
|
|
50054
|
+
);
|
|
50055
|
+
const partial2 = result.complete ? "" : `
|
|
50056
|
+
|
|
50057
|
+
${result.unverifiedNotes} note(s) could not be checked against their body (locked or unreadable) and were counted from tag objects alone.`;
|
|
50058
|
+
return successResponse(
|
|
50059
|
+
`${result.tagCount} native tag${result.tagCount === 1 ? "" : "s"}${scope2}` + (lines.length ? `:
|
|
50060
|
+
${lines.join("\n")}` : ".") + partial2,
|
|
50061
|
+
result
|
|
50062
|
+
);
|
|
50063
|
+
}
|
|
49261
50064
|
const tags = {};
|
|
49262
50065
|
const errors = {};
|
|
49263
50066
|
for (const note of notesManager.listNoteRefs(account, folder)) {
|
|
@@ -50372,6 +51175,88 @@ registerTool(
|
|
|
50372
51175
|
});
|
|
50373
51176
|
}, "Error saving attachment")
|
|
50374
51177
|
);
|
|
51178
|
+
function drawingView(noteId3, d) {
|
|
51179
|
+
const { pk, raster, ...rest } = d;
|
|
51180
|
+
return {
|
|
51181
|
+
attachmentId: attachmentCoreDataId(noteId3, pk),
|
|
51182
|
+
...rest,
|
|
51183
|
+
raster: raster ? { source: raster.source, format: raster.format, width: raster.width, height: raster.height } : null
|
|
51184
|
+
};
|
|
51185
|
+
}
|
|
51186
|
+
registerTool(
|
|
51187
|
+
"list-paper-attachments",
|
|
51188
|
+
{
|
|
51189
|
+
description: "Use when: finding the Paper drawings (com.apple.paper) and classic drawings in one note, and whether Notes has a rendered image of each.\nReturns: per drawing its attachmentId, identifier, uti, kind (paper or drawing), handwritingSummary (Notes' recognized handwriting text, or null), bundlePresent, fallbackImagePath, previewPath, and raster {source, format, width, height} (the validated image export-paper-image would copy, or null).\nDo not use when: you want every attachment (list-attachments) or the image file itself (export-paper-image).\nSafety: read-only; reads NoteStore and the Notes data folder without opening Notes.app and requires Full Disk Access. Strokes are not decoded: Notes' Paper bundle has no public reader, so the raster is Notes' own rendering.",
|
|
51190
|
+
inputSchema: { id: noteIdInput },
|
|
51191
|
+
outputSchema: {
|
|
51192
|
+
attachments: external_exports.array(external_exports.object({}).passthrough()).optional(),
|
|
51193
|
+
count: external_exports.number().optional()
|
|
51194
|
+
},
|
|
51195
|
+
annotations: { readOnlyHint: true }
|
|
51196
|
+
},
|
|
51197
|
+
withErrorHandling(({ id: id2 }) => {
|
|
51198
|
+
const drawings = notesManager.listPaperAttachmentsById(id2).map((d) => drawingView(id2, d));
|
|
51199
|
+
if (drawings.length === 0) {
|
|
51200
|
+
return successResponse("This note has no Paper or drawing attachments.", {
|
|
51201
|
+
attachments: [],
|
|
51202
|
+
count: 0
|
|
51203
|
+
});
|
|
51204
|
+
}
|
|
51205
|
+
const lines = drawings.map(
|
|
51206
|
+
(d) => ` - ${d.kind} ${d.attachmentId}: ${d.raster ? `${d.raster.format.toUpperCase()} ${d.raster.width}x${d.raster.height} (${d.raster.source})` : "no rendered image on disk"}${d.handwritingSummary ? "; handwriting text stored" : ""}`
|
|
51207
|
+
);
|
|
51208
|
+
return successResponse(
|
|
51209
|
+
`Found ${drawings.length} Paper or drawing attachment(s):
|
|
51210
|
+
${lines.join("\n")}`,
|
|
51211
|
+
{ attachments: drawings, count: drawings.length }
|
|
51212
|
+
);
|
|
51213
|
+
}, "Error listing Paper attachments")
|
|
51214
|
+
);
|
|
51215
|
+
registerTool(
|
|
51216
|
+
"export-paper-image",
|
|
51217
|
+
{
|
|
51218
|
+
description: "Use when: saving Notes' rendered image of a Paper drawing or classic drawing to a file.\nReturns: savedPath, format (png or jpeg), width, height, bytes, source (fallback: Notes' full rendering; preview: its largest thumbnail, used only when no full rendering exists), and the drawing's attachmentId and handwritingSummary.\nDo not use when: the attachment is a photo or file (save-attachment or export-attachments).\nSafety: writes one new file; savePath must be absolute, under the home directory, a temp dir, or /Volumes, outside the Notes data folder, must not exist yet, and must end in the image's extension (.png, or .jpg/.jpeg). The image header is validated before and after copying. Pass attachmentId (from list-paper-attachments) when the note has more than one drawing. Requires Full Disk Access; Notes.app is not opened.",
|
|
51219
|
+
inputSchema: {
|
|
51220
|
+
noteId: noteIdInput,
|
|
51221
|
+
savePath: external_exports.string().min(1, "savePath is required").max(MAX.SAVE_PATH).describe(
|
|
51222
|
+
"Absolute path for the new image file (.png, or .jpg/.jpeg for a JPEG rendering)"
|
|
51223
|
+
),
|
|
51224
|
+
attachmentId: external_exports.string().max(MAX.ATTACHMENT_ID).optional().describe(
|
|
51225
|
+
"Drawing to export (attachmentId or identifier from list-paper-attachments); required when the note has more than one"
|
|
51226
|
+
)
|
|
51227
|
+
},
|
|
51228
|
+
outputSchema: {
|
|
51229
|
+
savedPath: external_exports.string().optional(),
|
|
51230
|
+
format: external_exports.enum(["png", "jpeg"]).optional(),
|
|
51231
|
+
width: external_exports.number().optional(),
|
|
51232
|
+
height: external_exports.number().optional(),
|
|
51233
|
+
bytes: external_exports.number().optional(),
|
|
51234
|
+
source: external_exports.enum(["fallback", "preview"]).optional(),
|
|
51235
|
+
attachmentId: external_exports.string().optional(),
|
|
51236
|
+
identifier: external_exports.string().optional(),
|
|
51237
|
+
kind: external_exports.enum(["paper", "drawing"]).optional(),
|
|
51238
|
+
handwritingSummary: external_exports.string().nullable().optional()
|
|
51239
|
+
}
|
|
51240
|
+
},
|
|
51241
|
+
withErrorHandling(({ noteId: noteId3, savePath, attachmentId }) => {
|
|
51242
|
+
const r = notesManager.exportPaperImageById(noteId3, savePath, attachmentId);
|
|
51243
|
+
return successResponse(
|
|
51244
|
+
`Saved ${r.format.toUpperCase()} ${r.width}x${r.height} (${r.bytes} bytes, ${r.source === "fallback" ? "Notes' full rendering" : "largest preview"}) to ${r.savedPath}`,
|
|
51245
|
+
{
|
|
51246
|
+
savedPath: r.savedPath,
|
|
51247
|
+
format: r.format,
|
|
51248
|
+
width: r.width,
|
|
51249
|
+
height: r.height,
|
|
51250
|
+
bytes: r.bytes,
|
|
51251
|
+
source: r.source,
|
|
51252
|
+
attachmentId: attachmentCoreDataId(noteId3, r.drawing.pk),
|
|
51253
|
+
identifier: r.drawing.identifier,
|
|
51254
|
+
kind: r.drawing.kind,
|
|
51255
|
+
handwritingSummary: r.drawing.handwritingSummary
|
|
51256
|
+
}
|
|
51257
|
+
);
|
|
51258
|
+
}, "Error exporting Paper image")
|
|
51259
|
+
);
|
|
50375
51260
|
registerTool(
|
|
50376
51261
|
"export-attachments",
|
|
50377
51262
|
{
|
|
@@ -50697,6 +51582,57 @@ registerTool(
|
|
|
50697
51582
|
return successResponse(summary, metadata);
|
|
50698
51583
|
}, "Error reading note metadata")
|
|
50699
51584
|
);
|
|
51585
|
+
var SPECIAL_KIND_LABEL = {
|
|
51586
|
+
pinned: "pinned notes",
|
|
51587
|
+
"quick-notes": "Quick Notes",
|
|
51588
|
+
"recently-deleted": "notes in Recently Deleted",
|
|
51589
|
+
locked: "password-protected notes"
|
|
51590
|
+
};
|
|
51591
|
+
registerTool(
|
|
51592
|
+
"list-special-notes",
|
|
51593
|
+
{
|
|
51594
|
+
description: "Use when: listing pinned notes, Quick Notes, notes in Recently Deleted, or password-protected (locked) notes \u2014 sets AppleScript cannot enumerate.\nReturns: metadata rows newest first (id, identifier, title, folder path, account, created, modified, and pinned/locked/quickNote/inRecentlyDeleted flags; snippet except for locked notes; passwordHint for kind locked), plus total before limit. supported is false when this macOS version's database cannot answer that kind.\nDo not use when: you need note content (get-note-content) or a folder listing (list-notes).\nNote: reads the NoteStore SQLite database read-only and requires Full Disk Access. Pinned and Quick Notes listings cover notes in folders outside Recently Deleted; the locked listing includes trashed and folderless locked notes, flagged as such. Never reads locked note bodies.",
|
|
51595
|
+
inputSchema: {
|
|
51596
|
+
kind: external_exports.enum(["pinned", "quick-notes", "recently-deleted", "locked"]).describe("Which set of notes to list"),
|
|
51597
|
+
account: external_exports.string().min(1).max(MAX.ACCOUNT).optional().describe("Only this account (exact or unique-prefix name). Omit for every account."),
|
|
51598
|
+
limit: external_exports.number().int().min(1).max(SPECIAL_LIMIT.MAX).optional().describe(`Maximum notes to return (default ${SPECIAL_LIMIT.DEFAULT})`)
|
|
51599
|
+
},
|
|
51600
|
+
outputSchema: {
|
|
51601
|
+
kind: external_exports.string().optional(),
|
|
51602
|
+
notes: external_exports.array(external_exports.object({}).passthrough()).optional(),
|
|
51603
|
+
count: external_exports.number().optional(),
|
|
51604
|
+
total: external_exports.number().optional(),
|
|
51605
|
+
limit: external_exports.number().optional(),
|
|
51606
|
+
supported: external_exports.boolean().optional(),
|
|
51607
|
+
account: external_exports.string().optional()
|
|
51608
|
+
},
|
|
51609
|
+
annotations: { readOnlyHint: true }
|
|
51610
|
+
},
|
|
51611
|
+
withErrorHandling(({ kind, account, limit }) => {
|
|
51612
|
+
const result = listSpecialNotes({ kind, account, limit });
|
|
51613
|
+
const label = SPECIAL_KIND_LABEL[kind];
|
|
51614
|
+
const structured = result;
|
|
51615
|
+
if (!result.supported) {
|
|
51616
|
+
return successResponse(
|
|
51617
|
+
`This macOS version's Notes database does not record ${label}.`,
|
|
51618
|
+
structured
|
|
51619
|
+
);
|
|
51620
|
+
}
|
|
51621
|
+
const scope2 = result.account ? ` in ${result.account}` : "";
|
|
51622
|
+
if (result.count === 0) return successResponse(`No ${label}${scope2}.`, structured);
|
|
51623
|
+
const lines = result.notes.map(
|
|
51624
|
+
(row) => ` - ${row.title ?? "(untitled)"}${row.folder ? ` (${row.folder})` : ""} [id: ${row.id}]`
|
|
51625
|
+
);
|
|
51626
|
+
const more = result.total > result.count ? `
|
|
51627
|
+
|
|
51628
|
+
Showing ${result.count} of ${result.total}; pass a higher limit to see more.` : "";
|
|
51629
|
+
return successResponse(
|
|
51630
|
+
`Found ${result.total} ${label}${scope2}:
|
|
51631
|
+
${lines.join("\n")}${more}`,
|
|
51632
|
+
structured
|
|
51633
|
+
);
|
|
51634
|
+
}, "Error listing notes")
|
|
51635
|
+
);
|
|
50700
51636
|
registerResourcesAndPrompts(server, notesManager);
|
|
50701
51637
|
process.on("uncaughtException", (err) => {
|
|
50702
51638
|
if (err?.code === "EPIPE") process.exit(0);
|