@adonisjs/content 1.2.0 → 1.4.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/README.md +48 -1
- package/build/{chunk-2C5XZ5YD.js → chunk-Q6QIMTOW.js} +11 -1
- package/build/chunk-WO5VTK7D.js +331 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +6 -2
- package/build/providers/content_provider.d.ts +1 -0
- package/build/providers/content_provider.js +22 -2
- package/build/src/collection.d.ts +10 -3
- package/build/src/debug.d.ts +1 -1
- package/build/src/loaders/main.d.ts +30 -2
- package/build/src/loaders/main.js +202 -421
- package/build/src/loaders/oss_stats.d.ts +66 -0
- package/build/src/types.d.ts +58 -0
- package/build/src/utils.d.ts +98 -0
- package/package.json +16 -16
package/README.md
CHANGED
|
@@ -15,7 +15,8 @@ We use this package for all official AdonisJS websites to manage docs, blog post
|
|
|
15
15
|
**Key Features:**
|
|
16
16
|
|
|
17
17
|
- **Type-safe collections** with VineJS schema validation
|
|
18
|
-
- **GitHub loaders** for sponsors, releases, and
|
|
18
|
+
- **GitHub loaders** for sponsors, releases, contributors, and aggregated OSS statistics
|
|
19
|
+
- **npm package statistics** aggregation with download counts
|
|
19
20
|
- **Custom query methods** for filtering and transforming data
|
|
20
21
|
- **JSON file loading** with validation
|
|
21
22
|
- **Vite integration** for asset path resolution
|
|
@@ -178,6 +179,52 @@ const contributors = new Collection({
|
|
|
178
179
|
})
|
|
179
180
|
```
|
|
180
181
|
|
|
182
|
+
### OSS Stats Loader
|
|
183
|
+
|
|
184
|
+
Aggregate open source statistics from multiple sources including GitHub stars and npm package downloads:
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
import vine from '@vinejs/vine'
|
|
188
|
+
import app from '@adonisjs/core/services/app'
|
|
189
|
+
import { Collection } from '@adonisjs/content'
|
|
190
|
+
import { loaders } from '@adonisjs/content/loaders'
|
|
191
|
+
|
|
192
|
+
const statsSchema = vine.object({
|
|
193
|
+
stars: vine.number(),
|
|
194
|
+
installs: vine.number(),
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
const ossStatsLoader = loaders.ossStats({
|
|
198
|
+
outputPath: app.makePath('cache/oss-stats.json'),
|
|
199
|
+
refresh: 'daily',
|
|
200
|
+
sources: [
|
|
201
|
+
{
|
|
202
|
+
type: 'github',
|
|
203
|
+
org: 'adonisjs',
|
|
204
|
+
ghToken: process.env.GITHUB_TOKEN!,
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
type: 'npm',
|
|
208
|
+
packages: [
|
|
209
|
+
{ name: '@adonisjs/core', startDate: '2020-01-01' },
|
|
210
|
+
{ name: '@adonisjs/lucid', startDate: '2020-01-01' },
|
|
211
|
+
],
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
const ossStats = new Collection({
|
|
217
|
+
schema: statsSchema,
|
|
218
|
+
loader: ossStatsLoader,
|
|
219
|
+
cache: true,
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
const query = await ossStats.load()
|
|
223
|
+
const stats = query.all()
|
|
224
|
+
console.log(`Total GitHub stars: ${stats.stars}`)
|
|
225
|
+
console.log(`Total npm downloads: ${stats.installs}`)
|
|
226
|
+
```
|
|
227
|
+
|
|
181
228
|
### Custom Views
|
|
182
229
|
|
|
183
230
|
Views allow you to define reusable query methods with full type safety:
|
|
@@ -70,10 +70,20 @@ var Collection = class _Collection {
|
|
|
70
70
|
static multi(sections, callback) {
|
|
71
71
|
return sections.reduce(
|
|
72
72
|
(result, section) => {
|
|
73
|
+
;
|
|
73
74
|
result[section] = callback(section);
|
|
74
75
|
return result;
|
|
75
76
|
},
|
|
76
|
-
{
|
|
77
|
+
{
|
|
78
|
+
async load() {
|
|
79
|
+
const views = {};
|
|
80
|
+
for (let section of sections) {
|
|
81
|
+
;
|
|
82
|
+
views[section] = await this[section].load();
|
|
83
|
+
}
|
|
84
|
+
return views;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
77
87
|
);
|
|
78
88
|
}
|
|
79
89
|
/**
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import {
|
|
2
|
+
debug_default
|
|
3
|
+
} from "./chunk-LB6JFRVG.js";
|
|
4
|
+
|
|
5
|
+
// src/utils.ts
|
|
6
|
+
import { Octokit } from "@octokit/rest";
|
|
7
|
+
import { graphql } from "@octokit/graphql";
|
|
8
|
+
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
9
|
+
import dayjs from "dayjs";
|
|
10
|
+
import { dirname } from "path";
|
|
11
|
+
async function fetchAllSponsors({
|
|
12
|
+
login,
|
|
13
|
+
isOrg,
|
|
14
|
+
ghToken
|
|
15
|
+
}) {
|
|
16
|
+
let hasNext = true;
|
|
17
|
+
let cursor = null;
|
|
18
|
+
const allSponsors = [];
|
|
19
|
+
const query = `
|
|
20
|
+
query($login: String!, $cursor: String) {
|
|
21
|
+
${isOrg ? `organization(login: $login)` : `user(login: $login)`} {
|
|
22
|
+
sponsorshipsAsMaintainer(first: 100, after: $cursor) {
|
|
23
|
+
nodes {
|
|
24
|
+
id
|
|
25
|
+
createdAt
|
|
26
|
+
privacyLevel
|
|
27
|
+
isActive
|
|
28
|
+
tier {
|
|
29
|
+
name
|
|
30
|
+
isOneTime
|
|
31
|
+
monthlyPriceInCents
|
|
32
|
+
}
|
|
33
|
+
sponsorEntity {
|
|
34
|
+
__typename
|
|
35
|
+
... on User {
|
|
36
|
+
login
|
|
37
|
+
name
|
|
38
|
+
avatarUrl
|
|
39
|
+
url
|
|
40
|
+
}
|
|
41
|
+
... on Organization {
|
|
42
|
+
login
|
|
43
|
+
name
|
|
44
|
+
avatarUrl
|
|
45
|
+
url
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
pageInfo {
|
|
50
|
+
hasNextPage
|
|
51
|
+
endCursor
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
`;
|
|
57
|
+
while (hasNext) {
|
|
58
|
+
const data = await graphql(query, {
|
|
59
|
+
headers: {
|
|
60
|
+
authorization: `token ${ghToken}`
|
|
61
|
+
},
|
|
62
|
+
login,
|
|
63
|
+
cursor
|
|
64
|
+
});
|
|
65
|
+
const root = isOrg ? data.organization : data.user;
|
|
66
|
+
if (!root) {
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
const conn = root.sponsorshipsAsMaintainer;
|
|
70
|
+
if (!conn || !conn.nodes) {
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
for (const node of conn.nodes) {
|
|
74
|
+
const sponsorEntity = node.sponsorEntity;
|
|
75
|
+
allSponsors.push({
|
|
76
|
+
id: node.id,
|
|
77
|
+
createdAt: node.createdAt,
|
|
78
|
+
privacyLevel: node.privacyLevel,
|
|
79
|
+
tierName: node.tier?.name ?? null,
|
|
80
|
+
tierMonthlyPriceInCents: node.tier?.monthlyPriceInCents ?? null,
|
|
81
|
+
sponsorType: sponsorEntity.__typename,
|
|
82
|
+
sponsorLogin: sponsorEntity.login,
|
|
83
|
+
sponsorName: sponsorEntity.name ?? null,
|
|
84
|
+
sponsorAvatarUrl: sponsorEntity.avatarUrl ?? null,
|
|
85
|
+
sponsorUrl: sponsorEntity.url ?? null
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
hasNext = conn.pageInfo.hasNextPage;
|
|
89
|
+
cursor = conn.pageInfo.endCursor;
|
|
90
|
+
}
|
|
91
|
+
return allSponsors;
|
|
92
|
+
}
|
|
93
|
+
async function fetchReleases({
|
|
94
|
+
org,
|
|
95
|
+
ghToken,
|
|
96
|
+
filters
|
|
97
|
+
}) {
|
|
98
|
+
let hasMoreRepos = true;
|
|
99
|
+
let orgCursor = null;
|
|
100
|
+
const allReleases = [];
|
|
101
|
+
while (hasMoreRepos) {
|
|
102
|
+
const query = `
|
|
103
|
+
query($cursor: String) {
|
|
104
|
+
organization(login: "${org}") {
|
|
105
|
+
repositories(
|
|
106
|
+
first: 10
|
|
107
|
+
after: $cursor
|
|
108
|
+
privacy: PUBLIC
|
|
109
|
+
isArchived: false
|
|
110
|
+
) {
|
|
111
|
+
nodes {
|
|
112
|
+
name
|
|
113
|
+
releases(first: 50, orderBy: {field: CREATED_AT, direction: DESC}) {
|
|
114
|
+
nodes {
|
|
115
|
+
name
|
|
116
|
+
tagName
|
|
117
|
+
publishedAt
|
|
118
|
+
url
|
|
119
|
+
description
|
|
120
|
+
}
|
|
121
|
+
pageInfo {
|
|
122
|
+
endCursor
|
|
123
|
+
hasNextPage
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
pageInfo {
|
|
128
|
+
endCursor
|
|
129
|
+
hasNextPage
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
`;
|
|
135
|
+
const data = await graphql(query, {
|
|
136
|
+
headers: {
|
|
137
|
+
authorization: `token ${ghToken}`
|
|
138
|
+
},
|
|
139
|
+
cursor: orgCursor
|
|
140
|
+
});
|
|
141
|
+
for (const repo of data.organization.repositories.nodes) {
|
|
142
|
+
const filtered = repo.releases.nodes.filter((r) => {
|
|
143
|
+
if (!filters) {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
let pickRelease = true;
|
|
147
|
+
if (filters.nameDoesntInclude) {
|
|
148
|
+
pickRelease = !filters.nameDoesntInclude.some((substr) => r.name.includes(substr));
|
|
149
|
+
}
|
|
150
|
+
if (pickRelease && filters.nameIncludes) {
|
|
151
|
+
pickRelease = filters.nameIncludes.some((substr) => r.name.includes(substr));
|
|
152
|
+
}
|
|
153
|
+
return pickRelease;
|
|
154
|
+
}).map((r) => ({
|
|
155
|
+
repo: repo.name,
|
|
156
|
+
...r
|
|
157
|
+
}));
|
|
158
|
+
allReleases.push(...filtered);
|
|
159
|
+
}
|
|
160
|
+
hasMoreRepos = data.organization.repositories.pageInfo.hasNextPage;
|
|
161
|
+
orgCursor = data.organization.repositories.pageInfo.endCursor;
|
|
162
|
+
}
|
|
163
|
+
return allReleases;
|
|
164
|
+
}
|
|
165
|
+
async function fetchContributorsForOrg({
|
|
166
|
+
org,
|
|
167
|
+
ghToken
|
|
168
|
+
}) {
|
|
169
|
+
const REPO_PAGE_SIZE = 100;
|
|
170
|
+
const CONTRIB_PAGE_SIZE = 100;
|
|
171
|
+
const octokit = new Octokit({ auth: ghToken });
|
|
172
|
+
const repos = await octokit.paginate(octokit.repos.listForOrg, {
|
|
173
|
+
org,
|
|
174
|
+
type: "public",
|
|
175
|
+
per_page: REPO_PAGE_SIZE
|
|
176
|
+
});
|
|
177
|
+
const activeRepos = repos.filter((r) => !r.archived);
|
|
178
|
+
const result = [];
|
|
179
|
+
for (const repo of activeRepos) {
|
|
180
|
+
const repoName = repo.name;
|
|
181
|
+
try {
|
|
182
|
+
const contributors = await octokit.paginate(
|
|
183
|
+
octokit.repos.listContributors,
|
|
184
|
+
{
|
|
185
|
+
owner: org,
|
|
186
|
+
repo: repoName,
|
|
187
|
+
per_page: CONTRIB_PAGE_SIZE
|
|
188
|
+
},
|
|
189
|
+
(response) => response.data
|
|
190
|
+
);
|
|
191
|
+
contributors.forEach((c) => {
|
|
192
|
+
if (c.login) {
|
|
193
|
+
result.push({
|
|
194
|
+
login: c.login,
|
|
195
|
+
id: c.id,
|
|
196
|
+
avatar_url: c.avatar_url ?? null,
|
|
197
|
+
html_url: c.html_url ?? null,
|
|
198
|
+
contributions: c.contributions ?? 0
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
} catch (err) {
|
|
203
|
+
console.warn(
|
|
204
|
+
`Warning: failed to fetch contributors for ${org}/${repoName}: ${err?.message ?? err}`
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
function mergeArrays(existing, fresh, key) {
|
|
211
|
+
const seen = /* @__PURE__ */ new Set();
|
|
212
|
+
const deduped = [];
|
|
213
|
+
for (const r of [...existing, ...fresh]) {
|
|
214
|
+
if (!seen.has(r[key])) {
|
|
215
|
+
seen.add(r[key]);
|
|
216
|
+
deduped.push(r);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return deduped;
|
|
220
|
+
}
|
|
221
|
+
async function aggregateInstalls(packages) {
|
|
222
|
+
let total = 0;
|
|
223
|
+
for (let pkg of packages) {
|
|
224
|
+
const startDate = pkg.startDate;
|
|
225
|
+
const endDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
226
|
+
const res = await fetch(
|
|
227
|
+
`https://api.npmjs.org/downloads/point/${startDate}:${endDate}/${pkg.name}`
|
|
228
|
+
);
|
|
229
|
+
const data = await res.json();
|
|
230
|
+
total += data.downloads;
|
|
231
|
+
}
|
|
232
|
+
return total;
|
|
233
|
+
}
|
|
234
|
+
async function aggregateStars({
|
|
235
|
+
org,
|
|
236
|
+
ghToken
|
|
237
|
+
}) {
|
|
238
|
+
let totalStars = 0;
|
|
239
|
+
const octokit = new Octokit({ auth: ghToken });
|
|
240
|
+
await octokit.paginate(
|
|
241
|
+
octokit.repos.listForOrg,
|
|
242
|
+
{
|
|
243
|
+
org,
|
|
244
|
+
type: "public",
|
|
245
|
+
per_page: 100
|
|
246
|
+
},
|
|
247
|
+
(response) => {
|
|
248
|
+
for (const repo of response.data) {
|
|
249
|
+
if (!repo.archived && repo.stargazers_count) {
|
|
250
|
+
totalStars += repo.stargazers_count;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return response.data;
|
|
254
|
+
}
|
|
255
|
+
);
|
|
256
|
+
return totalStars;
|
|
257
|
+
}
|
|
258
|
+
function createCache({
|
|
259
|
+
key,
|
|
260
|
+
outputPath,
|
|
261
|
+
refresh
|
|
262
|
+
}) {
|
|
263
|
+
function isExpired(fetchDate) {
|
|
264
|
+
switch (refresh) {
|
|
265
|
+
case "daily":
|
|
266
|
+
return dayjs().isAfter(fetchDate, "day");
|
|
267
|
+
case "weekly":
|
|
268
|
+
return dayjs().isAfter(fetchDate, "week");
|
|
269
|
+
case "monthly":
|
|
270
|
+
return dayjs().isAfter(fetchDate, "month");
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
/**
|
|
275
|
+
* Retrieves cached data from disk if it exists and hasn't expired.
|
|
276
|
+
* Returns null if the cache doesn't exist, is expired, or the file is not found.
|
|
277
|
+
*
|
|
278
|
+
* @example
|
|
279
|
+
* ```ts
|
|
280
|
+
* const data = await cache.get()
|
|
281
|
+
* if (data === null) {
|
|
282
|
+
* console.log('Cache expired or not found')
|
|
283
|
+
* }
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
286
|
+
async get() {
|
|
287
|
+
try {
|
|
288
|
+
debug_default('loading %s from file "%s"', key, outputPath);
|
|
289
|
+
const cachedContents = JSON.parse(await readFile(outputPath, "utf-8"));
|
|
290
|
+
if (!cachedContents || isExpired(new Date(cachedContents.lastFetched))) {
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
return cachedContents[key];
|
|
294
|
+
} catch (error) {
|
|
295
|
+
if (error.code !== "ENOENT") {
|
|
296
|
+
throw error;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return null;
|
|
300
|
+
},
|
|
301
|
+
/**
|
|
302
|
+
* Saves data to the cache file with the current timestamp.
|
|
303
|
+
* Creates the directory structure if it doesn't exist.
|
|
304
|
+
*
|
|
305
|
+
* @param contents - The data to cache
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* ```ts
|
|
309
|
+
* const freshData = await fetchDataFromAPI()
|
|
310
|
+
* await cache.put(freshData)
|
|
311
|
+
* ```
|
|
312
|
+
*/
|
|
313
|
+
async put(contents) {
|
|
314
|
+
debug_default('caching %s "%s"', key, outputPath);
|
|
315
|
+
const fileContents = { lastFetched: (/* @__PURE__ */ new Date()).toISOString(), [key]: contents };
|
|
316
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
317
|
+
await writeFile(outputPath, JSON.stringify(fileContents));
|
|
318
|
+
return contents;
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export {
|
|
324
|
+
fetchAllSponsors,
|
|
325
|
+
fetchReleases,
|
|
326
|
+
fetchContributorsForOrg,
|
|
327
|
+
mergeArrays,
|
|
328
|
+
aggregateInstalls,
|
|
329
|
+
aggregateStars,
|
|
330
|
+
createCache
|
|
331
|
+
};
|
package/build/index.d.ts
CHANGED
package/build/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Collection
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-Q6QIMTOW.js";
|
|
4
|
+
import {
|
|
5
|
+
createCache
|
|
6
|
+
} from "./chunk-WO5VTK7D.js";
|
|
4
7
|
import "./chunk-LB6JFRVG.js";
|
|
5
8
|
|
|
6
9
|
// configure.ts
|
|
@@ -12,5 +15,6 @@ async function configure(command) {
|
|
|
12
15
|
}
|
|
13
16
|
export {
|
|
14
17
|
Collection,
|
|
15
|
-
configure
|
|
18
|
+
configure,
|
|
19
|
+
createCache
|
|
16
20
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type ApplicationService } from '@adonisjs/core/types';
|
|
2
2
|
declare module '@vinejs/vine' {
|
|
3
3
|
interface VineString {
|
|
4
|
+
toContents(): this;
|
|
4
5
|
/**
|
|
5
6
|
* Converts a relative path to a Vite asset path.
|
|
6
7
|
* This method transforms the path using Vite's asset resolution system.
|
|
@@ -1,14 +1,31 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Collection
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-Q6QIMTOW.js";
|
|
4
4
|
import "../chunk-LB6JFRVG.js";
|
|
5
5
|
|
|
6
6
|
// providers/content_provider.ts
|
|
7
7
|
import { resolve } from "path";
|
|
8
8
|
import vine, { VineString } from "@vinejs/vine";
|
|
9
|
+
import { readFile } from "fs/promises";
|
|
9
10
|
var toVitePath = vine.createRule(function vitePath(value, _, field) {
|
|
10
|
-
|
|
11
|
+
if (typeof value === "string") {
|
|
12
|
+
field.mutate(
|
|
13
|
+
field.meta.vite.assetPath(value.replace(/^\.\/|^\//, "").replace(/\/$/, "")),
|
|
14
|
+
field
|
|
15
|
+
);
|
|
16
|
+
}
|
|
11
17
|
});
|
|
18
|
+
var toContents = vine.createRule(
|
|
19
|
+
async function vitePath2(value, _, field) {
|
|
20
|
+
if (typeof value === "string") {
|
|
21
|
+
const absolutePath2 = resolve(field.meta.menuFileRoot, value);
|
|
22
|
+
field.mutate(await readFile(absolutePath2, "utf-8"), field);
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
isAsync: true
|
|
27
|
+
}
|
|
28
|
+
);
|
|
12
29
|
var toAbsolutePath = vine.createRule(function absolutePath(value, _, field) {
|
|
13
30
|
field.mutate(resolve(field.meta.menuFileRoot, value), field);
|
|
14
31
|
});
|
|
@@ -18,6 +35,9 @@ VineString.macro("toVitePath", function() {
|
|
|
18
35
|
VineString.macro("toAbsolutePath", function() {
|
|
19
36
|
return this.use(toAbsolutePath());
|
|
20
37
|
});
|
|
38
|
+
VineString.macro("toContents", function() {
|
|
39
|
+
return this.use(toContents());
|
|
40
|
+
});
|
|
21
41
|
var ContentProvider = class {
|
|
22
42
|
/**
|
|
23
43
|
* Creates a new instance of the content provider.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Vite } from '@adonisjs/vite';
|
|
2
2
|
import { type Infer, type SchemaTypes } from '@vinejs/vine/types';
|
|
3
3
|
import { type CollectionOptions, type ViewFn, type ViewsToQueryMethods } from './types.js';
|
|
4
|
+
import { type Prettify } from '@adonisjs/core/types/common';
|
|
4
5
|
/**
|
|
5
6
|
* Manages a collection of data with schema validation and custom view functions.
|
|
6
7
|
*
|
|
@@ -81,8 +82,14 @@ export declare class Collection<Schema extends SchemaTypes, Views extends Record
|
|
|
81
82
|
* // Results in: { api: Collection, guides: Collection, tutorials: Collection }
|
|
82
83
|
* ```
|
|
83
84
|
*/
|
|
84
|
-
static multi<Section extends string, Callback extends (section: Section) => any
|
|
85
|
+
static multi<Section extends string, Callback extends (section: Section) => Collection<any, any>>(sections: Section[], callback: Callback): {
|
|
85
86
|
[K in Section]: ReturnType<Callback>;
|
|
87
|
+
} & {
|
|
88
|
+
load(): Promise<{
|
|
89
|
+
[K in Section]: ReturnType<Callback> extends Collection<infer S, infer V> ? Prettify<{
|
|
90
|
+
all(): Infer<S>;
|
|
91
|
+
} & ViewsToQueryMethods<V>> : never;
|
|
92
|
+
}>;
|
|
86
93
|
};
|
|
87
94
|
/**
|
|
88
95
|
* Configures the Vite service instance for resolving asset paths.
|
|
@@ -129,7 +136,7 @@ export declare class Collection<Schema extends SchemaTypes, Views extends Record
|
|
|
129
136
|
* const post = query.findBySlug('hello-world')
|
|
130
137
|
* ```
|
|
131
138
|
*/
|
|
132
|
-
load(): Promise<{
|
|
139
|
+
load(): Promise<Prettify<{
|
|
133
140
|
all(): Infer<Schema>;
|
|
134
|
-
} & ViewsToQueryMethods<Views
|
|
141
|
+
} & ViewsToQueryMethods<Views>>>;
|
|
135
142
|
}
|
package/build/src/debug.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { type GithubSponsorsOptions, type GithubReleasesOptions, type GithubContributorsOptions } from '../types.ts';
|
|
1
|
+
import { type GithubSponsorsOptions, type GithubReleasesOptions, type GithubContributorsOptions, type OssStatsOptions } from '../types.ts';
|
|
2
|
+
import { JsonLoader } from './json.ts';
|
|
3
|
+
import { OssStatsLoader } from './oss_stats.ts';
|
|
2
4
|
import { GithubSponsorsLoader } from './gh_sponsors.ts';
|
|
3
5
|
import { GithubReleasesLoader } from './gh_releases.ts';
|
|
4
6
|
import { GithubContributorsLoader } from './gh_contributors.ts';
|
|
5
|
-
import { JsonLoader } from './json.ts';
|
|
6
7
|
/**
|
|
7
8
|
* Factory functions for creating content loaders.
|
|
8
9
|
* Provides convenient access to GitHub-based data loaders.
|
|
@@ -77,6 +78,33 @@ export declare const loaders: {
|
|
|
77
78
|
* ```
|
|
78
79
|
*/
|
|
79
80
|
ghReleases(options: GithubReleasesOptions): GithubReleasesLoader<import("@vinejs/vine/types").SchemaTypes>;
|
|
81
|
+
/**
|
|
82
|
+
* Creates an OSS statistics loader instance.
|
|
83
|
+
*
|
|
84
|
+
* @param options - Configuration options for the OSS stats loader
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* const loader = loaders.ossStats({
|
|
89
|
+
* outputPath: './cache/oss-stats.json',
|
|
90
|
+
* refresh: 'daily',
|
|
91
|
+
* sources: [
|
|
92
|
+
* {
|
|
93
|
+
* type: 'github',
|
|
94
|
+
* org: 'adonisjs',
|
|
95
|
+
* ghToken: process.env.GITHUB_TOKEN
|
|
96
|
+
* },
|
|
97
|
+
* {
|
|
98
|
+
* type: 'npm',
|
|
99
|
+
* packages: [
|
|
100
|
+
* { name: '@adonisjs/core', startDate: '2020-01-01' }
|
|
101
|
+
* ]
|
|
102
|
+
* }
|
|
103
|
+
* ]
|
|
104
|
+
* })
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
ossStats(options: OssStatsOptions): OssStatsLoader<import("@vinejs/vine/types").SchemaTypes>;
|
|
80
108
|
/**
|
|
81
109
|
* Creates a JSON file loader instance.
|
|
82
110
|
*
|