@anakonn/ankk 0.1.2 → 0.1.3

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.
Files changed (2) hide show
  1. package/dist/index.js +238 -66
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2157,7 +2157,7 @@ var {
2157
2157
  // package.json
2158
2158
  var package_default = {
2159
2159
  name: "@anakonn/ankk",
2160
- version: "0.1.2",
2160
+ version: "0.1.3",
2161
2161
  description: "Bun-first CLI for the ankk public API.",
2162
2162
  private: false,
2163
2163
  license: "UNLICENSED",
@@ -2697,12 +2697,171 @@ var configureCommanderOutput = (program2, io) => {
2697
2697
  };
2698
2698
  var isSuccessfulCommanderExit = (error) => typeof error === "object" && error !== null && ("exitCode" in error) && error.exitCode === 0;
2699
2699
 
2700
+ // src/brand-image-upload.ts
2701
+ import { readFile, stat } from "fs/promises";
2702
+ import { basename } from "path";
2703
+
2704
+ // src/output.ts
2705
+ var defaultIo = {
2706
+ stderr: process.stderr,
2707
+ stdout: process.stdout
2708
+ };
2709
+ var writeOutput = (io, mode, value, human) => {
2710
+ if (mode === "json") {
2711
+ io.stdout.write(`${JSON.stringify(value, null, 2)}
2712
+ `);
2713
+ return;
2714
+ }
2715
+ io.stdout.write(`${human}
2716
+ `);
2717
+ };
2718
+ var writeError = (io, error, mode = "human") => {
2719
+ if (mode === "json") {
2720
+ io.stderr.write(`${JSON.stringify(errorJson(error), null, 2)}
2721
+ `);
2722
+ return;
2723
+ }
2724
+ if (error instanceof CliHttpError) {
2725
+ io.stderr.write(`${error.message}
2726
+ `);
2727
+ return;
2728
+ }
2729
+ if (error instanceof Error) {
2730
+ io.stderr.write(`${error.message}
2731
+ `);
2732
+ return;
2733
+ }
2734
+ io.stderr.write(`Unexpected CLI error.
2735
+ `);
2736
+ };
2737
+ var errorJson = (error) => {
2738
+ if (error instanceof CliHttpError) {
2739
+ const body = error.body && typeof error.body === "object" && !Array.isArray(error.body) ? error.body : {};
2740
+ return {
2741
+ error: "http_error",
2742
+ message: error.message,
2743
+ ...body,
2744
+ status: error.status
2745
+ };
2746
+ }
2747
+ if (error instanceof Error) {
2748
+ return {
2749
+ error: "cli_error",
2750
+ message: error.message
2751
+ };
2752
+ }
2753
+ return {
2754
+ error: "unexpected_cli_error",
2755
+ message: "Unexpected CLI error."
2756
+ };
2757
+ };
2758
+
2759
+ // src/brand-image-upload.ts
2760
+ var runBrandImageUploadCommand = async ({
2761
+ alt,
2762
+ brandRef,
2763
+ client,
2764
+ contentType,
2765
+ description,
2766
+ fetch,
2767
+ file,
2768
+ io,
2769
+ outputMode,
2770
+ type
2771
+ }) => {
2772
+ const upload = await readBrandImageUploadFile(file, contentType);
2773
+ const prepared = responseOrThrow(await client.POST("/v1/brand-images/uploads", {
2774
+ body: {
2775
+ brand_ref: brandRef,
2776
+ content_type: upload.contentType,
2777
+ filename: upload.filename,
2778
+ size: upload.size
2779
+ }
2780
+ }));
2781
+ const uploaded = await fetch(prepared.upload_url, {
2782
+ body: upload.data,
2783
+ headers: {
2784
+ "content-type": prepared.content_type
2785
+ },
2786
+ method: prepared.method
2787
+ });
2788
+ if (!uploaded.ok) {
2789
+ throw new Error(`Brand image upload failed with HTTP ${uploaded.status}.`);
2790
+ }
2791
+ const image = responseOrThrow(await client.POST("/v1/brand-images", {
2792
+ body: {
2793
+ brand_ref: brandRef,
2794
+ origin_url: prepared.origin_url,
2795
+ ...type ? { type } : {},
2796
+ ...alt !== undefined ? { alt } : {},
2797
+ ...description !== undefined ? { description } : {}
2798
+ }
2799
+ }));
2800
+ writeOutput(io, outputMode, {
2801
+ ...image,
2802
+ uploaded: true
2803
+ }, `image_ref: ${image.image_ref}
2804
+ url: ${image.url}`);
2805
+ };
2806
+ var brandImageUploadPolicies = {
2807
+ ".gif": { contentType: "image/gif", maxSize: 20 * 1024 * 1024 },
2808
+ ".jpeg": { contentType: "image/jpeg", maxSize: 20 * 1024 * 1024 },
2809
+ ".jpg": { contentType: "image/jpeg", maxSize: 20 * 1024 * 1024 },
2810
+ ".png": { contentType: "image/png", maxSize: 20 * 1024 * 1024 },
2811
+ ".webp": { contentType: "image/webp", maxSize: 20 * 1024 * 1024 }
2812
+ };
2813
+ var readBrandImageUploadFile = async (file, contentTypeOverride) => {
2814
+ const filename = basename(file);
2815
+ const extension = brandImageExtension(filename);
2816
+ const extensionPolicy = brandImageUploadPolicies[extension];
2817
+ const contentType = contentTypeOverride?.trim().toLowerCase() || extensionPolicy.contentType;
2818
+ const contentTypePolicy = brandImageUploadPolicyForContentType(contentType);
2819
+ if (!contentTypePolicy) {
2820
+ throw new Error(`Unsupported brand image content type: ${contentType}`);
2821
+ }
2822
+ if (!contentTypePolicy.extensions.includes(extension)) {
2823
+ throw new Error(`Brand image file extension does not match content type: ${filename} (${contentType})`);
2824
+ }
2825
+ const info = await stat(file);
2826
+ if (!info.isFile()) {
2827
+ throw new Error(`Brand image path is not a file: ${file}`);
2828
+ }
2829
+ if (info.size <= 0) {
2830
+ throw new Error("Brand image file is empty.");
2831
+ }
2832
+ if (info.size > contentTypePolicy.maxSize) {
2833
+ throw new Error(`Brand image file exceeds ${contentTypePolicy.maxSize} bytes.`);
2834
+ }
2835
+ return {
2836
+ contentType,
2837
+ data: await readFile(file),
2838
+ filename,
2839
+ size: info.size
2840
+ };
2841
+ };
2842
+ var brandImageExtension = (filename) => {
2843
+ const index = filename.lastIndexOf(".");
2844
+ const extension = index > 0 ? filename.slice(index).toLowerCase() : "";
2845
+ if (extension in brandImageUploadPolicies)
2846
+ return extension;
2847
+ throw new Error(`Unsupported brand image file extension: ${filename}`);
2848
+ };
2849
+ var brandImageUploadPolicyForContentType = (contentType) => {
2850
+ const extensions = Object.entries(brandImageUploadPolicies).filter(([, policy]) => policy.contentType === contentType).map(([extension]) => extension);
2851
+ if (extensions.length === 0)
2852
+ return null;
2853
+ return {
2854
+ extensions,
2855
+ maxSize: brandImageUploadPolicies[extensions[0] ?? ".jpg"].maxSize
2856
+ };
2857
+ };
2858
+
2700
2859
  // src/config-command.ts
2701
2860
  import { createInterface } from "readline/promises";
2702
2861
  import { Writable } from "stream";
2703
2862
 
2704
2863
  // src/config.ts
2705
- import { mkdir, readFile, writeFile } from "fs/promises";
2864
+ import { mkdir, readFile as readFile2, writeFile } from "fs/promises";
2706
2865
  import { dirname, join } from "path";
2707
2866
 
2708
2867
  // ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
@@ -16999,7 +17158,7 @@ var defaultConfigPath = ({
16999
17158
  };
17000
17159
  var loadConfig = async (path) => {
17001
17160
  try {
17002
- const raw = await readFile(path, "utf8");
17161
+ const raw = await readFile2(path, "utf8");
17003
17162
  return configSchema.parse(JSON.parse(raw));
17004
17163
  } catch (error51) {
17005
17164
  if (isMissingFileError(error51))
@@ -17009,7 +17168,7 @@ var loadConfig = async (path) => {
17009
17168
  };
17010
17169
  var configFileExists = async (path) => {
17011
17170
  try {
17012
- await readFile(path, "utf8");
17171
+ await readFile2(path, "utf8");
17013
17172
  return true;
17014
17173
  } catch (error51) {
17015
17174
  if (isMissingFileError(error51))
@@ -17049,61 +17208,6 @@ var redactApiKey = (apiKey) => {
17049
17208
  var normalizeBaseUrl = (value) => value.replace(/\/+$/, "");
17050
17209
  var isMissingFileError = (error51) => typeof error51 === "object" && error51 !== null && ("code" in error51) && error51.code === "ENOENT";
17051
17210
 
17052
- // src/output.ts
17053
- var defaultIo = {
17054
- stderr: process.stderr,
17055
- stdout: process.stdout
17056
- };
17057
- var writeOutput = (io, mode, value, human) => {
17058
- if (mode === "json") {
17059
- io.stdout.write(`${JSON.stringify(value, null, 2)}
17060
- `);
17061
- return;
17062
- }
17063
- io.stdout.write(`${human}
17064
- `);
17065
- };
17066
- var writeError = (io, error51, mode = "human") => {
17067
- if (mode === "json") {
17068
- io.stderr.write(`${JSON.stringify(errorJson(error51), null, 2)}
17069
- `);
17070
- return;
17071
- }
17072
- if (error51 instanceof CliHttpError) {
17073
- io.stderr.write(`${error51.message}
17074
- `);
17075
- return;
17076
- }
17077
- if (error51 instanceof Error) {
17078
- io.stderr.write(`${error51.message}
17079
- `);
17080
- return;
17081
- }
17082
- io.stderr.write(`Unexpected CLI error.
17083
- `);
17084
- };
17085
- var errorJson = (error51) => {
17086
- if (error51 instanceof CliHttpError) {
17087
- const body = error51.body && typeof error51.body === "object" && !Array.isArray(error51.body) ? error51.body : {};
17088
- return {
17089
- error: "http_error",
17090
- message: error51.message,
17091
- ...body,
17092
- status: error51.status
17093
- };
17094
- }
17095
- if (error51 instanceof Error) {
17096
- return {
17097
- error: "cli_error",
17098
- message: error51.message
17099
- };
17100
- }
17101
- return {
17102
- error: "unexpected_cli_error",
17103
- message: "Unexpected CLI error."
17104
- };
17105
- };
17106
-
17107
17211
  // src/config-command.ts
17108
17212
  var registerConfigCommands = ({
17109
17213
  env,
@@ -17359,9 +17463,9 @@ var formatSnsContent = (response) => {
17359
17463
  };
17360
17464
 
17361
17465
  // src/json-input.ts
17362
- import { readFile as readFile2 } from "fs/promises";
17466
+ import { readFile as readFile3 } from "fs/promises";
17363
17467
  var readJsonInput = async (path, { readStdin = readProcessStdin } = {}) => {
17364
- const raw = path === "-" ? await readStdin() : await readFile2(path, "utf8");
17468
+ const raw = path === "-" ? await readStdin() : await readFile3(path, "utf8");
17365
17469
  try {
17366
17470
  return JSON.parse(raw);
17367
17471
  } catch (error51) {
@@ -17374,8 +17478,8 @@ var readJsonInput = async (path, { readStdin = readProcessStdin } = {}) => {
17374
17478
  var readProcessStdin = async () => Bun.stdin.text();
17375
17479
 
17376
17480
  // src/media-upload.ts
17377
- import { readFile as readFile3, stat } from "fs/promises";
17378
- import { basename } from "path";
17481
+ import { readFile as readFile4, stat as stat2 } from "fs/promises";
17482
+ import { basename as basename2 } from "path";
17379
17483
  var runMediaUploadCommand = async ({
17380
17484
  brandRef,
17381
17485
  client,
@@ -17420,7 +17524,7 @@ var mediaUploadPolicies = {
17420
17524
  ".webp": { contentType: "image/webp", maxSize: 20 * 1024 * 1024 }
17421
17525
  };
17422
17526
  var readMediaUploadFile = async (file2, contentTypeOverride) => {
17423
- const filename = basename(file2);
17527
+ const filename = basename2(file2);
17424
17528
  const extension = mediaExtension(filename);
17425
17529
  const extensionPolicy = mediaUploadPolicies[extension];
17426
17530
  const contentType = contentTypeOverride?.trim().toLowerCase() || extensionPolicy.contentType;
@@ -17431,7 +17535,7 @@ var readMediaUploadFile = async (file2, contentTypeOverride) => {
17431
17535
  if (!contentTypePolicy.extensions.includes(extension)) {
17432
17536
  throw new Error(`Media file extension does not match content type: ${filename} (${contentType})`);
17433
17537
  }
17434
- const info = await stat(file2);
17538
+ const info = await stat2(file2);
17435
17539
  if (!info.isFile()) {
17436
17540
  throw new Error(`Media path is not a file: ${file2}`);
17437
17541
  }
@@ -17443,7 +17547,7 @@ var readMediaUploadFile = async (file2, contentTypeOverride) => {
17443
17547
  }
17444
17548
  return {
17445
17549
  contentType,
17446
- data: await readFile3(file2),
17550
+ data: await readFile4(file2),
17447
17551
  filename,
17448
17552
  size: info.size
17449
17553
  };
@@ -17639,6 +17743,68 @@ var createProgram = ({
17639
17743
  outputMode: context.outputMode
17640
17744
  });
17641
17745
  });
17746
+ const brandImages = program2.command("brand-images").description("Manage brand images shown in the web brand image screen");
17747
+ withBrandRef(brandImages.command("list").description("List brand images")).option("--type <type>", "Image type filter: logo, banner, product, gallery, other").action(async (options) => {
17748
+ const context = await resolveCommandContext({ env, fetch, io, program: program2 });
17749
+ const type = options.type ? parseBrandImageType(options.type) : undefined;
17750
+ const result = responseOrThrow(await context.client.GET("/v1/brand-images", {
17751
+ params: {
17752
+ query: {
17753
+ brand_ref: options.brandRef,
17754
+ ...type ? { type } : {}
17755
+ }
17756
+ }
17757
+ }));
17758
+ writeOutput(context.io, context.outputMode, result, formatGenericRead(result));
17759
+ });
17760
+ withBrandRef(brandImages.command("upload").description("Upload and register a brand image").argument("<file>", "Image file path")).option("--type <type>", "Image type: logo, banner, product, gallery, other").option("--alt <text>", "Alternative text").option("--description <text>", "Image description").option("--content-type <content_type>", "Override detected MIME type").action(async (file2, options) => {
17761
+ const context = await resolveCommandContext({ env, fetch, io, program: program2 });
17762
+ await runBrandImageUploadCommand({
17763
+ alt: options.alt,
17764
+ brandRef: options.brandRef,
17765
+ client: context.client,
17766
+ contentType: options.contentType,
17767
+ description: options.description,
17768
+ fetch,
17769
+ file: file2,
17770
+ io: context.io,
17771
+ outputMode: context.outputMode,
17772
+ type: options.type ? parseBrandImageType(options.type) : undefined
17773
+ });
17774
+ });
17775
+ withBrandRef(brandImages.command("update").description("Update brand image metadata").argument("<image_ref>", "Brand image reference")).option("--type <type>", "Image type: logo, banner, product, gallery, other").option("--alt <text>", "Alternative text").option("--description <text>", "Image description").action(async (imageRef, options) => {
17776
+ const context = await resolveCommandContext({ env, fetch, io, program: program2 });
17777
+ const result = responseOrThrow(await context.client.PATCH("/v1/brand-images/{image_ref}", {
17778
+ body: apiBody({
17779
+ ...options.type ? { type: parseBrandImageType(options.type) } : {},
17780
+ ...options.alt !== undefined ? { alt: options.alt } : {},
17781
+ ...options.description !== undefined ? { description: options.description } : {}
17782
+ }),
17783
+ params: {
17784
+ path: {
17785
+ image_ref: imageRef
17786
+ },
17787
+ query: {
17788
+ brand_ref: options.brandRef
17789
+ }
17790
+ }
17791
+ }));
17792
+ writeOutput(context.io, context.outputMode, result, `Brand image updated: ${result.image_ref}`);
17793
+ });
17794
+ withBrandRef(brandImages.command("delete").description("Delete brand image metadata").argument("<image_ref>", "Brand image reference")).action(async (imageRef, options) => {
17795
+ const context = await resolveCommandContext({ env, fetch, io, program: program2 });
17796
+ const result = responseOrThrow(await context.client.DELETE("/v1/brand-images/{image_ref}", {
17797
+ params: {
17798
+ path: {
17799
+ image_ref: imageRef
17800
+ },
17801
+ query: {
17802
+ brand_ref: options.brandRef
17803
+ }
17804
+ }
17805
+ }));
17806
+ writeOutput(context.io, context.outputMode, result, `Brand image deleted: ${result.image_ref}`);
17807
+ });
17642
17808
  withBrandRef(content.command("cancel").description("Cancel scheduled SNS content").argument("<content_id>", "Content id")).option("--file <path>", "JSON request body file, or - for stdin").action(async (contentId, options) => {
17643
17809
  const context = await resolveCommandContext({ env, fetch, io, program: program2 });
17644
17810
  const body = await readBodyOrBrandRef(options, "SNS content cancel body");
@@ -17998,6 +18164,12 @@ var readObjectBody = (value, name) => {
17998
18164
  return value;
17999
18165
  };
18000
18166
  var apiBody = (body) => body;
18167
+ var brandImageTypes = ["logo", "banner", "product", "gallery", "other"];
18168
+ var parseBrandImageType = (value) => {
18169
+ if (brandImageTypes.includes(value))
18170
+ return value;
18171
+ throw new Error(`Unsupported brand image type: ${value}`);
18172
+ };
18001
18173
  var readBodyOrBrandRef = async (options, name) => {
18002
18174
  if (options.file) {
18003
18175
  return readObjectBody(await readJsonInput(options.file), name);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anakonn/ankk",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Bun-first CLI for the ankk public API.",
5
5
  "private": false,
6
6
  "license": "UNLICENSED",