stack-service-base 0.0.99 → 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.
- checksums.yaml +4 -4
- data/lib/stack-service-base/command_init.rb +5 -3
- data/lib/stack-service-base/frontend_template/github/.github/workflows/main.yml +19 -0
- data/lib/stack-service-base/frontend_template/github/docker/docker-compose.yml +15 -0
- data/lib/stack-service-base/frontend_template/gitlab/.gitlab-ci.yml +48 -0
- data/lib/stack-service-base/frontend_template/gitlab/docker/Dockerfile.build +36 -0
- data/lib/stack-service-base/frontend_template/gitlab/docker/docker-compose.yml +15 -0
- data/lib/stack-service-base/frontend_template/gitlab/docker/local_build.sh +10 -0
- data/lib/stack-service-base/frontend_template/gitlab-c/.gitlab-ci.yml +24 -0
- data/lib/stack-service-base/frontend_template/gitlab-c/docker/Dockerfile.build +17 -0
- data/lib/stack-service-base/frontend_template/gitlab-c/docker/docker-compose.yml +15 -0
- data/lib/stack-service-base/frontend_template/gitlab-c/docker/local_build.sh +11 -0
- data/lib/stack-service-base/frontend_template/home/.editorconfig +12 -0
- data/lib/stack-service-base/frontend_template/home/.gitattributes +4 -0
- data/lib/stack-service-base/frontend_template/home/.gitignore +17 -0
- data/lib/stack-service-base/frontend_template/home/AGENTS.md +3 -0
- data/lib/stack-service-base/frontend_template/home/README.md +68 -0
- data/lib/stack-service-base/frontend_template/home/docker/.env +3 -0
- data/lib/stack-service-base/frontend_template/home/docker/frontend/15-runtime-settings.envsh +90 -0
- data/lib/stack-service-base/frontend_template/home/docker/frontend/40-path-prefix-settings.sh +30 -0
- data/lib/stack-service-base/frontend_template/home/docker/frontend/45-runtime-config-settings.sh +24 -0
- data/lib/stack-service-base/frontend_template/home/docker/frontend/Dockerfile +46 -0
- data/lib/stack-service-base/frontend_template/home/docker/frontend/nginx.conf.template +75 -0
- data/lib/stack-service-base/frontend_template/home/src/.dockerignore +9 -0
- data/lib/stack-service-base/frontend_template/home/src/.env.example +7 -0
- data/lib/stack-service-base/frontend_template/home/src/.version +1 -0
- data/lib/stack-service-base/frontend_template/home/src/app/main.ts +4 -0
- data/lib/stack-service-base/frontend_template/home/src/app/runtime-config.ts +22 -0
- data/lib/stack-service-base/frontend_template/home/src/app/runtime-config.types.ts +5 -0
- data/lib/stack-service-base/frontend_template/home/src/app/style.css +82 -0
- data/lib/stack-service-base/frontend_template/home/src/app/vite-env.d.ts +1 -0
- data/lib/stack-service-base/frontend_template/home/src/eslint.config.js +34 -0
- data/lib/stack-service-base/frontend_template/home/src/index.html +24 -0
- data/lib/stack-service-base/frontend_template/home/src/package-lock.json +2812 -0
- data/lib/stack-service-base/frontend_template/home/src/package.json +30 -0
- data/lib/stack-service-base/frontend_template/home/src/proxy.config.json +8 -0
- data/lib/stack-service-base/frontend_template/home/src/public/runtime-config.js +1 -0
- data/lib/stack-service-base/frontend_template/home/src/tests/build-proxy.test.ts +28 -0
- data/lib/stack-service-base/frontend_template/home/src/tests/javascript-support.test.js +23 -0
- data/lib/stack-service-base/frontend_template/home/src/tests/path-prefix.test.ts +17 -0
- data/lib/stack-service-base/frontend_template/home/src/tests/runtime-config.test.ts +22 -0
- data/lib/stack-service-base/frontend_template/home/src/tests/vite-config.test.ts +16 -0
- data/lib/stack-service-base/frontend_template/home/src/tools/vite/build-proxy.ts +62 -0
- data/lib/stack-service-base/frontend_template/home/src/tools/vite/path-prefix.ts +27 -0
- data/lib/stack-service-base/frontend_template/home/src/tools/vite/runtime-config-dev-plugin.ts +27 -0
- data/lib/stack-service-base/frontend_template/home/src/tools/vite/runtime-config.ts +10 -0
- data/lib/stack-service-base/frontend_template/home/src/tsconfig.json +27 -0
- data/lib/stack-service-base/frontend_template/home/src/vite.config.ts +40 -0
- data/lib/stack-service-base/version.rb +1 -1
- metadata +47 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "${service_name}",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": "^24.18.0"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "vite --host 0.0.0.0",
|
|
11
|
+
"build": "vite build",
|
|
12
|
+
"build:preview": "vite build --mode preview",
|
|
13
|
+
"preview": "npm run build:preview && vite preview --host 0.0.0.0 --mode preview",
|
|
14
|
+
"typecheck": "tsc --noEmit",
|
|
15
|
+
"lint": "eslint .",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"test:watch": "vitest",
|
|
18
|
+
"check": "npm run typecheck && npm run lint && npm run test && npm run build"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@eslint/js": "9.39.4",
|
|
22
|
+
"@types/node": "24.13.3",
|
|
23
|
+
"eslint": "9.39.4",
|
|
24
|
+
"globals": "15.15.0",
|
|
25
|
+
"typescript": "5.9.3",
|
|
26
|
+
"typescript-eslint": "8.59.3",
|
|
27
|
+
"vite": "8.1.5",
|
|
28
|
+
"vitest": "4.1.10"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
window.__APP_CONFIG__ = {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { buildProxy } from '../tools/vite/build-proxy';
|
|
3
|
+
|
|
4
|
+
const rules = {
|
|
5
|
+
'/api': {
|
|
6
|
+
targetEnv: 'BACKEND_URL',
|
|
7
|
+
secure: true,
|
|
8
|
+
changeOrigin: true,
|
|
9
|
+
ws: true
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
describe('development proxy', () => {
|
|
14
|
+
it('builds root and prefixed routes for the configured backend', () => {
|
|
15
|
+
const proxy = buildProxy(
|
|
16
|
+
{ PATH_PREFIX: '/portal', BACKEND_URL: 'https://api.example.com' },
|
|
17
|
+
rules
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
expect(proxy['/api']?.target).toBe('https://api.example.com');
|
|
21
|
+
expect(proxy['/portal/api']?.target).toBe('https://api.example.com');
|
|
22
|
+
expect(proxy['/portal/api']?.rewrite?.('/portal/api/status')).toBe('/api/status');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('does not create routes when the backend is not configured', () => {
|
|
26
|
+
expect(buildProxy({}, rules)).toEqual({});
|
|
27
|
+
});
|
|
28
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ESLint } from 'eslint';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
import { normalizePathPrefix } from '../tools/vite/path-prefix';
|
|
6
|
+
|
|
7
|
+
const projectRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
8
|
+
|
|
9
|
+
describe('JavaScript support', () => {
|
|
10
|
+
it('allows JavaScript modules to import TypeScript modules', () => {
|
|
11
|
+
expect(normalizePathPrefix('/team/ui/')).toBe('/team/ui');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('lints application JavaScript with browser globals', async () => {
|
|
15
|
+
const eslint = new ESLint({ cwd: projectRoot });
|
|
16
|
+
const [result] = await eslint.lintText(
|
|
17
|
+
'document.body.dataset.path = window.location.pathname;',
|
|
18
|
+
{ filePath: resolve(projectRoot, 'app/javascript-support.js') }
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
expect(result.messages).toEqual([]);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { normalizePathPrefix, pathPrefixBase } from '../tools/vite/path-prefix';
|
|
3
|
+
|
|
4
|
+
describe('path prefix', () => {
|
|
5
|
+
it('normalizes empty and nested prefixes', () => {
|
|
6
|
+
expect(normalizePathPrefix(undefined)).toBe('');
|
|
7
|
+
expect(normalizePathPrefix(' /team/ui/ ')).toBe('/team/ui');
|
|
8
|
+
expect(pathPrefixBase('/team/ui')).toBe('/team/ui/');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it.each(['/api', '/assets', '/healthcheck', '/team//ui', '/../admin', '/admin?debug=true'])(
|
|
12
|
+
'rejects an unsafe or runtime-reserved prefix: %s',
|
|
13
|
+
(pathPrefix) => {
|
|
14
|
+
expect(() => normalizePathPrefix(pathPrefix)).toThrow();
|
|
15
|
+
}
|
|
16
|
+
);
|
|
17
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { buildRuntimeConfigFromEnv } from '../tools/vite/runtime-config';
|
|
3
|
+
|
|
4
|
+
describe('runtime config', () => {
|
|
5
|
+
it('exposes only the documented browser-visible values', () => {
|
|
6
|
+
const runtimeConfig = buildRuntimeConfigFromEnv({
|
|
7
|
+
PATH_PREFIX: ' /team/ui/ ',
|
|
8
|
+
API_BASE_URL: ' /team/ui/api ',
|
|
9
|
+
LOG_LEVEL: ' debug ',
|
|
10
|
+
BACKEND_URL: 'https://internal-api.example.com',
|
|
11
|
+
AUTH_PASS: 'must-not-be-public'
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
expect(runtimeConfig).toEqual({
|
|
15
|
+
PATH_PREFIX: '/team/ui',
|
|
16
|
+
API_BASE_URL: '/team/ui/api',
|
|
17
|
+
LOG_LEVEL: 'debug'
|
|
18
|
+
});
|
|
19
|
+
expect(JSON.stringify(runtimeConfig)).not.toContain('internal-api');
|
|
20
|
+
expect(JSON.stringify(runtimeConfig)).not.toContain('must-not-be-public');
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { buildBase } from '../vite.config';
|
|
3
|
+
|
|
4
|
+
describe('buildBase', () => {
|
|
5
|
+
it('keeps the runtime placeholder in a container build', () => {
|
|
6
|
+
expect(buildBase('build', 'production', '/team/ui')).toBe('/__PATH_PREFIX__/');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('uses the configured prefix in a local production preview', () => {
|
|
10
|
+
expect(buildBase('build', 'preview', '/team/ui')).toBe('/team/ui/');
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('uses the configured prefix in development', () => {
|
|
14
|
+
expect(buildBase('serve', 'development', '/team/ui')).toBe('/team/ui/');
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { ProxyOptions } from 'vite';
|
|
2
|
+
import { normalizePathPrefix } from './path-prefix';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_PROXY_OPTIONS: ProxyOptions = {
|
|
5
|
+
cookieDomainRewrite: '',
|
|
6
|
+
secure: true,
|
|
7
|
+
changeOrigin: true
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type ProxyRuleConfig = {
|
|
11
|
+
targetEnv: string;
|
|
12
|
+
secure?: boolean;
|
|
13
|
+
changeOrigin?: boolean;
|
|
14
|
+
ws?: boolean;
|
|
15
|
+
pathRewrite?: Record<string, string>;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export function buildProxy(
|
|
19
|
+
env: Record<string, string>,
|
|
20
|
+
rules: Record<string, ProxyRuleConfig>
|
|
21
|
+
): Record<string, ProxyOptions> {
|
|
22
|
+
const proxy: Record<string, ProxyOptions> = {};
|
|
23
|
+
const pathPrefix = normalizePathPrefix(env.PATH_PREFIX);
|
|
24
|
+
|
|
25
|
+
for (const [context, rule] of Object.entries(rules)) {
|
|
26
|
+
const target = env[rule.targetEnv];
|
|
27
|
+
if (!target) continue;
|
|
28
|
+
|
|
29
|
+
proxy[context] = createProxyOptions(target, rule);
|
|
30
|
+
if (pathPrefix) proxy[`${pathPrefix}${context}`] = createProxyOptions(target, rule, pathPrefix);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return proxy;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function createProxyOptions(target: string, rule: ProxyRuleConfig, pathPrefix = ''): ProxyOptions {
|
|
37
|
+
const { pathRewrite, targetEnv: _targetEnv, ...overrides } = rule;
|
|
38
|
+
const shouldRewrite = Boolean(pathPrefix || pathRewrite);
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
target,
|
|
42
|
+
...DEFAULT_PROXY_OPTIONS,
|
|
43
|
+
...overrides,
|
|
44
|
+
...(shouldRewrite ? { rewrite: (path: string) => rewritePath(stripPathPrefix(path, pathPrefix), pathRewrite) } : {})
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function stripPathPrefix(path: string, pathPrefix: string): string {
|
|
49
|
+
if (!pathPrefix || !path.startsWith(`${pathPrefix}/`)) return path;
|
|
50
|
+
return path.slice(pathPrefix.length) || '/';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function rewritePath(path: string, pathRewrite?: Record<string, string>): string {
|
|
54
|
+
if (!pathRewrite) return path;
|
|
55
|
+
|
|
56
|
+
for (const [from, to] of Object.entries(pathRewrite)) {
|
|
57
|
+
const rewrittenPath = path.replace(new RegExp(from), to);
|
|
58
|
+
if (rewrittenPath !== path) return rewrittenPath;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return path;
|
|
62
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const PATH_PREFIX_PATTERN = /^[A-Za-z0-9_/-]+$/u;
|
|
2
|
+
const RESERVED_PATH_PREFIXES = new Set(['/api', '/assets', '/healthcheck']);
|
|
3
|
+
|
|
4
|
+
export function normalizePathPrefix(value: string | undefined): string {
|
|
5
|
+
const normalized = value?.trim().replace(/^\/+|\/+$/gu, '') ?? '';
|
|
6
|
+
|
|
7
|
+
if (!normalized) {
|
|
8
|
+
return '';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (!PATH_PREFIX_PATTERN.test(normalized) || normalized.includes('//') || normalized.split('/').includes('..')) {
|
|
12
|
+
throw new Error(`Invalid PATH_PREFIX: ${value}`);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const pathPrefix = `/${normalized}`;
|
|
16
|
+
|
|
17
|
+
if (RESERVED_PATH_PREFIXES.has(pathPrefix)) {
|
|
18
|
+
throw new Error(`PATH_PREFIX is reserved by the service runtime: ${pathPrefix}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return pathPrefix;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function pathPrefixBase(value: string | undefined): string {
|
|
25
|
+
const pathPrefix = normalizePathPrefix(value);
|
|
26
|
+
return pathPrefix ? `${pathPrefix}/` : '/';
|
|
27
|
+
}
|
data/lib/stack-service-base/frontend_template/home/src/tools/vite/runtime-config-dev-plugin.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
import { buildRuntimeConfigFromEnv } from './runtime-config';
|
|
3
|
+
import { normalizePathPrefix } from './path-prefix';
|
|
4
|
+
|
|
5
|
+
export function runtimeConfigDevPlugin(env: Record<string, string>): Plugin {
|
|
6
|
+
const pathPrefix = normalizePathPrefix(env.PATH_PREFIX);
|
|
7
|
+
const runtimeConfigPath = `${pathPrefix}/runtime-config.js`;
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
name: 'runtime-config-dev',
|
|
11
|
+
configureServer(server) {
|
|
12
|
+
server.middlewares.use((request, response, next) => {
|
|
13
|
+
const requestPath = request.url?.split('?', 1)[0];
|
|
14
|
+
|
|
15
|
+
if (requestPath !== runtimeConfigPath) {
|
|
16
|
+
next();
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const runtimeConfig = buildRuntimeConfigFromEnv(env);
|
|
21
|
+
response.setHeader('Content-Type', 'application/javascript; charset=utf-8');
|
|
22
|
+
response.setHeader('Cache-Control', 'no-store');
|
|
23
|
+
response.end(`window.__APP_CONFIG__ = ${JSON.stringify(runtimeConfig)};`);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RuntimeConfig } from '../../app/runtime-config.types';
|
|
2
|
+
import { normalizePathPrefix } from './path-prefix';
|
|
3
|
+
|
|
4
|
+
export function buildRuntimeConfigFromEnv(env: Record<string, string>): RuntimeConfig {
|
|
5
|
+
return {
|
|
6
|
+
PATH_PREFIX: normalizePathPrefix(env.PATH_PREFIX),
|
|
7
|
+
API_BASE_URL: env.API_BASE_URL?.trim() ?? '',
|
|
8
|
+
LOG_LEVEL: env.LOG_LEVEL?.trim() || 'info'
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noUnusedLocals": true,
|
|
9
|
+
"noUnusedParameters": true,
|
|
10
|
+
"noImplicitAny": true,
|
|
11
|
+
"useDefineForClassFields": false,
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
"allowJs": true,
|
|
15
|
+
"checkJs": false,
|
|
16
|
+
"noEmit": true
|
|
17
|
+
},
|
|
18
|
+
"include": [
|
|
19
|
+
"app/**/*.js",
|
|
20
|
+
"app/**/*.ts",
|
|
21
|
+
"tests/**/*.js",
|
|
22
|
+
"tests/**/*.ts",
|
|
23
|
+
"tools/**/*.js",
|
|
24
|
+
"tools/**/*.ts"
|
|
25
|
+
],
|
|
26
|
+
"exclude": ["node_modules", "dist"]
|
|
27
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { defineConfig, loadEnv } from 'vite';
|
|
2
|
+
import proxyRules from './proxy.config.json';
|
|
3
|
+
import { buildProxy } from './tools/vite/build-proxy';
|
|
4
|
+
import { runtimeConfigDevPlugin } from './tools/vite/runtime-config-dev-plugin';
|
|
5
|
+
import { pathPrefixBase } from './tools/vite/path-prefix';
|
|
6
|
+
|
|
7
|
+
const DEPLOY_PATH_PLACEHOLDER = '/__PATH_PREFIX__/';
|
|
8
|
+
|
|
9
|
+
export function buildBase(
|
|
10
|
+
command: 'build' | 'serve',
|
|
11
|
+
mode: string,
|
|
12
|
+
pathPrefix: string | undefined
|
|
13
|
+
): string {
|
|
14
|
+
const isContainerBuild = command === 'build' && mode !== 'preview';
|
|
15
|
+
|
|
16
|
+
return isContainerBuild ? DEPLOY_PATH_PLACEHOLDER : pathPrefixBase(pathPrefix);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default defineConfig(({ command, mode }) => {
|
|
20
|
+
const env = loadEnv(mode, '.', '');
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
base: buildBase(command, mode, env.PATH_PREFIX),
|
|
24
|
+
plugins: [runtimeConfigDevPlugin(env)],
|
|
25
|
+
build: {
|
|
26
|
+
outDir: 'dist',
|
|
27
|
+
emptyOutDir: true
|
|
28
|
+
},
|
|
29
|
+
server: {
|
|
30
|
+
port: 3000,
|
|
31
|
+
strictPort: true,
|
|
32
|
+
open: false,
|
|
33
|
+
proxy: buildProxy(env, proxyRules)
|
|
34
|
+
},
|
|
35
|
+
preview: {
|
|
36
|
+
port: 3000,
|
|
37
|
+
strictPort: true
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
});
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stack-service-base
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.100
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Artyom B
|
|
@@ -418,6 +418,52 @@ files:
|
|
|
418
418
|
- lib/stack-service-base/env_fetch.rb
|
|
419
419
|
- lib/stack-service-base/examples/mcp_config.ru
|
|
420
420
|
- lib/stack-service-base/fiber_pool.rb
|
|
421
|
+
- lib/stack-service-base/frontend_template/github/.github/workflows/main.yml
|
|
422
|
+
- lib/stack-service-base/frontend_template/github/docker/docker-compose.yml
|
|
423
|
+
- lib/stack-service-base/frontend_template/gitlab-c/.gitlab-ci.yml
|
|
424
|
+
- lib/stack-service-base/frontend_template/gitlab-c/docker/Dockerfile.build
|
|
425
|
+
- lib/stack-service-base/frontend_template/gitlab-c/docker/docker-compose.yml
|
|
426
|
+
- lib/stack-service-base/frontend_template/gitlab-c/docker/local_build.sh
|
|
427
|
+
- lib/stack-service-base/frontend_template/gitlab/.gitlab-ci.yml
|
|
428
|
+
- lib/stack-service-base/frontend_template/gitlab/docker/Dockerfile.build
|
|
429
|
+
- lib/stack-service-base/frontend_template/gitlab/docker/docker-compose.yml
|
|
430
|
+
- lib/stack-service-base/frontend_template/gitlab/docker/local_build.sh
|
|
431
|
+
- lib/stack-service-base/frontend_template/home/.editorconfig
|
|
432
|
+
- lib/stack-service-base/frontend_template/home/.gitattributes
|
|
433
|
+
- lib/stack-service-base/frontend_template/home/.gitignore
|
|
434
|
+
- lib/stack-service-base/frontend_template/home/AGENTS.md
|
|
435
|
+
- lib/stack-service-base/frontend_template/home/README.md
|
|
436
|
+
- lib/stack-service-base/frontend_template/home/docker/.env
|
|
437
|
+
- lib/stack-service-base/frontend_template/home/docker/frontend/15-runtime-settings.envsh
|
|
438
|
+
- lib/stack-service-base/frontend_template/home/docker/frontend/40-path-prefix-settings.sh
|
|
439
|
+
- lib/stack-service-base/frontend_template/home/docker/frontend/45-runtime-config-settings.sh
|
|
440
|
+
- lib/stack-service-base/frontend_template/home/docker/frontend/Dockerfile
|
|
441
|
+
- lib/stack-service-base/frontend_template/home/docker/frontend/nginx.conf.template
|
|
442
|
+
- lib/stack-service-base/frontend_template/home/src/.dockerignore
|
|
443
|
+
- lib/stack-service-base/frontend_template/home/src/.env.example
|
|
444
|
+
- lib/stack-service-base/frontend_template/home/src/.version
|
|
445
|
+
- lib/stack-service-base/frontend_template/home/src/app/main.ts
|
|
446
|
+
- lib/stack-service-base/frontend_template/home/src/app/runtime-config.ts
|
|
447
|
+
- lib/stack-service-base/frontend_template/home/src/app/runtime-config.types.ts
|
|
448
|
+
- lib/stack-service-base/frontend_template/home/src/app/style.css
|
|
449
|
+
- lib/stack-service-base/frontend_template/home/src/app/vite-env.d.ts
|
|
450
|
+
- lib/stack-service-base/frontend_template/home/src/eslint.config.js
|
|
451
|
+
- lib/stack-service-base/frontend_template/home/src/index.html
|
|
452
|
+
- lib/stack-service-base/frontend_template/home/src/package-lock.json
|
|
453
|
+
- lib/stack-service-base/frontend_template/home/src/package.json
|
|
454
|
+
- lib/stack-service-base/frontend_template/home/src/proxy.config.json
|
|
455
|
+
- lib/stack-service-base/frontend_template/home/src/public/runtime-config.js
|
|
456
|
+
- lib/stack-service-base/frontend_template/home/src/tests/build-proxy.test.ts
|
|
457
|
+
- lib/stack-service-base/frontend_template/home/src/tests/javascript-support.test.js
|
|
458
|
+
- lib/stack-service-base/frontend_template/home/src/tests/path-prefix.test.ts
|
|
459
|
+
- lib/stack-service-base/frontend_template/home/src/tests/runtime-config.test.ts
|
|
460
|
+
- lib/stack-service-base/frontend_template/home/src/tests/vite-config.test.ts
|
|
461
|
+
- lib/stack-service-base/frontend_template/home/src/tools/vite/build-proxy.ts
|
|
462
|
+
- lib/stack-service-base/frontend_template/home/src/tools/vite/path-prefix.ts
|
|
463
|
+
- lib/stack-service-base/frontend_template/home/src/tools/vite/runtime-config-dev-plugin.ts
|
|
464
|
+
- lib/stack-service-base/frontend_template/home/src/tools/vite/runtime-config.ts
|
|
465
|
+
- lib/stack-service-base/frontend_template/home/src/tsconfig.json
|
|
466
|
+
- lib/stack-service-base/frontend_template/home/src/vite.config.ts
|
|
421
467
|
- lib/stack-service-base/logging.rb
|
|
422
468
|
- lib/stack-service-base/mcp/mcp_helper.rb
|
|
423
469
|
- lib/stack-service-base/mcp/mcp_processor.rb
|