@ahmedrowaihi/8n 6.0.56 → 6.0.58
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/dist/index.mjs +29 -234
- package/package.json +1 -1
- package/starter/app/[lang]/(docs)/upstream/page.jsx +1 -0
- package/starter/app/[lang]/(marketing)/layout.jsx +1 -1
- package/starter/content/mcp/01-config.mdx +4 -7
- package/starter/package.json +1 -1
- package/starter/src/components/logo-loader.jsx +1 -1
- package/starter/src/config.js +1 -1
- package/starter/src/features/auth/session.js +1 -1
- package/starter/src/features/docs/components/page-content.jsx +1 -1
- package/starter/src/features/upstream/rss-parser.js +1 -0
- package/starter/src/features/upstream/upstream-page.jsx +2 -0
- package/starter/src/features/upstream/use-upstream-feeds.js +2 -0
- package/starter/src/lib/content-source.js +1 -1
- package/starter/src/lib/layout.shared.jsx +1 -1
- package/starter/src/lib/source.js +1 -1
- package/starter/src/locale.config.js +1 -1
- package/starter/src/components/page-transition.jsx +0 -2
package/dist/index.mjs
CHANGED
|
@@ -590,7 +590,6 @@ const string$1 = (params) => {
|
|
|
590
590
|
const regex = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
|
|
591
591
|
return new RegExp(`^${regex}$`);
|
|
592
592
|
};
|
|
593
|
-
const number = /^-?\d+(?:\.\d+)?$/;
|
|
594
593
|
const boolean$1 = /^(?:true|false)$/i;
|
|
595
594
|
const lowercase = /^[^A-Z]*$/;
|
|
596
595
|
const uppercase = /^[^a-z]*$/;
|
|
@@ -1629,97 +1628,6 @@ function handleIntersectionResults(result, left, right) {
|
|
|
1629
1628
|
result.value = merged.data;
|
|
1630
1629
|
return result;
|
|
1631
1630
|
}
|
|
1632
|
-
const $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
1633
|
-
$ZodType.init(inst, def);
|
|
1634
|
-
inst._zod.parse = (payload, ctx) => {
|
|
1635
|
-
const input = payload.value;
|
|
1636
|
-
if (!isPlainObject(input)) {
|
|
1637
|
-
payload.issues.push({
|
|
1638
|
-
expected: "record",
|
|
1639
|
-
code: "invalid_type",
|
|
1640
|
-
input,
|
|
1641
|
-
inst
|
|
1642
|
-
});
|
|
1643
|
-
return payload;
|
|
1644
|
-
}
|
|
1645
|
-
const proms = [];
|
|
1646
|
-
const values = def.keyType._zod.values;
|
|
1647
|
-
if (values) {
|
|
1648
|
-
payload.value = {};
|
|
1649
|
-
const recordKeys = /* @__PURE__ */ new Set();
|
|
1650
|
-
for (const key of values) if (typeof key === "string" || typeof key === "number" || typeof key === "symbol") {
|
|
1651
|
-
recordKeys.add(typeof key === "number" ? key.toString() : key);
|
|
1652
|
-
const result = def.valueType._zod.run({
|
|
1653
|
-
value: input[key],
|
|
1654
|
-
issues: []
|
|
1655
|
-
}, ctx);
|
|
1656
|
-
if (result instanceof Promise) proms.push(result.then((result) => {
|
|
1657
|
-
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
1658
|
-
payload.value[key] = result.value;
|
|
1659
|
-
}));
|
|
1660
|
-
else {
|
|
1661
|
-
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
1662
|
-
payload.value[key] = result.value;
|
|
1663
|
-
}
|
|
1664
|
-
}
|
|
1665
|
-
let unrecognized;
|
|
1666
|
-
for (const key in input) if (!recordKeys.has(key)) {
|
|
1667
|
-
unrecognized = unrecognized ?? [];
|
|
1668
|
-
unrecognized.push(key);
|
|
1669
|
-
}
|
|
1670
|
-
if (unrecognized && unrecognized.length > 0) payload.issues.push({
|
|
1671
|
-
code: "unrecognized_keys",
|
|
1672
|
-
input,
|
|
1673
|
-
inst,
|
|
1674
|
-
keys: unrecognized
|
|
1675
|
-
});
|
|
1676
|
-
} else {
|
|
1677
|
-
payload.value = {};
|
|
1678
|
-
for (const key of Reflect.ownKeys(input)) {
|
|
1679
|
-
if (key === "__proto__") continue;
|
|
1680
|
-
let keyResult = def.keyType._zod.run({
|
|
1681
|
-
value: key,
|
|
1682
|
-
issues: []
|
|
1683
|
-
}, ctx);
|
|
1684
|
-
if (keyResult instanceof Promise) throw new Error("Async schemas not supported in object keys currently");
|
|
1685
|
-
if (typeof key === "string" && number.test(key) && keyResult.issues.length) {
|
|
1686
|
-
const retryResult = def.keyType._zod.run({
|
|
1687
|
-
value: Number(key),
|
|
1688
|
-
issues: []
|
|
1689
|
-
}, ctx);
|
|
1690
|
-
if (retryResult instanceof Promise) throw new Error("Async schemas not supported in object keys currently");
|
|
1691
|
-
if (retryResult.issues.length === 0) keyResult = retryResult;
|
|
1692
|
-
}
|
|
1693
|
-
if (keyResult.issues.length) {
|
|
1694
|
-
if (def.mode === "loose") payload.value[key] = input[key];
|
|
1695
|
-
else payload.issues.push({
|
|
1696
|
-
code: "invalid_key",
|
|
1697
|
-
origin: "record",
|
|
1698
|
-
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
1699
|
-
input: key,
|
|
1700
|
-
path: [key],
|
|
1701
|
-
inst
|
|
1702
|
-
});
|
|
1703
|
-
continue;
|
|
1704
|
-
}
|
|
1705
|
-
const result = def.valueType._zod.run({
|
|
1706
|
-
value: input[key],
|
|
1707
|
-
issues: []
|
|
1708
|
-
}, ctx);
|
|
1709
|
-
if (result instanceof Promise) proms.push(result.then((result) => {
|
|
1710
|
-
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
1711
|
-
payload.value[keyResult.value] = result.value;
|
|
1712
|
-
}));
|
|
1713
|
-
else {
|
|
1714
|
-
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
1715
|
-
payload.value[keyResult.value] = result.value;
|
|
1716
|
-
}
|
|
1717
|
-
}
|
|
1718
|
-
}
|
|
1719
|
-
if (proms.length) return Promise.all(proms).then(() => payload);
|
|
1720
|
-
return payload;
|
|
1721
|
-
};
|
|
1722
|
-
});
|
|
1723
1631
|
const $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
|
|
1724
1632
|
$ZodType.init(inst, def);
|
|
1725
1633
|
const values = getEnumValues(def.entries);
|
|
@@ -1738,24 +1646,6 @@ const $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
|
|
|
1738
1646
|
return payload;
|
|
1739
1647
|
};
|
|
1740
1648
|
});
|
|
1741
|
-
const $ZodLiteral = /* @__PURE__ */ $constructor("$ZodLiteral", (inst, def) => {
|
|
1742
|
-
$ZodType.init(inst, def);
|
|
1743
|
-
if (def.values.length === 0) throw new Error("Cannot create literal schema with no valid values");
|
|
1744
|
-
const values = new Set(def.values);
|
|
1745
|
-
inst._zod.values = values;
|
|
1746
|
-
inst._zod.pattern = new RegExp(`^(${def.values.map((o) => typeof o === "string" ? escapeRegex(o) : o ? escapeRegex(o.toString()) : String(o)).join("|")})$`);
|
|
1747
|
-
inst._zod.parse = (payload, _ctx) => {
|
|
1748
|
-
const input = payload.value;
|
|
1749
|
-
if (values.has(input)) return payload;
|
|
1750
|
-
payload.issues.push({
|
|
1751
|
-
code: "invalid_value",
|
|
1752
|
-
values: def.values,
|
|
1753
|
-
input,
|
|
1754
|
-
inst
|
|
1755
|
-
});
|
|
1756
|
-
return payload;
|
|
1757
|
-
};
|
|
1758
|
-
});
|
|
1759
1649
|
const $ZodTransform = /* @__PURE__ */ $constructor("$ZodTransform", (inst, def) => {
|
|
1760
1650
|
$ZodType.init(inst, def);
|
|
1761
1651
|
inst._zod.parse = (payload, ctx) => {
|
|
@@ -2821,27 +2711,6 @@ const enumProcessor = (schema, _ctx, json, _params) => {
|
|
|
2821
2711
|
if (values.every((v) => typeof v === "string")) json.type = "string";
|
|
2822
2712
|
json.enum = values;
|
|
2823
2713
|
};
|
|
2824
|
-
const literalProcessor = (schema, ctx, json, _params) => {
|
|
2825
|
-
const def = schema._zod.def;
|
|
2826
|
-
const vals = [];
|
|
2827
|
-
for (const val of def.values) if (val === void 0) {
|
|
2828
|
-
if (ctx.unrepresentable === "throw") throw new Error("Literal `undefined` cannot be represented in JSON Schema");
|
|
2829
|
-
} else if (typeof val === "bigint") if (ctx.unrepresentable === "throw") throw new Error("BigInt literals cannot be represented in JSON Schema");
|
|
2830
|
-
else vals.push(Number(val));
|
|
2831
|
-
else vals.push(val);
|
|
2832
|
-
if (vals.length === 0) {} else if (vals.length === 1) {
|
|
2833
|
-
const val = vals[0];
|
|
2834
|
-
json.type = val === null ? "null" : typeof val;
|
|
2835
|
-
if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") json.enum = [val];
|
|
2836
|
-
else json.const = val;
|
|
2837
|
-
} else {
|
|
2838
|
-
if (vals.every((v) => typeof v === "number")) json.type = "number";
|
|
2839
|
-
if (vals.every((v) => typeof v === "string")) json.type = "string";
|
|
2840
|
-
if (vals.every((v) => typeof v === "boolean")) json.type = "boolean";
|
|
2841
|
-
if (vals.every((v) => v === null)) json.type = "null";
|
|
2842
|
-
json.enum = vals;
|
|
2843
|
-
}
|
|
2844
|
-
};
|
|
2845
2714
|
const customProcessor = (_schema, ctx, _json, _params) => {
|
|
2846
2715
|
if (ctx.unrepresentable === "throw") throw new Error("Custom types cannot be represented in JSON Schema");
|
|
2847
2716
|
};
|
|
@@ -2924,39 +2793,6 @@ const intersectionProcessor = (schema, ctx, json, params) => {
|
|
|
2924
2793
|
const isSimpleIntersection = (val) => "allOf" in val && Object.keys(val).length === 1;
|
|
2925
2794
|
json.allOf = [...isSimpleIntersection(a) ? a.allOf : [a], ...isSimpleIntersection(b) ? b.allOf : [b]];
|
|
2926
2795
|
};
|
|
2927
|
-
const recordProcessor = (schema, ctx, _json, params) => {
|
|
2928
|
-
const json = _json;
|
|
2929
|
-
const def = schema._zod.def;
|
|
2930
|
-
json.type = "object";
|
|
2931
|
-
const keyType = def.keyType;
|
|
2932
|
-
const patterns = keyType._zod.bag?.patterns;
|
|
2933
|
-
if (def.mode === "loose" && patterns && patterns.size > 0) {
|
|
2934
|
-
const valueSchema = process$1(def.valueType, ctx, {
|
|
2935
|
-
...params,
|
|
2936
|
-
path: [
|
|
2937
|
-
...params.path,
|
|
2938
|
-
"patternProperties",
|
|
2939
|
-
"*"
|
|
2940
|
-
]
|
|
2941
|
-
});
|
|
2942
|
-
json.patternProperties = {};
|
|
2943
|
-
for (const pattern of patterns) json.patternProperties[pattern.source] = valueSchema;
|
|
2944
|
-
} else {
|
|
2945
|
-
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") json.propertyNames = process$1(def.keyType, ctx, {
|
|
2946
|
-
...params,
|
|
2947
|
-
path: [...params.path, "propertyNames"]
|
|
2948
|
-
});
|
|
2949
|
-
json.additionalProperties = process$1(def.valueType, ctx, {
|
|
2950
|
-
...params,
|
|
2951
|
-
path: [...params.path, "additionalProperties"]
|
|
2952
|
-
});
|
|
2953
|
-
}
|
|
2954
|
-
const keyValues = keyType._zod.values;
|
|
2955
|
-
if (keyValues) {
|
|
2956
|
-
const validKeyValues = [...keyValues].filter((v) => typeof v === "string" || typeof v === "number");
|
|
2957
|
-
if (validKeyValues.length > 0) json.required = validKeyValues;
|
|
2958
|
-
}
|
|
2959
|
-
};
|
|
2960
2796
|
const nullableProcessor = (schema, ctx, json, params) => {
|
|
2961
2797
|
const def = schema._zod.def;
|
|
2962
2798
|
const inner = process$1(def.innerType, ctx, params);
|
|
@@ -3417,21 +3253,6 @@ function intersection(left, right) {
|
|
|
3417
3253
|
right
|
|
3418
3254
|
});
|
|
3419
3255
|
}
|
|
3420
|
-
const ZodRecord = /* @__PURE__ */ $constructor("ZodRecord", (inst, def) => {
|
|
3421
|
-
$ZodRecord.init(inst, def);
|
|
3422
|
-
ZodType.init(inst, def);
|
|
3423
|
-
inst._zod.processJSONSchema = (ctx, json, params) => recordProcessor(inst, ctx, json, params);
|
|
3424
|
-
inst.keyType = def.keyType;
|
|
3425
|
-
inst.valueType = def.valueType;
|
|
3426
|
-
});
|
|
3427
|
-
function record(keyType, valueType, params) {
|
|
3428
|
-
return new ZodRecord({
|
|
3429
|
-
type: "record",
|
|
3430
|
-
keyType,
|
|
3431
|
-
valueType,
|
|
3432
|
-
...normalizeParams(params)
|
|
3433
|
-
});
|
|
3434
|
-
}
|
|
3435
3256
|
const ZodEnum = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
|
|
3436
3257
|
$ZodEnum.init(inst, def);
|
|
3437
3258
|
ZodType.init(inst, def);
|
|
@@ -3469,23 +3290,6 @@ function _enum(values, params) {
|
|
|
3469
3290
|
...normalizeParams(params)
|
|
3470
3291
|
});
|
|
3471
3292
|
}
|
|
3472
|
-
const ZodLiteral = /* @__PURE__ */ $constructor("ZodLiteral", (inst, def) => {
|
|
3473
|
-
$ZodLiteral.init(inst, def);
|
|
3474
|
-
ZodType.init(inst, def);
|
|
3475
|
-
inst._zod.processJSONSchema = (ctx, json, params) => literalProcessor(inst, ctx, json, params);
|
|
3476
|
-
inst.values = new Set(def.values);
|
|
3477
|
-
Object.defineProperty(inst, "value", { get() {
|
|
3478
|
-
if (def.values.length > 1) throw new Error("This schema contains multiple valid literal values. Use `.values` instead.");
|
|
3479
|
-
return def.values[0];
|
|
3480
|
-
} });
|
|
3481
|
-
});
|
|
3482
|
-
function literal(value, params) {
|
|
3483
|
-
return new ZodLiteral({
|
|
3484
|
-
type: "literal",
|
|
3485
|
-
values: Array.isArray(value) ? value : [value],
|
|
3486
|
-
...normalizeParams(params)
|
|
3487
|
-
});
|
|
3488
|
-
}
|
|
3489
3293
|
const ZodTransform = /* @__PURE__ */ $constructor("ZodTransform", (inst, def) => {
|
|
3490
3294
|
$ZodTransform.init(inst, def);
|
|
3491
3295
|
ZodType.init(inst, def);
|
|
@@ -3657,22 +3461,13 @@ const meta = meta$1;
|
|
|
3657
3461
|
const configSchema = object({
|
|
3658
3462
|
content: string().default("./content"),
|
|
3659
3463
|
locales: array(string()).min(1).default(["en"]),
|
|
3660
|
-
github:
|
|
3464
|
+
github: string().optional(),
|
|
3661
3465
|
siteName: string().optional(),
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
})).default([]) }).default({ links: [] }),
|
|
3668
|
-
animations: boolean().default(true),
|
|
3669
|
-
basePath: string().optional(),
|
|
3670
|
-
auth: object({
|
|
3671
|
-
provider: literal("github"),
|
|
3672
|
-
repo: string().optional(),
|
|
3673
|
-
protect: union([boolean(), array(string())]).default(true),
|
|
3674
|
-
sessionDuration: string().default("7d")
|
|
3675
|
-
}).optional()
|
|
3466
|
+
auth: union([boolean(), array(string())]).optional(),
|
|
3467
|
+
upstream: array(object({
|
|
3468
|
+
url: string(),
|
|
3469
|
+
label: string()
|
|
3470
|
+
})).optional()
|
|
3676
3471
|
});
|
|
3677
3472
|
async function resolveConfig() {
|
|
3678
3473
|
const { config } = await loadConfig({
|
|
@@ -3738,7 +3533,7 @@ async function checkSelfUpdate() {
|
|
|
3738
3533
|
});
|
|
3739
3534
|
if (!res.ok) return;
|
|
3740
3535
|
const { version: latest } = await res.json();
|
|
3741
|
-
const current = "6.0.
|
|
3536
|
+
const current = "6.0.58";
|
|
3742
3537
|
if (latest !== current) console.log(pc.yellow("⚠") + pc.dim(` new version available: `) + pc.cyan(latest) + pc.dim(` (current: ${current}) — run `) + pc.cyan("npm i -g @ahmedrowaihi/8n") + pc.dim(" to update"));
|
|
3743
3538
|
} catch {}
|
|
3744
3539
|
}
|
|
@@ -3809,17 +3604,14 @@ function buildEnv({ config, contentDir, staticExport = false }) {
|
|
|
3809
3604
|
CONTENT_DIR: contentDir,
|
|
3810
3605
|
LOCALES: (config.locales ?? ["en"]).join(","),
|
|
3811
3606
|
NEXT_PUBLIC_SITE_NAME: config.siteName ?? "Docs",
|
|
3812
|
-
NEXT_PUBLIC_GITHUB_REPO: config.github
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
NEXT_PUBLIC_ANIMATIONS: config.animations === false ? "false" : "true",
|
|
3816
|
-
NEXT_BASE_PATH: config.basePath ?? ghPagesBasePath ?? "",
|
|
3607
|
+
NEXT_PUBLIC_GITHUB_REPO: config.github ?? process.env.NEXT_PUBLIC_GITHUB_REPO ?? ghPagesUrl ?? vercelGithubUrl,
|
|
3608
|
+
NEXT_PUBLIC_UPSTREAM_SOURCES: JSON.stringify(config.upstream ?? []),
|
|
3609
|
+
NEXT_BASE_PATH: ghPagesBasePath ?? "",
|
|
3817
3610
|
NEXT_STATIC_EXPORT: staticExport ? "true" : "false",
|
|
3818
|
-
...config.auth ? {
|
|
3611
|
+
...config.auth !== void 0 ? {
|
|
3819
3612
|
AUTH_ENABLED: "true",
|
|
3820
|
-
AUTH_REPO: config.
|
|
3821
|
-
AUTH_PROTECT: JSON.stringify(config.auth
|
|
3822
|
-
AUTH_SESSION_DURATION: config.auth.sessionDuration
|
|
3613
|
+
AUTH_REPO: config.github ?? ghPagesUrl,
|
|
3614
|
+
AUTH_PROTECT: JSON.stringify(config.auth)
|
|
3823
3615
|
} : {}
|
|
3824
3616
|
};
|
|
3825
3617
|
}
|
|
@@ -3851,7 +3643,7 @@ async function dev() {
|
|
|
3851
3643
|
async function build({ server = false } = {}) {
|
|
3852
3644
|
const { config, contentDir } = await resolveProject();
|
|
3853
3645
|
const projectDir = process.cwd();
|
|
3854
|
-
console.log(pc.cyan("8n") + pc.dim(` v6.0.
|
|
3646
|
+
console.log(pc.cyan("8n") + pc.dim(` v6.0.58 build → ${contentDir}`));
|
|
3855
3647
|
if (server) await runNextFlat(projectDir, "build", buildEnv({
|
|
3856
3648
|
config,
|
|
3857
3649
|
contentDir,
|
|
@@ -3912,16 +3704,6 @@ const SCAFFOLD = {
|
|
|
3912
3704
|
locales: ["en"],
|
|
3913
3705
|
siteName: "Docs",
|
|
3914
3706
|
|
|
3915
|
-
// Pin to a specific starter version (git tag or commit SHA).
|
|
3916
|
-
// Remove this line to always track the latest release.
|
|
3917
|
-
// version: "v1.0.0",
|
|
3918
|
-
|
|
3919
|
-
// Sections auto-show when content exists, auto-hide when empty.
|
|
3920
|
-
// Set a section to false to hide it even if content is present.
|
|
3921
|
-
// sections: { api: false },
|
|
3922
|
-
|
|
3923
|
-
// Add links to the top navigation bar.
|
|
3924
|
-
// nav: { links: [{ text: "Blog", url: "https://example.com/blog" }] },
|
|
3925
3707
|
};
|
|
3926
3708
|
`,
|
|
3927
3709
|
["content/docs/index.mdx"]: `---
|
|
@@ -4007,6 +3789,19 @@ No folder restructuring needed. Files without a locale suffix belong to the defa
|
|
|
4007
3789
|
| \`icon\` | any index.mdx | sidebar group icon |
|
|
4008
3790
|
| \`redirect\` | any | immediately redirects to another URL |
|
|
4009
3791
|
|
|
3792
|
+
## Config options
|
|
3793
|
+
|
|
3794
|
+
\`\`\`ts
|
|
3795
|
+
export default {
|
|
3796
|
+
siteName: "Docs",
|
|
3797
|
+
locales: ["en", "ar"], // first is default
|
|
3798
|
+
nav: [{ text: "Blog", url: "https://example.com/blog" }],
|
|
3799
|
+
upstream: [{ url: "https://example.com/feed.xml", label: "Blog" }],
|
|
3800
|
+
sections: { api: false }, // force-hide a section
|
|
3801
|
+
github: { repo: "org/repo" }, // enables Edit on GitHub links
|
|
3802
|
+
};
|
|
3803
|
+
\`\`\`
|
|
3804
|
+
|
|
4010
3805
|
## CLI commands
|
|
4011
3806
|
|
|
4012
3807
|
\`\`\`bash
|
|
@@ -4223,7 +4018,7 @@ async function mcp() {
|
|
|
4223
4018
|
const mcpDir = join(getStarterDir(), "content", "mcp");
|
|
4224
4019
|
const server = new McpServer({
|
|
4225
4020
|
name: "8n",
|
|
4226
|
-
version: "6.0.
|
|
4021
|
+
version: "6.0.58"
|
|
4227
4022
|
});
|
|
4228
4023
|
server.registerTool("read_me", {
|
|
4229
4024
|
description: "Returns how to use the 8n MCP tools. Call this BEFORE documenting anything with 8n.",
|
|
@@ -4341,7 +4136,7 @@ async function generateApi({ input, output }) {
|
|
|
4341
4136
|
|
|
4342
4137
|
//#endregion
|
|
4343
4138
|
//#region src/index.ts
|
|
4344
|
-
const program = new Command().name("8n").description("Run your 8n docs site").version("6.0.
|
|
4139
|
+
const program = new Command().name("8n").description("Run your 8n docs site").version("6.0.58").addOption(new Option("--debug").hideHelp()).hook("preAction", (cmd) => {
|
|
4345
4140
|
if (cmd.opts().debug) process.env.DEBUG_8N = "1";
|
|
4346
4141
|
});
|
|
4347
4142
|
program.command("init").description("Scaffold a new docs project in the current directory").action(init);
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as r}from"react/jsx-runtime";import{UpstreamPage as t}from"../../../../src/features/upstream/upstream-page";import{redirect as a}from"next/navigation";import{env as o}from"../../../../src/config";import{defaultLocale as e}from"../../../../src/locale.config";export default async function i({params:m}){if(0===o.NEXT_PUBLIC_UPSTREAM_SOURCES.length){let{lang:r}=await m;a(`/${r??e}`)}let{lang:n}=await m;return r(t,{lang:n})}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{jsx as e,jsxs as r,Fragment as a}from"react/jsx-runtime";import t from"next/dynamic";import{AISearchTrigger as s}from"../../../src/features/ai/chat";import{MessageCircleIcon as i}from"lucide-react";
|
|
2
|
+
import{jsx as e,jsxs as r,Fragment as a}from"react/jsx-runtime";import t from"next/dynamic";import{AISearchTrigger as s}from"../../../src/features/ai/chat";import{MessageCircleIcon as i}from"lucide-react";let l=t(()=>import("../../../src/features/ai/chat").then(e=>({default:e.AISearchPanel})),{ssr:!1});export default function o({children:t}){return r(a,{children:[e(l,{}),e("div",{className:"flex flex-col flex-1",children:t}),e(s,{position:"float","aria-label":"Ask AI",variant:"secondary",size:"icon",className:"rounded-full text-muted-foreground size-12",children:e(i,{className:"size-5"})})]})}
|
|
@@ -10,16 +10,12 @@ export default {
|
|
|
10
10
|
content: "./content", // content directory (default: "./content")
|
|
11
11
|
locales: ["en"], // supported locales — first entry is the default
|
|
12
12
|
siteName: "Docs", // site name shown in the header
|
|
13
|
-
|
|
14
|
-
github: {
|
|
15
|
-
repo: "https://github.com/org/repo", // enables "Edit on GitHub" links on every page
|
|
16
|
-
},
|
|
13
|
+
github: "org/repo", // enables "Edit on GitHub" links on every page
|
|
17
14
|
sections: {
|
|
18
15
|
api: false, // false hides a section even when content exists
|
|
19
16
|
},
|
|
20
|
-
nav: {
|
|
21
|
-
|
|
22
|
-
},
|
|
17
|
+
nav: [{ text: "Blog", url: "https://example.com/blog" }],
|
|
18
|
+
upstream: [{ url: "https://example.com/feed.xml", label: "Blog" }],
|
|
23
19
|
};
|
|
24
20
|
```
|
|
25
21
|
|
|
@@ -32,6 +28,7 @@ export default {
|
|
|
32
28
|
| `ui` | `content/ui/` | UI component showcase |
|
|
33
29
|
| `changelog` | `content/changelog/` | Versioned release notes, sorted newest first |
|
|
34
30
|
| `home` | `content/home/` | Replaces the default landing page |
|
|
31
|
+
| `upstream` | — | RSS feed aggregator — configured via `upstream: [...]` |
|
|
35
32
|
|
|
36
33
|
Sections **auto-show** when their content directory exists and contains pages.
|
|
37
34
|
Sections **auto-hide** when the directory is missing or empty.
|
package/starter/package.json
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{jsx as t,jsxs as e}from"react/jsx-runtime";import{
|
|
2
|
+
import{jsx as t,jsxs as e}from"react/jsx-runtime";import{motion as o}from"motion/react";import{cn as r}from"../lib/cn";let i="M9.8339 17.7084C11.1402 16.073 11.6679 14.4352 11.8974 12.7433H12.1101C12.3396 14.4352 12.8673 16.073 14.1736 17.7084H14.3023L16.5019 13.3224C13.9398 11.8729 12.9035 9.87848 12.1716 7.29163H11.836C11.104 9.87848 10.0677 11.8729 7.50558 13.3224L9.70519 17.7084H9.8339Z";export function LogoLoader({className:n,...a}){return e("svg",{viewBox:"0 0 24 25",fill:"none",xmlns:"http://www.w3.org/2000/svg",className:r("size-4",n),...a,children:[t(o.path,{d:i,fill:"currentColor",animate:{opacity:[.08,.25,.08]},transition:{duration:1.6,repeat:1/0,ease:"easeInOut"}}),t(o.path,{d:i,fill:"none",stroke:"currentColor",strokeWidth:.6,strokeLinecap:"round",strokeLinejoin:"round",initial:{pathLength:0,opacity:0},animate:{pathLength:[0,1,1,0],opacity:[0,1,1,0]},transition:{duration:2,times:[0,.45,.7,1],repeat:1/0,ease:"easeInOut"}})]})}
|
package/starter/src/config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createEnv as
|
|
1
|
+
import{createEnv as E}from"@t3-oss/env-nextjs";import{z as _}from"zod";export const env=E({server:{SITE_URL:_.string().default("http://localhost:3000"),CONTENT_DIR:_.string().default("./content"),AUTH_ENABLED:_.enum(["true"]).optional(),AUTH_REPO:_.string().optional(),AUTH_PROTECT:_.string().default("true"),GITHUB_CLIENT_ID:_.string().optional(),GITHUB_CLIENT_SECRET:_.string().optional(),AUTH_SECRET:_.string().optional()},client:{NEXT_PUBLIC_SITE_NAME:_.string().default("Docs"),NEXT_PUBLIC_GITHUB_REPO:_.string().optional(),NEXT_PUBLIC_UPSTREAM_SOURCES:_.string().default("[]").transform(E=>JSON.parse(E))},runtimeEnv:{SITE_URL:process.env.SITE_URL??(process.env.VERCEL_PROJECT_PRODUCTION_URL?`https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`:process.env.VERCEL_URL?`https://${process.env.VERCEL_URL}`:void 0),CONTENT_DIR:process.env.CONTENT_DIR,AUTH_ENABLED:process.env.AUTH_ENABLED,AUTH_REPO:process.env.AUTH_REPO,AUTH_PROTECT:process.env.AUTH_PROTECT,GITHUB_CLIENT_ID:process.env.GITHUB_CLIENT_ID,GITHUB_CLIENT_SECRET:process.env.GITHUB_CLIENT_SECRET,AUTH_SECRET:process.env.AUTH_SECRET,NEXT_PUBLIC_SITE_NAME:process.env.NEXT_PUBLIC_SITE_NAME,NEXT_PUBLIC_GITHUB_REPO:process.env.NEXT_PUBLIC_GITHUB_REPO,NEXT_PUBLIC_UPSTREAM_SOURCES:process.env.NEXT_PUBLIC_UPSTREAM_SOURCES}});"development"===process.env.NODE_ENV&&env.NEXT_PUBLIC_GITHUB_REPO?.includes("your-org/your-repo")&&console.warn("[8n-starter] ⚠ NEXT_PUBLIC_GITHUB_REPO is still the placeholder value.\n Set github.repo in 8n.config.ts to enable Edit on GitHub links.");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cookies as e}from"next/headers";import{env as t}from"../../config";import{signJWT as n,verifyJWT as o}from"./jwt.js";let r="8n_session";export function parseDuration(e){let t=/^(\d+)([smhd])$/.exec(e);return t?parseInt(t[1])*({s:1,m:60,h:3600,d:86400})[t[2]]:604800}export async function getSession(){if(!t.AUTH_ENABLED||!t.AUTH_SECRET)return null;let n=(await e()).get(r)?.value;return n?o(n,t.AUTH_SECRET):null}export async function setSession(o){let a=t.AUTH_SECRET,s=parseDuration(
|
|
1
|
+
import{cookies as e}from"next/headers";import{env as t}from"../../config";import{signJWT as n,verifyJWT as o}from"./jwt.js";let r="8n_session";export function parseDuration(e){let t=/^(\d+)([smhd])$/.exec(e);return t?parseInt(t[1])*({s:1,m:60,h:3600,d:86400})[t[2]]:604800}export async function getSession(){if(!t.AUTH_ENABLED||!t.AUTH_SECRET)return null;let n=(await e()).get(r)?.value;return n?o(n,t.AUTH_SECRET):null}export async function setSession(o){let a=t.AUTH_SECRET,s=parseDuration("7d"),i=await n({...o,exp:Math.floor(Date.now()/1e3)+s},a);(await e()).set(r,i,{httpOnly:!0,secure:"production"===process.env.NODE_ENV,sameSite:"lax",path:"/",maxAge:s})}export async function clearSession(){(await e()).delete(r)}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{jsx as e,jsxs as o}from"react/jsx-runtime";import{DocsBody as t,DocsDescription as a,DocsPage as r,DocsTitle as i,EditOnGitHub as
|
|
2
|
+
import{jsx as e,jsxs as o}from"react/jsx-runtime";import{DocsBody as t,DocsDescription as a,DocsPage as r,DocsTitle as i,EditOnGitHub as l,PageLastUpdate as n,MarkdownCopyButton as c,ViewOptionsPopover as d}from"../../../components/fumadocs/layout/docs/page";import{DocsTOC as f}from"../../../components/fumadocs/layout/docs/page/docs-toc";import{Feedback as s,createGitHubFeedbackAction as b}from"../../feedback";import{localeConfig as m}from"../../../locale.config";export function DocsPageContent({toc:u,frontmatter:p,children:k,markdownUrl:h,github:g,path:U,lang:w,lastModified:x,neighbours:C,full:v}){let y=(m[w]??m.en).translations;return e(r,{asChild:!0,toc:u,full:v,tableOfContent:{enabled:!0,component:e(f,{toc:u,style:"clerk",translations:{toc:y.toc,aiChatTrigger:y.aiChatTrigger}})},tableOfContentPopover:{style:"clerk"},footer:{items:C},children:o("div",{children:[e(i,{children:p.title}),e(a,{children:p.description}),!v&&(h||g?.fileUrl)&&o("div",{className:"flex flex-row gap-2 items-center border-b -mt-4 pb-6",children:[h&&e(c,{markdownUrl:h}),h&&g?.fileUrl&&e(d,{markdownUrl:h,githubUrl:g.fileUrl}),g?.fileUrl&&e(l,{href:g.fileUrl})]}),e(t,{children:k}),!v&&x&&e(n,{date:new Date(x)}),!v&&g?.repo&&e(s,{onSendAction:b(p.title,g.repo),translations:{question:y.feedbackQuestion,feedbackLabel:y.feedbackLabel,good:y.feedbackGood,bad:y.feedbackBad,placeholder:y.feedbackPlaceholder,submit:y.feedbackSubmit,thankYou:y.feedbackThankYou,viewOnGitHub:y.feedbackViewOnGitHub,submitAgain:y.feedbackSubmitAgain}})]})})}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function e(e){if(!e)return null;let t=new Date(e.trim());return isNaN(t.getTime())?null:t}export async function fetchFeed(t,r){try{var n,l;let o=await fetch(t),u=await o.text(),i=new DOMParser().parseFromString(u,"text/xml");if(i.querySelector("parsererror"))return{status:"error",source:r,message:"Invalid XML"};return{status:"ok",items:(n=i,l=r,null!==n.querySelector("feed")?Array.from(n.querySelectorAll("entry")).map(t=>({title:t.querySelector("title")?.textContent?.trim()??"(no title)",url:t.querySelector("link[rel='alternate']")?.getAttribute("href")??t.querySelector("link")?.getAttribute("href")??"",date:e(t.querySelector("published")?.textContent??t.querySelector("updated")?.textContent),summary:t.querySelector("summary")?.textContent?.trim()??t.querySelector("content")?.textContent?.slice(0,200)?.trim()??"",source:l})):Array.from(n.querySelectorAll("item")).map(t=>({title:t.querySelector("title")?.textContent?.trim()??"(no title)",url:t.querySelector("link")?.textContent?.trim()??t.querySelector("guid")?.textContent?.trim()??"",date:e(t.querySelector("pubDate")?.textContent),summary:t.querySelector("description")?.textContent?.slice(0,200)?.trim()??"",source:l})))}}catch(t){let e=t instanceof TypeError?t.message:String(t);if(e.includes("Failed to fetch")||e.includes("NetworkError")||e.includes("CORS"))return{status:"cors",source:r};return{status:"error",source:r,message:e}}}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import{jsx as e,jsxs as r,Fragment as a}from"react/jsx-runtime";import{env as t}from"../../config";import{localeConfig as s,defaultLocale as l}from"../../locale.config";import{LogoLoader as n}from"../../components/logo-loader";import{useUpstreamFeeds as o}from"./use-upstream-feeds";import{ExternalLink as i,AlertTriangle as m}from"lucide-react";export function UpstreamPage({lang:c}){var d;let p=(d=c,s[d]?.translations??s[l].translations),{loading:u,results:x,items:f}=o(t.NEXT_PUBLIC_UPSTREAM_SOURCES),h=x.filter(e=>"ok"!==e.status);return r("div",{className:"container max-w-3xl py-12 px-4",children:[e("h1",{className:"text-2xl font-bold mb-8",children:p.upstream}),u&&e("div",{className:"flex justify-center py-24",children:e(n,{className:"size-12"})}),!u&&h.length>0&&e("div",{className:"mb-8 flex flex-col gap-3",children:h.map((a,t)=>r("div",{className:"flex gap-3 rounded-lg border border-amber-500/30 bg-amber-500/10 px-4 py-3 text-sm text-amber-700 dark:text-amber-400",children:[e(m,{className:"mt-0.5 size-4 shrink-0"}),r("div",{children:[e("span",{className:"font-medium",children:a.source})," — ","cors"===a.status?p.upstreamCorsHint:p.upstreamError]})]},t))}),!u&&0===f.length&&0===h.length&&e("p",{className:"text-muted-foreground",children:p.upstreamEmpty}),!u&&f.length>0&&e("div",{className:"flex flex-col divide-y divide-border",children:f.map((t,l)=>r("a",{href:t.url,target:"_blank",rel:"noopener noreferrer",className:"group flex flex-col gap-1 py-5 hover:bg-muted/40 -mx-4 px-4 rounded-lg transition-colors",children:[r("div",{className:"flex items-start justify-between gap-4",children:[e("span",{className:"font-medium group-hover:text-primary transition-colors line-clamp-2",children:t.title}),e(i,{className:"mt-1 size-3.5 shrink-0 opacity-40 group-hover:opacity-70 transition-opacity"})]}),t.summary&&e("p",{className:"text-sm text-muted-foreground line-clamp-2",children:t.summary}),r("div",{className:"flex gap-2 text-xs text-muted-foreground/70 mt-1",children:[e("span",{children:t.source}),t.date&&r(a,{children:[e("span",{children:"·"}),e("span",{children:t.date.toLocaleDateString(s[c]?.translations.dateLocale??"en-US",{year:"numeric",month:"short",day:"numeric"})})]})]})]},l))})]})}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import{useEffect as e,useState as t}from"react";import{fetchFeed as s}from"./rss-parser.js";export function useUpstreamFeeds(a){let[r,l]=t({loading:a.length>0,results:[],items:[]});return e(()=>{0!==a.length&&(l({loading:!0,results:[],items:[]}),Promise.allSettled(a.map(e=>s(e.url,e.label))).then(e=>{let t=e.map(e=>"fulfilled"===e.status?e.value:{status:"error",source:"unknown",message:String(e.reason)}),s=t.flatMap(e=>"ok"===e.status?e.items:[]).sort((e,t)=>e.date||t.date?e.date?t.date?t.date.getTime()-e.date.getTime():-1:1:0);l({loading:!1,results:t,items:s})}))},[a.map(e=>e.url).join(",")]),r}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readdir as t,readFile as e,stat as a}from"node:fs/promises";import{join as n,relative as i}from"node:path";import l from"gray-matter";import{locales as r}from"../locale.config";let m=new Set(["home"]);export async function discoverSections(e){let a;try{a=await t(e,{withFileTypes:!0})}catch{return[]}return a.filter(t=>t.isDirectory()&&!m.has(t.name)).map(t=>t.name)}let o=/^(\d+)-(.+)$/;function s(t){let e=t.match(o);return e?[parseInt(e[1],10),e[2]]:[1/0,t]}function f(t){return t.replace(o,"$2")}function c(t){return[...t].sort((t,e)=>{let[a,n]=s(t.name),[i,l]=s(e.name);return a!==i?a-i:n.localeCompare(l)})}function d(t){let e=t.endsWith(".mdx")?".mdx":t.endsWith(".md")?".md":"",a=e?t.slice(0,-e.length):t,n=a.lastIndexOf(".");if(n>=0){let t=a.slice(n+1);if(r.includes(t))return{base:a.slice(0,n),lang:t}}return{base:a,lang:null}}async function p(r,m,o){let s;try{s=await t(r,{withFileTypes:!0})}catch{return}let h=s.filter(t=>t.isFile()&&(t.name.endsWith(".mdx")||t.name.endsWith(".md"))),u=s.filter(t=>t.isDirectory()),y=i(m,r),g=h.filter(t=>"index"===d(t.name).base),w=c(h.filter(t=>"index"!==d(t.name).base));for(let t of g){let{lang:i}=d(t.name),m=n(r,t.name);try{let r=await e(m,"utf8"),s=await a(m),{data:f,content:c}=l(r),d=f.label??f.title??void 0,p={};d&&(p.title=d),f.icon&&(p.icon=f.icon);let h=i?`meta.${i}.json`:"meta.json",u=y?n(y,h):h;if(o.push({type:"meta",path:u,data:p}),c.trim().length>0){let e=y?n(y,t.name):t.name;o.push({type:"page",path:e,data:{...f,title:f.title??"Untitled",filePath:m,lastModified:s.mtime}})}}catch{}}let x=w.filter(t=>null===d(t.name).lang);if(x.length>0){let t=[...x.map(t=>f(d(t.name).base)),"..."],e=y?n(y,"meta.json"):"meta.json",a=o.find(t=>"meta"===t.type&&t.path===e);a&&"meta"===a.type?a.data={...a.data,pages:t}:o.push({type:"meta",path:e,data:{pages:t}})}for(let t of w){let{base:i,lang:m}=d(t.name),s=f(i),c=t.name.endsWith(".md")?".md":".mdx",p=m?`${s}.${m}${c}`:`${s}${c}`,h=y?n(y,p):p,u=n(r,t.name);try{let t=await e(u,"utf8"),n=await a(u),{data:i}=l(t);o.push({type:"page",path:h,data:{...i,title:i.title??"Untitled",filePath:u,lastModified:n.mtime}})}catch{}}for(let t of c(u))await p(n(r,t.name),m,o)}export async function createFsSource(t){let e=[];return await p(t,t,e),{files:e}}
|
|
1
|
+
import{readdir as t,readFile as e,stat as a}from"node:fs/promises";import{join as n,relative as i}from"node:path";import l from"gray-matter";import{locales as r}from"../locale.config";let m=new Set(["home","upstream"]);export async function discoverSections(e){let a;try{a=await t(e,{withFileTypes:!0})}catch{return[]}return a.filter(t=>t.isDirectory()&&!m.has(t.name)).map(t=>t.name)}let o=/^(\d+)-(.+)$/;function s(t){let e=t.match(o);return e?[parseInt(e[1],10),e[2]]:[1/0,t]}function f(t){return t.replace(o,"$2")}function c(t){return[...t].sort((t,e)=>{let[a,n]=s(t.name),[i,l]=s(e.name);return a!==i?a-i:n.localeCompare(l)})}function d(t){let e=t.endsWith(".mdx")?".mdx":t.endsWith(".md")?".md":"",a=e?t.slice(0,-e.length):t,n=a.lastIndexOf(".");if(n>=0){let t=a.slice(n+1);if(r.includes(t))return{base:a.slice(0,n),lang:t}}return{base:a,lang:null}}async function p(r,m,o){let s;try{s=await t(r,{withFileTypes:!0})}catch{return}let h=s.filter(t=>t.isFile()&&(t.name.endsWith(".mdx")||t.name.endsWith(".md"))),u=s.filter(t=>t.isDirectory()),y=i(m,r),g=h.filter(t=>"index"===d(t.name).base),w=c(h.filter(t=>"index"!==d(t.name).base));for(let t of g){let{lang:i}=d(t.name),m=n(r,t.name);try{let r=await e(m,"utf8"),s=await a(m),{data:f,content:c}=l(r),d=f.label??f.title??void 0,p={};d&&(p.title=d),f.icon&&(p.icon=f.icon);let h=i?`meta.${i}.json`:"meta.json",u=y?n(y,h):h;if(o.push({type:"meta",path:u,data:p}),c.trim().length>0){let e=y?n(y,t.name):t.name;o.push({type:"page",path:e,data:{...f,title:f.title??"Untitled",filePath:m,lastModified:s.mtime}})}}catch{}}let x=w.filter(t=>null===d(t.name).lang);if(x.length>0){let t=[...x.map(t=>f(d(t.name).base)),"..."],e=y?n(y,"meta.json"):"meta.json",a=o.find(t=>"meta"===t.type&&t.path===e);a&&"meta"===a.type?a.data={...a.data,pages:t}:o.push({type:"meta",path:e,data:{pages:t}})}for(let t of w){let{base:i,lang:m}=d(t.name),s=f(i),c=t.name.endsWith(".md")?".md":".mdx",p=m?`${s}.${m}${c}`:`${s}${c}`,h=y?n(y,p):p,u=n(r,t.name);try{let t=await e(u,"utf8"),n=await a(u),{data:i}=l(t);o.push({type:"page",path:h,data:{...i,title:i.title??"Untitled",filePath:u,lastModified:n.mtime}})}catch{}}for(let t of c(u))await p(n(r,t.name),m,o)}export async function createFsSource(t){let e=[];return await p(t,t,e),{files:e}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as o,jsxs as t,Fragment as n}from"react/jsx-runtime";import{CompactSearchToggle as e}from"../components/fumadocs/search-toggle";import{SidebarBackButton as r}from"../components/fumadocs/layout/sidebar-back-button";import{EditorButton as s}from"../components/fumadocs/layout/editor-button";import{Logo as a}from"../components/logo";import{env as i}from"../config";export const githubRepo=i.NEXT_PUBLIC_GITHUB_REPO;export function baseOptions(t="en"){return{nav:{title:o(a,{className:"h-5 w-auto"}),url:`/${t}`},githubUrl:githubRepo,i18n:void 0,searchToggle:{components:{lg:o(e,{})}}
|
|
1
|
+
import{jsx as o,jsxs as t,Fragment as n}from"react/jsx-runtime";import{CompactSearchToggle as e}from"../components/fumadocs/search-toggle";import{SidebarBackButton as r}from"../components/fumadocs/layout/sidebar-back-button";import{EditorButton as s}from"../components/fumadocs/layout/editor-button";import{Logo as a}from"../components/logo";import{env as i}from"../config";export const githubRepo=i.NEXT_PUBLIC_GITHUB_REPO;export function baseOptions(t="en"){return{nav:{title:o(a,{className:"h-5 w-auto"}),url:`/${t}`},githubUrl:githubRepo,i18n:void 0,searchToggle:{components:{lg:o(e,{})}}}}export function docsOptions(e="en"){let a=baseOptions(e);return{...a,nav:{...a.nav,children:t(n,{children:[o(r,{}),o(s,{lang:e})]})}}}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{loader as e}from"fumadocs-core/source";import{lucideIconsPlugin as t}from"fumadocs-core/source/lucide-icons";import{openapiPlugin as r}from"fumadocs-openapi/server";import{createSearchAPI as a}from"fumadocs-core/search/server";import{i18n as o}from"./i18n";import{join as n}from"node:path";import{existsSync as i,watch as s}from"node:fs";import{readFile as
|
|
1
|
+
import{loader as e}from"fumadocs-core/source";import{lucideIconsPlugin as t}from"fumadocs-core/source/lucide-icons";import{openapiPlugin as r}from"fumadocs-openapi/server";import{createSearchAPI as a}from"fumadocs-core/search/server";import{i18n as o}from"./i18n";import{join as n}from"node:path";import{existsSync as i,watch as s}from"node:fs";import{readFile as l}from"node:fs/promises";import c from"gray-matter";import{env as u}from"../config";import{createFsSource as m,discoverSections as f}from"./content-source.js";let p=[t(),r()];async function g(){let t=await f(u.CONTENT_DIR),r=Object.fromEntries(await Promise.all(t.map(async t=>{let r=e({source:await m(n(u.CONTENT_DIR,t)),baseUrl:`/${t}`,i18n:o,plugins:p});return[t,r]}))),i=a("simple",{indexes:await Promise.all(Object.entries(r).flatMap(([,e])=>e.getLanguages().flatMap(({language:e,pages:t})=>t.map(async t=>{let{content:r}=c(await l(t.data.filePath,"utf-8"));return{id:t.url,url:t.url,locale:e,title:t.data.title,content:r}}))))});return{sections:r,searchServer:i}}let d=null;export function getSources(){return d||(d=g(),"development"===process.env.NODE_ENV&&d.then(()=>{i(u.CONTENT_DIR)&&s(u.CONTENT_DIR,{recursive:!0},()=>{d=null})})),d}export async function getSections(){let{sections:e}=await getSources();return e}export async function getAllPages(){return Object.values(await getSections()).flatMap(e=>e.getPages())}export async function getUnifiedPageTree(e){let t=await getSections(),r=[];for(let a of Object.values(t)){let t=a.getPageTree(e);0!==t.children.length&&r.push({type:"folder",name:t.name,children:t.children})}return{name:"",children:r}}export async function getNavLinks(e){let t=Object.entries(await getSections()).map(([t,r])=>({text:r.getPageTree(e).name??t,url:`/${e}/${t}`,active:"nested-url"})),{env:r}=await import("../config");if(r.NEXT_PUBLIC_UPSTREAM_SOURCES.length>0){let{localeConfig:r,defaultLocale:a}=await import("../locale.config"),o=r[e]?.translations??r[a].translations;t.push({text:o.upstream,url:`/${e}/upstream`,active:"nested-url"})}return t}export async function getLLMText(e){let{content:t}=c(await l(e.data.filePath,"utf-8"));return`# ${e.data.title}
|
|
2
2
|
|
|
3
3
|
${t}`}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{env as e}from"./config";let a=e.NEXT_PUBLIC_SITE_NAME;export const localeConfig={en:{displayName:"English",dir:"ltr",siteName:a,siteDescription:"A docs starter built with Fumadocs, TanStack Start, and Thmanyah fonts — i18n, RTL, local search, and more.",translations:{search:"Search documentation...",searchNoResult:"No results found",toc:"On this page",tocNoHeadings:"No headings found",lastUpdate:"Last updated",chooseLanguage:"Choose language",nextPage:"Next",previousPage:"Previous",chooseTheme:"Theme",editOnGithub:"Edit on GitHub",copyMarkdown:"Copy Markdown",copyCode:"Copy",copied:"Copied",openMenu:"Open",openInGithub:"Open in GitHub",viewAsMarkdown:"View as Markdown",openInScira:"Open in Scira AI",openInChatGPT:"Open in ChatGPT",openInClaude:"Open in Claude",openInCursor:"Open in Cursor",toggleTheme:"Toggle theme",themeLight:"Light",themeDark:"Dark",themeSystem:"System",openSearch:"Open search",openSidebar:"Open sidebar",collapseSidebar:"Collapse sidebar",switchLanguage:"Switch language",toggleMenu:"Toggle menu",notFoundTitle:"Page not found",notFoundDescription:"The page you're looking for doesn't exist or has been moved.",notFoundBack:"Back to home",feedbackQuestion:"How is this page?",feedbackLabel:"Feedback",feedbackGood:"Good",feedbackBad:"Bad",feedbackPlaceholder:"Leave your feedback...",feedbackSubmit:"Submit",feedbackThankYou:"Thank you for your feedback!",feedbackViewOnGitHub:"View on GitHub",feedbackSubmitAgain:"Submit Again",changelog:"Changelog",changelogTitle:"What's new?",changelogDescription:"Latest updates and changes to this project.",changelogReadMore:"Read more →",docs:"Docs",dateLocale:"en-US",aiChat:"AI Chat",aiChatDisclaimer:"AI can be inaccurate, please verify the answers.",aiChatPlaceholder:"Ask a question",aiChatAnswering:"AI is answering...",aiChatAbort:"Abort Answer",aiChatRetry:"Retry",aiChatClear:"Clear Chat",aiChatEmpty:"Start a new chat below.",aiChatTrigger:"Ask AI",aiChatRoleUser:"you",aiChatRoleAssistant:"assistant",aiChatCopy:"Copy",aiChatCopied:"Copied!",aiChatSources:"Sources",aiChatSearching:"Searching…",aiChatStarters:["What features does this docs starter include?","How does search work?","How do I add a new language?"],aiChatApiKeyTitle:"Enter your Anthropic API key",aiChatApiKeyDescription:"Your key is stored in your browser and never sent to our servers.",aiChatApiKeyPlaceholder:"sk-ant-...",aiChatApiKeySave:"Start chatting",aiChatApiKeyChange:"Change API key",aiChatModelLabel:"Model",aiChatThinking:"Thinking",aiChatPages:"Pages",aiChatBrowsingPages:"Browsing pages…",aiChatSearchFailed:"Search failed",aiChatPageLoadFailed:"Failed to load page"}},ar:{displayName:"العربية",dir:"rtl",siteName:a,siteDescription:"قالب توثيق مبني بـ Fumadocs وTanStack Start وخطوط ثمانية — مع دعم i18n والعربية والبحث المحلي.",translations:{search:"ابحث في التوثيق...",searchNoResult:"لا توجد نتائج",toc:"في هذه الصفحة",tocNoHeadings:"لا توجد عناوين",lastUpdate:"آخر تحديث",chooseLanguage:"اختر اللغة",nextPage:"التالي",previousPage:"السابق",chooseTheme:"المظهر",editOnGithub:"عدّل على GitHub",copyMarkdown:"نسخ Markdown",copyCode:"نسخ",copied:"تم النسخ",openMenu:"فتح",openInGithub:"فتح في GitHub",viewAsMarkdown:"عرض كـ Markdown",openInScira:"فتح في Scira AI",openInChatGPT:"فتح في ChatGPT",openInClaude:"فتح في Claude",openInCursor:"فتح في Cursor",toggleTheme:"تبديل المظهر",themeLight:"فاتح",themeDark:"داكن",themeSystem:"النظام",openSearch:"فتح البحث",openSidebar:"فتح الشريط الجانبي",collapseSidebar:"طي الشريط الجانبي",switchLanguage:"تغيير اللغة",toggleMenu:"فتح القائمة",notFoundTitle:"الصفحة غير موجودة",notFoundDescription:"الصفحة التي تبحث عنها غير موجودة أو تم نقلها.",notFoundBack:"العودة إلى الرئيسية",feedbackQuestion:"ما رأيك في هذه الصفحة؟",feedbackLabel:"ملاحظة",feedbackGood:"جيدة",feedbackBad:"تحتاج تحسين",feedbackPlaceholder:"اكتب ملاحظاتك...",feedbackSubmit:"إرسال",feedbackThankYou:"شكراً على ملاحظاتك!",feedbackViewOnGitHub:"عرض على GitHub",feedbackSubmitAgain:"إرسال مجدداً",changelog:"سجل التغييرات",changelogTitle:"ما الجديد؟",changelogDescription:"أحدث التحديثات والتغييرات في هذا المشروع.",changelogReadMore:"قراءة التفاصيل ←",docs:"التوثيق",dateLocale:"ar-SA",aiChat:"محادثة الذكاء الاصطناعي",aiChatDisclaimer:"قد يكون الذكاء الاصطناعي غير دقيق، يرجى التحقق من الإجابات.",aiChatPlaceholder:"اطرح سؤالاً",aiChatAnswering:"الذكاء الاصطناعي يجيب...",aiChatAbort:"إيقاف الإجابة",aiChatRetry:"إعادة المحاولة",aiChatClear:"مسح المحادثة",aiChatEmpty:"ابدأ محادثة جديدة أدناه.",aiChatTrigger:"إسأل الذكالي",aiChatRoleUser:"أنت",aiChatRoleAssistant:"المساعد",aiChatCopy:"نسخ",aiChatCopied:"تم النسخ!",aiChatSources:"المصادر",aiChatSearching:"جارٍ البحث...",aiChatStarters:["ما المميزات التي يتضمنها هذا القالب؟","كيف يعمل البحث؟","كيف أضيف لغة جديدة؟"],aiChatApiKeyTitle:"أدخل مفتاح Anthropic API",aiChatApiKeyDescription:"يُحفظ مفتاحك في متصفحك ولا يُرسل إلى خوادمنا.",aiChatApiKeyPlaceholder:"sk-ant-...",aiChatApiKeySave:"ابدأ المحادثة",aiChatApiKeyChange:"تغيير مفتاح API",aiChatModelLabel:"النموذج",aiChatThinking:"التفكير",aiChatPages:"الصفحات",aiChatBrowsingPages:"جارٍ تصفح الصفحات…",aiChatSearchFailed:"فشل البحث",aiChatPageLoadFailed:"تعذّر تحميل الصفحة"}}};export const defaultLocale="en";export const locales=Object.keys(localeConfig);
|
|
1
|
+
import{env as e}from"./config";let a=e.NEXT_PUBLIC_SITE_NAME;export const localeConfig={en:{displayName:"English",dir:"ltr",siteName:a,siteDescription:"A docs starter built with Fumadocs, TanStack Start, and Thmanyah fonts — i18n, RTL, local search, and more.",translations:{search:"Search documentation...",searchNoResult:"No results found",toc:"On this page",tocNoHeadings:"No headings found",lastUpdate:"Last updated",chooseLanguage:"Choose language",nextPage:"Next",previousPage:"Previous",chooseTheme:"Theme",editOnGithub:"Edit on GitHub",copyMarkdown:"Copy Markdown",copyCode:"Copy",copied:"Copied",openMenu:"Open",openInGithub:"Open in GitHub",viewAsMarkdown:"View as Markdown",openInScira:"Open in Scira AI",openInChatGPT:"Open in ChatGPT",openInClaude:"Open in Claude",openInCursor:"Open in Cursor",toggleTheme:"Toggle theme",themeLight:"Light",themeDark:"Dark",themeSystem:"System",openSearch:"Open search",openSidebar:"Open sidebar",collapseSidebar:"Collapse sidebar",switchLanguage:"Switch language",toggleMenu:"Toggle menu",notFoundTitle:"Page not found",notFoundDescription:"The page you're looking for doesn't exist or has been moved.",notFoundBack:"Back to home",feedbackQuestion:"How is this page?",feedbackLabel:"Feedback",feedbackGood:"Good",feedbackBad:"Bad",feedbackPlaceholder:"Leave your feedback...",feedbackSubmit:"Submit",feedbackThankYou:"Thank you for your feedback!",feedbackViewOnGitHub:"View on GitHub",feedbackSubmitAgain:"Submit Again",changelog:"Changelog",changelogTitle:"What's new?",changelogDescription:"Latest updates and changes to this project.",changelogReadMore:"Read more →",docs:"Docs",dateLocale:"en-US",aiChat:"AI Chat",aiChatDisclaimer:"AI can be inaccurate, please verify the answers.",aiChatPlaceholder:"Ask a question",aiChatAnswering:"AI is answering...",aiChatAbort:"Abort Answer",aiChatRetry:"Retry",aiChatClear:"Clear Chat",aiChatEmpty:"Start a new chat below.",aiChatTrigger:"Ask AI",aiChatRoleUser:"you",aiChatRoleAssistant:"assistant",aiChatCopy:"Copy",aiChatCopied:"Copied!",aiChatSources:"Sources",aiChatSearching:"Searching…",aiChatStarters:["What features does this docs starter include?","How does search work?","How do I add a new language?"],aiChatApiKeyTitle:"Enter your Anthropic API key",aiChatApiKeyDescription:"Your key is stored in your browser and never sent to our servers.",aiChatApiKeyPlaceholder:"sk-ant-...",aiChatApiKeySave:"Start chatting",aiChatApiKeyChange:"Change API key",aiChatModelLabel:"Model",aiChatThinking:"Thinking",aiChatPages:"Pages",aiChatBrowsingPages:"Browsing pages…",aiChatSearchFailed:"Search failed",aiChatPageLoadFailed:"Failed to load page",upstream:"Upstream",upstreamEmpty:"No items found.",upstreamCorsHint:'This feed couldn\'t be loaded due to CORS restrictions. Try a browser extension like "CORS Unblock" to enable cross-origin requests.',upstreamError:"Failed to load"}},ar:{displayName:"العربية",dir:"rtl",siteName:a,siteDescription:"قالب توثيق مبني بـ Fumadocs وTanStack Start وخطوط ثمانية — مع دعم i18n والعربية والبحث المحلي.",translations:{search:"ابحث في التوثيق...",searchNoResult:"لا توجد نتائج",toc:"في هذه الصفحة",tocNoHeadings:"لا توجد عناوين",lastUpdate:"آخر تحديث",chooseLanguage:"اختر اللغة",nextPage:"التالي",previousPage:"السابق",chooseTheme:"المظهر",editOnGithub:"عدّل على GitHub",copyMarkdown:"نسخ Markdown",copyCode:"نسخ",copied:"تم النسخ",openMenu:"فتح",openInGithub:"فتح في GitHub",viewAsMarkdown:"عرض كـ Markdown",openInScira:"فتح في Scira AI",openInChatGPT:"فتح في ChatGPT",openInClaude:"فتح في Claude",openInCursor:"فتح في Cursor",toggleTheme:"تبديل المظهر",themeLight:"فاتح",themeDark:"داكن",themeSystem:"النظام",openSearch:"فتح البحث",openSidebar:"فتح الشريط الجانبي",collapseSidebar:"طي الشريط الجانبي",switchLanguage:"تغيير اللغة",toggleMenu:"فتح القائمة",notFoundTitle:"الصفحة غير موجودة",notFoundDescription:"الصفحة التي تبحث عنها غير موجودة أو تم نقلها.",notFoundBack:"العودة إلى الرئيسية",feedbackQuestion:"ما رأيك في هذه الصفحة؟",feedbackLabel:"ملاحظة",feedbackGood:"جيدة",feedbackBad:"تحتاج تحسين",feedbackPlaceholder:"اكتب ملاحظاتك...",feedbackSubmit:"إرسال",feedbackThankYou:"شكراً على ملاحظاتك!",feedbackViewOnGitHub:"عرض على GitHub",feedbackSubmitAgain:"إرسال مجدداً",changelog:"سجل التغييرات",changelogTitle:"ما الجديد؟",changelogDescription:"أحدث التحديثات والتغييرات في هذا المشروع.",changelogReadMore:"قراءة التفاصيل ←",docs:"التوثيق",dateLocale:"ar-SA",aiChat:"محادثة الذكاء الاصطناعي",aiChatDisclaimer:"قد يكون الذكاء الاصطناعي غير دقيق، يرجى التحقق من الإجابات.",aiChatPlaceholder:"اطرح سؤالاً",aiChatAnswering:"الذكاء الاصطناعي يجيب...",aiChatAbort:"إيقاف الإجابة",aiChatRetry:"إعادة المحاولة",aiChatClear:"مسح المحادثة",aiChatEmpty:"ابدأ محادثة جديدة أدناه.",aiChatTrigger:"إسأل الذكالي",aiChatRoleUser:"أنت",aiChatRoleAssistant:"المساعد",aiChatCopy:"نسخ",aiChatCopied:"تم النسخ!",aiChatSources:"المصادر",aiChatSearching:"جارٍ البحث...",aiChatStarters:["ما المميزات التي يتضمنها هذا القالب؟","كيف يعمل البحث؟","كيف أضيف لغة جديدة؟"],aiChatApiKeyTitle:"أدخل مفتاح Anthropic API",aiChatApiKeyDescription:"يُحفظ مفتاحك في متصفحك ولا يُرسل إلى خوادمنا.",aiChatApiKeyPlaceholder:"sk-ant-...",aiChatApiKeySave:"ابدأ المحادثة",aiChatApiKeyChange:"تغيير مفتاح API",aiChatModelLabel:"النموذج",aiChatThinking:"التفكير",aiChatPages:"الصفحات",aiChatBrowsingPages:"جارٍ تصفح الصفحات…",aiChatSearchFailed:"فشل البحث",aiChatPageLoadFailed:"تعذّر تحميل الصفحة",upstream:"المصادر",upstreamEmpty:"لا توجد عناصر.",upstreamCorsHint:'تعذّر تحميل هذا المصدر بسبب قيود CORS. جرّب إضافة متصفح مثل "CORS Unblock" لتفعيل الطلبات عبر النطاقات.',upstreamError:"فشل التحميل"}}};export const defaultLocale="en";export const locales=Object.keys(localeConfig);
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import{jsx as i}from"react/jsx-runtime";import{createElement as t}from"react";import{AnimatePresence as e,motion as r}from"motion/react";import{usePathname as a}from"next/navigation";import{locales as o}from"../locale.config";import{env as n}from"../config";let m=RegExp(`^/(${o.join("|")})(/|$)`),l={duration:.3,ease:"easeOut"},p={initial:{filter:"blur(8px)",opacity:.2},animate:{filter:"blur(0px)",opacity:1},exit:{filter:"blur(8px)",opacity:.2}};export function Transition({animationKey:o,children:c,...f}){let x=a(),s=o??(x.replace(m,"/")||"/");return n.NEXT_PUBLIC_ANIMATIONS?i(e,{mode:"wait",children:t(r.div,{...f,key:s,variants:p,initial:"initial",animate:"animate",exit:"exit",transition:l},c)}):i("div",{...f,children:c})}
|