Skip to content

Commit 4ea4d39

Browse files
committed
fix(core): resolve udl-codegen CLI issues when run standalone
- Pass cacheDir to loadPlugins() so cached nodes are found correctly - Use full plugin names for owner matching instead of basename() - Only load manual test configs within UDL monorepo development - Pass GraphQL schema to runCodegen() for extensions - Make resolver registration idempotent to handle duplicate loading
1 parent 9717309 commit 4ea4d39

3 files changed

Lines changed: 43 additions & 11 deletions

File tree

.changeset/fix-codegen-cli.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'universal-data-layer': patch
3+
---
4+
5+
Fix `udl-codegen` CLI to work correctly when run standalone
6+
7+
- Pass `cacheDir` to `loadPlugins()` so cached nodes are found in the app's `.udl-cache` directory instead of the plugin's node_modules
8+
- Use full plugin names instead of `basename()` for owner matching, fixing "No nodes found in store" errors
9+
- Only load manual test configs when running within the UDL monorepo development environment
10+
- Pass GraphQL schema to `runCodegen()` so extensions like `codegen-typed-queries` work correctly
11+
- Make reference resolver registration idempotent to prevent errors when plugins are loaded multiple times

packages/core/src/codegen-only.ts

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
*/
1212

1313
import { loadAppConfig, loadPlugins } from '@/loader.js';
14-
import { rebuildHandler } from '@/handlers/graphql.js';
14+
import { rebuildHandler, getCurrentSchema } from '@/handlers/graphql.js';
1515
import { runCodegen } from '@/codegen.js';
1616
import { loadEnv } from '@/env.js';
1717
import { fileURLToPath } from 'node:url';
18-
import { basename, dirname, resolve } from 'node:path';
18+
import { dirname, resolve } from 'node:path';
1919
import { defaultStore } from '@/nodes/defaultStore.js';
2020
import { startMockServer, stopMockServer } from '@/mocks/index.js';
2121
import { loadManualTestConfigs, type FeatureCodegenInfo } from '@/features.js';
@@ -61,19 +61,29 @@ export async function runCodegenOnly(
6161
const codegenConfigs: FeatureCodegenInfo[] = [];
6262
const mainAppPluginNames: string[] = [];
6363

64+
// Determine if caching is enabled
65+
const cacheEnabled = userConfig.cache !== false;
66+
6467
// Load main app config plugins
6568
if (userConfig.plugins && userConfig.plugins.length > 0) {
6669
console.log('Loading plugins...');
70+
// Track plugin names before loading
71+
// Note: The actual owner name is determined by the plugin's config.name or basename
72+
// For npm packages like '@universal-data-layer/plugin-source-contentful', the plugin's config.name is used
6773
for (const plugin of userConfig.plugins) {
6874
if (typeof plugin === 'string') {
69-
mainAppPluginNames.push(basename(plugin));
75+
// For package names, use the full name (not basename)
76+
// The plugin will use its config.name if available, or basename of resolved path
77+
mainAppPluginNames.push(plugin);
7078
} else {
71-
mainAppPluginNames.push(basename(plugin.name));
79+
mainAppPluginNames.push(plugin.name);
7280
}
7381
}
7482
const pluginResult = await loadPlugins(userConfig.plugins, {
7583
appConfig: userConfig,
7684
store: defaultStore,
85+
cache: cacheEnabled,
86+
cacheDir: configPath,
7787
});
7888

7989
for (const pluginCodegen of pluginResult.codegenConfigs) {
@@ -94,20 +104,31 @@ export async function runCodegenOnly(
94104
});
95105
}
96106

97-
// Load configs from manual test features
107+
// Load configs from manual test features (only when running from within UDL development)
108+
// Skip when running from a consumer's app (configPath outside the package)
98109
if (includeManualTests) {
99110
const __filename = fileURLToPath(import.meta.url);
100111
const __dirname = dirname(__filename);
101112
const packageRoot = resolve(__dirname, '..', '..');
102113

103-
const featureConfigs = await loadManualTestConfigs(packageRoot);
104-
codegenConfigs.push(...featureConfigs);
114+
// Only load manual tests if cwd is within the UDL monorepo
115+
const isWithinMonorepo =
116+
configPath.startsWith(packageRoot) ||
117+
configPath.startsWith(resolve(packageRoot, '..', '..'));
118+
119+
if (isWithinMonorepo) {
120+
const featureConfigs = await loadManualTestConfigs(packageRoot);
121+
codegenConfigs.push(...featureConfigs);
122+
}
105123
}
106124

107125
// Build the GraphQL schema
108126
console.log('🔨 Building GraphQL schema from sourced nodes...');
109127
await rebuildHandler();
110128

129+
// Get the current schema for query generation
130+
const schema = await getCurrentSchema();
131+
111132
// Run codegen for all configs
112133
let successCount = 0;
113134
let errorCount = 0;
@@ -123,6 +144,7 @@ export async function runCodegenOnly(
123144
store: defaultStore,
124145
basePath,
125146
owners: pluginNames,
147+
schema,
126148
});
127149
successCount++;
128150
} catch (error) {

packages/core/src/references/registry.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,12 @@ export class ReferenceRegistry {
6262

6363
/**
6464
* Register a reference resolver for a plugin.
65-
* @throws if a resolver with the same ID is already registered
65+
* If a resolver with the same ID is already registered, it is skipped.
6666
*/
6767
registerResolver(config: ReferenceResolverConfig): void {
6868
if (this.resolvers.has(config.id)) {
69-
throw new Error(
70-
`Reference resolver with ID "${config.id}" is already registered`
71-
);
69+
// Already registered, skip silently (same plugin loaded multiple times)
70+
return;
7271
}
7372

7473
this.resolvers.set(config.id, config);

0 commit comments

Comments
 (0)