hafez 1.4.0 → 2.1.0
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 +26 -33
- package/dist/apply.d.ts +5 -2
- package/dist/apply.js +249 -114
- package/dist/batch-ops.d.ts +95 -26
- package/dist/batch-ops.js +178 -18
- package/dist/cli/args.d.ts +43 -5
- package/dist/cli/args.js +69 -8
- package/dist/cli/batch-errors.js +19 -11
- package/dist/cli/block-hook.d.ts +9 -0
- package/dist/cli/block-hook.js +90 -0
- package/dist/cli/commands-schema.js +2 -0
- package/dist/cli/commands.d.ts +4 -3
- package/dist/cli/commands.js +300 -99
- package/dist/cli/format.d.ts +7 -3
- package/dist/cli/format.js +27 -10
- package/dist/cli/index.d.ts +18 -4
- package/dist/cli/index.js +73 -31
- package/dist/cli/install.d.ts +65 -0
- package/dist/cli/install.js +333 -0
- package/dist/cli/onboard.d.ts +15 -2
- package/dist/cli/onboard.js +273 -90
- package/dist/cli/resolve-vault.d.ts +11 -4
- package/dist/cli/resolve-vault.js +13 -11
- package/dist/cli/schema-introspect.js +4 -3
- package/dist/cli/upgrade.d.ts +15 -4
- package/dist/cli/upgrade.js +103 -44
- package/dist/closest.d.ts +8 -0
- package/dist/closest.js +65 -0
- package/dist/contracts.d.ts +17 -1
- package/dist/contracts.js +46 -0
- package/dist/db.d.ts +15 -2
- package/dist/db.js +69 -48
- package/dist/digest.d.ts +6 -4
- package/dist/digest.js +28 -17
- package/dist/document.d.ts +41 -3
- package/dist/document.js +218 -62
- package/dist/export-okf.d.ts +13 -0
- package/dist/export-okf.js +11 -7
- package/dist/harness.d.ts +58 -0
- package/dist/harness.js +50 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +94 -104
- package/dist/merge.js +7 -5
- package/dist/near-match.d.ts +9 -0
- package/dist/near-match.js +34 -0
- package/dist/stale.d.ts +41 -0
- package/dist/stale.js +43 -0
- package/dist/stopwords.d.ts +6 -0
- package/dist/stopwords.js +25 -0
- package/dist/surfaces/items.d.ts +366 -0
- package/dist/surfaces/items.js +527 -0
- package/dist/surfaces/surfaces.d.ts +32 -0
- package/dist/surfaces/surfaces.js +230 -0
- package/dist/types.d.ts +49 -16
- package/dist/validate.d.ts +7 -0
- package/dist/validate.js +109 -0
- package/dist/vault.js +1 -1
- package/package.json +4 -3
- package/skill/hafez/SKILL.md +68 -0
- package/skill/hafez-save/SKILL.md +29 -0
- package/dist/cli/help-agent.d.ts +0 -1
- package/dist/cli/help-agent.js +0 -210
- package/skill/SKILL.md +0 -137
package/dist/cli/args.d.ts
CHANGED
|
@@ -1,12 +1,50 @@
|
|
|
1
|
+
import { HafezError, type HafezErrorCode } from '../types.js';
|
|
1
2
|
/** Bad invocation (unknown flag, missing value, missing positional).
|
|
2
|
-
* Distinct from crashes: the error adapter maps it to exit 2.
|
|
3
|
+
* Distinct from crashes: the error adapter maps it to exit 2. The message is
|
|
4
|
+
* the reason, then the usage text when one is given; `reason` is the problem
|
|
5
|
+
* alone, for a command that follows it with a shape of its own. */
|
|
3
6
|
export declare class UsageError extends Error {
|
|
7
|
+
reason: string;
|
|
8
|
+
constructor(reason: string, usage?: string);
|
|
4
9
|
}
|
|
5
|
-
|
|
10
|
+
/** A flag the command does not declare. */
|
|
11
|
+
export declare class UnknownFlagError extends UsageError {
|
|
12
|
+
flag: string;
|
|
13
|
+
constructor(flag: string, usage: string);
|
|
14
|
+
}
|
|
15
|
+
/** `--help` or `-h` given to a command: the error adapter prints `usage` to
|
|
16
|
+
* stdout and exits 0. Not a UsageError, so no misuse handler wraps it. */
|
|
17
|
+
export declare class HelpRequest extends Error {
|
|
18
|
+
usage: string;
|
|
19
|
+
constructor(usage: string);
|
|
20
|
+
}
|
|
21
|
+
/** For a command that does not go through parseArgs: `--help` or `-h`
|
|
22
|
+
* anywhere in its args is a HelpRequest for its usage. */
|
|
23
|
+
export declare function helpIfAsked(args: string[], usage: string): void;
|
|
24
|
+
/** A failure whose output the command rendered in full (the `read` miss):
|
|
25
|
+
* the error adapter writes `output` verbatim to `stream` and exits by `code`. */
|
|
26
|
+
export declare class RenderedError extends HafezError {
|
|
27
|
+
output: string;
|
|
28
|
+
stream: 'stdout' | 'stderr';
|
|
29
|
+
constructor(code: HafezErrorCode, output: string, stream: 'stdout' | 'stderr');
|
|
30
|
+
}
|
|
31
|
+
/** A misuse whose report ends with the shape to retry from (Agent Contract: a
|
|
32
|
+
* misuse returns the corrected shape). Keeps the wrapped error's code, so its
|
|
33
|
+
* exit code is unchanged. */
|
|
34
|
+
export declare class MisuseError extends HafezError {
|
|
35
|
+
shape: string;
|
|
36
|
+
constructor(cause: HafezError, shape: string);
|
|
37
|
+
}
|
|
38
|
+
/** `repeat` is the one flag that may be given more than once: each repeat
|
|
39
|
+
* appends, and its value is always a list. Every other flag given twice is a
|
|
40
|
+
* UsageError on every command — never last-wins, which would drop the first
|
|
41
|
+
* value with exit 0 (`query --tag a --tag b` used to query `b` alone). */
|
|
42
|
+
export type FlagType = 'string' | 'boolean' | 'repeat';
|
|
43
|
+
export type FlagValue = string | boolean | string[] | undefined;
|
|
6
44
|
/** Flag names WITHOUT the leading dashes, e.g. { 'add-action': 'string' }. */
|
|
7
45
|
export type FlagSpec = Record<string, FlagType>;
|
|
8
46
|
export interface ParsedArgs {
|
|
9
|
-
flags: Record<string,
|
|
47
|
+
flags: Record<string, FlagValue>;
|
|
10
48
|
positionals: string[];
|
|
11
49
|
}
|
|
12
50
|
export declare function parseArgs(args: string[], spec: FlagSpec, usage: string): ParsedArgs;
|
|
@@ -15,5 +53,5 @@ export declare function parseArgs(args: string[], spec: FlagSpec, usage: string)
|
|
|
15
53
|
* domains (not `ai` and ` ml`, which no query matches) and `"eng,"` is one
|
|
16
54
|
* (not one plus an empty string persisted to frontmatter and the index).
|
|
17
55
|
* undefined stays undefined; an all-empty list is an empty array (a clear). */
|
|
18
|
-
export declare function splitList(value:
|
|
19
|
-
export declare function str(value:
|
|
56
|
+
export declare function splitList(value: FlagValue): string[] | undefined;
|
|
57
|
+
export declare function str(value: FlagValue): string | undefined;
|
package/dist/cli/args.js
CHANGED
|
@@ -3,21 +3,81 @@
|
|
|
3
3
|
// flags; parseArgs enforces the declaration — unknown flags and missing
|
|
4
4
|
// values are UsageErrors instead of silently ignored tokens (the getFlag era
|
|
5
5
|
// needed a documented workaround because values stayed in the positional
|
|
6
|
-
// stream).
|
|
6
|
+
// stream). It also holds the error classes the error → exit adapter maps,
|
|
7
|
+
// since the dispatch module may statically import only this file and types.
|
|
8
|
+
import { HafezError } from '../types.js';
|
|
9
|
+
import { splitCommaList } from '../batch-ops.js';
|
|
7
10
|
/** Bad invocation (unknown flag, missing value, missing positional).
|
|
8
|
-
* Distinct from crashes: the error adapter maps it to exit 2.
|
|
11
|
+
* Distinct from crashes: the error adapter maps it to exit 2. The message is
|
|
12
|
+
* the reason, then the usage text when one is given; `reason` is the problem
|
|
13
|
+
* alone, for a command that follows it with a shape of its own. */
|
|
9
14
|
export class UsageError extends Error {
|
|
15
|
+
reason;
|
|
16
|
+
constructor(reason, usage) {
|
|
17
|
+
super(usage === undefined ? reason : `${reason}\n${usage}`);
|
|
18
|
+
this.reason = reason;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** A flag the command does not declare. */
|
|
22
|
+
export class UnknownFlagError extends UsageError {
|
|
23
|
+
flag;
|
|
24
|
+
constructor(flag, usage) {
|
|
25
|
+
super(`Unknown flag --${flag}`, usage);
|
|
26
|
+
this.flag = flag;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** `--help` or `-h` given to a command: the error adapter prints `usage` to
|
|
30
|
+
* stdout and exits 0. Not a UsageError, so no misuse handler wraps it. */
|
|
31
|
+
export class HelpRequest extends Error {
|
|
32
|
+
usage;
|
|
33
|
+
constructor(usage) {
|
|
34
|
+
super(usage);
|
|
35
|
+
this.usage = usage;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** For a command that does not go through parseArgs: `--help` or `-h`
|
|
39
|
+
* anywhere in its args is a HelpRequest for its usage. */
|
|
40
|
+
export function helpIfAsked(args, usage) {
|
|
41
|
+
if (args.includes('--help') || args.includes('-h'))
|
|
42
|
+
throw new HelpRequest(usage);
|
|
43
|
+
}
|
|
44
|
+
/** A failure whose output the command rendered in full (the `read` miss):
|
|
45
|
+
* the error adapter writes `output` verbatim to `stream` and exits by `code`. */
|
|
46
|
+
export class RenderedError extends HafezError {
|
|
47
|
+
output;
|
|
48
|
+
stream;
|
|
49
|
+
constructor(code, output, stream) {
|
|
50
|
+
super(code, output);
|
|
51
|
+
this.output = output;
|
|
52
|
+
this.stream = stream;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** A misuse whose report ends with the shape to retry from (Agent Contract: a
|
|
56
|
+
* misuse returns the corrected shape). Keeps the wrapped error's code, so its
|
|
57
|
+
* exit code is unchanged. */
|
|
58
|
+
export class MisuseError extends HafezError {
|
|
59
|
+
shape;
|
|
60
|
+
constructor(cause, shape) {
|
|
61
|
+
super(cause.code, cause.message, cause.details);
|
|
62
|
+
this.shape = shape;
|
|
63
|
+
}
|
|
10
64
|
}
|
|
11
65
|
export function parseArgs(args, spec, usage) {
|
|
12
66
|
const flags = {};
|
|
13
67
|
const positionals = [];
|
|
14
68
|
for (let i = 0; i < args.length; i++) {
|
|
15
69
|
const token = args[i];
|
|
70
|
+
if (token === '--help' || token === '-h')
|
|
71
|
+
throw new HelpRequest(usage);
|
|
16
72
|
if (token.startsWith('--')) {
|
|
17
73
|
const name = token.slice(2);
|
|
18
|
-
|
|
74
|
+
// Own keys only: `--constructor` must not find Object.prototype's (#134)
|
|
75
|
+
const type = Object.hasOwn(spec, name) ? spec[name] : undefined;
|
|
19
76
|
if (!type)
|
|
20
|
-
throw new
|
|
77
|
+
throw new UnknownFlagError(name, usage);
|
|
78
|
+
if (type !== 'repeat' && Object.hasOwn(flags, name)) {
|
|
79
|
+
throw new UsageError(`--${name} was given more than once; it takes one value`, usage);
|
|
80
|
+
}
|
|
21
81
|
if (type === 'boolean') {
|
|
22
82
|
flags[name] = true;
|
|
23
83
|
continue;
|
|
@@ -26,10 +86,11 @@ export function parseArgs(args, spec, usage) {
|
|
|
26
86
|
// A declared flag in value position means the value was omitted
|
|
27
87
|
// (`--brief --clear-actions`) — consuming it would both corrupt the
|
|
28
88
|
// string and silently drop the swallowed flag.
|
|
29
|
-
if (value === undefined || (value.startsWith('--') && value.slice(2)
|
|
30
|
-
throw new UsageError(`--${name} requires a value
|
|
89
|
+
if (value === undefined || (value.startsWith('--') && Object.hasOwn(spec, value.slice(2)))) {
|
|
90
|
+
throw new UsageError(`--${name} requires a value`, usage);
|
|
31
91
|
}
|
|
32
|
-
flags[name]
|
|
92
|
+
const prev = flags[name];
|
|
93
|
+
flags[name] = type === 'repeat' ? [...(Array.isArray(prev) ? prev : []), value] : value;
|
|
33
94
|
i++;
|
|
34
95
|
}
|
|
35
96
|
else {
|
|
@@ -46,7 +107,7 @@ export function parseArgs(args, spec, usage) {
|
|
|
46
107
|
export function splitList(value) {
|
|
47
108
|
if (typeof value !== 'string')
|
|
48
109
|
return undefined;
|
|
49
|
-
return value
|
|
110
|
+
return splitCommaList(value);
|
|
50
111
|
}
|
|
51
112
|
export function str(value) {
|
|
52
113
|
return typeof value === 'string' ? value : undefined;
|
package/dist/cli/batch-errors.js
CHANGED
|
@@ -105,14 +105,24 @@ function formatPath(path) {
|
|
|
105
105
|
return '(root)';
|
|
106
106
|
return path.map(p => (typeof p === 'number' ? `[${p}]` : typeof p === 'symbol' ? p.toString() : p)).join('.');
|
|
107
107
|
}
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
const GOT_MAX = 60;
|
|
109
|
+
/**
|
|
110
|
+
* What the op sent at `path`, as one JSON line capped at GOT_MAX chars. Zod v4
|
|
111
|
+
* attaches no received value to an issue, so the raw op is walked instead.
|
|
112
|
+
* Null when nothing is at the path (a missing field) — the caller then omits
|
|
113
|
+
* its `got:` line rather than print `undefined`.
|
|
114
|
+
*/
|
|
115
|
+
function gotAt(raw, path) {
|
|
116
|
+
let cur = raw;
|
|
110
117
|
for (const p of path) {
|
|
111
|
-
if (cur
|
|
112
|
-
return
|
|
118
|
+
if (cur === null || typeof cur !== 'object' || !Object.hasOwn(cur, p))
|
|
119
|
+
return null;
|
|
113
120
|
cur = cur[p];
|
|
114
121
|
}
|
|
115
|
-
|
|
122
|
+
const s = JSON.stringify(cur);
|
|
123
|
+
if (s === undefined)
|
|
124
|
+
return null; // raw itself absent — never print `undefined`
|
|
125
|
+
return s.length > GOT_MAX ? `${s.slice(0, GOT_MAX - 1)}…` : s;
|
|
116
126
|
}
|
|
117
127
|
function toStr(v) {
|
|
118
128
|
if (typeof v === 'string')
|
|
@@ -188,27 +198,25 @@ export function formatIssue(issue, opIndex, raw) {
|
|
|
188
198
|
if (code === 'invalid_enum_value' || code === 'invalid_value') {
|
|
189
199
|
// Zod v3 uses `options`, Zod v4 uses `values`.
|
|
190
200
|
const expected = anyIssue.options ?? anyIssue.values;
|
|
191
|
-
|
|
192
|
-
// input by path to find it.
|
|
193
|
-
const received = anyIssue.received ?? anyIssue.input ?? lookupByPath(raw, issue.path);
|
|
201
|
+
const got = gotAt(raw, issue.path);
|
|
194
202
|
return [
|
|
195
203
|
header,
|
|
196
204
|
` field: ${fieldPath}`,
|
|
197
205
|
` issue: invalid value`,
|
|
198
206
|
...(expected ? [` expected: one of [${expected.join(', ')}]`] : []),
|
|
199
|
-
` got: ${
|
|
207
|
+
...(got !== null ? [` got: ${got}`] : []),
|
|
200
208
|
` ${tip}`,
|
|
201
209
|
].join('\n');
|
|
202
210
|
}
|
|
203
211
|
if (code === 'invalid_type') {
|
|
204
212
|
const expected = issue.expected;
|
|
205
|
-
const
|
|
213
|
+
const got = gotAt(raw, issue.path);
|
|
206
214
|
return [
|
|
207
215
|
header,
|
|
208
216
|
` field: ${fieldPath}`,
|
|
209
217
|
` issue: wrong type`,
|
|
210
218
|
` expected: ${expected}`,
|
|
211
|
-
` got: ${
|
|
219
|
+
...(got !== null ? [` got: ${got}`] : []),
|
|
212
220
|
` ${tip}`,
|
|
213
221
|
].join('\n');
|
|
214
222
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ConfigHome } from './resolve-vault.js';
|
|
2
|
+
export interface BlockHookCtx extends ConfigHome {
|
|
3
|
+
/** Defaults to the process's; read inside the catch, since a deleted
|
|
4
|
+
* working directory makes reading it throw. */
|
|
5
|
+
cwd?: string;
|
|
6
|
+
vaultFlag?: string;
|
|
7
|
+
}
|
|
8
|
+
/** The render, or null for any failure: the caller prints nothing. */
|
|
9
|
+
export declare function blockHook(ctx: BlockHookCtx): Promise<string | null>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// src/cli/block-hook.ts
|
|
2
|
+
//
|
|
3
|
+
// `onboard --block`, what the SessionStart hook prints (onboard decision #58):
|
|
4
|
+
// the Block, then the read line for every entity whose `resource` or slug
|
|
5
|
+
// matches the folder. Three folders are tried, each exactly: the working
|
|
6
|
+
// directory, its git root, and in a linked worktree the main repository's
|
|
7
|
+
// root; no directory in between. A `resource` matches a folder's path or the
|
|
8
|
+
// URL of one of its git remotes (case, `.git`, ssh vs https aside); a slug
|
|
9
|
+
// matches a folder's name. The hook never loads: the agent does the read.
|
|
10
|
+
//
|
|
11
|
+
// The hook must never block a session: any failure (no vault, bad config, an
|
|
12
|
+
// unbuilt native binding, no git) prints nothing. So the core and its native
|
|
13
|
+
// binding load here, inside the catch, never at module top. A bad invocation
|
|
14
|
+
// (unknown flag or harness) throws a usage error from `cmdOnboard`, which the
|
|
15
|
+
// CLI's `main` silences for `onboard --block` like any other failure (#132).
|
|
16
|
+
import { execFileSync } from 'child_process';
|
|
17
|
+
import { existsSync, realpathSync } from 'fs';
|
|
18
|
+
import { basename, dirname, isAbsolute, resolve } from 'path';
|
|
19
|
+
import { ENTITY_STATUSES } from '../contracts.js';
|
|
20
|
+
/** The render, or null for any failure: the caller prints nothing. */
|
|
21
|
+
export async function blockHook(ctx) {
|
|
22
|
+
try {
|
|
23
|
+
const { isVault, resolveVaultPath } = await import('./resolve-vault.js');
|
|
24
|
+
const vaultPath = resolveVaultPath(ctx.vaultFlag, ctx);
|
|
25
|
+
// A --vault flag is not checked by resolution; opening a non-vault would
|
|
26
|
+
// leave an index file in it.
|
|
27
|
+
if (typeof vaultPath !== 'string' || !isVault(vaultPath))
|
|
28
|
+
return null;
|
|
29
|
+
const cwd = realpathSync(ctx.cwd ?? process.cwd());
|
|
30
|
+
const folders = foldersOf(cwd);
|
|
31
|
+
const remotes = remoteUrls(cwd);
|
|
32
|
+
const { createHafez } = await import('../index.js');
|
|
33
|
+
const { items } = await createHafez({ vaultPath, git: { push: false } }).query({ filter: 'all' });
|
|
34
|
+
const matches = items
|
|
35
|
+
.filter(e => folders.some(f => basename(f) === e.slug) || (e.resource !== null && resourceMatches(e.resource, folders, remotes)))
|
|
36
|
+
// Active first: the status tuple is ordered active, paused, done.
|
|
37
|
+
.sort((a, b) => ENTITY_STATUSES.indexOf(a.status) - ENTITY_STATUSES.indexOf(b.status));
|
|
38
|
+
const { renderBlockHook } = await import('../surfaces/surfaces.js');
|
|
39
|
+
return renderBlockHook(matches);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** git's output, or null when git fails or is absent. */
|
|
46
|
+
function git(cwd, ...args) {
|
|
47
|
+
try {
|
|
48
|
+
return execFileSync('git', args, { cwd, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'], timeout: 5000 }).trim();
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** The working directory, its git root, and in a linked worktree the main
|
|
55
|
+
* repository's root. */
|
|
56
|
+
function foldersOf(cwd) {
|
|
57
|
+
const folders = [cwd];
|
|
58
|
+
const out = git(cwd, 'rev-parse', '--path-format=absolute', '--show-toplevel', '--git-common-dir');
|
|
59
|
+
const [top, common] = out?.split('\n') ?? [];
|
|
60
|
+
// Before git 2.31 `--path-format` is echoed back, not obeyed: no git root.
|
|
61
|
+
if (top && common && isAbsolute(top) && isAbsolute(common)) {
|
|
62
|
+
folders.push(top);
|
|
63
|
+
// A linked worktree shares the main checkout's `.git` as its common dir.
|
|
64
|
+
if (basename(common) === '.git' && dirname(common) !== top)
|
|
65
|
+
folders.push(dirname(common));
|
|
66
|
+
}
|
|
67
|
+
return [...new Set(folders)];
|
|
68
|
+
}
|
|
69
|
+
/** Every remote's URL, normalised. */
|
|
70
|
+
function remoteUrls(cwd) {
|
|
71
|
+
const out = git(cwd, 'config', '--get-regexp', '^remote\\..*\\.url$');
|
|
72
|
+
return out ? out.split('\n').map(line => normaliseUrl(line.slice(line.indexOf(' ') + 1))) : [];
|
|
73
|
+
}
|
|
74
|
+
/** `git@github.com:Org/Repo.git`, `ssh://git@github.com/org/repo` and
|
|
75
|
+
* `https://github.com/org/repo/` are all `github.com/org/repo`. */
|
|
76
|
+
function normaliseUrl(url) {
|
|
77
|
+
return url.trim().toLowerCase()
|
|
78
|
+
.replace(/^[a-z+]+:\/\//, '')
|
|
79
|
+
.replace(/^[^@/]+@/, '')
|
|
80
|
+
.replace(/^([^/:]+):(?!\d)/, '$1/')
|
|
81
|
+
.replace(/\/+$/, '')
|
|
82
|
+
.replace(/\.git$/, '');
|
|
83
|
+
}
|
|
84
|
+
function resourceMatches(resource, folders, remotes) {
|
|
85
|
+
if (isAbsolute(resource)) {
|
|
86
|
+
const path = resolve(resource);
|
|
87
|
+
return folders.includes(existsSync(path) ? realpathSync(path) : path);
|
|
88
|
+
}
|
|
89
|
+
return remotes.includes(normaliseUrl(resource));
|
|
90
|
+
}
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
import { HafezError } from '../types.js';
|
|
12
12
|
import { listOps, zodToJsonSchema, getOpExample, getEnumValues, getOpSchema, DIGEST_DESCRIPTION } from './schema-introspect.js';
|
|
13
13
|
import { didYouMean } from './batch-errors.js';
|
|
14
|
+
import { helpIfAsked } from './args.js';
|
|
14
15
|
export async function cmdSchema(_os, args) {
|
|
16
|
+
helpIfAsked(args, 'Usage: hafez schema [op] [--examples]');
|
|
15
17
|
// args come in already-stripped of global flags; first positional is the op name (if any)
|
|
16
18
|
const target = args[0];
|
|
17
19
|
const wantExamples = args.includes('--examples');
|
package/dist/cli/commands.d.ts
CHANGED
|
@@ -34,10 +34,11 @@ export declare function cmdLink(os: Hafez, args: string[], opts?: CommandOpts):
|
|
|
34
34
|
export declare function cmdUnlink(os: Hafez, args: string[], opts?: CommandOpts): Promise<string>;
|
|
35
35
|
export declare function cmdCapture(os: Hafez, args: string[], opts?: CommandOpts): Promise<string>;
|
|
36
36
|
export declare function cmdPromote(os: Hafez, args: string[], opts?: CommandOpts): Promise<string>;
|
|
37
|
-
export declare function
|
|
37
|
+
export declare function cmdDelete(os: Hafez, args: string[], opts?: CommandOpts): Promise<string>;
|
|
38
|
+
export declare function cmdValidate(os: Hafez, args: string[], opts?: CommandOpts): Promise<string>;
|
|
38
39
|
export declare function cmdIndexRebuild(os: Hafez): Promise<string>;
|
|
39
|
-
export declare function cmdSync(os: Hafez,
|
|
40
|
-
export declare function cmdStats(os: Hafez,
|
|
40
|
+
export declare function cmdSync(os: Hafez, args: string[]): Promise<string>;
|
|
41
|
+
export declare function cmdStats(os: Hafez, args: string[], opts?: CommandOpts): Promise<string>;
|
|
41
42
|
export declare function cmdChangelog(os: Hafez, args: string[], opts?: CommandOpts): Promise<string>;
|
|
42
43
|
export declare function parseBatchInput(json: string): BatchOperation[];
|
|
43
44
|
export declare function cmdBatch(os: Hafez, args: string[], opts?: CommandOpts): Promise<string>;
|