@rex0220/formula-authoring-tools 0.2.0 → 0.2.1

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 CHANGED
@@ -59,5 +59,6 @@ npm pack --dry-run # 公開前に中身を確かめる(dist、vendor、LICENS
59
59
 
60
60
  ## 履歴
61
61
 
62
+ - 0.2.1(2026-10): formula MCP の Codex レビューへの対応。`updateFields` の `common` を共通の設定のキー(`COMMON_KEYS`)だけに。Worker の中の誤りの種類(`EvalError.kind`)と名前を中核が instanceof で決める(zip のコードの例外の name / constructor.name / 文を応答や標準エラーに出さない。`classifyEvalError` / `builtinErrorName`)。保存の結果の想定外の誤りも種類だけ(`zipCode`)。CLI の想定外の誤りは種類だけ(`FORMULA_DEBUG=1` で文とスタック)。接続の誤りの文の print-craft の名残を直した
62
63
  - 0.2.0(2026-10): formula MCP のための中核の入口(`CORE_API_VERSION` 2。CLI の動きは変えない)。`core` に workspace / connections / permission / commit-file / take / users の参照コード / JSON の誤りの文 / 行のキーを追加。`src/commands/save.ts`(`saveNewSettings` / `updateFields`)。`runEval` の `workerFile`(Worker の入口の絶対パス)と `captureOutput`(Worker の標準出力・標準エラーを親に流さず受け取る)、`loadEngine` の `vendorDir`(moment の置き場所)。評価の結果に `findings` と calc のレコードごとの行
63
64
  - 0.1.0(2026-10): 最初の公開。version / fields / record / records / pull / summary / diff / users / normalize / calc / take / edit / files。扱う計算式プラグイン Ver.101 以降、authoring API 1
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- /*! @rex0220/formula-authoring-tools 0.2.0 (c) rex0220. MIT License. 計算式エンジンと計算式プラグインのコードは利用者の計算式プラグインプラグインの zip から読む(このファイルには含まれない)。commit 1e50847. */
2
+ /*! @rex0220/formula-authoring-tools 0.2.1 (c) rex0220. MIT License. 計算式エンジンと計算式プラグインのコードは利用者の計算式プラグインプラグインの zip から読む(このファイルには含まれない)。commit f2e46ef. */
3
3
 
4
4
  // src/cli.ts
5
5
  import { chmodSync, existsSync as existsSync9, mkdirSync as mkdirSync2, realpathSync as realpathSync5, writeFileSync as writeFileSync3 } from "node:fs";
@@ -355,7 +355,7 @@ function devMeta() {
355
355
  return { toolsVersion: pkg.version, pluginId: FORMULA_PLUGIN_ID, minPluginVersion: MIN_PLUGIN_VERSION, supportedApiVersions: [...SUPPORTED_API_VERSIONS], commit: gitCommit(AUTHORING_ROOT), builtAt: "", mode: "dev" };
356
356
  }
357
357
  function toolsMeta() {
358
- if (true) return JSON.parse('{"toolsVersion":"0.2.0","pluginId":"dhgihghfgfmibkdldkeibboabfnmdpke","minPluginVersion":101,"supportedApiVersions":[1],"commit":"1e50847","builtAt":"2026-10-18T02:11:59.644Z","mode":"build"}');
358
+ if (true) return JSON.parse('{"toolsVersion":"0.2.1","pluginId":"dhgihghfgfmibkdldkeibboabfnmdpke","minPluginVersion":101,"supportedApiVersions":[1],"commit":"f2e46ef","builtAt":"2026-10-18T03:55:45.474Z","mode":"build"}');
359
359
  return devMeta();
360
360
  }
361
361
 
