@hybridly/utils 0.0.1-dev.4 → 0.1.0-alpha.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/dist/index.cjs CHANGED
@@ -3,11 +3,13 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  const baseMerge = require('deepmerge');
6
+ const lodash_clonedeep = require('lodash.clonedeep');
6
7
  const makeDebugger = require('debug');
7
8
 
8
9
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
9
10
 
10
11
  const baseMerge__default = /*#__PURE__*/_interopDefaultLegacy(baseMerge);
12
+ const lodash_clonedeep__default = /*#__PURE__*/_interopDefaultLegacy(lodash_clonedeep);
11
13
  const makeDebugger__default = /*#__PURE__*/_interopDefaultLegacy(makeDebugger);
12
14
 
13
15
  function hasFiles(data) {
@@ -19,7 +21,7 @@ function hasFiles(data) {
19
21
  function objectToFormData(source, form, parentKey) {
20
22
  source ?? (source = {});
21
23
  form ?? (form = new FormData());
22
- if (typeof source !== "object" || Array.isArray(source) || source instanceof Blob || source instanceof Date || source instanceof FormData) {
24
+ if (typeof source !== "object" || source instanceof Set || Array.isArray(source) || source instanceof Blob || source instanceof Date || source instanceof FormData) {
23
25
  throw new TypeError("Source must be an object literal to be converted to a FormData object.");
24
26
  }
25
27
  for (const key in source) {
@@ -33,7 +35,12 @@ function composeKey(key, parentKey) {
33
35
  return parentKey ? `${parentKey}[${key}]` : key;
34
36
  }
35
37
  function append(form, key, value) {
36
- if (Array.isArray(value)) {
38
+ if (value instanceof Set) {
39
+ return [...value].forEach((_value, index) => append(form, composeKey(index.toString(), key), _value));
40
+ } else if (Array.isArray(value)) {
41
+ if (!value.length) {
42
+ return form.append(key, "");
43
+ }
37
44
  return Array.from(value.keys()).forEach((index) => append(form, composeKey(index.toString(), key), value[index]));
38
45
  } else if (value instanceof Date) {
39
46
  return form.append(key, value.toISOString());
@@ -53,17 +60,23 @@ function append(form, key, value) {
53
60
  objectToFormData(value, form, key);
54
61
  }
55
62
 
63
+ const stack = [];
56
64
  class Modal {
57
- constructor(html, animationDurationInMs = 200) {
65
+ constructor(html, id) {
58
66
  this.html = html;
59
- this.animationDurationInMs = animationDurationInMs;
60
- if (this.initializeDOM() !== false) {
61
- this.show();
67
+ this.id = id;
68
+ this.animationDurationInMs = 200;
69
+ if (stack.includes(id)) {
70
+ return;
71
+ }
72
+ if (this.initializeDOM() === false) {
73
+ return;
62
74
  }
75
+ this.show();
63
76
  }
64
- static fromException(response) {
77
+ static fromException(response, id) {
65
78
  if (typeof response === "string" && response.trim() !== "") {
66
- return new Modal(`<style>${htmlStyle()}</style>${response.toString()}`);
79
+ return new Modal(`<style>${htmlStyle()}</style>${response.toString()}`, id);
67
80
  }
68
81
  return new Modal(`
69
82
  <style>${style()}</style>
@@ -74,9 +87,9 @@ class Modal {
74
87
  <pre class="text-sm opacity-80 max-h-[500px] w-full mx-auto text-left mt-6">${JSON.stringify(response, null, 2)}</pre>
75
88
  </div>
76
89
  </div>
77
- `);
90
+ `, id);
78
91
  }
79
- static forPageComponent(component) {
92
+ static forPageComponent(component, id) {
80
93
  return new Modal(`
81
94
  <style>${style()}</style>
82
95
  <div class="h-full text-center flex">
@@ -86,7 +99,22 @@ class Modal {
86
99
  <div class="m-2 flex justify-center text-xl opacity-30 underline underline-dotted">${component}</div>
87
100
  </div>
88
101
  </div>
89
- `);
102
+ `, id);
103
+ }
104
+ static domainsDisabled(component, id) {
105
+ return new Modal(`
106
+ <style>${style()}</style>
107
+ <div class="h-full text-center flex">
108
+ <div class="m-auto">
109
+ <div class="text-5xl font-thin">Error</div>
110
+ <div class="opacity-30 text-lg font-thin m-1">
111
+ A domain-based page component was specificed, but domains are disabled. <br />
112
+ Set <code>domains</code> to <code>true</code> in <a class="underline underline-dotted" href="https://hybridly.dev/configuration/architecture.html#domains"><code>hybridly.config.ts</code></a>.
113
+ </div>
114
+ <div class="m-2 flex justify-center text-xl opacity-30 underline underline-dotted">${component}</div>
115
+ </div>
116
+ </div>
117
+ `, id);
90
118
  }
91
119
  initializeDOM() {
92
120
  if (!this.html) {
@@ -146,6 +174,7 @@ class Modal {
146
174
  this.style = style2;
147
175
  }
148
176
  show() {
177
+ stack.push(this.id);
149
178
  this.overlay.addEventListener("click", () => this.destroy());
150
179
  this.hideOnEscape = (event) => {
151
180
  if (event.keyCode === 27) {
@@ -161,6 +190,7 @@ class Modal {
161
190
  this.overlay.dataset.hybridly = "visible";
162
191
  }
163
192
  destroy() {
193
+ stack.splice(stack.indexOf(this.html), 1);
164
194
  this.overlay.dataset.hybridly = "";
165
195
  setTimeout(() => {
166
196
  this.overlay.outerHTML = "";
@@ -171,10 +201,13 @@ class Modal {
171
201
  }
172
202
  }
173
203
  function showResponseErrorModal(response) {
174
- return Modal.fromException(response);
204
+ return Modal.fromException(response, "non-hybrid-response");
175
205
  }
176
206
  function showPageComponentErrorModal(response) {
177
- return Modal.forPageComponent(response);
207
+ return Modal.forPageComponent(response, `page-component-${response}`);
208
+ }
209
+ function showDomainsDisabledErrorModal(response) {
210
+ return Modal.domainsDisabled(response, `domains-disabled-${response}`);
178
211
  }
179
212
  function htmlStyle() {
180
213
  return `
@@ -186,6 +219,10 @@ function htmlStyle() {
186
219
  flex-direction: column;
187
220
  height: 100%;
188
221
  }
222
+
223
+ a {
224
+ color: white;
225
+ }
189
226
  `;
190
227
  }
191
228
  function style() {
@@ -298,36 +335,12 @@ function when(condition, data, _default) {
298
335
  }
299
336
  return data;
300
337
  }
301
- function clone(val) {
302
- let k, out, tmp;
303
- if (Array.isArray(val)) {
304
- out = Array(k = val.length);
305
- while (k--) {
306
- out[k] = (tmp = val[k]) && typeof tmp === "object" ? clone(tmp) : tmp;
307
- }
308
- return out;
309
- }
310
- if (Object.prototype.toString.call(val) === "[object Object]") {
311
- out = {};
312
- for (k in val) {
313
- if (k === "__proto__") {
314
- Object.defineProperty(out, k, {
315
- value: clone(val[k]),
316
- configurable: true,
317
- enumerable: true,
318
- writable: true
319
- });
320
- } else {
321
- out[k] = (tmp = val[k]) && typeof tmp === "object" ? clone(tmp) : tmp;
322
- }
323
- }
324
- return out;
325
- }
326
- return val;
327
- }
328
338
  function merge(x, y) {
329
339
  return baseMerge__default(x, y, { arrayMerge: (_, s) => s });
330
340
  }
341
+ function removeTrailingSlash(string) {
342
+ return string.replace(/\/+$/, "");
343
+ }
331
344
 
332
345
  const debug = {
333
346
  router: makeDebugger__default("hybridly:core:router"),
@@ -341,7 +354,7 @@ const debug = {
341
354
  adapter: (name, ...args) => makeDebugger__default("hybridly:adapter").extend(name)(args.shift(), ...args)
342
355
  };
343
356
 
344
- exports.clone = clone;
357
+ exports.clone = lodash_clonedeep__default;
345
358
  exports.debounce = debounce;
346
359
  exports.debug = debug;
347
360
  exports.hasFiles = hasFiles;
@@ -349,6 +362,8 @@ exports.match = match;
349
362
  exports.merge = merge;
350
363
  exports.objectToFormData = objectToFormData;
351
364
  exports.random = random;
365
+ exports.removeTrailingSlash = removeTrailingSlash;
366
+ exports.showDomainsDisabledErrorModal = showDomainsDisabledErrorModal;
352
367
  exports.showPageComponentErrorModal = showPageComponentErrorModal;
353
368
  exports.showResponseErrorModal = showResponseErrorModal;
354
369
  exports.value = value;
package/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import makeDebugger from 'debug';
2
+ export { default as clone } from 'lodash.clonedeep';
2
3
 
3
- declare type RequestData = Record<string, FormDataConvertible> | FormDataConvertible | FormData;
4
- declare type FormDataConvertible = {
4
+ type RequestData = Record<string, FormDataConvertible> | FormDataConvertible | FormData;
5
+ type FormDataConvertible = {
5
6
  [key: string]: FormDataConvertible;
6
- } | Array<FormDataConvertible> | Blob | File | FormDataEntryValue | Date | boolean | number | null | undefined | string;
7
+ } | Array<FormDataConvertible> | Set<FormDataConvertible> | Blob | File | FormDataEntryValue | Date | boolean | number | null | undefined | string;
7
8
  /**
8
9
  * Checks if the given object has a file.
9
10
  */
@@ -15,29 +16,33 @@ declare function objectToFormData(source?: RequestData, form?: FormData, parentK
15
16
 
16
17
  declare class Modal {
17
18
  private html;
18
- private animationDurationInMs;
19
+ private id;
19
20
  private main;
20
21
  private overlay;
21
22
  private iframe;
22
23
  private style;
23
24
  private hideOnEscape?;
24
- constructor(html: string, animationDurationInMs?: number);
25
- static fromException(response: string): Modal;
26
- static forPageComponent(component: string): Modal;
25
+ private animationDurationInMs;
26
+ constructor(html: string, id: string);
27
+ static fromException(response: string, id: string): Modal;
28
+ static forPageComponent(component: string, id: string): Modal;
29
+ static domainsDisabled(component: string, id: string): Modal;
27
30
  initializeDOM(): false | undefined;
28
31
  show(): void;
29
32
  destroy(): void;
30
33
  }
31
34
  declare function showResponseErrorModal(response: string): Modal;
32
35
  declare function showPageComponentErrorModal(response: string): Modal;
36
+ declare function showDomainsDisabledErrorModal(response: string): Modal;
33
37
 
34
38
  declare function random(length?: number): string;
39
+ /** Simple pattern matching util. */
35
40
  declare function match<TValue extends string | number = string, TReturnValue = unknown>(value: TValue, lookup: Record<TValue | 'default', TReturnValue | ((...args: any[]) => TReturnValue)>, ...args: any[]): TReturnValue | Promise<TReturnValue>;
36
41
  declare function debounce<F extends (...params: any[]) => ReturnType<F>>(fn: F, delay: number): F;
37
42
  declare function value<T>(value: T | (() => T)): T;
38
43
  declare function when<T, D>(condition: any, data: T, _default?: D): T | D | undefined;
39
- declare function clone<T>(val: T): T;
40
44
  declare function merge<T>(x: Partial<T>, y: Partial<T>): T;
45
+ declare function removeTrailingSlash(string: string): string;
41
46
 
42
47
  declare const debug: {
43
48
  router: makeDebugger.Debugger;
@@ -51,4 +56,4 @@ declare const debug: {
51
56
  adapter: (name: string, ...args: any[]) => void;
52
57
  };
53
58
 
54
- export { FormDataConvertible, RequestData, clone, debounce, debug, hasFiles, match, merge, objectToFormData, random, showPageComponentErrorModal, showResponseErrorModal, value, when };
59
+ export { FormDataConvertible, RequestData, debounce, debug, hasFiles, match, merge, objectToFormData, random, removeTrailingSlash, showDomainsDisabledErrorModal, showPageComponentErrorModal, showResponseErrorModal, value, when };
package/dist/index.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import baseMerge from 'deepmerge';
2
+ export { default as clone } from 'lodash.clonedeep';
2
3
  import makeDebugger from 'debug';
3
4
 
4
5
  function hasFiles(data) {
@@ -10,7 +11,7 @@ function hasFiles(data) {
10
11
  function objectToFormData(source, form, parentKey) {
11
12
  source ?? (source = {});
12
13
  form ?? (form = new FormData());
13
- if (typeof source !== "object" || Array.isArray(source) || source instanceof Blob || source instanceof Date || source instanceof FormData) {
14
+ if (typeof source !== "object" || source instanceof Set || Array.isArray(source) || source instanceof Blob || source instanceof Date || source instanceof FormData) {
14
15
  throw new TypeError("Source must be an object literal to be converted to a FormData object.");
15
16
  }
16
17
  for (const key in source) {
@@ -24,7 +25,12 @@ function composeKey(key, parentKey) {
24
25
  return parentKey ? `${parentKey}[${key}]` : key;
25
26
  }
26
27
  function append(form, key, value) {
27
- if (Array.isArray(value)) {
28
+ if (value instanceof Set) {
29
+ return [...value].forEach((_value, index) => append(form, composeKey(index.toString(), key), _value));
30
+ } else if (Array.isArray(value)) {
31
+ if (!value.length) {
32
+ return form.append(key, "");
33
+ }
28
34
  return Array.from(value.keys()).forEach((index) => append(form, composeKey(index.toString(), key), value[index]));
29
35
  } else if (value instanceof Date) {
30
36
  return form.append(key, value.toISOString());
@@ -44,17 +50,23 @@ function append(form, key, value) {
44
50
  objectToFormData(value, form, key);
45
51
  }
46
52
 
53
+ const stack = [];
47
54
  class Modal {
48
- constructor(html, animationDurationInMs = 200) {
55
+ constructor(html, id) {
49
56
  this.html = html;
50
- this.animationDurationInMs = animationDurationInMs;
51
- if (this.initializeDOM() !== false) {
52
- this.show();
57
+ this.id = id;
58
+ this.animationDurationInMs = 200;
59
+ if (stack.includes(id)) {
60
+ return;
61
+ }
62
+ if (this.initializeDOM() === false) {
63
+ return;
53
64
  }
65
+ this.show();
54
66
  }
55
- static fromException(response) {
67
+ static fromException(response, id) {
56
68
  if (typeof response === "string" && response.trim() !== "") {
57
- return new Modal(`<style>${htmlStyle()}</style>${response.toString()}`);
69
+ return new Modal(`<style>${htmlStyle()}</style>${response.toString()}`, id);
58
70
  }
59
71
  return new Modal(`
60
72
  <style>${style()}</style>
@@ -65,9 +77,9 @@ class Modal {
65
77
  <pre class="text-sm opacity-80 max-h-[500px] w-full mx-auto text-left mt-6">${JSON.stringify(response, null, 2)}</pre>
66
78
  </div>
67
79
  </div>
68
- `);
80
+ `, id);
69
81
  }
70
- static forPageComponent(component) {
82
+ static forPageComponent(component, id) {
71
83
  return new Modal(`
72
84
  <style>${style()}</style>
73
85
  <div class="h-full text-center flex">
@@ -77,7 +89,22 @@ class Modal {
77
89
  <div class="m-2 flex justify-center text-xl opacity-30 underline underline-dotted">${component}</div>
78
90
  </div>
79
91
  </div>
80
- `);
92
+ `, id);
93
+ }
94
+ static domainsDisabled(component, id) {
95
+ return new Modal(`
96
+ <style>${style()}</style>
97
+ <div class="h-full text-center flex">
98
+ <div class="m-auto">
99
+ <div class="text-5xl font-thin">Error</div>
100
+ <div class="opacity-30 text-lg font-thin m-1">
101
+ A domain-based page component was specificed, but domains are disabled. <br />
102
+ Set <code>domains</code> to <code>true</code> in <a class="underline underline-dotted" href="https://hybridly.dev/configuration/architecture.html#domains"><code>hybridly.config.ts</code></a>.
103
+ </div>
104
+ <div class="m-2 flex justify-center text-xl opacity-30 underline underline-dotted">${component}</div>
105
+ </div>
106
+ </div>
107
+ `, id);
81
108
  }
82
109
  initializeDOM() {
83
110
  if (!this.html) {
@@ -137,6 +164,7 @@ class Modal {
137
164
  this.style = style2;
138
165
  }
139
166
  show() {
167
+ stack.push(this.id);
140
168
  this.overlay.addEventListener("click", () => this.destroy());
141
169
  this.hideOnEscape = (event) => {
142
170
  if (event.keyCode === 27) {
@@ -152,6 +180,7 @@ class Modal {
152
180
  this.overlay.dataset.hybridly = "visible";
153
181
  }
154
182
  destroy() {
183
+ stack.splice(stack.indexOf(this.html), 1);
155
184
  this.overlay.dataset.hybridly = "";
156
185
  setTimeout(() => {
157
186
  this.overlay.outerHTML = "";
@@ -162,10 +191,13 @@ class Modal {
162
191
  }
163
192
  }
164
193
  function showResponseErrorModal(response) {
165
- return Modal.fromException(response);
194
+ return Modal.fromException(response, "non-hybrid-response");
166
195
  }
167
196
  function showPageComponentErrorModal(response) {
168
- return Modal.forPageComponent(response);
197
+ return Modal.forPageComponent(response, `page-component-${response}`);
198
+ }
199
+ function showDomainsDisabledErrorModal(response) {
200
+ return Modal.domainsDisabled(response, `domains-disabled-${response}`);
169
201
  }
170
202
  function htmlStyle() {
171
203
  return `
@@ -177,6 +209,10 @@ function htmlStyle() {
177
209
  flex-direction: column;
178
210
  height: 100%;
179
211
  }
212
+
213
+ a {
214
+ color: white;
215
+ }
180
216
  `;
181
217
  }
182
218
  function style() {
@@ -289,36 +325,12 @@ function when(condition, data, _default) {
289
325
  }
290
326
  return data;
291
327
  }
292
- function clone(val) {
293
- let k, out, tmp;
294
- if (Array.isArray(val)) {
295
- out = Array(k = val.length);
296
- while (k--) {
297
- out[k] = (tmp = val[k]) && typeof tmp === "object" ? clone(tmp) : tmp;
298
- }
299
- return out;
300
- }
301
- if (Object.prototype.toString.call(val) === "[object Object]") {
302
- out = {};
303
- for (k in val) {
304
- if (k === "__proto__") {
305
- Object.defineProperty(out, k, {
306
- value: clone(val[k]),
307
- configurable: true,
308
- enumerable: true,
309
- writable: true
310
- });
311
- } else {
312
- out[k] = (tmp = val[k]) && typeof tmp === "object" ? clone(tmp) : tmp;
313
- }
314
- }
315
- return out;
316
- }
317
- return val;
318
- }
319
328
  function merge(x, y) {
320
329
  return baseMerge(x, y, { arrayMerge: (_, s) => s });
321
330
  }
331
+ function removeTrailingSlash(string) {
332
+ return string.replace(/\/+$/, "");
333
+ }
322
334
 
323
335
  const debug = {
324
336
  router: makeDebugger("hybridly:core:router"),
@@ -332,4 +344,4 @@ const debug = {
332
344
  adapter: (name, ...args) => makeDebugger("hybridly:adapter").extend(name)(args.shift(), ...args)
333
345
  };
334
346
 
335
- export { clone, debounce, debug, hasFiles, match, merge, objectToFormData, random, showPageComponentErrorModal, showResponseErrorModal, value, when };
347
+ export { debounce, debug, hasFiles, match, merge, objectToFormData, random, removeTrailingSlash, showDomainsDisabledErrorModal, showPageComponentErrorModal, showResponseErrorModal, value, when };
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@hybridly/utils",
3
- "version": "0.0.1-dev.4",
4
- "description": "A solution to develop server-driven, client-rendered applications",
3
+ "version": "0.1.0-alpha.0",
4
+ "description": "Utils used in Hybridly packages",
5
5
  "keywords": [
6
- "hybridly",
7
- "inertiajs"
6
+ "hybridly"
8
7
  ],
9
- "homepage": "https://github.com/hybridly/hybridly#readme",
8
+ "homepage": "https://github.com/hybridly/hybridly/tree/main/packages/config#readme",
10
9
  "bugs": {
11
10
  "url": "https://github.com/hybridly/hybridly/issues"
12
11
  },
13
12
  "license": "MIT",
14
13
  "repository": {
15
14
  "type": "git",
16
- "url": "git+https://github.com/hybridly/hybridly.git"
15
+ "url": "git+https://github.com/hybridly/hybridly.git",
16
+ "directory": "packages/utils"
17
17
  },
18
18
  "funding": "https://github.com/sponsors/innocenzi",
19
19
  "author": "Enzo Innocenzi <enzo@innocenzi.dev>",
@@ -34,7 +34,8 @@
34
34
  "types": "dist/index.d.ts",
35
35
  "dependencies": {
36
36
  "debug": "^4.3.4",
37
- "deepmerge": "^4.2.2"
37
+ "deepmerge": "^4.3.0",
38
+ "lodash.clonedeep": "^4.5.0"
38
39
  },
39
40
  "scripts": {
40
41
  "build": "unbuild",