eddev 2.0.0-beta.64 → 2.0.0-beta.66

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.
@@ -2,11 +2,13 @@ import { RequestHeaders } from "vinxi/http";
2
2
  import { UrlReplacerConf } from "./utils/replace-host.js";
3
3
  import { Manifest } from "vinxi/dist/types/types/manifest";
4
4
  import { TrackerTags } from "../lib/routing/types.js";
5
+ import type { EDConfig } from "../../node/project/config.js";
5
6
  export type ServerContextArgs = {
6
7
  dev: boolean;
7
8
  origin: string;
8
9
  replaceUrls?: UrlReplacerConf;
9
10
  rpcBases?: string[];
11
+ config: EDConfig;
10
12
  };
11
13
  export type ServerContextRuntime = {
12
14
  getManifest: (name: string) => Manifest;
@@ -23,6 +25,7 @@ export declare class ServerContext {
23
25
  origin: string;
24
26
  replaceUrls?: (text: string) => string;
25
27
  rpcBases: string[];
28
+ config: EDConfig;
26
29
  static main: ServerContext;
27
30
  constructor(conf: ServerContextArgs);
28
31
  get runtime(): ServerContextRuntime;
@@ -49,5 +52,20 @@ export declare class ServerContext {
49
52
  body: object;
50
53
  headers: RequestHeaders;
51
54
  }): Promise<Response>;
55
+ get allowedCorsOrigins(): string[];
56
+ getCorsOrigin(originHeader: string): string | undefined;
57
+ getCorsHeaders(origin: string): {
58
+ "Access-Control-Allow-Methods"?: undefined;
59
+ "Access-Control-Allow-Origin"?: undefined;
60
+ "Access-Control-Allow-Credentials"?: undefined;
61
+ "Access-Control-Allow-Headers"?: undefined;
62
+ "Access-Control-Expose-Headers"?: undefined;
63
+ } | {
64
+ "Access-Control-Allow-Methods": string;
65
+ "Access-Control-Allow-Origin": string;
66
+ "Access-Control-Allow-Credentials": string;
67
+ "Access-Control-Allow-Headers": string;
68
+ "Access-Control-Expose-Headers": string;
69
+ };
52
70
  }
53
71
  export {};
@@ -19,11 +19,13 @@ export class ServerContext {
19
19
  origin;
20
20
  replaceUrls;
21
21
  rpcBases = [];
22
+ config;
22
23
  static main;
23
24
  constructor(conf) {
24
25
  this.dev = conf.dev;
25
26
  this.origin = conf.origin;
26
27
  this.rpcBases = conf.rpcBases ?? [];
28
+ this.config = conf.config;
27
29
  if (conf.replaceUrls) {
28
30
  this.replaceUrls = createUrlReplacer(conf.replaceUrls);
29
31
  }
@@ -146,4 +148,40 @@ export class ServerContext {
146
148
  redirect: "manual",
147
149
  });
148
150
  }
151
+ get allowedCorsOrigins() {
152
+ let result = [];
153
+ if (this.config.serverless.endpoints) {
154
+ result.push(...Object.keys(this.config.serverless.endpoints));
155
+ result.push(...Object.values(this.config.serverless.endpoints));
156
+ result = result.filter((origin) => origin !== "*");
157
+ }
158
+ if (this.config.serverless.cors?.origins) {
159
+ result.push(...this.config.serverless.cors.origins);
160
+ }
161
+ return result;
162
+ }
163
+ getCorsOrigin(originHeader) {
164
+ const parsed = parseURL(originHeader);
165
+ if (this.allowedCorsOrigins.includes(parsed.host)) {
166
+ return originHeader;
167
+ }
168
+ if (this.allowedCorsOrigins.includes("*")) {
169
+ return "*";
170
+ }
171
+ }
172
+ getCorsHeaders(origin) {
173
+ if (!origin)
174
+ return {};
175
+ const allowedOrigin = this.getCorsOrigin(origin);
176
+ if (allowedOrigin) {
177
+ return {
178
+ "Access-Control-Allow-Methods": "OPTIONS,GET,HEAD,PUT,PATCH,POST,DELETE",
179
+ "Access-Control-Allow-Origin": allowedOrigin,
180
+ "Access-Control-Allow-Credentials": "true",
181
+ "Access-Control-Allow-Headers": "*",
182
+ "Access-Control-Expose-Headers": "*",
183
+ };
184
+ }
185
+ return {};
186
+ }
149
187
  }
