gitsheets-axi 0.0.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/LICENSE +201 -0
- package/README.md +116 -0
- package/dist/bin/gitsheets-axi.d.ts +3 -0
- package/dist/bin/gitsheets-axi.d.ts.map +1 -0
- package/dist/bin/gitsheets-axi.js +4 -0
- package/dist/bin/gitsheets-axi.js.map +1 -0
- package/dist/src/cli.d.ts +3 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +105 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/commands/attachment.d.ts +4 -0
- package/dist/src/commands/attachment.d.ts.map +1 -0
- package/dist/src/commands/attachment.js +356 -0
- package/dist/src/commands/attachment.js.map +1 -0
- package/dist/src/commands/check.d.ts +4 -0
- package/dist/src/commands/check.d.ts.map +1 -0
- package/dist/src/commands/check.js +136 -0
- package/dist/src/commands/check.js.map +1 -0
- package/dist/src/commands/delete.d.ts +4 -0
- package/dist/src/commands/delete.d.ts.map +1 -0
- package/dist/src/commands/delete.js +132 -0
- package/dist/src/commands/delete.js.map +1 -0
- package/dist/src/commands/diff.d.ts +4 -0
- package/dist/src/commands/diff.d.ts.map +1 -0
- package/dist/src/commands/diff.js +139 -0
- package/dist/src/commands/diff.js.map +1 -0
- package/dist/src/commands/home.d.ts +3 -0
- package/dist/src/commands/home.d.ts.map +1 -0
- package/dist/src/commands/home.js +71 -0
- package/dist/src/commands/home.js.map +1 -0
- package/dist/src/commands/infer.d.ts +4 -0
- package/dist/src/commands/infer.d.ts.map +1 -0
- package/dist/src/commands/infer.js +214 -0
- package/dist/src/commands/infer.js.map +1 -0
- package/dist/src/commands/init.d.ts +4 -0
- package/dist/src/commands/init.d.ts.map +1 -0
- package/dist/src/commands/init.js +172 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/migrate-config.d.ts +4 -0
- package/dist/src/commands/migrate-config.d.ts.map +1 -0
- package/dist/src/commands/migrate-config.js +161 -0
- package/dist/src/commands/migrate-config.js.map +1 -0
- package/dist/src/commands/normalize.d.ts +4 -0
- package/dist/src/commands/normalize.d.ts.map +1 -0
- package/dist/src/commands/normalize.js +142 -0
- package/dist/src/commands/normalize.js.map +1 -0
- package/dist/src/commands/patch.d.ts +4 -0
- package/dist/src/commands/patch.d.ts.map +1 -0
- package/dist/src/commands/patch.js +172 -0
- package/dist/src/commands/patch.js.map +1 -0
- package/dist/src/commands/push.d.ts +4 -0
- package/dist/src/commands/push.d.ts.map +1 -0
- package/dist/src/commands/push.js +112 -0
- package/dist/src/commands/push.js.map +1 -0
- package/dist/src/commands/query.d.ts +4 -0
- package/dist/src/commands/query.d.ts.map +1 -0
- package/dist/src/commands/query.js +141 -0
- package/dist/src/commands/query.js.map +1 -0
- package/dist/src/commands/read.d.ts +4 -0
- package/dist/src/commands/read.d.ts.map +1 -0
- package/dist/src/commands/read.js +149 -0
- package/dist/src/commands/read.js.map +1 -0
- package/dist/src/commands/sheets.d.ts +4 -0
- package/dist/src/commands/sheets.d.ts.map +1 -0
- package/dist/src/commands/sheets.js +142 -0
- package/dist/src/commands/sheets.js.map +1 -0
- package/dist/src/commands/upsert.d.ts +4 -0
- package/dist/src/commands/upsert.d.ts.map +1 -0
- package/dist/src/commands/upsert.js +137 -0
- package/dist/src/commands/upsert.js.map +1 -0
- package/dist/src/context.d.ts +17 -0
- package/dist/src/context.d.ts.map +1 -0
- package/dist/src/context.js +47 -0
- package/dist/src/context.js.map +1 -0
- package/dist/src/errors.d.ts +13 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +58 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/output/index.d.ts +3 -0
- package/dist/src/output/index.d.ts.map +1 -0
- package/dist/src/output/index.js +3 -0
- package/dist/src/output/index.js.map +1 -0
- package/dist/src/output/render.d.ts +28 -0
- package/dist/src/output/render.d.ts.map +1 -0
- package/dist/src/output/render.js +49 -0
- package/dist/src/output/render.js.map +1 -0
- package/dist/src/output/schema.d.ts +29 -0
- package/dist/src/output/schema.d.ts.map +1 -0
- package/dist/src/output/schema.js +51 -0
- package/dist/src/output/schema.js.map +1 -0
- package/dist/src/output/sheet-schema.d.ts +27 -0
- package/dist/src/output/sheet-schema.d.ts.map +1 -0
- package/dist/src/output/sheet-schema.js +114 -0
- package/dist/src/output/sheet-schema.js.map +1 -0
- package/dist/src/util/stdin.d.ts +7 -0
- package/dist/src/util/stdin.d.ts.map +1 -0
- package/dist/src/util/stdin.js +19 -0
- package/dist/src/util/stdin.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { isAbsolute, join } from 'node:path';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
import { AxiError } from 'axi-sdk-js';
|
|
6
|
+
import { parseConfigToml, stringifyRecord } from 'gitsheets';
|
|
7
|
+
import { translateError } from '../errors.js';
|
|
8
|
+
import { renderObject } from '../output/render.js';
|
|
9
|
+
const exec = promisify(execFile);
|
|
10
|
+
export const INIT_HELP = `usage: gitsheets-axi init <sheet> [--path <template>] [--schema <file>] [--force]
|
|
11
|
+
flags[4]:
|
|
12
|
+
--path <template> Path template (default: "\${{ id }}")
|
|
13
|
+
--schema <file> Path to a JSON file with the schema to embed
|
|
14
|
+
--force Overwrite an existing config
|
|
15
|
+
--message <m> Commit message (default: "<sheet> init sheet config")
|
|
16
|
+
examples:
|
|
17
|
+
gitsheets-axi init users
|
|
18
|
+
gitsheets-axi init posts --path '\${{ slug }}'
|
|
19
|
+
gitsheets-axi init users --schema users.schema.json
|
|
20
|
+
behavior:
|
|
21
|
+
Writes a starter \`.gitsheets/<sheet>.toml\` with a default root,
|
|
22
|
+
path template, and optional schema. Refuses to overwrite an
|
|
23
|
+
existing config unless --force is set.
|
|
24
|
+
idempotency:
|
|
25
|
+
When the rendered config matches the existing config byte-for-byte,
|
|
26
|
+
exits 0 with result: "no-op" — safe to re-run.
|
|
27
|
+
`;
|
|
28
|
+
function parseInitFlags(args) {
|
|
29
|
+
const flags = {
|
|
30
|
+
sheet: '',
|
|
31
|
+
path: '${{ id }}',
|
|
32
|
+
schemaFile: undefined,
|
|
33
|
+
force: false,
|
|
34
|
+
message: undefined,
|
|
35
|
+
};
|
|
36
|
+
const positional = [];
|
|
37
|
+
for (let i = 0; i < args.length; i++) {
|
|
38
|
+
const arg = args[i];
|
|
39
|
+
if (arg === undefined)
|
|
40
|
+
continue;
|
|
41
|
+
const next = args[i + 1];
|
|
42
|
+
switch (arg) {
|
|
43
|
+
case '--path':
|
|
44
|
+
if (!next)
|
|
45
|
+
throw new AxiError('--path expects a template', 'VALIDATION_ERROR');
|
|
46
|
+
flags.path = next;
|
|
47
|
+
i++;
|
|
48
|
+
break;
|
|
49
|
+
case '--schema':
|
|
50
|
+
if (!next)
|
|
51
|
+
throw new AxiError('--schema expects a file path', 'VALIDATION_ERROR');
|
|
52
|
+
flags.schemaFile = next;
|
|
53
|
+
i++;
|
|
54
|
+
break;
|
|
55
|
+
case '--force':
|
|
56
|
+
flags.force = true;
|
|
57
|
+
break;
|
|
58
|
+
case '--message':
|
|
59
|
+
if (!next)
|
|
60
|
+
throw new AxiError('--message expects a string', 'VALIDATION_ERROR');
|
|
61
|
+
flags.message = next;
|
|
62
|
+
i++;
|
|
63
|
+
break;
|
|
64
|
+
default:
|
|
65
|
+
if (arg.startsWith('-')) {
|
|
66
|
+
throw new AxiError(`Unknown flag: ${arg}`, 'VALIDATION_ERROR', [
|
|
67
|
+
'Run `gitsheets-axi init --help`',
|
|
68
|
+
]);
|
|
69
|
+
}
|
|
70
|
+
positional.push(arg);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (positional.length !== 1) {
|
|
74
|
+
throw new AxiError('init requires <sheet>', 'VALIDATION_ERROR', [
|
|
75
|
+
'Example: gitsheets-axi init users',
|
|
76
|
+
]);
|
|
77
|
+
}
|
|
78
|
+
flags.sheet = positional[0];
|
|
79
|
+
return flags;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Read the raw bytes of a tracked file at HEAD. Returns null if the file
|
|
83
|
+
* doesn't exist there (or if HEAD doesn't exist yet on a fresh repo).
|
|
84
|
+
*/
|
|
85
|
+
async function readBytesAtHead(gitDir, path) {
|
|
86
|
+
try {
|
|
87
|
+
const { stdout } = await exec('git', ['show', `HEAD:${path}`], {
|
|
88
|
+
cwd: gitDir,
|
|
89
|
+
maxBuffer: 100 * 1024 * 1024,
|
|
90
|
+
});
|
|
91
|
+
return stdout;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export async function initCommand(args, ctx) {
|
|
98
|
+
if (args.length === 0 || (args.length === 1 && args[0] === '--help')) {
|
|
99
|
+
return INIT_HELP;
|
|
100
|
+
}
|
|
101
|
+
const flags = parseInitFlags(args);
|
|
102
|
+
const repo = await ctx.repo();
|
|
103
|
+
const configPath = `.gitsheets/${flags.sheet}.toml`;
|
|
104
|
+
const newConfig = {
|
|
105
|
+
gitsheet: { root: flags.sheet, path: flags.path },
|
|
106
|
+
};
|
|
107
|
+
if (flags.schemaFile) {
|
|
108
|
+
const absPath = isAbsolute(flags.schemaFile)
|
|
109
|
+
? flags.schemaFile
|
|
110
|
+
: join(process.cwd(), flags.schemaFile);
|
|
111
|
+
let schemaText;
|
|
112
|
+
try {
|
|
113
|
+
schemaText = await readFile(absPath, 'utf-8');
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
throw new AxiError(`init: cannot read schema file ${flags.schemaFile}: ${err instanceof Error ? err.message : String(err)}`, 'NOT_FOUND');
|
|
117
|
+
}
|
|
118
|
+
let schemaParsed;
|
|
119
|
+
try {
|
|
120
|
+
schemaParsed = JSON.parse(schemaText);
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
throw new AxiError(`init: schema file isn't valid JSON: ${err instanceof Error ? err.message : String(err)}`, 'INVALID_JSON');
|
|
124
|
+
}
|
|
125
|
+
if (typeof schemaParsed !== 'object' || schemaParsed === null) {
|
|
126
|
+
throw new AxiError('init: --schema did not parse as a JSON object', 'VALIDATION_ERROR');
|
|
127
|
+
}
|
|
128
|
+
newConfig['gitsheet']['schema'] = schemaParsed;
|
|
129
|
+
}
|
|
130
|
+
const newText = stringifyRecord(newConfig);
|
|
131
|
+
// Validate the new config parses cleanly before committing.
|
|
132
|
+
try {
|
|
133
|
+
parseConfigToml(newText, configPath);
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
throw new AxiError(`init: produced an invalid config: ${err instanceof Error ? err.message : String(err)}`, 'CONFIG_INVALID');
|
|
137
|
+
}
|
|
138
|
+
const existing = await readBytesAtHead(repoGitDir(repo), configPath);
|
|
139
|
+
if (existing === newText) {
|
|
140
|
+
return renderObject({
|
|
141
|
+
result: 'no-op',
|
|
142
|
+
sheet: flags.sheet,
|
|
143
|
+
config: configPath,
|
|
144
|
+
reason: 'config already matches',
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (existing !== null && !flags.force) {
|
|
148
|
+
throw new AxiError(`init: ${configPath} already exists and bytes differ — re-run with --force to overwrite`, 'CONFIG_EXISTS', [`gitsheets-axi init ${flags.sheet} --force ...`]);
|
|
149
|
+
}
|
|
150
|
+
const commitMessage = flags.message ?? `${flags.sheet} init sheet config`;
|
|
151
|
+
let commitHash = '';
|
|
152
|
+
try {
|
|
153
|
+
const result = await repo.transact({ message: commitMessage }, async (tx) => {
|
|
154
|
+
await tx.tree.writeChild(configPath, newText);
|
|
155
|
+
tx.markMutated();
|
|
156
|
+
});
|
|
157
|
+
commitHash = result.commitHash ?? '';
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
throw translateError(error);
|
|
161
|
+
}
|
|
162
|
+
return renderObject({
|
|
163
|
+
result: existing === null ? 'created' : 'overwritten',
|
|
164
|
+
sheet: flags.sheet,
|
|
165
|
+
config: configPath,
|
|
166
|
+
commit: commitHash,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
function repoGitDir(repo) {
|
|
170
|
+
return repo.gitDir;
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAI7D,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAEjC,MAAM,CAAC,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;CAiBxB,CAAC;AAUF,SAAS,cAAc,CAAC,IAAc;IACpC,MAAM,KAAK,GAAc;QACvB,KAAK,EAAE,EAAE;QACT,IAAI,EAAE,WAAW;QACjB,UAAU,EAAE,SAAS;QACrB,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,SAAS;KACnB,CAAC;IACF,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,KAAK,SAAS;YAAE,SAAS;QAChC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzB,QAAQ,GAAG,EAAE,CAAC;YACZ,KAAK,QAAQ;gBACX,IAAI,CAAC,IAAI;oBAAE,MAAM,IAAI,QAAQ,CAAC,2BAA2B,EAAE,kBAAkB,CAAC,CAAC;gBAC/E,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;gBAClB,CAAC,EAAE,CAAC;gBACJ,MAAM;YACR,KAAK,UAAU;gBACb,IAAI,CAAC,IAAI;oBAAE,MAAM,IAAI,QAAQ,CAAC,8BAA8B,EAAE,kBAAkB,CAAC,CAAC;gBAClF,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;gBACxB,CAAC,EAAE,CAAC;gBACJ,MAAM;YACR,KAAK,SAAS;gBACZ,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;gBACnB,MAAM;YACR,KAAK,WAAW;gBACd,IAAI,CAAC,IAAI;oBAAE,MAAM,IAAI,QAAQ,CAAC,4BAA4B,EAAE,kBAAkB,CAAC,CAAC;gBAChF,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;gBACrB,CAAC,EAAE,CAAC;gBACJ,MAAM;YACR;gBACE,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACxB,MAAM,IAAI,QAAQ,CAAC,iBAAiB,GAAG,EAAE,EAAE,kBAAkB,EAAE;wBAC7D,iCAAiC;qBAClC,CAAC,CAAC;gBACL,CAAC;gBACD,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,QAAQ,CAAC,uBAAuB,EAAE,kBAAkB,EAAE;YAC9D,mCAAmC;SACpC,CAAC,CAAC;IACL,CAAC;IACD,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,CAAC,CAAE,CAAC;IAC7B,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,eAAe,CAC5B,MAAc,EACd,IAAY;IAEZ,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAC,EAAE;YAC7D,GAAG,EAAE,MAAM;YACX,SAAS,EAAE,GAAG,GAAG,IAAI,GAAG,IAAI;SAC7B,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAc,EACd,GAAqB;IAErB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;QACrE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,MAAM,UAAU,GAAG,cAAc,KAAK,CAAC,KAAK,OAAO,CAAC;IAEpD,MAAM,SAAS,GAAe;QAC5B,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE;KAClD,CAAC;IAEF,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACrB,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC;YAC1C,CAAC,CAAC,KAAK,CAAC,UAAU;YAClB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QAC1C,IAAI,UAAkB,CAAC;QACvB,IAAI,CAAC;YACH,UAAU,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,QAAQ,CAChB,iCAAiC,KAAK,CAAC,UAAU,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EACxG,WAAW,CACZ,CAAC;QACJ,CAAC;QACD,IAAI,YAAqB,CAAC;QAC1B,IAAI,CAAC;YACH,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,QAAQ,CAChB,uCAAuC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EACzF,cAAc,CACf,CAAC;QACJ,CAAC;QACD,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;YAC9D,MAAM,IAAI,QAAQ,CAAC,+CAA+C,EAAE,kBAAkB,CAAC,CAAC;QAC1F,CAAC;QACA,SAAS,CAAC,UAAU,CAAgB,CAAC,QAAQ,CAAC,GAAG,YAA0B,CAAC;IAC/E,CAAC;IAED,MAAM,OAAO,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAE3C,4DAA4D;IAC5D,IAAI,CAAC;QACH,eAAe,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,QAAQ,CAChB,qCAAqC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EACvF,gBAAgB,CACjB,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC;IAErE,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO,YAAY,CAAC;YAClB,MAAM,EAAE,OAAO;YACf,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,MAAM,EAAE,UAAU;YAClB,MAAM,EAAE,wBAAwB;SACjC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACtC,MAAM,IAAI,QAAQ,CAChB,SAAS,UAAU,qEAAqE,EACxF,eAAe,EACf,CAAC,sBAAsB,KAAK,CAAC,KAAK,cAAc,CAAC,CAClD,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,IAAI,GAAG,KAAK,CAAC,KAAK,oBAAoB,CAAC;IAC1E,IAAI,UAAU,GAAG,EAAE,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAChC,EAAE,OAAO,EAAE,aAAa,EAAE,EAC1B,KAAK,EAAE,EAAE,EAAE,EAAE;YACX,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAC9C,EAAE,CAAC,WAAW,EAAE,CAAC;QACnB,CAAC,CACF,CAAC;QACF,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO,YAAY,CAAC;QAClB,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa;QACrD,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,UAAU;QAClB,MAAM,EAAE,UAAU;KACnB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,UAAU,CAAC,IAAgB;IAClC,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { GitsheetsContext } from '../context.js';
|
|
2
|
+
export declare const MIGRATE_CONFIG_HELP = "usage: gitsheets-axi migrate-config <sheet> [--message m]\nflags[1]:\n --message <m> Commit message (default: \"<sheet> migrate-config\")\nexamples:\n gitsheets-axi migrate-config users\nbehavior:\n Translates a pre-v1.0 `[gitsheet.fields]` block into the modern\n `[gitsheet.schema]` block. type/enum/default move into JSON Schema\n properties; sort rules stay on the field (they're a normalization\n concern, not validation). trueValues/falseValues are dropped with\n a warning \u2014 those moved out of validation in v1.0 (CSV ingest concern).\nidempotency:\n If the config has no `[gitsheet.fields]` block, exits 0 with\n result: \"no-op\". If the migration produces identical bytes, same.\n";
|
|
3
|
+
export declare function migrateConfigCommand(args: string[], ctx: GitsheetsContext): Promise<string>;
|
|
4
|
+
//# sourceMappingURL=migrate-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-config.d.ts","sourceRoot":"","sources":["../../../src/commands/migrate-config.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAMtD,eAAO,MAAM,mBAAmB,4sBAc/B,CAAC;AAgDF,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,MAAM,CAAC,CAsGjB"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import { AxiError } from 'axi-sdk-js';
|
|
4
|
+
import { parseToml, stringifyRecord } from 'gitsheets';
|
|
5
|
+
import { translateError } from '../errors.js';
|
|
6
|
+
import { renderObject } from '../output/render.js';
|
|
7
|
+
const exec = promisify(execFile);
|
|
8
|
+
export const MIGRATE_CONFIG_HELP = `usage: gitsheets-axi migrate-config <sheet> [--message m]
|
|
9
|
+
flags[1]:
|
|
10
|
+
--message <m> Commit message (default: "<sheet> migrate-config")
|
|
11
|
+
examples:
|
|
12
|
+
gitsheets-axi migrate-config users
|
|
13
|
+
behavior:
|
|
14
|
+
Translates a pre-v1.0 \`[gitsheet.fields]\` block into the modern
|
|
15
|
+
\`[gitsheet.schema]\` block. type/enum/default move into JSON Schema
|
|
16
|
+
properties; sort rules stay on the field (they're a normalization
|
|
17
|
+
concern, not validation). trueValues/falseValues are dropped with
|
|
18
|
+
a warning — those moved out of validation in v1.0 (CSV ingest concern).
|
|
19
|
+
idempotency:
|
|
20
|
+
If the config has no \`[gitsheet.fields]\` block, exits 0 with
|
|
21
|
+
result: "no-op". If the migration produces identical bytes, same.
|
|
22
|
+
`;
|
|
23
|
+
function parseMigrateFlags(args) {
|
|
24
|
+
const flags = { sheet: '', message: undefined };
|
|
25
|
+
const positional = [];
|
|
26
|
+
for (let i = 0; i < args.length; i++) {
|
|
27
|
+
const arg = args[i];
|
|
28
|
+
if (arg === undefined)
|
|
29
|
+
continue;
|
|
30
|
+
const next = args[i + 1];
|
|
31
|
+
if (arg === '--message') {
|
|
32
|
+
if (!next)
|
|
33
|
+
throw new AxiError('--message expects a string', 'VALIDATION_ERROR');
|
|
34
|
+
flags.message = next;
|
|
35
|
+
i++;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (arg.startsWith('-')) {
|
|
39
|
+
throw new AxiError(`Unknown flag: ${arg}`, 'VALIDATION_ERROR', [
|
|
40
|
+
'Run `gitsheets-axi migrate-config --help`',
|
|
41
|
+
]);
|
|
42
|
+
}
|
|
43
|
+
positional.push(arg);
|
|
44
|
+
}
|
|
45
|
+
if (positional.length !== 1) {
|
|
46
|
+
throw new AxiError('migrate-config requires <sheet>', 'VALIDATION_ERROR', [
|
|
47
|
+
'Example: gitsheets-axi migrate-config users',
|
|
48
|
+
]);
|
|
49
|
+
}
|
|
50
|
+
flags.sheet = positional[0];
|
|
51
|
+
return flags;
|
|
52
|
+
}
|
|
53
|
+
async function readConfigText(gitDir, path) {
|
|
54
|
+
try {
|
|
55
|
+
const { stdout } = await exec('git', ['show', `HEAD:${path}`], {
|
|
56
|
+
cwd: gitDir,
|
|
57
|
+
maxBuffer: 100 * 1024 * 1024,
|
|
58
|
+
});
|
|
59
|
+
return stdout;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export async function migrateConfigCommand(args, ctx) {
|
|
66
|
+
if (args.length === 0 || (args.length === 1 && args[0] === '--help')) {
|
|
67
|
+
return MIGRATE_CONFIG_HELP;
|
|
68
|
+
}
|
|
69
|
+
const flags = parseMigrateFlags(args);
|
|
70
|
+
const repo = await ctx.repo();
|
|
71
|
+
const configPath = `.gitsheets/${flags.sheet}.toml`;
|
|
72
|
+
const configText = await readConfigText(repo.gitDir, configPath);
|
|
73
|
+
if (configText === null) {
|
|
74
|
+
throw new AxiError(`migrate-config: ${configPath} doesn't exist`, 'NOT_FOUND');
|
|
75
|
+
}
|
|
76
|
+
let parsed;
|
|
77
|
+
try {
|
|
78
|
+
parsed = parseToml(configText);
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
throw new AxiError(`migrate-config: ${configPath} failed to parse: ${err instanceof Error ? err.message : String(err)}`, 'CONFIG_INVALID');
|
|
82
|
+
}
|
|
83
|
+
const gitsheet = (parsed['gitsheet'] ?? {});
|
|
84
|
+
const fields = gitsheet['fields'];
|
|
85
|
+
if (!fields || typeof fields !== 'object') {
|
|
86
|
+
return renderObject({
|
|
87
|
+
result: 'no-op',
|
|
88
|
+
sheet: flags.sheet,
|
|
89
|
+
config: configPath,
|
|
90
|
+
reason: 'no [gitsheet.fields] block to migrate',
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
const properties = {};
|
|
94
|
+
const remainingFields = {};
|
|
95
|
+
const warnings = [];
|
|
96
|
+
for (const [name, cfg] of Object.entries(fields)) {
|
|
97
|
+
if (typeof cfg !== 'object' || cfg === null)
|
|
98
|
+
continue;
|
|
99
|
+
const schemaProp = {};
|
|
100
|
+
const remainingField = {};
|
|
101
|
+
if (cfg['type'] !== undefined)
|
|
102
|
+
schemaProp['type'] = cfg['type'];
|
|
103
|
+
if (cfg['enum'] !== undefined)
|
|
104
|
+
schemaProp['enum'] = cfg['enum'];
|
|
105
|
+
if (cfg['default'] !== undefined)
|
|
106
|
+
schemaProp['default'] = cfg['default'];
|
|
107
|
+
if (cfg['sort'] !== undefined)
|
|
108
|
+
remainingField['sort'] = cfg['sort'];
|
|
109
|
+
if (cfg['trueValues'] !== undefined || cfg['falseValues'] !== undefined) {
|
|
110
|
+
warnings.push(`${name}.trueValues/falseValues dropped (moved to CSV ingest)`);
|
|
111
|
+
}
|
|
112
|
+
if (Object.keys(schemaProp).length > 0)
|
|
113
|
+
properties[name] = schemaProp;
|
|
114
|
+
if (Object.keys(remainingField).length > 0)
|
|
115
|
+
remainingFields[name] = remainingField;
|
|
116
|
+
}
|
|
117
|
+
const newGitsheet = {};
|
|
118
|
+
for (const [k, v] of Object.entries(gitsheet)) {
|
|
119
|
+
if (k === 'fields' || k === 'schema')
|
|
120
|
+
continue;
|
|
121
|
+
newGitsheet[k] = v;
|
|
122
|
+
}
|
|
123
|
+
if (Object.keys(remainingFields).length > 0)
|
|
124
|
+
newGitsheet['fields'] = remainingFields;
|
|
125
|
+
if (Object.keys(properties).length > 0) {
|
|
126
|
+
newGitsheet['schema'] = { type: 'object', properties };
|
|
127
|
+
}
|
|
128
|
+
parsed['gitsheet'] = newGitsheet;
|
|
129
|
+
const newText = stringifyRecord(parsed);
|
|
130
|
+
if (newText === configText) {
|
|
131
|
+
return renderObject({
|
|
132
|
+
result: 'no-op',
|
|
133
|
+
sheet: flags.sheet,
|
|
134
|
+
config: configPath,
|
|
135
|
+
reason: 'migration produced identical bytes',
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
const commitMessage = flags.message ?? `${flags.sheet} migrate-config`;
|
|
139
|
+
let commitHash = '';
|
|
140
|
+
try {
|
|
141
|
+
const result = await repo.transact({ message: commitMessage }, async (tx) => {
|
|
142
|
+
await tx.tree.writeChild(configPath, newText);
|
|
143
|
+
tx.markMutated();
|
|
144
|
+
});
|
|
145
|
+
commitHash = result.commitHash ?? '';
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
throw translateError(error);
|
|
149
|
+
}
|
|
150
|
+
const output = {
|
|
151
|
+
result: 'committed',
|
|
152
|
+
sheet: flags.sheet,
|
|
153
|
+
config: configPath,
|
|
154
|
+
properties_migrated: Object.keys(properties).length,
|
|
155
|
+
commit: commitHash,
|
|
156
|
+
};
|
|
157
|
+
if (warnings.length > 0)
|
|
158
|
+
output['warnings'] = warnings;
|
|
159
|
+
return renderObject(output);
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=migrate-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-config.js","sourceRoot":"","sources":["../../../src/commands/migrate-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { GitsheetsContext } from '../context.js';
|
|
2
|
+
export declare const NORMALIZE_HELP = "usage: gitsheets-axi normalize <sheet> [--prefix p] [--message m]\nflags[2]:\n --prefix <p> Tenant sub-tree scope\n --message <m> Commit message (default: \"<sheet> normalize\")\nexamples:\n gitsheets-axi normalize users\nbehavior:\n Reads every record in the sheet, re-runs validation + canonical\n serialization, and writes back any record whose bytes differ.\n Idempotent per-record via Sheet.willChange: records that already\n serialize to identical bytes are skipped. If every record is already\n canonical, exits 0 with result: \"no-op\" and no commit is produced.\nexit codes:\n 0 Success (whether records were rewritten or no-op)\n";
|
|
3
|
+
export declare function normalizeCommand(args: string[], ctx: GitsheetsContext): Promise<string>;
|
|
4
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../src/commands/normalize.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAKtD,eAAO,MAAM,cAAc,8pBAc1B,CAAC;AA2CF,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,MAAM,CAAC,CAkGjB"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { AxiError } from 'axi-sdk-js';
|
|
2
|
+
import { translateError } from '../errors.js';
|
|
3
|
+
import { renderListResponse } from '../output/render.js';
|
|
4
|
+
import { field } from '../output/schema.js';
|
|
5
|
+
export const NORMALIZE_HELP = `usage: gitsheets-axi normalize <sheet> [--prefix p] [--message m]
|
|
6
|
+
flags[2]:
|
|
7
|
+
--prefix <p> Tenant sub-tree scope
|
|
8
|
+
--message <m> Commit message (default: "<sheet> normalize")
|
|
9
|
+
examples:
|
|
10
|
+
gitsheets-axi normalize users
|
|
11
|
+
behavior:
|
|
12
|
+
Reads every record in the sheet, re-runs validation + canonical
|
|
13
|
+
serialization, and writes back any record whose bytes differ.
|
|
14
|
+
Idempotent per-record via Sheet.willChange: records that already
|
|
15
|
+
serialize to identical bytes are skipped. If every record is already
|
|
16
|
+
canonical, exits 0 with result: "no-op" and no commit is produced.
|
|
17
|
+
exit codes:
|
|
18
|
+
0 Success (whether records were rewritten or no-op)
|
|
19
|
+
`;
|
|
20
|
+
function parseNormalizeFlags(args) {
|
|
21
|
+
const flags = { sheet: '', prefix: undefined, message: undefined };
|
|
22
|
+
const positional = [];
|
|
23
|
+
for (let i = 0; i < args.length; i++) {
|
|
24
|
+
const arg = args[i];
|
|
25
|
+
if (arg === undefined)
|
|
26
|
+
continue;
|
|
27
|
+
const next = args[i + 1];
|
|
28
|
+
if (arg === '--prefix') {
|
|
29
|
+
if (!next)
|
|
30
|
+
throw new AxiError('--prefix expects a path', 'VALIDATION_ERROR');
|
|
31
|
+
flags.prefix = next;
|
|
32
|
+
i++;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (arg === '--message') {
|
|
36
|
+
if (!next)
|
|
37
|
+
throw new AxiError('--message expects a string', 'VALIDATION_ERROR');
|
|
38
|
+
flags.message = next;
|
|
39
|
+
i++;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (arg.startsWith('-')) {
|
|
43
|
+
throw new AxiError(`Unknown flag: ${arg}`, 'VALIDATION_ERROR', [
|
|
44
|
+
'Run `gitsheets-axi normalize --help`',
|
|
45
|
+
]);
|
|
46
|
+
}
|
|
47
|
+
positional.push(arg);
|
|
48
|
+
}
|
|
49
|
+
if (positional.length !== 1) {
|
|
50
|
+
throw new AxiError('normalize requires <sheet>', 'VALIDATION_ERROR', [
|
|
51
|
+
'Example: gitsheets-axi normalize users',
|
|
52
|
+
]);
|
|
53
|
+
}
|
|
54
|
+
flags.sheet = positional[0];
|
|
55
|
+
return flags;
|
|
56
|
+
}
|
|
57
|
+
export async function normalizeCommand(args, ctx) {
|
|
58
|
+
if (args.length === 0 || (args.length === 1 && args[0] === '--help')) {
|
|
59
|
+
return NORMALIZE_HELP;
|
|
60
|
+
}
|
|
61
|
+
const flags = parseNormalizeFlags(args);
|
|
62
|
+
const repo = await ctx.repo();
|
|
63
|
+
let sheet;
|
|
64
|
+
try {
|
|
65
|
+
sheet = await repo.openSheet(flags.sheet, flags.prefix !== undefined ? { prefix: flags.prefix } : {});
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
throw translateError(error);
|
|
69
|
+
}
|
|
70
|
+
// Collect all records first so we know what to rewrite + can skip the
|
|
71
|
+
// commit entirely if every record is already canonical.
|
|
72
|
+
const records = [];
|
|
73
|
+
try {
|
|
74
|
+
for await (const r of sheet.query()) {
|
|
75
|
+
records.push(r);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
throw translateError(error);
|
|
80
|
+
}
|
|
81
|
+
if (records.length === 0) {
|
|
82
|
+
return renderListResponse({
|
|
83
|
+
summary: { result: 'no-op', records: '0 — empty sheet' },
|
|
84
|
+
name: 'rewrites',
|
|
85
|
+
items: [],
|
|
86
|
+
schema: [field('path'), field('hash')],
|
|
87
|
+
emptyMessage: 'no records',
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
// Determine which records would actually change.
|
|
91
|
+
const toWrite = [];
|
|
92
|
+
try {
|
|
93
|
+
for (const record of records) {
|
|
94
|
+
const will = await sheet.willChange(record, { allowMissingBody: true });
|
|
95
|
+
if (will.changed) {
|
|
96
|
+
toWrite.push({ record, path: will.path });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
throw translateError(error);
|
|
102
|
+
}
|
|
103
|
+
if (toWrite.length === 0) {
|
|
104
|
+
return renderListResponse({
|
|
105
|
+
summary: {
|
|
106
|
+
result: 'no-op',
|
|
107
|
+
records: `${records.length} already canonical`,
|
|
108
|
+
},
|
|
109
|
+
name: 'rewrites',
|
|
110
|
+
items: [],
|
|
111
|
+
schema: [field('path'), field('hash')],
|
|
112
|
+
emptyMessage: 'every record already canonical',
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
const commitMessage = flags.message ?? `${flags.sheet} normalize (${toWrite.length} records)`;
|
|
116
|
+
const rewrites = [];
|
|
117
|
+
let commitHash = '';
|
|
118
|
+
try {
|
|
119
|
+
const result = await repo.transact({ message: commitMessage }, async (tx) => {
|
|
120
|
+
const txSheet = tx.sheet(flags.sheet, flags.prefix !== undefined ? { prefix: flags.prefix } : {});
|
|
121
|
+
for (const { record } of toWrite) {
|
|
122
|
+
const r = await txSheet.upsert(record, { allowMissingBody: true });
|
|
123
|
+
rewrites.push({ path: r.path, hash: r.blob.hash });
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
commitHash = result.commitHash ?? '';
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
throw translateError(error);
|
|
130
|
+
}
|
|
131
|
+
return renderListResponse({
|
|
132
|
+
summary: {
|
|
133
|
+
result: 'committed',
|
|
134
|
+
records: `${rewrites.length} of ${records.length} rewritten`,
|
|
135
|
+
commit: commitHash,
|
|
136
|
+
},
|
|
137
|
+
name: 'rewrites',
|
|
138
|
+
items: rewrites,
|
|
139
|
+
schema: [field('path'), field('hash')],
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../../src/commands/normalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { GitsheetsContext } from '../context.js';
|
|
2
|
+
export declare const PATCH_HELP = "usage: gitsheets-axi patch <sheet> <query-json> [--patch <json>] [--prefix p] [--message m]\nflags[3]:\n --patch <json> RFC 7396 partial. If omitted, reads stdin.\n --prefix <p> Tenant sub-tree scope\n --message <m> Commit message (default: \"<sheet> patch <path>\")\nexamples:\n gitsheets-axi patch users '{\"slug\":\"jane\"}' --patch '{\"name\":\"Jane O. Doe\"}'\n echo '{\"name\":\"Jane O. Doe\"}' | gitsheets-axi patch users '{\"slug\":\"jane\"}'\nsemantics:\n RFC 7396 JSON Merge Patch. `null` deletes a field, arrays replace\n in full, objects merge recursively. Same as gitsheets's library patch.\nidempotency:\n Reads the existing record, applies the merge, runs the result through\n willChange. If the canonical bytes are unchanged, exits 0 with\n result: \"no-op\" and no commit is produced.\n";
|
|
3
|
+
export declare function patchCommand(args: string[], ctx: GitsheetsContext): Promise<string>;
|
|
4
|
+
//# sourceMappingURL=patch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch.d.ts","sourceRoot":"","sources":["../../../src/commands/patch.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAKtD,eAAO,MAAM,UAAU,u0BAetB,CAAC;AA0DF,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,MAAM,CAAC,CAuHjB"}
|