Skip to content
Merged

V3 #28

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .codebeatignore

This file was deleted.

6 changes: 0 additions & 6 deletions .codebeatsettings

This file was deleted.

54 changes: 49 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,60 @@
name: Node.js CI
name: Build

on:
push:
branches: [master]
tags: ['*']
pull_request:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
quality:
name: Lint & format
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: 24.x
cache: npm

- name: Install dependencies
run: npm ci

- name: Check formatting
run: npm run format:check

- name: Lint
run: npm run lint

test:
name: Test (Node ${{ matrix.node-version }})
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
node-version: [lts/*]

node-version: [22.x, 24.x]
services:
redis:
image: redis:7
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand All @@ -20,9 +63,10 @@ jobs:
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: npm

- name: Install dependencies
run: npm install
run: npm ci

- name: Run tests
run: npm test
2 changes: 0 additions & 2 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
.gitignore
.travis.yml
.dockerignore
.codebeatignore
.codebeatsettings

.ssh/
dist/
Expand Down
9 changes: 9 additions & 0 deletions .oxfmtrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"singleQuote": true,
"tabWidth": 4,
"printWidth": 80,
"semi": true,
"trailingComma": "all",
"arrowParens": "avoid",
"bracketSpacing": true
}
37 changes: 37 additions & 0 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"categories": {
"correctness": "error"
},
"rules": {
"no-debugger": "error",
"no-console": ["warn", { "allow": ["warn", "error", "info"] }],
"no-unused-vars": "warn",
"no-unused-expressions": [
"error",
{ "allowShortCircuit": true, "allowTernary": true }
]
},
"overrides": [
{
"files": ["test/**"],
"rules": {
"no-unused-expressions": "off",
"no-async-promise-executor": "off",
"no-useless-catch": "off",
"unicorn/no-new-array": "off",
"unicorn/prefer-string-starts-ends-with": "off",
"unicorn/no-unnecessary-await": "off",
"no-unused-vars": "off"
}
}
],
"ignorePatterns": [
"**/*.js",
"**/*.d.ts",
"docs/",
"coverage/",
".nyc_output/",
"node_modules/"
]
}
68 changes: 68 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,74 @@ import { hello } from './clients/Hello';
In this case all complex types defined within service implementation
will be available under imported namespace of the client.

## Complex Types

To expose complex (object) types as service method arguments or return values,
annotate the class with `@classType()` and its fields with `@property()`:

~~~typescript
import { classType, property, expose, IMQService } from '@imqueue/rpc';

@classType()
class Address {
@property('string')
country: string;

@property('string', true)
zipCode?: string; // optional
}

@classType()
class User {
@property('string')
firstName: string;

@property('Array<Address>', true)
addresses?: Address[];
}

class UserService extends IMQService {
/**
* Persists the given user
*
* @param {User} user - user to save
* @returns {Promise<boolean>}
*/
@expose()
public async save(user: User): Promise<boolean> {
// User and Address are now exposed to generated clients
return true;
}
}
~~~

The `@classType()` class decorator is **required** on every class that uses
`@property()` — without it the type will not be registered and will not appear
in generated clients. (Indexed types use `@indexed()`, which registers `@property`
fields as well.)

## Requirements

This package uses **standard (TC39) decorators**. Consuming projects must set,
in their `tsconfig.json`:

~~~json
{
"compilerOptions": {
"experimentalDecorators": false,
"removeComments": false,
"lib": ["es2023", "esnext.decorators"]
}
}
~~~

Because standard decorators provide no runtime type reflection (there is no
`emitDecoratorMetadata`), the RPC layer derives argument and return types from
**JSDoc**. Therefore **every exposed method must be documented with JSDoc**
`@param`/`@returns` tags carrying the types (as shown in the examples above),
and `removeComments` must remain `false` so those comments survive compilation.
Undocumented parameters fall back to `any` in generated clients.

## Notes

For image containers builds assign machine UUID in `/etc/machine-id` and
Expand Down
Loading
Loading