@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.
Files changed (53) hide show
  1. package/bin/jskit-create-app.js +5 -0
  2. package/package.json +2 -3
  3. package/src/client/index.js +1 -0
  4. package/src/index.js +1 -0
  5. package/src/server/cliEntrypoint.js +25 -0
  6. package/src/server/index.js +632 -0
  7. package/templates/base-shell/.jskit/lock.json +31 -0
  8. package/templates/base-shell/Procfile +1 -0
  9. package/templates/base-shell/README.md +43 -0
  10. package/templates/base-shell/app.scripts.config.mjs +3 -0
  11. package/templates/base-shell/bin/server.js +8 -0
  12. package/templates/base-shell/config/public.js +30 -0
  13. package/templates/base-shell/config/server.js +1 -0
  14. package/templates/base-shell/config/surfaceAccessPolicies.js +12 -0
  15. package/templates/base-shell/eslint.config.mjs +10 -0
  16. package/templates/base-shell/favicon.svg +7 -0
  17. package/templates/base-shell/gitignore +9 -0
  18. package/templates/base-shell/index.html +13 -0
  19. package/templates/base-shell/jsconfig.json +8 -0
  20. package/templates/base-shell/package.json +64 -0
  21. package/templates/base-shell/packages/main/package.descriptor.mjs +55 -0
  22. package/templates/base-shell/packages/main/package.json +12 -0
  23. package/templates/base-shell/packages/main/src/client/index.js +13 -0
  24. package/templates/base-shell/packages/main/src/client/providers/MainClientProvider.js +33 -0
  25. package/templates/base-shell/packages/main/src/server/controllers/index.js +9 -0
  26. package/templates/base-shell/packages/main/src/server/index.js +1 -0
  27. package/templates/base-shell/packages/main/src/server/providers/MainServiceProvider.js +22 -0
  28. package/templates/base-shell/packages/main/src/server/routes/index.js +9 -0
  29. package/templates/base-shell/packages/main/src/server/services/index.js +9 -0
  30. package/templates/base-shell/packages/main/src/server/support/loadAppConfig.js +55 -0
  31. package/templates/base-shell/packages/main/src/shared/index.js +8 -0
  32. package/templates/base-shell/packages/main/src/shared/schemas/index.js +20 -0
  33. package/templates/base-shell/scripts/dev-bootstrap-jskit.sh +110 -0
  34. package/templates/base-shell/scripts/just_run_verde +37 -0
  35. package/templates/base-shell/scripts/link-local-jskit-packages.sh +90 -0
  36. package/templates/base-shell/scripts/update-jskit-packages.sh +73 -0
  37. package/templates/base-shell/scripts/verdaccio/config.yaml +26 -0
  38. package/templates/base-shell/scripts/verdaccio-reset-and-publish-packages.sh +314 -0
  39. package/templates/base-shell/server/lib/runtimeEnv.js +45 -0
  40. package/templates/base-shell/server/lib/surfaceRuntime.js +10 -0
  41. package/templates/base-shell/server.js +69 -0
  42. package/templates/base-shell/src/App.vue +13 -0
  43. package/templates/base-shell/src/main.js +90 -0
  44. package/templates/base-shell/src/pages/console/index.vue +12 -0
  45. package/templates/base-shell/src/pages/console.vue +13 -0
  46. package/templates/base-shell/src/pages/home/index.vue +12 -0
  47. package/templates/base-shell/src/pages/home.vue +13 -0
  48. package/templates/base-shell/src/views/NotFound.vue +13 -0
  49. package/templates/base-shell/tests/client/smoke.vitest.js +7 -0
  50. package/templates/base-shell/tests/server/minimalShell.validator.test.js +134 -0
  51. package/templates/base-shell/tests/server/smoke.test.js +16 -0
  52. package/templates/base-shell/vite.config.mjs +64 -0
  53. 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 };
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <v-app>
3
+ <v-main>
4
+ <v-container class="py-10 py-md-14">
5
+ <v-row justify="center">
6
+ <v-col cols="12" sm="11" md="10" lg="8" xl="7">
7
+ <RouterView />
8
+ </v-col>
9
+ </v-row>
10
+ </v-container>
11
+ </v-main>
12
+ </v-app>
13
+ </template>