@kirchdev/duxt 0.2.0 → 0.2.1-dev-main.32-677294a

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.
@@ -143,6 +143,16 @@ declare global {
143
143
  | 'deprecated'
144
144
  | 'eol';
145
145
 
146
+ /** Lifecycle defaults a source may opt into for its different ref kinds. */
147
+ type DuxtSourceStatusDefaultsInput = {
148
+ /** The moving `latest` shorthand. */
149
+ latest?: DuxtSourceStatusInput;
150
+ /** An explicitly listed tag. */
151
+ tag?: DuxtSourceStatusInput;
152
+ /** A named branch, such as `main`. */
153
+ branch?: DuxtSourceStatusInput;
154
+ };
155
+
146
156
  /**
147
157
  * A branch by name, or a tag stated as one.
148
158
  *
@@ -154,12 +164,16 @@ declare global {
154
164
  | {
155
165
  branch: string;
156
166
  label?: string;
167
+ /** Serve this ref without a version prefix. */
168
+ default?: boolean;
157
169
  status?: DuxtSourceStatusInput;
158
170
  locales?: DuxtSourceLocaleInput[];
159
171
  }
160
172
  | {
161
173
  tag: string;
162
174
  label?: string;
175
+ /** Serve this ref without a version prefix. */
176
+ default?: boolean;
163
177
  status?: DuxtSourceStatusInput;
164
178
  locales?: DuxtSourceLocaleInput[];
165
179
  };
