@tsdoctor/manifest 0.1.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/BundleManifest.js +209 -0
- package/LICENSE +21 -0
- package/ManifestSource.js +38 -0
- package/index.d.ts +339 -0
- package/index.js +4 -0
- package/package.json +43 -0
- package/tsdoc-metadata.json +11 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
|
|
3
|
+
//#region src/BundleManifest.ts
|
|
4
|
+
/**
|
|
5
|
+
* The registry protocol families this reader knows how to do more than link
|
|
6
|
+
* to. `"npm"` means an npm-compatible registry — install commands and tarball
|
|
7
|
+
* fetching work against any instance of it — and `"jsr"` the jsr protocol.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* The manifest's `type` field is deliberately NOT constrained to these
|
|
11
|
+
* values: unknown future types must degrade to link-only rendering, not
|
|
12
|
+
* reject the manifest. Use {@link isKnownRegistryType} to branch.
|
|
13
|
+
*
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
const KNOWN_REGISTRY_TYPES = ["npm", "jsr"];
|
|
17
|
+
/**
|
|
18
|
+
* Whether a registry `type` value is a protocol family this reader
|
|
19
|
+
* recognizes. `false` means the registry entry should degrade to link-only
|
|
20
|
+
* rendering — it is never a validation failure.
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
function isKnownRegistryType(type) {
|
|
25
|
+
return KNOWN_REGISTRY_TYPES.includes(type);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* One registry the documented package is published to.
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* `type` is the PROTOCOL FAMILY (`"npm"` covers every npm-compatible
|
|
32
|
+
* registry), `name` the human instance label, `url` the package's page on
|
|
33
|
+
* that instance. Unknown `type` values decode successfully and degrade to
|
|
34
|
+
* link-only rendering (see {@link isKnownRegistryType}).
|
|
35
|
+
*
|
|
36
|
+
* @public
|
|
37
|
+
*/
|
|
38
|
+
const RegistryRef = Schema.Struct({
|
|
39
|
+
/** The protocol family, e.g. `"npm"` or `"jsr"`. Unknown values are accepted. */
|
|
40
|
+
type: Schema.String,
|
|
41
|
+
/** The human instance label, e.g. `"npm"` or `"Savvy Web Registry"`. */
|
|
42
|
+
name: Schema.String,
|
|
43
|
+
/** The package's URL on that registry instance. */
|
|
44
|
+
url: Schema.String
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* One Open Graph image declared by the manifest.
|
|
48
|
+
*
|
|
49
|
+
* @remarks
|
|
50
|
+
* Exactly ONE of `path` (a bundle-relative asset the consuming platform
|
|
51
|
+
* publishes and resolves to a URL) or `url` (an absolute external URL used
|
|
52
|
+
* verbatim) must be present — the schema enforces the XOR. `type` is a MIME
|
|
53
|
+
* type, inferred from the file extension by the resolver when omitted; `alt`
|
|
54
|
+
* has a documented inference chain (tagline → description →
|
|
55
|
+
* `"<name> API documentation"`).
|
|
56
|
+
*
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
const OpenGraphImage = Schema.Struct({
|
|
60
|
+
/** Bundle-relative asset path. Mutually exclusive with `url`. */
|
|
61
|
+
path: Schema.optionalKey(Schema.String),
|
|
62
|
+
/** Absolute external URL, used verbatim. Mutually exclusive with `path`. */
|
|
63
|
+
url: Schema.optionalKey(Schema.String),
|
|
64
|
+
/** MIME type; inferred from the extension when omitted. */
|
|
65
|
+
type: Schema.optionalKey(Schema.String),
|
|
66
|
+
/** Pixel width; 1200×630 (1.91:1) is the cross-platform safe default. */
|
|
67
|
+
width: Schema.optionalKey(Schema.Int),
|
|
68
|
+
/** Pixel height. */
|
|
69
|
+
height: Schema.optionalKey(Schema.Int),
|
|
70
|
+
/** Alt text; inferred (tagline → description → fallback) when omitted. */
|
|
71
|
+
alt: Schema.optionalKey(Schema.String)
|
|
72
|
+
}).check(Schema.makeFilter((image) => image.path === void 0 !== (image.url === void 0) ? void 0 : "exactly one of \"path\" or \"url\" must be present", { title: "openGraph image source" }));
|
|
73
|
+
/**
|
|
74
|
+
* The manifest's Open Graph block: the asset-ish pieces only — most OG tags
|
|
75
|
+
* are page-level and derive at render time in the consuming platform.
|
|
76
|
+
*
|
|
77
|
+
* @remarks
|
|
78
|
+
* Multiple images follow OG array semantics: the first declared wins, extras
|
|
79
|
+
* are alternates (e.g. a portrait 1000×1500 variant).
|
|
80
|
+
*
|
|
81
|
+
* @public
|
|
82
|
+
*/
|
|
83
|
+
const OpenGraphConfig = Schema.Struct({
|
|
84
|
+
/** Declared images, first-wins per OG array semantics. */
|
|
85
|
+
images: Schema.optionalKey(Schema.Array(OpenGraphImage)),
|
|
86
|
+
/** Embed accent color (e.g. Discord), a CSS color string. */
|
|
87
|
+
themeColor: Schema.optionalKey(Schema.String)
|
|
88
|
+
});
|
|
89
|
+
/**
|
|
90
|
+
* A pointer to the bundle's SBOM, computed by the bundler at publish and
|
|
91
|
+
* served as a downloadable static asset.
|
|
92
|
+
*
|
|
93
|
+
* @public
|
|
94
|
+
*/
|
|
95
|
+
const SbomRef = Schema.Struct({
|
|
96
|
+
/** Bundle-relative path to the SBOM file. */
|
|
97
|
+
path: Schema.String,
|
|
98
|
+
/** SBOM format label, e.g. `"spdx-json"`. Unknown values are accepted. */
|
|
99
|
+
format: Schema.optionalKey(Schema.String)
|
|
100
|
+
});
|
|
101
|
+
/**
|
|
102
|
+
* The inherited project tier, flattened into the emitted manifest by the
|
|
103
|
+
* bundler (a fetched bundle has no parent directory to walk). Kept nested —
|
|
104
|
+
* structurally distinguishable from the leaf fields — because provenance is
|
|
105
|
+
* load-bearing for override detection.
|
|
106
|
+
*
|
|
107
|
+
* @public
|
|
108
|
+
*/
|
|
109
|
+
const ProjectIdentity = Schema.Struct({
|
|
110
|
+
/** The project display name, e.g. `"Effected"` over leaf `@effected/store`. */
|
|
111
|
+
name: Schema.optionalKey(Schema.String),
|
|
112
|
+
/** The project tagline. */
|
|
113
|
+
tagline: Schema.optionalKey(Schema.String)
|
|
114
|
+
});
|
|
115
|
+
/**
|
|
116
|
+
* The versioned `tsdoctor.json` sidecar manifest — bundle layer 3.
|
|
117
|
+
*
|
|
118
|
+
* @remarks
|
|
119
|
+
* `spec` is the only required field; every other field enriches. Unknown
|
|
120
|
+
* top-level fields are ignored on decode (additive fields are minor spec
|
|
121
|
+
* revisions) and unknown enum-ish values (registry `type`, sbom `format`)
|
|
122
|
+
* degrade gracefully instead of rejecting — an old reader must be able to
|
|
123
|
+
* consume a new bundle.
|
|
124
|
+
*
|
|
125
|
+
* @public
|
|
126
|
+
*/
|
|
127
|
+
const BundleManifest = Schema.Struct({
|
|
128
|
+
/** The integer spec version. This reader understands spec 1. */
|
|
129
|
+
spec: Schema.Literal(1),
|
|
130
|
+
/** Human display name (the npm name is dry; this one is SEO-friendly). */
|
|
131
|
+
name: Schema.optionalKey(Schema.String),
|
|
132
|
+
/** Short tagline. */
|
|
133
|
+
tagline: Schema.optionalKey(Schema.String),
|
|
134
|
+
/** Long description; overrides the package.json description when present. */
|
|
135
|
+
description: Schema.optionalKey(Schema.String),
|
|
136
|
+
/** The inherited project tier, flattened in at emit time. */
|
|
137
|
+
project: Schema.optionalKey(ProjectIdentity),
|
|
138
|
+
/** Open Graph assets. */
|
|
139
|
+
openGraph: Schema.optionalKey(OpenGraphConfig),
|
|
140
|
+
/** SBOM pointer. */
|
|
141
|
+
sbom: Schema.optionalKey(SbomRef),
|
|
142
|
+
/** Registries the package is published to. */
|
|
143
|
+
registries: Schema.optionalKey(Schema.Array(RegistryRef))
|
|
144
|
+
});
|
|
145
|
+
/**
|
|
146
|
+
* Raised when a present `tsdoctor.json` cannot be parsed or does not satisfy
|
|
147
|
+
* the {@link (BundleManifest:variable)} schema.
|
|
148
|
+
*
|
|
149
|
+
* @remarks
|
|
150
|
+
* Absence of the manifest is NEVER this error — layers enrich, never gate,
|
|
151
|
+
* so a missing sidecar is the normal case and reads as `Option.none()`.
|
|
152
|
+
*
|
|
153
|
+
* @public
|
|
154
|
+
*/
|
|
155
|
+
var BundleManifestError = class extends Schema.TaggedError()("BundleManifestError", {
|
|
156
|
+
/** The manifest file path, when the failure is tied to a file on disk. */
|
|
157
|
+
path: Schema.optionalKey(Schema.String),
|
|
158
|
+
/** The underlying failure (JSON syntax or schema decode), preserved structurally. */
|
|
159
|
+
cause: Schema.Defect()
|
|
160
|
+
}) {
|
|
161
|
+
get message() {
|
|
162
|
+
return `Invalid tsdoctor.json manifest${this.path !== void 0 ? ` at ${this.path}` : ""}`;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* Decode an unknown value into a {@link (BundleManifest:type)}.
|
|
167
|
+
*
|
|
168
|
+
* @remarks
|
|
169
|
+
* The typed boundary for manifest input that has already been parsed from
|
|
170
|
+
* JSON (plugin options, fetched payloads). File-based reading lives in
|
|
171
|
+
* `readBundle`, which routes through this after parsing.
|
|
172
|
+
*
|
|
173
|
+
* @public
|
|
174
|
+
*/
|
|
175
|
+
function decodeBundleManifest(input, path) {
|
|
176
|
+
return Schema.decodeUnknownEffect(BundleManifest)(input).pipe(Effect.mapError((cause) => new BundleManifestError({
|
|
177
|
+
...path !== void 0 ? { path } : {},
|
|
178
|
+
cause
|
|
179
|
+
})));
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* The manifest spec version this package reads and writes.
|
|
183
|
+
*
|
|
184
|
+
* @public
|
|
185
|
+
*/
|
|
186
|
+
const MANIFEST_SPEC = 1;
|
|
187
|
+
/**
|
|
188
|
+
* The sidecar manifest's file name inside a bundle folder.
|
|
189
|
+
*
|
|
190
|
+
* @public
|
|
191
|
+
*/
|
|
192
|
+
const TSDOCTOR_MANIFEST_FILENAME = "tsdoctor.json";
|
|
193
|
+
/**
|
|
194
|
+
* Encode a {@link (BundleManifest:type)} into the JSON-ready value a writer
|
|
195
|
+
* serializes as `tsdoctor.json`.
|
|
196
|
+
*
|
|
197
|
+
* @remarks
|
|
198
|
+
* The writer's boundary. Going through the schema rather than
|
|
199
|
+
* `JSON.stringify` means an emitted file is by construction what
|
|
200
|
+
* {@link decodeBundleManifest} accepts.
|
|
201
|
+
*
|
|
202
|
+
* @public
|
|
203
|
+
*/
|
|
204
|
+
function encodeBundleManifest(manifest) {
|
|
205
|
+
return Schema.encodeEffect(BundleManifest)(manifest).pipe(Effect.mapError((cause) => new BundleManifestError({ cause })));
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
//#endregion
|
|
209
|
+
export { BundleManifest, BundleManifestError, KNOWN_REGISTRY_TYPES, MANIFEST_SPEC, OpenGraphConfig, OpenGraphImage, ProjectIdentity, RegistryRef, SbomRef, TSDOCTOR_MANIFEST_FILENAME, decodeBundleManifest, encodeBundleManifest, isKnownRegistryType };
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 C. Spencer Beggs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { BundleManifest, BundleManifestError } from "./BundleManifest.js";
|
|
2
|
+
import { Effect, Schema } from "effect";
|
|
3
|
+
|
|
4
|
+
//#region src/ManifestSource.ts
|
|
5
|
+
/**
|
|
6
|
+
* The shape an author checks in as a `tsdoctor.json` SOURCE file, at a
|
|
7
|
+
* package root (the leaf tier) or a workspace root (the project tier).
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* `BundleManifest` minus `spec` and `project`: a source file never declares
|
|
11
|
+
* its own spec version, and it never declares its inherited tier — the
|
|
12
|
+
* bundler supplies both when it flattens the hierarchy at emit time. Decoded
|
|
13
|
+
* only by writers; readers never see this shape.
|
|
14
|
+
*
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
const ManifestSource = Schema.Struct({
|
|
18
|
+
name: BundleManifest.fields.name,
|
|
19
|
+
tagline: BundleManifest.fields.tagline,
|
|
20
|
+
description: BundleManifest.fields.description,
|
|
21
|
+
openGraph: BundleManifest.fields.openGraph,
|
|
22
|
+
sbom: BundleManifest.fields.sbom,
|
|
23
|
+
registries: BundleManifest.fields.registries
|
|
24
|
+
});
|
|
25
|
+
/**
|
|
26
|
+
* Decode an unknown value into a {@link (ManifestSource:type)}.
|
|
27
|
+
*
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
function decodeManifestSource(input, path) {
|
|
31
|
+
return Schema.decodeUnknownEffect(ManifestSource)(input).pipe(Effect.mapError((cause) => new BundleManifestError({
|
|
32
|
+
...path !== void 0 ? { path } : {},
|
|
33
|
+
cause
|
|
34
|
+
})));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
//#endregion
|
|
38
|
+
export { ManifestSource, decodeManifestSource };
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
//#region src/BundleManifest.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* The registry protocol families this reader knows how to do more than link
|
|
5
|
+
* to. `"npm"` means an npm-compatible registry — install commands and tarball
|
|
6
|
+
* fetching work against any instance of it — and `"jsr"` the jsr protocol.
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* The manifest's `type` field is deliberately NOT constrained to these
|
|
10
|
+
* values: unknown future types must degrade to link-only rendering, not
|
|
11
|
+
* reject the manifest. Use {@link isKnownRegistryType} to branch.
|
|
12
|
+
*
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
declare const KNOWN_REGISTRY_TYPES: readonly ["npm", "jsr"];
|
|
16
|
+
/**
|
|
17
|
+
* A registry protocol family this reader recognizes.
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
type KnownRegistryType = (typeof KNOWN_REGISTRY_TYPES)[number];
|
|
22
|
+
/**
|
|
23
|
+
* Whether a registry `type` value is a protocol family this reader
|
|
24
|
+
* recognizes. `false` means the registry entry should degrade to link-only
|
|
25
|
+
* rendering — it is never a validation failure.
|
|
26
|
+
*
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
declare function isKnownRegistryType(type: string): type is KnownRegistryType;
|
|
30
|
+
/**
|
|
31
|
+
* One registry the documented package is published to.
|
|
32
|
+
*
|
|
33
|
+
* @remarks
|
|
34
|
+
* `type` is the PROTOCOL FAMILY (`"npm"` covers every npm-compatible
|
|
35
|
+
* registry), `name` the human instance label, `url` the package's page on
|
|
36
|
+
* that instance. Unknown `type` values decode successfully and degrade to
|
|
37
|
+
* link-only rendering (see {@link isKnownRegistryType}).
|
|
38
|
+
*
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
declare const RegistryRef: Schema.Struct<{
|
|
42
|
+
/** The protocol family, e.g. `"npm"` or `"jsr"`. Unknown values are accepted. */
|
|
43
|
+
readonly type: Schema.String;
|
|
44
|
+
/** The human instance label, e.g. `"npm"` or `"Savvy Web Registry"`. */
|
|
45
|
+
readonly name: Schema.String;
|
|
46
|
+
/** The package's URL on that registry instance. */
|
|
47
|
+
readonly url: Schema.String;
|
|
48
|
+
}>;
|
|
49
|
+
/**
|
|
50
|
+
* The decoded type of {@link (RegistryRef:variable)}.
|
|
51
|
+
*
|
|
52
|
+
* @public
|
|
53
|
+
*/
|
|
54
|
+
type RegistryRef = typeof RegistryRef.Type;
|
|
55
|
+
/**
|
|
56
|
+
* One Open Graph image declared by the manifest.
|
|
57
|
+
*
|
|
58
|
+
* @remarks
|
|
59
|
+
* Exactly ONE of `path` (a bundle-relative asset the consuming platform
|
|
60
|
+
* publishes and resolves to a URL) or `url` (an absolute external URL used
|
|
61
|
+
* verbatim) must be present — the schema enforces the XOR. `type` is a MIME
|
|
62
|
+
* type, inferred from the file extension by the resolver when omitted; `alt`
|
|
63
|
+
* has a documented inference chain (tagline → description →
|
|
64
|
+
* `"<name> API documentation"`).
|
|
65
|
+
*
|
|
66
|
+
* @public
|
|
67
|
+
*/
|
|
68
|
+
declare const OpenGraphImage: Schema.Struct<{
|
|
69
|
+
/** Bundle-relative asset path. Mutually exclusive with `url`. */
|
|
70
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
71
|
+
/** Absolute external URL, used verbatim. Mutually exclusive with `path`. */
|
|
72
|
+
readonly url: Schema.optionalKey<Schema.String>;
|
|
73
|
+
/** MIME type; inferred from the extension when omitted. */
|
|
74
|
+
readonly type: Schema.optionalKey<Schema.String>;
|
|
75
|
+
/** Pixel width; 1200×630 (1.91:1) is the cross-platform safe default. */
|
|
76
|
+
readonly width: Schema.optionalKey<Schema.Int>;
|
|
77
|
+
/** Pixel height. */
|
|
78
|
+
readonly height: Schema.optionalKey<Schema.Int>;
|
|
79
|
+
/** Alt text; inferred (tagline → description → fallback) when omitted. */
|
|
80
|
+
readonly alt: Schema.optionalKey<Schema.String>;
|
|
81
|
+
}>;
|
|
82
|
+
/**
|
|
83
|
+
* The decoded type of {@link (OpenGraphImage:variable)}.
|
|
84
|
+
*
|
|
85
|
+
* @public
|
|
86
|
+
*/
|
|
87
|
+
type OpenGraphImage = typeof OpenGraphImage.Type;
|
|
88
|
+
/**
|
|
89
|
+
* The manifest's Open Graph block: the asset-ish pieces only — most OG tags
|
|
90
|
+
* are page-level and derive at render time in the consuming platform.
|
|
91
|
+
*
|
|
92
|
+
* @remarks
|
|
93
|
+
* Multiple images follow OG array semantics: the first declared wins, extras
|
|
94
|
+
* are alternates (e.g. a portrait 1000×1500 variant).
|
|
95
|
+
*
|
|
96
|
+
* @public
|
|
97
|
+
*/
|
|
98
|
+
declare const OpenGraphConfig: Schema.Struct<{
|
|
99
|
+
/** Declared images, first-wins per OG array semantics. */
|
|
100
|
+
readonly images: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
101
|
+
/** Bundle-relative asset path. Mutually exclusive with `url`. */
|
|
102
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
103
|
+
/** Absolute external URL, used verbatim. Mutually exclusive with `path`. */
|
|
104
|
+
readonly url: Schema.optionalKey<Schema.String>;
|
|
105
|
+
/** MIME type; inferred from the extension when omitted. */
|
|
106
|
+
readonly type: Schema.optionalKey<Schema.String>;
|
|
107
|
+
/** Pixel width; 1200×630 (1.91:1) is the cross-platform safe default. */
|
|
108
|
+
readonly width: Schema.optionalKey<Schema.Int>;
|
|
109
|
+
/** Pixel height. */
|
|
110
|
+
readonly height: Schema.optionalKey<Schema.Int>;
|
|
111
|
+
/** Alt text; inferred (tagline → description → fallback) when omitted. */
|
|
112
|
+
readonly alt: Schema.optionalKey<Schema.String>;
|
|
113
|
+
}>>>;
|
|
114
|
+
/** Embed accent color (e.g. Discord), a CSS color string. */
|
|
115
|
+
readonly themeColor: Schema.optionalKey<Schema.String>;
|
|
116
|
+
}>;
|
|
117
|
+
/**
|
|
118
|
+
* The decoded type of {@link (OpenGraphConfig:variable)}.
|
|
119
|
+
*
|
|
120
|
+
* @public
|
|
121
|
+
*/
|
|
122
|
+
type OpenGraphConfig = typeof OpenGraphConfig.Type;
|
|
123
|
+
/**
|
|
124
|
+
* A pointer to the bundle's SBOM, computed by the bundler at publish and
|
|
125
|
+
* served as a downloadable static asset.
|
|
126
|
+
*
|
|
127
|
+
* @public
|
|
128
|
+
*/
|
|
129
|
+
declare const SbomRef: Schema.Struct<{
|
|
130
|
+
/** Bundle-relative path to the SBOM file. */
|
|
131
|
+
readonly path: Schema.String;
|
|
132
|
+
/** SBOM format label, e.g. `"spdx-json"`. Unknown values are accepted. */
|
|
133
|
+
readonly format: Schema.optionalKey<Schema.String>;
|
|
134
|
+
}>;
|
|
135
|
+
/**
|
|
136
|
+
* The decoded type of {@link (SbomRef:variable)}.
|
|
137
|
+
*
|
|
138
|
+
* @public
|
|
139
|
+
*/
|
|
140
|
+
type SbomRef = typeof SbomRef.Type;
|
|
141
|
+
/**
|
|
142
|
+
* The inherited project tier, flattened into the emitted manifest by the
|
|
143
|
+
* bundler (a fetched bundle has no parent directory to walk). Kept nested —
|
|
144
|
+
* structurally distinguishable from the leaf fields — because provenance is
|
|
145
|
+
* load-bearing for override detection.
|
|
146
|
+
*
|
|
147
|
+
* @public
|
|
148
|
+
*/
|
|
149
|
+
declare const ProjectIdentity: Schema.Struct<{
|
|
150
|
+
/** The project display name, e.g. `"Effected"` over leaf `@effected/store`. */
|
|
151
|
+
readonly name: Schema.optionalKey<Schema.String>;
|
|
152
|
+
/** The project tagline. */
|
|
153
|
+
readonly tagline: Schema.optionalKey<Schema.String>;
|
|
154
|
+
}>;
|
|
155
|
+
/**
|
|
156
|
+
* The decoded type of {@link (ProjectIdentity:variable)}.
|
|
157
|
+
*
|
|
158
|
+
* @public
|
|
159
|
+
*/
|
|
160
|
+
type ProjectIdentity = typeof ProjectIdentity.Type;
|
|
161
|
+
/**
|
|
162
|
+
* The versioned `tsdoctor.json` sidecar manifest — bundle layer 3.
|
|
163
|
+
*
|
|
164
|
+
* @remarks
|
|
165
|
+
* `spec` is the only required field; every other field enriches. Unknown
|
|
166
|
+
* top-level fields are ignored on decode (additive fields are minor spec
|
|
167
|
+
* revisions) and unknown enum-ish values (registry `type`, sbom `format`)
|
|
168
|
+
* degrade gracefully instead of rejecting — an old reader must be able to
|
|
169
|
+
* consume a new bundle.
|
|
170
|
+
*
|
|
171
|
+
* @public
|
|
172
|
+
*/
|
|
173
|
+
declare const BundleManifest: Schema.Struct<{
|
|
174
|
+
/** The integer spec version. This reader understands spec 1. */
|
|
175
|
+
readonly spec: Schema.Literal<1>;
|
|
176
|
+
/** Human display name (the npm name is dry; this one is SEO-friendly). */
|
|
177
|
+
readonly name: Schema.optionalKey<Schema.String>;
|
|
178
|
+
/** Short tagline. */
|
|
179
|
+
readonly tagline: Schema.optionalKey<Schema.String>;
|
|
180
|
+
/** Long description; overrides the package.json description when present. */
|
|
181
|
+
readonly description: Schema.optionalKey<Schema.String>;
|
|
182
|
+
/** The inherited project tier, flattened in at emit time. */
|
|
183
|
+
readonly project: Schema.optionalKey<Schema.Struct<{
|
|
184
|
+
/** The project display name, e.g. `"Effected"` over leaf `@effected/store`. */
|
|
185
|
+
readonly name: Schema.optionalKey<Schema.String>;
|
|
186
|
+
/** The project tagline. */
|
|
187
|
+
readonly tagline: Schema.optionalKey<Schema.String>;
|
|
188
|
+
}>>;
|
|
189
|
+
/** Open Graph assets. */
|
|
190
|
+
readonly openGraph: Schema.optionalKey<Schema.Struct<{
|
|
191
|
+
/** Declared images, first-wins per OG array semantics. */
|
|
192
|
+
readonly images: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
193
|
+
/** Bundle-relative asset path. Mutually exclusive with `url`. */
|
|
194
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
195
|
+
/** Absolute external URL, used verbatim. Mutually exclusive with `path`. */
|
|
196
|
+
readonly url: Schema.optionalKey<Schema.String>;
|
|
197
|
+
/** MIME type; inferred from the extension when omitted. */
|
|
198
|
+
readonly type: Schema.optionalKey<Schema.String>;
|
|
199
|
+
/** Pixel width; 1200×630 (1.91:1) is the cross-platform safe default. */
|
|
200
|
+
readonly width: Schema.optionalKey<Schema.Int>;
|
|
201
|
+
/** Pixel height. */
|
|
202
|
+
readonly height: Schema.optionalKey<Schema.Int>;
|
|
203
|
+
/** Alt text; inferred (tagline → description → fallback) when omitted. */
|
|
204
|
+
readonly alt: Schema.optionalKey<Schema.String>;
|
|
205
|
+
}>>>;
|
|
206
|
+
/** Embed accent color (e.g. Discord), a CSS color string. */
|
|
207
|
+
readonly themeColor: Schema.optionalKey<Schema.String>;
|
|
208
|
+
}>>;
|
|
209
|
+
/** SBOM pointer. */
|
|
210
|
+
readonly sbom: Schema.optionalKey<Schema.Struct<{
|
|
211
|
+
/** Bundle-relative path to the SBOM file. */
|
|
212
|
+
readonly path: Schema.String;
|
|
213
|
+
/** SBOM format label, e.g. `"spdx-json"`. Unknown values are accepted. */
|
|
214
|
+
readonly format: Schema.optionalKey<Schema.String>;
|
|
215
|
+
}>>;
|
|
216
|
+
/** Registries the package is published to. */
|
|
217
|
+
readonly registries: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
218
|
+
/** The protocol family, e.g. `"npm"` or `"jsr"`. Unknown values are accepted. */
|
|
219
|
+
readonly type: Schema.String;
|
|
220
|
+
/** The human instance label, e.g. `"npm"` or `"Savvy Web Registry"`. */
|
|
221
|
+
readonly name: Schema.String;
|
|
222
|
+
/** The package's URL on that registry instance. */
|
|
223
|
+
readonly url: Schema.String;
|
|
224
|
+
}>>>;
|
|
225
|
+
}>;
|
|
226
|
+
/**
|
|
227
|
+
* The decoded type of {@link (BundleManifest:variable)}.
|
|
228
|
+
*
|
|
229
|
+
* @public
|
|
230
|
+
*/
|
|
231
|
+
type BundleManifest = typeof BundleManifest.Type;
|
|
232
|
+
declare const BundleManifestError_base: Schema.Class<BundleManifestError, Schema.TaggedStruct<"BundleManifestError", {
|
|
233
|
+
/** The manifest file path, when the failure is tied to a file on disk. */
|
|
234
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
235
|
+
/** The underlying failure (JSON syntax or schema decode), preserved structurally. */
|
|
236
|
+
readonly cause: Schema.Defect;
|
|
237
|
+
}>, import("effect/Cause").YieldableError>;
|
|
238
|
+
/**
|
|
239
|
+
* Raised when a present `tsdoctor.json` cannot be parsed or does not satisfy
|
|
240
|
+
* the {@link (BundleManifest:variable)} schema.
|
|
241
|
+
*
|
|
242
|
+
* @remarks
|
|
243
|
+
* Absence of the manifest is NEVER this error — layers enrich, never gate,
|
|
244
|
+
* so a missing sidecar is the normal case and reads as `Option.none()`.
|
|
245
|
+
*
|
|
246
|
+
* @public
|
|
247
|
+
*/
|
|
248
|
+
declare class BundleManifestError extends BundleManifestError_base {
|
|
249
|
+
get message(): string;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Decode an unknown value into a {@link (BundleManifest:type)}.
|
|
253
|
+
*
|
|
254
|
+
* @remarks
|
|
255
|
+
* The typed boundary for manifest input that has already been parsed from
|
|
256
|
+
* JSON (plugin options, fetched payloads). File-based reading lives in
|
|
257
|
+
* `readBundle`, which routes through this after parsing.
|
|
258
|
+
*
|
|
259
|
+
* @public
|
|
260
|
+
*/
|
|
261
|
+
declare function decodeBundleManifest(input: unknown, path?: string): Effect.Effect<BundleManifest, BundleManifestError>;
|
|
262
|
+
/**
|
|
263
|
+
* The manifest spec version this package reads and writes.
|
|
264
|
+
*
|
|
265
|
+
* @public
|
|
266
|
+
*/
|
|
267
|
+
declare const MANIFEST_SPEC: 1;
|
|
268
|
+
/**
|
|
269
|
+
* The sidecar manifest's file name inside a bundle folder.
|
|
270
|
+
*
|
|
271
|
+
* @public
|
|
272
|
+
*/
|
|
273
|
+
declare const TSDOCTOR_MANIFEST_FILENAME = "tsdoctor.json";
|
|
274
|
+
/**
|
|
275
|
+
* Encode a {@link (BundleManifest:type)} into the JSON-ready value a writer
|
|
276
|
+
* serializes as `tsdoctor.json`.
|
|
277
|
+
*
|
|
278
|
+
* @remarks
|
|
279
|
+
* The writer's boundary. Going through the schema rather than
|
|
280
|
+
* `JSON.stringify` means an emitted file is by construction what
|
|
281
|
+
* {@link decodeBundleManifest} accepts.
|
|
282
|
+
*
|
|
283
|
+
* @public
|
|
284
|
+
*/
|
|
285
|
+
declare function encodeBundleManifest(manifest: BundleManifest): Effect.Effect<unknown, BundleManifestError>;
|
|
286
|
+
//#endregion
|
|
287
|
+
//#region src/ManifestSource.d.ts
|
|
288
|
+
/**
|
|
289
|
+
* The shape an author checks in as a `tsdoctor.json` SOURCE file, at a
|
|
290
|
+
* package root (the leaf tier) or a workspace root (the project tier).
|
|
291
|
+
*
|
|
292
|
+
* @remarks
|
|
293
|
+
* `BundleManifest` minus `spec` and `project`: a source file never declares
|
|
294
|
+
* its own spec version, and it never declares its inherited tier — the
|
|
295
|
+
* bundler supplies both when it flattens the hierarchy at emit time. Decoded
|
|
296
|
+
* only by writers; readers never see this shape.
|
|
297
|
+
*
|
|
298
|
+
* @public
|
|
299
|
+
*/
|
|
300
|
+
declare const ManifestSource: Schema.Struct<{
|
|
301
|
+
readonly name: Schema.optionalKey<Schema.String>;
|
|
302
|
+
readonly tagline: Schema.optionalKey<Schema.String>;
|
|
303
|
+
readonly description: Schema.optionalKey<Schema.String>;
|
|
304
|
+
readonly openGraph: Schema.optionalKey<Schema.Struct<{
|
|
305
|
+
readonly images: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
306
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
307
|
+
readonly url: Schema.optionalKey<Schema.String>;
|
|
308
|
+
readonly type: Schema.optionalKey<Schema.String>;
|
|
309
|
+
readonly width: Schema.optionalKey<Schema.Int>;
|
|
310
|
+
readonly height: Schema.optionalKey<Schema.Int>;
|
|
311
|
+
readonly alt: Schema.optionalKey<Schema.String>;
|
|
312
|
+
}>>>;
|
|
313
|
+
readonly themeColor: Schema.optionalKey<Schema.String>;
|
|
314
|
+
}>>;
|
|
315
|
+
readonly sbom: Schema.optionalKey<Schema.Struct<{
|
|
316
|
+
readonly path: Schema.String;
|
|
317
|
+
readonly format: Schema.optionalKey<Schema.String>;
|
|
318
|
+
}>>;
|
|
319
|
+
readonly registries: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
320
|
+
readonly type: Schema.String;
|
|
321
|
+
readonly name: Schema.String;
|
|
322
|
+
readonly url: Schema.String;
|
|
323
|
+
}>>>;
|
|
324
|
+
}>;
|
|
325
|
+
/**
|
|
326
|
+
* The decoded type of {@link (ManifestSource:variable)}.
|
|
327
|
+
*
|
|
328
|
+
* @public
|
|
329
|
+
*/
|
|
330
|
+
type ManifestSource = typeof ManifestSource.Type;
|
|
331
|
+
/**
|
|
332
|
+
* Decode an unknown value into a {@link (ManifestSource:type)}.
|
|
333
|
+
*
|
|
334
|
+
* @public
|
|
335
|
+
*/
|
|
336
|
+
declare function decodeManifestSource(input: unknown, path?: string): Effect.Effect<ManifestSource, BundleManifestError>;
|
|
337
|
+
//#endregion
|
|
338
|
+
export { BundleManifest, BundleManifestError, KNOWN_REGISTRY_TYPES, type KnownRegistryType, MANIFEST_SPEC, ManifestSource, OpenGraphConfig, OpenGraphImage, ProjectIdentity, RegistryRef, SbomRef, TSDOCTOR_MANIFEST_FILENAME, decodeBundleManifest, decodeManifestSource, encodeBundleManifest, isKnownRegistryType };
|
|
339
|
+
//# sourceMappingURL=index.d.ts.map
|
package/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { BundleManifest, BundleManifestError, KNOWN_REGISTRY_TYPES, MANIFEST_SPEC, OpenGraphConfig, OpenGraphImage, ProjectIdentity, RegistryRef, SbomRef, TSDOCTOR_MANIFEST_FILENAME, decodeBundleManifest, encodeBundleManifest, isKnownRegistryType } from "./BundleManifest.js";
|
|
2
|
+
import { ManifestSource, decodeManifestSource } from "./ManifestSource.js";
|
|
3
|
+
|
|
4
|
+
export { BundleManifest, BundleManifestError, KNOWN_REGISTRY_TYPES, MANIFEST_SPEC, ManifestSource, OpenGraphConfig, OpenGraphImage, ProjectIdentity, RegistryRef, SbomRef, TSDOCTOR_MANIFEST_FILENAME, decodeBundleManifest, decodeManifestSource, encodeBundleManifest, isKnownRegistryType };
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tsdoctor/manifest",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "The tsdoctor.json bundle manifest: the spec-1 schema, encode/decode boundaries and the authoring-file shape shared by bundlers that write it and readers that consume it.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"tsdoctor",
|
|
8
|
+
"manifest",
|
|
9
|
+
"api-extractor",
|
|
10
|
+
"effect"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/spencerbeggs/tsdoctor#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/spencerbeggs/tsdoctor/issues"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/spencerbeggs/tsdoctor.git",
|
|
19
|
+
"directory": "packages/manifest"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"author": {
|
|
23
|
+
"name": "C. Spencer Beggs",
|
|
24
|
+
"email": "spencer@beggs.codes",
|
|
25
|
+
"url": "https://spencerbeg.gs"
|
|
26
|
+
},
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"type": "module",
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./index.d.ts",
|
|
32
|
+
"import": "./index.js",
|
|
33
|
+
"default": "./index.js"
|
|
34
|
+
},
|
|
35
|
+
"./package.json": "./package.json"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"effect": "4.0.0-rc.109"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=24.11.0"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// This file is read by tools that parse documentation comments conforming to the TSDoc standard.
|
|
2
|
+
// It should be published with your NPM package. It should not be tracked by Git.
|
|
3
|
+
{
|
|
4
|
+
"tsdocVersion": "0.12",
|
|
5
|
+
"toolPackages": [
|
|
6
|
+
{
|
|
7
|
+
"packageName": "@microsoft/api-extractor",
|
|
8
|
+
"packageVersion": "7.59.0"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|