Skip to content

Commit c590e66

Browse files
committed
feat: enhance tsed-flow-package-symbols with Markdown support, error handling, and schema updates
Added support for a `markdown_url` to enrich package symbols with Markdown-based documentation. Improved error handling in migration logic for presets and introduced several schema enhancements, including new fields in the `package_symbols` collection and updated display options.
1 parent b6d29a5 commit c590e66

File tree

13 files changed

+840
-584
lines changed

13 files changed

+840
-584
lines changed

extensions/tsed-flow-package-symbols/src/api.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { defineOperationApi } from "@directus/extensions-sdk";
22
import { inject } from "@tsed/di";
33
import { wrapOperation } from "@tsed-cms/infra/bootstrap/directus.js";
4-
import type { Package, PackageSymbol } from "@tsed-cms/infra/directus/interfaces/DirectusSchema.js";
4+
import type { Package } from "@tsed-cms/infra/directus/interfaces/DirectusSchema.js";
55
import { HttpClient } from "@tsed-cms/infra/http/HttpClient.js";
66
import { PackageSymbolsService } from "@tsed-cms/usecases/package-symbols/PackageSymbolsService.js";
77
import { PackagesService } from "@tsed-cms/usecases/packages/PackagesService.js";
@@ -10,6 +10,7 @@ import { type ApiJsonModule, type ApiJsonResponse, mapApiSymbolToDirectus } from
1010

1111
export type Options = {
1212
url?: string;
13+
markdown_url?: string;
1314
};
1415

