@stackweld/registry 0.2.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/.turbo/turbo-build.log +4 -0
- package/.turbo/turbo-lint.log +436 -0
- package/.turbo/turbo-test.log +15 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/dist/__tests__/loader.test.d.ts +2 -0
- package/dist/__tests__/loader.test.d.ts.map +1 -0
- package/dist/__tests__/loader.test.js +126 -0
- package/dist/__tests__/loader.test.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/learning-resources.d.ts +16 -0
- package/dist/learning-resources.d.ts.map +1 -0
- package/dist/learning-resources.js +461 -0
- package/dist/learning-resources.js.map +1 -0
- package/dist/loader.d.ts +18 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +56 -0
- package/dist/loader.js.map +1 -0
- package/dist/schema.d.ts +147 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +79 -0
- package/dist/schema.js.map +1 -0
- package/package.json +39 -0
- package/src/__tests__/loader.test.ts +162 -0
- package/src/index.ts +4 -0
- package/src/learning-resources.ts +488 -0
- package/src/loader.ts +67 -0
- package/src/schema.ts +79 -0
- package/src/technologies/auth/clerk.yaml +29 -0
- package/src/technologies/auth/lucia.yaml +19 -0
- package/src/technologies/auth/nextauth.yaml +31 -0
- package/src/technologies/auth/supabase-auth.yaml +32 -0
- package/src/technologies/backend/django.yaml +17 -0
- package/src/technologies/backend/echo.yaml +17 -0
- package/src/technologies/backend/express.yaml +17 -0
- package/src/technologies/backend/fastapi.yaml +17 -0
- package/src/technologies/backend/fastify.yaml +17 -0
- package/src/technologies/backend/flask.yaml +17 -0
- package/src/technologies/backend/gin.yaml +17 -0
- package/src/technologies/backend/hono.yaml +17 -0
- package/src/technologies/backend/laravel.yaml +32 -0
- package/src/technologies/backend/nestjs.yaml +30 -0
- package/src/technologies/backend/spring-boot.yaml +30 -0
- package/src/technologies/backend/trpc.yaml +20 -0
- package/src/technologies/databases/kafka.yaml +27 -0
- package/src/technologies/databases/mariadb.yaml +30 -0
- package/src/technologies/databases/mongodb.yaml +25 -0
- package/src/technologies/databases/mysql.yaml +25 -0
- package/src/technologies/databases/neon.yaml +18 -0
- package/src/technologies/databases/pocketbase.yaml +24 -0
- package/src/technologies/databases/postgresql.yaml +26 -0
- package/src/technologies/databases/redis.yaml +23 -0
- package/src/technologies/databases/sqlite.yaml +19 -0
- package/src/technologies/databases/supabase.yaml +27 -0
- package/src/technologies/databases/turso.yaml +19 -0
- package/src/technologies/devops/biome.yaml +19 -0
- package/src/technologies/devops/cypress.yaml +20 -0
- package/src/technologies/devops/devcontainers.yaml +18 -0
- package/src/technologies/devops/docker.yaml +19 -0
- package/src/technologies/devops/eslint.yaml +18 -0
- package/src/technologies/devops/github-actions.yaml +18 -0
- package/src/technologies/devops/jest.yaml +19 -0
- package/src/technologies/devops/playwright.yaml +19 -0
- package/src/technologies/devops/pnpm.yaml +22 -0
- package/src/technologies/devops/prettier.yaml +19 -0
- package/src/technologies/devops/storybook.yaml +28 -0
- package/src/technologies/devops/turborepo.yaml +20 -0
- package/src/technologies/devops/typescript.yaml +20 -0
- package/src/technologies/devops/vitest.yaml +20 -0
- package/src/technologies/devops/zod.yaml +18 -0
- package/src/technologies/frontend/angular.yaml +19 -0
- package/src/technologies/frontend/astro.yaml +19 -0
- package/src/technologies/frontend/htmx.yaml +18 -0
- package/src/technologies/frontend/nextjs.yaml +22 -0
- package/src/technologies/frontend/nuxt.yaml +18 -0
- package/src/technologies/frontend/qwik.yaml +28 -0
- package/src/technologies/frontend/react.yaml +19 -0
- package/src/technologies/frontend/remix.yaml +28 -0
- package/src/technologies/frontend/solidjs.yaml +29 -0
- package/src/technologies/frontend/svelte.yaml +19 -0
- package/src/technologies/frontend/sveltekit.yaml +18 -0
- package/src/technologies/frontend/vue.yaml +18 -0
- package/src/technologies/orms/django-orm.yaml +21 -0
- package/src/technologies/orms/drizzle.yaml +23 -0
- package/src/technologies/orms/mongoose.yaml +22 -0
- package/src/technologies/orms/prisma.yaml +23 -0
- package/src/technologies/orms/sqlalchemy.yaml +21 -0
- package/src/technologies/orms/typeorm.yaml +21 -0
- package/src/technologies/runtimes/bun.yaml +24 -0
- package/src/technologies/runtimes/deno.yaml +30 -0
- package/src/technologies/runtimes/go.yaml +27 -0
- package/src/technologies/runtimes/nodejs.yaml +31 -0
- package/src/technologies/runtimes/php.yaml +30 -0
- package/src/technologies/runtimes/python.yaml +30 -0
- package/src/technologies/runtimes/rust.yaml +23 -0
- package/src/technologies/services/adminer.yaml +24 -0
- package/src/technologies/services/grafana.yaml +29 -0
- package/src/technologies/services/mailpit.yaml +27 -0
- package/src/technologies/services/minio.yaml +28 -0
- package/src/technologies/services/nginx.yaml +25 -0
- package/src/technologies/services/pgadmin.yaml +26 -0
- package/src/technologies/services/portainer.yaml +24 -0
- package/src/technologies/services/prometheus.yaml +27 -0
- package/src/technologies/services/rabbitmq.yaml +28 -0
- package/src/technologies/services/traefik.yaml +28 -0
- package/src/technologies/styling/chakra-ui.yaml +21 -0
- package/src/technologies/styling/css-modules.yaml +17 -0
- package/src/technologies/styling/daisyui.yaml +20 -0
- package/src/technologies/styling/material-ui.yaml +22 -0
- package/src/technologies/styling/shadcn-ui.yaml +20 -0
- package/src/technologies/styling/tailwindcss.yaml +20 -0
- package/tsconfig.json +11 -0
- package/tsconfig.tsbuildinfo +1 -0
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Schema for technology YAML files.
|
|
3
|
+
* Validated with ajv on load.
|
|
4
|
+
*/
|
|
5
|
+
export declare const technologySchema: {
|
|
6
|
+
readonly type: "object";
|
|
7
|
+
readonly required: readonly [
|
|
8
|
+
"id",
|
|
9
|
+
"name",
|
|
10
|
+
"category",
|
|
11
|
+
"description",
|
|
12
|
+
"website",
|
|
13
|
+
"versions",
|
|
14
|
+
"defaultVersion",
|
|
15
|
+
"requires",
|
|
16
|
+
"incompatibleWith",
|
|
17
|
+
"suggestedWith",
|
|
18
|
+
"envVars",
|
|
19
|
+
"configFiles",
|
|
20
|
+
"lastVerified",
|
|
21
|
+
"tags",
|
|
22
|
+
];
|
|
23
|
+
readonly properties: {
|
|
24
|
+
readonly id: {
|
|
25
|
+
readonly type: "string";
|
|
26
|
+
readonly pattern: "^[a-z][a-z0-9-]*$";
|
|
27
|
+
};
|
|
28
|
+
readonly name: {
|
|
29
|
+
readonly type: "string";
|
|
30
|
+
readonly minLength: 1;
|
|
31
|
+
};
|
|
32
|
+
readonly category: {
|
|
33
|
+
readonly type: "string";
|
|
34
|
+
readonly enum: readonly [
|
|
35
|
+
"runtime",
|
|
36
|
+
"frontend",
|
|
37
|
+
"backend",
|
|
38
|
+
"database",
|
|
39
|
+
"orm",
|
|
40
|
+
"auth",
|
|
41
|
+
"styling",
|
|
42
|
+
"service",
|
|
43
|
+
"devops",
|
|
44
|
+
];
|
|
45
|
+
};
|
|
46
|
+
readonly description: {
|
|
47
|
+
readonly type: "string";
|
|
48
|
+
};
|
|
49
|
+
readonly website: {
|
|
50
|
+
readonly type: "string";
|
|
51
|
+
};
|
|
52
|
+
readonly versions: {
|
|
53
|
+
readonly type: "array";
|
|
54
|
+
readonly minItems: 1;
|
|
55
|
+
readonly items: {
|
|
56
|
+
readonly type: "object";
|
|
57
|
+
readonly required: readonly ["version"];
|
|
58
|
+
readonly properties: {
|
|
59
|
+
readonly version: {
|
|
60
|
+
readonly type: "string";
|
|
61
|
+
};
|
|
62
|
+
readonly eol: {
|
|
63
|
+
readonly type: "string";
|
|
64
|
+
};
|
|
65
|
+
readonly lts: {
|
|
66
|
+
readonly type: "boolean";
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
readonly defaultVersion: {
|
|
72
|
+
readonly type: "string";
|
|
73
|
+
};
|
|
74
|
+
readonly defaultPort: {
|
|
75
|
+
readonly type: "integer";
|
|
76
|
+
readonly minimum: 1;
|
|
77
|
+
readonly maximum: 65535;
|
|
78
|
+
};
|
|
79
|
+
readonly requires: {
|
|
80
|
+
readonly type: "array";
|
|
81
|
+
readonly items: {
|
|
82
|
+
readonly type: "string";
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
readonly incompatibleWith: {
|
|
86
|
+
readonly type: "array";
|
|
87
|
+
readonly items: {
|
|
88
|
+
readonly type: "string";
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
readonly suggestedWith: {
|
|
92
|
+
readonly type: "array";
|
|
93
|
+
readonly items: {
|
|
94
|
+
readonly type: "string";
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
readonly officialScaffold: {
|
|
98
|
+
readonly type: readonly ["string", "null"];
|
|
99
|
+
};
|
|
100
|
+
readonly dockerImage: {
|
|
101
|
+
readonly type: readonly ["string", "null"];
|
|
102
|
+
};
|
|
103
|
+
readonly healthCheck: {
|
|
104
|
+
readonly type: "object";
|
|
105
|
+
readonly properties: {
|
|
106
|
+
readonly command: {
|
|
107
|
+
readonly type: "string";
|
|
108
|
+
};
|
|
109
|
+
readonly endpoint: {
|
|
110
|
+
readonly type: "string";
|
|
111
|
+
};
|
|
112
|
+
readonly interval: {
|
|
113
|
+
readonly type: "string";
|
|
114
|
+
};
|
|
115
|
+
readonly timeout: {
|
|
116
|
+
readonly type: "string";
|
|
117
|
+
};
|
|
118
|
+
readonly retries: {
|
|
119
|
+
readonly type: "integer";
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
readonly envVars: {
|
|
124
|
+
readonly type: "object";
|
|
125
|
+
readonly additionalProperties: {
|
|
126
|
+
readonly type: "string";
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
readonly configFiles: {
|
|
130
|
+
readonly type: "array";
|
|
131
|
+
readonly items: {
|
|
132
|
+
readonly type: "string";
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
readonly lastVerified: {
|
|
136
|
+
readonly type: "string";
|
|
137
|
+
};
|
|
138
|
+
readonly tags: {
|
|
139
|
+
readonly type: "array";
|
|
140
|
+
readonly items: {
|
|
141
|
+
readonly type: "string";
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
readonly additionalProperties: false;
|
|
146
|
+
};
|
|
147
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyEnB,CAAC"}
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Schema for technology YAML files.
|
|
3
|
+
* Validated with ajv on load.
|
|
4
|
+
*/
|
|
5
|
+
export const technologySchema = {
|
|
6
|
+
type: "object",
|
|
7
|
+
required: [
|
|
8
|
+
"id",
|
|
9
|
+
"name",
|
|
10
|
+
"category",
|
|
11
|
+
"description",
|
|
12
|
+
"website",
|
|
13
|
+
"versions",
|
|
14
|
+
"defaultVersion",
|
|
15
|
+
"requires",
|
|
16
|
+
"incompatibleWith",
|
|
17
|
+
"suggestedWith",
|
|
18
|
+
"envVars",
|
|
19
|
+
"configFiles",
|
|
20
|
+
"lastVerified",
|
|
21
|
+
"tags",
|
|
22
|
+
],
|
|
23
|
+
properties: {
|
|
24
|
+
id: { type: "string", pattern: "^[a-z][a-z0-9-]*$" },
|
|
25
|
+
name: { type: "string", minLength: 1 },
|
|
26
|
+
category: {
|
|
27
|
+
type: "string",
|
|
28
|
+
enum: [
|
|
29
|
+
"runtime",
|
|
30
|
+
"frontend",
|
|
31
|
+
"backend",
|
|
32
|
+
"database",
|
|
33
|
+
"orm",
|
|
34
|
+
"auth",
|
|
35
|
+
"styling",
|
|
36
|
+
"service",
|
|
37
|
+
"devops",
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
description: { type: "string" },
|
|
41
|
+
website: { type: "string" },
|
|
42
|
+
versions: {
|
|
43
|
+
type: "array",
|
|
44
|
+
minItems: 1,
|
|
45
|
+
items: {
|
|
46
|
+
type: "object",
|
|
47
|
+
required: ["version"],
|
|
48
|
+
properties: {
|
|
49
|
+
version: { type: "string" },
|
|
50
|
+
eol: { type: "string" },
|
|
51
|
+
lts: { type: "boolean" },
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
defaultVersion: { type: "string" },
|
|
56
|
+
defaultPort: { type: "integer", minimum: 1, maximum: 65535 },
|
|
57
|
+
requires: { type: "array", items: { type: "string" } },
|
|
58
|
+
incompatibleWith: { type: "array", items: { type: "string" } },
|
|
59
|
+
suggestedWith: { type: "array", items: { type: "string" } },
|
|
60
|
+
officialScaffold: { type: ["string", "null"] },
|
|
61
|
+
dockerImage: { type: ["string", "null"] },
|
|
62
|
+
healthCheck: {
|
|
63
|
+
type: "object",
|
|
64
|
+
properties: {
|
|
65
|
+
command: { type: "string" },
|
|
66
|
+
endpoint: { type: "string" },
|
|
67
|
+
interval: { type: "string" },
|
|
68
|
+
timeout: { type: "string" },
|
|
69
|
+
retries: { type: "integer" },
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
envVars: { type: "object", additionalProperties: { type: "string" } },
|
|
73
|
+
configFiles: { type: "array", items: { type: "string" } },
|
|
74
|
+
lastVerified: { type: "string" },
|
|
75
|
+
tags: { type: "array", items: { type: "string" } },
|
|
76
|
+
},
|
|
77
|
+
additionalProperties: false,
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE;QACR,IAAI;QACJ,MAAM;QACN,UAAU;QACV,aAAa;QACb,SAAS;QACT,UAAU;QACV,gBAAgB;QAChB,UAAU;QACV,kBAAkB;QAClB,eAAe;QACf,SAAS;QACT,aAAa;QACb,cAAc;QACd,MAAM;KACP;IACD,UAAU,EAAE;QACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,mBAAmB,EAAE;QACpD,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;QACtC,QAAQ,EAAE;YACR,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE;gBACJ,SAAS;gBACT,UAAU;gBACV,SAAS;gBACT,UAAU;gBACV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,SAAS;gBACT,QAAQ;aACT;SACF;QACD,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC/B,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC3B,QAAQ,EAAE;YACR,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,CAAC;YACX,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE,CAAC,SAAS,CAAC;gBACrB,UAAU,EAAE;oBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBAC3B,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACvB,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;iBACzB;aACF;SACF;QACD,cAAc,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAClC,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE;QAC5D,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QACtD,gBAAgB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QAC9D,aAAa,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QAC3D,gBAAgB,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE;QAC9C,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE;QACzC,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC3B,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC5B,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC5B,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC3B,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;aAC7B;SACF;QACD,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QACrE,WAAW,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QACzD,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAChC,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;KACnD;IACD,oBAAoB,EAAE,KAAK;CACnB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stackweld/registry",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Technology registry for Stackweld — 83 YAML technology definitions with JSON Schema validation.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Orlando Fernandez <hello@xplustechnologies.com>",
|
|
7
|
+
"homepage": "https://github.com/mundowise/Stackweld",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/mundowise/Stackweld.git",
|
|
11
|
+
"directory": "packages/registry"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": "./dist/index.js",
|
|
18
|
+
"./*": "./dist/*.js"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc -b",
|
|
22
|
+
"dev": "tsc -b --watch",
|
|
23
|
+
"test": "vitest run --passWithNoTests",
|
|
24
|
+
"typecheck": "tsc --noEmit",
|
|
25
|
+
"lint": "biome check src/",
|
|
26
|
+
"clean": "rm -rf dist .turbo"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@stackweld/core": "workspace:*",
|
|
30
|
+
"ajv": "^8.17.0",
|
|
31
|
+
"yaml": "^2.7.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@biomejs/biome": "^2.0.0",
|
|
35
|
+
"@types/node": "^22.0.0",
|
|
36
|
+
"typescript": "^5.9.0",
|
|
37
|
+
"vitest": "^4.1.2"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { listTechnologyIds, loadAllTechnologies, loadTechnology } from "../loader.js";
|
|
3
|
+
|
|
4
|
+
describe("Registry Loader", () => {
|
|
5
|
+
it("loads all 50 technologies", () => {
|
|
6
|
+
const techs = loadAllTechnologies();
|
|
7
|
+
expect(techs.length).toBeGreaterThanOrEqual(80);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("every technology has required fields", () => {
|
|
11
|
+
const techs = loadAllTechnologies();
|
|
12
|
+
for (const tech of techs) {
|
|
13
|
+
expect(tech.id).toBeTruthy();
|
|
14
|
+
expect(tech.name).toBeTruthy();
|
|
15
|
+
expect(tech.category).toBeTruthy();
|
|
16
|
+
expect(tech.versions.length).toBeGreaterThan(0);
|
|
17
|
+
expect(tech.defaultVersion).toBeTruthy();
|
|
18
|
+
expect(Array.isArray(tech.requires)).toBe(true);
|
|
19
|
+
expect(Array.isArray(tech.incompatibleWith)).toBe(true);
|
|
20
|
+
expect(Array.isArray(tech.suggestedWith)).toBe(true);
|
|
21
|
+
expect(Array.isArray(tech.tags)).toBe(true);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("loads a specific technology by ID", () => {
|
|
26
|
+
const tech = loadTechnology("nextjs");
|
|
27
|
+
expect(tech).not.toBeNull();
|
|
28
|
+
expect(tech?.name).toBe("Next.js");
|
|
29
|
+
expect(tech?.category).toBe("frontend");
|
|
30
|
+
expect(tech?.requires).toContain("nodejs");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("returns null for unknown technology", () => {
|
|
34
|
+
const tech = loadTechnology("nonexistent");
|
|
35
|
+
expect(tech).toBeNull();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("lists all technology IDs", () => {
|
|
39
|
+
const ids = listTechnologyIds();
|
|
40
|
+
expect(ids.length).toBeGreaterThanOrEqual(80);
|
|
41
|
+
expect(ids).toContain("nextjs");
|
|
42
|
+
expect(ids).toContain("postgresql");
|
|
43
|
+
expect(ids).toContain("prisma");
|
|
44
|
+
expect(ids).toContain("tailwindcss");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("has no broken cross-references", () => {
|
|
48
|
+
const techs = loadAllTechnologies();
|
|
49
|
+
const idSet = new Set(techs.map((t) => t.id));
|
|
50
|
+
|
|
51
|
+
for (const tech of techs) {
|
|
52
|
+
for (const ref of [...tech.requires, ...tech.incompatibleWith, ...tech.suggestedWith]) {
|
|
53
|
+
expect(idSet.has(ref), `${tech.id} references unknown "${ref}"`).toBe(true);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("covers all 9 categories", () => {
|
|
59
|
+
const techs = loadAllTechnologies();
|
|
60
|
+
const categories = new Set(techs.map((t) => t.category));
|
|
61
|
+
expect(categories).toContain("runtime");
|
|
62
|
+
expect(categories).toContain("frontend");
|
|
63
|
+
expect(categories).toContain("backend");
|
|
64
|
+
expect(categories).toContain("database");
|
|
65
|
+
expect(categories).toContain("orm");
|
|
66
|
+
expect(categories).toContain("auth");
|
|
67
|
+
expect(categories).toContain("styling");
|
|
68
|
+
expect(categories).toContain("service");
|
|
69
|
+
expect(categories).toContain("devops");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("incompatibleWith is symmetric", () => {
|
|
73
|
+
const techs = loadAllTechnologies();
|
|
74
|
+
const techMap = new Map(techs.map((t) => [t.id, t]));
|
|
75
|
+
|
|
76
|
+
for (const tech of techs) {
|
|
77
|
+
for (const incompId of tech.incompatibleWith) {
|
|
78
|
+
const other = techMap.get(incompId);
|
|
79
|
+
if (other) {
|
|
80
|
+
expect(
|
|
81
|
+
other.incompatibleWith.includes(tech.id),
|
|
82
|
+
`${tech.id} says incompatible with ${incompId}, but ${incompId} doesn't list ${tech.id}`,
|
|
83
|
+
).toBe(true);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("all technologies have unique IDs", () => {
|
|
90
|
+
const techs = loadAllTechnologies();
|
|
91
|
+
const ids = techs.map((t) => t.id);
|
|
92
|
+
const uniqueIds = new Set(ids);
|
|
93
|
+
expect(
|
|
94
|
+
uniqueIds.size,
|
|
95
|
+
`Found duplicate IDs: ${ids.filter((id, i) => ids.indexOf(id) !== i).join(", ")}`,
|
|
96
|
+
).toBe(ids.length);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("all requires references point to existing technology IDs", () => {
|
|
100
|
+
const techs = loadAllTechnologies();
|
|
101
|
+
const idSet = new Set(techs.map((t) => t.id));
|
|
102
|
+
|
|
103
|
+
for (const tech of techs) {
|
|
104
|
+
for (const reqId of tech.requires) {
|
|
105
|
+
expect(
|
|
106
|
+
idSet.has(reqId),
|
|
107
|
+
`${tech.id} requires "${reqId}" which does not exist in the registry`,
|
|
108
|
+
).toBe(true);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("all incompatibleWith references point to existing technology IDs", () => {
|
|
114
|
+
const techs = loadAllTechnologies();
|
|
115
|
+
const idSet = new Set(techs.map((t) => t.id));
|
|
116
|
+
|
|
117
|
+
for (const tech of techs) {
|
|
118
|
+
for (const incompId of tech.incompatibleWith) {
|
|
119
|
+
expect(
|
|
120
|
+
idSet.has(incompId),
|
|
121
|
+
`${tech.id} lists incompatibleWith "${incompId}" which does not exist in the registry`,
|
|
122
|
+
).toBe(true);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("no technology is incompatible with itself", () => {
|
|
128
|
+
const techs = loadAllTechnologies();
|
|
129
|
+
|
|
130
|
+
for (const tech of techs) {
|
|
131
|
+
expect(
|
|
132
|
+
tech.incompatibleWith.includes(tech.id),
|
|
133
|
+
`${tech.id} is listed as incompatible with itself`,
|
|
134
|
+
).toBe(false);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("all technologies have at least one version defined", () => {
|
|
139
|
+
const techs = loadAllTechnologies();
|
|
140
|
+
|
|
141
|
+
for (const tech of techs) {
|
|
142
|
+
expect(tech.versions.length, `${tech.id} has no versions defined`).toBeGreaterThan(0);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("bidirectional incompatibilities are symmetric (if A lists B, B lists A)", () => {
|
|
147
|
+
const techs = loadAllTechnologies();
|
|
148
|
+
const techMap = new Map(techs.map((t) => [t.id, t]));
|
|
149
|
+
const asymmetric: string[] = [];
|
|
150
|
+
|
|
151
|
+
for (const tech of techs) {
|
|
152
|
+
for (const incompId of tech.incompatibleWith) {
|
|
153
|
+
const other = techMap.get(incompId);
|
|
154
|
+
if (other && !other.incompatibleWith.includes(tech.id)) {
|
|
155
|
+
asymmetric.push(`${tech.id} -> ${incompId}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
expect(asymmetric, `Asymmetric incompatibilities found: ${asymmetric.join(", ")}`).toEqual([]);
|
|
161
|
+
});
|
|
162
|
+
});
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type { LearningResource } from "./learning-resources.js";
|
|
2
|
+
export { getLearningResources, LEARNING_RESOURCES } from "./learning-resources.js";
|
|
3
|
+
export { listTechnologyIds, loadAllTechnologies, loadTechnology } from "./loader.js";
|
|
4
|
+
export { technologySchema } from "./schema.js";
|