miolo-cli 3.0.0-beta.23 → 3.0.0-beta.230

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miolo-cli",
3
- "version": "3.0.0-beta.23",
3
+ "version": "3.0.0-beta.230",
4
4
  "description": "cli utils for miolo",
5
5
  "author": "Donato Lorenzo <donato@afialapis.com>",
6
6
  "contributors": [
@@ -17,32 +17,25 @@
17
17
  "license": "MIT",
18
18
  "type": "module",
19
19
  "exports": {
20
- ".": {
21
- "development": "./src/index.mjs",
22
- "import": "./dist/miolo-cli.mjs",
23
- "default": "./dist/miolo-cli.umd.js"
24
- }
20
+ ".": "./src/index.mjs"
25
21
  },
26
22
  "files": [
27
- "dist",
28
- "src"
23
+ "src",
24
+ "package.json"
29
25
  ],
30
26
  "scripts": {
31
- "reset": "rm -fr package-lock.json npm-lock.yaml dist/* && npm i",
32
- "clean": "rm -fr ./dist/*",
33
- "bundle": "npx xeira bundle --target=browser --source_index=./src/index.mjs --bundle_folder=./dist --bundle_name=miolo-cli --bundle_extension=umd,mjs",
34
- "dist": "npm run clean && npm run bundle"
27
+ "reset": "rm -fr package-lock.json npm-lock.yaml node_modules && npm i",
28
+ "lint": "biome check ./src --reporter=github",
29
+ "lint:fix": "biome check --write ./src --reporter=github",
30
+ "lint:types": "tsc -p jsconfig.json --noEmit",
31
+ "prepublishOnly": "npm run lint"
35
32
  },
36
33
  "dependencies": {
37
- "socket.io-client": "^4.8.1"
34
+ "qs": "^6.15.3",
35
+ "socket.io-client": "^4.8.3",
36
+ "tinguir": "^0.0.7"
38
37
  },
39
- "devDependencies": {
40
- "node-fetch": "^3.3.2",
41
- "xeira": "^1.2.3"
42
- },
43
- "eslintConfig": {
44
- "extends": [
45
- "../../node_modules/xeira/configs/eslint.cjs"
46
- ]
38
+ "engines": {
39
+ "node": ">=24"
47
40
  }
48
- }
41
+ }
@@ -1,9 +1,9 @@
1
- function init_catcher (catcher_url, fetcher) {
2
- if (typeof window == "undefined") {
1
+ function init_catcher(catcher_url, fetcher) {
2
+ if (typeof window === "undefined") {
3
3
  return
4
- }
4
+ }
5
5
 
6
- if (window.miolo_listeners===true) {
6
+ if (window.miolo_listeners === true) {
7
7
  return
8
8
  }
9
9
 
@@ -23,53 +23,51 @@ function init_catcher (catcher_url, fetcher) {
23
23
  // }
24
24
  // }
25
25
 
26
-
27
26
  window.addEventListener("error", (event) => {
28
27
  // https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent
29
28
 
30
29
  try {
31
- const params= {
32
- 'error': {
33
- msg: event?.message || 'Client error',
30
+ const params = {
31
+ error: {
32
+ msg: event?.message || "Client error",
34
33
  file: event?.filename,
35
34
  line: event?.lineno,
36
35
  col: event?.colno,
37
36
  error: event?.error
38
37
  },
39
- 'path' : window.location.pathname,
40
- 'agent': 'UserAgent' + navigator.userAgent
38
+ path: window.location.pathname,
39
+ agent: "UserAgent" + navigator.userAgent
41
40
  }
42
41
 
43
42
  fetcher.post(catcher_url, params)
44
- } catch(e) {
43
+ } catch (e) {
45
44
  console.error(e)
46
45
  }
47
- })
46
+ })
48
47
 
49
48
  window.addEventListener("unhandledrejection", (event) => {
50
49
  // https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent
51
50
 
52
51
  try {
53
- const params= {
54
- 'warning': {
55
- msg: event?.reason || 'Client Unhandled rejection',
52
+ const params = {
53
+ warning: {
54
+ msg: event?.reason || "Client Unhandled rejection",
56
55
  file: undefined,
57
56
  line: undefined,
58
57
  col: undefined,
59
58
  error: event?.reason
60
59
  },
61
- 'path' : window.location.pathname,
62
- 'agent': 'UserAgent' + navigator.userAgent
60
+ path: window.location.pathname,
61
+ agent: "UserAgent" + navigator.userAgent
63
62
  }
64
63
 
65
64
  fetcher.post(catcher_url, params)
66
- } catch(e) {
65
+ } catch (e) {
67
66
  console.error(e)
68
67
  }
69
- })
68
+ })
70
69
 
71
70
  window.miolo_listeners = true
72
-
73
71
  }
74
72
 
75
- export {init_catcher}
73
+ export { init_catcher }
@@ -1,214 +1,211 @@
1
- import {omit_nil, trim_left, json_to_query_string, parse_login_cookie} from './utils.mjs'
1
+ import { json_to_query_string, null_to_undefined, omit_nil, trim_left } from "./utils.mjs"
2
2
 
3
3
  class Fetcher {
4
4
  /**
5
5
  * @param {*} config {hostname, port, force_hostname, silent_fail: false}
6
6
  */
7
- constructor(config) {
8
- this.config= config
9
- this.auth = undefined
10
- this.cookie = undefined
7
+ constructor(config, socket = undefined) {
8
+ this.config = config
9
+ this.http_auth = undefined
10
+ this.socket = socket
11
11
  }
12
12
 
13
- set_auth(auth) {
13
+ set_http_auth(auth) {
14
14
  if (auth) {
15
- const {username, password}= auth
16
- this.auth= {username, password}
15
+ const { username, password } = auth
16
+ this.http_auth = { username, password }
17
17
  }
18
18
  }
19
19
 
20
20
  get_headers() {
21
- let headers = {}
21
+ const headers = {}
22
22
 
23
- if (this.auth) {
24
- let {username, password}= this.auth
25
- username= username || ''
26
- password= password || ''
23
+ if (this.socket?.id) {
24
+ headers["x-socket-id"] = this.socket.id
25
+ }
26
+
27
+ if (this.http_auth) {
28
+ let { username, password } = this.http_auth
29
+ username = username || ""
30
+ password = password || ""
27
31
 
28
32
  let sauth
29
33
  try {
30
- sauth= 'Basic ' + Buffer.from(username + ":" + password).toString('base64')
31
- } catch(_) {
32
- sauth= 'Basic ' + btoa(username + ":" + password)
34
+ sauth = "Basic " + Buffer.from(username + ":" + password).toString("base64")
35
+ } catch (_) {
36
+ sauth = "Basic " + btoa(username + ":" + password)
33
37
  }
34
38
 
35
- headers['Authorization']= sauth
36
- }
37
-
38
- if (this.cookie) {
39
- headers['Cookie']= this.cookie
39
+ headers.Authorization = sauth
40
40
  }
41
41
 
42
42
  return headers
43
43
  }
44
44
 
45
- _prepare_url (url) {
46
- const endpoint = '/' + trim_left(url, '/')
47
-
48
- const {hostname, port, force_hostname} = this.config || {}
45
+ _prepare_url(url) {
46
+ const endpoint = "/" + trim_left(url, "/")
47
+
48
+ const { hostname, port, force_hostname } = this.config || {}
49
49
  if (hostname && force_hostname) {
50
50
  return `http://${hostname}:${port}${endpoint}`
51
51
  }
52
-
52
+
53
53
  return endpoint
54
54
  }
55
55
 
56
- async _fetch (method, url, params, auth= undefined) {
57
- this.set_auth(auth)
56
+ async _fetch(method, url, params, http_auth = undefined) {
57
+ this.set_http_auth(http_auth)
58
58
 
59
- let request = {
59
+ const request = {
60
60
  method,
61
- mode: 'cors',
62
- credentials: 'include',
61
+ mode: "cors",
62
+ credentials: "include",
63
63
  headers: {
64
- 'content-type': 'application/json',
65
- ...this.get_headers() || {}
64
+ "content-type": "application/json",
65
+ ...(this.get_headers() || {})
66
66
  }
67
67
  }
68
68
 
69
69
  let wurl = this._prepare_url(url)
70
-
71
- if (method === 'POST') {
72
- request.body = JSON.stringify(params || {}, (k, v) => v === undefined ? null : v)
73
- } else if (method === 'GET') {
70
+
71
+ if (method === "POST") {
72
+ request.body = JSON.stringify(params || {}, (_k, v) => (v === undefined ? null : v))
73
+ } else if (method === "GET") {
74
74
  if (params) {
75
- wurl+= json_to_query_string(params)
75
+ wurl += json_to_query_string(params)
76
76
  }
77
77
  }
78
-
78
+
79
79
  const response = await fetch(wurl, request)
80
-
80
+
81
+ if (response.ok === false) {
82
+ return {
83
+ ok: false,
84
+ status: response.status,
85
+ response,
86
+ error: response.statusText
87
+ }
88
+ }
89
+
81
90
  if (response.redirected) {
82
- const isBrowser = typeof window == 'object'
91
+ const isBrowser = typeof window === "object"
83
92
  if (isBrowser) {
84
93
  // JSDOM does not support navigation, so lets skip it for tests
85
- const isTest = typeof navigator !== "undefined" &&
86
- navigator.userAgent.includes("Node.js");
94
+ const isTest = typeof navigator !== "undefined" && navigator.userAgent.includes("Node.js")
87
95
  if (!isTest) {
88
96
  window.location.replace(response.url)
89
97
  return Promise.resolve(response)
90
98
  } else {
91
- console.error(`Response for ${wurl} is a redirect to ${response.url}. But you are in a test environment, where redirects cannot be done. Unexpected results are coming...`)
99
+ console.error(
100
+ `Response for ${wurl} is a redirect to ${response.url}. But you are in a test environment, where redirects cannot be done. Unexpected results are coming...`
101
+ )
92
102
  }
93
103
  }
94
104
  }
95
-
96
- if (response.headers.get('content-type').indexOf('json') >= 0) {
97
- const data= await response.json()
98
-
105
+
106
+ if (response.headers.get("content-type").indexOf("json") >= 0) {
107
+ let resp = await response.json()
108
+ resp = null_to_undefined(resp)
109
+
99
110
  return {
100
- data,
111
+ ...resp,
101
112
  status: response.status,
102
113
  response
103
114
  }
104
115
  }
105
-
106
- const data= await response.text()
116
+
117
+ const data = await response.text()
107
118
  return {
119
+ ok: true,
108
120
  data,
109
121
  status: response.status,
110
122
  response
111
123
  }
112
-
113
124
  }
114
-
115
- async get(url, params, auth= undefined) {
116
- /* eslint no-unused-vars:0 */
125
+
126
+ async get(url, params, http_auth = undefined) {
117
127
  try {
118
- const resp = await this._fetch('GET', url, omit_nil(params), auth)
128
+ const resp = await this._fetch("GET", url, omit_nil(params), http_auth)
119
129
  return resp
120
- } catch(e) {
130
+ } catch (e) {
121
131
  if (this.config?.silent_fail !== true) {
122
132
  console.error(`Error on GET ${url}`)
123
133
  console.error(e)
124
134
  }
125
135
 
126
136
  return {
127
- data: e,
128
- status: -1,
137
+ ok: false,
138
+ error: e,
139
+ status: -1
129
140
  }
130
141
  }
131
142
  }
132
143
 
133
- async post(url, data, auth= undefined) {
144
+ async post(url, data, http_auth = undefined) {
134
145
  try {
135
- const resp = await this._fetch('POST', url, data, auth)
146
+ const resp = await this._fetch("POST", url, data, http_auth)
136
147
  return resp
137
- } catch(e) {
148
+ } catch (e) {
138
149
  if (this.config?.silent_fail !== true) {
139
150
  console.error(`Error on POST ${url}`)
140
151
  console.error(e)
141
152
  }
142
153
 
143
154
  return {
144
- data: e,
155
+ ok: false,
156
+ error: e,
145
157
  status: -1
146
158
  }
147
159
  }
148
- }
149
-
150
- async login(url, {username, password}) {
151
- const res= await this._fetch('POST', url || '/login', {username, password})
152
- this.cookie= parse_login_cookie(res.response)
153
- return res
154
160
  }
155
161
 
156
- async logout(url) {
157
- this.cookie= undefined
158
- const res= await this._fetch('POST', url || '/logout', {})
159
- return res
162
+ async read(url, params, http_auth = undefined) {
163
+ return await this.get(`${url}/read`, params, http_auth)
160
164
  }
161
165
 
162
- async read(url, params, auth= undefined) {
163
- const result = await this.get(`${url}/read`, params, auth)
164
- return result.data
166
+ async key_list(url, params, http_auth = undefined) {
167
+ return await this.get(`${url}/key_list`, params, http_auth)
165
168
  }
166
169
 
167
- async key_list(url, params, auth= undefined) {
168
- const result = await this.get(`${url}/key_list`, params, auth)
169
- return result.data
170
- }
171
-
172
- async name_list(url, params, auth= undefined) {
173
- const result = await this.key_list(url, params, auth)
174
- return Object.values(result)
170
+ async name_list(url, params, http_auth = undefined) {
171
+ const resp = await this.key_list(url, params, http_auth)
172
+ if (resp?.data) {
173
+ resp.data = Object.values(resp.data)
174
+ }
175
+ return resp
175
176
  }
176
177
 
177
- async find(url, id, auth= undefined) {
178
- const result = await this.get(`${url}/find`, { id: id }, auth)
179
- return result.data
178
+ async find(url, id, http_auth = undefined) {
179
+ return await this.get(`${url}/find`, { id: id }, http_auth)
180
180
  }
181
181
 
182
- async distinct(url, field, params, auth= undefined) {
183
- const nparams= {
182
+ async distinct(url, field, params, http_auth = undefined) {
183
+ const nparams = {
184
184
  ...params,
185
185
  distinct_field: field
186
186
  }
187
- const result = await this.get(`${url}/distinct`, nparams, auth)
188
- return result.data
187
+ return await this.get(`${url}/distinct`, nparams, http_auth)
189
188
  }
190
189
 
191
- async upsave(url, data, auth= undefined) {
192
- let result
193
- if (data.id == undefined) {
190
+ async upsave(url, data, http_auth = undefined) {
191
+ let resp
192
+ if (data.id === undefined) {
194
193
  delete data.id
195
- result= await this.post(`${url}/save`, data, auth)
194
+ resp = await this.post(`${url}/save`, data, http_auth)
196
195
  } else {
197
- result= await this.post(`${url}/update`, data, auth)
196
+ resp = await this.post(`${url}/update`, data, http_auth)
198
197
  }
199
-
200
- return result.data
201
- }
202
198
 
203
- async remove(url, id, auth= undefined) {
199
+ return resp
200
+ }
201
+
202
+ async remove(url, id, http_auth = undefined) {
204
203
  const data = { id: id }
205
- const result = await this.post(`${url}/delete`, data, auth)
206
- return result.data
204
+ return await this.post(`${url}/delete`, data, http_auth)
207
205
  }
208
206
  }
209
207
 
210
- Fetcher.keyList= Fetcher.key_list
211
- Fetcher.nameList= Fetcher.name_list
208
+ Fetcher.keyList = Fetcher.key_list
209
+ Fetcher.nameList = Fetcher.name_list
212
210
 
213
211
  export { Fetcher }
214
-
@@ -1,7 +1,6 @@
1
- import {Fetcher} from './fetcher.mjs'
1
+ import { Fetcher } from "./fetcher.mjs"
2
2
 
3
-
4
- export function init_fetcher(config) {
5
- const fetcher= new Fetcher(config)
3
+ export function init_fetcher(config, socket = undefined) {
4
+ const fetcher = new Fetcher(config, socket)
6
5
  return fetcher
7
6
  }
@@ -1,59 +1,60 @@
1
+ import qs from "qs"
2
+
1
3
  /**
2
4
  * Transform an JSON object to a query string
3
5
  */
4
- const _parse_value= (value) => {
5
- try {
6
- return value.replace(/\+/g, '%2B')
7
- } catch(e) {
8
- return value
9
- }
10
- }
6
+ // const _parse_value= (value) => {
7
+ // try {
8
+ // return value.replace(/\+/g, '%2B')
9
+ // } catch(e) {
10
+ // return value
11
+ // }
12
+ // }
13
+ //
14
+ // export function json_to_query_string(obj) {
15
+ // if (obj && (Object.keys(obj).length>0)) {
16
+ // const uparams = new URLSearchParams()
17
+ // for (const key in obj) {
18
+ // if (Object.hasOwn(obj, key)) {
19
+ // const value = obj[key];
20
+ // if (Array.isArray(value)) {
21
+ // value.forEach(item => uparams.append(key, _parse_value(item)))
22
+ // } else if (value !== undefined && value !== null) {
23
+ // uparams.append(key, _parse_value(value))
24
+ // }
25
+ // }
26
+ // }
27
+ // return `?${uparams.toString()}`
28
+ // }
29
+ // return ''
30
+ // }
11
31
 
12
32
  export function json_to_query_string(obj) {
13
- if (obj && (Object.keys(obj).length>0)) {
14
- const uparams = new URLSearchParams()
15
- for (const key in obj) {
16
- if (Object.hasOwn(obj, key)) {
17
- const value = obj[key];
18
- if (Array.isArray(value)) {
19
- value.forEach(item => uparams.append(key, _parse_value(item)))
20
- } else if (value !== undefined && value !== null) {
21
- uparams.append(key, _parse_value(value))
22
- }
23
- }
24
- }
25
- return `?${uparams.toString()}`
26
- }
27
- return ''
33
+ if (!obj || Object.keys(obj).length === 0) return ""
34
+ return `?${qs.stringify(obj, { arrayFormat: "repeat" })}`
28
35
  }
29
36
 
30
37
  export function trim_left(str, what) {
31
- return str.replace(new RegExp(`^${what || '\\s'}+`), '')
38
+ return str.replace(new RegExp(`^${what || "\\s"}+`), "")
32
39
  }
33
40
 
34
-
35
41
  export function omit_nil(obj) {
36
- if (typeof obj !== 'object') return obj
42
+ if (typeof obj !== "object") return obj
37
43
  return Object.keys(obj).reduce((acc, v) => {
38
- if (obj[v] !== undefined) acc[v] = obj[v]
44
+ if (obj[v] !== undefined) acc[v] = omit_nil(obj[v])
39
45
  return acc
40
46
  }, {})
41
47
  }
42
48
 
43
-
44
- export function parse_login_cookie(response) {
45
- if (typeof window !== 'object') {
46
- return undefined
47
- }
48
- try {
49
- const raw = response.headers.raw()['set-cookie'];
50
- return raw.map((entry) => {
51
- const parts = entry.split(';');
52
- const cookiePart = parts[0];
53
- return cookiePart;
54
- }).join(';');
55
- } catch(e) {
56
- console.log('[miolo-cli] Could not get the set-cookie after login')
57
- return undefined
49
+ export function null_to_undefined(value) {
50
+ if (Array.isArray(value)) {
51
+ return value.map(null_to_undefined)
52
+ } else if (value && typeof value === "object") {
53
+ const data = {}
54
+ for (const [key, val] of Object.entries(value)) {
55
+ data[key] = val === null ? undefined : null_to_undefined(val)
56
+ }
57
+ return data
58
58
  }
59
- }
59
+ return value
60
+ }
package/src/index.mjs CHANGED
@@ -1,30 +1,36 @@
1
- import {init_catcher} from './catcher/index.mjs'
2
- import {init_fetcher} from './fetcher/index.mjs'
3
- // import {init_socket} from './socket/index.mjs'
4
-
5
- function miolo_client(context) {
6
-
7
- const {config} = context
1
+ import { init_catcher } from "./catcher/index.mjs"
2
+ import { init_fetcher } from "./fetcher/index.mjs"
3
+ import { init_logger } from "./logger/index.mjs"
4
+ import { init_socket } from "./socket/index.mjs"
5
+
6
+ export function miolo_client(context) {
7
+ const { config } = context
8
+ const logger = init_logger(config?.log_level || "warn")
9
+
10
+ let socket
11
+ if (config?.socket?.enabled === true) {
12
+ logger.verbose(`[miolo-cli] init_socket at ${config?.socket?.url || "default url"}`)
13
+ const url = config?.socket?.url
14
+ const options = config?.socket?.options
15
+ socket = init_socket(url, options)
16
+ logger.verbose(
17
+ `[miolo-cli] socket initiated at ${socket?.url || "default url"} with id ${socket?.id}`
18
+ )
19
+ }
8
20
 
9
- const fetcher = init_fetcher(config)
21
+ logger.verbose(`[miolo-cli] init_fetcher`)
22
+ const fetcher = init_fetcher(config, socket)
10
23
 
11
24
  if (config?.catcher_url) {
12
- init_catcher(config?.catcher_url, fetcher)
25
+ logger.verbose(`[miolo-cli] init_catcher at ${config?.catcher_url}`)
26
+ init_catcher(config?.catcher_url, fetcher)
13
27
  }
14
28
 
15
- // let socket
16
- // if (config?.socket?.enabled===true) {
17
- // const domain = config?.socket?.domain
18
- // const options = config?.socket?.options
19
- // socket = init_socket(domain, options)
20
- // }
21
-
22
- const miolo_obj= {
29
+ const miolo_obj = {
30
+ logger,
23
31
  fetcher,
24
- //socket
32
+ socket
25
33
  }
26
34
 
27
35
  return miolo_obj
28
36
  }
29
-
30
- export {miolo_client}
@@ -0,0 +1,51 @@
1
+ import { blue, cyan, gray, magenta, red, yellow } from "tinguir"
2
+
3
+ const LEVELS = {
4
+ none: 0,
5
+ error: 1,
6
+ warn: 2,
7
+ info: 3,
8
+ verbose: 4,
9
+ debug: 5,
10
+ silly: 6
11
+ }
12
+
13
+ export default class Logger {
14
+ constructor(level) {
15
+ this.set_level(level)
16
+ }
17
+
18
+ set_level(level) {
19
+ this.level = LEVELS[level !== undefined ? level : "none"]
20
+ }
21
+
22
+ _log(color, lvl, msg) {
23
+ if (this.level >= LEVELS[lvl]) {
24
+ console.log(`[${lvl}] ${color(msg)}`)
25
+ }
26
+ }
27
+
28
+ silly(msg) {
29
+ this._log(gray, "silly", msg)
30
+ }
31
+
32
+ debug(msg) {
33
+ this._log(magenta, "debug", msg)
34
+ }
35
+
36
+ verbose(msg) {
37
+ this._log(cyan, "verbose", msg)
38
+ }
39
+
40
+ info(msg) {
41
+ this._log(blue, "info", msg)
42
+ }
43
+
44
+ warn(msg) {
45
+ this._log(yellow, "warn", msg)
46
+ }
47
+
48
+ error(msg) {
49
+ this._log(red, "error", msg)
50
+ }
51
+ }