ruact 0.0.11 → 0.0.13
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +147 -48
- data/CONTRIBUTING.md +233 -0
- data/README.md +18 -8
- data/RELEASING.md +125 -139
- data/lib/generators/ruact/install/install_generator.rb +305 -126
- data/lib/generators/ruact/install/templates/AGENTS.md.tt +14 -13
- data/lib/generators/ruact/install/templates/initializer.rb.tt +29 -7
- data/lib/generators/ruact/install/templates/tsconfig.json.tt +3 -0
- data/lib/generators/ruact/layout/layout_generator.rb +52 -0
- data/lib/generators/ruact/scaffold/templates/controller.rb.tt +5 -3
- data/lib/ruact/configuration.rb +65 -13
- data/lib/ruact/controller/document_rendering.rb +72 -16
- data/lib/ruact/controller/page_rendering.rb +134 -0
- data/lib/ruact/controller/pages.rb +116 -0
- data/lib/ruact/controller.rb +78 -11
- data/lib/ruact/doctor.rb +233 -25
- data/lib/ruact/layout_source.rb +29 -7
- data/lib/ruact/navigation_boundary.rb +240 -0
- data/lib/ruact/packaging.rb +68 -0
- data/lib/ruact/railtie.rb +30 -0
- data/lib/ruact/server.rb +10 -1
- data/lib/ruact/version.rb +1 -1
- data/lib/ruact/view_helper.rb +158 -1
- data/lib/ruact/views/layouts/ruact.html.erb +32 -0
- data/lib/ruact.rb +29 -0
- data/vendor/javascript/vite-plugin-ruact/flight-client.test.mjs +321 -0
- data/vendor/javascript/vite-plugin-ruact/package-lock.json +11 -0
- data/vendor/javascript/vite-plugin-ruact/package.json +1 -0
- data/vendor/javascript/vite-plugin-ruact/ruact-router.test.mjs +433 -0
- data/vendor/javascript/vite-plugin-ruact/runtime/flight-client.js +14 -3
- data/vendor/javascript/vite-plugin-ruact/runtime/ruact-router.js +170 -7
- metadata +12 -107
- data/.codecov.yml +0 -31
- data/.github/workflows/ci.yml +0 -284
- data/.github/workflows/server-functions-bench.yml +0 -54
- data/.rubocop.yml +0 -107
- data/.rubocop_todo.yml +0 -63
- data/Rakefile +0 -10
- data/bench/server_functions_dispatch_bench.rb +0 -276
- data/bench/server_functions_dispatch_bench.results.md +0 -150
- data/docs/internal/README.md +0 -9
- data/docs/internal/decisions/server-functions-api.md +0 -2236
- data/spec/benchmarks/baseline.json +0 -12
- data/spec/benchmarks/render_pipeline_benchmark_spec.rb +0 -109
- data/spec/fixtures/flight/README.md +0 -136
- data/spec/fixtures/flight/array.txt +0 -1
- data/spec/fixtures/flight/as_json_object.txt +0 -2
- data/spec/fixtures/flight/bigint.txt +0 -1
- data/spec/fixtures/flight/boolean_false.txt +0 -1
- data/spec/fixtures/flight/boolean_true.txt +0 -1
- data/spec/fixtures/flight/client_component_with_props.txt +0 -2
- data/spec/fixtures/flight/client_reference.txt +0 -2
- data/spec/fixtures/flight/hash.txt +0 -1
- data/spec/fixtures/flight/infinity.txt +0 -1
- data/spec/fixtures/flight/nan.txt +0 -1
- data/spec/fixtures/flight/negative_infinity.txt +0 -1
- data/spec/fixtures/flight/nil.txt +0 -1
- data/spec/fixtures/flight/number_float.txt +0 -1
- data/spec/fixtures/flight/number_integer.txt +0 -1
- data/spec/fixtures/flight/react_element_no_props.txt +0 -1
- data/spec/fixtures/flight/redirect_row.txt +0 -1
- data/spec/fixtures/flight/serializable_object.txt +0 -2
- data/spec/fixtures/flight/string_basic.txt +0 -1
- data/spec/fixtures/flight/string_dollar_escape.txt +0 -1
- data/spec/fixtures/flight/undefined.txt +0 -1
- data/spec/fixtures/readme/children-error.html.erb +0 -3
- data/spec/fixtures/readme/children-error.txt +0 -1
- data/spec/fixtures/story_7_9_views/controller_request_spec_support/demo/show.html.erb +0 -3
- data/spec/fixtures/story_7_9_views/controller_request_spec_support/errors_demo/new.html.erb +0 -3
- data/spec/fixtures/story_7_9_views/controller_request_spec_support/exploding_layout_demo/show.html.erb +0 -3
- data/spec/fixtures/story_7_9_views/controller_request_spec_support/ghost_layout_demo/show.html.erb +0 -3
- data/spec/fixtures/story_7_9_views/controller_request_spec_support/layout_demo/show.html.erb +0 -3
- data/spec/fixtures/story_7_9_views/controller_request_spec_support/rootless_layout_demo/show.html.erb +0 -3
- data/spec/fixtures/story_7_9_views/controller_request_spec_support/unwired_layout_demo/show.html.erb +0 -3
- data/spec/fixtures/story_7_9_views/layouts/bare_host.html.erb +0 -16
- data/spec/fixtures/story_7_9_views/layouts/exploding_host.html.erb +0 -24
- data/spec/fixtures/story_7_9_views/layouts/rootless_host.html.erb +0 -15
- data/spec/fixtures/story_7_9_views/layouts/ruact_host.html.erb +0 -17
- data/spec/readme_demo_message_spec.rb +0 -67
- data/spec/readme_spec.rb +0 -282
- data/spec/ruact/client_manifest_spec.rb +0 -270
- data/spec/ruact/component_contract_spec.rb +0 -119
- data/spec/ruact/configuration_spec.rb +0 -518
- data/spec/ruact/controller_request_spec.rb +0 -671
- data/spec/ruact/controller_spec.rb +0 -343
- data/spec/ruact/doctor_spec.rb +0 -769
- data/spec/ruact/erb_preprocessor_hook_spec.rb +0 -55
- data/spec/ruact/erb_preprocessor_spec.rb +0 -361
- data/spec/ruact/errors_spec.rb +0 -93
- data/spec/ruact/flight/renderer_spec.rb +0 -133
- data/spec/ruact/flight/serializer_spec.rb +0 -494
- data/spec/ruact/html_converter_spec.rb +0 -375
- data/spec/ruact/install_generator_spec.rb +0 -1549
- data/spec/ruact/layout_source_spec.rb +0 -108
- data/spec/ruact/manifest_resolver_spec.rb +0 -174
- data/spec/ruact/query_request_spec.rb +0 -706
- data/spec/ruact/query_spec.rb +0 -105
- data/spec/ruact/railtie_spec.rb +0 -155
- data/spec/ruact/render_context_spec.rb +0 -58
- data/spec/ruact/render_pipeline_concurrency_spec.rb +0 -78
- data/spec/ruact/render_pipeline_spec.rb +0 -928
- data/spec/ruact/scaffold_generator_spec.rb +0 -1849
- data/spec/ruact/serializable_spec.rb +0 -179
- data/spec/ruact/server_bucket_request_spec.rb +0 -785
- data/spec/ruact/server_function_name_spec.rb +0 -53
- data/spec/ruact/server_functions/backtrace_cleaner_spec.rb +0 -63
- data/spec/ruact/server_functions/bucket_two_payload_spec.rb +0 -200
- data/spec/ruact/server_functions/codegen_spec.rb +0 -397
- data/spec/ruact/server_functions/error_payload_spec.rb +0 -222
- data/spec/ruact/server_functions/error_suggestion_spec.rb +0 -79
- data/spec/ruact/server_functions/introspection_spec.rb +0 -135
- data/spec/ruact/server_functions/name_bridge_spec.rb +0 -212
- data/spec/ruact/server_functions/query_context_spec.rb +0 -72
- data/spec/ruact/server_functions/query_source_spec.rb +0 -193
- data/spec/ruact/server_functions/railtie_integration_spec.rb +0 -215
- data/spec/ruact/server_functions/rake_spec.rb +0 -86
- data/spec/ruact/server_functions/route_source_spec.rb +0 -202
- data/spec/ruact/server_functions/snapshot_spec.rb +0 -96
- data/spec/ruact/server_functions/snapshot_writer_spec.rb +0 -71
- data/spec/ruact/server_rescue_request_spec.rb +0 -416
- data/spec/ruact/server_spec.rb +0 -179
- data/spec/ruact/server_upload_request_spec.rb +0 -311
- data/spec/ruact/signed_references_spec.rb +0 -164
- data/spec/ruact/string_distance_spec.rb +0 -38
- data/spec/ruact/tasks_json_introspection_spec.rb +0 -141
- data/spec/ruact/testing/have_ruact_component_spec.rb +0 -170
- data/spec/ruact/testing/no_production_load_spec.rb +0 -41
- data/spec/ruact/validation_errors_spec.rb +0 -116
- data/spec/ruact/view_helper_spec.rb +0 -131
- data/spec/spec_helper.rb +0 -77
- data/spec/support/fixtures/pixel.png +0 -0
- data/spec/support/flight_wire_parser.rb +0 -21
- data/spec/support/flight_wire_parser_spec.rb +0 -93
- data/spec/support/matchers/flight_fixture_matcher.rb +0 -130
- data/spec/support/matchers/flight_fixture_matcher_spec.rb +0 -250
- data/spec/support/rails_stub.rb +0 -115
|
@@ -275,6 +275,101 @@ function _buildFormData(form, submitter) {
|
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
// Story 17.0f — the navigation boundary
|
|
280
|
+
// ---------------------------------------------------------------------------
|
|
281
|
+
|
|
282
|
+
function _isNativeBoundary(response) {
|
|
283
|
+
return response.headers?.get("ruact-boundary") === "native";
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function _isFlight(response) {
|
|
287
|
+
return (response.headers?.get("content-type") || "").includes("text/x-component");
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// A full document load of the final URL (after any redirect the fetch
|
|
291
|
+
// followed). `replace` for back/forward, so no entry is pushed mid-history.
|
|
292
|
+
//
|
|
293
|
+
// `response.url` never carries the #fragment (Fetch strips it), so the one
|
|
294
|
+
// the link asked for is put back.
|
|
295
|
+
function _fullLoad(response, targetUrl, { replace = false } = {}) {
|
|
296
|
+
const requested = new URL(targetUrl, location.href);
|
|
297
|
+
const destination = new URL(response.url || requested.href);
|
|
298
|
+
if (!destination.hash && requested.hash) destination.hash = requested.hash;
|
|
299
|
+
if (replace) location.replace(destination.href);
|
|
300
|
+
else location.assign(destination.href);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function _escapedFormMessage(method, targetUrl, response) {
|
|
304
|
+
const path = new URL(targetUrl, location.href).pathname;
|
|
305
|
+
const type = response.headers?.get("content-type") || "no content type";
|
|
306
|
+
return `[ruact] ${method} ${path} answered ${response.status} with ${type}, not a ruact page. ` +
|
|
307
|
+
"The action already ran, so ruact will not submit the form again. " +
|
|
308
|
+
'Add data-ruact="false" to this <form> to let the browser submit it, ' +
|
|
309
|
+
"or have the action answer through ruact.";
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Submits the form as the browser would, WITHOUT dispatching a `submit` event —
|
|
313
|
+
// so neither this router nor Turbo intercepts it again. The browser only sends
|
|
314
|
+
// the clicked button's `name=value` (and honours its `formaction` / `formmethod`
|
|
315
|
+
// / `formtarget`) when that button is the submitter, which `submit()` has no way
|
|
316
|
+
// to express: both are carried over onto the form first.
|
|
317
|
+
//
|
|
318
|
+
// Everything added to the form is taken back right after: `submit()` builds its
|
|
319
|
+
// entry list synchronously, and a page that survives the submit (a download, a
|
|
320
|
+
// 204, a return from the back-forward cache) must not keep the last button's
|
|
321
|
+
// overrides and value for the next one.
|
|
322
|
+
//
|
|
323
|
+
// A form rendered by a React component has no `authenticity_token` field — the
|
|
324
|
+
// router's own fetch sent the token as a header. A native submit cannot, so the
|
|
325
|
+
// token from `<meta name="csrf-token">` goes in as a field, the way rails-ujs
|
|
326
|
+
// does it.
|
|
327
|
+
const _SUBMITTER_OVERRIDES = [
|
|
328
|
+
["formaction", "action"], ["formmethod", "method"], ["formtarget", "target"], ["formenctype", "enctype"],
|
|
329
|
+
];
|
|
330
|
+
|
|
331
|
+
function _nativeSubmit(form, submitter) {
|
|
332
|
+
const restore = [];
|
|
333
|
+
const added = [];
|
|
334
|
+
|
|
335
|
+
if (submitter) {
|
|
336
|
+
for (const [override, attribute] of _SUBMITTER_OVERRIDES) {
|
|
337
|
+
if (!submitter.hasAttribute(override)) continue;
|
|
338
|
+
restore.push([attribute, form.hasAttribute(attribute) ? form.getAttribute(attribute) : null]);
|
|
339
|
+
form.setAttribute(attribute, submitter.getAttribute(override));
|
|
340
|
+
}
|
|
341
|
+
if (submitter.name) added.push(_hiddenField(submitter.name, submitter.value));
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const csrfParam = document.querySelector('meta[name="csrf-param"]')?.content;
|
|
345
|
+
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content;
|
|
346
|
+
if (csrfParam && csrfToken && !_hasField(form, csrfParam)) added.push(_hiddenField(csrfParam, csrfToken));
|
|
347
|
+
|
|
348
|
+
added.forEach((field) => form.appendChild(field));
|
|
349
|
+
try {
|
|
350
|
+
HTMLFormElement.prototype.submit.call(form);
|
|
351
|
+
} finally {
|
|
352
|
+
added.forEach((field) => field.remove?.());
|
|
353
|
+
restore.forEach(([attribute, value]) => {
|
|
354
|
+
if (value === null) form.removeAttribute?.(attribute);
|
|
355
|
+
else form.setAttribute(attribute, value);
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function _hiddenField(name, value) {
|
|
361
|
+
const field = document.createElement("input");
|
|
362
|
+
field.type = "hidden";
|
|
363
|
+
field.name = name;
|
|
364
|
+
field.value = value;
|
|
365
|
+
return field;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function _hasField(form, name) {
|
|
369
|
+
const quoted = name.replace(/["\\]/g, "\\$&");
|
|
370
|
+
return Boolean(form.elements?.namedItem?.(name) ?? form.querySelector?.(`[name="${quoted}"]`));
|
|
371
|
+
}
|
|
372
|
+
|
|
278
373
|
async function _submitForm(form, submitter = null) {
|
|
279
374
|
clearPendingChunks();
|
|
280
375
|
|
|
@@ -317,7 +412,18 @@ async function _submitForm(form, submitter = null) {
|
|
|
317
412
|
headers,
|
|
318
413
|
signal: controller.signal,
|
|
319
414
|
});
|
|
320
|
-
|
|
415
|
+
// Story 17.0f — not a ruact page, and the action did NOT run: this native
|
|
416
|
+
// submit is its one and only run, and its real response (a 422 with the
|
|
417
|
+
// validation errors included) is what the user sees.
|
|
418
|
+
if (_isNativeBoundary(response)) {
|
|
419
|
+
// The boundary answer came at the END of a redirect the fetch followed:
|
|
420
|
+
// the form's action already ran (a real 3xx, e.g. to another scheme), and
|
|
421
|
+
// resubmitting would run it twice. Load where it redirected to instead.
|
|
422
|
+
if (response.redirected) _fullLoad(response, action);
|
|
423
|
+
else _nativeSubmit(form, submitter);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
await _processFlightResponse(response, { push: true, targetUrl: action, method: htmlMethod });
|
|
321
427
|
} catch (err) {
|
|
322
428
|
if (err.name === "AbortError") return;
|
|
323
429
|
console.error("[ruact-router] Form submission error:", err);
|
|
@@ -330,7 +436,9 @@ async function _submitForm(form, submitter = null) {
|
|
|
330
436
|
// ---------------------------------------------------------------------------
|
|
331
437
|
|
|
332
438
|
function handlePopstate() {
|
|
333
|
-
|
|
439
|
+
// Story 17.0f — `replace`: if this entry turns out not to be a ruact page, the
|
|
440
|
+
// full load must not push a NEW entry into the history being walked.
|
|
441
|
+
navigate(location.pathname + location.search + location.hash, { push: false, scroll: false, replace: true });
|
|
334
442
|
}
|
|
335
443
|
|
|
336
444
|
// ---------------------------------------------------------------------------
|
|
@@ -346,7 +454,7 @@ function handlePopstate() {
|
|
|
346
454
|
* REJECTS on a failed Flight fetch — without this, callers cannot
|
|
347
455
|
* branch on success vs. failure of a programmatic refetch.
|
|
348
456
|
*/
|
|
349
|
-
async function navigate(url, { push = true, scroll = true, throwOnError = false } = {}) {
|
|
457
|
+
async function navigate(url, { push = true, scroll = true, throwOnError = false, replace = false } = {}) {
|
|
350
458
|
// Clear stale lazy refs from any previous streaming navigation
|
|
351
459
|
clearPendingChunks();
|
|
352
460
|
|
|
@@ -359,11 +467,21 @@ async function navigate(url, { push = true, scroll = true, throwOnError = false
|
|
|
359
467
|
headers: { Accept: "text/x-component", "Ruact-Request": "1" },
|
|
360
468
|
signal: controller.signal,
|
|
361
469
|
});
|
|
470
|
+
// Story 17.0f — the server said the destination is not a ruact page, and
|
|
471
|
+
// ran nothing to say so. The browser takes it from here.
|
|
472
|
+
if (_isNativeBoundary(response)) {
|
|
473
|
+
// A caller that asked to be told (revalidate) refetches the page it is
|
|
474
|
+
// ON; "not a ruact page" there is a failure to report, not a reload.
|
|
475
|
+
if (throwOnError) throw new Error(`[ruact] ${url} is not a ruact page`);
|
|
476
|
+
_fullLoad(response, url, { replace });
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
362
479
|
await _processFlightResponse(response, {
|
|
363
480
|
push,
|
|
364
481
|
targetUrl: url,
|
|
365
482
|
scroll,
|
|
366
483
|
throwOnError,
|
|
484
|
+
replace,
|
|
367
485
|
});
|
|
368
486
|
} catch (err) {
|
|
369
487
|
if (err.name === "AbortError") {
|
|
@@ -380,8 +498,47 @@ async function navigate(url, { push = true, scroll = true, throwOnError = false
|
|
|
380
498
|
// Shared Flight response processor (used by navigate + _submitForm)
|
|
381
499
|
// ---------------------------------------------------------------------------
|
|
382
500
|
|
|
383
|
-
async function _processFlightResponse(response, {
|
|
384
|
-
|
|
501
|
+
async function _processFlightResponse(response, {
|
|
502
|
+
push, targetUrl, scroll = true, throwOnError = false, replace = false, method = "GET",
|
|
503
|
+
}) {
|
|
504
|
+
// Story 17.0f — a response that is not Flight escaped the server's boundary
|
|
505
|
+
// classifier. Feeding it to the line parser was the old dead click: every HTML
|
|
506
|
+
// line parses to null, nothing renders, nothing reports.
|
|
507
|
+
//
|
|
508
|
+
// A non-Flight GET — a page, or an error page (404, 500, a 401 from auth) —
|
|
509
|
+
// is loaded in full so the user SEES it: the default app passes no onError,
|
|
510
|
+
// and a console line is a dead click by another name. Repeating a GET is
|
|
511
|
+
// harmless. A caller that asked to be told (`throwOnError`: revalidate)
|
|
512
|
+
// gets the error instead of a reload.
|
|
513
|
+
if (!_isFlight(response)) {
|
|
514
|
+
if (method === "GET" && !throwOnError) {
|
|
515
|
+
_fullLoad(response, targetUrl, { replace });
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
// A form whose action answered HTML — it ran, so it will not be resubmitted.
|
|
519
|
+
// Only a 2xx or a 422 is that; a 403 (CSRF) or a 500 is a failure, below.
|
|
520
|
+
if (method !== "GET" && (response.ok || response.status === 422)) {
|
|
521
|
+
const err = new Error(_escapedFormMessage(method, targetUrl, response));
|
|
522
|
+
console.error(err.message);
|
|
523
|
+
_onError?.(err);
|
|
524
|
+
if (throwOnError) throw err;
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
if (response.ok) {
|
|
528
|
+
const err = new Error(`[ruact] ${targetUrl} did not answer with a ruact response`);
|
|
529
|
+
console.error(err.message);
|
|
530
|
+
_onError?.(err);
|
|
531
|
+
if (throwOnError) throw err;
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Story 17.0i — a Flight 422 is a page: `render :new, status:
|
|
537
|
+
// :unprocessable_entity` re-rendering a form with its validation errors. The
|
|
538
|
+
// errors are the content, not a transport failure. Every other non-2xx stays
|
|
539
|
+
// a failure — an HTML 422 (Rails' own error page) included.
|
|
540
|
+
const unprocessable = response.status === 422 && _isFlight(response);
|
|
541
|
+
if (!response.ok && !unprocessable) {
|
|
385
542
|
const msg = `[ruact] Request failed: ${response.status} ${response.statusText}`;
|
|
386
543
|
console.error(msg);
|
|
387
544
|
const err = new Error(msg);
|
|
@@ -392,6 +549,12 @@ async function _processFlightResponse(response, { push, targetUrl, scroll = true
|
|
|
392
549
|
return;
|
|
393
550
|
}
|
|
394
551
|
|
|
552
|
+
// Story 17.0i — a form's 422 re-render keeps the form's URL: the POST URL is
|
|
553
|
+
// not one a reload or Back can ask for again (a reload of `/posts` would be
|
|
554
|
+
// the index). Unless the fetch followed a redirect: it then ended on a GET,
|
|
555
|
+
// and that URL is the page being shown.
|
|
556
|
+
const pushEntry = push && !(unprocessable && method !== "GET" && !response.redirected);
|
|
557
|
+
|
|
395
558
|
// Use final URL after any redirects (response.url is the resolved URL).
|
|
396
559
|
const finalPath = response.url
|
|
397
560
|
? (() => { const u = new URL(response.url); return u.pathname + u.search + u.hash; })()
|
|
@@ -422,7 +585,7 @@ async function _processFlightResponse(response, { push, targetUrl, scroll = true
|
|
|
422
585
|
}
|
|
423
586
|
// Normal case: build tree and render immediately.
|
|
424
587
|
const tree = buildTreeFromRows(rows, _moduleRegistry);
|
|
425
|
-
if (
|
|
588
|
+
if (pushEntry) history.pushState(null, "", finalPath);
|
|
426
589
|
_onNavigate(tree);
|
|
427
590
|
if (scroll) window.scrollTo(0, 0);
|
|
428
591
|
initialTreeSet = true;
|
|
@@ -466,7 +629,7 @@ async function _processFlightResponse(response, { push, targetUrl, scroll = true
|
|
|
466
629
|
// Fallback: if row 0 never triggered (shouldn't happen with valid server)
|
|
467
630
|
if (!initialTreeSet && !redirected && rows.has(0)) {
|
|
468
631
|
const tree = buildTreeFromRows(rows, _moduleRegistry);
|
|
469
|
-
if (
|
|
632
|
+
if (pushEntry) history.pushState(null, "", finalPath);
|
|
470
633
|
_onNavigate(tree);
|
|
471
634
|
if (scroll) window.scrollTo(0, 0);
|
|
472
635
|
}
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruact
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.13
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Luiz Garcia
|
|
8
8
|
autorequire:
|
|
9
|
-
bindir:
|
|
9
|
+
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-09-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: nokogiri
|
|
@@ -36,21 +36,12 @@ executables: []
|
|
|
36
36
|
extensions: []
|
|
37
37
|
extra_rdoc_files: []
|
|
38
38
|
files:
|
|
39
|
-
- ".codecov.yml"
|
|
40
|
-
- ".github/workflows/ci.yml"
|
|
41
|
-
- ".github/workflows/server-functions-bench.yml"
|
|
42
|
-
- ".rubocop.yml"
|
|
43
|
-
- ".rubocop_todo.yml"
|
|
44
39
|
- CHANGELOG.md
|
|
40
|
+
- CONTRIBUTING.md
|
|
45
41
|
- LICENSE.txt
|
|
46
42
|
- README.md
|
|
47
43
|
- RELEASING.md
|
|
48
|
-
- Rakefile
|
|
49
44
|
- SECURITY.md
|
|
50
|
-
- bench/server_functions_dispatch_bench.rb
|
|
51
|
-
- bench/server_functions_dispatch_bench.results.md
|
|
52
|
-
- docs/internal/README.md
|
|
53
|
-
- docs/internal/decisions/server-functions-api.md
|
|
54
45
|
- lib/generators/ruact/install/install_generator.rb
|
|
55
46
|
- lib/generators/ruact/install/templates/AGENTS.md.tt
|
|
56
47
|
- lib/generators/ruact/install/templates/Procfile.dev.tt
|
|
@@ -60,6 +51,7 @@ files:
|
|
|
60
51
|
- lib/generators/ruact/install/templates/package.json.tt
|
|
61
52
|
- lib/generators/ruact/install/templates/tsconfig.json.tt
|
|
62
53
|
- lib/generators/ruact/install/templates/vite.config.js.tt
|
|
54
|
+
- lib/generators/ruact/layout/layout_generator.rb
|
|
63
55
|
- lib/generators/ruact/scaffold/scaffold_attribute.rb
|
|
64
56
|
- lib/generators/ruact/scaffold/scaffold_form_helpers.rb
|
|
65
57
|
- lib/generators/ruact/scaffold/scaffold_generator.rb
|
|
@@ -84,6 +76,8 @@ files:
|
|
|
84
76
|
- lib/ruact/configuration.rb
|
|
85
77
|
- lib/ruact/controller.rb
|
|
86
78
|
- lib/ruact/controller/document_rendering.rb
|
|
79
|
+
- lib/ruact/controller/page_rendering.rb
|
|
80
|
+
- lib/ruact/controller/pages.rb
|
|
87
81
|
- lib/ruact/doctor.rb
|
|
88
82
|
- lib/ruact/erb_preprocessor.rb
|
|
89
83
|
- lib/ruact/erb_preprocessor_hook.rb
|
|
@@ -97,6 +91,8 @@ files:
|
|
|
97
91
|
- lib/ruact/html_converter.rb
|
|
98
92
|
- lib/ruact/layout_source.rb
|
|
99
93
|
- lib/ruact/manifest_resolver.rb
|
|
94
|
+
- lib/ruact/navigation_boundary.rb
|
|
95
|
+
- lib/ruact/packaging.rb
|
|
100
96
|
- lib/ruact/query.rb
|
|
101
97
|
- lib/ruact/railtie.rb
|
|
102
98
|
- lib/ruact/render_context.rb
|
|
@@ -132,6 +128,7 @@ files:
|
|
|
132
128
|
- lib/ruact/validation_errors_collector.rb
|
|
133
129
|
- lib/ruact/version.rb
|
|
134
130
|
- lib/ruact/view_helper.rb
|
|
131
|
+
- lib/ruact/views/layouts/ruact.html.erb
|
|
135
132
|
- lib/rubocop/cop/ruact.rb
|
|
136
133
|
- lib/rubocop/cop/ruact/no_extend_self.rb
|
|
137
134
|
- lib/rubocop/cop/ruact/no_io_in_flight.rb
|
|
@@ -139,112 +136,20 @@ files:
|
|
|
139
136
|
- lib/tasks/benchmark.rake
|
|
140
137
|
- lib/tasks/ruact.rake
|
|
141
138
|
- sig/ruact.rbs
|
|
142
|
-
- spec/benchmarks/baseline.json
|
|
143
|
-
- spec/benchmarks/render_pipeline_benchmark_spec.rb
|
|
144
|
-
- spec/fixtures/flight/README.md
|
|
145
|
-
- spec/fixtures/flight/array.txt
|
|
146
|
-
- spec/fixtures/flight/as_json_object.txt
|
|
147
|
-
- spec/fixtures/flight/bigint.txt
|
|
148
|
-
- spec/fixtures/flight/boolean_false.txt
|
|
149
|
-
- spec/fixtures/flight/boolean_true.txt
|
|
150
|
-
- spec/fixtures/flight/client_component_with_props.txt
|
|
151
|
-
- spec/fixtures/flight/client_reference.txt
|
|
152
|
-
- spec/fixtures/flight/hash.txt
|
|
153
|
-
- spec/fixtures/flight/infinity.txt
|
|
154
|
-
- spec/fixtures/flight/nan.txt
|
|
155
|
-
- spec/fixtures/flight/negative_infinity.txt
|
|
156
|
-
- spec/fixtures/flight/nil.txt
|
|
157
|
-
- spec/fixtures/flight/number_float.txt
|
|
158
|
-
- spec/fixtures/flight/number_integer.txt
|
|
159
|
-
- spec/fixtures/flight/react_element_no_props.txt
|
|
160
|
-
- spec/fixtures/flight/redirect_row.txt
|
|
161
|
-
- spec/fixtures/flight/serializable_object.txt
|
|
162
|
-
- spec/fixtures/flight/string_basic.txt
|
|
163
|
-
- spec/fixtures/flight/string_dollar_escape.txt
|
|
164
|
-
- spec/fixtures/flight/undefined.txt
|
|
165
|
-
- spec/fixtures/readme/children-error.html.erb
|
|
166
|
-
- spec/fixtures/readme/children-error.txt
|
|
167
|
-
- spec/fixtures/story_7_9_views/controller_request_spec_support/demo/show.html.erb
|
|
168
|
-
- spec/fixtures/story_7_9_views/controller_request_spec_support/errors_demo/new.html.erb
|
|
169
|
-
- spec/fixtures/story_7_9_views/controller_request_spec_support/exploding_layout_demo/show.html.erb
|
|
170
|
-
- spec/fixtures/story_7_9_views/controller_request_spec_support/ghost_layout_demo/show.html.erb
|
|
171
|
-
- spec/fixtures/story_7_9_views/controller_request_spec_support/layout_demo/show.html.erb
|
|
172
|
-
- spec/fixtures/story_7_9_views/controller_request_spec_support/rootless_layout_demo/show.html.erb
|
|
173
|
-
- spec/fixtures/story_7_9_views/controller_request_spec_support/unwired_layout_demo/show.html.erb
|
|
174
|
-
- spec/fixtures/story_7_9_views/layouts/bare_host.html.erb
|
|
175
|
-
- spec/fixtures/story_7_9_views/layouts/exploding_host.html.erb
|
|
176
|
-
- spec/fixtures/story_7_9_views/layouts/rootless_host.html.erb
|
|
177
|
-
- spec/fixtures/story_7_9_views/layouts/ruact_host.html.erb
|
|
178
|
-
- spec/readme_demo_message_spec.rb
|
|
179
|
-
- spec/readme_spec.rb
|
|
180
|
-
- spec/ruact/client_manifest_spec.rb
|
|
181
|
-
- spec/ruact/component_contract_spec.rb
|
|
182
|
-
- spec/ruact/configuration_spec.rb
|
|
183
|
-
- spec/ruact/controller_request_spec.rb
|
|
184
|
-
- spec/ruact/controller_spec.rb
|
|
185
|
-
- spec/ruact/doctor_spec.rb
|
|
186
|
-
- spec/ruact/erb_preprocessor_hook_spec.rb
|
|
187
|
-
- spec/ruact/erb_preprocessor_spec.rb
|
|
188
|
-
- spec/ruact/errors_spec.rb
|
|
189
|
-
- spec/ruact/flight/renderer_spec.rb
|
|
190
|
-
- spec/ruact/flight/serializer_spec.rb
|
|
191
|
-
- spec/ruact/html_converter_spec.rb
|
|
192
|
-
- spec/ruact/install_generator_spec.rb
|
|
193
|
-
- spec/ruact/layout_source_spec.rb
|
|
194
|
-
- spec/ruact/manifest_resolver_spec.rb
|
|
195
|
-
- spec/ruact/query_request_spec.rb
|
|
196
|
-
- spec/ruact/query_spec.rb
|
|
197
|
-
- spec/ruact/railtie_spec.rb
|
|
198
|
-
- spec/ruact/render_context_spec.rb
|
|
199
|
-
- spec/ruact/render_pipeline_concurrency_spec.rb
|
|
200
|
-
- spec/ruact/render_pipeline_spec.rb
|
|
201
|
-
- spec/ruact/scaffold_generator_spec.rb
|
|
202
|
-
- spec/ruact/serializable_spec.rb
|
|
203
|
-
- spec/ruact/server_bucket_request_spec.rb
|
|
204
|
-
- spec/ruact/server_function_name_spec.rb
|
|
205
|
-
- spec/ruact/server_functions/backtrace_cleaner_spec.rb
|
|
206
|
-
- spec/ruact/server_functions/bucket_two_payload_spec.rb
|
|
207
|
-
- spec/ruact/server_functions/codegen_spec.rb
|
|
208
|
-
- spec/ruact/server_functions/error_payload_spec.rb
|
|
209
|
-
- spec/ruact/server_functions/error_suggestion_spec.rb
|
|
210
|
-
- spec/ruact/server_functions/introspection_spec.rb
|
|
211
|
-
- spec/ruact/server_functions/name_bridge_spec.rb
|
|
212
|
-
- spec/ruact/server_functions/query_context_spec.rb
|
|
213
|
-
- spec/ruact/server_functions/query_source_spec.rb
|
|
214
|
-
- spec/ruact/server_functions/railtie_integration_spec.rb
|
|
215
|
-
- spec/ruact/server_functions/rake_spec.rb
|
|
216
|
-
- spec/ruact/server_functions/route_source_spec.rb
|
|
217
|
-
- spec/ruact/server_functions/snapshot_spec.rb
|
|
218
|
-
- spec/ruact/server_functions/snapshot_writer_spec.rb
|
|
219
|
-
- spec/ruact/server_rescue_request_spec.rb
|
|
220
|
-
- spec/ruact/server_spec.rb
|
|
221
|
-
- spec/ruact/server_upload_request_spec.rb
|
|
222
|
-
- spec/ruact/signed_references_spec.rb
|
|
223
|
-
- spec/ruact/string_distance_spec.rb
|
|
224
|
-
- spec/ruact/tasks_json_introspection_spec.rb
|
|
225
|
-
- spec/ruact/testing/have_ruact_component_spec.rb
|
|
226
|
-
- spec/ruact/testing/no_production_load_spec.rb
|
|
227
|
-
- spec/ruact/validation_errors_spec.rb
|
|
228
|
-
- spec/ruact/view_helper_spec.rb
|
|
229
|
-
- spec/spec_helper.rb
|
|
230
|
-
- spec/support/fixtures/pixel.png
|
|
231
|
-
- spec/support/flight_wire_parser.rb
|
|
232
|
-
- spec/support/flight_wire_parser_spec.rb
|
|
233
|
-
- spec/support/matchers/flight_fixture_matcher.rb
|
|
234
|
-
- spec/support/matchers/flight_fixture_matcher_spec.rb
|
|
235
|
-
- spec/support/rails_stub.rb
|
|
236
139
|
- vendor/javascript/ruact-server-functions-runtime/index.d.ts
|
|
237
140
|
- vendor/javascript/ruact-server-functions-runtime/index.js
|
|
238
141
|
- vendor/javascript/ruact-server-functions-runtime/index.test.mjs
|
|
239
142
|
- vendor/javascript/ruact-server-functions-runtime/package.json
|
|
240
143
|
- vendor/javascript/ruact-server-functions-runtime/usequery.test.mjs
|
|
241
144
|
- vendor/javascript/vite-plugin-ruact/bootstrap.test.mjs
|
|
145
|
+
- vendor/javascript/vite-plugin-ruact/flight-client.test.mjs
|
|
242
146
|
- vendor/javascript/vite-plugin-ruact/index.js
|
|
243
147
|
- vendor/javascript/vite-plugin-ruact/manifest-contract.test.mjs
|
|
244
148
|
- vendor/javascript/vite-plugin-ruact/manifest-http.test.mjs
|
|
245
149
|
- vendor/javascript/vite-plugin-ruact/package-lock.json
|
|
246
150
|
- vendor/javascript/vite-plugin-ruact/package.json
|
|
247
151
|
- vendor/javascript/vite-plugin-ruact/registry.test.mjs
|
|
152
|
+
- vendor/javascript/vite-plugin-ruact/ruact-router.test.mjs
|
|
248
153
|
- vendor/javascript/vite-plugin-ruact/runtime/bootstrap.jsx
|
|
249
154
|
- vendor/javascript/vite-plugin-ruact/runtime/flight-client.js
|
|
250
155
|
- vendor/javascript/vite-plugin-ruact/runtime/ruact-router.js
|
data/.codecov.yml
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# Codecov configuration for the ruact gem.
|
|
2
|
-
# Story 6.7 — coverage is informativo (not a CI gate); Codecov reports status
|
|
3
|
-
# but never fails a PR. Diff coverage targets (90% line / 80% branch) are
|
|
4
|
-
# project DoD, surfaced via the per-PR comment for visibility.
|
|
5
|
-
|
|
6
|
-
coverage:
|
|
7
|
-
status:
|
|
8
|
-
project:
|
|
9
|
-
default:
|
|
10
|
-
informational: true
|
|
11
|
-
target: auto
|
|
12
|
-
threshold: 1%
|
|
13
|
-
patch:
|
|
14
|
-
default:
|
|
15
|
-
informational: true
|
|
16
|
-
target: 90%
|
|
17
|
-
threshold: 0%
|
|
18
|
-
|
|
19
|
-
comment:
|
|
20
|
-
layout: "diff, files"
|
|
21
|
-
behavior: default
|
|
22
|
-
require_changes: false
|
|
23
|
-
|
|
24
|
-
flags:
|
|
25
|
-
gem:
|
|
26
|
-
# Paths are relative to the gem repo root (where this CI runs and uploads
|
|
27
|
-
# from). lcov.info emits source paths like `./lib/ruact.rb`; Codecov
|
|
28
|
-
# normalizes the leading `./` so a `lib/` prefix matches.
|
|
29
|
-
paths:
|
|
30
|
-
- lib/
|
|
31
|
-
carryforward: false
|