@tinycloud/cli 0.7.0-beta.1 → 0.7.0-beta.2
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/dist/index.js +119 -33
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -973,11 +973,19 @@ Open this URL in a browser to authenticate:
|
|
|
973
973
|
|
|
974
974
|
// src/commands/init.ts
|
|
975
975
|
function registerInitCommand(program2) {
|
|
976
|
-
program2.command("init").description("Initialize a new TinyCloud profile").option("--name <profile>", "Profile name", "default").option("--key-only", "Only generate key, skip authentication").option("--host <url>", "TinyCloud node URL").option("--paste", "Use manual paste mode for authentication").option("--no-popup", "Print the OpenKey URL without opening a browser").action(async (options, cmd) => {
|
|
976
|
+
program2.command("init").description("Initialize a new TinyCloud profile").option("--name <profile>", "Profile name", "default").option("--key-only", "Only generate key, skip authentication").option("--host <url>", "TinyCloud node URL").option("--paste", "Use manual paste mode for authentication").option("--no-popup", "Print the OpenKey URL without opening a browser").option("--default-space <name>", "Default space used when --space is omitted (e.g. applications)").action(async (options, cmd) => {
|
|
977
977
|
try {
|
|
978
978
|
const globalOpts = cmd.optsWithGlobals();
|
|
979
979
|
const profileName = options.name;
|
|
980
980
|
const host = options.host ?? globalOpts.host ?? DEFAULT_HOST;
|
|
981
|
+
const defaultSpace = options.defaultSpace;
|
|
982
|
+
if (defaultSpace !== void 0 && !/^[A-Za-z0-9_-]+$/.test(defaultSpace)) {
|
|
983
|
+
throw new CLIError(
|
|
984
|
+
"INVALID_SPACE",
|
|
985
|
+
`Invalid --default-space "${defaultSpace}". Use a short name ([A-Za-z0-9_-]).`,
|
|
986
|
+
ExitCode.USAGE_ERROR
|
|
987
|
+
);
|
|
988
|
+
}
|
|
981
989
|
if (await ProfileManager.profileExists(profileName)) {
|
|
982
990
|
throw new CLIError(
|
|
983
991
|
"PROFILE_EXISTS",
|
|
@@ -996,7 +1004,8 @@ function registerInitCommand(program2) {
|
|
|
996
1004
|
chainId: DEFAULT_CHAIN_ID,
|
|
997
1005
|
spaceName: "default",
|
|
998
1006
|
did,
|
|
999
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1007
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1008
|
+
...defaultSpace ? { defaultSpace } : {}
|
|
1000
1009
|
};
|
|
1001
1010
|
await ProfileManager.setProfile(profileName, profileConfig);
|
|
1002
1011
|
const config = await ProfileManager.getConfig();
|
|
@@ -5781,6 +5790,38 @@ var KVService = class extends BaseService {
|
|
|
5781
5790
|
signal: this.combineSignals(signal)
|
|
5782
5791
|
});
|
|
5783
5792
|
}
|
|
5793
|
+
/**
|
|
5794
|
+
* Serialize a single put value into a fetch body.
|
|
5795
|
+
*
|
|
5796
|
+
* Binary values (Blob/ArrayBuffer/typed-array, incl. Node Buffer) are sent as
|
|
5797
|
+
* raw bytes (as a Blob) so they round-trip byte-identically — without this a
|
|
5798
|
+
* Buffer would be JSON.stringify'd into `{"type":"Buffer","data":[...]}`.
|
|
5799
|
+
* Strings are returned unchanged (preserving prior behavior); other values are
|
|
5800
|
+
* JSON-encoded. `contentType` overrides the inferred type for binary values.
|
|
5801
|
+
*/
|
|
5802
|
+
serializePutValue(value, contentType) {
|
|
5803
|
+
if (value instanceof Blob) {
|
|
5804
|
+
if (!contentType || value.type === contentType) {
|
|
5805
|
+
return value;
|
|
5806
|
+
}
|
|
5807
|
+
return new Blob([value], { type: contentType });
|
|
5808
|
+
}
|
|
5809
|
+
if (value instanceof ArrayBuffer) {
|
|
5810
|
+
return new Blob([value], {
|
|
5811
|
+
type: contentType ?? "application/octet-stream"
|
|
5812
|
+
});
|
|
5813
|
+
}
|
|
5814
|
+
if (ArrayBuffer.isView(value)) {
|
|
5815
|
+
const view = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
|
5816
|
+
return new Blob([view], {
|
|
5817
|
+
type: contentType ?? "application/octet-stream"
|
|
5818
|
+
});
|
|
5819
|
+
}
|
|
5820
|
+
if (typeof value === "string") {
|
|
5821
|
+
return contentType ? new Blob([value], { type: contentType }) : value;
|
|
5822
|
+
}
|
|
5823
|
+
return JSON.stringify(value);
|
|
5824
|
+
}
|
|
5784
5825
|
serializeBatchPutValue(item) {
|
|
5785
5826
|
const contentType = item.contentType;
|
|
5786
5827
|
if (item.value instanceof Blob) {
|
|
@@ -5850,10 +5891,13 @@ var KVService = class extends BaseService {
|
|
|
5850
5891
|
* @param raw - Whether to return raw text
|
|
5851
5892
|
* @returns Parsed data
|
|
5852
5893
|
*/
|
|
5853
|
-
async parseResponse(response, raw = false) {
|
|
5894
|
+
async parseResponse(response, raw = false, binary = false) {
|
|
5854
5895
|
if (!response.ok) {
|
|
5855
5896
|
return void 0;
|
|
5856
5897
|
}
|
|
5898
|
+
if (binary) {
|
|
5899
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
5900
|
+
}
|
|
5857
5901
|
if (raw) {
|
|
5858
5902
|
return await response.text();
|
|
5859
5903
|
}
|
|
@@ -5960,7 +6004,11 @@ var KVService = class extends BaseService {
|
|
|
5960
6004
|
)
|
|
5961
6005
|
);
|
|
5962
6006
|
}
|
|
5963
|
-
const data = await this.parseResponse(
|
|
6007
|
+
const data = await this.parseResponse(
|
|
6008
|
+
response,
|
|
6009
|
+
options?.raw,
|
|
6010
|
+
options?.binary
|
|
6011
|
+
);
|
|
5964
6012
|
return ok({
|
|
5965
6013
|
data,
|
|
5966
6014
|
headers: this.createResponseHeaders(response.headers)
|
|
@@ -5979,12 +6027,7 @@ var KVService = class extends BaseService {
|
|
|
5979
6027
|
return err(authRequiredError("kv"));
|
|
5980
6028
|
}
|
|
5981
6029
|
const path = this.getFullPath(key, options?.prefix);
|
|
5982
|
-
|
|
5983
|
-
if (typeof value === "string") {
|
|
5984
|
-
body = value;
|
|
5985
|
-
} else {
|
|
5986
|
-
body = JSON.stringify(value);
|
|
5987
|
-
}
|
|
6030
|
+
const body = this.serializePutValue(value, options?.contentType);
|
|
5988
6031
|
try {
|
|
5989
6032
|
const response = await this.invokeOperation(
|
|
5990
6033
|
path,
|
|
@@ -10733,30 +10776,31 @@ function resolveChainId(profile, session) {
|
|
|
10733
10776
|
return profile.chainId;
|
|
10734
10777
|
}
|
|
10735
10778
|
async function resolveSpaceUri(input, profileName) {
|
|
10736
|
-
|
|
10737
|
-
|
|
10738
|
-
|
|
10779
|
+
const profile = await ProfileManager.getProfile(profileName);
|
|
10780
|
+
const effective = input || profile.defaultSpace;
|
|
10781
|
+
if (!effective) return void 0;
|
|
10782
|
+
if (effective.startsWith("tinycloud:")) {
|
|
10783
|
+
const parsed = parseSpaceUri(effective);
|
|
10739
10784
|
if (!parsed) {
|
|
10740
10785
|
throw new CLIError(
|
|
10741
10786
|
"INVALID_SPACE",
|
|
10742
|
-
`Invalid
|
|
10787
|
+
`Invalid space "${effective}". Use a short name ([A-Za-z0-9_-]) or a full tinycloud:... URI.`,
|
|
10743
10788
|
ExitCode.USAGE_ERROR
|
|
10744
10789
|
);
|
|
10745
10790
|
}
|
|
10746
10791
|
return buildSpaceUri(parsed.owner, parsed.name);
|
|
10747
10792
|
}
|
|
10748
|
-
if (!/^[A-Za-z0-9_-]+$/.test(
|
|
10793
|
+
if (!/^[A-Za-z0-9_-]+$/.test(effective)) {
|
|
10749
10794
|
throw new CLIError(
|
|
10750
10795
|
"INVALID_SPACE",
|
|
10751
|
-
`Invalid
|
|
10796
|
+
`Invalid space "${effective}". Use a short name ([A-Za-z0-9_-]) or a full tinycloud:... URI.`,
|
|
10752
10797
|
ExitCode.USAGE_ERROR
|
|
10753
10798
|
);
|
|
10754
10799
|
}
|
|
10755
|
-
const profile = await ProfileManager.getProfile(profileName);
|
|
10756
10800
|
const session = await ProfileManager.getSession(profileName);
|
|
10757
10801
|
const address = resolveAddress(profile, session);
|
|
10758
10802
|
const chainId = resolveChainId(profile, session);
|
|
10759
|
-
return makePkhSpaceId(address, chainId,
|
|
10803
|
+
return makePkhSpaceId(address, chainId, effective);
|
|
10760
10804
|
}
|
|
10761
10805
|
|
|
10762
10806
|
// src/lib/permissions.ts
|
|
@@ -12144,7 +12188,11 @@ function registerKvCommand(program2) {
|
|
|
12144
12188
|
const ctx = await ProfileManager.resolveContext(globalOpts);
|
|
12145
12189
|
const node = await ensureAuthenticated(ctx);
|
|
12146
12190
|
const kv2 = await kvHandle(node, options.space, ctx.profile);
|
|
12147
|
-
const
|
|
12191
|
+
const wantBytes = !!options.output || !!options.raw;
|
|
12192
|
+
const result = await withSpinner(
|
|
12193
|
+
`Getting ${key}...`,
|
|
12194
|
+
() => kv2.get(key, wantBytes ? { binary: true } : void 0)
|
|
12195
|
+
);
|
|
12148
12196
|
if (!result.ok) {
|
|
12149
12197
|
if (result.error.code === "KV_NOT_FOUND" || result.error.code === "NOT_FOUND") {
|
|
12150
12198
|
throw new CLIError("NOT_FOUND", `Key "${key}" not found`, ExitCode.NOT_FOUND);
|
|
@@ -12154,14 +12202,12 @@ function registerKvCommand(program2) {
|
|
|
12154
12202
|
const data = result.data.data;
|
|
12155
12203
|
const metadata = result.data.headers ?? {};
|
|
12156
12204
|
if (options.output) {
|
|
12157
|
-
|
|
12158
|
-
await writeFile3(options.output, content);
|
|
12205
|
+
await writeFile3(options.output, data);
|
|
12159
12206
|
outputJson({ key, written: options.output });
|
|
12160
12207
|
return;
|
|
12161
12208
|
}
|
|
12162
12209
|
if (options.raw) {
|
|
12163
|
-
|
|
12164
|
-
process.stdout.write(content);
|
|
12210
|
+
process.stdout.write(data);
|
|
12165
12211
|
return;
|
|
12166
12212
|
}
|
|
12167
12213
|
if (shouldOutputJson()) {
|
|
@@ -12178,7 +12224,7 @@ function registerKvCommand(program2) {
|
|
|
12178
12224
|
handleError(error);
|
|
12179
12225
|
}
|
|
12180
12226
|
});
|
|
12181
|
-
kv.command("put <key> [value]").description("Set a value").option("--file <path>", "Read value from file").option("--stdin", "Read value from stdin").action(async (key, value, options, cmd) => {
|
|
12227
|
+
kv.command("put <key> [value]").description("Set a value").option("--file <path>", "Read value from file").option("--stdin", "Read value from stdin").option("--space <name|uri>", "Target a non-primary space (short name or full URI)").action(async (key, value, options, cmd) => {
|
|
12182
12228
|
try {
|
|
12183
12229
|
const globalOpts = cmd.optsWithGlobals();
|
|
12184
12230
|
const ctx = await ProfileManager.resolveContext(globalOpts);
|
|
@@ -12202,7 +12248,8 @@ function registerKvCommand(program2) {
|
|
|
12202
12248
|
putValue = value;
|
|
12203
12249
|
}
|
|
12204
12250
|
}
|
|
12205
|
-
const
|
|
12251
|
+
const kv2 = await kvHandle(node, options.space, ctx.profile);
|
|
12252
|
+
const result = await withSpinner(`Writing ${key}...`, () => kv2.put(key, putValue));
|
|
12206
12253
|
if (!result.ok) {
|
|
12207
12254
|
throw new CLIError(result.error.code, result.error.message, ExitCode.ERROR);
|
|
12208
12255
|
}
|
|
@@ -12211,12 +12258,13 @@ function registerKvCommand(program2) {
|
|
|
12211
12258
|
handleError(error);
|
|
12212
12259
|
}
|
|
12213
12260
|
});
|
|
12214
|
-
kv.command("delete <key>").description("Delete a key").action(async (key,
|
|
12261
|
+
kv.command("delete <key>").description("Delete a key").option("--space <name|uri>", "Target a non-primary space (short name or full URI)").action(async (key, options, cmd) => {
|
|
12215
12262
|
try {
|
|
12216
12263
|
const globalOpts = cmd.optsWithGlobals();
|
|
12217
12264
|
const ctx = await ProfileManager.resolveContext(globalOpts);
|
|
12218
12265
|
const node = await ensureAuthenticated(ctx);
|
|
12219
|
-
const
|
|
12266
|
+
const kv2 = await kvHandle(node, options.space, ctx.profile);
|
|
12267
|
+
const result = await withSpinner(`Deleting ${key}...`, () => kv2.delete(key));
|
|
12220
12268
|
if (!result.ok) {
|
|
12221
12269
|
throw new CLIError(result.error.code, result.error.message, ExitCode.ERROR);
|
|
12222
12270
|
}
|
|
@@ -12315,16 +12363,13 @@ function registerSpaceCommand(program2) {
|
|
|
12315
12363
|
handleError(error);
|
|
12316
12364
|
}
|
|
12317
12365
|
});
|
|
12318
|
-
space.command("create <name>").description("Create
|
|
12366
|
+
space.command("create <name>").alias("host").description("Create (host) one of your owned spaces by name").action(async (name, _options, cmd) => {
|
|
12319
12367
|
try {
|
|
12320
12368
|
const globalOpts = cmd.optsWithGlobals();
|
|
12321
12369
|
const ctx = await ProfileManager.resolveContext(globalOpts);
|
|
12322
12370
|
const node = await ensureAuthenticated(ctx);
|
|
12323
|
-
const
|
|
12324
|
-
|
|
12325
|
-
throw new CLIError(result.error.code, result.error.message, ExitCode.ERROR);
|
|
12326
|
-
}
|
|
12327
|
-
outputJson({ spaceId: result.data.id, name });
|
|
12371
|
+
const spaceId = await node.hostOwnedSpace(name);
|
|
12372
|
+
outputJson({ spaceId, name, hosted: true });
|
|
12328
12373
|
} catch (error) {
|
|
12329
12374
|
handleError(error);
|
|
12330
12375
|
}
|
|
@@ -12776,6 +12821,7 @@ function registerProfileCommand(program2) {
|
|
|
12776
12821
|
process.stdout.write(formatField("Posture", posture) + "\n");
|
|
12777
12822
|
process.stdout.write(formatField("Operator", operatorType) + "\n");
|
|
12778
12823
|
process.stdout.write(formatField("Space", p.spaceId || null) + "\n");
|
|
12824
|
+
process.stdout.write(formatField("Default Space", p.defaultSpace || null) + "\n");
|
|
12779
12825
|
process.stdout.write(formatField("Key", hasKey) + "\n");
|
|
12780
12826
|
process.stdout.write(formatField("Session", hasSession) + "\n");
|
|
12781
12827
|
process.stdout.write(formatField("Created", p.createdAt) + "\n");
|
|
@@ -12796,6 +12842,46 @@ function registerProfileCommand(program2) {
|
|
|
12796
12842
|
handleError(error);
|
|
12797
12843
|
}
|
|
12798
12844
|
});
|
|
12845
|
+
profile.command("set-default-space [name]").description("Set (or clear) the default space used when --space is omitted").option("--profile <name>", "Profile to modify (defaults to the active profile)").option("--unset", "Clear the default space so commands fall back to the primary space").addHelpText("after", `
|
|
12846
|
+
|
|
12847
|
+
The default space is a short space NAME (e.g. "applications"), resolved per
|
|
12848
|
+
profile at command time. Precedence for every kv/sql command:
|
|
12849
|
+
explicit --space flag > profile defaultSpace > primary space.
|
|
12850
|
+
|
|
12851
|
+
Examples:
|
|
12852
|
+
$ tc profile set-default-space applications
|
|
12853
|
+
$ tc profile set-default-space applications --profile cli-test
|
|
12854
|
+
$ tc profile set-default-space --unset
|
|
12855
|
+
`).action(async (name, options, cmd) => {
|
|
12856
|
+
try {
|
|
12857
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
12858
|
+
const ctx = await ProfileManager.resolveContext({
|
|
12859
|
+
...globalOpts,
|
|
12860
|
+
profile: options.profile ?? globalOpts.profile
|
|
12861
|
+
});
|
|
12862
|
+
const profileName = ctx.profile;
|
|
12863
|
+
if (!options.unset && (name === void 0 || name === "")) {
|
|
12864
|
+
throw new CLIError(
|
|
12865
|
+
"USAGE_ERROR",
|
|
12866
|
+
"Provide a space name (e.g. `tc profile set-default-space applications`) or pass --unset.",
|
|
12867
|
+
ExitCode.USAGE_ERROR
|
|
12868
|
+
);
|
|
12869
|
+
}
|
|
12870
|
+
if (!options.unset && !/^[A-Za-z0-9_-]+$/.test(name)) {
|
|
12871
|
+
throw new CLIError(
|
|
12872
|
+
"INVALID_SPACE",
|
|
12873
|
+
`Invalid space name "${name}". Use a short name ([A-Za-z0-9_-]).`,
|
|
12874
|
+
ExitCode.USAGE_ERROR
|
|
12875
|
+
);
|
|
12876
|
+
}
|
|
12877
|
+
const p = await ProfileManager.getProfile(profileName);
|
|
12878
|
+
const defaultSpace = options.unset ? void 0 : name;
|
|
12879
|
+
await ProfileManager.setProfile(profileName, { ...p, defaultSpace });
|
|
12880
|
+
outputJson({ profile: profileName, defaultSpace: defaultSpace ?? null, updated: true });
|
|
12881
|
+
} catch (error) {
|
|
12882
|
+
handleError(error);
|
|
12883
|
+
}
|
|
12884
|
+
});
|
|
12799
12885
|
profile.command("delete <name>").description("Delete a profile").action(async (name, _options, cmd) => {
|
|
12800
12886
|
try {
|
|
12801
12887
|
if (isInteractive()) {
|