@nospt/plugin-tech-radar-ng-backend 0.9.0
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 +204 -0
- package/dist/database/TechRadarDb.cjs.js +244 -0
- package/dist/database/TechRadarDb.cjs.js.map +1 -0
- package/dist/index.cjs.js +10 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/plugin.cjs.js +67 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/router.cjs.js +79 -0
- package/dist/router.cjs.js.map +1 -0
- package/dist/service/GitHubMetricsService.cjs.js +108 -0
- package/dist/service/GitHubMetricsService.cjs.js.map +1 -0
- package/dist/service/HuggingFaceMetricsService.cjs.js +114 -0
- package/dist/service/HuggingFaceMetricsService.cjs.js.map +1 -0
- package/dist/service/RadarMetricsService.cjs.js +139 -0
- package/dist/service/RadarMetricsService.cjs.js.map +1 -0
- package/migrations/001_create_segments_table.js +34 -0
- package/migrations/002_add_segments.js +124 -0
- package/migrations/003_create_rings_table.js +46 -0
- package/migrations/004_add_rings.js +30 -0
- package/migrations/005_create_radar_candidates_table.js +43 -0
- package/migrations/006_create_radar_candidates_snapshot_table.js +35 -0
- package/package.json +67 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration: add default segments
|
|
3
|
+
*
|
|
4
|
+
* Stores segment entries — categories for the Tech Radar NG.
|
|
5
|
+
*
|
|
6
|
+
* NOTE: Migrations must be plain JS (not TS). Backstage runs them
|
|
7
|
+
* at runtime without a TypeScript loader.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { id } = require('zod/v4/locales');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {import('knex').Knex} knex
|
|
14
|
+
*/
|
|
15
|
+
exports.up = async function (knex) {
|
|
16
|
+
// Seed default segments
|
|
17
|
+
await knex('segments').insert([
|
|
18
|
+
{
|
|
19
|
+
id: 'ai-code-development',
|
|
20
|
+
name: 'AI Code Development',
|
|
21
|
+
description:
|
|
22
|
+
'AI tools and assistants that support software development workflows.',
|
|
23
|
+
search_params: JSON.stringify([
|
|
24
|
+
'code',
|
|
25
|
+
'coding',
|
|
26
|
+
'programming',
|
|
27
|
+
'copilot',
|
|
28
|
+
'code-generation',
|
|
29
|
+
'developer',
|
|
30
|
+
'ide',
|
|
31
|
+
'autocomplete',
|
|
32
|
+
'code generation',
|
|
33
|
+
]),
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: 'infrastructure',
|
|
37
|
+
name: 'Infrastructure',
|
|
38
|
+
description:
|
|
39
|
+
'Platforms, runtimes, and cloud services powering AI workloads.',
|
|
40
|
+
search_params: JSON.stringify([
|
|
41
|
+
'infrastructure',
|
|
42
|
+
'api',
|
|
43
|
+
'platform',
|
|
44
|
+
'runtime',
|
|
45
|
+
'pipeline',
|
|
46
|
+
'orchestration',
|
|
47
|
+
'vector',
|
|
48
|
+
'database',
|
|
49
|
+
'deployment',
|
|
50
|
+
'serving',
|
|
51
|
+
'gateway',
|
|
52
|
+
]),
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 'llm-techniques',
|
|
56
|
+
name: 'LLM Techniques',
|
|
57
|
+
description:
|
|
58
|
+
'Large language model architectures, fine-tuning, and prompting strategies.',
|
|
59
|
+
search_params: JSON.stringify([
|
|
60
|
+
'llm',
|
|
61
|
+
'language model',
|
|
62
|
+
'gpt',
|
|
63
|
+
'transformer',
|
|
64
|
+
'prompt',
|
|
65
|
+
'rag',
|
|
66
|
+
'embedding',
|
|
67
|
+
'fine-tuning',
|
|
68
|
+
'agent',
|
|
69
|
+
'chatbot',
|
|
70
|
+
'assistant',
|
|
71
|
+
'reasoning',
|
|
72
|
+
'inference',
|
|
73
|
+
]),
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: 'standards-protocols',
|
|
77
|
+
name: 'Standards & Protocols',
|
|
78
|
+
description:
|
|
79
|
+
'Emerging standards, APIs, and interoperability protocols for AI systems.',
|
|
80
|
+
search_params: JSON.stringify([
|
|
81
|
+
'standard',
|
|
82
|
+
'protocol',
|
|
83
|
+
'specification',
|
|
84
|
+
'mcp',
|
|
85
|
+
'openapi',
|
|
86
|
+
'schema',
|
|
87
|
+
'format',
|
|
88
|
+
'interoperability',
|
|
89
|
+
]),
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: 'ai-low-code-no-code',
|
|
93
|
+
name: 'AI Low-Code/No-Code',
|
|
94
|
+
description:
|
|
95
|
+
'AI-powered low-code and no-code platforms for building applications.',
|
|
96
|
+
search_params: JSON.stringify([
|
|
97
|
+
'no-code',
|
|
98
|
+
'low-code',
|
|
99
|
+
'nocode',
|
|
100
|
+
'lowcode',
|
|
101
|
+
'visual',
|
|
102
|
+
'builder',
|
|
103
|
+
'workflow',
|
|
104
|
+
'automation',
|
|
105
|
+
'drag',
|
|
106
|
+
]),
|
|
107
|
+
},
|
|
108
|
+
]);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @param {import('knex').Knex} knex
|
|
113
|
+
*/
|
|
114
|
+
exports.down = async function (knex) {
|
|
115
|
+
await knex('segments')
|
|
116
|
+
.whereIn('id', [
|
|
117
|
+
'ai-code-development',
|
|
118
|
+
'infrastructure',
|
|
119
|
+
'llm-techniques',
|
|
120
|
+
'standards-protocols',
|
|
121
|
+
'ai-low-code-no-code',
|
|
122
|
+
])
|
|
123
|
+
.delete();
|
|
124
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration: create rings table
|
|
3
|
+
*
|
|
4
|
+
* Stores GenAITechCandidate entries — technologies discovered and
|
|
5
|
+
* proposed for the Tech Radar NG.
|
|
6
|
+
*
|
|
7
|
+
* NOTE: Migrations must be plain JS (not TS). Backstage runs them
|
|
8
|
+
* at runtime without a TypeScript loader.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Returns a DB-level default expression that generates a UUID v4.
|
|
13
|
+
* Works with PostgreSQL (gen_random_uuid) and SQLite (randomblob).
|
|
14
|
+
* @param {import('knex').Knex} knex
|
|
15
|
+
*/
|
|
16
|
+
function uuidDefault(knex) {
|
|
17
|
+
if (knex.client.config.client === 'pg') {
|
|
18
|
+
return knex.raw('gen_random_uuid()');
|
|
19
|
+
}
|
|
20
|
+
return knex.raw(
|
|
21
|
+
"(lower(hex(randomblob(4))) || '-' || lower(hex(randomblob(2))) || '-' || '4' || substr(lower(hex(randomblob(2))),2) || '-' || substr('89ab', abs(random()) % 4 + 1, 1) || substr(lower(hex(randomblob(2))),2) || '-' || lower(hex(randomblob(6))))",
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {import('knex').Knex} knex
|
|
27
|
+
*/
|
|
28
|
+
exports.up = async function (knex) {
|
|
29
|
+
await knex.schema.createTable('rings', table => {
|
|
30
|
+
table.uuid('id').primary().defaultTo(uuidDefault(knex));
|
|
31
|
+
|
|
32
|
+
// Core identity
|
|
33
|
+
table.string('name').notNullable().unique();
|
|
34
|
+
table.string('color').notNullable().defaultTo('#000000');
|
|
35
|
+
|
|
36
|
+
table.timestamp('created_at').defaultTo(knex.fn.now());
|
|
37
|
+
table.timestamp('updated_at').defaultTo(knex.fn.now());
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {import('knex').Knex} knex
|
|
43
|
+
*/
|
|
44
|
+
exports.down = async function (knex) {
|
|
45
|
+
await knex.schema.dropTable('rings');
|
|
46
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration: create rings table
|
|
3
|
+
*
|
|
4
|
+
* Stores ring entries — categories for the Tech Radar NG.
|
|
5
|
+
*
|
|
6
|
+
* NOTE: Migrations must be plain JS (not TS). Backstage runs them
|
|
7
|
+
* at runtime without a TypeScript loader.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {import('knex').Knex} knex
|
|
12
|
+
*/
|
|
13
|
+
exports.up = async function (knex) {
|
|
14
|
+
// Seed default rings
|
|
15
|
+
await knex('rings').insert([
|
|
16
|
+
{ name: 'Adopt', color: '#5ba300' },
|
|
17
|
+
{ name: 'Trial', color: '#009eb0' },
|
|
18
|
+
{ name: 'Assess', color: '#c7ba00' },
|
|
19
|
+
{ name: 'Hold', color: '#e09b96' },
|
|
20
|
+
]);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param {import('knex').Knex} knex
|
|
25
|
+
*/
|
|
26
|
+
exports.down = async function (knex) {
|
|
27
|
+
await knex('rings')
|
|
28
|
+
.whereIn('name', ['Adopt', 'Trial', 'Assess', 'Hold'])
|
|
29
|
+
.delete();
|
|
30
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration: create radar_candidates table
|
|
3
|
+
*
|
|
4
|
+
* Stores Tech radar candidate entries — candidates discovered and
|
|
5
|
+
* proposed for the Tech Radar.
|
|
6
|
+
*
|
|
7
|
+
* NOTE: Migrations must be plain JS (not TS). Backstage runs them
|
|
8
|
+
* at runtime without a TypeScript loader.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {import('knex').Knex} knex
|
|
13
|
+
*/
|
|
14
|
+
exports.up = async function (knex) {
|
|
15
|
+
await knex.schema.createTable('radar_candidates', table => {
|
|
16
|
+
table.uuid('id').primary();
|
|
17
|
+
|
|
18
|
+
// Core identity
|
|
19
|
+
table.string('platform_id').notNullable().unique(); // GitHub node_id, HuggingFace repo id, etc.
|
|
20
|
+
table.string('full_name').notNullable().unique();
|
|
21
|
+
table.string('name').notNullable();
|
|
22
|
+
table.text('description').nullable();
|
|
23
|
+
table.text('url').notNullable();
|
|
24
|
+
table.text('homepage').nullable();
|
|
25
|
+
table.string('primary_language').nullable();
|
|
26
|
+
table.text('license').nullable();
|
|
27
|
+
table.uuid('ring').nullable().references('id').inTable('rings');
|
|
28
|
+
table.string('segment').nullable().references('id').inTable('segments');
|
|
29
|
+
table.boolean('in_radar').notNullable().defaultTo(false);
|
|
30
|
+
table.boolean('is_active').notNullable().defaultTo(true);
|
|
31
|
+
table.enum('platform', ['github', 'hugging_face']).notNullable();
|
|
32
|
+
table.timestamp('last_activity_at').notNullable();
|
|
33
|
+
table.timestamp('created_at').notNullable();
|
|
34
|
+
table.timestamp('last_synced_at').notNullable().defaultTo(knex.fn.now());
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param {import('knex').Knex} knex
|
|
40
|
+
*/
|
|
41
|
+
exports.down = async function (knex) {
|
|
42
|
+
await knex.schema.dropTable('radar_candidates');
|
|
43
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration: create radar_candidates_snapshots table
|
|
3
|
+
*
|
|
4
|
+
* Stores AI radar candidate snapshot entries — snapshots of candidates discovered and
|
|
5
|
+
* proposed for the Tech Radar NG.
|
|
6
|
+
*
|
|
7
|
+
* NOTE: Migrations must be plain JS (not TS). Backstage runs them
|
|
8
|
+
* at runtime without a TypeScript loader.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {import('knex').Knex} knex
|
|
13
|
+
*/
|
|
14
|
+
exports.up = async function (knex) {
|
|
15
|
+
await knex.schema.createTable('radar_candidates_snapshots', table => {
|
|
16
|
+
table.uuid('id').primary();
|
|
17
|
+
table
|
|
18
|
+
.uuid('candidate_id')
|
|
19
|
+
.notNullable()
|
|
20
|
+
.references('id')
|
|
21
|
+
.inTable('radar_candidates')
|
|
22
|
+
.onDelete('CASCADE');
|
|
23
|
+
// Core identity
|
|
24
|
+
table.integer('popularity_score').notNullable();
|
|
25
|
+
table.integer('usage_score').notNullable();
|
|
26
|
+
table.timestamp('snapshot_at').notNullable().defaultTo(knex.fn.now());
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {import('knex').Knex} knex
|
|
32
|
+
*/
|
|
33
|
+
exports.down = async function (knex) {
|
|
34
|
+
await knex.schema.dropTable('radar_candidates_snapshots');
|
|
35
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nospt/plugin-tech-radar-ng-backend",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"license": "UNLICENSED",
|
|
5
|
+
"main": "dist/index.cjs.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public",
|
|
9
|
+
"main": "dist/index.cjs.js",
|
|
10
|
+
"types": "dist/index.d.ts"
|
|
11
|
+
},
|
|
12
|
+
"backstage": {
|
|
13
|
+
"role": "backend-plugin",
|
|
14
|
+
"pluginId": "tech-radar-ng",
|
|
15
|
+
"pluginPackages": [
|
|
16
|
+
"@nospt/plugin-tech-radar-ng",
|
|
17
|
+
"@nospt/plugin-tech-radar-ng-backend",
|
|
18
|
+
"@nospt/plugin-tech-radar-ng-common"
|
|
19
|
+
],
|
|
20
|
+
"features": {
|
|
21
|
+
".": "@backstage/BackendFeature"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"start": "backstage-cli package start",
|
|
26
|
+
"build": "backstage-cli package build",
|
|
27
|
+
"lint": "backstage-cli package lint",
|
|
28
|
+
"test": "backstage-cli package test",
|
|
29
|
+
"clean": "backstage-cli package clean",
|
|
30
|
+
"prepack": "backstage-cli package prepack",
|
|
31
|
+
"postpack": "backstage-cli package postpack"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@backstage/backend-defaults": "^0.15.2",
|
|
35
|
+
"@backstage/backend-plugin-api": "^1.7.0",
|
|
36
|
+
"@backstage/catalog-client": "^1.13.0",
|
|
37
|
+
"@backstage/errors": "^1.2.7",
|
|
38
|
+
"@backstage/integration": "^1.20.1",
|
|
39
|
+
"@backstage/plugin-catalog-node": "^2.0.0",
|
|
40
|
+
"@backstage/types": "^1.2.2",
|
|
41
|
+
"@nospt/plugin-tech-radar-ng-common": "workspace:^",
|
|
42
|
+
"better-sqlite3": "^12.6.2",
|
|
43
|
+
"express": "^4.17.1",
|
|
44
|
+
"express-promise-router": "^4.1.0",
|
|
45
|
+
"uuid": "^13.0.0",
|
|
46
|
+
"zod": "^4.3.6"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@backstage/backend-test-utils": "^1.11.0",
|
|
50
|
+
"@backstage/cli": "^0.35.4",
|
|
51
|
+
"@types/express": "^4.17.6",
|
|
52
|
+
"@types/jest": "^30.0.0",
|
|
53
|
+
"@types/supertest": "^2.0.12",
|
|
54
|
+
"supertest": "^6.2.4"
|
|
55
|
+
},
|
|
56
|
+
"files": [
|
|
57
|
+
"dist",
|
|
58
|
+
"migrations"
|
|
59
|
+
],
|
|
60
|
+
"typesVersions": {
|
|
61
|
+
"*": {
|
|
62
|
+
"package.json": [
|
|
63
|
+
"package.json"
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|