@nospt/backstage-plugin-apigee-backend 1.1.0-rc2
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 +118 -0
- package/config.d.ts +85 -0
- package/dist/index.cjs.js +22 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +511 -0
- package/dist/lib/api-hub-client.cjs.js +118 -0
- package/dist/lib/api-hub-client.cjs.js.map +1 -0
- package/dist/lib/apigee-client.cjs.js +40 -0
- package/dist/lib/apigee-client.cjs.js.map +1 -0
- package/dist/lib/apigee-stitching-processor.cjs.js +104 -0
- package/dist/lib/apigee-stitching-processor.cjs.js.map +1 -0
- package/dist/lib/entity-builder.cjs.js +347 -0
- package/dist/lib/entity-builder.cjs.js.map +1 -0
- package/dist/lib/entity-provider.cjs.js +502 -0
- package/dist/lib/entity-provider.cjs.js.map +1 -0
- package/dist/lib/fetch-utils.cjs.js +49 -0
- package/dist/lib/fetch-utils.cjs.js.map +1 -0
- package/dist/lib/sharedflow-client.cjs.js +21 -0
- package/dist/lib/sharedflow-client.cjs.js.map +1 -0
- package/dist/module.cjs.js +93 -0
- package/dist/module.cjs.js.map +1 -0
- package/dist/plugin.cjs.js +28 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/router.cjs.js +26 -0
- package/dist/router.cjs.js.map +1 -0
- package/package.json +78 -0
package/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# @nospt/backstage-plugin-apigee-backend
|
|
2
|
+
|
|
3
|
+
Backend package for the bootstrap stage of the Backstage Apigee plugin.
|
|
4
|
+
|
|
5
|
+
## Included
|
|
6
|
+
|
|
7
|
+
- New Backend System plugin registration
|
|
8
|
+
- Minimal router mounted at `/api/apigee`
|
|
9
|
+
- Placeholder health endpoint at `/api/apigee/health`
|
|
10
|
+
|
|
11
|
+
## Development
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
cd plugins/apigee-backend
|
|
15
|
+
yarn start
|
|
16
|
+
yarn test
|
|
17
|
+
yarn lint
|
|
18
|
+
yarn build
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Repository Stitching
|
|
22
|
+
|
|
23
|
+
A Backstage `CatalogProcessor` (`ApigeeStitchingProcessor`) links a backend
|
|
24
|
+
`Component` to its proxy `API` entity by emitting the native `providesApi` /
|
|
25
|
+
`apiProvidedBy` relations. This surfaces the standard **"Provided APIs"** card on
|
|
26
|
+
the component page and the **"Providers"** card on the API page — with zero custom
|
|
27
|
+
UI. A repository opts in by adding `nos.pt/apigee-*` annotations to its
|
|
28
|
+
`catalog-info.yaml`.
|
|
29
|
+
|
|
30
|
+
### Annotation styles
|
|
31
|
+
|
|
32
|
+
**Direct mapping (active in this release):**
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
apiVersion: backstage.io/v1alpha1
|
|
36
|
+
kind: Component
|
|
37
|
+
metadata:
|
|
38
|
+
name: orders-service
|
|
39
|
+
annotations:
|
|
40
|
+
nos.pt/apigee-api-name: my-proxy
|
|
41
|
+
nos.pt/apigee-project-id: apigee-x-public-p-123
|
|
42
|
+
spec:
|
|
43
|
+
type: service
|
|
44
|
+
owner: team-orders
|
|
45
|
+
lifecycle: production
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**TargetServer-based mapping (documented; resolution planned, not yet active):**
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
metadata:
|
|
52
|
+
annotations:
|
|
53
|
+
nos.pt/apigee-targetserver-hostname: backend.nos.pt
|
|
54
|
+
nos.pt/apigee-targetserver-port: "443"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Precedence rule
|
|
58
|
+
|
|
59
|
+
When both styles are present, the **TargetServer-based mapping is the preferred**
|
|
60
|
+
resolution path (STITCH-02). The direct API-name mapping is the **fallback**, used
|
|
61
|
+
when no TargetServer annotation is present or when TargetServer resolution is
|
|
62
|
+
ambiguous (for example, a generic load balancer shared by many proxies).
|
|
63
|
+
|
|
64
|
+
> **In this release only the direct-mapping path is implemented.** TargetServer
|
|
65
|
+
> resolution is planned but not yet active — no TargetServer data is captured by the
|
|
66
|
+
> entity provider yet (see `04-CONTEXT` D-01). The processor is structured around a
|
|
67
|
+
> resolution-strategy seam so the TargetServer branch slots in without rework.
|
|
68
|
+
|
|
69
|
+
### Apigee → Backstage mapping
|
|
70
|
+
|
|
71
|
+
| Apigee concept | Backstage entity |
|
|
72
|
+
|----------------|------------------|
|
|
73
|
+
| API proxy (implementation) | `kind: Component`, `spec.type: api-proxy` |
|
|
74
|
+
| API proxy (contract) | `kind: API`, `spec.type` from API Hub (default `openapi`) |
|
|
75
|
+
| Sharedflow | `kind: Component`, `spec.type: library` |
|
|
76
|
+
| Backend repo component ↔ proxy API | `providesApi` / `apiProvidedBy` relation |
|
|
77
|
+
|
|
78
|
+
### Resolution detail
|
|
79
|
+
|
|
80
|
+
The target API entity ref is deterministic:
|
|
81
|
+
`api:default/<slugify(nos.pt/apigee-api-name)>`. The processor reads the annotations,
|
|
82
|
+
synthesizes the ref, and emits the relation pair — no live catalog lookup is needed.
|
|
83
|
+
A partial annotation set (e.g. `nos.pt/apigee-api-name` without
|
|
84
|
+
`nos.pt/apigee-project-id`) or an empty/unresolvable value is skipped with a warning
|
|
85
|
+
(warn-and-skip), so no malformed relations are emitted.
|
|
86
|
+
|
|
87
|
+
### Example fixture
|
|
88
|
+
|
|
89
|
+
See [`examples/components.yaml`](./examples/components.yaml) for ready-to-register
|
|
90
|
+
sample `Component` entities exercising both annotation styles — useful for local
|
|
91
|
+
smoke testing of the stitching processor.
|
|
92
|
+
|
|
93
|
+
## API Hub enrichment
|
|
94
|
+
|
|
95
|
+
`kind: API` entities discovered from Apigee are enriched with API Hub metadata
|
|
96
|
+
(owner, description, categories, department, spec). The **"Source repository"** link
|
|
97
|
+
on the API entity page (`metadata.links`) is resolved in this order:
|
|
98
|
+
|
|
99
|
+
1. API Hub **Documentation** field (`Api.documentation.externalUri`) — NOS records
|
|
100
|
+
the proxy's GitHub repository URL here (e.g.
|
|
101
|
+
`https://github.com/nosportugal/apigee-x-proxy-<proxy-name>`).
|
|
102
|
+
2. The first `sourceMetadata[]` entry whose value is an `http(s)` URL
|
|
103
|
+
(`repo`/`git`/`source` types preferred when several qualify).
|
|
104
|
+
3. The `apigee.orgs[].githubOrgSlug` convention:
|
|
105
|
+
`https://github.com/<slug>/<entity-name>`.
|
|
106
|
+
|
|
107
|
+
Only `http(s)` URLs are ever emitted; `javascript:`/`data:` values are rejected to
|
|
108
|
+
prevent link injection into rendered entity pages.
|
|
109
|
+
|
|
110
|
+
### Department label
|
|
111
|
+
|
|
112
|
+
Both the proxy `kind: Component` and its `kind: API` entity carry a `department`
|
|
113
|
+
label (`metadata.labels.department`) sourced from the Cloud API Hub **Business
|
|
114
|
+
unit** attribute. Business unit is a top-level API Hub `AttributeValues` field; a
|
|
115
|
+
user-modelled `business-unit` attribute is scanned only as a fallback. The raw
|
|
116
|
+
value is slugified and capped at 63 characters so it is always a valid Backstage
|
|
117
|
+
label value. The frontend catalog page exposes it as a **Department** filter
|
|
118
|
+
facet.
|
package/config.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
export interface Config {
|
|
2
|
+
/** Apigee catalog module configuration */
|
|
3
|
+
apigee?: {
|
|
4
|
+
/**
|
|
5
|
+
* List of Apigee X organisations to sync.
|
|
6
|
+
* At least one entry is required; the module fails fast at startup if missing.
|
|
7
|
+
* @visibility backend
|
|
8
|
+
*/
|
|
9
|
+
orgs: Array<{
|
|
10
|
+
/** Human-readable label for this org */
|
|
11
|
+
name: string;
|
|
12
|
+
/** GCP project ID that owns this Apigee X organisation */
|
|
13
|
+
projectId: string;
|
|
14
|
+
/**
|
|
15
|
+
* Optional list of environments to include (e.g. ["prod", "staging"]).
|
|
16
|
+
* If omitted, all environments are synced.
|
|
17
|
+
* @visibility backend
|
|
18
|
+
*/
|
|
19
|
+
environments?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Optional GitHub organisation slug used to derive GitHub repo links
|
|
22
|
+
* when API Hub does not supply a repositoryUri (FR17).
|
|
23
|
+
* @visibility backend
|
|
24
|
+
*/
|
|
25
|
+
githubOrgSlug?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Explicit proxy-name -> API Hub apiId overrides for proxies whose slug
|
|
28
|
+
* does not match their API Hub apiId (D-01).
|
|
29
|
+
* @visibility backend
|
|
30
|
+
*/
|
|
31
|
+
apiHubMappings?: { [proxyName: string]: string };
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Catalog sync interval in minutes. Default: 60.
|
|
35
|
+
* @visibility backend
|
|
36
|
+
*/
|
|
37
|
+
syncIntervalMinutes?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Default spec.owner for API entities whose API Hub ownerTeam is absent.
|
|
40
|
+
* Must be a Backstage entity reference, e.g. "group:default/platform-team".
|
|
41
|
+
* @visibility backend
|
|
42
|
+
*/
|
|
43
|
+
defaultOwner?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Maximum inline spec size in bytes; specs larger than this are linked via
|
|
46
|
+
* apigee.com/spec-url instead of embedded. Default 512000 (500 KB).
|
|
47
|
+
* @visibility backend
|
|
48
|
+
*/
|
|
49
|
+
specMaxBytes?: number;
|
|
50
|
+
/**
|
|
51
|
+
* Optional map of Apigee environment name to Backstage lifecycle
|
|
52
|
+
* ("production" | "experimental" | "deprecated"). When set, a proxy's
|
|
53
|
+
* lifecycle is derived from the environments it is deployed to, with the
|
|
54
|
+
* highest-ranked lifecycle winning (production > experimental > deprecated).
|
|
55
|
+
* Environments not listed default to "experimental". When omitted, any
|
|
56
|
+
* ready deployment marks the proxy as "production".
|
|
57
|
+
* @visibility backend
|
|
58
|
+
*/
|
|
59
|
+
environmentLifecycle?: { [environment: string]: string };
|
|
60
|
+
/**
|
|
61
|
+
* API Hub location (GCP region) to query. Defaults to "global".
|
|
62
|
+
* Use this when your API Hub instance is regional, e.g. "europe-west1".
|
|
63
|
+
* @visibility backend
|
|
64
|
+
*/
|
|
65
|
+
apiHubLocation?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Optional custom schedule for the catalog sync task.
|
|
68
|
+
* When provided, overrides syncIntervalMinutes.
|
|
69
|
+
* @visibility backend
|
|
70
|
+
*/
|
|
71
|
+
schedule?: {
|
|
72
|
+
/** How often to run the sync. */
|
|
73
|
+
frequency?: {
|
|
74
|
+
cron?: string;
|
|
75
|
+
minutes?: number;
|
|
76
|
+
hours?: number;
|
|
77
|
+
seconds?: number;
|
|
78
|
+
};
|
|
79
|
+
/** Maximum time allowed for a single sync run. */
|
|
80
|
+
timeout?: { minutes?: number; seconds?: number };
|
|
81
|
+
/** Delay before the first run after startup. */
|
|
82
|
+
initialDelay?: { minutes?: number; seconds?: number };
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var plugin = require('./plugin.cjs.js');
|
|
6
|
+
var module$1 = require('./module.cjs.js');
|
|
7
|
+
var apigeeClient = require('./lib/apigee-client.cjs.js');
|
|
8
|
+
var apiHubClient = require('./lib/api-hub-client.cjs.js');
|
|
9
|
+
var entityProvider = require('./lib/entity-provider.cjs.js');
|
|
10
|
+
var sharedflowClient = require('./lib/sharedflow-client.cjs.js');
|
|
11
|
+
var apigeeStitchingProcessor = require('./lib/apigee-stitching-processor.cjs.js');
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
exports.default = plugin.apigeePlugin;
|
|
16
|
+
exports.catalogModuleApigee = module$1.catalogModuleApigee;
|
|
17
|
+
exports.ApigeeClient = apigeeClient.ApigeeClient;
|
|
18
|
+
exports.ApiHubClient = apiHubClient.ApiHubClient;
|
|
19
|
+
exports.ApigeeEntityProvider = entityProvider.ApigeeEntityProvider;
|
|
20
|
+
exports.SharedflowClient = sharedflowClient.SharedflowClient;
|
|
21
|
+
exports.ApigeeStitchingProcessor = apigeeStitchingProcessor.ApigeeStitchingProcessor;
|
|
22
|
+
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;"}
|