stack-service-base 0.0.98 → 0.0.100

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/lib/stack-service-base/command_init.rb +8 -6
  3. data/lib/stack-service-base/examples/mcp_config.ru +16 -16
  4. data/lib/stack-service-base/frontend_template/github/.github/workflows/main.yml +19 -0
  5. data/lib/stack-service-base/frontend_template/github/docker/docker-compose.yml +15 -0
  6. data/lib/stack-service-base/frontend_template/gitlab/.gitlab-ci.yml +48 -0
  7. data/lib/stack-service-base/frontend_template/gitlab/docker/Dockerfile.build +36 -0
  8. data/lib/stack-service-base/frontend_template/gitlab/docker/docker-compose.yml +15 -0
  9. data/lib/stack-service-base/frontend_template/gitlab/docker/local_build.sh +10 -0
  10. data/lib/stack-service-base/frontend_template/gitlab-c/.gitlab-ci.yml +24 -0
  11. data/lib/stack-service-base/frontend_template/gitlab-c/docker/Dockerfile.build +17 -0
  12. data/lib/stack-service-base/frontend_template/gitlab-c/docker/docker-compose.yml +15 -0
  13. data/lib/stack-service-base/frontend_template/gitlab-c/docker/local_build.sh +11 -0
  14. data/lib/stack-service-base/frontend_template/home/.editorconfig +12 -0
  15. data/lib/stack-service-base/frontend_template/home/.gitattributes +4 -0
  16. data/lib/stack-service-base/frontend_template/home/.gitignore +17 -0
  17. data/lib/stack-service-base/frontend_template/home/AGENTS.md +3 -0
  18. data/lib/stack-service-base/frontend_template/home/README.md +68 -0
  19. data/lib/stack-service-base/frontend_template/home/docker/.env +3 -0
  20. data/lib/stack-service-base/frontend_template/home/docker/frontend/15-runtime-settings.envsh +90 -0
  21. data/lib/stack-service-base/frontend_template/home/docker/frontend/40-path-prefix-settings.sh +30 -0
  22. data/lib/stack-service-base/frontend_template/home/docker/frontend/45-runtime-config-settings.sh +24 -0
  23. data/lib/stack-service-base/frontend_template/home/docker/frontend/Dockerfile +46 -0
  24. data/lib/stack-service-base/frontend_template/home/docker/frontend/nginx.conf.template +75 -0
  25. data/lib/stack-service-base/frontend_template/home/src/.dockerignore +9 -0
  26. data/lib/stack-service-base/frontend_template/home/src/.env.example +7 -0
  27. data/lib/stack-service-base/frontend_template/home/src/.version +1 -0
  28. data/lib/stack-service-base/frontend_template/home/src/app/main.ts +4 -0
  29. data/lib/stack-service-base/frontend_template/home/src/app/runtime-config.ts +22 -0
  30. data/lib/stack-service-base/frontend_template/home/src/app/runtime-config.types.ts +5 -0
  31. data/lib/stack-service-base/frontend_template/home/src/app/style.css +82 -0
  32. data/lib/stack-service-base/frontend_template/home/src/app/vite-env.d.ts +1 -0
  33. data/lib/stack-service-base/frontend_template/home/src/eslint.config.js +34 -0
  34. data/lib/stack-service-base/frontend_template/home/src/index.html +24 -0
  35. data/lib/stack-service-base/frontend_template/home/src/package-lock.json +2812 -0
  36. data/lib/stack-service-base/frontend_template/home/src/package.json +30 -0
  37. data/lib/stack-service-base/frontend_template/home/src/proxy.config.json +8 -0
  38. data/lib/stack-service-base/frontend_template/home/src/public/runtime-config.js +1 -0
  39. data/lib/stack-service-base/frontend_template/home/src/tests/build-proxy.test.ts +28 -0
  40. data/lib/stack-service-base/frontend_template/home/src/tests/javascript-support.test.js +23 -0
  41. data/lib/stack-service-base/frontend_template/home/src/tests/path-prefix.test.ts +17 -0
  42. data/lib/stack-service-base/frontend_template/home/src/tests/runtime-config.test.ts +22 -0
  43. data/lib/stack-service-base/frontend_template/home/src/tests/vite-config.test.ts +16 -0
  44. data/lib/stack-service-base/frontend_template/home/src/tools/vite/build-proxy.ts +62 -0
  45. data/lib/stack-service-base/frontend_template/home/src/tools/vite/path-prefix.ts +27 -0
  46. data/lib/stack-service-base/frontend_template/home/src/tools/vite/runtime-config-dev-plugin.ts +27 -0
  47. data/lib/stack-service-base/frontend_template/home/src/tools/vite/runtime-config.ts +10 -0
  48. data/lib/stack-service-base/frontend_template/home/src/tsconfig.json +27 -0
  49. data/lib/stack-service-base/frontend_template/home/src/vite.config.ts +40 -0
  50. data/lib/stack-service-base/mcp/mcp_helper.rb +1 -1
  51. data/lib/stack-service-base/mcp/mcp_processor.rb +22 -22
  52. data/lib/stack-service-base/mcp/mcp_tool_registry.rb +1 -1
  53. data/lib/stack-service-base/project_template/gitlab/.gitlab-ci.yml +42 -11
  54. data/lib/stack-service-base/project_template/gitlab/docker/Dockerfile.build +36 -0
  55. data/lib/stack-service-base/project_template/gitlab/docker/docker-compose.yml +1 -1
  56. data/lib/stack-service-base/project_template/gitlab/docker/local_build.sh +10 -0
  57. data/lib/stack-service-base/version.rb +1 -1
  58. metadata +49 -1
