@durable-streams/cli 0.1.3 → 0.1.4

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 CHANGED
@@ -70,6 +70,11 @@ durable-stream-dev read my-stream
70
70
 
71
71
  - `STREAM_URL` - Base URL of the stream server (default: `http://localhost:4437`)
72
72
 
73
+ ### Write Options
74
+
75
+ - `--content-type <type>` - Content-Type for the message (default: `application/octet-stream`)
76
+ - `--json` - Shorthand for `--content-type application/json`
77
+
73
78
  ### Commands
74
79
 
75
80
  #### Create a stream
@@ -87,6 +92,12 @@ durable-stream-dev write <stream_id> "Hello, world!"
87
92
  # Pipe content from stdin
88
93
  echo "Hello from stdin" | durable-stream-dev write <stream_id>
89
94
  cat file.txt | durable-stream-dev write <stream_id>
95
+
96
+ # Specify content type
97
+ durable-stream-dev write <stream_id> '{"key": "value"}' --content-type application/json
98
+
99
+ # Shorthand for JSON
100
+ durable-stream-dev write <stream_id> '{"key": "value"}' --json
90
101
  ```
91
102
 
92
103
  #### Read from a stream
package/dist/index.cjs CHANGED
@@ -23,9 +23,39 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  }) : target, mod));
24
24
 
25
25
  //#endregion
26
+ const node_path = __toESM(require("node:path"));
26
27
  const node_process = __toESM(require("node:process"));
28
+ const node_url = __toESM(require("node:url"));
27
29
  const __durable_streams_client = __toESM(require("@durable-streams/client"));
28
30
 
31
+ //#region src/parseWriteArgs.ts
32
+ /**
33
+ * Parse write command arguments, extracting content-type flags and content.
34
+ * @param args - Arguments after the stream_id (starting from index 2)
35
+ * @returns Parsed content type and content string
36
+ * @throws Error if --content-type is missing its value or if unknown flags are provided
37
+ */
38
+ function parseWriteArgs(args) {
39
+ let contentType = `application/octet-stream`;
40
+ const contentParts = [];
41
+ for (let i = 0; i < args.length; i++) {
42
+ const arg = args[i];
43
+ if (arg === `--json`) contentType = `application/json`;
44
+ else if (arg === `--content-type`) {
45
+ const nextArg = args[i + 1];
46
+ if (!nextArg || nextArg.startsWith(`--`)) throw new Error(`--content-type requires a value`);
47
+ contentType = nextArg;
48
+ i++;
49
+ } else if (arg.startsWith(`--`)) throw new Error(`unknown flag: ${arg}`);
50
+ else contentParts.push(arg);
51
+ }
52
+ return {
53
+ contentType,
54
+ content: contentParts.join(` `)
55
+ };
56
+ }
57
+
58
+ //#endregion
29
59
  //#region src/index.ts
30
60
  const STREAM_URL = process.env.STREAM_URL || `http://localhost:4437`;
