@lukoweb/apitogo 0.1.42 → 0.1.44
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/cli/cli.js +380 -264
- package/dist/declarations/config/local-manifest.d.ts +80 -0
- package/docs/configuration/authentication.md +11 -2
- package/package.json +9 -1
- package/src/config/local-manifest.ts +142 -0
- package/src/types.d.ts +5 -0
- package/src/vite/dev-portal-env.ts +0 -72
- package/src/vite/plugin-local-manifest.ts +79 -0
- package/src/vite/plugin.ts +2 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const DEV_PORTAL_MANIFEST_FILENAME = "apitogo.local.json";
|
|
3
|
+
export declare const ManifestPlanInputSchema: z.ZodObject<{
|
|
4
|
+
sku: z.ZodString;
|
|
5
|
+
displayName: z.ZodString;
|
|
6
|
+
isFree: z.ZodBoolean;
|
|
7
|
+
priceAmount: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
priceCurrency: z.ZodOptional<z.ZodString>;
|
|
9
|
+
billingPeriod: z.ZodOptional<z.ZodEnum<{
|
|
10
|
+
month: "month";
|
|
11
|
+
monthly: "monthly";
|
|
12
|
+
year: "year";
|
|
13
|
+
annual: "annual";
|
|
14
|
+
}>>;
|
|
15
|
+
limitsJson: z.ZodOptional<z.ZodString>;
|
|
16
|
+
includedActionKeys: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
17
|
+
}, z.core.$strip>;
|
|
18
|
+
export declare const DevPortalLocalManifestSchema: z.ZodObject<{
|
|
19
|
+
siteName: z.ZodOptional<z.ZodString>;
|
|
20
|
+
branding: z.ZodOptional<z.ZodObject<{
|
|
21
|
+
title: z.ZodOptional<z.ZodString>;
|
|
22
|
+
logoUrl: z.ZodOptional<z.ZodString>;
|
|
23
|
+
}, z.core.$strip>>;
|
|
24
|
+
plans: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
25
|
+
sku: z.ZodString;
|
|
26
|
+
displayName: z.ZodString;
|
|
27
|
+
isFree: z.ZodBoolean;
|
|
28
|
+
priceAmount: z.ZodOptional<z.ZodNumber>;
|
|
29
|
+
priceCurrency: z.ZodOptional<z.ZodString>;
|
|
30
|
+
billingPeriod: z.ZodOptional<z.ZodEnum<{
|
|
31
|
+
month: "month";
|
|
32
|
+
monthly: "monthly";
|
|
33
|
+
year: "year";
|
|
34
|
+
annual: "annual";
|
|
35
|
+
}>>;
|
|
36
|
+
limitsJson: z.ZodOptional<z.ZodString>;
|
|
37
|
+
includedActionKeys: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
38
|
+
}, z.core.$strip>>>;
|
|
39
|
+
backend: z.ZodOptional<z.ZodObject<{
|
|
40
|
+
sourceDirectory: z.ZodOptional<z.ZodString>;
|
|
41
|
+
publishDirectory: z.ZodOptional<z.ZodString>;
|
|
42
|
+
openApiPath: z.ZodOptional<z.ZodString>;
|
|
43
|
+
runtime: z.ZodOptional<z.ZodString>;
|
|
44
|
+
runtimeVersion: z.ZodOptional<z.ZodString>;
|
|
45
|
+
deployed: z.ZodOptional<z.ZodBoolean>;
|
|
46
|
+
}, z.core.$strip>>;
|
|
47
|
+
gateway: z.ZodOptional<z.ZodObject<{
|
|
48
|
+
authMode: z.ZodOptional<z.ZodEnum<{
|
|
49
|
+
platformManagedEntra: "platformManagedEntra";
|
|
50
|
+
bringYourOwnOidc: "bringYourOwnOidc";
|
|
51
|
+
}>>;
|
|
52
|
+
oidcMetadataUrl: z.ZodOptional<z.ZodString>;
|
|
53
|
+
oidcAllowedIssuers: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
54
|
+
oidcAudiences: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
55
|
+
limitsJson: z.ZodOptional<z.ZodString>;
|
|
56
|
+
publicHealthActionKey: z.ZodOptional<z.ZodString>;
|
|
57
|
+
}, z.core.$strip>>;
|
|
58
|
+
projectId: z.ZodOptional<z.ZodString>;
|
|
59
|
+
projectName: z.ZodOptional<z.ZodString>;
|
|
60
|
+
}, z.core.$strip>;
|
|
61
|
+
export type ManifestPlanInput = z.infer<typeof ManifestPlanInputSchema>;
|
|
62
|
+
export type DevPortalLocalManifest = z.infer<typeof DevPortalLocalManifestSchema>;
|
|
63
|
+
export type DevPortalPreviewPlan = {
|
|
64
|
+
sku: string;
|
|
65
|
+
displayName: string;
|
|
66
|
+
isFree: boolean;
|
|
67
|
+
priceAmount: number;
|
|
68
|
+
priceCurrency: string;
|
|
69
|
+
billingPeriod: string;
|
|
70
|
+
limitsJson: string | null;
|
|
71
|
+
includedActionKeys: string[];
|
|
72
|
+
};
|
|
73
|
+
export type DevPortalPreviewPlanCatalog = {
|
|
74
|
+
plans: DevPortalPreviewPlan[];
|
|
75
|
+
};
|
|
76
|
+
export declare function normalizeBillingPeriod(period?: string): string;
|
|
77
|
+
export declare function plansToPreviewCatalog(plans: ManifestPlanInput[] | undefined): DevPortalPreviewPlanCatalog;
|
|
78
|
+
export declare function manifestFilePath(rootDir: string): string;
|
|
79
|
+
export declare function parseLocalManifestJson(raw: string): DevPortalLocalManifest | null;
|
|
80
|
+
export declare function readLocalManifest(rootDir: string): Promise<DevPortalLocalManifest | null>;
|
|
@@ -45,8 +45,17 @@ VITE_APITOGO_DEV_PORTAL_API_URL=https://your-dev-portal-api.example.com
|
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
**Local preview:** When the backend URL is a placeholder or unreachable, the account area shows a
|
|
48
|
-
message that sign-in unlocks after publish. Docs and API reference remain public.
|
|
49
|
-
|
|
48
|
+
message that sign-in unlocks after publish. Docs and API reference remain public. Plans on
|
|
49
|
+
`/pricing` load from `apitogo.local.json` (including `includedActionKeys` per plan). Plan edits
|
|
50
|
+
hot-reload without restarting the dev server.
|
|
51
|
+
|
|
52
|
+
### Dev portal configuration files
|
|
53
|
+
|
|
54
|
+
| Concern | File |
|
|
55
|
+
| --- | --- |
|
|
56
|
+
| Site nav, docs, plugins, auth wiring | `apitogo.config.tsx` |
|
|
57
|
+
| Plans, rate limits, `includedActionKeys`, project/deploy metadata | `apitogo.local.json` |
|
|
58
|
+
| OIDC and Stripe for publish (MCP only) | `apitogo.local.secrets.json` |
|
|
50
59
|
|
|
51
60
|
**Production:** Register one OIDC app with redirect URI `https://{backend}/signin-oidc` (see MCP
|
|
52
61
|
`manualSteps.oidcRedirectUri`). The frontend uses cookie sessions via `credentials: "include"` on
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lukoweb/apitogo",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.44",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"**/*.css",
|
|
@@ -149,6 +149,10 @@
|
|
|
149
149
|
"./testing": {
|
|
150
150
|
"types": "./dist/declarations/lib/testing/index.d.ts",
|
|
151
151
|
"default": "./src/lib/testing/index.tsx"
|
|
152
|
+
},
|
|
153
|
+
"./local-manifest": {
|
|
154
|
+
"types": "./dist/declarations/config/local-manifest.d.ts",
|
|
155
|
+
"default": "./src/config/local-manifest.ts"
|
|
152
156
|
}
|
|
153
157
|
},
|
|
154
158
|
"scripts": {
|
|
@@ -459,6 +463,10 @@
|
|
|
459
463
|
"./testing": {
|
|
460
464
|
"types": "./dist/declarations/lib/testing/index.d.ts",
|
|
461
465
|
"default": "./src/lib/testing/index.tsx"
|
|
466
|
+
},
|
|
467
|
+
"./local-manifest": {
|
|
468
|
+
"types": "./dist/declarations/config/local-manifest.d.ts",
|
|
469
|
+
"default": "./src/config/local-manifest.ts"
|
|
462
470
|
}
|
|
463
471
|
},
|
|
464
472
|
"access": "public"
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
export const DEV_PORTAL_MANIFEST_FILENAME = "apitogo.local.json";
|
|
6
|
+
|
|
7
|
+
const BillingPeriodSchema = z.enum([
|
|
8
|
+
"month",
|
|
9
|
+
"year",
|
|
10
|
+
"monthly",
|
|
11
|
+
"annual",
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
export const ManifestPlanInputSchema = z.object({
|
|
15
|
+
sku: z.string().min(1),
|
|
16
|
+
displayName: z.string().min(1),
|
|
17
|
+
isFree: z.boolean(),
|
|
18
|
+
priceAmount: z.number().optional(),
|
|
19
|
+
priceCurrency: z.string().optional(),
|
|
20
|
+
billingPeriod: BillingPeriodSchema.optional(),
|
|
21
|
+
limitsJson: z.string().optional(),
|
|
22
|
+
includedActionKeys: z.array(z.string()).optional(),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const DevPortalLocalManifestSchema = z.object({
|
|
26
|
+
siteName: z.string().optional(),
|
|
27
|
+
branding: z
|
|
28
|
+
.object({
|
|
29
|
+
title: z.string().optional(),
|
|
30
|
+
logoUrl: z.string().optional(),
|
|
31
|
+
})
|
|
32
|
+
.optional(),
|
|
33
|
+
plans: z.array(ManifestPlanInputSchema).optional(),
|
|
34
|
+
backend: z
|
|
35
|
+
.object({
|
|
36
|
+
sourceDirectory: z.string().optional(),
|
|
37
|
+
publishDirectory: z.string().optional(),
|
|
38
|
+
openApiPath: z.string().optional(),
|
|
39
|
+
runtime: z.string().optional(),
|
|
40
|
+
runtimeVersion: z.string().optional(),
|
|
41
|
+
deployed: z.boolean().optional(),
|
|
42
|
+
})
|
|
43
|
+
.optional(),
|
|
44
|
+
gateway: z
|
|
45
|
+
.object({
|
|
46
|
+
authMode: z.enum(["platformManagedEntra", "bringYourOwnOidc"]).optional(),
|
|
47
|
+
oidcMetadataUrl: z.string().optional(),
|
|
48
|
+
oidcAllowedIssuers: z.array(z.string()).optional(),
|
|
49
|
+
oidcAudiences: z.array(z.string()).optional(),
|
|
50
|
+
limitsJson: z.string().optional(),
|
|
51
|
+
publicHealthActionKey: z.string().optional(),
|
|
52
|
+
})
|
|
53
|
+
.optional(),
|
|
54
|
+
projectId: z.string().optional(),
|
|
55
|
+
projectName: z.string().optional(),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
export type ManifestPlanInput = z.infer<typeof ManifestPlanInputSchema>;
|
|
59
|
+
export type DevPortalLocalManifest = z.infer<typeof DevPortalLocalManifestSchema>;
|
|
60
|
+
|
|
61
|
+
export type DevPortalPreviewPlan = {
|
|
62
|
+
sku: string;
|
|
63
|
+
displayName: string;
|
|
64
|
+
isFree: boolean;
|
|
65
|
+
priceAmount: number;
|
|
66
|
+
priceCurrency: string;
|
|
67
|
+
billingPeriod: string;
|
|
68
|
+
limitsJson: string | null;
|
|
69
|
+
includedActionKeys: string[];
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type DevPortalPreviewPlanCatalog = {
|
|
73
|
+
plans: DevPortalPreviewPlan[];
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export function normalizeBillingPeriod(period?: string): string {
|
|
77
|
+
if (!period) {
|
|
78
|
+
return "monthly";
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const normalized = period.toLowerCase();
|
|
82
|
+
if (normalized === "month") {
|
|
83
|
+
return "monthly";
|
|
84
|
+
}
|
|
85
|
+
if (normalized === "year") {
|
|
86
|
+
return "annual";
|
|
87
|
+
}
|
|
88
|
+
return normalized;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function plansToPreviewCatalog(
|
|
92
|
+
plans: ManifestPlanInput[] | undefined,
|
|
93
|
+
): DevPortalPreviewPlanCatalog {
|
|
94
|
+
if (!plans?.length) {
|
|
95
|
+
return { plans: [] };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
plans: plans.map((plan) => ({
|
|
100
|
+
sku: plan.sku,
|
|
101
|
+
displayName: plan.displayName,
|
|
102
|
+
isFree: plan.isFree,
|
|
103
|
+
priceAmount: plan.priceAmount ?? 0,
|
|
104
|
+
priceCurrency: plan.priceCurrency ?? "usd",
|
|
105
|
+
billingPeriod: normalizeBillingPeriod(plan.billingPeriod),
|
|
106
|
+
limitsJson: plan.limitsJson ?? null,
|
|
107
|
+
includedActionKeys: plan.includedActionKeys ?? [],
|
|
108
|
+
})),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function manifestFilePath(rootDir: string): string {
|
|
113
|
+
return path.join(path.resolve(rootDir), DEV_PORTAL_MANIFEST_FILENAME);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function parseLocalManifestJson(
|
|
117
|
+
raw: string,
|
|
118
|
+
): DevPortalLocalManifest | null {
|
|
119
|
+
try {
|
|
120
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
121
|
+
const result = DevPortalLocalManifestSchema.safeParse(parsed);
|
|
122
|
+
if (!result.success) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
return result.data;
|
|
126
|
+
} catch {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export async function readLocalManifest(
|
|
132
|
+
rootDir: string,
|
|
133
|
+
): Promise<DevPortalLocalManifest | null> {
|
|
134
|
+
const filePath = manifestFilePath(rootDir);
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
const raw = await readFile(filePath, "utf8");
|
|
138
|
+
return parseLocalManifestJson(raw);
|
|
139
|
+
} catch {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
}
|
package/src/types.d.ts
CHANGED
|
@@ -55,3 +55,8 @@ declare module "virtual:zudoku-shiki-register" {
|
|
|
55
55
|
import type { HighlighterCore } from "shiki/core";
|
|
56
56
|
export const registerShiki: (highlighter: HighlighterCore) => Promise<void>;
|
|
57
57
|
}
|
|
58
|
+
|
|
59
|
+
declare module "virtual:apitogo-local-manifest" {
|
|
60
|
+
const catalog: import("./config/local-manifest.ts").DevPortalPreviewPlanCatalog;
|
|
61
|
+
export default catalog;
|
|
62
|
+
}
|
|
@@ -1,76 +1,10 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
2
1
|
import path from "node:path";
|
|
3
2
|
import { loadEnv } from "vite";
|
|
4
3
|
|
|
5
|
-
export const DEV_PORTAL_MANIFEST_FILENAME = "apitogo.local.json";
|
|
6
|
-
|
|
7
4
|
export const DEV_PORTAL_VITE_ENV_KEYS = [
|
|
8
5
|
"VITE_APITOGO_DEV_PORTAL_API_URL",
|
|
9
|
-
"VITE_APITOGO_DEV_PORTAL_MOCK_PLANS",
|
|
10
6
|
] as const;
|
|
11
7
|
|
|
12
|
-
interface ManifestPlanInput {
|
|
13
|
-
sku: string;
|
|
14
|
-
displayName: string;
|
|
15
|
-
isFree: boolean;
|
|
16
|
-
priceAmount?: number;
|
|
17
|
-
priceCurrency?: string;
|
|
18
|
-
billingPeriod?: string;
|
|
19
|
-
limitsJson?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface DevPortalLocalManifest {
|
|
23
|
-
plans?: ManifestPlanInput[];
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function normalizeBillingPeriod(period?: string): string {
|
|
27
|
-
if (!period) {
|
|
28
|
-
return "monthly";
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const normalized = period.toLowerCase();
|
|
32
|
-
if (normalized === "month") {
|
|
33
|
-
return "monthly";
|
|
34
|
-
}
|
|
35
|
-
if (normalized === "year") {
|
|
36
|
-
return "annual";
|
|
37
|
-
}
|
|
38
|
-
return normalized;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function plansToMockEnvValue(
|
|
42
|
-
plans: ManifestPlanInput[] | undefined,
|
|
43
|
-
): string | null {
|
|
44
|
-
if (!plans?.length) {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const mockPlans = plans.map((plan) => ({
|
|
49
|
-
sku: plan.sku,
|
|
50
|
-
displayName: plan.displayName,
|
|
51
|
-
isFree: plan.isFree,
|
|
52
|
-
priceAmount: plan.priceAmount ?? 0,
|
|
53
|
-
priceCurrency: plan.priceCurrency ?? "usd",
|
|
54
|
-
billingPeriod: normalizeBillingPeriod(plan.billingPeriod),
|
|
55
|
-
limitsJson: plan.limitsJson ?? null,
|
|
56
|
-
}));
|
|
57
|
-
|
|
58
|
-
return JSON.stringify(mockPlans);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export async function readDevPortalManifest(
|
|
62
|
-
rootDir: string,
|
|
63
|
-
): Promise<DevPortalLocalManifest | null> {
|
|
64
|
-
const manifestPath = path.join(rootDir, DEV_PORTAL_MANIFEST_FILENAME);
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
const raw = await readFile(manifestPath, "utf8");
|
|
68
|
-
return JSON.parse(raw) as DevPortalLocalManifest;
|
|
69
|
-
} catch {
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
8
|
export async function loadDevPortalViteDefines(
|
|
75
9
|
rootDir: string,
|
|
76
10
|
mode: string,
|
|
@@ -83,11 +17,5 @@ export async function loadDevPortalViteDefines(
|
|
|
83
17
|
defines.VITE_APITOGO_DEV_PORTAL_API_URL = JSON.stringify(apiUrl);
|
|
84
18
|
}
|
|
85
19
|
|
|
86
|
-
const manifest = await readDevPortalManifest(rootDir);
|
|
87
|
-
const mockPlansValue = plansToMockEnvValue(manifest?.plans);
|
|
88
|
-
if (mockPlansValue) {
|
|
89
|
-
defines.VITE_APITOGO_DEV_PORTAL_MOCK_PLANS = JSON.stringify(mockPlansValue);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
20
|
return defines;
|
|
93
21
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import type { Plugin, ResolvedConfig } from "vite";
|
|
3
|
+
import {
|
|
4
|
+
DEV_PORTAL_MANIFEST_FILENAME,
|
|
5
|
+
manifestFilePath,
|
|
6
|
+
parseLocalManifestJson,
|
|
7
|
+
plansToPreviewCatalog,
|
|
8
|
+
} from "../config/local-manifest.js";
|
|
9
|
+
|
|
10
|
+
export const APITOGO_LOCAL_MANIFEST_VIRTUAL_ID = "virtual:apitogo-local-manifest";
|
|
11
|
+
const resolvedVirtualModuleId = `\0${APITOGO_LOCAL_MANIFEST_VIRTUAL_ID}`;
|
|
12
|
+
|
|
13
|
+
const viteLocalManifestPlugin = (): Plugin => {
|
|
14
|
+
let rootDir = "";
|
|
15
|
+
let manifestPath = "";
|
|
16
|
+
|
|
17
|
+
const loadManifestModule = async (): Promise<string> => {
|
|
18
|
+
const { readFile } = await import("node:fs/promises");
|
|
19
|
+
let catalog = { plans: [] as ReturnType<typeof plansToPreviewCatalog>["plans"] };
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
const raw = await readFile(manifestPath, "utf8");
|
|
23
|
+
const manifest = parseLocalManifestJson(raw);
|
|
24
|
+
catalog = plansToPreviewCatalog(manifest?.plans);
|
|
25
|
+
} catch {
|
|
26
|
+
// Missing or invalid manifest — empty catalog for preview.
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return `export default ${JSON.stringify(catalog)};`;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
name: "apitogo-local-manifest-plugin",
|
|
34
|
+
configResolved(resolvedConfig: ResolvedConfig) {
|
|
35
|
+
rootDir = resolvedConfig.root;
|
|
36
|
+
manifestPath = manifestFilePath(rootDir);
|
|
37
|
+
},
|
|
38
|
+
resolveId(id) {
|
|
39
|
+
if (id === APITOGO_LOCAL_MANIFEST_VIRTUAL_ID) {
|
|
40
|
+
return resolvedVirtualModuleId;
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
async load(id) {
|
|
44
|
+
if (id !== resolvedVirtualModuleId) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return loadManifestModule();
|
|
49
|
+
},
|
|
50
|
+
configureServer(server) {
|
|
51
|
+
const watchPath = path.join(rootDir, DEV_PORTAL_MANIFEST_FILENAME);
|
|
52
|
+
|
|
53
|
+
server.watcher.add(watchPath);
|
|
54
|
+
server.watcher.on("change", async (changedPath) => {
|
|
55
|
+
if (path.resolve(changedPath) !== path.resolve(manifestPath)) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const module = server.moduleGraph.getModuleById(
|
|
60
|
+
resolvedVirtualModuleId,
|
|
61
|
+
);
|
|
62
|
+
if (module) {
|
|
63
|
+
server.moduleGraph.invalidateModule(module);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const mod = await server.moduleGraph.getModuleByUrl(
|
|
67
|
+
APITOGO_LOCAL_MANIFEST_VIRTUAL_ID,
|
|
68
|
+
);
|
|
69
|
+
if (mod) {
|
|
70
|
+
server.reloadModule(mod);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
server.ws.send({ type: "full-reload", path: "*" });
|
|
74
|
+
});
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export default viteLocalManifestPlugin;
|
package/src/vite/plugin.ts
CHANGED
|
@@ -17,12 +17,14 @@ import viteModulesPlugin from "./plugin-modules.js";
|
|
|
17
17
|
import { viteNavigationPlugin } from "./plugin-navigation.js";
|
|
18
18
|
import { viteSearchPlugin } from "./plugin-search.js";
|
|
19
19
|
import { viteShikiRegisterPlugin } from "./plugin-shiki-register.js";
|
|
20
|
+
import viteLocalManifestPlugin from "./plugin-local-manifest.js";
|
|
20
21
|
import { viteThemePlugin } from "./plugin-theme.js";
|
|
21
22
|
|
|
22
23
|
export default function vitePlugin(): PluginOption {
|
|
23
24
|
return [
|
|
24
25
|
viteShikiRegisterPlugin(),
|
|
25
26
|
viteConfigReloadPlugin(),
|
|
27
|
+
viteLocalManifestPlugin(),
|
|
26
28
|
viteMdxPlugin(),
|
|
27
29
|
react({ include: /\.(mdx?|jsx?|tsx?)$/ }),
|
|
28
30
|
viteConfigPlugin(),
|