@lumpcode/core 0.0.10 → 0.0.12

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.
Files changed (43) hide show
  1. package/dist/helpers/executeStepsForContextList/main.d.ts +1 -1
  2. package/dist/helpers/executeStepsForContextList/main.d.ts.map +1 -1
  3. package/dist/helpers/getCodeBasePaths/main.d.ts +2 -2
  4. package/dist/helpers/getCodeBasePaths/main.d.ts.map +1 -1
  5. package/dist/helpers/getContextStatus/main.d.ts.map +1 -1
  6. package/dist/helpers/getToDoContextList/main.d.ts +2 -2
  7. package/dist/helpers/getToDoContextList/main.d.ts.map +1 -1
  8. package/dist/index.cjs +71 -59
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.js +71 -58
  11. package/dist/index.js.map +1 -1
  12. package/dist/utils/appendMissingGitignoreLines/index.d.ts +2 -0
  13. package/dist/utils/appendMissingGitignoreLines/index.d.ts.map +1 -0
  14. package/dist/utils/appendMissingGitignoreLines/main.d.ts +6 -0
  15. package/dist/utils/appendMissingGitignoreLines/main.d.ts.map +1 -0
  16. package/dist/utils/historyFile/main.d.ts.map +1 -1
  17. package/dist/utils/index.d.ts +2 -3
  18. package/dist/utils/index.d.ts.map +1 -1
  19. package/dist/utils/isProcessAlive/index.d.ts +2 -0
  20. package/dist/utils/isProcessAlive/index.d.ts.map +1 -0
  21. package/dist/utils/isProcessAlive/main.d.ts +6 -0
  22. package/dist/utils/isProcessAlive/main.d.ts.map +1 -0
  23. package/dist/utils/nodeErrnoCode/index.d.ts +2 -0
  24. package/dist/utils/nodeErrnoCode/index.d.ts.map +1 -0
  25. package/dist/utils/nodeErrnoCode/main.d.ts +3 -0
  26. package/dist/utils/nodeErrnoCode/main.d.ts.map +1 -0
  27. package/dist/utils/parseGitLogHashSubjectLines/index.d.ts +2 -0
  28. package/dist/utils/parseGitLogHashSubjectLines/index.d.ts.map +1 -0
  29. package/dist/utils/parseGitLogHashSubjectLines/main.d.ts +7 -0
  30. package/dist/utils/parseGitLogHashSubjectLines/main.d.ts.map +1 -0
  31. package/dist/utils/pathExists/index.d.ts +2 -0
  32. package/dist/utils/pathExists/index.d.ts.map +1 -0
  33. package/dist/utils/pathExists/main.d.ts +3 -0
  34. package/dist/utils/pathExists/main.d.ts.map +1 -0
  35. package/dist/utils/readJsonFile/index.d.ts +2 -0
  36. package/dist/utils/readJsonFile/index.d.ts.map +1 -0
  37. package/dist/utils/readJsonFile/main.d.ts +21 -0
  38. package/dist/utils/readJsonFile/main.d.ts.map +1 -0
  39. package/dist/utils/resolveBundledAssetPath/index.d.ts +2 -0
  40. package/dist/utils/resolveBundledAssetPath/index.d.ts.map +1 -0
  41. package/dist/utils/resolveBundledAssetPath/main.d.ts +3 -0
  42. package/dist/utils/resolveBundledAssetPath/main.d.ts.map +1 -0
  43. package/package.json +2 -1
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import * as fs from 'node:fs';
4
4
  import * as path from 'node:path';
5
5
  import { extname, dirname } from 'node:path';
6
6
  import * as fs$1 from 'node:fs/promises';
7
- import { readFile, mkdir, writeFile, stat } from 'node:fs/promises';
7
+ import { readFile, mkdir, writeFile } from 'node:fs/promises';
8
8
  import ignore from 'ignore';
9
9
  import z from 'zod';
10
10
 
@@ -38,18 +38,6 @@ function failure(data) {
38
38
  };
39
39
  }
40
40
 
41
- function decision(possibilities, defaultValue) {
42
- for (const [condition, result] of possibilities) {
43
- if (condition()) {
44
- return result();
45
- }
46
- }
47
- if (defaultValue) {
48
- return defaultValue;
49
- }
50
- throw new Error('No value found in decision');
51
- }
52
-
53
41
  /**
54
42
  * Wrap an arbitrary string in quotes so it can be safely embedded in
55
43
  * a shell command (e.g. the command string passed to `execAsync`).
@@ -64,18 +52,6 @@ function shellSingleQuote(value) {
64
52
  return `'${value.split("'").join(`'\\''`)}'`;
65
53
  }
66
54
 
67
- /**
68
- * Wrap a shell fragment so failure does not break a surrounding `&&` chain.
69
- *
70
- * Unix: `cmd || true`. Windows cmd.exe: `(cmd || cd .)`.
71
- */
72
- function shellBestEffort(command) {
73
- if (process.platform === 'win32') {
74
- return `(${command} || cd .)`;
75
- }
76
- return `${command} || true`;
77
- }
78
-
79
55
  const DEFAULT_WINDOWS_PATHEXT = [
80
56
  '.COM',
81
57
  '.EXE',
@@ -226,14 +202,6 @@ function createConsoleLogger(input) {
226
202
  return makeLogger(prefix);
227
203
  }
228
204
 
229
- const noopLogger = {
230
- error: () => { },
231
- warn: () => { },
232
- info: () => { },
233
- verbose: () => { },
234
- child: () => noopLogger,
235
- };
236
-
237
205
  function firstNonEmptyLine(value) {
238
206
  if (value == null)
239
207
  return undefined;
@@ -3165,6 +3133,49 @@ function dump(input, options = {}) {
3165
3133
  });
3166
3134
  }