@@ -0,0 +1,46 @@
1
+ FROM node:24.18-alpine AS base
2
+
3
+ WORKDIR /app
4
+
5
+ COPY package.json package-lock.json ./
6
+ RUN npm ci
7
+
8
+ COPY . .
9
+
10
+ FROM base AS tests
11
+ CMD ["npm", "run", "check"]
12
+
13
+ FROM base AS build
14
+
15
+ RUN npm run build
16
+
17
+ FROM nginxinc/nginx-unprivileged:1.28.1-alpine AS deploy
18
+
19
+ USER root
20
+ RUN apk add --no-cache ca-certificates curl jq \
21
+ && rm -rf /usr/share/nginx/html/*
22
+
23
+ ENV PORT=8080 \
24
+ NODE_ENV=production \
25
+ PATH_PREFIX= \
26
+ API_BASE_URL= \
27
+ LOG_LEVEL=info \
28
+ BACKEND_URL=http://127.0.0.1:65535
29
+
30
+ COPY --from=docker /frontend/nginx.conf.template /etc/nginx/templates/default.conf.template
31
+ COPY --chmod=755 --from=docker /frontend/15-runtime-settings.envsh /docker-entrypoint.d/
32
+ COPY --chmod=755 --from=docker /frontend/40-path-prefix-settings.sh /docker-entrypoint.d/
33
+ COPY --chmod=755 --from=docker /frontend/45-runtime-config-settings.sh /docker-entrypoint.d/
34
+ RUN rm -f /etc/nginx/conf.d/default.conf \
35
+ && chown -R 101:101 /etc/nginx/conf.d /usr/share/nginx/html
36
+
37
+ COPY --chown=101:101 --from=build /app/dist /usr/share/nginx/html
38
+
39
+ USER 101:101
40
+
41
+ HEALTHCHECK --interval=30s --timeout=5s --retries=3 --start-period=10s \
42
+ CMD curl -fsS "http://127.0.0.1:${PORT}/healthcheck" || exit 1
43
+
44
+ EXPOSE 8080
45
+
46
+ CMD ["nginx", "-g", "daemon off;"]
@@ -0,0 +1,75 @@
1
+ server {
2
+ listen ${PORT};
3
+ server_name _;
4
+
5
+ resolver ${DNS_RESOLVER} valid=30s ipv6=off;
6
+ resolver_timeout 10s;
7
+
8
+ root /usr/share/nginx/html;
9
+ index index.html;
10
+
11
+ gzip on;
12
+ gzip_min_length 1024;
13
+ gzip_types text/plain text/css application/javascript application/json image/svg+xml;
14
+
15
+ add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; connect-src 'self'; font-src 'self' data:; form-action 'self'; frame-ancestors 'self'; img-src 'self' data: blob:; object-src 'none'; script-src 'self'; style-src 'self'; worker-src 'self' blob:" always;
16
+ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
17
+ add_header X-Content-Type-Options "nosniff" always;
18
+ add_header X-Frame-Options "SAMEORIGIN" always;
19
+
20
+ location = /healthcheck {
21
+ access_log off;
22
+ default_type application/json;
23
+ return 200 '{"Status":"Healthy"}';
24
+ }
25
+
26
+ location ^~ /api {
27
+ set $backend_origin "${BACKEND_PROTO}://${BACKEND_HOST}:${BACKEND_PORT}";
28
+
29
+ proxy_pass $backend_origin;
30
+ proxy_http_version 1.1;
31
+ proxy_set_header Connection "upgrade";
32
+ proxy_set_header Host ${BACKEND_HOST};
33
+ proxy_set_header Upgrade $http_upgrade;
34
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
35
+ proxy_set_header X-Forwarded-Host $host;
36
+ proxy_set_header X-Forwarded-Proto $scheme;
37
+ proxy_ssl_name ${BACKEND_HOST};
38
+ proxy_ssl_server_name on;
39
+ proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
40
+ proxy_ssl_verify on;
41
+ proxy_cookie_domain ~.* $host;
42
+ proxy_cookie_path / /;
43
+ }
44
+
45
+ location = /runtime-config.js {
46
+ expires -1;
47
+ add_header Cache-Control "no-store" always;
48
+ add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; connect-src 'self'; font-src 'self' data:; form-action 'self'; frame-ancestors 'self'; img-src 'self' data: blob:; object-src 'none'; script-src 'self'; style-src 'self'; worker-src 'self' blob:" always;
49
+ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
50
+ add_header X-Content-Type-Options "nosniff" always;
51
+ add_header X-Frame-Options "SAMEORIGIN" always;
52
+ try_files $uri =404;
53
+ }
54
+
55
+ location = /index.html {
56
+ expires -1;
57
+ add_header Cache-Control "no-store" always;
58
+ add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; connect-src 'self'; font-src 'self' data:; form-action 'self'; frame-ancestors 'self'; img-src 'self' data: blob:; object-src 'none'; script-src 'self'; style-src 'self'; worker-src 'self' blob:" always;
59
+ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
60
+ add_header X-Content-Type-Options "nosniff" always;
61
+ add_header X-Frame-Options "SAMEORIGIN" always;
62
+ try_files $uri =404;
63
+ }
64
+
65
+ location /assets/ {
66
+ expires 1y;
67
+ try_files $uri =404;
68
+ }
69
+
70
+ location / {
71
+ try_files $uri $uri/ /index.html;
72
+ }
73
+
74
+ ${PATH_PREFIX_RULE}
75
+ }
@@ -0,0 +1,9 @@
1
+ node_modules
2
+ dist
3
+ .env
4
+ .env.*
5
+ !.env.example
6
+ *.log
7
+ coverage
8
+ test-results
9
+ playwright-report
@@ -0,0 +1,7 @@
1
+ # Browser-visible runtime configuration.
2
+ PATH_PREFIX=
3
+ API_BASE_URL=
4
+ LOG_LEVEL=info
5
+
6
+ # Development proxy target. This value is not exposed to browser code.
7
+ BACKEND_URL=http://localhost:8080
@@ -0,0 +1,4 @@
1
+ import './style.css';
2
+
3
+ await import(/* @vite-ignore */ `${import.meta.env.BASE_URL}runtime-config.js`);
4
+ await import('./runtime-config');
@@ -0,0 +1,22 @@
1
+ import { normalizePathPrefix } from '../tools/vite/path-prefix';
2
+ import type { RuntimeConfig } from './runtime-config.types';
3
+
4
+ declare global {
5
+ interface Window {
6
+ __APP_CONFIG__?: RuntimeConfig;
7
+ }
8
+ }
9
+
10
+ const runtimeConfig = window.__APP_CONFIG__ ?? {};
11
+ const pathPrefix = normalizePathPrefix(runtimeConfig.PATH_PREFIX);
12
+
13
+ export const environment = Object.freeze({
14
+ serviceName: '${service_name}',
15
+ pathPrefix,
16
+ apiBaseUrl: runtimeConfig.API_BASE_URL?.trim() || joinPath(pathPrefix, 'api'),
17
+ logLevel: runtimeConfig.LOG_LEVEL?.trim() || 'info'
18
+ });
19
+
20
+ function joinPath(prefix: string, path: string): string {
21
+ return `${prefix}/${path}`.replace(/\/+/gu, '/');
22
+ }
@@ -0,0 +1,5 @@
1
+ export type RuntimeConfig = {
2
+ PATH_PREFIX?: string;
3
+ API_BASE_URL?: string;
4
+ LOG_LEVEL?: string;
5
+ };
@@ -0,0 +1,82 @@
1
+ :root {
2
+ --color-background: #f3f4f6;
3
+ --color-text: #1f2937;
4
+ --color-muted: #6b7280;
5
+ --color-running: #166534;
6
+ --color-running-indicator: #22c55e;
7
+ --space-1: 4px;
8
+ --space-2: 8px;
9
+ --space-4: 16px;
10
+ --space-6: 24px;
11
+ --space-8: 32px;
12
+
13
+ color: var(--color-text);
14
+ background: var(--color-background);
15
+ font-family:
16
+ Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
17
+ font-synthesis: none;
18
+ }
19
+
20
+ * {
21
+ box-sizing: border-box;
22
+ }
23
+
24
+ body {
25
+ display: grid;
26
+ min-width: 320px;
27
+ min-height: 100vh;
28
+ margin: 0;
29
+ place-items: center;
30
+ }
31
+
32
+ .page {
33
+ width: min(640px, calc(100% - var(--space-8)));
34
+ padding: var(--space-8) 0;
35
+ }
36
+
37
+ .page__header {
38
+ margin-bottom: var(--space-6);
39
+ }
40
+
41
+ h1,
42
+ p {
43
+ margin: 0;
44
+ }
45
+
46
+ h1 {
47
+ margin-top: var(--space-1);
48
+ font-size: clamp(28px, 5vw, 40px);
49
+ font-weight: 600;
50
+ letter-spacing: -0.025em;
51
+ }
52
+
53
+ .eyebrow {
54
+ color: var(--color-muted);
55
+ font-size: 12px;
56
+ font-weight: 600;
57
+ letter-spacing: 0.08em;
58
+ text-transform: uppercase;
59
+ }
60
+
61
+ .status {
62
+ display: inline-flex;
63
+ align-items: center;
64
+ gap: var(--space-2);
65
+ color: var(--color-running);
66
+ font-size: 14px;
67
+ font-weight: 600;
68
+ }
69
+
70
+ .status__indicator {
71
+ width: var(--space-2);
72
+ height: var(--space-2);
73
+ border-radius: 50%;
74
+ background: var(--color-running-indicator);
75
+ }
76
+
77
+ @media (max-width: 640px) {
78
+ .page {
79
+ width: calc(100% - var(--space-6));
80
+ padding: var(--space-6) 0;
81
+ }
82
+ }
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
@@ -0,0 +1,34 @@
1
+ import js from '@eslint/js';
2
+ import globals from 'globals';
3
+ import tseslint from 'typescript-eslint';
4
+
5
+ export default tseslint.config(
6
+ {
7
+ ignores: ['dist/**', 'node_modules/**']
8
+ },
9
+ js.configs.recommended,
10
+ ...tseslint.configs.recommended,
11
+ {
12
+ files: ['**/*.ts'],
13
+ rules: {
14
+ '@typescript-eslint/no-explicit-any': 'error',
15
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }]
16
+ }
17
+ },
18
+ {
19
+ files: ['app/**/*.{js,ts}', 'public/**/*.js'],
20
+ languageOptions: {
21
+ ecmaVersion: 2022,
22
+ sourceType: 'module',
23
+ globals: globals.browser
24
+ }
25
+ },
26
+ {
27
+ files: ['tests/**/*.{js,ts}', 'tools/**/*.{js,ts}', '*.config.{js,ts}'],
28
+ languageOptions: {
29
+ ecmaVersion: 2022,
30
+ sourceType: 'module',
31
+ globals: globals.node
32
+ }
33
+ }
34
+ );
@@ -0,0 +1,24 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="color-scheme" content="light" />
7
+ <title>${service_name}</title>
8
+ </head>
9
+ <body>
10
+ <main class="page">
11
+ <header class="page__header">
12
+ <p class="eyebrow">Frontend service</p>
13
+ <h1>${service_name}</h1>
14
+ </header>
15
+
16
+ <p class="status" role="status">
17
+ <span class="status__indicator" aria-hidden="true"></span>
18
+ Running
19
+ </p>
20
+ </main>
21
+
22
+ <script type="module" src="/app/main.ts"></script>
23
+ </body>
24
+ </html>