1516
async function ensurePackage(pkgName: string): Promise<Package> {
@@ -27,9 +28,10 @@ async function ensurePackage(pkgName: string): Promise<Package> {
2728

2829
export default defineOperationApi<Options>({
2930
id: "tsed-flow-package-symbols",
30-
handler: wrapOperation(async (opts, _context) => {
31+
handler: wrapOperation(async (opts) => {
3132
const startedAt = Date.now();
3233
const url = (opts?.url?.trim() || "https://tsed.dev/api.json").toString();
34+
const markdownUrl = (opts?.markdown_url?.trim() || "https://tsed.dev/ai/references").toString();
3335

3436
const http = inject(HttpClient);
3537
const symbolsService = inject(PackageSymbolsService);
@@ -48,13 +50,16 @@ export default defineOperationApi<Options>({
4850
for (const s of mod.symbols) {
4951
try {
5052
const pkg = await ensurePackage(pkgName);
51-
const mapped = mapApiSymbolToDirectus(pkg.id, s, origin);
53+
const mapped = mapApiSymbolToDirectus(s, origin, markdownUrl);
5254

53-
await symbolsService.upsertOne(mapped);
55+
mapped.versions.push(data.version);
56+
57+
await symbolsService.upsertOne({ ...mapped, package: pkg.id });
5458

5559
upserted += 1;
5660
processed += 1;
5761
} catch (er: any) {
62+
console.log(er);
5863
errors.push({
5964
name: s.symbolName,
6065
pkg: pkgName,

extensions/tsed-flow-package-symbols/src/app.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export default defineOperationApp({
44
id: "tsed-flow-package-symbols",
55
name: "Ts.ED Package Symbols importer",
66
icon: "code",
7-
description: "Récupère les symboles exportés des packages Ts.ED depuis api.json et les upsert dans package_symbols.",
7+
description: "Retrieves exported symbols from Ts.ED packages from api.json and upserts them into package_symbols.",
88
overview: ({ url }) => [
99
{
1010
label: "API URL",
@@ -19,11 +19,24 @@ export default defineOperationApp({
1919
meta: {
2020
width: "full",
2121
interface: "input",
22-
note: "URL du JSON des symboles (default: https://tsed.dev/api.json)"
22+
note: "URL of JSON symbols (default: https://tsed.dev/api.json)"
2323
},
2424
schema: {
2525
default_value: "https://tsed.dev/api.json"
2626
}
27+
},
28+
{
29+
field: "markdown_url",
30+
name: "Markdown base URL",
31+
type: "string",
32+
meta: {
33+
width: "full",
34+
interface: "input",
35+
note: "URL where the markdown contents of the symbols are stored (default: https://tsed.dev/ai/references/api)"
36+
},
37+
schema: {
38+
default_value: "https://tsed.dev/ai/references/api"
39+
}
2740
}
2841
]
2942
});

extensions/tsed-flow-package-symbols/src/mappers/mapApiSymbolToDirectus.spec.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,30 @@
1-
import { describe, it, expect } from "vitest";
2-
import { mapApiSymbolToDirectus, type ApiJsonModuleSymbol } from "./mapApiSymbolToDirectus.js";
1+
import { type ApiJsonModuleSymbol, mapApiSymbolToDirectus } from "./mapApiSymbolToDirectus.js";
32

43
describe("mapApiSymbolToDirectus", () => {
54
const baseOrigin = "https://tsed.dev";
5+
const markdownOrigin = "https://tsed.dev/ai/references";
66
const pkgId = "pkg-1";
77

88
it("mappe les champs de base correctement", () => {
99
const input: ApiJsonModuleSymbol = {
1010
id: "sym-1",
11-
path: "/api/core/Controller.html",
11+
path: "/api/core/Controller",
1212
symbolName: "Controller",
1313
module: "@tsed/core",
1414
symbolType: "class",
1515
status: []
1616
};
1717

18-
const out = mapApiSymbolToDirectus(pkgId, input, baseOrigin);
18+
const out = mapApiSymbolToDirectus(pkgId, input, baseOrigin, markdownOrigin);
1919

2020
expect(out).toMatchObject({
2121
id: "sym-1",
2222
status: "published",
2323
name: "Controller",
2424
type: "class",
25-
doc_url: "https://tsed.dev/api/core/Controller.html",
26-
versions: null,
25+
doc_url: "https://tsed.dev/api/core/Controller",
26+
markdown_url: "https://tsed.dev/ai/references/api/core/Controller.md",
27+
versions: [],
2728
package: pkgId,
2829
deprecated: false,
2930
tags: []

extensions/tsed-flow-package-symbols/src/mappers/mapApiSymbolToDirectus.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,20 @@ export type ApiJsonResponse = {
3030
* Responsibility: mapping fields and normalizing optional metadata only.
3131
* Caller is responsible for resolving/ensuring the `package` id.
3232
*/
33-
export function mapApiSymbolToDirectus(pkg: string, symbol: ApiJsonModuleSymbol, baseOrigin: string) {
33+
export function mapApiSymbolToDirectus(symbol: ApiJsonModuleSymbol, baseOrigin: string, markdownUrl?: string) {
3434
const deprecated = symbol.status ? symbol.status.includes("deprecated") : false;
35-
const tags = (symbol.status || []).filter((t) => t === "deprecated");
35+
const tags = (symbol.status || []).filter((t) => t !== "deprecated");
3636

3737
return {
3838
id: symbol.id,
3939
status: "published",
4040
name: symbol.symbolName,
4141
type: symbol.symbolType,
4242
doc_url: `${baseOrigin}${symbol.path}`,
43-
versions: null,
44-
package: pkg,
43+
markdown_url: `${markdownUrl}${symbol.path}.md`,
44+
additional_doc_url: "",
45+
versions: [] as string[],
4546
deprecated,
4647
tags
47-
} satisfies Omit<PackageSymbol, "user_created" | "date_created" | "user_updated" | "date_updated">;
48+
} satisfies Omit<PackageSymbol, "package" | "user_created" | "date_created" | "user_updated" | "date_updated">;
4849
}

migrations/data/directus_flows.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,27 @@
132132
"operation": "70f217d9-bcef-4637-aee3-083f5e60f82a",
133133
"date_created": "2025-11-03T08:34:33.531Z",
134134
"user_created": "dc515c74-5ed5-4464-b522-6ea1f2f6d270"
135+
},
136+
{
137+
"id": "569895a0-7a65-4cb2-94aa-67f77a776a08",
138+
"name": "Manual import package symbols",
139+
"icon": "bolt",
140+
"color": null,
141+
"description": null,
142+
"status": "active",
143+
"trigger": "manual",
144+
"accountability": "all",
145+
"options": {
146+
"collections": [
147+
"package_symbols"
148+
],
149+
"requireSelection": false,
150+
"location": "collection",
151+
"requireConfirmation": true,
152+
"async": true
153+
},
154+
"operation": "c651e60f-159c-4b4d-b636-c9d50debe3de",
155+
"date_created": "2025-11-15T10:33:07.296Z",
156+
"user_created": "dc515c74-5ed5-4464-b522-6ea1f2f6d270"
135157
}
136158
]

migrations/data/directus_operations.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,5 +106,22 @@
106106
"flow": "30be3802-3c63-41a3-9469-6aa5c48c58d6",
107107
"date_created": "2025-11-03T08:35:08.005Z",
108108
"user_created": "dc515c74-5ed5-4464-b522-6ea1f2f6d270"
109+
},
110+
{
111+
"id": "c651e60f-159c-4b4d-b636-c9d50debe3de",
112+
"name": "Ts.ED Package Symbols importer",
113+
"key": "tsed_flow_package_symbols_k8436",
114+
"type": "tsed-flow-package-symbols",
115+
"position_x": 19,
116+
"position_y": 1,
117+
"options": {
118+
"url": "https://tsed.dev/api.json",
119+
"markdown_url": "https://tsed.dev/ai/references/api"
120+
},
121+
"resolve": null,
122+
"reject": null,
123+
"flow": "569895a0-7a65-4cb2-94aa-67f77a776a08",
124+
"date_created": "2025-11-15T10:35:32.381Z",
125+
"user_created": "dc515c74-5ed5-4464-b522-6ea1f2f6d270"
109126
}
110127
]

migrations/data/directus_presets.json

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,5 +186,54 @@
186186
"icon": "bookmark",
187187
"color": null,
188188
"uuid": "5990ceea-5ce1-451f-a119-248de002975b"
189+
},
190+
{
191+
"id": 32,
192+
"bookmark": null,
193+
"user": null,
194+
"role": null,
195+
"collection": "package_symbols",
196+
"search": null,
197+
"layout": "tabular",
198+
"layout_query": {
199+
"tabular": {
200+
"fields": [
201+
"status",
202+
"name",
203+
"package",
204+
"type",
205+
"versions",
206+
"tags",
207+
"doc_url",
208+
"user_created",
209+
"date_created",
210+
"user_updated",
211+
"date_updated"
212+
],
213+
"page": 9
214+
}
215+
},
216+
"layout_options": {
217+
"tabular": {
218+
"widths": {
219+
"status": 32,
220+
"name": 160,
221+
"type": 160,
222+
"versions": 160,
223+
"tags": 160,
224+
"doc_url": 320.5,
225+
"package": 160,
226+
"user_created": 160,
227+
"date_created": 160,
228+
"user_updated": 160,
229+
"date_updated": 160
230+
}
231+
}
232+
},
233+
"refresh_interval": null,
234+
"filter": null,
235+
"icon": "bookmark",
236+
"color": null,
237+
"uuid": "3408e10b-df03-4a2c-b5da-ce0b13547f5b"
189238
}
190239
]

migrations/utils/installPresets.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ export async function installPresets(knex: Knex, presets: Preset[]): Promise<voi
3030
}
3131
} catch (error) {
3232
logger.error(`Error altering directus_presets or directus_fields table:`, error);
33-
throw error;
3433
}
3534

3635
// For each language, check if it exists and insert it if it doesn't
@@ -50,21 +49,27 @@ export async function installPresets(knex: Knex, presets: Preset[]): Promise<voi
5049

5150
await knex(TABLE).insert(preset);
5251
} catch (er) {
53-
delete (preset as any).uuid;
54-
await knex(TABLE).insert(preset);
52+
try {
53+
delete (preset as any).uuid;
54+
await knex(TABLE).insert(preset);
55+
} catch (er) {}
5556
}
5657
} else {
5758
logger.info(`Update preset: ${preset.collection}`);
58-
if (uuidExists) {
59-
await knex(TABLE)
60-
.update(preset as any)
61-
.where({ uuid: uuidExists.uuid });
62-
} else {
63-
(preset as any).uuid = v4();
59+
try {
60+
if (uuidExists) {
61+
await knex(TABLE)
62+
.update(preset as any)
63+
.where({ uuid: uuidExists.uuid });
64+
} else {
65+
(preset as any).uuid = v4();
6466

65-
await knex(TABLE)
66-
.update(preset as any)
67-
.where({ id: exists.id });
67+
await knex(TABLE)
68+
.update(preset as any)
69+
.where({ id: exists.id });
70+
}
71+
} catch (error) {
72+
logger.error(`Error updating preset: ${preset.id}`);
6873
}
6974
}
7075
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@
145145
"supertest": "7.1.1",
146146
"tsdown": "0.15.12",
147147
"typescript": "5.8.3",
148+
"uuid": "13.0.0",
148149
"vitest": "3.2.1"
149150
},
150151
"keywords": [

0 commit comments

Comments
 (0)