Skip to content

Commit 00e9275

Browse files
Merge pull request #1434 from opencomponents/fallback-client
add fallback client option and new oc.json section for dev
2 parents 934d240 + 5585822 commit 00e9275

File tree

18 files changed

+11928
-117
lines changed

18 files changed

+11928
-117
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,4 @@ test/fixtures/components/welcome-with-optional-parameters/_package
4444

4545
logintervals.md
4646
dist/
47+
test-components/

src/cli/domain/get-mocked-plugins.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import fs from 'fs-extra';
33

44
import strings from '../../resources/';
55
import settings from '../../resources/settings';
6-
import type { OcJsonConfig } from '../../types';
76
import type { Logger } from '../logger';
7+
import { getOcConfig } from './ocConfig';
88

99
interface MockedPlugin {
1010
register: (options: unknown, dependencies: unknown, next: () => void) => void;
@@ -134,22 +134,22 @@ export default function getMockedPlugins(
134134
return plugins;
135135
}
136136

137-
const content: OcJsonConfig = fs.readJsonSync(ocJsonPath);
137+
const content = getOcConfig(ocJsonPath);
138138
const ocJsonLocation = ocJsonPath.slice(0, -ocJsonFileName.length);
139139

140-
if (!content.mocks || !content.mocks.plugins) {
140+
if (!content.development?.plugins) {
141141
return plugins;
142142
}
143143

144144
logger.warn(strings.messages.cli.REGISTERING_MOCKED_PLUGINS);
145145

146146
plugins = plugins.concat(
147-
registerStaticMocks(content.mocks.plugins.static ?? {}, logger)
147+
registerStaticMocks(content.development.plugins.static ?? {}, logger)
148148
);
149149
plugins = plugins.concat(
150150
registerDynamicMocks(
151151
ocJsonLocation,
152-
content.mocks.plugins.dynamic ?? {},
152+
content.development.plugins.dynamic ?? {},
153153
logger
154154
)
155155
);

src/cli/domain/mock.ts

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,33 @@
11
import path from 'node:path';
22
import fs from 'fs-extra';
3-
4-
import settings from '../../resources/settings';
3+
import { getOcConfig, setOcConfig } from './ocConfig';
54

65
export default function mock() {
76
return async (params: {
8-
targetType: string;
7+
targetType: 'plugin';
98
targetValue: string;
109
targetName: string;
1110
}): Promise<void> => {
12-
const localConfig = await fs
13-
.readJson(settings.configFile.src)
14-
.catch(() => ({}));
15-
16-
const mockType = params.targetType + 's';
11+
const localConfig = getOcConfig();
1712

18-
if (!localConfig.mocks) {
19-
localConfig.mocks = {};
20-
}
13+
const mockType = `${params.targetType}s` as const;
2114

22-
if (!localConfig.mocks[mockType]) {
23-
localConfig.mocks[mockType] = {};
15+
if (!localConfig.development[mockType]) {
16+
localConfig.development[mockType] = {};
2417
}
2518

26-
let pluginType = 'static';
19+
let pluginType: 'static' | 'dynamic' = 'static';
2720
if (fs.existsSync(path.resolve(params.targetValue.toString()))) {
2821
pluginType = 'dynamic';
2922
}
3023

31-
if (!localConfig.mocks[mockType][pluginType]) {
32-
localConfig.mocks[mockType][pluginType] = {};
24+
if (!localConfig.development[mockType][pluginType]) {
25+
localConfig.development[mockType][pluginType] = {};
3326
}
3427

35-
localConfig.mocks[mockType][pluginType][params.targetName] =
28+
localConfig.development[mockType][pluginType]![params.targetName] =
3629
params.targetValue;
3730

38-
return fs.writeJson(settings.configFile.src, localConfig, { spaces: 2 });
31+
return setOcConfig(localConfig);
3932
};
4033
}

src/cli/domain/ocConfig.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import fs from 'node:fs';
2+
import settings from '../../resources/settings';
3+
4+
export interface OpenComponentsConfig {
5+
/** JSON schema specification reference */
6+
$schema?: string | null;
7+
/** List of registry URLs where components will be published */
8+
registries?: string[];
9+
/** Development-specific configuration settings */
10+
development?: {
11+
/** Fallback configuration for when components cannot be found locally */
12+
fallback?: {
13+
/** URL of the fallback registry to use when components cannot be found locally */
14+
url: string;
15+
/** Whether to use the fallback registry's oc-client-browser.js for previewing components */
16+
client?: boolean;
17+
};
18+
19+
/** Plugin mocking configuration for development */
20+
plugins?: {
21+
/** Dynamic plugin mocks - file paths to JavaScript modules */
22+
dynamic?: Record<string, string>;
23+
/** Static plugin mocks - static values that will always be returned */
24+
static?: Record<string, string>;
25+
};
26+
};
27+
/** @deprecated Use development.plugins instead */
28+
mocks?: {
29+
/** @deprecated Use development.plugins instead */
30+
plugins?: {
31+
/** @deprecated Use development.plugins.dynamic instead */
32+
dynamic?: Record<string, string>;
33+
/** @deprecated Use development.plugins.static instead */
34+
static?: Record<string, string>;
35+
};
36+
};
37+
}
38+
39+
type ParsedConfig = {
40+
registries: string[];
41+
development: {
42+
plugins: {
43+
dynamic?: Record<string, string>;
44+
static?: Record<string, string>;
45+
};
46+
fallback?: {
47+
url: string;
48+
client?: boolean;
49+
};
50+
};
51+
};
52+
53+
function parseConfig(config: OpenComponentsConfig): ParsedConfig {
54+
const plugins = {
55+
...(config.mocks?.plugins || {}),
56+
...(config.development?.plugins || {})
57+
};
58+
59+
const parsedConfig: ParsedConfig = {
60+
...config,
61+
registries: config.registries || [],
62+
development: {
63+
plugins,
64+
fallback: config.development?.fallback
65+
}
66+
};
67+
68+
return parsedConfig;
69+
}
70+
71+
export function getOcConfig(path?: string): ParsedConfig {
72+
try {
73+
const config = JSON.parse(
74+
fs.readFileSync(path || settings.configFile.src, 'utf8')
75+
);
76+
return parseConfig(config);
77+
} catch {
78+
return {
79+
registries: [],
80+
development: {
81+
plugins: {}
82+
}
83+
};
84+
}
85+
}
86+
87+
export function setOcConfig(config: ParsedConfig, path?: string) {
88+
fs.writeFileSync(
89+
path || settings.configFile.src,
90+
JSON.stringify(parseConfig(config), null, 2)
91+
);
92+
}

src/cli/domain/package-components.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ const packageComponents =
8383
production
8484
};
8585

86+
console.log('compiling component', componentPath);
8687
const ocTemplate = requireTemplate(type, {
8788
compiler: true,
8889
componentPath

src/cli/domain/registry.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import settings from '../../resources/settings';
77
import type { Component } from '../../types';
88
import put from '../../utils/put';
99
import * as urlParser from '../domain/url-parser';
10+
import { getOcConfig, setOcConfig } from './ocConfig';
1011

1112
const getOcVersion = (): string => {
1213
const ocPackagePath = path.join(__dirname, '../../../package.json');
@@ -41,9 +42,7 @@ export default function registry(opts: RegistryOptions = {}) {
4142
if (!apiResponse) throw 'oc registry not available';
4243
if (apiResponse.type !== 'oc-registry') throw 'not a valid oc registry';
4344

44-
const res = await fs
45-
.readJson(settings.configFile.src)
46-
.catch(() => ({}));
45+
const res = getOcConfig();
4746

4847
if (!res.registries) {
4948
res.registries = [];
@@ -53,7 +52,7 @@ export default function registry(opts: RegistryOptions = {}) {
5352
res.registries.push(registry);
5453
}
5554

56-
return fs.writeJson(settings.configFile.src, res);
55+
return setOcConfig(res);
5756
} catch {
5857
throw 'oc registry not available';
5958
}
@@ -64,7 +63,7 @@ export default function registry(opts: RegistryOptions = {}) {
6463
}
6564

6665
try {
67-
const res = await fs.readJson(settings.configFile.src);
66+
const res = getOcConfig();
6867

6968
if (!res.registries || res.registries.length === 0)
7069
throw 'No oc registries';
@@ -135,12 +134,10 @@ export default function registry(opts: RegistryOptions = {}) {
135134
registry += '/';
136135
}
137136

138-
const res: { registries: string[] } = await fs
139-
.readJson(settings.configFile.src)
140-
.catch(() => ({ registries: [] }));
141-
res.registries = res.registries.filter((x) => x !== registry);
137+
const res = getOcConfig();
138+
res.registries = res.registries?.filter((x) => x !== registry) || [];
142139

143-
await fs.writeJson(settings.configFile.src, res);
140+
setOcConfig(res);
144141
}
145142
};
146143
}

src/cli/facade/dev.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import path from 'node:path';
22
import { promisify } from 'node:util';
33
import colors from 'colors/safe';
4+
import fs from 'fs-extra';
45
import getPortCb from 'getport';
56
import livereload from 'livereload';
67
import { fromPromise } from 'universalify';
78

89
import * as oc from '../../index';
910
import strings from '../../resources/index';
11+
import settings from '../../resources/settings';
1012
import getMockedPlugins from '../domain/get-mocked-plugins';
1113
import handleDependencies from '../domain/handle-dependencies';
1214
import type { Local } from '../domain/local';
@@ -39,7 +41,24 @@ const dev = ({ local, logger }: { logger: Logger; local: Local }) =>
3941
const componentsDir = opts.dirPath;
4042
const port = opts.port || 3000;
4143
const baseUrl = opts.baseUrl || `http://localhost:${port}/`;
42-
const fallbackRegistryUrl = opts.fallbackRegistryUrl;
44+
45+
let fallbackRegistryUrl = opts.fallbackRegistryUrl;
46+
let fallbackClient = false;
47+
if (!fallbackRegistryUrl) {
48+
try {
49+
const localConfig = await fs.readJson(settings.configFile.src);
50+
if (
51+
!fallbackRegistryUrl &&
52+
typeof localConfig.development?.fallback?.url === 'string'
53+
) {
54+
fallbackRegistryUrl = localConfig.development?.fallback?.url;
55+
}
56+
fallbackClient = !!localConfig.development?.fallback?.client;
57+
} catch {
58+
// Config file doesn't exist or is invalid, continue without fallback
59+
}
60+
}
61+
4362
const hotReloading =
4463
typeof opts.hotReloading === 'undefined' ? true : opts.hotReloading;
4564
const optWatch = typeof opts.watch === 'undefined' ? true : opts.watch;
@@ -180,6 +199,7 @@ const dev = ({ local, logger }: { logger: Logger; local: Local }) =>
180199
discovery: true,
181200
env: { name: 'local' },
182201
fallbackRegistryUrl,
202+
fallbackClient,
183203
hotReloading,
184204
liveReloadPort: liveReload.port,
185205
local: true,

src/cli/facade/mock.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@ import type { Logger } from '../logger';
66
const mock = ({ local, logger }: { local: Local; logger: Logger }) =>
77
fromPromise(
88
async (opts: {
9-
targetType: string;
9+
targetType: 'plugin';
1010
targetValue: string;
1111
targetName: string;
1212
}): Promise<void> => {
13+
if (opts.targetType !== 'plugin') {
14+
throw new Error('targetType must be "plugin"');
15+
}
16+
1317
await local.mock(opts);
1418
logger.ok(
1519
strings.messages.cli.MOCKED_PLUGIN(opts.targetName, opts.targetValue)

0 commit comments

Comments
 (0)