repoburg 1.3.8 → 1.3.10
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/backend/dist/bin/grammar/tree-sitter-bash.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-css.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-html.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-javascript.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-json.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-python.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-rust.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-toml.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-tsx.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-typescript.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-yaml.wasm +0 -0
- package/backend/dist/packages/tokenpatch/index.d.ts +1 -0
- package/backend/dist/packages/tokenpatch/index.js +52 -0
- package/backend/dist/packages/tokenpatch/index.js.map +1 -0
- package/backend/dist/packages/tokenpatch/parser.d.ts +2 -0
- package/backend/dist/packages/tokenpatch/parser.js +17 -0
- package/backend/dist/packages/tokenpatch/parser.js.map +1 -0
- package/backend/dist/packages/tokenpatch/patcher.d.ts +11 -0
- package/backend/dist/packages/tokenpatch/patcher.js +189 -0
- package/backend/dist/packages/tokenpatch/patcher.js.map +1 -0
- package/backend/dist/packages/tokenpatch/tokens.d.ts +6 -0
- package/backend/dist/packages/tokenpatch/tokens.js +49 -0
- package/backend/dist/packages/tokenpatch/tokens.js.map +1 -0
- package/backend/dist/packages/tokenpatch/types.d.ts +8 -0
- package/backend/dist/packages/tokenpatch/types.js +3 -0
- package/backend/dist/packages/tokenpatch/types.js.map +1 -0
- package/backend/dist/src/ai-actions/ai-actions.service.d.ts +1 -0
- package/backend/dist/src/ai-actions/ai-actions.service.js +2 -0
- package/backend/dist/src/ai-actions/ai-actions.service.js.map +1 -1
- package/backend/dist/src/llm-orchestration/action-handlers/apply-diff.handler.js +6 -3
- package/backend/dist/src/llm-orchestration/action-handlers/apply-diff.handler.js.map +1 -1
- package/backend/dist/src/llm-orchestration/action-handlers/dto/patch.args.dto.d.ts +4 -0
- package/backend/dist/src/llm-orchestration/action-handlers/dto/patch.args.dto.js +29 -0
- package/backend/dist/src/llm-orchestration/action-handlers/dto/patch.args.dto.js.map +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/patch.handler.d.ts +12 -0
- package/backend/dist/src/llm-orchestration/action-handlers/patch.handler.js +142 -0
- package/backend/dist/src/llm-orchestration/action-handlers/patch.handler.js.map +1 -0
- package/backend/dist/src/llm-orchestration/llm-orchestration.module.js +2 -0
- package/backend/dist/src/llm-orchestration/llm-orchestration.module.js.map +1 -1
- package/backend/dist/src/llm-orchestration/llm-turn-processor.service.js +1 -0
- package/backend/dist/src/llm-orchestration/llm-turn-processor.service.js.map +1 -1
- package/backend/dist/src/seeding/data/system-prompts/experimental_master-agent.d.ts +1 -1
- package/backend/dist/src/seeding/data/system-prompts/experimental_master-agent.js +13 -13
- package/backend/dist/src/seeding/data/system-prompts/experimental_patch_master-agent.d.ts +2 -0
- package/backend/dist/src/seeding/data/system-prompts/experimental_patch_master-agent.js +463 -0
- package/backend/dist/src/seeding/data/system-prompts/experimental_patch_master-agent.js.map +1 -0
- package/backend/dist/tsconfig.build.tsbuildinfo +1 -1
- package/backend/package.json +6 -3
- package/backend/packages/tokenpatch/grammar/tree-sitter-tsx.wasm +0 -0
- package/backend/packages/tokenpatch/grammar/tree-sitter-typescript.wasm +0 -0
- package/backend/packages/tokenpatch/index.spec.ts +579 -0
- package/backend/packages/tokenpatch/index.ts +80 -0
- package/backend/packages/tokenpatch/parser.ts +18 -0
- package/backend/packages/tokenpatch/patcher.spec.ts +194 -0
- package/backend/packages/tokenpatch/patcher.ts +300 -0
- package/backend/packages/tokenpatch/tokens.spec.ts +84 -0
- package/backend/packages/tokenpatch/tokens.ts +50 -0
- package/backend/packages/tokenpatch/types.ts +9 -0
- package/package.json +13 -12
- package/backend/coverage/clover.xml +0 -3434
- package/backend/coverage/coverage-final.json +0 -120
- package/backend/coverage/lcov-report/base.css +0 -224
- package/backend/coverage/lcov-report/block-navigation.js +0 -87
- package/backend/coverage/lcov-report/favicon.png +0 -0
- package/backend/coverage/lcov-report/index.html +0 -701
- package/backend/coverage/lcov-report/prettify.css +0 -1
- package/backend/coverage/lcov-report/prettify.js +0 -2
- package/backend/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/backend/coverage/lcov-report/sorter.js +0 -196
- package/backend/coverage/lcov-report/src/action-execution/action-execution.module.ts.html +0 -109
- package/backend/coverage/lcov-report/src/action-execution/action-execution.service.ts.html +0 -448
- package/backend/coverage/lcov-report/src/action-execution/index.html +0 -131
- package/backend/coverage/lcov-report/src/ai-actions/ai-action-batch.service.ts.html +0 -940
- package/backend/coverage/lcov-report/src/ai-actions/ai-action-creation.service.ts.html +0 -1243
- package/backend/coverage/lcov-report/src/ai-actions/ai-actions.controller.ts.html +0 -664
- package/backend/coverage/lcov-report/src/ai-actions/ai-actions.module.ts.html +0 -154
- package/backend/coverage/lcov-report/src/ai-actions/ai-actions.service.ts.html +0 -859
- package/backend/coverage/lcov-report/src/ai-actions/index.html +0 -176
- package/backend/coverage/lcov-report/src/app.controller.ts.html +0 -151
- package/backend/coverage/lcov-report/src/app.module.ts.html +0 -373
- package/backend/coverage/lcov-report/src/app.service.ts.html +0 -196
- package/backend/coverage/lcov-report/src/application-state/application-state.controller.ts.html +0 -319
- package/backend/coverage/lcov-report/src/application-state/application-state.module.ts.html +0 -124
- package/backend/coverage/lcov-report/src/application-state/application-state.service.ts.html +0 -439
- package/backend/coverage/lcov-report/src/application-state/dto/index.html +0 -161
- package/backend/coverage/lcov-report/src/application-state/dto/set-auto-context-fetch-enabled.dto.ts.html +0 -103
- package/backend/coverage/lcov-report/src/application-state/dto/set-orchestration-timeout.dto.ts.html +0 -103
- package/backend/coverage/lcov-report/src/application-state/dto/set-theme.dto.ts.html +0 -106
- package/backend/coverage/lcov-report/src/application-state/dto/set-websocket-enabled.dto.ts.html +0 -103
- package/backend/coverage/lcov-report/src/application-state/index.html +0 -146
- package/backend/coverage/lcov-report/src/context-generation/context-generation.module.ts.html +0 -118
- package/backend/coverage/lcov-report/src/context-generation/context-generation.service.ts.html +0 -1348
- package/backend/coverage/lcov-report/src/context-generation/index.html +0 -131
- package/backend/coverage/lcov-report/src/context-snippets/context-snippets.controller.ts.html +0 -289
- package/backend/coverage/lcov-report/src/context-snippets/context-snippets.module.ts.html +0 -136
- package/backend/coverage/lcov-report/src/context-snippets/context-snippets.service.ts.html +0 -400
- package/backend/coverage/lcov-report/src/context-snippets/dto/context-snippet.dto.ts.html +0 -211
- package/backend/coverage/lcov-report/src/context-snippets/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/context-snippets/index.html +0 -146
- package/backend/coverage/lcov-report/src/context-templates/context-templates.controller.ts.html +0 -397
- package/backend/coverage/lcov-report/src/context-templates/context-templates.module.ts.html +0 -136
- package/backend/coverage/lcov-report/src/context-templates/context-templates.service.ts.html +0 -835
- package/backend/coverage/lcov-report/src/context-templates/dto/context-template.dto.ts.html +0 -358
- package/backend/coverage/lcov-report/src/context-templates/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/context-templates/index.html +0 -146
- package/backend/coverage/lcov-report/src/core-entities/ai-action.entity.ts.html +0 -241
- package/backend/coverage/lcov-report/src/core-entities/application-state.entity.ts.html +0 -115
- package/backend/coverage/lcov-report/src/core-entities/base.entity.ts.html +0 -145
- package/backend/coverage/lcov-report/src/core-entities/context-snippet.entity.ts.html +0 -130
- package/backend/coverage/lcov-report/src/core-entities/context-template.entity.ts.html +0 -223
- package/backend/coverage/lcov-report/src/core-entities/custom-snippet.entity.ts.html +0 -136
- package/backend/coverage/lcov-report/src/core-entities/execution-log.entity.ts.html +0 -157
- package/backend/coverage/lcov-report/src/core-entities/index.html +0 -281
- package/backend/coverage/lcov-report/src/core-entities/index.ts.html +0 -118
- package/backend/coverage/lcov-report/src/core-entities/project.entity.ts.html +0 -130
- package/backend/coverage/lcov-report/src/core-entities/session-input.entity.ts.html +0 -289
- package/backend/coverage/lcov-report/src/core-entities/session.entity.ts.html +0 -280
- package/backend/coverage/lcov-report/src/core-entities/system-prompt.entity.ts.html +0 -148
- package/backend/coverage/lcov-report/src/custom-snippets/custom-snippets.controller.ts.html +0 -277
- package/backend/coverage/lcov-report/src/custom-snippets/custom-snippets.module.ts.html +0 -124
- package/backend/coverage/lcov-report/src/custom-snippets/custom-snippets.service.ts.html +0 -304
- package/backend/coverage/lcov-report/src/custom-snippets/dto/custom-snippet.dto.ts.html +0 -205
- package/backend/coverage/lcov-report/src/custom-snippets/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/custom-snippets/index.html +0 -146
- package/backend/coverage/lcov-report/src/events/events.gateway.ts.html +0 -292
- package/backend/coverage/lcov-report/src/events/events.module.ts.html +0 -109
- package/backend/coverage/lcov-report/src/events/index.html +0 -131
- package/backend/coverage/lcov-report/src/execution-logs/dto/execution-log.dto.ts.html +0 -130
- package/backend/coverage/lcov-report/src/execution-logs/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/execution-logs/execution-logs.controller.ts.html +0 -130
- package/backend/coverage/lcov-report/src/execution-logs/execution-logs.module.ts.html +0 -124
- package/backend/coverage/lcov-report/src/execution-logs/execution-logs.service.ts.html +0 -238
- package/backend/coverage/lcov-report/src/execution-logs/index.html +0 -146
- package/backend/coverage/lcov-report/src/http-exception.filter.ts.html +0 -340
- package/backend/coverage/lcov-report/src/index.html +0 -191
- package/backend/coverage/lcov-report/src/llm-response-parser/dto/ai-action.dto.ts.html +0 -400
- package/backend/coverage/lcov-report/src/llm-response-parser/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/llm-response-parser/errors/index.html +0 -116
- package/backend/coverage/lcov-report/src/llm-response-parser/errors/parsing.error.ts.html +0 -118
- package/backend/coverage/lcov-report/src/llm-response-parser/index.html +0 -146
- package/backend/coverage/lcov-report/src/llm-response-parser/llm-response-parser.module.ts.html +0 -109
- package/backend/coverage/lcov-report/src/llm-response-parser/llm-response-parser.service.ts.html +0 -808
- package/backend/coverage/lcov-report/src/llm-response-parser/parsing.constants.ts.html +0 -139
- package/backend/coverage/lcov-report/src/llm-responses/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/llm-responses/dto/submit-llm-response.dto.ts.html +0 -172
- package/backend/coverage/lcov-report/src/llm-responses/index.html +0 -146
- package/backend/coverage/lcov-report/src/llm-responses/llm-responses.controller.ts.html +0 -154
- package/backend/coverage/lcov-report/src/llm-responses/llm-responses.module.ts.html +0 -166
- package/backend/coverage/lcov-report/src/llm-responses/llm-responses.service.ts.html +0 -787
- package/backend/coverage/lcov-report/src/main.ts.html +0 -382
- package/backend/coverage/lcov-report/src/orchestration/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/orchestration/dto/orchestration.dto.ts.html +0 -169
- package/backend/coverage/lcov-report/src/orchestration/index.html +0 -191
- package/backend/coverage/lcov-report/src/orchestration/orchestration-fs.service.ts.html +0 -595
- package/backend/coverage/lcov-report/src/orchestration/orchestration-parser.service.ts.html +0 -142
- package/backend/coverage/lcov-report/src/orchestration/orchestration.controller.ts.html +0 -406
- package/backend/coverage/lcov-report/src/orchestration/orchestration.module.ts.html +0 -169
- package/backend/coverage/lcov-report/src/orchestration/orchestration.service.ts.html +0 -1093
- package/backend/coverage/lcov-report/src/orchestration/orchestration.types.ts.html +0 -175
- package/backend/coverage/lcov-report/src/projects/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/projects/dto/project.dto.ts.html +0 -154
- package/backend/coverage/lcov-report/src/projects/index.html +0 -146
- package/backend/coverage/lcov-report/src/projects/projects.controller.ts.html +0 -232
- package/backend/coverage/lcov-report/src/projects/projects.module.ts.html +0 -124
- package/backend/coverage/lcov-report/src/projects/projects.service.ts.html +0 -223
- package/backend/coverage/lcov-report/src/seeding/context-template-seeding.service.ts.html +0 -355
- package/backend/coverage/lcov-report/src/seeding/custom-snippet-seeding.service.ts.html +0 -271
- package/backend/coverage/lcov-report/src/seeding/data/context-templates/default-followup_ad-hoc-focused-context.ts.html +0 -136
- package/backend/coverage/lcov-report/src/seeding/data/context-templates/default-initial_condensed-project-context.ts.html +0 -148
- package/backend/coverage/lcov-report/src/seeding/data/context-templates/default-initial_full-project-context.ts.html +0 -247
- package/backend/coverage/lcov-report/src/seeding/data/context-templates/index.html +0 -190
- package/backend/coverage/lcov-report/src/seeding/data/context-templates/pm-context.ts.html +0 -250
- package/backend/coverage/lcov-report/src/seeding/data/context-templates/pr-description.ts.html +0 -186
- package/backend/coverage/lcov-report/src/seeding/data/context-templates/sample_focused-tree.ts.html +0 -124
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/default_rglob.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/git-diff.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/index.html +0 -236
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/rg-exclude.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/rg-search-glob.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/rg-search.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/run-command.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/tree.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/usr-adhoc-incl.ts.html +0 -100
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/usr-input-incl.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/system-prompts/codebase-explorer.ts.html +0 -331
- package/backend/coverage/lcov-report/src/seeding/data/system-prompts/default_multi-file-action-generator-with-requester.ts.html +0 -675
- package/backend/coverage/lcov-report/src/seeding/data/system-prompts/index.html +0 -160
- package/backend/coverage/lcov-report/src/seeding/data/system-prompts/multi-file-action-generator.ts.html +0 -550
- package/backend/coverage/lcov-report/src/seeding/data/system-prompts/packup.ts.html +0 -184
- package/backend/coverage/lcov-report/src/seeding/data/system-prompts/refactor-split.ts.html +0 -244
- package/backend/coverage/lcov-report/src/seeding/index.html +0 -176
- package/backend/coverage/lcov-report/src/seeding/seeding.module.ts.html +0 -145
- package/backend/coverage/lcov-report/src/seeding/seeding.service.ts.html +0 -151
- package/backend/coverage/lcov-report/src/seeding/system-prompt-seeding.service.ts.html +0 -289
- package/backend/coverage/lcov-report/src/session-followup/index.html +0 -131
- package/backend/coverage/lcov-report/src/session-followup/session-followup.module.ts.html +0 -130
- package/backend/coverage/lcov-report/src/session-followup/session-followup.service.ts.html +0 -670
- package/backend/coverage/lcov-report/src/session-inputs/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/session-inputs/dto/session-input.dto.ts.html +0 -247
- package/backend/coverage/lcov-report/src/session-inputs/index.html +0 -161
- package/backend/coverage/lcov-report/src/session-inputs/session-input-context.service.ts.html +0 -763
- package/backend/coverage/lcov-report/src/session-inputs/session-inputs.controller.ts.html +0 -337
- package/backend/coverage/lcov-report/src/session-inputs/session-inputs.module.ts.html +0 -205
- package/backend/coverage/lcov-report/src/session-inputs/session-inputs.service.ts.html +0 -1621
- package/backend/coverage/lcov-report/src/session-transfer/index.html +0 -131
- package/backend/coverage/lcov-report/src/session-transfer/session-transfer.module.ts.html +0 -172
- package/backend/coverage/lcov-report/src/session-transfer/session-transfer.service.ts.html +0 -574
- package/backend/coverage/lcov-report/src/sessions/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/sessions/dto/session.dto.ts.html +0 -340
- package/backend/coverage/lcov-report/src/sessions/index.html +0 -146
- package/backend/coverage/lcov-report/src/sessions/sessions.controller.ts.html +0 -457
- package/backend/coverage/lcov-report/src/sessions/sessions.module.ts.html +0 -214
- package/backend/coverage/lcov-report/src/sessions/sessions.service.ts.html +0 -844
- package/backend/coverage/lcov-report/src/system-prompts/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/system-prompts/dto/system-prompt.dto.ts.html +0 -217
- package/backend/coverage/lcov-report/src/system-prompts/index.html +0 -146
- package/backend/coverage/lcov-report/src/system-prompts/system-prompts.controller.ts.html +0 -298
- package/backend/coverage/lcov-report/src/system-prompts/system-prompts.module.ts.html +0 -127
- package/backend/coverage/lcov-report/src/system-prompts/system-prompts.service.ts.html +0 -352
- package/backend/coverage/lcov-report/src/timeout.interceptor.ts.html +0 -178
- package/backend/coverage/lcov-report/src/utils/fuzzy-search.ts.html +0 -310
- package/backend/coverage/lcov-report/src/utils/index.html +0 -131
- package/backend/coverage/lcov-report/src/utils/index.ts.html +0 -88
- package/backend/coverage/lcov-report/src/workspace/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/workspace/dto/search-workspace.dto.ts.html +0 -193
- package/backend/coverage/lcov-report/src/workspace/index.html +0 -146
- package/backend/coverage/lcov-report/src/workspace/workspace.controller.ts.html +0 -247
- package/backend/coverage/lcov-report/src/workspace/workspace.module.ts.html +0 -121
- package/backend/coverage/lcov-report/src/workspace/workspace.service.ts.html +0 -745
- package/backend/coverage/lcov.info +0 -5590
package/backend/package.json
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"start:debug": "nest start --debug --watch",
|
|
14
14
|
"start:prod": "NODE_ENV=production node dist/main",
|
|
15
15
|
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
|
16
|
-
"test": "jest --bail",
|
|
16
|
+
"test": "NODE_OPTIONS=--experimental-vm-modules jest --bail",
|
|
17
17
|
"test:watch": "jest --watch",
|
|
18
18
|
"test:cov": "jest --coverage",
|
|
19
19
|
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
|
@@ -57,7 +57,10 @@
|
|
|
57
57
|
"json",
|
|
58
58
|
"ts"
|
|
59
59
|
],
|
|
60
|
-
"
|
|
60
|
+
"roots": [
|
|
61
|
+
"<rootDir>/src",
|
|
62
|
+
"<rootDir>/packages"
|
|
63
|
+
],
|
|
61
64
|
"testRegex": ".*\\.spec\\.ts$",
|
|
62
65
|
"transform": {
|
|
63
66
|
"^.+\\.(t|j)s$": "ts-jest"
|
|
@@ -65,7 +68,7 @@
|
|
|
65
68
|
"collectCoverageFrom": [
|
|
66
69
|
"**/*.(t|j)s"
|
|
67
70
|
],
|
|
68
|
-
"coverageDirectory": "
|
|
71
|
+
"coverageDirectory": "coverage",
|
|
69
72
|
"testEnvironment": "node"
|
|
70
73
|
}
|
|
71
74
|
}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
import { applySnippetPatch } from './index';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
|
|
4
|
+
const TS_WASM_PATH = path.join(
|
|
5
|
+
__dirname,
|
|
6
|
+
'./grammar/tree-sitter-typescript.wasm',
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
const TSX_WASM_PATH = path.join(__dirname, './grammar/tree-sitter-tsx.wasm');
|
|
10
|
+
|
|
11
|
+
// Helper to normalize whitespace for robust comparison
|
|
12
|
+
const normalize = (str: string) => str.replace(/\s+/g, ' ').trim();
|
|
13
|
+
|
|
14
|
+
describe('applySnippetPatch', () => {
|
|
15
|
+
it('should replace a method body in a class by automatically finding anchor size', async () => {
|
|
16
|
+
const sourceCode = `
|
|
17
|
+
class Greeter {
|
|
18
|
+
greet() {
|
|
19
|
+
return "Hello, world";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
fc(){ return 42; }
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
const patchCode = `
|
|
26
|
+
greet() {
|
|
27
|
+
// A new implementation
|
|
28
|
+
return "Hello, TypeScript!";
|
|
29
|
+
}
|
|
30
|
+
fc(){
|
|
31
|
+
`;
|
|
32
|
+
const expectedResult = `
|
|
33
|
+
class Greeter {
|
|
34
|
+
greet() {
|
|
35
|
+
// A new implementation
|
|
36
|
+
return "Hello, TypeScript!";
|
|
37
|
+
}
|
|
38
|
+
fc(){ return 42; }
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
`;
|
|
42
|
+
const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
|
|
43
|
+
expect(normalize(result)).toEqual(normalize(expectedResult));
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should replace a data structure definition', async () => {
|
|
47
|
+
const sourceCode = `
|
|
48
|
+
interface MyData {
|
|
49
|
+
field1: string;
|
|
50
|
+
}
|
|
51
|
+
console.log("hello");
|
|
52
|
+
`;
|
|
53
|
+
const patchCode = `
|
|
54
|
+
interface MyData {
|
|
55
|
+
field1: number;
|
|
56
|
+
field2: boolean;
|
|
57
|
+
}
|
|
58
|
+
`;
|
|
59
|
+
const expectedResult = `
|
|
60
|
+
interface MyData {
|
|
61
|
+
field1: number;
|
|
62
|
+
field2: boolean;
|
|
63
|
+
}
|
|
64
|
+
console.log("hello");
|
|
65
|
+
`;
|
|
66
|
+
const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
|
|
67
|
+
expect(normalize(result)).toEqual(normalize(expectedResult));
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should replace a full function definition', async () => {
|
|
71
|
+
const sourceCode = `
|
|
72
|
+
import fs from 'fs';
|
|
73
|
+
|
|
74
|
+
function calculate() {
|
|
75
|
+
return 1 + 1;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export { calculate };
|
|
79
|
+
`;
|
|
80
|
+
const patchCode = `
|
|
81
|
+
function calculate() {
|
|
82
|
+
// A more complex calculation
|
|
83
|
+
const result = 2 * 2;
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
`;
|
|
87
|
+
const expectedResult = `
|
|
88
|
+
import fs from 'fs';
|
|
89
|
+
|
|
90
|
+
function calculate() {
|
|
91
|
+
// A more complex calculation
|
|
92
|
+
const result = 2 * 2;
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export { calculate };
|
|
97
|
+
`;
|
|
98
|
+
const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
|
|
99
|
+
expect(normalize(result)).toEqual(normalize(expectedResult));
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should replace a beginning of the file @begin-of-file', async () => {
|
|
103
|
+
const sourceCode = `
|
|
104
|
+
import { ModuleA } from './moduleA';
|
|
105
|
+
import { ModuleB } from './moduleB';
|
|
106
|
+
|
|
107
|
+
console.log('starting up');
|
|
108
|
+
`;
|
|
109
|
+
const patchCode = `
|
|
110
|
+
// @begin-of-file
|
|
111
|
+
import groupBy from 'lodash';
|
|
112
|
+
import { ModuleA } from './moduleA';
|
|
113
|
+
`;
|
|
114
|
+
const expectedResult = `
|
|
115
|
+
import groupBy from 'lodash';
|
|
116
|
+
import { ModuleA } from './moduleA';
|
|
117
|
+
import { ModuleB } from './moduleB';
|
|
118
|
+
|
|
119
|
+
console.log('starting up');
|
|
120
|
+
`;
|
|
121
|
+
const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
|
|
122
|
+
expect(normalize(result)).toEqual(normalize(expectedResult));
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should handle @begin-of-file marker with variations', async () => {
|
|
126
|
+
const sourceCode = `
|
|
127
|
+
import { ModuleA } from './moduleA';
|
|
128
|
+
import { ModuleB } from './moduleB';
|
|
129
|
+
|
|
130
|
+
console.log('starting up');
|
|
131
|
+
`;
|
|
132
|
+
const patchCode = `
|
|
133
|
+
//@begin-of-file extra text
|
|
134
|
+
import groupBy from 'lodash';
|
|
135
|
+
import { ModuleA } from './moduleA';
|
|
136
|
+
`;
|
|
137
|
+
const expectedResult = `
|
|
138
|
+
import groupBy from 'lodash';
|
|
139
|
+
import { ModuleA } from './moduleA';
|
|
140
|
+
import { ModuleB } from './moduleB';
|
|
141
|
+
|
|
142
|
+
console.log('starting up');
|
|
143
|
+
`;
|
|
144
|
+
const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
|
|
145
|
+
expect(normalize(result)).toEqual(normalize(expectedResult));
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should replace a end of the file @end-of-file', async () => {
|
|
149
|
+
const sourceCode = `
|
|
150
|
+
import fs from 'fs';
|
|
151
|
+
|
|
152
|
+
function calculate() {
|
|
153
|
+
return 1 + 1;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export { calculate };
|
|
157
|
+
`;
|
|
158
|
+
const patchCode = `
|
|
159
|
+
export { calculate };
|
|
160
|
+
export { sum };
|
|
161
|
+
// @end-of-file
|
|
162
|
+
`;
|
|
163
|
+
const expectedResult = `
|
|
164
|
+
import fs from 'fs';
|
|
165
|
+
|
|
166
|
+
function calculate() {
|
|
167
|
+
return 1 + 1;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export { calculate };
|
|
171
|
+
export { sum };
|
|
172
|
+
`;
|
|
173
|
+
const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
|
|
174
|
+
expect(normalize(result)).toEqual(normalize(expectedResult));
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('should handle @end-of-file marker with variations', async () => {
|
|
178
|
+
const sourceCode = `
|
|
179
|
+
import fs from 'fs';
|
|
180
|
+
|
|
181
|
+
function calculate() {
|
|
182
|
+
return 1 + 1;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export { calculate };
|
|
186
|
+
`;
|
|
187
|
+
const patchCode = `
|
|
188
|
+
export { calculate };
|
|
189
|
+
export { sum };
|
|
190
|
+
//@end-of-file some extra text
|
|
191
|
+
`;
|
|
192
|
+
const expectedResult = `
|
|
193
|
+
import fs from 'fs';
|
|
194
|
+
|
|
195
|
+
function calculate() {
|
|
196
|
+
return 1 + 1;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export { calculate };
|
|
200
|
+
export { sum };
|
|
201
|
+
`;
|
|
202
|
+
const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
|
|
203
|
+
expect(normalize(result)).toEqual(normalize(expectedResult));
|
|
204
|
+
});
|
|
205
|
+
it('should succeed with dynamic anchor sizing when initial anchors are ambiguous', async () => {
|
|
206
|
+
const sourceCode = `
|
|
207
|
+
const config = {
|
|
208
|
+
port: 8080,
|
|
209
|
+
host: 'localhost',
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
function connect() {
|
|
213
|
+
// uses config
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const config2 = {
|
|
217
|
+
port: 3000,
|
|
218
|
+
host: 'remote',
|
|
219
|
+
};
|
|
220
|
+
`;
|
|
221
|
+
const patchCode = `
|
|
222
|
+
const config = {
|
|
223
|
+
port: 9000,
|
|
224
|
+
host: 'localhost',
|
|
225
|
+
protocol: 'https'
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
function connect() {
|
|
229
|
+
`;
|
|
230
|
+
const expectedResult = `
|
|
231
|
+
const config = {
|
|
232
|
+
port: 9000,
|
|
233
|
+
host: 'localhost',
|
|
234
|
+
protocol: 'https'
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
function connect() {
|
|
238
|
+
// uses config
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const config2 = {
|
|
242
|
+
port: 3000,
|
|
243
|
+
host: 'remote',
|
|
244
|
+
};
|
|
245
|
+
`;
|
|
246
|
+
const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
|
|
247
|
+
expect(normalize(result)).toEqual(normalize(expectedResult));
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it('should handle partial type definitions by trimming ambiguous tokens', async () => {
|
|
251
|
+
const sourceCode = `
|
|
252
|
+
/**
|
|
253
|
+
* Bill date of the vendor bill
|
|
254
|
+
*/
|
|
255
|
+
billDate: everest_appserver_primitive_PlainDate;
|
|
256
|
+
billNumber: everest_appserver_primitive_Text;
|
|
257
|
+
businessPartnerId: everest_appserver_primitive_ID;
|
|
258
|
+
/**
|
|
259
|
+
* Conditionally return status or paymentStatus
|
|
260
|
+
*/
|
|
261
|
+
combinedStatus?: everest_appserver_primitive_Text | null;
|
|
262
|
+
/**
|
|
263
|
+
* Contains Billable Expense line
|
|
264
|
+
*/
|
|
265
|
+
containsBillableItem?: everest_appserver_primitive_TrueFalse | null;
|
|
266
|
+
/**
|
|
267
|
+
* Denotes whether bill type is prepaid or not
|
|
268
|
+
*/
|
|
269
|
+
containsPrepaidItem?: everest_appserver_primitive_TrueFalse | null;
|
|
270
|
+
`;
|
|
271
|
+
const patchCode = `
|
|
272
|
+
businessPartnerId: everest_appserver_primitive_ID;
|
|
273
|
+
/**
|
|
274
|
+
* Conditionally return status or paymentStatus
|
|
275
|
+
*/
|
|
276
|
+
combinedStatusNew2?: everest_appserver_primitive_Text | null;
|
|
277
|
+
/**
|
|
278
|
+
`;
|
|
279
|
+
const expectedResult = `
|
|
280
|
+
/**
|
|
281
|
+
* Bill date of the vendor bill
|
|
282
|
+
*/
|
|
283
|
+
billDate: everest_appserver_primitive_PlainDate;
|
|
284
|
+
billNumber: everest_appserver_primitive_Text;
|
|
285
|
+
businessPartnerId: everest_appserver_primitive_ID;
|
|
286
|
+
/**
|
|
287
|
+
* Conditionally return status or paymentStatus
|
|
288
|
+
*/
|
|
289
|
+
combinedStatusNew2?: everest_appserver_primitive_Text | null;
|
|
290
|
+
/**
|
|
291
|
+
* Contains Billable Expense line
|
|
292
|
+
*/
|
|
293
|
+
containsBillableItem?: everest_appserver_primitive_TrueFalse | null;
|
|
294
|
+
/**
|
|
295
|
+
* Denotes whether bill type is prepaid or not
|
|
296
|
+
*/
|
|
297
|
+
containsPrepaidItem?: everest_appserver_primitive_TrueFalse | null;
|
|
298
|
+
`;
|
|
299
|
+
const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
|
|
300
|
+
expect(normalize(result)).toEqual(normalize(expectedResult));
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it('should patch TSX correctly by trimming tokens from invalid partial snippets', async () => {
|
|
304
|
+
const sourceCode = `
|
|
305
|
+
import { useEffect, useMemo } from "react"
|
|
306
|
+
import { trpc } from "@/lib/trpc"
|
|
307
|
+
|
|
308
|
+
import { Button } from "@/components/ui/button"
|
|
309
|
+
import { DataTable } from "@/components/ui/data-table"
|
|
310
|
+
import { useReconciliationStore } from "@/store/reconciliation"
|
|
311
|
+
|
|
312
|
+
import {
|
|
313
|
+
getBillColumns,
|
|
314
|
+
getInvoiceColumns,
|
|
315
|
+
getMatchedColumns,
|
|
316
|
+
getTransactionColumns,
|
|
317
|
+
} from "./transactions-columns"
|
|
318
|
+
|
|
319
|
+
export function TransactionsPage() {
|
|
320
|
+
const {
|
|
321
|
+
transactions,
|
|
322
|
+
invoices,
|
|
323
|
+
matchedItems,
|
|
324
|
+
selectedTransactionId,
|
|
325
|
+
selectedMatchableId,
|
|
326
|
+
loadInitialData,
|
|
327
|
+
selectTransaction,
|
|
328
|
+
selectMatchable,
|
|
329
|
+
matchItems,
|
|
330
|
+
unmatchItems,
|
|
331
|
+
} = useReconciliationStore()
|
|
332
|
+
const { data: bills = [] } = trpc.bills.getBills.useQuery()
|
|
333
|
+
|
|
334
|
+
// Load mock data when component mounts
|
|
335
|
+
useEffect(() => {
|
|
336
|
+
loadInitialData()
|
|
337
|
+
}, [loadInitialData])
|
|
338
|
+
|
|
339
|
+
const selectedTransaction =
|
|
340
|
+
transactions.find((t) => t.id === selectedTransactionId) || null
|
|
341
|
+
|
|
342
|
+
const transactionColumns = useMemo(() => getTransactionColumns(), [])
|
|
343
|
+
|
|
344
|
+
const invoiceColumns = useMemo(() => getInvoiceColumns(), [])
|
|
345
|
+
|
|
346
|
+
const billColumns = useMemo(() => getBillColumns(), [])
|
|
347
|
+
|
|
348
|
+
const matchedColumns = useMemo(
|
|
349
|
+
() =>
|
|
350
|
+
getMatchedColumns({
|
|
351
|
+
onUnmatch: unmatchItems,
|
|
352
|
+
}),
|
|
353
|
+
[unmatchItems]
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
const canMatch = selectedTransactionId && selectedMatchableId
|
|
357
|
+
|
|
358
|
+
return (
|
|
359
|
+
<div>
|
|
360
|
+
<div className="flex justify-between items-center mb-4">
|
|
361
|
+
<h2 className="text-2xl font-bold">Transaction Matching</h2>
|
|
362
|
+
<Button onClick={matchItems} disabled={!canMatch}>
|
|
363
|
+
Match Items
|
|
364
|
+
</Button>
|
|
365
|
+
</div>
|
|
366
|
+
|
|
367
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
368
|
+
{/* Left Panel: Bank Transactions */}
|
|
369
|
+
<div>
|
|
370
|
+
<h3 className="text-lg font-semibold mb-2">Bank Transactions</h3>
|
|
371
|
+
<p className="text-sm text-muted-foreground mb-4">
|
|
372
|
+
Select a transaction to begin matching.
|
|
373
|
+
</p>
|
|
374
|
+
<DataTable
|
|
375
|
+
columns={transactionColumns}
|
|
376
|
+
data={transactions}
|
|
377
|
+
onRowClick={(row) => selectTransaction(row.id)}
|
|
378
|
+
selectedId={selectedTransactionId}
|
|
379
|
+
/>
|
|
380
|
+
</div>
|
|
381
|
+
|
|
382
|
+
{/* Right Panel: Matching Items */}
|
|
383
|
+
<div>
|
|
384
|
+
<h3 className="text-lg font-semibold mb-2">Potential Matches</h3>
|
|
385
|
+
{!selectedTransaction ? (
|
|
386
|
+
<div className="h-full flex items-center justify-center rounded-lg border-2 border-dashed border-muted-foreground/30 p-8">
|
|
387
|
+
<p className="text-muted-foreground">
|
|
388
|
+
Select a transaction to see potential matches.
|
|
389
|
+
</p>
|
|
390
|
+
</div>
|
|
391
|
+
) : selectedTransaction.amount > 0 ? (
|
|
392
|
+
<div>
|
|
393
|
+
<h4 className="text-md font-semibold mb-2 text-muted-foreground">
|
|
394
|
+
Unpaid Invoices
|
|
395
|
+
</h4>
|
|
396
|
+
<DataTable
|
|
397
|
+
columns={invoiceColumns}
|
|
398
|
+
data={invoices}
|
|
399
|
+
onRowClick={(row) => selectMatchable(row.id)}
|
|
400
|
+
selectedId={selectedMatchableId}
|
|
401
|
+
/>
|
|
402
|
+
</div>
|
|
403
|
+
) : (
|
|
404
|
+
<div>
|
|
405
|
+
<h4 className="text-md font-semibold mb-2 text-muted-foreground">
|
|
406
|
+
Unpaid Bills
|
|
407
|
+
</h4>
|
|
408
|
+
<DataTable
|
|
409
|
+
columns={billColumns}
|
|
410
|
+
data={bills}
|
|
411
|
+
onRowClick={(row) => selectMatchable(row.id)}
|
|
412
|
+
selectedId={selectedMatchableId}
|
|
413
|
+
/>
|
|
414
|
+
</div>
|
|
415
|
+
)}
|
|
416
|
+
</div>
|
|
417
|
+
</div>
|
|
418
|
+
|
|
419
|
+
{matchedItems.length > 0 && (
|
|
420
|
+
<div className="mt-12">
|
|
421
|
+
<h3 className="text-lg font-semibold mb-2">Matched Transactions</h3>
|
|
422
|
+
<DataTable columns={matchedColumns} data={matchedItems} />
|
|
423
|
+
</div>
|
|
424
|
+
)}
|
|
425
|
+
</div>
|
|
426
|
+
)
|
|
427
|
+
}
|
|
428
|
+
`;
|
|
429
|
+
const patchCode = `
|
|
430
|
+
Unpaid Bills
|
|
431
|
+
</h4>
|
|
432
|
+
<DataTable
|
|
433
|
+
columns={billColumns}
|
|
434
|
+
data={bills}
|
|
435
|
+
onRowClick={(row) => {
|
|
436
|
+
console.log(\`[UI] Selected matchable bill ID\`)
|
|
437
|
+
selectMatchable(row.id)
|
|
438
|
+
}}
|
|
439
|
+
selectedId={selectedMatchableId}
|
|
440
|
+
/>
|
|
441
|
+
</div>
|
|
442
|
+
)}
|
|
443
|
+
`;
|
|
444
|
+
const expectedResult = `
|
|
445
|
+
import { useEffect, useMemo } from "react"
|
|
446
|
+
import { trpc } from "@/lib/trpc"
|
|
447
|
+
|
|
448
|
+
import { Button } from "@/components/ui/button"
|
|
449
|
+
import { DataTable } from "@/components/ui/data-table"
|
|
450
|
+
import { useReconciliationStore } from "@/store/reconciliation"
|
|
451
|
+
|
|
452
|
+
import {
|
|
453
|
+
getBillColumns,
|
|
454
|
+
getInvoiceColumns,
|
|
455
|
+
getMatchedColumns,
|
|
456
|
+
getTransactionColumns,
|
|
457
|
+
} from "./transactions-columns"
|
|
458
|
+
|
|
459
|
+
export function TransactionsPage() {
|
|
460
|
+
const {
|
|
461
|
+
transactions,
|
|
462
|
+
invoices,
|
|
463
|
+
matchedItems,
|
|
464
|
+
selectedTransactionId,
|
|
465
|
+
selectedMatchableId,
|
|
466
|
+
loadInitialData,
|
|
467
|
+
selectTransaction,
|
|
468
|
+
selectMatchable,
|
|
469
|
+
matchItems,
|
|
470
|
+
unmatchItems,
|
|
471
|
+
} = useReconciliationStore()
|
|
472
|
+
const { data: bills = [] } = trpc.bills.getBills.useQuery()
|
|
473
|
+
|
|
474
|
+
// Load mock data when component mounts
|
|
475
|
+
useEffect(() => {
|
|
476
|
+
loadInitialData()
|
|
477
|
+
}, [loadInitialData])
|
|
478
|
+
|
|
479
|
+
const selectedTransaction =
|
|
480
|
+
transactions.find((t) => t.id === selectedTransactionId) || null
|
|
481
|
+
|
|
482
|
+
const transactionColumns = useMemo(() => getTransactionColumns(), [])
|
|
483
|
+
|
|
484
|
+
const invoiceColumns = useMemo(() => getInvoiceColumns(), [])
|
|
485
|
+
|
|
486
|
+
const billColumns = useMemo(() => getBillColumns(), [])
|
|
487
|
+
|
|
488
|
+
const matchedColumns = useMemo(
|
|
489
|
+
() =>
|
|
490
|
+
getMatchedColumns({
|
|
491
|
+
onUnmatch: unmatchItems,
|
|
492
|
+
}),
|
|
493
|
+
[unmatchItems]
|
|
494
|
+
)
|
|
495
|
+
|
|
496
|
+
const canMatch = selectedTransactionId && selectedMatchableId
|
|
497
|
+
|
|
498
|
+
return (
|
|
499
|
+
<div>
|
|
500
|
+
<div className="flex justify-between items-center mb-4">
|
|
501
|
+
<h2 className="text-2xl font-bold">Transaction Matching</h2>
|
|
502
|
+
<Button onClick={matchItems} disabled={!canMatch}>
|
|
503
|
+
Match Items
|
|
504
|
+
</Button>
|
|
505
|
+
</div>
|
|
506
|
+
|
|
507
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
508
|
+
{/* Left Panel: Bank Transactions */}
|
|
509
|
+
<div>
|
|
510
|
+
<h3 className="text-lg font-semibold mb-2">Bank Transactions</h3>
|
|
511
|
+
<p className="text-sm text-muted-foreground mb-4">
|
|
512
|
+
Select a transaction to begin matching.
|
|
513
|
+
</p>
|
|
514
|
+
<DataTable
|
|
515
|
+
columns={transactionColumns}
|
|
516
|
+
data={transactions}
|
|
517
|
+
onRowClick={(row) => selectTransaction(row.id)}
|
|
518
|
+
selectedId={selectedTransactionId}
|
|
519
|
+
/>
|
|
520
|
+
</div>
|
|
521
|
+
|
|
522
|
+
{/* Right Panel: Matching Items */}
|
|
523
|
+
<div>
|
|
524
|
+
<h3 className="text-lg font-semibold mb-2">Potential Matches</h3>
|
|
525
|
+
{!selectedTransaction ? (
|
|
526
|
+
<div className="h-full flex items-center justify-center rounded-lg border-2 border-dashed border-muted-foreground/30 p-8">
|
|
527
|
+
<p className="text-muted-foreground">
|
|
528
|
+
Select a transaction to see potential matches.
|
|
529
|
+
</p>
|
|
530
|
+
</div>
|
|
531
|
+
) : selectedTransaction.amount > 0 ? (
|
|
532
|
+
<div>
|
|
533
|
+
<h4 className="text-md font-semibold mb-2 text-muted-foreground">
|
|
534
|
+
Unpaid Invoices
|
|
535
|
+
</h4>
|
|
536
|
+
<DataTable
|
|
537
|
+
columns={invoiceColumns}
|
|
538
|
+
data={invoices}
|
|
539
|
+
onRowClick={(row) => selectMatchable(row.id)}
|
|
540
|
+
selectedId={selectedMatchableId}
|
|
541
|
+
/>
|
|
542
|
+
</div>
|
|
543
|
+
) : (
|
|
544
|
+
<div>
|
|
545
|
+
<h4 className="text-md font-semibold mb-2 text-muted-foreground">
|
|
546
|
+
Unpaid Bills
|
|
547
|
+
</h4>
|
|
548
|
+
<DataTable
|
|
549
|
+
columns={billColumns}
|
|
550
|
+
data={bills}
|
|
551
|
+
onRowClick={(row) => {
|
|
552
|
+
console.log(\`[UI] Selected matchable bill ID\`)
|
|
553
|
+
selectMatchable(row.id)
|
|
554
|
+
}}
|
|
555
|
+
selectedId={selectedMatchableId}
|
|
556
|
+
/>
|
|
557
|
+
</div>
|
|
558
|
+
)}
|
|
559
|
+
</div>
|
|
560
|
+
</div>
|
|
561
|
+
|
|
562
|
+
{matchedItems.length > 0 && (
|
|
563
|
+
<div className="mt-12">
|
|
564
|
+
<h3 className="text-lg font-semibold mb-2">Matched Transactions</h3>
|
|
565
|
+
<DataTable columns={matchedColumns} data={matchedItems} />
|
|
566
|
+
</div>
|
|
567
|
+
)}
|
|
568
|
+
</div>
|
|
569
|
+
)
|
|
570
|
+
}
|
|
571
|
+
`;
|
|
572
|
+
const result = await applySnippetPatch(
|
|
573
|
+
sourceCode,
|
|
574
|
+
patchCode,
|
|
575
|
+
TSX_WASM_PATH,
|
|
576
|
+
);
|
|
577
|
+
expect(normalize(result)).toEqual(normalize(expectedResult));
|
|
578
|
+
});
|
|
579
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { initializeParser } from './parser';
|
|
2
|
+
import { collectTokens } from './tokens';
|
|
3
|
+
import {
|
|
4
|
+
handleBeginOfFilePatch,
|
|
5
|
+
handleEndOfFilePatch,
|
|
6
|
+
handleStandardPatch,
|
|
7
|
+
} from './patcher';
|
|
8
|
+
|
|
9
|
+
export async function applySnippetPatch(
|
|
10
|
+
sourceCode: string,
|
|
11
|
+
patchCode: string,
|
|
12
|
+
grammarPath: string,
|
|
13
|
+
): Promise<string> {
|
|
14
|
+
const parser = await initializeParser(grammarPath);
|
|
15
|
+
|
|
16
|
+
const sourceTree = parser.parse(sourceCode);
|
|
17
|
+
if (!sourceTree) {
|
|
18
|
+
throw new Error('Failed to parse source code.');
|
|
19
|
+
}
|
|
20
|
+
const sourceTokens = collectTokens(sourceTree, sourceCode);
|
|
21
|
+
|
|
22
|
+
let patchResult: {
|
|
23
|
+
replaceStart: number;
|
|
24
|
+
replaceEnd: number;
|
|
25
|
+
patchInsertStart: number;
|
|
26
|
+
patchInsertEnd: number;
|
|
27
|
+
};
|
|
28
|
+
let processedPatchCode = patchCode;
|
|
29
|
+
|
|
30
|
+
const beginOfFileRegex = /\/\/\s*@begin-of-file.*/;
|
|
31
|
+
const endOfFileRegex = /\/\/\s*@end-of-file.*/;
|
|
32
|
+
|
|
33
|
+
const hasBeginOfFile = beginOfFileRegex.test(patchCode);
|
|
34
|
+
const hasEndOfFile = endOfFileRegex.test(patchCode);
|
|
35
|
+
|
|
36
|
+
if (hasBeginOfFile) {
|
|
37
|
+
processedPatchCode = patchCode.replace(beginOfFileRegex, '');
|
|
38
|
+
const patchTree = parser.parse(processedPatchCode);
|
|
39
|
+
if (!patchTree) {
|
|
40
|
+
throw new Error('Failed to parse patch code.');
|
|
41
|
+
}
|
|
42
|
+
const patchTokens = collectTokens(patchTree, processedPatchCode).filter(
|
|
43
|
+
(t) => t.text !== '',
|
|
44
|
+
);
|
|
45
|
+
patchResult = handleBeginOfFilePatch(sourceTokens, patchTokens);
|
|
46
|
+
} else if (hasEndOfFile) {
|
|
47
|
+
processedPatchCode = patchCode.replace(endOfFileRegex, '');
|
|
48
|
+
const patchTree = parser.parse(processedPatchCode);
|
|
49
|
+
if (!patchTree) {
|
|
50
|
+
throw new Error('Failed to parse patch code.');
|
|
51
|
+
}
|
|
52
|
+
const patchTokens = collectTokens(patchTree, processedPatchCode).filter(
|
|
53
|
+
(t) => t.text !== '',
|
|
54
|
+
);
|
|
55
|
+
patchResult = handleEndOfFilePatch(sourceTokens, patchTokens, sourceCode);
|
|
56
|
+
} else {
|
|
57
|
+
processedPatchCode = patchCode.trim();
|
|
58
|
+
const patchTree = parser.parse(processedPatchCode);
|
|
59
|
+
if (!patchTree) {
|
|
60
|
+
throw new Error('Failed to parse patch code.');
|
|
61
|
+
}
|
|
62
|
+
const patchTokens = collectTokens(patchTree, processedPatchCode).filter(
|
|
63
|
+
(t) => t.text !== '',
|
|
64
|
+
);
|
|
65
|
+
patchResult = handleStandardPatch(sourceTokens, patchTokens);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// NOTE: replaceStart/End are byte offsets.
|
|
69
|
+
// If your code can contain non-ASCII characters, you need to
|
|
70
|
+
// map byte offsets to JS string indices. For pure ASCII, this
|
|
71
|
+
// works as-is.
|
|
72
|
+
const prefix = sourceCode.slice(0, patchResult.replaceStart);
|
|
73
|
+
const suffix = sourceCode.slice(patchResult.replaceEnd);
|
|
74
|
+
const finalPatchContent = processedPatchCode.slice(
|
|
75
|
+
patchResult.patchInsertStart,
|
|
76
|
+
patchResult.patchInsertEnd,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
return prefix + finalPatchContent + suffix;
|
|
80
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// import Parser from 'web-tree-sitter';
|
|
2
|
+
|
|
3
|
+
// Cache parsers by grammar path to avoid re-initialization.
|
|
4
|
+
import { Language, Parser } from 'web-tree-sitter';
|
|
5
|
+
|
|
6
|
+
const parsers = new Map<string, Parser>();
|
|
7
|
+
|
|
8
|
+
export async function initializeParser(grammarPath: string): Promise<Parser> {
|
|
9
|
+
if (parsers.has(grammarPath)) {
|
|
10
|
+
return parsers.get(grammarPath)!;
|
|
11
|
+
}
|
|
12
|
+
await Parser.init();
|
|
13
|
+
const newParser = new Parser();
|
|
14
|
+
const language = await Language.load(grammarPath);
|
|
15
|
+
newParser.setLanguage(language);
|
|
16
|
+
parsers.set(grammarPath, newParser);
|
|
17
|
+
return newParser;
|
|
18
|
+
}
|