@@ -130,3 +130,101 @@ test("normalizeOrderBy: SDK field 与遗留 col / 数组互通(LSP)", async () =
130130 ] ) ;
131131 throws ( ( ) => normalizeOrderBy ( { dir : "asc" } ) , / f i e l d \/ c o l / ) ;
132132} ) ;
133+
134+ test ( "module-auth: ensureModuleToken / revoke 复用 secret(DRY)" , async ( ) => {
135+ const { deriveToken, ensureModuleToken, revokeModuleToken } = await import ( "./module-auth.js" ) ;
136+ const secret = "test-secret" ;
137+ const auth = { secret, tokens : { } as Record < string , string > } ;
138+ equal ( ensureModuleToken ( auth , "feature-afk" ) , true ) ;
139+ equal ( auth . tokens [ "feature-afk" ] , deriveToken ( "feature-afk" , secret ) ) ;
140+ equal ( ensureModuleToken ( auth , "feature-afk" ) , false ) ;
141+ equal ( revokeModuleToken ( auth , "feature-afk" ) , true ) ;
142+ equal ( auth . tokens [ "feature-afk" ] , undefined ) ;
143+ equal ( revokeModuleToken ( auth , "feature-afk" ) , false ) ;
144+ } ) ;
145+
146+ test ( "builtin-handlers: 热禁用按 serviceNames 卸载(OCP)" , async ( ) => {
147+ const { BUILTIN_SERVICE_PLUGINS , unregisterBuiltinPluginForModule } = await import (
148+ "./services/builtin-handlers.js"
149+ ) ;
150+ const economy = BUILTIN_SERVICE_PLUGINS . find ( ( p ) => p . moduleId === "feature-economy" ) ;
151+ equal ( ! ! economy ?. serviceNames ?. includes ( "economy.account.get" ) , true ) ;
152+
153+ const reg = new ServiceRegistry ( ) ;
154+ reg . registerHandler ( "feature-economy" , "economy.account.get" , async ( ) => ( { } ) ) ;
155+ reg . registerHandler ( "feature-economy" , "economy.account.debit" , async ( ) => ( { } ) ) ;
156+ equal ( unregisterBuiltinPluginForModule ( reg , "feature-economy" ) , 2 ) ;
157+ equal ( reg . list ( ) . length , 0 ) ;
158+ equal ( unregisterBuiltinPluginForModule ( reg , "feature-unknown" ) , 0 ) ;
159+ } ) ;
160+
161+ test ( "TxRunner 交互会话: step 中途读回 insert/get(PR #31 leftover)" , async ( ) => {
162+ const { DatabaseSync } = await import ( "node:sqlite" ) ;
163+ const { createQuery } = await import ( "./lib/sqlite.js" ) ;
164+ const { SchemaRegistry } = await import ( "./schema-registry.js" ) ;
165+ const { TxRunner } = await import ( "./tx-runner.js" ) ;
166+
167+ const db = new DatabaseSync ( ":memory:" ) ;
168+ const query = createQuery ( db ) ;
169+ const schema = new SchemaRegistry ( db ) ;
170+ schema . define ( "feature-demo" , {
171+ name : "demo_items" ,
172+ columns : {
173+ id : { type : "text" , primary : true } ,
174+ name : { type : "text" , notNull : true } ,
175+ } ,
176+ softDelete : false ,
177+ } ) ;
178+
179+ const enabled = new Map ( [
180+ [
181+ "feature-demo" ,
182+ {
183+ id : "feature-demo" ,
184+ version : "1.0.0" ,
185+ permissions : [ "db:read:demo_items" , "db:write:demo_items" ] ,
186+ services : { provides : [ ] , requires : [ ] } ,
187+ db : { tables : [ ] } ,
188+ config : { key : "demo" } ,
189+ } as unknown as import ( "./manifest-loader.js" ) . ModuleManifestV2 ,
190+ ] ,
191+ ] ) ;
192+
193+ const runner = new TxRunner ( {
194+ db,
195+ query,
196+ schema,
197+ serviceRegistry : new ServiceRegistry ( ) ,
198+ enabled,
199+ } ) ;
200+
201+ const begin = runner . beginSession ( "feature-demo" ) ;
202+ equal ( begin . ok , true ) ;
203+ if ( ! begin . ok ) return ;
204+ const { txId } = begin ;
205+
206+ const ins = await runner . stepSession ( txId , "feature-demo" , {
207+ op : "insert" ,
208+ table : "demo_items" ,
209+ row : { id : "a1" , name : "alpha" } ,
210+ } ) ;
211+ equal ( ins . ok , true ) ;
212+ if ( ! ins . ok ) return ;
213+ equal ( ( ins . result as { op : string ; row : { id : string } } ) . row . id , "a1" ) ;
214+
215+ const got = await runner . stepSession ( txId , "feature-demo" , {
216+ op : "get" ,
217+ table : "demo_items" ,
218+ id : "a1" ,
219+ } ) ;
220+ equal ( got . ok , true ) ;
221+ if ( ! got . ok ) return ;
222+ equal ( ( got . result as { row : { name : string } | null } ) . row ?. name , "alpha" ) ;
223+
224+ const committed = runner . commitSession ( txId , "feature-demo" ) ;
225+ equal ( committed . ok , true ) ;
226+
227+ const rows = db . prepare ( "SELECT name FROM demo_items WHERE id = ?" ) . all ( "a1" ) as Array < { name : string } > ;
228+ equal ( rows [ 0 ] ?. name , "alpha" ) ;
229+ db . close ( ) ;
230+ } ) ;
0 commit comments