@webtypen/webframez-core 0.3.97 → 0.3.100
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/README.md +10 -1
- package/build-cache.d.ts +1 -1
- package/build-cache.js +12 -1
- package/dist/Router/Route.d.ts +2 -0
- package/dist/Router/Route.js +4 -0
- package/dist/Router/Router.d.ts +4 -0
- package/dist/Router/Router.js +15 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/docs/databuilder.md +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -996,7 +996,10 @@ Metro consumers can call
|
|
|
996
996
|
`require('@webtypen/webframez-core/build-cache').configureMetroCache(config)`.
|
|
997
997
|
It applies `WEBFRAMEZ_BUILD_MAX_WORKERS` and `WEBFRAMEZ_METRO_CACHE_DIRECTORY`,
|
|
998
998
|
preserving Expo's FileStore implementation and supporting old/new file-map option
|
|
999
|
-
names.
|
|
999
|
+
names. Transform and file-map caches are separated by a stable hash of sorted
|
|
1000
|
+
`EXPO_PUBLIC_*`, `NODE_ENV` and `BABEL_ENV` values. The cache version also includes
|
|
1001
|
+
this hash for custom/remote stores; public values are not written into path names.
|
|
1002
|
+
Private registry credentials do not participate in this build identity. Do not pass Expo `--clear` on normal cached builds.
|
|
1000
1003
|
|
|
1001
1004
|
|
|
1002
1005
|
### Reusable build workspaces
|
|
@@ -1024,3 +1027,9 @@ Asset builds use a stable staging directory so bundler caches can reuse module p
|
|
|
1024
1027
|
An exclusive per-output lock prevents concurrent builds overwriting that directory.
|
|
1025
1028
|
After a killed local build, remove its `.webframez-build/.building-*.lock` directory
|
|
1026
1029
|
only after confirming that no previous build is running. WSM Force Clear removes it.
|
|
1030
|
+
|
|
1031
|
+
### Explicit HEAD routes
|
|
1032
|
+
|
|
1033
|
+
`Route.head(path, handler, options)` registers metadata-only requests separately from GET.
|
|
1034
|
+
Group prefixes, middleware, domain filters and OPTIONS preflight resolution work as for other routes.
|
|
1035
|
+
Return headers with `res.header(...)` and finish with `res.end()`; no response body is needed.
|
package/build-cache.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function configureMetroCache<T extends {cacheStores?: any; maxWorkers?: number}>(config:T, env?:Record<string,string | undefined>):T;
|
|
1
|
+
export function configureMetroCache<T extends {cacheVersion?: string; cacheStores?: any; maxWorkers?: number}>(config:T, env?:Record<string,string | undefined>):T;
|
package/build-cache.js
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
const path = require("node:path");
|
|
2
2
|
const fs = require("node:fs");
|
|
3
|
+
const crypto = require("node:crypto");
|
|
3
4
|
|
|
4
5
|
/** Preserve the platform's FileStore subclass (including Expo CSS handling). */
|
|
5
6
|
function configureMetroCache(config, env = process.env) {
|
|
7
|
+
// Expo inlines public values into transforms. Metro's persistent cache must
|
|
8
|
+
// not share those transforms between origins or feature configurations.
|
|
9
|
+
const publicEnvironment = Object.keys(env)
|
|
10
|
+
.filter(key => key.startsWith("EXPO_PUBLIC_") || key === "NODE_ENV" || key === "BABEL_ENV")
|
|
11
|
+
.sort()
|
|
12
|
+
.map(key => [key, env[key]]);
|
|
13
|
+
const environmentKey = crypto.createHash("sha256").update(JSON.stringify(publicEnvironment)).digest("hex");
|
|
14
|
+
config.cacheVersion = `${config.cacheVersion || "1.0"}:webframez-public-env-v1:${environmentKey}`;
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
if (env.WEBFRAMEZ_BUILD_MAX_WORKERS !== undefined) {
|
|
7
18
|
const workers = Number(env.WEBFRAMEZ_BUILD_MAX_WORKERS);
|
|
8
19
|
if (!Number.isInteger(workers) || workers < 1 || workers > 64) throw new Error("Invalid WEBFRAMEZ_BUILD_MAX_WORKERS");
|
|
9
20
|
config.maxWorkers = workers;
|
|
10
21
|
}
|
|
11
22
|
if (!env.WEBFRAMEZ_METRO_CACHE_DIRECTORY) return config;
|
|
12
|
-
const root = path.resolve(env.WEBFRAMEZ_METRO_CACHE_DIRECTORY);
|
|
23
|
+
const root = path.join(path.resolve(env.WEBFRAMEZ_METRO_CACHE_DIRECTORY), `env-${environmentKey}`);
|
|
13
24
|
const relocate = stores => stores.map((store, index) => {
|
|
14
25
|
// Leave remote and custom stores untouched; their constructors need other options.
|
|
15
26
|
if (!store || typeof store._root !== "string") return store;
|
package/dist/Router/Route.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export declare class RouteFacade {
|
|
|
27
27
|
* @param options
|
|
28
28
|
*/
|
|
29
29
|
get(path: string, component: any, options?: RouteRegistrationOptions): void;
|
|
30
|
+
/** Register a HEAD route, for metadata without a response body. */
|
|
31
|
+
head(path: string, component: any, options?: RouteRegistrationOptions): void;
|
|
30
32
|
/** Register the existing DataBuilder POST protocol with request-local configuration. */
|
|
31
33
|
databuilder(path: string, options?: DataBuilderRouteOptions): void;
|
|
32
34
|
/** Register CSRF, model login, logout and refresh using the browser auth contract. */
|
package/dist/Router/Route.js
CHANGED
|
@@ -77,6 +77,10 @@ class RouteFacade {
|
|
|
77
77
|
get(path, component, options) {
|
|
78
78
|
this.registerWithGroupContext("GET", path, component, options);
|
|
79
79
|
}
|
|
80
|
+
/** Register a HEAD route, for metadata without a response body. */
|
|
81
|
+
head(path, component, options) {
|
|
82
|
+
this.registerWithGroupContext("HEAD", path, component, options);
|
|
83
|
+
}
|
|
80
84
|
/** Register the existing DataBuilder POST protocol with request-local configuration. */
|
|
81
85
|
databuilder(path, options = {}) {
|
|
82
86
|
this.registerWithGroupContext("POST", path, (0, DataBuilderRoute_1.dataBuilderRoute)(options), { middleware: options.middleware, domains: options.domains });
|
package/dist/Router/Router.d.ts
CHANGED
|
@@ -43,6 +43,10 @@ declare class RouterFacade {
|
|
|
43
43
|
routesGET: {
|
|
44
44
|
[key: string]: RouteObject[];
|
|
45
45
|
};
|
|
46
|
+
/** Explicit HEAD routes, with the same middleware and domain matching as GET. */
|
|
47
|
+
routesHEAD: {
|
|
48
|
+
[key: string]: RouteObject[];
|
|
49
|
+
};
|
|
46
50
|
/**
|
|
47
51
|
* POST Route Store
|
|
48
52
|
*/
|
package/dist/Router/Router.js
CHANGED
|
@@ -53,6 +53,8 @@ class RouterFacade {
|
|
|
53
53
|
* GET Route Store
|
|
54
54
|
*/
|
|
55
55
|
this.routesGET = {};
|
|
56
|
+
/** Explicit HEAD routes, with the same middleware and domain matching as GET. */
|
|
57
|
+
this.routesHEAD = {};
|
|
56
58
|
/**
|
|
57
59
|
* POST Route Store
|
|
58
60
|
*/
|
|
@@ -86,6 +88,7 @@ class RouterFacade {
|
|
|
86
88
|
? options.maxRequestBodySizeBytes
|
|
87
89
|
: 10 * 1024 * 1024;
|
|
88
90
|
this.routesGET = {};
|
|
91
|
+
this.routesHEAD = {};
|
|
89
92
|
this.routesPOST = {};
|
|
90
93
|
this.routesPUT = {};
|
|
91
94
|
this.routesPATCH = {};
|
|
@@ -153,6 +156,12 @@ class RouterFacade {
|
|
|
153
156
|
}
|
|
154
157
|
this.routesGET[path].push(routeConf);
|
|
155
158
|
}
|
|
159
|
+
else if (type === "HEAD") {
|
|
160
|
+
if (!this.routesHEAD[path]) {
|
|
161
|
+
this.routesHEAD[path] = [];
|
|
162
|
+
}
|
|
163
|
+
this.routesHEAD[path].push(routeConf);
|
|
164
|
+
}
|
|
156
165
|
else if (type === "POST") {
|
|
157
166
|
if (!this.routesPOST[path]) {
|
|
158
167
|
this.routesPOST[path] = [];
|
|
@@ -196,6 +205,9 @@ class RouterFacade {
|
|
|
196
205
|
if (req.method === "GET") {
|
|
197
206
|
return this.dissolveRoute(this.routesGET, cleanUrl, req);
|
|
198
207
|
}
|
|
208
|
+
else if (req.method === "HEAD") {
|
|
209
|
+
return this.dissolveRoute(this.routesHEAD, cleanUrl, req);
|
|
210
|
+
}
|
|
199
211
|
else if (req.method === "POST") {
|
|
200
212
|
return this.dissolveRoute(this.routesPOST, cleanUrl, req);
|
|
201
213
|
}
|
|
@@ -212,6 +224,9 @@ class RouterFacade {
|
|
|
212
224
|
if (req.headers["access-control-request-method"] === "GET") {
|
|
213
225
|
return this.dissolveRoute(this.routesGET, cleanUrl, req);
|
|
214
226
|
}
|
|
227
|
+
else if (req.headers["access-control-request-method"] === "HEAD") {
|
|
228
|
+
return this.dissolveRoute(this.routesHEAD, cleanUrl, req);
|
|
229
|
+
}
|
|
215
230
|
else if (req.headers["access-control-request-method"] === "POST") {
|
|
216
231
|
return this.dissolveRoute(this.routesPOST, cleanUrl, req);
|
|
217
232
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -76,3 +76,4 @@ export { ModelForm, ModelFormContext, ModelFormConstructor } from "./DataBuilder
|
|
|
76
76
|
export { Field, Validates, Forms, DataBuilderFieldOptions } from "./DataBuilder/decorators";
|
|
77
77
|
export { DataBuilderRouteOptions } from "./DataBuilder/DataBuilderRoute";
|
|
78
78
|
export { LegacyFieldTypeAdapter } from "./DataBuilder/LegacyFieldTypeAdapter";
|
|
79
|
+
export { defaultFormFields } from "./DataBuilder/formScope";
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.LegacyFieldTypeAdapter = exports.Forms = exports.Validates = exports.Field = exports.ModelForm = void 0;
|
|
17
|
+
exports.defaultFormFields = exports.LegacyFieldTypeAdapter = exports.Forms = exports.Validates = exports.Field = exports.ModelForm = void 0;
|
|
18
18
|
__exportStar(require("./Config"), exports);
|
|
19
19
|
__exportStar(require("./Functions/DateFunctions"), exports);
|
|
20
20
|
__exportStar(require("./Functions/FileFunctions"), exports);
|
|
@@ -96,3 +96,5 @@ Object.defineProperty(exports, "Validates", { enumerable: true, get: function ()
|
|
|
96
96
|
Object.defineProperty(exports, "Forms", { enumerable: true, get: function () { return decorators_1.Forms; } });
|
|
97
97
|
var LegacyFieldTypeAdapter_1 = require("./DataBuilder/LegacyFieldTypeAdapter");
|
|
98
98
|
Object.defineProperty(exports, "LegacyFieldTypeAdapter", { enumerable: true, get: function () { return LegacyFieldTypeAdapter_1.LegacyFieldTypeAdapter; } });
|
|
99
|
+
var formScope_1 = require("./DataBuilder/formScope");
|
|
100
|
+
Object.defineProperty(exports, "defaultFormFields", { enumerable: true, get: function () { return formScope_1.defaultFormFields; } });
|
package/docs/databuilder.md
CHANGED
|
@@ -32,6 +32,11 @@ Metadata is inherited without mutating parent definitions. Decorated definitions
|
|
|
32
32
|
|
|
33
33
|
Without registered forms or legacy `__forms`, decorated models get a default form containing their fields, including child layouts. Existing `__schema` still carries version, collection, hooks, aggregation, uniqueness, new-data and deletion behavior. Defining `static forms = () => [UserProfileForm]` is an alternative to `@Forms()`; the decorator takes precedence.
|
|
34
34
|
|
|
35
|
+
For dynamic sections inside an explicit layout, import `defaultFormFields` from
|
|
36
|
+
`@webtypen/webframez-core` and use `{ field: "attributes", fields: defaultFormFields(attributeSchema) }`.
|
|
37
|
+
It recursively supplies the `fields` layouts for object and array schemas, including
|
|
38
|
+
objects inside array entries. It does not modify the schema or populate data values.
|
|
39
|
+
|
|
35
40
|
## Server-side form classes
|
|
36
41
|
|
|
37
42
|
```ts
|
package/package.json
CHANGED