sliftutils 0.6.3 → 0.6.5
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/builders/extensionBuild.ts +138 -0
- package/builders/extensionBuildRun.js +3 -0
- package/builders/nodeJSBuild.ts +1 -1
- package/builders/webBuild.ts +89 -0
- package/builders/webBuildRun.js +4 -0
- package/misc/fs.ts +19 -0
- package/package.json +10 -9
- package/spec.txt +1 -4
- package/package-lock.json +0 -2418
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import { delay } from "socket-function/src/batching";
|
|
3
|
+
import { bundleEntryCaller } from "../bundler/bundleEntryCaller";
|
|
4
|
+
import yargs from "yargs";
|
|
5
|
+
import { formatTime } from "socket-function/src/formatting/format";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { getAllFiles } from "../misc/fs";
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
let time = Date.now();
|
|
11
|
+
//todonext
|
|
12
|
+
// We need to build both the extBackground.ts and extContentScript.ts
|
|
13
|
+
// And copy the manifest.json
|
|
14
|
+
// AND copy everything in ./assets which has updated
|
|
15
|
+
let yargObj = yargs(process.argv)
|
|
16
|
+
.option("backgroundEntry", { type: "string", default: "./extBackground.ts", desc: `Path to the entry point file` })
|
|
17
|
+
.option("contentEntry", { type: "string", default: "./extContentScript.ts", desc: `Path to the entry point file` })
|
|
18
|
+
.option("manifestPath", { type: "string", default: "./manifest.json", desc: `Path to the manifest.json file` })
|
|
19
|
+
.option("assetsFolder", { type: "string", default: "./assets", desc: `Path to the assets folder` })
|
|
20
|
+
.option("outputFolder", { type: "string", default: "./build-extension", desc: `Output folder` })
|
|
21
|
+
.argv || {}
|
|
22
|
+
;
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
// Wait for any async functions to load.
|
|
26
|
+
await delay(0);
|
|
27
|
+
|
|
28
|
+
let hasBackgroundEntry = fs.existsSync(yargObj.backgroundEntry);
|
|
29
|
+
let hasContentEntry = fs.existsSync(yargObj.contentEntry);
|
|
30
|
+
let hasManifest = fs.existsSync(yargObj.manifestPath);
|
|
31
|
+
let hasAssets = fs.existsSync(yargObj.assetsFolder);
|
|
32
|
+
|
|
33
|
+
if (!hasBackgroundEntry && !hasContentEntry) {
|
|
34
|
+
throw new Error("No extension entry points found. Please specify at least one entry point with the --backgroundEntry or --contentEntry option. Or, create the default file at ./extBackground.ts or ./extContentScript.ts.");
|
|
35
|
+
}
|
|
36
|
+
if (!hasManifest) {
|
|
37
|
+
throw new Error("No manifest file found. Please specify the manifest file with the --manifestPath option. Or, create the default file at ./manifest.json.");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
await fs.promises.mkdir("./build-extension", { recursive: true });
|
|
41
|
+
|
|
42
|
+
if (hasBackgroundEntry) {
|
|
43
|
+
await bundleEntryCaller({
|
|
44
|
+
entryPoint: yargObj.backgroundEntry,
|
|
45
|
+
outputFolder: yargObj.outputFolder,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (hasContentEntry) {
|
|
49
|
+
await bundleEntryCaller({
|
|
50
|
+
entryPoint: yargObj.contentEntry,
|
|
51
|
+
outputFolder: yargObj.outputFolder,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
await fs.promises.cp(yargObj.manifestPath, path.join(yargObj.outputFolder, "manifest.json"));
|
|
55
|
+
|
|
56
|
+
// Parse manifest and collect referenced files
|
|
57
|
+
let manifestContent = await fs.promises.readFile(yargObj.manifestPath, "utf-8");
|
|
58
|
+
let manifest = JSON.parse(manifestContent);
|
|
59
|
+
|
|
60
|
+
// Collect all files to copy
|
|
61
|
+
let filesToCopy: string[] = [];
|
|
62
|
+
|
|
63
|
+
// Helper to add icons (can be string or object of strings)
|
|
64
|
+
function addIconPaths(icon: string | object | undefined) {
|
|
65
|
+
if (!icon) return;
|
|
66
|
+
if (typeof icon === "string") {
|
|
67
|
+
filesToCopy.push(icon);
|
|
68
|
+
} else if (typeof icon === "object") {
|
|
69
|
+
for (const iconPath of Object.values(icon)) {
|
|
70
|
+
if (typeof iconPath === "string") {
|
|
71
|
+
filesToCopy.push(iconPath);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Add manifest-referenced files
|
|
78
|
+
if (manifest.action?.default_popup) filesToCopy.push(manifest.action.default_popup);
|
|
79
|
+
if (manifest.browser_action?.default_popup) filesToCopy.push(manifest.browser_action.default_popup);
|
|
80
|
+
if (manifest.page_action?.default_popup) filesToCopy.push(manifest.page_action.default_popup);
|
|
81
|
+
if (manifest.options_page) filesToCopy.push(manifest.options_page);
|
|
82
|
+
if (manifest.options_ui?.page) filesToCopy.push(manifest.options_ui.page);
|
|
83
|
+
if (manifest.devtools_page) filesToCopy.push(manifest.devtools_page);
|
|
84
|
+
if (manifest.sidebar_action?.default_panel) filesToCopy.push(manifest.sidebar_action.default_panel);
|
|
85
|
+
if (manifest.chrome_url_overrides?.newtab) filesToCopy.push(manifest.chrome_url_overrides.newtab);
|
|
86
|
+
if (manifest.chrome_url_overrides?.bookmarks) filesToCopy.push(manifest.chrome_url_overrides.bookmarks);
|
|
87
|
+
if (manifest.chrome_url_overrides?.history) filesToCopy.push(manifest.chrome_url_overrides.history);
|
|
88
|
+
|
|
89
|
+
// Add icons
|
|
90
|
+
addIconPaths(manifest.icons);
|
|
91
|
+
addIconPaths(manifest.action?.default_icon);
|
|
92
|
+
addIconPaths(manifest.browser_action?.default_icon);
|
|
93
|
+
addIconPaths(manifest.page_action?.default_icon);
|
|
94
|
+
|
|
95
|
+
// Add assets folder files if it exists
|
|
96
|
+
if (hasAssets) {
|
|
97
|
+
for await (const file of getAllFiles(yargObj.assetsFolder)) {
|
|
98
|
+
filesToCopy.push(file);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Copy all files with timestamp checking
|
|
103
|
+
async function getTimestamp(filePath: string): Promise<number> {
|
|
104
|
+
try {
|
|
105
|
+
const stats = await fs.promises.stat(filePath);
|
|
106
|
+
return stats.mtimeMs;
|
|
107
|
+
} catch (error) {
|
|
108
|
+
return 0;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
let filesCopied = 0;
|
|
113
|
+
let root = path.resolve(".");
|
|
114
|
+
for (const file of filesToCopy) {
|
|
115
|
+
let sourcePath = path.resolve(file);
|
|
116
|
+
if (!fs.existsSync(sourcePath)) {
|
|
117
|
+
console.warn(`Warning: File not found: ${file}`);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
let relativePath = path.relative(root, sourcePath);
|
|
121
|
+
let destPath = path.join(yargObj.outputFolder, relativePath);
|
|
122
|
+
|
|
123
|
+
let sourceTimestamp = await getTimestamp(sourcePath);
|
|
124
|
+
let destTimestamp = await getTimestamp(destPath);
|
|
125
|
+
if (sourceTimestamp > destTimestamp) {
|
|
126
|
+
await fs.promises.mkdir(path.dirname(destPath), { recursive: true });
|
|
127
|
+
await fs.promises.cp(sourcePath, destPath);
|
|
128
|
+
filesCopied++;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (filesCopied > 0) {
|
|
132
|
+
console.log(`Copied ${filesCopied} changed assets`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
let duration = Date.now() - time;
|
|
136
|
+
console.log(`NodeJS build completed in ${formatTime(duration)}`);
|
|
137
|
+
}
|
|
138
|
+
main().catch(console.error).finally(() => process.exit());
|
package/builders/nodeJSBuild.ts
CHANGED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import { delay } from "socket-function/src/batching";
|
|
3
|
+
import { bundleEntryCaller } from "../bundler/bundleEntryCaller";
|
|
4
|
+
import yargs from "yargs";
|
|
5
|
+
import { formatTime } from "socket-function/src/formatting/format";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { getAllFiles } from "../misc/fs";
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
let time = Date.now();
|
|
11
|
+
let yargObj = yargs(process.argv)
|
|
12
|
+
.option("entryPoint", { type: "string", default: "./browser.tsx", desc: `Path to the entry point file` })
|
|
13
|
+
.option("indexHtml", { type: "string", default: "./index.html", desc: `Path to the index.html file` })
|
|
14
|
+
.option("assetsFolder", { type: "string", default: "./assets", desc: `Path to the assets folder` })
|
|
15
|
+
.option("outputFolder", { type: "string", default: "./build-web", desc: `Output folder` })
|
|
16
|
+
.argv || {}
|
|
17
|
+
;
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
// Wait for any async functions to load.
|
|
21
|
+
await delay(0);
|
|
22
|
+
|
|
23
|
+
let hasEntryPoint = fs.existsSync(yargObj.entryPoint);
|
|
24
|
+
let hasIndexHtml = fs.existsSync(yargObj.indexHtml);
|
|
25
|
+
let hasAssets = fs.existsSync(yargObj.assetsFolder);
|
|
26
|
+
|
|
27
|
+
if (!hasEntryPoint) {
|
|
28
|
+
throw new Error(`Entry point not found at ${yargObj.entryPoint}. Please specify the entry point with the --entryPoint option.`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
await fs.promises.mkdir(yargObj.outputFolder, { recursive: true });
|
|
32
|
+
|
|
33
|
+
await bundleEntryCaller({
|
|
34
|
+
entryPoint: yargObj.entryPoint,
|
|
35
|
+
outputFolder: yargObj.outputFolder,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Collect all files to copy
|
|
39
|
+
let filesToCopy: string[] = [];
|
|
40
|
+
|
|
41
|
+
if (hasIndexHtml) {
|
|
42
|
+
filesToCopy.push(yargObj.indexHtml);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Add assets folder files if it exists
|
|
46
|
+
if (hasAssets) {
|
|
47
|
+
for await (const file of getAllFiles(yargObj.assetsFolder)) {
|
|
48
|
+
filesToCopy.push(file);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Copy all files with timestamp checking
|
|
53
|
+
async function getTimestamp(filePath: string): Promise<number> {
|
|
54
|
+
try {
|
|
55
|
+
const stats = await fs.promises.stat(filePath);
|
|
56
|
+
return stats.mtimeMs;
|
|
57
|
+
} catch (error) {
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let filesCopied = 0;
|
|
63
|
+
let root = path.resolve(".");
|
|
64
|
+
for (const file of filesToCopy) {
|
|
65
|
+
let sourcePath = path.resolve(file);
|
|
66
|
+
if (!fs.existsSync(sourcePath)) {
|
|
67
|
+
console.warn(`Warning: File not found: ${file}`);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
let relativePath = path.relative(root, sourcePath);
|
|
71
|
+
let destPath = path.join(yargObj.outputFolder, relativePath);
|
|
72
|
+
|
|
73
|
+
let sourceTimestamp = await getTimestamp(sourcePath);
|
|
74
|
+
let destTimestamp = await getTimestamp(destPath);
|
|
75
|
+
if (sourceTimestamp > destTimestamp) {
|
|
76
|
+
await fs.promises.mkdir(path.dirname(destPath), { recursive: true });
|
|
77
|
+
await fs.promises.cp(sourcePath, destPath);
|
|
78
|
+
filesCopied++;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (filesCopied > 0) {
|
|
82
|
+
console.log(`Copied ${filesCopied} changed files`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let duration = Date.now() - time;
|
|
86
|
+
console.log(`Web build completed in ${formatTime(duration)}`);
|
|
87
|
+
}
|
|
88
|
+
main().catch(console.error).finally(() => process.exit());
|
|
89
|
+
|
package/misc/fs.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
export async function* getAllFiles(folder: string): AsyncIterableIterator<string> {
|
|
5
|
+
const files = await fs.promises.readdir(folder);
|
|
6
|
+
for (const file of files) {
|
|
7
|
+
const filePath = path.join(folder, file);
|
|
8
|
+
try {
|
|
9
|
+
const stats = await fs.promises.stat(filePath);
|
|
10
|
+
if (stats.isDirectory()) {
|
|
11
|
+
yield* getAllFiles(filePath);
|
|
12
|
+
} else {
|
|
13
|
+
yield filePath;
|
|
14
|
+
}
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.warn(`Failed while accessing path, skipping: ${filePath}`, error);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sliftutils",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"type": "yarn tsc --noEmit",
|
|
8
|
-
"build-nodejs": "yarn typenode ./builders/nodeJSBuild.ts"
|
|
8
|
+
"build-nodejs": "yarn typenode ./builders/nodeJSBuild.ts",
|
|
9
|
+
"notes": "mobx, preact, socket-function, typenode SHOULD be peerDependencies. But we want to use yarn (better dependency deduplication), so we can't use peerDependencies (as they aren't installed by default, which makes them a nightmare to use). If you want to override the versions, feel free to use overrides/resolutions."
|
|
9
10
|
},
|
|
10
11
|
"bin": {
|
|
11
|
-
"build-nodejs": "./builders/nodeJSBuildRun.js"
|
|
12
|
+
"build-nodejs": "./builders/nodeJSBuildRun.js",
|
|
13
|
+
"build-extension": "./builders/extensionBuildRun.js",
|
|
14
|
+
"build-web": "./builders/webBuildRun.js"
|
|
12
15
|
},
|
|
13
16
|
"dependencies": {
|
|
14
17
|
"@types/shell-quote": "^1.7.5",
|
|
15
18
|
"js-sha256": "^0.11.1",
|
|
19
|
+
"mobx": "^6.13.3",
|
|
20
|
+
"preact": "10.24.3",
|
|
16
21
|
"shell-quote": "^1.8.3",
|
|
22
|
+
"socket-function": "^0.155.0",
|
|
23
|
+
"typenode": "^6.0.0",
|
|
17
24
|
"typesafecss": "^0.26.0",
|
|
18
25
|
"yargs": "15.4.1"
|
|
19
26
|
},
|
|
@@ -22,11 +29,5 @@
|
|
|
22
29
|
"@types/yargs": "15.0.19",
|
|
23
30
|
"debugbreak": "^0.9.9",
|
|
24
31
|
"typedev": "^0.1.1"
|
|
25
|
-
},
|
|
26
|
-
"peerDependencies": {
|
|
27
|
-
"mobx": "^6.13.3",
|
|
28
|
-
"preact": "10.24.3",
|
|
29
|
-
"socket-function": "^0.155.0",
|
|
30
|
-
"typenode": "^6.0.0"
|
|
31
32
|
}
|
|
32
33
|
}
|
package/spec.txt
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
TODO:
|
|
2
2
|
|
|
3
|
-
Ugh... where is it getting the typescript version? Why is it picking the latest... typenode doesn't want the latest...
|
|
4
|
-
|
|
5
|
-
Why is the binary not being added?
|
|
6
3
|
|
|
7
4
|
4) New project with:
|
|
8
5
|
|
|
9
|
-
|
|
6
|
+
We need bins and entry points for the common types of builds
|
|
10
7
|
extension
|
|
11
8
|
copy manifest.json
|
|
12
9
|
build background.ts, copy it
|