apple-numbers-mcp 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/build/utils/python.d.ts +1 -1
- package/build/utils/python.d.ts.map +1 -1
- package/build/utils/python.js +177 -29
- package/build/utils/python.js.map +1 -1
- package/package.json +1 -1
- package/scripts/setup.sh +4 -0
package/README.md
CHANGED
|
@@ -703,7 +703,9 @@ Contributions are welcome! Please open an issue or PR at [github.com/sweetrb/app
|
|
|
703
703
|
|
|
704
704
|
## Related Projects
|
|
705
705
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
- [apple-
|
|
706
|
+
Part of a family of macOS MCP servers:
|
|
707
|
+
|
|
708
|
+
- [apple-mail-mcp](https://github.com/sweetrb/apple-mail-mcp) — MCP server for Apple Mail (read, search, send, and organize email)
|
|
709
|
+
- [apple-notes-mcp](https://github.com/sweetrb/apple-notes-mcp) — MCP server for Apple Notes (create, search, update, and export notes)
|
|
710
|
+
- [apple-photos-mcp](https://github.com/sweetrb/apple-photos-mcp) — MCP server for Apple Photos (query metadata and export originals)
|
|
709
711
|
- [numbers-parser](https://pypi.org/project/numbers-parser/) — The Python library that powers this server
|
package/build/utils/python.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export interface PythonResult<T = unknown> {
|
|
|
2
2
|
data?: T;
|
|
3
3
|
error?: string;
|
|
4
4
|
}
|
|
5
|
-
/** Reset
|
|
5
|
+
/** Reset cached interpreter + bootstrap state (useful for testing). */
|
|
6
6
|
export declare function _resetPythonCache(): void;
|
|
7
7
|
export declare function runNumbersReader<T = unknown>(command: string, args: string[], timeoutMs?: number): PythonResult<T>;
|
|
8
8
|
export declare function checkDependencies(): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../src/utils/python.ts"],"names":[],"mappings":"AA+
|
|
1
|
+
{"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../src/utils/python.ts"],"names":[],"mappings":"AA+DA,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD,uEAAuE;AACvE,wBAAgB,iBAAiB,IAAI,IAAI,CAIxC;AAsKD,wBAAgB,gBAAgB,CAAC,CAAC,GAAG,OAAO,EAC1C,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,SAAS,SAAQ,GAChB,YAAY,CAAC,CAAC,CAAC,CAkBjB;AAED,wBAAgB,iBAAiB,IAAI;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAepE"}
|
package/build/utils/python.js
CHANGED
|
@@ -1,31 +1,68 @@
|
|
|
1
1
|
import { execSync, execFileSync } from "node:child_process";
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
const __filename = fileURLToPath(import.meta.url);
|
|
6
6
|
const __dirname = dirname(__filename);
|
|
7
|
+
// pip/display name vs. the importable module name (underscore).
|
|
8
|
+
const PACKAGE = "numbers-parser";
|
|
9
|
+
const MODULE = "numbers_parser";
|
|
10
|
+
const ENV_PREFIX = "APPLE_NUMBERS_MCP";
|
|
7
11
|
function getProjectRoot() {
|
|
8
|
-
//
|
|
12
|
+
// build/utils/ or src/utils/ -> project root
|
|
9
13
|
return join(__dirname, "..", "..");
|
|
10
14
|
}
|
|
11
|
-
// Resolve path to the Python helper script
|
|
12
15
|
function getScriptPath() {
|
|
13
16
|
return join(getProjectRoot(), "src", "utils", "numbers_reader.py");
|
|
14
17
|
}
|
|
18
|
+
function venvPythonPath() {
|
|
19
|
+
return join(getProjectRoot(), "venv", "bin", "python3");
|
|
20
|
+
}
|
|
21
|
+
function requirementsPath() {
|
|
22
|
+
return join(getProjectRoot(), "requirements.txt");
|
|
23
|
+
}
|
|
24
|
+
function setupScriptPath() {
|
|
25
|
+
return join(getProjectRoot(), "scripts", "setup.sh");
|
|
26
|
+
}
|
|
27
|
+
// Written by scripts/setup.sh after a successful install; holds a copy of the
|
|
28
|
+
// requirements.txt the venv was built against, so we can detect a stale venv
|
|
29
|
+
// after a package update changes requirements.
|
|
30
|
+
function depsMarkerPath() {
|
|
31
|
+
return join(getProjectRoot(), "venv", ".deps-ok");
|
|
32
|
+
}
|
|
33
|
+
function readIfExists(p) {
|
|
34
|
+
try {
|
|
35
|
+
return existsSync(p) ? readFileSync(p, "utf8") : null;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
15
41
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* 3. System python
|
|
42
|
+
* True when the venv exists AND was built against the CURRENT requirements.txt.
|
|
43
|
+
* A package update that changes requirements invalidates the marker, so the
|
|
44
|
+
* server knows to rebuild rather than run against stale deps.
|
|
20
45
|
*/
|
|
21
|
-
function
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
46
|
+
function venvIsReady() {
|
|
47
|
+
if (!existsSync(venvPythonPath()))
|
|
48
|
+
return false;
|
|
49
|
+
const reqs = readIfExists(requirementsPath());
|
|
50
|
+
// If requirements.txt isn't present (unexpected), trust an existing venv.
|
|
51
|
+
if (reqs === null)
|
|
52
|
+
return true;
|
|
53
|
+
const marker = readIfExists(depsMarkerPath());
|
|
54
|
+
return marker !== null && marker.trim() === reqs.trim();
|
|
55
|
+
}
|
|
56
|
+
let cachedPython = null;
|
|
57
|
+
let readyConfirmed = false;
|
|
58
|
+
let bootstrapAttempted = false;
|
|
59
|
+
/** Reset cached interpreter + bootstrap state (useful for testing). */
|
|
60
|
+
export function _resetPythonCache() {
|
|
61
|
+
cachedPython = null;
|
|
62
|
+
readyConfirmed = false;
|
|
63
|
+
bootstrapAttempted = false;
|
|
64
|
+
}
|
|
65
|
+
function findSystemPython() {
|
|
29
66
|
for (const cmd of ["python3", "python"]) {
|
|
30
67
|
try {
|
|
31
68
|
execSync(`${cmd} --version`, { stdio: "pipe" });
|
|
@@ -37,15 +74,101 @@ function findPython() {
|
|
|
37
74
|
}
|
|
38
75
|
throw new Error('Python 3 not found. Run "npm run setup" to create a venv, or ensure python3 is on PATH.');
|
|
39
76
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Resolve a Python interpreter. The project venv is cached once present (it's
|
|
79
|
+
* stable); a system-Python fallback is deliberately NOT cached, so a venv
|
|
80
|
+
* created later (e.g. by auto-bootstrap, or a manual `npm run setup`) is picked
|
|
81
|
+
* up on the very next call WITHOUT requiring a server restart.
|
|
82
|
+
*/
|
|
83
|
+
function resolvePython() {
|
|
84
|
+
if (cachedPython && existsSync(cachedPython))
|
|
85
|
+
return cachedPython;
|
|
43
86
|
cachedPython = null;
|
|
87
|
+
const venv = venvPythonPath();
|
|
88
|
+
if (existsSync(venv)) {
|
|
89
|
+
cachedPython = venv;
|
|
90
|
+
return venv;
|
|
91
|
+
}
|
|
92
|
+
return findSystemPython();
|
|
93
|
+
}
|
|
94
|
+
function isTrueish(v) {
|
|
95
|
+
return v !== undefined && v !== "" && v !== "0" && v.toLowerCase() !== "false";
|
|
96
|
+
}
|
|
97
|
+
/** Auto-bootstrap is off under tests, or when explicitly disabled via env. */
|
|
98
|
+
function autoSetupDisabled() {
|
|
99
|
+
if (process.env.VITEST || process.env.NODE_ENV === "test")
|
|
100
|
+
return true;
|
|
101
|
+
return isTrueish(process.env[`${ENV_PREFIX}_NO_AUTO_SETUP`]);
|
|
102
|
+
}
|
|
103
|
+
function bootstrapTimeoutMs() {
|
|
104
|
+
const raw = process.env[`${ENV_PREFIX}_SETUP_TIMEOUT`];
|
|
105
|
+
if (raw !== undefined) {
|
|
106
|
+
const n = Number(raw);
|
|
107
|
+
if (Number.isFinite(n) && n > 0)
|
|
108
|
+
return n;
|
|
109
|
+
}
|
|
110
|
+
return 5 * 60 * 1000; // 5 minutes — pip install of numbers-parser can be slow.
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Create or refresh the venv by running scripts/setup.sh. Returns true on
|
|
114
|
+
* success. Progress is logged to STDERR only — stdout is the MCP protocol
|
|
115
|
+
* channel and must never be written to.
|
|
116
|
+
*/
|
|
117
|
+
function bootstrapVenv() {
|
|
118
|
+
bootstrapAttempted = true;
|
|
119
|
+
const setup = setupScriptPath();
|
|
120
|
+
if (!existsSync(setup))
|
|
121
|
+
return false;
|
|
122
|
+
console.error(`[numbers-mcp] ${PACKAGE} not ready — setting up the Python venv (one-time; this can take a minute)…`);
|
|
123
|
+
try {
|
|
124
|
+
const out = execFileSync("bash", [setup], {
|
|
125
|
+
encoding: "utf-8",
|
|
126
|
+
timeout: bootstrapTimeoutMs(),
|
|
127
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
128
|
+
env: process.env,
|
|
129
|
+
});
|
|
130
|
+
const last = out.trim().split("\n").pop() ?? "";
|
|
131
|
+
console.error(`[numbers-mcp] Python venv ready. ${last}`.trim());
|
|
132
|
+
cachedPython = null;
|
|
133
|
+
readyConfirmed = false;
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
const e = err;
|
|
138
|
+
const detail = (e.stderr?.toString() || e.stdout?.toString() || e.message || "").trim();
|
|
139
|
+
console.error(`[numbers-mcp] Automatic venv setup failed: ${detail.split("\n").pop() ?? detail}`);
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Ensure the Python deps are ready, auto-bootstrapping the venv if it's missing
|
|
145
|
+
* or stale (and auto-setup isn't disabled). Cheap and idempotent: once the venv
|
|
146
|
+
* is confirmed ready it short-circuits, and bootstrap is attempted at most once
|
|
147
|
+
* per process.
|
|
148
|
+
*/
|
|
149
|
+
function ensureReady() {
|
|
150
|
+
if (readyConfirmed)
|
|
151
|
+
return;
|
|
152
|
+
if (venvIsReady()) {
|
|
153
|
+
readyConfirmed = true;
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (bootstrapAttempted || autoSetupDisabled())
|
|
157
|
+
return;
|
|
158
|
+
if (bootstrapVenv() && venvIsReady()) {
|
|
159
|
+
readyConfirmed = true;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function looksLikeMissingDep(message) {
|
|
163
|
+
return /not installed|No module named|ModuleNotFoundError/i.test(message);
|
|
164
|
+
}
|
|
165
|
+
function setupHint() {
|
|
166
|
+
return `Run: npm run setup (or set ${ENV_PREFIX}_NO_AUTO_SETUP=0 to allow automatic setup).`;
|
|
44
167
|
}
|
|
45
168
|
const DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024; // 50MB for large spreadsheets
|
|
46
169
|
/** Max stdout bytes from the Python sidecar, overridable via env for huge files. */
|
|
47
170
|
function getMaxBuffer() {
|
|
48
|
-
const raw = process.env
|
|
171
|
+
const raw = process.env[`${ENV_PREFIX}_MAX_BUFFER`];
|
|
49
172
|
if (raw !== undefined) {
|
|
50
173
|
const n = Number(raw);
|
|
51
174
|
if (Number.isFinite(n) && n > 0)
|
|
@@ -53,12 +176,11 @@ function getMaxBuffer() {
|
|
|
53
176
|
}
|
|
54
177
|
return DEFAULT_MAX_BUFFER_BYTES;
|
|
55
178
|
}
|
|
56
|
-
|
|
57
|
-
const python =
|
|
179
|
+
function execReader(command, args, timeoutMs) {
|
|
180
|
+
const python = resolvePython();
|
|
58
181
|
const scriptPath = getScriptPath();
|
|
59
182
|
const fullArgs = [scriptPath, command, ...args];
|
|
60
|
-
|
|
61
|
-
if (debug) {
|
|
183
|
+
if (process.env.DEBUG || process.env.VERBOSE) {
|
|
62
184
|
console.error(`[numbers-mcp] ${python} ${fullArgs.join(" ")}`);
|
|
63
185
|
}
|
|
64
186
|
try {
|
|
@@ -76,25 +198,51 @@ export function runNumbersReader(command, args, timeoutMs = 30000) {
|
|
|
76
198
|
}
|
|
77
199
|
catch (err) {
|
|
78
200
|
const error = err;
|
|
79
|
-
|
|
80
|
-
|
|
201
|
+
const stderr = error.stderr?.toString().trim() ?? "";
|
|
202
|
+
if (stderr.includes(`${PACKAGE} not installed`) || looksLikeMissingDep(stderr)) {
|
|
203
|
+
return { error: `${PACKAGE} not installed. ${setupHint()}` };
|
|
81
204
|
}
|
|
82
205
|
if (error.message?.includes("ETIMEDOUT") || error.message?.includes("timed out")) {
|
|
83
206
|
return { error: `Operation timed out after ${timeoutMs}ms. File may be very large.` };
|
|
84
207
|
}
|
|
208
|
+
// Surface the Python traceback when there is one — without it the user just
|
|
209
|
+
// sees "Command failed: <python> <args>" with no clue what actually broke.
|
|
210
|
+
if (stderr) {
|
|
211
|
+
return { error: stderr };
|
|
212
|
+
}
|
|
85
213
|
return { error: error.message || "Unknown error executing Python script" };
|
|
86
214
|
}
|
|
87
215
|
}
|
|
216
|
+
export function runNumbersReader(command, args, timeoutMs = 30000) {
|
|
217
|
+
ensureReady();
|
|
218
|
+
const result = execReader(command, args, timeoutMs);
|
|
219
|
+
// Belt-and-suspenders: if the deps still look missing and we haven't tried a
|
|
220
|
+
// bootstrap yet, attempt it once and retry — covers a venv that exists but is
|
|
221
|
+
// missing the package, which the marker check alone wouldn't catch.
|
|
222
|
+
if (result.error &&
|
|
223
|
+
looksLikeMissingDep(result.error) &&
|
|
224
|
+
!bootstrapAttempted &&
|
|
225
|
+
!autoSetupDisabled()) {
|
|
226
|
+
if (bootstrapVenv()) {
|
|
227
|
+
return execReader(command, args, timeoutMs);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
88
232
|
export function checkDependencies() {
|
|
233
|
+
ensureReady();
|
|
89
234
|
try {
|
|
90
|
-
const python =
|
|
91
|
-
const version = execSync(`${python} -c "import
|
|
92
|
-
|
|
235
|
+
const python = resolvePython();
|
|
236
|
+
const version = execSync(`${python} -c "import ${MODULE}; print(${MODULE}.__version__)"`, {
|
|
237
|
+
encoding: "utf-8",
|
|
238
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
239
|
+
}).trim();
|
|
240
|
+
return { ok: true, message: `All dependencies available (${PACKAGE} ${version})` };
|
|
93
241
|
}
|
|
94
242
|
catch {
|
|
95
243
|
return {
|
|
96
244
|
ok: false,
|
|
97
|
-
message:
|
|
245
|
+
message: `${PACKAGE} not installed. ${setupHint()}`,
|
|
98
246
|
};
|
|
99
247
|
}
|
|
100
248
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"python.js","sourceRoot":"","sources":["../../src/utils/python.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"python.js","sourceRoot":"","sources":["../../src/utils/python.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,gEAAgE;AAChE,MAAM,OAAO,GAAG,gBAAgB,CAAC;AACjC,MAAM,MAAM,GAAG,gBAAgB,CAAC;AAChC,MAAM,UAAU,GAAG,mBAAmB,CAAC;AAEvC,SAAS,cAAc;IACrB,6CAA6C;IAC7C,OAAO,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,aAAa;IACpB,OAAO,IAAI,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,cAAc;IACrB,OAAO,IAAI,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO,IAAI,CAAC,cAAc,EAAE,EAAE,kBAAkB,CAAC,CAAC;AACpD,CAAC;AAED,SAAS,eAAe;IACtB,OAAO,IAAI,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AACvD,CAAC;AAED,8EAA8E;AAC9E,6EAA6E;AAC7E,+CAA+C;AAC/C,SAAS,cAAc;IACrB,OAAO,IAAI,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;AACpD,CAAC;AAED,SAAS,YAAY,CAAC,CAAS;IAC7B,IAAI,CAAC;QACH,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW;IAClB,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC;QAAE,OAAO,KAAK,CAAC;IAChD,MAAM,IAAI,GAAG,YAAY,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAC9C,0EAA0E;IAC1E,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,MAAM,GAAG,YAAY,CAAC,cAAc,EAAE,CAAC,CAAC;IAC9C,OAAO,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;AAC1D,CAAC;AAOD,IAAI,YAAY,GAAkB,IAAI,CAAC;AACvC,IAAI,cAAc,GAAG,KAAK,CAAC;AAC3B,IAAI,kBAAkB,GAAG,KAAK,CAAC;AAE/B,uEAAuE;AACvE,MAAM,UAAU,iBAAiB;IAC/B,YAAY,GAAG,IAAI,CAAC;IACpB,cAAc,GAAG,KAAK,CAAC;IACvB,kBAAkB,GAAG,KAAK,CAAC;AAC7B,CAAC;AAED,SAAS,gBAAgB;IACvB,KAAK,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,QAAQ,CAAC,GAAG,GAAG,YAAY,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YAChD,OAAO,GAAG,CAAC;QACb,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CACb,yFAAyF,CAC1F,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,aAAa;IACpB,IAAI,YAAY,IAAI,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,YAAY,CAAC;IAClE,YAAY,GAAG,IAAI,CAAC;IACpB,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,YAAY,GAAG,IAAI,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,gBAAgB,EAAE,CAAC;AAC5B,CAAC;AAED,SAAS,SAAS,CAAC,CAAqB;IACtC,OAAO,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC;AACjF,CAAC;AAED,8EAA8E;AAC9E,SAAS,iBAAiB;IACxB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACvE,OAAO,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,UAAU,gBAAgB,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,kBAAkB;IACzB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,UAAU,gBAAgB,CAAC,CAAC;IACvD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACtB,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,yDAAyD;AACjF,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa;IACpB,kBAAkB,GAAG,IAAI,CAAC;IAC1B,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAErC,OAAO,CAAC,KAAK,CACX,iBAAiB,OAAO,6EAA6E,CACtG,CAAC;IACF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE;YACxC,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,kBAAkB,EAAE;YAC7B,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;YACjC,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QAChD,OAAO,CAAC,KAAK,CAAC,oCAAoC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACjE,YAAY,GAAG,IAAI,CAAC;QACpB,cAAc,GAAG,KAAK,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,GAAqE,CAAC;QAChF,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACxF,OAAO,CAAC,KAAK,CACX,8CAA8C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,MAAM,EAAE,CACnF,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,WAAW;IAClB,IAAI,cAAc;QAAE,OAAO;IAC3B,IAAI,WAAW,EAAE,EAAE,CAAC;QAClB,cAAc,GAAG,IAAI,CAAC;QACtB,OAAO;IACT,CAAC;IACD,IAAI,kBAAkB,IAAI,iBAAiB,EAAE;QAAE,OAAO;IACtD,IAAI,aAAa,EAAE,IAAI,WAAW,EAAE,EAAE,CAAC;QACrC,cAAc,GAAG,IAAI,CAAC;IACxB,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAe;IAC1C,OAAO,oDAAoD,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,8BAA8B,UAAU,6CAA6C,CAAC;AAC/F,CAAC;AAED,MAAM,wBAAwB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,8BAA8B;AAEjF,oFAAoF;AACpF,SAAS,YAAY;IACnB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,UAAU,aAAa,CAAC,CAAC;IACpD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACtB,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,wBAAwB,CAAC;AAClC,CAAC;AAED,SAAS,UAAU,CAAI,OAAe,EAAE,IAAc,EAAE,SAAiB;IACvE,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IAEhD,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,iBAAiB,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,QAAQ,EAAE;YAC5C,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,SAAS;YAClB,SAAS,EAAE,YAAY,EAAE;YACzB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACzC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;QACjC,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,MAAW,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,GAA4D,CAAC;QAC3E,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;QAErD,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,OAAO,gBAAgB,CAAC,IAAI,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/E,OAAO,EAAE,KAAK,EAAE,GAAG,OAAO,mBAAmB,SAAS,EAAE,EAAE,EAAE,CAAC;QAC/D,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACjF,OAAO,EAAE,KAAK,EAAE,6BAA6B,SAAS,6BAA6B,EAAE,CAAC;QACxF,CAAC;QACD,4EAA4E;QAC5E,2EAA2E;QAC3E,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAC3B,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,IAAI,uCAAuC,EAAE,CAAC;IAC7E,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,IAAc,EACd,SAAS,GAAG,KAAK;IAEjB,WAAW,EAAE,CAAC;IACd,MAAM,MAAM,GAAG,UAAU,CAAI,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAEvD,6EAA6E;IAC7E,8EAA8E;IAC9E,oEAAoE;IACpE,IACE,MAAM,CAAC,KAAK;QACZ,mBAAmB,CAAC,MAAM,CAAC,KAAK,CAAC;QACjC,CAAC,kBAAkB;QACnB,CAAC,iBAAiB,EAAE,EACpB,CAAC;QACD,IAAI,aAAa,EAAE,EAAE,CAAC;YACpB,OAAO,UAAU,CAAI,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,WAAW,EAAE,CAAC;IACd,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,MAAM,eAAe,MAAM,WAAW,MAAM,gBAAgB,EAAE;YACxF,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,+BAA+B,OAAO,IAAI,OAAO,GAAG,EAAE,CAAC;IACrF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,GAAG,OAAO,mBAAmB,SAAS,EAAE,EAAE;SACpD,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
package/scripts/setup.sh
CHANGED
|
@@ -43,4 +43,8 @@ echo "==> Installing numbers-parser..."
|
|
|
43
43
|
echo "==> Verifying installation..."
|
|
44
44
|
"$VENV_DIR/bin/python3" -c "import numbers_parser; print(f' numbers-parser {numbers_parser.__version__} installed')"
|
|
45
45
|
|
|
46
|
+
# Record which requirements.txt this venv was built against, so the server can
|
|
47
|
+
# detect a stale venv after an update changes requirements and rebuild itself.
|
|
48
|
+
cp "$PROJECT_ROOT/requirements.txt" "$VENV_DIR/.deps-ok"
|
|
49
|
+
|
|
46
50
|
echo "==> Done! Python venv ready."
|