31
61
  function printUsage() {
@@ -37,6 +67,10 @@ Usage:
37
67
  durable-stream read <stream_id> Follow a stream and write to stdout
38
68
  durable-stream delete <stream_id> Delete a stream
39
69
 
70
+ Write Options:
71
+ --content-type <type> Content-Type for the message (default: application/octet-stream)
72
+ --json Shorthand for --content-type application/json
73
+
40
74
  Environment Variables:
41
75
  STREAM_URL Base URL of the stream server (default: http://localhost:4437)
42
76
  `);
@@ -54,10 +88,13 @@ async function createStream(streamId) {
54
88
  process.exit(1);
55
89
  }
56
90
  }
57
- async function writeStream(streamId, content) {
91
+ async function writeStream(streamId, contentType, content) {
58
92
  const url = `${STREAM_URL}/v1/stream/${streamId}`;
59
93
  try {
60
- const stream = new __durable_streams_client.DurableStream({ url });
94
+ const stream = new __durable_streams_client.DurableStream({
95
+ url,
96
+ contentType
97
+ });
61
98
  if (content) {
62
99
  const processedContent = content.replace(/\\n/g, `\n`).replace(/\\t/g, `\t`).replace(/\\r/g, `\r`).replace(/\\\\/g, `\\`);
63
100
  await stream.append(processedContent);
@@ -126,9 +163,15 @@ async function main() {
126
163
  process.exit(1);
127
164
  }
128
165
  const streamId = args[1];
129
- const content = args.slice(2).join(` `);
130
- if (!node_process.stdin.isTTY) await writeStream(streamId);
131
- else if (content) await writeStream(streamId, content);
166
+ let parsed;
167
+ try {
168
+ parsed = parseWriteArgs(args.slice(2));
169
+ } catch (error) {
170
+ if (error instanceof Error) node_process.stderr.write(`Error: ${error.message}\n`);
171
+ process.exit(1);
172
+ }
173
+ if (!node_process.stdin.isTTY) await writeStream(streamId, parsed.contentType);
174
+ else if (parsed.content) await writeStream(streamId, parsed.contentType, parsed.content);
132
175
  else {
133
176
  node_process.stderr.write(`Error: content required (provide as argument or pipe to stdin)\n`);
134
177
  printUsage();
@@ -160,9 +203,16 @@ async function main() {
160
203
  process.exit(1);
161
204
  }
162
205
  }
163
- main().catch((error) => {
206
+ function isMainModule() {
207
+ if (!process.argv[1]) return false;
208
+ const scriptPath = (0, node_path.resolve)(process.argv[1]);
209
+ const modulePath = (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
210
+ return scriptPath === modulePath;
211
+ }
212
+ if (isMainModule()) main().catch((error) => {
164
213
  node_process.stderr.write(`Fatal error: ${error.message}\n`);
165
214
  process.exit(1);
166
215
  });
167
216
 
168
- //#endregion
217
+ //#endregion
218
+ exports.parseWriteArgs = parseWriteArgs
package/dist/index.d.cts CHANGED
@@ -1 +1,15 @@
1
- export { };
1
+ //#region src/parseWriteArgs.d.ts
2
+ interface ParsedWriteArgs {
3
+ contentType: string;
4
+ content: string;
5
+ }
6
+ /**
7
+ * Parse write command arguments, extracting content-type flags and content.
8
+ * @param args - Arguments after the stream_id (starting from index 2)
9
+ * @returns Parsed content type and content string
10
+ * @throws Error if --content-type is missing its value or if unknown flags are provided
11
+ */
12
+ declare function parseWriteArgs(args: Array<string>): ParsedWriteArgs;
13
+
14
+ //#endregion
15
+ export { ParsedWriteArgs, parseWriteArgs };
package/dist/index.d.ts CHANGED
@@ -1 +1,15 @@
1
- export { };
1
+ //#region src/parseWriteArgs.d.ts
2
+ interface ParsedWriteArgs {
3
+ contentType: string;
4
+ content: string;
5
+ }
6
+ /**
7
+ * Parse write command arguments, extracting content-type flags and content.
8
+ * @param args - Arguments after the stream_id (starting from index 2)
9
+ * @returns Parsed content type and content string
10
+ * @throws Error if --content-type is missing its value or if unknown flags are provided
11
+ */
12
+ declare function parseWriteArgs(args: Array<string>): ParsedWriteArgs;
13
+
14
+ //#endregion
15
+ export { ParsedWriteArgs, parseWriteArgs };
package/dist/index.js CHANGED
@@ -1,7 +1,37 @@
1
1
  #!/usr/bin/env node
2
+ import { resolve } from "node:path";
2
3
  import { stderr, stdin, stdout } from "node:process";
4
+ import { fileURLToPath } from "node:url";
3
5
  import { DurableStream } from "@durable-streams/client";
4
6
 
7
+ //#region src/parseWriteArgs.ts
8
+ /**
9
+ * Parse write command arguments, extracting content-type flags and content.
10
+ * @param args - Arguments after the stream_id (starting from index 2)
11
+ * @returns Parsed content type and content string
12
+ * @throws Error if --content-type is missing its value or if unknown flags are provided
13
+ */
14
+ function parseWriteArgs(args) {
15
+ let contentType = `application/octet-stream`;
16
+ const contentParts = [];
17
+ for (let i = 0; i < args.length; i++) {
18
+ const arg = args[i];
19
+ if (arg === `--json`) contentType = `application/json`;
20
+ else if (arg === `--content-type`) {
21
+ const nextArg = args[i + 1];
22
+ if (!nextArg || nextArg.startsWith(`--`)) throw new Error(`--content-type requires a value`);
23
+ contentType = nextArg;
24
+ i++;
25
+ } else if (arg.startsWith(`--`)) throw new Error(`unknown flag: ${arg}`);
26
+ else contentParts.push(arg);
27
+ }
28
+ return {
29
+ contentType,
30
+ content: contentParts.join(` `)
31
+ };
32
+ }
33
+
34
+ //#endregion
5
35
  //#region src/index.ts
6
36
  const STREAM_URL = process.env.STREAM_URL || `http://localhost:4437`;
7
37
  function printUsage() {
@@ -13,6 +43,10 @@ Usage:
13
43
  durable-stream read <stream_id> Follow a stream and write to stdout
14
44
  durable-stream delete <stream_id> Delete a stream
15
45
 
46
+ Write Options:
47
+ --content-type <type> Content-Type for the message (default: application/octet-stream)
48
+ --json Shorthand for --content-type application/json
49
+
16
50
  Environment Variables:
17
51
  STREAM_URL Base URL of the stream server (default: http://localhost:4437)
18
52
  `);
@@ -30,10 +64,13 @@ async function createStream(streamId) {
30
64
  process.exit(1);
31
65
  }
32
66
  }
33
- async function writeStream(streamId, content) {
67
+ async function writeStream(streamId, contentType, content) {
34
68
  const url = `${STREAM_URL}/v1/stream/${streamId}`;
35
69
  try {
36
- const stream = new DurableStream({ url });
70
+ const stream = new DurableStream({
71
+ url,
72
+ contentType
73
+ });
37
74
  if (content) {
38
75
  const processedContent = content.replace(/\\n/g, `\n`).replace(/\\t/g, `\t`).replace(/\\r/g, `\r`).replace(/\\\\/g, `\\`);
39
76
  await stream.append(processedContent);
@@ -43,8 +80,8 @@ async function writeStream(streamId, content) {
43
80
  stdin.on(`data`, (chunk) => {
44
81
  chunks.push(chunk);
45
82
  });
46
- await new Promise((resolve, reject) => {
47
- stdin.on(`end`, resolve);
83
+ await new Promise((resolve$1, reject) => {
84
+ stdin.on(`end`, resolve$1);
48
85
  stdin.on(`error`, reject);
49
86
  });
50
87
  const data = Buffer.concat(chunks);
@@ -102,9 +139,15 @@ async function main() {
102
139
  process.exit(1);
103
140
  }
104
141
  const streamId = args[1];
105
- const content = args.slice(2).join(` `);
106
- if (!stdin.isTTY) await writeStream(streamId);
107
- else if (content) await writeStream(streamId, content);
142
+ let parsed;
143
+ try {
144
+ parsed = parseWriteArgs(args.slice(2));
145
+ } catch (error) {
146
+ if (error instanceof Error) stderr.write(`Error: ${error.message}\n`);
147
+ process.exit(1);
148
+ }
149
+ if (!stdin.isTTY) await writeStream(streamId, parsed.contentType);
150
+ else if (parsed.content) await writeStream(streamId, parsed.contentType, parsed.content);
108
151
  else {
109
152
  stderr.write(`Error: content required (provide as argument or pipe to stdin)\n`);
110
153
  printUsage();
@@ -136,9 +179,16 @@ async function main() {
136
179
  process.exit(1);
137
180
  }
138
181
  }
139
- main().catch((error) => {
182
+ function isMainModule() {
183
+ if (!process.argv[1]) return false;
184
+ const scriptPath = resolve(process.argv[1]);
185
+ const modulePath = fileURLToPath(import.meta.url);
186
+ return scriptPath === modulePath;
187
+ }
188
+ if (isMainModule()) main().catch((error) => {
140
189
  stderr.write(`Fatal error: ${error.message}\n`);
141
190
  process.exit(1);
142
191
  });
143
192
 
144
- //#endregion
193
+ //#endregion
194
+ export { parseWriteArgs };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@durable-streams/cli",
3
3
  "description": "CLI tool for working with Durable Streams",
4
- "version": "0.1.3",
4
+ "version": "0.1.4",
5
5
  "author": "Durable Stream contributors",
6
6
  "bin": {
7
7
  "cli": "./dist/index.js",
@@ -12,14 +12,15 @@
12
12
  "url": "https://github.com/durable-streams/durable-streams/issues"
13
13
  },
14
14
  "dependencies": {
15
- "@durable-streams/client": "0.1.2"
15
+ "@durable-streams/client": "0.1.3"
16
16
  },
17
17
  "devDependencies": {
18
18
  "@types/node": "^22.15.21",
19
19
  "tsdown": "^0.9.0",
20
20
  "tsx": "^4.19.2",
21
21
  "typescript": "^5.5.2",
22
- "@durable-streams/server": "0.1.3"
22
+ "vitest": "^3.1.3",
23
+ "@durable-streams/server": "0.1.4"
23
24
  },
24
25
  "engines": {
25
26
  "node": ">=18.0.0"
@@ -62,6 +63,7 @@
62
63
  "build": "tsdown",
63
64
  "dev": "tsdown --watch",
64
65
  "link:dev": "pnpm link --global",
65
- "start:dev": "tsx --watch example-server.ts"
66
+ "start:dev": "tsx --watch example-server.ts",
67
+ "test": "vitest run"
66
68
  }
67
69
  }