@jskit-ai/create-app 0.1.3 → 0.1.6
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/bin/jskit-create-app.js +5 -0
- package/package.json +2 -3
- package/src/client/index.js +1 -0
- package/src/index.js +1 -0
- package/src/server/cliEntrypoint.js +25 -0
- package/src/server/index.js +632 -0
- package/templates/base-shell/.jskit/lock.json +31 -0
- package/templates/base-shell/Procfile +1 -0
- package/templates/base-shell/README.md +43 -0
- package/templates/base-shell/app.scripts.config.mjs +3 -0
- package/templates/base-shell/bin/server.js +8 -0
- package/templates/base-shell/config/public.js +30 -0
- package/templates/base-shell/config/server.js +1 -0
- package/templates/base-shell/config/surfaceAccessPolicies.js +12 -0
- package/templates/base-shell/eslint.config.mjs +10 -0
- package/templates/base-shell/favicon.svg +7 -0
- package/templates/base-shell/gitignore +9 -0
- package/templates/base-shell/index.html +13 -0
- package/templates/base-shell/jsconfig.json +8 -0
- package/templates/base-shell/package.json +64 -0
- package/templates/base-shell/packages/main/package.descriptor.mjs +55 -0
- package/templates/base-shell/packages/main/package.json +12 -0
- package/templates/base-shell/packages/main/src/client/index.js +13 -0
- package/templates/base-shell/packages/main/src/client/providers/MainClientProvider.js +33 -0
- package/templates/base-shell/packages/main/src/server/controllers/index.js +9 -0
- package/templates/base-shell/packages/main/src/server/index.js +1 -0
- package/templates/base-shell/packages/main/src/server/providers/MainServiceProvider.js +22 -0
- package/templates/base-shell/packages/main/src/server/routes/index.js +9 -0
- package/templates/base-shell/packages/main/src/server/services/index.js +9 -0
- package/templates/base-shell/packages/main/src/server/support/loadAppConfig.js +55 -0
- package/templates/base-shell/packages/main/src/shared/index.js +8 -0
- package/templates/base-shell/packages/main/src/shared/schemas/index.js +20 -0
- package/templates/base-shell/scripts/dev-bootstrap-jskit.sh +110 -0
- package/templates/base-shell/scripts/just_run_verde +37 -0
- package/templates/base-shell/scripts/link-local-jskit-packages.sh +90 -0
- package/templates/base-shell/scripts/update-jskit-packages.sh +73 -0
- package/templates/base-shell/scripts/verdaccio/config.yaml +26 -0
- package/templates/base-shell/scripts/verdaccio-reset-and-publish-packages.sh +314 -0
- package/templates/base-shell/server/lib/runtimeEnv.js +45 -0
- package/templates/base-shell/server/lib/surfaceRuntime.js +10 -0
- package/templates/base-shell/server.js +69 -0
- package/templates/base-shell/src/App.vue +13 -0
- package/templates/base-shell/src/main.js +90 -0
- package/templates/base-shell/src/pages/console/index.vue +12 -0
- package/templates/base-shell/src/pages/console.vue +13 -0
- package/templates/base-shell/src/pages/home/index.vue +12 -0
- package/templates/base-shell/src/pages/home.vue +13 -0
- package/templates/base-shell/src/views/NotFound.vue +13 -0
- package/templates/base-shell/tests/client/smoke.vitest.js +7 -0
- package/templates/base-shell/tests/server/minimalShell.validator.test.js +134 -0
- package/templates/base-shell/tests/server/smoke.test.js +16 -0
- package/templates/base-shell/vite.config.mjs +64 -0
- package/templates/base-shell/vite.shared.mjs +59 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Re-link installed @jskit-ai packages in node_modules to a local jskit-ai monorepo checkout.
|
|
3
|
+
# Run this AFTER `npm install` when you want live local development without publishing packages.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# npm run link:local:jskit
|
|
7
|
+
# JSKIT_REPO_ROOT=/abs/path/to/jskit-ai npm run link:local:jskit
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
APP_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
11
|
+
SCOPE_DIR="$APP_ROOT/node_modules/@jskit-ai"
|
|
12
|
+
|
|
13
|
+
is_valid_jskit_repo_root() {
|
|
14
|
+
local candidate_root="$1"
|
|
15
|
+
[[ -d "$candidate_root/packages" && -d "$candidate_root/packages/kernel" && -d "$candidate_root/tooling" ]]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
resolve_local_repo_root() {
|
|
19
|
+
if [[ -n "${JSKIT_REPO_ROOT:-}" ]]; then
|
|
20
|
+
echo "$JSKIT_REPO_ROOT"
|
|
21
|
+
return 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
local current_dir="$APP_ROOT"
|
|
25
|
+
while true; do
|
|
26
|
+
if is_valid_jskit_repo_root "$current_dir"; then
|
|
27
|
+
echo "$current_dir"
|
|
28
|
+
return 0
|
|
29
|
+
fi
|
|
30
|
+
if [[ "$current_dir" == "/" ]]; then
|
|
31
|
+
return 1
|
|
32
|
+
fi
|
|
33
|
+
current_dir="$(dirname "$current_dir")"
|
|
34
|
+
done
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
JSKIT_REPO_ROOT="$(resolve_local_repo_root || true)"
|
|
38
|
+
|
|
39
|
+
if [[ ! -d "$SCOPE_DIR" ]]; then
|
|
40
|
+
echo "[link-local] @jskit-ai scope not found at $SCOPE_DIR (run npm install first)." >&2
|
|
41
|
+
exit 1
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
if [[ -z "$JSKIT_REPO_ROOT" ]]; then
|
|
45
|
+
echo "[link-local] no JSKIT repository found." >&2
|
|
46
|
+
echo "[link-local] set JSKIT_REPO_ROOT to a local jskit-ai checkout path." >&2
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
if ! is_valid_jskit_repo_root "$JSKIT_REPO_ROOT"; then
|
|
51
|
+
echo "[link-local] JSKIT_REPO_ROOT is not a valid jskit-ai checkout: $JSKIT_REPO_ROOT" >&2
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
resolve_source_dir() {
|
|
56
|
+
local package_dir_name="$1"
|
|
57
|
+
case "$package_dir_name" in
|
|
58
|
+
config-eslint|create-app|jskit-cli|jskit-catalog)
|
|
59
|
+
echo "$JSKIT_REPO_ROOT/tooling/$package_dir_name"
|
|
60
|
+
;;
|
|
61
|
+
*)
|
|
62
|
+
echo "$JSKIT_REPO_ROOT/packages/$package_dir_name"
|
|
63
|
+
;;
|
|
64
|
+
esac
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
linked_count=0
|
|
68
|
+
skipped_count=0
|
|
69
|
+
|
|
70
|
+
for installed_path in "$SCOPE_DIR"/*; do
|
|
71
|
+
if [[ ! -e "$installed_path" && ! -L "$installed_path" ]]; then
|
|
72
|
+
continue
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
package_dir_name="$(basename "$installed_path")"
|
|
76
|
+
source_dir="$(resolve_source_dir "$package_dir_name")"
|
|
77
|
+
|
|
78
|
+
if [[ ! -f "$source_dir/package.json" ]]; then
|
|
79
|
+
echo "[link-local] skip @jskit-ai/$package_dir_name (no local source at $source_dir)"
|
|
80
|
+
skipped_count=$((skipped_count + 1))
|
|
81
|
+
continue
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
rm -rf "$installed_path"
|
|
85
|
+
ln -s "$source_dir" "$installed_path"
|
|
86
|
+
echo "[link-local] linked @jskit-ai/$package_dir_name -> $source_dir"
|
|
87
|
+
linked_count=$((linked_count + 1))
|
|
88
|
+
done
|
|
89
|
+
|
|
90
|
+
echo "[link-local] done. linked=$linked_count skipped=$skipped_count"
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
APP_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
|
+
PACKAGE_JSON_PATH="$APP_ROOT/package.json"
|
|
6
|
+
JSKIT_REGISTRY="${JSKIT_REGISTRY:-}"
|
|
7
|
+
|
|
8
|
+
if [[ ! -f "$PACKAGE_JSON_PATH" ]]; then
|
|
9
|
+
echo "[jskit:update] package.json not found: $PACKAGE_JSON_PATH" >&2
|
|
10
|
+
exit 1
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
readarray -t runtime_packages < <(
|
|
14
|
+
node -e '
|
|
15
|
+
const fs = require("node:fs");
|
|
16
|
+
const packageJson = JSON.parse(fs.readFileSync(process.argv[1], "utf8"));
|
|
17
|
+
const dependencies = packageJson?.dependencies || {};
|
|
18
|
+
const names = Object.keys(dependencies).filter((name) => name.startsWith("@jskit-ai/")).sort();
|
|
19
|
+
for (const name of names) {
|
|
20
|
+
process.stdout.write(`${name}\n`);
|
|
21
|
+
}
|
|
22
|
+
' "$PACKAGE_JSON_PATH"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
readarray -t dev_packages < <(
|
|
26
|
+
node -e '
|
|
27
|
+
const fs = require("node:fs");
|
|
28
|
+
const packageJson = JSON.parse(fs.readFileSync(process.argv[1], "utf8"));
|
|
29
|
+
const dependencies = packageJson?.devDependencies || {};
|
|
30
|
+
const names = Object.keys(dependencies).filter((name) => name.startsWith("@jskit-ai/")).sort();
|
|
31
|
+
for (const name of names) {
|
|
32
|
+
process.stdout.write(`${name}\n`);
|
|
33
|
+
}
|
|
34
|
+
' "$PACKAGE_JSON_PATH"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
runtime_specs=()
|
|
38
|
+
for package_name in "${runtime_packages[@]}"; do
|
|
39
|
+
runtime_specs+=("${package_name}@latest")
|
|
40
|
+
done
|
|
41
|
+
|
|
42
|
+
dev_specs=()
|
|
43
|
+
for package_name in "${dev_packages[@]}"; do
|
|
44
|
+
dev_specs+=("${package_name}@latest")
|
|
45
|
+
done
|
|
46
|
+
|
|
47
|
+
registry_args=()
|
|
48
|
+
if [[ -n "$JSKIT_REGISTRY" ]]; then
|
|
49
|
+
registry_args+=(--registry "$JSKIT_REGISTRY")
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
if (( ${#runtime_specs[@]} == 0 && ${#dev_specs[@]} == 0 )); then
|
|
53
|
+
echo "[jskit:update] no @jskit-ai packages found in dependencies."
|
|
54
|
+
exit 0
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
if (( ${#runtime_specs[@]} > 0 )); then
|
|
58
|
+
echo "[jskit:update] updating runtime packages: ${runtime_specs[*]}"
|
|
59
|
+
(
|
|
60
|
+
cd "$APP_ROOT"
|
|
61
|
+
npm install --save-exact "${registry_args[@]}" "${runtime_specs[@]}"
|
|
62
|
+
)
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
if (( ${#dev_specs[@]} > 0 )); then
|
|
66
|
+
echo "[jskit:update] updating dev packages: ${dev_specs[*]}"
|
|
67
|
+
(
|
|
68
|
+
cd "$APP_ROOT"
|
|
69
|
+
npm install --save-dev --save-exact "${registry_args[@]}" "${dev_specs[@]}"
|
|
70
|
+
)
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
echo "[jskit:update] done."
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
storage: ./storage
|
|
2
|
+
|
|
3
|
+
auth:
|
|
4
|
+
htpasswd:
|
|
5
|
+
file: ./htpasswd
|
|
6
|
+
|
|
7
|
+
uplinks:
|
|
8
|
+
npmjs:
|
|
9
|
+
url: https://registry.npmjs.org/
|
|
10
|
+
|
|
11
|
+
packages:
|
|
12
|
+
"@jskit-ai/*":
|
|
13
|
+
access: $all
|
|
14
|
+
publish: $all
|
|
15
|
+
unpublish: $all
|
|
16
|
+
|
|
17
|
+
"**":
|
|
18
|
+
access: $all
|
|
19
|
+
publish: $all
|
|
20
|
+
unpublish: $all
|
|
21
|
+
proxy: npmjs
|
|
22
|
+
|
|
23
|
+
log:
|
|
24
|
+
- type: stdout
|
|
25
|
+
format: pretty
|
|
26
|
+
level: http
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
|
+
DEFAULT_VERDACCIO_CONFIG="$ROOT_DIR/scripts/verdaccio/config.yaml"
|
|
6
|
+
if [[ -f "$DEFAULT_VERDACCIO_CONFIG" ]]; then
|
|
7
|
+
VERDACCIO_CONFIG="${VERDACCIO_CONFIG:-$DEFAULT_VERDACCIO_CONFIG}"
|
|
8
|
+
else
|
|
9
|
+
VERDACCIO_CONFIG="${VERDACCIO_CONFIG:-$HOME/.config/verdaccio/config.yaml}"
|
|
10
|
+
fi
|
|
11
|
+
VERDACCIO_LISTEN="${VERDACCIO_LISTEN:-127.0.0.1:4873}"
|
|
12
|
+
VERDACCIO_REGISTRY="${VERDACCIO_REGISTRY:-http://$VERDACCIO_LISTEN}"
|
|
13
|
+
VERDACCIO_REGISTRY="${VERDACCIO_REGISTRY%/}"
|
|
14
|
+
VERDACCIO_LOG_FILE="${VERDACCIO_LOG_FILE:-/tmp/verdaccio-jskit.log}"
|
|
15
|
+
VERDACCIO_PID_FILE="${VERDACCIO_PID_FILE:-/tmp/verdaccio-jskit.pid}"
|
|
16
|
+
PUBLISH_CONCURRENCY="${PUBLISH_CONCURRENCY:-10}"
|
|
17
|
+
JSKIT_REPO_ROOT="${JSKIT_REPO_ROOT:-}"
|
|
18
|
+
PACKAGES_DIR="${PACKAGES_DIR:-}"
|
|
19
|
+
TOOLING_DIR="${TOOLING_DIR:-}"
|
|
20
|
+
|
|
21
|
+
is_valid_jskit_repo_root() {
|
|
22
|
+
local candidate_root="$1"
|
|
23
|
+
[[ -d "$candidate_root/packages" && -d "$candidate_root/packages/kernel" && -d "$candidate_root/tooling" ]]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
resolve_jskit_repo_root() {
|
|
27
|
+
if [[ -n "$JSKIT_REPO_ROOT" ]]; then
|
|
28
|
+
echo "$JSKIT_REPO_ROOT"
|
|
29
|
+
return 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
local current_dir="$ROOT_DIR"
|
|
33
|
+
while true; do
|
|
34
|
+
if is_valid_jskit_repo_root "$current_dir"; then
|
|
35
|
+
echo "$current_dir"
|
|
36
|
+
return 0
|
|
37
|
+
fi
|
|
38
|
+
if [[ "$current_dir" == "/" ]]; then
|
|
39
|
+
return 1
|
|
40
|
+
fi
|
|
41
|
+
current_dir="$(dirname "$current_dir")"
|
|
42
|
+
done
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
configure_source_dirs() {
|
|
46
|
+
if [[ -z "$PACKAGES_DIR" || -z "$TOOLING_DIR" ]]; then
|
|
47
|
+
local detected_root
|
|
48
|
+
detected_root="$(resolve_jskit_repo_root || true)"
|
|
49
|
+
if [[ -n "$detected_root" ]]; then
|
|
50
|
+
JSKIT_REPO_ROOT="$detected_root"
|
|
51
|
+
if [[ -z "$PACKAGES_DIR" ]]; then
|
|
52
|
+
PACKAGES_DIR="$JSKIT_REPO_ROOT/packages"
|
|
53
|
+
fi
|
|
54
|
+
if [[ -z "$TOOLING_DIR" ]]; then
|
|
55
|
+
TOOLING_DIR="$JSKIT_REPO_ROOT/tooling"
|
|
56
|
+
fi
|
|
57
|
+
fi
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
if [[ -z "$PACKAGES_DIR" ]]; then
|
|
61
|
+
echo "Packages directory not configured." >&2
|
|
62
|
+
echo "Set PACKAGES_DIR directly, or set JSKIT_REPO_ROOT to a local jskit-ai checkout." >&2
|
|
63
|
+
exit 1
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
if [[ -z "$TOOLING_DIR" ]]; then
|
|
67
|
+
TOOLING_DIR="/dev/null"
|
|
68
|
+
fi
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
resolve_storage_dir() {
|
|
72
|
+
if [[ -n "${VERDACCIO_STORAGE_DIR:-}" ]]; then
|
|
73
|
+
echo "$VERDACCIO_STORAGE_DIR"
|
|
74
|
+
return
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
if [[ -f "$VERDACCIO_CONFIG" ]]; then
|
|
78
|
+
local configured_storage=""
|
|
79
|
+
configured_storage="$(sed -nE 's/^[[:space:]]*storage:[[:space:]]*([^#]+).*$/\1/p' "$VERDACCIO_CONFIG" | head -n 1 | xargs || true)"
|
|
80
|
+
if [[ -n "$configured_storage" ]]; then
|
|
81
|
+
if [[ "$configured_storage" = /* ]]; then
|
|
82
|
+
echo "$configured_storage"
|
|
83
|
+
else
|
|
84
|
+
echo "$(cd "$(dirname "$VERDACCIO_CONFIG")" && pwd)/$configured_storage"
|
|
85
|
+
fi
|
|
86
|
+
return
|
|
87
|
+
fi
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
echo "$HOME/.local/share/verdaccio/storage"
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
stop_verdaccio() {
|
|
94
|
+
local listen_port
|
|
95
|
+
listen_port="${VERDACCIO_LISTEN##*:}"
|
|
96
|
+
|
|
97
|
+
if [[ -f "$VERDACCIO_PID_FILE" ]]; then
|
|
98
|
+
local pid
|
|
99
|
+
pid="$(cat "$VERDACCIO_PID_FILE" || true)"
|
|
100
|
+
if [[ -n "${pid:-}" ]] && kill -0 "$pid" 2>/dev/null; then
|
|
101
|
+
kill "$pid" || true
|
|
102
|
+
fi
|
|
103
|
+
rm -f "$VERDACCIO_PID_FILE"
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
if command -v lsof >/dev/null 2>&1; then
|
|
107
|
+
local listener_pids
|
|
108
|
+
listener_pids="$(lsof -tiTCP:"$listen_port" -sTCP:LISTEN 2>/dev/null || true)"
|
|
109
|
+
if [[ -n "$listener_pids" ]]; then
|
|
110
|
+
for pid in $listener_pids; do
|
|
111
|
+
if [[ "$pid" != "$$" ]]; then
|
|
112
|
+
kill "$pid" >/dev/null 2>&1 || true
|
|
113
|
+
fi
|
|
114
|
+
done
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
local attempts=0
|
|
118
|
+
while lsof -tiTCP:"$listen_port" -sTCP:LISTEN >/dev/null 2>&1; do
|
|
119
|
+
attempts=$((attempts + 1))
|
|
120
|
+
if (( attempts > 20 )); then
|
|
121
|
+
break
|
|
122
|
+
fi
|
|
123
|
+
sleep 0.25
|
|
124
|
+
done
|
|
125
|
+
|
|
126
|
+
listener_pids="$(lsof -tiTCP:"$listen_port" -sTCP:LISTEN 2>/dev/null || true)"
|
|
127
|
+
if [[ -n "$listener_pids" ]]; then
|
|
128
|
+
for pid in $listener_pids; do
|
|
129
|
+
if [[ "$pid" != "$$" ]]; then
|
|
130
|
+
kill -9 "$pid" >/dev/null 2>&1 || true
|
|
131
|
+
fi
|
|
132
|
+
done
|
|
133
|
+
fi
|
|
134
|
+
fi
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
start_verdaccio() {
|
|
138
|
+
local cmd=(npx --yes verdaccio --listen "$VERDACCIO_LISTEN")
|
|
139
|
+
local config_dir
|
|
140
|
+
config_dir="$(pwd)"
|
|
141
|
+
if [[ -f "$VERDACCIO_CONFIG" ]]; then
|
|
142
|
+
cmd+=(--config "$VERDACCIO_CONFIG")
|
|
143
|
+
config_dir="$(cd "$(dirname "$VERDACCIO_CONFIG")" && pwd)"
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
(
|
|
147
|
+
cd "$config_dir"
|
|
148
|
+
nohup "${cmd[@]}" >"$VERDACCIO_LOG_FILE" 2>&1 &
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
local attempts=0
|
|
152
|
+
until curl -fsS "$VERDACCIO_REGISTRY/-/ping" >/dev/null 2>&1; do
|
|
153
|
+
attempts=$((attempts + 1))
|
|
154
|
+
if (( attempts > 60 )); then
|
|
155
|
+
echo "Verdaccio did not become ready at $VERDACCIO_REGISTRY within 60s." >&2
|
|
156
|
+
echo "See log: $VERDACCIO_LOG_FILE" >&2
|
|
157
|
+
exit 1
|
|
158
|
+
fi
|
|
159
|
+
sleep 1
|
|
160
|
+
done
|
|
161
|
+
|
|
162
|
+
local listen_port
|
|
163
|
+
listen_port="${VERDACCIO_LISTEN##*:}"
|
|
164
|
+
local listener_pid
|
|
165
|
+
listener_pid="$(lsof -tiTCP:"$listen_port" -sTCP:LISTEN 2>/dev/null | head -n 1 || true)"
|
|
166
|
+
if [[ -n "$listener_pid" ]]; then
|
|
167
|
+
echo "$listener_pid" >"$VERDACCIO_PID_FILE"
|
|
168
|
+
fi
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
publish_packages() {
|
|
172
|
+
if [[ ! -d "$PACKAGES_DIR" ]]; then
|
|
173
|
+
echo "Packages directory not found: $PACKAGES_DIR" >&2
|
|
174
|
+
echo "Set PACKAGES_DIR to your monorepo packages path, or set JSKIT_REPO_ROOT." >&2
|
|
175
|
+
exit 1
|
|
176
|
+
fi
|
|
177
|
+
|
|
178
|
+
local dirs=()
|
|
179
|
+
if [[ -d "$TOOLING_DIR" ]]; then
|
|
180
|
+
while IFS= read -r dir; do
|
|
181
|
+
if [[ ! -f "$dir/package.json" ]]; then
|
|
182
|
+
continue
|
|
183
|
+
fi
|
|
184
|
+
local package_name
|
|
185
|
+
package_name="$(cd "$dir" && node -p "require('./package.json').name || ''" 2>/dev/null || true)"
|
|
186
|
+
if [[ "$package_name" == @jskit-ai/* ]]; then
|
|
187
|
+
dirs+=("$dir")
|
|
188
|
+
fi
|
|
189
|
+
done < <(find "$TOOLING_DIR" -mindepth 1 -maxdepth 1 -type d | sort)
|
|
190
|
+
fi
|
|
191
|
+
while IFS= read -r dir; do
|
|
192
|
+
dirs+=("$dir")
|
|
193
|
+
done < <(find "$PACKAGES_DIR" -mindepth 1 -maxdepth 1 -type d | sort)
|
|
194
|
+
|
|
195
|
+
if (( ${#dirs[@]} > 1 )); then
|
|
196
|
+
local deduped=()
|
|
197
|
+
local seen=":"
|
|
198
|
+
for dir in "${dirs[@]}"; do
|
|
199
|
+
if [[ "$seen" != *":$dir:"* ]]; then
|
|
200
|
+
deduped+=("$dir")
|
|
201
|
+
seen="${seen}${dir}:"
|
|
202
|
+
fi
|
|
203
|
+
done
|
|
204
|
+
dirs=("${deduped[@]}")
|
|
205
|
+
fi
|
|
206
|
+
|
|
207
|
+
if (( ${#dirs[@]} == 0 )); then
|
|
208
|
+
echo "No package directories found under $PACKAGES_DIR" >&2
|
|
209
|
+
exit 1
|
|
210
|
+
fi
|
|
211
|
+
|
|
212
|
+
local npm_userconfig
|
|
213
|
+
local registry_with_slash
|
|
214
|
+
local verdaccio_auth_token
|
|
215
|
+
npm_userconfig="$(mktemp)"
|
|
216
|
+
registry_with_slash="${VERDACCIO_REGISTRY%/}/"
|
|
217
|
+
verdaccio_auth_token="${VERDACCIO_AUTH_TOKEN:-dev-local-token}"
|
|
218
|
+
printf "@jskit-ai:registry=%s\nregistry=%s\n//%s/:_authToken=%s\n" \
|
|
219
|
+
"$registry_with_slash" \
|
|
220
|
+
"$registry_with_slash" \
|
|
221
|
+
"${VERDACCIO_LISTEN}" \
|
|
222
|
+
"$verdaccio_auth_token" >"$npm_userconfig"
|
|
223
|
+
|
|
224
|
+
if [[ ! "$PUBLISH_CONCURRENCY" =~ ^[0-9]+$ ]] || (( PUBLISH_CONCURRENCY < 1 )); then
|
|
225
|
+
echo "PUBLISH_CONCURRENCY must be a positive integer (got: $PUBLISH_CONCURRENCY)." >&2
|
|
226
|
+
exit 1
|
|
227
|
+
fi
|
|
228
|
+
|
|
229
|
+
echo "Publishing with concurrency=$PUBLISH_CONCURRENCY"
|
|
230
|
+
|
|
231
|
+
publish_one_package() {
|
|
232
|
+
local dir="$1"
|
|
233
|
+
local npm_userconfig="$2"
|
|
234
|
+
if [[ ! -f "$dir/package.json" ]]; then
|
|
235
|
+
return 0
|
|
236
|
+
fi
|
|
237
|
+
|
|
238
|
+
local package_name
|
|
239
|
+
local publish_dir
|
|
240
|
+
package_name="$(cd "$dir" && node -p "require('./package.json').name || ''")"
|
|
241
|
+
echo "Publishing $package_name from $dir"
|
|
242
|
+
|
|
243
|
+
publish_dir="$(mktemp -d)"
|
|
244
|
+
(
|
|
245
|
+
cd "$dir"
|
|
246
|
+
tar --exclude='./node_modules' -cf - .
|
|
247
|
+
) | (
|
|
248
|
+
cd "$publish_dir"
|
|
249
|
+
tar -xf -
|
|
250
|
+
)
|
|
251
|
+
node -e 'const fs=require("node:fs");const p=process.argv[1];const j=JSON.parse(fs.readFileSync(p,"utf8"));delete j.private;fs.writeFileSync(p,`${JSON.stringify(j,null,2)}\n`);' "$publish_dir/package.json"
|
|
252
|
+
(
|
|
253
|
+
cd "$publish_dir"
|
|
254
|
+
npm publish \
|
|
255
|
+
--registry "$VERDACCIO_REGISTRY" \
|
|
256
|
+
--access public \
|
|
257
|
+
--workspaces=false \
|
|
258
|
+
--userconfig "$npm_userconfig"
|
|
259
|
+
)
|
|
260
|
+
rm -rf "$publish_dir"
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
local running_jobs=0
|
|
264
|
+
local publish_failed=0
|
|
265
|
+
for dir in "${dirs[@]}"; do
|
|
266
|
+
publish_one_package "$dir" "$npm_userconfig" &
|
|
267
|
+
running_jobs=$((running_jobs + 1))
|
|
268
|
+
|
|
269
|
+
if (( running_jobs >= PUBLISH_CONCURRENCY )); then
|
|
270
|
+
if ! wait -n; then
|
|
271
|
+
publish_failed=1
|
|
272
|
+
fi
|
|
273
|
+
running_jobs=$((running_jobs - 1))
|
|
274
|
+
fi
|
|
275
|
+
done
|
|
276
|
+
|
|
277
|
+
while (( running_jobs > 0 )); do
|
|
278
|
+
if ! wait -n; then
|
|
279
|
+
publish_failed=1
|
|
280
|
+
fi
|
|
281
|
+
running_jobs=$((running_jobs - 1))
|
|
282
|
+
done
|
|
283
|
+
|
|
284
|
+
if (( publish_failed != 0 )); then
|
|
285
|
+
echo "One or more package publishes failed." >&2
|
|
286
|
+
exit 1
|
|
287
|
+
fi
|
|
288
|
+
|
|
289
|
+
rm -f "$npm_userconfig"
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
main() {
|
|
293
|
+
configure_source_dirs
|
|
294
|
+
|
|
295
|
+
local storage_dir
|
|
296
|
+
storage_dir="$(resolve_storage_dir)"
|
|
297
|
+
|
|
298
|
+
echo "Stopping Verdaccio..."
|
|
299
|
+
stop_verdaccio
|
|
300
|
+
|
|
301
|
+
echo "Clearing Verdaccio storage: $storage_dir"
|
|
302
|
+
rm -rf "$storage_dir"
|
|
303
|
+
mkdir -p "$storage_dir"
|
|
304
|
+
|
|
305
|
+
echo "Starting Verdaccio at $VERDACCIO_REGISTRY..."
|
|
306
|
+
start_verdaccio
|
|
307
|
+
|
|
308
|
+
echo "Publishing packages from $PACKAGES_DIR and tooling in $TOOLING_DIR..."
|
|
309
|
+
publish_packages
|
|
310
|
+
|
|
311
|
+
echo "Done. Verdaccio is running at $VERDACCIO_REGISTRY"
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
main "$@"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { surfaceRuntime } from "./surfaceRuntime.js";
|
|
3
|
+
|
|
4
|
+
const require = createRequire(import.meta.url);
|
|
5
|
+
|
|
6
|
+
function toPort(value, fallback = 3000) {
|
|
7
|
+
const parsed = Number.parseInt(String(value || "").trim(), 10);
|
|
8
|
+
if (Number.isInteger(parsed) && parsed > 0) {
|
|
9
|
+
return parsed;
|
|
10
|
+
}
|
|
11
|
+
return fallback;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let envLoaded = false;
|
|
15
|
+
|
|
16
|
+
function ensureRuntimeEnvLoaded() {
|
|
17
|
+
if (envLoaded) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const dotenvModule = require("dotenv");
|
|
22
|
+
const loadDotEnv = dotenvModule?.config;
|
|
23
|
+
if (typeof loadDotEnv === "function") {
|
|
24
|
+
loadDotEnv();
|
|
25
|
+
}
|
|
26
|
+
} catch {
|
|
27
|
+
// dotenv is optional in base-shell; bundles can add it when needed.
|
|
28
|
+
}
|
|
29
|
+
envLoaded = true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function resolveRuntimeEnv() {
|
|
33
|
+
ensureRuntimeEnvLoaded();
|
|
34
|
+
const serverSurface = surfaceRuntime.normalizeSurfaceMode(
|
|
35
|
+
process.env.JSKIT_SERVER_SURFACE || process.env.SERVER_SURFACE
|
|
36
|
+
);
|
|
37
|
+
return {
|
|
38
|
+
...process.env,
|
|
39
|
+
SERVER_SURFACE: serverSurface,
|
|
40
|
+
PORT: toPort(process.env.PORT, 3000),
|
|
41
|
+
HOST: String(process.env.HOST || "").trim() || "0.0.0.0"
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { resolveRuntimeEnv };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createSurfaceRuntime } from "@jskit-ai/kernel/shared/surface/runtime";
|
|
2
|
+
import { config } from "../../config/public.js";
|
|
3
|
+
|
|
4
|
+
const surfaceRuntime = createSurfaceRuntime({
|
|
5
|
+
allMode: config.surfaceModeAll,
|
|
6
|
+
surfaces: config.surfaceDefinitions,
|
|
7
|
+
defaultSurfaceId: config.surfaceDefaultId
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export { surfaceRuntime };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import Fastify from "fastify";
|
|
2
|
+
import { TypeBoxValidatorCompiler } from "@fastify/type-provider-typebox";
|
|
3
|
+
import { registerTypeBoxFormats } from "@jskit-ai/http-runtime/shared/validators/typeboxFormats";
|
|
4
|
+
import { resolveRuntimeEnv } from "./server/lib/runtimeEnv.js";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import {
|
|
7
|
+
registerSurfaceRequestConstraint,
|
|
8
|
+
resolveRuntimeProfileFromSurface,
|
|
9
|
+
tryCreateProviderRuntimeFromApp
|
|
10
|
+
} from "@jskit-ai/kernel/server/platform";
|
|
11
|
+
import { surfaceRuntime } from "./server/lib/surfaceRuntime.js";
|
|
12
|
+
|
|
13
|
+
async function createServer() {
|
|
14
|
+
const app = Fastify({ logger: true });
|
|
15
|
+
registerTypeBoxFormats();
|
|
16
|
+
app.setValidatorCompiler(TypeBoxValidatorCompiler);
|
|
17
|
+
|
|
18
|
+
app.get("/api/health", async () => {
|
|
19
|
+
return {
|
|
20
|
+
ok: true,
|
|
21
|
+
app: "__APP_NAME__"
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
const runtimeEnv = resolveRuntimeEnv();
|
|
25
|
+
const appRoot = path.resolve(process.cwd());
|
|
26
|
+
const runtime = await tryCreateProviderRuntimeFromApp({
|
|
27
|
+
appRoot,
|
|
28
|
+
profile: resolveRuntimeProfileFromSurface({
|
|
29
|
+
surfaceRuntime,
|
|
30
|
+
serverSurface: runtimeEnv.SERVER_SURFACE,
|
|
31
|
+
defaultProfile: "app"
|
|
32
|
+
}),
|
|
33
|
+
env: runtimeEnv,
|
|
34
|
+
logger: app.log,
|
|
35
|
+
fastify: app
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
registerSurfaceRequestConstraint({
|
|
39
|
+
fastify: app,
|
|
40
|
+
surfaceRuntime,
|
|
41
|
+
serverSurface: runtimeEnv.SERVER_SURFACE,
|
|
42
|
+
globalUiPaths: runtime?.globalUiPaths || []
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (runtime) {
|
|
46
|
+
app.log.info(
|
|
47
|
+
{
|
|
48
|
+
routeCount: runtime.routeCount,
|
|
49
|
+
surface: surfaceRuntime.normalizeSurfaceMode(runtimeEnv.SERVER_SURFACE),
|
|
50
|
+
providerPackages: runtime.providerPackageOrder,
|
|
51
|
+
packageOrder: runtime.packageOrder
|
|
52
|
+
},
|
|
53
|
+
"Registered JSKIT provider server runtime."
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return app;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function startServer(options = {}) {
|
|
61
|
+
const runtimeEnv = resolveRuntimeEnv();
|
|
62
|
+
const port = Number(options?.port) || runtimeEnv.PORT;
|
|
63
|
+
const host = String(options?.host || "").trim() || runtimeEnv.HOST;
|
|
64
|
+
const app = await createServer();
|
|
65
|
+
await app.listen({ port, host });
|
|
66
|
+
return app;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { createServer, startServer };
|