@@ -1,6 +1,11 @@
1
1
  import { createTRPCUntypedClient, httpLink, splitLink, unstable_httpSubscriptionLink, } from "@trpc/client";
2
2
  import SuperJSON from "superjson";
3
3
  import { parseURL, stringifyParsedURL } from "ufo";
4
+ const updatePath = (url) => {
5
+ const parsed = parseURL(url);
6
+ parsed.pathname = "/" + parsed.pathname.replace(/(^\/|\/$)/g, "").replace(/\./g, "/") + "/";
7
+ return stringifyParsedURL(parsed);
8
+ };
4
9
  let client;
5
10
  export function getRPCClient() {
6
11
  if (env.rpcEnabled) {
@@ -10,7 +15,6 @@ export function getRPCClient() {
10
15
  client = createTRPCUntypedClient({
11
16
  links: [
12
17
  splitLink({
13
- // uses the httpSubscriptionLink for subscriptions
14
18
  condition: (op) => op.type === "subscription",
15
19
  true: unstable_httpSubscriptionLink({
16
20
  url: endpoint,
@@ -18,10 +22,11 @@ export function getRPCClient() {
18
22
  }),
19
23
  false: httpLink({
20
24
  url: endpoint,
21
- fetch: (input, init) => {
22
- const parsed = parseURL(input);
23
- parsed.pathname = "/" + parsed.pathname.replace(/(^\/|\/$)/g, "").replace(/\./g, "/") + "/";
24
- return fetch(stringifyParsedURL(parsed), init);
25
+ fetch: (url, opts) => {
26
+ return fetch(updatePath(url), {
27
+ ...opts,
28
+ credentials: "omit",
29
+ });
25
30
  },
26
31
  transformer: SuperJSON,
27
32
  }),
@@ -1 +1 @@
1
- export declare const VERSION = "2.0.0-beta.62";
1
+ export declare const VERSION = "2.0.0-beta.66";
@@ -1 +1 @@
1
- export const VERSION = "2.0.0-beta.62";
1
+ export const VERSION = "2.0.0-beta.66";
@@ -17,8 +17,8 @@ export async function buildVinxi(opts) {
17
17
  publicUrl: project.publicUrl,
18
18
  rootDir: project.rootDir,
19
19
  rpcBases: (await project.serverRoutes.get()).bases,
20
- // log: console,
21
20
  preset,
21
+ config: project.config,
22
22
  };
23
23
  const codegen = createVinxiCodegen({
24
24
  mode: "production",
@@ -40,6 +40,7 @@ export class DevServer {
40
40
  rootDir: this.project.rootDir,
41
41
  log: console,
42
42
  rpcBases: (await this.project.serverRoutes.get()).bases,
43
+ config: this.project.config,
43
44
  });
44
45
  const preset = process.env.TARGET ??
45
46
  process.env.PRESET ??
@@ -1,4 +1,5 @@
1
1
  import { StatefulLog } from "../utils/stateful-log.js";
2
+ import { EDConfig } from "../project/config.js";
2
3
  export type AppArgs = {
3
4
  mode: "development" | "production";
4
5
  publicUrl: string;
@@ -8,6 +9,7 @@ export type AppArgs = {
8
9
  preset?: string;
9
10
  routes?: CustomRoute[];
10
11
  rpcBases?: string[];
12
+ config: EDConfig;
11
13
  };
12
14
  type HTTPMethod = "GET" | "POST" | "PUT" | "OPTIONS" | "HEAD";
13
15
  type CustomRouteFunction = (req: Request) => Response;
@@ -11,16 +11,6 @@ export function createVinxiApp(args) {
11
11
  mode: args.mode,
12
12
  serverless: true,
13
13
  });
14
- console.log("Creating Vinxi app with args", args.rpcBases);
15
- console.log("Base routes", args.rpcBases?.reduce((acc, base) => {
16
- return {
17
- ...acc,
18
- ["/" + base.replace(/(^\/|\/$)/g, "") + "/**/*"]: {
19
- isr: false,
20
- swr: false,
21
- },
22
- };
23
- }, {}));
24
14
  return createApp({
25
15
  server: {
26
16
  // experimental: {
@@ -31,6 +31,7 @@ export function createVinxiCodegen(opts) {
31
31
  ],
32
32
  },
33
33
  rpcBases: (await project.serverRoutes.get()).bases ?? [],
34
+ config: project.config,
34
35
  };
35
36
  return code /* tsx */ `
36
37
  import { ServerContext } from "eddev/server"
@@ -467,10 +468,21 @@ export function createVinxiCodegen(opts) {
467
468
  import "./context.js"
468
469
  import { fetchRequestHandler } from "@trpc/server/adapters/fetch"
469
470
  import { parseURL, stringifyParsedURL } from "ufo"
470
- import { EventHandlerRequest, getWebRequest, H3Event } from "vinxi/http"
471
+ import { EventHandlerRequest, getWebRequest, H3Event, setResponseHeaders } from "vinxi/http"
471
472
  import { createContext, router } from "./manifest/routes.ts"
473
+ import { ServerContext } from "eddev/server"
472
474
 
473
475
  export function handleRPC(event: H3Event<EventHandlerRequest>) {
476
+ const serverContext = ServerContext.main
477
+
478
+ // Handle CORS
479
+ setResponseHeaders(event, serverContext.getCorsHeaders(event.headers.get("origin") ?? event.headers.get("referer") ?? ""))
480
+ if (event.method === "OPTIONS") {
481
+ event.node.res.statusCode = 204
482
+ event.node.res.statusMessage = "No Content."
483
+ return "OK"
484
+ }
485
+
474
486
  // Update URLs with dots, which tRPC prefers
475
487
  const originalReq = getWebRequest(event)
476
488
  const parsed = parseURL(originalReq.url)
@@ -9,20 +9,20 @@ export declare const EDConfigSchema: z.ZodObject<{
9
9
  provider: z.ZodLiteral<"ga4">;
10
10
  id: z.ZodString;
11
11
  }, "strip", z.ZodTypeAny, {
12
- provider: "ga4";
13
12
  id: string;
14
- }, {
15
13
  provider: "ga4";
14
+ }, {
16
15
  id: string;
16
+ provider: "ga4";
17
17
  }>, z.ZodObject<{
18
18
  provider: z.ZodLiteral<"gtm">;
19
19
  id: z.ZodString;
20
20
  }, "strip", z.ZodTypeAny, {
21
- provider: "gtm";
22
21
  id: string;
23
- }, {
24
22
  provider: "gtm";
23
+ }, {
25
24
  id: string;
25
+ provider: "gtm";
26
26
  }>]>, "many">>;
27
27
  serverless: z.ZodObject<{
28
28
  enabled: z.ZodDefault<z.ZodBoolean>;
@@ -33,24 +33,37 @@ export declare const EDConfigSchema: z.ZodObject<{
33
33
  endpoints: z.ZodRecord<z.ZodString, z.ZodString>;
34
34
  defaultRevalidate: z.ZodOptional<z.ZodNumber>;
35
35
  defaultRevalidateQueries: z.ZodOptional<z.ZodNumber>;
36
+ cors: z.ZodOptional<z.ZodObject<{
37
+ origins: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
38
+ }, "strip", z.ZodTypeAny, {
39
+ origins?: string[] | undefined;
40
+ }, {
41
+ origins?: string[] | undefined;
42
+ }>>;
36
43
  }, "strip", z.ZodTypeAny, {
44
+ plugins: "proxy" | "remote";
37
45
  enabled: boolean;
38
46
  uploads: "proxy" | "remote";
39
- plugins: "proxy" | "remote";
40
47
  themeAssets: string[];
41
48
  apiOnly: boolean;
42
49
  endpoints: Record<string, string>;
43
50
  defaultRevalidate?: number | undefined;
44
51
  defaultRevalidateQueries?: number | undefined;
52
+ cors?: {
53
+ origins?: string[] | undefined;
54
+ } | undefined;
45
55
  }, {
46
56
  uploads: "proxy" | "remote";
47
57
  endpoints: Record<string, string>;
48
- enabled?: boolean | undefined;
49
58
  plugins?: "proxy" | "remote" | undefined;
59
+ enabled?: boolean | undefined;
50
60
  themeAssets?: string[] | undefined;
51
61
  apiOnly?: boolean | undefined;
52
62
  defaultRevalidate?: number | undefined;
53
63
  defaultRevalidateQueries?: number | undefined;
64
+ cors?: {
65
+ origins?: string[] | undefined;
66
+ } | undefined;
54
67
  }>;
55
68
  cache: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
56
69
  props: z.ZodNumber;
@@ -68,55 +81,61 @@ export declare const EDConfigSchema: z.ZodObject<{
68
81
  legacyMetadata: boolean;
69
82
  legacyStitches: boolean;
70
83
  serverless: {
84
+ plugins: "proxy" | "remote";
71
85
  enabled: boolean;
72
86
  uploads: "proxy" | "remote";
73
- plugins: "proxy" | "remote";
74
87
  themeAssets: string[];
75
88
  apiOnly: boolean;
76
89
  endpoints: Record<string, string>;
77
90
  defaultRevalidate?: number | undefined;
78
91
  defaultRevalidateQueries?: number | undefined;
92
+ cors?: {
93
+ origins?: string[] | undefined;
94
+ } | undefined;
79
95
  };
80
- devUI: "enabled" | "disabled";
96
+ devUI: "disabled" | "enabled";
97
+ cache?: Record<string, {
98
+ props: number;
99
+ queries: number;
100
+ }> | undefined;
81
101
  $schema?: string | undefined;
82
102
  trackers?: ({
83
- provider: "ga4";
84
103
  id: string;
104
+ provider: "ga4";
85
105
  } | {
86
- provider: "gtm";
87
106
  id: string;
107
+ provider: "gtm";
88
108
  })[] | undefined;
89
- cache?: Record<string, {
90
- props: number;
91
- queries: number;
92
- }> | undefined;
93
109
  }, {
94
110
  version: "1" | "2";
95
111
  serverless: {
96
112
  uploads: "proxy" | "remote";
97
113
  endpoints: Record<string, string>;
98
- enabled?: boolean | undefined;
99
114
  plugins?: "proxy" | "remote" | undefined;
115
+ enabled?: boolean | undefined;
100
116
  themeAssets?: string[] | undefined;
101
117
  apiOnly?: boolean | undefined;
102
118
  defaultRevalidate?: number | undefined;
103
119
  defaultRevalidateQueries?: number | undefined;
120
+ cors?: {
121
+ origins?: string[] | undefined;
122
+ } | undefined;
104
123
  };
124
+ cache?: Record<string, {
125
+ props: number;
126
+ queries: number;
127
+ }> | undefined;
105
128
  $schema?: string | undefined;
106
129
  legacyMetadata?: boolean | undefined;
107
130
  legacyStitches?: boolean | undefined;
108
131
  trackers?: ({
109
- provider: "ga4";
110
132
  id: string;
133
+ provider: "ga4";
111
134
  } | {
112
- provider: "gtm";
113
135
  id: string;
136
+ provider: "gtm";
114
137
  })[] | undefined;
115
- cache?: Record<string, {
116
- props: number;
117
- queries: number;
118
- }> | undefined;
119
- devUI?: "enabled" | "disabled" | undefined;
138
+ devUI?: "disabled" | "enabled" | undefined;
120
139
  }>;
121
140
  export type EDConfig = z.infer<typeof EDConfigSchema>;
122
141
  export declare class Configurator {
@@ -49,6 +49,14 @@ export const EDConfigSchema = z.object({
49
49
  .describe("A map of WordPress hostnames -> serverless hostnames. You can use `*` as a wildcard for the key.\n\nFor example, `{'cms.ed.studio': 'ed.studio'}` tells the WordPress frontend where it can find any serverless API endpoints."),
50
50
  defaultRevalidate: z.number().optional(),
51
51
  defaultRevalidateQueries: z.number().optional(),
52
+ cors: z
53
+ .object({
54
+ origins: z
55
+ .array(z.string())
56
+ .optional()
57
+ .describe("A list of allowed origins for CORS. Set to ['*'] to allow all. All WordPress hosts are also allowed."),
58
+ })
59
+ .optional(),
52
60
  }),
53
61
  cache: z
54
62
  .record(z.string(), z.object({
@@ -35,27 +35,27 @@ export declare const BlockMetaSchema: z.ZodObject<{
35
35
  frontendMode: z.ZodDefault<z.ZodEnum<["hidden", "childrenOnly", "default"]>>;
36
36
  inserter: z.ZodDefault<z.ZodBoolean>;
37
37
  }, "strip", z.ZodTypeAny, {
38
- cache: boolean;
38
+ title: string;
39
+ mode: "both" | "edit" | "preview";
40
+ slug: string;
41
+ tags: string[];
42
+ flags: Record<string, any>;
43
+ category: string;
44
+ parent: string[];
39
45
  acfName: string;
40
46
  fileName: string;
41
- slug: string;
42
47
  graphqlFieldName: string;
43
- title: string;
44
- category: string;
45
48
  types: string[];
46
- mode: "preview" | "edit" | "both";
47
- tags: string[];
48
- flags: Record<string, any>;
49
49
  childTags: string[];
50
50
  childBlocks: string[];
51
- parent: string[];
52
51
  ancestors: string[];
53
52
  dynamic: boolean;
53
+ cache: boolean;
54
54
  allowMultiple: boolean;
55
- frontendMode: "hidden" | "childrenOnly" | "default";
55
+ frontendMode: "hidden" | "default" | "childrenOnly";
56
56
  inserter: boolean;
57
- description?: string | undefined;
58
57
  icon?: string | undefined;
58
+ description?: string | undefined;
59
59
  keywords?: string[] | undefined;
60
60
  templates?: string[] | null | undefined;
61
61
  postMetaBlock?: {
@@ -63,32 +63,32 @@ export declare const BlockMetaSchema: z.ZodObject<{
63
63
  fieldName: string;
64
64
  } | undefined;
65
65
  }, {
66
+ title: string;
67
+ slug: string;
66
68
  acfName: string;
67
69
  fileName: string;
68
- slug: string;
69
70
  graphqlFieldName: string;
70
- title: string;
71
71
  types: string[];
72
- cache?: boolean | undefined;
73
- description?: string | undefined;
74
- category?: string | undefined;
72
+ mode?: "both" | "edit" | "preview" | undefined;
73
+ tags?: string[] | undefined;
74
+ flags?: Record<string, any> | undefined;
75
75
  icon?: string | undefined;
76
+ category?: string | undefined;
77
+ parent?: string[] | undefined;
78
+ description?: string | undefined;
76
79
  keywords?: string[] | undefined;
77
80
  templates?: string[] | null | undefined;
78
- mode?: "preview" | "edit" | "both" | undefined;
79
- tags?: string[] | undefined;
80
- flags?: Record<string, any> | undefined;
81
81
  childTags?: string[] | undefined;
82
82
  childBlocks?: string[] | undefined;
83
- parent?: string[] | undefined;
84
83
  ancestors?: string[] | undefined;
85
84
  dynamic?: boolean | undefined;
85
+ cache?: boolean | undefined;
86
86
  allowMultiple?: boolean | undefined;
87
87
  postMetaBlock?: {
88
88
  postTypes: string[];
89
89
  fieldName: string;
90
90
  } | undefined;
91
- frontendMode?: "hidden" | "childrenOnly" | "default" | undefined;
91
+ frontendMode?: "hidden" | "default" | "childrenOnly" | undefined;
92
92
  inserter?: boolean | undefined;
93
93
  }>;
94
94
  export type BlockMetadata = z.infer<typeof BlockMetaSchema>;
@@ -9,21 +9,21 @@ export declare const ViewMetaSchema: z.ZodObject<{
9
9
  routePattern: z.ZodOptional<z.ZodString>;
10
10
  postType: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
11
11
  }, "strip", z.ZodTypeAny, {
12
- cache: boolean;
13
- fileName: string;
14
- slug: string;
15
12
  title: string;
13
+ slug: string;
14
+ fileName: string;
15
+ cache: boolean;
16
16
  isCustomTemplate: boolean;
17
- routePattern?: string | undefined;
18
17
  postType?: string[] | undefined;
18
+ routePattern?: string | undefined;
19
19
  }, {
20
- fileName: string;
21
- slug: string;
22
20
  title: string;
21
+ slug: string;
22
+ fileName: string;
23
+ postType?: string[] | undefined;
23
24
  cache?: boolean | undefined;
24
25
  isCustomTemplate?: boolean | undefined;
25
26
  routePattern?: string | undefined;
26
- postType?: string[] | undefined;
27
27
  }>;
28
28
  export type ViewMetadata = z.infer<typeof ViewMetaSchema>;
29
29
  export type ViewMetadataConstructor = z.input<typeof ViewMetaSchema>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eddev",
3
- "version": "2.0.0-beta.64",
3
+ "version": "2.0.0-beta.66",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",