spooder 4.2.0 → 4.2.2
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 +29 -4
- package/package.json +1 -1
- package/src/api.d.ts +3 -0
- package/src/api.ts +38 -20
package/README.md
CHANGED
|
@@ -430,6 +430,7 @@ In addition to the information provided by the developer, `spooder` also include
|
|
|
430
430
|
- [`ErrorWithMetadata(message: string, metadata: object)`](#api-error-handling-error-with-metadata)
|
|
431
431
|
- [`caution(err_message_or_obj: string | object, ...err: object[]): Promise<void>`](#api-error-handling-caution)
|
|
432
432
|
- [`panic(err_message_or_obj: string | object, ...err: object[]): Promise<void>`](#api-error-handling-panic)
|
|
433
|
+
- [`safe(fn: Callable): Promise<void>`](#api-error-handling-safe)
|
|
433
434
|
- [API > Content](#api-content)
|
|
434
435
|
- [`parse_template(template: string, replacements: Record<string, string>): string`](#api-content-parse-template)
|
|
435
436
|
- [`generate_hash_subs(length: number, prefix: string): Promise<Record<string, string>>`](#api-content-generate-hash-subs)
|
|
@@ -872,6 +873,30 @@ try {
|
|
|
872
873
|
}
|
|
873
874
|
```
|
|
874
875
|
|
|
876
|
+
<a id="api-error-handling-safe"></a>
|
|
877
|
+
### 🔧 `safe(fn: Callable): Promise<void>`
|
|
878
|
+
|
|
879
|
+
`safe()` is a utility function that wraps a "callable" and calls `caution()` if it throws an error.
|
|
880
|
+
|
|
881
|
+
> ![NOTE]
|
|
882
|
+
> This utility is primarily intended to be used to reduce boilerplate for fire-and-forget functions that you want to be notified about if they fail.
|
|
883
|
+
|
|
884
|
+
```ts
|
|
885
|
+
safe(async (() => {
|
|
886
|
+
// This code will run async and any errors will invoke caution().
|
|
887
|
+
});
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
`safe()` supports both async and sync callables, as well as Promise objects. `safe()` can also used with `await`.
|
|
891
|
+
|
|
892
|
+
```ts
|
|
893
|
+
await safe(() => {
|
|
894
|
+
return new Promise((resolve, reject) => {
|
|
895
|
+
// Do stuff.
|
|
896
|
+
});
|
|
897
|
+
});
|
|
898
|
+
```
|
|
899
|
+
|
|
875
900
|
<a id="api-content"></a>
|
|
876
901
|
## API > Content
|
|
877
902
|
|
|
@@ -962,7 +987,7 @@ let hash_sub_table = {};
|
|
|
962
987
|
generate_hash_subs().then(subs => hash_sub_table = subs).catch(caution);
|
|
963
988
|
|
|
964
989
|
server.route('/test', (req, url) => {
|
|
965
|
-
return parse_template('Hello world {hash=docs/project-logo.png}', hash_sub_table);
|
|
990
|
+
return parse_template('Hello world {$hash=docs/project-logo.png}', hash_sub_table);
|
|
966
991
|
});
|
|
967
992
|
```
|
|
968
993
|
|
|
@@ -983,13 +1008,13 @@ generate_hash_subs(40).then(...);
|
|
|
983
1008
|
> [!NOTE]
|
|
984
1009
|
> SHA-1 hashes are `40` characters. Git is transitioning to SHA-256, which are `64` characters. Short hashes of `7` are generally sufficient for cache-busting.
|
|
985
1010
|
|
|
986
|
-
Use a different prefix other than
|
|
1011
|
+
Use a different prefix other than `$hash=` by passing it as the first parameter.
|
|
987
1012
|
|
|
988
1013
|
```ts
|
|
989
|
-
generate_hash_subs(7, '
|
|
1014
|
+
generate_hash_subs(7, '$#').then(subs => hash_sub_table = subs).catch(caution);
|
|
990
1015
|
|
|
991
1016
|
server.route('/test', (req, url) => {
|
|
992
|
-
return parse_template('Hello world {
|
|
1017
|
+
return parse_template('Hello world {$#docs/project-logo.png}', hash_sub_table);
|
|
993
1018
|
});
|
|
994
1019
|
```
|
|
995
1020
|
|
package/package.json
CHANGED
package/src/api.d.ts
CHANGED
|
@@ -15,6 +15,9 @@ export declare class ErrorWithMetadata extends Error {
|
|
|
15
15
|
}
|
|
16
16
|
export declare function panic(err_message_or_obj: string | object, ...err: object[]): Promise<void>;
|
|
17
17
|
export declare function caution(err_message_or_obj: string | object, ...err: object[]): Promise<void>;
|
|
18
|
+
type CallableFunction = (...args: any[]) => any;
|
|
19
|
+
type Callable = Promise<any> | CallableFunction;
|
|
20
|
+
export declare function safe(target_fn: Callable): Promise<void>;
|
|
18
21
|
export declare function parse_template(template: string, replacements: Record<string, string | Array<string>>): string;
|
|
19
22
|
export declare function generate_hash_subs(length?: number, prefix?: string): Promise<Record<string, string>>;
|
|
20
23
|
type CookieOptions = {
|
package/src/api.ts
CHANGED
|
@@ -89,6 +89,20 @@ export async function caution(err_message_or_obj: string | object, ...err: objec
|
|
|
89
89
|
await handle_error('caution: ', err_message_or_obj, ...err);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
type CallableFunction = (...args: any[]) => any;
|
|
93
|
+
type Callable = Promise<any> | CallableFunction;
|
|
94
|
+
|
|
95
|
+
export async function safe(target_fn: Callable) {
|
|
96
|
+
try {
|
|
97
|
+
if (target_fn instanceof Promise)
|
|
98
|
+
await target_fn;
|
|
99
|
+
else
|
|
100
|
+
await target_fn();
|
|
101
|
+
} catch (e) {
|
|
102
|
+
caution(e as Error);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
92
106
|
export function parse_template(template: string, replacements: Record<string, string | Array<string>>): string {
|
|
93
107
|
let result = '';
|
|
94
108
|
let buffer = '';
|
|
@@ -109,26 +123,30 @@ export function parse_template(template: string, replacements: Record<string, st
|
|
|
109
123
|
const loop_key = buffer.substring(4);
|
|
110
124
|
|
|
111
125
|
const loop_entries = replacements[loop_key];
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
// More performat than replaceAll on larger arrays (and equal on tiny arrays).
|
|
118
|
-
const content_parts = loop_content.split('%s');
|
|
119
|
-
const indicies = [] as Array<number>;
|
|
120
|
-
|
|
121
|
-
for (let j = 0; j < content_parts.length; j++)
|
|
122
|
-
if (content_parts[j] === '%s')
|
|
123
|
-
indicies.push(j);
|
|
124
|
-
|
|
125
|
-
for (const loop_entry of loop_entries)
|
|
126
|
-
for (const index of indicies)
|
|
127
|
-
content_parts[index] = loop_entry;
|
|
128
|
-
|
|
129
|
-
i += loop_content.length + 6;
|
|
130
|
-
} else {
|
|
126
|
+
const loop_content_start_index = i + 1;
|
|
127
|
+
const loop_close_index = template.indexOf('{/for}', loop_content_start_index);
|
|
128
|
+
|
|
129
|
+
if (loop_close_index === -1) {
|
|
131
130
|
result += '{$' + buffer + '}';
|
|
131
|
+
} else {
|
|
132
|
+
const loop_content = template.substring(loop_content_start_index, loop_close_index);
|
|
133
|
+
if (loop_entries !== undefined) {
|
|
134
|
+
// More performat than replaceAll on larger arrays (and equal on tiny arrays).
|
|
135
|
+
const content_parts = loop_content.split('%s');
|
|
136
|
+
const indicies = [] as Array<number>;
|
|
137
|
+
|
|
138
|
+
for (let j = 0; j < content_parts.length; j++)
|
|
139
|
+
if (content_parts[j] === '%s')
|
|
140
|
+
indicies.push(j);
|
|
141
|
+
|
|
142
|
+
for (const loop_entry of loop_entries)
|
|
143
|
+
for (const index of indicies)
|
|
144
|
+
content_parts[index] = loop_entry;
|
|
145
|
+
|
|
146
|
+
i += loop_content.length + 6;
|
|
147
|
+
} else {
|
|
148
|
+
result += '{$' + buffer + '}' + loop_content + '{/for}';
|
|
149
|
+
}
|
|
132
150
|
}
|
|
133
151
|
} else {
|
|
134
152
|
result += replacements[buffer] ?? '{$' + buffer + '}';
|
|
@@ -144,7 +162,7 @@ export function parse_template(template: string, replacements: Record<string, st
|
|
|
144
162
|
return result;
|
|
145
163
|
}
|
|
146
164
|
|
|
147
|
-
export async function generate_hash_subs(length = 7, prefix = 'hash='): Promise<Record<string, string>> {
|
|
165
|
+
export async function generate_hash_subs(length = 7, prefix = '$hash='): Promise<Record<string, string>> {
|
|
148
166
|
const cmd = ['git', 'ls-tree', '-r', 'HEAD'];
|
|
149
167
|
const process = Bun.spawn(cmd, {
|
|
150
168
|
stdout: 'pipe',
|