diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index fa6c5bc..ff0b4de 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -60,7 +60,7 @@ representative at an online or offline event. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at -[team@kottster.io](team@kottster.io). +[team@kottster.app](team@kottster.app). All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the diff --git a/README.md b/README.md index f07707d..878be45 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ See [CONTRIBUTING.md](https://github.com/kottster/kottster/blob/main/CONTRIBUTIN - 💬 [Join our Discord](https://discord.com/invite/Qce9uUqK98) - 📬 [Contact us](https://kottster.app/contact-us) -- ✉️ [team@kottster.io](mailto:team@kottster.io) +- ✉️ [team@kottster.app](mailto:team@kottster.app) ## License diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 39a8de6..ac6e9ff 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -55,7 +55,7 @@ export default defineConfig({ 'script', { src: '/docs/js/discord.js', - defer: 'true', + defer: 'true' } ], [ @@ -107,8 +107,6 @@ export default defineConfig({ ], ], - - sitemap: { hostname: 'https://kottster.app', }, diff --git a/packages/cli/cli/actions/buildServer.action.ts b/packages/cli/cli/actions/buildServer.action.ts index 9cd8927..a9cf842 100644 --- a/packages/cli/cli/actions/buildServer.action.ts +++ b/packages/cli/cli/actions/buildServer.action.ts @@ -4,13 +4,35 @@ import fs from 'fs/promises'; import { checkTsUsage } from '@kottster/common'; export async function buildServer(): Promise { - const projectDir = process.cwd(); const usingTsc = checkTsUsage(); - - // Find all api.server.js files in the app/pages directory - const filenameEnding = `.server.${usingTsc ? 'ts' : 'js'}`; + const projectDir = process.cwd(); const pagesDir = path.join(projectDir, 'app/pages'); - const apiFiles: string[] = []; + const dataSourcesDir = path.join(projectDir, 'app/_server/data-sources'); + + // Find all app/pages//page.json + const pageJsonFiles: string[] = []; + try { + const dirs = await fs.readdir(pagesDir, { withFileTypes: true }); + + for (const dir of dirs) { + if (dir.isDirectory()) { + const dirPath = path.join(pagesDir, dir.name); + const files = await fs.readdir(dirPath); + + for (const file of files) { + if (file === 'page.json') { + pageJsonFiles.push(path.join(dirPath, file)); + } + } + } + } + } catch (error) { + console.warn('Could not read pages directory:', error); + } + + // Find all app/pages//api.server.js or .ts files + const filenameEnding = `.server.${usingTsc ? 'ts' : 'js'}`; + const pageApiFiles: string[] = []; try { const dirs = await fs.readdir(pagesDir, { withFileTypes: true }); @@ -21,7 +43,7 @@ export async function buildServer(): Promise { for (const file of files) { if (file.endsWith(filenameEnding)) { - apiFiles.push(path.join(dirPath, file)); + pageApiFiles.push(path.join(dirPath, file)); } } } @@ -30,8 +52,26 @@ export async function buildServer(): Promise { console.warn('Could not read pages directory:', error); } - // Find all data source files in the app/_server/data-sources directory - const dataSourcesDir = path.join(projectDir, 'app/_server/data-sources'); + // Find all app/_server/data-sources//dataSource.json + const dataSourceJsonFiles: string[] = []; + try { + const dirs = await fs.readdir(dataSourcesDir, { withFileTypes: true }); + for (const dir of dirs) { + if (dir.isDirectory()) { + const dirPath = path.join(dataSourcesDir, dir.name); + const files = await fs.readdir(dirPath); + for (const file of files) { + if (file === 'dataSource.json') { + dataSourceJsonFiles.push(path.join(dirPath, file)); + } + } + } + } + } catch (error) { + console.warn('Could not read data sources directory:', error); + } + + // Find all app/_server/data-sources//index.js or .ts files const dataSourceFiles: string[] = []; try { const dirs = await fs.readdir(dataSourcesDir, { withFileTypes: true }); @@ -53,7 +93,7 @@ export async function buildServer(): Promise { const input = { server: `app/_server/server.${usingTsc ? 'ts' : 'js'}`, ...Object.fromEntries( - apiFiles.map(file => [ + pageApiFiles.map(file => [ file.replace(path.join(projectDir, 'app/'), '').replace(filenameEnding, ''), file ]) @@ -63,7 +103,7 @@ export async function buildServer(): Promise { file.replace(path.join(projectDir, 'app/_server/'), '').replace(`.${usingTsc ? 'ts' : 'js'}`, ''), file ]) - ) + ), }; try { @@ -86,7 +126,30 @@ export async function buildServer(): Promise { '@': '/app' } } - }) + }); + + // Copy app/pages//page.json files + for (const file of pageJsonFiles) { + const destPath = path.join( + projectDir, + 'dist/server', + path.relative(path.join(projectDir, 'app'), file) + ); + await fs.mkdir(path.dirname(destPath), { recursive: true }); + await fs.copyFile(file, destPath); + } + + // Copy app/_server/data-sources//dataSource.json files + for (const file of dataSourceJsonFiles) { + const destPath = path.join( + projectDir, + 'dist/server', + path.relative(path.join(projectDir, 'app/_server'), file) + ); + await fs.mkdir(path.dirname(destPath), { recursive: true }); + await fs.copyFile(file, destPath); + } + console.log('Build completed successfully!'); } catch (error) { console.error('Build failed:', error) diff --git a/packages/cli/cli/actions/startProjectDev.action.ts b/packages/cli/cli/actions/startProjectDev.action.ts index 4c971f9..740f6d6 100644 --- a/packages/cli/cli/actions/startProjectDev.action.ts +++ b/packages/cli/cli/actions/startProjectDev.action.ts @@ -45,7 +45,12 @@ export async function startProjectDev(options: Options): Promise { const serverEnv = { ...process.env, + // Set NODE_ENV=development just in case NODE_ENV: 'development', + + // Kottster app uses it's environment variable to determine the stage, + KOTTSTER_APP_STAGE: 'development', + VITE_KOTTSTER_APP_STAGE: 'development', DEV_API_SERVER_PORT: devApiServerPortStr, VITE_DEV_API_SERVER_PORT: devApiServerPortStr, diff --git a/packages/cli/cli/services/fileCreator.service.ts b/packages/cli/cli/services/fileCreator.service.ts index 9c542bc..624c23a 100644 --- a/packages/cli/cli/services/fileCreator.service.ts +++ b/packages/cli/cli/services/fileCreator.service.ts @@ -75,6 +75,8 @@ export class FileCreator { // Create files this.createFileFromTemplate('vite.config.js', path.join(this.projectDir, `vite.config.${this.jsExt}`)); + this.createFileFromTemplate('Dockerfile', path.join(this.projectDir, 'Dockerfile')); + this.createFileFromTemplate('docker-compose.yml', path.join(this.projectDir, 'docker-compose.yml')); this.createFileFromTemplate('app/index.html', path.join(this.projectDir, `app/index.html`)); this.createFileFromTemplate('app/main.jsx', path.join(this.projectDir, `app/main.${this.jsxExt}`)); this.createFileFromTemplate('app/_server/app.js', path.join(this.projectDir, `app/_server/app.${this.jsExt}`)); diff --git a/packages/cli/cli/services/fileTemplateManager.service.ts b/packages/cli/cli/services/fileTemplateManager.service.ts index 86de189..4903c0e 100644 --- a/packages/cli/cli/services/fileTemplateManager.service.ts +++ b/packages/cli/cli/services/fileTemplateManager.service.ts @@ -3,6 +3,8 @@ import { stripIndent } from "@kottster/common"; type TemplateVars = { 'vite.config.js': undefined; 'tsconfig.json': undefined; + 'Dockerfile': undefined; + 'docker-compose.yml': undefined; 'app/_server/app.js': undefined; 'app/_server/server.js': undefined; 'app/_server/data-sources/postgres/index.js': { @@ -127,6 +129,48 @@ export class FileTemplateManager { } `), + 'Dockerfile': stripIndent(` + # For production deployment + + FROM node:22-alpine AS builder + WORKDIR /app + + COPY package*.json ./ + RUN npm install + + COPY . . + RUN npm run build + + FROM node:22-alpine + WORKDIR /app + + COPY package*.json ./ + RUN npm install --omit=dev + + COPY --from=builder /app/dist ./dist + + ENV PORT=3000 + EXPOSE $PORT + + CMD ["node", "dist/server/server.cjs"] + `), + + 'docker-compose.yml': stripIndent(` + # For production deployment + + version: '3.8' + + services: + app: + build: + context: . + dockerfile: Dockerfile + ports: + - "3000:3000" + environment: + - PORT=3000 + `), + 'app/_server/app.js': stripIndent(` import { createApp } from '@kottster/server'; import schema from '../../kottster-app.json'; diff --git a/packages/cli/package-lock.json b/packages/cli/package-lock.json index 57d8cba..8203e95 100644 --- a/packages/cli/package-lock.json +++ b/packages/cli/package-lock.json @@ -1,6 +1,6 @@ { "name": "@kottster/cli", - "version": "3.0.2", + "version": "3.1.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1110,9 +1110,9 @@ "dev": true }, "@kottster/common": { - "version": "3.0.1", - "resolved": "https://registry.yarnpkg.com/@kottster/common/-/common-3.0.1.tgz", - "integrity": "sha1-NcFT/q4T03aRu5st/jpk5L35rFA= sha512-wOUDHFfwh/gMtOGHiZeFdR4nG3NawzFbLCIdX1UuYOxgYstr1E4kUNFJL6yXKGpLcx06lxwv4o4x0DZdh3Ldmg==", + "version": "3.0.6", + "resolved": "https://registry.yarnpkg.com/@kottster/common/-/common-3.0.6.tgz", + "integrity": "sha1-Y1cetuDb3maVnD0D7ARxe1AS0co= sha512-38ubX4CmJXTRDFXAodSyEoJgIzJk2PE2Y1nADldxk/tgglzYn7BD0xE6Xj/7Ly4X38glUQNObb59KhDYdfvVDQ==", "dev": true }, "@nodelib/fs.scandir": { diff --git a/packages/cli/package.json b/packages/cli/package.json index 6a10d85..ffa1e5b 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@kottster/cli", - "version": "3.0.2", + "version": "3.1.1", "description": "CLI for Kottster", "main": "dist/index.js", "license": "Apache-2.0", @@ -32,7 +32,7 @@ "@babel/traverse": "^7.24.1", "@babel/types": "^7.24.0", "@eslint/js": "^9.2.0", - "@kottster/common": "^3.0.1", + "@kottster/common": "^3.0.6", "@types/babel__traverse": "^7.20.5", "@types/cross-spawn": "^6.0.6", "@types/dotenv": "^8.2.0", diff --git a/packages/cli/yarn.lock b/packages/cli/yarn.lock index fb1b29c..de9d982 100644 --- a/packages/cli/yarn.lock +++ b/packages/cli/yarn.lock @@ -899,10 +899,10 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@kottster/common@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@kottster/common/-/common-3.0.1.tgz#35c153feae13d37691bb9b2dfe3a64e4bdf9ac50" - integrity sha512-wOUDHFfwh/gMtOGHiZeFdR4nG3NawzFbLCIdX1UuYOxgYstr1E4kUNFJL6yXKGpLcx06lxwv4o4x0DZdh3Ldmg== +"@kottster/common@^3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@kottster/common/-/common-3.0.6.tgz#63571eb6e0dbde66959c3d03ec04717b5012d1ca" + integrity sha512-38ubX4CmJXTRDFXAodSyEoJgIzJk2PE2Y1nADldxk/tgglzYn7BD0xE6Xj/7Ly4X38glUQNObb59KhDYdfvVDQ== "@nodelib/fs.scandir@2.1.5": version "2.1.5" diff --git a/packages/server/lib/actions/createPage.action.ts b/packages/server/lib/actions/createPage.action.ts index 5c00325..17017e6 100644 --- a/packages/server/lib/actions/createPage.action.ts +++ b/packages/server/lib/actions/createPage.action.ts @@ -1,4 +1,4 @@ -import { PageFileStructure } from "@kottster/common"; +import { PageFileStructure, Stage } from "@kottster/common"; import { DevAction } from "../models/action.model"; import { FileReader } from "../services/fileReader.service"; import { FileWriter } from "../services/fileWriter.service"; @@ -14,7 +14,7 @@ interface Data { export class CreatePage extends DevAction { public async executeDevAction(data: Data) { const fileWriter = new FileWriter({ usingTsc: this.app.usingTsc }); - const fileReader = new FileReader(); + const fileReader = new FileReader(this.app.stage === Stage.development); const appSchema = fileReader.readSchemaJsonFile(); // Add page file diff --git a/packages/server/lib/actions/deletePage.action.ts b/packages/server/lib/actions/deletePage.action.ts index 149b68d..f8f9f2e 100644 --- a/packages/server/lib/actions/deletePage.action.ts +++ b/packages/server/lib/actions/deletePage.action.ts @@ -1,3 +1,4 @@ +import { Stage } from "@kottster/common"; import { DevAction } from "../models/action.model"; import { FileReader } from "../services/fileReader.service"; import { FileWriter } from "../services/fileWriter.service"; @@ -12,7 +13,7 @@ interface Data { export class DeletePage extends DevAction { public async executeDevAction(data: Data) { const fileWriter = new FileWriter({ usingTsc: this.app.usingTsc }); - const fileReader = new FileReader(); + const fileReader = new FileReader(this.app.stage === Stage.development); const { key } = data; const appSchema = fileReader.readSchemaJsonFile(); diff --git a/packages/server/lib/actions/getAppSchema.ts b/packages/server/lib/actions/getAppSchema.ts index a8d8aa2..e9e4e88 100644 --- a/packages/server/lib/actions/getAppSchema.ts +++ b/packages/server/lib/actions/getAppSchema.ts @@ -1,4 +1,4 @@ -import { ClientAppSchema } from "@kottster/common"; +import { ClientAppSchema, Page, Stage } from "@kottster/common"; import { Action } from "../models/action.model"; import { FileReader } from "../services/fileReader.service"; @@ -6,10 +6,22 @@ import { FileReader } from "../services/fileReader.service"; * Get the app schema */ export class GetAppSchema extends Action { + private cachedPages: Page[] | null = null; + public async execute(): Promise { - const fileReader = new FileReader(); - const appSchema = fileReader.readSchemaJsonFile(); - const pages = fileReader.getPageConfigs(); + const fileReader = new FileReader(this.app.stage === Stage.development); + + // Cache pages in production to avoid reading files every time + const pages = this.app.stage === Stage.production && this.cachedPages + ? this.cachedPages + : fileReader.getPageConfigs(); + + if (this.app.stage === Stage.production && !this.cachedPages) { + this.cachedPages = pages; + } + + // In production, use the in-memory schema; in development, read from file + const appSchema = this.app.stage === Stage.production ? this.app.schema : fileReader.readSchemaJsonFile(); return { ...appSchema, diff --git a/packages/server/lib/actions/updateAppSchema.action.ts b/packages/server/lib/actions/updateAppSchema.action.ts index 3a23acd..43cd9aa 100644 --- a/packages/server/lib/actions/updateAppSchema.action.ts +++ b/packages/server/lib/actions/updateAppSchema.action.ts @@ -1,4 +1,4 @@ -import { AppSchema } from "@kottster/common"; +import { AppSchema, Stage } from "@kottster/common"; import { DevAction } from "../models/action.model"; import { FileReader } from "../services/fileReader.service"; import { FileWriter } from "../services/fileWriter.service"; @@ -13,7 +13,7 @@ interface Data { export class UpdateAppSchema extends DevAction { public async executeDevAction(data: Data) { const fileWriter = new FileWriter({ usingTsc: this.app.usingTsc }); - const fileReader = new FileReader(); + const fileReader = new FileReader(this.app.stage === Stage.development); const { menuPageOrder } = data; const appSchema = fileReader.readSchemaJsonFile(); diff --git a/packages/server/lib/actions/updatePage.action.ts b/packages/server/lib/actions/updatePage.action.ts index 596c03d..13a4825 100644 --- a/packages/server/lib/actions/updatePage.action.ts +++ b/packages/server/lib/actions/updatePage.action.ts @@ -1,4 +1,4 @@ -import { Page } from "@kottster/common"; +import { Page, Stage } from "@kottster/common"; import { DevAction } from "../models/action.model"; import { FileReader } from "../services/fileReader.service"; import { FileWriter } from "../services/fileWriter.service"; @@ -14,7 +14,7 @@ interface Data { export class UpdatePage extends DevAction { public async executeDevAction(data: Data) { const fileWriter = new FileWriter({ usingTsc: this.app.usingTsc }); - const fileReader = new FileReader(); + const fileReader = new FileReader(this.app.stage === Stage.development); const { key, page } = data; const appSchema = fileReader.readSchemaJsonFile(); diff --git a/packages/server/lib/core/app.ts b/packages/server/lib/core/app.ts index 660ae69..3e41ce9 100644 --- a/packages/server/lib/core/app.ts +++ b/packages/server/lib/core/app.ts @@ -45,7 +45,7 @@ export class KottsterApp { private readonly secretKey: string; public readonly usingTsc: boolean; public readonly readOnlyMode: boolean = false; - public readonly stage: Stage = process.env.NODE_ENV === Stage.development ? Stage.development : Stage.production; + public readonly stage: Stage = process.env.KOTTSTER_APP_STAGE === Stage.development ? Stage.development : Stage.production; public dataSources: DataSource[] = []; public schema: AppSchema; private customEnsureValidToken?: (request: Request) => Promise; @@ -123,7 +123,7 @@ export class KottsterApp { return; } } catch (error) { - console.error('Error handling internal API request:', error); + console.error('Internal API error:', error); res.status(500).json({ error: 'Internal Server Error' }); return; } @@ -153,7 +153,7 @@ export class KottsterApp { result: await this.executeAction(action, actionData), }; } catch (error) { - console.error('Error handling Kottster API request:', error); + console.error('Kottster API error:', error); result = { status: 'error', @@ -472,7 +472,7 @@ export class KottsterApp { let user: User; if (this.schema.enterpriseHub) { - const response = await fetch(`${this.schema.enterpriseHub.url}/apps/${this.appId}/users/current`, { + const response = await fetch(`${this.schema.enterpriseHub.url}/v1/apps/${this.appId}/users/current`, { headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}`, diff --git a/packages/server/lib/core/server.ts b/packages/server/lib/core/server.ts index ca4b256..56ceca7 100644 --- a/packages/server/lib/core/server.ts +++ b/packages/server/lib/core/server.ts @@ -57,8 +57,7 @@ export class KottsterServer { } private setupServiceRoutes() { - this.expressApp.use('/internal-api/', this.app.getInternalApiRoute()); - // this.expressApp.use('/devsync-api/', this.app.getDevSyncApiRoute()); + this.expressApp.use('/internal-api', this.app.getInternalApiRoute()); } private setupWebSocketHealthCheck() { @@ -87,7 +86,7 @@ export class KottsterServer { private async setupDynamicDataSources() { const isDevelopment = this.app.stage === Stage.development; - const fileReader = new FileReader(); + const fileReader = new FileReader(isDevelopment); // Dynamically load data sources from the data-sources directory const dataSourcesDir = isDevelopment ? `${PROJECT_DIR}/app/_server/data-sources` : `${PROJECT_DIR}/dist/server/data-sources`; @@ -96,7 +95,6 @@ export class KottsterServer { if (!fs.existsSync(dataSourcesDir)) { return; } - const dataSources: DataSource[] = []; const dataSourceConfigs = fileReader.getDataSourceConfigs(); @@ -138,40 +136,43 @@ export class KottsterServer { private async setupDynamicRoutes() { const isDevelopment = this.app.stage === Stage.development; - const fileReader = new FileReader(); + const fileReader = new FileReader(isDevelopment); const pageConfigs = fileReader.getPageConfigs(); - // Set routes for pages specified in the schema if (pageConfigs) { for (const pageConfig of pageConfigs) { - const pagesDir = isDevelopment ? `${PROJECT_DIR}/app/pages` : `${PROJECT_DIR}/dist/server/pages`; - const usingTsc = this.app.usingTsc; - const apiPath = path.join(pagesDir, pageConfig.key, isDevelopment ? `api.server.${usingTsc ? 'ts' : 'js'}` : 'api.cjs'); - - // If the page is custom or has a defined api.server.js file, load it - if (pageConfig.type === 'custom' || fs.existsSync(apiPath)) { - try { - const routeModule = await import(apiPath); - if (routeModule.default && typeof routeModule.default === 'function') { - const routePath = `/api/${pageConfig.key}`; - - this.expressApp.post(routePath, this.app.createRequestWithPageDataMiddleware(pageConfig), routeModule.default); + try { + const pagesDir = isDevelopment ? `${PROJECT_DIR}/app/pages` : `${PROJECT_DIR}/dist/server/pages`; + const usingTsc = this.app.usingTsc; + const apiPath = path.join(pagesDir, pageConfig.key, isDevelopment ? `api.server.${usingTsc ? 'ts' : 'js'}` : 'api.cjs'); + + // If the page is custom or has a defined api.server.js file, load it + if (pageConfig.type === 'custom' || fs.existsSync(apiPath)) { + try { + const routeModule = await import(apiPath); + if (routeModule.default && typeof routeModule.default === 'function') { + const routePath = `/api/${pageConfig.key}`; + + this.expressApp.post(routePath, this.app.createRequestWithPageDataMiddleware(pageConfig), routeModule.default); + } + } catch (error) { + console.error(`Failed to load route "${pageConfig.key}":`, error); } - } catch (error) { - console.error(`Failed to load route "${pageConfig.key}":`, error); - } - } else { - if (pageConfig.type === 'table') { - if (!pageConfig.config.dataSource) { - console.warn(`Page "${pageConfig.key}" does not have a data source specified. Skipping route setup.`); - continue; + } else { + if (pageConfig.type === 'table') { + if (!pageConfig.config.dataSource) { + console.warn(`Page "${pageConfig.key}" does not have a data source specified. Skipping route setup.`); + continue; + } + + this.expressApp.post(`/api/${pageConfig.key}`, this.app.createRequestWithPageDataMiddleware(pageConfig), this.app.defineTableController(pageConfig.config)); + } + if (pageConfig.type === 'dashboard') { + this.expressApp.post(`/api/${pageConfig.key}`, this.app.createRequestWithPageDataMiddleware(pageConfig), this.app.defineDashboardController(pageConfig.config)); } - - this.expressApp.post(`/api/${pageConfig.key}`, this.app.createRequestWithPageDataMiddleware(pageConfig), this.app.defineTableController(pageConfig.config)); - } - if (pageConfig.type === 'dashboard') { - this.expressApp.post(`/api/${pageConfig.key}`, this.app.createRequestWithPageDataMiddleware(pageConfig), this.app.defineDashboardController(pageConfig.config)); } + } catch (error) { + console.error(`Error setting up route for page "${pageConfig.key}":`, error); } }; } @@ -196,7 +197,7 @@ export class KottsterServer { } }); } else { - throw new Error(`Client directory not found: ${clientDir}`); + console.warn(`Client directory not found: ${clientDir}`); } } diff --git a/packages/server/lib/services/fileReader.service.ts b/packages/server/lib/services/fileReader.service.ts index 1cf5bb1..3b7f5aa 100644 --- a/packages/server/lib/services/fileReader.service.ts +++ b/packages/server/lib/services/fileReader.service.ts @@ -7,6 +7,7 @@ import { PageFileStructure, File, AppSchema, Page, DataSource } from "@kottster/ * Service for reading files */ export class FileReader { + constructor(private readonly isDevelopment?: boolean) {} /** * Read the schema from the kottster-app.json file @@ -40,7 +41,7 @@ export class FileReader { * @returns The page directories */ public getPagesDirectories(): string[] { - const dir = `${PROJECT_DIR}/app/pages`; + const dir = this.isDevelopment ? `${PROJECT_DIR}/app/pages` : `${PROJECT_DIR}/dist/server/pages`; if (!fs.existsSync(dir)) { return []; } @@ -53,7 +54,7 @@ export class FileReader { * @returns The data source directories */ public getDataSourceDirectories(): string[] { - const dir = `${PROJECT_DIR}/app/_server/data-sources`; + const dir = this.isDevelopment ? `${PROJECT_DIR}/app/_server/data-sources` : `${PROJECT_DIR}/dist/server/data-sources`; if (!fs.existsSync(dir)) { return []; } @@ -70,7 +71,7 @@ export class FileReader { const result: Omit[] = []; for (const dir of dataSourceDirectories) { - const dataSourceJsonPath = path.join(PROJECT_DIR, `app/_server/data-sources/${dir}/dataSource.json`); + const dataSourceJsonPath = path.join(PROJECT_DIR, this.isDevelopment ? `app/_server/data-sources/${dir}/dataSource.json` : `dist/server/data-sources/${dir}/dataSource.json`); if (!fs.existsSync(dataSourceJsonPath)) { console.warn(`Data source config not found for directory: ${dir}`); continue; @@ -136,7 +137,7 @@ export class FileReader { * @returns The page structure or null if the page does not exist */ public getPageFileStructure(pageKey: string): PageFileStructure | null { - const dirPath = `app/pages/${pageKey}`; + const dirPath = this.isDevelopment ? `app/pages/${pageKey}` : `dist/server/pages/${pageKey}`; const absoluteDirPath = `${PROJECT_DIR}/${dirPath}`; const filePaths = this.getAllFilePathsInDirectory(absoluteDirPath); diff --git a/packages/server/package-lock.json b/packages/server/package-lock.json index 351f03d..7accfd9 100644 --- a/packages/server/package-lock.json +++ b/packages/server/package-lock.json @@ -1,6 +1,6 @@ { "name": "@kottster/server", - "version": "3.0.7", + "version": "3.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/packages/server/package.json b/packages/server/package.json index 83d0f39..86a1ae4 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "@kottster/server", - "version": "3.0.7", + "version": "3.1.0", "description": "Instant admin panel for your project", "keywords": [ "admin",