@storecraft/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -0
- package/index.js +103 -0
- package/package.json +29 -0
- package/src/auth.js +382 -0
- package/src/bots.js +113 -0
- package/src/collections.js +129 -0
- package/src/customers.js +21 -0
- package/src/discounts.js +149 -0
- package/src/images.js +21 -0
- package/src/notifications.js +102 -0
- package/src/orders.js +47 -0
- package/src/payments.js +89 -0
- package/src/posts.js +22 -0
- package/src/products.js +74 -0
- package/src/settings.js +19 -0
- package/src/shipping.js +22 -0
- package/src/statistics.js +99 -0
- package/src/storage.js +325 -0
- package/src/storefronts.js +113 -0
- package/src/tags.js +21 -0
- package/src/templates.js +21 -0
- package/src/utils.api.fetch.js +281 -0
- package/src/utils.functional.js +141 -0
- package/tsconfig.json +29 -0
- package/types.d.ts +1 -0
@@ -0,0 +1,281 @@
|
|
1
|
+
|
2
|
+
import {
|
3
|
+
api_query_to_searchparams
|
4
|
+
} from '@storecraft/core/v-api/utils.query.js';
|
5
|
+
import { assert } from './utils.functional.js';
|
6
|
+
|
7
|
+
|
8
|
+
/**
|
9
|
+
*
|
10
|
+
* @param {import("../index.js").StorecraftSDKConfig} config
|
11
|
+
* @param {string} path
|
12
|
+
*/
|
13
|
+
export const url = (config, path) => {
|
14
|
+
let base = config?.endpoint?.trim();
|
15
|
+
|
16
|
+
base = base?.endsWith('/') ? base.slice(0, -1) : base;
|
17
|
+
path = path?.startsWith('/') ? path.slice(1) : path;
|
18
|
+
|
19
|
+
return base ? `${base}/api/${path}` : `/api/${path}`;
|
20
|
+
}
|
21
|
+
|
22
|
+
|
23
|
+
/**
|
24
|
+
* - Prepends `backend` endpoint.
|
25
|
+
* - Fetches with `authentication` middleware.
|
26
|
+
* - Refreshed `auth` if needed.
|
27
|
+
*
|
28
|
+
* @param {import('../index.js').StorecraftSDK} sdk
|
29
|
+
* @param {string} path relative path in api
|
30
|
+
* @param {RequestInit} [init] request `init` type
|
31
|
+
*
|
32
|
+
* @returns {Promise<Response>}
|
33
|
+
*/
|
34
|
+
export const fetchOnlyApiResponseWithAuth = async (sdk, path, init={}) => {
|
35
|
+
|
36
|
+
const auth_token = await sdk.auth.working_auth_token();
|
37
|
+
const auth_header_value = (
|
38
|
+
sdk.auth.authStrategy==='apikey' ? 'Basic' : 'Bearer'
|
39
|
+
) + ` ${auth_token}`;
|
40
|
+
|
41
|
+
|
42
|
+
const response = await fetch(
|
43
|
+
url(sdk.config, path),
|
44
|
+
{
|
45
|
+
...init,
|
46
|
+
headers: {
|
47
|
+
...(init?.headers ?? {}),
|
48
|
+
'Authorization': auth_header_value
|
49
|
+
}
|
50
|
+
}
|
51
|
+
);
|
52
|
+
|
53
|
+
return response;
|
54
|
+
|
55
|
+
// const auth_problem = response.status >= 400 && response.status < 500;
|
56
|
+
|
57
|
+
// if(auth_problem) {
|
58
|
+
|
59
|
+
// }
|
60
|
+
}
|
61
|
+
|
62
|
+
|
63
|
+
/**
|
64
|
+
* - Prepends `backend` endpoint.
|
65
|
+
* - Fetches with `authentication` middleware.
|
66
|
+
* - Refreshed `auth` if needed.
|
67
|
+
* - Throws a `json` representation of the `error`,
|
68
|
+
* if the request is `bad`
|
69
|
+
*
|
70
|
+
* @template {any} R
|
71
|
+
*
|
72
|
+
* @param {import('../index.js').StorecraftSDK} sdk
|
73
|
+
* @param {string} path relative path in api
|
74
|
+
* @param {RequestInit} [init] request `init` type
|
75
|
+
*
|
76
|
+
*
|
77
|
+
* @throws {import('@storecraft/core/v-api').error}
|
78
|
+
*
|
79
|
+
* @returns {Promise<R>}
|
80
|
+
*/
|
81
|
+
export const fetchApiWithAuth = async (sdk, path, init={}) => {
|
82
|
+
|
83
|
+
const response = await fetchOnlyApiResponseWithAuth(
|
84
|
+
sdk, path, init
|
85
|
+
);
|
86
|
+
|
87
|
+
// console.log('fetchApiWithAuth::response', response)
|
88
|
+
|
89
|
+
const isok = response.ok;
|
90
|
+
let payload = undefined;
|
91
|
+
|
92
|
+
try {
|
93
|
+
payload = await response.json();
|
94
|
+
} catch(e) {
|
95
|
+
console.log('fetchApiWithAuth.json()', e)
|
96
|
+
}
|
97
|
+
|
98
|
+
if(!isok)
|
99
|
+
throw payload;
|
100
|
+
|
101
|
+
return payload;
|
102
|
+
}
|
103
|
+
|
104
|
+
|
105
|
+
/**
|
106
|
+
* @template {any} G Get type
|
107
|
+
*
|
108
|
+
*
|
109
|
+
* @param {import('../index.js').StorecraftSDK} sdk
|
110
|
+
* @param {string} handle_or_id `handle` or `id`
|
111
|
+
* @param {string} resource base path of resource
|
112
|
+
*
|
113
|
+
*
|
114
|
+
* @returns {Promise<G>}
|
115
|
+
*/
|
116
|
+
export async function get(sdk, resource, handle_or_id) {
|
117
|
+
return fetchApiWithAuth(
|
118
|
+
sdk,
|
119
|
+
`${resource}/${handle_or_id}`,
|
120
|
+
{
|
121
|
+
method: 'get'
|
122
|
+
}
|
123
|
+
);
|
124
|
+
}
|
125
|
+
|
126
|
+
|
127
|
+
/**
|
128
|
+
*
|
129
|
+
* @template {any} U the upsert type
|
130
|
+
*
|
131
|
+
*
|
132
|
+
* @param {import('../index.js').StorecraftSDK} sdk
|
133
|
+
* @param {string} resource base path of resource
|
134
|
+
* @param {U} item Item to upsert
|
135
|
+
*
|
136
|
+
*
|
137
|
+
* @returns {Promise<string>} id
|
138
|
+
*/
|
139
|
+
export async function upsert(sdk, resource, item) {
|
140
|
+
return fetchApiWithAuth(
|
141
|
+
sdk,
|
142
|
+
`${resource}`,
|
143
|
+
{
|
144
|
+
method: 'post',
|
145
|
+
body: JSON.stringify(item),
|
146
|
+
headers: {
|
147
|
+
'Content-Type': 'application/json'
|
148
|
+
}
|
149
|
+
}
|
150
|
+
);
|
151
|
+
}
|
152
|
+
|
153
|
+
|
154
|
+
/**
|
155
|
+
*
|
156
|
+
* @param {import('../index.js').StorecraftSDK} sdk
|
157
|
+
* @param {string} resource base path of resource
|
158
|
+
* @param {string} handle_or_id `handle` or `id`
|
159
|
+
*
|
160
|
+
*
|
161
|
+
* @returns {Promise<boolean>}
|
162
|
+
*/
|
163
|
+
export async function remove(sdk, resource, handle_or_id) {
|
164
|
+
return fetchApiWithAuth(
|
165
|
+
sdk,
|
166
|
+
`${resource}/${handle_or_id}`,
|
167
|
+
{
|
168
|
+
method: 'delete'
|
169
|
+
}
|
170
|
+
);
|
171
|
+
}
|
172
|
+
|
173
|
+
|
174
|
+
/**
|
175
|
+
* @description Invoke `api` endpoint that requires use of `query`
|
176
|
+
* object. I named it `list` because it usually entails list op.
|
177
|
+
*
|
178
|
+
*
|
179
|
+
* @template {any} G Get type
|
180
|
+
*
|
181
|
+
*
|
182
|
+
* @param {import('../index.js').StorecraftSDK} sdk
|
183
|
+
* @param {string} resource base path of resource
|
184
|
+
* @param {import('@storecraft/core/v-api').ApiQuery} [query]
|
185
|
+
*
|
186
|
+
*
|
187
|
+
* @returns {Promise<G[]>}
|
188
|
+
*/
|
189
|
+
export async function list(sdk, resource, query={}) {
|
190
|
+
const sq = api_query_to_searchparams(query);
|
191
|
+
|
192
|
+
// console.log('sq', sq.toString())
|
193
|
+
return fetchApiWithAuth(
|
194
|
+
sdk,
|
195
|
+
`${resource}?${sq.toString()}`,
|
196
|
+
{
|
197
|
+
method: 'get'
|
198
|
+
}
|
199
|
+
);
|
200
|
+
}
|
201
|
+
|
202
|
+
|
203
|
+
/**
|
204
|
+
* A simple resource base `class` with `CRUD` helpers
|
205
|
+
*
|
206
|
+
*
|
207
|
+
* @template {any} U upsert type
|
208
|
+
* @template {any} G get type
|
209
|
+
*/
|
210
|
+
export class collection_base {
|
211
|
+
|
212
|
+
/** @type {import('../index.js').StorecraftSDK} */
|
213
|
+
#sdk = undefined;
|
214
|
+
|
215
|
+
/** @type {string} */
|
216
|
+
#base_name = undefined;
|
217
|
+
|
218
|
+
/**
|
219
|
+
*
|
220
|
+
* @param {import('../index.js').StorecraftSDK} sdk storecraft sdk
|
221
|
+
* @param {string} base_name base name of resource type
|
222
|
+
*/
|
223
|
+
constructor(sdk, base_name) {
|
224
|
+
this.#sdk = sdk;
|
225
|
+
this.#base_name = base_name;
|
226
|
+
}
|
227
|
+
|
228
|
+
|
229
|
+
/**
|
230
|
+
*
|
231
|
+
* @param {string} handle_or_id `handle` or `id`
|
232
|
+
*
|
233
|
+
*
|
234
|
+
* @returns {Promise<G>}
|
235
|
+
*/
|
236
|
+
async get(handle_or_id) {
|
237
|
+
return get(this.sdk, this.base_name, handle_or_id);
|
238
|
+
}
|
239
|
+
|
240
|
+
/**
|
241
|
+
*
|
242
|
+
* @param {U} item Item to upsert
|
243
|
+
*
|
244
|
+
*
|
245
|
+
* @returns {Promise<string>} id
|
246
|
+
*/
|
247
|
+
async upsert(item) {
|
248
|
+
return upsert(this.sdk, this.base_name, item);
|
249
|
+
}
|
250
|
+
|
251
|
+
/**
|
252
|
+
*
|
253
|
+
* @param {string} handle_or_id `handle` or `id`
|
254
|
+
*
|
255
|
+
*
|
256
|
+
* @returns {Promise<boolean>}
|
257
|
+
*/
|
258
|
+
async remove(handle_or_id) {
|
259
|
+
return remove(this.sdk, this.base_name, handle_or_id);
|
260
|
+
}
|
261
|
+
|
262
|
+
/**
|
263
|
+
*
|
264
|
+
* @param {import('@storecraft/core/v-api').ApiQuery} query Query object
|
265
|
+
*
|
266
|
+
*
|
267
|
+
* @returns {Promise<G[]>}
|
268
|
+
*/
|
269
|
+
async list(query) {
|
270
|
+
return list(this.sdk, this.base_name, query);
|
271
|
+
}
|
272
|
+
|
273
|
+
get base_name() {
|
274
|
+
return this.#base_name;
|
275
|
+
}
|
276
|
+
|
277
|
+
get sdk() {
|
278
|
+
return this.#sdk;
|
279
|
+
}
|
280
|
+
|
281
|
+
}
|
@@ -0,0 +1,141 @@
|
|
1
|
+
/**
|
2
|
+
* @param {...any} fields
|
3
|
+
*/
|
4
|
+
export const select_fields = (...fields) => {
|
5
|
+
/**
|
6
|
+
* @param {object} o
|
7
|
+
*/
|
8
|
+
return o => fields.reduce((p, c) => ({ ...p, [c] : o[c] }), {});
|
9
|
+
}
|
10
|
+
|
11
|
+
/**
|
12
|
+
*
|
13
|
+
* @param {...any} fields
|
14
|
+
*/
|
15
|
+
export const filter_fields = (...fields) => {
|
16
|
+
/**
|
17
|
+
* @param {any[]} items
|
18
|
+
*/
|
19
|
+
return items => items.map(item => select_fields(...fields)(item))
|
20
|
+
}
|
21
|
+
|
22
|
+
/**
|
23
|
+
*
|
24
|
+
* @param {object} o
|
25
|
+
*/
|
26
|
+
export const select_unused_fields = o => Object.keys(o).reduce((p, c) => {
|
27
|
+
if(Array.isArray(o[c])) {
|
28
|
+
if(o[c].length) p[c]=o[c]
|
29
|
+
}
|
30
|
+
else if(typeof o[c]!=='undefined')
|
31
|
+
p[c]=o[c]
|
32
|
+
return p
|
33
|
+
}, {});
|
34
|
+
|
35
|
+
/**
|
36
|
+
*
|
37
|
+
* @param {any[]} items
|
38
|
+
*/
|
39
|
+
export const filter_unused = items =>
|
40
|
+
items.map(item => select_unused_fields(item));
|
41
|
+
|
42
|
+
/**
|
43
|
+
* @param {...string} keys
|
44
|
+
*/
|
45
|
+
export const delete_keys = (...keys) => {
|
46
|
+
/**
|
47
|
+
* @param {any} o
|
48
|
+
*/
|
49
|
+
return o => {
|
50
|
+
o = Array.isArray(o) ? o : [o]
|
51
|
+
o.forEach(it => keys.forEach(k => delete it[k] ))
|
52
|
+
return o
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
|
57
|
+
/**
|
58
|
+
*
|
59
|
+
* @param {string} text
|
60
|
+
*/
|
61
|
+
export const text2tokens_unsafe = (text) => {
|
62
|
+
return text?.toString().toLowerCase().match(/\S+/g)
|
63
|
+
}
|
64
|
+
|
65
|
+
export const STOP_WORDS = [
|
66
|
+
'i','me','my','myself','we','our','ours','ourselves','you',
|
67
|
+
'your','yours','yourself','yourselves','he','him','his','himself',
|
68
|
+
'she','her','hers','herself','it','its','itself','they','them',
|
69
|
+
'their','theirs','themselves','what','which','who','whom','this',
|
70
|
+
'that','these','those','am','is','are','was','were','be','been',
|
71
|
+
'being','have','has','had','having','do','does','did','doing','a',
|
72
|
+
'an','the','and','but','if','or','because','as','until','while',
|
73
|
+
'of','at','by','for','with','about','against','between','into',
|
74
|
+
'through','during','before','after','above','below','to','from','up',
|
75
|
+
'down','in','out','on','off','over','under','again','further','then','once',
|
76
|
+
'here','there','when','where','why','how','all','any','both','each','few',
|
77
|
+
'more','most','other','some','such','no','nor','not','only','own','same',
|
78
|
+
'so','than','too','very','s','t','can','will','just','don','should','now'
|
79
|
+
]
|
80
|
+
|
81
|
+
/**
|
82
|
+
*
|
83
|
+
* @param {string} text
|
84
|
+
* @returns {string[] | undefined}
|
85
|
+
*/
|
86
|
+
export const text2tokens = (text) => {
|
87
|
+
// match can return undefined
|
88
|
+
// let tokens = text?.toString().toLowerCase().match(/\S+/g)
|
89
|
+
// let tokens = text?.toString().toLowerCase().match(/[^\W_]+/g)
|
90
|
+
let tokens = text?.toString().toLowerCase().match(/[\p{L}\d]+/gu)
|
91
|
+
|
92
|
+
tokens = tokens ?? []
|
93
|
+
tokens = tokens.filter(
|
94
|
+
t => !STOP_WORDS.includes(t)
|
95
|
+
)
|
96
|
+
|
97
|
+
return tokens
|
98
|
+
}
|
99
|
+
|
100
|
+
|
101
|
+
/**
|
102
|
+
*
|
103
|
+
* @param {any[]} arrA
|
104
|
+
* @param {any[]} arrB
|
105
|
+
* @returns
|
106
|
+
*/
|
107
|
+
export const union_array = (arrA=[], arrB=[]) => [
|
108
|
+
...new Set([...arrA, ...arrB])
|
109
|
+
];
|
110
|
+
|
111
|
+
/**
|
112
|
+
* @param {string} str
|
113
|
+
*/
|
114
|
+
export const isEmpty = (str) => (!str?.trim().length)
|
115
|
+
|
116
|
+
/**
|
117
|
+
* Transforms a string into a handle
|
118
|
+
* @param {string} title
|
119
|
+
*/
|
120
|
+
export const to_handle = (title) => {
|
121
|
+
if(typeof title !== 'string')
|
122
|
+
return undefined
|
123
|
+
let trimmed = title.trim()
|
124
|
+
if(trimmed === "")
|
125
|
+
return undefined
|
126
|
+
|
127
|
+
trimmed = trimmed.toLowerCase().match(/[\p{L}\d]+/gu).join('-')
|
128
|
+
if(trimmed.length==0)
|
129
|
+
return undefined
|
130
|
+
|
131
|
+
return trimmed
|
132
|
+
}
|
133
|
+
|
134
|
+
/**
|
135
|
+
* @param {any} condition
|
136
|
+
* @param {string} msg
|
137
|
+
*/
|
138
|
+
export const assert = (condition, msg) => {
|
139
|
+
if(!Boolean(condition))
|
140
|
+
throw msg
|
141
|
+
}
|
package/tsconfig.json
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
{
|
2
|
+
"compileOnSave": false,
|
3
|
+
"compilerOptions": {
|
4
|
+
"noEmit": true,
|
5
|
+
"allowJs": true,
|
6
|
+
"checkJs": true,
|
7
|
+
"resolveJsonModule": true,
|
8
|
+
"target": "ESNext",
|
9
|
+
"module": "NodeNext",
|
10
|
+
"moduleResolution": "NodeNext",
|
11
|
+
"esModuleInterop": true,
|
12
|
+
"lib": [
|
13
|
+
"dom",
|
14
|
+
"dom.iterable",
|
15
|
+
"esnext"
|
16
|
+
],
|
17
|
+
"skipLibCheck": true,
|
18
|
+
"strict": false,
|
19
|
+
"incremental": true,
|
20
|
+
"isolatedModules": true
|
21
|
+
},
|
22
|
+
"include": [
|
23
|
+
"*",
|
24
|
+
"**/*"
|
25
|
+
],
|
26
|
+
"exclude": [
|
27
|
+
"**/*.json"
|
28
|
+
]
|
29
|
+
}
|
package/types.d.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export * from './index.js'
|