sliftutils 0.8.0 → 0.10.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/.cursorrules CHANGED
@@ -1,5 +1,7 @@
1
1
  The code automatically updates on save, so do not ever run commands to rerun the site.
2
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
+
3
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:
4
6
  import preact from "preact";
5
7
  import { observable } from "mobx";
@@ -22,9 +24,29 @@ We use MobX for state management. Components should use a variable called synced
22
24
  }
23
25
  }
24
26
 
27
+ The code automatically updates on save, so do not ever run commands to rerun the site.
28
+
29
+ In the implementation for every type of API, there should be a companion file to manage the session (ex smsSession.ts). This should export a function which makes calling the API functions simple by automatically managing the session. Because the session helper will be making the function calls, it can try catch them and appropriately handle the session errors that require regenerating the session. Of course, if it's not a session error, it should just rethrow it.
30
+
31
+ Use createPersistentObject for persistent things like session states. It's accessed synchronously and the key will have an undefined value if it the value isn't set.
32
+
33
+ let persistent = createPersistentObject<{
34
+ token: string;
35
+ }>("sms");
36
+
37
+ persistent.token = "...";
38
+ persistent.token;
39
+
40
+
25
41
  Coding Styles
26
42
  Try not to use "null", and instead always use "undefined".
27
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
+
28
50
  He used double quotes, not single quotes.
29
51
 
30
52
  Never use the ternary operator. Instead, do this: "x ? y : z" => "x && y || z".
@@ -53,6 +75,10 @@ Coding Styles
53
75
 
54
76
  Do not use types when they can be inferred.
55
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
+
56
82
 
57
83
  General Styling
58
84
  Never use em or rem. Only use px or vw/vh/%.
@@ -0,0 +1,63 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+
4
+ const FOLDERS_TO_INCLUDE = ["render-utils", "misc"];
5
+
6
+ function getAllDtsFiles(dir: string, fileList: string[] = []): string[] {
7
+ const files = fs.readdirSync(dir);
8
+
9
+ for (const file of files) {
10
+ const filePath = path.join(dir, file);
11
+ const stat = fs.statSync(filePath);
12
+
13
+ if (stat.isDirectory()) {
14
+ getAllDtsFiles(filePath, fileList);
15
+ } else if (file.endsWith(".d.ts")) {
16
+ fileList.push(filePath);
17
+ }
18
+ }
19
+
20
+ return fileList;
21
+ }
22
+
23
+ function generateIndexDts() {
24
+ const allModules: string[] = [];
25
+
26
+ for (const folderName of FOLDERS_TO_INCLUDE) {
27
+ const folderPath = path.join(__dirname, "..", folderName);
28
+
29
+ if (!fs.existsSync(folderPath)) {
30
+ console.log(`Warning: Folder ${folderName} does not exist, skipping...`);
31
+ continue;
32
+ }
33
+
34
+ const dtsFiles = getAllDtsFiles(folderPath);
35
+
36
+ const modules = dtsFiles
37
+ .map(filePath => {
38
+ const relativePath = path.relative(folderPath, filePath);
39
+ const withoutExt = relativePath.replace(/\.d\.ts$/, "");
40
+ const modulePath = "sliftutils/" + folderName + "/" + withoutExt.replace(/\\/g, "/");
41
+
42
+ const content = fs.readFileSync(filePath, "utf8");
43
+ const indentedContent = content
44
+ .split("\n")
45
+ .map(line => line ? " " + line : line)
46
+ .join("\n");
47
+
48
+ return `declare module "${modulePath}" {\n${indentedContent}\n}`;
49
+ });
50
+
51
+ allModules.push(...modules);
52
+ }
53
+
54
+ const sortedModules = allModules.sort().join("\n\n");
55
+ const outputPath = path.join(__dirname, "..", "index.d.ts");
56
+ const header = `// Auto-generated file. Do not edit manually.\n// Generated by: yarn generate-index-dts\n\n`;
57
+
58
+ fs.writeFileSync(outputPath, header + sortedModules + "\n", "utf8");
59
+ console.log(`Generated ${outputPath} with ${allModules.length} module declarations`);
60
+ }
61
+
62
+ generateIndexDts();
63
+
package/index.d.ts CHANGED
@@ -1,6 +1,51 @@
1
1
  // Auto-generated file. Do not edit manually.
