Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
N
nfkit
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
nfkit
Commits
c584a517
Commit
c584a517
authored
Feb 08, 2026
by
nanahira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mid
parent
adbfce6d
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
107 additions
and
36 deletions
+107
-36
src/app-context/app-context.ts
src/app-context/app-context.ts
+35
-13
src/app-context/app-service-base.ts
src/app-context/app-service-base.ts
+2
-2
src/app-context/types.ts
src/app-context/types.ts
+70
-21
No files found.
src/app-context/app-context.ts
View file @
c584a517
...
...
@@ -11,42 +11,59 @@ import {
const
ServiceClassPrefix
=
'
class:
'
;
const
ProvidePrefix
=
'
provide:
'
;
export
class
AppContextCore
<
T
=
Empty
,
Req
=
Empty
>
{
private
__current
:
T
;
export
class
AppContextCore
<
Cur
=
Empty
,
Req
=
Empty
>
{
private
__current
:
Cur
;
private
__required
:
Req
;
registry
=
new
Map
<
string
,
any
>
();
loadSeq
:
any
[]
=
[];
provide
<
C
extends
AppServiceClass
<
T
>
,
C
extends
AppServiceClass
<
Cur
>
,
const
P
extends
string
=
''
,
const
M
extends
(
keyof
InstanceType
<
C
>
)[]
=
[],
>
(
cls
:
C
,
...
args
:
AppProvideArgs
<
T
,
C
,
P
,
M
>
):
AppProvidedMerged
<
T
,
Req
,
C
,
P
,
M
>
{
...
args
:
AppProvideArgs
<
Cur
,
Req
,
C
,
P
,
M
>
):
AppProvidedMerged
<
Cur
,
Req
,
C
,
P
,
M
>
{
const
options
=
args
[
args
.
length
-
1
]
as
|
AppProvideOptions
<
T
,
C
,
P
,
M
>
|
AppProvideOptions
<
Cur
,
Req
,
C
,
P
,
M
>
|
undefined
;
const
_args
:
ConstructorParameters
<
C
>
=
args
;
const
inst
=
options
?.
useValue
??
(
options
?.
useFactory
?
options
.
useFactory
(
this
as
any
,
...
_args
)
:
new
(
options
?.
useClass
??
cls
)(
this
as
any
,
_args
));
this
.
registry
.
set
(
ServiceClassPrefix
+
cls
.
name
,
inst
);
return
this
as
any
;
}
get
<
R
>
(
cls
:
AppServiceClass
<
T
,
any
,
R
>
):
R
{}
get
<
R
>
(
cls
:
AppServiceClass
<
Cur
,
Req
,
any
,
R
>
):
R
{}
getAsync
<
R
>
(
cls
:
AppServiceClass
<
Cur
,
Req
,
any
,
R
>
):
Promise
<
R
>
{}
use
<
T2
>
(
ctx
:
AppContext
<
T2
,
T
>
):
AppContext
<
Prettify
<
T
&
T2
>
,
Req
>
{
use
<
const
Ctxes
extends
AppContext
<
any
,
any
>
[]
>
(
...
ctxes
:
Ctxes
):
AppContextUsed
<
Cur
,
Req
,
Ctxes
>
{
return
this
as
any
;
}
define
():
AppContext
<
T
,
Req
>
{
define
():
AppContext
<
Cur
,
Req
>
{
return
this
as
any
;
}
async
start
():
Promise
<
AppContext
<
T
,
Req
>
>
{
async
start
():
Promise
<
Empty
extends
Req
?
AppContext
<
Cur
,
Req
>
:
never
>
{
return
this
as
any
;
}
}
export
const
createAppContext
=
<
Req
=
Empty
>
()
=>
new
AppContextCore
<
Req
,
Req
>
()
as
AppContext
<
Req
,
Req
>
;
new
AppContextCore
<
Empty
,
Req
>
()
as
AppContext
<
Empty
,
Req
>
;
// testing code below
...
...
@@ -86,7 +103,6 @@ async function test() {
.
provide
(
Bar
,
5
,
{
merge
:
[
'
getBar
'
],
})
.
provide
(
Foo
,
3
,
{
provide
:
'
foo22
'
})
.
define
();
const
ctx2
=
createAppContext
<
{
foo
:
Foo
}
>
()
...
...
@@ -95,5 +111,11 @@ async function test() {
})
.
define
();
const
ctx
=
await
createAppContext
().
use
(
ctx2
).
define
().
start
();
const
ctx2Used
=
await
createAppContext
().
use
(
ctx2
).
define
().
start
();
const
final
=
await
createAppContext
().
use
(
ctx1
).
use
(
ctx2
).
define
().
start
();
const
reversed
=
await
createAppContext
()
.
use
(
ctx2
)
.
use
(
ctx1
)
.
define
()
.
start
();
}
src/app-context/app-service-base.ts
View file @
c584a517
import
{
Empty
}
from
'
../types
'
;
import
{
AppContext
}
from
'
./types
'
;
export
class
AppServiceBase
<
T
=
Empty
,
Config
extends
any
[]
=
[]
>
{
export
class
AppServiceBase
<
Cur
=
Empty
,
Config
extends
any
[]
=
[]
>
{
constructor
(
public
ctx
:
AppContext
<
T
>
,
public
ctx
:
AppContext
<
Cur
>
,
...
args
:
Config
)
{}
...
...
src/app-context/types.ts
View file @
c584a517
import
{
Awaitable
,
Empty
,
Prettify
}
from
'
../types
'
;
import
{
AppContextCore
}
from
'
./app-context
'
;
export
type
AppContext
<
T
=
Empty
,
Req
=
Empty
>
=
AppContextCore
<
T
,
Req
>
&
T
;
type
CurAndReq
<
Cur
,
Req
>
=
{
[
K
in
keyof
Cur
|
keyof
Req
]:
K
extends
keyof
Cur
?
Cur
[
K
]
:
K
extends
keyof
Req
?
Req
[
K
]
:
never
;
};
export
type
AppContext
<
Cur
=
Empty
,
Req
=
Empty
>
=
AppContextCore
<
Cur
,
Req
>
&
CurAndReq
<
Cur
,
Req
>
;
export
type
AppServiceClass
<
T
=
Empty
,
A
extends
any
[]
=
any
[],
R
=
any
>
=
new
(
ctx
:
AppContext
<
T
>
,
...
args
:
A
)
=>
R
;
export
type
AppServiceClass
<
Cur
=
Empty
,
Req
=
Empty
,
A
extends
any
[]
=
any
[],
R
=
any
,
>
=
new
(
ctx
:
AppContext
<
Cur
,
Req
>
,
...
args
:
A
)
=>
R
;
export
type
AppServiceConfig
<
C
extends
AppServiceClass
>
=
C
extends
new
(
first
:
any
,
...
...
@@ -16,39 +27,77 @@ export type AppServiceConfig<C extends AppServiceClass> = C extends new (
:
never
;
export
type
AppProvideOptions
<
T
,
C
extends
AppServiceClass
<
T
>
,
Cur
,
Req
,
C
extends
AppServiceClass
<
Cur
>
,
P
extends
string
,
M
extends
(
keyof
InstanceType
<
C
>
)[],
>
=
{
provide
?:
P
;
merge
?:
M
;
useValue
?:
InstanceType
<
C
>
;
useValue
?:
Awaitable
<
InstanceType
<
C
>
>
;
useFactory
?:
(
ctx
:
AppContext
<
T
>
,
ctx
:
AppContext
<
Cur
,
Req
>
,
...
args
:
ConstructorParameters
<
C
>
)
=>
Awaitable
<
InstanceType
<
C
>>
;
useClass
?:
new
(...
args
:
ConstructorParameters
<
C
>
)
=>
InstanceType
<
C
>
;
};
export
type
AppProvideArgs
<
T
,
C
extends
AppServiceClass
<
T
>
,
Cur
,
Req
,
C
extends
AppServiceClass
<
Cur
>
,
P
extends
string
,
M
extends
(
keyof
InstanceType
<
C
>
)[],
>
=
[...
args
:
AppServiceConfig
<
C
>
,
options
?:
AppProvideOptions
<
T
,
C
,
P
,
M
>
];
>
=
[
...
args
:
AppServiceConfig
<
C
>
,
options
?:
AppProvideOptions
<
Cur
,
Req
,
C
,
P
,
M
>
,
];
type
CurResolved
<
Cur
,
Req
,
Cur2
,
Req2
>
=
Prettify
<
Cur
&
Cur2
>
;
type
ResolveReq
<
Provided
,
Req
>
=
{
[
K
in
keyof
Req
as
K
extends
keyof
Provided
?
Provided
[
K
]
extends
Req
[
K
]
?
never
// ✅ 满足 → 删除
:
K
// ❌ 类型不匹配 → 保留
:
K
]:
Req
[
K
];
// ❌ 没提供 → 保留
};
type
ReqResolved
<
Cur
,
Req
,
Cur2
,
Req2
>
=
Prettify
<
ResolveReq
<
Cur
&
Cur2
,
Req
&
Req2
>
>
;
type
AppContextResolved
<
Cur
,
Req
,
Cur2
,
Req2
>
=
AppContext
<
CurResolved
<
Cur
,
Req
,
Cur2
,
Req2
>
,
ReqResolved
<
Cur
,
Req
,
Cur2
,
Req2
>
>
;
export
type
AppProvidedMerged
<
T
,
Cur
,
Req
,
C
extends
AppServiceClass
<
any
>
,
C
extends
AppServiceClass
<
any
,
any
>
,
P
extends
string
,
M
extends
(
keyof
InstanceType
<
C
>
)[],
>
=
AppContext
<
Prettify
<
T
&
{
[
K
in
M
[
number
]]:
InstanceType
<
C
>
[
K
];
}
&
(
P
extends
''
?
Empty
:
{
[
K
in
P
]:
InstanceType
<
C
>
})
>
,
Req
>
=
AppContext
Resolved
<
Cur
,
Req
,
{
[
K
in
M
[
number
]]:
InstanceType
<
C
>
[
K
];
}
&
(
P
extends
''
?
Empty
:
{
[
K
in
P
]:
InstanceType
<
C
>
})
,
Empty
>
;
export
type
AppContextUsed
<
Cur
,
Req
,
Ctxes
extends
AppContext
<
any
,
any
>
[],
>
=
Ctxes
extends
[]
?
AppContext
<
Cur
,
Req
>
:
Ctxes
extends
[
infer
First
,
...
infer
Rest
extends
AppContext
<
any
,
any
>
[]]
?
First
extends
AppContext
<
infer
Cur2
,
infer
Req2
>
?
AppContextUsed
<
CurResolved
<
Cur
,
Req
,
Cur2
,
Req2
>
,
ReqResolved
<
Cur
,
Req
,
Cur2
,
Req2
>
,
Rest
>
:
never
:
never
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment