feat: Add debug script for field defaults and enhance Jest configuration for ES modules
This commit is contained in:
parent
1e3c5d46be
commit
831c977eda
44
debug_fields.js
Normal file
44
debug_fields.js
Normal file
@ -0,0 +1,44 @@
|
||||
// Simple debug script to test field defaults
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
// Run a small test using jest directly
|
||||
const testCode = `
|
||||
import { BaseModel } from './src/framework/models/BaseModel';
|
||||
import { Model, Field } from './src/framework/models/decorators';
|
||||
|
||||
@Model({
|
||||
scope: 'global',
|
||||
type: 'docstore'
|
||||
})
|
||||
class TestUser extends BaseModel {
|
||||
@Field({ type: 'string', required: true })
|
||||
username: string;
|
||||
|
||||
@Field({ type: 'number', required: false, default: 0 })
|
||||
score: number;
|
||||
|
||||
@Field({ type: 'boolean', required: false, default: true })
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
// Debug the fields
|
||||
console.log('TestUser.fields:', TestUser.fields);
|
||||
console.log('TestUser.fields size:', TestUser.fields?.size);
|
||||
|
||||
if (TestUser.fields) {
|
||||
for (const [fieldName, fieldConfig] of TestUser.fields) {
|
||||
console.log(\`Field: \${fieldName}, Config:\`, fieldConfig);
|
||||
}
|
||||
}
|
||||
|
||||
// Test instance creation
|
||||
const user = new TestUser();
|
||||
console.log('User instance score:', user.score);
|
||||
console.log('User instance isActive:', user.isActive);
|
||||
|
||||
// Check private fields
|
||||
console.log('User _score:', (user as any)._score);
|
||||
console.log('User _isActive:', (user as any)._isActive);
|
||||
`;
|
||||
|
||||
console.log('Test code created for debugging...');
|
@ -1,13 +1,17 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
preset: 'ts-jest/presets/default-esm',
|
||||
testEnvironment: 'node',
|
||||
roots: ['<rootDir>/tests/real'],
|
||||
testMatch: ['**/real/**/*.test.ts'],
|
||||
|
||||
// ES Module configuration
|
||||
extensionsToTreatAsEsm: ['.ts'],
|
||||
|
||||
transform: {
|
||||
'^.+\\.ts$': [
|
||||
'ts-jest',
|
||||
{
|
||||
isolatedModules: true,
|
||||
useESM: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -28,9 +32,6 @@ module.exports = {
|
||||
// Environment variables for real tests
|
||||
setupFilesAfterEnv: ['<rootDir>/tests/real/jest.setup.ts'],
|
||||
|
||||
// Longer timeout for setup/teardown
|
||||
setupFilesTimeout: 120000,
|
||||
|
||||
// Disable watch mode (real tests are too slow)
|
||||
watchman: false,
|
||||
|
||||
@ -44,9 +45,18 @@ module.exports = {
|
||||
// Fail fast on first error (saves time with slow tests)
|
||||
bail: 1,
|
||||
|
||||
// Module path mapping
|
||||
moduleNameMapping: {
|
||||
'^@/(.*)$': '<rootDir>/src/$1',
|
||||
'^@tests/(.*)$': '<rootDir>/tests/$1'
|
||||
}
|
||||
// ES Module support
|
||||
extensionsToTreatAsEsm: ['.ts'],
|
||||
|
||||
// Transform ES modules - more comprehensive pattern
|
||||
transformIgnorePatterns: [
|
||||
'node_modules/(?!(helia|@helia|@orbitdb|@libp2p|@chainsafe|@multiformats|multiformats|datastore-fs|blockstore-fs|libp2p)/)',
|
||||
],
|
||||
|
||||
// Module resolution for ES modules
|
||||
resolver: undefined,
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], // Module name mapping to handle ES modules
|
||||
moduleNameMapper: {
|
||||
'^(\\.{1,2}/.*)\\.js$': '$1',
|
||||
},
|
||||
};
|
@ -27,7 +27,7 @@
|
||||
"test:e2e": "jest tests/e2e",
|
||||
"test:real": "jest --config jest.real.config.cjs",
|
||||
"test:real:debug": "REAL_TEST_DEBUG=true jest --config jest.real.config.cjs",
|
||||
"test:real:basic": "jest --config jest.real.config.cjs tests/real/basic-integration.test.ts",
|
||||
"test:real:basic": "jest --config jest.real.config.cjs tests/real/real-integration.test.ts",
|
||||
"test:real:p2p": "jest --config jest.real.config.cjs tests/real/peer-discovery.test.ts"
|
||||
},
|
||||
"keywords": [
|
||||
|
@ -6,11 +6,20 @@ module.exports = async () => {
|
||||
process.env.NODE_ENV = 'test';
|
||||
process.env.DEBROS_TEST_MODE = 'real';
|
||||
|
||||
// Check for required dependencies
|
||||
// Check for required dependencies - skip for ES module packages
|
||||
try {
|
||||
require('helia');
|
||||
require('@orbitdb/core');
|
||||
// Just check if the packages exist without importing them
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const heliaPath = path.join(__dirname, '../../node_modules/helia');
|
||||
const orbitdbPath = path.join(__dirname, '../../node_modules/@orbitdb/core');
|
||||
|
||||
if (fs.existsSync(heliaPath) && fs.existsSync(orbitdbPath)) {
|
||||
console.log('✅ Required dependencies available');
|
||||
} else {
|
||||
throw new Error('Required packages not found');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Missing required dependencies for real tests:', error.message);
|
||||
process.exit(1);
|
||||
|
@ -11,10 +11,20 @@ const debugMode = process.env.REAL_TEST_DEBUG === 'true';
|
||||
if (!debugMode) {
|
||||
// Silence routine logs but keep errors and important messages
|
||||
console.log = (...args: any[]) => {
|
||||
const message = args.join(' ');
|
||||
try {
|
||||
const message = args.map(arg => {
|
||||
if (typeof arg === 'string') return arg;
|
||||
if (typeof arg === 'object' && arg !== null) return JSON.stringify(arg);
|
||||
return String(arg);
|
||||
}).join(' ');
|
||||
|
||||
if (message.includes('❌') || message.includes('✅') || message.includes('🚀') || message.includes('🧹')) {
|
||||
originalConsole.log(...args);
|
||||
}
|
||||
} catch (_error) {
|
||||
// Fallback to original console if there's any issue
|
||||
originalConsole.log(...args);
|
||||
}
|
||||
};
|
||||
|
||||
console.info = () => {}; // Silence info
|
||||
|
66
tests/real/setup/helia-wrapper.ts
Normal file
66
tests/real/setup/helia-wrapper.ts
Normal file
@ -0,0 +1,66 @@
|
||||
// Manual wrapper for ES modules to work with Jest
|
||||
// This file provides CommonJS-compatible interfaces for pure ES modules
|
||||
|
||||
// Synchronous wrappers that use dynamic imports with await
|
||||
export async function loadModules() {
|
||||
const [
|
||||
heliaModule,
|
||||
libp2pModule,
|
||||
tcpModule,
|
||||
noiseModule,
|
||||
yamuxModule,
|
||||
gossipsubModule,
|
||||
identifyModule,
|
||||
] = await Promise.all([
|
||||
import('helia'),
|
||||
import('libp2p'),
|
||||
import('@libp2p/tcp'),
|
||||
import('@chainsafe/libp2p-noise'),
|
||||
import('@chainsafe/libp2p-yamux'),
|
||||
import('@chainsafe/libp2p-gossipsub'),
|
||||
import('@libp2p/identify'),
|
||||
]);
|
||||
|
||||
return {
|
||||
createHelia: heliaModule.createHelia,
|
||||
createLibp2p: libp2pModule.createLibp2p,
|
||||
tcp: tcpModule.tcp,
|
||||
noise: noiseModule.noise,
|
||||
yamux: yamuxModule.yamux,
|
||||
gossipsub: gossipsubModule.gossipsub,
|
||||
identify: identifyModule.identify,
|
||||
};
|
||||
}
|
||||
|
||||
// Separate async loader for OrbitDB
|
||||
export async function loadOrbitDBModules() {
|
||||
const orbitdbModule = await import('@orbitdb/core');
|
||||
|
||||
return {
|
||||
createOrbitDB: orbitdbModule.createOrbitDB,
|
||||
};
|
||||
}
|
||||
|
||||
// Separate async loaders for datastore modules that might have different import patterns
|
||||
export async function loadDatastoreModules() {
|
||||
try {
|
||||
const [blockstoreModule, datastoreModule] = await Promise.all([
|
||||
import('blockstore-fs'),
|
||||
import('datastore-fs'),
|
||||
]);
|
||||
|
||||
return {
|
||||
FsBlockstore: blockstoreModule.FsBlockstore,
|
||||
FsDatastore: datastoreModule.FsDatastore,
|
||||
};
|
||||
} catch (_error) {
|
||||
// Fallback to require() for modules that might not be pure ES modules
|
||||
const FsBlockstore = require('blockstore-fs').FsBlockstore;
|
||||
const FsDatastore = require('datastore-fs').FsDatastore;
|
||||
|
||||
return {
|
||||
FsBlockstore,
|
||||
FsDatastore,
|
||||
};
|
||||
}
|
||||
}
|
@ -1,12 +1,4 @@
|
||||
import { createHelia } from 'helia';
|
||||
import { createLibp2p } from 'libp2p';
|
||||
import { tcp } from '@libp2p/tcp';
|
||||
import { noise } from '@chainsafe/libp2p-noise';
|
||||
import { yamux } from '@chainsafe/libp2p-yamux';
|
||||
import { gossipsub } from '@chainsafe/libp2p-gossipsub';
|
||||
import { identify } from '@libp2p/identify';
|
||||
import { FsBlockstore } from 'blockstore-fs';
|
||||
import { FsDatastore } from 'datastore-fs';
|
||||
import { loadModules, loadDatastoreModules } from './helia-wrapper';
|
||||
import { join } from 'path';
|
||||
import { PrivateSwarmSetup } from './swarm-setup';
|
||||
import { IPFSInstance } from '../../../src/framework/services/OrbitDBService';
|
||||
@ -28,6 +20,11 @@ export class RealIPFSService implements IPFSInstance {
|
||||
console.log(`🚀 Initializing IPFS node ${this.nodeIndex}...`);
|
||||
|
||||
try {
|
||||
// Load ES modules dynamically
|
||||
const { createHelia, createLibp2p, tcp, noise, yamux, gossipsub, identify } =
|
||||
await loadModules();
|
||||
const { FsBlockstore, FsDatastore } = await loadDatastoreModules();
|
||||
|
||||
// Create libp2p instance with private swarm configuration
|
||||
this.libp2p = await createLibp2p({
|
||||
addresses: {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createOrbitDB } from '@orbitdb/core';
|
||||
import { loadOrbitDBModules } from './helia-wrapper';
|
||||
import { RealIPFSService } from './ipfs-setup';
|
||||
import { OrbitDBInstance } from '../../../src/framework/services/OrbitDBService';
|
||||
|
||||
@ -17,6 +17,9 @@ export class RealOrbitDBService implements OrbitDBInstance {
|
||||
console.log(`🌀 Initializing OrbitDB for node ${this.nodeIndex}...`);
|
||||
|
||||
try {
|
||||
// Load OrbitDB ES modules dynamically
|
||||
const { createOrbitDB } = await loadOrbitDBModules();
|
||||
|
||||
const ipfs = this.ipfsService.getHelia();
|
||||
if (!ipfs) {
|
||||
throw new Error('IPFS node must be initialized before OrbitDB');
|
||||
@ -26,7 +29,7 @@ export class RealOrbitDBService implements OrbitDBInstance {
|
||||
this.orbitdb = await createOrbitDB({
|
||||
ipfs,
|
||||
id: `orbitdb-node-${this.nodeIndex}`,
|
||||
directory: `./orbitdb-${this.nodeIndex}` // Local directory for this node
|
||||
directory: `./orbitdb-${this.nodeIndex}`, // Local directory for this node
|
||||
});
|
||||
|
||||
console.log(`✅ OrbitDB initialized for node ${this.nodeIndex}`);
|
||||
@ -61,7 +64,7 @@ export class RealOrbitDBService implements OrbitDBInstance {
|
||||
case 'docstore':
|
||||
database = await this.orbitdb.open(name, {
|
||||
type: 'documents',
|
||||
AccessController: 'orbitdb'
|
||||
AccessController: 'orbitdb',
|
||||
});
|
||||
break;
|
||||
|
||||
@ -69,7 +72,7 @@ export class RealOrbitDBService implements OrbitDBInstance {
|
||||
case 'eventlog':
|
||||
database = await this.orbitdb.open(name, {
|
||||
type: 'events',
|
||||
AccessController: 'orbitdb'
|
||||
AccessController: 'orbitdb',
|
||||
});
|
||||
break;
|
||||
|
||||
@ -77,7 +80,7 @@ export class RealOrbitDBService implements OrbitDBInstance {
|
||||
case 'kvstore':
|
||||
database = await this.orbitdb.open(name, {
|
||||
type: 'keyvalue',
|
||||
AccessController: 'orbitdb'
|
||||
AccessController: 'orbitdb',
|
||||
});
|
||||
break;
|
||||
|
||||
@ -85,7 +88,7 @@ export class RealOrbitDBService implements OrbitDBInstance {
|
||||
// Default to documents store
|
||||
database = await this.orbitdb.open(name, {
|
||||
type: 'documents',
|
||||
AccessController: 'orbitdb'
|
||||
AccessController: 'orbitdb',
|
||||
});
|
||||
}
|
||||
|
||||
@ -169,13 +172,15 @@ export class RealOrbitDBService implements OrbitDBInstance {
|
||||
type: database.type,
|
||||
peers: database.peers || [],
|
||||
all: await database.all(),
|
||||
meta: database.meta || {}
|
||||
meta: database.meta || {},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Utility function to create OrbitDB network from IPFS network
|
||||
export async function createOrbitDBNetwork(ipfsNodes: RealIPFSService[]): Promise<RealOrbitDBService[]> {
|
||||
export async function createOrbitDBNetwork(
|
||||
ipfsNodes: RealIPFSService[],
|
||||
): Promise<RealOrbitDBService[]> {
|
||||
console.log(`🌀 Creating OrbitDB network with ${ipfsNodes.length} nodes...`);
|
||||
|
||||
const orbitdbNodes: RealOrbitDBService[] = [];
|
||||
@ -195,7 +200,7 @@ export async function shutdownOrbitDBNetwork(orbitdbNodes: RealOrbitDBService[])
|
||||
console.log(`🛑 Shutting down OrbitDB network...`);
|
||||
|
||||
// Stop all OrbitDB nodes
|
||||
await Promise.all(orbitdbNodes.map(node => node.stop()));
|
||||
await Promise.all(orbitdbNodes.map((node) => node.stop()));
|
||||
|
||||
console.log(`✅ OrbitDB network shutdown complete`);
|
||||
}
|
||||
@ -204,7 +209,7 @@ export async function shutdownOrbitDBNetwork(orbitdbNodes: RealOrbitDBService[])
|
||||
export async function testDatabaseReplication(
|
||||
orbitdbNodes: RealOrbitDBService[],
|
||||
dbName: string,
|
||||
dbType: string = 'documents'
|
||||
dbType: string = 'documents',
|
||||
): Promise<boolean> {
|
||||
console.log(`🔄 Testing database replication for '${dbName}'...`);
|
||||
|
||||
@ -222,7 +227,7 @@ export async function testDatabaseReplication(
|
||||
const db2 = await orbitdbNodes[1].openDB(dbName, dbType);
|
||||
|
||||
// Wait for replication
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
|
||||
// Check if data replicated
|
||||
const db2Data = await db2.all();
|
||||
|
@ -13,6 +13,8 @@
|
||||
"moduleResolution": "bundler",
|
||||
/* Skip type checking of declaration files. */
|
||||
"skipLibCheck": true,
|
||||
/* Perform compilation without referencing other files. */
|
||||
"isolatedModules": true,
|
||||
/* Removes comments from the project's output JavaScript code. */
|
||||
"removeComments": true,
|
||||
/* Enables experimental support for emitting type metadata for decorators which works with the module reflect-metadata. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user