@plurid/plurid-react-server 0.0.0-16 → 0.0.0-17
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/distribution/index.d.mts
CHANGED
|
@@ -46,6 +46,14 @@ interface PluridServerOptions {
|
|
|
46
46
|
* Name of the directory where the assets files are bundled.
|
|
47
47
|
*/
|
|
48
48
|
assetsDirectory: string;
|
|
49
|
+
/**
|
|
50
|
+
* Directory of static assets (favicon, og-image, manifest, robots) served at
|
|
51
|
+
* the URL root `/`. Empty string (the default) resolves to
|
|
52
|
+
* `<buildDirectory>/public`; the mount is skipped if the directory does not
|
|
53
|
+
* exist, so apps without a public directory are unaffected. The framework
|
|
54
|
+
* points this at `source/public` during `plurid dev`.
|
|
55
|
+
*/
|
|
56
|
+
publicDirectory: string;
|
|
49
57
|
/**
|
|
50
58
|
* Default: `/gateway`.
|
|
51
59
|
*/
|
|
@@ -136,6 +144,44 @@ interface PluridServerTemplateConfiguration {
|
|
|
136
144
|
*/
|
|
137
145
|
defaultPreloadedPluridMetastate?: string;
|
|
138
146
|
minify?: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Favicon links injected into `<head>`. A bare string is the primary icon
|
|
149
|
+
* (`rel="icon"`); the object expands to icon / apple-touch-icon / sized /
|
|
150
|
+
* mask-icon links plus a `theme-color` meta. Paths resolve against the served
|
|
151
|
+
* public directory (see `PluridServerOptions.publicDirectory`).
|
|
152
|
+
*/
|
|
153
|
+
favicon?: string | {
|
|
154
|
+
icon?: string;
|
|
155
|
+
apple?: string;
|
|
156
|
+
sizes?: Record<string, string>;
|
|
157
|
+
maskIcon?: string;
|
|
158
|
+
themeColor?: string;
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* Web app manifest href, injected as `<link rel="manifest">`.
|
|
162
|
+
*/
|
|
163
|
+
manifest?: string;
|
|
164
|
+
/**
|
|
165
|
+
* Static `<head>` metadata injected AHEAD of the react-helmet-async output,
|
|
166
|
+
* so per-route `<Helmet>` tags still override these defaults.
|
|
167
|
+
*/
|
|
168
|
+
head?: {
|
|
169
|
+
title?: string;
|
|
170
|
+
description?: string;
|
|
171
|
+
meta?: Array<{
|
|
172
|
+
name?: string;
|
|
173
|
+
property?: string;
|
|
174
|
+
content: string;
|
|
175
|
+
}>;
|
|
176
|
+
links?: Array<{
|
|
177
|
+
rel: string;
|
|
178
|
+
href: string;
|
|
179
|
+
}>;
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Override the built-in 500 error page HTML (sent on a render failure).
|
|
183
|
+
*/
|
|
184
|
+
errorHtml?: string;
|
|
139
185
|
}
|
|
140
186
|
interface PluridStillerOptions {
|
|
141
187
|
/**
|
|
@@ -213,6 +259,12 @@ declare class PluridServer {
|
|
|
213
259
|
private resolvePreserveAfterServe;
|
|
214
260
|
private handleGateway;
|
|
215
261
|
private renderApplication;
|
|
262
|
+
/**
|
|
263
|
+
* Build the static `<head>` markup from the template config (favicon set,
|
|
264
|
+
* manifest, default title / meta / links). Returns an empty string when none
|
|
265
|
+
* are configured, so the head is byte-identical to before for existing apps.
|
|
266
|
+
*/
|
|
267
|
+
private buildStaticHead;
|
|
216
268
|
private getContentAndStyles;
|
|
217
269
|
private computeRequestTime;
|
|
218
270
|
private handleOptions;
|
package/distribution/index.d.ts
CHANGED
|
@@ -46,6 +46,14 @@ interface PluridServerOptions {
|
|
|
46
46
|
* Name of the directory where the assets files are bundled.
|
|
47
47
|
*/
|
|
48
48
|
assetsDirectory: string;
|
|
49
|
+
/**
|
|
50
|
+
* Directory of static assets (favicon, og-image, manifest, robots) served at
|
|
51
|
+
* the URL root `/`. Empty string (the default) resolves to
|
|
52
|
+
* `<buildDirectory>/public`; the mount is skipped if the directory does not
|
|
53
|
+
* exist, so apps without a public directory are unaffected. The framework
|
|
54
|
+
* points this at `source/public` during `plurid dev`.
|
|
55
|
+
*/
|
|
56
|
+
publicDirectory: string;
|
|
49
57
|
/**
|
|
50
58
|
* Default: `/gateway`.
|
|
51
59
|
*/
|
|
@@ -136,6 +144,44 @@ interface PluridServerTemplateConfiguration {
|
|
|
136
144
|
*/
|
|
137
145
|
defaultPreloadedPluridMetastate?: string;
|
|
138
146
|
minify?: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Favicon links injected into `<head>`. A bare string is the primary icon
|
|
149
|
+
* (`rel="icon"`); the object expands to icon / apple-touch-icon / sized /
|
|
150
|
+
* mask-icon links plus a `theme-color` meta. Paths resolve against the served
|
|
151
|
+
* public directory (see `PluridServerOptions.publicDirectory`).
|
|
152
|
+
*/
|
|
153
|
+
favicon?: string | {
|
|
154
|
+
icon?: string;
|
|
155
|
+
apple?: string;
|
|
156
|
+
sizes?: Record<string, string>;
|
|
157
|
+
maskIcon?: string;
|
|
158
|
+
themeColor?: string;
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* Web app manifest href, injected as `<link rel="manifest">`.
|
|
162
|
+
*/
|
|
163
|
+
manifest?: string;
|
|
164
|
+
/**
|
|
165
|
+
* Static `<head>` metadata injected AHEAD of the react-helmet-async output,
|
|
166
|
+
* so per-route `<Helmet>` tags still override these defaults.
|
|
167
|
+
*/
|
|
168
|
+
head?: {
|
|
169
|
+
title?: string;
|
|
170
|
+
description?: string;
|
|
171
|
+
meta?: Array<{
|
|
172
|
+
name?: string;
|
|
173
|
+
property?: string;
|
|
174
|
+
content: string;
|
|
175
|
+
}>;
|
|
176
|
+
links?: Array<{
|
|
177
|
+
rel: string;
|
|
178
|
+
href: string;
|
|
179
|
+
}>;
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Override the built-in 500 error page HTML (sent on a render failure).
|
|
183
|
+
*/
|
|
184
|
+
errorHtml?: string;
|
|
139
185
|
}
|
|
140
186
|
interface PluridStillerOptions {
|
|
141
187
|
/**
|
|
@@ -213,6 +259,12 @@ declare class PluridServer {
|
|
|
213
259
|
private resolvePreserveAfterServe;
|
|
214
260
|
private handleGateway;
|
|
215
261
|
private renderApplication;
|
|
262
|
+
/**
|
|
263
|
+
* Build the static `<head>` markup from the template config (favicon set,
|
|
264
|
+
* manifest, default title / meta / links). Returns an empty string when none
|
|
265
|
+
* are configured, so the head is byte-identical to before for existing apps.
|
|
266
|
+
*/
|
|
267
|
+
private buildStaticHead;
|
|
216
268
|
private getContentAndStyles;
|
|
217
269
|
private computeRequestTime;
|
|
218
270
|
private handleOptions;
|
package/distribution/index.js
CHANGED
|
@@ -248,7 +248,7 @@ var template = async (data) => {
|
|
|
248
248
|
|
|
249
249
|
${headScripts.join("\n")}
|
|
250
250
|
|
|
251
|
-
|
|
251
|
+
${vendorScriptSource ? `<script src="${vendorScriptSource}"></script>` : ""}
|
|
252
252
|
<script defer src="${mainScriptSource}"></script>
|
|
253
253
|
</head>
|
|
254
254
|
<body ${bodyAttributes}>
|
|
@@ -328,7 +328,7 @@ var PluridRenderer = class {
|
|
|
328
328
|
this.styles = styles;
|
|
329
329
|
this.headScripts = headScripts;
|
|
330
330
|
this.bodyScripts = bodyScripts;
|
|
331
|
-
this.vendorScriptSource = vendorScriptSource
|
|
331
|
+
this.vendorScriptSource = vendorScriptSource ?? DEFAULT_RENDERER_VENDOR_SCRIPT_SOURCE;
|
|
332
332
|
this.mainScriptSource = mainScriptSource || DEFAULT_RENDERER_MAIN_SCRIPT_SOURCE;
|
|
333
333
|
this.root = root || DEFAULT_RENDERER_ROOT;
|
|
334
334
|
this.content = assetsPathRewrite(content) || "";
|
|
@@ -883,7 +883,7 @@ var PluridServer = class {
|
|
|
883
883
|
error
|
|
884
884
|
);
|
|
885
885
|
}
|
|
886
|
-
response.status(500).send(SERVER_ERROR_TEMPLATE);
|
|
886
|
+
response.status(500).send(this.template?.errorHtml || SERVER_ERROR_TEMPLATE);
|
|
887
887
|
return;
|
|
888
888
|
}
|
|
889
889
|
}
|
|
@@ -991,7 +991,7 @@ var PluridServer = class {
|
|
|
991
991
|
error
|
|
992
992
|
);
|
|
993
993
|
}
|
|
994
|
-
response.status(500).send(SERVER_ERROR_TEMPLATE);
|
|
994
|
+
response.status(500).send(this.template?.errorHtml || SERVER_ERROR_TEMPLATE);
|
|
995
995
|
return;
|
|
996
996
|
}
|
|
997
997
|
}
|
|
@@ -1163,7 +1163,7 @@ var PluridServer = class {
|
|
|
1163
1163
|
const {
|
|
1164
1164
|
helmet
|
|
1165
1165
|
} = this.helmet;
|
|
1166
|
-
const
|
|
1166
|
+
const helmetHead = helmet ? `
|
|
1167
1167
|
${helmet.meta.toString()}
|
|
1168
1168
|
${helmet.title.toString()}
|
|
1169
1169
|
${helmet.base.toString()}
|
|
@@ -1172,6 +1172,7 @@ var PluridServer = class {
|
|
|
1172
1172
|
${helmet.noscript.toString()}
|
|
1173
1173
|
${helmet.script.toString()}
|
|
1174
1174
|
` : "";
|
|
1175
|
+
const head = helmetHead + this.buildStaticHead();
|
|
1175
1176
|
const htmlAttributes = {
|
|
1176
1177
|
...this.template?.htmlAttributes,
|
|
1177
1178
|
...helmet?.htmlAttributes.toComponent()
|
|
@@ -1210,6 +1211,67 @@ var PluridServer = class {
|
|
|
1210
1211
|
});
|
|
1211
1212
|
return renderer;
|
|
1212
1213
|
}
|
|
1214
|
+
/**
|
|
1215
|
+
* Build the static `<head>` markup from the template config (favicon set,
|
|
1216
|
+
* manifest, default title / meta / links). Returns an empty string when none
|
|
1217
|
+
* are configured, so the head is byte-identical to before for existing apps.
|
|
1218
|
+
*/
|
|
1219
|
+
buildStaticHead() {
|
|
1220
|
+
const template2 = this.template;
|
|
1221
|
+
if (!template2) {
|
|
1222
|
+
return "";
|
|
1223
|
+
}
|
|
1224
|
+
const escapeAttribute2 = (value) => value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
1225
|
+
const escapeText = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1226
|
+
const parts = [];
|
|
1227
|
+
const favicon = template2.favicon;
|
|
1228
|
+
if (typeof favicon === "string") {
|
|
1229
|
+
parts.push(`<link rel="icon" href="${escapeAttribute2(favicon)}">`);
|
|
1230
|
+
} else if (favicon) {
|
|
1231
|
+
if (favicon.icon) {
|
|
1232
|
+
parts.push(`<link rel="icon" href="${escapeAttribute2(favicon.icon)}">`);
|
|
1233
|
+
}
|
|
1234
|
+
if (favicon.apple) {
|
|
1235
|
+
parts.push(`<link rel="apple-touch-icon" href="${escapeAttribute2(favicon.apple)}">`);
|
|
1236
|
+
}
|
|
1237
|
+
for (const [size, href] of Object.entries(favicon.sizes || {})) {
|
|
1238
|
+
parts.push(`<link rel="icon" sizes="${escapeAttribute2(size)}" href="${escapeAttribute2(href)}">`);
|
|
1239
|
+
}
|
|
1240
|
+
if (favicon.maskIcon) {
|
|
1241
|
+
const color = favicon.themeColor ? ` color="${escapeAttribute2(favicon.themeColor)}"` : "";
|
|
1242
|
+
parts.push(`<link rel="mask-icon" href="${escapeAttribute2(favicon.maskIcon)}"${color}>`);
|
|
1243
|
+
}
|
|
1244
|
+
if (favicon.themeColor) {
|
|
1245
|
+
parts.push(`<meta name="theme-color" content="${escapeAttribute2(favicon.themeColor)}">`);
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
if (template2.manifest) {
|
|
1249
|
+
parts.push(`<link rel="manifest" href="${escapeAttribute2(template2.manifest)}">`);
|
|
1250
|
+
}
|
|
1251
|
+
const head = template2.head;
|
|
1252
|
+
if (head) {
|
|
1253
|
+
if (head.title) {
|
|
1254
|
+
parts.push(`<title>${escapeText(head.title)}</title>`);
|
|
1255
|
+
}
|
|
1256
|
+
if (head.description) {
|
|
1257
|
+
parts.push(`<meta name="description" content="${escapeAttribute2(head.description)}">`);
|
|
1258
|
+
}
|
|
1259
|
+
for (const meta of head.meta || []) {
|
|
1260
|
+
const selector = meta.name ? `name="${escapeAttribute2(meta.name)}"` : meta.property ? `property="${escapeAttribute2(meta.property)}"` : "";
|
|
1261
|
+
if (!selector) {
|
|
1262
|
+
continue;
|
|
1263
|
+
}
|
|
1264
|
+
parts.push(`<meta ${selector} content="${escapeAttribute2(meta.content)}">`);
|
|
1265
|
+
}
|
|
1266
|
+
for (const link of head.links || []) {
|
|
1267
|
+
parts.push(`<link rel="${escapeAttribute2(link.rel)}" href="${escapeAttribute2(link.href)}">`);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
if (parts.length === 0) {
|
|
1271
|
+
return "";
|
|
1272
|
+
}
|
|
1273
|
+
return "\n " + parts.join("\n ");
|
|
1274
|
+
}
|
|
1213
1275
|
async getContentAndStyles(isoMatch, pluridMetastate, preserveResult, matchedPlane) {
|
|
1214
1276
|
const stylesheet = new import_styled_components2.ServerStyleSheet();
|
|
1215
1277
|
let content = "";
|
|
@@ -1283,6 +1345,7 @@ var PluridServer = class {
|
|
|
1283
1345
|
open: partialOptions?.open ?? DEFAULT_SERVER_OPTIONS.OPEN,
|
|
1284
1346
|
buildDirectory: partialOptions?.buildDirectory || DEFAULT_SERVER_OPTIONS.BUILD_DIRECTORY,
|
|
1285
1347
|
assetsDirectory: partialOptions?.assetsDirectory || DEFAULT_SERVER_OPTIONS.ASSETS_DIRECTORY,
|
|
1348
|
+
publicDirectory: partialOptions?.publicDirectory || "",
|
|
1286
1349
|
gatewayEndpoint: partialOptions?.gatewayEndpoint || DEFAULT_SERVER_OPTIONS.GATEWAY,
|
|
1287
1350
|
staticCache: partialOptions?.staticCache || 0,
|
|
1288
1351
|
ignore: partialOptions?.ignore || [],
|
|
@@ -1335,6 +1398,15 @@ var PluridServer = class {
|
|
|
1335
1398
|
maxAge: this.options.staticCache
|
|
1336
1399
|
})
|
|
1337
1400
|
);
|
|
1401
|
+
const publicPath = this.options.publicDirectory || import_path2.default.join(this.options.buildDirectory, "public");
|
|
1402
|
+
if (import_fs2.default.existsSync(publicPath)) {
|
|
1403
|
+
this.serverApplication.use(
|
|
1404
|
+
import_express.default.static(publicPath, {
|
|
1405
|
+
index: false,
|
|
1406
|
+
maxAge: this.options.staticCache
|
|
1407
|
+
})
|
|
1408
|
+
);
|
|
1409
|
+
}
|
|
1338
1410
|
this.loadMiddleware();
|
|
1339
1411
|
}
|
|
1340
1412
|
loadMiddleware() {
|