@neopress/cli 4.4.0 → 4.6.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/dist/bin.cjs +328 -7
- package/dist/index.js +175 -5
- package/package.json +6 -3
package/dist/bin.cjs
CHANGED
|
@@ -24893,6 +24893,7 @@ function serializeRedirect(r) {
|
|
|
24893
24893
|
siteId: r.site_id,
|
|
24894
24894
|
source: r.source,
|
|
24895
24895
|
destination: r.destination,
|
|
24896
|
+
mode: r.mode,
|
|
24896
24897
|
redirectType: r.redirect_type,
|
|
24897
24898
|
includeChildren: r.include_children,
|
|
24898
24899
|
preservePath: r.preserve_path,
|
|
@@ -24944,6 +24945,30 @@ function serializeHeadshot(h) {
|
|
|
24944
24945
|
updatedAt: h.updated_at
|
|
24945
24946
|
};
|
|
24946
24947
|
}
|
|
24948
|
+
function serializeLogo(l) {
|
|
24949
|
+
return {
|
|
24950
|
+
id: l.id,
|
|
24951
|
+
imageUrl: l.image_url,
|
|
24952
|
+
width: l.width,
|
|
24953
|
+
height: l.height,
|
|
24954
|
+
aspectRatio: l.aspect_ratio,
|
|
24955
|
+
mimeType: l.mime_type,
|
|
24956
|
+
byteSize: l.byte_size,
|
|
24957
|
+
type: l.type,
|
|
24958
|
+
font: l.font,
|
|
24959
|
+
color: l.color,
|
|
24960
|
+
hue: l.hue,
|
|
24961
|
+
tone: l.tone,
|
|
24962
|
+
toneScore: l.tone_score,
|
|
24963
|
+
name: l.name,
|
|
24964
|
+
variant: l.variant,
|
|
24965
|
+
sha256: l.sha256,
|
|
24966
|
+
tags: l.tags ?? [],
|
|
24967
|
+
isActive: l.is_active,
|
|
24968
|
+
createdAt: l.created_at,
|
|
24969
|
+
updatedAt: l.updated_at
|
|
24970
|
+
};
|
|
24971
|
+
}
|
|
24947
24972
|
function serializeSite(site) {
|
|
24948
24973
|
return {
|
|
24949
24974
|
id: site.id,
|
|
@@ -25093,7 +25118,8 @@ var COLLECTION_FIELD_TYPES = [
|
|
|
25093
25118
|
"checkbox",
|
|
25094
25119
|
"radio",
|
|
25095
25120
|
"multi_checkbox",
|
|
25096
|
-
"consent"
|
|
25121
|
+
"consent",
|
|
25122
|
+
"place"
|
|
25097
25123
|
];
|
|
25098
25124
|
var COLLECTION_FIELD_TYPE_ALIASES = {
|
|
25099
25125
|
boolean: "bool",
|
|
@@ -38971,12 +38997,10 @@ var COLLECTION_PRESET_CONTRACTS = {
|
|
|
38971
38997
|
schema: {
|
|
38972
38998
|
title: titleField("Name"),
|
|
38973
38999
|
slug: slugField(),
|
|
38974
|
-
|
|
38975
|
-
address: field("address", "Address", "text"),
|
|
38976
|
-
city: field("city", "City", "text"),
|
|
39000
|
+
location: field("location", "Location", "place"),
|
|
38977
39001
|
description: field("description", "Description", "content")
|
|
38978
39002
|
},
|
|
38979
|
-
lockedFieldIds: ["title", "slug", "
|
|
39003
|
+
lockedFieldIds: ["title", "slug", "location"]
|
|
38980
39004
|
},
|
|
38981
39005
|
category: {
|
|
38982
39006
|
schema: {
|
|
@@ -40416,6 +40440,12 @@ var SiteEndpoint = class {
|
|
|
40416
40440
|
};
|
|
40417
40441
|
|
|
40418
40442
|
// ../sdk/dist/endpoints/redirects.js
|
|
40443
|
+
var DASHBOARD_ONLY_REWRITE_MESSAGE = "Rewrite proxy rules can only be managed in the dashboard.";
|
|
40444
|
+
function rejectModeParam(data) {
|
|
40445
|
+
if (data && typeof data === "object" && Object.prototype.hasOwnProperty.call(data, "mode")) {
|
|
40446
|
+
throw new NeopressApiError("REDIRECT_RULE_DASHBOARD_ONLY", DASHBOARD_ONLY_REWRITE_MESSAGE, 400);
|
|
40447
|
+
}
|
|
40448
|
+
}
|
|
40419
40449
|
var RedirectsEndpoint = class {
|
|
40420
40450
|
client;
|
|
40421
40451
|
constructor(client) {
|
|
@@ -40430,6 +40460,7 @@ var RedirectsEndpoint = class {
|
|
|
40430
40460
|
return (data ?? []).map((r) => serializeRedirect(r));
|
|
40431
40461
|
}
|
|
40432
40462
|
async create(data) {
|
|
40463
|
+
rejectModeParam(data);
|
|
40433
40464
|
const values = {
|
|
40434
40465
|
site_id: this.client.siteIdNumber,
|
|
40435
40466
|
source: data.source,
|
|
@@ -40445,7 +40476,21 @@ var RedirectsEndpoint = class {
|
|
|
40445
40476
|
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
40446
40477
|
return serializeRedirect(row);
|
|
40447
40478
|
}
|
|
40479
|
+
async assertRedirectRuleWritable(ruleId) {
|
|
40480
|
+
const { data, error: error48 } = await this.client.db.from("redirect_rules").select("id, mode").eq("site_id", this.client.siteIdNumber).eq("id", ruleId).maybeSingle();
|
|
40481
|
+
if (error48)
|
|
40482
|
+
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
40483
|
+
if (!data) {
|
|
40484
|
+
throw new NeopressApiError("REDIRECT_RULE_NOT_FOUND", `Redirect rule ${ruleId} not found for this site`, 404);
|
|
40485
|
+
}
|
|
40486
|
+
const row = data;
|
|
40487
|
+
if (row.mode === "proxy") {
|
|
40488
|
+
throw new NeopressApiError("REDIRECT_RULE_DASHBOARD_ONLY", DASHBOARD_ONLY_REWRITE_MESSAGE, 400);
|
|
40489
|
+
}
|
|
40490
|
+
}
|
|
40448
40491
|
async update(ruleId, data) {
|
|
40492
|
+
rejectModeParam(data);
|
|
40493
|
+
await this.assertRedirectRuleWritable(ruleId);
|
|
40449
40494
|
const values = {};
|
|
40450
40495
|
if ("source" in data)
|
|
40451
40496
|
values.source = data.source;
|
|
@@ -40467,6 +40512,7 @@ var RedirectsEndpoint = class {
|
|
|
40467
40512
|
return serializeRedirect(row);
|
|
40468
40513
|
}
|
|
40469
40514
|
async delete(ruleId) {
|
|
40515
|
+
await this.assertRedirectRuleWritable(ruleId);
|
|
40470
40516
|
const { error: error48 } = await this.client.db.from("redirect_rules").delete().eq("site_id", this.client.siteIdNumber).eq("id", ruleId);
|
|
40471
40517
|
if (error48)
|
|
40472
40518
|
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
@@ -40785,6 +40831,128 @@ var HeadshotsEndpoint = class {
|
|
|
40785
40831
|
}
|
|
40786
40832
|
};
|
|
40787
40833
|
|
|
40834
|
+
// ../sdk/dist/endpoints/logos.js
|
|
40835
|
+
var LogosEndpoint = class {
|
|
40836
|
+
client;
|
|
40837
|
+
constructor(client) {
|
|
40838
|
+
this.client = client;
|
|
40839
|
+
}
|
|
40840
|
+
async list(params) {
|
|
40841
|
+
const { page, limit, offset } = this.client.resolvePagination(params);
|
|
40842
|
+
let query = this.client.db.from("logo_pool").select("*", { count: "exact" });
|
|
40843
|
+
if (params?.type)
|
|
40844
|
+
query = query.eq("type", params.type);
|
|
40845
|
+
if (params?.tone)
|
|
40846
|
+
query = query.eq("tone", params.tone);
|
|
40847
|
+
if (params?.font)
|
|
40848
|
+
query = query.eq("font", params.font);
|
|
40849
|
+
if (params?.hue !== void 0)
|
|
40850
|
+
query = query.eq("hue", params.hue);
|
|
40851
|
+
if (params?.isActive !== void 0)
|
|
40852
|
+
query = query.eq("is_active", params.isActive);
|
|
40853
|
+
if (params?.order) {
|
|
40854
|
+
query = query.order("created_at", { ascending: params.order === "asc" });
|
|
40855
|
+
} else {
|
|
40856
|
+
query = query.order("type", { ascending: true }).order("hue", { ascending: true }).order("name", { ascending: true });
|
|
40857
|
+
}
|
|
40858
|
+
const { data, error: error48, count } = await query.range(offset, offset + limit - 1);
|
|
40859
|
+
if (error48)
|
|
40860
|
+
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
40861
|
+
return {
|
|
40862
|
+
data: (data ?? []).map((r) => serializeLogo(r)),
|
|
40863
|
+
pagination: this.client.paginationMeta(page, limit, offset, count ?? 0)
|
|
40864
|
+
};
|
|
40865
|
+
}
|
|
40866
|
+
async get(id) {
|
|
40867
|
+
const { data, error: error48 } = await this.client.db.from("logo_pool").select("*").eq("id", id).single();
|
|
40868
|
+
if (error48)
|
|
40869
|
+
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
40870
|
+
return serializeLogo(data);
|
|
40871
|
+
}
|
|
40872
|
+
async create(params) {
|
|
40873
|
+
const values = {
|
|
40874
|
+
image_url: params.imageUrl,
|
|
40875
|
+
type: params.type,
|
|
40876
|
+
font: params.font,
|
|
40877
|
+
color: params.color,
|
|
40878
|
+
hue: params.hue,
|
|
40879
|
+
tone: params.tone,
|
|
40880
|
+
name: params.name
|
|
40881
|
+
};
|
|
40882
|
+
if (params.toneScore !== void 0)
|
|
40883
|
+
values.tone_score = params.toneScore;
|
|
40884
|
+
if (params.variant !== void 0)
|
|
40885
|
+
values.variant = params.variant;
|
|
40886
|
+
if (params.sha256 !== void 0)
|
|
40887
|
+
values.sha256 = params.sha256;
|
|
40888
|
+
if (params.width !== void 0)
|
|
40889
|
+
values.width = params.width;
|
|
40890
|
+
if (params.height !== void 0)
|
|
40891
|
+
values.height = params.height;
|
|
40892
|
+
if (params.aspectRatio !== void 0)
|
|
40893
|
+
values.aspect_ratio = params.aspectRatio;
|
|
40894
|
+
if (params.mimeType !== void 0)
|
|
40895
|
+
values.mime_type = params.mimeType;
|
|
40896
|
+
if (params.byteSize !== void 0)
|
|
40897
|
+
values.byte_size = params.byteSize;
|
|
40898
|
+
if (params.tags !== void 0)
|
|
40899
|
+
values.tags = params.tags;
|
|
40900
|
+
if (params.isActive !== void 0)
|
|
40901
|
+
values.is_active = params.isActive;
|
|
40902
|
+
const { data, error: error48 } = await this.client.db.from("logo_pool").insert(values).select().single();
|
|
40903
|
+
if (error48)
|
|
40904
|
+
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
40905
|
+
return serializeLogo(data);
|
|
40906
|
+
}
|
|
40907
|
+
async update(id, params) {
|
|
40908
|
+
const values = {};
|
|
40909
|
+
if (params.imageUrl !== void 0)
|
|
40910
|
+
values.image_url = params.imageUrl;
|
|
40911
|
+
if (params.type !== void 0)
|
|
40912
|
+
values.type = params.type;
|
|
40913
|
+
if (params.font !== void 0)
|
|
40914
|
+
values.font = params.font;
|
|
40915
|
+
if (params.color !== void 0)
|
|
40916
|
+
values.color = params.color;
|
|
40917
|
+
if (params.hue !== void 0)
|
|
40918
|
+
values.hue = params.hue;
|
|
40919
|
+
if (params.tone !== void 0)
|
|
40920
|
+
values.tone = params.tone;
|
|
40921
|
+
if (params.name !== void 0)
|
|
40922
|
+
values.name = params.name;
|
|
40923
|
+
if (params.toneScore !== void 0)
|
|
40924
|
+
values.tone_score = params.toneScore;
|
|
40925
|
+
if (params.variant !== void 0)
|
|
40926
|
+
values.variant = params.variant;
|
|
40927
|
+
if (params.sha256 !== void 0)
|
|
40928
|
+
values.sha256 = params.sha256;
|
|
40929
|
+
if (params.width !== void 0)
|
|
40930
|
+
values.width = params.width;
|
|
40931
|
+
if (params.height !== void 0)
|
|
40932
|
+
values.height = params.height;
|
|
40933
|
+
if (params.aspectRatio !== void 0)
|
|
40934
|
+
values.aspect_ratio = params.aspectRatio;
|
|
40935
|
+
if (params.mimeType !== void 0)
|
|
40936
|
+
values.mime_type = params.mimeType;
|
|
40937
|
+
if (params.byteSize !== void 0)
|
|
40938
|
+
values.byte_size = params.byteSize;
|
|
40939
|
+
if (params.tags !== void 0)
|
|
40940
|
+
values.tags = params.tags;
|
|
40941
|
+
if (params.isActive !== void 0)
|
|
40942
|
+
values.is_active = params.isActive;
|
|
40943
|
+
const { data, error: error48 } = await this.client.db.from("logo_pool").update(values).eq("id", id).select().single();
|
|
40944
|
+
if (error48)
|
|
40945
|
+
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
40946
|
+
return serializeLogo(data);
|
|
40947
|
+
}
|
|
40948
|
+
async delete(id) {
|
|
40949
|
+
const { error: error48 } = await this.client.db.from("logo_pool").delete().eq("id", id);
|
|
40950
|
+
if (error48)
|
|
40951
|
+
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
40952
|
+
return { id, deleted: true };
|
|
40953
|
+
}
|
|
40954
|
+
};
|
|
40955
|
+
|
|
40788
40956
|
// ../sdk/dist/client.js
|
|
40789
40957
|
var NeopressClient = class {
|
|
40790
40958
|
baseUrl;
|
|
@@ -40806,6 +40974,7 @@ var NeopressClient = class {
|
|
|
40806
40974
|
analytics;
|
|
40807
40975
|
templates;
|
|
40808
40976
|
headshots;
|
|
40977
|
+
logos;
|
|
40809
40978
|
constructor(options) {
|
|
40810
40979
|
this.baseUrl = (options.baseUrl || "https://app.neopress.ai").replace(/\/$/, "");
|
|
40811
40980
|
this.accessToken = options.accessToken || "";
|
|
@@ -40825,6 +40994,7 @@ var NeopressClient = class {
|
|
|
40825
40994
|
this.analytics = new AnalyticsEndpoint(this);
|
|
40826
40995
|
this.templates = new TemplatesEndpoint(this);
|
|
40827
40996
|
this.headshots = new HeadshotsEndpoint(this);
|
|
40997
|
+
this.logos = new LogosEndpoint(this);
|
|
40828
40998
|
}
|
|
40829
40999
|
get siteBasePath() {
|
|
40830
41000
|
return `/api/v1/sites/${this.siteId}`;
|
|
@@ -41842,7 +42012,7 @@ Examples:
|
|
|
41842
42012
|
var AGE_BANDS = ["young", "middle"];
|
|
41843
42013
|
var GENDERS = ["male", "female"];
|
|
41844
42014
|
var ETHNICITIES = ["asian", "white", "black", "latino"];
|
|
41845
|
-
var ATTIRES = ["formal"];
|
|
42015
|
+
var ATTIRES = ["formal", "casual"];
|
|
41846
42016
|
function validateEnum(value, allowed, flag) {
|
|
41847
42017
|
if (value !== void 0 && !allowed.includes(value)) {
|
|
41848
42018
|
fail(`${flag} must be one of: ${allowed.join(", ")}`);
|
|
@@ -41974,6 +42144,156 @@ Pass at least one field. --active/--inactive toggle is_active; --tags replaces t
|
|
|
41974
42144
|
});
|
|
41975
42145
|
}
|
|
41976
42146
|
|
|
42147
|
+
// src/commands/logos.ts
|
|
42148
|
+
var TYPES = ["wordmark", "lockup", "signature"];
|
|
42149
|
+
var TONES = ["playful", "neutral", "serious"];
|
|
42150
|
+
function validateEnum2(value, allowed, flag) {
|
|
42151
|
+
if (value !== void 0 && !allowed.includes(value)) {
|
|
42152
|
+
fail(`${flag} must be one of: ${allowed.join(", ")}`);
|
|
42153
|
+
}
|
|
42154
|
+
}
|
|
42155
|
+
function parseNonNegativeInt2(raw, flag) {
|
|
42156
|
+
if (raw === void 0) return void 0;
|
|
42157
|
+
const value = Number(raw);
|
|
42158
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
42159
|
+
fail(`${flag} must be a non-negative integer`);
|
|
42160
|
+
}
|
|
42161
|
+
return value;
|
|
42162
|
+
}
|
|
42163
|
+
function parseHue(raw) {
|
|
42164
|
+
if (raw === void 0) return void 0;
|
|
42165
|
+
const value = Number(raw);
|
|
42166
|
+
if (!Number.isInteger(value) || value < 0 || value > 11) {
|
|
42167
|
+
fail("--hue must be an integer 0-11 (12-bucket hue wheel)");
|
|
42168
|
+
}
|
|
42169
|
+
return value;
|
|
42170
|
+
}
|
|
42171
|
+
function registerLogoCommands(program3) {
|
|
42172
|
+
const logos = program3.command("logos").description("Manage the shared logo pool (super-admin only)").addHelpText("after", `
|
|
42173
|
+
Examples:
|
|
42174
|
+
$ neopress logos list --type lockup --tone playful
|
|
42175
|
+
$ neopress logos create --image-url https://cdn/x.webp --type wordmark --font geometric --color '#4f46e5' --hue 8 --tone neutral --name Northwind
|
|
42176
|
+
$ neopress logos update 12 --inactive
|
|
42177
|
+
The pool is global and RLS-gated: only the super-admin account can read or write it. No active site is needed.`);
|
|
42178
|
+
logos.command("list").description("List logo pool entries").option("--type <type>", `Filter by type (${TYPES.join("/")})`).option("--tone <tone>", `Filter by tone (${TONES.join("/")})`).option("--font <font>", "Filter by font family").option("--hue <n>", "Filter by hue bucket (0-11)").option("--active", "Only active entries").option("--inactive", "Only inactive entries").option("--order <asc|desc>", ORDER_OPTION_DESC).option("--page <n>", "Page number", "1").option("--limit <n>", "Results per page", "20").addHelpText("after", `
|
|
42179
|
+
Examples:
|
|
42180
|
+
$ neopress logos list
|
|
42181
|
+
$ neopress logos list --type signature --tone serious --active
|
|
42182
|
+
Filters are equality matches on the pool's diversity axes; results are paginated.`).action(async (options) => {
|
|
42183
|
+
validateEnum2(options.type, TYPES, "--type");
|
|
42184
|
+
validateEnum2(options.tone, TONES, "--tone");
|
|
42185
|
+
if (options.active && options.inactive) {
|
|
42186
|
+
fail("Use only one of --active or --inactive.");
|
|
42187
|
+
}
|
|
42188
|
+
const hue = parseHue(options.hue);
|
|
42189
|
+
const params = {
|
|
42190
|
+
page: parseInt(options.page, 10),
|
|
42191
|
+
limit: parseInt(options.limit, 10),
|
|
42192
|
+
order: parseOrder(options.order),
|
|
42193
|
+
type: options.type,
|
|
42194
|
+
tone: options.tone,
|
|
42195
|
+
font: options.font
|
|
42196
|
+
};
|
|
42197
|
+
if (hue !== void 0) params.hue = hue;
|
|
42198
|
+
if (options.active) params.isActive = true;
|
|
42199
|
+
else if (options.inactive) params.isActive = false;
|
|
42200
|
+
const client = await getGlobalClientAsync();
|
|
42201
|
+
const res = await client.logos.list(params);
|
|
42202
|
+
output(res);
|
|
42203
|
+
});
|
|
42204
|
+
logos.command("get <id>").description("Get a logo pool entry").action(async (id) => {
|
|
42205
|
+
const client = await getGlobalClientAsync();
|
|
42206
|
+
const data = await client.logos.get(parseInt(id, 10));
|
|
42207
|
+
output(data);
|
|
42208
|
+
});
|
|
42209
|
+
logos.command("create").description("Add a logo to the pool").requiredOption("--image-url <url>", "Public image URL").requiredOption("--type <type>", `Type (${TYPES.join("/")})`).requiredOption("--font <font>", "Font family, e.g. geometric").requiredOption("--color <hex>", "Brand ink hex, e.g. #4f46e5").requiredOption("--hue <n>", "Hue bucket (0-11)").requiredOption("--tone <tone>", `Tone (${TONES.join("/")})`).requiredOption("--name <name>", "Fictional brand name").option("--tone-score <n>", "Authored tone score (provenance)").option("--variant <variant>", "Variant descriptor, e.g. lk-mark7-left-duo").option("--sha256 <hash>", "Content hash").option("--width <n>", "Image width in px").option("--height <n>", "Image height in px").option("--aspect-ratio <ratio>", "Aspect ratio, e.g. 4:1").option("--mime-type <type>", "MIME type, e.g. image/webp").option("--byte-size <n>", "File size in bytes").option("--tags <csv>", "Comma-separated tags").option("--inactive", "Create as inactive (default active)").addHelpText("after", `
|
|
42210
|
+
Examples:
|
|
42211
|
+
$ neopress logos create --image-url https://cdn/a.webp --type lockup --font grotesk --color '#0d9488' --hue 5 --tone neutral --name Kestrel
|
|
42212
|
+
image_url is unique. The DB rejects out-of-range type/tone/hue values.`).action(async (options) => {
|
|
42213
|
+
validateEnum2(options.type, TYPES, "--type");
|
|
42214
|
+
validateEnum2(options.tone, TONES, "--tone");
|
|
42215
|
+
const hue = parseHue(options.hue);
|
|
42216
|
+
const params = {
|
|
42217
|
+
imageUrl: options.imageUrl,
|
|
42218
|
+
type: options.type,
|
|
42219
|
+
font: options.font,
|
|
42220
|
+
color: options.color,
|
|
42221
|
+
hue,
|
|
42222
|
+
tone: options.tone,
|
|
42223
|
+
name: options.name
|
|
42224
|
+
};
|
|
42225
|
+
if (options.toneScore !== void 0) {
|
|
42226
|
+
const n = Number(options.toneScore);
|
|
42227
|
+
if (Number.isNaN(n)) fail("--tone-score must be a number");
|
|
42228
|
+
params.toneScore = n;
|
|
42229
|
+
}
|
|
42230
|
+
if (options.variant) params.variant = options.variant;
|
|
42231
|
+
if (options.sha256) params.sha256 = options.sha256;
|
|
42232
|
+
const width = parseNonNegativeInt2(options.width, "--width");
|
|
42233
|
+
if (width !== void 0) params.width = width;
|
|
42234
|
+
const height = parseNonNegativeInt2(options.height, "--height");
|
|
42235
|
+
if (height !== void 0) params.height = height;
|
|
42236
|
+
if (options.aspectRatio) params.aspectRatio = options.aspectRatio;
|
|
42237
|
+
if (options.mimeType) params.mimeType = options.mimeType;
|
|
42238
|
+
const byteSize = parseNonNegativeInt2(options.byteSize, "--byte-size");
|
|
42239
|
+
if (byteSize !== void 0) params.byteSize = byteSize;
|
|
42240
|
+
if (options.tags) params.tags = String(options.tags).split(",").map((t) => t.trim()).filter(Boolean);
|
|
42241
|
+
if (options.inactive) params.isActive = false;
|
|
42242
|
+
const client = await getGlobalClientAsync();
|
|
42243
|
+
const data = await client.logos.create(params);
|
|
42244
|
+
output(data);
|
|
42245
|
+
});
|
|
42246
|
+
logos.command("update <id>").description("Update a logo pool entry").option("--image-url <url>", "Public image URL").option("--type <type>", `Type (${TYPES.join("/")})`).option("--font <font>", "Font family").option("--color <hex>", "Brand ink hex").option("--hue <n>", "Hue bucket (0-11)").option("--tone <tone>", `Tone (${TONES.join("/")})`).option("--name <name>", "Fictional brand name").option("--tone-score <n>", "Authored tone score").option("--variant <variant>", "Variant descriptor").option("--sha256 <hash>", "Content hash").option("--width <n>", "Image width in px").option("--height <n>", "Image height in px").option("--aspect-ratio <ratio>", "Aspect ratio, e.g. 4:1").option("--mime-type <type>", "MIME type, e.g. image/webp").option("--byte-size <n>", "File size in bytes").option("--tags <csv>", "Comma-separated tags (replaces existing)").option("--active", "Mark active").option("--inactive", "Mark inactive").addHelpText("after", `
|
|
42247
|
+
Examples:
|
|
42248
|
+
$ neopress logos update 12 --inactive
|
|
42249
|
+
$ neopress logos update 12 --tone playful --tags studio,flat
|
|
42250
|
+
Pass at least one field. --active/--inactive toggle is_active; --tags replaces the tag list.`).action(async (id, options) => {
|
|
42251
|
+
validateEnum2(options.type, TYPES, "--type");
|
|
42252
|
+
validateEnum2(options.tone, TONES, "--tone");
|
|
42253
|
+
if (options.active && options.inactive) {
|
|
42254
|
+
fail("Use only one of --active or --inactive.");
|
|
42255
|
+
}
|
|
42256
|
+
const params = {};
|
|
42257
|
+
if (options.imageUrl) params.imageUrl = options.imageUrl;
|
|
42258
|
+
if (options.type) params.type = options.type;
|
|
42259
|
+
if (options.font) params.font = options.font;
|
|
42260
|
+
if (options.color) params.color = options.color;
|
|
42261
|
+
const hue = parseHue(options.hue);
|
|
42262
|
+
if (hue !== void 0) params.hue = hue;
|
|
42263
|
+
if (options.tone) params.tone = options.tone;
|
|
42264
|
+
if (options.name) params.name = options.name;
|
|
42265
|
+
if (options.toneScore !== void 0) {
|
|
42266
|
+
const n = Number(options.toneScore);
|
|
42267
|
+
if (Number.isNaN(n)) fail("--tone-score must be a number");
|
|
42268
|
+
params.toneScore = n;
|
|
42269
|
+
}
|
|
42270
|
+
if (options.variant) params.variant = options.variant;
|
|
42271
|
+
if (options.sha256) params.sha256 = options.sha256;
|
|
42272
|
+
const width = parseNonNegativeInt2(options.width, "--width");
|
|
42273
|
+
if (width !== void 0) params.width = width;
|
|
42274
|
+
const height = parseNonNegativeInt2(options.height, "--height");
|
|
42275
|
+
if (height !== void 0) params.height = height;
|
|
42276
|
+
if (options.aspectRatio) params.aspectRatio = options.aspectRatio;
|
|
42277
|
+
if (options.mimeType) params.mimeType = options.mimeType;
|
|
42278
|
+
const byteSize = parseNonNegativeInt2(options.byteSize, "--byte-size");
|
|
42279
|
+
if (byteSize !== void 0) params.byteSize = byteSize;
|
|
42280
|
+
if (options.tags) params.tags = String(options.tags).split(",").map((t) => t.trim()).filter(Boolean);
|
|
42281
|
+
if (options.active) params.isActive = true;
|
|
42282
|
+
else if (options.inactive) params.isActive = false;
|
|
42283
|
+
if (Object.keys(params).length === 0) {
|
|
42284
|
+
fail("No fields to update.");
|
|
42285
|
+
}
|
|
42286
|
+
const client = await getGlobalClientAsync();
|
|
42287
|
+
const data = await client.logos.update(parseInt(id, 10), params);
|
|
42288
|
+
output(data);
|
|
42289
|
+
});
|
|
42290
|
+
logos.command("delete <id>").description("Delete a logo pool entry (hard delete)").action(async (id) => {
|
|
42291
|
+
const client = await getGlobalClientAsync();
|
|
42292
|
+
await client.logos.delete(parseInt(id, 10));
|
|
42293
|
+
ok(`Logo ${id} deleted`);
|
|
42294
|
+
});
|
|
42295
|
+
}
|
|
42296
|
+
|
|
41977
42297
|
// src/commands/guide.ts
|
|
41978
42298
|
function describeOption(opt) {
|
|
41979
42299
|
const info = { flags: opt.flags, description: opt.description || "" };
|
|
@@ -42058,7 +42378,7 @@ function registerGuideCommands(program3) {
|
|
|
42058
42378
|
|
|
42059
42379
|
// src/bin.ts
|
|
42060
42380
|
var program2 = new Command();
|
|
42061
|
-
program2.name("neopress").description("Neopress CLI \u2014 manage your site from the terminal").version("4.
|
|
42381
|
+
program2.name("neopress").description("Neopress CLI \u2014 manage your site from the terminal").version("4.6.0").option("--json", "Output in JSON format (for AI tools and pipes)").option("--site <idOrHandle>", "Target a specific site (overrides active site; not persisted)").option("--no-input", "Non-interactive mode").hook("preAction", (thisCommand) => {
|
|
42062
42382
|
const opts = thisCommand.optsWithGlobals();
|
|
42063
42383
|
if (opts.site) setSiteOverride(String(opts.site));
|
|
42064
42384
|
if (opts.json || !process.stdout.isTTY) setJsonMode(true);
|
|
@@ -42077,6 +42397,7 @@ registerEntryReferenceCommands(program2);
|
|
|
42077
42397
|
registerAnalyticsCommands(program2);
|
|
42078
42398
|
registerTemplateCommands(program2);
|
|
42079
42399
|
registerHeadshotCommands(program2);
|
|
42400
|
+
registerLogoCommands(program2);
|
|
42080
42401
|
registerGuideCommands(program2);
|
|
42081
42402
|
program2.addHelpText(
|
|
42082
42403
|
"after",
|
package/dist/index.js
CHANGED
|
@@ -21115,6 +21115,7 @@ function serializeRedirect(r) {
|
|
|
21115
21115
|
siteId: r.site_id,
|
|
21116
21116
|
source: r.source,
|
|
21117
21117
|
destination: r.destination,
|
|
21118
|
+
mode: r.mode,
|
|
21118
21119
|
redirectType: r.redirect_type,
|
|
21119
21120
|
includeChildren: r.include_children,
|
|
21120
21121
|
preservePath: r.preserve_path,
|
|
@@ -21166,6 +21167,30 @@ function serializeHeadshot(h) {
|
|
|
21166
21167
|
updatedAt: h.updated_at
|
|
21167
21168
|
};
|
|
21168
21169
|
}
|
|
21170
|
+
function serializeLogo(l) {
|
|
21171
|
+
return {
|
|
21172
|
+
id: l.id,
|
|
21173
|
+
imageUrl: l.image_url,
|
|
21174
|
+
width: l.width,
|
|
21175
|
+
height: l.height,
|
|
21176
|
+
aspectRatio: l.aspect_ratio,
|
|
21177
|
+
mimeType: l.mime_type,
|
|
21178
|
+
byteSize: l.byte_size,
|
|
21179
|
+
type: l.type,
|
|
21180
|
+
font: l.font,
|
|
21181
|
+
color: l.color,
|
|
21182
|
+
hue: l.hue,
|
|
21183
|
+
tone: l.tone,
|
|
21184
|
+
toneScore: l.tone_score,
|
|
21185
|
+
name: l.name,
|
|
21186
|
+
variant: l.variant,
|
|
21187
|
+
sha256: l.sha256,
|
|
21188
|
+
tags: l.tags ?? [],
|
|
21189
|
+
isActive: l.is_active,
|
|
21190
|
+
createdAt: l.created_at,
|
|
21191
|
+
updatedAt: l.updated_at
|
|
21192
|
+
};
|
|
21193
|
+
}
|
|
21169
21194
|
function serializeSite(site) {
|
|
21170
21195
|
return {
|
|
21171
21196
|
id: site.id,
|
|
@@ -21315,7 +21340,8 @@ var COLLECTION_FIELD_TYPES = [
|
|
|
21315
21340
|
"checkbox",
|
|
21316
21341
|
"radio",
|
|
21317
21342
|
"multi_checkbox",
|
|
21318
|
-
"consent"
|
|
21343
|
+
"consent",
|
|
21344
|
+
"place"
|
|
21319
21345
|
];
|
|
21320
21346
|
var COLLECTION_FIELD_TYPE_ALIASES = {
|
|
21321
21347
|
boolean: "bool",
|
|
@@ -35193,12 +35219,10 @@ var COLLECTION_PRESET_CONTRACTS = {
|
|
|
35193
35219
|
schema: {
|
|
35194
35220
|
title: titleField("Name"),
|
|
35195
35221
|
slug: slugField(),
|
|
35196
|
-
|
|
35197
|
-
address: field("address", "Address", "text"),
|
|
35198
|
-
city: field("city", "City", "text"),
|
|
35222
|
+
location: field("location", "Location", "place"),
|
|
35199
35223
|
description: field("description", "Description", "content")
|
|
35200
35224
|
},
|
|
35201
|
-
lockedFieldIds: ["title", "slug", "
|
|
35225
|
+
lockedFieldIds: ["title", "slug", "location"]
|
|
35202
35226
|
},
|
|
35203
35227
|
category: {
|
|
35204
35228
|
schema: {
|
|
@@ -36638,6 +36662,12 @@ var SiteEndpoint = class {
|
|
|
36638
36662
|
};
|
|
36639
36663
|
|
|
36640
36664
|
// ../sdk/dist/endpoints/redirects.js
|
|
36665
|
+
var DASHBOARD_ONLY_REWRITE_MESSAGE = "Rewrite proxy rules can only be managed in the dashboard.";
|
|
36666
|
+
function rejectModeParam(data) {
|
|
36667
|
+
if (data && typeof data === "object" && Object.prototype.hasOwnProperty.call(data, "mode")) {
|
|
36668
|
+
throw new NeopressApiError("REDIRECT_RULE_DASHBOARD_ONLY", DASHBOARD_ONLY_REWRITE_MESSAGE, 400);
|
|
36669
|
+
}
|
|
36670
|
+
}
|
|
36641
36671
|
var RedirectsEndpoint = class {
|
|
36642
36672
|
client;
|
|
36643
36673
|
constructor(client) {
|
|
@@ -36652,6 +36682,7 @@ var RedirectsEndpoint = class {
|
|
|
36652
36682
|
return (data ?? []).map((r) => serializeRedirect(r));
|
|
36653
36683
|
}
|
|
36654
36684
|
async create(data) {
|
|
36685
|
+
rejectModeParam(data);
|
|
36655
36686
|
const values = {
|
|
36656
36687
|
site_id: this.client.siteIdNumber,
|
|
36657
36688
|
source: data.source,
|
|
@@ -36667,7 +36698,21 @@ var RedirectsEndpoint = class {
|
|
|
36667
36698
|
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
36668
36699
|
return serializeRedirect(row);
|
|
36669
36700
|
}
|
|
36701
|
+
async assertRedirectRuleWritable(ruleId) {
|
|
36702
|
+
const { data, error: error48 } = await this.client.db.from("redirect_rules").select("id, mode").eq("site_id", this.client.siteIdNumber).eq("id", ruleId).maybeSingle();
|
|
36703
|
+
if (error48)
|
|
36704
|
+
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
36705
|
+
if (!data) {
|
|
36706
|
+
throw new NeopressApiError("REDIRECT_RULE_NOT_FOUND", `Redirect rule ${ruleId} not found for this site`, 404);
|
|
36707
|
+
}
|
|
36708
|
+
const row = data;
|
|
36709
|
+
if (row.mode === "proxy") {
|
|
36710
|
+
throw new NeopressApiError("REDIRECT_RULE_DASHBOARD_ONLY", DASHBOARD_ONLY_REWRITE_MESSAGE, 400);
|
|
36711
|
+
}
|
|
36712
|
+
}
|
|
36670
36713
|
async update(ruleId, data) {
|
|
36714
|
+
rejectModeParam(data);
|
|
36715
|
+
await this.assertRedirectRuleWritable(ruleId);
|
|
36671
36716
|
const values = {};
|
|
36672
36717
|
if ("source" in data)
|
|
36673
36718
|
values.source = data.source;
|
|
@@ -36689,6 +36734,7 @@ var RedirectsEndpoint = class {
|
|
|
36689
36734
|
return serializeRedirect(row);
|
|
36690
36735
|
}
|
|
36691
36736
|
async delete(ruleId) {
|
|
36737
|
+
await this.assertRedirectRuleWritable(ruleId);
|
|
36692
36738
|
const { error: error48 } = await this.client.db.from("redirect_rules").delete().eq("site_id", this.client.siteIdNumber).eq("id", ruleId);
|
|
36693
36739
|
if (error48)
|
|
36694
36740
|
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
@@ -37007,6 +37053,128 @@ var HeadshotsEndpoint = class {
|
|
|
37007
37053
|
}
|
|
37008
37054
|
};
|
|
37009
37055
|
|
|
37056
|
+
// ../sdk/dist/endpoints/logos.js
|
|
37057
|
+
var LogosEndpoint = class {
|
|
37058
|
+
client;
|
|
37059
|
+
constructor(client) {
|
|
37060
|
+
this.client = client;
|
|
37061
|
+
}
|
|
37062
|
+
async list(params) {
|
|
37063
|
+
const { page, limit, offset } = this.client.resolvePagination(params);
|
|
37064
|
+
let query = this.client.db.from("logo_pool").select("*", { count: "exact" });
|
|
37065
|
+
if (params?.type)
|
|
37066
|
+
query = query.eq("type", params.type);
|
|
37067
|
+
if (params?.tone)
|
|
37068
|
+
query = query.eq("tone", params.tone);
|
|
37069
|
+
if (params?.font)
|
|
37070
|
+
query = query.eq("font", params.font);
|
|
37071
|
+
if (params?.hue !== void 0)
|
|
37072
|
+
query = query.eq("hue", params.hue);
|
|
37073
|
+
if (params?.isActive !== void 0)
|
|
37074
|
+
query = query.eq("is_active", params.isActive);
|
|
37075
|
+
if (params?.order) {
|
|
37076
|
+
query = query.order("created_at", { ascending: params.order === "asc" });
|
|
37077
|
+
} else {
|
|
37078
|
+
query = query.order("type", { ascending: true }).order("hue", { ascending: true }).order("name", { ascending: true });
|
|
37079
|
+
}
|
|
37080
|
+
const { data, error: error48, count } = await query.range(offset, offset + limit - 1);
|
|
37081
|
+
if (error48)
|
|
37082
|
+
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
37083
|
+
return {
|
|
37084
|
+
data: (data ?? []).map((r) => serializeLogo(r)),
|
|
37085
|
+
pagination: this.client.paginationMeta(page, limit, offset, count ?? 0)
|
|
37086
|
+
};
|
|
37087
|
+
}
|
|
37088
|
+
async get(id) {
|
|
37089
|
+
const { data, error: error48 } = await this.client.db.from("logo_pool").select("*").eq("id", id).single();
|
|
37090
|
+
if (error48)
|
|
37091
|
+
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
37092
|
+
return serializeLogo(data);
|
|
37093
|
+
}
|
|
37094
|
+
async create(params) {
|
|
37095
|
+
const values = {
|
|
37096
|
+
image_url: params.imageUrl,
|
|
37097
|
+
type: params.type,
|
|
37098
|
+
font: params.font,
|
|
37099
|
+
color: params.color,
|
|
37100
|
+
hue: params.hue,
|
|
37101
|
+
tone: params.tone,
|
|
37102
|
+
name: params.name
|
|
37103
|
+
};
|
|
37104
|
+
if (params.toneScore !== void 0)
|
|
37105
|
+
values.tone_score = params.toneScore;
|
|
37106
|
+
if (params.variant !== void 0)
|
|
37107
|
+
values.variant = params.variant;
|
|
37108
|
+
if (params.sha256 !== void 0)
|
|
37109
|
+
values.sha256 = params.sha256;
|
|
37110
|
+
if (params.width !== void 0)
|
|
37111
|
+
values.width = params.width;
|
|
37112
|
+
if (params.height !== void 0)
|
|
37113
|
+
values.height = params.height;
|
|
37114
|
+
if (params.aspectRatio !== void 0)
|
|
37115
|
+
values.aspect_ratio = params.aspectRatio;
|
|
37116
|
+
if (params.mimeType !== void 0)
|
|
37117
|
+
values.mime_type = params.mimeType;
|
|
37118
|
+
if (params.byteSize !== void 0)
|
|
37119
|
+
values.byte_size = params.byteSize;
|
|
37120
|
+
if (params.tags !== void 0)
|
|
37121
|
+
values.tags = params.tags;
|
|
37122
|
+
if (params.isActive !== void 0)
|
|
37123
|
+
values.is_active = params.isActive;
|
|
37124
|
+
const { data, error: error48 } = await this.client.db.from("logo_pool").insert(values).select().single();
|
|
37125
|
+
if (error48)
|
|
37126
|
+
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
37127
|
+
return serializeLogo(data);
|
|
37128
|
+
}
|
|
37129
|
+
async update(id, params) {
|
|
37130
|
+
const values = {};
|
|
37131
|
+
if (params.imageUrl !== void 0)
|
|
37132
|
+
values.image_url = params.imageUrl;
|
|
37133
|
+
if (params.type !== void 0)
|
|
37134
|
+
values.type = params.type;
|
|
37135
|
+
if (params.font !== void 0)
|
|
37136
|
+
values.font = params.font;
|
|
37137
|
+
if (params.color !== void 0)
|
|
37138
|
+
values.color = params.color;
|
|
37139
|
+
if (params.hue !== void 0)
|
|
37140
|
+
values.hue = params.hue;
|
|
37141
|
+
if (params.tone !== void 0)
|
|
37142
|
+
values.tone = params.tone;
|
|
37143
|
+
if (params.name !== void 0)
|
|
37144
|
+
values.name = params.name;
|
|
37145
|
+
if (params.toneScore !== void 0)
|
|
37146
|
+
values.tone_score = params.toneScore;
|
|
37147
|
+
if (params.variant !== void 0)
|
|
37148
|
+
values.variant = params.variant;
|
|
37149
|
+
if (params.sha256 !== void 0)
|
|
37150
|
+
values.sha256 = params.sha256;
|
|
37151
|
+
if (params.width !== void 0)
|
|
37152
|
+
values.width = params.width;
|
|
37153
|
+
if (params.height !== void 0)
|
|
37154
|
+
values.height = params.height;
|
|
37155
|
+
if (params.aspectRatio !== void 0)
|
|
37156
|
+
values.aspect_ratio = params.aspectRatio;
|
|
37157
|
+
if (params.mimeType !== void 0)
|
|
37158
|
+
values.mime_type = params.mimeType;
|
|
37159
|
+
if (params.byteSize !== void 0)
|
|
37160
|
+
values.byte_size = params.byteSize;
|
|
37161
|
+
if (params.tags !== void 0)
|
|
37162
|
+
values.tags = params.tags;
|
|
37163
|
+
if (params.isActive !== void 0)
|
|
37164
|
+
values.is_active = params.isActive;
|
|
37165
|
+
const { data, error: error48 } = await this.client.db.from("logo_pool").update(values).eq("id", id).select().single();
|
|
37166
|
+
if (error48)
|
|
37167
|
+
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
37168
|
+
return serializeLogo(data);
|
|
37169
|
+
}
|
|
37170
|
+
async delete(id) {
|
|
37171
|
+
const { error: error48 } = await this.client.db.from("logo_pool").delete().eq("id", id);
|
|
37172
|
+
if (error48)
|
|
37173
|
+
throw new NeopressApiError("DB_ERROR", error48.message, 0, error48);
|
|
37174
|
+
return { id, deleted: true };
|
|
37175
|
+
}
|
|
37176
|
+
};
|
|
37177
|
+
|
|
37010
37178
|
// ../sdk/dist/client.js
|
|
37011
37179
|
var NeopressClient = class {
|
|
37012
37180
|
baseUrl;
|
|
@@ -37028,6 +37196,7 @@ var NeopressClient = class {
|
|
|
37028
37196
|
analytics;
|
|
37029
37197
|
templates;
|
|
37030
37198
|
headshots;
|
|
37199
|
+
logos;
|
|
37031
37200
|
constructor(options) {
|
|
37032
37201
|
this.baseUrl = (options.baseUrl || "https://app.neopress.ai").replace(/\/$/, "");
|
|
37033
37202
|
this.accessToken = options.accessToken || "";
|
|
@@ -37047,6 +37216,7 @@ var NeopressClient = class {
|
|
|
37047
37216
|
this.analytics = new AnalyticsEndpoint(this);
|
|
37048
37217
|
this.templates = new TemplatesEndpoint(this);
|
|
37049
37218
|
this.headshots = new HeadshotsEndpoint(this);
|
|
37219
|
+
this.logos = new LogosEndpoint(this);
|
|
37050
37220
|
}
|
|
37051
37221
|
get siteBasePath() {
|
|
37052
37222
|
return `/api/v1/sites/${this.siteId}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neopress/cli",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.0",
|
|
4
4
|
"description": "Neopress CLI — manage your Neopress site from the terminal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -21,14 +21,17 @@
|
|
|
21
21
|
"dist",
|
|
22
22
|
"README.md"
|
|
23
23
|
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=24"
|
|
26
|
+
},
|
|
24
27
|
"publishConfig": {
|
|
25
28
|
"access": "public"
|
|
26
29
|
},
|
|
27
30
|
"devDependencies": {
|
|
28
|
-
"@types/node": "^
|
|
31
|
+
"@types/node": "^24",
|
|
29
32
|
"commander": "^13.0.0",
|
|
30
33
|
"tsup": "^8.5.1",
|
|
31
|
-
"typescript": "^5.
|
|
34
|
+
"typescript": "^5.9.3",
|
|
32
35
|
"@neopress/sdk": "0.4.0"
|
|
33
36
|
},
|
|
34
37
|
"scripts": {
|