@grapity/grapity 0.4.0 → 0.5.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/dist/index.html CHANGED
@@ -9,9 +9,8 @@
9
9
  <link rel="preconnect" href="https://fonts.googleapis.com" />
10
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
11
11
  <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
12
- <script src="/config.js"></script>
13
- <script type="module" crossorigin src="/assets/index-JAhtTTW2.js"></script>
14
- <link rel="stylesheet" crossorigin href="/assets/index-LDlidn22.css">
12
+ <script type="module" crossorigin src="/assets/index-BAMa58dH.js"></script>
13
+ <link rel="stylesheet" crossorigin href="/assets/index-D24I8qIY.css">
15
14
  </head>
16
15
  <body>
17
16
  <div id="root"></div>
@@ -2963,7 +2963,7 @@ function buildKeycloakUrls(config) {
2963
2963
  tokenUrl: `${base}/protocol/openid-connect/token`
2964
2964
  };
2965
2965
  }
2966
- function createAuthMiddleware(config, routeScopes) {
2966
+ function createAuthMiddleware(config, routeScopes2) {
2967
2967
  if (config.auth?.mode !== "keycloak") {
2968
2968
  return async (_c, next) => await next();
2969
2969
  }
@@ -2971,7 +2971,7 @@ function createAuthMiddleware(config, routeScopes) {
2971
2971
  const { issuer, jwksUri } = buildKeycloakUrls(authConfig);
2972
2972
  const jwks = createRemoteJWKSet(new URL(jwksUri));
2973
2973
  const scopeByRoute = /* @__PURE__ */ new Map();
2974
- for (const route of routeScopes) {
2974
+ for (const route of routeScopes2) {
2975
2975
  const key = `${route.method.toUpperCase()}:${route.path}`;
2976
2976
  scopeByRoute.set(key, {
2977
2977
  operationId: route.operationId,
@@ -3033,47 +3033,194 @@ function extractScopes(payload, source) {
3033
3033
  }
3034
3034
  return /* @__PURE__ */ new Set();
3035
3035
  }
3036
- function parseRouteScopes(spec) {
3037
- const routes = [];
3038
- const paths = spec.paths;
3039
- if (!paths) return routes;
3040
- for (const [path, operations] of Object.entries(paths)) {
3041
- for (const [method, operation] of Object.entries(operations)) {
3042
- if (typeof operation !== "object" || operation === null) continue;
3043
- const op = operation;
3044
- const operationId = op.operationId;
3045
- if (!operationId) continue;
3046
- const security = op.security;
3047
- const scopes = [];
3048
- if (security) {
3049
- for (const sec of security) {
3050
- for (const [name, required] of Object.entries(sec)) {
3051
- if (name === "keycloak" && Array.isArray(required)) {
3052
- scopes.push(...required);
3053
- }
3054
- }
3055
- }
3056
- }
3057
- routes.push({
3058
- method: method.toUpperCase(),
3059
- path: path.replace(/\{([^}]+)\}/g, ":$1"),
3060
- operationId,
3061
- scopes
3062
- });
3063
- }
3036
+
3037
+ // src/registry/generated/route-scopes.ts
3038
+ var routeScopes = [
3039
+ {
3040
+ "method": "GET",
3041
+ "path": "/v1/health",
3042
+ "operationId": "getHealth",
3043
+ "scopes": []
3044
+ },
3045
+ {
3046
+ "method": "GET",
3047
+ "path": "/v1/specs",
3048
+ "operationId": "listSpecs",
3049
+ "scopes": [
3050
+ "specs:read"
3051
+ ]
3052
+ },
3053
+ {
3054
+ "method": "POST",
3055
+ "path": "/v1/specs",
3056
+ "operationId": "pushSpec",
3057
+ "scopes": [
3058
+ "specs:write"
3059
+ ]
3060
+ },
3061
+ {
3062
+ "method": "GET",
3063
+ "path": "/v1/specs/:name",
3064
+ "operationId": "getSpec",
3065
+ "scopes": [
3066
+ "specs:read"
3067
+ ]
3068
+ },
3069
+ {
3070
+ "method": "DELETE",
3071
+ "path": "/v1/specs/:name",
3072
+ "operationId": "deleteSpec",
3073
+ "scopes": [
3074
+ "specs:write"
3075
+ ]
3076
+ },
3077
+ {
3078
+ "method": "POST",
3079
+ "path": "/v1/specs/:name/validate",
3080
+ "operationId": "validateSpec",
3081
+ "scopes": [
3082
+ "specs:write"
3083
+ ]
3084
+ },
3085
+ {
3086
+ "method": "GET",
3087
+ "path": "/v1/specs/:name/versions",
3088
+ "operationId": "listVersions",
3089
+ "scopes": [
3090
+ "specs:read"
3091
+ ]
3092
+ },
3093
+ {
3094
+ "method": "GET",
3095
+ "path": "/v1/specs/:name/versions/:semver",
3096
+ "operationId": "getVersion",
3097
+ "scopes": [
3098
+ "specs:read"
3099
+ ]
3100
+ },
3101
+ {
3102
+ "method": "GET",
3103
+ "path": "/v1/specs/:name/spec.json",
3104
+ "operationId": "getSpecJson",
3105
+ "scopes": [
3106
+ "specs:read"
3107
+ ]
3108
+ },
3109
+ {
3110
+ "method": "GET",
3111
+ "path": "/v1/specs/:name/spec.yaml",
3112
+ "operationId": "getSpecYaml",
3113
+ "scopes": [
3114
+ "specs:read"
3115
+ ]
3116
+ },
3117
+ {
3118
+ "method": "GET",
3119
+ "path": "/v1/specs/:name/versions/:semver/spec.json",
3120
+ "operationId": "getVersionSpecJson",
3121
+ "scopes": [
3122
+ "specs:read"
3123
+ ]
3124
+ },
3125
+ {
3126
+ "method": "GET",
3127
+ "path": "/v1/specs/:name/versions/:semver/spec.yaml",
3128
+ "operationId": "getVersionSpecYaml",
3129
+ "scopes": [
3130
+ "specs:read"
3131
+ ]
3132
+ },
3133
+ {
3134
+ "method": "GET",
3135
+ "path": "/v1/specs/:name/compat/:semver",
3136
+ "operationId": "getCompatReport",
3137
+ "scopes": [
3138
+ "specs:read"
3139
+ ]
3140
+ },
3141
+ {
3142
+ "method": "GET",
3143
+ "path": "/v1/specs/:name/compare",
3144
+ "operationId": "compareVersions",
3145
+ "scopes": [
3146
+ "specs:read"
3147
+ ]
3148
+ },
3149
+ {
3150
+ "method": "GET",
3151
+ "path": "/v1/gateway-configs",
3152
+ "operationId": "listGatewayConfigs",
3153
+ "scopes": [
3154
+ "gateway-configs:read"
3155
+ ]
3156
+ },
3157
+ {
3158
+ "method": "POST",
3159
+ "path": "/v1/gateway-configs",
3160
+ "operationId": "pushGatewayConfig",
3161
+ "scopes": [
3162
+ "gateway-configs:write"
3163
+ ]
3164
+ },
3165
+ {
3166
+ "method": "GET",
3167
+ "path": "/v1/gateway-configs/:name",
3168
+ "operationId": "getGatewayConfig",
3169
+ "scopes": [
3170
+ "gateway-configs:read"
3171
+ ]
3172
+ },
3173
+ {
3174
+ "method": "GET",
3175
+ "path": "/v1/gateway-configs/:name/versions",
3176
+ "operationId": "listGatewayConfigVersions",
3177
+ "scopes": [
3178
+ "gateway-configs:read"
3179
+ ]
3180
+ },
3181
+ {
3182
+ "method": "GET",
3183
+ "path": "/v1/gateway-configs/:name/versions/:versionId",
3184
+ "operationId": "getGatewayConfigVersion",
3185
+ "scopes": [
3186
+ "gateway-configs:read"
3187
+ ]
3188
+ },
3189
+ {
3190
+ "method": "POST",
3191
+ "path": "/v1/gateway-logs/ingest/:provider/:environment",
3192
+ "operationId": "ingestGatewayLog",
3193
+ "scopes": [
3194
+ "gateway-logs:write"
3195
+ ]
3196
+ },
3197
+ {
3198
+ "method": "GET",
3199
+ "path": "/v1/gateway-logs",
3200
+ "operationId": "listGatewayLogs",
3201
+ "scopes": [
3202
+ "gateway-logs:read"
3203
+ ]
3204
+ },
3205
+ {
3206
+ "method": "GET",
3207
+ "path": "/v1/gateway-logs/stats",
3208
+ "operationId": "getGatewayLogStats",
3209
+ "scopes": [
3210
+ "gateway-logs:read"
3211
+ ]
3212
+ },
3213
+ {
3214
+ "method": "GET",
3215
+ "path": "/v1/gateway-logs/:id",
3216
+ "operationId": "getGatewayLog",
3217
+ "scopes": [
3218
+ "gateway-logs:read"
3219
+ ]
3064
3220
  }
3065
- return routes;
3066
- }
3221
+ ];
3067
3222
 
3068
3223
  // src/registry/server.ts
3069
- import { readFileSync } from "fs";
3070
- import { fileURLToPath } from "url";
3071
- import yaml6 from "js-yaml";
3072
- function loadOpenApiSpec() {
3073
- const path = fileURLToPath(new URL("../../openapi.yaml", import.meta.url));
3074
- const content = readFileSync(path, "utf-8");
3075
- return yaml6.load(content);
3076
- }
3077
3224
  function createApp(config, store) {
3078
3225
  const app = new Hono22();
3079
3226
  app.use("*", logger());
@@ -3084,8 +3231,8 @@ function createApp(config, store) {
3084
3231
  c.set("config", config);
3085
3232
  await next();
3086
3233
  });
3087
- const routeScopes = parseRouteScopes(loadOpenApiSpec());
3088
- app.use("*", createAuthMiddleware(config, routeScopes));
3234
+ const authRouteScopes = config.auth?.mode === "keycloak" ? routeScopes : [];
3235
+ app.use("*", createAuthMiddleware(config, authRouteScopes));
3089
3236
  app.onError((err, c) => {
3090
3237
  if (err instanceof AuthError) {
3091
3238
  return c.json(
@@ -2968,7 +2968,7 @@ function buildKeycloakUrls(config) {
2968
2968
  tokenUrl: `${base}/protocol/openid-connect/token`
2969
2969
  };
2970
2970
  }
2971
- function createAuthMiddleware(config, routeScopes) {
2971
+ function createAuthMiddleware(config, routeScopes2) {
2972
2972
  if (config.auth?.mode !== "keycloak") {
2973
2973
  return async (_c, next) => await next();
2974
2974
  }
@@ -2976,7 +2976,7 @@ function createAuthMiddleware(config, routeScopes) {
2976
2976
  const { issuer, jwksUri } = buildKeycloakUrls(authConfig);
2977
2977
  const jwks = createRemoteJWKSet(new URL(jwksUri));
2978
2978
  const scopeByRoute = /* @__PURE__ */ new Map();
2979
- for (const route of routeScopes) {
2979
+ for (const route of routeScopes2) {
2980
2980
  const key = `${route.method.toUpperCase()}:${route.path}`;
2981
2981
  scopeByRoute.set(key, {
2982
2982
  operationId: route.operationId,
@@ -3038,47 +3038,194 @@ function extractScopes(payload, source) {
3038
3038
  }
3039
3039
  return /* @__PURE__ */ new Set();
3040
3040
  }
3041
- function parseRouteScopes(spec) {
3042
- const routes = [];
3043
- const paths = spec.paths;
3044
- if (!paths) return routes;
3045
- for (const [path2, operations] of Object.entries(paths)) {
3046
- for (const [method, operation] of Object.entries(operations)) {
3047
- if (typeof operation !== "object" || operation === null) continue;
3048
- const op = operation;
3049
- const operationId = op.operationId;
3050
- if (!operationId) continue;
3051
- const security = op.security;
3052
- const scopes = [];
3053
- if (security) {
3054
- for (const sec of security) {
3055
- for (const [name, required] of Object.entries(sec)) {
3056
- if (name === "keycloak" && Array.isArray(required)) {
3057
- scopes.push(...required);
3058
- }
3059
- }
3060
- }
3061
- }
3062
- routes.push({
3063
- method: method.toUpperCase(),
3064
- path: path2.replace(/\{([^}]+)\}/g, ":$1"),
3065
- operationId,
3066
- scopes
3067
- });
3068
- }
3041
+
3042
+ // src/registry/generated/route-scopes.ts
3043
+ var routeScopes = [
3044
+ {
3045
+ "method": "GET",
3046
+ "path": "/v1/health",
3047
+ "operationId": "getHealth",
3048
+ "scopes": []
3049
+ },
3050
+ {
3051
+ "method": "GET",
3052
+ "path": "/v1/specs",
3053
+ "operationId": "listSpecs",
3054
+ "scopes": [
3055
+ "specs:read"
3056
+ ]
3057
+ },
3058
+ {
3059
+ "method": "POST",
3060
+ "path": "/v1/specs",
3061
+ "operationId": "pushSpec",
3062
+ "scopes": [
3063
+ "specs:write"
3064
+ ]
3065
+ },
3066
+ {
3067
+ "method": "GET",
3068
+ "path": "/v1/specs/:name",
3069
+ "operationId": "getSpec",
3070
+ "scopes": [
3071
+ "specs:read"
3072
+ ]
3073
+ },
3074
+ {
3075
+ "method": "DELETE",
3076
+ "path": "/v1/specs/:name",
3077
+ "operationId": "deleteSpec",
3078
+ "scopes": [
3079
+ "specs:write"
3080
+ ]
3081
+ },
3082
+ {
3083
+ "method": "POST",
3084
+ "path": "/v1/specs/:name/validate",
3085
+ "operationId": "validateSpec",
3086
+ "scopes": [
3087
+ "specs:write"
3088
+ ]
3089
+ },
3090
+ {
3091
+ "method": "GET",
3092
+ "path": "/v1/specs/:name/versions",
3093
+ "operationId": "listVersions",
3094
+ "scopes": [
3095
+ "specs:read"
3096
+ ]
3097
+ },
3098
+ {
3099
+ "method": "GET",
3100
+ "path": "/v1/specs/:name/versions/:semver",
3101
+ "operationId": "getVersion",
3102
+ "scopes": [
3103
+ "specs:read"
3104
+ ]
3105
+ },
3106
+ {
3107
+ "method": "GET",
3108
+ "path": "/v1/specs/:name/spec.json",
3109
+ "operationId": "getSpecJson",
3110
+ "scopes": [
3111
+ "specs:read"
3112
+ ]
3113
+ },
3114
+ {
3115
+ "method": "GET",
3116
+ "path": "/v1/specs/:name/spec.yaml",
3117
+ "operationId": "getSpecYaml",
3118
+ "scopes": [
3119
+ "specs:read"
3120
+ ]
3121
+ },
3122
+ {
3123
+ "method": "GET",
3124
+ "path": "/v1/specs/:name/versions/:semver/spec.json",
3125
+ "operationId": "getVersionSpecJson",
3126
+ "scopes": [
3127
+ "specs:read"
3128
+ ]
3129
+ },
3130
+ {
3131
+ "method": "GET",
3132
+ "path": "/v1/specs/:name/versions/:semver/spec.yaml",
3133
+ "operationId": "getVersionSpecYaml",
3134
+ "scopes": [
3135
+ "specs:read"
3136
+ ]
3137
+ },
3138
+ {
3139
+ "method": "GET",
3140
+ "path": "/v1/specs/:name/compat/:semver",
3141
+ "operationId": "getCompatReport",
3142
+ "scopes": [
3143
+ "specs:read"
3144
+ ]
3145
+ },
3146
+ {
3147
+ "method": "GET",
3148
+ "path": "/v1/specs/:name/compare",
3149
+ "operationId": "compareVersions",
3150
+ "scopes": [
3151
+ "specs:read"
3152
+ ]
3153
+ },
3154
+ {
3155
+ "method": "GET",
3156
+ "path": "/v1/gateway-configs",
3157
+ "operationId": "listGatewayConfigs",
3158
+ "scopes": [
3159
+ "gateway-configs:read"
3160
+ ]
3161
+ },
3162
+ {
3163
+ "method": "POST",
3164
+ "path": "/v1/gateway-configs",
3165
+ "operationId": "pushGatewayConfig",
3166
+ "scopes": [
3167
+ "gateway-configs:write"
3168
+ ]
3169
+ },
3170
+ {
3171
+ "method": "GET",
3172
+ "path": "/v1/gateway-configs/:name",
3173
+ "operationId": "getGatewayConfig",
3174
+ "scopes": [
3175
+ "gateway-configs:read"
3176
+ ]
3177
+ },
3178
+ {
3179
+ "method": "GET",
3180
+ "path": "/v1/gateway-configs/:name/versions",
3181
+ "operationId": "listGatewayConfigVersions",
3182
+ "scopes": [
3183
+ "gateway-configs:read"
3184
+ ]
3185
+ },
3186
+ {
3187
+ "method": "GET",
3188
+ "path": "/v1/gateway-configs/:name/versions/:versionId",
3189
+ "operationId": "getGatewayConfigVersion",
3190
+ "scopes": [
3191
+ "gateway-configs:read"
3192
+ ]
3193
+ },
3194
+ {
3195
+ "method": "POST",
3196
+ "path": "/v1/gateway-logs/ingest/:provider/:environment",
3197
+ "operationId": "ingestGatewayLog",
3198
+ "scopes": [
3199
+ "gateway-logs:write"
3200
+ ]
3201
+ },
3202
+ {
3203
+ "method": "GET",
3204
+ "path": "/v1/gateway-logs",
3205
+ "operationId": "listGatewayLogs",
3206
+ "scopes": [
3207
+ "gateway-logs:read"
3208
+ ]
3209
+ },
3210
+ {
3211
+ "method": "GET",
3212
+ "path": "/v1/gateway-logs/stats",
3213
+ "operationId": "getGatewayLogStats",
3214
+ "scopes": [
3215
+ "gateway-logs:read"
3216
+ ]
3217
+ },
3218
+ {
3219
+ "method": "GET",
3220
+ "path": "/v1/gateway-logs/:id",
3221
+ "operationId": "getGatewayLog",
3222
+ "scopes": [
3223
+ "gateway-logs:read"
3224
+ ]
3069
3225
  }
3070
- return routes;
3071
- }
3226
+ ];
3072
3227
 
3073
3228
  // src/registry/server.ts
3074
- import { readFileSync } from "fs";
3075
- import { fileURLToPath } from "url";
3076
- import yaml6 from "js-yaml";
3077
- function loadOpenApiSpec() {
3078
- const path2 = fileURLToPath(new URL("../../openapi.yaml", import.meta.url));
3079
- const content = readFileSync(path2, "utf-8");
3080
- return yaml6.load(content);
3081
- }
3082
3229
  function createApp(config, store) {
3083
3230
  const app = new Hono22();
3084
3231
  app.use("*", logger());
@@ -3089,8 +3236,8 @@ function createApp(config, store) {
3089
3236
  c.set("config", config);
3090
3237
  await next();
3091
3238
  });
3092
- const routeScopes = parseRouteScopes(loadOpenApiSpec());
3093
- app.use("*", createAuthMiddleware(config, routeScopes));
3239
+ const authRouteScopes = config.auth?.mode === "keycloak" ? routeScopes : [];
3240
+ app.use("*", createAuthMiddleware(config, authRouteScopes));
3094
3241
  app.onError((err, c) => {
3095
3242
  if (err instanceof AuthError) {
3096
3243
  return c.json(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grapity/grapity",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "description": "grapity - API spec registry and compatibility guardian",
6
6
  "license": "Apache-2.0",
@@ -71,18 +71,18 @@
71
71
  "better-sqlite3": "^12.10.0",
72
72
  "chalk": "^5.4.0",
73
73
  "commander": "^13.1.0",
74
- "drizzle-orm": "^0.44.0",
74
+ "drizzle-orm": "^0.45.0",
75
75
  "hono": "^4.12.22",
76
76
  "jose": "^6.2.3",
77
77
  "js-yaml": "^4.1.0",
78
- "lucide-react": "^0.475.0",
79
- "ora": "^8.2.0",
78
+ "lucide-react": "^0.577.0",
79
+ "ora": "^9.0.0",
80
80
  "pg": "^8.16.0",
81
81
  "react": "^19.0.0",
82
82
  "react-dom": "^19.0.0",
83
83
  "react-router-dom": "^7.4.0",
84
84
  "shiki": "^4.2.0",
85
- "uuid": "^11.1.0",
85
+ "uuid": "^14.0.0",
86
86
  "zod": "^3.24.0"
87
87
  },
88
88
  "devDependencies": {