laravel-workers 0.4.0 → 0.4.1

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.
@@ -1,123 +1,123 @@
1
- // kernel/validation.mjs — ValidationException + the session error-bag shape.
2
- //
3
- // Mirrors the parts of Laravel the compiled rung needs to turn a failed
4
- // `$request->validate()` into the same redirect a real app produces:
5
- // - Illuminate\Validation\ValidationException (status 422, errorBag, redirectTo,
6
- // summarize() message)
7
- // - Illuminate\Foundation\Exceptions\Handler::dontFlash (inputs never flashed back)
8
- // - Illuminate\Http\RedirectResponse::withErrors()/withInput() ->
9
- // session flash 'errors' + '_old_input'
10
- // - Illuminate\Session\Store::prepareErrorBagForSerialization() (json sessions
11
- // store the error bag as { bag: { format, messages } })
12
- //
13
- // The actual rule engine is kernel/validator.mjs. This module only owns the
14
- // exception surface and the on-disk bag shape.
15
- import { validate as runValidator } from './validator.mjs';
16
-
17
- // Illuminate\Foundation\Exceptions\Handler::$dontFlash (13.x default).
18
- export const DEFAULT_DONT_FLASH = ['current_password', 'password', 'password_confirmation'];
19
-
20
- // Illuminate\Support\MessageBag default format.
21
- export const MESSAGE_BAG_FORMAT = ':message';
22
-
23
- // Illuminate\Validation\ValidationException::summarize() — first message plus
24
- // "(and N more error(s))".
25
- export function summarizeValidation(errors) {
26
- const all = [];
27
- for (const field of Object.keys(errors || {})) {
28
- for (const m of errors[field]) all.push(m);
29
- }
30
- if (all.length === 0) return 'The given data was invalid.';
31
- const message = all.shift();
32
- const count = all.length;
33
- return count ? `${message} (and ${count} more error${count === 1 ? '' : 's'})` : message;
34
- }
35
-
36
- export class ValidationException extends Error {
37
- /**
38
- * @param {object} errors { field: [messages] } (validator->errors())
39
- * @param {object} [opts] { errorBag = 'default', redirectTo = null, status = 422 }
40
- */
41
- constructor(errors, opts = {}) {
42
- super(summarizeValidation(errors));
43
- this.name = 'ValidationException';
44
- this.validationErrors = errors;
45
- this.status = opts.status ?? 422;
46
- this.errorBag = opts.errorBag ?? 'default';
47
- this.redirectTo = opts.redirectTo ?? null;
48
- // Compiled controllers rethrow this marker so the HTTP kernel renders it
49
- // (redirect + flash) instead of rt.errorResponse() flattening it to a body.
50
- this.lwKernel = true;
51
- }
52
-
53
- /** ValidationException::errors() — { field: [messages] }. */
54
- errors() {
55
- return this.validationErrors;
56
- }
57
- }
58
-
59
- /**
60
- * Illuminate\Validation\ValidationException::withMessages() — build an exception
61
- * straight from a `{ field: message | [messages] }` map. Mirrors the vendor
62
- * implementation: `Arr::wrap()` each value and append through MessageBag::add()
63
- * (which skips duplicates), so `summarize()`/the flashed bag match byte-for-byte.
64
- */
65
- export function validationExceptionWithMessages(messages, opts = {}) {
66
- const errors = {};
67
- for (const key of Object.keys(messages || {})) {
68
- const value = messages[key];
69
- const list = Array.isArray(value) ? value : [value];
70
- for (const message of list) {
71
- const bucket = errors[key] || (errors[key] = []);
72
- if (!bucket.includes(message)) bucket.push(message);
73
- }
74
- }
75
- return new ValidationException(errors, opts);
76
- }
77
-
78
- /**
79
- * Attach `validate()` / `validateWithBag()` to a compiled request object
80
- * (Illuminate\Http\Request::validate / validateWithBag, via ValidatesRequests).
81
- *
82
- * @param {object} request the kernel request object (request.all() is the data)
83
- * @param {object} [opts] { db } — passed to the rule engine for unique/exists
84
- */
85
- export function installValidation(request, opts = {}) {
86
- const run = async (rules, messages = {}, attributes = {}, errorBag = 'default') => {
87
- const { ok, errors, validated } = await runValidator(request.all(), rules, messages, {
88
- db: opts.db ?? null,
89
- attributes,
90
- // The app's own validation messages (its published lang file wins over
91
- // the framework's copy, exactly like Laravel's translator).
92
- defaultMessages: opts.defaultMessages ?? null,
93
- });
94
- if (!ok) throw new ValidationException(errors, { errorBag });
95
- request._validatedData = validated;
96
- return validated;
97
- };
98
-
99
- request.validate = (rules, messages, attributes) => run(rules, messages, attributes);
100
- request.validateWithBag = (bag, rules, messages, attributes) =>
101
- run(rules, messages, attributes, bag);
102
- request.validated = () => (request._validatedData ? request._validatedData : {});
103
- return request;
104
- }
105
-
106
- /**
107
- * Illuminate\Http\RedirectResponse::withErrors() session value, in the shape
108
- * Illuminate\Session\Store::prepareErrorBagForSerialization() writes for json
109
- * sessions: `{ [bag]: { format: ':message', messages: { field: [msg] } } }`.
110
- */
111
- export function sessionErrorBag(bag, messages) {
112
- return { [bag]: { format: MESSAGE_BAG_FORMAT, messages } };
113
- }
114
-
115
- export default {
116
- ValidationException,
117
- validationExceptionWithMessages,
118
- installValidation,
119
- summarizeValidation,
120
- sessionErrorBag,
121
- DEFAULT_DONT_FLASH,
122
- MESSAGE_BAG_FORMAT,
123
- };
1
+ // kernel/validation.mjs — ValidationException + the session error-bag shape.
2
+ //
3
+ // Mirrors the parts of Laravel the compiled rung needs to turn a failed
4
+ // `$request->validate()` into the same redirect a real app produces:
5
+ // - Illuminate\Validation\ValidationException (status 422, errorBag, redirectTo,
6
+ // summarize() message)
7
+ // - Illuminate\Foundation\Exceptions\Handler::dontFlash (inputs never flashed back)
8
+ // - Illuminate\Http\RedirectResponse::withErrors()/withInput() ->
9
+ // session flash 'errors' + '_old_input'
10
+ // - Illuminate\Session\Store::prepareErrorBagForSerialization() (json sessions
11
+ // store the error bag as { bag: { format, messages } })
12
+ //
13
+ // The actual rule engine is kernel/validator.mjs. This module only owns the
14
+ // exception surface and the on-disk bag shape.
15
+ import { validate as runValidator } from './validator.mjs';
16
+
17
+ // Illuminate\Foundation\Exceptions\Handler::$dontFlash (13.x default).
18
+ export const DEFAULT_DONT_FLASH = ['current_password', 'password', 'password_confirmation'];
19
+
20
+ // Illuminate\Support\MessageBag default format.
21
+ export const MESSAGE_BAG_FORMAT = ':message';
22
+
23
+ // Illuminate\Validation\ValidationException::summarize() — first message plus
24
+ // "(and N more error(s))".
25
+ export function summarizeValidation(errors) {
26
+ const all = [];
27
+ for (const field of Object.keys(errors || {})) {
28
+ for (const m of errors[field]) all.push(m);
29
+ }
30
+ if (all.length === 0) return 'The given data was invalid.';
31
+ const message = all.shift();
32
+ const count = all.length;
33
+ return count ? `${message} (and ${count} more error${count === 1 ? '' : 's'})` : message;
34
+ }
35
+
36
+ export class ValidationException extends Error {
37
+ /**
38
+ * @param {object} errors { field: [messages] } (validator->errors())
39
+ * @param {object} [opts] { errorBag = 'default', redirectTo = null, status = 422 }
40
+ */
41
+ constructor(errors, opts = {}) {
42
+ super(summarizeValidation(errors));
43
+ this.name = 'ValidationException';
44
+ this.validationErrors = errors;
45
+ this.status = opts.status ?? 422;
46
+ this.errorBag = opts.errorBag ?? 'default';
47
+ this.redirectTo = opts.redirectTo ?? null;
48
+ // Compiled controllers rethrow this marker so the HTTP kernel renders it
49
+ // (redirect + flash) instead of rt.errorResponse() flattening it to a body.
50
+ this.lwKernel = true;
51
+ }
52
+
53
+ /** ValidationException::errors() — { field: [messages] }. */
54
+ errors() {
55
+ return this.validationErrors;
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Illuminate\Validation\ValidationException::withMessages() — build an exception
61
+ * straight from a `{ field: message | [messages] }` map. Mirrors the vendor
62
+ * implementation: `Arr::wrap()` each value and append through MessageBag::add()
63
+ * (which skips duplicates), so `summarize()`/the flashed bag match byte-for-byte.
64
+ */
65
+ export function validationExceptionWithMessages(messages, opts = {}) {
66
+ const errors = {};
67
+ for (const key of Object.keys(messages || {})) {
68
+ const value = messages[key];
69
+ const list = Array.isArray(value) ? value : [value];
70
+ for (const message of list) {
71
+ const bucket = errors[key] || (errors[key] = []);
72
+ if (!bucket.includes(message)) bucket.push(message);
73
+ }
74
+ }
75
+ return new ValidationException(errors, opts);
76
+ }
77
+
78
+ /**
79
+ * Attach `validate()` / `validateWithBag()` to a compiled request object
80
+ * (Illuminate\Http\Request::validate / validateWithBag, via ValidatesRequests).
81
+ *
82
+ * @param {object} request the kernel request object (request.all() is the data)
83
+ * @param {object} [opts] { db } — passed to the rule engine for unique/exists
84
+ */
85
+ export function installValidation(request, opts = {}) {
86
+ const run = async (rules, messages = {}, attributes = {}, errorBag = 'default') => {
87
+ const { ok, errors, validated } = await runValidator(request.all(), rules, messages, {
88
+ db: opts.db ?? null,
89
+ attributes,
90
+ // The app's own validation messages (its published lang file wins over
91
+ // the framework's copy, exactly like Laravel's translator).
92
+ defaultMessages: opts.defaultMessages ?? null,
93
+ });
94
+ if (!ok) throw new ValidationException(errors, { errorBag });
95
+ request._validatedData = validated;
96
+ return validated;
97
+ };
98
+
99
+ request.validate = (rules, messages, attributes) => run(rules, messages, attributes);
100
+ request.validateWithBag = (bag, rules, messages, attributes) =>
101
+ run(rules, messages, attributes, bag);
102
+ request.validated = () => (request._validatedData ? request._validatedData : {});
103
+ return request;
104
+ }
105
+
106
+ /**
107
+ * Illuminate\Http\RedirectResponse::withErrors() session value, in the shape
108
+ * Illuminate\Session\Store::prepareErrorBagForSerialization() writes for json
109
+ * sessions: `{ [bag]: { format: ':message', messages: { field: [msg] } } }`.
110
+ */
111
+ export function sessionErrorBag(bag, messages) {
112
+ return { [bag]: { format: MESSAGE_BAG_FORMAT, messages } };
113
+ }
114
+
115
+ export default {
116
+ ValidationException,
117
+ validationExceptionWithMessages,
118
+ installValidation,
119
+ summarizeValidation,
120
+ sessionErrorBag,
121
+ DEFAULT_DONT_FLASH,
122
+ MESSAGE_BAG_FORMAT,
123
+ };
package/package.json CHANGED
@@ -1,69 +1,69 @@
1
- {
2
- "name": "laravel-workers",
3
- "version": "0.4.0",
4
- "description": "Build-time toolchain: compile a Laravel app's Blade views, routes and D1 read paths to a Cloudflare Workers artifact (static + snapshot + compiled handlers); unsupported constructs fail the build",
5
- "type": "module",
6
- "license": "MIT",
7
- "author": "arfoux",
8
- "repository": {
9
- "type": "git",
10
- "url": "git+https://github.com/arfoux/laravel-workers.git"
11
- },
12
- "homepage": "https://github.com/arfoux/laravel-workers#readme",
13
- "bugs": {
14
- "url": "https://github.com/arfoux/laravel-workers/issues"
15
- },
16
- "keywords": [
17
- "laravel",
18
- "cloudflare",
19
- "workers",
20
- "edge",
21
- "d1",
22
- "blade",
23
- "transpiler",
24
- "workers-native",
25
- "build-time",
26
- "toolchain"
27
- ],
28
- "bin": {
29
- "laravel-workers": "bin/laravel-workers.mjs"
30
- },
31
- "files": [
32
- "bin",
33
- "build.mjs",
34
- "compiler/bin",
35
- "compiler/src",
36
- "compiler/runtime",
37
- "kernel",
38
- "src",
39
- "tools",
40
- "shadow",
41
- "!tools/pack-smoke.mjs"
42
- ],
43
- "scripts": {
44
- "setup": "npm install && npm --prefix compiler install",
45
- "test": "node --test kernel/tests/router.test.mjs kernel/tests/db.test.mjs kernel/tests/sqlite-integration.test.mjs kernel/tests/hash.test.mjs kernel/tests/encrypter.test.mjs kernel/tests/validator.test.mjs kernel/tests/services.test.mjs kernel/tests/str.test.mjs kernel/tests/routes-json.test.mjs kernel/tests/registry-json.test.mjs kernel/tests/ports.test.mjs kernel/tests/budget.test.mjs kernel/tests/paginator.test.mjs kernel/tests/php-serialize.test.mjs kernel/tests/php-json.test.mjs kernel/tests/cookies.test.mjs kernel/tests/session.test.mjs kernel/tests/ratelimit.test.mjs kernel/tests/cache.test.mjs kernel/tests/storage.test.mjs kernel/tests/image.test.mjs kernel/tests/collections.test.mjs compiler/tests/queue.test.mjs kernel/tests/redis.test.mjs kernel/tests/model.test.mjs kernel/tests/resources.test.mjs kernel/tests/csrf.test.mjs kernel/tests/auth.test.mjs kernel/tests/http.test.mjs kernel/tests/validation.test.mjs kernel/tests/login-flow.test.mjs kernel/tests/upload.test.mjs kernel/tests/validation-messages.test.mjs kernel/tests/validator-hooks.test.mjs compiler/tests/controller.test.mjs compiler/tests/classes.test.mjs compiler/tests/policy.test.mjs compiler/tests/request-call-consistency.test.mjs compiler/tests/source-syntax.test.mjs compiler/tests/dist-swap.test.mjs compiler/tests/resource-class.test.mjs compiler/tests/relation-property.test.mjs compiler/tests/model-accessor.test.mjs compiler/tests/allowlist-surface.test.mjs compiler/tests/rt-str.test.mjs compiler/tests/rt-arith.test.mjs compiler/tests/rt-json.test.mjs compiler/tests/rt-semantics.test.mjs compiler/tests/rt-semantics2.test.mjs compiler/tests/rt-break.test.mjs compiler/tests/rt-increment.test.mjs compiler/tests/rt-mail.test.mjs compiler/tests/mail-reach.test.mjs compiler/tests/inline-class-call.test.mjs compiler/tests/mail-views-dump.test.mjs compiler/tests/rt-blade.test.mjs compiler/tests/formrequest-dump.test.mjs compiler/tests/formrequest-lifecycle.test.mjs kernel/tests/readiness.test.mjs",
46
- "test:db": "node --test kernel/tests/db.test.mjs",
47
- "test:sqlite": "node --test kernel/tests/sqlite-integration.test.mjs",
48
- "test:hash": "node --test kernel/tests/hash.test.mjs kernel/tests/encrypter.test.mjs",
49
- "test:validator": "node --test kernel/tests/validator.test.mjs",
50
- "test:corpus": "node compiler/tests/run-corpus.mjs",
51
- "build": "node build.mjs --strict",
52
- "verify": "node bin/laravel-workers.mjs verify",
53
- "test:services": "node --test kernel/tests/services.test.mjs",
54
- "test:budget": "node --test kernel/tests/budget.test.mjs",
55
- "check:docs": "node tools/gate.mjs",
56
- "bench": "node tools/bench.mjs",
57
- "test:shadow": "node shadow/run.mjs",
58
- "test:pack": "node tools/pack-smoke.mjs",
59
- "audit:constructs": "node tools/construct-audit.mjs",
60
- "test:str": "node --test kernel/tests/str.test.mjs"
61
- },
62
- "engines": {
63
- "node": ">=22"
64
- },
65
- "dependencies": {
66
- "bcryptjs": "2.4.3",
67
- "php-parser": "3.7.0"
68
- }
69
- }
1
+ {
2
+ "name": "laravel-workers",
3
+ "version": "0.4.1",
4
+ "description": "Build-time toolchain: compile a Laravel app's Blade views, routes and D1 read paths to a Cloudflare Workers artifact (static + snapshot + compiled handlers); unsupported constructs fail the build",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "arfoux",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/arfoux/laravel-workers.git"
11
+ },
12
+ "homepage": "https://github.com/arfoux/laravel-workers#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/arfoux/laravel-workers/issues"
15
+ },
16
+ "keywords": [
17
+ "laravel",
18
+ "cloudflare",
19
+ "workers",
20
+ "edge",
21
+ "d1",
22
+ "blade",
23
+ "transpiler",
24
+ "workers-native",
25
+ "build-time",
26
+ "toolchain"
27
+ ],
28
+ "bin": {
29
+ "laravel-workers": "bin/laravel-workers.mjs"
30
+ },
31
+ "files": [
32
+ "bin",
33
+ "build.mjs",
34
+ "compiler/bin",
35
+ "compiler/src",
36
+ "compiler/runtime",
37
+ "kernel",
38
+ "src",
39
+ "tools",
40
+ "shadow",
41
+ "!tools/pack-smoke.mjs"
42
+ ],
43
+ "scripts": {
44
+ "setup": "npm install && npm --prefix compiler install",
45
+ "test": "node --test kernel/tests/router.test.mjs kernel/tests/db.test.mjs kernel/tests/sqlite-integration.test.mjs kernel/tests/hash.test.mjs kernel/tests/encrypter.test.mjs kernel/tests/validator.test.mjs kernel/tests/services.test.mjs kernel/tests/str.test.mjs kernel/tests/routes-json.test.mjs kernel/tests/registry-json.test.mjs kernel/tests/ports.test.mjs kernel/tests/budget.test.mjs kernel/tests/paginator.test.mjs kernel/tests/php-serialize.test.mjs kernel/tests/php-json.test.mjs kernel/tests/cookies.test.mjs kernel/tests/session.test.mjs kernel/tests/ratelimit.test.mjs kernel/tests/cache.test.mjs kernel/tests/storage.test.mjs kernel/tests/image.test.mjs kernel/tests/collections.test.mjs compiler/tests/queue.test.mjs kernel/tests/redis.test.mjs kernel/tests/model.test.mjs kernel/tests/resources.test.mjs kernel/tests/csrf.test.mjs kernel/tests/auth.test.mjs kernel/tests/http.test.mjs kernel/tests/validation.test.mjs kernel/tests/login-flow.test.mjs kernel/tests/upload.test.mjs kernel/tests/validation-messages.test.mjs kernel/tests/validator-hooks.test.mjs compiler/tests/controller.test.mjs compiler/tests/classes.test.mjs compiler/tests/policy.test.mjs compiler/tests/request-call-consistency.test.mjs compiler/tests/source-syntax.test.mjs compiler/tests/dist-swap.test.mjs compiler/tests/resource-class.test.mjs compiler/tests/relation-property.test.mjs compiler/tests/model-accessor.test.mjs compiler/tests/allowlist-surface.test.mjs compiler/tests/rt-str.test.mjs compiler/tests/rt-arith.test.mjs compiler/tests/rt-json.test.mjs compiler/tests/rt-semantics.test.mjs compiler/tests/rt-semantics2.test.mjs compiler/tests/rt-break.test.mjs compiler/tests/rt-increment.test.mjs compiler/tests/rt-mail.test.mjs compiler/tests/mail-reach.test.mjs compiler/tests/inline-class-call.test.mjs compiler/tests/mail-views-dump.test.mjs compiler/tests/rt-blade.test.mjs compiler/tests/formrequest-dump.test.mjs compiler/tests/formrequest-lifecycle.test.mjs kernel/tests/readiness.test.mjs",
46
+ "test:db": "node --test kernel/tests/db.test.mjs",
47
+ "test:sqlite": "node --test kernel/tests/sqlite-integration.test.mjs",
48
+ "test:hash": "node --test kernel/tests/hash.test.mjs kernel/tests/encrypter.test.mjs",
49
+ "test:validator": "node --test kernel/tests/validator.test.mjs",
50
+ "test:corpus": "node compiler/tests/run-corpus.mjs",
51
+ "build": "node build.mjs --strict",
52
+ "verify": "node bin/laravel-workers.mjs verify",
53
+ "test:services": "node --test kernel/tests/services.test.mjs",
54
+ "test:budget": "node --test kernel/tests/budget.test.mjs",
55
+ "check:docs": "node tools/gate.mjs",
56
+ "bench": "node tools/bench.mjs",
57
+ "test:shadow": "node shadow/run.mjs",
58
+ "test:pack": "node tools/pack-smoke.mjs",
59
+ "audit:constructs": "node tools/construct-audit.mjs",
60
+ "test:str": "node --test kernel/tests/str.test.mjs"
61
+ },
62
+ "engines": {
63
+ "node": ">=22"
64
+ },
65
+ "dependencies": {
66
+ "bcryptjs": "2.4.3",
67
+ "php-parser": "3.7.0"
68
+ }
69
+ }