sliftutils 1.2.1 → 1.2.3
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/.cursor/rules/api-calls.mdc +16 -0
- package/.cursor/rules/coding-styles.mdc +50 -0
- package/.cursor/rules/components.mdc +44 -0
- package/.cursor/rules/disk-collection.mdc +31 -0
- package/.cursor/rules/general-guidelines.mdc +11 -0
- package/.cursor/rules/mobx-state.mdc +33 -0
- package/.cursor/rules/styling-css.mdc +99 -0
- package/builders/setup.ts +2 -2
- package/index.d.ts +104 -15
- package/misc/zip.d.ts +2 -13
- package/misc/zip.ts +2 -104
- package/package.json +2 -2
- package/render-utils/InputLabel.d.ts +1 -2
- package/render-utils/InputLabel.tsx +1 -1
- package/storage/backblaze.d.ts +97 -0
- package/storage/backblaze.ts +915 -0
- package/yarn.lock +4 -4
- package/.cursorrules +0 -251
package/yarn.lock
CHANGED
|
@@ -1812,10 +1812,10 @@ slash@^3.0.0:
|
|
|
1812
1812
|
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
|
1813
1813
|
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
|
1814
1814
|
|
|
1815
|
-
socket-function@^1.
|
|
1816
|
-
version "1.
|
|
1817
|
-
resolved "https://registry.yarnpkg.com/socket-function/-/socket-function-1.
|
|
1818
|
-
integrity sha512-
|
|
1815
|
+
socket-function@^1.1.1:
|
|
1816
|
+
version "1.1.1"
|
|
1817
|
+
resolved "https://registry.yarnpkg.com/socket-function/-/socket-function-1.1.1.tgz#1384a41d70dec192caba4b5b93bfc594b5ac08c8"
|
|
1818
|
+
integrity sha512-WsjlLdaUZzKhMfcc7rjP8/gPQaXUf4jLCgwJtDfIf+pzvS9Rqw4uxxoHkGAUwGp/iT13qyKiryZ+EBrR8/pwJg==
|
|
1819
1819
|
dependencies:
|
|
1820
1820
|
"@types/pako" "^2.0.3"
|
|
1821
1821
|
"@types/ws" "^8.5.3"
|
package/.cursorrules
DELETED
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
The code automatically updates on save, so do not ever run commands to rerun the site.
|
|
2
|
-
|
|
3
|
-
Don't run shell commands when you need to create or move small code files. You should use tool calls to do this. You should also use tool calls to make files within folders. You don't need to make the folder, just make the file. The folder will automatically be created.
|
|
4
|
-
|
|
5
|
-
We use MobX for state management. Components should use a variable called synced that is an observable for their state, and never Component.state. All components need the @observer decorator. For example:
|
|
6
|
-
import preact from "preact";
|
|
7
|
-
import { observable } from "mobx";
|
|
8
|
-
|
|
9
|
-
@observer
|
|
10
|
-
class Example extends preact.Component {
|
|
11
|
-
synced = observable({
|
|
12
|
-
x: 0,
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
render() {
|
|
16
|
-
return <div>
|
|
17
|
-
<button onClick={() => this.synced.x++}>
|
|
18
|
-
Click me
|
|
19
|
-
</button>
|
|
20
|
-
<p>
|
|
21
|
-
{this.synced.x}
|
|
22
|
-
</p>
|
|
23
|
-
</div>;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
The code automatically updates on save, so do not ever run commands to rerun the site.
|
|
28
|
-
|
|
29
|
-
If you need to add a dependency, don't just change the packs to JSON file. Properly use yarn add so you get the latest version, unless the user specifies a version or tells you otherwise.
|
|
30
|
-
|
|
31
|
-
Use tool calls to read files and directories where possible, instead of running "ls", "dir", etc.
|
|
32
|
-
|
|
33
|
-
Coding Styles
|
|
34
|
-
Times should almost always be in milliseconds, and if not told, you should assume a time is in milliseconds.
|
|
35
|
-
|
|
36
|
-
Don't make functions that will never be reused and are short. This just makes the code too confusing. If the function is under five lines and it's not being reused, you shouldn't create it, unless instructed explicitly to create it.
|
|
37
|
-
|
|
38
|
-
Comments should be used sparingly and only if it's required to explain what's being done. If you're calling a function called create imageName and the comment is called create imageName, you will be fired because that's just stupid. It's a waste of lines.
|
|
39
|
-
|
|
40
|
-
Comments go in the line before, never after the semicolon.
|
|
41
|
-
|
|
42
|
-
Try not to use "null", and instead always use "undefined".
|
|
43
|
-
|
|
44
|
-
Almost never check for undefined or null, just check for falsey.
|
|
45
|
-
|
|
46
|
-
When functions have more than one primitive parameter, such that you could confuse them, even something as simple as start time and end time, you should put them inside of an object and call that object config, so the function only has a single parameter.
|
|
47
|
-
|
|
48
|
-
Never use return codes, always prefer to throw on error. Include a lot of context information in the error. If any values might be extremely large, such as parsing a file, limit them (ex, to 500 characters).
|
|
49
|
-
|
|
50
|
-
He used double quotes, not single quotes.
|
|
51
|
-
|
|
52
|
-
Never use the ternary operator. Instead, do this: "x ? y : z" => "x && y || z".
|
|
53
|
-
|
|
54
|
-
Never use non-null assertion operator, instead check the value, and if necessary (because it is accessed in nested functions), use a const variable to preserve the type.
|
|
55
|
-
|
|
56
|
-
Errors should almost always use a template string to include the expected value, and the actual value, as in: "throw new Error(`Expected X, was ${Y}`);"
|
|
57
|
-
|
|
58
|
-
Don't use switch statements. Use if/else statements instead.
|
|
59
|
-
|
|
60
|
-
Don't use ! when accessing a value from a map. Use the get / if undefined initialize and set, and then use style. It's faster, and more type safe.
|
|
61
|
-
|
|
62
|
-
Sort with this function, which takes a single function to map each object to a sortable value
|
|
63
|
-
import { sort } from "socket-function/src/misc";
|
|
64
|
-
export function sort<T>(arr: T[], sortKey: (obj: T) => unknown);
|
|
65
|
-
|
|
66
|
-
Prefer to return, instead of using else statements. Handle error cases, warn/throw, and then return. Your main case should be below, not in an if statement, just in the main code.
|
|
67
|
-
|
|
68
|
-
Use template strings for error messages, which include the exact value that triggered the error, and the exact expectation it failed.
|
|
69
|
-
|
|
70
|
-
Use functions to prevent code duplication only when something is actually duplicated.
|
|
71
|
-
|
|
72
|
-
Don't recreate collections or URL parameters, import them instead.
|
|
73
|
-
|
|
74
|
-
Do not redefine types. Import the types correctly.
|
|
75
|
-
|
|
76
|
-
Do not use types when they can be inferred.
|
|
77
|
-
|
|
78
|
-
Constants that are arbitrary and that we might to reconfigure should be near the top of the file under the imports, not buried within functions.
|
|
79
|
-
|
|
80
|
-
Never use environment variables. All configuration should be on the disk, or, if specific to a current run, passed as command line parameters.
|
|
81
|
-
|
|
82
|
-
Never use inline styles, always use the CSS helper.
|
|
83
|
-
|
|
84
|
-
Don't use `as any`.
|
|
85
|
-
|
|
86
|
-
When you're making fetch calls and you get a type of any, you need to cast it to the actual type, and not leave it as any. The same goes for when you're deserializing values.
|
|
87
|
-
|
|
88
|
-
DO NOT redeclare constants and copy their value. JUST IMPORT THEM!
|
|
89
|
-
|
|
90
|
-
DO NOT redeclare types. JUST IMPORT THEM!
|
|
91
|
-
|
|
92
|
-
Do not try catch for no reason. If you can't actually handle the exception, just let it throw.
|
|
93
|
-
|
|
94
|
-
For input events, always use event.currentTarget.
|
|
95
|
-
|
|
96
|
-
Use ref={elem => } callbacks. NEVER use .createRef.
|
|
97
|
-
|
|
98
|
-
NEVER render images with a fixed width+height. This will cause them to be stretched or cut off. This is terrible. Only set the width or height.
|
|
99
|
-
|
|
100
|
-
Callback held should be avoided by using async and `import { PromiseObj } from "socket-function/src/misc";`. Most of the time, if there's an event callback, you should wrap it with a promise obj so that you can wait for it asynchronously.
|
|
101
|
-
|
|
102
|
-
`import { keyBy, keyByArray } from "socket-function/src/misc";` Should be used when you need to create lookups from lists and you know what key you want. This can clobber values, or it can gather in an array.
|
|
103
|
-
let example: Map<number, { x: number }> = keyBy([{ x: 5 }, { x: 6 }]);
|
|
104
|
-
let example: Map<number, { x: number }[]> = keyByArrat([{ x: 5 }, { x: 5, version: 2 } { x: 6 }]);
|
|
105
|
-
|
|
106
|
-
Never use alert. If there's an error, you should throw it.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
General Styling
|
|
111
|
-
Never use em or rem. Only use px or vw/vh/%.
|
|
112
|
-
|
|
113
|
-
Don't add font colors unless asked to add styling. Don't add any aethetics beyond hbox/vbox/pad2 unless asked to add styling. Don't add fontSize unless asked to add styling. If you believe styling is possible, just tell the user, I can add styling, but won't do it unless you ask me to.
|
|
114
|
-
|
|
115
|
-
Never use h1/h2/h3 etc. These classes have extremely large built-in margins and paddings, instead set the font size explicitly.
|
|
116
|
-
|
|
117
|
-
Make sure to not use fillWidth, where flexGrow(1) would suffice.
|
|
118
|
-
|
|
119
|
-
Components
|
|
120
|
-
Anchor (<a> tag), for linking using URLParam
|
|
121
|
-
<Anchor
|
|
122
|
-
params={[[todolistURL, listKey]]}
|
|
123
|
-
>
|
|
124
|
-
{list.name}
|
|
125
|
-
</Anchor>
|
|
126
|
-
URLParam, Parameters which are stored in the URL. The second argument is the default, which can be a number, string, or an object. Set and get with .value
|
|
127
|
-
const todolistURL = new URLParam("todolist", "");
|
|
128
|
-
|
|
129
|
-
InputLabel and InputLabelURL should be used for inputs. For example:
|
|
130
|
-
<InputLabelURL
|
|
131
|
-
label="Show Previous Video"
|
|
132
|
-
checkbox
|
|
133
|
-
persisted={showPreviousVideoURL}
|
|
134
|
-
/>
|
|
135
|
-
<InputLabel
|
|
136
|
-
label="Notes"
|
|
137
|
-
fillWidth
|
|
138
|
-
value={node.notes || ""}
|
|
139
|
-
onChangeValue={async (value) => {
|
|
140
|
-
const updatedNode = deepCloneJSON(node);
|
|
141
|
-
updatedNode.notes = value;
|
|
142
|
-
await VideoNode.set(node.id, updatedNode);
|
|
143
|
-
}}
|
|
144
|
-
/>
|
|
145
|
-
|
|
146
|
-
API Calls
|
|
147
|
-
When in an event callback (which must be async)
|
|
148
|
-
APIController(getExtNodeId()).getModels.promise()
|
|
149
|
-
When in a render function/context
|
|
150
|
-
APIController(getExtNodeId()).getModels()
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
DiskCollection
|
|
154
|
-
If read an object from a collection, and then mutate it, and want to set it in the collection, you have to shallow copy it, so the DiskCollection picks up the change.
|
|
155
|
-
let x = collection.get("x");
|
|
156
|
-
x.y = Math.random();
|
|
157
|
-
// Not asynchronous, as sets are synchronous
|
|
158
|
-
collection.set("x", { ...x });
|
|
159
|
-
The non-async functions should be called in render functions, the async functions should be called in event handlers, etc. Except for .set, which should be called in all both cases.
|
|
160
|
-
get(key: string): T | undefined;
|
|
161
|
-
async getPromise(key: string): Promise<T | undefined>;
|
|
162
|
-
set(key: string, value: T): void;
|
|
163
|
-
remove(key: string): void;
|
|
164
|
-
getKeys(): string[];
|
|
165
|
-
getKeysPromise(): Promise<string[]>;
|
|
166
|
-
getEntries(): [string, T][];
|
|
167
|
-
getValues(): T[];
|
|
168
|
-
async getValuesPromise(): Promise<T[]>;
|
|
169
|
-
getInfo(key: string);
|
|
170
|
-
async reset();
|
|
171
|
-
|
|
172
|
-
css
|
|
173
|
-
Add very little styling, such as colours, rounding, etc, unless asked to add more styling.
|
|
174
|
-
|
|
175
|
-
css should be set using className={css.cssPropertyName(cssPropertyValue).anotherPropertyName...}
|
|
176
|
-
Always use the "css" helper for styling. For example:
|
|
177
|
-
<div className={css.width(100).height(50)}>My width is 100px, my height is 50px</div>
|
|
178
|
-
All css fields can be set in this way, with the function being the field name and the argument being the value.
|
|
179
|
-
Generally speaking, the CSS helpers are on two lines. Wrapping is fine.
|
|
180
|
-
className={css.size(100, 100).hbox(4)
|
|
181
|
-
.hsl(0, 50, 50).borderRadius(4)
|
|
182
|
-
}
|
|
183
|
-
position
|
|
184
|
-
- Position, size, font size, layout, hints, etc.
|
|
185
|
-
- The cursor, color, font color, border radius, pointer, bold.
|
|
186
|
-
|
|
187
|
-
Conditionals come after, and should use this style:
|
|
188
|
-
className={css
|
|
189
|
-
...
|
|
190
|
-
+ (conditionalExample && css.opacity(0.5))
|
|
191
|
-
}
|
|
192
|
-
Specifically, it should be a value that you check for, and then the value. Don't use ternary, don't do `|| ""`
|
|
193
|
-
- If you have multiple values, chain them with || and &&
|
|
194
|
-
Keep the CSS simple, don't add too much, because it's easier to add than to remove.
|
|
195
|
-
|
|
196
|
-
However, there are some helper functions that will directly map to commonly used styles.
|
|
197
|
-
|
|
198
|
-
If you want to make a NON-Button feel like a button, you can use "css.button", which makes the background color change on hover, and make the cursor a pointer. Only use this if the background color is set, otherwise you need to message it's a button in another way. And never use it for <Button>/<button> which already does this.
|
|
199
|
-
|
|
200
|
-
Generally use hbox/vbox to set the spacing between elements, instead of using margins.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
There are also some special aliases, some of which take parameters, some of which don't (which allows them to be chained like so: css.vbox0.wrap):
|
|
204
|
-
let nonCallAliases = {
|
|
205
|
-
relative: (c: CSSHelperTypeBase) => c.position("relative"),
|
|
206
|
-
absolute: (c: CSSHelperTypeBase) => c.position("absolute"),
|
|
207
|
-
fixed: (c: CSSHelperTypeBase) => c.position("fixed"),
|
|
208
|
-
wrap: (c: CSSHelperTypeBase) => c.flexWrap("wrap").display("flex", "soft").alignItems("center", "soft"),
|
|
209
|
-
marginAuto: (c: CSSHelperTypeBase) => c.margin("auto"),
|
|
210
|
-
fillBoth: (c: CSSHelperTypeBase) => c.width("100%").height("100%"),
|
|
211
|
-
fillWidth: (c: CSSHelperTypeBase) => c.width("100%"),
|
|
212
|
-
fillHeight: (c: CSSHelperTypeBase) => c.height("100%"),
|
|
213
|
-
flexShrink0: (c: CSSHelperTypeBase) => c.flexShrink(0),
|
|
214
|
-
ellipsis: (c: CSSHelperTypeBase) => c.overflow("hidden").textOverflow("ellipsis").whiteSpace("nowrap").display("inline-block"),
|
|
215
|
-
overflowAuto: (c: CSSHelperTypeBase) => c.overflow("auto"),
|
|
216
|
-
overflowHidden: (c: CSSHelperTypeBase) => c.overflow("hidden"),
|
|
217
|
-
};
|
|
218
|
-
let callAliases = {
|
|
219
|
-
hbox: (c: CSSHelperTypeBase, gap: number, rowGap?: number) => c.display("flex").flexDirection("row").rowGap(rowGap ?? gap).columnGap(gap).alignItems("center", "soft"),
|
|
220
|
-
vbox: (c: CSSHelperTypeBase, gap: number, columnGap?: number) => c.display("flex").flexDirection("column").rowGap(gap).columnGap(columnGap ?? gap).alignItems("start", "soft"),
|
|
221
|
-
pad2: (c: CSSHelperTypeBase, value: number, verticalValue?: number): CSSHelperTypeBase => {
|
|
222
|
-
if (verticalValue !== undefined) return c.padding(`${verticalValue}px ${value}px` as any);
|
|
223
|
-
return c.padding(value);
|
|
224
|
-
},
|
|
225
|
-
hsl: (c: CSSHelperTypeBase, h: number, s: number, l: number): CSSHelperTypeBase => c.background(`hsl(${h}, ${s}%, ${l}%)`),
|
|
226
|
-
hslhover: (c: CSSHelperTypeBase, h: number, s: number, l: number): CSSHelperTypeBase => c.background(`hsl(${h}, ${s}%, ${l}%)`, "hover"),
|
|
227
|
-
hsla: (c: CSSHelperTypeBase, h: number, s: number, l: number, a: number): CSSHelperTypeBase => c.background(`hsla(${h}, ${s}%, ${l}%, ${a})`),
|
|
228
|
-
hslahover: (c: CSSHelperTypeBase, h: number, s: number, l: number, a: number): CSSHelperTypeBase => c.background(`hsla(${h}, ${s}%, ${l}%, ${a})`, "hover"),
|
|
229
|
-
bord: (c: CSSHelperTypeBase, width: number, color: string | { h: number; s: number; l: number; a?: number; }, style = "solid"): CSSHelperTypeBase => {
|
|
230
|
-
let colorStr = typeof color === "string" ? color : `hsla(${color.h}, ${color.s}%, ${color.l}%, ${color.a ?? 1})`;
|
|
231
|
-
return c.border(`${width}px ${style} ${colorStr}`);
|
|
232
|
-
},
|
|
233
|
-
bord2: (c: CSSHelperTypeBase, h: number, s: number, l: number, width = 1, style = "solid"): CSSHelperTypeBase => {
|
|
234
|
-
return c.border(`${width}px ${style} hsla(${h}, ${s}%, ${l}%, 1)`);
|
|
235
|
-
},
|
|
236
|
-
hslcolor: (c: CSSHelperTypeBase, h: number, s: number, l: number): CSSHelperTypeBase => c.color(`hsl(${h}, ${s}%, ${l}%)`),
|
|
237
|
-
colorhsl: (c: CSSHelperTypeBase, h: number, s: number, l: number): CSSHelperTypeBase => c.color(`hsl(${h}, ${s}%, ${l}%)`),
|
|
238
|
-
hslacolor: (c: CSSHelperTypeBase, h: number, s: number, l: number, a: number): CSSHelperTypeBase => c.color(`hsla(${h}, ${s}%, ${l}%, ${a})`),
|
|
239
|
-
colorhsla: (c: CSSHelperTypeBase, h: number, s: number, l: number, a: number): CSSHelperTypeBase => c.color(`hsla(${h}, ${s}%, ${l}%, ${a})`),
|
|
240
|
-
size: (c: CSSHelperTypeBase, width: LengthOrPercentage, height: LengthOrPercentage) => c.width(width).height(height),
|
|
241
|
-
pos: (c: CSSHelperTypeBase, x: LengthOrPercentage, y: LengthOrPercentage) => c.left(x).top(y),
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
For animation keyframes, a style tag is required.
|
|
246
|
-
<style>{`
|
|
247
|
-
@keyframes spinner-ring {
|
|
248
|
-
0% { transform: rotate(0deg); }
|
|
249
|
-
100% { transform: rotate(360deg); }
|
|
250
|
-
}
|
|
251
|
-
`}</style>
|