3167
3135
 
3136
+ /** Returns whether `filePath` is accessible to this process (typically exists). */
3137
+ async function pathExists(filePath) {
3138
+ try {
3139
+ await fs$1.access(filePath);
3140
+ return true;
3141
+ }
3142
+ catch {
3143
+ return false;
3144
+ }
3145
+ }
3146
+
3147
+ /** Strip terminal ANSI escapes and other C0 controls js-yaml rejects in literal blocks. */
3148
+ function sanitizeHistoryText(value) {
3149
+ return value
3150
+ .replace(/\x1b\[[0-9;]*[A-Za-z]/g, '')
3151
+ .replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, '');
3152
+ }
3153
+ function parseHistoryYamlContent(content) {
3154
+ const parsed = load(content, { schema: YAML11_SCHEMA });
3155
+ if (!Array.isArray(parsed)) {
3156
+ throw new Error('History file must contain a YAML sequence');
3157
+ }
3158
+ return parsed;
3159
+ }
3160
+ function tryParseHistoryContent(content) {
3161
+ try {
3162
+ return parseHistoryYamlContent(content);
3163
+ }
3164
+ catch (firstError) {
3165
+ const sanitized = sanitizeHistoryText(content);
3166
+ if (sanitized === content) {
3167
+ throw firstError;
3168
+ }
3169
+ return parseHistoryYamlContent(sanitized);
3170
+ }
3171
+ }
3172
+ function sanitizeHistoryEntry(entry) {
3173
+ return {
3174
+ ...entry,
3175
+ prompt: sanitizeHistoryText(entry.prompt),
3176
+ commandResult: sanitizeHistoryText(entry.commandResult),
3177
+ };
3178
+ }
3168
3179
  function historyFormatFromPath(filePath) {
3169
3180
  const ext = extname(filePath).toLowerCase();
3170
3181
  if (ext === '.yaml' || ext === '.yml') {
@@ -3202,7 +3213,8 @@ function dumpHistoryEntries(entries) {
3202
3213
  if (entries.length === 0) {
3203
3214
  return '[]\n';
3204
3215
  }
3205
- return dump(entries, {
3216
+ const sanitizedEntries = entries.map(sanitizeHistoryEntry);
3217
+ return dump(sanitizedEntries, {
3206
3218
  schema: YAML11_SCHEMA,
3207
3219
  lineWidth: 0,
3208
3220
  noRefs: true,
@@ -3220,11 +3232,7 @@ async function readHistoryFile({ filePath, }) {
3220
3232
  }
3221
3233
  try {
3222
3234
  const content = await readFile(filePath, 'utf-8');
3223
- const parsed = load(content, { schema: YAML11_SCHEMA });
3224
- if (!Array.isArray(parsed)) {
3225
- return failure(`History file ${filePath} must contain a YAML sequence`);
3226
- }
3227
- return success(parsed);
3235
+ return success(tryParseHistoryContent(content));
3228
3236
  }
3229
3237
  catch (error) {
3230
3238
  const detail = error instanceof Error ? error.message : String(error);
@@ -3251,7 +3259,7 @@ async function appendHistoryEntry({ filePath, entry, }) {
3251
3259
  if (!formatResult.success) {
3252
3260
  return formatResult;
3253
3261
  }
3254
- const exists = await stat(filePath).then(() => true).catch(() => false);
3262
+ const exists = await pathExists(filePath);
3255
3263
  let entries;
3256
3264
  if (exists) {
3257
3265
  const readResult = await readHistoryFile({ filePath });
@@ -3264,10 +3272,25 @@ async function appendHistoryEntry({ filePath, entry, }) {
3264
3272
  await mkdir(dirname(filePath), { recursive: true });
3265
3273
  entries = [];
3266
3274
  }
3267
- entries.push(entry);
3275
+ entries.push(sanitizeHistoryEntry(entry));
3268
3276
  return writeHistoryFile({ filePath, entries });
3269
3277
  }
3270
3278
 
3279
+ /** Parses `git log --format='%H %s'` lines into commit hash and subject pairs. */
3280
+ function parseGitLogHashSubjectLines(stdout) {
3281
+ return stdout
3282
+ .split('\n')
3283
+ .map((line) => line.trim())
3284
+ .filter(Boolean)
3285
+ .map((line) => {
3286
+ const sp = line.indexOf(' ');
3287
+ return {
3288
+ hash: sp === -1 ? line : line.slice(0, sp),
3289
+ subject: sp === -1 ? '' : line.slice(sp + 1),
3290
+ };
3291
+ });
3292
+ }
3293
+
3271
3294
  const execAsyncBase = promisify(exec);
3272
3295
  async function execAsync(command, options) {
3273
3296
  const { stdout, stderr, hasErrored } = await execAsyncBase(command, { cwd: options?.cwd })
@@ -3563,8 +3586,8 @@ async function executeStepsForContextList({ baseBranch, branchFn, lumpVariables,
3563
3586
  entry: postCommandExecFnInput,
3564
3587
  });
3565
3588
  if (!appendResult.success) {
3566
- stepWalkFailure = failure({ message: appendResult.data });
3567
- return;
3589
+ // TODO: sanitize history appending to avoid this warning for certain commands outputs
3590
+ logger.warn(`Failed to append history entry to ${keepHistoryFilePath}: ${appendResult.data}`);
3568
3591
  }
3569
3592
  }
3570
3593
  if (postCommandExecFn) {
@@ -3654,7 +3677,7 @@ async function getGitignoresMap({ startDir, stopAtDir }) {
3654
3677
  const stopAtDirParent = path.dirname(stopAtDir);
3655
3678
  while (currentDir !== stopAtDirParent) {
3656
3679
  const gitignorePath = path.join(currentDir, '.gitignore');
3657
- const hasGitignore = await fs$1.access(gitignorePath).then(() => true).catch(() => false);
3680
+ const hasGitignore = await pathExists(gitignorePath);
3658
3681
  if (hasGitignore) {
3659
3682
  const gitignoreContent = await fs$1.readFile(gitignorePath, 'utf-8');
3660
3683
  gitignores.set(currentDir, ignore().add(gitignoreContent));
@@ -3721,19 +3744,9 @@ async function getContextStatus(params) {
3721
3744
  return 'toDo';
3722
3745
  logger?.verbose(`logResult ${JSON.stringify(logResult.data)}`);
3723
3746
  const logResultOutput = logResult.data.stdout || logResult.data.stderr || '';
3724
- const matchingHashes = logResultOutput
3725
- .split('\n')
3726
- .map((line) => line.trim())
3727
- .filter((line) => !!line)
3728
- .map((line) => {
3729
- const sp = line ? line.indexOf(' ') : -1;
3730
- return {
3731
- hash: sp === -1 ? line : line.slice(0, sp),
3732
- subject: sp === -1 ? '' : line.slice(sp + 1),
3733
- };
3734
- })
3735
- .filter((c) => c.subject === commitMessage)
3736
- .map((c) => c.hash);
3747
+ const matchingHashes = parseGitLogHashSubjectLines(logResultOutput)
3748
+ .filter((entry) => entry.subject === commitMessage)
3749
+ .map((entry) => entry.hash);
3737
3750
  logger?.verbose(`remoteName ${remoteName}`);
3738
3751
  logger?.verbose(`baseBranch ${baseBranch}`);
3739
3752
  logger?.verbose(`commitMessage ${commitMessage}`);
@@ -3941,5 +3954,5 @@ async function runLump(input) {
3941
3954
  });
3942
3955
  }
3943
3956
 
3944
- export { appendHistoryEntry, collectStepsForContext, contextStatus, contextStatusSchema, createConsoleLogger, decision, defaultGitAddCommandFn, defaultGitCommitCommandFn, defaultGitCommitMessageFn, defaultGitPushCommandFn, defaultSetupWorkspaceFn, defaultSetupWorkspaceFnWithWorktree, defaultTeardownWorkspaceFn, defaultTeardownWorkspaceFnWithWorktree, execAsync, execBinary, executeStepsForContextList, failure, formatExecFailureMessage, getCodeBasePaths, getContextStatus, getToDoContextList, historyFormatFromPath, noopLogger, readHistoryFile, resolveSpawnExecutable, runLump, set, shellBestEffort, shellSingleQuote, success, validateContextListNames, writeHistoryFile };
3957
+ export { appendHistoryEntry, collectStepsForContext, contextStatus, contextStatusSchema, createConsoleLogger, defaultGitAddCommandFn, defaultGitCommitCommandFn, defaultGitCommitMessageFn, defaultGitPushCommandFn, defaultSetupWorkspaceFn, defaultSetupWorkspaceFnWithWorktree, defaultTeardownWorkspaceFn, defaultTeardownWorkspaceFnWithWorktree, execAsync, execBinary, executeStepsForContextList, failure, formatExecFailureMessage, getCodeBasePaths, getContextStatus, getToDoContextList, historyFormatFromPath, parseGitLogHashSubjectLines, pathExists, readHistoryFile, resolveSpawnExecutable, runLump, set, shellSingleQuote, success, validateContextListNames, writeHistoryFile };
3945
3958
  //# sourceMappingURL=index.js.map