Skip to content

Commit d0c319a

Browse files
committed
Updated dependency versions.
Added safety dupe checks in app start & load functions.
1 parent 6f11c44 commit d0c319a

File tree

6 files changed

+150
-103
lines changed

6 files changed

+150
-103
lines changed

COPYRIGHT

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Copyright 2024 Toreda, Inc. All Rights Reserved.
1+
Copyright 2025 Toreda, Inc. All Rights Reserved.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ We recommend `yarn` to manage project packages. Although you can use `npm instal
9797

9898
### *What are resolutions?*
9999

100-
Yarn `resolutions` support selective package version overrides used by the project & dependencies.
100+
Yarn `resolutions` allow per-package version overrides. All dependencies use the specified package version.
101101

102102
### *Why are there packages in the `resolutions` field?*
103103

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@
3636
},
3737
"homepage": "https://github.com/toreda/typescript-cli-starter#readme",
3838
"devDependencies": {
39-
"@swc/core": "^1.11.13",
40-
"@swc/jest": "^0.2.37",
39+
"@swc/core": "^1.11.24",
40+
"@swc/jest": "^0.2.38",
4141
"@toreda/build-tools": "^0.8.0",
4242
"@toreda/eslint-config": "^2.2.0",
4343
"@toreda/lifecycle": "^2.2.1",
@@ -52,13 +52,13 @@
5252
"@types/yargs": "^17.0.32",
5353
"@typescript-eslint/eslint-plugin": "^7.13.0",
5454
"@typescript-eslint/parser": "^7.13.0",
55-
"esbuild": "^0.25.1",
55+
"esbuild": "0.25.1",
5656
"esbuild-config": "^1.0.1",
5757
"esbuild-loader": "^4.3.0",
5858
"esbuild-node-externals": "^1.18.0",
59-
"eslint": "^9.23.0",
60-
"eslint-config-prettier": "^10.1.1",
61-
"eslint-plugin-prettier": "^5.2.5",
59+
"eslint": "^9.27.0",
60+
"eslint-config-prettier": "^10.1.5",
61+
"eslint-plugin-prettier": "^5.4.0",
6262
"fork-ts-checker-webpack-plugin": "^9.0.2",
6363
"gulp": "^5.0.0",
6464
"gulp-typescript": "^6.0.0-alpha.1",

src/app.ts

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import {AppConfig} from './app/config';
22
import type {CliArgs} from './cli/args';
33
import {Log} from '@toreda/log';
44
import {type ClientDelegate, ClientLifecycle, clientPhase} from '@toreda/lifecycle';
5+
import {Bool, boolMake} from '@toreda/strong-types';
6+
import {Defaults} from './defaults';
57

68
/**
79
* Example app class called by the CLI.
@@ -10,21 +12,62 @@ export class App implements ClientDelegate {
1012
public readonly lifecycle: ClientLifecycle;
1113
public readonly log: Log;
1214
public readonly cfg: AppConfig;
15+
private readonly loaded: Bool;
16+
private readonly running: Bool;
1317

1418
constructor(args: CliArgs, log: Log) {
1519
this.lifecycle = new ClientLifecycle();
1620
this.log = log;
1721

22+
this.loaded = boolMake(Defaults.App.Loaded);
23+
this.running = boolMake(Defaults.App.Running);
1824
this.cfg = new AppConfig(args, log);
25+
26+
this.bindListeners();
1927
}
2028

21-
public async start(): Promise<App> {
22-
this.log.info(`CLI App starting..`);
29+
private bindListeners(): void {
30+
this.load = this.load.bind(this);
31+
this.start = this.start.bind(this);
32+
}
2333

34+
public async load(): Promise<App> {
35+
// Ignore duplicate load calls after app finishes loading. Not strictly necessary
36+
// when `load` contains only Lifecycle phase calls as lifecycle methods set their own
37+
// flags to prevent dupe calls. Prevents problematic behavior if unprotected calls
38+
// are added in the future.
39+
if (this.loaded()) {
40+
return this;
41+
}
42+
await clientPhase('clientWillInit', this);
2443
await clientPhase('clientOnInit', this);
44+
await clientPhase('clientDidInit', this);
45+
46+
await clientPhase('clientWillLoad', this);
2547
await clientPhase('clientOnLoad', this);
48+
await clientPhase('clientDidLoad', this);
49+
50+
this.loaded(true);
51+
return this;
52+
53+
}
54+
55+
public async start(): Promise<App> {
56+
// Ignore dupe calls after app start. Lifecycle phases maintain their own flags
57+
// to prevent dupe calls, but other logic here isn't protected without the check.
58+
if (this.running()) {
59+
return this;
60+
}
61+
62+
this.log.info(`CLI App starting..`);
63+
await this.load();
64+
await clientPhase('clientWillStart', this);
2665
await clientPhase('clientOnStart', this);
66+
await clientPhase('clientDidStart', this);
67+
68+
await clientPhase('clientWillBecomeReady', this);
2769
await clientPhase('clientOnReady', this);
70+
await clientPhase('clientDidBecomeReady', this);
2871

2972
return this;
3073
}
@@ -42,7 +85,7 @@ export class App implements ClientDelegate {
4285

4386
this.log.debug(`CLI app init complete.`);
4487

45-
return this.lifecycle.phase('clientOnInit');
88+
return this.lifecycle.endPhase('clientOnInit');
4689
}
4790

4891
public async clientOnLoad(): Promise<boolean> {
@@ -53,7 +96,7 @@ export class App implements ClientDelegate {
5396
return false;
5497
}
5598

56-
return this.lifecycle.phase('clientOnLoad');
99+
return this.lifecycle.endPhase('clientOnLoad');
57100
}
58101

59102
public async clientOnStart(): Promise<boolean> {
@@ -64,7 +107,7 @@ export class App implements ClientDelegate {
64107
return false;
65108
}
66109

67-
return this.lifecycle.phase('clientOnStart');
110+
return this.lifecycle.endPhase('clientOnStart');
68111
}
69112

70113
public async clientOnReady(): Promise<boolean> {
@@ -75,7 +118,7 @@ export class App implements ClientDelegate {
75118
return false;
76119
}
77120

78-
return this.lifecycle.phase('clientOnReady');
121+
return this.lifecycle.endPhase('clientOnReady');
79122
}
80123

81124
public reset(): void {

src/defaults.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,9 @@ import type {Env} from './env';
55
*
66
*/
77
export class Defaults {
8+
public static App = {
9+
Loaded: false as const,
10+
Running: false as const
11+
} as const;
812
public static Env: Env = 'prod' as const;
913
}

0 commit comments

Comments
 (0)