@@ -1401,7 +1401,7 @@ function authFor(set, profile, appId) {
1401
1401
  if (value === void 0) throw new ConnectionError(`profile「${profile.profile}」の tokenMap に APP${appId} が無い(そのアプリの API トークンを足す)`, "no-token");
1402
1402
  if (value.startsWith("env:")) {
1403
1403
  const token = nonblank(held.env[value.slice(4)]);
1404
- if (!token) throw new ConnectionError(`profile「${profile.profile}」の APP${appId} のトークンの環境変数が無い(設定した後、print-craft を再接続する。Desktop は起動し直す)`, "env-missing");
1404
+ if (!token) throw new ConnectionError(`profile「${profile.profile}」の APP${appId} のトークンの環境変数が無い(環境変数を置いてから実行し直す。MCP なら再接続する: Claude Code は /mcp、Desktop は起動し直す)`, "env-missing");
1405
1405
  return { baseUrl: profile.baseUrl, token };
1406
1406
  }
1407
1407
  return { baseUrl: profile.baseUrl, token: value };
@@ -3079,6 +3079,22 @@ function calcSettings(input) {
3079
3079
  }
3080
3080
 
3081
3081
  // src/worker/eval-run.ts
3082
+ function classifyEvalError(e) {
3083
+ const message = String(e?.message ?? e);
3084
+ if (e instanceof InputError) return { kind: "input", name: "InputError", message };
3085
+ if (e instanceof PluginZipError) return { kind: "zip", name: "PluginZipError", message, code: e.code };
3086
+ if (e instanceof UsersDataError) return { kind: "users", name: "UsersDataError", message };
3087
+ if (e instanceof PolicyError) return { kind: "policy", name: "PolicyError", message };
3088
+ return { kind: "other", name: builtinErrorName(e), message };
3089
+ }
3090
+ function builtinErrorName(e) {
3091
+ if (e instanceof TypeError) return "TypeError";
3092
+ if (e instanceof RangeError) return "RangeError";
3093
+ if (e instanceof ReferenceError) return "ReferenceError";
3094
+ if (e instanceof SyntaxError) return "SyntaxError";
3095
+ if (e instanceof URIError) return "URIError";
3096
+ return "Error";
3097
+ }
3082
3098
  async function runEvalJob(job) {
3083
3099
  const engine = await loadEngine({ pluginZip: job.pluginZip, devPluginDir: job.devPluginDir, mode: job.mode, vendorDir: job.vendorDir });
3084
3100
  if (job.baseUrl) engine.setContext({ baseUrl: job.baseUrl });
@@ -3137,10 +3153,12 @@ var EvalTimeoutError = class extends Error {
3137
3153
  var EvalError = class extends Error {
3138
3154
  innerName;
3139
3155
  code;
3140
- constructor(message, innerName, code) {
3156
+ kind;
3157
+ constructor(message, innerName, code, kind = "other") {
3141
3158
  super(message);
3142
3159
  this.innerName = innerName;
3143
3160
  this.code = code;
3161
+ this.kind = kind;
3144
3162
  }
3145
3163
  };
3146
3164
  function workerEntry() {
@@ -3154,7 +3172,14 @@ function workerEntry() {
3154
3172
  }
3155
3173
  async function runEval(job, opt = {}) {
3156
3174
  const timeoutSec = Math.min(Math.max(opt.timeoutSec ?? DEFAULT_TIMEOUT_SEC, 1), MAX_TIMEOUT_SEC);
3157
- if (opt.inline) return runEvalJob(job);
3175
+ if (opt.inline) {
3176
+ try {
3177
+ return await runEvalJob(job);
3178
+ } catch (e) {
3179
+ const c = classifyEvalError(e);
3180
+ throw new EvalError(c.message, c.name, c.code, c.kind);
3181
+ }
3182
+ }
3158
3183
  let entry;
3159
3184
  if (opt.workerFile !== void 0) {
3160
3185
  if (!path13.isAbsolute(opt.workerFile) || !existsSync8(opt.workerFile)) throw new Error(`Worker の入口が無い(絶対パスで指定する): ${opt.workerFile}`);
@@ -3183,10 +3208,10 @@ async function runEval(job, opt = {}) {
3183
3208
  worker.on("message", (m) => {
3184
3209
  finish(() => {
3185
3210
  if (m.ok) resolve(m.outcome);
3186
- else reject(new EvalError(m.error.message, m.error.name, m.error.code));
3211
+ else reject(new EvalError(m.error.message, m.error.name, m.error.code, m.error.kind ?? "other"));
3187
3212
  });
3188
3213
  });
3189
- worker.on("error", (e) => finish(() => reject(e)));
3214
+ worker.on("error", (e) => finish(() => reject(new EvalError(e?.message ?? String(e), builtinErrorName(e), void 0, "other"))));
3190
3215
  worker.on("exit", (code) => finish(() => reject(new Error(`評価の Worker が結果を返さずに終わった(exit ${code})`))));
3191
3216
  });
3192
3217
  }
@@ -3792,13 +3817,18 @@ ${USAGE}`);
3792
3817
  return 1;
3793
3818
  }
3794
3819
  if (e instanceof EvalError) {
3795
- if (["PluginZipError", "InputError", "UsersDataError", "PolicyError", "AuthError"].includes(e.innerName)) {
3820
+ if (e.kind !== "other") {
3796
3821
  console.error(e.message);
3797
3822
  return 1;
3798
3823
  }
3799
- throw new Error(`${e.innerName}: ${e.message}`);
3824
+ console.error(`評価の途中で想定外の誤り(${e.innerName})。誤りの文は値を含みうるので表示しない(FORMULA_DEBUG=1 で表示)。normalize で設定を、version で zip を確かめる`);
3825
+ if (W.env.FORMULA_DEBUG === "1") console.error(e.message);
3826
+ return 1;
3800
3827
  }
3801
- throw e;
3828
+ const name = builtinErrorName(e);
3829
+ console.error(`想定外の誤り(${name})。誤りの文は値を含みうるので表示しない(FORMULA_DEBUG=1 で表示)`);
3830
+ if (W.env.FORMULA_DEBUG === "1") console.error(e instanceof Error ? e.stack ?? e.message : String(e));
3831
+ return 1;
3802
3832
  }
3803
3833
  }
3804
3834
  var invokedRaw = process.argv[1] ? path14.resolve(process.argv[1]) : "";
@@ -3817,6 +3847,9 @@ try {
3817
3847
  if (invoked && (invoked === self || /[\\/]dist[\\/]cli\.mjs$/.test(invoked))) {
3818
3848
  main(process.argv.slice(2)).then((code) => {
3819
3849
  process.exitCode = code;
3850
+ }, (e) => {
3851
+ console.error(`想定外の誤り(${builtinErrorName(e)})`);
3852
+ process.exitCode = 1;
3820
3853
  });
3821
3854
  }
3822
3855
  export {
package/dist/core.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! @rex0220/formula-authoring-tools/core 0.2.0 (c) rex0220. MIT License. 計算式エンジンと計算式プラグインのコードは利用者の計算式プラグインプラグインの zip から読む(このファイルには含まれない)。commit 1e50847. */
1
+ /*! @rex0220/formula-authoring-tools/core 0.2.1 (c) rex0220. MIT License. 計算式エンジンと計算式プラグインのコードは利用者の計算式プラグインプラグインの zip から読む(このファイルには含まれない)。commit f2e46ef. */
2
2
 
3
3
  // src/safe-path.ts
4
4
  import { lstatSync, realpathSync } from "node:fs";
@@ -190,7 +190,7 @@ function devMeta() {
190
190
  return { toolsVersion: pkg.version, pluginId: FORMULA_PLUGIN_ID, minPluginVersion: MIN_PLUGIN_VERSION, supportedApiVersions: [...SUPPORTED_API_VERSIONS], commit: gitCommit(AUTHORING_ROOT), builtAt: "", mode: "dev" };
191
191
  }
192
192
  function toolsMeta() {
193
- if (true) return JSON.parse('{"toolsVersion":"0.2.0","pluginId":"dhgihghfgfmibkdldkeibboabfnmdpke","minPluginVersion":101,"supportedApiVersions":[1],"commit":"1e50847","builtAt":"2026-10-18T02:11:59.644Z","mode":"build"}');
193
+ if (true) return JSON.parse('{"toolsVersion":"0.2.1","pluginId":"dhgihghfgfmibkdldkeibboabfnmdpke","minPluginVersion":101,"supportedApiVersions":[1],"commit":"f2e46ef","builtAt":"2026-10-18T03:55:45.474Z","mode":"build"}');
194
194
  return devMeta();
195
195
  }
196
196
 
@@ -2649,7 +2649,7 @@ function authFor(set, profile, appId) {
2649
2649
  if (value === void 0) throw new ConnectionError(`profile「${profile.profile}」の tokenMap に APP${appId} が無い(そのアプリの API トークンを足す)`, "no-token");
2650
2650
  if (value.startsWith("env:")) {
2651
2651
  const token = nonblank(held.env[value.slice(4)]);
2652
- if (!token) throw new ConnectionError(`profile「${profile.profile}」の APP${appId} のトークンの環境変数が無い(設定した後、print-craft を再接続する。Desktop は起動し直す)`, "env-missing");
2652
+ if (!token) throw new ConnectionError(`profile「${profile.profile}」の APP${appId} のトークンの環境変数が無い(環境変数を置いてから実行し直す。MCP なら再接続する: Claude Code は /mcp、Desktop は起動し直す)`, "env-missing");
2653
2653
  return { baseUrl: profile.baseUrl, token };
2654
2654
  }
2655
2655
  return { baseUrl: profile.baseUrl, token: value };
@@ -3227,6 +3227,22 @@ import { fileURLToPath as fileURLToPath2 } from "node:url";
3227
3227
  import path13 from "node:path";
3228
3228
 
3229
3229
  // src/worker/eval-run.ts
3230
+ function classifyEvalError(e) {
3231
+ const message = String(e?.message ?? e);
3232
+ if (e instanceof InputError) return { kind: "input", name: "InputError", message };
3233
+ if (e instanceof PluginZipError) return { kind: "zip", name: "PluginZipError", message, code: e.code };
3234
+ if (e instanceof UsersDataError) return { kind: "users", name: "UsersDataError", message };
3235
+ if (e instanceof PolicyError) return { kind: "policy", name: "PolicyError", message };
3236
+ return { kind: "other", name: builtinErrorName(e), message };
3237
+ }
3238
+ function builtinErrorName(e) {
3239
+ if (e instanceof TypeError) return "TypeError";
3240
+ if (e instanceof RangeError) return "RangeError";
3241
+ if (e instanceof ReferenceError) return "ReferenceError";
3242
+ if (e instanceof SyntaxError) return "SyntaxError";
3243
+ if (e instanceof URIError) return "URIError";
3244
+ return "Error";
3245
+ }
3230
3246
  async function runEvalJob(job) {
3231
3247
  const engine = await loadEngine({ pluginZip: job.pluginZip, devPluginDir: job.devPluginDir, mode: job.mode, vendorDir: job.vendorDir });
3232
3248
  if (job.baseUrl) engine.setContext({ baseUrl: job.baseUrl });
@@ -3285,10 +3301,12 @@ var EvalTimeoutError = class extends Error {
3285
3301
  var EvalError = class extends Error {
3286
3302
  innerName;
3287
3303
  code;
3288
- constructor(message, innerName, code) {
3304
+ kind;
3305
+ constructor(message, innerName, code, kind = "other") {
3289
3306
  super(message);
3290
3307
  this.innerName = innerName;
3291
3308
  this.code = code;
3309
+ this.kind = kind;
3292
3310
  }
3293
3311
  };
3294
3312
  function workerEntry() {
@@ -3302,7 +3320,14 @@ function workerEntry() {
3302
3320
  }
3303
3321
  async function runEval(job, opt = {}) {
3304
3322
  const timeoutSec = Math.min(Math.max(opt.timeoutSec ?? DEFAULT_TIMEOUT_SEC, 1), MAX_TIMEOUT_SEC);
3305
- if (opt.inline) return runEvalJob(job);
3323
+ if (opt.inline) {
3324
+ try {
3325
+ return await runEvalJob(job);
3326
+ } catch (e) {
3327
+ const c = classifyEvalError(e);
3328
+ throw new EvalError(c.message, c.name, c.code, c.kind);
3329
+ }
3330
+ }
3306
3331
  let entry;
3307
3332
  if (opt.workerFile !== void 0) {
3308
3333
  if (!path13.isAbsolute(opt.workerFile) || !existsSync7(opt.workerFile)) throw new Error(`Worker の入口が無い(絶対パスで指定する): ${opt.workerFile}`);
@@ -3331,10 +3356,10 @@ async function runEval(job, opt = {}) {
3331
3356
  worker.on("message", (m) => {
3332
3357
  finish2(() => {
3333
3358
  if (m.ok) resolve(m.outcome);
3334
- else reject(new EvalError(m.error.message, m.error.name, m.error.code));
3359
+ else reject(new EvalError(m.error.message, m.error.name, m.error.code, m.error.kind ?? "other"));
3335
3360
  });
3336
3361
  });
3337
- worker.on("error", (e) => finish2(() => reject(e)));
3362
+ worker.on("error", (e) => finish2(() => reject(new EvalError(e?.message ?? String(e), builtinErrorName(e), void 0, "other"))));
3338
3363
  worker.on("exit", (code) => finish2(() => reject(new Error(`評価の Worker が結果を返さずに終わった(exit ${code})`))));
3339
3364
  });
3340
3365
  }
@@ -3342,6 +3367,7 @@ async function runEval(job, opt = {}) {
3342
3367
  // src/commands/save.ts
3343
3368
  var MAX_SAVE_INPUT_BYTES = 256 * 1024;
3344
3369
  var MAX_UPDATE_ROWS = 50;
3370
+ var COMMON_KEYS2 = ["pluginEnable", "pluginProductEnv", "toolEnable", "pluginComment", "pluginDescription", "pluginBtnInfo", "pluginListInfo", "authority", "pluginMiscInfo"];
3345
3371
  function digestOf(text) {
3346
3372
  return createHash4("sha256").update(text).digest("hex");
3347
3373
  }
@@ -3430,7 +3456,7 @@ function statusOf(e) {
3430
3456
  if (e instanceof ConflictError || e instanceof FileExistsError || e instanceof LockBusyError) return "conflict";
3431
3457
  if (e instanceof SaveDenied || e instanceof PermissionError || e instanceof PathError) return "denied";
3432
3458
  if (e instanceof InputError || e instanceof SyntaxError) return "invalid";
3433
- if (e instanceof EvalError && e.innerName === "InputError") return "invalid";
3459
+ if (e instanceof EvalError && e.kind === "input") return "invalid";
3434
3460
  return "failed";
3435
3461
  }
3436
3462
  function connectionStatusOf(e) {
@@ -3453,12 +3479,20 @@ function codeOf(e) {
3453
3479
  if (e instanceof ConnectionError) return e.code;
3454
3480
  if (e instanceof ConflictError || e instanceof FileExistsError || e instanceof LockBusyError) return "ConflictError";
3455
3481
  if (e instanceof SaveDenied || e instanceof PermissionError) return "PermissionError";
3456
- if (e instanceof EvalError) return e.innerName;
3482
+ if (e instanceof EvalError) return { input: "InputError", zip: "PluginZipError", users: "UsersDataError", policy: "PolicyError", other: e.innerName }[e.kind];
3457
3483
  if (e instanceof EvalTimeoutError) return "EvalTimeoutError";
3458
- return e instanceof Error ? e.constructor.name : "Error";
3484
+ if (e instanceof InputError) return "InputError";
3485
+ if (e instanceof PathError) return "PathError";
3486
+ return builtinErrorName(e);
3487
+ }
3488
+ function safeMessageOf(e) {
3489
+ if (e instanceof ConnectionError || e instanceof ConflictError || e instanceof FileExistsError || e instanceof LockBusyError || e instanceof SaveDenied || e instanceof PermissionError || e instanceof PathError || e instanceof InputError || e instanceof EvalTimeoutError) return e.message;
3490
+ if (e instanceof EvalError) return e.kind === "other" ? `評価の途中で想定外の誤り(${e.innerName})。誤りの文は値やパスを含みうるので返さない` : e.message;
3491
+ if (e instanceof SyntaxError) return "JSON の構文の誤り(中身は返さない)";
3492
+ return `想定外の誤り(${builtinErrorName(e)})。誤りの文は値やパスを含みうるので返さない`;
3459
3493
  }
3460
3494
  function errorResult(root, target, e, findings = []) {
3461
- return { status: statusOf(e), code: codeOf(e), path: rel(root, target), findings, message: e instanceof Error ? e.message : String(e) };
3495
+ return { status: statusOf(e), code: codeOf(e), path: rel(root, target), findings, message: safeMessageOf(e), ...e instanceof EvalError && e.kind === "zip" && e.code ? { zipCode: e.code } : {} };
3462
3496
  }
3463
3497
  function finish(ctx, target, outcome, run, extra = {}) {
3464
3498
  const findings = outcome.normalize.findings;
@@ -3532,9 +3566,11 @@ function parseRows(text, current) {
3532
3566
  }
3533
3567
  function parseCommon(text) {
3534
3568
  const v = parseInput(text, "common");
3535
- if (!isPlainObject2(v)) throw new InputError("common は最上位のキー(pluginMiscInfo、pluginListInfo、authority、pluginEnable など)を持つオブジェクト");
3536
- const bad = Object.keys(v).filter((k) => k === "pluginInfos" || ENVELOPE_KEYS2.includes(k));
3537
- if (bad.length) throw new InputError(`common で変えられないキー: ${bad.join(", ")}(項目の行は rows、封筒(appId など)は変えない)`);
3569
+ if (!isPlainObject2(v)) throw new InputError(`common は共通の設定のキー(${COMMON_KEYS2.join("、")})を持つオブジェクト`);
3570
+ const fixed = Object.keys(v).filter((k) => k === "pluginInfos" || ENVELOPE_KEYS2.includes(k));
3571
+ if (fixed.length) throw new InputError(`common で変えられないキー: ${fixed.join(", ")}(項目の行は rows、封筒(appId など)は変えない)`);
3572
+ const unknown = Object.keys(v).filter((k) => !COMMON_KEYS2.includes(k));
3573
+ if (unknown.length) throw new InputError(`common に共通の設定でないキーがある: ${unknown.join(", ")}(使えるのは ${COMMON_KEYS2.join("、")})`);
3538
3574
  if (!Object.keys(v).length) throw new InputError("common が空(変えないなら渡さない)");
3539
3575
  return v;
3540
3576
  }
@@ -3607,6 +3643,7 @@ export {
3607
3643
  ALLOWED_USER_APIS,
3608
3644
  APP_MARKER,
3609
3645
  AuthError,
3646
+ COMMON_KEYS2 as COMMON_KEYS,
3610
3647
  CONNECTION_MAX_BYTES,
3611
3648
  CORE_API_VERSION,
3612
3649
  ConnectionError,
@@ -3679,8 +3716,10 @@ export {
3679
3716
  baseUrlFromEnv,
3680
3717
  bodyOf,
3681
3718
  buildUsersInfo,
3719
+ builtinErrorName,
3682
3720
  calcSettings,
3683
3721
  classOfAppPath,
3722
+ classifyEvalError,
3684
3723
  cleanupAll,
3685
3724
  connectionStatusOf,
3686
3725
  contextTargetsOf,
@@ -93,7 +93,7 @@ function devMeta() {
93
93
  return { toolsVersion: pkg.version, pluginId: FORMULA_PLUGIN_ID, minPluginVersion: MIN_PLUGIN_VERSION, supportedApiVersions: [...SUPPORTED_API_VERSIONS], commit: gitCommit(AUTHORING_ROOT), builtAt: "", mode: "dev" };
94
94
  }
95
95
  function toolsMeta() {
96
- if (true) return JSON.parse('{"toolsVersion":"0.2.0","pluginId":"dhgihghfgfmibkdldkeibboabfnmdpke","minPluginVersion":101,"supportedApiVersions":[1],"commit":"1e50847","builtAt":"2026-10-18T02:11:59.644Z","mode":"build"}');
96
+ if (true) return JSON.parse('{"toolsVersion":"0.2.1","pluginId":"dhgihghfgfmibkdldkeibboabfnmdpke","minPluginVersion":101,"supportedApiVersions":[1],"commit":"f2e46ef","builtAt":"2026-10-18T03:55:45.474Z","mode":"build"}');
97
97
  return devMeta();
98
98
  }
99
99
 
@@ -326,6 +326,8 @@ var DEFAULT_USERS = {
326
326
  };
327
327
 
328
328
  // src/users/index.ts
329
+ var UsersDataError = class extends Error {
330
+ };
329
331
  function buildUsersInfo(src) {
330
332
  const t = { users: [], organizations: [], groups: [], userCodes: {}, orgCodes: {}, groupCodes: {}, userIds: {}, orgIds: {}, groupIds: {} };
331
333
  const orgsOf = {};
@@ -739,6 +741,8 @@ var ROW_SOURCE_KEYS = ["fieldcode", "state", "formulaSet", "edit", "hide", "rank
739
741
 
740
742
  // src/normalize/policy.ts
741
743
  import path4 from "node:path";
744
+ var PolicyError = class extends Error {
745
+ };
742
746
  var POLICY_FILE = path4.join("policy", "authoring-policy.json");
743
747
  var MAX_POLICY_BYTES = 64 * 1024;
744
748
  var DEFAULT_POLICY = { allowFunctions: [], allowMiscChanges: false };
@@ -1262,6 +1266,22 @@ function calcSettings(input) {
1262
1266
  }
1263
1267
 
1264
1268
  // src/worker/eval-run.ts
1269
+ function classifyEvalError(e) {
1270
+ const message = String(e?.message ?? e);
1271
+ if (e instanceof InputError) return { kind: "input", name: "InputError", message };
1272
+ if (e instanceof PluginZipError) return { kind: "zip", name: "PluginZipError", message, code: e.code };
1273
+ if (e instanceof UsersDataError) return { kind: "users", name: "UsersDataError", message };
1274
+ if (e instanceof PolicyError) return { kind: "policy", name: "PolicyError", message };
1275
+ return { kind: "other", name: builtinErrorName(e), message };
1276
+ }
1277
+ function builtinErrorName(e) {
1278
+ if (e instanceof TypeError) return "TypeError";
1279
+ if (e instanceof RangeError) return "RangeError";
1280
+ if (e instanceof ReferenceError) return "ReferenceError";
1281
+ if (e instanceof SyntaxError) return "SyntaxError";
1282
+ if (e instanceof URIError) return "URIError";
1283
+ return "Error";
1284
+ }
1265
1285
  async function runEvalJob(job) {
1266
1286
  const engine = await loadEngine({ pluginZip: job.pluginZip, devPluginDir: job.devPluginDir, mode: job.mode, vendorDir: job.vendorDir });
1267
1287
  if (job.baseUrl) engine.setContext({ baseUrl: job.baseUrl });
@@ -1316,9 +1336,4 @@ async function runEvalJob(job) {
1316
1336
  var post = (m) => {
1317
1337
  parentPort?.postMessage(m);
1318
1338
  };
1319
- runEvalJob(workerData).then((outcome) => post({ ok: true, outcome })).catch((e) => {
1320
- const err = e;
1321
- const own = err?.name && err.name !== "Error" ? err.name : void 0;
1322
- const name = own ?? err?.constructor?.name ?? "Error";
1323
- post({ ok: false, error: { name: String(name), message: String(err?.message ?? e), ...err?.code ? { code: String(err.code) } : {} } });
1324
- });
1339
+ runEvalJob(workerData).then((outcome) => post({ ok: true, outcome })).catch((e) => post({ ok: false, error: classifyEvalError(e) }));
@@ -25,6 +25,8 @@ export interface SaveResult {
25
25
  message?: string;
26
26
  /** status が ok でないときの誤りの種類(ConflictError、PermissionError、PathError、InputError、NormalizeError、接続の誤りの code など。想定外の失敗は Error) */
27
27
  code?: string;
28
+ /** code が PluginZipError のときの、zip の誤りの種類(MCP が種類ごとの決まった文にする) */
29
+ zipCode?: string;
28
30
  /** ok だが、確定の後に一時ファイルかロックを消せなかった(確定はしている。利用者に伝えて消してもらう) */
29
31
  cleanup?: string[];
30
32
  }
@@ -58,6 +60,8 @@ export interface SaveContext {
58
60
  export declare const MAX_SAVE_INPUT_BYTES: number;
59
61
  /** updateFields の rows の行数の上限 */
60
62
  export declare const MAX_UPDATE_ROWS = 50;
63
+ /** updateFields の common で置き換えられる共通の設定のキー(封筒と pluginInfos 以外の最上位のキー。設定ファイル仕様の順。Codex のレビュー MAJOR 4) */
64
+ export declare const COMMON_KEYS: readonly string[];
61
65
  /** ファイルの digest(sha256。fml_summary が返し、fml_update_fields が照合する) */
62
66
  export declare function digestOf(text: string | Buffer): string;
63
67
  /** 接続の誤りの状態(print-craft MCP の 15.10 の表) */
@@ -27,13 +27,13 @@ export { DEFAULT_MAX_CALLS, USER_INFO_FUNCTIONS, UsersPullError, pullReferencedU
27
27
  export { normalizeSettings, findCycles, stronglyConnected, type ContextNeeds, type NormalizeInput, type NormalizeResult } from "./commands/normalize.ts";
28
28
  export { DEFAULT_EVENT, EVENT_RE, RECORDS_MAX, calcSettings, validateEvent, type CalcInput, type CalcLine, type CalcRecordResult, type CalcResult } from "./commands/calc.ts";
29
29
  export { takeInbox, type TakeResult } from "./commands/take.ts";
30
- export { MAX_SAVE_INPUT_BYTES, MAX_UPDATE_ROWS, connectionStatusOf, digestOf, saveNewSettings, updateFields, type EvalSource, type SaveContext, type SaveResult, type SaveStatus } from "./commands/save.ts";
30
+ export { COMMON_KEYS, MAX_SAVE_INPUT_BYTES, MAX_UPDATE_ROWS, connectionStatusOf, digestOf, saveNewSettings, updateFields, type EvalSource, type SaveContext, type SaveResult, type SaveStatus } from "./commands/save.ts";
31
31
  export { DEFAULT_POLICY, POLICY_FILE, PolicyError, loadPolicy, parsePolicy, type Policy } from "./normalize/policy.ts";
32
32
  export { Findings, type Finding, type Level } from "./normalize/findings.ts";
33
33
  export { ENVELOPE_KEYS, OUTER_KEYS, ROW_SCREEN_KEYS, ROW_SOURCE_KEYS, materialsOf, viewsOf, type FormulaSaved, type FormulaSource, type Lang } from "./normalize/model.ts";
34
34
  export { DEFAULT_TIMEOUT_SEC, EvalError, EvalTimeoutError, MAX_TIMEOUT_SEC, runEval, type RunOptions } from "./worker/run.ts";
35
- export { runEvalJob } from "./worker/eval-run.ts";
36
- export type { EvalJob, EvalMessage, EvalOutcome } from "./worker/eval-job.ts";
35
+ export { builtinErrorName, classifyEvalError, runEvalJob } from "./worker/eval-run.ts";
36
+ export type { EvalErrorKind, EvalJob, EvalMessage, EvalOutcome } from "./worker/eval-job.ts";
37
37
  export { APP_MARKER, EDIT_RE, INBOX, KINTONE_ROOT, LEGACY_WORKSPACE_FILE, SNAPSHOT_PREFIX, SNAPSHOT_RE, WorkspaceError, appDirFor, appFolderOfFile, appFoldersOf, assertAppMark, assertInsideWorkspace, assertUsableInKintone, editNameOf, ensureAppFolder, findAppDir, folderNameOf, hasLegacyConfig, legacyBlockedError, listAppFolder, markOf, modeOf, profileDirOf, readAppMark, requireProfiles, snapshotNameOf, unusedProfileDirs, type AppFolderList, type AppMark, type AppMarkState, type ModeOptions, type ProfilesContext, type WorkspaceMode } from "./workspace.ts";
38
38
  export { CONNECTION_MAX_BYTES, ConnectionError, FALLBACK_PROFILE, PROFILE_NAME_RE, assertSameConnection, authFor, identityOf, loadConnections, pickProfile, sameIdentity, semanticDigest, snapshotOf, userApiAuthFor, type ConnectionErrorCode, type ConnectionSet, type ConnectionSnapshot, type Env, type LoadConnectionsOptions, type ProfileDef, type ProfileIdentity } from "./connections.ts";
39
39
  export { PermissionError, assertChangeAllowed, classOfAppPath, type ChangeOp, type TargetClass } from "./permission.ts";
@@ -71,12 +71,18 @@ export interface EvalOutcome {
71
71
  /** エンジンの読み込みの注意 */
72
72
  engineWarnings: string[];
73
73
  }
74
+ /**
75
+ * Worker の中の誤りの種類(信頼できる境界 = 中核の eval-run.ts が instanceof で決める。zip のコードが name を偽装しても変わらない。Codex の r2 レビュー R1):
76
+ * input(中核の InputError)、zip(PluginZipError。code 付き)、users(UsersDataError)、policy(PolicyError)、other(zip のコードの例外など。文は信用しない)
77
+ */
78
+ export type EvalErrorKind = "input" | "zip" | "users" | "policy" | "other";
74
79
  export type EvalMessage = {
75
80
  ok: true;
76
81
  outcome: EvalOutcome;
77
82
  } | {
78
83
  ok: false;
79
84
  error: {
85
+ kind: EvalErrorKind;
80
86
  name: string;
81
87
  message: string;
82
88
  code?: string;
@@ -1,2 +1,12 @@
1
- import type { EvalJob, EvalOutcome } from "./eval-job.ts";
1
+ import type { EvalJob, EvalMessage, EvalOutcome } from "./eval-job.ts";
2
+ /**
3
+ * Worker の中の誤りを種類に分ける(instanceof で。中核のクラスは zip のコードから届かないので、name の偽装では input / zip にならない)。
4
+ * name も instanceof で決めた固定の名前(中核のクラスの名前か、JavaScript の組み込みの Error の名前。例外の name / constructor.name は使わない =
5
+ * zip のコードが name に値やパスを入れても出ない。Codex の r3 レビュー N1)。文は other のときは信用しない(呼ぶ側が決まった文にする)
6
+ */
7
+ export declare function classifyEvalError(e: unknown): Extract<EvalMessage, {
8
+ ok: false;
9
+ }>["error"];
10
+ /** JavaScript の組み込みの Error の種類(instanceof。同じ realm で動く zip のコードの例外も、この判定は偽装できない)。それ以外は Error */
11
+ export declare function builtinErrorName(e: unknown): string;
2
12
  export declare function runEvalJob(job: EvalJob): Promise<EvalOutcome>;
@@ -1,13 +1,17 @@
1
- import type { EvalJob, EvalOutcome } from "./eval-job.ts";
1
+ import type { EvalErrorKind, EvalJob, EvalOutcome } from "./eval-job.ts";
2
2
  export declare const DEFAULT_TIMEOUT_SEC = 60;
3
3
  export declare const MAX_TIMEOUT_SEC = 600;
4
4
  export declare class EvalTimeoutError extends Error {
5
5
  }
6
- /** Worker の中の誤り(name / code を持って主スレッドに戻す) */
6
+ /**
7
+ * Worker の中の誤り(kind / name / code を持って主スレッドに戻す)。kind は中核が instanceof で決めた信頼できる種類(input / zip / users / policy / other)。
8
+ * innerName は参考の名前(other のときは zip のコードが付けた名前かもしれない)。other のときの文は値やパスを含みうる(MCP は返さない)
9
+ */
7
10
  export declare class EvalError extends Error {
8
11
  readonly innerName: string;
9
12
  readonly code?: string;
10
- constructor(message: string, innerName: string, code?: string);
13
+ readonly kind: EvalErrorKind;
14
+ constructor(message: string, innerName: string, code?: string, kind?: EvalErrorKind);
11
15
  }
12
16
  export interface RunOptions {
13
17
  timeoutSec?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rex0220/formula-authoring-tools",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "rex0220 計算式プラグイン(kintone)の設定を AI で作るための CLI。利用者のプラグインの zip から authoring API と計算式エンジンを読んで Node で動く",
5
5
  "license": "MIT",
6
6
  "type": "module",