maeve-cli 0.9.0 → 0.10.0
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 +98 -9
- package/dist/index.js +716 -297
- package/examples/create-content.json +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { readFileSync as readFileSync2 } from "fs";
|
|
5
|
-
import {
|
|
4
|
+
import { readFileSync as readFileSync2, realpathSync } from "fs";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
6
|
import { Command } from "commander";
|
|
7
7
|
|
|
8
8
|
// src/commands/analytics.ts
|
|
@@ -42,7 +42,7 @@ import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync }
|
|
|
42
42
|
import { homedir } from "os";
|
|
43
43
|
import { dirname, join } from "path";
|
|
44
44
|
function getCredentialFilePath(env = process.env, platform = process.platform) {
|
|
45
|
-
const override = env.MAEVE_CLI_AUTH_FILE
|
|
45
|
+
const override = env.MAEVE_CLI_AUTH_FILE;
|
|
46
46
|
if (override) return override;
|
|
47
47
|
if (platform === "win32") {
|
|
48
48
|
return join(env.APPDATA || join(homedir(), "AppData", "Roaming"), "Maeve", "cli-auth.json");
|
|
@@ -52,30 +52,6 @@ function getCredentialFilePath(env = process.env, platform = process.platform) {
|
|
|
52
52
|
}
|
|
53
53
|
return join(env.XDG_CONFIG_HOME || join(homedir(), ".config"), "maeve", "cli-auth.json");
|
|
54
54
|
}
|
|
55
|
-
function getLegacyCredentialFilePath(env = process.env, platform = process.platform) {
|
|
56
|
-
if (env.MAEVE_CLI_AUTH_FILE ?? env.EZIBREEZY_CLI_AUTH_FILE) return void 0;
|
|
57
|
-
if (platform === "win32") {
|
|
58
|
-
return join(env.APPDATA || join(homedir(), "AppData", "Roaming"), "EziBreezy", "cli-auth.json");
|
|
59
|
-
}
|
|
60
|
-
if (platform === "darwin") {
|
|
61
|
-
return join(homedir(), "Library", "Application Support", "EziBreezy", "cli-auth.json");
|
|
62
|
-
}
|
|
63
|
-
return join(env.XDG_CONFIG_HOME || join(homedir(), ".config"), "ezibreezy", "cli-auth.json");
|
|
64
|
-
}
|
|
65
|
-
function migrateLegacyCredentialFile(env = process.env, platform = process.platform) {
|
|
66
|
-
const legacyPath = getLegacyCredentialFilePath(env, platform);
|
|
67
|
-
if (!legacyPath) return;
|
|
68
|
-
const targetPath = getCredentialFilePath(env, platform);
|
|
69
|
-
if (targetPath === legacyPath) return;
|
|
70
|
-
if (existsSync(targetPath) || !existsSync(legacyPath)) return;
|
|
71
|
-
try {
|
|
72
|
-
mkdirSync(dirname(targetPath), { recursive: true });
|
|
73
|
-
writeFileSync(targetPath, readFileSync(legacyPath, "utf8"), { mode: 384 });
|
|
74
|
-
restrictCredentialFilePermissions(targetPath);
|
|
75
|
-
rmSync(legacyPath, { force: true });
|
|
76
|
-
} catch {
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
55
|
function readCredentialFile(filePath = getCredentialFilePath()) {
|
|
80
56
|
if (!existsSync(filePath)) return { profiles: {} };
|
|
81
57
|
try {
|
|
@@ -512,7 +488,10 @@ function registerAnalyticsCommands(program) {
|
|
|
512
488
|
})
|
|
513
489
|
);
|
|
514
490
|
});
|
|
515
|
-
addConnectionOptions(program.command("analytics:report")).description("Generate an
|
|
491
|
+
addConnectionOptions(program.command("analytics:report")).description("Generate an team-plan analytics PDF report.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption(
|
|
492
|
+
"--provider <provider>",
|
|
493
|
+
"Report provider: instagram, facebook, youtube, tiktok, pinterest, or threads."
|
|
494
|
+
).requiredOption("--json <file>", "JSON file containing report integration IDs and report options.").requiredOption("--output <file>", "PDF output file.").option("--yes", "Confirm report generation.").action(
|
|
516
495
|
async (options, command) => {
|
|
517
496
|
if (!options.yes) {
|
|
518
497
|
throw new CliError("analytics:report requires --yes because PDF generation can be expensive.", {
|
|
@@ -714,16 +693,222 @@ function registerAuthCommands(program) {
|
|
|
714
693
|
});
|
|
715
694
|
}
|
|
716
695
|
|
|
717
|
-
// src/
|
|
696
|
+
// src/commands/boosts.ts
|
|
697
|
+
function registerBoostCommands(program) {
|
|
698
|
+
addConnectionOptions(program.command("boosts:list")).description("List boosts for a workspace. Requires team plan.").requiredOption("-w, --workspace <id>", "Workspace ID.").option("--content-ids <ids>", "Comma-separated content IDs to filter by.").option("--statuses <statuses>", "Comma-separated statuses: creating, active, paused, completed, error.").action(async (options, command) => {
|
|
699
|
+
const client = createApiClient(resolveConfig(command));
|
|
700
|
+
writeRawJson(
|
|
701
|
+
await client.request("GET", `/v1/workspaces/${options.workspace}/boosts`, {
|
|
702
|
+
query: { contentIds: options.contentIds, statuses: options.statuses }
|
|
703
|
+
})
|
|
704
|
+
);
|
|
705
|
+
});
|
|
706
|
+
addConnectionOptions(program.command("boosts:get")).description("Read one boost. Requires team plan.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <boostId>", "Boost ID.").action(async (options, command) => {
|
|
707
|
+
const client = createApiClient(resolveConfig(command));
|
|
708
|
+
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/boosts/${options.id}`));
|
|
709
|
+
});
|
|
710
|
+
addConnectionOptions(program.command("boosts:performance")).description("Refresh and read boost performance. Requires team plan.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <boostId>", "Boost ID.").action(async (options, command) => {
|
|
711
|
+
const client = createApiClient(resolveConfig(command));
|
|
712
|
+
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/boosts/${options.id}/performance`));
|
|
713
|
+
});
|
|
714
|
+
addConnectionOptions(program.command("boosts:ad-accounts")).description("List available Meta ad accounts for an integration. Requires team plan.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("-i, --integration <id>", "Integration ID.").action(async (options, command) => {
|
|
715
|
+
const client = createApiClient(resolveConfig(command));
|
|
716
|
+
writeRawJson(
|
|
717
|
+
await client.request("GET", `/v1/workspaces/${options.workspace}/boosts/ad-accounts/${options.integration}`)
|
|
718
|
+
);
|
|
719
|
+
});
|
|
720
|
+
addConnectionOptions(program.command("boosts:boosted-content-ids")).description("List active boosted content IDs. Requires team plan.").requiredOption("-w, --workspace <id>", "Workspace ID.").option("--content-ids <ids>", "Comma-separated content IDs to filter by.").action(async (options, command) => {
|
|
721
|
+
const client = createApiClient(resolveConfig(command));
|
|
722
|
+
writeRawJson(
|
|
723
|
+
await client.request("GET", `/v1/workspaces/${options.workspace}/boosts/boosted-content-ids`, {
|
|
724
|
+
query: { contentIds: options.contentIds }
|
|
725
|
+
})
|
|
726
|
+
);
|
|
727
|
+
});
|
|
728
|
+
addConnectionOptions(program.command("boosts:by-content")).description("Read the boost for one published content item. Requires team plan.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--content <contentId>", "Published content ID.").action(async (options, command) => {
|
|
729
|
+
const client = createApiClient(resolveConfig(command));
|
|
730
|
+
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/boosts/content/${options.content}`));
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
// src/campaign-schema.ts
|
|
718
735
|
import { z as z2 } from "zod";
|
|
719
736
|
var uuid2 = z2.string().uuid();
|
|
720
|
-
var
|
|
721
|
-
var
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
var
|
|
726
|
-
var
|
|
737
|
+
var hexColor = z2.string().regex(/^#?(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/, "Color must be a hex color, e.g. #2563EB.");
|
|
738
|
+
var isoDate = z2.string().refine(
|
|
739
|
+
(value) => /^\d{4}-\d{2}-\d{2}([Tt]\d{2}:\d{2}(:\d{2}(\.\d+)?)?([Zz]|[+-]\d{2}:?\d{2})?)?$/.test(value) && !Number.isNaN(Date.parse(value)),
|
|
740
|
+
{ message: "Must be an ISO 8601 date string, e.g. 2026-01-01 or 2026-01-01T00:00:00Z." }
|
|
741
|
+
);
|
|
742
|
+
var budgetAmount = z2.string().regex(/^\d+(\.\d{1,2})?$/, 'Budget must be a decimal string like "1000" or "1000.50".');
|
|
743
|
+
var currencyCode = z2.string().regex(/^[A-Z]{3}$/, 'Currency must be a 3-letter ISO code like "USD".');
|
|
744
|
+
var campaignBaseShape = {
|
|
745
|
+
name: z2.string().min(1).max(160),
|
|
746
|
+
color: hexColor.nullable().optional(),
|
|
747
|
+
goal: z2.string().max(500).nullable().optional(),
|
|
748
|
+
description: z2.string().max(2e4).nullable().optional(),
|
|
749
|
+
startDate: isoDate,
|
|
750
|
+
endDate: isoDate,
|
|
751
|
+
targetPlatforms: z2.array(z2.string()).max(50).optional(),
|
|
752
|
+
estimatedBudget: budgetAmount.nullable().optional(),
|
|
753
|
+
actualBudget: budgetAmount.nullable().optional(),
|
|
754
|
+
budgetCurrency: currencyCode.nullable().optional()
|
|
755
|
+
};
|
|
756
|
+
var createCampaignSchema = z2.object(campaignBaseShape).strict();
|
|
757
|
+
var updateCampaignSchema = z2.object({
|
|
758
|
+
...campaignBaseShape,
|
|
759
|
+
// The update DTO drops @IsNotEmpty on name and makes the dates optional.
|
|
760
|
+
name: z2.string().max(160).optional(),
|
|
761
|
+
startDate: isoDate.optional(),
|
|
762
|
+
endDate: isoDate.optional()
|
|
763
|
+
}).strict().refine((payload) => Object.keys(payload).length > 0, {
|
|
764
|
+
message: "Campaign update payload must include at least one field."
|
|
765
|
+
});
|
|
766
|
+
var createCampaignPhaseSchema = z2.object({
|
|
767
|
+
name: z2.string().min(1).max(120),
|
|
768
|
+
color: hexColor.nullable().optional(),
|
|
769
|
+
startDate: isoDate.nullable().optional(),
|
|
770
|
+
endDate: isoDate.nullable().optional(),
|
|
771
|
+
sortOrder: z2.number().int().min(0).optional()
|
|
772
|
+
}).strict();
|
|
773
|
+
var updateCampaignPhaseSchema = z2.object({
|
|
774
|
+
name: z2.string().max(120).optional(),
|
|
775
|
+
color: hexColor.nullable().optional(),
|
|
776
|
+
startDate: isoDate.nullable().optional(),
|
|
777
|
+
endDate: isoDate.nullable().optional(),
|
|
778
|
+
sortOrder: z2.number().int().min(0).optional()
|
|
779
|
+
}).strict().refine((payload) => Object.keys(payload).length > 0, {
|
|
780
|
+
message: "Campaign phase update payload must include at least one field."
|
|
781
|
+
});
|
|
782
|
+
var saveCampaignPhaseDraftSchema = z2.object({
|
|
783
|
+
id: uuid2.optional(),
|
|
784
|
+
name: z2.string().min(1).max(120),
|
|
785
|
+
color: hexColor.nullable().optional(),
|
|
786
|
+
startDate: isoDate.nullable().optional(),
|
|
787
|
+
endDate: isoDate.nullable().optional()
|
|
788
|
+
}).strict();
|
|
789
|
+
var saveCampaignPhasesSchema = z2.object({
|
|
790
|
+
phases: z2.array(saveCampaignPhaseDraftSchema).max(100)
|
|
791
|
+
}).strict();
|
|
792
|
+
|
|
793
|
+
// src/commands/campaigns.ts
|
|
794
|
+
function registerCampaignCommands(program) {
|
|
795
|
+
addConnectionOptions(program.command("campaigns:list")).description("List campaigns for a workspace.").requiredOption("-w, --workspace <id>", "Workspace ID.").option("--search <text>", "Case-insensitive campaign name search.").option("--include-archived", "Include archived campaigns.").option("--include-phases", "Include campaign phases on each campaign.").action(async (options, command) => {
|
|
796
|
+
const client = createApiClient(resolveConfig(command));
|
|
797
|
+
writeRawJson(
|
|
798
|
+
await client.request("GET", `/v1/workspaces/${options.workspace}/campaigns`, {
|
|
799
|
+
query: {
|
|
800
|
+
search: options.search,
|
|
801
|
+
includeArchived: options.includeArchived,
|
|
802
|
+
includePhases: options.includePhases
|
|
803
|
+
}
|
|
804
|
+
})
|
|
805
|
+
);
|
|
806
|
+
});
|
|
807
|
+
addConnectionOptions(program.command("campaigns:get")).description("Get one campaign.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <campaignId>", "Campaign ID.").action(async (options, command) => {
|
|
808
|
+
const client = createApiClient(resolveConfig(command));
|
|
809
|
+
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/campaigns/${options.id}`));
|
|
810
|
+
});
|
|
811
|
+
addConnectionOptions(program.command("campaigns:content")).description("List compact content for one campaign.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <campaignId>", "Campaign ID.").option("--limit <number>", "Maximum rows to return.").option("--offset <number>", "Rows to skip.").option("--phase <phaseId>", 'Phase ID, or "none" for content without a phase.').option("--status <status>", "Content status filter.").option("--platform <platform>", "Integration platform filter.").option("--sort-direction <direction>", "Primary date sort direction: asc or desc.").action(async (options, command) => {
|
|
812
|
+
const client = createApiClient(resolveConfig(command));
|
|
813
|
+
writeRawJson(
|
|
814
|
+
await client.request("GET", `/v1/workspaces/${options.workspace}/campaigns/${options.id}/content`, {
|
|
815
|
+
query: {
|
|
816
|
+
limit: options.limit,
|
|
817
|
+
offset: options.offset,
|
|
818
|
+
phase: options.phase,
|
|
819
|
+
status: options.status,
|
|
820
|
+
platform: options.platform,
|
|
821
|
+
sortDirection: options.sortDirection
|
|
822
|
+
}
|
|
823
|
+
})
|
|
824
|
+
);
|
|
825
|
+
});
|
|
826
|
+
addConnectionOptions(program.command("campaigns:create")).description("Create a campaign from a JSON payload file.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--json <file>", "JSON file containing the campaign payload.").action(async (options, command) => {
|
|
827
|
+
const payload = createCampaignSchema.parse(await readJsonFile(options.json));
|
|
828
|
+
const client = createApiClient(resolveConfig(command));
|
|
829
|
+
writeRawJson(
|
|
830
|
+
await client.request("POST", `/v1/workspaces/${options.workspace}/campaigns`, {
|
|
831
|
+
body: payload
|
|
832
|
+
})
|
|
833
|
+
);
|
|
834
|
+
});
|
|
835
|
+
addConnectionOptions(program.command("campaigns:update")).description("Update a campaign from a JSON payload file.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <campaignId>", "Campaign ID.").requiredOption("--json <file>", "JSON file containing fields to update.").action(async (options, command) => {
|
|
836
|
+
const payload = updateCampaignSchema.parse(await readJsonFile(options.json));
|
|
837
|
+
const client = createApiClient(resolveConfig(command));
|
|
838
|
+
writeRawJson(
|
|
839
|
+
await client.request("PATCH", `/v1/workspaces/${options.workspace}/campaigns/${options.id}`, {
|
|
840
|
+
body: payload
|
|
841
|
+
})
|
|
842
|
+
);
|
|
843
|
+
});
|
|
844
|
+
addConnectionOptions(program.command("campaigns:archive")).description("Archive a campaign.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <campaignId>", "Campaign ID.").action(async (options, command) => {
|
|
845
|
+
const client = createApiClient(resolveConfig(command));
|
|
846
|
+
writeRawJson(await client.request("POST", `/v1/workspaces/${options.workspace}/campaigns/${options.id}/archive`));
|
|
847
|
+
});
|
|
848
|
+
addConnectionOptions(program.command("campaigns:restore")).description("Restore an archived campaign.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <campaignId>", "Campaign ID.").action(async (options, command) => {
|
|
849
|
+
const client = createApiClient(resolveConfig(command));
|
|
850
|
+
writeRawJson(await client.request("POST", `/v1/workspaces/${options.workspace}/campaigns/${options.id}/restore`));
|
|
851
|
+
});
|
|
852
|
+
addConnectionOptions(program.command("campaigns:phases:list")).description("List phases for one campaign.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <campaignId>", "Campaign ID.").action(async (options, command) => {
|
|
853
|
+
const client = createApiClient(resolveConfig(command));
|
|
854
|
+
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/campaigns/${options.id}/phases`));
|
|
855
|
+
});
|
|
856
|
+
addConnectionOptions(program.command("campaigns:phases:create")).description("Create a campaign phase from a JSON payload file.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <campaignId>", "Campaign ID.").requiredOption("--json <file>", "JSON file containing the campaign phase payload.").action(async (options, command) => {
|
|
857
|
+
const payload = createCampaignPhaseSchema.parse(await readJsonFile(options.json));
|
|
858
|
+
const client = createApiClient(resolveConfig(command));
|
|
859
|
+
writeRawJson(
|
|
860
|
+
await client.request("POST", `/v1/workspaces/${options.workspace}/campaigns/${options.id}/phases`, {
|
|
861
|
+
body: payload
|
|
862
|
+
})
|
|
863
|
+
);
|
|
864
|
+
});
|
|
865
|
+
addConnectionOptions(program.command("campaigns:phases:replace")).description("Replace all phases for one campaign from a JSON payload file.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <campaignId>", "Campaign ID.").requiredOption("--json <file>", "JSON file containing the complete phases array.").action(async (options, command) => {
|
|
866
|
+
const payload = saveCampaignPhasesSchema.parse(await readJsonFile(options.json));
|
|
867
|
+
const client = createApiClient(resolveConfig(command));
|
|
868
|
+
writeRawJson(
|
|
869
|
+
await client.request("PUT", `/v1/workspaces/${options.workspace}/campaigns/${options.id}/phases`, {
|
|
870
|
+
body: payload
|
|
871
|
+
})
|
|
872
|
+
);
|
|
873
|
+
});
|
|
874
|
+
addConnectionOptions(program.command("campaigns:phases:update")).description("Update one campaign phase from a JSON payload file.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <campaignId>", "Campaign ID.").requiredOption("--phase-id <phaseId>", "Campaign phase ID.").requiredOption("--json <file>", "JSON file containing fields to update.").action(async (options, command) => {
|
|
875
|
+
const payload = updateCampaignPhaseSchema.parse(await readJsonFile(options.json));
|
|
876
|
+
const client = createApiClient(resolveConfig(command));
|
|
877
|
+
writeRawJson(
|
|
878
|
+
await client.request(
|
|
879
|
+
"PATCH",
|
|
880
|
+
`/v1/workspaces/${options.workspace}/campaigns/${options.id}/phases/${options.phaseId}`,
|
|
881
|
+
{
|
|
882
|
+
body: payload
|
|
883
|
+
}
|
|
884
|
+
)
|
|
885
|
+
);
|
|
886
|
+
});
|
|
887
|
+
addConnectionOptions(program.command("campaigns:phases:delete")).description("Delete one campaign phase.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <campaignId>", "Campaign ID.").requiredOption("--phase-id <phaseId>", "Campaign phase ID.").option("--yes", "Confirm deleting the campaign phase.").action(async (options, command) => {
|
|
888
|
+
if (!options.yes) {
|
|
889
|
+
throw new CliError("campaigns:phases:delete requires --yes because it permanently removes the phase.", {
|
|
890
|
+
code: "INVALID_OPTIONS"
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
const client = createApiClient(resolveConfig(command));
|
|
894
|
+
await client.request(
|
|
895
|
+
"DELETE",
|
|
896
|
+
`/v1/workspaces/${options.workspace}/campaigns/${options.id}/phases/${options.phaseId}`
|
|
897
|
+
);
|
|
898
|
+
writeJson({ campaignId: options.id, phaseId: options.phaseId, deleted: true });
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// src/approval-schema.ts
|
|
903
|
+
import { z as z3 } from "zod";
|
|
904
|
+
var uuid3 = z3.string().uuid();
|
|
905
|
+
var nonEmptyString = z3.string().min(1);
|
|
906
|
+
var nullableString = z3.string().nullable().optional();
|
|
907
|
+
var approvalPolicy = z3.enum(["any", "all"]);
|
|
908
|
+
var workflowMode = z3.enum(["client", "internal_client"]);
|
|
909
|
+
var attachmentContentType = z3.enum(["image/jpeg", "image/png", "image/gif", "image/webp"]);
|
|
910
|
+
var reviewLifecyclePhase = z3.enum(["none", "internal", "client"]);
|
|
911
|
+
var reviewLifecycleState = z3.enum([
|
|
727
912
|
"none",
|
|
728
913
|
"internal_review_pending",
|
|
729
914
|
"internal_review_approved",
|
|
@@ -739,8 +924,8 @@ var reviewLifecycleState = z2.enum([
|
|
|
739
924
|
"client_review_cancelled",
|
|
740
925
|
"client_review_expired"
|
|
741
926
|
]);
|
|
742
|
-
var reviewLifecycleActor =
|
|
743
|
-
var reviewLifecycleNextAction =
|
|
927
|
+
var reviewLifecycleActor = z3.enum(["none", "agency", "author", "approver", "client", "system"]);
|
|
928
|
+
var reviewLifecycleNextAction = z3.enum([
|
|
744
929
|
"none",
|
|
745
930
|
"request_internal_approval",
|
|
746
931
|
"complete_internal_review",
|
|
@@ -754,7 +939,7 @@ var reviewLifecycleNextAction = z2.enum([
|
|
|
754
939
|
"publish",
|
|
755
940
|
"set_intended_publish_time"
|
|
756
941
|
]);
|
|
757
|
-
var reviewLifecycleBlockerCode =
|
|
942
|
+
var reviewLifecycleBlockerCode = z3.enum([
|
|
758
943
|
"missing_schedule",
|
|
759
944
|
"internal_approval_pending",
|
|
760
945
|
"internal_changes_requested",
|
|
@@ -767,49 +952,49 @@ var reviewLifecycleBlockerCode = z2.enum([
|
|
|
767
952
|
"missing_review_snapshot",
|
|
768
953
|
"review_snapshot_hash_mismatch"
|
|
769
954
|
]);
|
|
770
|
-
var reviewLifecycleSharedVersionStatus =
|
|
955
|
+
var reviewLifecycleSharedVersionStatus = z3.enum([
|
|
771
956
|
"not_shared",
|
|
772
957
|
"current",
|
|
773
958
|
"stale",
|
|
774
959
|
"missing_snapshot",
|
|
775
960
|
"hash_mismatch"
|
|
776
961
|
]);
|
|
777
|
-
var clientReviewBatchStatus =
|
|
778
|
-
var clientReviewItemStatus =
|
|
779
|
-
var approvalRequestSchema =
|
|
780
|
-
approverIds:
|
|
962
|
+
var clientReviewBatchStatus = z3.enum(["open", "waiting_internal", "pending", "completed", "expired", "cancelled"]);
|
|
963
|
+
var clientReviewItemStatus = z3.enum(["pending", "approved", "changes_requested", "admin_overridden", "cancelled"]);
|
|
964
|
+
var approvalRequestSchema = z3.object({
|
|
965
|
+
approverIds: z3.array(uuid3).min(1),
|
|
781
966
|
policy: approvalPolicy
|
|
782
967
|
});
|
|
783
|
-
var approvalDecisionSchema =
|
|
784
|
-
decision:
|
|
785
|
-
override:
|
|
786
|
-
reason:
|
|
968
|
+
var approvalDecisionSchema = z3.object({
|
|
969
|
+
decision: z3.enum(["approve", "reject"]),
|
|
970
|
+
override: z3.boolean().optional(),
|
|
971
|
+
reason: z3.string().max(2e3).optional()
|
|
787
972
|
}).refine((payload) => !(payload.decision === "reject" || payload.override === true) || Boolean(payload.reason?.trim()), {
|
|
788
973
|
message: "reason is required when rejecting or using override."
|
|
789
974
|
});
|
|
790
|
-
var approvalCommentSchema =
|
|
791
|
-
body:
|
|
792
|
-
attachmentId:
|
|
975
|
+
var approvalCommentSchema = z3.object({
|
|
976
|
+
body: z3.string().max(2e3).optional(),
|
|
977
|
+
attachmentId: uuid3.optional()
|
|
793
978
|
}).refine((payload) => Boolean(payload.body?.trim() || payload.attachmentId), {
|
|
794
979
|
message: "Comment payload must include body or attachmentId."
|
|
795
980
|
});
|
|
796
|
-
var approvalAttachmentInitSchema =
|
|
797
|
-
contentId:
|
|
798
|
-
batchId:
|
|
799
|
-
audience:
|
|
981
|
+
var approvalAttachmentInitSchema = z3.object({
|
|
982
|
+
contentId: uuid3,
|
|
983
|
+
batchId: uuid3.optional(),
|
|
984
|
+
audience: z3.enum(["internal", "client"]),
|
|
800
985
|
filename: nonEmptyString.max(255),
|
|
801
986
|
contentType: attachmentContentType,
|
|
802
|
-
fileSize:
|
|
987
|
+
fileSize: z3.number().int().min(1)
|
|
803
988
|
});
|
|
804
|
-
var approvalReactionSchema =
|
|
989
|
+
var approvalReactionSchema = z3.object({
|
|
805
990
|
emoji: nonEmptyString.max(16)
|
|
806
991
|
});
|
|
807
|
-
var clientReviewerSchema =
|
|
992
|
+
var clientReviewerSchema = z3.object({
|
|
808
993
|
name: nonEmptyString.max(255),
|
|
809
|
-
email:
|
|
994
|
+
email: z3.string().email().max(320)
|
|
810
995
|
});
|
|
811
|
-
var clientReviewConfigSchema =
|
|
812
|
-
reviewers:
|
|
996
|
+
var clientReviewConfigSchema = z3.object({
|
|
997
|
+
reviewers: z3.array(clientReviewerSchema).min(1),
|
|
813
998
|
policy: approvalPolicy,
|
|
814
999
|
expiresAt: nullableString,
|
|
815
1000
|
inviteNote: nullableString.refine((value) => value === void 0 || value === null || value.length <= 2e3, {
|
|
@@ -819,79 +1004,79 @@ var clientReviewConfigSchema = z2.object({
|
|
|
819
1004
|
message: "batchLabel must be 255 characters or fewer."
|
|
820
1005
|
})
|
|
821
1006
|
});
|
|
822
|
-
var internalReviewConfigSchema =
|
|
823
|
-
approverIds:
|
|
1007
|
+
var internalReviewConfigSchema = z3.object({
|
|
1008
|
+
approverIds: z3.array(uuid3).min(1),
|
|
824
1009
|
policy: approvalPolicy
|
|
825
1010
|
});
|
|
826
|
-
var clientReviewCreateSchema =
|
|
827
|
-
contentIds:
|
|
1011
|
+
var clientReviewCreateSchema = z3.object({
|
|
1012
|
+
contentIds: z3.array(uuid3).min(1),
|
|
828
1013
|
workflowMode,
|
|
829
1014
|
client: clientReviewConfigSchema,
|
|
830
1015
|
internal: internalReviewConfigSchema.optional()
|
|
831
1016
|
}).refine((payload) => payload.workflowMode !== "internal_client" || Boolean(payload.internal), {
|
|
832
1017
|
message: "internal is required when workflowMode is internal_client."
|
|
833
1018
|
});
|
|
834
|
-
var clientReviewPostMutationSchema =
|
|
835
|
-
contentId:
|
|
1019
|
+
var clientReviewPostMutationSchema = z3.object({
|
|
1020
|
+
contentId: uuid3
|
|
836
1021
|
});
|
|
837
|
-
var clientReviewOverrideSchema =
|
|
838
|
-
contentId:
|
|
1022
|
+
var clientReviewOverrideSchema = z3.object({
|
|
1023
|
+
contentId: uuid3,
|
|
839
1024
|
reason: nonEmptyString.max(2e3)
|
|
840
1025
|
});
|
|
841
|
-
var clientReviewParticipantUpdateSchema =
|
|
842
|
-
participantId:
|
|
843
|
-
email:
|
|
844
|
-
name:
|
|
1026
|
+
var clientReviewParticipantUpdateSchema = z3.object({
|
|
1027
|
+
participantId: uuid3,
|
|
1028
|
+
email: z3.string().email().max(320),
|
|
1029
|
+
name: z3.string().max(255).optional()
|
|
845
1030
|
});
|
|
846
|
-
var clientReviewCommentSchema =
|
|
847
|
-
contentId:
|
|
848
|
-
body:
|
|
849
|
-
attachmentId:
|
|
1031
|
+
var clientReviewCommentSchema = z3.object({
|
|
1032
|
+
contentId: uuid3,
|
|
1033
|
+
body: z3.string().max(2e3).optional(),
|
|
1034
|
+
attachmentId: uuid3.optional()
|
|
850
1035
|
}).refine((payload) => Boolean(payload.body?.trim() || payload.attachmentId), {
|
|
851
1036
|
message: "Comment payload must include body or attachmentId."
|
|
852
1037
|
});
|
|
853
|
-
var reviewLifecycleSchema =
|
|
1038
|
+
var reviewLifecycleSchema = z3.object({
|
|
854
1039
|
phase: reviewLifecyclePhase,
|
|
855
1040
|
state: reviewLifecycleState,
|
|
856
1041
|
actor: reviewLifecycleActor,
|
|
857
1042
|
nextAction: reviewLifecycleNextAction,
|
|
858
|
-
blocksPublishing:
|
|
859
|
-
blockers:
|
|
860
|
-
|
|
1043
|
+
blocksPublishing: z3.boolean(),
|
|
1044
|
+
blockers: z3.array(
|
|
1045
|
+
z3.object({
|
|
861
1046
|
code: reviewLifecycleBlockerCode,
|
|
862
|
-
message:
|
|
863
|
-
details:
|
|
1047
|
+
message: z3.string().optional(),
|
|
1048
|
+
details: z3.record(z3.string(), z3.unknown()).optional()
|
|
864
1049
|
}).strict()
|
|
865
1050
|
),
|
|
866
|
-
progress:
|
|
1051
|
+
progress: z3.object({
|
|
867
1052
|
policy: approvalPolicy.nullable(),
|
|
868
|
-
requestedCount:
|
|
869
|
-
approvedCount:
|
|
870
|
-
changesRequestedCount:
|
|
1053
|
+
requestedCount: z3.number().int().min(0),
|
|
1054
|
+
approvedCount: z3.number().int().min(0),
|
|
1055
|
+
changesRequestedCount: z3.number().int().min(0).optional()
|
|
871
1056
|
}).strict().nullable().optional(),
|
|
872
|
-
clientReview:
|
|
873
|
-
batchId:
|
|
874
|
-
itemId:
|
|
1057
|
+
clientReview: z3.object({
|
|
1058
|
+
batchId: uuid3.nullable(),
|
|
1059
|
+
itemId: uuid3.nullable(),
|
|
875
1060
|
batchStatus: clientReviewBatchStatus.nullable(),
|
|
876
1061
|
itemStatus: clientReviewItemStatus.nullable(),
|
|
877
|
-
isClientFacing:
|
|
1062
|
+
isClientFacing: z3.boolean(),
|
|
878
1063
|
sharedVersionStatus: reviewLifecycleSharedVersionStatus,
|
|
879
|
-
hasSentLinkBefore:
|
|
880
|
-
readyForClientSend:
|
|
1064
|
+
hasSentLinkBefore: z3.boolean().optional(),
|
|
1065
|
+
readyForClientSend: z3.boolean().optional()
|
|
881
1066
|
}).strict().nullable().optional(),
|
|
882
|
-
labels:
|
|
883
|
-
phase:
|
|
884
|
-
state:
|
|
885
|
-
nextAction:
|
|
1067
|
+
labels: z3.object({
|
|
1068
|
+
phase: z3.string().optional(),
|
|
1069
|
+
state: z3.string().optional(),
|
|
1070
|
+
nextAction: z3.string().optional()
|
|
886
1071
|
}).strict().optional()
|
|
887
1072
|
}).strict();
|
|
888
|
-
var reviewLifecycleResponseSchema =
|
|
1073
|
+
var reviewLifecycleResponseSchema = z3.object({
|
|
889
1074
|
reviewLifecycle: reviewLifecycleSchema.nullable().optional()
|
|
890
1075
|
}).passthrough();
|
|
891
1076
|
|
|
892
1077
|
// src/commands/client-reviews.ts
|
|
893
1078
|
function registerClientReviewCommands(program) {
|
|
894
|
-
addConnectionOptions(program.command("client-reviews:create")).description("Create a client review batch. Requires
|
|
1079
|
+
addConnectionOptions(program.command("client-reviews:create")).description("Create a client review batch. Requires team plan and client review send capability.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--json <file>", "JSON file containing the client review batch payload.").action(async (options, command) => {
|
|
895
1080
|
const payload = clientReviewCreateSchema.parse(await readJsonFile(options.json));
|
|
896
1081
|
const client = createApiClient(resolveConfig(command));
|
|
897
1082
|
writeRawJson(
|
|
@@ -901,7 +1086,7 @@ function registerClientReviewCommands(program) {
|
|
|
901
1086
|
);
|
|
902
1087
|
});
|
|
903
1088
|
addConnectionOptions(program.command("client-reviews:open")).description(
|
|
904
|
-
"List open client review batches that have not had links sent. Requires
|
|
1089
|
+
"List open client review batches that have not had links sent. Requires team plan and client review read capability."
|
|
905
1090
|
).requiredOption("-w, --workspace <id>", "Workspace ID.").option("--workflow-mode <mode>", "Workflow mode: client or internal_client.").action(async (options, command) => {
|
|
906
1091
|
const client = createApiClient(resolveConfig(command));
|
|
907
1092
|
writeRawJson(
|
|
@@ -910,7 +1095,7 @@ function registerClientReviewCommands(program) {
|
|
|
910
1095
|
})
|
|
911
1096
|
);
|
|
912
1097
|
});
|
|
913
|
-
addConnectionOptions(program.command("client-reviews:get")).description("Get one client review batch. Requires
|
|
1098
|
+
addConnectionOptions(program.command("client-reviews:get")).description("Get one client review batch. Requires team plan.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--batch <batchId>", "Client review batch ID.").action(async (options, command) => {
|
|
914
1099
|
const client = createApiClient(resolveConfig(command));
|
|
915
1100
|
writeRawJson(
|
|
916
1101
|
await client.request(
|
|
@@ -919,7 +1104,7 @@ function registerClientReviewCommands(program) {
|
|
|
919
1104
|
)
|
|
920
1105
|
);
|
|
921
1106
|
});
|
|
922
|
-
addConnectionOptions(program.command("client-reviews:add-post")).description("Add content to an open client review batch. Requires
|
|
1107
|
+
addConnectionOptions(program.command("client-reviews:add-post")).description("Add content to an open client review batch. Requires team plan and client review send capability.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--batch <batchId>", "Client review batch ID.").requiredOption("--json <file>", "JSON file containing contentId.").action(async (options, command) => {
|
|
923
1108
|
const payload = clientReviewPostMutationSchema.parse(await readJsonFile(options.json));
|
|
924
1109
|
const client = createApiClient(resolveConfig(command));
|
|
925
1110
|
writeRawJson(
|
|
@@ -931,7 +1116,7 @@ function registerClientReviewCommands(program) {
|
|
|
931
1116
|
);
|
|
932
1117
|
});
|
|
933
1118
|
addConnectionOptions(program.command("client-reviews:remove-post")).description(
|
|
934
|
-
"Remove content from an open client review batch. Requires
|
|
1119
|
+
"Remove content from an open client review batch. Requires team plan and client review send capability."
|
|
935
1120
|
).requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--batch <batchId>", "Client review batch ID.").requiredOption("--json <file>", "JSON file containing contentId.").action(async (options, command) => {
|
|
936
1121
|
const payload = clientReviewPostMutationSchema.parse(await readJsonFile(options.json));
|
|
937
1122
|
const client = createApiClient(resolveConfig(command));
|
|
@@ -944,7 +1129,7 @@ function registerClientReviewCommands(program) {
|
|
|
944
1129
|
);
|
|
945
1130
|
});
|
|
946
1131
|
addConnectionOptions(program.command("client-reviews:send")).description(
|
|
947
|
-
"Send a client review batch. Requires
|
|
1132
|
+
"Send a client review batch. Requires team plan and client review send capability; may notify reviewers."
|
|
948
1133
|
).requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--batch <batchId>", "Client review batch ID.").option("--yes", "Confirm reviewer notifications.").action(async (options, command) => {
|
|
949
1134
|
if (!options.yes) {
|
|
950
1135
|
throw new CliError("client-reviews:send requires --yes because it may notify reviewers.", {
|
|
@@ -960,7 +1145,7 @@ function registerClientReviewCommands(program) {
|
|
|
960
1145
|
);
|
|
961
1146
|
});
|
|
962
1147
|
addConnectionOptions(program.command("client-reviews:resend")).description(
|
|
963
|
-
"Resend a client review batch. Requires
|
|
1148
|
+
"Resend a client review batch. Requires team plan and client review send capability; may notify reviewers."
|
|
964
1149
|
).requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--batch <batchId>", "Client review batch ID.").option("--yes", "Confirm reviewer notifications.").action(async (options, command) => {
|
|
965
1150
|
if (!options.yes) {
|
|
966
1151
|
throw new CliError("client-reviews:resend requires --yes because it may notify reviewers.", {
|
|
@@ -975,7 +1160,7 @@ function registerClientReviewCommands(program) {
|
|
|
975
1160
|
)
|
|
976
1161
|
);
|
|
977
1162
|
});
|
|
978
|
-
addConnectionOptions(program.command("client-reviews:cancel")).description("Cancel a client review batch. Requires
|
|
1163
|
+
addConnectionOptions(program.command("client-reviews:cancel")).description("Cancel a client review batch. Requires team plan and client review send capability.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--batch <batchId>", "Client review batch ID.").action(async (options, command) => {
|
|
979
1164
|
const client = createApiClient(resolveConfig(command));
|
|
980
1165
|
writeRawJson(
|
|
981
1166
|
await client.request(
|
|
@@ -984,7 +1169,7 @@ function registerClientReviewCommands(program) {
|
|
|
984
1169
|
)
|
|
985
1170
|
);
|
|
986
1171
|
});
|
|
987
|
-
addConnectionOptions(program.command("client-reviews:override")).description("Override a client review batch item. Requires
|
|
1172
|
+
addConnectionOptions(program.command("client-reviews:override")).description("Override a client review batch item. Requires team plan and content review override capability.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--batch <batchId>", "Client review batch ID.").requiredOption("--json <file>", "JSON file containing contentId and reason.").action(async (options, command) => {
|
|
988
1173
|
const payload = clientReviewOverrideSchema.parse(await readJsonFile(options.json));
|
|
989
1174
|
const client = createApiClient(resolveConfig(command));
|
|
990
1175
|
writeRawJson(
|
|
@@ -995,7 +1180,7 @@ function registerClientReviewCommands(program) {
|
|
|
995
1180
|
)
|
|
996
1181
|
);
|
|
997
1182
|
});
|
|
998
|
-
addConnectionOptions(program.command("client-reviews:update-participant")).description("Update a client review participant. Requires
|
|
1183
|
+
addConnectionOptions(program.command("client-reviews:update-participant")).description("Update a client review participant. Requires team plan and client review send capability.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--batch <batchId>", "Client review batch ID.").requiredOption("--json <file>", "JSON file containing participantId and email.").action(async (options, command) => {
|
|
999
1184
|
const payload = clientReviewParticipantUpdateSchema.parse(await readJsonFile(options.json));
|
|
1000
1185
|
const client = createApiClient(resolveConfig(command));
|
|
1001
1186
|
writeRawJson(
|
|
@@ -1007,7 +1192,7 @@ function registerClientReviewCommands(program) {
|
|
|
1007
1192
|
);
|
|
1008
1193
|
});
|
|
1009
1194
|
addConnectionOptions(program.command("client-reviews:comment")).description(
|
|
1010
|
-
"Add an internal client-review thread comment. Requires
|
|
1195
|
+
"Add an internal client-review thread comment. Requires team plan and client review comment capability."
|
|
1011
1196
|
).requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--batch <batchId>", "Client review batch ID.").requiredOption("--json <file>", "JSON file containing contentId and body or attachmentId.").action(async (options, command) => {
|
|
1012
1197
|
const payload = clientReviewCommentSchema.parse(await readJsonFile(options.json));
|
|
1013
1198
|
const client = createApiClient(resolveConfig(command));
|
|
@@ -1025,9 +1210,9 @@ function registerClientReviewCommands(program) {
|
|
|
1025
1210
|
import { randomUUID } from "crypto";
|
|
1026
1211
|
|
|
1027
1212
|
// src/content-schema.ts
|
|
1028
|
-
import { z as
|
|
1029
|
-
var
|
|
1030
|
-
var isoWithTimezone =
|
|
1213
|
+
import { z as z4 } from "zod";
|
|
1214
|
+
var uuid4 = z4.string().uuid();
|
|
1215
|
+
var isoWithTimezone = z4.string().refine(
|
|
1031
1216
|
(value) => {
|
|
1032
1217
|
const date = new Date(value);
|
|
1033
1218
|
return !Number.isNaN(date.getTime()) && (value.endsWith("Z") || /[+-]\d{2}:\d{2}$/.test(value));
|
|
@@ -1036,42 +1221,42 @@ var isoWithTimezone = z3.string().refine(
|
|
|
1036
1221
|
message: "scheduledAt must be an ISO8601 date string with explicit timezone, e.g. 2026-05-01T10:00:00Z."
|
|
1037
1222
|
}
|
|
1038
1223
|
);
|
|
1039
|
-
var captionOverridesSchema =
|
|
1040
|
-
x:
|
|
1041
|
-
linkedin:
|
|
1042
|
-
youtube:
|
|
1043
|
-
instagram:
|
|
1044
|
-
facebook:
|
|
1045
|
-
threads:
|
|
1046
|
-
tiktok:
|
|
1047
|
-
pinterest:
|
|
1224
|
+
var captionOverridesSchema = z4.object({
|
|
1225
|
+
x: z4.string().max(25e3).optional(),
|
|
1226
|
+
linkedin: z4.string().max(25e3).optional(),
|
|
1227
|
+
youtube: z4.string().max(25e3).optional(),
|
|
1228
|
+
instagram: z4.string().max(25e3).optional(),
|
|
1229
|
+
facebook: z4.string().max(25e3).optional(),
|
|
1230
|
+
threads: z4.string().max(25e3).optional(),
|
|
1231
|
+
tiktok: z4.string().max(25e3).optional(),
|
|
1232
|
+
pinterest: z4.string().max(25e3).optional()
|
|
1048
1233
|
}).strict();
|
|
1049
|
-
var captionsSchema =
|
|
1050
|
-
canonical:
|
|
1234
|
+
var captionsSchema = z4.object({
|
|
1235
|
+
canonical: z4.string().max(25e3).nullable().optional(),
|
|
1051
1236
|
overrides: captionOverridesSchema.optional()
|
|
1052
1237
|
}).strict();
|
|
1053
|
-
var contentMediaCoverSchema =
|
|
1054
|
-
coverMediaId:
|
|
1055
|
-
thumbOffsetMs:
|
|
1238
|
+
var contentMediaCoverSchema = z4.object({
|
|
1239
|
+
coverMediaId: uuid4.optional(),
|
|
1240
|
+
thumbOffsetMs: z4.number().int().min(0).optional()
|
|
1056
1241
|
}).strict().nullable();
|
|
1057
|
-
var contentMediaSchema =
|
|
1058
|
-
|
|
1059
|
-
mediaId:
|
|
1060
|
-
order:
|
|
1061
|
-
crops:
|
|
1062
|
-
userTags:
|
|
1063
|
-
|
|
1064
|
-
username:
|
|
1065
|
-
x:
|
|
1066
|
-
y:
|
|
1242
|
+
var contentMediaSchema = z4.array(
|
|
1243
|
+
z4.object({
|
|
1244
|
+
mediaId: uuid4,
|
|
1245
|
+
order: z4.number().int().min(0).optional(),
|
|
1246
|
+
crops: z4.record(z4.string(), z4.unknown()).optional(),
|
|
1247
|
+
userTags: z4.array(
|
|
1248
|
+
z4.object({
|
|
1249
|
+
username: z4.string().min(1),
|
|
1250
|
+
x: z4.number().min(0).max(1),
|
|
1251
|
+
y: z4.number().min(0).max(1)
|
|
1067
1252
|
}).strict()
|
|
1068
1253
|
).optional(),
|
|
1069
|
-
productTags:
|
|
1070
|
-
|
|
1071
|
-
productId:
|
|
1072
|
-
productName:
|
|
1073
|
-
x:
|
|
1074
|
-
y:
|
|
1254
|
+
productTags: z4.array(
|
|
1255
|
+
z4.object({
|
|
1256
|
+
productId: z4.string().min(1),
|
|
1257
|
+
productName: z4.string().max(500).optional(),
|
|
1258
|
+
x: z4.number().min(0).max(1).optional(),
|
|
1259
|
+
y: z4.number().min(0).max(1).optional()
|
|
1075
1260
|
}).strict()
|
|
1076
1261
|
).optional(),
|
|
1077
1262
|
cover: contentMediaCoverSchema.optional()
|
|
@@ -1115,37 +1300,37 @@ var threadsReplyControlValues = [
|
|
|
1115
1300
|
"parent_post_author_only",
|
|
1116
1301
|
"followers_only"
|
|
1117
1302
|
];
|
|
1118
|
-
var settingsSchema =
|
|
1119
|
-
collaborators:
|
|
1120
|
-
locationId:
|
|
1121
|
-
facebookLinkUrl:
|
|
1122
|
-
facebookCtaType:
|
|
1123
|
-
facebookLocationId:
|
|
1124
|
-
xCommunityUrl:
|
|
1125
|
-
topicTag:
|
|
1126
|
-
linkAttachment:
|
|
1127
|
-
isGhostPost:
|
|
1128
|
-
replyControl:
|
|
1129
|
-
privacy_level:
|
|
1130
|
-
disable_comment:
|
|
1131
|
-
disable_duet:
|
|
1132
|
-
disable_stitch:
|
|
1133
|
-
brand_content_toggle:
|
|
1134
|
-
brand_organic_toggle:
|
|
1135
|
-
is_aigc:
|
|
1136
|
-
tiktok_post_to_drafts:
|
|
1137
|
-
photo_cover_index:
|
|
1138
|
-
auto_add_music:
|
|
1139
|
-
privacyStatus:
|
|
1140
|
-
categoryId:
|
|
1141
|
-
tags:
|
|
1142
|
-
madeForKids:
|
|
1143
|
-
notifySubscribers:
|
|
1144
|
-
embeddable:
|
|
1145
|
-
license:
|
|
1146
|
-
boardId:
|
|
1147
|
-
link:
|
|
1148
|
-
altText:
|
|
1303
|
+
var settingsSchema = z4.object({
|
|
1304
|
+
collaborators: z4.array(z4.string()).optional(),
|
|
1305
|
+
locationId: z4.string().optional(),
|
|
1306
|
+
facebookLinkUrl: z4.string().optional(),
|
|
1307
|
+
facebookCtaType: z4.enum(facebookPagePostCtaTypes).optional(),
|
|
1308
|
+
facebookLocationId: z4.string().optional(),
|
|
1309
|
+
xCommunityUrl: z4.string().optional(),
|
|
1310
|
+
topicTag: z4.string().optional(),
|
|
1311
|
+
linkAttachment: z4.string().optional(),
|
|
1312
|
+
isGhostPost: z4.boolean().optional(),
|
|
1313
|
+
replyControl: z4.enum(threadsReplyControlValues).optional(),
|
|
1314
|
+
privacy_level: z4.string().optional(),
|
|
1315
|
+
disable_comment: z4.boolean().optional(),
|
|
1316
|
+
disable_duet: z4.boolean().optional(),
|
|
1317
|
+
disable_stitch: z4.boolean().optional(),
|
|
1318
|
+
brand_content_toggle: z4.boolean().optional(),
|
|
1319
|
+
brand_organic_toggle: z4.boolean().optional(),
|
|
1320
|
+
is_aigc: z4.boolean().optional(),
|
|
1321
|
+
tiktok_post_to_drafts: z4.boolean().optional(),
|
|
1322
|
+
photo_cover_index: z4.number().optional(),
|
|
1323
|
+
auto_add_music: z4.boolean().optional(),
|
|
1324
|
+
privacyStatus: z4.enum(["public", "unlisted", "private"]).optional(),
|
|
1325
|
+
categoryId: z4.string().optional(),
|
|
1326
|
+
tags: z4.array(z4.string()).optional(),
|
|
1327
|
+
madeForKids: z4.boolean().optional(),
|
|
1328
|
+
notifySubscribers: z4.boolean().optional(),
|
|
1329
|
+
embeddable: z4.boolean().optional(),
|
|
1330
|
+
license: z4.enum(["youtube", "creativeCommon"]).optional(),
|
|
1331
|
+
boardId: z4.string().optional(),
|
|
1332
|
+
link: z4.string().optional(),
|
|
1333
|
+
altText: z4.string().optional()
|
|
1149
1334
|
}).strict().superRefine((settings, context) => {
|
|
1150
1335
|
for (const key of unsupportedSettingsKeys) {
|
|
1151
1336
|
if (Object.prototype.hasOwnProperty.call(settings, key)) {
|
|
@@ -1157,28 +1342,30 @@ var settingsSchema = z3.object({
|
|
|
1157
1342
|
}
|
|
1158
1343
|
}
|
|
1159
1344
|
}).optional();
|
|
1160
|
-
var createContentBaseSchema =
|
|
1161
|
-
intent:
|
|
1162
|
-
integrationId:
|
|
1163
|
-
internalTitle:
|
|
1164
|
-
publishTitle:
|
|
1165
|
-
notes:
|
|
1345
|
+
var createContentBaseSchema = z4.object({
|
|
1346
|
+
intent: z4.enum(["draft", "schedule", "publish_now"]).default("draft"),
|
|
1347
|
+
integrationId: uuid4,
|
|
1348
|
+
internalTitle: z4.string().max(500).nullable().optional(),
|
|
1349
|
+
publishTitle: z4.string().max(500).nullable().optional(),
|
|
1350
|
+
notes: z4.string().max(1e5).optional(),
|
|
1166
1351
|
captions: captionsSchema.optional(),
|
|
1167
1352
|
contentMedia: contentMediaSchema.optional(),
|
|
1168
1353
|
scheduledAt: isoWithTimezone.optional(),
|
|
1169
1354
|
settings: settingsSchema,
|
|
1170
|
-
postType:
|
|
1171
|
-
firstComment:
|
|
1172
|
-
shareToFeed:
|
|
1173
|
-
pillarIds:
|
|
1174
|
-
formatIds:
|
|
1175
|
-
labelIds:
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1355
|
+
postType: z4.enum(["post", "reel", "story", "thread"]).optional(),
|
|
1356
|
+
firstComment: z4.string().optional(),
|
|
1357
|
+
shareToFeed: z4.boolean().optional(),
|
|
1358
|
+
pillarIds: z4.array(uuid4).optional(),
|
|
1359
|
+
formatIds: z4.array(uuid4).optional(),
|
|
1360
|
+
labelIds: z4.array(uuid4).optional(),
|
|
1361
|
+
// Root-post metadata. The API accepts these on content payloads and stores
|
|
1362
|
+
// them on the canonical post record, not the channel edition row.
|
|
1363
|
+
campaignId: uuid4.nullable().optional(),
|
|
1364
|
+
campaignPhaseId: uuid4.nullable().optional(),
|
|
1365
|
+
priority: z4.enum(["urgent", "high", "medium", "low"]).optional(),
|
|
1366
|
+
assigneeIds: z4.array(uuid4).optional(),
|
|
1367
|
+
threadMessages: z4.array(
|
|
1368
|
+
z4.object({
|
|
1182
1369
|
captions: captionsSchema,
|
|
1183
1370
|
contentMedia: contentMediaSchema.optional()
|
|
1184
1371
|
}).strict()
|
|
@@ -1210,17 +1397,14 @@ var createContentSchema = createContentBaseSchema.superRefine((payload, ctx) =>
|
|
|
1210
1397
|
var updateContentSchema = createContentBaseSchema.omit({ intent: true }).partial().refine((payload) => Object.keys(payload).length > 0, {
|
|
1211
1398
|
message: "Update payload must include at least one field."
|
|
1212
1399
|
});
|
|
1213
|
-
var scheduleContentSchema =
|
|
1400
|
+
var scheduleContentSchema = z4.object({
|
|
1214
1401
|
scheduledAt: isoWithTimezone
|
|
1215
1402
|
});
|
|
1216
|
-
var
|
|
1217
|
-
|
|
1218
|
-
});
|
|
1219
|
-
var updateContentNotesSchema = z3.object({
|
|
1220
|
-
notes: z3.string().max(1e5)
|
|
1403
|
+
var updateContentNotesSchema = z4.object({
|
|
1404
|
+
notes: z4.string().max(1e5)
|
|
1221
1405
|
});
|
|
1222
|
-
var updatePublishedCaptionSchema =
|
|
1223
|
-
message:
|
|
1406
|
+
var updatePublishedCaptionSchema = z4.object({
|
|
1407
|
+
message: z4.string().max(25e3)
|
|
1224
1408
|
}).strict();
|
|
1225
1409
|
|
|
1226
1410
|
// src/commands/content.ts
|
|
@@ -1321,15 +1505,6 @@ function registerContentCommands(program) {
|
|
|
1321
1505
|
})
|
|
1322
1506
|
);
|
|
1323
1507
|
});
|
|
1324
|
-
addConnectionOptions(program.command("content:workflow")).description("Update a content item workflow status. Allowed statuses: idea, drafting (In Progress).").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <contentId>", "Content ID.").requiredOption("--status <status>", "Workflow status: idea or drafting (In Progress).").action(async (options, command) => {
|
|
1325
|
-
const payload = workflowStatusSchema.parse({ workflowStatus: options.status });
|
|
1326
|
-
const client = createApiClient(resolveConfig(command));
|
|
1327
|
-
writeRawJson(
|
|
1328
|
-
await client.request("PATCH", `/v1/workspaces/${options.workspace}/content/${options.id}/workflow-status`, {
|
|
1329
|
-
body: payload
|
|
1330
|
-
})
|
|
1331
|
-
);
|
|
1332
|
-
});
|
|
1333
1508
|
addConnectionOptions(program.command("content:get")).description("Get one content item.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <contentId>", "Content ID.").action(async (options, command) => {
|
|
1334
1509
|
const client = createApiClient(resolveConfig(command));
|
|
1335
1510
|
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/content/${options.id}`));
|
|
@@ -1376,11 +1551,11 @@ function registerContentCommands(program) {
|
|
|
1376
1551
|
const client = createApiClient(resolveConfig(command));
|
|
1377
1552
|
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/content/failed-count`));
|
|
1378
1553
|
});
|
|
1379
|
-
addConnectionOptions(program.command("content:pending-approval-count")).description("Get the pending approval count for a workspace. Requires
|
|
1554
|
+
addConnectionOptions(program.command("content:pending-approval-count")).description("Get the pending approval count for a workspace. Requires team plan.").requiredOption("-w, --workspace <id>", "Workspace ID.").action(async (options, command) => {
|
|
1380
1555
|
const client = createApiClient(resolveConfig(command));
|
|
1381
1556
|
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/content/pending-approval-count`));
|
|
1382
1557
|
});
|
|
1383
|
-
addConnectionOptions(program.command("content:approval-history")).description("List approval history for a workspace. Requires
|
|
1558
|
+
addConnectionOptions(program.command("content:approval-history")).description("List approval history for a workspace. Requires team plan.").requiredOption("-w, --workspace <id>", "Workspace ID.").option("--limit <number>", "Page size.").option("--cursor <cursor>", "Pagination cursor.").option("--search <text>", "Search approval history.").option("--workflow-path <path>", "Workflow path: all, internal, client, or internal_client.").option("--outcome <outcome>", "Outcome filter.").option("--platform <platform>", "Platform filter.").option("--reviewer <text>", "Reviewer filter.").option("--date-from <iso>", "ISO8601 start date.").option("--date-to <iso>", "ISO8601 end date.").action(async (options, command) => {
|
|
1384
1559
|
const client = createApiClient(resolveConfig(command));
|
|
1385
1560
|
writeRawJson(
|
|
1386
1561
|
await client.request("GET", `/v1/workspaces/${options.workspace}/content/approval-history`, {
|
|
@@ -1398,7 +1573,7 @@ function registerContentCommands(program) {
|
|
|
1398
1573
|
})
|
|
1399
1574
|
);
|
|
1400
1575
|
});
|
|
1401
|
-
addConnectionOptions(program.command("content:approval-history:client-batch")).description("Get client batch approval history detail. Requires
|
|
1576
|
+
addConnectionOptions(program.command("content:approval-history:client-batch")).description("Get client batch approval history detail. Requires team plan.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--batch <batchId>", "Client review batch ID.").action(async (options, command) => {
|
|
1402
1577
|
const client = createApiClient(resolveConfig(command));
|
|
1403
1578
|
writeRawJson(
|
|
1404
1579
|
await client.request(
|
|
@@ -1407,7 +1582,7 @@ function registerContentCommands(program) {
|
|
|
1407
1582
|
)
|
|
1408
1583
|
);
|
|
1409
1584
|
});
|
|
1410
|
-
addConnectionOptions(program.command("content:approval-history:internal")).description("Get internal approval history detail. Requires
|
|
1585
|
+
addConnectionOptions(program.command("content:approval-history:internal")).description("Get internal approval history detail. Requires team plan.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--record <recordId>", "Approval record ID.").action(async (options, command) => {
|
|
1411
1586
|
const client = createApiClient(resolveConfig(command));
|
|
1412
1587
|
writeRawJson(
|
|
1413
1588
|
await client.request(
|
|
@@ -1417,7 +1592,7 @@ function registerContentCommands(program) {
|
|
|
1417
1592
|
);
|
|
1418
1593
|
});
|
|
1419
1594
|
addConnectionOptions(program.command("content:comment-attachments:init")).description(
|
|
1420
|
-
"Initialize an approval comment attachment upload. Requires
|
|
1595
|
+
"Initialize an approval comment attachment upload. Requires team plan and content review comment capability."
|
|
1421
1596
|
).requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--json <file>", "JSON file containing the attachment upload payload.").action(async (options, command) => {
|
|
1422
1597
|
const payload = approvalAttachmentInitSchema.parse(await readJsonFile(options.json));
|
|
1423
1598
|
const client = createApiClient(resolveConfig(command));
|
|
@@ -1428,7 +1603,7 @@ function registerContentCommands(program) {
|
|
|
1428
1603
|
);
|
|
1429
1604
|
});
|
|
1430
1605
|
addConnectionOptions(program.command("content:comment-attachments:complete")).description(
|
|
1431
|
-
"Complete an approval comment attachment upload. Requires
|
|
1606
|
+
"Complete an approval comment attachment upload. Requires team plan and content review comment capability."
|
|
1432
1607
|
).requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--attachment <attachmentId>", "Attachment ID.").action(async (options, command) => {
|
|
1433
1608
|
const client = createApiClient(resolveConfig(command));
|
|
1434
1609
|
writeRawJson(
|
|
@@ -1439,7 +1614,7 @@ function registerContentCommands(program) {
|
|
|
1439
1614
|
);
|
|
1440
1615
|
});
|
|
1441
1616
|
addConnectionOptions(program.command("content:comment-attachments:abort")).description(
|
|
1442
|
-
"Abort an approval comment attachment upload. Requires
|
|
1617
|
+
"Abort an approval comment attachment upload. Requires team plan and content review comment capability."
|
|
1443
1618
|
).requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--attachment <attachmentId>", "Attachment ID.").action(async (options, command) => {
|
|
1444
1619
|
const client = createApiClient(resolveConfig(command));
|
|
1445
1620
|
writeRawJson(
|
|
@@ -1449,7 +1624,7 @@ function registerContentCommands(program) {
|
|
|
1449
1624
|
)
|
|
1450
1625
|
);
|
|
1451
1626
|
});
|
|
1452
|
-
addConnectionOptions(program.command("content:activity:react")).description("Add a reaction to an approval activity. Requires
|
|
1627
|
+
addConnectionOptions(program.command("content:activity:react")).description("Add a reaction to an approval activity. Requires team plan and content review comment capability.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--activity <activityId>", "Activity ID.").requiredOption("--json <file>", "JSON file containing emoji.").action(async (options, command) => {
|
|
1453
1628
|
const payload = approvalReactionSchema.parse(await readJsonFile(options.json));
|
|
1454
1629
|
const client = createApiClient(resolveConfig(command));
|
|
1455
1630
|
writeRawJson(
|
|
@@ -1463,7 +1638,7 @@ function registerContentCommands(program) {
|
|
|
1463
1638
|
);
|
|
1464
1639
|
});
|
|
1465
1640
|
addConnectionOptions(program.command("content:activity:unreact")).description(
|
|
1466
|
-
"Remove a reaction from an approval activity. Requires
|
|
1641
|
+
"Remove a reaction from an approval activity. Requires team plan and content review comment capability."
|
|
1467
1642
|
).requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--activity <activityId>", "Activity ID.").requiredOption("--emoji <emoji>", "Reaction emoji to remove.").action(async (options, command) => {
|
|
1468
1643
|
const client = createApiClient(resolveConfig(command));
|
|
1469
1644
|
writeRawJson(
|
|
@@ -1474,7 +1649,7 @@ function registerContentCommands(program) {
|
|
|
1474
1649
|
);
|
|
1475
1650
|
});
|
|
1476
1651
|
addConnectionOptions(program.command("content:request-approval")).description(
|
|
1477
|
-
"Request internal approval for a content item. Requires
|
|
1652
|
+
"Request internal approval for a content item. Requires team plan and content review request capability; may notify approvers."
|
|
1478
1653
|
).requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <contentId>", "Content ID.").requiredOption("--json <file>", "JSON file containing approverIds and policy.").option("--yes", "Confirm approver notifications.").action(async (options, command) => {
|
|
1479
1654
|
if (!options.yes) {
|
|
1480
1655
|
throw new CliError("content:request-approval requires --yes because it may notify approvers.", {
|
|
@@ -1489,7 +1664,7 @@ function registerContentCommands(program) {
|
|
|
1489
1664
|
})
|
|
1490
1665
|
);
|
|
1491
1666
|
});
|
|
1492
|
-
addConnectionOptions(program.command("content:decision")).description("Submit an internal approval decision. Requires
|
|
1667
|
+
addConnectionOptions(program.command("content:decision")).description("Submit an internal approval decision. Requires team plan and content review decision capability.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <contentId>", "Content ID.").requiredOption("--json <file>", "JSON file containing decision, optional override, and reason.").action(async (options, command) => {
|
|
1493
1668
|
const payload = approvalDecisionSchema.parse(await readJsonFile(options.json));
|
|
1494
1669
|
const client = createApiClient(resolveConfig(command));
|
|
1495
1670
|
writeRawJson(
|
|
@@ -1498,12 +1673,12 @@ function registerContentCommands(program) {
|
|
|
1498
1673
|
})
|
|
1499
1674
|
);
|
|
1500
1675
|
});
|
|
1501
|
-
addConnectionOptions(program.command("content:withdraw")).description("Withdraw an internal approval request. Requires
|
|
1676
|
+
addConnectionOptions(program.command("content:withdraw")).description("Withdraw an internal approval request. Requires team plan and content review withdraw capability.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <contentId>", "Content ID.").action(async (options, command) => {
|
|
1502
1677
|
const client = createApiClient(resolveConfig(command));
|
|
1503
1678
|
writeRawJson(await client.request("POST", `/v1/workspaces/${options.workspace}/content/${options.id}/withdraw`));
|
|
1504
1679
|
});
|
|
1505
1680
|
addConnectionOptions(program.command("content:resubmit")).description(
|
|
1506
|
-
"Resubmit rejected content for approval. Requires
|
|
1681
|
+
"Resubmit rejected content for approval. Requires team plan and content review request capability; may notify approvers."
|
|
1507
1682
|
).requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <contentId>", "Content ID.").requiredOption("--json <file>", "JSON file containing approverIds and policy.").option("--yes", "Confirm approver notifications.").action(async (options, command) => {
|
|
1508
1683
|
if (!options.yes) {
|
|
1509
1684
|
throw new CliError("content:resubmit requires --yes because it may notify approvers.", {
|
|
@@ -1518,12 +1693,12 @@ function registerContentCommands(program) {
|
|
|
1518
1693
|
})
|
|
1519
1694
|
);
|
|
1520
1695
|
});
|
|
1521
|
-
addConnectionOptions(program.command("content:history")).description("Get approval activity history for one content item. Requires
|
|
1696
|
+
addConnectionOptions(program.command("content:history")).description("Get approval activity history for one content item. Requires team plan.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <contentId>", "Content ID.").action(async (options, command) => {
|
|
1522
1697
|
const client = createApiClient(resolveConfig(command));
|
|
1523
1698
|
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/content/${options.id}/history`));
|
|
1524
1699
|
});
|
|
1525
1700
|
addConnectionOptions(program.command("content:comment")).description(
|
|
1526
|
-
"Add an internal approval comment to one content item. Requires
|
|
1701
|
+
"Add an internal approval comment to one content item. Requires team plan and content review comment capability."
|
|
1527
1702
|
).requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <contentId>", "Content ID.").requiredOption("--json <file>", "JSON file containing body or attachmentId.").action(async (options, command) => {
|
|
1528
1703
|
const payload = approvalCommentSchema.parse(await readJsonFile(options.json));
|
|
1529
1704
|
const client = createApiClient(resolveConfig(command));
|
|
@@ -1533,7 +1708,7 @@ function registerContentCommands(program) {
|
|
|
1533
1708
|
})
|
|
1534
1709
|
);
|
|
1535
1710
|
});
|
|
1536
|
-
addConnectionOptions(program.command("content:reopen-client-review")).description("Reopen client review for one content item. Requires
|
|
1711
|
+
addConnectionOptions(program.command("content:reopen-client-review")).description("Reopen client review for one content item. Requires team plan and client review send capability.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <contentId>", "Content ID.").action(async (options, command) => {
|
|
1537
1712
|
const client = createApiClient(resolveConfig(command));
|
|
1538
1713
|
writeRawJson(
|
|
1539
1714
|
await client.request("POST", `/v1/workspaces/${options.workspace}/content/${options.id}/reopen-client-review`)
|
|
@@ -1547,24 +1722,24 @@ function registerContentCommands(program) {
|
|
|
1547
1722
|
}
|
|
1548
1723
|
|
|
1549
1724
|
// src/grid-planner-schema.ts
|
|
1550
|
-
import { z as
|
|
1551
|
-
var uuidV4 =
|
|
1552
|
-
var placeholderSettingsSchema =
|
|
1553
|
-
title:
|
|
1554
|
-
color:
|
|
1725
|
+
import { z as z5 } from "zod";
|
|
1726
|
+
var uuidV4 = z5.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i, "Expected a UUIDv4 string.");
|
|
1727
|
+
var placeholderSettingsSchema = z5.object({
|
|
1728
|
+
title: z5.string().trim().min(1).max(40),
|
|
1729
|
+
color: z5.string().regex(/^#[0-9a-fA-F]{6}$/)
|
|
1555
1730
|
}).strict();
|
|
1556
|
-
var settingsSchema2 =
|
|
1557
|
-
aspectRatio:
|
|
1731
|
+
var settingsSchema2 = z5.object({
|
|
1732
|
+
aspectRatio: z5.number().min(0.1).max(10).nullable().optional(),
|
|
1558
1733
|
placeholder: placeholderSettingsSchema.optional()
|
|
1559
1734
|
}).strict();
|
|
1560
|
-
var gridPlannerCreateSchema =
|
|
1735
|
+
var gridPlannerCreateSchema = z5.object({
|
|
1561
1736
|
integrationId: uuidV4,
|
|
1562
|
-
kind:
|
|
1563
|
-
mediaIds:
|
|
1737
|
+
kind: z5.enum(["visual_only", "linked_post", "placeholder"]),
|
|
1738
|
+
mediaIds: z5.array(uuidV4).min(1).optional(),
|
|
1564
1739
|
linkedContentId: uuidV4.optional(),
|
|
1565
1740
|
coverMediaId: uuidV4.nullable().optional(),
|
|
1566
|
-
note:
|
|
1567
|
-
position:
|
|
1741
|
+
note: z5.string().optional(),
|
|
1742
|
+
position: z5.number().int().min(0).optional(),
|
|
1568
1743
|
settings: settingsSchema2.optional()
|
|
1569
1744
|
}).strict().superRefine((payload, context) => {
|
|
1570
1745
|
if (payload.kind === "visual_only" && !payload.mediaIds) {
|
|
@@ -1626,18 +1801,18 @@ var gridPlannerCreateSchema = z4.object({
|
|
|
1626
1801
|
});
|
|
1627
1802
|
}
|
|
1628
1803
|
});
|
|
1629
|
-
var gridPlannerUpdateSchema =
|
|
1804
|
+
var gridPlannerUpdateSchema = z5.object({
|
|
1630
1805
|
integrationId: uuidV4,
|
|
1631
|
-
note:
|
|
1806
|
+
note: z5.string().nullable().optional(),
|
|
1632
1807
|
settings: settingsSchema2.optional()
|
|
1633
1808
|
}).strict();
|
|
1634
|
-
var gridPlannerReorderSchema =
|
|
1809
|
+
var gridPlannerReorderSchema = z5.object({
|
|
1635
1810
|
integrationId: uuidV4,
|
|
1636
|
-
itemIds:
|
|
1637
|
-
items:
|
|
1638
|
-
|
|
1811
|
+
itemIds: z5.array(uuidV4).min(1).optional(),
|
|
1812
|
+
items: z5.array(
|
|
1813
|
+
z5.object({
|
|
1639
1814
|
itemId: uuidV4,
|
|
1640
|
-
position:
|
|
1815
|
+
position: z5.number().int().min(0)
|
|
1641
1816
|
}).strict()
|
|
1642
1817
|
).min(1).optional()
|
|
1643
1818
|
}).strict().refine((payload) => Boolean(payload.itemIds) !== Boolean(payload.items), {
|
|
@@ -1656,18 +1831,18 @@ var gridPlannerReorderSchema = z4.object({
|
|
|
1656
1831
|
message: "items must contain unique positions."
|
|
1657
1832
|
}
|
|
1658
1833
|
);
|
|
1659
|
-
var gridPlannerReplaceMediaSchema =
|
|
1834
|
+
var gridPlannerReplaceMediaSchema = z5.object({
|
|
1660
1835
|
integrationId: uuidV4,
|
|
1661
|
-
mediaIds:
|
|
1836
|
+
mediaIds: z5.array(uuidV4).min(1).max(10)
|
|
1662
1837
|
}).strict().refine((payload) => new Set(payload.mediaIds).size === payload.mediaIds.length, {
|
|
1663
1838
|
path: ["mediaIds"],
|
|
1664
1839
|
message: "mediaIds must contain unique UUIDs."
|
|
1665
1840
|
});
|
|
1666
|
-
var gridPlannerSetCoverSchema =
|
|
1841
|
+
var gridPlannerSetCoverSchema = z5.object({
|
|
1667
1842
|
integrationId: uuidV4,
|
|
1668
1843
|
mediaId: uuidV4
|
|
1669
1844
|
}).strict();
|
|
1670
|
-
var gridPlannerPromoteSchema =
|
|
1845
|
+
var gridPlannerPromoteSchema = z5.object({
|
|
1671
1846
|
integrationId: uuidV4
|
|
1672
1847
|
}).strict();
|
|
1673
1848
|
|
|
@@ -1771,10 +1946,10 @@ function registerGridPlannerCommands(program) {
|
|
|
1771
1946
|
}
|
|
1772
1947
|
|
|
1773
1948
|
// src/commands/hashtags.ts
|
|
1774
|
-
import { z as
|
|
1775
|
-
var hashtagGroupSchema =
|
|
1776
|
-
name:
|
|
1777
|
-
content:
|
|
1949
|
+
import { z as z6 } from "zod";
|
|
1950
|
+
var hashtagGroupSchema = z6.object({
|
|
1951
|
+
name: z6.string().trim().min(1).max(100),
|
|
1952
|
+
content: z6.string().trim().min(1)
|
|
1778
1953
|
});
|
|
1779
1954
|
function registerHashtagCommands(program) {
|
|
1780
1955
|
addConnectionOptions(program.command("hashtags:list")).description("List saved hashtag groups for a workspace.").requiredOption("-w, --workspace <id>", "Workspace ID.").action(async (options, command) => {
|
|
@@ -1806,31 +1981,49 @@ function registerHashtagCommands(program) {
|
|
|
1806
1981
|
}
|
|
1807
1982
|
|
|
1808
1983
|
// src/inbox-schema.ts
|
|
1809
|
-
import { z as
|
|
1810
|
-
var
|
|
1811
|
-
var inboxAttachmentSchema =
|
|
1812
|
-
type:
|
|
1813
|
-
url:
|
|
1984
|
+
import { z as z7 } from "zod";
|
|
1985
|
+
var uuid5 = z7.string().uuid();
|
|
1986
|
+
var inboxAttachmentSchema = z7.object({
|
|
1987
|
+
type: z7.enum(["image", "video", "audio", "file"]),
|
|
1988
|
+
url: z7.url()
|
|
1814
1989
|
});
|
|
1815
|
-
var inboxReplySchema =
|
|
1816
|
-
content:
|
|
1817
|
-
parentMessageId:
|
|
1990
|
+
var inboxReplySchema = z7.object({
|
|
1991
|
+
content: z7.string().max(2e3).optional(),
|
|
1992
|
+
parentMessageId: uuid5.optional(),
|
|
1818
1993
|
attachment: inboxAttachmentSchema.optional()
|
|
1819
1994
|
}).refine((payload) => Boolean(payload.content?.trim() || payload.attachment), {
|
|
1820
1995
|
message: "Reply payload must include content or attachment."
|
|
1821
1996
|
});
|
|
1822
|
-
var inboxNoteSchema =
|
|
1823
|
-
content:
|
|
1997
|
+
var inboxNoteSchema = z7.object({
|
|
1998
|
+
content: z7.string().min(1).max(5e3)
|
|
1824
1999
|
});
|
|
1825
|
-
var inboxModerateSchema =
|
|
1826
|
-
action:
|
|
2000
|
+
var inboxModerateSchema = z7.object({
|
|
2001
|
+
action: z7.enum(["hide", "unhide", "delete"])
|
|
1827
2002
|
});
|
|
1828
|
-
var inboxMarkAllReadSchema =
|
|
1829
|
-
platform:
|
|
1830
|
-
status:
|
|
1831
|
-
integrationId:
|
|
1832
|
-
messageType:
|
|
2003
|
+
var inboxMarkAllReadSchema = z7.object({
|
|
2004
|
+
platform: z7.enum(["instagram", "facebook", "threads"]).optional(),
|
|
2005
|
+
status: z7.enum(["open", "archived", "all"]).optional(),
|
|
2006
|
+
integrationId: z7.string().min(1).optional(),
|
|
2007
|
+
messageType: z7.enum(["comment", "dm", "review", "mention"]).optional()
|
|
1833
2008
|
});
|
|
2009
|
+
var inboxResolveSchema = z7.object({
|
|
2010
|
+
reason: z7.enum(["manual", "reply_sent", "moderated", "handled_natively", "handled_offline", "no_response_needed"]).optional(),
|
|
2011
|
+
note: z7.string().max(1e3).optional()
|
|
2012
|
+
}).strict();
|
|
2013
|
+
var inboxResolveAllSchema = z7.object({
|
|
2014
|
+
platform: z7.enum(["instagram", "facebook", "threads"]).optional(),
|
|
2015
|
+
status: z7.enum(["open", "archived", "all"]).optional(),
|
|
2016
|
+
integrationId: uuid5.optional(),
|
|
2017
|
+
messageType: z7.enum(["comment", "dm", "review", "mention"]).optional(),
|
|
2018
|
+
search: z7.string().max(200).optional(),
|
|
2019
|
+
read: z7.enum(["read", "unread", "all"]).optional(),
|
|
2020
|
+
resolution: z7.enum(["resolved", "unresolved", "all"]).optional(),
|
|
2021
|
+
page: z7.number().int().min(1).optional(),
|
|
2022
|
+
limit: z7.number().int().min(1).max(50).optional(),
|
|
2023
|
+
threadIds: z7.array(uuid5).max(50).optional(),
|
|
2024
|
+
reason: z7.enum(["manual", "reply_sent", "moderated", "handled_natively", "handled_offline", "no_response_needed"]).optional(),
|
|
2025
|
+
note: z7.string().max(1e3).optional()
|
|
2026
|
+
}).strict();
|
|
1834
2027
|
|
|
1835
2028
|
// src/commands/inbox.ts
|
|
1836
2029
|
function registerInboxCommands(program) {
|
|
@@ -1948,6 +2141,50 @@ function registerInboxCommands(program) {
|
|
|
1948
2141
|
await client.request("DELETE", `/v1/workspaces/${options.workspace}/inbox/messages/${options.message}/failed`)
|
|
1949
2142
|
);
|
|
1950
2143
|
});
|
|
2144
|
+
addConnectionOptions(program.command("inbox:resolve")).description("Resolve an inbox thread. Requires inbox resolve capability.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--thread <threadId>", "Inbox thread ID.").option("--json <file>", "JSON file with optional resolution reason and note.").action(async (options, command) => {
|
|
2145
|
+
const payload = inboxResolveSchema.parse(options.json ? await readJsonFile(options.json) : {});
|
|
2146
|
+
const client = createApiClient(resolveConfig(command));
|
|
2147
|
+
writeRawJson(
|
|
2148
|
+
await client.request("POST", `/v1/workspaces/${options.workspace}/inbox/threads/${options.thread}/resolve`, {
|
|
2149
|
+
body: payload
|
|
2150
|
+
})
|
|
2151
|
+
);
|
|
2152
|
+
});
|
|
2153
|
+
addConnectionOptions(program.command("inbox:reopen")).description("Reopen a resolved inbox thread. Requires inbox resolve capability.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--thread <threadId>", "Inbox thread ID.").action(async (options, command) => {
|
|
2154
|
+
const client = createApiClient(resolveConfig(command));
|
|
2155
|
+
writeRawJson(
|
|
2156
|
+
await client.request("DELETE", `/v1/workspaces/${options.workspace}/inbox/threads/${options.thread}/resolve`)
|
|
2157
|
+
);
|
|
2158
|
+
});
|
|
2159
|
+
addConnectionOptions(program.command("inbox:resolve-all")).description("Resolve matching inbox threads from a JSON filter payload. Requires inbox resolve capability.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--json <file>", "JSON file containing resolve-all filters.").option("--yes", "Confirm resolving matching threads.").action(async (options, command) => {
|
|
2160
|
+
if (!options.yes) {
|
|
2161
|
+
throw new CliError("inbox:resolve-all requires --yes because it can resolve many customer threads at once.", {
|
|
2162
|
+
code: "INVALID_OPTIONS"
|
|
2163
|
+
});
|
|
2164
|
+
}
|
|
2165
|
+
const payload = inboxResolveAllSchema.parse(await readJsonFile(options.json));
|
|
2166
|
+
const client = createApiClient(resolveConfig(command));
|
|
2167
|
+
writeRawJson(
|
|
2168
|
+
await client.request("POST", `/v1/workspaces/${options.workspace}/inbox/threads/resolve-all`, {
|
|
2169
|
+
body: payload
|
|
2170
|
+
})
|
|
2171
|
+
);
|
|
2172
|
+
});
|
|
2173
|
+
addConnectionOptions(program.command("inbox:resolve-message")).description("Resolve an inbox message. Requires inbox resolve capability.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--message <messageId>", "Inbox message ID.").option("--json <file>", "JSON file with optional resolution reason and note.").action(async (options, command) => {
|
|
2174
|
+
const payload = inboxResolveSchema.parse(options.json ? await readJsonFile(options.json) : {});
|
|
2175
|
+
const client = createApiClient(resolveConfig(command));
|
|
2176
|
+
writeRawJson(
|
|
2177
|
+
await client.request("POST", `/v1/workspaces/${options.workspace}/inbox/messages/${options.message}/resolve`, {
|
|
2178
|
+
body: payload
|
|
2179
|
+
})
|
|
2180
|
+
);
|
|
2181
|
+
});
|
|
2182
|
+
addConnectionOptions(program.command("inbox:reopen-message")).description("Reopen a resolved inbox message. Requires inbox resolve capability.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--message <messageId>", "Inbox message ID.").action(async (options, command) => {
|
|
2183
|
+
const client = createApiClient(resolveConfig(command));
|
|
2184
|
+
writeRawJson(
|
|
2185
|
+
await client.request("DELETE", `/v1/workspaces/${options.workspace}/inbox/messages/${options.message}/resolve`)
|
|
2186
|
+
);
|
|
2187
|
+
});
|
|
1951
2188
|
}
|
|
1952
2189
|
|
|
1953
2190
|
// src/commands/integrations.ts
|
|
@@ -1981,51 +2218,67 @@ function registerIntegrationCommands(program) {
|
|
|
1981
2218
|
}
|
|
1982
2219
|
|
|
1983
2220
|
// src/media-schema.ts
|
|
1984
|
-
import { z as
|
|
1985
|
-
var
|
|
1986
|
-
var
|
|
1987
|
-
var mediaUpdateSchema =
|
|
1988
|
-
filename:
|
|
1989
|
-
altText:
|
|
1990
|
-
isFavorite:
|
|
1991
|
-
folderId:
|
|
2221
|
+
import { z as z8 } from "zod";
|
|
2222
|
+
var uuid6 = z8.string().uuid();
|
|
2223
|
+
var hexColor2 = z8.string().regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/, "Color must be a hex color.");
|
|
2224
|
+
var mediaUpdateSchema = z8.object({
|
|
2225
|
+
filename: z8.string().min(1).max(255).optional(),
|
|
2226
|
+
altText: z8.string().max(500).optional(),
|
|
2227
|
+
isFavorite: z8.boolean().optional(),
|
|
2228
|
+
folderId: uuid6.nullable().optional()
|
|
1992
2229
|
}).refine((payload) => Object.keys(payload).length > 0, {
|
|
1993
2230
|
message: "Media update payload must include at least one field."
|
|
1994
2231
|
});
|
|
1995
|
-
var createMediaFolderSchema =
|
|
1996
|
-
name:
|
|
1997
|
-
parentId:
|
|
2232
|
+
var createMediaFolderSchema = z8.object({
|
|
2233
|
+
name: z8.string().min(1).max(255),
|
|
2234
|
+
parentId: uuid6.optional()
|
|
1998
2235
|
});
|
|
1999
|
-
var updateMediaFolderSchema =
|
|
2000
|
-
name:
|
|
2236
|
+
var updateMediaFolderSchema = z8.object({
|
|
2237
|
+
name: z8.string().min(1).max(255)
|
|
2001
2238
|
});
|
|
2002
|
-
var moveMediaFolderSchema =
|
|
2003
|
-
parentId:
|
|
2239
|
+
var moveMediaFolderSchema = z8.object({
|
|
2240
|
+
parentId: uuid6.nullable().optional()
|
|
2004
2241
|
}).refine((payload) => Object.prototype.hasOwnProperty.call(payload, "parentId"), {
|
|
2005
2242
|
message: "Folder move payload must include parentId. Use null to move to root."
|
|
2006
2243
|
});
|
|
2007
|
-
var createMediaLabelSchema =
|
|
2008
|
-
name:
|
|
2009
|
-
color:
|
|
2244
|
+
var createMediaLabelSchema = z8.object({
|
|
2245
|
+
name: z8.string().min(1).max(50),
|
|
2246
|
+
color: hexColor2.optional()
|
|
2010
2247
|
});
|
|
2011
|
-
var updateMediaLabelSchema =
|
|
2012
|
-
name:
|
|
2013
|
-
color:
|
|
2248
|
+
var updateMediaLabelSchema = z8.object({
|
|
2249
|
+
name: z8.string().min(1).max(50).optional(),
|
|
2250
|
+
color: hexColor2.optional()
|
|
2014
2251
|
}).refine((payload) => Object.keys(payload).length > 0, {
|
|
2015
2252
|
message: "Media label update payload must include at least one field."
|
|
2016
2253
|
});
|
|
2017
|
-
var mediaIdsSchema =
|
|
2018
|
-
mediaIds:
|
|
2254
|
+
var mediaIdsSchema = z8.object({
|
|
2255
|
+
mediaIds: z8.array(uuid6).min(1).max(100)
|
|
2019
2256
|
});
|
|
2020
2257
|
var mediaBulkMoveSchema = mediaIdsSchema.extend({
|
|
2021
|
-
folderId:
|
|
2258
|
+
folderId: uuid6.nullable().optional()
|
|
2022
2259
|
});
|
|
2023
|
-
var mediaLabelIdsSchema =
|
|
2024
|
-
labelIds:
|
|
2260
|
+
var mediaLabelIdsSchema = z8.object({
|
|
2261
|
+
labelIds: z8.array(uuid6).min(1).max(50)
|
|
2025
2262
|
});
|
|
2026
2263
|
var mediaBulkLabelSchema = mediaIdsSchema.extend({
|
|
2027
|
-
labelIds:
|
|
2264
|
+
labelIds: z8.array(uuid6).min(1).max(50)
|
|
2028
2265
|
});
|
|
2266
|
+
var mergeLabelsSchema = z8.object({ targetLabelId: uuid6 }).strict();
|
|
2267
|
+
var createLabelGroupSchema = z8.object({
|
|
2268
|
+
name: z8.string().min(1).max(100),
|
|
2269
|
+
color: hexColor2.nullable().optional(),
|
|
2270
|
+
sortOrder: z8.number().int().optional()
|
|
2271
|
+
}).strict();
|
|
2272
|
+
var updateLabelGroupSchema = z8.object({
|
|
2273
|
+
name: z8.string().max(100).optional(),
|
|
2274
|
+
color: hexColor2.nullable().optional(),
|
|
2275
|
+
sortOrder: z8.number().int().optional()
|
|
2276
|
+
}).strict().refine((payload) => Object.keys(payload).length > 0, {
|
|
2277
|
+
message: "Label group update payload must include at least one field."
|
|
2278
|
+
});
|
|
2279
|
+
var deleteLabelGroupSchema = z8.object({ mode: z8.enum(["archive-labels", "ungroup-labels"]) }).strict();
|
|
2280
|
+
var reorderLabelGroupsSchema = z8.object({ groupIds: z8.array(uuid6) }).strict();
|
|
2281
|
+
var moveLabelsToGroupSchema = z8.object({ labelIds: z8.array(uuid6).min(1).max(100) }).strict();
|
|
2029
2282
|
|
|
2030
2283
|
// src/commands/media.ts
|
|
2031
2284
|
function registerMediaCommands(program) {
|
|
@@ -2068,6 +2321,14 @@ function registerMediaCommands(program) {
|
|
|
2068
2321
|
const client = createApiClient(resolveConfig(command));
|
|
2069
2322
|
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/media/${options.id}`));
|
|
2070
2323
|
});
|
|
2324
|
+
addConnectionOptions(program.command("media:usage-history")).description("Get usage history for one media item.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <mediaId>", "Media ID.").option("--limit <number>", "Page size.").option("--cursor <cursor>", "Pagination cursor.").action(async (options, command) => {
|
|
2325
|
+
const client = createApiClient(resolveConfig(command));
|
|
2326
|
+
writeRawJson(
|
|
2327
|
+
await client.request("GET", `/v1/workspaces/${options.workspace}/media/${options.id}/usage-history`, {
|
|
2328
|
+
query: { limit: options.limit, cursor: options.cursor }
|
|
2329
|
+
})
|
|
2330
|
+
);
|
|
2331
|
+
});
|
|
2071
2332
|
addConnectionOptions(program.command("media:update")).description("Update one media item from a JSON payload file.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <mediaId>", "Media ID.").requiredOption("--json <file>", "JSON file containing fields to update.").action(async (options, command) => {
|
|
2072
2333
|
const payload = mediaUpdateSchema.parse(await readJsonFile(options.json));
|
|
2073
2334
|
const client = createApiClient(resolveConfig(command));
|
|
@@ -2093,6 +2354,19 @@ function registerMediaCommands(program) {
|
|
|
2093
2354
|
const client = createApiClient(resolveConfig(command));
|
|
2094
2355
|
writeRawJson(await client.request("DELETE", `/v1/workspaces/${options.workspace}/media/${options.id}`));
|
|
2095
2356
|
});
|
|
2357
|
+
addConnectionOptions(program.command("media:restore")).description("Restore one media item from the Bin.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <mediaId>", "Media ID.").action(async (options, command) => {
|
|
2358
|
+
const client = createApiClient(resolveConfig(command));
|
|
2359
|
+
writeRawJson(await client.request("POST", `/v1/workspaces/${options.workspace}/media/${options.id}/restore`));
|
|
2360
|
+
});
|
|
2361
|
+
addConnectionOptions(program.command("media:delete-permanent")).description("Permanently delete one media item from the Bin. This cannot be undone.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <mediaId>", "Media ID.").option("--yes", "Confirm permanent deletion.").action(async (options, command) => {
|
|
2362
|
+
if (!options.yes) {
|
|
2363
|
+
throw new CliError("media:delete-permanent requires --yes because it permanently deletes media.", {
|
|
2364
|
+
code: "INVALID_OPTIONS"
|
|
2365
|
+
});
|
|
2366
|
+
}
|
|
2367
|
+
const client = createApiClient(resolveConfig(command));
|
|
2368
|
+
writeRawJson(await client.request("DELETE", `/v1/workspaces/${options.workspace}/media/${options.id}/permanent`));
|
|
2369
|
+
});
|
|
2096
2370
|
addConnectionOptions(program.command("media:folders:list")).description("List media folders.").requiredOption("-w, --workspace <id>", "Workspace ID.").option("--parent-id <id>", "Parent folder ID, or root for top-level folders.").action(async (options, command) => {
|
|
2097
2371
|
const client = createApiClient(resolveConfig(command));
|
|
2098
2372
|
writeRawJson(
|
|
@@ -2188,6 +2462,97 @@ function registerMediaCommands(program) {
|
|
|
2188
2462
|
})
|
|
2189
2463
|
);
|
|
2190
2464
|
});
|
|
2465
|
+
addConnectionOptions(program.command("media:labels:usage")).description("Get workspace label usage counts for media.").requiredOption("-w, --workspace <id>", "Workspace ID.").option("--label-ids <ids>", "Comma-separated label IDs to scope the counts.").action(async (options, command) => {
|
|
2466
|
+
const client = createApiClient(resolveConfig(command));
|
|
2467
|
+
writeRawJson(
|
|
2468
|
+
await client.request("GET", `/v1/workspaces/${options.workspace}/media/labels/usage`, {
|
|
2469
|
+
query: { labelIds: options.labelIds }
|
|
2470
|
+
})
|
|
2471
|
+
);
|
|
2472
|
+
});
|
|
2473
|
+
addConnectionOptions(program.command("media:labels:health")).description("Get the workspace label health summary for media.").requiredOption("-w, --workspace <id>", "Workspace ID.").action(async (options, command) => {
|
|
2474
|
+
const client = createApiClient(resolveConfig(command));
|
|
2475
|
+
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/media/labels/health`));
|
|
2476
|
+
});
|
|
2477
|
+
addConnectionOptions(program.command("media:labels:archive")).description("Archive one media label.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <labelId>", "Media label ID.").action(async (options, command) => {
|
|
2478
|
+
const client = createApiClient(resolveConfig(command));
|
|
2479
|
+
writeRawJson(
|
|
2480
|
+
await client.request("POST", `/v1/workspaces/${options.workspace}/media/labels/${options.id}/archive`)
|
|
2481
|
+
);
|
|
2482
|
+
});
|
|
2483
|
+
addConnectionOptions(program.command("media:labels:restore")).description("Restore one archived media label.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <labelId>", "Media label ID.").action(async (options, command) => {
|
|
2484
|
+
const client = createApiClient(resolveConfig(command));
|
|
2485
|
+
writeRawJson(
|
|
2486
|
+
await client.request("POST", `/v1/workspaces/${options.workspace}/media/labels/${options.id}/restore`)
|
|
2487
|
+
);
|
|
2488
|
+
});
|
|
2489
|
+
addConnectionOptions(program.command("media:labels:merge")).description("Merge one media label into another from a JSON payload file.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <labelId>", "Source media label ID.").requiredOption("--json <file>", "JSON file containing targetLabelId.").action(async (options, command) => {
|
|
2490
|
+
const payload = mergeLabelsSchema.parse(await readJsonFile(options.json));
|
|
2491
|
+
const client = createApiClient(resolveConfig(command));
|
|
2492
|
+
writeRawJson(
|
|
2493
|
+
await client.request("POST", `/v1/workspaces/${options.workspace}/media/labels/${options.id}/merge`, {
|
|
2494
|
+
body: payload
|
|
2495
|
+
})
|
|
2496
|
+
);
|
|
2497
|
+
});
|
|
2498
|
+
addConnectionOptions(program.command("media:label-groups:list")).description("List media label groups.").requiredOption("-w, --workspace <id>", "Workspace ID.").action(async (options, command) => {
|
|
2499
|
+
const client = createApiClient(resolveConfig(command));
|
|
2500
|
+
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/media/label-groups`));
|
|
2501
|
+
});
|
|
2502
|
+
addConnectionOptions(program.command("media:label-groups:create")).description("Create a media label group from a JSON payload file.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--json <file>", "JSON file containing the label group payload.").action(async (options, command) => {
|
|
2503
|
+
const payload = createLabelGroupSchema.parse(await readJsonFile(options.json));
|
|
2504
|
+
const client = createApiClient(resolveConfig(command));
|
|
2505
|
+
writeRawJson(
|
|
2506
|
+
await client.request("POST", `/v1/workspaces/${options.workspace}/media/label-groups`, {
|
|
2507
|
+
body: payload
|
|
2508
|
+
})
|
|
2509
|
+
);
|
|
2510
|
+
});
|
|
2511
|
+
addConnectionOptions(program.command("media:label-groups:update")).description("Update a media label group from a JSON payload file.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <groupId>", "Label group ID.").requiredOption("--json <file>", "JSON file containing fields to update.").action(async (options, command) => {
|
|
2512
|
+
const payload = updateLabelGroupSchema.parse(await readJsonFile(options.json));
|
|
2513
|
+
const client = createApiClient(resolveConfig(command));
|
|
2514
|
+
writeRawJson(
|
|
2515
|
+
await client.request("PATCH", `/v1/workspaces/${options.workspace}/media/label-groups/${options.id}`, {
|
|
2516
|
+
body: payload
|
|
2517
|
+
})
|
|
2518
|
+
);
|
|
2519
|
+
});
|
|
2520
|
+
addConnectionOptions(program.command("media:label-groups:delete")).description("Delete a media label group from a JSON payload file.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <groupId>", "Label group ID.").requiredOption("--json <file>", "JSON file containing mode: archive-labels or ungroup-labels.").action(async (options, command) => {
|
|
2521
|
+
const payload = deleteLabelGroupSchema.parse(await readJsonFile(options.json));
|
|
2522
|
+
const client = createApiClient(resolveConfig(command));
|
|
2523
|
+
writeRawJson(
|
|
2524
|
+
await client.request("DELETE", `/v1/workspaces/${options.workspace}/media/label-groups/${options.id}`, {
|
|
2525
|
+
body: payload
|
|
2526
|
+
})
|
|
2527
|
+
);
|
|
2528
|
+
});
|
|
2529
|
+
addConnectionOptions(program.command("media:label-groups:reorder")).description("Reorder media label groups from a JSON payload file.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--json <file>", "JSON file containing the complete groupIds order.").action(async (options, command) => {
|
|
2530
|
+
const payload = reorderLabelGroupsSchema.parse(await readJsonFile(options.json));
|
|
2531
|
+
const client = createApiClient(resolveConfig(command));
|
|
2532
|
+
writeRawJson(
|
|
2533
|
+
await client.request("POST", `/v1/workspaces/${options.workspace}/media/label-groups/reorder`, {
|
|
2534
|
+
body: payload
|
|
2535
|
+
})
|
|
2536
|
+
);
|
|
2537
|
+
});
|
|
2538
|
+
addConnectionOptions(program.command("media:label-groups:add-labels")).description("Move media labels into a label group from a JSON payload file.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <groupId>", "Label group ID.").requiredOption("--json <file>", "JSON file containing labelIds.").action(async (options, command) => {
|
|
2539
|
+
const payload = moveLabelsToGroupSchema.parse(await readJsonFile(options.json));
|
|
2540
|
+
const client = createApiClient(resolveConfig(command));
|
|
2541
|
+
writeRawJson(
|
|
2542
|
+
await client.request("POST", `/v1/workspaces/${options.workspace}/media/label-groups/${options.id}/labels`, {
|
|
2543
|
+
body: payload
|
|
2544
|
+
})
|
|
2545
|
+
);
|
|
2546
|
+
});
|
|
2547
|
+
addConnectionOptions(program.command("media:label-groups:ungroup-labels")).description("Remove media labels from any label group from a JSON payload file.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--json <file>", "JSON file containing labelIds.").action(async (options, command) => {
|
|
2548
|
+
const payload = moveLabelsToGroupSchema.parse(await readJsonFile(options.json));
|
|
2549
|
+
const client = createApiClient(resolveConfig(command));
|
|
2550
|
+
writeRawJson(
|
|
2551
|
+
await client.request("POST", `/v1/workspaces/${options.workspace}/media/label-groups/ungroup-labels`, {
|
|
2552
|
+
body: payload
|
|
2553
|
+
})
|
|
2554
|
+
);
|
|
2555
|
+
});
|
|
2191
2556
|
addConnectionOptions(program.command("media:bulk-archive")).description("Archive media in bulk from a JSON payload file.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--json <file>", "JSON file containing mediaIds.").action(async (options, command) => {
|
|
2192
2557
|
const payload = mediaIdsSchema.parse(await readJsonFile(options.json));
|
|
2193
2558
|
const client = createApiClient(resolveConfig(command));
|
|
@@ -2236,6 +2601,49 @@ function registerMediaCommands(program) {
|
|
|
2236
2601
|
})
|
|
2237
2602
|
);
|
|
2238
2603
|
});
|
|
2604
|
+
addConnectionOptions(program.command("media:bulk-restore")).description("Restore media from the Bin in bulk from a JSON payload file.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--json <file>", "JSON file containing mediaIds.").action(async (options, command) => {
|
|
2605
|
+
const payload = mediaIdsSchema.parse(await readJsonFile(options.json));
|
|
2606
|
+
const client = createApiClient(resolveConfig(command));
|
|
2607
|
+
writeRawJson(
|
|
2608
|
+
await client.request("POST", `/v1/workspaces/${options.workspace}/media/bulk-restore`, {
|
|
2609
|
+
body: payload
|
|
2610
|
+
})
|
|
2611
|
+
);
|
|
2612
|
+
});
|
|
2613
|
+
addConnectionOptions(program.command("media:bulk-delete-forever")).description("Permanently delete binned media in bulk from a JSON payload file. This cannot be undone.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--json <file>", "JSON file containing mediaIds.").option("--yes", "Confirm permanent deletion of the explicit media IDs.").action(async (options, command) => {
|
|
2614
|
+
if (!options.yes) {
|
|
2615
|
+
throw new CliError("media:bulk-delete-forever requires --yes because it permanently deletes media.", {
|
|
2616
|
+
code: "INVALID_OPTIONS"
|
|
2617
|
+
});
|
|
2618
|
+
}
|
|
2619
|
+
const payload = mediaIdsSchema.parse(await readJsonFile(options.json));
|
|
2620
|
+
const client = createApiClient(resolveConfig(command));
|
|
2621
|
+
writeRawJson(
|
|
2622
|
+
await client.request("POST", `/v1/workspaces/${options.workspace}/media/bulk-delete-forever`, {
|
|
2623
|
+
body: payload
|
|
2624
|
+
})
|
|
2625
|
+
);
|
|
2626
|
+
});
|
|
2627
|
+
}
|
|
2628
|
+
|
|
2629
|
+
// src/commands/strategy.ts
|
|
2630
|
+
function registerStrategyCommands(program) {
|
|
2631
|
+
addConnectionOptions(program.command("strategy:foundation")).description("Get the workspace strategy foundation brief.").requiredOption("-w, --workspace <id>", "Workspace ID.").action(async (options, command) => {
|
|
2632
|
+
const client = createApiClient(resolveConfig(command));
|
|
2633
|
+
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/strategy/foundation`));
|
|
2634
|
+
});
|
|
2635
|
+
addConnectionOptions(program.command("strategy:goals")).description("List workspace strategy goals with computed status and current values.").requiredOption("-w, --workspace <id>", "Workspace ID.").action(async (options, command) => {
|
|
2636
|
+
const client = createApiClient(resolveConfig(command));
|
|
2637
|
+
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/strategy/goals`));
|
|
2638
|
+
});
|
|
2639
|
+
addConnectionOptions(program.command("strategy:goals:metrics")).description("List the metric catalog available for strategy goals.").requiredOption("-w, --workspace <id>", "Workspace ID.").action(async (options, command) => {
|
|
2640
|
+
const client = createApiClient(resolveConfig(command));
|
|
2641
|
+
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/strategy/goals/metrics`));
|
|
2642
|
+
});
|
|
2643
|
+
addConnectionOptions(program.command("strategy:goal")).description("Get one strategy goal with computed status and current value.").requiredOption("-w, --workspace <id>", "Workspace ID.").requiredOption("--id <goalId>", "Strategy goal ID.").action(async (options, command) => {
|
|
2644
|
+
const client = createApiClient(resolveConfig(command));
|
|
2645
|
+
writeRawJson(await client.request("GET", `/v1/workspaces/${options.workspace}/strategy/goals/${options.id}`));
|
|
2646
|
+
});
|
|
2239
2647
|
}
|
|
2240
2648
|
|
|
2241
2649
|
// src/commands/taxonomy.ts
|
|
@@ -2289,11 +2697,14 @@ function createProgram() {
|
|
|
2289
2697
|
registerMediaCommands(program);
|
|
2290
2698
|
registerContentCommands(program);
|
|
2291
2699
|
registerClientReviewCommands(program);
|
|
2700
|
+
registerCampaignCommands(program);
|
|
2701
|
+
registerStrategyCommands(program);
|
|
2292
2702
|
registerTaxonomyCommands(program);
|
|
2293
2703
|
registerHashtagCommands(program);
|
|
2294
2704
|
registerAnalyticsCommands(program);
|
|
2295
2705
|
registerInboxCommands(program);
|
|
2296
2706
|
registerGridPlannerCommands(program);
|
|
2707
|
+
registerBoostCommands(program);
|
|
2297
2708
|
return program;
|
|
2298
2709
|
}
|
|
2299
2710
|
async function runCli(argv = process.argv) {
|
|
@@ -2318,8 +2729,16 @@ async function runCli(argv = process.argv) {
|
|
|
2318
2729
|
process.exitCode = 1;
|
|
2319
2730
|
}
|
|
2320
2731
|
}
|
|
2321
|
-
|
|
2322
|
-
|
|
2732
|
+
function isDirectInvocation() {
|
|
2733
|
+
const entry = process.argv[1];
|
|
2734
|
+
if (!entry) return false;
|
|
2735
|
+
try {
|
|
2736
|
+
return realpathSync(entry) === realpathSync(fileURLToPath(import.meta.url));
|
|
2737
|
+
} catch {
|
|
2738
|
+
return false;
|
|
2739
|
+
}
|
|
2740
|
+
}
|
|
2741
|
+
if (isDirectInvocation()) {
|
|
2323
2742
|
void runCli();
|
|
2324
2743
|
}
|
|
2325
2744
|
export {
|