@neonwilderness/ecjsonstorage 1.0.3 → 1.0.5
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/CHANGELOG.md +3 -0
- package/README.md +171 -21
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
- package/src/index.ts +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -18,3 +18,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
18
18
|
## [1.0.3] - 2026-09-30
|
|
19
19
|
- Change package name to @neonwilderness/ecjsonstorage
|
|
20
20
|
- Adapt installation
|
|
21
|
+
|
|
22
|
+
## [1.0.4] - 2026-10-01
|
|
23
|
+
- Throw when param "bin" is missing (getBin, updateBin, patchBin and deleteBin)
|
package/README.md
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
# About ECJsonStorage
|
|
2
2
|
ECJsonStorage is a TS/JS wrapper to the [ExtendsClass JSON Storage API](https://extendsclass.com/json-storage.html) offering of Cyril Bois.
|
|
3
3
|
|
|
4
|
-
For API usage, you need a (free) API-Key for which you can apply [
|
|
4
|
+
For API usage, you need a (free) API-Key for which you can apply on the [ExtendsClass site](https://extendsclass.com/create-account-form).
|
|
5
5
|
|
|
6
|
-
ECJsonStorage enables you to create, update, patch and delete Bins
|
|
6
|
+
ECJsonStorage enables you to create, update, patch and delete "Bins" to store JSON data. There is a usage limit of
|
|
7
7
|
- 10.000 calls per month
|
|
8
8
|
- Bin size limit of 100kb
|
|
9
9
|
- total account limit of 10mb.
|
|
10
10
|
|
|
11
11
|
# Installation
|
|
12
12
|
|
|
13
|
-
- `npm i @neonwilderness/ecjsonstorage -S` to install the
|
|
13
|
+
- `npm i @neonwilderness/ecjsonstorage -S` to install the package (available as CommonJs and ESM).
|
|
14
14
|
|
|
15
|
-
-
|
|
15
|
+
- Copy the `.env.template` to your project folder and create a related `.env` file by adding at least the following keys:
|
|
16
16
|
|
|
17
17
|
`JSONAPI=your ExtendsClass Api-key`
|
|
18
18
|
|
|
@@ -24,26 +24,176 @@
|
|
|
24
24
|
|
|
25
25
|
# Usage
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
## Constructor
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
import { ECJsonStorage } from '@neonwilderness/ecjsonstorage';
|
|
31
|
-
import { config } from 'dotenv-safe';
|
|
32
|
-
config();
|
|
29
|
+
### constructor(apiKey: string, securityKey?: string, url?: string)
|
|
33
30
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
```
|
|
32
|
+
import { ECJsonStorage } from '@neonwilderness/ecjsonstorage';
|
|
33
|
+
import { config } from 'dotenv-safe';
|
|
34
|
+
config();
|
|
37
35
|
|
|
38
|
-
|
|
36
|
+
const json = new ECJsonStorage(process.env.JSONAPI, process.env.JSONSEC);
|
|
37
|
+
...
|
|
38
|
+
```
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
> Param `url` will only be needed once the main API address changes. To protect your bins from unauthorized access, you should use a Security-key and pass it as the second parameter.
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
const json = new ECJsonStorage(process.env.JSONAPI, process.env.JSONSEC);
|
|
44
|
-
const payload = { name: 'Neon', profession: 'IT-Consultant' };
|
|
45
|
-
const res = await json.createBin(payload, true);
|
|
46
|
-
console.log(res);
|
|
47
|
-
```
|
|
42
|
+
## Create a new bin
|
|
48
43
|
|
|
49
|
-
|
|
44
|
+
### createBin(payload: object, keepPrivate: boolean): Promise<resCreateBin | resError>
|
|
45
|
+
|
|
46
|
+
Param | Type | Text
|
|
47
|
+
--- | --- | ---
|
|
48
|
+
payload | object | JSON object
|
|
49
|
+
keepPrivate | boolean | TRUE=Bin is kept private | Security-key needed for access
|
|
50
|
+
|
|
51
|
+
resCreateBin Property | Type | Text
|
|
52
|
+
--- | --- | ---
|
|
53
|
+
status | string | 'ok'
|
|
54
|
+
uri | string | full URI of the created bin
|
|
55
|
+
bin | string | bin ID
|
|
56
|
+
|
|
57
|
+
<u>or</u>
|
|
58
|
+
|
|
59
|
+
resError Property | Type | Text
|
|
60
|
+
--- | --- | ---
|
|
61
|
+
status | string | 'error'
|
|
62
|
+
statusText | string | error text
|
|
63
|
+
|
|
64
|
+
> If an error occurs, the returned object is always `<resError>`.
|
|
65
|
+
|
|
66
|
+
> Best practice is to always check `res.status` first. If it's not 'ok' (lowercase), then the class function did not run successfully.
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
const json = new ECJsonStorage(process.env.JSONAPI, process.env.JSONSEC);
|
|
70
|
+
const payload = { name: 'Neon', profession: 'IT-Consultant' };
|
|
71
|
+
const res = await json.createBin(payload, true);
|
|
72
|
+
console.log(res);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Get all bin IDs
|
|
76
|
+
|
|
77
|
+
### getBins(): Promise<resGetBins | resError>
|
|
78
|
+
|
|
79
|
+
This function returns all bins that have been created (and still exist) for the given Api-key. It also returns the current quota limit, i.e. number of calls made and number of ramaining calls (Limit is 10.000 calls per month).
|
|
80
|
+
|
|
81
|
+
resGetBins Property | Type | Text
|
|
82
|
+
--- | --- | ---
|
|
83
|
+
status | string | 'ok'
|
|
84
|
+
callsDone | number | number of API calls made this month
|
|
85
|
+
callsRemaining | number | number of API calls remaining before the limit kicks in
|
|
86
|
+
bins | string[] | array of strings (bin ID)
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
const json = new ECJsonStorage(process.env.JSONAPI, process.env.JSONSEC);
|
|
90
|
+
const res = await json.getBins();
|
|
91
|
+
console.log(`I have ${res.bins.length} bins and the IDs are: ${res.bins}`);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Get statistics (Quota limit)
|
|
95
|
+
|
|
96
|
+
### getStats(): Promise<resGetStats | resError>
|
|
97
|
+
|
|
98
|
+
This function is a syntactic sugar function for getBins and only returns the current quota limit, i.e. number of calls made and number of ramaining calls.
|
|
99
|
+
|
|
100
|
+
resGetStats Property | Type | Text
|
|
101
|
+
--- | --- | ---
|
|
102
|
+
status | string | 'ok'
|
|
103
|
+
callsDone | number | number of API calls made this month
|
|
104
|
+
callsRemaining | number | number of API calls remaining before the limit kicks in
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
const json = new ECJsonStorage(process.env.JSONAPI, process.env.JSONSEC);
|
|
108
|
+
const res = await json.getStats();
|
|
109
|
+
console.log(`Used calls: ${res.callsDone}, calls remaining: ${res.callsRemaining}`);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Get a bin's content
|
|
113
|
+
|
|
114
|
+
### getBin(bin: string): Promise<resGetBin | resError>
|
|
115
|
+
|
|
116
|
+
This function reads the bin and returns its content.
|
|
117
|
+
|
|
118
|
+
Param | Type | Text
|
|
119
|
+
--- | --- | ---
|
|
120
|
+
bin | string | Bin ID to read
|
|
121
|
+
|
|
122
|
+
resGetBin Property | Type | Text
|
|
123
|
+
--- | --- | ---
|
|
124
|
+
status | string | 'ok'
|
|
125
|
+
data | object | JSON object (Content of bin)
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
const json = new ECJsonStorage(process.env.JSONAPI, process.env.JSONSEC);
|
|
129
|
+
const res = await json.getBin('c8ba8b1da99c');
|
|
130
|
+
console.log(res.data);
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Update a bin
|
|
134
|
+
|
|
135
|
+
### updateBin(payload: object, bin: string): Promise<resUpdateBin | resError>
|
|
136
|
+
|
|
137
|
+
Param | Type | Text
|
|
138
|
+
--- | --- | ---
|
|
139
|
+
payload | object | JSON object
|
|
140
|
+
bin | string | Bin ID to be updated
|
|
141
|
+
|
|
142
|
+
resUpdateBin Property | Type | Text
|
|
143
|
+
--- | --- | ---
|
|
144
|
+
status | string | 'ok'
|
|
145
|
+
data | string | Stringified JSON object (Content of updated bin)
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
const json = new ECJsonStorage(process.env.JSONAPI, process.env.JSONSEC);
|
|
149
|
+
const newPayload = { name: 'Wilderness', profession: 'Web Ninja' };
|
|
150
|
+
const res = await json.updateBin(newPayload, 'c8ba8b1da99c');
|
|
151
|
+
console.log(res);
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Patch a bin
|
|
155
|
+
|
|
156
|
+
### patchBin(payload: object, bin: string): Promise<resPatchBin | resError>
|
|
157
|
+
|
|
158
|
+
Param | Type | Text
|
|
159
|
+
--- | --- | ---
|
|
160
|
+
payload | object | JSON object
|
|
161
|
+
bin | string | Bin ID to be patched
|
|
162
|
+
|
|
163
|
+
resUpdateBin Property | Type | Text
|
|
164
|
+
--- | --- | ---
|
|
165
|
+
status | string | 'ok'
|
|
166
|
+
data | string | Stringified JSON object (Content of patched bin)
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
const json = new ECJsonStorage(process.env.JSONAPI, process.env.JSONSEC);
|
|
170
|
+
//current bin = { name: 'Wilderness', profession: 'Web Ninja' }
|
|
171
|
+
const addPayload = { song: 'In a NeonWilderness he was restless', state: 'Germany' };
|
|
172
|
+
const res = await json.patchBin(addPayload, 'c8ba8b1da99c');
|
|
173
|
+
console.log(res);
|
|
174
|
+
//patched bin = { name: 'Wilderness', profession: 'Web Ninja', song: 'In a NeonWilderness he was restless', state: 'Germany' }
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
> For more information regarding PATCH, please refer to the [ExtendsClass site - "Partially update JSON"](https://extendsclass.com/json-storage.html#apiDocumentation).
|
|
178
|
+
|
|
179
|
+
## Delete a bin
|
|
180
|
+
|
|
181
|
+
### deleteBin(bin: string): Promise<resDeleteBin | resError>
|
|
182
|
+
|
|
183
|
+
Param | Type | Text
|
|
184
|
+
--- | --- | ---
|
|
185
|
+
bin | string | Bin ID to be deleted
|
|
186
|
+
|
|
187
|
+
resDeleteBin Property | Type | Text
|
|
188
|
+
--- | --- | ---
|
|
189
|
+
status | string | 'ok'
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
const json = new ECJsonStorage(process.env.JSONAPI, process.env.JSONSEC);
|
|
193
|
+
const bin = 'c8ba8b1da99c';
|
|
194
|
+
const res = await json.deleteBin(bin);
|
|
195
|
+
if (res.status !== 'ok')
|
|
196
|
+
console.error(`Could not delete bin ${bin}, error=${<resError>statusText}.`);
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
In addition, you also may wanna consult the [TS types file](dist/index.d.ts).
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var o=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var h=Object.prototype.hasOwnProperty;var y=(i,t)=>{for(var r in t)o(i,r,{get:t[r],enumerable:!0})},l=(i,t,r,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of u(t))!h.call(i,s)&&s!==r&&o(i,s,{get:()=>t[s],enumerable:!(e=p(t,s))||e.enumerable});return i};var d=i=>l(o({},"__esModule",{value:!0}),i);var g={};y(g,{ECJsonStorage:()=>a});module.exports=d(g);var a=class{url;apiKey;securityKey;monthlyLimit=1e4;constructor(t,r,e){if(this.url=e||"https://json.extendsclass.com/bin",this.apiKey=t||"",this.securityKey=r||"",!this.url||!this.apiKey)throw new Error("Invalid constructor params!");for(;this.url.endsWith("/");)this.url=this.url.slice(0,-1)}validateResponse=async t=>{if(!t.ok)throw new Error(`HTTP error! Status: ${t.status}`);if((t.headers.get("content-type")||"").startsWith("text/html"))throw new Error(`Expected JSON but server returned HTML: "${(await t.text()).slice(0,100)}..."`)};getBins=async()=>{try{let t=await fetch(`${this.url}s`,{method:"GET",headers:{"Api-key":this.apiKey,Accept:"application/json"}});await this.validateResponse(t);let r=Number(t.headers.get("x-counter")),e=await t.json();return{status:"ok",callsDone:r,callsRemaining:this.monthlyLimit-r,bins:e}}catch(t){return console.error("getBins error:",t),{status:"error",statusText:t}}};getStats=async()=>{try{let t=await this.getBins();if(t.status==="error")throw new Error(`HTTP error! Status: ${t.statusText}`);return delete t.bins,t}catch(t){return console.error("getStats error:",t),{status:"error",statusText:t}}};getBin=async t=>{try{if(!t)throw new Error("Bin ID missing!");let r=await fetch(`${this.url}/${t}`,{method:"GET",headers:{"Security-key":this.securityKey,Accept:"application/json"}});return await this.validateResponse(r),{status:"ok",data:await r.json()}}catch(r){return console.error("getBin error:",r),{status:"error",statusText:r}}};createBin=async(t,r)=>{let e=new Headers({"Api-key":this.apiKey,"Security-key":this.securityKey,"Content-Type":"application/json",Accept:"application/json"});e.append("Private",r.toString());try{let s=await fetch(this.url,{method:"POST",headers:e,body:JSON.stringify(t)});await this.validateResponse(s);let{uri:c,bin:n}=await s.json();return n||(n=c.split("/").pop()),{status:"ok",uri:c,bin:n}}catch(s){return console.error("createBin error:",s),{status:"error",statusText:s}}};updateBin=async(t,r)=>{try{if(!r)throw new Error("Bin ID missing!");let e=await fetch(`${this.url}/${r}`,{method:"PUT",headers:{"Security-key":this.securityKey,"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(t)});await this.validateResponse(e);let{data:s}=await e.json();return{status:"ok",data:s}}catch(e){return console.error("updateBin error:",e),{status:"error",statusText:e}}};patchBin=async(t,r)=>{try{if(!r)throw new Error("Bin ID missing!");let e=await fetch(`${this.url}/${r}`,{method:"PATCH",headers:{"Security-key":this.securityKey,"Content-Type":"application/merge-patch+json",Accept:"application/json"},body:JSON.stringify(t)});await this.validateResponse(e);let{data:s}=await e.json();return{status:"ok",data:s}}catch(e){return console.error("patchBin error:",e),{status:"error",statusText:e}}};deleteBin=async t=>{try{if(!t)throw new Error("Bin ID missing!");let r=await fetch(`${this.url}/${t}`,{method:"DELETE",headers:{"Security-key":this.securityKey,"Content-Type":"application/json",Accept:"application/json"}});await this.validateResponse(r);let{status:e}=await r.json();if(e!==0)throw new Error(`Bin delete failed with error: ${e.message}`);return{status:"ok"}}catch(r){return console.error("deleteBin error:",r),{status:"error",statusText:r}}}};0&&(module.exports={ECJsonStorage});
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\r\n * ESJsonStorage class is a wrapper to the ExtendsClass JSON-Storage API\r\n */\r\nexport type resGetBins = {\r\n status: 'ok';\r\n callsDone: number;\r\n callsRemaining: number;\r\n bins?: string[];\r\n};\r\nexport type resGetStats = Omit<resGetBins, 'bins'>;\r\n\r\nexport type resGetBin = {\r\n status: 'ok';\r\n data: object;\r\n};\r\n\r\nexport type resUpdateBin = {\r\n status: 'ok';\r\n data: string;\r\n};\r\nexport type resPatchBin = resUpdateBin;\r\n\r\nexport type resCreateBin = {\r\n status: 'ok';\r\n uri: string;\r\n bin: string;\r\n};\r\n\r\nexport type resDeleteBin = Omit<resGetBin, 'data'>;\r\n\r\nexport type resError = {\r\n status: 'error';\r\n statusText: string;\r\n};\r\n\r\nexport class ECJsonStorage {\r\n url: string;\r\n apiKey: string;\r\n securityKey: string;\r\n monthlyLimit: number = 10000;\r\n\r\n constructor(apiKey: string, securityKey?: string, url?: string) {\r\n this.url = url || 'https://json.extendsclass.com/bin';\r\n this.apiKey = apiKey || '';\r\n this.securityKey = securityKey || '';\r\n\r\n if (!this.url || !this.apiKey) throw new Error('Invalid constructor params!');\r\n while (this.url.endsWith('/')) {\r\n this.url = this.url.slice(0, -1);\r\n }\r\n }\r\n\r\n /**\r\n * Utility function to validate the response after the class function call\r\n * @param response\r\n */\r\n validateResponse = async (response: Response) => {\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! Status: ${response.status}`);\r\n }\r\n\r\n const contentType = response.headers.get('content-type') || '';\r\n if (contentType.startsWith('text/html')) {\r\n throw new Error(`Expected JSON but server returned HTML: \"${(await response.text()).slice(0, 100)}...\"`);\r\n }\r\n };\r\n\r\n /**\r\n * Get all bin IDs for a certain Api-key\r\n * @returns {object} <resGetBins | resError>\r\n */\r\n getBins = async (): Promise<resGetBins | resError> => {\r\n try {\r\n const response = await fetch(`${this.url}s`, {\r\n method: 'GET',\r\n headers: {\r\n 'Api-key': this.apiKey,\r\n Accept: 'application/json'\r\n }\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const counter = Number(response.headers.get('x-counter'));\r\n const data = await response.json();\r\n return {\r\n status: 'ok',\r\n callsDone: counter,\r\n callsRemaining: this.monthlyLimit - counter,\r\n bins: data\r\n };\r\n } catch (error) {\r\n console.error('getBins error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Syntactic sugar function for getBins to only return limit counter\r\n * @returns {object} <resGetStats | resError>\r\n */\r\n getStats = async (): Promise<resGetStats | resError> => {\r\n try {\r\n const res = await this.getBins();\r\n if (res.status === 'error') {\r\n throw new Error(`HTTP error! Status: ${(<resError>res).statusText}`);\r\n }\r\n\r\n delete (<resGetBins>res).bins;\r\n return <resGetStats>res;\r\n } catch (error) {\r\n console.error('getStats error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Reads the content of a certain bin ID\r\n * @param bin string Bin ID to read\r\n * @returns {object} <resGetBin | resError>\r\n */\r\n getBin = async (bin: string): Promise<resGetBin | resError> => {\r\n try {\r\n if (!bin) throw new Error('Bin ID missing!');\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'GET',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n Accept: 'application/json'\r\n }\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const data = await response.json();\r\n return {\r\n status: 'ok',\r\n data\r\n };\r\n } catch (error) {\r\n console.error('getBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Creates a new bin and saves the given JSON payload to it\r\n * @param payload {object} JSON object to create the bin with\r\n * @param keepPrivate {boolean} TRUE=bin shall be kept private\r\n * @returns {object} <resCreateBin | resError>\r\n */\r\n createBin = async (payload: object, keepPrivate: boolean): Promise<resCreateBin | resError> => {\r\n const headers = new Headers({\r\n 'Api-key': this.apiKey,\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/json',\r\n Accept: 'application/json'\r\n });\r\n headers.append('Private', keepPrivate.toString());\r\n try {\r\n const response = await fetch(this.url, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify(payload)\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n let { uri, bin } = await response.json();\r\n if (!bin) bin = uri.split('/').pop();\r\n\r\n return {\r\n status: 'ok',\r\n uri,\r\n bin\r\n };\r\n } catch (error) {\r\n console.error('createBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Updates a certain bin with the given JSON object\r\n * @param payload {object} JSON object to update the bin with\r\n * @param bin string Bin ID to be updated\r\n * @returns {object} <resUpdateBin | resError>\r\n */\r\n updateBin = async (payload: object, bin: string): Promise<resUpdateBin | resError> => {\r\n try {\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'PUT',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/json',\r\n Accept: 'application/json'\r\n },\r\n body: JSON.stringify(payload)\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const { data } = await response.json();\r\n return {\r\n status: 'ok',\r\n data\r\n };\r\n } catch (error) {\r\n console.error('updateBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Patches/inserts/changes a certain bin with the given JSON payload\r\n * ref: \"Partially update JSON\" at https://extendsclass.com/json-storage.html#apiDocumentation\r\n * @param payload {object} JSON object to patch the bin with\r\n * @param bin string Bin ID to be patched\r\n * @returns {object} <resPatchBin | resError>\r\n */\r\n patchBin = async (payload: object, bin: string): Promise<resPatchBin | resError> => {\r\n try {\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'PATCH',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/merge-patch+json',\r\n Accept: 'application/json'\r\n },\r\n body: JSON.stringify(payload)\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const { data } = await response.json();\r\n return {\r\n status: 'ok',\r\n data\r\n };\r\n } catch (error) {\r\n console.error('patchBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Deletes a certain bin\r\n * @param bin string Bin ID to be deleted\r\n * @returns {object} <resDeleteBin | resError>\r\n */\r\n deleteBin = async (bin: string): Promise<resDeleteBin | resError> => {\r\n try {\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'DELETE',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/json',\r\n Accept: 'application/json'\r\n }\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const { status } = await response.json();\r\n if (status !== 0) throw new Error(`Bin delete failed with error: ${status.message}`);\r\n\r\n return {\r\n status: 'ok'\r\n };\r\n } catch (error) {\r\n console.error('deleteBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n}\r\n"],"mappings":"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","names":["index_exports","__export","ECJsonStorage","__toCommonJS","apiKey","securityKey","url","response","counter","data","error","res","bin","payload","keepPrivate","headers","uri","status"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\r\n * ESJsonStorage class is a wrapper to the ExtendsClass JSON-Storage API\r\n */\r\nexport type resGetBins = {\r\n status: 'ok';\r\n callsDone: number;\r\n callsRemaining: number;\r\n bins?: string[];\r\n};\r\nexport type resGetStats = Omit<resGetBins, 'bins'>;\r\n\r\nexport type resGetBin = {\r\n status: 'ok';\r\n data: object;\r\n};\r\n\r\nexport type resUpdateBin = {\r\n status: 'ok';\r\n data: string;\r\n};\r\nexport type resPatchBin = resUpdateBin;\r\n\r\nexport type resCreateBin = {\r\n status: 'ok';\r\n uri: string;\r\n bin: string;\r\n};\r\n\r\nexport type resDeleteBin = Omit<resGetBin, 'data'>;\r\n\r\nexport type resError = {\r\n status: 'error';\r\n statusText: string;\r\n};\r\n\r\nexport class ECJsonStorage {\r\n url: string;\r\n apiKey: string;\r\n securityKey: string;\r\n monthlyLimit: number = 10000;\r\n\r\n constructor(apiKey: string, securityKey?: string, url?: string) {\r\n this.url = url || 'https://json.extendsclass.com/bin';\r\n this.apiKey = apiKey || '';\r\n this.securityKey = securityKey || '';\r\n\r\n if (!this.url || !this.apiKey) throw new Error('Invalid constructor params!');\r\n while (this.url.endsWith('/')) {\r\n this.url = this.url.slice(0, -1);\r\n }\r\n }\r\n\r\n /**\r\n * Utility function to validate the response after the class function call\r\n * @param response\r\n */\r\n validateResponse = async (response: Response) => {\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! Status: ${response.status}`);\r\n }\r\n\r\n const contentType = response.headers.get('content-type') || '';\r\n if (contentType.startsWith('text/html')) {\r\n throw new Error(`Expected JSON but server returned HTML: \"${(await response.text()).slice(0, 100)}...\"`);\r\n }\r\n };\r\n\r\n /**\r\n * Get all bin IDs for a certain Api-key\r\n * @returns {object} <resGetBins | resError>\r\n */\r\n getBins = async (): Promise<resGetBins | resError> => {\r\n try {\r\n const response = await fetch(`${this.url}s`, {\r\n method: 'GET',\r\n headers: {\r\n 'Api-key': this.apiKey,\r\n Accept: 'application/json'\r\n }\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const counter = Number(response.headers.get('x-counter'));\r\n const data = await response.json();\r\n return {\r\n status: 'ok',\r\n callsDone: counter,\r\n callsRemaining: this.monthlyLimit - counter,\r\n bins: data\r\n };\r\n } catch (error) {\r\n console.error('getBins error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Syntactic sugar function for getBins to only return limit counter\r\n * @returns {object} <resGetStats | resError>\r\n */\r\n getStats = async (): Promise<resGetStats | resError> => {\r\n try {\r\n const res = await this.getBins();\r\n if (res.status === 'error') {\r\n throw new Error(`HTTP error! Status: ${(<resError>res).statusText}`);\r\n }\r\n\r\n delete (<resGetBins>res).bins;\r\n return <resGetStats>res;\r\n } catch (error) {\r\n console.error('getStats error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Reads the content of a certain bin ID\r\n * @param bin string Bin ID to read\r\n * @returns {object} <resGetBin | resError>\r\n */\r\n getBin = async (bin: string): Promise<resGetBin | resError> => {\r\n try {\r\n if (!bin) throw new Error('Bin ID missing!');\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'GET',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n Accept: 'application/json'\r\n }\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const data = await response.json();\r\n return {\r\n status: 'ok',\r\n data\r\n };\r\n } catch (error) {\r\n console.error('getBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Creates a new bin and saves the given JSON payload to it\r\n * @param payload {object} JSON object to create the bin with\r\n * @param keepPrivate {boolean} TRUE=bin shall be kept private\r\n * @returns {object} <resCreateBin | resError>\r\n */\r\n createBin = async (payload: object, keepPrivate: boolean): Promise<resCreateBin | resError> => {\r\n const headers = new Headers({\r\n 'Api-key': this.apiKey,\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/json',\r\n Accept: 'application/json'\r\n });\r\n headers.append('Private', keepPrivate.toString());\r\n try {\r\n const response = await fetch(this.url, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify(payload)\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n let { uri, bin } = await response.json();\r\n if (!bin) bin = uri.split('/').pop();\r\n\r\n return {\r\n status: 'ok',\r\n uri,\r\n bin\r\n };\r\n } catch (error) {\r\n console.error('createBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Updates a certain bin with the given JSON object\r\n * @param payload {object} JSON object to update the bin with\r\n * @param bin string Bin ID to be updated\r\n * @returns {object} <resUpdateBin | resError>\r\n */\r\n updateBin = async (payload: object, bin: string): Promise<resUpdateBin | resError> => {\r\n try {\r\n if (!bin) throw new Error('Bin ID missing!');\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'PUT',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/json',\r\n Accept: 'application/json'\r\n },\r\n body: JSON.stringify(payload)\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const { data } = await response.json();\r\n return {\r\n status: 'ok',\r\n data\r\n };\r\n } catch (error) {\r\n console.error('updateBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Patches/inserts/changes a certain bin with the given JSON payload\r\n * ref: \"Partially update JSON\" at https://extendsclass.com/json-storage.html#apiDocumentation\r\n * @param payload {object} JSON object to patch the bin with\r\n * @param bin string Bin ID to be patched\r\n * @returns {object} <resPatchBin | resError>\r\n */\r\n patchBin = async (payload: object, bin: string): Promise<resPatchBin | resError> => {\r\n try {\r\n if (!bin) throw new Error('Bin ID missing!');\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'PATCH',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/merge-patch+json',\r\n Accept: 'application/json'\r\n },\r\n body: JSON.stringify(payload)\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const { data } = await response.json();\r\n return {\r\n status: 'ok',\r\n data\r\n };\r\n } catch (error) {\r\n console.error('patchBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Deletes a certain bin\r\n * @param bin string Bin ID to be deleted\r\n * @returns {object} <resDeleteBin | resError>\r\n */\r\n deleteBin = async (bin: string): Promise<resDeleteBin | resError> => {\r\n try {\r\n if (!bin) throw new Error('Bin ID missing!');\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'DELETE',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/json',\r\n Accept: 'application/json'\r\n }\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const { status } = await response.json();\r\n if (status !== 0) throw new Error(`Bin delete failed with error: ${status.message}`);\r\n\r\n return {\r\n status: 'ok'\r\n };\r\n } catch (error) {\r\n console.error('deleteBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n}\r\n"],"mappings":"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","names":["index_exports","__export","ECJsonStorage","__toCommonJS","apiKey","securityKey","url","response","counter","data","error","res","bin","payload","keepPrivate","headers","uri","status"]}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
1
|
+
var o=class{url;apiKey;securityKey;monthlyLimit=1e4;constructor(t,r,e){if(this.url=e||"https://json.extendsclass.com/bin",this.apiKey=t||"",this.securityKey=r||"",!this.url||!this.apiKey)throw new Error("Invalid constructor params!");for(;this.url.endsWith("/");)this.url=this.url.slice(0,-1)}validateResponse=async t=>{if(!t.ok)throw new Error(`HTTP error! Status: ${t.status}`);if((t.headers.get("content-type")||"").startsWith("text/html"))throw new Error(`Expected JSON but server returned HTML: "${(await t.text()).slice(0,100)}..."`)};getBins=async()=>{try{let t=await fetch(`${this.url}s`,{method:"GET",headers:{"Api-key":this.apiKey,Accept:"application/json"}});await this.validateResponse(t);let r=Number(t.headers.get("x-counter")),e=await t.json();return{status:"ok",callsDone:r,callsRemaining:this.monthlyLimit-r,bins:e}}catch(t){return console.error("getBins error:",t),{status:"error",statusText:t}}};getStats=async()=>{try{let t=await this.getBins();if(t.status==="error")throw new Error(`HTTP error! Status: ${t.statusText}`);return delete t.bins,t}catch(t){return console.error("getStats error:",t),{status:"error",statusText:t}}};getBin=async t=>{try{if(!t)throw new Error("Bin ID missing!");let r=await fetch(`${this.url}/${t}`,{method:"GET",headers:{"Security-key":this.securityKey,Accept:"application/json"}});return await this.validateResponse(r),{status:"ok",data:await r.json()}}catch(r){return console.error("getBin error:",r),{status:"error",statusText:r}}};createBin=async(t,r)=>{let e=new Headers({"Api-key":this.apiKey,"Security-key":this.securityKey,"Content-Type":"application/json",Accept:"application/json"});e.append("Private",r.toString());try{let s=await fetch(this.url,{method:"POST",headers:e,body:JSON.stringify(t)});await this.validateResponse(s);let{uri:n,bin:i}=await s.json();return i||(i=n.split("/").pop()),{status:"ok",uri:n,bin:i}}catch(s){return console.error("createBin error:",s),{status:"error",statusText:s}}};updateBin=async(t,r)=>{try{if(!r)throw new Error("Bin ID missing!");let e=await fetch(`${this.url}/${r}`,{method:"PUT",headers:{"Security-key":this.securityKey,"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(t)});await this.validateResponse(e);let{data:s}=await e.json();return{status:"ok",data:s}}catch(e){return console.error("updateBin error:",e),{status:"error",statusText:e}}};patchBin=async(t,r)=>{try{if(!r)throw new Error("Bin ID missing!");let e=await fetch(`${this.url}/${r}`,{method:"PATCH",headers:{"Security-key":this.securityKey,"Content-Type":"application/merge-patch+json",Accept:"application/json"},body:JSON.stringify(t)});await this.validateResponse(e);let{data:s}=await e.json();return{status:"ok",data:s}}catch(e){return console.error("patchBin error:",e),{status:"error",statusText:e}}};deleteBin=async t=>{try{if(!t)throw new Error("Bin ID missing!");let r=await fetch(`${this.url}/${t}`,{method:"DELETE",headers:{"Security-key":this.securityKey,"Content-Type":"application/json",Accept:"application/json"}});await this.validateResponse(r);let{status:e}=await r.json();if(e!==0)throw new Error(`Bin delete failed with error: ${e.message}`);return{status:"ok"}}catch(r){return console.error("deleteBin error:",r),{status:"error",statusText:r}}}};export{o as ECJsonStorage};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\r\n * ESJsonStorage class is a wrapper to the ExtendsClass JSON-Storage API\r\n */\r\nexport type resGetBins = {\r\n status: 'ok';\r\n callsDone: number;\r\n callsRemaining: number;\r\n bins?: string[];\r\n};\r\nexport type resGetStats = Omit<resGetBins, 'bins'>;\r\n\r\nexport type resGetBin = {\r\n status: 'ok';\r\n data: object;\r\n};\r\n\r\nexport type resUpdateBin = {\r\n status: 'ok';\r\n data: string;\r\n};\r\nexport type resPatchBin = resUpdateBin;\r\n\r\nexport type resCreateBin = {\r\n status: 'ok';\r\n uri: string;\r\n bin: string;\r\n};\r\n\r\nexport type resDeleteBin = Omit<resGetBin, 'data'>;\r\n\r\nexport type resError = {\r\n status: 'error';\r\n statusText: string;\r\n};\r\n\r\nexport class ECJsonStorage {\r\n url: string;\r\n apiKey: string;\r\n securityKey: string;\r\n monthlyLimit: number = 10000;\r\n\r\n constructor(apiKey: string, securityKey?: string, url?: string) {\r\n this.url = url || 'https://json.extendsclass.com/bin';\r\n this.apiKey = apiKey || '';\r\n this.securityKey = securityKey || '';\r\n\r\n if (!this.url || !this.apiKey) throw new Error('Invalid constructor params!');\r\n while (this.url.endsWith('/')) {\r\n this.url = this.url.slice(0, -1);\r\n }\r\n }\r\n\r\n /**\r\n * Utility function to validate the response after the class function call\r\n * @param response\r\n */\r\n validateResponse = async (response: Response) => {\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! Status: ${response.status}`);\r\n }\r\n\r\n const contentType = response.headers.get('content-type') || '';\r\n if (contentType.startsWith('text/html')) {\r\n throw new Error(`Expected JSON but server returned HTML: \"${(await response.text()).slice(0, 100)}...\"`);\r\n }\r\n };\r\n\r\n /**\r\n * Get all bin IDs for a certain Api-key\r\n * @returns {object} <resGetBins | resError>\r\n */\r\n getBins = async (): Promise<resGetBins | resError> => {\r\n try {\r\n const response = await fetch(`${this.url}s`, {\r\n method: 'GET',\r\n headers: {\r\n 'Api-key': this.apiKey,\r\n Accept: 'application/json'\r\n }\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const counter = Number(response.headers.get('x-counter'));\r\n const data = await response.json();\r\n return {\r\n status: 'ok',\r\n callsDone: counter,\r\n callsRemaining: this.monthlyLimit - counter,\r\n bins: data\r\n };\r\n } catch (error) {\r\n console.error('getBins error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Syntactic sugar function for getBins to only return limit counter\r\n * @returns {object} <resGetStats | resError>\r\n */\r\n getStats = async (): Promise<resGetStats | resError> => {\r\n try {\r\n const res = await this.getBins();\r\n if (res.status === 'error') {\r\n throw new Error(`HTTP error! Status: ${(<resError>res).statusText}`);\r\n }\r\n\r\n delete (<resGetBins>res).bins;\r\n return <resGetStats>res;\r\n } catch (error) {\r\n console.error('getStats error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Reads the content of a certain bin ID\r\n * @param bin string Bin ID to read\r\n * @returns {object} <resGetBin | resError>\r\n */\r\n getBin = async (bin: string): Promise<resGetBin | resError> => {\r\n try {\r\n if (!bin) throw new Error('Bin ID missing!');\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'GET',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n Accept: 'application/json'\r\n }\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const data = await response.json();\r\n return {\r\n status: 'ok',\r\n data\r\n };\r\n } catch (error) {\r\n console.error('getBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Creates a new bin and saves the given JSON payload to it\r\n * @param payload {object} JSON object to create the bin with\r\n * @param keepPrivate {boolean} TRUE=bin shall be kept private\r\n * @returns {object} <resCreateBin | resError>\r\n */\r\n createBin = async (payload: object, keepPrivate: boolean): Promise<resCreateBin | resError> => {\r\n const headers = new Headers({\r\n 'Api-key': this.apiKey,\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/json',\r\n Accept: 'application/json'\r\n });\r\n headers.append('Private', keepPrivate.toString());\r\n try {\r\n const response = await fetch(this.url, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify(payload)\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n let { uri, bin } = await response.json();\r\n if (!bin) bin = uri.split('/').pop();\r\n\r\n return {\r\n status: 'ok',\r\n uri,\r\n bin\r\n };\r\n } catch (error) {\r\n console.error('createBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Updates a certain bin with the given JSON object\r\n * @param payload {object} JSON object to update the bin with\r\n * @param bin string Bin ID to be updated\r\n * @returns {object} <resUpdateBin | resError>\r\n */\r\n updateBin = async (payload: object, bin: string): Promise<resUpdateBin | resError> => {\r\n try {\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'PUT',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/json',\r\n Accept: 'application/json'\r\n },\r\n body: JSON.stringify(payload)\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const { data } = await response.json();\r\n return {\r\n status: 'ok',\r\n data\r\n };\r\n } catch (error) {\r\n console.error('updateBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Patches/inserts/changes a certain bin with the given JSON payload\r\n * ref: \"Partially update JSON\" at https://extendsclass.com/json-storage.html#apiDocumentation\r\n * @param payload {object} JSON object to patch the bin with\r\n * @param bin string Bin ID to be patched\r\n * @returns {object} <resPatchBin | resError>\r\n */\r\n patchBin = async (payload: object, bin: string): Promise<resPatchBin | resError> => {\r\n try {\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'PATCH',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/merge-patch+json',\r\n Accept: 'application/json'\r\n },\r\n body: JSON.stringify(payload)\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const { data } = await response.json();\r\n return {\r\n status: 'ok',\r\n data\r\n };\r\n } catch (error) {\r\n console.error('patchBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Deletes a certain bin\r\n * @param bin string Bin ID to be deleted\r\n * @returns {object} <resDeleteBin | resError>\r\n */\r\n deleteBin = async (bin: string): Promise<resDeleteBin | resError> => {\r\n try {\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'DELETE',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/json',\r\n Accept: 'application/json'\r\n }\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const { status } = await response.json();\r\n if (status !== 0) throw new Error(`Bin delete failed with error: ${status.message}`);\r\n\r\n return {\r\n status: 'ok'\r\n };\r\n } catch (error) {\r\n console.error('deleteBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n}\r\n"],"mappings":"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","names":["ECJsonStorage","apiKey","securityKey","url","response","counter","data","error","res","bin","payload","keepPrivate","headers","uri","status"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\r\n * ESJsonStorage class is a wrapper to the ExtendsClass JSON-Storage API\r\n */\r\nexport type resGetBins = {\r\n status: 'ok';\r\n callsDone: number;\r\n callsRemaining: number;\r\n bins?: string[];\r\n};\r\nexport type resGetStats = Omit<resGetBins, 'bins'>;\r\n\r\nexport type resGetBin = {\r\n status: 'ok';\r\n data: object;\r\n};\r\n\r\nexport type resUpdateBin = {\r\n status: 'ok';\r\n data: string;\r\n};\r\nexport type resPatchBin = resUpdateBin;\r\n\r\nexport type resCreateBin = {\r\n status: 'ok';\r\n uri: string;\r\n bin: string;\r\n};\r\n\r\nexport type resDeleteBin = Omit<resGetBin, 'data'>;\r\n\r\nexport type resError = {\r\n status: 'error';\r\n statusText: string;\r\n};\r\n\r\nexport class ECJsonStorage {\r\n url: string;\r\n apiKey: string;\r\n securityKey: string;\r\n monthlyLimit: number = 10000;\r\n\r\n constructor(apiKey: string, securityKey?: string, url?: string) {\r\n this.url = url || 'https://json.extendsclass.com/bin';\r\n this.apiKey = apiKey || '';\r\n this.securityKey = securityKey || '';\r\n\r\n if (!this.url || !this.apiKey) throw new Error('Invalid constructor params!');\r\n while (this.url.endsWith('/')) {\r\n this.url = this.url.slice(0, -1);\r\n }\r\n }\r\n\r\n /**\r\n * Utility function to validate the response after the class function call\r\n * @param response\r\n */\r\n validateResponse = async (response: Response) => {\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! Status: ${response.status}`);\r\n }\r\n\r\n const contentType = response.headers.get('content-type') || '';\r\n if (contentType.startsWith('text/html')) {\r\n throw new Error(`Expected JSON but server returned HTML: \"${(await response.text()).slice(0, 100)}...\"`);\r\n }\r\n };\r\n\r\n /**\r\n * Get all bin IDs for a certain Api-key\r\n * @returns {object} <resGetBins | resError>\r\n */\r\n getBins = async (): Promise<resGetBins | resError> => {\r\n try {\r\n const response = await fetch(`${this.url}s`, {\r\n method: 'GET',\r\n headers: {\r\n 'Api-key': this.apiKey,\r\n Accept: 'application/json'\r\n }\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const counter = Number(response.headers.get('x-counter'));\r\n const data = await response.json();\r\n return {\r\n status: 'ok',\r\n callsDone: counter,\r\n callsRemaining: this.monthlyLimit - counter,\r\n bins: data\r\n };\r\n } catch (error) {\r\n console.error('getBins error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Syntactic sugar function for getBins to only return limit counter\r\n * @returns {object} <resGetStats | resError>\r\n */\r\n getStats = async (): Promise<resGetStats | resError> => {\r\n try {\r\n const res = await this.getBins();\r\n if (res.status === 'error') {\r\n throw new Error(`HTTP error! Status: ${(<resError>res).statusText}`);\r\n }\r\n\r\n delete (<resGetBins>res).bins;\r\n return <resGetStats>res;\r\n } catch (error) {\r\n console.error('getStats error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Reads the content of a certain bin ID\r\n * @param bin string Bin ID to read\r\n * @returns {object} <resGetBin | resError>\r\n */\r\n getBin = async (bin: string): Promise<resGetBin | resError> => {\r\n try {\r\n if (!bin) throw new Error('Bin ID missing!');\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'GET',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n Accept: 'application/json'\r\n }\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const data = await response.json();\r\n return {\r\n status: 'ok',\r\n data\r\n };\r\n } catch (error) {\r\n console.error('getBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Creates a new bin and saves the given JSON payload to it\r\n * @param payload {object} JSON object to create the bin with\r\n * @param keepPrivate {boolean} TRUE=bin shall be kept private\r\n * @returns {object} <resCreateBin | resError>\r\n */\r\n createBin = async (payload: object, keepPrivate: boolean): Promise<resCreateBin | resError> => {\r\n const headers = new Headers({\r\n 'Api-key': this.apiKey,\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/json',\r\n Accept: 'application/json'\r\n });\r\n headers.append('Private', keepPrivate.toString());\r\n try {\r\n const response = await fetch(this.url, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify(payload)\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n let { uri, bin } = await response.json();\r\n if (!bin) bin = uri.split('/').pop();\r\n\r\n return {\r\n status: 'ok',\r\n uri,\r\n bin\r\n };\r\n } catch (error) {\r\n console.error('createBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Updates a certain bin with the given JSON object\r\n * @param payload {object} JSON object to update the bin with\r\n * @param bin string Bin ID to be updated\r\n * @returns {object} <resUpdateBin | resError>\r\n */\r\n updateBin = async (payload: object, bin: string): Promise<resUpdateBin | resError> => {\r\n try {\r\n if (!bin) throw new Error('Bin ID missing!');\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'PUT',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/json',\r\n Accept: 'application/json'\r\n },\r\n body: JSON.stringify(payload)\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const { data } = await response.json();\r\n return {\r\n status: 'ok',\r\n data\r\n };\r\n } catch (error) {\r\n console.error('updateBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Patches/inserts/changes a certain bin with the given JSON payload\r\n * ref: \"Partially update JSON\" at https://extendsclass.com/json-storage.html#apiDocumentation\r\n * @param payload {object} JSON object to patch the bin with\r\n * @param bin string Bin ID to be patched\r\n * @returns {object} <resPatchBin | resError>\r\n */\r\n patchBin = async (payload: object, bin: string): Promise<resPatchBin | resError> => {\r\n try {\r\n if (!bin) throw new Error('Bin ID missing!');\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'PATCH',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/merge-patch+json',\r\n Accept: 'application/json'\r\n },\r\n body: JSON.stringify(payload)\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const { data } = await response.json();\r\n return {\r\n status: 'ok',\r\n data\r\n };\r\n } catch (error) {\r\n console.error('patchBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Deletes a certain bin\r\n * @param bin string Bin ID to be deleted\r\n * @returns {object} <resDeleteBin | resError>\r\n */\r\n deleteBin = async (bin: string): Promise<resDeleteBin | resError> => {\r\n try {\r\n if (!bin) throw new Error('Bin ID missing!');\r\n const response = await fetch(`${this.url}/${bin}`, {\r\n method: 'DELETE',\r\n headers: {\r\n 'Security-key': this.securityKey,\r\n 'Content-Type': 'application/json',\r\n Accept: 'application/json'\r\n }\r\n });\r\n\r\n await this.validateResponse(response);\r\n\r\n const { status } = await response.json();\r\n if (status !== 0) throw new Error(`Bin delete failed with error: ${status.message}`);\r\n\r\n return {\r\n status: 'ok'\r\n };\r\n } catch (error) {\r\n console.error('deleteBin error:', error);\r\n return {\r\n status: 'error',\r\n statusText: <string>error\r\n };\r\n }\r\n };\r\n}\r\n"],"mappings":"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","names":["ECJsonStorage","apiKey","securityKey","url","response","counter","data","error","res","bin","payload","keepPrivate","headers","uri","status"]}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neonwilderness/ecjsonstorage",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.cts",
|
|
8
|
-
"exports":
|
|
8
|
+
"exports": {
|
|
9
9
|
"import": {
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"import": "./dist/index.js"
|
|
@@ -39,14 +39,15 @@
|
|
|
39
39
|
"type": "module",
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/dotenv-safe": "^9.1.0",
|
|
42
|
-
"@types/node": "^26.6.
|
|
43
|
-
"dotenv": "^18.0.
|
|
42
|
+
"@types/node": "^26.6.4",
|
|
43
|
+
"dotenv": "^18.0.5",
|
|
44
44
|
"dotenv-safe": "^9.1.0",
|
|
45
45
|
"tsup": "^8.5.1",
|
|
46
46
|
"typescript": "^6.0.3",
|
|
47
47
|
"vitest": "^5.0.3"
|
|
48
48
|
},
|
|
49
49
|
"allowScripts": {
|
|
50
|
-
"esbuild@0.28.2": true
|
|
50
|
+
"esbuild@0.28.2": true,
|
|
51
|
+
"esbuild@0.27.2": true
|
|
51
52
|
}
|
|
52
53
|
}
|
package/src/index.ts
CHANGED
|
@@ -200,6 +200,7 @@ export class ECJsonStorage {
|
|
|
200
200
|
*/
|
|
201
201
|
updateBin = async (payload: object, bin: string): Promise<resUpdateBin | resError> => {
|
|
202
202
|
try {
|
|
203
|
+
if (!bin) throw new Error('Bin ID missing!');
|
|
203
204
|
const response = await fetch(`${this.url}/${bin}`, {
|
|
204
205
|
method: 'PUT',
|
|
205
206
|
headers: {
|
|
@@ -235,6 +236,7 @@ export class ECJsonStorage {
|
|
|
235
236
|
*/
|
|
236
237
|
patchBin = async (payload: object, bin: string): Promise<resPatchBin | resError> => {
|
|
237
238
|
try {
|
|
239
|
+
if (!bin) throw new Error('Bin ID missing!');
|
|
238
240
|
const response = await fetch(`${this.url}/${bin}`, {
|
|
239
241
|
method: 'PATCH',
|
|
240
242
|
headers: {
|
|
@@ -268,6 +270,7 @@ export class ECJsonStorage {
|
|
|
268
270
|
*/
|
|
269
271
|
deleteBin = async (bin: string): Promise<resDeleteBin | resError> => {
|
|
270
272
|
try {
|
|
273
|
+
if (!bin) throw new Error('Bin ID missing!');
|
|
271
274
|
const response = await fetch(`${this.url}/${bin}`, {
|
|
272
275
|
method: 'DELETE',
|
|
273
276
|
headers: {
|