2
2
  // Generated by: yarn generate-index-dts
3
3
 
4
+ declare module "sliftutils/misc/environment" {
5
+ /// <reference types="chrome" />
6
+ export declare function isInChromeExtension(): string | false;
7
+ export declare function isInChromeExtensionBackground(): boolean;
8
+ export declare function isInChromeExtensionContentScript(): boolean | "";
9
+ export declare function isInElectron(): string | false | undefined;
10
+ export declare function triggerIsInBuild(): void;
11
+ export declare function isInBuild(): boolean;
12
+ export declare function isInBrowser(): boolean;
13
+
14
+ }
15
+
16
+ declare module "sliftutils/misc/fs" {
17
+ export declare function getAllFiles(folder: string): AsyncIterableIterator<string>;
18
+
19
+ }
20
+
21
+ declare module "sliftutils/misc/getSecret" {
22
+ export declare const getSecret: {
23
+ (key: string): Promise<string>;
24
+ clear(key: string): void;
25
+ clearAll(): void;
26
+ forceSet(key: string, value: Promise<string>): void;
27
+ getAllKeys(): string[];
28
+ get(key: string): Promise<string> | undefined;
29
+ };
30
+
31
+ }
32
+
33
+ declare module "sliftutils/misc/types" {
34
+ export declare function isDefined<T>(value: T | undefined | null): value is T;
35
+
36
+ }
37
+
38
+ declare module "sliftutils/misc/zip" {
39
+ /// <reference types="node" />
40
+ /// <reference types="node" />
41
+ export declare class Zip {
42
+ static gzip(buffer: Buffer, level?: number): Promise<Buffer>;
43
+ static gunzip(buffer: Buffer): Promise<Buffer>;
44
+ static gunzipBatch(buffers: Buffer[]): Promise<Buffer[]>;
45
+ }
46
+
47
+ }
48
+
4
49
  declare module "sliftutils/render-utils/DropdownCustom" {
5
50
  import preact from "preact";
6
51
  import { LengthOrPercentage } from "typesafecss/cssTypes";
@@ -182,6 +227,7 @@ declare module "sliftutils/render-utils/LocalStorageParam" {
182
227
  }
183
228
 
184
229
  declare module "sliftutils/render-utils/SyncedController" {
230
+ /// <reference types="socket-function" />
185
231
  import { SocketRegistered } from "socket-function/SocketFunctionTypes";
186
232
  type RemapFunction<T> = T extends (...args: infer Args) => Promise<infer Return> ? {
187
233
  (...args: Args): Return | undefined;
@@ -0,0 +1,8 @@
1
+ /// <reference types="chrome" />
2
+ export declare function isInChromeExtension(): string | false;
3
+ export declare function isInChromeExtensionBackground(): boolean;
4
+ export declare function isInChromeExtensionContentScript(): boolean | "";
5
+ export declare function isInElectron(): string | false | undefined;
6
+ export declare function triggerIsInBuild(): void;
7
+ export declare function isInBuild(): boolean;
8
+ export declare function isInBrowser(): boolean;
package/misc/fs.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function getAllFiles(folder: string): AsyncIterableIterator<string>;
@@ -0,0 +1,8 @@
1
+ export declare const getSecret: {
2
+ (key: string): Promise<string>;
3
+ clear(key: string): void;
4
+ clearAll(): void;
5
+ forceSet(key: string, value: Promise<string>): void;
6
+ getAllKeys(): string[];
7
+ get(key: string): Promise<string> | undefined;
8
+ };
@@ -0,0 +1,28 @@
1
+
2
+ import { cache } from "socket-function/src/caching";
3
+ import os from "os";
4
+ import fs from "fs";
5
+
6
+ export const getSecret = cache(async function getSecret(key: string): Promise<string> {
7
+ const jsonIndex = key.indexOf(".json");
8
+ if (jsonIndex === -1) {
9
+ const filePath = os.homedir() + "/" + key;
10
+ return fs.readFileSync(filePath, "utf-8").trim();
11
+ }
12
+
13
+ const pathPart = key.slice(0, jsonIndex + ".json".length);
14
+ const filePath = os.homedir() + "/" + pathPart;
15
+ const contents = fs.readFileSync(filePath, "utf-8");
16
+ const json = JSON.parse(contents);
17
+
18
+ const keyPart = key.slice(jsonIndex + ".json.".length);
19
+ if (!keyPart) {
20
+ return JSON.stringify(json);
21
+ }
22
+
23
+ const value = json[keyPart];
24
+ if (value === undefined) {
25
+ throw new Error(`Expected key "${keyPart}" in ${filePath}, was undefined`);
26
+ }
27
+ return String(value);
28
+ });
@@ -0,0 +1 @@
1
+ export declare function isDefined<T>(value: T | undefined | null): value is T;
package/misc/zip.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ export declare class Zip {
4
+ static gzip(buffer: Buffer, level?: number): Promise<Buffer>;
5
+ static gunzip(buffer: Buffer): Promise<Buffer>;
6
+ static gunzipBatch(buffers: Buffer[]): Promise<Buffer[]>;
7
+ }
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "sliftutils",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "scripts": {
7
7
  "type": "yarn tsc --noEmit",
8
- "emit-dts": "yarn tsc --project tsconfig.declarations.json",
9
- "generate-index-dts": "node ./builders/generateIndexDts.js",
8
+ "update-types": "yarn emit-dts && yarn generate-index-dts",
9
+ "emit-dts": "yarn tsc --project tsconfig.declarations.json || true",
10
+ "generate-index-dts": "typenode ./builders/generateIndexDts.ts",
10
11
  "run-nodejs": "node ./build-nodejs/server.js",
11
12
  "run-nodejs-dev": "typenode ./nodejs/server.ts",
12
13
  "run-web": "node ./builders/webRun.js",
@@ -1,3 +1,4 @@
1
+ /// <reference types="socket-function" />
1
2
  import { SocketRegistered } from "socket-function/SocketFunctionTypes";
2
3
  type RemapFunction<T> = T extends (...args: infer Args) => Promise<infer Return> ? {
3
4
  (...args: Args): Return | undefined;
@@ -8,7 +8,9 @@
8
8
  },
9
9
  "include": [
10
10
  "render-utils/**/*.ts",
11
- "render-utils/**/*.tsx"
11
+ "render-utils/**/*.tsx",
12
+ "misc/**/*.ts",
13
+ "misc/**/*.tsx"
12
14
  ],
13
15
  "exclude": [
14
16
  "node_modules",
@@ -1,50 +0,0 @@
1
- const fs = require("fs");
2
- const path = require("path");
3
-
4
- function getAllDtsFiles(dir, fileList = []) {
5
- const files = fs.readdirSync(dir);
6
-
7
- for (const file of files) {
8
- const filePath = path.join(dir, file);
9
- const stat = fs.statSync(filePath);
10
-
11
- if (stat.isDirectory()) {
12
- getAllDtsFiles(filePath, fileList);
13
- } else if (file.endsWith(".d.ts")) {
14
- fileList.push(filePath);
15
- }
16
- }
17
-
18
- return fileList;
19
- }
20
-
21
- function generateIndexDts() {
22
- const renderUtilsPath = path.join(__dirname, "..", "render-utils");
23
- const dtsFiles = getAllDtsFiles(renderUtilsPath);
24
-
25
- const modules = dtsFiles
26
- .map(filePath => {
27
- const relativePath = path.relative(renderUtilsPath, filePath);
28
- const withoutExt = relativePath.replace(/\.d\.ts$/, "");
29
- const modulePath = "sliftutils/render-utils/" + withoutExt.replace(/\\/g, "/");
30
-
31
- const content = fs.readFileSync(filePath, "utf8");
32
- const indentedContent = content
33
- .split("\n")
34
- .map(line => line ? " " + line : line)
35
- .join("\n");
36
-
37
- return `declare module "${modulePath}" {\n${indentedContent}\n}`;
38
- })
39
- .sort()
40
- .join("\n\n");
41
-
42
- const outputPath = path.join(__dirname, "..", "index.d.ts");
43
- const header = `// Auto-generated file. Do not edit manually.\n// Generated by: yarn generate-index-dts\n\n`;
44
-
45
- fs.writeFileSync(outputPath, header + modules + "\n", "utf8");
46
- console.log(`Generated ${outputPath} with ${dtsFiles.length} module declarations`);
47
- }
48
-
49
- generateIndexDts();
50
-