@ait-co/console-cli 0.1.26 → 0.1.28
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/cli.mjs +234 -54
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -2448,7 +2448,7 @@ function optionalPathArray(input, key, configDir) {
|
|
|
2448
2448
|
});
|
|
2449
2449
|
}
|
|
2450
2450
|
const EMAIL_REGEX = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
|
2451
|
-
function isValidEmail(v) {
|
|
2451
|
+
function isValidEmail$1(v) {
|
|
2452
2452
|
return EMAIL_REGEX.test(v.toLowerCase());
|
|
2453
2453
|
}
|
|
2454
2454
|
const TITLE_KO_REGEX = /^[가-힣A-Za-z0-9 :·?]+$/;
|
|
@@ -2491,6 +2491,11 @@ function isValidHttpUrl(v) {
|
|
|
2491
2491
|
}
|
|
2492
2492
|
}
|
|
2493
2493
|
function validateManifest(raw, configDir) {
|
|
2494
|
+
let miniAppId;
|
|
2495
|
+
if (raw.miniAppId !== void 0 && raw.miniAppId !== null) {
|
|
2496
|
+
if (typeof raw.miniAppId !== "number" || !Number.isInteger(raw.miniAppId) || raw.miniAppId <= 0) throw new ManifestError("invalid-config", `miniAppId must be a positive integer (got ${JSON.stringify(raw.miniAppId)})`, "miniAppId");
|
|
2497
|
+
miniAppId = raw.miniAppId;
|
|
2498
|
+
}
|
|
2494
2499
|
const titleKo = requireString(raw, "titleKo");
|
|
2495
2500
|
if (!TITLE_KO_REGEX.test(titleKo)) throw new ManifestError("invalid-config", `titleKo may only contain Korean/English letters, digits, spaces, and ":·?" (got "${titleKo}"; server-side rule, errorCode: miniApp.InvalidTitle)`, "titleKo");
|
|
2496
2501
|
const titleKoLen = codePointsExcludingSpaces(titleKo);
|
|
@@ -2505,7 +2510,7 @@ function validateManifest(raw, configDir) {
|
|
|
2505
2510
|
}
|
|
2506
2511
|
const appName = requireString(raw, "appName");
|
|
2507
2512
|
const csEmail = requireString(raw, "csEmail");
|
|
2508
|
-
if (!isValidEmail(csEmail)) throw new ManifestError("invalid-config", `csEmail is not a valid email address (got ${csEmail})`, "csEmail");
|
|
2513
|
+
if (!isValidEmail$1(csEmail)) throw new ManifestError("invalid-config", `csEmail is not a valid email address (got ${csEmail})`, "csEmail");
|
|
2509
2514
|
const subtitle = requireString(raw, "subtitle");
|
|
2510
2515
|
if (subtitle.length > MANIFEST_LIMITS.subtitleMaxChars) throw new ManifestError("invalid-config", `subtitle must be ${MANIFEST_LIMITS.subtitleMaxChars} characters or fewer (got ${subtitle.length})`, "subtitle");
|
|
2511
2516
|
const description = requireString(raw, "description");
|
|
@@ -2513,21 +2518,29 @@ function validateManifest(raw, configDir) {
|
|
|
2513
2518
|
if (descriptionCodepoints > DETAIL_DESCRIPTION_MAX_CODEPOINTS) throw new ManifestError("invalid-config", `description must be ${DETAIL_DESCRIPTION_MAX_CODEPOINTS} characters or fewer (got ${descriptionCodepoints})`, "description");
|
|
2514
2519
|
const homePageUri = optionalString(raw, "homePageUri");
|
|
2515
2520
|
if (homePageUri !== void 0 && !isValidHttpUrl(homePageUri)) throw new ManifestError("invalid-config", `homePageUri must be a http(s) URL (got ${homePageUri})`, "homePageUri");
|
|
2521
|
+
const logo = requirePath(raw, "logo", configDir);
|
|
2522
|
+
const logoDarkMode = optionalPath(raw, "logoDarkMode", configDir);
|
|
2523
|
+
const horizontalThumbnail = requirePath(raw, "horizontalThumbnail", configDir);
|
|
2524
|
+
const categoryIds = requireNumberArray(raw, "categoryIds", { min: 1 });
|
|
2525
|
+
const keywords = optionalStringArray(raw, "keywords", { max: 10 });
|
|
2526
|
+
const verticalScreenshots = requirePathArray(raw, "verticalScreenshots", configDir, { min: 3 });
|
|
2527
|
+
const horizontalScreenshots = optionalPathArray(raw, "horizontalScreenshots", configDir);
|
|
2516
2528
|
return {
|
|
2529
|
+
miniAppId,
|
|
2517
2530
|
titleKo,
|
|
2518
2531
|
titleEn,
|
|
2519
2532
|
appName,
|
|
2520
2533
|
homePageUri,
|
|
2521
2534
|
csEmail,
|
|
2522
|
-
logo
|
|
2523
|
-
logoDarkMode
|
|
2524
|
-
horizontalThumbnail
|
|
2525
|
-
categoryIds
|
|
2535
|
+
logo,
|
|
2536
|
+
logoDarkMode,
|
|
2537
|
+
horizontalThumbnail,
|
|
2538
|
+
categoryIds,
|
|
2526
2539
|
subtitle,
|
|
2527
2540
|
description,
|
|
2528
|
-
keywords
|
|
2529
|
-
verticalScreenshots
|
|
2530
|
-
horizontalScreenshots
|
|
2541
|
+
keywords,
|
|
2542
|
+
verticalScreenshots,
|
|
2543
|
+
horizontalScreenshots
|
|
2531
2544
|
};
|
|
2532
2545
|
}
|
|
2533
2546
|
//#endregion
|
|
@@ -2779,7 +2792,7 @@ function validateAppName(raw) {
|
|
|
2779
2792
|
return true;
|
|
2780
2793
|
}
|
|
2781
2794
|
function validateEmail(raw) {
|
|
2782
|
-
if (!isValidEmail(raw)) return "not a valid email address";
|
|
2795
|
+
if (!isValidEmail$1(raw)) return "not a valid email address";
|
|
2783
2796
|
return true;
|
|
2784
2797
|
}
|
|
2785
2798
|
function validateSubtitle(raw) {
|
|
@@ -2904,6 +2917,7 @@ function buildSubmitPayload(manifest, urls) {
|
|
|
2904
2917
|
description: manifest.subtitle,
|
|
2905
2918
|
detailDescription: manifest.description,
|
|
2906
2919
|
images,
|
|
2920
|
+
...manifest.miniAppId !== void 0 ? { miniAppId: manifest.miniAppId } : {},
|
|
2907
2921
|
...urls.logoDarkMode !== void 0 ? { darkModeIconUri: urls.logoDarkMode } : {},
|
|
2908
2922
|
...manifest.homePageUri !== void 0 ? { homePageUri: manifest.homePageUri } : {}
|
|
2909
2923
|
},
|
|
@@ -2925,6 +2939,7 @@ async function runRegister(args, deps = {}) {
|
|
|
2925
2939
|
printContextHeader(ctx, { json: args.json });
|
|
2926
2940
|
const manifest = await loadAndValidateManifest(args, deps);
|
|
2927
2941
|
if (!manifest) return;
|
|
2942
|
+
if (manifest.miniAppId !== void 0 && !args.json) process.stderr.write(`[mode: update · miniAppId ${manifest.miniAppId}] existing app draft will be overwritten and re-enter the review queue.\n`);
|
|
2928
2943
|
if (!args.dryRun && !args.acceptTerms) {
|
|
2929
2944
|
emitTermsNotAccepted(args.json);
|
|
2930
2945
|
await exitAfterFlush(ExitCode.Usage);
|
|
@@ -8680,6 +8695,46 @@ async function fetchWorkspaceMembers(workspaceId, cookies, opts = {}) {
|
|
|
8680
8695
|
if (!Array.isArray(raw)) throw new Error(`Unexpected members shape for workspace=${workspaceId}: not an array`);
|
|
8681
8696
|
return raw.map((entry, index) => normalizeMember(entry, workspaceId, index));
|
|
8682
8697
|
}
|
|
8698
|
+
/**
|
|
8699
|
+
* Invite a user by email to the workspace.
|
|
8700
|
+
*
|
|
8701
|
+
* Maps to `POST /workspaces/:wid/invites/send/by-email`. Payload shape is
|
|
8702
|
+
* inferred from static bundle analysis (PR #118); `role` is optional —
|
|
8703
|
+
* omit to use the server default.
|
|
8704
|
+
*
|
|
8705
|
+
* ⚠️ Inferred endpoint: method/path confirmed, payload/response/errorCodes
|
|
8706
|
+
* not live-captured. See docs/api/members.md "Invite 관련 endpoint".
|
|
8707
|
+
*/
|
|
8708
|
+
async function inviteMember(workspaceId, email, role, cookies, opts = {}) {
|
|
8709
|
+
const url = `${BASE$1}/workspaces/${workspaceId}/invites/send/by-email`;
|
|
8710
|
+
const body = { email };
|
|
8711
|
+
if (role !== void 0) body.role = role;
|
|
8712
|
+
return { raw: await requestConsoleApi({
|
|
8713
|
+
method: "POST",
|
|
8714
|
+
url,
|
|
8715
|
+
cookies,
|
|
8716
|
+
body,
|
|
8717
|
+
...opts.fetchImpl ? { fetchImpl: opts.fetchImpl } : {}
|
|
8718
|
+
}) };
|
|
8719
|
+
}
|
|
8720
|
+
/**
|
|
8721
|
+
* Remove a member from the workspace by their `bizUserNo`.
|
|
8722
|
+
*
|
|
8723
|
+
* Maps to `DELETE /workspaces/:wid/members/:memberBizUserNo`. The path
|
|
8724
|
+
* param name `memberBizUserNo` is confirmed from bundle analysis (PR #118).
|
|
8725
|
+
* Response body shape is uncaptured; we treat any SUCCESS as success.
|
|
8726
|
+
*
|
|
8727
|
+
* ⚠️ Inferred endpoint: method/path confirmed, response/errorCodes not
|
|
8728
|
+
* live-captured. See docs/api/members.md "DELETE …/members/<memberBizUserNo>".
|
|
8729
|
+
*/
|
|
8730
|
+
async function removeMember(workspaceId, memberBizUserNo, cookies, opts = {}) {
|
|
8731
|
+
await requestConsoleApi({
|
|
8732
|
+
method: "DELETE",
|
|
8733
|
+
url: `${BASE$1}/workspaces/${workspaceId}/members/${memberBizUserNo}`,
|
|
8734
|
+
cookies,
|
|
8735
|
+
...opts.fetchImpl ? { fetchImpl: opts.fetchImpl } : {}
|
|
8736
|
+
});
|
|
8737
|
+
}
|
|
8683
8738
|
function normalizeMember(raw, workspaceId, index) {
|
|
8684
8739
|
if (raw === null || typeof raw !== "object") throw new Error(`Unexpected member entry at index ${index} for workspace=${workspaceId}: not an object`);
|
|
8685
8740
|
const rec = raw;
|
|
@@ -8704,60 +8759,185 @@ function normalizeMember(raw, workspaceId, index) {
|
|
|
8704
8759
|
isAdult: Boolean(rec.isAdult)
|
|
8705
8760
|
};
|
|
8706
8761
|
}
|
|
8762
|
+
//#endregion
|
|
8763
|
+
//#region src/commands/members.ts
|
|
8764
|
+
const lsCommand$2 = defineCommand({
|
|
8765
|
+
meta: {
|
|
8766
|
+
name: "ls",
|
|
8767
|
+
description: "List members of the selected workspace."
|
|
8768
|
+
},
|
|
8769
|
+
args: {
|
|
8770
|
+
workspace: {
|
|
8771
|
+
type: "string",
|
|
8772
|
+
description: "Workspace ID. Defaults to the selected workspace (`aitcc workspace use`)."
|
|
8773
|
+
},
|
|
8774
|
+
json: {
|
|
8775
|
+
type: "boolean",
|
|
8776
|
+
description: "Emit machine-readable JSON to stdout.",
|
|
8777
|
+
default: false
|
|
8778
|
+
}
|
|
8779
|
+
},
|
|
8780
|
+
async run({ args }) {
|
|
8781
|
+
const ctx = await resolveWorkspaceContext(args);
|
|
8782
|
+
if (!ctx) return;
|
|
8783
|
+
const { session, workspaceId } = ctx;
|
|
8784
|
+
printContextHeader(ctx, { json: args.json });
|
|
8785
|
+
try {
|
|
8786
|
+
const members = await fetchWorkspaceMembers(workspaceId, session.cookies);
|
|
8787
|
+
if (args.json) {
|
|
8788
|
+
emitJson({
|
|
8789
|
+
ok: true,
|
|
8790
|
+
workspaceId,
|
|
8791
|
+
members: members.map((m) => ({
|
|
8792
|
+
bizUserNo: m.bizUserNo,
|
|
8793
|
+
name: m.name,
|
|
8794
|
+
email: m.email,
|
|
8795
|
+
status: m.status,
|
|
8796
|
+
role: m.role,
|
|
8797
|
+
isOwnerDelegationRequested: m.isOwnerDelegationRequested
|
|
8798
|
+
}))
|
|
8799
|
+
});
|
|
8800
|
+
return exitAfterFlush(ExitCode.Ok);
|
|
8801
|
+
}
|
|
8802
|
+
if (members.length === 0) {
|
|
8803
|
+
process.stdout.write(`No members in workspace ${workspaceId}.\n`);
|
|
8804
|
+
return exitAfterFlush(ExitCode.Ok);
|
|
8805
|
+
}
|
|
8806
|
+
for (const m of members) process.stdout.write(`${m.bizUserNo}\t${m.name}\t${m.email}\t${m.role}\t${m.status}\n`);
|
|
8807
|
+
return exitAfterFlush(ExitCode.Ok);
|
|
8808
|
+
} catch (err) {
|
|
8809
|
+
return emitFailureFromError(args.json, err);
|
|
8810
|
+
}
|
|
8811
|
+
}
|
|
8812
|
+
});
|
|
8813
|
+
function isValidEmail(email) {
|
|
8814
|
+
const at = email.indexOf("@");
|
|
8815
|
+
if (at <= 0) return false;
|
|
8816
|
+
const domain = email.slice(at + 1);
|
|
8817
|
+
return domain.length > 0 && domain.includes(".");
|
|
8818
|
+
}
|
|
8707
8819
|
const membersCommand = defineCommand({
|
|
8708
8820
|
meta: {
|
|
8709
8821
|
name: "members",
|
|
8710
|
-
description: "Inspect workspace members."
|
|
8822
|
+
description: "Inspect and manage workspace members."
|
|
8711
8823
|
},
|
|
8712
|
-
subCommands: {
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
workspace: {
|
|
8719
|
-
type: "string",
|
|
8720
|
-
description: "Workspace ID. Defaults to the selected workspace (`aitcc workspace use`)."
|
|
8824
|
+
subCommands: {
|
|
8825
|
+
ls: lsCommand$2,
|
|
8826
|
+
invite: defineCommand({
|
|
8827
|
+
meta: {
|
|
8828
|
+
name: "invite",
|
|
8829
|
+
description: "Invite a user to the workspace by email."
|
|
8721
8830
|
},
|
|
8722
|
-
|
|
8723
|
-
|
|
8724
|
-
|
|
8725
|
-
|
|
8726
|
-
|
|
8727
|
-
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
|
|
8731
|
-
|
|
8732
|
-
|
|
8733
|
-
|
|
8734
|
-
|
|
8735
|
-
|
|
8736
|
-
|
|
8737
|
-
|
|
8738
|
-
|
|
8739
|
-
|
|
8740
|
-
|
|
8741
|
-
|
|
8742
|
-
|
|
8743
|
-
|
|
8744
|
-
|
|
8745
|
-
|
|
8746
|
-
|
|
8831
|
+
args: {
|
|
8832
|
+
email: {
|
|
8833
|
+
type: "positional",
|
|
8834
|
+
required: true,
|
|
8835
|
+
description: "Email address of the user to invite."
|
|
8836
|
+
},
|
|
8837
|
+
role: {
|
|
8838
|
+
type: "string",
|
|
8839
|
+
description: "Role to assign (default: server default). Example: MEMBER."
|
|
8840
|
+
},
|
|
8841
|
+
workspace: {
|
|
8842
|
+
type: "string",
|
|
8843
|
+
description: "Workspace ID. Defaults to the selected workspace (`aitcc workspace use`)."
|
|
8844
|
+
},
|
|
8845
|
+
json: {
|
|
8846
|
+
type: "boolean",
|
|
8847
|
+
description: "Emit machine-readable JSON to stdout.",
|
|
8848
|
+
default: false
|
|
8849
|
+
}
|
|
8850
|
+
},
|
|
8851
|
+
async run({ args }) {
|
|
8852
|
+
const ctx = await resolveWorkspaceContext(args);
|
|
8853
|
+
if (!ctx) return;
|
|
8854
|
+
const { session, workspaceId } = ctx;
|
|
8855
|
+
printContextHeader(ctx, { json: args.json });
|
|
8856
|
+
const email = String(args.email).trim();
|
|
8857
|
+
if (!isValidEmail(email)) {
|
|
8858
|
+
const message = `<email> must be a valid email address (got ${JSON.stringify(email)})`;
|
|
8859
|
+
if (args.json) emitJson({
|
|
8860
|
+
ok: false,
|
|
8861
|
+
reason: "invalid-email",
|
|
8862
|
+
message
|
|
8747
8863
|
});
|
|
8864
|
+
else process.stderr.write(`${message}\n`);
|
|
8865
|
+
return exitAfterFlush(ExitCode.Usage);
|
|
8866
|
+
}
|
|
8867
|
+
const role = args.role ? String(args.role).trim() : void 0;
|
|
8868
|
+
try {
|
|
8869
|
+
await inviteMember(workspaceId, email, role, session.cookies);
|
|
8870
|
+
if (args.json) {
|
|
8871
|
+
emitJson({
|
|
8872
|
+
ok: true,
|
|
8873
|
+
workspaceId,
|
|
8874
|
+
email
|
|
8875
|
+
});
|
|
8876
|
+
return exitAfterFlush(ExitCode.Ok);
|
|
8877
|
+
}
|
|
8878
|
+
process.stdout.write(`Invited ${email} to workspace ${workspaceId}.\n`);
|
|
8748
8879
|
return exitAfterFlush(ExitCode.Ok);
|
|
8880
|
+
} catch (err) {
|
|
8881
|
+
return emitFailureFromError(args.json, err);
|
|
8749
8882
|
}
|
|
8750
|
-
|
|
8751
|
-
|
|
8883
|
+
}
|
|
8884
|
+
}),
|
|
8885
|
+
remove: defineCommand({
|
|
8886
|
+
meta: {
|
|
8887
|
+
name: "remove",
|
|
8888
|
+
description: "Remove a member from the workspace by their bizUserNo."
|
|
8889
|
+
},
|
|
8890
|
+
args: {
|
|
8891
|
+
bizUserNo: {
|
|
8892
|
+
type: "positional",
|
|
8893
|
+
required: true,
|
|
8894
|
+
description: "bizUserNo of the member to remove (from `aitcc members ls`)."
|
|
8895
|
+
},
|
|
8896
|
+
workspace: {
|
|
8897
|
+
type: "string",
|
|
8898
|
+
description: "Workspace ID. Defaults to the selected workspace (`aitcc workspace use`)."
|
|
8899
|
+
},
|
|
8900
|
+
json: {
|
|
8901
|
+
type: "boolean",
|
|
8902
|
+
description: "Emit machine-readable JSON to stdout.",
|
|
8903
|
+
default: false
|
|
8904
|
+
}
|
|
8905
|
+
},
|
|
8906
|
+
async run({ args }) {
|
|
8907
|
+
const ctx = await resolveWorkspaceContext(args);
|
|
8908
|
+
if (!ctx) return;
|
|
8909
|
+
const { session, workspaceId } = ctx;
|
|
8910
|
+
printContextHeader(ctx, { json: args.json });
|
|
8911
|
+
const rawId = String(args.bizUserNo);
|
|
8912
|
+
const parsed = parsePositiveInt$1(rawId);
|
|
8913
|
+
if (parsed === null) {
|
|
8914
|
+
const message = `<bizUserNo> must be a positive integer (got ${JSON.stringify(rawId)})`;
|
|
8915
|
+
if (args.json) emitJson({
|
|
8916
|
+
ok: false,
|
|
8917
|
+
reason: "invalid-id",
|
|
8918
|
+
message
|
|
8919
|
+
});
|
|
8920
|
+
else process.stderr.write(`${message}\n`);
|
|
8921
|
+
return exitAfterFlush(ExitCode.Usage);
|
|
8922
|
+
}
|
|
8923
|
+
try {
|
|
8924
|
+
await removeMember(workspaceId, parsed, session.cookies);
|
|
8925
|
+
if (args.json) {
|
|
8926
|
+
emitJson({
|
|
8927
|
+
ok: true,
|
|
8928
|
+
workspaceId,
|
|
8929
|
+
bizUserNo: parsed
|
|
8930
|
+
});
|
|
8931
|
+
return exitAfterFlush(ExitCode.Ok);
|
|
8932
|
+
}
|
|
8933
|
+
process.stdout.write(`Removed member ${parsed} from workspace ${workspaceId}.\n`);
|
|
8752
8934
|
return exitAfterFlush(ExitCode.Ok);
|
|
8935
|
+
} catch (err) {
|
|
8936
|
+
return emitFailureFromError(args.json, err);
|
|
8753
8937
|
}
|
|
8754
|
-
for (const m of members) process.stdout.write(`${m.bizUserNo}\t${m.name}\t${m.email}\t${m.role}\t${m.status}\n`);
|
|
8755
|
-
return exitAfterFlush(ExitCode.Ok);
|
|
8756
|
-
} catch (err) {
|
|
8757
|
-
return emitFailureFromError(args.json, err);
|
|
8758
8938
|
}
|
|
8759
|
-
}
|
|
8760
|
-
}
|
|
8939
|
+
})
|
|
8940
|
+
}
|
|
8761
8941
|
});
|
|
8762
8942
|
const BASE = "https://api-public.toss.im/api-public/v3/ipd-thor/api/v1";
|
|
8763
8943
|
async function fetchNotices(params, cookies, opts = {}) {
|
|
@@ -9151,7 +9331,7 @@ function resolveVersion() {
|
|
|
9151
9331
|
if (typeof injected === "string" && injected.length > 0) return injected;
|
|
9152
9332
|
} catch {}
|
|
9153
9333
|
try {
|
|
9154
|
-
return "0.1.
|
|
9334
|
+
return "0.1.28";
|
|
9155
9335
|
} catch {}
|
|
9156
9336
|
return "0.0.0-dev";
|
|
9157
9337
|
}
|