diff --git a/deno.json b/deno.json index 8140dd1f1..f8495b6cb 100644 --- a/deno.json +++ b/deno.json @@ -49,9 +49,10 @@ "@opentelemetry/core": "npm:@opentelemetry/core@^2.5.0", "@opentelemetry/sdk-trace-base": "npm:@opentelemetry/sdk-trace-base@^2.5.0", "@opentelemetry/semantic-conventions": "npm:@opentelemetry/semantic-conventions@^1.39.0", - "@optique/config": "jsr:@optique/config@^1.0.0", - "@optique/core": "jsr:@optique/core@^1.0.0", - "@optique/run": "jsr:@optique/run@^1.0.0", + "@optique/config": "jsr:@optique/config@^1.0.2", + "@optique/core": "jsr:@optique/core@^1.0.2", + "@optique/run": "jsr:@optique/run@^1.0.2", + "@standard-schema/spec": "jsr:@standard-schema/spec@^1.1.0", "@std/assert": "jsr:@std/assert@^1.0.13", "@std/async": "jsr:@std/async@^1.0.13", "@std/encoding": "jsr:@std/encoding@^1.0.10", diff --git a/deno.lock b/deno.lock index a7201c1ee..0a79f5092 100644 --- a/deno.lock +++ b/deno.lock @@ -20,9 +20,10 @@ "jsr:@logtape/file@^2.0.5": "2.0.5", "jsr:@logtape/logtape@^1.0.4": "1.3.7", "jsr:@logtape/logtape@^2.0.5": "2.0.5", - "jsr:@optique/config@1": "1.0.0", - "jsr:@optique/core@1": "1.0.0", - "jsr:@optique/run@1": "1.0.0", + "jsr:@optique/config@^1.0.2": "1.0.2", + "jsr:@optique/core@^1.0.2": "1.0.2", + "jsr:@optique/run@^1.0.2": "1.0.2", + "jsr:@standard-schema/spec@^1.1.0": "1.1.0", "jsr:@std/assert@0.224": "0.224.0", "jsr:@std/assert@0.226": "0.226.0", "jsr:@std/assert@^1.0.13": "1.0.19", @@ -303,22 +304,25 @@ "@logtape/logtape@2.0.5": { "integrity": "604d2121ed4ffb7aad35b47e729e2298d0cd7a7ddf1cb4171d27a61fa7d840a5" }, - "@optique/config@1.0.0": { - "integrity": "8230c7f216b14ffd807df596bceee4d5ac756cf4dd0e493e175b2016f1c08043", + "@optique/config@1.0.2": { + "integrity": "9ba458a3cb2f00f83d36a70f942782cd2c622fd72c527f59e5f8234c780c4b30", "dependencies": [ "jsr:@optique/core", - "npm:@standard-schema/spec" + "npm:@standard-schema/spec@^1.1.0" ] }, - "@optique/core@1.0.0": { - "integrity": "841e61ea4606cf1fbacac2e0fe16961decf8c0e1bcd86f9fcfb5e43c396a3b36" + "@optique/core@1.0.2": { + "integrity": "3f90a2965286cd4d4d103f6605ed9a00951393dbab0748402576350ad3780b33" }, - "@optique/run@1.0.0": { - "integrity": "b5ba928cce667530f44265bebb71064a7974435c73f7608bdee90c310c415db3", + "@optique/run@1.0.2": { + "integrity": "353c3cfafb69f2099ff2f29e1145696ef6ecd355d44d9626ab4726020c9d72f5", "dependencies": [ "jsr:@optique/core" ] }, + "@standard-schema/spec@1.1.0": { + "integrity": "2ccd54513cd9c960bd155ab569b1a901bc99c6f9ad29559d3f38a28c91c1822d" + }, "@std/assert@0.224.0": { "integrity": "8643233ec7aec38a940a8264a6e3eed9bfa44e7a71cc6b3c8874213ff401967f", "dependencies": [ @@ -9275,9 +9279,10 @@ "jsr:@hono/hono@^4.8.3", "jsr:@logtape/file@^2.0.5", "jsr:@logtape/logtape@^2.0.5", - "jsr:@optique/config@1", - "jsr:@optique/core@1", - "jsr:@optique/run@1", + "jsr:@optique/config@^1.0.2", + "jsr:@optique/core@^1.0.2", + "jsr:@optique/run@^1.0.2", + "jsr:@standard-schema/spec@^1.1.0", "jsr:@std/assert@^1.0.13", "jsr:@std/async@^1.0.13", "jsr:@std/encoding@^1.0.10", diff --git a/packages/cli/package.json b/packages/cli/package.json index 31c8d9a81..555b86ebf 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -84,6 +84,7 @@ "@optique/config": "catalog:", "@optique/core": "catalog:", "@optique/run": "catalog:", + "@standard-schema/spec": "catalog:", "@hongminhee/localtunnel": "^0.3.0", "@inquirer/prompts": "^7.8.4", "@jimp/core": "^1.6.0", diff --git a/packages/cli/src/lookup.ts b/packages/cli/src/lookup.ts index 0eed6bb7c..7f8dcd7c7 100644 --- a/packages/cli/src/lookup.ts +++ b/packages/cli/src/lookup.ts @@ -163,23 +163,21 @@ const lookupModeOption = withDefault( key: (config) => config.lookup?.recurse, }, ), - recurseDepth: withDefault( - bindConfig( - option( - "--recurse-depth", - integer({ min: 1, metavar: "DEPTH" }), - { - description: message`Maximum recursion depth for ${ - optionNames(["--recurse"]) - }.`, - }, - ), + recurseDepth: bindConfig( + option( + "--recurse-depth", + integer({ min: 1, metavar: "DEPTH" }), { - context: configContext, - key: (config) => config.lookup?.recurseDepth, + description: message`Maximum recursion depth for ${ + optionNames(["--recurse"]) + }.`, }, ), - 20, + { + context: configContext, + key: (config) => config.lookup?.recurseDepth, + default: 20, + }, ), suppressErrors: suppressErrorsOption, }), diff --git a/packages/cli/src/options.ts b/packages/cli/src/options.ts index 33c8011c3..c0902a8ad 100644 --- a/packages/cli/src/options.ts +++ b/packages/cli/src/options.ts @@ -10,6 +10,7 @@ import { message, object, option, + optional, type OptionName, or, string, @@ -40,7 +41,7 @@ export function createTunnelServiceOption( const [firstOptionName, ...restOptionNames] = optionNames; // Note that we don't provide a default value here, since the tunneling // implementation will randomly select a service if none is specified. - return withDefault( + return optional( bindConfig( option( firstOptionName, @@ -57,7 +58,6 @@ By default, any of the supported tunneling services will be used key: (config) => config.tunnelService, }, ), - undefined, ); } @@ -76,19 +76,21 @@ type TunnelConfigSection = "inbox" | "relay"; export function createTunnelOption(section: S) { return object({ tunnel: bindConfig( - withDefault( - map( - flag("-T", "--no-tunnel", { - description: - message`Do not tunnel the server to the public Internet.`, - }), - () => false as const, - ), - true, + map( + flag("-T", "--no-tunnel", { + description: + message`Do not tunnel the server to the public Internet.`, + }), + () => false as const, ), { context: configContext, - key: (config: Config) => !(config[section]?.noTunnel ?? false), + key: (config: Config) => { + const sectionConfig = config[section]; + return sectionConfig?.noTunnel == null + ? undefined + : !sectionConfig.noTunnel; + }, default: true, }, ), diff --git a/packages/cli/src/tunnel.test.ts b/packages/cli/src/tunnel.test.ts index d8e477ebc..2c5996334 100644 --- a/packages/cli/src/tunnel.test.ts +++ b/packages/cli/src/tunnel.test.ts @@ -2,6 +2,7 @@ import type { Tunnel, TunnelOptions } from "@hongminhee/localtunnel"; import { runSync } from "@optique/run"; import { deepEqual, rejects } from "node:assert/strict"; import test from "node:test"; +import { runCli } from "./runner.ts"; import type { Ora } from "ora"; import { runTunnel, tunnelCommand } from "./tunnel.ts"; @@ -21,6 +22,57 @@ test("tunnel command structure", () => { deepEqual(testCommandWithoutOptions.service, undefined); }); +test("tunnel runner accepts omitted tunnel service", async () => { + const result = await runCli(["tunnel", "3000", "--ignore-config"]); + + deepEqual(result.command, "tunnel"); + deepEqual(result.port, 3000); + deepEqual((result as { service?: unknown }).service, undefined); +}); + +test("inbox runner accepts tunnel options without a tunnel service", async () => { + const withoutTunnel = await runCli([ + "inbox", + "--no-tunnel", + "--ignore-config", + ]); + const withOtherOption = await runCli([ + "inbox", + "--actor-name", + "Test Inbox", + "--ignore-config", + ]); + + deepEqual(withoutTunnel.command, "inbox"); + deepEqual((withoutTunnel as { tunnel?: unknown }).tunnel, false); + deepEqual( + (withoutTunnel as { tunnelService?: unknown }).tunnelService, + undefined, + ); + deepEqual(withOtherOption.command, "inbox"); + deepEqual((withOtherOption as { tunnel?: unknown }).tunnel, true); + deepEqual( + (withOtherOption as { actorName?: unknown }).actorName, + "Test Inbox", + ); + deepEqual( + (withOtherOption as { tunnelService?: unknown }).tunnelService, + undefined, + ); +}); + +test("relay runner accepts tunnel options without a tunnel service", async () => { + const result = await runCli([ + "relay", + "--no-tunnel", + "--ignore-config", + ]); + + deepEqual(result.command, "relay"); + deepEqual((result as { tunnel?: unknown }).tunnel, false); + deepEqual((result as { tunnelService?: unknown }).tunnelService, undefined); +}); + test("tunnel successfully creates and manages tunnel", async () => { const mockCommand = { command: "tunnel" as const, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f77476dae..c2adbabf1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,14 +49,17 @@ catalogs: specifier: ^1.39.0 version: 1.39.0 '@optique/config': - specifier: ^1.0.0 - version: 1.0.0 + specifier: ^1.0.2 + version: 1.0.2 '@optique/core': - specifier: ^1.0.0 - version: 1.0.0 + specifier: ^1.0.2 + version: 1.0.2 '@optique/run': - specifier: ^1.0.0 - version: 1.0.0 + specifier: ^1.0.2 + version: 1.0.2 + '@standard-schema/spec': + specifier: ^1.1.0 + version: 1.1.0 '@std/assert': specifier: jsr:^1.0.13 version: 1.0.13 @@ -889,16 +892,19 @@ importers: version: 2.0.5 '@optique/config': specifier: 'catalog:' - version: 1.0.0(@standard-schema/spec@1.0.0) + version: 1.0.2(@standard-schema/spec@1.1.0) '@optique/core': specifier: 'catalog:' - version: 1.0.0 + version: 1.0.2 '@optique/run': specifier: 'catalog:' - version: 1.0.0 + version: 1.0.2 '@poppanator/http-constants': specifier: ^1.1.1 version: 1.1.1 + '@standard-schema/spec': + specifier: 'catalog:' + version: 1.1.0 byte-encodings: specifier: 'catalog:' version: 1.0.11 @@ -971,10 +977,10 @@ importers: version: link:../init '@optique/core': specifier: 'catalog:' - version: 1.0.0 + version: 1.0.2 '@optique/run': specifier: 'catalog:' - version: 1.0.0 + version: 1.0.2 es-toolkit: specifier: 'catalog:' version: 1.43.0 @@ -1250,10 +1256,10 @@ importers: version: 2.0.5 '@optique/core': specifier: 'catalog:' - version: 1.0.0 + version: 1.0.2 '@optique/run': specifier: 'catalog:' - version: 1.0.0 + version: 1.0.2 chalk: specifier: 'catalog:' version: 5.6.2 @@ -4482,18 +4488,18 @@ packages: peerDependencies: '@opentelemetry/api': ^1.1.0 - '@optique/config@1.0.0': - resolution: {integrity: sha512-O7PgpWLAEj+il0nZMKRnQq+kIA1uVfvH0PLyqRZowKkTBUbijiub5HI30Y7W5/ucx0zAg26dLDO7VnMETQ573Q==} + '@optique/config@1.0.2': + resolution: {integrity: sha512-h0OnuXdVIE+bDxVuhMuYtEv0lzllSK7dYBTDSPdfDZq1NZ0dcpYs1dsgYKKG8PtuDN/svRr7xZ2oSonPhxNpow==} engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} peerDependencies: '@standard-schema/spec': ^1.1.0 - '@optique/core@1.0.0': - resolution: {integrity: sha512-8h2GgREAQl4vGFUWLxqZQty4rg36FAlMvcAHPMGEAL5IUR97qSRZohtI99vwoQ6eHIRBOyF/krnMQZGPFyoNVw==} + '@optique/core@1.0.2': + resolution: {integrity: sha512-znsqMmjAdeOgSJzdJlpZpgAscojwQmeQYXzYnuEKllz5VCj6WyEkdzU4QuvJQtWQY3ve2taXwudEBRur0VHBOQ==} engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} - '@optique/run@1.0.0': - resolution: {integrity: sha512-QQywmuYmCWBYaok+MTL1c+NwGHzeUrV7AsMqiWYnRKcAxGmAhKKfdY2Hofq321fZWgqOpGBGGCW8YDGEr3zhmw==} + '@optique/run@1.0.2': + resolution: {integrity: sha512-0Wc+zC8SLGV8zXQX+pk+o0c6wE/ddx/36CHZ0toTh5lApsjruUuGhqbxvljerAAG5un1xQbOLxzksBVC6UPgSg==} engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} '@oslojs/encoding@1.1.0': @@ -5544,6 +5550,9 @@ packages: '@standard-schema/spec@1.0.0': resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@sveltejs/acorn-typescript@1.0.5': resolution: {integrity: sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==} peerDependencies: @@ -15812,16 +15821,16 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) - '@optique/config@1.0.0(@standard-schema/spec@1.0.0)': + '@optique/config@1.0.2(@standard-schema/spec@1.1.0)': dependencies: - '@optique/core': 1.0.0 - '@standard-schema/spec': 1.0.0 + '@optique/core': 1.0.2 + '@standard-schema/spec': 1.1.0 - '@optique/core@1.0.0': {} + '@optique/core@1.0.2': {} - '@optique/run@1.0.0': + '@optique/run@1.0.2': dependencies: - '@optique/core': 1.0.0 + '@optique/core': 1.0.2 '@oslojs/encoding@1.1.0': {} @@ -16640,6 +16649,8 @@ snapshots: '@standard-schema/spec@1.0.0': {} + '@standard-schema/spec@1.1.0': {} + '@sveltejs/acorn-typescript@1.0.5(acorn@8.15.0)': dependencies: acorn: 8.15.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index de1bad4f5..da386e5f5 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -57,9 +57,10 @@ catalog: "@opentelemetry/sdk-node": ^0.211.0 "@opentelemetry/sdk-trace-base": ^2.5.0 "@opentelemetry/semantic-conventions": ^1.39.0 - "@optique/config": ^1.0.0 - "@optique/core": ^1.0.0 - "@optique/run": ^1.0.0 + "@optique/config": ^1.0.2 + "@optique/core": ^1.0.2 + "@optique/run": ^1.0.2 + "@standard-schema/spec": ^1.1.0 "@std/assert": "jsr:^1.0.13" "@std/async": "jsr:^1.0.13" "@std/path": "jsr:^1.0.6"