@junejs/server 1.0.0-dev.19 → 1.0.0-dev.20
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/adapter-DcZ-W1-7.d.ts +62 -0
- package/dist/adapter.d.ts +1 -61
- package/dist/build.d.ts +5 -26
- package/dist/build.js +10 -276
- package/dist/config-freeze-DwI-Rmvq.d.ts +17 -0
- package/dist/config-freeze.d.ts +2 -0
- package/dist/config-freeze.js +51 -0
- package/dist/connection-auth.d.ts +39 -0
- package/dist/connection-auth.js +31 -0
- package/dist/content-freeze-CyiW2fRK.d.ts +4 -0
- package/dist/content-freeze.d.ts +2 -0
- package/dist/content-freeze.js +83 -0
- package/dist/index.d.ts +9 -4
- package/dist/index.js +7 -2
- package/dist/manifest-gcNWqWoI.d.ts +11 -0
- package/dist/manifest.d.ts +2 -0
- package/dist/manifest.js +111 -0
- package/dist/route-scan-DMlwoESy.d.ts +13 -0
- package/dist/route-scan.d.ts +2 -0
- package/dist/route-scan.js +55 -0
- package/dist/worker-BkFHGtxp.d.ts +61 -0
- package/dist/worker.d.ts +1 -60
- package/package.json +2 -2
- package/src/agent-discover.ts +8 -5
- package/src/build.ts +26 -440
- package/src/config-freeze.ts +104 -0
- package/src/connection-auth.ts +101 -0
- package/src/content-freeze.ts +151 -0
- package/src/index.ts +14 -0
- package/src/manifest.ts +128 -0
- package/src/route-scan.ts +84 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { JuneConfig } from "@junejs/core/config";
|
|
2
|
+
//#region src/adapter.d.ts
|
|
3
|
+
type AdapterCapabilities = {
|
|
4
|
+
runtime: "edge" | "node" | "serverless" | "native" | "static";
|
|
5
|
+
persistentConnections: boolean;
|
|
6
|
+
assets: "platform" | "server" | "none";
|
|
7
|
+
durableObjects?: boolean;
|
|
8
|
+
};
|
|
9
|
+
type AdapterEntry = {
|
|
10
|
+
imports: string[];
|
|
11
|
+
wrap(pipelineVar: string): string;
|
|
12
|
+
};
|
|
13
|
+
type ResourcePlan = {
|
|
14
|
+
db?: {
|
|
15
|
+
binding: string;
|
|
16
|
+
databaseName: string;
|
|
17
|
+
};
|
|
18
|
+
agent?: {
|
|
19
|
+
binding: string;
|
|
20
|
+
className: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
type AdapterEmitContext = {
|
|
24
|
+
appRoot: string;
|
|
25
|
+
outDir: string;
|
|
26
|
+
hasAssets: boolean;
|
|
27
|
+
linkHeader: string | null;
|
|
28
|
+
config: JuneConfig;
|
|
29
|
+
plan: ResourcePlan;
|
|
30
|
+
defaultName: string;
|
|
31
|
+
publicFiles?: string[];
|
|
32
|
+
};
|
|
33
|
+
interface JuneAdapter {
|
|
34
|
+
readonly name: string;
|
|
35
|
+
readonly capabilities: AdapterCapabilities;
|
|
36
|
+
readonly conditions: string[];
|
|
37
|
+
readonly buildExternal?: string[];
|
|
38
|
+
validate?(ctx: {
|
|
39
|
+
plan: ResourcePlan;
|
|
40
|
+
config: JuneConfig;
|
|
41
|
+
}): void;
|
|
42
|
+
entry(opts: {
|
|
43
|
+
linkHeader: string | null;
|
|
44
|
+
}): AdapterEntry;
|
|
45
|
+
emit(ctx: AdapterEmitContext): Promise<void>;
|
|
46
|
+
}
|
|
47
|
+
declare function hasDurableBinding(text: string, file: string, binding: string, className: string): boolean;
|
|
48
|
+
declare function workers(opts?: {
|
|
49
|
+
name?: string;
|
|
50
|
+
domain?: string;
|
|
51
|
+
}): JuneAdapter;
|
|
52
|
+
declare function vercel(opts?: {
|
|
53
|
+
runtime?: "node" | "edge";
|
|
54
|
+
regions?: string[];
|
|
55
|
+
}): JuneAdapter;
|
|
56
|
+
declare function deno(opts?: {
|
|
57
|
+
org?: string;
|
|
58
|
+
app?: string;
|
|
59
|
+
}): JuneAdapter;
|
|
60
|
+
declare function staticSite(): JuneAdapter;
|
|
61
|
+
//#endregion
|
|
62
|
+
export { ResourcePlan as a, staticSite as c, JuneAdapter as i, vercel as l, AdapterEmitContext as n, deno as o, AdapterEntry as r, hasDurableBinding as s, AdapterCapabilities as t, workers as u };
|
package/dist/adapter.d.ts
CHANGED
|
@@ -1,62 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
//#region src/adapter.d.ts
|
|
3
|
-
type AdapterCapabilities = {
|
|
4
|
-
runtime: "edge" | "node" | "serverless" | "native" | "static";
|
|
5
|
-
persistentConnections: boolean;
|
|
6
|
-
assets: "platform" | "server" | "none";
|
|
7
|
-
durableObjects?: boolean;
|
|
8
|
-
};
|
|
9
|
-
type AdapterEntry = {
|
|
10
|
-
imports: string[];
|
|
11
|
-
wrap(pipelineVar: string): string;
|
|
12
|
-
};
|
|
13
|
-
type ResourcePlan = {
|
|
14
|
-
db?: {
|
|
15
|
-
binding: string;
|
|
16
|
-
databaseName: string;
|
|
17
|
-
};
|
|
18
|
-
agent?: {
|
|
19
|
-
binding: string;
|
|
20
|
-
className: string;
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
type AdapterEmitContext = {
|
|
24
|
-
appRoot: string;
|
|
25
|
-
outDir: string;
|
|
26
|
-
hasAssets: boolean;
|
|
27
|
-
linkHeader: string | null;
|
|
28
|
-
config: JuneConfig;
|
|
29
|
-
plan: ResourcePlan;
|
|
30
|
-
defaultName: string;
|
|
31
|
-
publicFiles?: string[];
|
|
32
|
-
};
|
|
33
|
-
interface JuneAdapter {
|
|
34
|
-
readonly name: string;
|
|
35
|
-
readonly capabilities: AdapterCapabilities;
|
|
36
|
-
readonly conditions: string[];
|
|
37
|
-
readonly buildExternal?: string[];
|
|
38
|
-
validate?(ctx: {
|
|
39
|
-
plan: ResourcePlan;
|
|
40
|
-
config: JuneConfig;
|
|
41
|
-
}): void;
|
|
42
|
-
entry(opts: {
|
|
43
|
-
linkHeader: string | null;
|
|
44
|
-
}): AdapterEntry;
|
|
45
|
-
emit(ctx: AdapterEmitContext): Promise<void>;
|
|
46
|
-
}
|
|
47
|
-
declare function hasDurableBinding(text: string, file: string, binding: string, className: string): boolean;
|
|
48
|
-
declare function workers(opts?: {
|
|
49
|
-
name?: string;
|
|
50
|
-
domain?: string;
|
|
51
|
-
}): JuneAdapter;
|
|
52
|
-
declare function vercel(opts?: {
|
|
53
|
-
runtime?: "node" | "edge";
|
|
54
|
-
regions?: string[];
|
|
55
|
-
}): JuneAdapter;
|
|
56
|
-
declare function deno(opts?: {
|
|
57
|
-
org?: string;
|
|
58
|
-
app?: string;
|
|
59
|
-
}): JuneAdapter;
|
|
60
|
-
declare function staticSite(): JuneAdapter;
|
|
61
|
-
//#endregion
|
|
1
|
+
import { a as ResourcePlan, c as staticSite, i as JuneAdapter, l as vercel, n as AdapterEmitContext, o as deno, r as AdapterEntry, s as hasDurableBinding, t as AdapterCapabilities, u as workers } from "./adapter-DcZ-W1-7.js";
|
|
62
2
|
export { AdapterCapabilities, AdapterEmitContext, AdapterEntry, JuneAdapter, ResourcePlan, deno, hasDurableBinding, staticSite, vercel, workers };
|
package/dist/build.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { n as scanAppRoutes, r as scanRoutes, t as RouteEntry } from "./route-scan-DMlwoESy.js";
|
|
2
|
+
import { t as generateContent } from "./content-freeze-CyiW2fRK.js";
|
|
3
|
+
import { i as workerName, n as normalizeBase, r as resolveDeployAdapter, t as freezeConfig } from "./config-freeze-DwI-Rmvq.js";
|
|
4
|
+
import { n as buildManifest } from "./manifest-gcNWqWoI.js";
|
|
5
5
|
//#region src/build.d.ts
|
|
6
6
|
type BuildResult = {
|
|
7
7
|
outFile: string;
|
|
@@ -10,31 +10,10 @@ type BuildResult = {
|
|
|
10
10
|
contentCollections: string[];
|
|
11
11
|
prerendered: string[];
|
|
12
12
|
};
|
|
13
|
-
type RouteEntry = {
|
|
14
|
-
path: string;
|
|
15
|
-
file: string;
|
|
16
|
-
dynamic: boolean;
|
|
17
|
-
resource?: boolean;
|
|
18
|
-
layouts: string[];
|
|
19
|
-
loading?: string;
|
|
20
|
-
};
|
|
21
13
|
declare const isBunSpecifier: (id: string) => boolean;
|
|
22
|
-
declare function resolveDeployAdapter(deploy: JuneConfig["deploy"]): JuneAdapter;
|
|
23
|
-
declare function scanRoutes(appDir: string, dir?: string, layouts?: string[], out?: RouteEntry[], loading?: string): Promise<RouteEntry[]>;
|
|
24
|
-
declare function generateContent(appRoot: string): Promise<string[]>;
|
|
25
|
-
declare function freezeConfig(appRoot: string): Promise<{
|
|
26
|
-
document: DocumentConfig;
|
|
27
|
-
agent: WorkerManifest["agent"];
|
|
28
|
-
i18n: WorkerManifest["i18n"];
|
|
29
|
-
earlyHints: string[];
|
|
30
|
-
buildExternal: string[];
|
|
31
|
-
}>;
|
|
32
|
-
declare function normalizeBase(base?: string): string;
|
|
33
|
-
declare function workerName(raw: string): string;
|
|
34
|
-
declare function buildManifest(appRoot: string): Promise<WorkerManifest>;
|
|
35
14
|
declare function juneBuild(appRoot: string, options?: {
|
|
36
15
|
outDir?: string;
|
|
37
16
|
external?: string[];
|
|
38
17
|
}): Promise<BuildResult>;
|
|
39
18
|
//#endregion
|
|
40
|
-
export { BuildResult, buildManifest, freezeConfig, generateContent, isBunSpecifier, juneBuild, normalizeBase, resolveDeployAdapter, scanRoutes, workerName };
|
|
19
|
+
export { BuildResult, type RouteEntry, buildManifest, freezeConfig, generateContent, isBunSpecifier, juneBuild, normalizeBase, resolveDeployAdapter, scanAppRoutes, scanRoutes, workerName };
|
package/dist/build.js
CHANGED
|
@@ -1,289 +1,27 @@
|
|
|
1
1
|
import { jsxTransform } from "./tsconfig-jsx.js";
|
|
2
|
-
import { deno, staticSite, vercel, workers } from "./adapter.js";
|
|
3
2
|
import { generateAgentModule } from "./agent-compile.js";
|
|
4
3
|
import { findMiddlewareFile } from "./router.js";
|
|
5
4
|
import { resolveBoundary } from "./segment.js";
|
|
6
5
|
import { buildModuleCss, registerCssModules, rolldownCssModulesPlugin } from "./css-modules.js";
|
|
7
|
-
import {
|
|
6
|
+
import { bundleClientToFile, findClientEntry } from "./client-bundle.js";
|
|
8
7
|
import { generateIslandRegistry } from "./island-registry.js";
|
|
9
|
-
import {
|
|
8
|
+
import { cssTargets, minifyCss, processCss } from "./css.js";
|
|
10
9
|
import { RESERVED_PREFIX } from "./static-files.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
10
|
+
import { loadJuneConfig } from "./config-loader.js";
|
|
11
|
+
import { freezeConfig, normalizeBase, resolveDeployAdapter, workerName } from "./config-freeze.js";
|
|
12
|
+
import { generateContent } from "./content-freeze.js";
|
|
13
13
|
import { createWorker } from "./worker.js";
|
|
14
|
+
import { scanAppRoutes, scanRoutes } from "./route-scan.js";
|
|
15
|
+
import { buildManifest, importLayout } from "./manifest.js";
|
|
14
16
|
import { buildRsc, findRscRoutes } from "./rsc-build.js";
|
|
15
17
|
import { existsSync, lstatSync } from "node:fs";
|
|
16
|
-
import { copyFile, mkdir,
|
|
18
|
+
import { copyFile, mkdir, readdir, rm, writeFile } from "node:fs/promises";
|
|
17
19
|
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
18
|
-
import { pathToFileURL } from "node:url";
|
|
19
|
-
import { routeFromModule } from "@junejs/core/route";
|
|
20
|
-
import { resolveAgent, resolveClientRouter, resolveSpeculationRules } from "@junejs/core/config";
|
|
21
20
|
import { buildLinkHeader } from "@junejs/core/discovery";
|
|
22
21
|
import { localeHref } from "@junejs/core/i18n";
|
|
23
22
|
import { createHash } from "node:crypto";
|
|
24
|
-
import { execFileSync } from "node:child_process";
|
|
25
23
|
//#region src/build.ts
|
|
26
|
-
const PAGE_BASENAMES = /* @__PURE__ */ new Set(["page", "index"]);
|
|
27
|
-
const ROUTE_EXTS = [
|
|
28
|
-
".tsx",
|
|
29
|
-
".jsx",
|
|
30
|
-
".ts",
|
|
31
|
-
".js"
|
|
32
|
-
];
|
|
33
|
-
const isRouteGroup = (name) => /^\(.+\)$/.test(name);
|
|
34
24
|
const isBunSpecifier = (id) => id === "bun" || id.startsWith("bun:");
|
|
35
|
-
function resolveDeployAdapter(deploy) {
|
|
36
|
-
if (deploy?.adapter) return deploy.adapter;
|
|
37
|
-
switch (deploy?.target) {
|
|
38
|
-
case "static": return staticSite();
|
|
39
|
-
case "vercel": return vercel();
|
|
40
|
-
case "deno": return deno();
|
|
41
|
-
default: return workers({
|
|
42
|
-
name: deploy?.name,
|
|
43
|
-
domain: deploy?.domain
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
function segmentFile(dir, base) {
|
|
48
|
-
return ROUTE_EXTS.map((e) => join(dir, `${base}${e}`)).find(existsSync);
|
|
49
|
-
}
|
|
50
|
-
async function scanRoutes(appDir, dir = appDir, layouts = [], out = [], loading) {
|
|
51
|
-
const ownLayout = segmentFile(dir, "layout");
|
|
52
|
-
const chain = ownLayout ? [...layouts, ownLayout] : layouts;
|
|
53
|
-
const nearestLoading = segmentFile(dir, "loading") ?? loading;
|
|
54
|
-
const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
55
|
-
for (const e of entries) {
|
|
56
|
-
if (e.name.startsWith("_") || e.name.startsWith(".")) continue;
|
|
57
|
-
const full = join(dir, e.name);
|
|
58
|
-
if (e.isDirectory()) {
|
|
59
|
-
await scanRoutes(appDir, full, chain, out, nearestLoading);
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
const ext = e.name.match(/\.[^.]+$/)?.[0] ?? "";
|
|
63
|
-
if (!ROUTE_EXTS.includes(ext)) continue;
|
|
64
|
-
const base = basename(e.name, ext);
|
|
65
|
-
const resource = base === "route";
|
|
66
|
-
if (!PAGE_BASENAMES.has(base) && !resource) continue;
|
|
67
|
-
const relDir = relative(appDir, dir);
|
|
68
|
-
const path = "/" + (relDir === "" ? [] : relDir.split(sep).filter((s) => !isRouteGroup(s))).join("/");
|
|
69
|
-
out.push({
|
|
70
|
-
path: path === "/" ? "/" : path,
|
|
71
|
-
file: full,
|
|
72
|
-
dynamic: /\[.+\]/.test(path),
|
|
73
|
-
resource,
|
|
74
|
-
layouts: chain,
|
|
75
|
-
loading: nearestLoading
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
return out;
|
|
79
|
-
}
|
|
80
|
-
async function generateContent(appRoot) {
|
|
81
|
-
const contentDir = join(appRoot, "content");
|
|
82
|
-
await mkdir(join(appRoot, "app"), { recursive: true });
|
|
83
|
-
const emit = async (sources, knownLocales) => {
|
|
84
|
-
const { code, names } = generateContentModule(contentDir, knownLocales, sources);
|
|
85
|
-
await writeFile(join(appRoot, "app", "_content.ts"), code);
|
|
86
|
-
return names;
|
|
87
|
-
};
|
|
88
|
-
const resolveSources = (sources) => sources.map((s) => ({
|
|
89
|
-
...s,
|
|
90
|
-
dir: resolve(appRoot, s.dir)
|
|
91
|
-
}));
|
|
92
|
-
const declaredLocales = (config) => config.i18n ? [.../* @__PURE__ */ new Set([config.i18n.defaultLocale, ...Object.keys(config.i18n.locales)])] : [];
|
|
93
|
-
let config = null;
|
|
94
|
-
try {
|
|
95
|
-
config = await loadJuneConfig(appRoot);
|
|
96
|
-
} catch {}
|
|
97
|
-
if (config) return emit(resolveSources(config.content?.sources ?? []), declaredLocales(config));
|
|
98
|
-
const names = await emit([], void 0);
|
|
99
|
-
await seedContentImports(appRoot);
|
|
100
|
-
const probed = probeConfigFresh(appRoot);
|
|
101
|
-
if (probed === null) {
|
|
102
|
-
console.warn("[june gen] june.config.ts failed to load — content.sources/i18n locales (if any) not applied");
|
|
103
|
-
return names;
|
|
104
|
-
}
|
|
105
|
-
return emit(resolveSources(probed.sources), probed.locales);
|
|
106
|
-
}
|
|
107
|
-
async function seedContentImports(appRoot) {
|
|
108
|
-
const cfgPath = findJuneConfigPath(appRoot);
|
|
109
|
-
if (!cfgPath) return;
|
|
110
|
-
const contentFile = join(appRoot, "app", "_content.ts");
|
|
111
|
-
const current = existsSync(contentFile) ? await readFile(contentFile, "utf8") : "";
|
|
112
|
-
const cfgSrc = await readFile(cfgPath, "utf8");
|
|
113
|
-
const isIdent = (s) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(s);
|
|
114
|
-
const seen = /* @__PURE__ */ new Set();
|
|
115
|
-
const stubs = [];
|
|
116
|
-
for (const m of cfgSrc.matchAll(/import\s*(?:type\s+)?\{([^}]*)\}\s*from\s*["'][^"']*app\/_content(?:\.\w+)?["']/g)) {
|
|
117
|
-
const inner = (m[1] ?? "").replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/[^\n]*/g, "");
|
|
118
|
-
for (const part of inner.split(",")) {
|
|
119
|
-
const name = part.replace(/\btype\b/g, "").split(/\s+as\s+/).pop()?.trim();
|
|
120
|
-
if (!name || !isIdent(name) || seen.has(name)) continue;
|
|
121
|
-
seen.add(name);
|
|
122
|
-
const reName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
123
|
-
if (!new RegExp(`export (?:const|function|type) ${reName}\\b`).test(current)) stubs.push(`export const ${name}: ContentEntry[] = [];`);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
if (stubs.length) await writeFile(contentFile, current + stubs.join("\n") + "\n");
|
|
127
|
-
}
|
|
128
|
-
function probeConfigFresh(appRoot) {
|
|
129
|
-
const path = findJuneConfigPath(appRoot);
|
|
130
|
-
if (!path) return {
|
|
131
|
-
sources: [],
|
|
132
|
-
locales: []
|
|
133
|
-
};
|
|
134
|
-
const code = `import(${JSON.stringify(pathToFileURL(path).href)}).then((m) => { const c = m.default ?? {}; process.stdout.write("\\n__JUNE_CONTENT__" + JSON.stringify({ sources: c.content?.sources ?? [], locales: c.i18n ? [...new Set([c.i18n.defaultLocale, ...Object.keys(c.i18n.locales ?? {})])] : [] }) + "__END__"); }, () => process.exit(42));`;
|
|
135
|
-
try {
|
|
136
|
-
const m = execFileSync(process.execPath, [
|
|
137
|
-
...process.execArgv,
|
|
138
|
-
"-e",
|
|
139
|
-
code
|
|
140
|
-
], {
|
|
141
|
-
encoding: "utf8",
|
|
142
|
-
stdio: [
|
|
143
|
-
"ignore",
|
|
144
|
-
"pipe",
|
|
145
|
-
"ignore"
|
|
146
|
-
]
|
|
147
|
-
}).match(/__JUNE_CONTENT__(.*?)__END__/s);
|
|
148
|
-
return m ? JSON.parse(m[1]) : null;
|
|
149
|
-
} catch {
|
|
150
|
-
return null;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
async function freezeConfig(appRoot) {
|
|
154
|
-
const cfg = await loadJuneConfig(appRoot);
|
|
155
|
-
const hasClient = findClientEntry(join(appRoot, "app")) !== void 0 || findClientEntry(join(appRoot, ".june", "routes")) !== void 0;
|
|
156
|
-
const hasCss = findGlobalCss(join(appRoot, "app")) !== null;
|
|
157
|
-
return {
|
|
158
|
-
document: {
|
|
159
|
-
site: cfg.site ?? {},
|
|
160
|
-
speculationRules: resolveSpeculationRules(cfg.speculation ?? void 0),
|
|
161
|
-
speculationDelivery: "inline",
|
|
162
|
-
viewTransitions: cfg.viewTransitions ?? true,
|
|
163
|
-
cssReset: cfg.cssReset ?? !globalCssUsesTailwind(join(appRoot, "app")),
|
|
164
|
-
clientRouter: resolveClientRouter(cfg.clientRouter),
|
|
165
|
-
clientScript: hasClient ? CLIENT_SCRIPT_URL : null,
|
|
166
|
-
styles: hasCss ? STYLES_URL : null,
|
|
167
|
-
basePath: normalizeBase(cfg.basePath)
|
|
168
|
-
},
|
|
169
|
-
agent: resolveAgent(cfg.agent),
|
|
170
|
-
i18n: cfg.i18n,
|
|
171
|
-
earlyHints: cfg.earlyHints ?? [],
|
|
172
|
-
buildExternal: cfg.build?.external ?? []
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
function normalizeBase(base) {
|
|
176
|
-
if (!base) return "";
|
|
177
|
-
const b = base.startsWith("/") ? base : `/${base}`;
|
|
178
|
-
return b.endsWith("/") ? b.slice(0, -1) : b;
|
|
179
|
-
}
|
|
180
|
-
async function importLayout(file) {
|
|
181
|
-
const mod = await import(pathToFileURL(file).href);
|
|
182
|
-
return typeof mod.default === "function" ? {
|
|
183
|
-
component: mod.default,
|
|
184
|
-
boundary: mod.segmentBoundary === true
|
|
185
|
-
} : null;
|
|
186
|
-
}
|
|
187
|
-
function workerName(raw) {
|
|
188
|
-
return raw.replace(/^@[^/]+\//, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") || "app";
|
|
189
|
-
}
|
|
190
|
-
async function buildManifest(appRoot) {
|
|
191
|
-
const appDir = join(appRoot, "app");
|
|
192
|
-
const juneRoutesDir = join(appRoot, ".june", "routes");
|
|
193
|
-
const frozen = await freezeConfig(appRoot);
|
|
194
|
-
const appRoutes = await scanRoutes(appDir);
|
|
195
|
-
const frameworkRoutes = existsSync(juneRoutesDir) ? await scanRoutes(juneRoutesDir) : [];
|
|
196
|
-
const appPaths = new Set(appRoutes.map((r) => r.path));
|
|
197
|
-
const scanned = [...appRoutes, ...frameworkRoutes.filter((r) => !appPaths.has(r.path))].sort((a, b) => a.path.localeCompare(b.path));
|
|
198
|
-
const layoutCache = /* @__PURE__ */ new Map();
|
|
199
|
-
const loadCached = async (f) => {
|
|
200
|
-
if (!layoutCache.has(f)) layoutCache.set(f, await importLayout(f));
|
|
201
|
-
return layoutCache.get(f) ?? null;
|
|
202
|
-
};
|
|
203
|
-
const componentsFor = async (files) => {
|
|
204
|
-
const items = [];
|
|
205
|
-
for (const f of files) {
|
|
206
|
-
const c = await loadCached(f);
|
|
207
|
-
items.push({
|
|
208
|
-
file: f,
|
|
209
|
-
entry: c?.component ?? null,
|
|
210
|
-
boundary: !!c?.boundary
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
return resolveBoundary(items);
|
|
214
|
-
};
|
|
215
|
-
const loadingCache = /* @__PURE__ */ new Map();
|
|
216
|
-
const loadingFor = async (file) => {
|
|
217
|
-
if (!file) return void 0;
|
|
218
|
-
if (!loadingCache.has(file)) {
|
|
219
|
-
const loaded = await importLayout(file);
|
|
220
|
-
loadingCache.set(file, loaded ? loaded.component : null);
|
|
221
|
-
}
|
|
222
|
-
return loadingCache.get(file) ?? void 0;
|
|
223
|
-
};
|
|
224
|
-
const routes = {};
|
|
225
|
-
const dynamicRoutes = [];
|
|
226
|
-
const resourceRoutes = [];
|
|
227
|
-
const layoutChains = {};
|
|
228
|
-
const layoutBoundaries = {};
|
|
229
|
-
const loadings = {};
|
|
230
|
-
for (const r of scanned) {
|
|
231
|
-
const mod = await import(pathToFileURL(r.file).href);
|
|
232
|
-
if (r.resource) {
|
|
233
|
-
const handler = mod.default;
|
|
234
|
-
if (typeof handler === "function") resourceRoutes.push({
|
|
235
|
-
pattern: r.path,
|
|
236
|
-
handler
|
|
237
|
-
});
|
|
238
|
-
continue;
|
|
239
|
-
}
|
|
240
|
-
const def = routeFromModule(mod);
|
|
241
|
-
if (!def) continue;
|
|
242
|
-
const { chain, boundaryIndex, key } = await componentsFor(r.layouts);
|
|
243
|
-
const loading = await loadingFor(r.loading);
|
|
244
|
-
if (r.dynamic) {
|
|
245
|
-
dynamicRoutes.push({
|
|
246
|
-
pattern: r.path,
|
|
247
|
-
def
|
|
248
|
-
});
|
|
249
|
-
layoutChains[r.path] = chain;
|
|
250
|
-
} else {
|
|
251
|
-
routes[r.path] = def;
|
|
252
|
-
layoutChains[r.path] = chain;
|
|
253
|
-
}
|
|
254
|
-
if (boundaryIndex !== null && key !== null) layoutBoundaries[r.path] = {
|
|
255
|
-
index: boundaryIndex,
|
|
256
|
-
key
|
|
257
|
-
};
|
|
258
|
-
if (loading) loadings[r.path] = loading;
|
|
259
|
-
}
|
|
260
|
-
let extra;
|
|
261
|
-
const extraFile = findMiddlewareFile(appDir);
|
|
262
|
-
if (extraFile) {
|
|
263
|
-
const mod = await import(pathToFileURL(extraFile).href);
|
|
264
|
-
if (typeof mod.default === "function") extra = mod.default;
|
|
265
|
-
}
|
|
266
|
-
let agentName;
|
|
267
|
-
const agentDir = join(appDir, frozen.agent.runtime.dir);
|
|
268
|
-
if (frozen.agent.runtime.enabled && existsSync(agentDir)) {
|
|
269
|
-
const cfgFile = join(agentDir, "agent.ts");
|
|
270
|
-
agentName = (existsSync(cfgFile) ? (await import(pathToFileURL(cfgFile).href)).default : void 0)?.name ?? basename(agentDir);
|
|
271
|
-
}
|
|
272
|
-
return {
|
|
273
|
-
routes,
|
|
274
|
-
dynamicRoutes,
|
|
275
|
-
resourceRoutes,
|
|
276
|
-
layoutChains,
|
|
277
|
-
layoutBoundaries,
|
|
278
|
-
loadings,
|
|
279
|
-
document: frozen.document,
|
|
280
|
-
agent: frozen.agent,
|
|
281
|
-
agentName,
|
|
282
|
-
i18n: frozen.i18n,
|
|
283
|
-
earlyHints: frozen.earlyHints,
|
|
284
|
-
extra
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
25
|
function importPath(fromDir, file) {
|
|
288
26
|
const p = relative(fromDir, file).split(sep).join("/").replace(/\.[^.]+$/, "");
|
|
289
27
|
return p.startsWith(".") ? p : `./${p}`;
|
|
@@ -308,11 +46,7 @@ async function juneBuild(appRoot, options = {}) {
|
|
|
308
46
|
force: true
|
|
309
47
|
});
|
|
310
48
|
const contentCollections = await generateContent(appRoot);
|
|
311
|
-
const
|
|
312
|
-
const appRoutes2 = await scanRoutes(appDir);
|
|
313
|
-
const frameworkRoutes2 = existsSync(juneRoutesDir2) ? await scanRoutes(juneRoutesDir2) : [];
|
|
314
|
-
const appPaths2 = new Set(appRoutes2.map((r) => r.path));
|
|
315
|
-
const routes = [...appRoutes2, ...frameworkRoutes2.filter((r) => !appPaths2.has(r.path))].sort((a, b) => a.path.localeCompare(b.path));
|
|
49
|
+
const routes = await scanAppRoutes(appRoot);
|
|
316
50
|
if (routes.length === 0) throw new Error(`no page.* routes found under ${appDir} or .june/routes/`);
|
|
317
51
|
const frozen = await freezeConfig(appRoot);
|
|
318
52
|
if (frozen.i18n?.resolveLocale) console.warn("[june build] i18n.resolveLocale is not yet wired into the built worker (URL-pinned + built-in negotiation work; the hook runs in dev only).");
|
|
@@ -650,4 +384,4 @@ ${doClass}`;
|
|
|
650
384
|
};
|
|
651
385
|
}
|
|
652
386
|
//#endregion
|
|
653
|
-
export { buildManifest, freezeConfig, generateContent, isBunSpecifier, juneBuild, normalizeBase, resolveDeployAdapter, scanRoutes, workerName };
|
|
387
|
+
export { buildManifest, freezeConfig, generateContent, isBunSpecifier, juneBuild, normalizeBase, resolveDeployAdapter, scanAppRoutes, scanRoutes, workerName };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { i as JuneAdapter } from "./adapter-DcZ-W1-7.js";
|
|
2
|
+
import { n as WorkerManifest } from "./worker-BkFHGtxp.js";
|
|
3
|
+
import { JuneConfig } from "@junejs/core/config";
|
|
4
|
+
import { DocumentConfig } from "@junejs/core/document";
|
|
5
|
+
//#region src/config-freeze.d.ts
|
|
6
|
+
declare function resolveDeployAdapter(deploy: JuneConfig["deploy"]): JuneAdapter;
|
|
7
|
+
declare function freezeConfig(appRoot: string): Promise<{
|
|
8
|
+
document: DocumentConfig;
|
|
9
|
+
agent: WorkerManifest["agent"];
|
|
10
|
+
i18n: WorkerManifest["i18n"];
|
|
11
|
+
earlyHints: string[];
|
|
12
|
+
buildExternal: string[];
|
|
13
|
+
}>;
|
|
14
|
+
declare function normalizeBase(base?: string): string;
|
|
15
|
+
declare function workerName(raw: string): string;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { workerName as i, normalizeBase as n, resolveDeployAdapter as r, freezeConfig as t };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { deno, staticSite, vercel, workers } from "./adapter.js";
|
|
2
|
+
import { CLIENT_SCRIPT_URL, findClientEntry } from "./client-bundle.js";
|
|
3
|
+
import { STYLES_URL, findGlobalCss, globalCssUsesTailwind } from "./css.js";
|
|
4
|
+
import { loadJuneConfig } from "./config-loader.js";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { resolveAgent, resolveClientRouter, resolveSpeculationRules } from "@junejs/core/config";
|
|
7
|
+
//#region src/config-freeze.ts
|
|
8
|
+
function resolveDeployAdapter(deploy) {
|
|
9
|
+
if (deploy?.adapter) return deploy.adapter;
|
|
10
|
+
switch (deploy?.target) {
|
|
11
|
+
case "static": return staticSite();
|
|
12
|
+
case "vercel": return vercel();
|
|
13
|
+
case "deno": return deno();
|
|
14
|
+
default: return workers({
|
|
15
|
+
name: deploy?.name,
|
|
16
|
+
domain: deploy?.domain
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function freezeConfig(appRoot) {
|
|
21
|
+
const cfg = await loadJuneConfig(appRoot);
|
|
22
|
+
const hasClient = findClientEntry(join(appRoot, "app")) !== void 0 || findClientEntry(join(appRoot, ".june", "routes")) !== void 0;
|
|
23
|
+
const hasCss = findGlobalCss(join(appRoot, "app")) !== null;
|
|
24
|
+
return {
|
|
25
|
+
document: {
|
|
26
|
+
site: cfg.site ?? {},
|
|
27
|
+
speculationRules: resolveSpeculationRules(cfg.speculation ?? void 0),
|
|
28
|
+
speculationDelivery: "inline",
|
|
29
|
+
viewTransitions: cfg.viewTransitions ?? true,
|
|
30
|
+
cssReset: cfg.cssReset ?? !globalCssUsesTailwind(join(appRoot, "app")),
|
|
31
|
+
clientRouter: resolveClientRouter(cfg.clientRouter),
|
|
32
|
+
clientScript: hasClient ? CLIENT_SCRIPT_URL : null,
|
|
33
|
+
styles: hasCss ? STYLES_URL : null,
|
|
34
|
+
basePath: normalizeBase(cfg.basePath)
|
|
35
|
+
},
|
|
36
|
+
agent: resolveAgent(cfg.agent),
|
|
37
|
+
i18n: cfg.i18n,
|
|
38
|
+
earlyHints: cfg.earlyHints ?? [],
|
|
39
|
+
buildExternal: cfg.build?.external ?? []
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function normalizeBase(base) {
|
|
43
|
+
if (!base) return "";
|
|
44
|
+
const b = base.startsWith("/") ? base : `/${base}`;
|
|
45
|
+
return b.endsWith("/") ? b.slice(0, -1) : b;
|
|
46
|
+
}
|
|
47
|
+
function workerName(raw) {
|
|
48
|
+
return raw.replace(/^@[^/]+\//, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") || "app";
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { freezeConfig, normalizeBase, resolveDeployAdapter, workerName };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ActionContext } from "@junejs/core/context";
|
|
2
|
+
//#region src/connection-auth.d.ts
|
|
3
|
+
type AccountTokenStore = (args: {
|
|
4
|
+
userId: string;
|
|
5
|
+
providerId: string;
|
|
6
|
+
}) => Promise<{
|
|
7
|
+
accessToken: string;
|
|
8
|
+
} | null> | {
|
|
9
|
+
accessToken: string;
|
|
10
|
+
} | null;
|
|
11
|
+
type LinkedAccountAuthOptions = {
|
|
12
|
+
providerId: string;
|
|
13
|
+
store: AccountTokenStore;
|
|
14
|
+
};
|
|
15
|
+
type ConnectionAuth = (ctx?: ActionContext) => Promise<{
|
|
16
|
+
token: string;
|
|
17
|
+
}>;
|
|
18
|
+
declare function linkedAccountAuth(opts: LinkedAccountAuthOptions): ConnectionAuth;
|
|
19
|
+
type BetterAuthLike = {
|
|
20
|
+
api: {
|
|
21
|
+
getAccessToken: (input: {
|
|
22
|
+
body: {
|
|
23
|
+
providerId: string;
|
|
24
|
+
userId?: string;
|
|
25
|
+
accountId?: string;
|
|
26
|
+
};
|
|
27
|
+
headers?: HeadersInit;
|
|
28
|
+
}) => Promise<{
|
|
29
|
+
accessToken?: string;
|
|
30
|
+
token?: string;
|
|
31
|
+
} | null | undefined>;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
declare function betterAuthAccountTokenStore(auth: BetterAuthLike): AccountTokenStore;
|
|
35
|
+
declare function betterAuthAccessToken(auth: BetterAuthLike, opts: {
|
|
36
|
+
providerId: string;
|
|
37
|
+
}): ConnectionAuth;
|
|
38
|
+
//#endregion
|
|
39
|
+
export { AccountTokenStore, BetterAuthLike, ConnectionAuth, LinkedAccountAuthOptions, betterAuthAccessToken, betterAuthAccountTokenStore, linkedAccountAuth };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region src/connection-auth.ts
|
|
2
|
+
function linkedAccountAuth(opts) {
|
|
3
|
+
return async (ctx) => {
|
|
4
|
+
const userId = ctx?.user?.id;
|
|
5
|
+
if (!userId) throw new Error(`connection auth (${opts.providerId}): no authenticated principal — set requiresPrincipal and resolve identity on the surface`);
|
|
6
|
+
const record = await opts.store({
|
|
7
|
+
userId,
|
|
8
|
+
providerId: opts.providerId
|
|
9
|
+
});
|
|
10
|
+
if (!record?.accessToken) throw new Error(`connection auth (${opts.providerId}): user "${userId}" has no linked "${opts.providerId}" account`);
|
|
11
|
+
return { token: record.accessToken };
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function betterAuthAccountTokenStore(auth) {
|
|
15
|
+
return async ({ userId, providerId }) => {
|
|
16
|
+
const res = await auth.api.getAccessToken({ body: {
|
|
17
|
+
providerId,
|
|
18
|
+
userId
|
|
19
|
+
} });
|
|
20
|
+
const accessToken = res?.accessToken ?? res?.token;
|
|
21
|
+
return accessToken ? { accessToken } : null;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function betterAuthAccessToken(auth, opts) {
|
|
25
|
+
return linkedAccountAuth({
|
|
26
|
+
providerId: opts.providerId,
|
|
27
|
+
store: betterAuthAccountTokenStore(auth)
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { betterAuthAccessToken, betterAuthAccountTokenStore, linkedAccountAuth };
|