Skip to content

Commit 4f97755

Browse files
committed
clean(data-access): remove bad fixes and simplify
1 parent ae79548 commit 4f97755

File tree

2 files changed

+45
-174
lines changed

2 files changed

+45
-174
lines changed

src/backend/src/modules/data-access/AppService.comp.test.js

Lines changed: 17 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -20,137 +20,6 @@ import AppService from './AppService';
2020

2121
import { describe, expect, it } from 'vitest';
2222

23-
/*
24-
// CRITICAL: Mock BOTH Context modules (CommonJS and ESM) BEFORE any other imports
25-
// CommonJS modules use '../../util/context', ESM modules use '../../util/esmcontext.js'
26-
vi.mock('../../util/context', async () => {
27-
const actual = await vi.importActual('../../util/context');
28-
const { Context: OriginalContext } = actual;
29-
30-
// Store original get method BEFORE patching
31-
const originalGet = OriginalContext.get;
32-
33-
// Store test values
34-
let testContext = null;
35-
let testActor = null;
36-
let testUser = null;
37-
38-
// Patch Context.get to use test values
39-
OriginalContext.get = function(key, options) {
40-
// Check test values FIRST
41-
if (key === 'actor' && testActor) {
42-
return testActor;
43-
}
44-
if (key === 'user' && testUser) {
45-
return testUser;
46-
}
47-
48-
// Call original get method
49-
return originalGet.call(this, key, options);
50-
};
51-
52-
// Export patched Context with setters for test values
53-
return {
54-
...actual,
55-
Context: OriginalContext,
56-
__setTestValues: (ctx, actor, user) => {
57-
testContext = ctx;
58-
testActor = actor;
59-
testUser = user;
60-
},
61-
__clearTestValues: () => {
62-
testContext = null;
63-
testActor = null;
64-
testUser = null;
65-
},
66-
};
67-
});
68-
69-
vi.mock('../../util/esmcontext.js', async () => {
70-
const actual = await vi.importActual('../../util/esmcontext.js');
71-
const { Context: OriginalContext } = actual;
72-
73-
// Store original get method BEFORE patching
74-
const originalGet = OriginalContext.get;
75-
76-
// Store test values
77-
let testContext = null;
78-
let testActor = null;
79-
let testUser = null;
80-
81-
// Patch Context.get to use test values
82-
OriginalContext.get = function(key, options) {
83-
// Check test values FIRST
84-
if (key === 'actor' && testActor) {
85-
return testActor;
86-
}
87-
if (key === 'user' && testUser) {
88-
return testUser;
89-
}
90-
91-
// Call original get method
92-
return originalGet.call(this, key, options);
93-
};
94-
95-
// Export patched Context with setters for test values
96-
return {
97-
...actual,
98-
Context: OriginalContext,
99-
__setTestValues: (ctx, actor, user) => {
100-
testContext = ctx;
101-
testActor = actor;
102-
testUser = user;
103-
},
104-
__clearTestValues: () => {
105-
testContext = null;
106-
testActor = null;
107-
testUser = null;
108-
},
109-
};
110-
});
111-
112-
// Store test values globally - this is the most reliable approach
113-
let globalTestActor = null;
114-
let globalTestUser = null;
115-
116-
// Patch Context.get directly (after imports) - this MUST work
117-
// We patch it on the actual Context class that's imported
118-
const originalContextGet = Context.get;
119-
Context.get = function(key, options) {
120-
// ALWAYS check global test values FIRST - this is the most reliable
121-
if (key === 'actor' && globalTestActor) {
122-
return globalTestActor;
123-
}
124-
if (key === 'user' && globalTestUser) {
125-
return globalTestUser;
126-
}
127-
// Call original
128-
return originalContextGet.call(this, key, options);
129-
};
130-
131-
// Also patch the Context class that CommonJS modules might have cached
132-
// Intercept require() calls to context.js and ensure they get our patched version
133-
const Module = require('module');
134-
const originalRequire = Module.prototype.require;
135-
Module.prototype.require = function(id) {
136-
const result = originalRequire.call(this, id);
137-
// If this is context.js, patch its Context.get
138-
if (id.includes('util/context') && result && result.Context) {
139-
const originalGet = result.Context.get;
140-
result.Context.get = function(key, options) {
141-
if (key === 'actor' && globalTestActor) {
142-
return globalTestActor;
143-
}
144-
if (key === 'user' && globalTestUser) {
145-
return globalTestUser;
146-
}
147-
return originalGet.call(this, key, options);
148-
};
149-
}
150-
return result;
151-
};
152-
*/
153-
15423
const ES_APP_ARGS = {
15524
entity: 'app',
15625
upstream: ESBuilder.create([
@@ -182,16 +51,15 @@ const ES_APP_ARGS = {
18251
]),
18352
};
18453

54+
// Fix: Manually initialize AsyncLocalStorage store for Vitest
55+
// Under Vitest, AsyncLocalStorage may not have a store initialized, causing Context.get() to fail.
56+
// This manually creates a store and sets the root context, ensuring Context operations work.
57+
// This may be a side-effect of OpenTelemetry's own use of AsyncLocalStorage.
18558
const fixContextInitialization = async (callback) => {
186-
process.stdout.write(`contextAsyncLocalStorage:${ Context.contextAsyncLocalStorage }\n`);
187-
try {
188-
return Context.contextAsyncLocalStorage.run(Context.root, () => {
189-
Context.contextAsyncLocalStorage.getStore().set('context', Context.root);
190-
callback();
191-
});
192-
} catch (e) {
193-
process.stdout.write(e.stack);
194-
}
59+
return await Context.contextAsyncLocalStorage.run(Context.root, async () => {
60+
Context.contextAsyncLocalStorage.getStore().set('context', Context.root);
61+
return await callback();
62+
});
19563
};
19664

19765
const testWithEachService = async (fnToRunOnBoth) => {
@@ -244,8 +112,6 @@ describe('AppService Regression Prevention Tests', () => {
244112
it('should create the app', async () => {
245113
await fixContextInitialization(async () => {
246114
await testWithEachService(async ({ kernel, key }) => {
247-
// Context initialization fix
248-
249115
// Create a test user and context
250116
const db = kernel.services.get('database').get('write', 'test');
251117
const userId = 1;
@@ -284,38 +150,15 @@ describe('AppService Regression Prevention Tests', () => {
284150

285151
await userContext.arun(async () => {
286152
Context.set('actor', actor);
287-
// Set test values in BOTH mocked Context modules AND globally
288-
// globalTestActor = actor;
289-
// globalTestUser = user;
290-
291-
const contextCJS = require('../../util/context');
292-
const contextESM = await import('../../util/esmcontext.js');
293-
if ( contextCJS.__setTestValues ) contextCJS.__setTestValues(userContext, actor, user);
294-
if ( contextESM.__setTestValues ) contextESM.__setTestValues(userContext, actor, user);
295-
296-
process.stdout.write(`actor: ${actor}\n`);
297-
process.stdout.write(`context root from test: ${Context.get('rootContextUUID')}\n`);
298-
299-
try {
300-
const service = kernel.services.get(key);
301-
const crudQ = service.constructor.IMPLEMENTS['crud-q'];
302-
await crudQ.create.call(service, {
303-
object: {
304-
name: 'test-app',
305-
title: 'Test App',
306-
index_url: 'https://example.com',
307-
},
308-
});
309-
} finally {
310-
// Clear after test
311-
// globalTestActor = null;
312-
// globalTestUser = null;
313-
314-
const contextCJS = require('../../util/context');
315-
const contextESM = await import('../../util/esmcontext.js');
316-
if ( contextCJS.__clearTestValues ) contextCJS.__clearTestValues();
317-
if ( contextESM.__clearTestValues ) contextESM.__clearTestValues();
318-
}
153+
const service = kernel.services.get(key);
154+
const crudQ = service.constructor.IMPLEMENTS['crud-q'];
155+
await crudQ.create.call(service, {
156+
object: {
157+
name: 'test-app',
158+
title: 'Test App',
159+
index_url: 'https://example.com',
160+
},
161+
});
319162
});
320163
});
321164
});

src/backend/src/util/esmcontext.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (C) 2026-present Puter Technologies Inc.
3+
*
4+
* This file is part of Puter.
5+
*
6+
* Puter is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published
8+
* by the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
20+
// Bridge file to ensure ES modules and CommonJS modules use the same Context instance
21+
// This file uses require() to load context.js, ensuring compatibility with
22+
// CommonJS modules that also require() context.js
23+
const { Context, ContextExpressMiddleware } = require('./context.js');
24+
25+
module.exports = {
26+
Context,
27+
ContextExpressMiddleware,
28+
};

0 commit comments

Comments
 (0)