@obsidiane/meridiane 2.0.10 → 2.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -2
- package/cli.js +21 -37
- package/package.json +3 -3
- package/src/README.md +9 -0
- package/{tools/app → src/application}/bridge-workflow.js +15 -13
- package/src/application/generate-bridge.js +50 -0
- package/{tools/app → src/application}/run-build.js +1 -1
- package/{tools/app → src/application}/run-dev.js +30 -36
- package/{tools/app → src/application}/run-generate.js +3 -3
- package/{tools → src}/domain/bridge-options.js +8 -21
- package/src/domain/list-values.js +6 -0
- package/src/generators/bridge/write-bridge-files.js +100 -0
- package/src/generators/models/interface-schema.js +116 -0
- package/src/generators/models/model-selection.js +148 -0
- package/src/generators/models/oas-contract.js +170 -0
- package/{tools/generator → src/generators}/models/oas-schema-name.js +6 -15
- package/src/generators/models/openapi-to-models.js +136 -0
- package/{tools/generator → src/generators}/models/schema-utils.js +27 -3
- package/src/generators/models/templates/type-alias.hbs +2 -0
- package/src/generators/models/type-expression.js +65 -0
- package/src/generators/models/type-resolver.js +240 -0
- package/src/generators/models/utils.js +89 -0
- package/src/generators/models/write-model-files.js +55 -0
- package/src/infrastructure/dev-project.js +48 -0
- package/{tools/infra → src/infrastructure}/exec.js +3 -2
- package/src/infrastructure/local-package-install.js +104 -0
- package/src/infrastructure/spec-loader.js +65 -0
- package/{tools/infra → src/infrastructure}/standalone-workspace.js +31 -29
- package/templates/{_lib_template → angular-bridge}/README.md +9 -0
- package/templates/angular-bridge/src/lib/bridge/rest/api-platform.adapter.ts +82 -0
- package/templates/angular-bridge/src/lib/bridge/rest/http-request.options.ts +30 -0
- package/templates/{_lib_template → angular-bridge}/src/lib/bridge/rest/query-builder.ts +10 -10
- package/templates/angular-bridge/src/lib/bridge/sse/mercure-connections.ts +255 -0
- package/templates/angular-bridge/src/lib/bridge/sse/mercure-payload.ts +82 -0
- package/templates/angular-bridge/src/lib/bridge/sse/mercure-url.builder.ts +39 -0
- package/templates/angular-bridge/src/lib/bridge/sse/mercure.adapter.ts +358 -0
- package/templates/{_lib_template → angular-bridge}/src/lib/bridge/sse/ref-count-topic.registry.ts +3 -12
- package/templates/angular-bridge/src/lib/bridge/sse/subscription-claims.ts +76 -0
- package/templates/angular-bridge/src/lib/bridge-options.ts +59 -0
- package/templates/{_lib_template → angular-bridge}/src/lib/facades/bridge.facade.ts +50 -51
- package/templates/{_lib_template → angular-bridge}/src/lib/facades/facade.factory.ts +0 -1
- package/templates/angular-bridge/src/lib/facades/facade.interface.ts +13 -0
- package/templates/{_lib_template → angular-bridge}/src/lib/facades/resource.facade.ts +24 -31
- package/templates/angular-bridge/src/lib/interceptors/bearer-auth.interceptor.ts +33 -0
- package/templates/angular-bridge/src/lib/interceptors/bridge-defaults.interceptor.ts +65 -0
- package/templates/angular-bridge/src/lib/interceptors/content-type.interceptor.ts +37 -0
- package/templates/angular-bridge/src/lib/interceptors/scoped.interceptor.ts +9 -0
- package/templates/angular-bridge/src/lib/interceptors/singleflight.interceptor.ts +46 -0
- package/templates/{_lib_template → angular-bridge}/src/lib/ports/realtime.port.ts +6 -2
- package/templates/{_lib_template → angular-bridge}/src/lib/ports/resource-repository.port.ts +7 -7
- package/templates/angular-bridge/src/lib/provide-bridge.ts +98 -0
- package/templates/angular-bridge/src/lib/utils/iri.ts +6 -0
- package/templates/angular-bridge/src/lib/utils/request-url.ts +31 -0
- package/templates/{_lib_template → angular-bridge}/src/public-api.ts +2 -0
- package/templates/_lib_template/src/lib/bridge/rest/api-platform.adapter.ts +0 -84
- package/templates/_lib_template/src/lib/bridge/rest/http-request.options.ts +0 -21
- package/templates/_lib_template/src/lib/bridge/sse/mercure-url.builder.ts +0 -17
- package/templates/_lib_template/src/lib/bridge/sse/mercure.adapter.ts +0 -806
- package/templates/_lib_template/src/lib/facades/facade.interface.ts +0 -31
- package/templates/_lib_template/src/lib/interceptors/bridge-defaults.interceptor.ts +0 -53
- package/templates/_lib_template/src/lib/interceptors/content-type.interceptor.ts +0 -49
- package/templates/_lib_template/src/lib/interceptors/singleflight.interceptor.ts +0 -55
- package/templates/_lib_template/src/lib/provide-bridge.ts +0 -186
- package/tools/build.js +0 -1
- package/tools/dev.js +0 -1
- package/tools/domain/paths.js +0 -10
- package/tools/generate.js +0 -1
- package/tools/generator/models/oas-contract.js +0 -159
- package/tools/generator/models/openapi-to-models.js +0 -240
- package/tools/generator/models/type-resolver.js +0 -107
- package/tools/generator/models/utils.js +0 -62
- package/tools/infra/dev-support.js +0 -189
- package/tools/infra/generate/bridge.js +0 -212
- package/tools/infra/spec-loader.js +0 -59
- /package/{tools → src}/domain/lib-name.js +0 -0
- /package/{tools/generator → src/generators}/models/handlebars.js +0 -0
- /package/{tools/generator → src/generators}/models/templates/index.hbs +0 -0
- /package/{tools/generator → src/generators}/models/templates/model.hbs +0 -0
- /package/{tools/infra → src/infrastructure}/json.js +0 -0
- /package/{tools/infra → src/infrastructure}/logger.js +0 -0
- /package/templates/{_lib_template → angular-bridge}/ng-package.json +0 -0
- /package/templates/{_lib_template → angular-bridge}/package.json +0 -0
- /package/templates/{_lib_template → angular-bridge}/src/lib/bridge/sse/eventsource-wrapper.ts +0 -0
- /package/templates/{_lib_template → angular-bridge}/src/lib/bridge/sse/mercure-topic.mapper.ts +0 -0
- /package/templates/{_lib_template → angular-bridge}/src/lib/bridge.types.ts +0 -0
- /package/templates/{_lib_template → angular-bridge}/src/lib/interceptors/bridge-debug.interceptor.ts +0 -0
- /package/templates/{_lib_template → angular-bridge}/src/lib/tokens.ts +0 -0
- /package/templates/{_lib_template → angular-bridge}/src/lib/utils/url.ts +0 -0
- /package/templates/{_lib_template → angular-bridge}/src/models/index.ts +0 -0
- /package/templates/{_lib_template → angular-bridge}/tsconfig.lib.json +0 -0
- /package/templates/{_lib_template → angular-bridge}/tsconfig.lib.prod.json +0 -0
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
import {existsSync} from 'node:fs';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import {fileURLToPath} from 'node:url';
|
|
5
|
-
|
|
6
|
-
import {readJson, writeJsonIfChanged} from '../json.js';
|
|
7
|
-
import {renderTemplateToFile} from '../../generator/models/handlebars.js';
|
|
8
|
-
import {ensureCleanDir} from '../../generator/models/utils.js';
|
|
9
|
-
import {buildModelsFromOpenAPI} from '../../generator/models/openapi-to-models.js';
|
|
10
|
-
|
|
11
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
-
const __dirname = path.dirname(__filename);
|
|
13
|
-
|
|
14
|
-
const pkgRoot = path.resolve(__dirname, '../../..'); // packages/meridiane
|
|
15
|
-
|
|
16
|
-
async function readTextIfExists(filePath) {
|
|
17
|
-
try {
|
|
18
|
-
return await fs.readFile(filePath, 'utf8');
|
|
19
|
-
} catch {
|
|
20
|
-
return undefined;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async function appendProjectReadme({targetReadmePath, projectReadmePath, debug, log}) {
|
|
25
|
-
if (!projectReadmePath) return;
|
|
26
|
-
|
|
27
|
-
const projectReadme = await readTextIfExists(projectReadmePath);
|
|
28
|
-
if (!projectReadme || projectReadme.trim().length === 0) return;
|
|
29
|
-
|
|
30
|
-
const targetReadme = await readTextIfExists(targetReadmePath);
|
|
31
|
-
if (!targetReadme || targetReadme.trim().length === 0) {
|
|
32
|
-
await fs.writeFile(targetReadmePath, projectReadme);
|
|
33
|
-
if (debug) log?.debug?.('[meridiane] project README copied', {source: projectReadmePath});
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const combined =
|
|
38
|
-
`${targetReadme.trimEnd()}\n\n---\n\n` +
|
|
39
|
-
`## Documentation du projet\n\n` +
|
|
40
|
-
`${projectReadme.trimStart()}`;
|
|
41
|
-
await fs.writeFile(targetReadmePath, combined);
|
|
42
|
-
if (debug) log?.debug?.('[meridiane] project README appended', {source: projectReadmePath});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async function replacePlaceholdersInDir(dir, placeholders) {
|
|
46
|
-
const entries = await fs.readdir(dir, {withFileTypes: true});
|
|
47
|
-
for (const entry of entries) {
|
|
48
|
-
const fullPath = path.join(dir, entry.name);
|
|
49
|
-
if (entry.isDirectory()) {
|
|
50
|
-
await replacePlaceholdersInDir(fullPath, placeholders);
|
|
51
|
-
} else if (entry.isFile()) {
|
|
52
|
-
let content = await fs.readFile(fullPath, 'utf8');
|
|
53
|
-
for (const [key, value] of Object.entries(placeholders)) {
|
|
54
|
-
content = content.replaceAll(key, value);
|
|
55
|
-
}
|
|
56
|
-
await fs.writeFile(fullPath, content);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async function generateLibrary({projectDir, libName, packageName, version, debug, log, projectReadmePath}) {
|
|
62
|
-
const tplDir = path.resolve(pkgRoot, 'templates/_lib_template');
|
|
63
|
-
const targetDir = projectDir;
|
|
64
|
-
|
|
65
|
-
if (debug) {
|
|
66
|
-
log?.debug?.('[meridiane] generate lib', {
|
|
67
|
-
libName,
|
|
68
|
-
packageName,
|
|
69
|
-
version,
|
|
70
|
-
targetDir
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
await fs.rm(targetDir, {recursive: true, force: true});
|
|
75
|
-
await fs.mkdir(targetDir, {recursive: true});
|
|
76
|
-
await fs.cp(tplDir, targetDir, {recursive: true});
|
|
77
|
-
|
|
78
|
-
await replacePlaceholdersInDir(targetDir, {
|
|
79
|
-
'__LIB_NAME__': libName,
|
|
80
|
-
'__PACKAGE_NAME__': packageName,
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
const libPackageJsonPath = path.join(targetDir, 'package.json');
|
|
84
|
-
if (existsSync(libPackageJsonPath)) {
|
|
85
|
-
const libPkg = await readJson(libPackageJsonPath);
|
|
86
|
-
libPkg.name = packageName;
|
|
87
|
-
libPkg.version = version;
|
|
88
|
-
await writeJsonIfChanged(libPackageJsonPath, libPkg);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
await appendProjectReadme({
|
|
92
|
-
targetReadmePath: path.join(targetDir, 'README.md'),
|
|
93
|
-
projectReadmePath,
|
|
94
|
-
debug,
|
|
95
|
-
log,
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
// angular.json / workspace patching is intentionally not done here.
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
async function generateModels({projectDir, spec, requiredMode, formats, include, exclude, debug, log}) {
|
|
102
|
-
const outDir = path.resolve(projectDir, 'src', 'models');
|
|
103
|
-
const templatesDir = path.resolve(pkgRoot, 'tools', 'generator', 'models', 'templates');
|
|
104
|
-
|
|
105
|
-
if (debug) {
|
|
106
|
-
log?.debug?.('[meridiane] generate models', {
|
|
107
|
-
outDir,
|
|
108
|
-
requiredMode,
|
|
109
|
-
formats: Array.isArray(formats) ? formats : [],
|
|
110
|
-
includeCount: include.length,
|
|
111
|
-
excludeCount: exclude.length,
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
await ensureCleanDir(outDir);
|
|
116
|
-
|
|
117
|
-
// Write models + index.ts.
|
|
118
|
-
const {models} = buildModelsFromOpenAPI(spec, {
|
|
119
|
-
requiredMode,
|
|
120
|
-
formats: Array.isArray(formats) ? formats : [],
|
|
121
|
-
includeSchemaNames: include,
|
|
122
|
-
excludeSchemaNames: exclude,
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
for (const m of models) {
|
|
126
|
-
await renderTemplateToFile({
|
|
127
|
-
templatePath: path.join(templatesDir, 'model.hbs'),
|
|
128
|
-
outPath: path.join(outDir, `${m.name}.ts`),
|
|
129
|
-
ctx: {
|
|
130
|
-
name: m.name,
|
|
131
|
-
props: m.props,
|
|
132
|
-
imports: m.imports,
|
|
133
|
-
extendsTypes: m.extendsTypes || [],
|
|
134
|
-
extendsItem: m.extendsItem === true,
|
|
135
|
-
},
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
await renderTemplateToFile({
|
|
140
|
-
templatePath: path.join(templatesDir, 'index.hbs'),
|
|
141
|
-
outPath: path.join(outDir, 'index.ts'),
|
|
142
|
-
ctx: {models: models.map((m) => ({name: m.name}))},
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
if (debug) log?.debug?.(`[meridiane] ${models.length} model(s) generated`);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* @param {{
|
|
150
|
-
* cwd: string,
|
|
151
|
-
* libName: string,
|
|
152
|
-
* packageName: string,
|
|
153
|
-
* version: string,
|
|
154
|
-
* noModels: boolean,
|
|
155
|
-
* spec?: any,
|
|
156
|
-
* requiredMode: 'all'|'spec',
|
|
157
|
-
* formats?: string[],
|
|
158
|
-
* include: string[],
|
|
159
|
-
* exclude: string[],
|
|
160
|
-
* debug: boolean,
|
|
161
|
-
* log?: { step?: (msg: string) => void, info?: (msg: string) => void, success?: (msg: string) => void, debug?: (msg: string, data?: any) => void },
|
|
162
|
-
* workspaceMode?: 'angular'|'standalone',
|
|
163
|
-
* distRoot?: string,
|
|
164
|
-
* projectDir?: string,
|
|
165
|
-
* projectReadmePath?: string,
|
|
166
|
-
* }} params
|
|
167
|
-
*/
|
|
168
|
-
export async function generateBridgeWorkspace(params) {
|
|
169
|
-
const {
|
|
170
|
-
cwd,
|
|
171
|
-
libName,
|
|
172
|
-
packageName,
|
|
173
|
-
version,
|
|
174
|
-
noModels,
|
|
175
|
-
spec,
|
|
176
|
-
requiredMode,
|
|
177
|
-
formats,
|
|
178
|
-
include,
|
|
179
|
-
exclude,
|
|
180
|
-
debug,
|
|
181
|
-
log,
|
|
182
|
-
distRoot,
|
|
183
|
-
projectDir: projectDirInput,
|
|
184
|
-
projectReadmePath,
|
|
185
|
-
} = params;
|
|
186
|
-
|
|
187
|
-
const projectDir = projectDirInput ?? path.resolve(cwd, 'projects', libName);
|
|
188
|
-
log?.step?.(`génération de la librairie (${path.relative(cwd, projectDir)})`);
|
|
189
|
-
await generateLibrary({projectDir, libName, packageName, version, debug, log, projectReadmePath});
|
|
190
|
-
|
|
191
|
-
// If a dist root is provided, force ng-packagr output to that directory.
|
|
192
|
-
if (distRoot) {
|
|
193
|
-
const ngPackagePath = path.resolve(projectDir, 'ng-package.json');
|
|
194
|
-
const ngPkg = await readJson(ngPackagePath);
|
|
195
|
-
const desiredDestAbs = path.resolve(distRoot, libName);
|
|
196
|
-
const projectRoot = path.dirname(ngPackagePath);
|
|
197
|
-
ngPkg.dest = path.relative(projectRoot, desiredDestAbs).split(path.sep).join('/');
|
|
198
|
-
await writeJsonIfChanged(ngPackagePath, ngPkg);
|
|
199
|
-
log?.debug?.('ng-package.json dest overridden', {dest: ngPkg.dest});
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
if (noModels) {
|
|
203
|
-
log?.info?.('models ignorés (--no-models)');
|
|
204
|
-
if (debug) log?.debug?.('[meridiane] --no-models enabled, skipping models generation');
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (!spec) throw new Error('Internal error: spec is required when noModels=false');
|
|
209
|
-
log?.step?.('génération des models (OpenAPI)');
|
|
210
|
-
await generateModels({projectDir, spec, requiredMode, formats, include, exclude, debug, log});
|
|
211
|
-
log?.success?.('génération terminée');
|
|
212
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
|
|
3
|
-
function isHttpUrl(v) {
|
|
4
|
-
return /^https?:\/\//i.test(String(v || ''));
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
async function fetchJson(url) {
|
|
8
|
-
let res;
|
|
9
|
-
try {
|
|
10
|
-
res = await fetch(url);
|
|
11
|
-
} catch (err) {
|
|
12
|
-
const msg = err?.message ?? String(err);
|
|
13
|
-
throw new Error(
|
|
14
|
-
`Spec fetch failed: ${url}\n` +
|
|
15
|
-
`Reason: ${msg}\n` +
|
|
16
|
-
`Tip: if your environment cannot access the network, use a local JSON file via --spec ./openapi.json`
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
if (!res.ok) {
|
|
20
|
-
const body = await res.text().catch(() => '');
|
|
21
|
-
throw new Error(`Spec fetch failed: ${res.status} ${res.statusText}${body ? `\n${body}` : ''}`);
|
|
22
|
-
}
|
|
23
|
-
return await res.json();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export async function readOpenApiSpec(specArg) {
|
|
27
|
-
if (!specArg) throw new Error('Missing --spec (url or JSON file path)');
|
|
28
|
-
const spec = String(specArg);
|
|
29
|
-
|
|
30
|
-
if (isHttpUrl(spec)) {
|
|
31
|
-
try {
|
|
32
|
-
return await fetchJson(spec);
|
|
33
|
-
} catch (err) {
|
|
34
|
-
const isDocsJson = /\/api\/docs\.json$/i.test(spec);
|
|
35
|
-
if (!isDocsJson) throw err;
|
|
36
|
-
const fallback = spec.replace(/\/api\/docs\.json$/i, '/api/docs.jsonopenapi');
|
|
37
|
-
try {
|
|
38
|
-
return await fetchJson(fallback);
|
|
39
|
-
} catch (err2) {
|
|
40
|
-
const m1 = err?.message ?? String(err);
|
|
41
|
-
const m2 = err2?.message ?? String(err2);
|
|
42
|
-
throw new Error(`Spec fetch failed (both endpoints tried)\n- ${spec}\n ${m1}\n- ${fallback}\n ${m2}`);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
try {
|
|
48
|
-
const raw = await fs.readFile(spec, 'utf8');
|
|
49
|
-
return JSON.parse(raw);
|
|
50
|
-
} catch (err) {
|
|
51
|
-
if (err?.code === 'ENOENT') {
|
|
52
|
-
throw new Error(`Spec file not found: ${spec}`);
|
|
53
|
-
}
|
|
54
|
-
if (err?.name === 'SyntaxError') {
|
|
55
|
-
throw new Error(`Invalid JSON in spec file ${spec}: ${err.message}`);
|
|
56
|
-
}
|
|
57
|
-
throw err;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/{_lib_template → angular-bridge}/src/lib/bridge/sse/eventsource-wrapper.ts
RENAMED
|
File without changes
|
/package/templates/{_lib_template → angular-bridge}/src/lib/bridge/sse/mercure-topic.mapper.ts
RENAMED
|
File without changes
|
|
File without changes
|
/package/templates/{_lib_template → angular-bridge}/src/lib/interceptors/bridge-debug.interceptor.ts
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|