@crombolo/contracts 0.14.4 → 0.15.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/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/overrides.ts +40 -0
- package/src/spec.ts +16 -2
package/package.json
CHANGED
package/src/index.ts
CHANGED
package/src/overrides.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where crombolo's Management API differs from Umbraco's contract on purpose.
|
|
3
|
+
* `OpenApi.json` stays exactly Umbraco's, so a re-copy from a new release is a
|
|
4
|
+
* clean diff; each difference is listed here with its reason, and applied when
|
|
5
|
+
* the contract is loaded and when it is served.
|
|
6
|
+
*/
|
|
7
|
+
export interface ContractOverride {
|
|
8
|
+
/** The schema under `components.schemas` it changes. */
|
|
9
|
+
schema: string
|
|
10
|
+
story: string
|
|
11
|
+
reason: string
|
|
12
|
+
apply(schema: Record<string, unknown>): void
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const CONTRACT_OVERRIDES: readonly ContractOverride[] = [
|
|
16
|
+
{
|
|
17
|
+
schema: 'CreateMemberRequestModel',
|
|
18
|
+
story: '035',
|
|
19
|
+
reason:
|
|
20
|
+
'A member who will only ever sign in through an identity provider is created with no password, as external sign-in creates one.',
|
|
21
|
+
apply(schema) {
|
|
22
|
+
schema.required = ((schema.required as string[] | undefined) ?? []).filter(
|
|
23
|
+
(field) => field !== 'password',
|
|
24
|
+
)
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
/** The contract with every override applied, leaving the one given untouched. */
|
|
30
|
+
export function applyOverrides<T extends { components: { schemas: Record<string, unknown> } }>(
|
|
31
|
+
spec: T,
|
|
32
|
+
): T {
|
|
33
|
+
const copy = structuredClone(spec)
|
|
34
|
+
for (const override of CONTRACT_OVERRIDES) {
|
|
35
|
+
const schema = copy.components.schemas[override.schema] as Record<string, unknown> | undefined
|
|
36
|
+
if (!schema) throw new Error(`The contract has no schema ${override.schema} to override`)
|
|
37
|
+
override.apply(schema)
|
|
38
|
+
}
|
|
39
|
+
return copy
|
|
40
|
+
}
|
package/src/spec.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** Loads and indexes the vendored Umbraco Management API OpenAPI contract. */
|
|
2
2
|
import { readFileSync } from 'node:fs'
|
|
3
3
|
import { join } from 'node:path'
|
|
4
|
+
import { applyOverrides } from './overrides.ts'
|
|
4
5
|
|
|
5
6
|
export const SPEC_PATH = join(import.meta.dir, '../OpenApi.json')
|
|
6
7
|
|
|
@@ -40,12 +41,25 @@ export interface OpenApiSpec {
|
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
let cached: OpenApiSpec | undefined
|
|
44
|
+
let served: string | undefined
|
|
43
45
|
|
|
46
|
+
/** Umbraco's contract exactly as vendored, before crombolo's deliberate differences. */
|
|
47
|
+
export function loadUmbracoSpec(): OpenApiSpec {
|
|
48
|
+
return JSON.parse(readFileSync(SPEC_PATH, 'utf8')) as OpenApiSpec
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** The contract crombolo answers to: Umbraco's, with `CONTRACT_OVERRIDES` applied. */
|
|
44
52
|
export function loadSpec(): OpenApiSpec {
|
|
45
|
-
if (!cached) cached =
|
|
53
|
+
if (!cached) cached = applyOverrides(loadUmbracoSpec())
|
|
46
54
|
return cached
|
|
47
55
|
}
|
|
48
56
|
|
|
57
|
+
/** The contract as `GET …/openapi.json` serves it. */
|
|
58
|
+
export function servedContract(): string {
|
|
59
|
+
if (!served) served = JSON.stringify(loadSpec())
|
|
60
|
+
return served
|
|
61
|
+
}
|
|
62
|
+
|
|
49
63
|
let deliveryCached: OpenApiSpec | undefined
|
|
50
64
|
|
|
51
65
|
export function loadDeliverySpec(): OpenApiSpec {
|
|
@@ -55,7 +69,7 @@ export function loadDeliverySpec(): OpenApiSpec {
|
|
|
55
69
|
}
|
|
56
70
|
|
|
57
71
|
export async function loadSpecAsync(): Promise<OpenApiSpec> {
|
|
58
|
-
if (!cached) cached = (await Bun.file(SPEC_PATH).json()) as OpenApiSpec
|
|
72
|
+
if (!cached) cached = applyOverrides((await Bun.file(SPEC_PATH).json()) as OpenApiSpec)
|
|
59
73
|
return cached
|
|
60
74
|
}
|
|
61
75
|
|