@@ -215,8 +229,8 @@ declare global {
215
229
  *
216
230
  * Named here, everything else follows the ref path exactly: the URL segment,
217
231
  * the switcher entry (scoped to the same artefact), the banner and the
218
- * canonical. `sourceOptions.defaultRef` names which of them is served without
219
- * a prefix, whether it is a ref or one of these.
232
+ * canonical. A ref may name itself as the default; otherwise
233
+ * `sourceOptions.defaultRef` names which is served without a prefix.
220
234
  *
221
235
  * Never beside `refs` — a source with both would have to be served at two
222
236
  * prefixes at once, and the resolver says so rather than picking one.
@@ -234,6 +248,8 @@ declare global {
234
248
  slug?: string;
235
249
  /** Lifecycle of every version this entry publishes, unless a ref says otherwise. */
236
250
  status?: DuxtSourceStatusInput;
251
+ /** Lifecycle defaults by ref kind; an explicit ref status wins. */
252
+ statusDefaults?: DuxtSourceStatusDefaultsInput;
237
253
  /**
238
254
  * The repository a source read off disk lives in, for links back to it.
239
255
  * Not `repo`, which is what makes Content download a source.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://www.schemastore.org/package.json",
3
3
  "name": "@kirchdev/duxt",
4
- "version": "0.2.0",
4
+ "version": "0.2.1-dev-main.32-677294a",
5
5
  "description": "Nuxt documentation layer on Content v3 — multi-repo, versioned docs from one compact source list.",
6
6
  "keywords": [
7
7
  "content-v3",
package/sources-git.ts CHANGED
@@ -4,6 +4,8 @@ import {
4
4
  expandSources,
5
5
  isLatestRef,
6
6
  newestTag,
7
+ refIsTag,
8
+ refName,
7
9
  repoUrl
8
10
  } from './sources-resolve';
9
11
 
@@ -102,19 +104,33 @@ export function resolveLatestRefs(sources: DuxtSource[]): DuxtSource[] {
102
104
 
103
105
  return {
104
106
  ...source,
105
- refs: source.refs.map((ref) =>
106
- isLatestRef(ref)
107
- ? {
108
- tag: newest,
109
- // The URL keeps saying `latest`, so a bookmark survives the next
110
- // release; only the ref underneath moves. `label` is what the
111
- // switcher and the prefix are built from.
112
- label:
113
- typeof ref === 'object' ? (ref.label ?? 'latest') : 'latest',
114
- status: typeof ref === 'object' ? ref.status : undefined
115
- }
116
- : ref
117
- )
107
+ refs: source.refs.flatMap((ref) => {
108
+ if (isLatestRef(ref)) {
109
+ return {
110
+ tag: newest,
111
+ // The URL keeps saying `latest`, so a bookmark survives the next
112
+ // release; only the ref underneath moves. `label` is what the
113
+ // switcher and the prefix are built from.
114
+ label: typeof ref === 'object' ? (ref.label ?? 'latest') : 'latest',
115
+ // `latest` stops being distinguishable from an ordinary tag after
116
+ // resolution, so settle its source-level default while that fact
117
+ // still exists. An explicit ref or all-refs source status wins.
118
+ status:
119
+ (typeof ref === 'object' ? ref.status : undefined) ??
120
+ source.status ??
121
+ source.statusDefaults?.latest,
122
+ locales: typeof ref === 'object' ? ref.locales : undefined,
123
+ default: typeof ref === 'object' ? ref.default : undefined
124
+ };
125
+ }
126
+
127
+ // Keep an older release ready in the declaration, without serving the
128
+ // current release twice. Once a newer tag exists this condition stops
129
+ // matching and the retained release becomes its own edition.
130
+ if (refIsTag(ref) && refName(ref) === newest) return [];
131
+
132
+ return ref;
133
+ })
118
134
  };
119
135
  });
120
136
  }
@@ -55,8 +55,8 @@ export interface DuxtSource {
55
55
  *
56
56
  * Named here, everything else follows the ref path exactly: the URL segment,
57
57
  * the switcher entry (scoped to the same artefact), the banner and the
58
- * canonical. `sourceOptions.defaultRef` names which of them is served without
59
- * a prefix, whether it is a ref or one of these.
58
+ * canonical. A ref may name itself as the default; otherwise
59
+ * `sourceOptions.defaultRef` names which is served without a prefix.
60
60
  *
61
61
  * Never beside `refs` — a source with both would have to be served at two
62
62
  * prefixes at once, and the resolver says so rather than picking one.
@@ -80,6 +80,12 @@ export interface DuxtSource {
80
80
  * otherwise. See `DuxtSourceStatus`.
81
81
  */
82
82
  status?: DuxtSourceStatus;
83
+ /**
84
+ * Lifecycle defaults by ref kind. An explicit ref `status` wins; `status`
85
+ * above remains the legacy all-refs fallback. A source opts in because only
86
+ * its maintainer knows whether an older release is really deprecated.
87
+ */
88
+ statusDefaults?: DuxtSourceStatusDefaults;
83
89
  /**
84
90
  * The repository these pages live in, for a source read off disk.
85
91
  *
@@ -134,6 +140,16 @@ export type DuxtSourceStatus =
134
140
  | 'deprecated'
135
141
  | 'eol';
136
142
 
143
+ /** Lifecycle defaults a source may opt into for its different ref kinds. */
144
+ export interface DuxtSourceStatusDefaults {
145
+ /** The moving `latest` shorthand, before it becomes a concrete tag. */
146
+ latest?: DuxtSourceStatus;
147
+ /** A tag explicitly listed beside `latest`. */
148
+ tag?: DuxtSourceStatus;
149
+ /** A named branch, such as `main` or a preview branch. */
150
+ branch?: DuxtSourceStatus;
151
+ }
152
+
137
153
  /** A branch by name, or a tag stated as one. */
138
154
  export type DuxtRef =
139
155
  | string
@@ -143,6 +159,13 @@ export type DuxtRef =
143
159
  interface DuxtRefOptions {
144
160
  /** Shown in the switcher and used in the URL; defaults to the ref name. */
145
161
  label?: string;
162
+ /**
163
+ * Serve this ref without a version prefix, even when another source has its
164
+ * own default. A site with several independently versioned trees needs this:
165
+ * its docs can serve the newest release at `/` while an API stays at its own
166
+ * current edition.
167
+ */
168
+ default?: boolean;
146
169
  /** This one version's lifecycle, overriding the source's. */
147
170
  status?: DuxtSourceStatus;
148
171
  /**
@@ -577,7 +600,10 @@ export function resolveSources(
577
600
  const code = locale ? localeCode(locale) : defaultLocale;
578
601
  const isDefaultLocale = !code || code === defaultLocale;
579
602
  const version = name ? slugify(label ?? name) : undefined;
580
- const isDefault = !name || name === defaultRef;
603
+ const isDefault =
604
+ !name ||
605
+ (ref && typeof ref === 'object' && Boolean(ref.default)) ||
606
+ name === defaultRef;
581
607
 
582
608
  const segments: string[] = [];
583
609
  if (segmented(source)) segments.push(repoSlug(source));
@@ -639,6 +665,11 @@ export function resolveSources(
639
665
  status:
640
666
  (ref && typeof ref === 'object' ? ref.status : undefined) ??
641
667
  source.status ??
668
+ (effectiveRef
669
+ ? refIsTag(effectiveRef)
670
+ ? source.statusDefaults?.tag
671
+ : source.statusDefaults?.branch
672
+ : undefined) ??
642
673
  'current',
643
674
  // A local source is a full checkout already; a remote one has to be
644
675
  // unshallowed, which is why it has to be asked for.