remote-entry.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. import { get_request_store, with_request_store } from "@sveltejs/kit/internal/server";
  2. import { parse } from "devalue";
  3. import { error, json } from "@sveltejs/kit";
  4. import { v as stringify_remote_arg, f as create_remote_key, w as unfriendly_hydratable, k as stringify, M as MUTATIVE_METHODS, x as create_field_proxy, y as normalize_issue, z as set_nested_value, A as flatten_issues, B as deep_set, h as handle_error_and_jsonify, p as parse_remote_arg } from "./chunks/shared.js";
  5. import { ValidationError, HttpError, SvelteKitError } from "@sveltejs/kit/internal";
  6. import { B as BROWSER } from "./chunks/false.js";
  7. import { b as base, c as app_dir, p as prerendering } from "./chunks/environment.js";
  8. function create_validator(validate_or_fn, maybe_fn) {
  9. if (!maybe_fn) {
  10. return (arg) => {
  11. if (arg !== void 0) {
  12. error(400, "Bad Request");
  13. }
  14. };
  15. }
  16. if (validate_or_fn === "unchecked") {
  17. return (arg) => arg;
  18. }
  19. if ("~standard" in validate_or_fn) {
  20. return async (arg) => {
  21. const { event, state } = get_request_store();
  22. const result = await validate_or_fn["~standard"].validate(arg);
  23. if (result.issues) {
  24. error(
  25. 400,
  26. await state.handleValidationError({
  27. issues: result.issues,
  28. event
  29. })
  30. );
  31. }
  32. return result.value;
  33. };
  34. }
  35. throw new Error(
  36. 'Invalid validator passed to remote function. Expected "unchecked" or a Standard Schema (https://standardschema.dev)'
  37. );
  38. }
  39. async function get_response(internals, arg, state, get_result) {
  40. await 0;
  41. const cache = get_cache(internals, state);
  42. const key = stringify_remote_arg(arg, state.transport);
  43. const entry = cache[key] ??= {
  44. serialize: false,
  45. data: get_result()
  46. };
  47. entry.serialize ||= !!state.is_in_universal_load;
  48. if (state.is_in_render && internals.id) {
  49. const remote_key = create_remote_key(internals.id, key);
  50. Promise.resolve(entry.data).then((value) => {
  51. void unfriendly_hydratable(remote_key, () => stringify(value, state.transport));
  52. }).catch(() => {
  53. });
  54. }
  55. return entry.data;
  56. }
  57. function parse_remote_response(data, transport) {
  58. const revivers = {};
  59. for (const key in transport) {
  60. revivers[key] = transport[key].decode;
  61. }
  62. return parse(data, revivers);
  63. }
  64. async function run_remote_function(event, state, allow_cookies, get_input, fn) {
  65. const store = {
  66. event: {
  67. ...event,
  68. setHeaders: () => {
  69. throw new Error("setHeaders is not allowed in remote functions");
  70. },
  71. cookies: {
  72. ...event.cookies,
  73. set: (name, value, opts) => {
  74. if (!allow_cookies) {
  75. throw new Error("Cannot set cookies in `query` or `prerender` functions");
  76. }
  77. if (opts.path && !opts.path.startsWith("/")) {
  78. throw new Error("Cookies set in remote functions must have an absolute path");
  79. }
  80. return event.cookies.set(name, value, opts);
  81. },
  82. delete: (name, opts) => {
  83. if (!allow_cookies) {
  84. throw new Error("Cannot delete cookies in `query` or `prerender` functions");
  85. }
  86. if (opts.path && !opts.path.startsWith("/")) {
  87. throw new Error("Cookies deleted in remote functions must have an absolute path");
  88. }
  89. return event.cookies.delete(name, opts);
  90. }
  91. }
  92. },
  93. state: {
  94. ...state,
  95. is_in_remote_function: true
  96. }
  97. };
  98. const input = await with_request_store(store, get_input);
  99. return with_request_store(store, () => fn(input));
  100. }
  101. function get_cache(internals, state = get_request_store().state) {
  102. let cache = state.remote.data?.get(internals);
  103. if (cache === void 0) {
  104. cache = {};
  105. (state.remote.data ??= /* @__PURE__ */ new Map()).set(internals, cache);
  106. }
  107. return cache;
  108. }
  109. // @__NO_SIDE_EFFECTS__
  110. function command(validate_or_fn, maybe_fn) {
  111. const fn = maybe_fn ?? validate_or_fn;
  112. const validate = create_validator(validate_or_fn, maybe_fn);
  113. const __ = { type: "command", id: "", name: "" };
  114. const wrapper = (arg) => {
  115. const { event, state } = get_request_store();
  116. if (!MUTATIVE_METHODS.includes(event.request.method)) {
  117. throw new Error(
  118. `Cannot call a command (\`${__.name}(${maybe_fn ? "..." : ""})\`) from a ${event.request.method} handler`
  119. );
  120. }
  121. if (state.is_in_render) {
  122. throw new Error(
  123. `Cannot call a command (\`${__.name}(${maybe_fn ? "..." : ""})\`) during server-side rendering`
  124. );
  125. }
  126. state.remote.refreshes ??= {};
  127. const promise = Promise.resolve(
  128. run_remote_function(event, state, true, () => validate(arg), fn)
  129. );
  130. promise.updates = () => {
  131. throw new Error(`Cannot call '${__.name}(...).updates(...)' on the server`);
  132. };
  133. return (
  134. /** @type {ReturnType<RemoteCommand<Input, Output>>} */
  135. promise
  136. );
  137. };
  138. Object.defineProperty(wrapper, "__", { value: __ });
  139. Object.defineProperty(wrapper, "pending", {
  140. get: () => 0
  141. });
  142. return wrapper;
  143. }
  144. // @__NO_SIDE_EFFECTS__
  145. function form(validate_or_fn, maybe_fn) {
  146. const fn = maybe_fn ?? validate_or_fn;
  147. const schema = !maybe_fn || validate_or_fn === "unchecked" ? null : (
  148. /** @type {any} */
  149. validate_or_fn
  150. );
  151. function create_instance(key) {
  152. const instance = {};
  153. instance.method = "POST";
  154. Object.defineProperty(instance, "enhance", {
  155. value: () => {
  156. return { action: instance.action, method: instance.method };
  157. }
  158. });
  159. const __ = {
  160. type: "form",
  161. name: "",
  162. id: "",
  163. fn: async (data, meta, form_data) => {
  164. const output = {};
  165. output.submission = true;
  166. const { event, state } = get_request_store();
  167. const validated = await schema?.["~standard"].validate(data);
  168. if (meta.validate_only) {
  169. return validated?.issues?.map((issue) => normalize_issue(issue, true)) ?? [];
  170. }
  171. if (validated?.issues !== void 0) {
  172. handle_issues(output, validated.issues, form_data);
  173. } else {
  174. if (validated !== void 0) {
  175. data = validated.value;
  176. }
  177. state.remote.refreshes ??= {};
  178. const issue = create_issues();
  179. try {
  180. output.result = await run_remote_function(
  181. event,
  182. state,
  183. true,
  184. () => data,
  185. (data2) => !maybe_fn ? fn() : fn(data2, issue)
  186. );
  187. } catch (e) {
  188. if (e instanceof ValidationError) {
  189. handle_issues(output, e.issues, form_data);
  190. } else {
  191. throw e;
  192. }
  193. }
  194. }
  195. if (!event.isRemoteRequest) {
  196. get_cache(__, state)[""] ??= { serialize: true, data: output };
  197. }
  198. return output;
  199. }
  200. };
  201. Object.defineProperty(instance, "__", { value: __ });
  202. Object.defineProperty(instance, "action", {
  203. get: () => `?/remote=${__.id}`,
  204. enumerable: true
  205. });
  206. Object.defineProperty(instance, "fields", {
  207. get() {
  208. return create_field_proxy(
  209. {},
  210. () => get_cache(__)?.[""]?.data?.input ?? {},
  211. (path, value) => {
  212. const cache = get_cache(__);
  213. const entry = cache[""];
  214. if (entry?.data?.submission) {
  215. return;
  216. }
  217. if (path.length === 0) {
  218. (cache[""] ??= { serialize: true, data: {} }).data.input = value;
  219. return;
  220. }
  221. const input = entry?.data?.input ?? {};
  222. deep_set(input, path.map(String), value);
  223. (cache[""] ??= { serialize: true, data: {} }).data.input = input;
  224. },
  225. () => flatten_issues(get_cache(__)?.[""]?.data?.issues ?? [])
  226. );
  227. }
  228. });
  229. Object.defineProperty(instance, "result", {
  230. get() {
  231. try {
  232. return get_cache(__)?.[""]?.data?.result;
  233. } catch {
  234. return void 0;
  235. }
  236. }
  237. });
  238. Object.defineProperty(instance, "pending", {
  239. get: () => 0
  240. });
  241. Object.defineProperty(instance, "preflight", {
  242. // preflight is a noop on the server
  243. value: () => instance
  244. });
  245. Object.defineProperty(instance, "validate", {
  246. value: () => {
  247. throw new Error("Cannot call validate() on the server");
  248. }
  249. });
  250. if (key == void 0) {
  251. Object.defineProperty(instance, "for", {
  252. /** @type {RemoteForm<any, any>['for']} */
  253. value: (key2) => {
  254. const { state } = get_request_store();
  255. const cache_key = __.id + "|" + JSON.stringify(key2);
  256. let instance2 = (state.remote.forms ??= /* @__PURE__ */ new Map()).get(cache_key);
  257. if (!instance2) {
  258. instance2 = create_instance(key2);
  259. instance2.__.id = `${__.id}/${encodeURIComponent(JSON.stringify(key2))}`;
  260. instance2.__.name = __.name;
  261. state.remote.forms.set(cache_key, instance2);
  262. }
  263. return instance2;
  264. }
  265. });
  266. }
  267. return instance;
  268. }
  269. return create_instance();
  270. }
  271. function handle_issues(output, issues, form_data) {
  272. output.issues = issues.map((issue) => normalize_issue(issue, true));
  273. if (form_data) {
  274. output.input = {};
  275. for (let key of form_data.keys()) {
  276. if (/^[.\]]?_/.test(key)) continue;
  277. const is_array = key.endsWith("[]");
  278. const values = form_data.getAll(key).filter((value) => typeof value === "string");
  279. if (is_array) key = key.slice(0, -2);
  280. set_nested_value(
  281. /** @type {Record<string, any>} */
  282. output.input,
  283. key,
  284. is_array ? values : values[0]
  285. );
  286. }
  287. }
  288. }
  289. function create_issues() {
  290. return (
  291. /** @type {InvalidField<any>} */
  292. new Proxy(
  293. /** @param {string} message */
  294. (message) => {
  295. if (typeof message !== "string") {
  296. throw new Error(
  297. "`invalid` should now be imported from `@sveltejs/kit` to throw validation issues. The second parameter provided to the form function (renamed to `issue`) is still used to construct issues, e.g. `invalid(issue.field('message'))`. For more info see https://github.com/sveltejs/kit/pulls/14768"
  298. );
  299. }
  300. return create_issue(message);
  301. },
  302. {
  303. get(target, prop) {
  304. if (typeof prop === "symbol") return (
  305. /** @type {any} */
  306. target[prop]
  307. );
  308. return create_issue_proxy(prop, []);
  309. }
  310. }
  311. )
  312. );
  313. function create_issue(message, path = []) {
  314. return {
  315. message,
  316. path
  317. };
  318. }
  319. function create_issue_proxy(key, path) {
  320. const new_path = [...path, key];
  321. const issue_func = (message) => create_issue(message, new_path);
  322. return new Proxy(issue_func, {
  323. get(target, prop) {
  324. if (typeof prop === "symbol") return (
  325. /** @type {any} */
  326. target[prop]
  327. );
  328. if (/^\d+$/.test(prop)) {
  329. return create_issue_proxy(parseInt(prop, 10), new_path);
  330. }
  331. return create_issue_proxy(prop, new_path);
  332. }
  333. });
  334. }
  335. }
  336. // @__NO_SIDE_EFFECTS__
  337. function prerender(validate_or_fn, fn_or_options, maybe_options) {
  338. const maybe_fn = typeof fn_or_options === "function" ? fn_or_options : void 0;
  339. const options = maybe_options ?? (maybe_fn ? void 0 : fn_or_options);
  340. const fn = maybe_fn ?? validate_or_fn;
  341. const validate = create_validator(validate_or_fn, maybe_fn);
  342. const __ = {
  343. type: "prerender",
  344. id: "",
  345. name: "",
  346. has_arg: !!maybe_fn,
  347. inputs: options?.inputs,
  348. dynamic: options?.dynamic
  349. };
  350. const wrapper = (arg) => {
  351. const promise = (async () => {
  352. const { event, state } = get_request_store();
  353. const payload = stringify_remote_arg(arg, state.transport);
  354. const id = __.id;
  355. const url = `${base}/${app_dir}/remote/${id}${payload ? `/${payload}` : ""}`;
  356. if (!state.prerendering && !BROWSER && !event.isRemoteRequest) {
  357. try {
  358. return await get_response(__, arg, state, async () => {
  359. const key = stringify_remote_arg(arg, state.transport);
  360. const cache = get_cache(__, state);
  361. const promise3 = (cache[key] ??= {
  362. serialize: true,
  363. data: fetch(new URL(url, event.url.origin).href).then(async (response) => {
  364. if (!response.ok) {
  365. throw new Error("Prerendered response not found");
  366. }
  367. const prerendered = await response.json();
  368. if (prerendered.type === "error") {
  369. error(prerendered.status, prerendered.error);
  370. }
  371. return prerendered.result;
  372. })
  373. }).data;
  374. return parse_remote_response(await promise3, state.transport);
  375. });
  376. } catch {
  377. }
  378. }
  379. if (state.prerendering?.remote_responses.has(url)) {
  380. return (
  381. /** @type {Promise<any>} */
  382. state.prerendering.remote_responses.get(url)
  383. );
  384. }
  385. const promise2 = get_response(
  386. __,
  387. arg,
  388. state,
  389. () => run_remote_function(event, state, false, () => validate(arg), fn)
  390. );
  391. if (state.prerendering) {
  392. state.prerendering.remote_responses.set(url, promise2);
  393. }
  394. const result = await promise2;
  395. if (state.prerendering) {
  396. const body = { type: "result", result: stringify(result, state.transport) };
  397. state.prerendering.dependencies.set(url, {
  398. body: JSON.stringify(body),
  399. response: json(body)
  400. });
  401. }
  402. return result;
  403. })();
  404. promise.catch(() => {
  405. });
  406. return (
  407. /** @type {RemoteResource<Output>} */
  408. promise
  409. );
  410. };
  411. Object.defineProperty(wrapper, "__", { value: __ });
  412. return wrapper;
  413. }
  414. // @__NO_SIDE_EFFECTS__
  415. function query(validate_or_fn, maybe_fn) {
  416. const fn = maybe_fn ?? validate_or_fn;
  417. const validate = create_validator(validate_or_fn, maybe_fn);
  418. const __ = { type: "query", id: "", name: "", validate };
  419. const wrapper = (arg) => {
  420. if (prerendering) {
  421. throw new Error(
  422. `Cannot call query '${__.name}' while prerendering, as prerendered pages need static data. Use 'prerender' from $app/server instead`
  423. );
  424. }
  425. const { event, state } = get_request_store();
  426. const is_validated = is_validated_argument(__, state, arg);
  427. return create_query_resource(
  428. __,
  429. arg,
  430. state,
  431. () => run_remote_function(event, state, false, () => is_validated ? arg : validate(arg), fn)
  432. );
  433. };
  434. Object.defineProperty(wrapper, "__", { value: __ });
  435. return wrapper;
  436. }
  437. function is_validated_argument(__, state, arg) {
  438. return state.remote.validated?.get(__.id)?.has(arg) ?? false;
  439. }
  440. function mark_argument_validated(__, state, arg) {
  441. const validated = state.remote.validated ??= /* @__PURE__ */ new Map();
  442. let validated_args = validated.get(__.id);
  443. if (!validated_args) {
  444. validated_args = /* @__PURE__ */ new Set();
  445. validated.set(__.id, validated_args);
  446. }
  447. validated_args.add(arg);
  448. return arg;
  449. }
  450. // @__NO_SIDE_EFFECTS__
  451. function batch(validate_or_fn, maybe_fn) {
  452. const fn = maybe_fn ?? validate_or_fn;
  453. const validate = create_validator(validate_or_fn, maybe_fn);
  454. const __ = {
  455. type: "query_batch",
  456. id: "",
  457. name: "",
  458. run: async (args, options) => {
  459. const { event, state } = get_request_store();
  460. return run_remote_function(
  461. event,
  462. state,
  463. false,
  464. async () => Promise.all(args.map(validate)),
  465. async (input) => {
  466. const get_result = await fn(input);
  467. return Promise.all(
  468. input.map(async (arg, i) => {
  469. try {
  470. const data = get_result(arg, i);
  471. return { type: "result", data: stringify(data, state.transport) };
  472. } catch (error2) {
  473. return {
  474. type: "error",
  475. error: await handle_error_and_jsonify(event, state, options, error2),
  476. status: error2 instanceof HttpError || error2 instanceof SvelteKitError ? error2.status : 500
  477. };
  478. }
  479. })
  480. );
  481. }
  482. );
  483. }
  484. };
  485. let batching = /* @__PURE__ */ new Map();
  486. const wrapper = (arg) => {
  487. if (prerendering) {
  488. throw new Error(
  489. `Cannot call query.batch '${__.name}' while prerendering, as prerendered pages need static data. Use 'prerender' from $app/server instead`
  490. );
  491. }
  492. const { event, state } = get_request_store();
  493. return create_query_resource(__, arg, state, () => {
  494. return new Promise((resolve, reject) => {
  495. const key = stringify_remote_arg(arg, state.transport);
  496. const entry = batching.get(key);
  497. if (entry) {
  498. entry.resolvers.push({ resolve, reject });
  499. return;
  500. }
  501. batching.set(key, {
  502. arg,
  503. resolvers: [{ resolve, reject }]
  504. });
  505. if (batching.size > 1) return;
  506. setTimeout(async () => {
  507. const batched = batching;
  508. batching = /* @__PURE__ */ new Map();
  509. const entries = Array.from(batched.values());
  510. const args = entries.map((entry2) => entry2.arg);
  511. try {
  512. return await run_remote_function(
  513. event,
  514. state,
  515. false,
  516. async () => Promise.all(args.map(validate)),
  517. async (input) => {
  518. const get_result = await fn(input);
  519. for (let i = 0; i < entries.length; i++) {
  520. try {
  521. const result = get_result(input[i], i);
  522. for (const resolver of entries[i].resolvers) {
  523. resolver.resolve(result);
  524. }
  525. } catch (error2) {
  526. for (const resolver of entries[i].resolvers) {
  527. resolver.reject(error2);
  528. }
  529. }
  530. }
  531. }
  532. );
  533. } catch (error2) {
  534. for (const entry2 of batched.values()) {
  535. for (const resolver of entry2.resolvers) {
  536. resolver.reject(error2);
  537. }
  538. }
  539. }
  540. }, 0);
  541. });
  542. });
  543. };
  544. Object.defineProperty(wrapper, "__", { value: __ });
  545. return wrapper;
  546. }
  547. function create_query_resource(__, arg, state, fn) {
  548. let promise = null;
  549. const get_promise = () => {
  550. return promise ??= get_response(__, arg, state, fn);
  551. };
  552. return {
  553. /** @type {Promise<any>['catch']} */
  554. catch(onrejected) {
  555. return get_promise().catch(onrejected);
  556. },
  557. current: void 0,
  558. error: void 0,
  559. /** @type {Promise<any>['finally']} */
  560. finally(onfinally) {
  561. return get_promise().finally(onfinally);
  562. },
  563. loading: true,
  564. ready: false,
  565. refresh() {
  566. const refresh_context = get_refresh_context(__, "refresh", arg);
  567. const is_immediate_refresh = !refresh_context.cache[refresh_context.cache_key];
  568. const value = is_immediate_refresh ? get_promise() : fn();
  569. return update_refresh_value(refresh_context, value, is_immediate_refresh);
  570. },
  571. run() {
  572. if (!state.is_in_universal_load) {
  573. throw new Error(
  574. "On the server, .run() can only be called in universal `load` functions. Anywhere else, just await the query directly"
  575. );
  576. }
  577. return get_response(__, arg, state, fn);
  578. },
  579. /** @param {any} value */
  580. set(value) {
  581. return update_refresh_value(get_refresh_context(__, "set", arg), value);
  582. },
  583. /** @type {Promise<any>['then']} */
  584. then(onfulfilled, onrejected) {
  585. return get_promise().then(onfulfilled, onrejected);
  586. },
  587. withOverride() {
  588. throw new Error(`Cannot call '${__.name}.withOverride()' on the server`);
  589. },
  590. get [Symbol.toStringTag]() {
  591. return "QueryResource";
  592. }
  593. };
  594. }
  595. Object.defineProperty(query, "batch", { value: batch, enumerable: true });
  596. function get_refresh_context(__, action, arg) {
  597. const { state } = get_request_store();
  598. const { refreshes } = state.remote;
  599. if (!refreshes) {
  600. const name = __.type === "query_batch" ? `query.batch '${__.name}'` : `query '${__.name}'`;
  601. throw new Error(
  602. `Cannot call ${action} on ${name} because it is not executed in the context of a command/form remote function`
  603. );
  604. }
  605. const cache = get_cache(__, state);
  606. const cache_key = stringify_remote_arg(arg, state.transport);
  607. const refreshes_key = create_remote_key(__.id, cache_key);
  608. return { __, state, refreshes, refreshes_key, cache, cache_key };
  609. }
  610. function update_refresh_value({ __, refreshes, refreshes_key, cache, cache_key }, value, is_immediate_refresh = false) {
  611. const promise = Promise.resolve(value);
  612. if (!is_immediate_refresh) {
  613. cache[cache_key] = { serialize: true, data: promise };
  614. }
  615. if (__.id) {
  616. refreshes[refreshes_key] = promise;
  617. }
  618. return promise.then(
  619. () => {
  620. },
  621. () => {
  622. }
  623. );
  624. }
  625. function requested(query2, limit = Infinity) {
  626. const { state } = get_request_store();
  627. const internals = (
  628. /** @type {RemoteQueryInternals | undefined} */
  629. /** @type {any} */
  630. query2.__
  631. );
  632. if (!internals || internals.type !== "query") {
  633. throw new Error("requested(...) expects a query function created with query(...)");
  634. }
  635. const requested2 = state.remote.requested;
  636. const payloads = requested2?.get(internals.id) ?? [];
  637. const refreshes = state.remote.refreshes ??= {};
  638. const [selected, skipped] = split_limit(payloads, limit);
  639. const record_failure = (payload, error2) => {
  640. const promise = Promise.reject(error2);
  641. promise.catch(() => {
  642. });
  643. const key = create_remote_key(internals.id, payload);
  644. refreshes[key] = promise;
  645. };
  646. for (const payload of skipped) {
  647. record_failure(
  648. payload,
  649. new Error(
  650. `Requested refresh was rejected because it exceeded requested(${internals.name}, ${limit}) limit`
  651. )
  652. );
  653. }
  654. return {
  655. *[Symbol.iterator]() {
  656. for (const payload of selected) {
  657. try {
  658. const parsed = parse_remote_arg(payload, state.transport);
  659. const validated = internals.validate(parsed);
  660. if (is_thenable(validated)) {
  661. throw new Error(
  662. // TODO improve
  663. `requested(${internals.name}, ${limit}) cannot be used with synchronous iteration because the query validator is async. Use \`for await ... of\` instead`
  664. );
  665. }
  666. yield mark_argument_validated(internals, state, validated);
  667. } catch (error2) {
  668. record_failure(payload, error2);
  669. continue;
  670. }
  671. }
  672. },
  673. async *[Symbol.asyncIterator]() {
  674. yield* race_all(selected, async (payload) => {
  675. try {
  676. const parsed = parse_remote_arg(payload, state.transport);
  677. const validated = await internals.validate(parsed);
  678. return mark_argument_validated(internals, state, validated);
  679. } catch (error2) {
  680. record_failure(payload, error2);
  681. throw new Error(`Skipping ${internals.name}(${payload})`, { cause: error2 });
  682. }
  683. });
  684. },
  685. async refreshAll() {
  686. for await (const arg of this) {
  687. void query2(arg).refresh();
  688. }
  689. }
  690. };
  691. }
  692. function split_limit(array, limit) {
  693. if (limit === Infinity) {
  694. return [array, []];
  695. }
  696. if (!Number.isInteger(limit) || limit < 0) {
  697. throw new Error("Limit must be a non-negative integer or Infinity");
  698. }
  699. return [array.slice(0, limit), array.slice(limit)];
  700. }
  701. function is_thenable(value) {
  702. return !!value && (typeof value === "object" || typeof value === "function") && "then" in value;
  703. }
  704. async function* race_all(array, fn) {
  705. const pending = /* @__PURE__ */ new Set();
  706. for (const value of array) {
  707. const promise = Promise.resolve(fn(value)).then((result) => ({
  708. promise,
  709. value: result
  710. }));
  711. promise.catch(() => {
  712. });
  713. pending.add(promise);
  714. }
  715. while (pending.size > 0) {
  716. try {
  717. const { promise, value } = await Promise.race(pending);
  718. pending.delete(promise);
  719. yield value;
  720. } catch {
  721. }
  722. }
  723. }
  724. export {
  725. command,
  726. form,
  727. prerender,
  728. query,
  729. requested
  730. };