@sjcrh/proteinpaint-front 2.207.1 → 2.208.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/README.md +14 -17
- package/bundles.tgz +0 -0
- package/init.js +79 -30
- package/package.json +7 -5
- package/public/index.html +2 -1
package/README.md
CHANGED
|
@@ -11,33 +11,30 @@ an embedder.
|
|
|
11
11
|
|
|
12
12
|
## Usage
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
```
|
|
14
|
+
This package is used inside a ppfull container (https://github.com/stjude/proteinpaint/pkgs/container/ppfull).
|
|
15
|
+
The container image ensures that a matching proteinpaint-server is used to serve the data as expected by
|
|
16
|
+
proteinpaint-client code. Standalone usage outside of a ppfull container is not recommended. From within
|
|
17
|
+
the container, the command below is used:
|
|
20
18
|
|
|
21
|
-
You can manually test your project's postinstall lifecyle script by running the following
|
|
22
|
-
to extract the Proteinpaint bundles, with the correct public path for the dynamically
|
|
23
|
-
loaded Proteinpaint bundles.
|
|
24
19
|
```bash
|
|
25
20
|
npx proteinpaint-front [URL_PUBLIC_PATH]
|
|
26
21
|
```
|
|
27
22
|
|
|
28
|
-
|
|
29
|
-
the same PP server. But note that in this case, the web bundle or
|
|
30
|
-
other domains, even if CORS is allowed, since script
|
|
23
|
+
See `init.js` for details. If the URL_PUBLIC_PATH argument is omitted above, then it will default to `'.'`,
|
|
24
|
+
which assumes that the bundle is served by the same PP server. But note that in this case, the web bundle or
|
|
25
|
+
server host may NOT be embedded or used as host from other domains, even if CORS is allowed, since script
|
|
26
|
+
bundles will not be sourced properly and loaded dynamically.
|
|
31
27
|
|
|
32
|
-
Note that you can serve the web bundle using the Proteinpaint server or any web server,
|
|
33
|
-
see the example in the Develop section.
|
|
34
28
|
|
|
35
29
|
## Develop
|
|
36
30
|
|
|
31
|
+
The usual dev workflow typically focuses on the client workspace development. For troubleshooting builds
|
|
32
|
+
for production, the following may be performed:
|
|
33
|
+
|
|
37
34
|
```bash
|
|
38
|
-
# must run the module bundling of proteinpaint-client
|
|
39
|
-
cd ../client
|
|
40
|
-
npm run
|
|
35
|
+
# must run the module bundling of proteinpaint-client, either from sjpp dev process or below
|
|
36
|
+
cd ../client
|
|
37
|
+
npm run dev
|
|
41
38
|
|
|
42
39
|
# in another terminal
|
|
43
40
|
cd ../front
|
package/bundles.tgz
CHANGED
|
Binary file
|
package/init.js
CHANGED
|
@@ -11,49 +11,98 @@ if (URLPATH.endsWith('/')) URLPATH = URLPATH.slice(0, -1)
|
|
|
11
11
|
const publicBinOnly = process.argv.includes('--publicBinOnly')
|
|
12
12
|
|
|
13
13
|
const CWD = process.cwd()
|
|
14
|
+
const PUBLIC_DIR = `${CWD}/public`
|
|
15
|
+
// The client bundle is generated into a PER-CONTAINER dir at CWD/bin — a sibling of public/, in the
|
|
16
|
+
// container's own writable layer, NOT under any mount — and is served at /bin by the server, which
|
|
17
|
+
// routes /bin to CWD/bin when it exists (see the server's serverconfig binDir + app.middlewares.js).
|
|
18
|
+
//
|
|
19
|
+
// It is deliberately NOT written into public/: when several instances bind-mount the SAME public/,
|
|
20
|
+
// regenerating a shared public/bin at startup makes them clobber one another (one instance's recursive
|
|
21
|
+
// rmdir races another's tar extract -> "ENOTEMPTY, Directory not empty: .../public/bin", crashing a
|
|
22
|
+
// startup). Generating per-container removes the shared write entirely, so concurrent starts can't race
|
|
23
|
+
// — no lock or cross-instance key needed. It also makes a rolling deploy safe: init never mutates the
|
|
24
|
+
// shared public/bin, so instances still on an older release keep serving their own public/bin while new
|
|
25
|
+
// instances serve their CWD/bin. An older image that has no CWD/bin also still works — the server falls
|
|
26
|
+
// back to serving /bin from public/bin.
|
|
27
|
+
const BIN_DIR = `${CWD}/bin`
|
|
28
|
+
// A distinctively named marker written LAST, only after the bundle is fully extracted AND its __PP_URL__
|
|
29
|
+
// placeholder is replaced. It serves two purposes:
|
|
30
|
+
// - completion: reuse requires it, so a container that stops mid-generation (after tar creates
|
|
31
|
+
// proteinpaint.js but before the URL rewrite, or on a partial extraction) regenerates on its next
|
|
32
|
+
// start instead of reusing a partial/unpatched bundle forever — which the health gate can't catch,
|
|
33
|
+
// since an unpatched or incomplete proteinpaint.js still returns 200.
|
|
34
|
+
// - ownership: the server publishes CWD/bin at /bin ONLY when this marker is present (see the server's
|
|
35
|
+
// app.middlewares.js), so launching the server package from a consumer project never exposes an
|
|
36
|
+
// unrelated CWD/bin (e.g. that project's own bin/ scripts) over HTTP. The name is distinctive so it
|
|
37
|
+
// won't collide with a consumer's files.
|
|
38
|
+
const BIN_READY = `${BIN_DIR}/.pp-bundle-ready`
|
|
14
39
|
|
|
15
40
|
console.log('CWD', CWD)
|
|
16
41
|
try {
|
|
17
|
-
if (!fs.existsSync(
|
|
42
|
+
if (!fs.existsSync(PUBLIC_DIR)) {
|
|
18
43
|
console.log(`making a public directory at ${CWD}`)
|
|
19
|
-
fs.mkdirSync(
|
|
20
|
-
}
|
|
21
|
-
if (fs.existsSync(`${CWD}/public/bin`)) {
|
|
22
|
-
console.log(`removing the old public/bin at ${CWD}`)
|
|
23
|
-
// should update as part of v16 upgrade
|
|
24
|
-
fs.rmdirSync(`${CWD}/public/bin`, { recursive: true, force: true }, () => {})
|
|
44
|
+
fs.mkdirSync(PUBLIC_DIR)
|
|
25
45
|
}
|
|
46
|
+
// index.html / cards are ensured independently of the bundle below (idempotent, and needed even when
|
|
47
|
+
// the bundle is reused), so a skipped regeneration still leaves the public scaffolding in place.
|
|
26
48
|
if (!publicBinOnly) {
|
|
27
|
-
if (!fs.existsSync(`${
|
|
49
|
+
if (!fs.existsSync(`${PUBLIC_DIR}/index.html`)) {
|
|
28
50
|
console.log(`creating a public/index.html file`)
|
|
29
|
-
fs.copyFileSync(path.join(__dirname, './public/index.html'), `${
|
|
51
|
+
fs.copyFileSync(path.join(__dirname, './public/index.html'), `${PUBLIC_DIR}/index.html`)
|
|
30
52
|
}
|
|
31
|
-
if (!fs.existsSync(`${
|
|
53
|
+
if (!fs.existsSync(`${PUBLIC_DIR}/cards`)) {
|
|
32
54
|
console.log(`Copying cards into public/cards folder`)
|
|
33
|
-
execSync(`cp -r ${CWD}/node_modules/@sjcrh/proteinpaint-front/public/cards ${
|
|
55
|
+
execSync(`cp -r ${CWD}/node_modules/@sjcrh/proteinpaint-front/public/cards ${PUBLIC_DIR}/cards`, {
|
|
34
56
|
stdio: 'inherit'
|
|
35
57
|
})
|
|
36
58
|
}
|
|
37
59
|
}
|
|
38
|
-
|
|
39
|
-
if
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
|
|
61
|
+
// Generate the bundle into CWD/bin only if it isn't already there. CWD/bin is in the container's
|
|
62
|
+
// writable layer, so it persists across restarts of THIS container (reuse) and is empty in any freshly
|
|
63
|
+
// created container (regenerate) — including after an image update, which always yields a new
|
|
64
|
+
// container. Because CWD/bin is per-container, there is no shared directory to race on.
|
|
65
|
+
//
|
|
66
|
+
// NOTE: reuse is keyed on the completion marker (a fully extracted, URL-patched bundle), not on its
|
|
67
|
+
// version or URL. That is correct for the normal container lifecycle (a new image, or a changed URL,
|
|
68
|
+
// arrives with a new container and hence an empty CWD/bin). It would be stale only if the SAME
|
|
69
|
+
// container were reused across a bundle or URL change — e.g. CWD/bin persisted via a mounted volume,
|
|
70
|
+
// or serverconfig.json remounted with a different URL and merely restarted — uncommon, and outside
|
|
71
|
+
// this simple scheme.
|
|
72
|
+
if (fs.existsSync(BIN_READY)) {
|
|
73
|
+
console.log(`bundle already present and complete at ${BIN_DIR}; reusing it`)
|
|
74
|
+
} else {
|
|
75
|
+
if (fs.existsSync(BIN_DIR)) {
|
|
76
|
+
console.log(`removing an incomplete ${BIN_DIR}`)
|
|
77
|
+
fs.rmSync(BIN_DIR, { recursive: true, force: true })
|
|
78
|
+
}
|
|
79
|
+
// bundles.tgz contains public/bin/*; --strip-components=1 drops the leading public/ so the files
|
|
80
|
+
// land in CWD/bin/* (this container's private bin), not in the shared public/.
|
|
81
|
+
const tar = ps.spawnSync('tar', [`-xzf`, `${__dirname}/bundles.tgz`, `-C`, `${CWD}`, `--strip-components=1`], {
|
|
82
|
+
encoding: 'utf8'
|
|
83
|
+
})
|
|
84
|
+
if (tar.status !== 0) {
|
|
85
|
+
throw new Error(`Tar command failed with exit code ${tar.status}: ${tar.stderr}`)
|
|
86
|
+
}
|
|
87
|
+
if (tar.stderr) {
|
|
88
|
+
console.warn('Tar command warnings:', tar.stderr)
|
|
89
|
+
}
|
|
90
|
+
console.log(`Setting the dynamic bundle path to ${URLPATH}`)
|
|
91
|
+
const codeFile = `${BIN_DIR}/proteinpaint.js`
|
|
92
|
+
// remember the modified time before setting the bundle public path
|
|
93
|
+
const mtime = fs.statSync(codeFile).mtime
|
|
94
|
+
const code = fs.readFileSync(codeFile, { encoding: 'utf8' })
|
|
95
|
+
const newcode = code.replace(`__PP_URL__`, `${URLPATH}/bin/`)
|
|
96
|
+
fs.writeFileSync(codeFile, newcode, { encoding: 'utf8' })
|
|
97
|
+
try {
|
|
98
|
+
// reset the atime and mtime to the original mtime before setting the bundle public path
|
|
99
|
+
fs.utimesSync(codeFile, mtime, mtime)
|
|
100
|
+
} catch (e) {
|
|
101
|
+
console.log('--- !!! unable to reset the mtime for the extracted proteinpaint bundle: ', e)
|
|
102
|
+
}
|
|
103
|
+
// mark generation complete LAST (see BIN_READY above): a crash before this leaves no marker, so
|
|
104
|
+
// the next start regenerates rather than reusing a partial or unpatched bundle.
|
|
105
|
+
fs.writeFileSync(BIN_READY, '')
|
|
57
106
|
}
|
|
58
107
|
} catch (e) {
|
|
59
108
|
console.error(e)
|
package/package.json
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sjcrh/proteinpaint-front",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.208.0",
|
|
4
4
|
"browser": "src/app.js",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": "init.js",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"dev": "./dev.sh
|
|
8
|
+
"dev": "./dev.sh",
|
|
9
9
|
"//TODO": "# delete webpack use, once esbuild migration is fully tested and unlikely to be reverted",
|
|
10
10
|
"client-dist": "if ! -d ../client/dist; then cd ../client; npm pack; fi",
|
|
11
|
-
"prepack": "npm run client-dist && rm -rf public/bin && rm -rf *.tgz && webpack && tar -czf bundles.tgz public/bin",
|
|
11
|
+
"prepack": "npm run client-dist && rm -rf public/bin && rm -rf *.tgz && webpack && tar -czf bundles.tgz public/bin && npm pkg set _buildTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
12
|
+
"postpack": "npm pkg delete _buildTime",
|
|
12
13
|
"test:unit": "echo 'TODO: front unit tests'",
|
|
13
14
|
"test:integration": "echo 'TODO: front integration tests'"
|
|
14
15
|
},
|
|
15
16
|
"devDependencies": {
|
|
16
|
-
"@sjcrh/proteinpaint-client": "2.
|
|
17
|
+
"@sjcrh/proteinpaint-client": "2.208.0",
|
|
17
18
|
"webpack": "^5.76.0",
|
|
18
19
|
"webpack-cli": "^4.9.2",
|
|
19
20
|
"webpack-node-externals": "^3.0.0"
|
|
@@ -30,5 +31,6 @@
|
|
|
30
31
|
"type": "git",
|
|
31
32
|
"url": "https://github.com/stjude/proteinpaint",
|
|
32
33
|
"directory": "front"
|
|
33
|
-
}
|
|
34
|
+
},
|
|
35
|
+
"_buildTime": "2026-09-13T18:12:02Z"
|
|
34
36
|
}
|
package/public/index.html
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
best practice is to use <script defer> or to put script tags before </body> end tag and
|
|
9
9
|
just before the runproteinpaint() call
|
|
10
10
|
-->
|
|
11
|
-
<script src="/bin/
|
|
11
|
+
<script src="/bin/proteinpaint.js" charset="utf-8"></script>
|
|
12
12
|
</head>
|
|
13
13
|
<body style="margin:0px;width:100%;height:100%">
|
|
14
14
|
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
<script>
|
|
20
20
|
runproteinpaint({
|
|
21
|
+
//host: 'http://localhost:3000',
|
|
21
22
|
host: 'https://proteinpaint.stjude.org',
|
|
22
23
|
holder:document.getElementById('aaa'),
|
|
23
24
|
parseurl:true,
|