@applica-software-guru/didonato-storage-client 1.0.29

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 ADDED
@@ -0,0 +1,66 @@
1
+ # @applica-software-guru/didonato-storage-client
2
+
3
+ Client TypeScript package for Didonato Storage.
4
+
5
+ Quick start
6
+
7
+ Install:
8
+
9
+ ```bash
10
+ npm install @applica-software-guru/didonato-storage-client
11
+ ```
12
+
13
+ Usage (ESM):
14
+
15
+ ```ts
16
+ import DidonatoStorageClient from "@applica-software-guru/didonato-storage-client";
17
+
18
+ const c = new DidonatoStorageClient({ baseUrl: "https://example.com" });
19
+ console.log(await c.getSignedUrl("path/to/file"));
20
+ ```
21
+
22
+ ## Authentication
23
+
24
+ The client accepts an optional `token` option which can be provided in two ways:
25
+
26
+ - As a static token string: `new DidonatoStorageClient({ token: 'my-token' })`.
27
+ - As a function that returns a token (sync or async): `new DidonatoStorageClient({ token: () => fetchToken() })`.
28
+
29
+ Examples
30
+
31
+ 1. Pass a static token:
32
+
33
+ ```ts
34
+ import DidonatoStorageClient from "@applica-software-guru/didonato-storage-client";
35
+
36
+ const client = new DidonatoStorageClient({ baseUrl: "https://example.com", token: "MY_STATIC_TOKEN" });
37
+ // methods will include `Authorization: Bearer MY_STATIC_TOKEN` when calling the server
38
+ ```
39
+
40
+ 2. Pass a token factory (sync or async):
41
+
42
+ ```ts
43
+ import DidonatoStorageClient from '@applica-software-guru/didonato-storage-client';
44
+
45
+ // sync factory
46
+ const clientSync = new DidonatoStorageClient({ baseUrl: 'https://example.com', token: () => 'token-from-fn' });
47
+
48
+ // async factory
49
+ const clientAsync = new DidonatoStorageClient({
50
+ baseUrl: 'https://example.com',
51
+ token: async () => {
52
+ // refresh or fetch token from secure storage
53
+ return await getFreshToken();
54
+ }
55
+ });
56
+
57
+ // The library will call your function before requests and attach
58
+ // `Authorization: Bearer <token>` header when present.
59
+
60
+ Notes
61
+ -----
62
+ - If you need to pass custom headers beyond Authorization, call the low-level endpoints
63
+ on your server or extend the client.
64
+ - The token option is optional; if omitted, requests are sent without an Authorization header.
65
+
66
+ ```
@@ -0,0 +1,24 @@
1
+ interface DidonatoOptions {
2
+ baseUrl?: string;
3
+ bucket?: string;
4
+ credentials?: Record<string, any>;
5
+ /**
6
+ * A static token string (Bearer) or a function that returns a token string (sync or Promise)
7
+ */
8
+ token?: string | (() => string | Promise<string>);
9
+ }
10
+ declare class DidonatoStorageClient {
11
+ options: DidonatoOptions;
12
+ constructor(opts?: DidonatoOptions);
13
+ getToken(): Promise<string | undefined>;
14
+ getSignedUrl(key: string, expiresSec?: number): Promise<string>;
15
+ createSignedPost(key: string): Promise<{
16
+ url: string;
17
+ fields: Record<string, string>;
18
+ }>;
19
+ uploadWithSignedPost(url: string, fields: Record<string, string>, body: Buffer | Blob | string): Promise<boolean>;
20
+ delete(key: string): Promise<boolean>;
21
+ list(prefix?: string): Promise<string[]>;
22
+ }
23
+
24
+ export { type DidonatoOptions, DidonatoStorageClient, DidonatoStorageClient as default };
@@ -0,0 +1,24 @@
1
+ interface DidonatoOptions {
2
+ baseUrl?: string;
3
+ bucket?: string;
4
+ credentials?: Record<string, any>;
5
+ /**
6
+ * A static token string (Bearer) or a function that returns a token string (sync or Promise)
7
+ */
8
+ token?: string | (() => string | Promise<string>);
9
+ }
10
+ declare class DidonatoStorageClient {
11
+ options: DidonatoOptions;
12
+ constructor(opts?: DidonatoOptions);
13
+ getToken(): Promise<string | undefined>;
14
+ getSignedUrl(key: string, expiresSec?: number): Promise<string>;
15
+ createSignedPost(key: string): Promise<{
16
+ url: string;
17
+ fields: Record<string, string>;
18
+ }>;
19
+ uploadWithSignedPost(url: string, fields: Record<string, string>, body: Buffer | Blob | string): Promise<boolean>;
20
+ delete(key: string): Promise<boolean>;
21
+ list(prefix?: string): Promise<string[]>;
22
+ }
23
+
24
+ export { type DidonatoOptions, DidonatoStorageClient, DidonatoStorageClient as default };
package/dist/index.js ADDED
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ DidonatoStorageClient: () => DidonatoStorageClient,
34
+ default: () => DidonatoStorageClient
35
+ });
36
+ module.exports = __toCommonJS(index_exports);
37
+
38
+ // src/DidonatoStorageClient.ts
39
+ var import_cross_fetch = __toESM(require("cross-fetch"));
40
+ var DidonatoStorageClient = class {
41
+ constructor(opts = {}) {
42
+ this.options = opts;
43
+ }
44
+ async getToken() {
45
+ const t = this.options.token;
46
+ if (!t) return void 0;
47
+ if (typeof t === "function") {
48
+ try {
49
+ return await t();
50
+ } catch (err) {
51
+ return void 0;
52
+ }
53
+ }
54
+ return String(t);
55
+ }
56
+ async getSignedUrl(key, expiresSec = 3600) {
57
+ return `${this.options.baseUrl || "https://storage.example.com"}/signed/${encodeURIComponent(
58
+ key
59
+ )}?exp=${expiresSec}`;
60
+ }
61
+ async createSignedPost(key) {
62
+ const url = `${this.options.baseUrl || ""}/signed-post/${encodeURIComponent(key)}`;
63
+ const res = await (0, import_cross_fetch.default)(url);
64
+ if (!res.ok) throw new Error("failed to get signed post");
65
+ const json = await res.json();
66
+ return json;
67
+ }
68
+ async uploadWithSignedPost(url, fields, body) {
69
+ if (typeof FormData !== "undefined") {
70
+ const fd = new FormData();
71
+ for (const k in fields) fd.append(k, fields[k]);
72
+ fd.append("file", body);
73
+ const res = await (0, import_cross_fetch.default)(url, { method: "POST", body: fd });
74
+ return res.ok;
75
+ }
76
+ throw new Error("FormData not available; use form-data package in Node tests");
77
+ }
78
+ async delete(key) {
79
+ const url = `${this.options.baseUrl || ""}/objects/${encodeURIComponent(key)}`;
80
+ const token = await this.getToken();
81
+ const headers = token ? { Authorization: `Bearer ${token}` } : void 0;
82
+ const res = await (0, import_cross_fetch.default)(url, { method: "DELETE", headers });
83
+ return res.ok;
84
+ }
85
+ async list(prefix = "") {
86
+ const url = `${this.options.baseUrl || ""}/objects?prefix=${encodeURIComponent(prefix)}`;
87
+ const token = await this.getToken();
88
+ const headers = token ? { Authorization: `Bearer ${token}` } : void 0;
89
+ const res = await (0, import_cross_fetch.default)(url, { headers });
90
+ if (!res.ok) return [];
91
+ const json = await res.json();
92
+ return Array.isArray(json) ? json : [];
93
+ }
94
+ };
95
+ // Annotate the CommonJS export names for ESM import in node:
96
+ 0 && (module.exports = {
97
+ DidonatoStorageClient
98
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,61 @@
1
+ // src/DidonatoStorageClient.ts
2
+ import fetch from "cross-fetch";
3
+ var DidonatoStorageClient = class {
4
+ constructor(opts = {}) {
5
+ this.options = opts;
6
+ }
7
+ async getToken() {
8
+ const t = this.options.token;
9
+ if (!t) return void 0;
10
+ if (typeof t === "function") {
11
+ try {
12
+ return await t();
13
+ } catch (err) {
14
+ return void 0;
15
+ }
16
+ }
17
+ return String(t);
18
+ }
19
+ async getSignedUrl(key, expiresSec = 3600) {
20
+ return `${this.options.baseUrl || "https://storage.example.com"}/signed/${encodeURIComponent(
21
+ key
22
+ )}?exp=${expiresSec}`;
23
+ }
24
+ async createSignedPost(key) {
25
+ const url = `${this.options.baseUrl || ""}/signed-post/${encodeURIComponent(key)}`;
26
+ const res = await fetch(url);
27
+ if (!res.ok) throw new Error("failed to get signed post");
28
+ const json = await res.json();
29
+ return json;
30
+ }
31
+ async uploadWithSignedPost(url, fields, body) {
32
+ if (typeof FormData !== "undefined") {
33
+ const fd = new FormData();
34
+ for (const k in fields) fd.append(k, fields[k]);
35
+ fd.append("file", body);
36
+ const res = await fetch(url, { method: "POST", body: fd });
37
+ return res.ok;
38
+ }
39
+ throw new Error("FormData not available; use form-data package in Node tests");
40
+ }
41
+ async delete(key) {
42
+ const url = `${this.options.baseUrl || ""}/objects/${encodeURIComponent(key)}`;
43
+ const token = await this.getToken();
44
+ const headers = token ? { Authorization: `Bearer ${token}` } : void 0;
45
+ const res = await fetch(url, { method: "DELETE", headers });
46
+ return res.ok;
47
+ }
48
+ async list(prefix = "") {
49
+ const url = `${this.options.baseUrl || ""}/objects?prefix=${encodeURIComponent(prefix)}`;
50
+ const token = await this.getToken();
51
+ const headers = token ? { Authorization: `Bearer ${token}` } : void 0;
52
+ const res = await fetch(url, { headers });
53
+ if (!res.ok) return [];
54
+ const json = await res.json();
55
+ return Array.isArray(json) ? json : [];
56
+ }
57
+ };
58
+ export {
59
+ DidonatoStorageClient,
60
+ DidonatoStorageClient as default
61
+ };
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@applica-software-guru/didonato-storage-client",
3
+ "version": "1.0.29",
4
+ "description": "Client per Didonato Storage (Node + Browser)",
5
+ "main": "dist/index.cjs",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
13
+ "test": "vitest",
14
+ "prepare": "npm run build"
15
+ },
16
+ "keywords": [
17
+ "didonato",
18
+ "storage",
19
+ "gcs",
20
+ "signed-post"
21
+ ],
22
+ "author": "applica-software-guru",
23
+ "license": "MIT",
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "dependencies": {
28
+ "cross-fetch": "^4.1.0",
29
+ "form-data": "^4.0.5"
30
+ },
31
+ "devDependencies": {
32
+ "tsup": "^8.5.1",
33
+ "typescript": "^5.9.3",
34
+ "vitest": "^4.0.16",
35
+ "@types/node": "^25.0.3"
36
+ }
37
+ }