This release contains a lot of bugfixes and features. We're working towards the first beta release. You can read more about what is included in the beta in its milestone: https://github.com/deepkit/deepkit-framework/milestone/1
Features
- new ProgressTracker abstraction (2a36a12, c2e6be8, a8d3c95, 3483e20)
This new abstraction allows to monitor remote progress of a long-running task with a way to abort it.
class MyController {
@rpc.action()
async startMigration(): Promise<ProgressTracker> {
const progressTracker = new ProgressTracker();
const total = 100;
const track = progressTracker.track('migration', total); //multiple tracks are possible
setTimeout(async () => {
for (let i = 0; i < total; i++) {
if (!track.running) break; //user aborted
//to some heavy work
//both will be streamed to the client
track.message = `migration: ${table}`;
track.done++;
}
});
return progressTracker;
}
}
const controller = rpcClient.controller<MyController>('/controller');
const progress = await controller.startMigration();
progress.subscribe(() => {
console.log(`progress: ${progress.done}/${progress.total}: ${progress.message}`);
});
abortButton.onclick = () => progress.stop();
In @deepkit/desktop-ui there is now a new component that shows progress
:
<dui-progress-indicator display="vertical" [progressTracker]="progress"></dui-progress-indicator>
Screen.Recording.2023-05-01.at.21.35.33.mov
-
Core: Add range and zip functions (3dcb39c)
Same as in Python -
Core-RxJS: Add decoupleSubject + more docs (850b99a)
In order to send RXJS shared Subject/BehaviourSubject/ProgressTracker to the client, you can now use decoupleSubject,
so that the origin subject will not be completed when the client disconnects or manually completes.
//a service not part of 'rpc' scope, so its shared between all clients
class AppState {
progresses: { [id: number]: ProgressTracker } = {};
}
class MyController {
constructor(private state: AppState) {
}
@rpc.action()
getProgress(id: number): ProgressTracker {
//multiple clients can access the progress
return decoupleSubject(this.state.progresses[id]);
}
@rpc.action()
startProgress(id: number): ProgressTracker {
this.state.progresses[id] = new ProgressTracker();
}
}
-
RPC: Make RpcKernelSecurity scoped (d2740e8)
This allows to inject
rpc
scoped providers into the security class. -
Type: Add to validation errors the value that caused the error (98fa1ab)
This allows to show the value that caused the error in the validation error message.
const oldError = { code: 'minLength', message: 'Min length is 3', path: 'username' }
const newError = { code: 'minLength', message: 'Min length is 3', path: 'username', value: 'Pe' }
-
Type: TypedFormGroup supports now new Angular version (7966ac5)
With this change you can use TypedFormGroup with Angular 14+.
-
Type: Implement call signatures in object literals (ece8c02)
With this change it's now supported to read call signatures from TypeScript types.
interface Caller {
(a: number): string;
}
const type = typeOf<Caller>();
assertType(type, ReflectionKind.objectLiteral);
for (const member of resolveTypeMembers(type)) {
//one member will be of kind ReflectionKind.callSignature
}
-
Type: Allow working with null objects (2e3f454)
This change allows to work with null objects (objects created via
Object.create(null)
). -
Type-Compiler: Use TS config resolution code to resolve reflection options (bb2ac7e)
This is an important change in the way the Type-Compiler resolves tsconfig options.
The old way was our own tsconfig.json resolution algorithm, but with this change we read
CompilerOptions.configFilePath
which is much more correct. -
Type-Compiler: Support esm module (48de497)
This should enable the use of @deepkit/type-compiler in ESM environments.
-
Type-Compiler: Print correct module specifier when module was not found (06e3876)
-
Type-Compiler: Load
compilerOptions.paths
manually if not provided (d872afc) -
Injector: Allow using sub configuration classes as dependency (ba7c68e)
Application configurations can now be split into multiple classes and still be used as dependency.
class DatabaseConfig {
host: string = 'localhost';
port: number = 3306;
}
class AppConfiguration {
database: DatabaseConfig = new DatabaseConfig;
}
class Database {
//refering to a child of `AppConfiguration` is new!
constructor(config: DatabaseConfig) {
}
}
const app = new App({
config: AppConfiguration,
providers: [
Database
]
}).run();
-
Mongo: Adds support for expireAfterSeconds index (81765c5)
-
Mongo: Adds export for FindAndModifyCommand to allow $rename (6a00da9)
-
Mongo: Adds export for AggregateCommand to allow custom queries (7f6b4b3)
-
Mongo: Adds export for UpdateCommand to allow custom queries (4d627d2)
-
API-Console-GUI: Show the route description with white-space:pre-wrap to respect the newlines the developer used in description for formatting (058f090)
-
HTTP: Graceful shutdown including waiting for active http requests (09fb4d5)
-
HTTP: Add thrown
Error
in controller to http.OnAccessDenied event (53ffb33) -
HTTP: Add support for DI auto-wiring in methods of event class listeners (ff432d8)
-
HTTP: Allow injecting http values (query/path/header) into http listener (01c24c4)
This allows to inject services and HTTP request data into http listeners the same way as it is possible in routes.
@http.controller('/:groupId')
class Controller {
@http.GET('/:userId')
handle(userId: number, request: HttpRequest) {
// ...
}
}
class Listener {
@eventDispatcher.listen(httpWorkflow.onController)
handle(event: typeof httpWorkflow.onController.event, groupId: HttpPath<number>) {
// access to the route path parameter `:groupId`
}
}
-
HTTP: Handle HttpError errors in parameter resolver (0ead2fe)
Additionally, to HttpQuery, HttpBody, HttpQueries it's now possible to inject header values.
class Controller {
@http.GET('/:userId')
handle(userId: number, authorization: HttpHeader<string>) {
// access HTTP 'authorization' header
}
}
-
HTTP: Allow reading parameter object (name -> value) for a route in onController event (6872dee)
-
Desktop-UI: Add new state abstraction (e786f09)
This introduces a new state abstraction model for complex applications. It allows to register
a class with properties and methods as state. The state is monitored and change-detection (as well as state persistence)
triggered automatically. Properties marked asPartOfUrl
will be persisted automatically in the URL (query parameter).
class State extends EfficientState {
// stored in URL
shop: number & PartOfUrl = 0;
// stored in localStorage
sidebarVisible: boolean = true;
}
@NgModule({
providers: [
provideState(State)
],
})
export class AppModule {
}
@Component({
template: `
Store: {{state.shop}}
<!-- This triggers state listeners and changes the URL since PartOfUrl -- >
<dui-button(click) = 'state.shop = 2' > Change < /dui-button>
`
})
class Component {
constructor(public state: State) {
}
}
-
Desktop-UI: Table freezed columns support (e786f09)
This allows to freeze columns in a table. The user can then scroll the table horizontally and the frozen columns
will stay visible.
<dui-table [items]="items" [freezeColumns]="1">
// ...
</dui-table>
Screen.Recording.2023-05-01.at.21.25.10.mov
- Desktop-UI: Tab-button: remove [model] API (5b1e015)
- Desktop-IO: Hotkey component, animated duiDialog (like quick-look macOS) (327c35c)
This feature allows to attach hotkeys to arbitrary dui-buttons.
<dui-button hotkey="meta+s">Save</dui-button>
The user can now press cmd+s
to trigger the button. When alt (or option on macOS) is pressed,
the button will reveal its keymap.
Screen.Recording.2023-05-01.at.21.24.39.mov
-
ORM: Support RegExp directly as filter value + case-insensitive filter (b14fca2)
-
ORM: Support Query.use in joins (2ac4866)
-
ORM: Add Query.use/Query.fetch method to allow more dynamic query composition (ee439cd)
-
Add everywhere .js extension to support ESM (2fd3dda)
This should be it possible to use Deepkit Framework in ESM environments.
Fixes
- Logger: Maintain logger level when scoped logger is created (f590558)
- Type: Default assignment for optional literals (05247ae)
- Type: Treat
keyof this
asany
so that it does not work in a strange unexpected way (e02fa0d) - Logger: Don't use rawMessage in JSONTransport so that color xml is removed (e1f956c)
- RPC: Unwrap type only to determine inner type, don't use as return type (9898223)
- Core: Move reflection option for database tests to it matches latest compiler changes (f938643)
- Core: Remove debug statement + set compiler host only when not overridden (713bd1c)
- Core: Removed debug statements (dc3abbc)
- Core: Invalid json syntax in tsconfig (ac093c8)
- Type-Compiler: Make sure only TS/TSX files are processed by the transformer (c4c508a)
- Type-Compiler: Duplicate method (48730fb)
- Injector: Missing factoryDependencyNotFound function in resolver compiler context (e0f3a1a)
- Type: Typo in error message (2a79e5a)
- SQL: Disconnect on test end (f836247)
- SQL: Array element serialization (f7d6c22)
- SQL: Patch PK extraction when there were no modified rows (535ba29)
- Bump Node to current LTS (18.x) (5503563)
- ORM: Apply joins to preloaded entities from previous joins (aa90b17)
- HTTP: Enable streaming tests (c62906b)
- Angular-Universal: Adjust to new http parameter structure (e2accfb)
- Use cross-environment
globalThis
to access the global object (7af681b) - Create-App: Remove .js extension for the files being created (1164205)
- Template: Correct execution of functional components (8bd19c4)
- Framework: Http worker wrong options + rpc for https (fabc163)
- ORM-Browser: Support detecting wss:// (c0d51f0)
New Contributors
- @T-Hugs made their first contribution in #416
- @hidemire made their first contribution in #417
- @marcus-sa made their first contribution in #426
Full Changelog: v1.0.1-alpha.87...v1.0.1-alpha.93