@hydranium/cli 1.0.0-next.277 → 1.0.0-next.278
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 +5 -5
- package/lib/cli.js +3 -1
- package/lib/cli.js.map +1 -1
- package/lib/commands/client-session.d.ts +17 -0
- package/lib/commands/client-session.d.ts.map +1 -0
- package/lib/commands/client-session.js +27 -0
- package/lib/commands/client-session.js.map +1 -0
- package/lib/commands/create-args.d.ts +17 -0
- package/lib/commands/create-args.d.ts.map +1 -0
- package/lib/commands/create-args.js +53 -0
- package/lib/commands/create-args.js.map +1 -0
- package/lib/commands/create.d.ts +38 -0
- package/lib/commands/create.d.ts.map +1 -0
- package/lib/commands/create.js +47 -0
- package/lib/commands/create.js.map +1 -0
- package/lib/commands/delete.d.ts.map +1 -1
- package/lib/commands/delete.js +5 -14
- package/lib/commands/delete.js.map +1 -1
- package/lib/commands/harness-args.d.ts +7 -0
- package/lib/commands/harness-args.d.ts.map +1 -1
- package/lib/commands/harness-args.js +18 -0
- package/lib/commands/harness-args.js.map +1 -1
- package/lib/commands/init-templates.d.ts.map +1 -1
- package/lib/commands/init-templates.js +11 -12
- package/lib/commands/init-templates.js.map +1 -1
- package/lib/commands/save-args.d.ts.map +1 -1
- package/lib/commands/save-args.js +1 -0
- package/lib/commands/save-args.js.map +1 -1
- package/lib/commands/save.d.ts +4 -4
- package/lib/commands/save.d.ts.map +1 -1
- package/lib/commands/save.js +8 -44
- package/lib/commands/save.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/spawn-data-server.d.ts +3 -3
- package/lib/spawn-data-server.js +3 -3
- package/package.json +10 -10
- package/src/cli.ts +3 -1
- package/src/commands/client-session.ts +33 -0
- package/src/commands/create-args.ts +68 -0
- package/src/commands/create.ts +86 -0
- package/src/commands/delete.ts +5 -13
- package/src/commands/harness-args.ts +19 -0
- package/src/commands/init-templates.ts +11 -12
- package/src/commands/save-args.ts +1 -0
- package/src/commands/save.ts +13 -53
- package/src/index.ts +1 -0
- package/src/spawn-data-server.ts +3 -3
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
|
|
34
34
|
import { describeError, type LogThreshold } from '@hydranium/protocol';
|
|
35
35
|
import { statSync } from 'node:fs';
|
|
36
|
+
import * as fs from 'node:fs/promises';
|
|
36
37
|
import * as path from 'node:path';
|
|
37
38
|
import { fileURLToPath } from 'node:url';
|
|
38
39
|
import { type LogOptions, parseLogLevelOption } from '../log-level.js';
|
|
@@ -472,3 +473,21 @@ export function parseServerSpawnOptions(args: string[], commandName: string, onE
|
|
|
472
473
|
}
|
|
473
474
|
return { serverCommand, serverArgs, cwd, ...logOptions(logFlags), extra };
|
|
474
475
|
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Resolve the `--content` argument to its textual form. The `@<path>`
|
|
479
|
+
* prefix reads from a file (parses as UTF-8); anything else is taken
|
|
480
|
+
* literally. The leading `@` can be escaped as `\@` for content that
|
|
481
|
+
* legitimately starts with `@`.
|
|
482
|
+
*/
|
|
483
|
+
export async function resolveContent(content: string, readFile?: (path: string) => Promise<string>): Promise<string> {
|
|
484
|
+
if (content.startsWith('@')) {
|
|
485
|
+
const file = content.slice(1);
|
|
486
|
+
const reader = readFile ?? ((target: string) => fs.readFile(target, 'utf8'));
|
|
487
|
+
return reader(file);
|
|
488
|
+
}
|
|
489
|
+
if (content.startsWith('\\@')) {
|
|
490
|
+
return content.slice(1);
|
|
491
|
+
}
|
|
492
|
+
return content;
|
|
493
|
+
}
|
|
@@ -1130,9 +1130,9 @@ void glspServer;
|
|
|
1130
1130
|
data
|
|
1131
1131
|
? `
|
|
1132
1132
|
//
|
|
1133
|
-
// NOT the entry
|
|
1134
|
-
//
|
|
1135
|
-
//
|
|
1133
|
+
// NOT the entry the data-server subcommands of \`hydranium-cli\` speak to: stdio
|
|
1134
|
+
// here carries LSP, and the data head is a socket whose port is published over
|
|
1135
|
+
// the LSP connection. Those subcommands spawn \`data-server-main.js\`.`
|
|
1136
1136
|
: ''
|
|
1137
1137
|
}
|
|
1138
1138
|
//
|
|
@@ -1163,11 +1163,11 @@ ${dataBlock}${glspBlock}`;
|
|
|
1163
1163
|
* Emitted with the `data` head because it is the ONLY command line that reaches
|
|
1164
1164
|
* that head from outside the editor. `main.ts` gives stdio to LSP and publishes
|
|
1165
1165
|
* the data head's socket port over the LSP connection, so a client that is not
|
|
1166
|
-
* an LSP client cannot discover it — which is every
|
|
1167
|
-
* `
|
|
1168
|
-
*
|
|
1169
|
-
*
|
|
1170
|
-
*
|
|
1166
|
+
* an LSP client cannot discover it — which is every data-server subcommand of
|
|
1167
|
+
* `hydranium-cli`, since each drives the data protocol over a spawned child's
|
|
1168
|
+
* stdin/stdout. Without this file a scaffolded project has no `--server` value,
|
|
1169
|
+
* and the closest guess — the LSP entry — fails as an unrecognised method
|
|
1170
|
+
* rather than as a missing head.
|
|
1171
1171
|
*
|
|
1172
1172
|
* A separate process rather than a flag on `main.ts`: only one protocol can own
|
|
1173
1173
|
* stdio, so the two entries are mutually exclusive by construction.
|
|
@@ -1178,10 +1178,9 @@ function dataServerMainFile(composition: InitComposition): string {
|
|
|
1178
1178
|
const plural = roots.length > 1 ? 's' : '';
|
|
1179
1179
|
|
|
1180
1180
|
const text = `${SHEBANG}// Standalone entry point: a data-server head on **stdio**, with no LSP head in
|
|
1181
|
-
// the process. This is the transport \`hydranium-cli\` speaks —
|
|
1182
|
-
//
|
|
1183
|
-
//
|
|
1184
|
-
// language.
|
|
1181
|
+
// the process. This is the transport \`hydranium-cli\` speaks — its data-server
|
|
1182
|
+
// subcommands spawn a server command and drive JSON-RPC over its stdin/stdout —
|
|
1183
|
+
// so it is what makes those subcommands usable against this language.
|
|
1185
1184
|
//
|
|
1186
1185
|
// Invocation: \`node lib/data-server-main.js [<workspace-path>]\`, or the
|
|
1187
1186
|
// package's \`__PROJECT_ID__-data-server\` bin script. The workspace path defaults to
|
|
@@ -40,6 +40,7 @@ export const SAVE_HELP: readonly string[] = [
|
|
|
40
40
|
'Usage: hydranium-cli save --server "<cmd>..." --uri <uri> --content <text|@file> [--client-id <id>] [--cwd <dir>] [--log-level <lvl>] [--log-file <file>] [--log-file-level <lvl>]',
|
|
41
41
|
'',
|
|
42
42
|
'Update the document at `<uri>` with `<content>` and persist via saveModelDocument.',
|
|
43
|
+
'Fails when the file does not exist; `create` writes a new one.',
|
|
43
44
|
'Output is the post-save envelope as a single JSON line.',
|
|
44
45
|
'',
|
|
45
46
|
'Options:',
|
package/src/commands/save.ts
CHANGED
|
@@ -7,11 +7,12 @@
|
|
|
7
7
|
* SPDX-License-Identifier: MIT
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import type { TransferElement } from '@hydranium/protocol';
|
|
11
11
|
import type { DataServerProtocol } from '@hydranium/protocol/data';
|
|
12
|
-
import * as fs from 'node:fs/promises';
|
|
13
12
|
import { logEnv, type LogOptions } from '../log-level.js';
|
|
14
13
|
import { withDataServer } from '../spawn-data-server.js';
|
|
14
|
+
import { withClientSession } from './client-session.js';
|
|
15
|
+
import { resolveContent } from './harness-args.js';
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Options for the {@link runSave} subcommand. Updates the document at
|
|
@@ -25,9 +26,9 @@ import { withDataServer } from '../spawn-data-server.js';
|
|
|
25
26
|
* identity (per-user, per-script) override.
|
|
26
27
|
*
|
|
27
28
|
* The command saves as a client session under `clientId`: it registers the
|
|
28
|
-
* session,
|
|
29
|
-
*
|
|
30
|
-
*
|
|
29
|
+
* session, opens the document, saves, and ends the session, which leaves
|
|
30
|
+
* nothing open behind it. A missing file fails the open; `runCreate` writes a
|
|
31
|
+
* new one.
|
|
31
32
|
*/
|
|
32
33
|
export interface SaveCommandOptions extends LogOptions {
|
|
33
34
|
readonly serverCommand: string;
|
|
@@ -66,56 +67,15 @@ export async function runSave(options: SaveCommandOptions): Promise<void> {
|
|
|
66
67
|
);
|
|
67
68
|
}
|
|
68
69
|
|
|
69
|
-
/**
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
* swallowed: the save's error is the one the user needs.
|
|
73
|
-
*/
|
|
74
|
-
async function saveOpened(
|
|
75
|
-
server: Pick<
|
|
76
|
-
DataServerProtocol<TransferElement>,
|
|
77
|
-
'createSession' | 'openModelDocument' | 'createModelDocument' | 'saveModelDocument' | 'closeSession'
|
|
78
|
-
>,
|
|
70
|
+
/** Open `uri` as the session `clientId` and save `model` to it, then end the session. */
|
|
71
|
+
function saveOpened(
|
|
72
|
+
server: Pick<DataServerProtocol<TransferElement>, 'createSession' | 'openModelDocument' | 'saveModelDocument' | 'closeSession'>,
|
|
79
73
|
uri: string,
|
|
80
74
|
clientId: string,
|
|
81
75
|
model: string
|
|
82
76
|
): Promise<unknown> {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
// client has it open; anything else is opened. An open that fails
|
|
88
|
-
// reports why the create failed too, since that may be the real cause.
|
|
89
|
-
await server.createModelDocument({ uri, clientId, text: model }).catch((created: unknown) =>
|
|
90
|
-
server.openModelDocument({ uri, clientId }).catch((opened: unknown) => {
|
|
91
|
-
throw new Error(`Cannot save ${uri}: ${describeError(opened)} (creating it failed first: ${describeError(created)})`, {
|
|
92
|
-
cause: created
|
|
93
|
-
});
|
|
94
|
-
})
|
|
95
|
-
);
|
|
96
|
-
saved = await server.saveModelDocument({ uri, clientId, model, baseVersion: 'any' });
|
|
97
|
-
} catch (error: unknown) {
|
|
98
|
-
await server.closeSession({ clientId }).catch(() => undefined);
|
|
99
|
-
throw error;
|
|
100
|
-
}
|
|
101
|
-
await server.closeSession({ clientId });
|
|
102
|
-
return saved;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Resolve the `--content` argument to its textual form. The `@<path>`
|
|
107
|
-
* prefix reads from a file (parses as UTF-8); anything else is taken
|
|
108
|
-
* literally. The leading `@` can be escaped as `\@` for content that
|
|
109
|
-
* legitimately starts with `@`.
|
|
110
|
-
*/
|
|
111
|
-
async function resolveContent(content: string, readFile?: (path: string) => Promise<string>): Promise<string> {
|
|
112
|
-
if (content.startsWith('@')) {
|
|
113
|
-
const path = content.slice(1);
|
|
114
|
-
const reader = readFile ?? ((target: string) => fs.readFile(target, 'utf8'));
|
|
115
|
-
return reader(path);
|
|
116
|
-
}
|
|
117
|
-
if (content.startsWith('\\@')) {
|
|
118
|
-
return content.slice(1);
|
|
119
|
-
}
|
|
120
|
-
return content;
|
|
77
|
+
return withClientSession(server, clientId, async () => {
|
|
78
|
+
await server.openModelDocument({ uri, clientId });
|
|
79
|
+
return server.saveModelDocument({ uri, clientId, model, baseVersion: 'any' });
|
|
80
|
+
});
|
|
121
81
|
}
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* SPDX-License-Identifier: MIT
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
|
+
export * from './commands/create.js';
|
|
10
11
|
export * from './commands/delete.js';
|
|
11
12
|
export * from './commands/generate-ast-builder.js';
|
|
12
13
|
export * from './commands/generate-transfer-model.js';
|
package/src/spawn-data-server.ts
CHANGED
|
@@ -236,9 +236,9 @@ export function spawnDataServer<TTransfer extends TransferElement, TDiagnostic e
|
|
|
236
236
|
* child down afterwards. The `use` call is raced against
|
|
237
237
|
* {@link DataServerHandle.whenTerminated}, so a spawn failure or a premature child
|
|
238
238
|
* exit rejects with a clear message instead of hanging on an RPC that can never be
|
|
239
|
-
* answered. This is the one-shot counterpart the
|
|
240
|
-
*
|
|
241
|
-
*
|
|
239
|
+
* answered. This is the one-shot counterpart the data-server subcommands
|
|
240
|
+
* compose; `watch` races its own long-running loop against `whenTerminated`
|
|
241
|
+
* directly.
|
|
242
242
|
*/
|
|
243
243
|
export async function withDataServer<TTransfer extends TransferElement, TDiagnostic extends TransferDiagnostic, R>(
|
|
244
244
|
options: SpawnDataServerOptions,
|