@git-stunts/git-warp 10.8.0 → 11.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 +53 -32
- package/SECURITY.md +64 -0
- package/bin/cli/commands/check.js +168 -0
- package/bin/cli/commands/doctor/checks.js +422 -0
- package/bin/cli/commands/doctor/codes.js +46 -0
- package/bin/cli/commands/doctor/index.js +239 -0
- package/bin/cli/commands/doctor/types.js +89 -0
- package/bin/cli/commands/history.js +73 -0
- package/bin/cli/commands/info.js +139 -0
- package/bin/cli/commands/install-hooks.js +128 -0
- package/bin/cli/commands/materialize.js +99 -0
- package/bin/cli/commands/path.js +88 -0
- package/bin/cli/commands/query.js +194 -0
- package/bin/cli/commands/registry.js +28 -0
- package/bin/cli/commands/seek.js +592 -0
- package/bin/cli/commands/trust.js +154 -0
- package/bin/cli/commands/verify-audit.js +113 -0
- package/bin/cli/commands/view.js +45 -0
- package/bin/cli/infrastructure.js +336 -0
- package/bin/cli/schemas.js +177 -0
- package/bin/cli/shared.js +244 -0
- package/bin/cli/types.js +85 -0
- package/bin/presenters/index.js +6 -0
- package/bin/presenters/text.js +136 -0
- package/bin/warp-graph.js +5 -2346
- package/index.d.ts +32 -2
- package/index.js +2 -0
- package/package.json +8 -7
- package/src/domain/WarpGraph.js +106 -3252
- package/src/domain/errors/QueryError.js +2 -2
- package/src/domain/errors/TrustError.js +29 -0
- package/src/domain/errors/index.js +1 -0
- package/src/domain/services/AuditMessageCodec.js +137 -0
- package/src/domain/services/AuditReceiptService.js +471 -0
- package/src/domain/services/AuditVerifierService.js +693 -0
- package/src/domain/services/HttpSyncServer.js +36 -22
- package/src/domain/services/MessageCodecInternal.js +3 -0
- package/src/domain/services/MessageSchemaDetector.js +2 -2
- package/src/domain/services/SyncAuthService.js +69 -3
- package/src/domain/services/WarpMessageCodec.js +4 -1
- package/src/domain/trust/TrustCanonical.js +42 -0
- package/src/domain/trust/TrustCrypto.js +111 -0
- package/src/domain/trust/TrustEvaluator.js +180 -0
- package/src/domain/trust/TrustRecordService.js +274 -0
- package/src/domain/trust/TrustStateBuilder.js +209 -0
- package/src/domain/trust/canonical.js +68 -0
- package/src/domain/trust/reasonCodes.js +64 -0
- package/src/domain/trust/schemas.js +160 -0
- package/src/domain/trust/verdict.js +42 -0
- package/src/domain/types/git-cas.d.ts +20 -0
- package/src/domain/utils/RefLayout.js +59 -0
- package/src/domain/warp/PatchSession.js +18 -0
- package/src/domain/warp/Writer.js +18 -3
- package/src/domain/warp/_internal.js +26 -0
- package/src/domain/warp/_wire.js +58 -0
- package/src/domain/warp/_wiredMethods.d.ts +100 -0
- package/src/domain/warp/checkpoint.methods.js +397 -0
- package/src/domain/warp/fork.methods.js +323 -0
- package/src/domain/warp/materialize.methods.js +188 -0
- package/src/domain/warp/materializeAdvanced.methods.js +339 -0
- package/src/domain/warp/patch.methods.js +529 -0
- package/src/domain/warp/provenance.methods.js +284 -0
- package/src/domain/warp/query.methods.js +279 -0
- package/src/domain/warp/subscribe.methods.js +272 -0
- package/src/domain/warp/sync.methods.js +549 -0
- package/src/infrastructure/adapters/GitGraphAdapter.js +67 -1
- package/src/infrastructure/adapters/InMemoryGraphAdapter.js +36 -0
- package/src/ports/CommitPort.js +10 -0
- package/src/ports/RefPort.js +17 -0
- package/src/hooks/post-merge.sh +0 -60
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { renderGraphView } from '../../../src/visualization/renderers/ascii/graph.js';
|
|
2
|
+
import { renderSvg } from '../../../src/visualization/renderers/svg/index.js';
|
|
3
|
+
import { layoutGraph, queryResultToGraphData } from '../../../src/visualization/layouts/index.js';
|
|
4
|
+
import { EXIT_CODES, usageError, parseCommandArgs } from '../infrastructure.js';
|
|
5
|
+
import { openGraph, applyCursorCeiling, emitCursorWarning } from '../shared.js';
|
|
6
|
+
import { querySchema } from '../schemas.js';
|
|
7
|
+
|
|
8
|
+
/** @typedef {import('../types.js').CliOptions} CliOptions */
|
|
9
|
+
|
|
10
|
+
const QUERY_OPTIONS = {
|
|
11
|
+
match: { type: 'string' },
|
|
12
|
+
'where-prop': { type: 'string', multiple: true },
|
|
13
|
+
select: { type: 'string' },
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Extracts --outgoing/--incoming traversal steps from args, returning
|
|
18
|
+
* remaining args for standard parseArgs processing.
|
|
19
|
+
*
|
|
20
|
+
* These flags have optional-value semantics: --outgoing [label].
|
|
21
|
+
* The label is consumed only if the next arg is not a flag.
|
|
22
|
+
*
|
|
23
|
+
* @param {string[]} args
|
|
24
|
+
* @returns {{steps: Array<{type: string, label?: string}>, remaining: string[]}}
|
|
25
|
+
*/
|
|
26
|
+
function extractTraversalSteps(args) {
|
|
27
|
+
/** @type {Array<{type: string, label?: string}>} */
|
|
28
|
+
const steps = [];
|
|
29
|
+
/** @type {string[]} */
|
|
30
|
+
const remaining = [];
|
|
31
|
+
|
|
32
|
+
for (let i = 0; i < args.length; i++) {
|
|
33
|
+
const arg = args[i];
|
|
34
|
+
if (arg === '--outgoing' || arg === '--incoming') {
|
|
35
|
+
const next = args[i + 1];
|
|
36
|
+
const label = next && !next.startsWith('-') ? next : undefined;
|
|
37
|
+
steps.push({ type: arg.slice(2), label });
|
|
38
|
+
if (label) {
|
|
39
|
+
i += 1;
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
remaining.push(arg);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return { steps, remaining };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** @param {string} value */
|
|
50
|
+
function parseWhereProp(value) {
|
|
51
|
+
const [key, ...rest] = value.split('=');
|
|
52
|
+
if (!key || rest.length === 0) {
|
|
53
|
+
throw usageError('Expected --where-prop key=value');
|
|
54
|
+
}
|
|
55
|
+
return { type: 'where-prop', key, value: rest.join('=') };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** @param {string} value */
|
|
59
|
+
function parseSelectFields(value) {
|
|
60
|
+
if (value === '') {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
return value.split(',').map((field) => field.trim()).filter(Boolean);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** @param {string[]} args */
|
|
67
|
+
function parseQueryArgs(args) {
|
|
68
|
+
// Extract traversal steps first (optional-value semantics)
|
|
69
|
+
const { steps, remaining } = extractTraversalSteps(args);
|
|
70
|
+
|
|
71
|
+
// Parse remaining flags with parseArgs + Zod
|
|
72
|
+
const { values } = parseCommandArgs(remaining, QUERY_OPTIONS, querySchema);
|
|
73
|
+
|
|
74
|
+
// Convert --where-prop values to steps
|
|
75
|
+
const allSteps = [
|
|
76
|
+
...steps,
|
|
77
|
+
...values.whereProp.map((/** @type {string} */ wp) => parseWhereProp(wp)),
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
match: values.match,
|
|
82
|
+
select: values.select !== undefined ? parseSelectFields(values.select) : null,
|
|
83
|
+
steps: allSteps,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @param {*} builder
|
|
89
|
+
* @param {Array<{type: string, label?: string, key?: string, value?: string}>} steps
|
|
90
|
+
*/
|
|
91
|
+
function applyQuerySteps(builder, steps) {
|
|
92
|
+
let current = builder;
|
|
93
|
+
for (const step of steps) {
|
|
94
|
+
current = applyQueryStep(current, step);
|
|
95
|
+
}
|
|
96
|
+
return current;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @param {*} builder
|
|
101
|
+
* @param {{type: string, label?: string, key?: string, value?: string}} step
|
|
102
|
+
*/
|
|
103
|
+
function applyQueryStep(builder, step) {
|
|
104
|
+
if (step.type === 'outgoing') {
|
|
105
|
+
return builder.outgoing(step.label);
|
|
106
|
+
}
|
|
107
|
+
if (step.type === 'incoming') {
|
|
108
|
+
return builder.incoming(step.label);
|
|
109
|
+
}
|
|
110
|
+
if (step.type === 'where-prop') {
|
|
111
|
+
return builder.where((/** @type {*} */ node) => matchesPropFilter(node, /** @type {string} */ (step.key), /** @type {string} */ (step.value))); // TODO(ts-cleanup): type CLI payload
|
|
112
|
+
}
|
|
113
|
+
return builder;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @param {*} node
|
|
118
|
+
* @param {string} key
|
|
119
|
+
* @param {string} value
|
|
120
|
+
*/
|
|
121
|
+
function matchesPropFilter(node, key, value) {
|
|
122
|
+
const props = node.props || {};
|
|
123
|
+
if (!Object.prototype.hasOwnProperty.call(props, key)) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
return String(props[key]) === value;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @param {string} graphName
|
|
131
|
+
* @param {*} result
|
|
132
|
+
* @returns {{graph: string, stateHash: *, nodes: *, _renderedSvg?: string, _renderedAscii?: string}}
|
|
133
|
+
*/
|
|
134
|
+
function buildQueryPayload(graphName, result) {
|
|
135
|
+
return {
|
|
136
|
+
graph: graphName,
|
|
137
|
+
stateHash: result.stateHash,
|
|
138
|
+
nodes: result.nodes,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** @param {*} error */
|
|
143
|
+
function mapQueryError(error) {
|
|
144
|
+
if (error && error.code && String(error.code).startsWith('E_QUERY')) {
|
|
145
|
+
throw usageError(error.message);
|
|
146
|
+
}
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Handles the `query` command: runs a logical graph query.
|
|
152
|
+
* @param {{options: CliOptions, args: string[]}} params
|
|
153
|
+
* @returns {Promise<{payload: *, exitCode: number}>}
|
|
154
|
+
*/
|
|
155
|
+
export default async function handleQuery({ options, args }) {
|
|
156
|
+
const querySpec = parseQueryArgs(args);
|
|
157
|
+
const { graph, graphName, persistence } = await openGraph(options);
|
|
158
|
+
const cursorInfo = await applyCursorCeiling(graph, persistence, graphName);
|
|
159
|
+
emitCursorWarning(cursorInfo, null);
|
|
160
|
+
let builder = graph.query();
|
|
161
|
+
|
|
162
|
+
if (querySpec.match !== null) {
|
|
163
|
+
builder = builder.match(querySpec.match);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
builder = applyQuerySteps(builder, querySpec.steps);
|
|
167
|
+
|
|
168
|
+
if (querySpec.select !== null) {
|
|
169
|
+
builder = builder.select(querySpec.select);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
const result = await builder.run();
|
|
174
|
+
const payload = buildQueryPayload(graphName, result);
|
|
175
|
+
|
|
176
|
+
if (options.view) {
|
|
177
|
+
const edges = await graph.getEdges();
|
|
178
|
+
const graphData = queryResultToGraphData(payload, edges);
|
|
179
|
+
const positioned = await layoutGraph(graphData, { type: 'query' });
|
|
180
|
+
if (typeof options.view === 'string' && (options.view.startsWith('svg:') || options.view.startsWith('html:'))) {
|
|
181
|
+
payload._renderedSvg = renderSvg(positioned, { title: `${graphName} query` });
|
|
182
|
+
} else {
|
|
183
|
+
payload._renderedAscii = renderGraphView(positioned, { title: `QUERY: ${graphName}` });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
payload,
|
|
189
|
+
exitCode: EXIT_CODES.OK,
|
|
190
|
+
};
|
|
191
|
+
} catch (error) {
|
|
192
|
+
throw mapQueryError(error);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import handleInfo from './info.js';
|
|
2
|
+
import handleQuery from './query.js';
|
|
3
|
+
import handlePath from './path.js';
|
|
4
|
+
import handleHistory from './history.js';
|
|
5
|
+
import handleCheck from './check.js';
|
|
6
|
+
import handleDoctor from './doctor/index.js';
|
|
7
|
+
import handleMaterialize from './materialize.js';
|
|
8
|
+
import handleSeek from './seek.js';
|
|
9
|
+
import handleVerifyAudit from './verify-audit.js';
|
|
10
|
+
import handleView from './view.js';
|
|
11
|
+
import handleInstallHooks from './install-hooks.js';
|
|
12
|
+
import handleTrust from './trust.js';
|
|
13
|
+
|
|
14
|
+
/** @type {Map<string, Function>} */
|
|
15
|
+
export const COMMANDS = new Map(/** @type {[string, Function][]} */ ([
|
|
16
|
+
['info', handleInfo],
|
|
17
|
+
['query', handleQuery],
|
|
18
|
+
['path', handlePath],
|
|
19
|
+
['history', handleHistory],
|
|
20
|
+
['check', handleCheck],
|
|
21
|
+
['doctor', handleDoctor],
|
|
22
|
+
['materialize', handleMaterialize],
|
|
23
|
+
['seek', handleSeek],
|
|
24
|
+
['verify-audit', handleVerifyAudit],
|
|
25
|
+
['trust', handleTrust],
|
|
26
|
+
['view', handleView],
|
|
27
|
+
['install-hooks', handleInstallHooks],
|
|
28
|
+
]));
|