diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index f3efb53..ee43ab6 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: - node-version: [20.x, 21.x] + node-version: [22.x, 24.x] steps: - uses: actions/checkout@v4 @@ -29,8 +29,11 @@ jobs: - name: Recreate JSON Schemas run: yarn create-schemas && yarn build # an incremental rebuild is neccessary to use the updated schema - name: Test - run: yarn test:unit - - uses: codecov/codecov-action@v2 + run: yarn test:unit --reporter=junit --outputFile=test-report.junit.xml + + - name: Upload test results to Codecov + if: ${{ !cancelled() }} + uses: codecov/test-results-action@v1 with: token: ${{ secrets.CODECOV_TOKEN }} env: diff --git a/.github/workflows/check-version-bump.yml b/.github/workflows/check-version-bump.yml index 381634f..898fdf4 100644 --- a/.github/workflows/check-version-bump.yml +++ b/.github/workflows/check-version-bump.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: - node-version: [20.x] + node-version: [22.x] steps: - name: Checkout diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index 0d7319a..aea1e41 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: - node-version: [20.x, 22.x] + node-version: [22.x, 24.x] steps: - uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index 367e89f..b084437 100644 --- a/.gitignore +++ b/.gitignore @@ -73,4 +73,6 @@ testresults !.yarn/plugins !.yarn/releases !.yarn/sdks -!.yarn/versions \ No newline at end of file +!.yarn/versions + +test-results \ No newline at end of file diff --git a/.yarn/versions/2d4efe43.yml b/.yarn/versions/2d4efe43.yml deleted file mode 100644 index 6e6773b..0000000 --- a/.yarn/versions/2d4efe43.yml +++ /dev/null @@ -1,5 +0,0 @@ -releases: - common: patch - frontend: patch - furystack-boilerplate-app: patch - service: patch diff --git a/.yarn/versions/544e081e.yml b/.yarn/versions/544e081e.yml deleted file mode 100644 index 6e6773b..0000000 --- a/.yarn/versions/544e081e.yml +++ /dev/null @@ -1,5 +0,0 @@ -releases: - common: patch - frontend: patch - furystack-boilerplate-app: patch - service: patch diff --git a/.yarn/versions/bf3e3cf4.yml b/.yarn/versions/bf3e3cf4.yml deleted file mode 100644 index 6e6773b..0000000 --- a/.yarn/versions/bf3e3cf4.yml +++ /dev/null @@ -1,5 +0,0 @@ -releases: - common: patch - frontend: patch - furystack-boilerplate-app: patch - service: patch diff --git a/.yarn/versions/cee96777.yml b/.yarn/versions/cee96777.yml deleted file mode 100644 index 6e6773b..0000000 --- a/.yarn/versions/cee96777.yml +++ /dev/null @@ -1,5 +0,0 @@ -releases: - common: patch - frontend: patch - furystack-boilerplate-app: patch - service: patch diff --git a/.yarn/versions/e54633dc.yml b/.yarn/versions/e54633dc.yml deleted file mode 100644 index 6e6773b..0000000 --- a/.yarn/versions/e54633dc.yml +++ /dev/null @@ -1,5 +0,0 @@ -releases: - common: patch - frontend: patch - furystack-boilerplate-app: patch - service: patch diff --git a/README.md b/README.md index 68490d1..080e410 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# boilerplate +# obsidian-core -Boilerplate app with common type api definitions, a furystack-based backend service and a Shades-based single page application. +Obsidian Core is an advanced smart home management system built with Furystack. It provides a robust backend service and a user-friendly frontend interface to control and monitor your smart home devices. # Usage diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ce92671..30953d3 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -17,7 +17,7 @@ pool: steps: - task: NodeTool@0 inputs: - versionSpec: '20.x' + versionSpec: '22.x' displayName: 'Install Node.js' - script: yarn install displayName: 'Yarn install' diff --git a/common/schemas/authentication-api.json b/common/schemas/authentication-api.json new file mode 100644 index 0000000..1d1ddec --- /dev/null +++ b/common/schemas/authentication-api.json @@ -0,0 +1,206 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/AuthenticationApi", + "definitions": { + "AuthenticationApi": { + "type": "object", + "properties": { + "GET": { + "type": "object", + "properties": { + "/isAuthenticated": { + "type": "object", + "properties": { + "result": { + "type": "object", + "properties": { + "isAuthenticated": { + "type": "boolean" + } + }, + "required": ["isAuthenticated"], + "additionalProperties": false + } + }, + "required": ["result"], + "additionalProperties": false + }, + "/currentUser": { + "type": "object", + "properties": { + "result": { + "$ref": "#/definitions/User" + } + }, + "required": ["result"], + "additionalProperties": false + } + }, + "required": ["/isAuthenticated", "/currentUser"], + "additionalProperties": false + }, + "POST": { + "type": "object", + "properties": { + "/login": { + "type": "object", + "properties": { + "result": { + "$ref": "#/definitions/User" + }, + "body": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "password": { + "type": "string" + } + }, + "required": ["username", "password"], + "additionalProperties": false + } + }, + "required": ["result", "body"], + "additionalProperties": false + }, + "/logout": { + "type": "object", + "properties": { + "result": {} + }, + "required": ["result"], + "additionalProperties": false + } + }, + "required": ["/login", "/logout"], + "additionalProperties": false + }, + "PATCH": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "result": {}, + "url": {}, + "query": {}, + "body": {}, + "headers": {} + }, + "required": ["result"], + "additionalProperties": false + } + }, + "PUT": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "result": {}, + "url": {}, + "query": {}, + "body": {}, + "headers": {} + }, + "required": ["result"], + "additionalProperties": false + } + }, + "DELETE": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "result": {}, + "url": {}, + "query": {}, + "body": {}, + "headers": {} + }, + "required": ["result"], + "additionalProperties": false + } + }, + "HEAD": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "result": {}, + "url": {}, + "query": {}, + "body": {}, + "headers": {} + }, + "required": ["result"], + "additionalProperties": false + } + }, + "CONNECT": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "result": {}, + "url": {}, + "query": {}, + "body": {}, + "headers": {} + }, + "required": ["result"], + "additionalProperties": false + } + }, + "TRACE": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "result": {}, + "url": {}, + "query": {}, + "body": {}, + "headers": {} + }, + "required": ["result"], + "additionalProperties": false + } + }, + "OPTIONS": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "result": {}, + "url": {}, + "query": {}, + "body": {}, + "headers": {} + }, + "required": ["result"], + "additionalProperties": false + } + } + }, + "required": ["GET", "POST"], + "additionalProperties": false + }, + "User": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["username", "roles"], + "additionalProperties": false + } + } +} diff --git a/common/schemas/boilerplate-api.json b/common/schemas/boilerplate-api.json deleted file mode 100644 index 9e239dc..0000000 --- a/common/schemas/boilerplate-api.json +++ /dev/null @@ -1,436 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "definitions": { - "TestQueryEndpoint": { - "type": "object", - "properties": { - "query": { - "type": "object", - "properties": { - "param1": { - "type": "string" - } - }, - "required": ["param1"], - "additionalProperties": false - }, - "result": { - "type": "object", - "properties": { - "param1Value": { - "type": "string" - } - }, - "required": ["param1Value"], - "additionalProperties": false - } - }, - "required": ["query", "result"], - "additionalProperties": false - }, - "TestUrlParamsEndpoint": { - "type": "object", - "properties": { - "url": { - "type": "object", - "properties": { - "urlParam": { - "type": "string" - } - }, - "required": ["urlParam"], - "additionalProperties": false - }, - "result": { - "type": "object", - "properties": { - "urlParamValue": { - "type": "string" - } - }, - "required": ["urlParamValue"], - "additionalProperties": false - } - }, - "required": ["url", "result"], - "additionalProperties": false - }, - "TestPostBodyEndpoint": { - "type": "object", - "properties": { - "body": { - "type": "object", - "properties": { - "value": { - "type": "string" - } - }, - "required": ["value"], - "additionalProperties": false - }, - "result": { - "type": "object", - "properties": { - "bodyValue": { - "type": "string" - } - }, - "required": ["bodyValue"], - "additionalProperties": false - } - }, - "required": ["body", "result"], - "additionalProperties": false - }, - "BoilerplateApi": { - "type": "object", - "properties": { - "GET": { - "type": "object", - "properties": { - "/isAuthenticated": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "isAuthenticated": { - "type": "boolean" - } - }, - "required": ["isAuthenticated"], - "additionalProperties": false - } - }, - "required": ["result"], - "additionalProperties": false - }, - "/currentUser": { - "type": "object", - "properties": { - "result": { - "$ref": "#/definitions/User" - } - }, - "required": ["result"], - "additionalProperties": false - }, - "/testQuery": { - "$ref": "#/definitions/TestQueryEndpoint" - }, - "/testUrlParams/:urlParam": { - "$ref": "#/definitions/TestUrlParamsEndpoint" - } - }, - "required": ["/isAuthenticated", "/currentUser", "/testQuery", "/testUrlParams/:urlParam"], - "additionalProperties": false - }, - "POST": { - "type": "object", - "properties": { - "/login": { - "type": "object", - "properties": { - "result": { - "$ref": "#/definitions/User" - }, - "body": { - "type": "object", - "properties": { - "username": { - "type": "string" - }, - "password": { - "type": "string" - } - }, - "required": ["username", "password"], - "additionalProperties": false - } - }, - "required": ["result", "body"], - "additionalProperties": false - }, - "/logout": { - "type": "object", - "properties": { - "result": {} - }, - "required": ["result"], - "additionalProperties": false - }, - "/testPostBody": { - "$ref": "#/definitions/TestPostBodyEndpoint" - } - }, - "required": ["/login", "/logout", "/testPostBody"], - "additionalProperties": false - }, - "PATCH": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - }, - "PUT": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - }, - "DELETE": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - }, - "HEAD": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - }, - "CONNECT": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - }, - "TRACE": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - }, - "OPTIONS": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - } - }, - "required": ["GET", "POST"], - "additionalProperties": false - }, - "RestApi": { - "type": "object", - "properties": { - "GET": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - }, - "POST": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - }, - "PATCH": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - }, - "PUT": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - }, - "DELETE": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - }, - "HEAD": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - }, - "CONNECT": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - }, - "TRACE": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - }, - "OPTIONS": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "result": {}, - "url": {}, - "query": {}, - "body": {}, - "headers": {} - }, - "required": ["result"], - "additionalProperties": false - } - } - }, - "additionalProperties": false - }, - "User": { - "type": "object", - "properties": { - "username": { - "type": "string" - }, - "roles": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": ["username", "roles"], - "additionalProperties": false - } - } -} diff --git a/common/src/authentication-api.ts b/common/src/authentication-api.ts new file mode 100644 index 0000000..11f8293 --- /dev/null +++ b/common/src/authentication-api.ts @@ -0,0 +1,13 @@ +import type { RestApi } from '@furystack/rest' +import type { User } from './models/index.js' + +export interface AuthenticationApi extends RestApi { + GET: { + '/isAuthenticated': { result: { isAuthenticated: boolean } } + '/currentUser': { result: User } + } + POST: { + '/login': { result: User; body: { username: string; password: string } } + '/logout': { result: unknown } + } +} diff --git a/common/src/bin/create-schemas.ts b/common/src/bin/create-schemas.ts index 19556ad..aa465e3 100644 --- a/common/src/bin/create-schemas.ts +++ b/common/src/bin/create-schemas.ts @@ -21,8 +21,8 @@ export const entityValues: SchemaGenerationSetting[] = [ export const apiValues: SchemaGenerationSetting[] = [ { - inputFile: './src/boilerplate-api.ts', - outputFile: './schemas/boilerplate-api.json', + inputFile: './src/authentication-api.ts', + outputFile: './schemas/authentication-api.json', type: '*', }, ] diff --git a/common/src/boilerplate-api.ts b/common/src/boilerplate-api.ts deleted file mode 100644 index ff2299b..0000000 --- a/common/src/boilerplate-api.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { RestApi } from '@furystack/rest' -import type { User } from './models/index.js' - -export type TestQueryEndpoint = { query: { param1: string }; result: { param1Value: string } } -export type TestUrlParamsEndpoint = { url: { urlParam: string }; result: { urlParamValue: string } } -export type TestPostBodyEndpoint = { body: { value: string }; result: { bodyValue: string } } - -export interface BoilerplateApi extends RestApi { - GET: { - '/isAuthenticated': { result: { isAuthenticated: boolean } } - '/currentUser': { result: User } - '/testQuery': TestQueryEndpoint - '/testUrlParams/:urlParam': TestUrlParamsEndpoint - } - POST: { - '/login': { result: User; body: { username: string; password: string } } - '/logout': { result: unknown } - '/testPostBody': TestPostBodyEndpoint - } -} diff --git a/common/src/index.ts b/common/src/index.ts index c6bf005..b4d6ed2 100644 --- a/common/src/index.ts +++ b/common/src/index.ts @@ -1,2 +1,2 @@ +export * from './authentication-api.js' export * from './models/index.js' -export * from './boilerplate-api.js' diff --git a/frontend/index.html b/frontend/index.html index 1a0137a..4894646 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -2,7 +2,7 @@
-