diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..84503b80 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +min-release-age=4 \ No newline at end of file diff --git a/documentation/docs/integrate/vite-plugin.md b/documentation/docs/integrate/vite-plugin.md index 4db2ba91..39d44bc1 100644 --- a/documentation/docs/integrate/vite-plugin.md +++ b/documentation/docs/integrate/vite-plugin.md @@ -15,101 +15,4 @@ next: For easy integration with popular frontend frameworks like React, Angular, Vue, etc. we provide a plugin for [Vite](https://vitejs.dev/){target="_blank"}. -::: tip -We think it's good to put all the frontend code in a separate folder for better separation of concerns. It also simplifies the build process. For this, we use the `webui` folder throughout the documentation. -::: - -::: info NOTE -We also provide a creator app with templates for the most used frameworks. We recommend checking this out first before using this plugin. More information can be found in [our quick start](../introduction/quick-start). -::: - -## Installation - -You can simply install the plugin as dev-dependency using NPM. - -```bash -npm install --save-dev @jitar/plugin-vite -``` - -Next it has to be added to the Vite config file. - -```ts -// vite.config.js -import jitar, { JitarConfig } from '@jitar/plugin-vite'; -import { defineConfig } from 'vite'; - -const JITAR_URL = 'http://localhost:3000'; -const JITAR_SEGMENTS = ['frontend']; -const JITAR_MIDDLEWARES = ['./requesterMiddleware']; - -const jitarConfig: JitarConfig = { - projectRoot: '../../', - sourceRoot: '../', - configurationFile: './jitar.json', - environmentFile: './dev.env', - jitarUrl: JITAR_URL, - segments: JITAR_SEGMENTS, - middleware: JITAR_MIDDLEWARES -}; - -export default defineConfig({ - publicDir: 'src/webui/public', - build: { - assetsDir: 'webui', - emptyOutDir: false - }, - plugins: [ - jitar(jitarConfig) - ] -}); -``` - -The plugin configuration has 5 parameters: - -1. projectRoot - The root directory of the the project relative to the Vite configuration. -1. sourceRoot - The source directory relative to the Vite configuration. -1. configurationFile - The Jitar configuration file relative to the project root. Jitar uses `./jitar.json` by default. -1. environmentFile - The environment file relative to the project root. Is only loaded when configured. -1. jitarUrl - The URL of the Jitar instance. Jitar uses by default `http://localhost:3000`, but can be configured differently. -1. segments - The segments to use for the client app. This is an array of strings. The default is an empty array. -1. middlewares - The middlewares to use for calling remote procedures. This is an array of strings. The default is an empty array. - -To build the segments, an additional tsconfig file is required to compile the source code. The configuration is also used to exclude the `webui` folder from the TypeScript compilation. - -```json -// tsconfig.jitar.json -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "target": "ESNext", - "module": "ESNext", - "noEmit": false, - "rootDir": "./src", - "outDir": "./dist" - }, - "include": ["src"], - "exclude": ["src/webui"] -} -``` - -Finally, the TypeScript compilation needs to be set as the last step in the package.json file. - -```json -{ - "build": "npm run build-domain && npm run build-webui", - "build-domain": "rm -rf dist && tsc -p tsconfig.jitar.json && jitar build", - "build-webui": "vite build", -} -``` - -::: tip -Checkout our demo project [Comify](https://github.com/MaskingTechnology/comify){target="_blank"} for a complete working setup. -::: - -## Usage - -For development you can run Vite as you would normally do. The only requirement is that an instance of Jitar must already run in the background. For production you can build the project and use Jitar as your web server. - -::: info IMPORTANT -Jitar currently doesn’t support hot reloads. This means that the Jitar server needs to get restarted every time the backend functions are created or updated. -::: +Documentation can be found on the [Jitar docs](https://docs.jitar.dev/integrate/vite-plugin.html). diff --git a/examples/.gitignore b/examples/.gitignore index 86ef7726..4e46d83c 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,4 +1,4 @@ -.jitar +build dist node_modules package-lock.json \ No newline at end of file diff --git a/examples/access-protection/jitar.json b/examples/access-protection/jitar.json index 4bb49481..0686e62b 100644 --- a/examples/access-protection/jitar.json +++ b/examples/access-protection/jitar.json @@ -1,4 +1,4 @@ { "source": "./dist", - "target": "./.jitar" + "target": "./build" } \ No newline at end of file diff --git a/examples/access-protection/package.json b/examples/access-protection/package.json index 078a372b..f015b062 100644 --- a/examples/access-protection/package.json +++ b/examples/access-protection/package.json @@ -5,7 +5,7 @@ "license": "MIT", "private": true, "scripts": { - "build": "rimraf dist .jitar && tsc && jitar build", + "build": "rimraf dist build && tsc && jitar build", "standalone": "jitar start --service=services/standalone.json", "gateway": "jitar start --service=services/gateway.json", "worker-public": "jitar start --service=services/public.json", @@ -16,6 +16,6 @@ "typescript": "5.9.3" }, "dependencies": { - "jitar": "0.10.5" + "jitar": "0.11.0" } } \ No newline at end of file diff --git a/examples/data-transportation/jitar.json b/examples/data-transportation/jitar.json index 4bb49481..0686e62b 100644 --- a/examples/data-transportation/jitar.json +++ b/examples/data-transportation/jitar.json @@ -1,4 +1,4 @@ { "source": "./dist", - "target": "./.jitar" + "target": "./build" } \ No newline at end of file diff --git a/examples/data-transportation/package.json b/examples/data-transportation/package.json index a53c8e95..c23028fb 100644 --- a/examples/data-transportation/package.json +++ b/examples/data-transportation/package.json @@ -5,7 +5,7 @@ "license": "MIT", "private": true, "scripts": { - "build": "rimraf dist .jitar && tsc && jitar build", + "build": "rimraf dist build && tsc && jitar build", "standalone": "jitar start --service=services/standalone.json", "gateway": "jitar start --service=services/gateway.json", "worker-account": "jitar start --service=services/account.json", @@ -16,6 +16,6 @@ "typescript": "5.9.3" }, "dependencies": { - "jitar": "0.10.5" + "jitar": "0.11.0" } } \ No newline at end of file diff --git a/examples/error-handling/jitar.json b/examples/error-handling/jitar.json index 4bb49481..0686e62b 100644 --- a/examples/error-handling/jitar.json +++ b/examples/error-handling/jitar.json @@ -1,4 +1,4 @@ { "source": "./dist", - "target": "./.jitar" + "target": "./build" } \ No newline at end of file diff --git a/examples/error-handling/package.json b/examples/error-handling/package.json index 9fbe4b2c..3cf6bdb3 100644 --- a/examples/error-handling/package.json +++ b/examples/error-handling/package.json @@ -5,7 +5,7 @@ "license": "MIT", "private": true, "scripts": { - "build": "rimraf dist .jitar && tsc && jitar build", + "build": "rimraf dist build && tsc && jitar build", "standalone": "jitar start --service=services/standalone.json", "gateway": "jitar start --service=services/gateway.json", "worker-data": "jitar start --service=services/data.json", @@ -16,6 +16,6 @@ "typescript": "5.9.3" }, "dependencies": { - "jitar": "0.10.5" + "jitar": "0.11.0" } } \ No newline at end of file diff --git a/examples/health-checks/jitar.json b/examples/health-checks/jitar.json index 4bb49481..0686e62b 100644 --- a/examples/health-checks/jitar.json +++ b/examples/health-checks/jitar.json @@ -1,4 +1,4 @@ { "source": "./dist", - "target": "./.jitar" + "target": "./build" } \ No newline at end of file diff --git a/examples/health-checks/package.json b/examples/health-checks/package.json index 67c90149..8b0572a0 100644 --- a/examples/health-checks/package.json +++ b/examples/health-checks/package.json @@ -5,7 +5,7 @@ "license": "MIT", "private": true, "scripts": { - "build": "rimraf dist .jitar && tsc && jitar build", + "build": "rimraf dist build && tsc && jitar build", "standalone": "jitar start --service=services/standalone.json" }, "devDependencies": { @@ -13,6 +13,6 @@ "typescript": "5.9.3" }, "dependencies": { - "jitar": "0.10.5" + "jitar": "0.11.0" } } \ No newline at end of file diff --git a/examples/hello-world/jitar.json b/examples/hello-world/jitar.json index 4bb49481..0686e62b 100644 --- a/examples/hello-world/jitar.json +++ b/examples/hello-world/jitar.json @@ -1,4 +1,4 @@ { "source": "./dist", - "target": "./.jitar" + "target": "./build" } \ No newline at end of file diff --git a/examples/hello-world/package.json b/examples/hello-world/package.json index 8b93fb5b..a6c212a9 100644 --- a/examples/hello-world/package.json +++ b/examples/hello-world/package.json @@ -5,7 +5,7 @@ "license": "MIT", "private": true, "scripts": { - "build": "rimraf dist .jitar && tsc && jitar build", + "build": "rimraf dist build && tsc && jitar build", "standalone": "jitar start --service=services/standalone.json" }, "devDependencies": { @@ -13,6 +13,6 @@ "typescript": "5.9.3" }, "dependencies": { - "jitar": "0.10.5" + "jitar": "0.11.0" } } \ No newline at end of file diff --git a/examples/load-balancing/jitar.json b/examples/load-balancing/jitar.json index 4bb49481..0686e62b 100644 --- a/examples/load-balancing/jitar.json +++ b/examples/load-balancing/jitar.json @@ -1,4 +1,4 @@ { "source": "./dist", - "target": "./.jitar" + "target": "./build" } \ No newline at end of file diff --git a/examples/load-balancing/package.json b/examples/load-balancing/package.json index d62cc00b..00291abd 100644 --- a/examples/load-balancing/package.json +++ b/examples/load-balancing/package.json @@ -5,7 +5,7 @@ "license": "MIT", "private": true, "scripts": { - "build": "rimraf dist .jitar && tsc && jitar build", + "build": "rimraf dist build && tsc && jitar build", "standalone": "jitar start --service=services/standalone.json", "gateway": "jitar start --service=services/gateway.json", "worker1": "jitar start --service=services/worker1.json", @@ -16,6 +16,6 @@ "typescript": "5.9.3" }, "dependencies": { - "jitar": "0.10.5" + "jitar": "0.11.0" } } \ No newline at end of file diff --git a/examples/middleware/jitar.json b/examples/middleware/jitar.json index 4bb49481..0686e62b 100644 --- a/examples/middleware/jitar.json +++ b/examples/middleware/jitar.json @@ -1,4 +1,4 @@ { "source": "./dist", - "target": "./.jitar" + "target": "./build" } \ No newline at end of file diff --git a/examples/middleware/package.json b/examples/middleware/package.json index 3b51ebae..46b503cb 100644 --- a/examples/middleware/package.json +++ b/examples/middleware/package.json @@ -5,7 +5,7 @@ "license": "MIT", "private": true, "scripts": { - "build": "rimraf dist .jitar && tsc && jitar build", + "build": "rimraf dist build && tsc && jitar build", "standalone": "jitar start --service=services/standalone.json" }, "devDependencies": { @@ -13,6 +13,6 @@ "typescript": "5.9.3" }, "dependencies": { - "jitar": "0.10.5" + "jitar": "0.11.0" } } \ No newline at end of file diff --git a/examples/multi-version/jitar.json b/examples/multi-version/jitar.json index 4bb49481..0686e62b 100644 --- a/examples/multi-version/jitar.json +++ b/examples/multi-version/jitar.json @@ -1,4 +1,4 @@ { "source": "./dist", - "target": "./.jitar" + "target": "./build" } \ No newline at end of file diff --git a/examples/multi-version/package.json b/examples/multi-version/package.json index d4fb686e..a8bfaf50 100644 --- a/examples/multi-version/package.json +++ b/examples/multi-version/package.json @@ -5,7 +5,7 @@ "license": "MIT", "private": true, "scripts": { - "build": "rimraf dist .jitar && tsc && jitar build", + "build": "rimraf dist build && tsc && jitar build", "standalone": "jitar start --service=services/standalone.json" }, "devDependencies": { @@ -13,6 +13,6 @@ "typescript": "5.9.3" }, "dependencies": { - "jitar": "0.10.5" + "jitar": "0.11.0" } } \ No newline at end of file diff --git a/examples/resources/jitar.json b/examples/resources/jitar.json index 3f0be613..403a2140 100644 --- a/examples/resources/jitar.json +++ b/examples/resources/jitar.json @@ -1,6 +1,6 @@ { "source": "./dist", - "target": "./.jitar", + "target": "./build", "segments": "./segments", "resources": "./resources" } \ No newline at end of file diff --git a/examples/resources/package.json b/examples/resources/package.json index 977dd630..8c65f26d 100644 --- a/examples/resources/package.json +++ b/examples/resources/package.json @@ -5,7 +5,7 @@ "license": "MIT", "private": true, "scripts": { - "build": "rimraf dist .jitar && tsc && jitar build", + "build": "rimraf dist build && tsc && jitar build", "standalone": "jitar start --service=services/standalone.json" }, "devDependencies": { @@ -13,6 +13,6 @@ "typescript": "5.9.3" }, "dependencies": { - "jitar": "0.10.5" + "jitar": "0.11.0" } } \ No newline at end of file diff --git a/examples/segmentation/jitar.json b/examples/segmentation/jitar.json index beae5c58..1bb66f26 100644 --- a/examples/segmentation/jitar.json +++ b/examples/segmentation/jitar.json @@ -1,5 +1,5 @@ { "source": "./dist", - "target": "./.jitar", + "target": "./build", "segments": "./segments" } \ No newline at end of file diff --git a/examples/segmentation/package.json b/examples/segmentation/package.json index 98999543..22d82d43 100644 --- a/examples/segmentation/package.json +++ b/examples/segmentation/package.json @@ -5,7 +5,7 @@ "license": "MIT", "private": true, "scripts": { - "build": "rimraf dist .jitar && tsc && jitar build", + "build": "rimraf dist build && tsc && jitar build", "standalone": "jitar start --service=services/standalone.json", "gateway": "jitar start --service=services/gateway.json", "worker-data": "jitar start --service=services/data.json", @@ -16,6 +16,6 @@ "typescript": "5.9.3" }, "dependencies": { - "jitar": "0.10.5" + "jitar": "0.11.0" } } diff --git a/packages/analysis/src/static/Coder.ts b/packages/analysis/src/static/Coder.ts index 80b41b57..2c81036d 100644 --- a/packages/analysis/src/static/Coder.ts +++ b/packages/analysis/src/static/Coder.ts @@ -1,7 +1,8 @@ import Token from './models/Token'; import { TokenType } from './definitions/TokenType'; -import { isDeclaration, Keyword } from './definitions/Keyword'; + +const NO_TOKEN = new Token(TokenType.NONE, '', -1, 0); export default class Coder { @@ -27,27 +28,29 @@ export default class Coder generate(): string { let code = ''; - let previous: Token = new Token(TokenType.NOTHING, '', 0, 0); - - for (const current of this.#tokens) + + for (let index = 0; index < this.#tokens.length; index++) { - const glue = this.#needsSpacing(previous, current) ? ' ' : ''; - - code += `${glue}${current.value}`; + const previous = this.#tokens[index - 1] ?? NO_TOKEN; + const current = this.#tokens[index]; + const next = this.#tokens[index + 1] ?? NO_TOKEN; + + const prefix = this.#needsSpacingBefore(previous, current) ? ' ' : ''; + const postfix = this.#needsSpacingAfter(current, next) ? ' ' : ''; - previous = current; + code += `${prefix}${current.value}${postfix}`; } return code; } - #needsSpacing(previous: Token, current: Token): boolean + #needsSpacingBefore(previous: Token, current: Token): boolean { - if (previous.isType(TokenType.KEYWORD) && this.#isSpacedKeyword(previous)) + if (current.isType(TokenType.KEYWORD) && this.#isTextType(previous)) { return true; } - if (previous.isType(TokenType.OPERATOR) && current.isType(TokenType.OPERATOR)) + else if (current.isType(TokenType.OPERATOR) && previous.isType(TokenType.OPERATOR)) { return true; } @@ -55,14 +58,16 @@ export default class Coder return false; } - #isSpacedKeyword(token: Token): boolean + #needsSpacingAfter(current: Token, next: Token): boolean + { + return current.isType(TokenType.KEYWORD) && (next.isType(TokenType.KEYWORD) || this.#isTextType(next)); + } + + #isTextType(token: Token) { - return isDeclaration(token.value) - || token.hasValue(Keyword.RETURN) - || token.hasValue(Keyword.ASYNC) - || token.hasValue(Keyword.AWAIT) - || token.hasValue(Keyword.YIELD) - || token.hasValue(Keyword.NEW) - || token.hasValue(Keyword.THROW); + return token.isType(TokenType.IDENTIFIER) + || token.isType(TokenType.BOOLEAN) + || token.isType(TokenType.NOTHING) + || token.isType(TokenType.NUMBER); } } diff --git a/packages/analysis/src/static/definitions/TokenType.ts b/packages/analysis/src/static/definitions/TokenType.ts index 165cab04..c411231a 100644 --- a/packages/analysis/src/static/definitions/TokenType.ts +++ b/packages/analysis/src/static/definitions/TokenType.ts @@ -15,7 +15,8 @@ const TokenType = INDICATOR: 'indicator', REGEX: 'regex', SCOPE: 'scope', - WHITESPACE: 'whitespace' + WHITESPACE: 'whitespace', + NONE: 'none' }; export { TokenType }; diff --git a/packages/analysis/test/static/Parser.spec.ts b/packages/analysis/test/static/Parser.spec.ts index f443af14..b7021d62 100644 --- a/packages/analysis/test/static/Parser.spec.ts +++ b/packages/analysis/test/static/Parser.spec.ts @@ -12,7 +12,7 @@ import { import { Parser } from '../../src/static'; -import { VALUES, IMPORTS, EXPORTS, DECLARATIONS, FUNCTIONS, CLASSES, MODULES, MODULES_STRINGS } from './fixtures'; +import { VALUES, IMPORTS, EXPORTS, VARIABLES, FUNCTIONS, CLASSES, MODULES, MODULES_STRINGS } from './fixtures'; const parser = new Parser(); @@ -52,7 +52,7 @@ describe('Parser', () => { const expression = parser.parseStatement(VALUES.IF_ELSE); expect(expression).toBeInstanceOf(ESExpression); - expect(expression.toString(false)).toEqual('if(true){return "value1";}else{return "value2";}'); + expect(expression.toString(false)).toEqual('if(true){return"value1";}else{return"value2";}'); }); it('should parse an try...catch...finally expression', () => @@ -402,7 +402,7 @@ describe('Parser', () => { it('should parse an empty declaration', () => { - const variable = parser.parseVariable(DECLARATIONS.EMPTY); + const variable = parser.parseVariable(VARIABLES.EMPTY); expect(variable.identifier).toEqual('name'); expect(variable.binding).toBeInstanceOf(ESIdentifierBinding); expect(variable.type).toEqual('let'); @@ -411,7 +411,7 @@ describe('Parser', () => it('should parse a const variable', () => { - const variable = parser.parseVariable(DECLARATIONS.CONST); + const variable = parser.parseVariable(VARIABLES.CONST); expect(variable.identifier).toEqual('name'); expect(variable.binding).toBeInstanceOf(ESIdentifierBinding); expect(variable.type).toEqual('const'); @@ -421,7 +421,7 @@ describe('Parser', () => it('should parse a let declaration with value', () => { - const variable = parser.parseVariable(DECLARATIONS.LET); + const variable = parser.parseVariable(VARIABLES.LET); expect(variable.identifier).toEqual('name'); expect(variable.binding).toBeInstanceOf(ESIdentifierBinding); expect(variable.type).toEqual('let'); @@ -431,7 +431,7 @@ describe('Parser', () => it('should parse a var declaration with value', () => { - const variable = parser.parseVariable(DECLARATIONS.VAR); + const variable = parser.parseVariable(VARIABLES.VAR); expect(variable.identifier).toEqual('name'); expect(variable.binding).toBeInstanceOf(ESIdentifierBinding); expect(variable.type).toEqual('var'); @@ -441,7 +441,7 @@ describe('Parser', () => it('should parse a declaration with multiple declarations', () => { - const variable = parser.parseVariable(DECLARATIONS.MULTIPLE); + const variable = parser.parseVariable(VARIABLES.MULTIPLE); expect(variable.identifier).toEqual('name1'); expect(variable.binding).toBeInstanceOf(ESIdentifierBinding); expect(variable.type).toEqual('let'); @@ -451,7 +451,7 @@ describe('Parser', () => it('should parse a declaration with an expression', () => { - const variable = parser.parseVariable(DECLARATIONS.EXPRESSION); + const variable = parser.parseVariable(VARIABLES.EXPRESSION); expect(variable.identifier).toEqual('number'); expect(variable.binding).toBeInstanceOf(ESIdentifierBinding); expect(variable.type).toEqual('const'); @@ -461,7 +461,7 @@ describe('Parser', () => it('should parse a declaration with an array value', () => { - const variable = parser.parseVariable(DECLARATIONS.ARRAY); + const variable = parser.parseVariable(VARIABLES.ARRAY); expect(variable.identifier).toEqual('array'); expect(variable.binding).toBeInstanceOf(ESIdentifierBinding); expect(variable.type).toEqual('const'); @@ -471,7 +471,7 @@ describe('Parser', () => it('should parse a declaration with an object value', () => { - const variable = parser.parseVariable(DECLARATIONS.OBJECT); + const variable = parser.parseVariable(VARIABLES.OBJECT); expect(variable.identifier).toEqual('object'); expect(variable.binding).toBeInstanceOf(ESIdentifierBinding); expect(variable.type).toEqual('const'); @@ -481,7 +481,7 @@ describe('Parser', () => it('should parse a declaration with a regex value', () => { - const variable = parser.parseVariable(DECLARATIONS.REGEX); + const variable = parser.parseVariable(VARIABLES.REGEX); expect(variable.identifier).toEqual('regex'); expect(variable.binding).toBeInstanceOf(ESIdentifierBinding); expect(variable.type).toEqual('const'); @@ -491,7 +491,7 @@ describe('Parser', () => it('should parse a declaration that is destructuring an array', () => { - const variable = parser.parseVariable(DECLARATIONS.DESTRUCTURING_ARRAY); + const variable = parser.parseVariable(VARIABLES.DESTRUCTURING_ARRAY); expect(variable.identifier).toEqual('[value1,value2=true]'); expect(variable.binding).toBeInstanceOf(ESArrayBinding); expect(variable.type).toEqual('const'); @@ -517,7 +517,7 @@ describe('Parser', () => it('should parse a declaration that is destructuring an object', () => { - const variable = parser.parseVariable(DECLARATIONS.DESTRUCTURING_OBJECT); + const variable = parser.parseVariable(VARIABLES.DESTRUCTURING_OBJECT); expect(variable.identifier).toEqual('{key1,key2=false}'); expect(variable.binding).toBeInstanceOf(ESObjectBinding); expect(variable.type).toEqual('const'); @@ -542,7 +542,7 @@ describe('Parser', () => it('should parse a declaration with a non reserved keyword as name', () => { - const variable = parser.parseVariable(DECLARATIONS.KEYWORD_AS_NAME); + const variable = parser.parseVariable(VARIABLES.KEYWORD_AS_NAME); expect(variable.identifier).toEqual('as'); expect(variable.binding).toBeInstanceOf(ESIdentifierBinding); expect(variable.type).toEqual('const'); @@ -552,7 +552,7 @@ describe('Parser', () => it('should parse a declaration that refers to a non reserved keyword as value', () => { - const variable = parser.parseVariable(DECLARATIONS.KEYWORD_AS_VALUE); + const variable = parser.parseVariable(VARIABLES.KEYWORD_AS_VALUE); expect(variable.identifier).toEqual('alias'); expect(variable.binding).toBeInstanceOf(ESIdentifierBinding); expect(variable.type).toEqual('const'); @@ -928,7 +928,7 @@ describe('Parser', () => expect(funktion.identifier).toEqual('name'); expect(funktion.isAsync).toBeFalsy(); - expect(funktion.body.toString()).toEqual("{return 'value';}"); + expect(funktion.body.toString()).toEqual("{return'value';}"); const parameters = funktion.parameters; expect(parameters).toHaveLength(0); @@ -940,7 +940,7 @@ describe('Parser', () => expect(funktion.identifier).toEqual('name'); expect(funktion.isAsync).toBeFalsy(); - expect(funktion.body.toString()).toEqual("{if(true){return 'value';}}"); + expect(funktion.body.toString()).toEqual("{if(true){return'value';}}"); const parameters = funktion.parameters; expect(parameters).toHaveLength(0); diff --git a/packages/analysis/test/static/fixtures/index.ts b/packages/analysis/test/static/fixtures/index.ts index c87031d7..30447888 100644 --- a/packages/analysis/test/static/fixtures/index.ts +++ b/packages/analysis/test/static/fixtures/index.ts @@ -1,7 +1,7 @@ export * from './classes.fixture'; export * from './code.fixture'; -export * from './declarations.fixture'; +export * from './variables.fixture'; export * from './exports.fixture'; export * from './functions.fixture'; export * from './imports.fixture'; diff --git a/packages/analysis/test/static/fixtures/declarations.fixture.ts b/packages/analysis/test/static/fixtures/variables.fixture.ts similarity index 95% rename from packages/analysis/test/static/fixtures/declarations.fixture.ts rename to packages/analysis/test/static/fixtures/variables.fixture.ts index d8833d65..e0837c4f 100644 --- a/packages/analysis/test/static/fixtures/declarations.fixture.ts +++ b/packages/analysis/test/static/fixtures/variables.fixture.ts @@ -1,5 +1,5 @@ -export const DECLARATIONS = +export const VARIABLES = { EMPTY: "let name;", CONST: "const name = 'const';", diff --git a/packages/init/templates/backend/.gitignore b/packages/init/templates/backend/.gitignore index 9dc6c7d3..09da1a97 100644 --- a/packages/init/templates/backend/.gitignore +++ b/packages/init/templates/backend/.gitignore @@ -8,7 +8,7 @@ pnpm-debug.log* lerna-debug.log* node_modules -.jitar +build dist dist-ssr *.local diff --git a/packages/init/templates/react/.gitignore b/packages/init/templates/react/.gitignore index a13e852c..f19ce19a 100644 --- a/packages/init/templates/react/.gitignore +++ b/packages/init/templates/react/.gitignore @@ -8,7 +8,7 @@ pnpm-debug.log* lerna-debug.log* node_modules -.jitar +build dist dist-ssr *.local diff --git a/packages/init/templates/react/package.json b/packages/init/templates/react/package.json index 4a903441..cd2b2616 100644 --- a/packages/init/templates/react/package.json +++ b/packages/init/templates/react/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite", + "dev": "vite --config src/app/vite.config.ts", "build": "npm run build-domain && npm run build-app", "build-domain": "rimraf build dist && tsc -p src/tsconfig.json && jitar build", "build-app": "vite build --config src/app/vite.config.ts", diff --git a/packages/init/templates/vue/.gitignore b/packages/init/templates/vue/.gitignore index 89b15d15..09da1a97 100644 --- a/packages/init/templates/vue/.gitignore +++ b/packages/init/templates/vue/.gitignore @@ -8,8 +8,8 @@ pnpm-debug.log* lerna-debug.log* node_modules +build dist -.jitar dist-ssr *.local diff --git a/packages/init/templates/vue/package.json b/packages/init/templates/vue/package.json index f9e21b70..f9ef3ef0 100644 --- a/packages/init/templates/vue/package.json +++ b/packages/init/templates/vue/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite", + "dev": "vite --config src/app/vite.config.ts", "build": "npm run build-domain && npm run build-app", "build-domain": "rimraf build dist && tsc -p src/tsconfig.json && jitar build", "build-app": "vite build --config=src/app/vite.config.ts && vue-tsc --noEmit", diff --git a/packages/plugin-vite/package.json b/packages/plugin-vite/package.json index b598ddae..d2a1f584 100644 --- a/packages/plugin-vite/package.json +++ b/packages/plugin-vite/package.json @@ -32,7 +32,7 @@ }, "peerDependencies": { "jitar": "^0.11.0", - "vite": ">=4.0.0 || >=5.0.0 || >=6.0.0 || >=7.0.0" + "vite": ">=7" }, "peerDependenciesMeta": { "vite": { diff --git a/packages/plugin-vite/src/index.ts b/packages/plugin-vite/src/index.ts index da7d6f03..a39704a0 100644 --- a/packages/plugin-vite/src/index.ts +++ b/packages/plugin-vite/src/index.ts @@ -1,5 +1,4 @@ -import fs from 'node:fs'; import path from 'node:path'; import { ConfigurationManager, BuildHelper } from 'jitar'; @@ -8,6 +7,7 @@ import { normalizePath, PluginOption, ResolvedConfig } from 'vite'; const JITAR_SOURCE_ID = 'jitar'; const JITAR_CLIENT_ID = 'jitar/client'; const JITAR_BUNDLE_ID = 'jitar-bundle'; +const JITAR_BUNDLE_RESOLVE_ID = `\0${JITAR_BUNDLE_ID}`; function assureExtension(filename: string) { @@ -21,7 +21,7 @@ function assureExtension(filename: string) function createJitarBundle(middlewares: string[], targetPath: string) { - const middlewareFiles = middlewares.map(name => assureExtension(`${targetPath}/${name}`)); + const middlewareFiles = middlewares.map(name => assureExtension(path.join(targetPath, name))); const jitarImport = `import { ClientBuilder, HttpRemoteBuilder } from "${JITAR_CLIENT_ID}";`; const middlewareImports = middlewareFiles.map((filename, index) => `import { default as $M${index} } from "${filename}";`).join(''); @@ -86,13 +86,12 @@ export default function viteJitar(pluginConfig: PluginConfig): PluginOption }; let buildHelper: BuildHelper; - - let jitarBundleFilename: string | undefined; - let jitarBundleImported = false; + let jitarImported = false; return { name: 'jitar-plugin-vite', + enforce: 'pre', config() { @@ -106,7 +105,7 @@ export default function viteJitar(pluginConfig: PluginConfig): PluginOption { paths.vite.input = normalizePath(path.join(resolvedConfig.root)); paths.vite.output = normalizePath(path.join(paths.vite.input, resolvedConfig.build.outDir)); - paths.vite.assetOutput = normalizePath(path.join(paths.vite.input, resolvedConfig.build.assetsDir)); + paths.vite.assetOutput = normalizePath(path.join(paths.vite.output, resolvedConfig.build.assetsDir)); paths.project.root = normalizePath(path.join(paths.vite.input, pluginConfig.projectRoot)); paths.project.source = normalizePath(path.join(paths.vite.input, pluginConfig.sourceRoot)); @@ -114,6 +113,8 @@ export default function viteJitar(pluginConfig: PluginConfig): PluginOption async buildStart() { + jitarImported = false; + const configurationManager = new ConfigurationManager(paths.project.root); if (pluginConfig.environmentFile !== undefined) @@ -129,62 +130,27 @@ export default function viteJitar(pluginConfig: PluginConfig): PluginOption await buildHelper.readApplication(); }, - options(options) + resolveId(id) { - // Add the jitar client bundle to the input - - if (options.input === undefined) - { - options.input = JITAR_BUNDLE_ID; - } - else if (typeof options.input === 'string') - { - options.input = [options.input, JITAR_BUNDLE_ID]; - } - else if (Array.isArray(options.input)) - { - options.input.push(JITAR_BUNDLE_ID); - } - else if (typeof options.input === 'object') + if (id === JITAR_BUNDLE_ID) { - options.input.additionalEntry = JITAR_BUNDLE_ID; + return JITAR_BUNDLE_RESOLVE_ID; } - return options; - }, - - resolveId: - { - order: 'pre', - async handler(source: string, importer: string | undefined) + if (id === JITAR_SOURCE_ID) { - if (source === JITAR_BUNDLE_ID) - { - return source; - } - - if (source === JITAR_SOURCE_ID) - { - // Redirect all jitar imports to the jitar client bundle - // so we can bundle the client code with the application - - if (importer?.endsWith('.segment.js') === false) - { - // Flag that the jitar bundle was imported by the application - // so we can avoid adding it to the HTML - - jitarBundleImported = true; - } - - return JITAR_BUNDLE_ID; - } + return JITAR_BUNDLE_RESOLVE_ID; } + + return null; }, load(id) { - if (id === JITAR_BUNDLE_ID) + if (id === JITAR_BUNDLE_RESOLVE_ID) { + jitarImported = true; + return createJitarBundle(middlewares, paths.vite.output!); } @@ -219,63 +185,20 @@ export default function viteJitar(pluginConfig: PluginConfig): PluginOption return null; }, - generateBundle(options, bundle) + transform(code, id) { - // Find the jitar client bundle so we can add it later to the HTML - - const bundles = Object.entries(bundle); + // Import the Jitar bundle from the first application component - for (const [fileName, chunk] of bundles) - { - if (chunk.type === 'chunk' && chunk.name === JITAR_BUNDLE_ID) - { - jitarBundleFilename = fileName; - - break; - } - } - }, - - transformIndexHtml(html) - { - // Add the jitar client bundle to the HTML if it wasn't imported - // by any of the application files. + const isFirstAppComponent = jitarImported === false + && id.startsWith(paths.project.source!) + && (id.endsWith('.js') || id.endsWith('.ts') || id.endsWith('.jsx') || id.endsWith('.tsx')); - if (jitarBundleImported === true) - { - return html; - } - - if (jitarBundleFilename === undefined) + if (isFirstAppComponent) { - // Dev mode: insert the pre generated jitar bundle - - if (paths.vite.assetOutput === undefined) - { - console.warn('Output path not found!'); - - return html; - } - - const filenames = fs.readdirSync(paths.vite.assetOutput); - - const jitarFilename = filenames.find(fileName => fileName.startsWith(JITAR_BUNDLE_ID) && fileName.endsWith('.js')); - - if (jitarFilename === undefined) - { - console.warn('Jitar bundle not found! Did you build the application first?'); - - return html; - } - - const jitarBundle = fs.readFileSync(path.join(paths.vite.assetOutput, jitarFilename), 'utf-8'); - - return html.replace('${jitarBundle}\n \n