From 4220eba132c92633563aa0d4b94ca09b2262514f Mon Sep 17 00:00:00 2001 From: Gonzalo Riestra Date: Wed, 18 Dec 2024 13:47:02 +0100 Subject: [PATCH] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 4e3ffcc13a312904263f3eed3a5385983be18a8e Merge: a15cffc81d b711a00061 Author: Isaac Roldán Date: Wed Dec 18 10:56:33 2024 +0000 Merge pull request #5112 from Shopify/12-16-add_try_catch_to_currentprocessisglobal_function Fix global CLI detection error handling commit a15cffc81dc874407a11720e3fec127653e00482 Merge: 3c13412fab 5258c521b3 Author: Ariel Caplan Date: Tue Dec 17 10:22:37 2024 +0000 Merge pull request #4918 from Shopify/identify-app-by-api-key Allow identifying apps by API key, not ID commit 3c13412fabe377fd8c0bc2a037f2a054b6a55ae7 Merge: cb09e4d0dc c4593009c2 Author: Ariel Caplan Date: Mon Dec 16 19:08:04 2024 +0000 Merge pull request #5056 from Shopify/fallback-to-github-when-not-on-spin Fall back to GitHub when repo is not on spin commit 5258c521b30bbe837e90c10d1b5107a844366948 Author: Ariel Caplan Date: Mon Dec 16 16:43:45 2024 +0200 Handle not having app ID available for function schema operations commit 78662531af324f9309dabb3aa2f98e5185b2bb87 Author: Ariel Caplan Date: Mon Dec 16 16:42:27 2024 +0200 Only search for apps by API key, not ID commit 8f0c2bbfa2e6681e0673b4d420bd70e9a5ffee21 Author: Ariel Caplan Date: Mon Dec 9 21:30:54 2024 +0200 Remove copying mechanism which falsely suggests immutability In fact it's just a second reference to the same thing after the code changes in the previous commit. So it would be better to avoid suggesting that changes are safe. commit 66e62abbf3845c7a64ea3e65a7f9007619567940 Author: Ariel Caplan Date: Tue Nov 26 15:59:41 2024 +0200 Rename for accuracy We may have API key rather than ID commit f9deee5df3d25a649fe14504555b8863177224e8 Author: Ariel Caplan Date: Tue Nov 26 14:39:01 2024 +0200 Rename for consistency commit b9def1a6a18e16b1d9fc9a7dbdd944982348094f Author: Ariel Caplan Date: Tue Nov 26 14:33:07 2024 +0200 Remove unnecessary handling of app_id in TOML commit 63d77bc4318d5831eacec3a29c56aed37f3f85f4 Author: Ariel Caplan Date: Mon Nov 25 17:25:31 2024 +0200 Allow identifying apps by API key, not ID commit cb09e4d0dc6c481053d86776230956848544a0e6 Merge: 720ad9c4b1 d7153b8e9f Author: Jeffrey Charles Date: Mon Dec 16 16:09:58 2024 +0000 Merge pull request #5040 from Shopify/jc.use-shopify-functions-javy-plugin Use Shopify Functions Javy plugin instead of default Javy plugin commit 720ad9c4b1b370761822ec94d5b455bc31f65a7b Merge: 228e0a4ba3 24a149ff88 Author: Isaac Roldán Date: Mon Dec 16 15:01:50 2024 +0000 Merge pull request #5115 from Shopify/12-16-catch_errors_when_building_functions Catch errors when building functions commit 24a149ff881a3b43545409c369011a7d1a917863 Author: Isaac Roldán Date: Mon Dec 16 15:37:32 2024 +0100 Catch errors when building functions commit 228e0a4ba3ebba5e33d9c9a37f1f7d2a3270d161 Merge: 1d5dff4627 cae67c8d75 Author: Isaac Roldán Date: Mon Dec 16 14:02:33 2024 +0000 Merge pull request #5073 from Shopify/12-10-group_app_config_updates_during_a_dev_session Group app config updates during a dev session commit 1d5dff46272bba24b4774fa0897bc7e7d3c04ce7 Merge: 17f19d1a13 2b64a86234 Author: Isaac Roldán Date: Mon Dec 16 14:02:25 2024 +0000 Merge pull request #5111 from Shopify/update-esbuild-to-0.24 Update esbuild to 0.24 commit b711a000614ff0f9feee80cd3cc29cc824291949 Author: Isaac Roldán Date: Mon Dec 16 15:01:33 2024 +0100 Update is-global.ts commit c4593009c211c088963be5e0706360ec4754665a Author: Ariel Caplan Date: Mon Dec 16 15:56:51 2024 +0200 Reraise exception commit 3e5dea0856375ca1ff3deae814c5df64f23e3b21 Author: Ariel Caplan Date: Mon Dec 16 15:56:44 2024 +0200 Fetch slowly to avoid undiagnosable rate limiting issues commit 57edc7d361ae1cf8342dc01f031163ce40fc1503 Author: Ariel Caplan Date: Sun Dec 8 12:31:06 2024 +0200 Fall back to GitHub when repo is not on spin commit 5bacf4c2a678ce316b02ce2f6d98d083a2f1fb6e Author: Isaac Roldán Date: Mon Dec 16 13:28:28 2024 +0100 Add try/catch to currentProcessIsGlobal function commit 2b64a862341139b47c84af341a304b11267400e3 Author: Isaac Roldán Date: Mon Dec 16 11:37:45 2024 +0100 Update esbuild to 0.24 commit 17f19d1a13a40c4a2188a61fc15eebadf047b833 Merge: 011fc5067d 219b31cfc9 Author: Alex Bradley Date: Fri Dec 13 21:15:54 2024 +0000 Merge pull request #5063 from Shopify/lopert.wasm-opt Download and run wasm-opt commit 011fc5067d69cd42d1e7e2ac7a939c4ce22466e9 Merge: 9f0c8838d5 4bda2922ae Author: Alfonso Noriega Date: Fri Dec 13 15:51:29 2024 +0000 Merge pull request #5102 from Shopify/fix_subdomain_underscores_in_admin_link_import Fix undescores in subdomain target when importing legacy links commit 219b31cfc931fa772591819c49db181c4b7beae7 Author: Alex Bradley Date: Thu Dec 12 09:19:06 2024 -0500 add debug log for runWasmOpt commit f47844ac3ad2f40826f12d53952866cc9ec318b5 Author: Alex Bradley Date: Tue Dec 10 16:04:10 2024 -0500 remove flag, prefer config commit 3139db8724b3ec5a440f2ce73b8d46a51b1871d0 Author: Alex Bradley Date: Tue Dec 10 15:59:36 2024 -0500 Use wasm_opt from config commit 62ad101203150b43d815d77b336e5b51a469049f Author: Alex Bradley Date: Tue Dec 10 14:48:35 2024 -0500 add strip-debug arg for wasm-opt commit ad762ad57486c1f5677cef3212c5db61bbf613d8 Author: Alex Bradley Date: Tue Dec 10 14:16:53 2024 -0500 add disable-wasm-opt flag commit b795a278fcc7e3649932855e21b9d6f3203fb1bb Author: Alex Bradley Date: Tue Dec 10 11:06:11 2024 -0500 add wasm-opt build step test commit 87dc62e7a74582dc2884b8ff6bc6fb1b363bdc13 Author: Alex Bradley Date: Mon Dec 9 16:40:50 2024 -0500 use exec over execSync commit 30a0c08584047e19ce24b9309f2b6525c31a10fa Author: Alex Bradley Date: Mon Dec 9 16:14:31 2024 -0500 wasm opt binary test commit b403d970b3bbfd58a89d7df9befdaa465faa0b81 Author: Alex Bradley Date: Mon Dec 9 13:58:49 2024 -0500 download and run wasm-opt commit 9f0c8838d5bb75c836274023f8b9bebb17a5440b Merge: 8e14ad8e12 bd13665847 Author: Shaun Stanworth Date: Fri Dec 13 13:57:44 2024 +0000 Merge pull request #5107 from Shopify/shauns/12-13-correctly_log_last_request_id_when_the_last_request_was_a_failure Correctly log last request ID when the last request was a failure commit 8e14ad8e1200c9a86da81707208661680f5cd365 Author: Gonzalo Riestra Date: Fri Dec 13 12:41:00 2024 +0100 Revert "Postrelease stack for shipit" This reverts commit 5c1711abd38f9b76ff0a68c73e4f13fc488a257f. commit bd13665847beeeafaac42ca3bc629603e4206820 Author: Shaun Stanworth Date: Fri Dec 13 11:39:28 2024 +0000 Correctly log last request ID when the last request was a failure commit 5c1711abd38f9b76ff0a68c73e4f13fc488a257f Author: Gonzalo Riestra Date: Fri Dec 13 12:37:55 2024 +0100 Postrelease stack for shipit commit d8c8998be2012e73ea96c0b01feb91c42e5b18ba Merge: e8179567b5 dea9a09d51 Author: Shaun Stanworth Date: Fri Dec 13 11:00:54 2024 +0000 Merge pull request #5082 from Shopify/shauns/12-11-fix_exception_raised_when_selectorcreateapp_fails_to_find_an_app Fix exception raised when selectOrCreateApp fails to find an app commit dea9a09d513a9a1d40bd254944612db0c69f1043 Author: Shaun Stanworth Date: Wed Dec 11 19:33:45 2024 +0000 Fix exception raised when selectOrCreateApp fails to find an app commit e8179567b5d25a4c689c727ee0101bd07e1af3d6 Merge: f7d281e9fe 8b072a194f Author: Shaun Stanworth Date: Fri Dec 13 10:27:10 2024 +0000 Merge pull request #5093 from Shopify/shauns/12-12-check_that_shopify_shopify_function_has_a_run_module Check that @shopify/shopify_function has a `run` module commit 4bda2922aeed5ac5c48cfc64d1745d7a457973eb Author: Alfonso Noriega Date: Fri Dec 13 10:47:33 2024 +0100 Fix undescores in subdomain target when importing legacy links commit 8b072a194f1e1cc4e115a36cf8047b6dd4101611 Author: Shaun Stanworth Date: Thu Dec 12 09:52:08 2024 +0000 Check that @shopify/shopify_function has a `run` module commit f7d281e9fe3a2038a09525fbdce21753c474f6b7 Merge: ab2173f964 85bc807789 Author: Paulo Margarido <64600052+paulomarg@users.noreply.github.com> Date: Thu Dec 12 13:41:14 2024 +0000 Merge pull request #5059 from Shopify/pm/remove_unused_lockfiles Remove unused lockfiles after clone commit ab2173f9649247348d9afef03f799f6c598e99db Merge: ffd13e4b43 beab713acd Author: Alok Swamy Date: Thu Dec 12 11:23:21 2024 +0000 Merge pull request #4782 from Shopify/feature/create-pull-metafields-cmd Create shopify theme metafields pull command commit ffd13e4b439903903309d109181f6630810209c4 Merge: e934b6d9f3 9545f7259a Author: Shaun Stanworth Date: Thu Dec 12 09:32:39 2024 +0000 Merge pull request #5085 from Shopify/shauns/12-11-fix_an_error_when_user_enters_in_an_auto_complete Fix an error when user enters '\' in an auto complete commit e934b6d9f32684592f3d1afd4f06e196ab5bf5e1 Merge: 18a42fe2b4 865728de5a Author: Shaun Stanworth Date: Thu Dec 12 08:52:53 2024 +0000 Merge pull request #5078 from Shopify/hl-bump-cli-hydrogen Bump cli-hydrogen to 9.0.3 commit 18a42fe2b47be2c701b2ce8ec24cb6ead1878f93 Merge: f95c1fcf34 ea27def4ee Author: Shaun Stanworth Date: Wed Dec 11 20:13:58 2024 +0000 Merge pull request #5083 from Shopify/shauns/12-11-fix_exception_raised_when_gettomls_is_passed_a_non-directory Fix exception raised when getTomls is passed a non-directory commit 9545f7259aa5cf602ea77bec5eed4ba51015e0c7 Author: Shaun Stanworth Date: Wed Dec 11 20:07:47 2024 +0000 Fix an error when user enters '\' in an auto complete commit f95c1fcf3446df976734d4c2a04cc83f9fccdace Merge: 39e10174b3 f4a6f958b1 Author: Shaun Stanworth Date: Wed Dec 11 19:58:52 2024 +0000 Merge pull request #5084 from Shopify/shauns/12-11-fix_exceptions_raised_for_fs_level_errors Fix exceptions raised for FS level errors commit f4a6f958b19344a621fb8cb10c712359f2137af9 Author: Shaun Stanworth Date: Wed Dec 11 19:46:42 2024 +0000 Fix exceptions raised for FS level errors commit ea27def4ee8b489c8f1b45971087679c433eb02e Author: Shaun Stanworth Date: Wed Dec 11 19:40:35 2024 +0000 Fix exception raised when getTomls is passed a non-directory commit 865728de5ae919c9d31d734d6a0a17a4ad6f3bec Author: Helen Lin Date: Wed Dec 11 10:02:10 2024 -0800 update lock file commit cbfc36ca88fe507a4fd2d6a196a026ade1a784f3 Author: Helen Lin Date: Wed Dec 11 09:58:21 2024 -0800 Bump cli-hydrogen commit beab713acd113d546a0b86db202f3eaa2353ee06 Author: Alok Swamy Date: Mon Nov 4 15:45:17 2024 -0500 Create `shopify theme metafields pull` command commit 39e10174b380d2b129a23636e9f308eac67e861e Merge: dd0cc149d9 a92307dce8 Author: Gray Gilmore Date: Tue Dec 10 22:34:00 2024 +0000 Merge pull request #5064 from Shopify/bump/theme-tools-2024-12-09 Bump Shopify/theme-tools packages commit a92307dce8d23ba0e5333707a1a34c0caf44e75a Author: Gray Gilmore Date: Mon Dec 9 11:18:17 2024 -0800 Bump Shopify/theme-tools packages commit cae67c8d75f676b2eeadf17915deb1e525d4faf1 Author: Isaac Roldán Date: Tue Dec 10 17:54:59 2024 +0100 Group app config updates during a dev session commit 85bc807789594b2e9637a6c1e10cb0ab90e90527 Author: Paulo Margarido <64600052+paulomarg@users.noreply.github.com> Date: Tue Dec 10 11:08:45 2024 -0500 Remove all lock files when manager is unknown commit d7153b8e9f59afb4b799d1a6f2ef4f08ee68826b Merge: 07f8394e4f dd0cc149d9 Author: Jeff Charles Date: Tue Dec 10 11:09:45 2024 -0500 Merge branch 'main' into jc.use-shopify-functions-javy-plugin commit 07f8394e4f398c6064353ae30a531d0879144670 Author: Jeff Charles Date: Tue Dec 10 11:06:35 2024 -0500 Use version constant in plugin name and path commit b4eda0235dc469019e9514b6e5ad1219f99de677 Author: Jeff Charles Date: Tue Dec 10 11:02:51 2024 -0500 Update Shopify Functions to version with plugin commit 3b835f06c050d1d61080cc6702f6f7fc73ae4fe0 Author: Paulo Margarido <64600052+paulomarg@users.noreply.github.com> Date: Tue Dec 10 09:05:33 2024 -0500 Applying comments from code review commit dd0cc149d9da189bb82730ff2b15d2c63d7beff5 Merge: ed4f150544 4d722c64fc Author: Luke Hickin <88160492+lukeh-shopify@users.noreply.github.com> Date: Tue Dec 10 13:09:23 2024 +0000 Merge pull request #4905 from Shopify/lukeh/theme-pull-git-dir Ensure git directory is clean when running `theme pull` commit ed4f150544c7232adb13fa1b822454fb26c647b9 Merge: 1c5559d85d c18109c272 Author: Isaac Roldán Date: Tue Dec 10 10:41:13 2024 +0000 Merge pull request #5071 from Shopify/release-notes-3.72 Release notes for 3.72 commit c18109c27224ab94858693129c3b2c7b1a243563 Author: Isaac Roldán Date: Tue Dec 10 11:33:45 2024 +0100 Release notes for 3.72 commit 1c5559d85df25bab1517c460a2564382388c1f19 Merge: cd1e758b76 63ad38687e Author: Isaac Roldán Date: Tue Dec 10 10:55:33 2024 +0100 Merge pull request #5069 from Shopify/changeset-release/main Version Packages - main commit 63ad38687e122966a2a5ccbca502a774e853b5a1 Author: github-actions[bot] Date: Tue Dec 10 09:42:43 2024 +0000 Version Packages commit cd1e758b761b1f58e1b8f3d6295f03a85edf8574 Merge: 5beaf5faa9 178c17e820 Author: Isaac Roldán Date: Tue Dec 10 10:40:11 2024 +0100 Merge pull request #5068 from Shopify/bump-minor-version-to-3.75 Bump minor version to 3.75 commit 178c17e820130ba8710dbbf6d7eeb0130197cd97 Author: Isaac Roldán Date: Tue Dec 10 10:30:42 2024 +0100 Bump minor version commit 5beaf5faa97de45486bd0f39f5c776f35e1ec1bb Merge: 61911a8fef 7cf6a1f2fc Author: Jamie Guerrero Date: Mon Dec 9 14:21:28 2024 -0500 Merge pull request #5023 from Shopify/changeset-release/main Version Packages - main commit 7cf6a1f2fc7477920291c2452f1acc0a66458e21 Author: Jamie Guerrero Date: Mon Dec 9 14:10:13 2024 -0500 trigger CI commit 7b56b4b5fbe2726b4e22dcb8c868dc837b21abd3 Author: Paulo Margarido <64600052+paulomarg@users.noreply.github.com> Date: Mon Dec 9 13:06:10 2024 -0500 Applying comment from review commit 03fb93e3c9f233954fd4dddf8aa13b33c64ba8a0 Author: Paulo Margarido <64600052+paulomarg@users.noreply.github.com> Date: Mon Dec 9 11:22:18 2024 -0500 Remove unused lockfiles after clone commit 7b455195ad00a08b3773c1d2fd99586529f4c147 Author: github-actions[bot] Date: Mon Dec 9 15:10:40 2024 +0000 Version Packages commit 61911a8fef7f3ed2c87afa20d6937e0455efcb3b Merge: 9299e907c2 44844a7752 Author: Jacob Date: Mon Dec 9 15:01:35 2024 +0000 Merge pull request #5046 from Shopify/js.bump-function-runner bump function-runner to 6.4.0 commit 9299e907c2130f7d975d0b7bdb37ed89f79742d6 Merge: 8335447600 4e58f44685 Author: Shaun Stanworth Date: Fri Dec 6 19:48:00 2024 +0000 Merge pull request #5050 from Shopify/stable/3.71 Backport 3.71 patches commit 83354476003a539b2184d262a11011dd34e87225 Merge: 2711cc27b6 a077c930b9 Author: Cameron Barker Date: Fri Dec 6 19:28:19 2024 +0000 Merge pull request #5041 from Shopify/1836-use-name-as-text Use name as link text insted of text property commit 4e58f446856cb6832f1a123f7454f43cb2733a69 Merge: 8cd1218b7f a473a44639 Author: Shaun Stanworth Date: Fri Dec 6 19:02:17 2024 +0000 Merge pull request #5049 from Shopify/changeset-release/stable/3.71 Version Packages - stable/3.71 commit a473a446391080d81ff91054650e6814241711db Author: github-actions[bot] Date: Fri Dec 6 18:58:14 2024 +0000 Version Packages commit 8cd1218b7f4e89e56d38a90739e3f8ca88b9300d Merge: 7835a90802 94953a671e Author: Shaun Stanworth Date: Fri Dec 6 18:55:42 2024 +0000 Merge pull request #5048 from Shopify/gg-fix-empty-file-upload Allow empty theme files to be uploaded commit 94953a671ed48f0186834a7d989842abff2f1193 Author: Gray Gilmore Date: Tue Dec 3 10:58:19 2024 -0800 Allow empty theme files to be uploaded commit 7835a90802a9650722cde46d743675869f72a065 Merge: 4dc64d7b09 b3233ffead Author: Shaun Stanworth Date: Fri Dec 6 18:44:43 2024 +0000 Merge pull request #5047 from Shopify/shauns/12-06-make_launcher_option_for_cli_optional Make launcher option for CLI optional commit 2711cc27b6a16b6f60a2febafd02489f9f228d2c Merge: 98eb7bd649 07ff693af4 Author: James Meng <35415298+jamesmengo@users.noreply.github.com> Date: Fri Dec 6 16:01:20 2024 +0000 Merge pull request #5042 from Shopify/jm/theme_blocks_ordering [Themes] Add support for block liquid files in theme partitioning commit b3233ffead08f53ab0a0e9a2f566b910de0e95fd Author: Shaun Stanworth Date: Fri Dec 6 10:28:29 2024 +0000 Make launcher option for CLI optional commit 44844a7752040747950bc7d1e770e0316728ae4d Author: Jacob Steves Date: Thu Dec 5 17:00:05 2024 -0500 bump function-runner to 6.4.0 commit a077c930b91e4d85050e97c981638c600c8d7f29 Author: Cameron Barker Date: Thu Dec 5 16:54:27 2024 -0500 fixing tests commit 07ff693af4599519f5a4990ee689afd5ea0ec801 Author: James Meng Date: Thu Dec 5 11:14:43 2024 -0800 Theme Upload: Add theme blocks to dependant files commit 98eb7bd6491b670fc866148a1dcae5fa0aa92a1e Merge: 2926cb0fd1 52ea1944ac Author: Mehdi Salemi Date: Thu Dec 5 19:56:31 2024 +0000 Merge pull request #4875 from Shopify/ms.proto3 [ShopifyVM] Use Functions App Management API for Dev Dash commit a367e700e6c2918507fc53a49766676bff5ea3cd Author: James Meng Date: Thu Dec 5 11:06:11 2024 -0800 Improve theme file partitioning to handle theme blocks commit aacd79875322ab66287f759615df0466a952e638 Author: Alfonso Noriega Date: Thu Dec 5 19:47:49 2024 +0100 Use name as link text insted of text property commit adcce6d6642ab42ed1b25a331fc8c12d650a80b0 Author: Jeff Charles Date: Thu Dec 5 11:46:43 2024 -0500 Use Shopify Functions Javy plugin instead of default Javy plugin commit 52ea1944acd2721cb79a4a28603676da24691e90 Author: Mehdi Salemi Date: Mon Nov 18 16:06:03 2024 -0500 adds functions api client to fetch schema for dev dash commit 2926cb0fd145d48723c06eb7dd39dab0ebc29503 Merge: 673a588a1a d248695a34 Author: Isaac Roldán Date: Thu Dec 5 10:32:45 2024 +0000 Merge pull request #5028 from Shopify/fix-function-drafts Fix function drafts commit 673a588a1a76445d1ecb5e7d794dee86d73e5986 Merge: c92d0a2b42 a4e15e1edd Author: Isaac Roldán Date: Thu Dec 5 10:24:18 2024 +0000 Merge pull request #5027 from Shopify/increase-localization-file-size-limit Increase localization file size limit commit c92d0a2b422fb69acdb6e4350b94db9123064bf2 Merge: 7d2f856437 6797334f29 Author: Gray Gilmore Date: Wed Dec 4 17:08:30 2024 +0000 Merge pull request #5015 from Shopify/gg-fix-empty-file-upload Allow empty theme files to be uploaded commit 4dc64d7b09926cf2d3f8ebc48cb90219101abc77 Merge: 0d7f9b5154 7d993b5028 Author: Isaac Roldán Date: Wed Dec 4 17:57:20 2024 +0100 Merge pull request #5029 from Shopify/changeset-release/stable/3.71 Version Packages - stable/3.71 commit 7d993b5028513271a462d48617ebe69556d68cbd Author: github-actions[bot] Date: Wed Dec 4 16:55:11 2024 +0000 Version Packages commit 0d7f9b5154b16eff2545639a968629a00c39baa1 Merge: 6d1c64eb0a 05a1eda9eb Author: Isaac Roldán Date: Wed Dec 4 17:52:52 2024 +0100 Merge pull request #5022 from Shopify/update_context_to_target_mappings Update context to target mappings commit 6d1c64eb0ac9e5b41468eb26d4813b6a590c5276 Merge: 1312153877 7516cbde84 Author: Isaac Roldán Date: Wed Dec 4 17:51:05 2024 +0100 Merge pull request #5026 from Shopify/increase-localization-file-size-limit-stable [stable] Increase extension locale file size limit commit 1312153877988e0697f2a92b3c40b5aaea7842e0 Merge: 38dc70c124 998ba06cef Author: Isaac Roldán Date: Wed Dec 4 17:50:53 2024 +0100 Merge pull request #5024 from Shopify/fix-function-drafts-stable [stable] Fix function drafts during `dev` commit d248695a34ce0cbb5170d8a50f14738130e42f56 Author: Isaac Roldán Date: Wed Dec 4 17:32:05 2024 +0100 Remove changeset commit e08f0bae23c4884da5d5941498f9ca002bce11fd Author: Isaac Roldán Date: Wed Dec 4 17:03:07 2024 +0100 Fix tests commit 09f0c9f5cc4589cdb5421146e39a9cde8b815de4 Author: Isaac Roldán Date: Wed Dec 4 15:44:11 2024 +0100 Fix function drafts not working during dev commit a4e15e1edd21e188b46eb8d6ed0a7e6fe8f0b524 Author: Isaac Roldán Date: Wed Dec 4 17:19:35 2024 +0100 Update tests commit d80c4022fd8eee4af91c2f57a4f041608c631a32 Author: Isaac Roldán Date: Wed Dec 4 17:11:59 2024 +0100 Increase file size limits for localization files commit 7516cbde84ac87425011ea6636c852bc0143089e Author: Isaac Roldán Date: Wed Dec 4 17:19:35 2024 +0100 Update tests commit 9767860ecae18db44e7d45771edc1f3f76512d06 Author: Isaac Roldán Date: Wed Dec 4 17:11:59 2024 +0100 Increase file size limits for localization files commit 998ba06cefa6e58841b0d31d5fdf184b2ba073dd Author: Isaac Roldán Date: Wed Dec 4 17:03:07 2024 +0100 Fix tests commit 73eb727757f353342978453929a294a8ba124fdf Author: Isaac Roldán Date: Wed Dec 4 15:44:11 2024 +0100 Fix function drafts not working during dev commit d5b0856f783aafa53d132194e8ef587a99103926 Author: Isaac Roldán Date: Wed Dec 4 15:23:33 2024 +0100 Increase file size limits for localization files commit 7d2f856437333f40513fb7de30a736600ab9ab4e Merge: c15413ea86 78cbc67c26 Author: Jeffrey Charles Date: Wed Dec 4 14:04:37 2024 +0000 Merge pull request #5014 from Shopify/jc.download-plugin-ahead-of-time-with-javy Download Javy plugin with Javy binary commit 05a1eda9ebf6f1c2964760a71b602e9b5bedbb8b Author: Alfonso Noriega Date: Wed Dec 4 13:43:53 2024 +0100 Added changeset commit 76893d242a4501ae10e3655fa940c587c61005ee Author: Alfonso Noriega Date: Tue Dec 3 18:30:21 2024 +0100 Update context to target transform to match link targets commit c15413ea865ea0148c4c2cba0df8175d525e49b7 Merge: 084f555570 2fa6126867 Author: Alfonso Noriega Date: Wed Dec 4 12:37:26 2024 +0000 Merge pull request #5013 from Shopify/update_mapping_from_context_to_targets Update context to target transform to match link targets commit 2fa6126867066fadcb56a78f81e2f5b424b8ab3a Author: Alfonso Noriega Date: Tue Dec 3 18:30:21 2024 +0100 Update context to target transform to match link targets commit 38dc70c124f20fdb8ad72d7bf1d224f0ff6f5da8 Merge: c2bdeabc96 4501441b90 Author: Isaac Roldán Date: Wed Dec 4 11:09:14 2024 +0100 Merge pull request #5018 from Shopify/changeset-release/stable/3.71 Version Packages - stable/3.71 commit 4501441b901dba3e01c40151ba1292c4242fca01 Author: github-actions[bot] Date: Wed Dec 4 10:06:56 2024 +0000 Version Packages commit c2bdeabc96d72ddbe81a254cc7a7d949b9718f6f Merge: ce0ee89cb7 a395820e7b Author: Isaac Roldán Date: Wed Dec 4 11:04:27 2024 +0100 Merge pull request #5017 from Shopify/fix-not-found-in-check-command-safety-stable [stable] Fix dev for Ruby apps commit a395820e7b3c5cfa3479332cbb67807616db4743 Author: Gonzalo Riestra Date: Wed Dec 4 10:54:58 2024 +0100 Add changeset commit 73d72944d32d1d34f2e37a2cb64b91d9973107f9 Author: Gonzalo Riestra Date: Wed Dec 4 10:54:03 2024 +0100 Avoid errors on checkCommandSafety when the command is not found commit 084f555570080dfbc5243b02e184c1684736fc5b Merge: 4721974f42 f559cb05a4 Author: Gonzalo Riestra Date: Wed Dec 4 09:45:26 2024 +0000 Merge pull request #4522 from Shopify/fix-not-found-in-check-command-safety Fix dev for Ruby apps commit f559cb05a48778df7c8065608b2b6818e3715095 Merge: a84792f30c 4721974f42 Author: Gonzalo Riestra Date: Wed Dec 4 10:08:49 2024 +0100 Merge branch 'main' into fix-not-found-in-check-command-safety commit 6797334f2987919b0b3d8fdbdee8580f93d2cef2 Author: Gray Gilmore Date: Tue Dec 3 11:02:07 2024 -0800 Update codeowners for themes API files commit 94a7d4ce4f33edbf0d48f772c3e3b2efebdab6b3 Author: Gray Gilmore Date: Tue Dec 3 10:58:19 2024 -0800 Allow empty theme files to be uploaded commit 78cbc67c26d558a1021e0ac1da234ff86e394818 Author: Jeff Charles Date: Tue Dec 3 12:40:48 2024 -0500 Download Javy plugin with Javy binary commit ce0ee89cb7cc4e40714c693e5ad9ea65f21d2567 Merge: 9b8c291dbb 869d5ac5fc Author: Isaac Roldán Date: Tue Dec 3 18:34:26 2024 +0100 Merge pull request #5012 from Shopify/changeset-release/stable/3.71 Version Packages - stable/3.71 commit 869d5ac5fce962f90c6148d2aa7d901ae6776d23 Author: github-actions[bot] Date: Tue Dec 3 17:21:52 2024 +0000 Version Packages commit 9b8c291dbb889cc9f44f1277cf99b5e4796e9e4e Merge: e643396983 4b93d76290 Author: Isaac Roldán Date: Tue Dec 3 18:19:22 2024 +0100 Merge pull request #5011 from Shopify/jc.set-overwrite-flag-stable Fix dest already exists error by setting overwrite flag on stable branch commit 4b93d76290447cd3c2f9a2aa29e3e3fcc1cccab2 Author: Jeff Charles Date: Tue Dec 3 12:08:17 2024 -0500 Set override flag when moving downloaded binary commit 4721974f42e205e01bdba96c1c7841c74bca88d1 Merge: 55b65ecaa7 a930bd6148 Author: Jeffrey Charles Date: Tue Dec 3 16:51:28 2024 +0000 Merge pull request #5009 from Shopify/jc.set-overwrite-flag Fix dest already exists error by setting overwrite flag commit a930bd6148ee9edec5ec0bb99728dba1533d9648 Author: Jeff Charles Date: Tue Dec 3 11:20:38 2024 -0500 Fix dest already exists error by setting overwrite flag commit e643396983b225b716ddcac066f171136c1858a9 Author: Isaac Roldán Date: Tue Dec 3 15:59:25 2024 +0100 Add stable/3.71 shipit configuration commit 87ba0d3f0477c2731b9ec8de59b6ffd8bb214217 Author: Isaac Roldán Date: Tue Dec 3 15:58:58 2024 +0100 3.71 release notes commit 55b65ecaa75ebc71855b9cb4956b799e6178bdf3 Merge: 15b2a6fe18 0075a0e104 Author: Isaac Roldán Date: Tue Dec 3 15:04:09 2024 +0100 Merge pull request #4844 from Shopify/changeset-release/main Version Packages - main commit 0075a0e104cb41eac15c2e7af37df027a79ac0f7 Author: github-actions[bot] Date: Mon Dec 2 16:15:50 2024 +0000 Version Packages commit 15b2a6fe1881f96585b81a65d2417470f043a6d8 Merge: c202990cb9 80ec997d22 Author: Chris AtLee Date: Mon Dec 2 16:06:48 2024 +0000 Merge pull request #5001 from Shopify/catlee/refresh_graphql Refresh session on 401 for graphQL requests commit c202990cb93a0df2b78dee5135477c39703e9acc Merge: 7fc88c3880 11fd136c57 Author: Guilherme Carreiro Date: Mon Dec 2 15:54:39 2024 +0000 Merge pull request #4792 from Shopify/catlee/theme_files_put Use graphQL to upload theme files commit 11fd136c57014b8c200caefe12f05e0bd6abe79b Author: Guilherme Carreiro Date: Mon Dec 2 15:44:56 2024 +0100 Remove the "refresh the session when 401 errors happen" commit 7fc88c38801674ca880502b87e60ddadb46d52fb Merge: 2af2272f47 b81ec3645e Author: Ariel Caplan Date: Mon Dec 2 11:34:59 2024 +0000 Merge pull request #5003 from Shopify/centralize-app-management-gating Centralize gating of the App Management API commit b81ec3645efcfe7387bd8341b505a75abffb3eff Author: Ariel Caplan Date: Sun Dec 1 23:35:09 2024 +0200 Centralize gating of the App Management API commit 80ec997d22ec7e9e96fe9450e3a05a2768da7122 Author: Chris AtLee Date: Fri Nov 29 14:56:20 2024 -0500 Refresh session on 401 for graphQL requests commit 4d722c64fcfc15e7e9dbac5cb6807d8cee96d526 Author: Luke Hickin Date: Thu Nov 21 15:25:13 2024 -0800 Ensure git directory is clean when running `theme pull` commit 2af2272f47688c5b49351f1702b2b68f07526e7b Merge: b70d526660 115718cdf5 Author: James Meng <35415298+jamesmengo@users.noreply.github.com> Date: Fri Nov 29 17:26:46 2024 +0000 Merge pull request #4936 from Shopify/jm/clean-password-redirect [Themes] - Improve storefront password detection for password-protected shops with redirects commit b70d526660d5b7a3be3ed483ddfc24a8137efbf6 Merge: 8d21357d61 5b0d610259 Author: Isaac Roldán Date: Fri Nov 29 15:44:16 2024 +0100 Improve multiple CLI installations warning performance (#4999) ### WHY are these changes introduced? Checking for multiple installed CLIs is very expensive. ### WHAT is this pull request doing? Wraps the `showMultipleCLIWarningIfNeeded` function call with `runAtMinimumInterval` to ensure the warning is only checked once every 24 hours. ### How to test your changes? 1. Having a local CLI and a global CLI 2. Run `shopify app info`, you should see a warning 3. Run it again: no warning -> command runs faster ### Measuring impact How do we know this change was effective? Please choose one: - [x] n/a - this doesn't need measurement, e.g. a linting rule or a bug-fix ### Checklist - [x] I've considered possible cross-platform impacts (Mac, Linux, Windows) - [x] I've considered possible [documentation](https://shopify.dev) changes commit 8d21357d615c49ae2daca7f83241b83f18672917 Merge: 55da34b1c5 d7cf5425c4 Author: Isaac Roldán Date: Fri Nov 29 15:37:48 2024 +0100 Show `app init` success after loading the app (#4998) ### WHY are these changes introduced? App init shows the success message and then it still takes 1-2s to finish. ### WHAT is this pull request doing? Load the app BEFORE showing the success message. ### How to test your changes? 1. Run `shopify app init` to create a new app 2. Verify that after the success message, the command finishes immediately (it can still take up to 500ms to process analytics) ### Measuring impact How do we know this change was effective? Please choose one: - [x] n/a - this doesn't need measurement, e.g. a linting rule or a bug-fix - [ ] Existing analytics will cater for this addition - [ ] PR includes analytics changes to measure impact ### Checklist - [x] I've considered possible cross-platform impacts (Mac, Linux, Windows) - [x] I've considered possible [documentation](https://shopify.dev) changes commit 55da34b1c58c144796dc07f5944b30c2ef7aa2f3 Merge: 4254118fa3 0442d42213 Author: Isaac Roldán Date: Fri Nov 29 15:36:51 2024 +0100 Add proper support for gitignore in AppWatcher (#4917) ### WHY are these changes introduced? Fixes issues with file watching and extension creation detection during `app dev`. ### WHAT is this pull request doing? - Improves file watching by using the `ignore` package to properly handle `.gitignore` files in extensions. If an extension defines it, anything in it will be ignored by the app watcher. - Fixes extension creation mid-dev by updating the file watcher when the app is reloaded. ### How to test your changes? 1. Create a new app with some extensions 2. Add a `.gitignore` file to an extension directory 3. Start dev and verify: - File changes matching `.gitignore` patterns are properly ignored - New extensions are properly detected mid-dev ### Checklist - [x] I've considered possible cross-platform impacts (Mac, Linux, Windows) - [x] I've considered possible documentation changes commit 5b0d6102598d7114f67ab187439d5572538edf51 Author: Isaac Roldán Date: Fri Nov 29 13:02:32 2024 +0100 Only check for multiple CLI once a day commit d7cf5425c418450f99b3f2e2e649a2b454202a68 Author: Isaac Roldán Date: Fri Nov 29 11:42:22 2024 +0100 Show app init success after getting linked app commit 0442d422134354ca8127d18f88d7d529cb9b2ae5 Author: Isaac Roldán Date: Mon Nov 25 17:57:11 2024 +0100 Update tests commit 642bebdc3d0552a522d73bbe3436591b158bbf01 Author: Isaac Roldán Date: Mon Nov 25 17:26:48 2024 +0100 Update tests commit 80ab0cdaf5382bc6171d8c6888f9750446678fe9 Author: Isaac Roldán Date: Mon Nov 25 16:22:35 2024 +0100 Add proper support for gitignore in AppWatcher commit 4915786a7c3d8a50c3beff86c748da69d29a5454 Author: Chris AtLee Date: Mon Nov 4 17:57:58 2024 -0500 Use themeFilesUpsert graphQL instead of REST commit 4254118fa32c23040cd68009f02938637bce2c8e Merge: 3704940d47 33f713e06e Author: Gonzalo Riestra Date: Thu Nov 28 19:02:06 2024 +0000 Merge pull request #4886 from Shopify/bump/theme-tools-2024-11-19 Bump Shopify/theme-tools packages commit 33f713e06e1a50dfc9e6218d493f1432a0d82d15 Author: Charles-P. Clermont Date: Tue Nov 19 16:02:45 2024 -0500 Bump theme tools packages commit 3704940d4768069b82fb75c5bac589f1eb04065a Merge: 2c6914b66e ec6b5e0e6d Author: Gonzalo Riestra Date: Thu Nov 28 18:24:32 2024 +0000 Merge pull request #4921 from Shopify/upload-artifact-v4 update to upload-artifact@v4 commit 2c6914b66ee8708cb5d8b64406a00a0256f116c8 Merge: 01ae0697b4 62c69bbf50 Author: Cédric Darne Date: Thu Nov 28 17:48:53 2024 +0000 Merge pull request #4884 from Shopify/dev-dash-webhooks-api Introduce dev dash webhooks API commit 01ae0697b459f67f5cefda40e73346df92f95724 Merge: 8e761560e3 97117a0a8e Author: Gonzalo Riestra Date: Thu Nov 28 17:42:48 2024 +0000 Merge pull request #4696 from Shopify/checkout-ui-add-product-url-fix Fix the URL output to add a new product commit 62c69bbf50d131faca5d16770bbf8e0abdfd0b26 Author: Cedric Darne Date: Thu Nov 28 12:42:48 2024 -0500 Fix lint commit 8e761560e3e4139825f320bd1e3ee15cb05af3a7 Merge: 7ad15fe64f 5d960d494a Author: Gonzalo Riestra Date: Thu Nov 28 18:36:38 2024 +0100 Merge pull request #4553 from Shopify/surma-patch-1 Remove reference to package.json commit 7ad15fe64f3fc82f7b72d97148cd1b4cd9509c09 Merge: 93a01390e6 e736a23ebc Author: Gonzalo Riestra Date: Thu Nov 28 17:21:28 2024 +0000 Merge pull request #4941 from Shopify/improve-issue-template Collapse verbose output by default in bug template commit 93a01390e60496f9dd39bdab80f341170452eeb6 Merge: f3d039650b b25d93a5eb Author: Guilherme Carreiro Date: Thu Nov 28 17:12:46 2024 +0000 Merge pull request #4903 from AaronBarcos/fix/storefront-password-validation-localized-redirect Fix: Handle localized URLs in storefront password validation commit 115718cdf5d258a1e9ac3310c6f6b8c69a8d5f1a Author: James Meng Date: Thu Nov 28 08:56:41 2024 -0800 Use URL constructor to grab redirect pathname commit f3d039650b532a22e8b95e7105a8d040a063935b Merge: caab0fcd66 af36a6a4ca Author: Isaac Roldán Date: Thu Nov 28 17:50:03 2024 +0100 Add client-id and reset as global flags (#4940) ### WHY are these changes introduced? Standardizes the handling of `client-id` and `reset` flags across all app commands by moving them to the shared app flags. ### WHAT is this pull request doing? - Moves `client-id` and `reset` flags to shared app flags - Updates all commands to use the shared flag implementations - Standardizes the usage of `client-id` and `reset` flags in `linkedAppContext` calls ### How to test your changes? 1. Run various app commands with `--client-id` flag 2. Run various app commands with `--reset` flag 3. Verify that both flags work consistently across all commands ### Checklist - [x] I've considered possible cross-platform impacts (Mac, Linux, Windows) - [x] I've considered possible documentation changes commit af36a6a4ca80b3ebf671ca2c84d29e97c5fa2428 Author: Isaac Roldán Date: Thu Nov 28 14:23:34 2024 +0100 Add client-id and reset as global flags commit caab0fcd6693dde66a0791032e0d8e93c982ab40 Author: Shaun Stanworth Date: Thu Nov 28 16:23:00 2024 +0000 Make a dependabot group for dev dependencies (#4994) ### WHY are these changes introduced? Updates Dependabot configuration to better organize dependency updates by grouping all dev dependencies together commit 86c1afe3e9a35a4559603d6fa94427a8d7320970 Author: Cedric Darne Date: Thu Nov 28 11:08:13 2024 -0500 Update webhooks GQL schema branch commit ef45023b924c6bdd2658b1d9af6115bd62d951f0 Merge: 9f4fbc6489 26ceb5c47a Author: belalsj <107405858+belalsj@users.noreply.github.com> Date: Thu Nov 28 15:49:03 2024 +0000 Merge pull request #4846 from Shopify/condition-with-manifest Enable multiple asset handling commit 26ceb5c47a3bbc59cd9a6be1e295266e35483280 Author: belalsj Date: Wed Nov 20 11:50:00 2024 +0100 Enable multiple assets for extensions commit 9f4fbc6489372fedfca9a96e3aba1da42311577c Merge: 82b872fb4d ba794ba47a Author: Gonzalo Riestra Date: Thu Nov 28 15:12:55 2024 +0000 Merge pull request #4942 from Shopify/fix-dependabot-config Fix dependabot config commit ba794ba47a043bff680f5ac7b694e81aa6c5f0fb Author: Gonzalo Riestra Date: Thu Nov 28 15:31:07 2024 +0100 Include the packages subdirectories commit 69b8fe4850a7b12e7797216ac1f8eb883f15ff14 Author: Gonzalo Riestra Date: Thu Nov 28 15:30:43 2024 +0100 Remove unneeded config for bundler commit e736a23ebc70f3e6d6b0dbcf6711638325f611f3 Author: Gonzalo Riestra Date: Thu Nov 28 15:29:44 2024 +0100 Collapse verbose output by default in bug template commit 82b872fb4d9aff53031e0283366141ec6a2db7e2 Merge: 4e3f75759d 4d1d7e00f1 Author: Gonzalo Riestra Date: Thu Nov 28 12:28:32 2024 +0000 Merge pull request #4939 from Shopify/revert-4931-upgrade-pnpm Revert "Upgrade pnpm to v9" commit 4d1d7e00f15e6c034c482872d550d3c6316e0879 Author: Gonzalo Riestra Date: Thu Nov 28 13:16:15 2024 +0100 Revert "Upgrade pnpm to v9" commit 4e3f75759dc5a43eafe30da8cc3aee5211766f1e Merge: 66fe10cc58 80d2f2d9a1 Author: Isaac Roldán Date: Thu Nov 28 13:13:04 2024 +0100 Refactor FileWatcher into a Class (#4916) ### WHY are these changes introduced? Refactors the file watcher implementation into a class-based structure to improve maintainability and testability of the file watching system used during app development. ### WHAT is this pull request doing? NO NEW FEATURES, mainly a refactor: - Converts the file watcher from a function-based to a class-based implementation: the new `FileWatcher` class - Adds proper dependency injection for testing - Introduces constants for configuration values - Updates tests to use the new class-based structure - Remove `micromatch`, it's not used anymore. ### How to test your changes? 1. Run `dev` command on an app with multiple extensions 2. Verify that file changes are properly detected and handled 3. Create new extensions and verify they are detected 4. Delete extensions and verify proper cleanup ### Measuring impact - [x] n/a - this doesn't need measurement, e.g. a linting rule or a bug-fix ### Checklist - [x] I've considered possible cross-platform impacts (Mac, Linux, Windows) - [x] I've considered possible [documentation](https://shopify.dev) changes commit 80d2f2d9a1cde58b3ec402264d022d2913257f6b Merge: 599e99b5da 66fe10cc58 Author: Isaac Roldán Date: Thu Nov 28 11:16:49 2024 +0100 Merge branch 'main' into 11-25-refactor_filewatcher_into_a_class commit 599e99b5da72801e486f6f976b5a882e74069713 Author: Isaac Roldán Date: Mon Nov 25 13:39:59 2024 +0100 Refactor FileWatcher into a Class commit 66fe10cc58250451633f935d1f5e7d65ef590fbe Merge: a2347d869b 504289fe52 Author: Isaac Roldán Date: Thu Nov 28 09:52:42 2024 +0000 Merge pull request #4934 from Shopify/fix-dev-session-tests-memory-leak Fix AppWatcher tests memory leak commit a2347d869bf9436165a0486507cdd4338fc6e310 Merge: 8650ee09a6 a2cd0eb951 Author: Gonzalo Riestra Date: Thu Nov 28 08:31:52 2024 +0000 Merge pull request #4931 from Shopify/upgrade-pnpm Upgrade pnpm to v9 commit 7017b9e31c8dca04bed008ae9064e67339e4afc8 Author: James Meng Date: Wed Nov 27 16:02:35 2024 -0800 fix - Fix storefront password detection for password-protected shops with redirects commit ec6b5e0e6dca2a623e20863e1363b66a3975d5a1 Author: gracejychang Date: Mon Nov 25 16:47:37 2024 -0800 update to upload-artifact@v4 commit 8650ee09a6e045b332e748ddfe39cffed8c7d866 Merge: 34ce42dd91 5107f4e805 Author: James Meng <35415298+jamesmengo@users.noreply.github.com> Date: Wed Nov 27 17:55:07 2024 +0000 Merge pull request #4900 from Shopify/jm/strict_push Add --strict flag to theme push to enforce theme check before pushing commit 5107f4e80529c4e9e68303c62d029537cbf79491 Author: James Meng Date: Thu Nov 21 15:10:04 2024 -0500 Update docs Changeset commit bad47dcd2ae0ac8d3893f4fc1517fbeda94d8172 Author: James Meng Date: Thu Nov 21 11:45:07 2024 -0500 Update manifests commit c6c1406f2367bbad9b30fd1d3f8b0a1531c988d4 Author: James Meng Date: Thu Nov 21 11:38:10 2024 -0500 Add and update tests Add JSON flag test commit 7dcd1a5ff599241154f6ae2012d61aaf0bd26d14 Author: James Meng Date: Thu Nov 21 15:34:12 2024 -0500 [Refactor] Cleanup unused conditional commit 1a1b3b18f41a0ee8591624952f651e0c68f9fbce Author: James Meng Date: Thu Nov 21 11:22:56 2024 -0500 refactor: extract theme check logic and improve strict mode handling commit 3feeac33fa1e0f25787fca0b679ae0414b694340 Author: James Meng Date: Thu Nov 21 01:09:09 2024 -0500 Add --strict flag to theme push to enforce theme check before pushing commit 34ce42dd91d6a0837c191e57ee8bb69f5aa8ec26 Merge: a1af910e5e d00e41a0d2 Author: James Meng <35415298+jamesmengo@users.noreply.github.com> Date: Wed Nov 27 17:02:10 2024 +0000 Merge pull request #4920 from Shopify/jamesmengo-patch-1 Update CODEOWNERS file patterns and add CLI README commit a2cd0eb951aaedf79f6387a324dbfc5dc2e45998 Author: Gonzalo Riestra Date: Wed Nov 27 17:53:21 2024 +0100 Fix merge commit 984670ab60d5cffb078e5f717a878b72bbac5bb3 Merge: fdf0d22506 a1af910e5e Author: Gonzalo Riestra Date: Wed Nov 27 17:52:28 2024 +0100 Merge branch 'main' into upgrade-pnpm commit 504289fe529e7e2214c581340328aa20a31b3434 Author: Isaac Roldán Date: Wed Nov 27 16:59:20 2024 +0100 Add extra mock commit bd38db39847e390f2c1a5a889175ba99e52ba58b Author: Isaac Roldán Date: Wed Nov 27 15:53:05 2024 +0100 abort watcher process after each test commit 3b6f7337a8d35f9ca4eadd751e3a411d4d540dee Merge: 274718e511 a1af910e5e Author: Isaac Roldán Date: Wed Nov 27 15:42:37 2024 +0100 Merge branch 'main' into fix-dev-session-tests-memory-leak commit a1af910e5e8c37e630b5fe3ca85a1d90fa77df34 Merge: a25af5a250 992bf9422e Author: Isaac Roldán Date: Wed Nov 27 15:32:28 2024 +0100 Improvements to App reload speed (#4924) ### WHY are these changes introduced? Improves app reloading performance by caching or avoiding expensive operations. ### WHAT is this pull request doing? - `~200ms` Introduces a new `reloadApp` function that reuses data from the previous app instance. - `~200ms` Caches JSON schema validators to avoid recompilation on each validation. - `~100ms` Replaces git ignore checking with a more efficient alternative: the `ignore` package - `~1200ms` Improves handling of CLI version warning to only check once per command execution. - Reduces the file-watcher debouncing time to 200ms Before this PR, time to reload an app: `1500-2000ms` New time: `~15-20ms` ❗ Improvement: `100x` ### How to test your changes? 1. Run `dev` on an app with multiple extensions using the app management API. 2. Make changes to extension configuration files. 3. Verify that reloading is faster and the app continues to function correctly. ### Measuring impact - [x] n/a - this doesn't need measurement, e.g. a linting rule or a bug-fix ### Checklist - [x] I've considered possible cross-platform impacts (Mac, Linux, Windows) - [x] I've considered possible documentation changes commit 992bf9422eb45e9ff5d5eb18060e15ea7e4b03d1 Author: Isaac Roldán Date: Wed Nov 27 14:56:04 2024 +0100 Remove global didCheckForGlobalCLIWarning and update debounce to use leading commit f339b3cdeaa28299f69ce53bdec9094f61226d9d Author: Isaac Roldán Date: Wed Nov 27 13:46:46 2024 +0100 Add more tests for gitTracked commit 271acdb7ff3ab7026f7c868b912ab3164e06cadd Author: Isaac Roldán Date: Tue Nov 26 12:59:34 2024 +0100 Loader improvements commit 43f0bd5d521ce247430c1ea539dfe98cc85b1fcc Author: Isaac Roldán Date: Tue Nov 26 12:29:35 2024 +0100 Cache json schema validators commit a25af5a250f92389cd6dd78577d12534685f783d Merge: aecf7fe2bb 3fee076cd6 Author: Alfonso Noriega Date: Wed Nov 27 14:14:52 2024 +0000 Merge pull request #4877 from Shopify/admin-link-import-transform-url-to-relative on import link extensions make absolute urls relative commit aecf7fe2bb11b8ad875f3686730f000e5d8af3c4 Merge: 55eef10137 9ed8458c4e Author: Gonzalo Riestra Date: Wed Nov 27 13:57:50 2024 +0000 Merge pull request #4930 from Shopify/skip-notifications-with-json-flag Skip notifications when using --json commit fdf0d22506f784ff9df5362e615f24dadeeedcfd Author: Gonzalo Riestra Date: Wed Nov 27 14:50:17 2024 +0100 Update workflows commit 1ac92cc9e406c0bf572755454eba0755e20aea12 Author: Gonzalo Riestra Date: Wed Nov 27 14:38:45 2024 +0100 Update get-started.md commit b649a540e38a7b2345a119e6554a432410bd9a16 Author: Gonzalo Riestra Date: Wed Nov 27 14:37:15 2024 +0100 Upgrade pnpm to v9 commit 9ed8458c4ec8a040c0aeadf3ae77f9ad57d8608b Author: Gonzalo Riestra Date: Wed Nov 27 14:25:36 2024 +0100 Fix lint issue commit 21d6b33287b3e9f3e10905102eeeae46f92737d3 Author: Gonzalo Riestra Date: Wed Nov 27 14:04:25 2024 +0100 Keep a single reference of SHOPIFY_FLAG_JSON commit 2ca99425e212e720344240c257843fb5f0548419 Author: Gonzalo Riestra Date: Wed Nov 27 13:23:09 2024 +0100 Update documentation commit 740d15d4df309b0108c16ab2450c763e147b99b6 Author: Gonzalo Riestra Date: Wed Nov 27 13:19:37 2024 +0100 Refresh manifests commit 8e03a724d8beab1594d9b047a743c47d44782aec Author: Gonzalo Riestra Date: Wed Nov 27 13:10:36 2024 +0100 Add test commit 451c1769ab644ae0d579967723e0379ebcea47fd Author: Gonzalo Riestra Date: Wed Nov 27 13:05:15 2024 +0100 Update changeset commit db0391081e7d70e0696decff47192e5ebcc7bcd2 Author: Gonzalo Riestra Date: Wed Nov 27 13:03:25 2024 +0100 Skip notifications when using SHOPIFY_FLAG_JSON commit 55eef10137cfab0b386748922f5c03bec9daddd0 Merge: 6a802151a6 0da3319aeb Author: Isaac Roldán Date: Wed Nov 27 12:56:35 2024 +0100 Fix initial draft update (#4929) ### WHY are these changes introduced? Addresses potential race conditions when pushing updates for draftable extensions in parallel. ### WHAT is this pull request doing? - Filters extension events to only process draftable extensions - Implements concurrent processing of extension updates using `Promise.all` ### How to test your changes? 1. Run dev with multiple draftable extensions (admin-action, theme) 2. Verify that we send initial drafts for every extension. ### Measuring impact - [x] n/a - this doesn't need measurement, e.g. a linting rule or a bug-fix ### Checklist - [x] I've considered possible cross-platform impacts (Mac, Linux, Windows) - [x] I've considered possible [documentation](https://shopify.dev) changes commit b47fdc347db7dcd12c80f571f572f27b8a804798 Author: Gonzalo Riestra Date: Wed Nov 27 12:52:46 2024 +0100 Unify --json flag across commands commit e67cf3bf5fff4c269b9af3bb6569ac0dc8cad43b Author: Gonzalo Riestra Date: Wed Nov 27 12:52:10 2024 +0100 Skip notifications when using -j commit 5531731c115d9363fc870f721827036424937c84 Author: Gonzalo Riestra Date: Wed Nov 27 12:29:48 2024 +0100 Add changeset commit 40d7edc1b562d1966e3de1bbdd5613c7c45dbb7d Author: Gonzalo Riestra Date: Wed Nov 27 12:29:10 2024 +0100 Skip notifications when using --json commit 0da3319aeb3bd8d37c625beecc65816ac3edb0c5 Author: Isaac Roldán Date: Wed Nov 27 12:25:42 2024 +0100 Update draftable-extension.ts commit 274718e511ab3d1678ecaf9ec3ba83936fa2ec74 Author: Isaac Roldán Date: Wed Nov 27 12:19:24 2024 +0100 Abort AppWatcher after every test commit 4b4c8756e0870068bfaeb9fe60acfe1322ce9989 Author: Isaac Roldán Date: Wed Nov 27 11:28:31 2024 +0100 Fix initial draft update commit 3fee076cd6f6a0340521889197c118c734bda37d Author: Alfonso Noriega Date: Mon Nov 25 15:53:46 2024 +0100 Add missing update imported flag for admin link and subscription link commit e6746ac5372e79fe09a5662dd813c9f547186525 Author: Alfonso Noriega Date: Mon Nov 25 15:20:08 2024 +0100 Remove All option if only one is imported commit d56b534dd3e898110dcae2be2fb12eee2afed7f9 Author: Alfonso Noriega Date: Tue Nov 19 11:34:57 2024 +0100 on import of legacy link extensions make absolute urls relative for embedded apps commit b25d93a5eb8c94c3045d790a1681b8a9ffc0dac3 Author: AaronBarcos Date: Wed Nov 27 10:25:41 2024 +0100 Fix lint error: handle unexpected errors in catch block commit ff994c34d370fe732d7f41c8677546520e8da489 Author: AaronBarcos Date: Wed Nov 27 10:12:27 2024 +0100 Add changeset for password validation fix commit 5ac28c0c89187e3fed052b988a1149e6552d9799 Author: aaronbarcos Date: Thu Nov 21 11:27:18 2024 +0100 Enhance storefront password validation to check redirect URL origin commit 501fadf8e98de8e0e1f5fa308f6d93a35fce3946 Author: aaronbarcos Date: Thu Nov 21 11:25:59 2024 +0100 Add tests for storefront password validation with localized URL and origin checks commit fe1b92e862faa60a0427da574cd34ee5110b9ea8 Author: Cedric Darne Date: Tue Nov 26 17:02:08 2024 -0500 Add the OrgId to all webhooks API calls The Organization ID is required by the new API to check the various token permissions commit d00e41a0d23e49a0ea7e534a12b132bdfe493ad1 Author: James Meng <35415298+jamesmengo@users.noreply.github.com> Date: Mon Nov 25 12:07:03 2024 -0800 Update CODEOWNERS - Add docs to Advanced edits allow-list - Add subfolders to `docs-shopify.dev` - Update README.md Motivation: Self serve for PR's like https://github.com/Shopify/cli/pull/4900/files where we add a new flag commit 6a802151a6bc01932631c363e6a790b23adc058f Merge: 04d6a2e6ce af2a07d082 Author: Ariel Caplan Date: Tue Nov 26 18:54:12 2024 +0000 Merge pull request #4926 from Shopify/message-field Use message field properly commit af2a07d082eb148abd8253a111547d91d2bb7635 Author: Ariel Caplan Date: Tue Nov 26 19:11:12 2024 +0200 Use message field properly commit 04d6a2e6ce6f08a3a746b903d387d2d6f41592c4 Merge: ecb0b9d103 928fbe72b4 Author: Shaun Stanworth Date: Tue Nov 26 18:07:33 2024 +0000 Merge pull request #4923 from Shopify/fix-knip Remove micromatch dependency commit ebca8acc260931d6dd2a1a65395b38ec917feaf9 Author: Cedric Darne Date: Mon Nov 25 18:12:56 2024 -0500 sendSampleWebhook better null field handling commit c49eb8ac5045a315987cb035c98783e36ff34ca9 Author: Cedric Darne Date: Mon Nov 25 12:19:50 2024 -0500 Simplify the PublicApiVersions query commit d567c2f246146771ba925a3166baf8433f5a699d Author: Cedric Darne Date: Fri Nov 15 16:30:50 2024 -0500 Introduce dev dash webhooks API commit 928fbe72b418d528a966fd45cfab60f6b0ca6102 Author: Isaac Roldán Date: Tue Nov 26 10:33:15 2024 +0100 fix-knip commit 97117a0a8ef3bea19eb8a6b0700bd8a47a92970a Author: Nick Wesselman <27013789+nickwesselman@users.noreply.github.com> Date: Mon Oct 21 11:45:14 2024 -0400 Normalize URL and use hyperlinks commit 6b063d17c1464c9fa36c4ec9ddeeab343f7069eb Author: Nick Wesselman <27013789+nickwesselman@users.noreply.github.com> Date: Mon Oct 21 10:36:40 2024 -0400 Fix the URL output to add a new product commit 5d960d494a32ff3735ce34fa92d3835448e8c997 Author: Surma Date: Tue Oct 1 14:36:33 2024 +0100 Remove reference to package.json commit a84792f30c81dedd2ff0c6444bb37d8cc6f741e9 Author: Gonzalo Riestra Date: Wed Sep 25 17:32:11 2024 +0200 Add tests commit 07cd7c1b1388f34c914561539c8b6db7b19a4ba3 Author: Ariel Caplan Date: Wed Sep 25 14:49:27 2024 +0300 Fix check to enforce everything commit 9c9b8df4ed578f548d222645d023d730e5e9fa88 Author: Gonzalo Riestra Date: Wed Sep 25 12:32:56 2024 +0200 Avoid errors on checkCommandSafety when the command is not found --- .changeset/dry-rice-guess.md | 5 - .changeset/eight-dragons-grab.md | 5 - .changeset/forty-islands-itch.md | 6 - .changeset/fresh-donkeys-clean.md | 5 - .changeset/good-plums-fail.md | 6 + .changeset/nervous-terms-invite.md | 6 + .changeset/pink-garlics-act.md | 5 - .changeset/quick-eggs-end.md | 5 + .changeset/red-tips-mix.md | 6 + .changeset/seven-seahorses-bake.md | 5 + .changeset/shaggy-cheetahs-think.md | 5 + .changeset/silver-mice-thank.md | 6 + .changeset/swift-frogs-fail.md | 5 - .changeset/wet-rats-applaud.md | 5 - .github/CODEOWNERS | 6 +- .github/ISSUE_TEMPLATE/bug-report.yml | 12 +- .../run-and-save-test-coverage/action.yml | 2 +- .github/dependabot.yml | 28 +- .gitignore | 1 + RELEASE_NOTES/3.71.md | 17 + RELEASE_NOTES/3.72.md | 8 + bin/get-graphql-schemas.js | 37 +- .../examples/theme-metafields-pull.example.sh | 1 + .../interfaces/app-build.interface.ts | 8 +- .../interfaces/app-config-link.interface.ts | 6 + .../interfaces/app-config-use.interface.ts | 8 +- .../interfaces/app-env-pull.interface.ts | 12 + .../interfaces/app-env-show.interface.ts | 12 + .../app-function-build.interface.ts | 12 + .../app-function-replay.interface.ts | 10 +- .../interfaces/app-function-run.interface.ts | 14 +- .../app-function-schema.interface.ts | 8 +- .../app-function-typegen.interface.ts | 12 + .../app-import-extensions.interface.ts | 6 + .../commands/interfaces/app-info.interface.ts | 16 +- .../interfaces/app-logs-sources.interface.ts | 12 + .../commands/interfaces/app-logs.interface.ts | 2 +- .../interfaces/app-versions-list.interface.ts | 12 +- .../app-webhook-trigger.interface.ts | 6 + .../interfaces/theme-info.interface.ts | 4 +- .../interfaces/theme-list.interface.ts | 4 +- .../theme-metafields-pull.interface.ts | 38 ++ .../interfaces/theme-push.interface.ts | 8 +- .../commands/theme-metafields-pull.doc.ts | 36 ++ .../generated/generated_docs_data.json | 417 ++++++++++++++--- docs/api/cli-kit/assets/navigation.js | 2 +- docs/api/cli-kit/assets/search.js | 2 +- .../classes/node_abort.AbortController.html | 2 +- .../classes/node_abort.AbortSignal.html | 2 +- .../classes/node_base_command.default.html | 4 +- ...ode_custom_oclif_loader.ShopifyConfig.html | 4 +- .../classes/node_error.AbortError.html | 4 +- .../classes/node_error.AbortSilentError.html | 4 +- .../cli-kit/classes/node_error.BugError.html | 4 +- .../classes/node_error.CancelExecution.html | 2 +- .../classes/node_error.ExternalError.html | 4 +- .../classes/node_error.FatalError.html | 4 +- .../node_git.GitDirectoryNotCleanError.html | 4 +- .../node_git.OutsideGitDirectoryError.html | 4 +- .../node_local_storage.LocalStorage.html | 12 +- ...FindUpAndReadPackageJsonNotFoundError.html | 4 +- ...kage_manager.PackageJsonNotFoundError.html | 4 +- ...ge_manager.UnknownPackageManagerError.html | 4 +- .../classes/node_output.TokenizedString.html | 4 +- .../node_plugins_tunnel.TunnelError.html | 4 +- docs/api/cli-kit/classes/node_result.Err.html | 16 +- docs/api/cli-kit/classes/node_result.Ok.html | 16 +- .../classes/node_testing_ui.Stdin.html | 4 +- ...ode_themes_theme_manager.ThemeManager.html | 4 +- ...vendor_dev_server_DevServer.DevServer.html | 7 + ...or_dev_server_DevServer.DevServerCore.html | 7 + ...etricReader.InstantaneousMetricReader.html | 4 +- ...rvice_BaseOtelService.BaseOtelService.html | 6 +- ...ultMeterProvider.DefaultMeterProvider.html | 4 +- ...DefaultOtelService.DefaultOtelService.html | 6 +- .../enums/node_error.FatalErrorType.html | 4 +- .../enums/node_themes_types.Operation.html | 4 +- ...js_service_types.MetricInstrumentType.html | 4 +- .../functions/common_array.difference.html | 2 +- ...mmon_array.getArrayContainsDuplicates.html | 2 +- ...mmon_array.getArrayRejectingUndefined.html | 2 +- .../common_array.takeRandomFromArray.html | 2 +- .../cli-kit/functions/common_array.uniq.html | 2 +- .../functions/common_array.uniqBy.html | 2 +- .../functions/common_collection.groupBy.html | 2 +- .../common_collection.partition.html | 2 +- .../functions/common_function.debounce.html | 2 +- .../functions/common_function.memoize.html | 2 +- .../functions/common_lang.isEqual.html | 2 +- .../functions/common_object.compact.html | 2 +- .../functions/common_object.deepCompare.html | 2 +- .../common_object.deepDifference.html | 2 +- .../common_object.deepMergeObjects.html | 2 +- .../functions/common_object.getPathValue.html | 2 +- .../functions/common_object.isEmpty.html | 2 +- .../functions/common_object.mapValues.html | 2 +- .../functions/common_object.pickBy.html | 2 +- .../functions/common_object.setPathValue.html | 2 +- ...y.performActionWithRetryAfterRecovery.html | 2 +- .../functions/common_string.camelize.html | 2 +- .../functions/common_string.capitalize.html | 2 +- .../functions/common_string.constantize.html | 2 +- .../functions/common_string.escapeRegExp.html | 2 +- .../functions/common_string.formatDate.html | 2 +- .../common_string.formatLocalDate.html | 2 +- .../common_string.getRandomName.html | 2 +- .../functions/common_string.hyphenate.html | 2 +- .../functions/common_string.joinWithAnd.html | 2 +- .../common_string.linesToColumns.html | 2 +- ...ommon_string.normalizeDelimitedString.html | 2 +- .../functions/common_string.pascalize.html | 2 +- .../functions/common_string.pluralize.html | 2 +- .../functions/common_string.slugify.html | 2 +- .../functions/common_string.tryParseInt.html | 2 +- .../functions/common_string.underscore.html | 2 +- ...mon_ts_json_narrowing.assertStringMap.html | 2 +- .../functions/common_url.isValidURL.html | 2 +- .../functions/common_url.safeParseURL.html | 2 +- .../node_analytics.reportAnalyticsEvent.html | 2 +- .../node_api_admin.adminRequest.html | 2 +- .../node_api_admin.adminRequestDoc.html | 2 +- .../functions/node_api_admin.adminUrl.html | 2 +- .../functions/node_api_admin.restRequest.html | 2 +- .../node_api_admin.supportedApiVersions.html | 2 +- .../node_api_app_dev.appDevRequest.html | 2 +- ...pp_management.appManagementRequestDoc.html | 2 +- ...api_app_management.handleDeprecations.html | 2 +- ....businessPlatformOrganizationsRequest.html | 2 +- ...sinessPlatformOrganizationsRequestDoc.html | 2 +- ...ness_platform.businessPlatformRequest.html | 2 +- ...s_platform.businessPlatformRequestDoc.html | 2 +- ...ode_api_functions.functionsRequestDoc.html | 8 + .../node_api_graphql.graphqlRequest.html | 2 +- .../node_api_graphql.graphqlRequestDoc.html | 2 +- .../node_api_partners.handleDeprecations.html | 2 +- .../node_api_partners.partnersRequest.html | 2 +- .../node_api_partners.partnersRequestDoc.html | 2 +- ...pi_rest_api_throttler.delayAwareRetry.html | 2 +- .../node_api_rest_api_throttler.throttle.html | 2 +- ...ottler.updateApiCallLimitFromResponse.html | 2 +- .../node_api_webhooks.webhooksRequest.html | 8 + .../cli-kit/functions/node_archiver.zip.html | 2 +- .../node_base_command.addFromParsedFlags.html | 2 +- .../functions/node_cli.clearCache.html | 2 +- .../functions/node_cli.localCliPackage.html | 1 - .../cli-kit/functions/node_cli.runCLI.html | 6 +- .../functions/node_cli.runCreateCLI.html | 4 +- .../node_cli.useLocalCLIIfDetected.html | 1 - .../node_cli_launcher.launchCLI.html | 4 + .../node_context_fqdn.appManagementFqdn.html | 2 +- ...ode_context_fqdn.businessPlatformFqdn.html | 2 +- ...e_context_fqdn.developerDashboardFqdn.html | 2 +- .../node_context_fqdn.identityFqdn.html | 2 +- .../node_context_fqdn.normalizeStoreFqdn.html | 2 +- .../node_context_fqdn.partnersFqdn.html | 2 +- ...node_context_local.alwaysLogAnalytics.html | 2 +- .../node_context_local.alwaysLogMetrics.html | 2 +- .../node_context_local.analyticsDisabled.html | 2 +- .../node_context_local.ciPlatform.html | 2 +- .../node_context_local.cloudEnvironment.html | 2 +- ...t_local.codespacePortForwardingDomain.html | 2 +- .../node_context_local.codespaceURL.html | 2 +- .../node_context_local.firstPartyDev.html | 2 +- .../node_context_local.gitpodURL.html | 2 +- .../functions/node_context_local.hasGit.html | 2 +- .../node_context_local.homeDirectory.html | 2 +- ..._context_local.isAppManagementEnabled.html | 4 + ...node_context_local.isCloudEnvironment.html | 2 +- .../node_context_local.isDevelopment.html | 2 +- .../node_context_local.isShopify.html | 2 +- ...e_context_local.isTerminalInteractive.html | 2 +- .../node_context_local.isUnitTest.html | 2 +- .../node_context_local.isVerbose.html | 2 +- .../node_context_local.macAddress.html | 2 +- ...ode_context_local.opentelemetryDomain.html | 2 +- .../node_context_local.themeToken.html | 2 +- ...ode_context_local.useEmbeddedThemeCLI.html | 2 +- .../node_context_local.useThemebundling.html | 2 +- .../functions/node_context_spin.appHost.html | 2 +- .../functions/node_context_spin.appPort.html | 2 +- .../node_context_spin.fetchSpinPort.html | 2 +- .../functions/node_context_spin.instance.html | 2 +- .../functions/node_context_spin.isSpin.html | 2 +- .../node_context_spin.isSpinEnvironment.html | 2 +- .../functions/node_context_spin.show.html | 2 +- .../functions/node_context_spin.spinFqdn.html | 2 +- .../node_context_utilities.isTruthy.html | 2 +- .../node_crypto.base64URLEncode.html | 2 +- .../functions/node_crypto.fileHash.html | 2 +- .../functions/node_crypto.hashString.html | 2 +- .../functions/node_crypto.nonRandomUUID.html | 2 +- .../functions/node_crypto.randomBytes.html | 2 +- .../functions/node_crypto.randomHex.html | 2 +- .../functions/node_crypto.randomUUID.html | 2 +- .../cli-kit/functions/node_crypto.sha256.html | 2 +- .../node_dot_env.createDotEnvFileLine.html | 2 +- .../functions/node_dot_env.patchEnvFile.html | 2 +- .../node_dot_env.readAndParseDotEnv.html | 2 +- .../functions/node_dot_env.writeDotEnv.html | 2 +- .../node_environment.getBackendPort.html | 2 +- ...e_environment.getEnvironmentVariables.html | 2 +- ...vironment.getIdentityTokenInformation.html | 2 +- .../node_environment.getOrganization.html | 2 +- .../node_environment.getPartnersToken.html | 2 +- .../node_environment.jsonOutputEnabled.html | 4 + .../node_environment.usePartnersToken.html | 2 +- .../node_environments.loadEnvironment.html | 2 +- .../node_error.cleanSingleStackTracePath.html | 2 +- .../functions/node_error.errorMapper.html | 2 +- .../cli-kit/functions/node_error.handler.html | 2 +- ...e_error.shouldReportErrorAsUnexpected.html | 2 +- ...node_error_handler.addBugsnagMetadata.html | 2 +- ...error_handler.cleanStackFrameFilePath.html | 2 +- .../node_error_handler.errorHandler.html | 2 +- ...erCleanBugsnagErrorsFromWithinPlugins.html | 2 +- ...node_error_handler.sendErrorToBugsnag.html | 2 +- .../node_framework.resolveFramework.html | 2 +- .../cli-kit/functions/node_fs.appendFile.html | 2 +- .../functions/node_fs.appendFileSync.html | 2 +- docs/api/cli-kit/functions/node_fs.chmod.html | 2 +- .../cli-kit/functions/node_fs.copyFile.html | 2 +- .../node_fs.createFileReadStream.html | 2 +- .../node_fs.createFileWriteStream.html | 2 +- .../cli-kit/functions/node_fs.fileExists.html | 2 +- .../functions/node_fs.fileExistsSync.html | 2 +- .../node_fs.fileHasExecutablePermissions.html | 2 +- .../functions/node_fs.fileLastUpdated.html | 2 +- .../node_fs.fileLastUpdatedTimestamp.html | 2 +- .../functions/node_fs.fileRealPath.html | 2 +- .../cli-kit/functions/node_fs.fileSize.html | 2 +- .../functions/node_fs.fileSizeSync.html | 2 +- .../cli-kit/functions/node_fs.findPathUp.html | 2 +- ..._fs.generateRandomNameForSubdirectory.html | 2 +- docs/api/cli-kit/functions/node_fs.glob.html | 2 +- .../node_fs.inTemporaryDirectory.html | 2 +- .../functions/node_fs.isDirectory.html | 2 +- .../cli-kit/functions/node_fs.matchGlob.html | 2 +- .../cli-kit/functions/node_fs.mkTmpDir.html | 2 +- docs/api/cli-kit/functions/node_fs.mkdir.html | 2 +- .../cli-kit/functions/node_fs.mkdirSync.html | 2 +- .../cli-kit/functions/node_fs.moveFile.html | 2 +- .../functions/node_fs.pathToFileURL.html | 2 +- .../cli-kit/functions/node_fs.readFile.html | 4 +- .../functions/node_fs.readFileSync.html | 2 +- .../cli-kit/functions/node_fs.removeFile.html | 2 +- .../functions/node_fs.removeFileSync.html | 2 +- .../cli-kit/functions/node_fs.renameFile.html | 2 +- docs/api/cli-kit/functions/node_fs.rmdir.html | 2 +- .../functions/node_fs.stripUpPath.html | 2 +- .../functions/node_fs.tempDirectory.html | 2 +- .../cli-kit/functions/node_fs.touchFile.html | 2 +- .../functions/node_fs.touchFileSync.html | 2 +- .../functions/node_fs.unlinkFileSync.html | 2 +- .../cli-kit/functions/node_fs.writeFile.html | 2 +- .../functions/node_fs.writeFileSync.html | 2 +- .../node_git.addAllToGitFromDirectory.html | 2 +- ...ode_git.checkIfIgnoredInGitRepository.html | 2 +- .../functions/node_git.createGitCommit.html | 2 +- .../functions/node_git.createGitIgnore.html | 2 +- .../node_git.downloadGitRepository.html | 2 +- .../node_git.ensureGitIsPresentOrAbort.html | 2 +- .../node_git.ensureInsideGitDirectory.html | 2 +- .../functions/node_git.ensureIsClean.html | 2 +- .../node_git.getHeadSymbolicRef.html | 2 +- .../node_git.getLatestGitCommit.html | 2 +- .../node_git.initializeGitRepository.html | 2 +- .../cli-kit/functions/node_git.isClean.html | 2 +- .../node_github.getLatestGitHubRelease.html | 2 +- ...github.parseGitHubRepositoryReference.html | 2 +- .../node_github.parseGitHubRepositoryURL.html | 2 +- ...de_global_context.getCurrentCommandId.html | 2 +- ...de_global_context.setCurrentCommandId.html | 2 +- .../node_hooks_deprecations.postrun.html | 2 +- .../functions/node_hooks_postrun.hook.html | 2 +- .../functions/node_hooks_prerun.hook.html | 2 +- ...node_hooks_prerun.parseCommandContent.html | 2 +- ...e_hooks_prerun.warnOnAvailableUpgrade.html | 2 +- .../functions/node_hrtime.endHRTimeInMs.html | 2 +- .../functions/node_hrtime.startHRTime.html | 2 +- .../functions/node_http.downloadFile.html | 2 +- .../cli-kit/functions/node_http.fetch.html | 2 +- .../cli-kit/functions/node_http.formData.html | 2 +- .../functions/node_http.shopifyFetch.html | 2 +- ...node_is_global.currentProcessIsGlobal.html | 2 +- ...lobal.inferPackageManagerForGlobalCLI.html | 2 +- ...node_is_global.installGlobalCLIPrompt.html | 2 +- ...ode_is_global.installGlobalShopifyCLI.html | 2 +- .../node_is_global.isGlobalCLIInstalled.html | 2 +- .../node_json_schema.jsonSchemaValidate.html | 5 +- .../node_json_schema.normaliseJsonSchema.html | 2 +- ...de_liquid.recursiveLiquidTemplateCopy.html | 2 +- .../node_liquid.renderLiquidTemplate.html | 2 +- .../functions/node_logs.createLogsDir.html | 2 +- .../functions/node_logs.getLogsDir.html | 2 +- .../cli-kit/functions/node_logs.writeLog.html | 2 +- .../node_metadata.addPublicMetadata.html | 2 +- .../node_metadata.addSensitiveMetadata.html | 2 +- ...tadata.createRuntimeMetadataContainer.html | 2 +- .../node_metadata.getAllPublicMetadata.html | 2 +- ...node_metadata.getAllSensitiveMetadata.html | 2 +- .../functions/node_metadata.runWithTimer.html | 2 +- .../functions/node_mimes.lookupMimeType.html | 2 +- .../functions/node_mimes.setMimeTypes.html | 2 +- .../node_monorail.publishMonorailEvent.html | 2 +- ...de_package_manager.addNPMDependencies.html | 2 +- ...ge_manager.addNPMDependenciesIfNeeded.html | 2 +- ...NPMDependenciesWithoutVersionIfNeeded.html | 2 +- ...ckage_manager.addResolutionOrOverride.html | 2 +- ...kage_manager.checkForCachedNewVersion.html | 2 +- ...de_package_manager.checkForNewVersion.html | 2 +- ...kage_manager.findUpAndReadPackageJson.html | 2 +- ..._node_package_manager.getDependencies.html | 2 +- ...ode_package_manager.getPackageManager.html | 2 +- ...e_node_package_manager.getPackageName.html | 2 +- ...ode_package_manager.getPackageVersion.html | 2 +- ...e_package_manager.inferPackageManager.html | 2 +- ...ger.installNPMDependenciesRecursively.html | 2 +- ...de_package_manager.installNodeModules.html | 2 +- ...e_manager.packageManagerFromUserAgent.html | 2 +- ...ckage_manager.readAndParsePackageJson.html | 2 +- ...e_node_package_manager.usesWorkspaces.html | 2 +- ...node_package_manager.versionSatisfies.html | 2 +- ...node_package_manager.writePackageJSON.html | 2 +- ...ifications_system.filterNotifications.html | 2 +- ...notifications_system.getNotifications.html | 2 +- ...ions_system.showNotificationsIfNeeded.html | 5 +- ...notifications_system.stringifyFilters.html | 2 +- .../functions/node_os.platformAndArch.html | 2 +- .../cli-kit/functions/node_os.username.html | 2 +- .../node_output.clearCollectedLogs.html | 2 +- .../functions/node_output.collectLog.html | 2 +- .../functions/node_output.consoleError.html | 2 +- .../functions/node_output.consoleLog.html | 2 +- .../functions/node_output.consoleWarn.html | 2 +- ...de_output.formatPackageManagerCommand.html | 2 +- .../functions/node_output.formatSection.html | 2 +- .../functions/node_output.itemToString.html | 2 +- .../node_output.outputCompleted.html | 2 +- .../functions/node_output.outputContent.html | 2 +- .../functions/node_output.outputDebug.html | 2 +- .../functions/node_output.outputInfo.html | 2 +- .../functions/node_output.outputNewline.html | 2 +- .../functions/node_output.outputSuccess.html | 2 +- .../functions/node_output.outputWarn.html | 2 +- .../node_output.outputWhereAppropriate.html | 5 +- .../node_output.shouldDisplayColors.html | 2 +- .../node_output.stringifyMessage.html | 2 +- .../functions/node_output.unstyled.html | 2 +- .../cli-kit/functions/node_path.basename.html | 2 +- docs/api/cli-kit/functions/node_path.cwd.html | 2 +- .../cli-kit/functions/node_path.dirname.html | 2 +- .../cli-kit/functions/node_path.extname.html | 2 +- .../functions/node_path.isAbsolutePath.html | 2 +- .../functions/node_path.isSubpath.html | 2 +- .../cli-kit/functions/node_path.joinPath.html | 2 +- .../functions/node_path.moduleDirectory.html | 2 +- .../functions/node_path.normalizePath.html | 2 +- .../functions/node_path.relativePath.html | 2 +- .../functions/node_path.relativizePath.html | 2 +- .../functions/node_path.resolvePath.html | 2 +- .../functions/node_path.sniffForJson.html | 8 +- .../functions/node_path.sniffForPath.html | 2 +- .../functions/node_plugins.fanoutHooks.html | 2 +- .../node_plugins.getListOfTunnelPlugins.html | 2 +- .../node_plugins_tunnel.defineProvider.html | 2 +- .../node_plugins_tunnel.startTunnel.html | 2 +- .../node_promises.flushPromises.html | 2 +- .../cli-kit/functions/node_result.err-1.html | 2 +- .../cli-kit/functions/node_result.ok-1.html | 2 +- .../functions/node_schema.deepStrict.html | 2 +- .../functions/node_schema.errorsToString.html | 2 +- ...node_session.ensureAuthenticatedAdmin.html | 2 +- ...sion.ensureAuthenticatedAppManagement.html | 2 +- ...n.ensureAuthenticatedBusinessPlatform.html | 2 +- ...e_session.ensureAuthenticatedPartners.html | 2 +- ...session.ensureAuthenticatedStorefront.html | 2 +- ...ode_session.ensureAuthenticatedThemes.html | 2 +- .../functions/node_session.logout.html | 2 +- .../functions/node_system.captureOutput.html | 2 +- .../cli-kit/functions/node_system.exec.html | 2 +- .../functions/node_system.openURL.html | 2 +- .../cli-kit/functions/node_system.sleep.html | 2 +- ...node_system.terminalSupportsPrompting.html | 2 +- .../node_tcp.checkPortAvailability.html | 2 +- .../node_tcp.getAvailableTCPPort.html | 2 +- ...e_testing_output.mockAndCaptureOutput.html | 2 +- ...e_testing_ui.getLastFrameAfterUnmount.html | 2 +- .../functions/node_testing_ui.render.html | 2 +- .../node_testing_ui.sendInputAndWait.html | 2 +- ..._testing_ui.sendInputAndWaitForChange.html | 2 +- ...testing_ui.sendInputAndWaitForContent.html | 2 +- .../node_testing_ui.waitForContent.html | 2 +- ...ode_testing_ui.waitForInputsToBeReady.html | 2 +- ...node_themes_api.bulkUploadThemeAssets.html | 2 +- .../node_themes_api.createTheme.html | 2 +- .../node_themes_api.deleteThemeAsset.html | 2 +- .../node_themes_api.fetchChecksums.html | 2 +- .../functions/node_themes_api.fetchTheme.html | 2 +- .../node_themes_api.fetchThemeAssets.html | 2 +- .../node_themes_api.fetchThemes.html | 2 +- .../node_themes_api.themeDelete.html | 2 +- .../node_themes_api.themePublish.html | 2 +- .../node_themes_api.themeUpdate.html | 2 +- .../node_themes_conf.getHostTheme.html | 2 +- ...ode_themes_conf.hostThemeLocalStorage.html | 2 +- .../node_themes_conf.removeHostTheme.html | 2 +- .../node_themes_conf.setHostTheme.html | 2 +- ...emes_factories.buildBulkUploadResults.html | 1 - .../node_themes_factories.buildChecksum.html | 2 +- .../node_themes_factories.buildTheme.html | 2 +- ...node_themes_factories.buildThemeAsset.html | 2 +- .../node_themes_urls.codeEditorUrl.html | 2 +- .../node_themes_urls.storeAdminUrl.html | 2 +- .../node_themes_urls.storePasswordPage.html | 2 +- .../node_themes_urls.themeEditorUrl.html | 2 +- .../node_themes_urls.themePreviewUrl.html | 2 +- .../node_themes_utils.composeThemeGid.html | 2 +- .../node_themes_utils.isDevelopmentTheme.html | 2 +- .../functions/node_themes_utils.parseGid.html | 2 +- .../node_themes_utils.promptThemeName.html | 2 +- .../functions/node_toml.decodeToml.html | 2 +- .../functions/node_toml.encodeToml.html | 2 +- .../functions/node_tree_kill.treeKill.html | 2 +- .../functions/node_ui.handleCtrlC.html | 2 +- docs/api/cli-kit/functions/node_ui.isTTY.html | 2 +- .../cli-kit/functions/node_ui.keypress.html | 2 +- .../api/cli-kit/functions/node_ui.render.html | 2 +- .../node_ui.renderAutocompletePrompt.html | 2 +- .../functions/node_ui.renderConcurrent.html | 2 +- .../node_ui.renderConfirmationPrompt.html | 2 +- ..._ui.renderDangerousConfirmationPrompt.html | 2 +- .../functions/node_ui.renderError.html | 2 +- .../functions/node_ui.renderFatalError.html | 2 +- .../cli-kit/functions/node_ui.renderInfo.html | 2 +- .../functions/node_ui.renderSelectPrompt.html | 2 +- .../functions/node_ui.renderSuccess.html | 2 +- .../functions/node_ui.renderTable.html | 2 +- .../functions/node_ui.renderTasks.html | 2 +- .../cli-kit/functions/node_ui.renderText.html | 2 +- .../functions/node_ui.renderTextPrompt.html | 2 +- .../functions/node_ui.renderWarning.html | 2 +- .../node_ui_components.ConcurrentOutput.html | 2 +- ...components.useConcurrentOutputContext.html | 2 +- .../node_ui_hooks.useAbortSignal.html | 2 +- .../node_upgrade.cliInstallCommand.html | 2 +- ...de_upgrade.getOutputUpdateCLIReminder.html | 2 +- ..._dev_server_network_interfaces.fromIp.html | 1 + ...erver_network_interfaces.getInterface.html | 1 + ...or_dev_server_network_interfaces.toIp.html | 1 + ...endor_otel_js_utils_throttle.throttle.html | 2 +- ...js_utils_validators.isValidMetricName.html | 2 +- .../node_version.globalCLIVersion.html | 2 +- .../node_version.localCLIVersion.html | 2 +- .../node_vscode.addRecommendedExtensions.html | 2 +- .../functions/node_vscode.isVSCode.html | 2 +- docs/api/cli-kit/index.html | 5 + .../node_api_admin.RestResponse.html | 8 +- ...de_api_graphql.GraphQLResponseOptions.html | 4 +- .../node_api_graphql.GraphQLVariables.html | 2 +- .../interfaces/node_dot_env.DotEnvFile.html | 6 +- .../node_environments.Environments.html | 2 +- .../interfaces/node_fs.MatchGlobOptions.html | 4 +- .../interfaces/node_fs.WriteOptions.html | 4 +- .../node_git.CreateGitCommitOptions.html | 4 +- .../interfaces/node_git.GitCloneOptions.html | 4 +- .../node_git.GitIgnoreTemplate.html | 2 +- .../interfaces/node_github.GithubRelease.html | 4 +- ...node_github.GithubRepositoryReference.html | 4 +- .../node_global_context.GlobalContext.html | 4 +- .../node_hooks_prerun.CommandContent.html | 4 +- ...s_global.InstallGlobalCLIPromptResult.html | 4 +- .../node_metadata.RuntimeMetadataManager.html | 12 +- .../interfaces/node_monorail.Schemas.html | 4 +- ...ode_package_manager.DependencyVersion.html | 6 +- ...node_node_package_manager.PackageJson.html | 28 +- .../interfaces/node_output.OutputProcess.html | 6 +- .../node_plugins.HookReturnsPerPlugin.html | 4 +- .../node_plugins.TunnelPluginError.html | 4 +- ...gins_tunnel.HookReturnPerTunnelPlugin.html | 4 +- .../node_plugins_tunnel.TunnelClient.html | 4 +- .../interfaces/node_session.AdminSession.html | 4 +- .../interfaces/node_system.ExecOptions.html | 4 +- ...es_factories.RemoteBulkUploadResponse.html | 4 +- .../node_themes_types.Checksum.html | 6 +- .../interfaces/node_themes_types.Result.html | 12 +- .../interfaces/node_themes_types.Theme.html | 14 +- .../node_themes_types.ThemeAsset.html | 12 +- ...themes_types.ThemeExtensionFileSystem.html | 20 +- .../node_themes_types.ThemeFileSystem.html | 22 +- ...e_themes_types.ThemeFileSystemOptions.html | 4 +- .../node_themes_types.VirtualFileSystem.html | 18 +- .../interfaces/node_ui.InfoTableSection.html | 4 +- .../cli-kit/interfaces/node_ui.LinkToken.html | 4 +- .../cli-kit/interfaces/node_ui.ListToken.html | 4 +- .../node_ui.RenderAutocompleteOptions.html | 4 +- .../node_ui.RenderConcurrentOptions.html | 4 +- ...de_ui.RenderConfirmationPromptOptions.html | 4 +- ...derDangerousConfirmationPromptOptions.html | 4 +- .../node_ui.RenderSelectPromptOptions.html | 4 +- .../node_ui.RenderTextPromptOptions.html | 4 +- docs/api/cli-kit/interfaces/node_ui.Task.html | 4 +- ...ui_components.ConcurrentOutputContext.html | 4 +- ...ader.InstantaneousMetricReaderOptions.html | 6 +- ...aseOtelService.BaseOtelServiceOptions.html | 12 +- ...OtelService.DefaultOtelServiceOptions.html | 18 +- ...r_otel_js_service_types.MetricsConfig.html | 2 +- ...dor_otel_js_service_types.OtelService.html | 6 +- docs/api/cli-kit/modules/common_array.html | 2 +- .../cli-kit/modules/common_collection.html | 2 +- docs/api/cli-kit/modules/common_function.html | 2 +- docs/api/cli-kit/modules/common_lang.html | 2 +- docs/api/cli-kit/modules/common_object.html | 2 +- docs/api/cli-kit/modules/common_retry.html | 2 +- docs/api/cli-kit/modules/common_string.html | 2 +- .../modules/common_ts_deep_required.html | 2 +- .../modules/common_ts_json_narrowing.html | 2 +- .../modules/common_ts_pick_by_prefix.html | 2 +- docs/api/cli-kit/modules/common_url.html | 2 +- docs/api/cli-kit/modules/common_version.html | 2 +- docs/api/cli-kit/modules/node_abort.html | 2 +- docs/api/cli-kit/modules/node_analytics.html | 2 +- docs/api/cli-kit/modules/node_api_admin.html | 2 +- .../api/cli-kit/modules/node_api_app_dev.html | 2 +- .../modules/node_api_app_management.html | 2 +- .../modules/node_api_business_platform.html | 2 +- .../cli-kit/modules/node_api_functions.html | 2 + .../api/cli-kit/modules/node_api_graphql.html | 2 +- docs/api/cli-kit/modules/node_api_http.html | 2 +- .../cli-kit/modules/node_api_partners.html | 2 +- .../modules/node_api_rest_api_throttler.html | 2 +- .../cli-kit/modules/node_api_webhooks.html | 2 + docs/api/cli-kit/modules/node_archiver.html | 2 +- .../cli-kit/modules/node_base_command.html | 2 +- docs/api/cli-kit/modules/node_cli.html | 5 +- .../cli-kit/modules/node_cli_launcher.html | 2 + docs/api/cli-kit/modules/node_colors.html | 2 +- .../cli-kit/modules/node_context_fqdn.html | 2 +- .../cli-kit/modules/node_context_local.html | 3 +- .../cli-kit/modules/node_context_spin.html | 2 +- .../modules/node_context_utilities.html | 2 +- docs/api/cli-kit/modules/node_crypto.html | 2 +- .../modules/node_custom_oclif_loader.html | 2 +- docs/api/cli-kit/modules/node_dot_env.html | 2 +- .../api/cli-kit/modules/node_environment.html | 3 +- .../cli-kit/modules/node_environments.html | 2 +- docs/api/cli-kit/modules/node_error.html | 2 +- .../cli-kit/modules/node_error_handler.html | 2 +- docs/api/cli-kit/modules/node_figures.html | 2 +- docs/api/cli-kit/modules/node_framework.html | 2 +- docs/api/cli-kit/modules/node_fs.html | 2 +- docs/api/cli-kit/modules/node_git.html | 2 +- docs/api/cli-kit/modules/node_github.html | 2 +- .../cli-kit/modules/node_global_context.html | 2 +- .../modules/node_hooks_deprecations.html | 2 +- .../cli-kit/modules/node_hooks_postrun.html | 2 +- .../cli-kit/modules/node_hooks_prerun.html | 2 +- docs/api/cli-kit/modules/node_hrtime.html | 2 +- docs/api/cli-kit/modules/node_http.html | 2 +- docs/api/cli-kit/modules/node_ink.html | 2 +- docs/api/cli-kit/modules/node_is_global.html | 2 +- .../api/cli-kit/modules/node_json_schema.html | 2 +- docs/api/cli-kit/modules/node_liquid.html | 2 +- .../cli-kit/modules/node_local_storage.html | 2 +- docs/api/cli-kit/modules/node_logs.html | 2 +- docs/api/cli-kit/modules/node_metadata.html | 2 +- docs/api/cli-kit/modules/node_mimes.html | 2 +- docs/api/cli-kit/modules/node_monorail.html | 2 +- .../modules/node_node_package_manager.html | 2 +- .../modules/node_notifications_system.html | 2 +- docs/api/cli-kit/modules/node_os.html | 2 +- docs/api/cli-kit/modules/node_output.html | 2 +- docs/api/cli-kit/modules/node_path.html | 2 +- docs/api/cli-kit/modules/node_plugins.html | 2 +- .../cli-kit/modules/node_plugins_tunnel.html | 2 +- docs/api/cli-kit/modules/node_promises.html | 2 +- docs/api/cli-kit/modules/node_result.html | 2 +- docs/api/cli-kit/modules/node_schema.html | 2 +- docs/api/cli-kit/modules/node_session.html | 2 +- docs/api/cli-kit/modules/node_system.html | 2 +- docs/api/cli-kit/modules/node_tcp.html | 2 +- .../cli-kit/modules/node_testing_output.html | 2 +- docs/api/cli-kit/modules/node_testing_ui.html | 2 +- docs/api/cli-kit/modules/node_themes_api.html | 2 +- .../api/cli-kit/modules/node_themes_conf.html | 2 +- .../modules/node_themes_factories.html | 5 +- .../modules/node_themes_theme_manager.html | 2 +- .../cli-kit/modules/node_themes_types.html | 2 +- .../api/cli-kit/modules/node_themes_urls.html | 2 +- .../cli-kit/modules/node_themes_utils.html | 2 +- docs/api/cli-kit/modules/node_toml.html | 2 +- docs/api/cli-kit/modules/node_tree_kill.html | 2 +- docs/api/cli-kit/modules/node_ui.html | 2 +- .../cli-kit/modules/node_ui_components.html | 2 +- docs/api/cli-kit/modules/node_ui_hooks.html | 2 +- docs/api/cli-kit/modules/node_upgrade.html | 2 +- .../node_vendor_dev_server_DevServer.html | 3 + ..._vendor_dev_server_network_interfaces.html | 4 + ...l_js_export_InstantaneousMetricReader.html | 2 +- ...rvice_BaseOtelService_BaseOtelService.html | 2 +- ...faultOtelService_DefaultMeterProvider.html | 2 +- ...DefaultOtelService_DefaultOtelService.html | 2 +- .../node_vendor_otel_js_service_types.html | 2 +- .../node_vendor_otel_js_utils_throttle.html | 2 +- .../node_vendor_otel_js_utils_validators.html | 2 +- docs/api/cli-kit/modules/node_version.html | 2 +- docs/api/cli-kit/modules/node_vscode.html | 2 +- .../types/common_string.RandomNameFamily.html | 2 +- .../common_ts_deep_required.DeepRequired.html | 2 +- ...common_ts_pick_by_prefix.PickByPrefix.html | 2 +- .../types/node_analytics.CommandExitMode.html | 2 +- .../cli-kit/types/node_api_graphql.Exact.html | 2 +- ..._api_graphql.GraphQLRequestDocOptions.html | 2 +- ...ode_api_graphql.GraphQLRequestOptions.html | 2 +- .../node_api_graphql.GraphQLResponse.html | 2 +- .../types/node_context_local.CIMetadata.html | 2 +- .../cli-kit/types/node_fs.ReadOptions.html | 2 +- .../cli-kit/types/node_hrtime.StartTime.html | 2 +- .../cli-kit/types/node_metadata.Public.html | 2 +- .../types/node_metadata.PublicSchema.html | 2 +- .../types/node_metadata.Sensitive.html | 2 +- .../types/node_metadata.SensitiveSchema.html | 2 +- .../node_monorail.MonorailEventPublic.html | 2 +- .../node_monorail.MonorailEventSensitive.html | 2 +- ...e_node_package_manager.DependencyType.html | 2 +- .../node_node_package_manager.Lockfile.html | 2 +- ...e_node_package_manager.PackageManager.html | 2 +- ...ode_notifications_system.Notification.html | 2 +- ...de_notifications_system.Notifications.html | 2 +- .../cli-kit/types/node_output.LogLevel.html | 2 +- .../api/cli-kit/types/node_output.Logger.html | 2 +- .../types/node_output.OutputMessage.html | 2 +- .../node_plugins.FanoutHookFunction.html | 2 +- .../node_plugins.PluginReturnsForHook.html | 2 +- .../node_plugins_tunnel.TunnelErrorType.html | 2 +- ...plugins_tunnel.TunnelProviderFunction.html | 2 +- ...node_plugins_tunnel.TunnelStartAction.html | 2 +- ...de_plugins_tunnel.TunnelStartFunction.html | 2 +- ...node_plugins_tunnel.TunnelStartReturn.html | 2 +- .../node_plugins_tunnel.TunnelStatusType.html | 2 +- .../api/cli-kit/types/node_result.Result.html | 2 +- .../node_schema.ParseConfigurationResult.html | 2 +- .../types/node_schema.ZodObjectOf.html | 2 +- .../types/node_themes_api.AssetParams.html | 2 +- .../types/node_themes_api.ThemeParams.html | 2 +- .../cli-kit/types/node_themes_types.Key.html | 2 +- .../node_themes_types.ThemeFSEventName.html | 2 +- ...node_themes_types.ThemeFSEventPayload.html | 2 +- .../cli-kit/types/node_themes_utils.Role.html | 2 +- .../cli-kit/types/node_toml.JsonMapType.html | 2 +- .../types/node_ui.AlertCustomSection.html | 2 +- .../cli-kit/types/node_ui.InfoMessage.html | 2 +- .../cli-kit/types/node_ui.InlineToken.html | 2 +- docs/api/cli-kit/types/node_ui.Key.html | 2 +- .../types/node_ui.RenderAlertOptions.html | 2 +- .../cli-kit/types/node_ui.TableColumn.html | 2 +- docs/api/cli-kit/types/node_ui.Token.html | 2 +- docs/api/cli-kit/types/node_ui.TokenItem.html | 2 +- ...vice_DefaultMeterProvider.Environment.html | 2 +- ...l_js_service_types.CustomMetricLabels.html | 2 +- ...tel_js_service_types.MetricDescriptor.html | 2 +- ...tel_js_service_types.MetricInstrument.html | 2 +- ...otel_js_service_types.MetricRecording.html | 2 +- ...tel_js_service_types.OnRecordCallback.html | 2 +- ...js_service_types.RecordMetricFunction.html | 2 +- .../common_version.CLI_KIT_VERSION.html | 2 +- .../variables/node_cli.globalFlags.html | 2 +- .../cli-kit/variables/node_cli.jsonFlag.html | 1 + ...dn.CouldntObtainIdentitySpinFQDNError.html | 2 +- ...dn.CouldntObtainPartnersSpinFQDNError.html | 2 +- ...qdn.CouldntObtainShopifySpinFQDNError.html | 2 +- ...ontext_fqdn.NotProvidedStoreFQDNError.html | 2 +- .../node_context_spin.spinVariables.html | 2 +- .../node_monorail.MONORAIL_COMMAND_TOPIC.html | 2 +- ...node_node_package_manager.bunLockfile.html | 2 +- .../node_node_package_manager.lockfiles.html | 2 +- ...node_node_package_manager.npmLockfile.html | 2 +- ...node_package_manager.packageManager-1.html | 2 +- ...ode_node_package_manager.pnpmLockfile.html | 2 +- ...ode_package_manager.pnpmWorkspaceFile.html | 2 +- ...ode_node_package_manager.yarnLockfile.html | 2 +- .../variables/node_output.collectedLogs.html | 2 +- .../variables/node_output.outputToken.html | 2 +- ...e_themes_utils.DEVELOPMENT_THEME_ROLE.html | 2 +- .../node_themes_utils.LIVE_THEME_ROLE.html | 2 +- ...e_themes_utils.UNPUBLISHED_THEME_ROLE.html | 2 +- graphql.config.ts | 7 +- nx.json | 1 + package.json | 2 +- packages/app/CHANGELOG.md | 81 ++++ packages/app/package.json | 15 +- packages/app/project.json | 42 +- .../active-app-release-from-api-key.ts | 164 +++++++ .../generated/active-app-release.ts | 231 +++++++--- .../generated/app-version-by-id.ts | 3 +- .../active-app-release-from-api-key.graphql | 5 + .../queries/active-app-release.graphql | 28 +- .../queries/app-version-by-id.graphql | 1 + .../functions/api_schema_definition.ts | 6 - .../schema-definition-by-api-type.ts | 74 +++ .../generated/schema-definition-by-target.ts | 84 ++++ .../graphql/functions/generated/types.d.ts | 24 + .../schema-definition-by-api-type.graphql | 7 + .../schema-definition-by-target.graphql | 9 + .../functions/target_schema_definition.ts | 6 - .../webhooks/generated/available-topics.ts | 44 ++ .../graphql/webhooks/generated/cli-testing.ts | 111 +++++ .../webhooks/generated/public-api-versions.ts | 35 ++ .../api/graphql/webhooks/generated/types.d.ts | 16 + .../webhooks/queries/available-topics.graphql | 3 + .../webhooks/queries/cli-testing.graphql | 8 + .../queries/public-api-versions.graphql | 5 + .../src/cli/commands/app/app-logs/sources.ts | 4 +- packages/app/src/cli/commands/app/build.ts | 12 +- .../app/src/cli/commands/app/config/link.ts | 6 - .../app/src/cli/commands/app/config/use.ts | 8 +- .../app/src/cli/commands/app/demo/watcher.ts | 4 +- packages/app/src/cli/commands/app/deploy.ts | 13 - packages/app/src/cli/commands/app/dev.ts | 13 - packages/app/src/cli/commands/app/env/pull.ts | 4 +- packages/app/src/cli/commands/app/env/show.ts | 4 +- .../src/cli/commands/app/function/build.ts | 2 + .../src/cli/commands/app/function/replay.ts | 18 +- .../app/src/cli/commands/app/function/run.ts | 15 +- .../src/cli/commands/app/function/schema.ts | 12 +- .../src/cli/commands/app/function/typegen.ts | 2 + .../cli/commands/app/generate/extension.ts | 15 +- .../src/cli/commands/app/import-extensions.ts | 9 +- packages/app/src/cli/commands/app/info.ts | 12 +- packages/app/src/cli/commands/app/init.ts | 17 +- packages/app/src/cli/commands/app/logs.ts | 12 +- packages/app/src/cli/commands/app/release.ts | 14 +- .../app/src/cli/commands/app/versions/list.ts | 18 +- .../src/cli/commands/app/webhook/trigger.ts | 9 +- packages/app/src/cli/flags.ts | 13 + .../app/src/cli/models/app/app.test-data.ts | 41 +- packages/app/src/cli/models/app/app.test.ts | 2 + packages/app/src/cli/models/app/app.ts | 1 - .../app/src/cli/models/app/loader.test.ts | 44 +- packages/app/src/cli/models/app/loader.ts | 92 ++-- .../app/validation/multi-cli-warning.ts | 43 ++ .../extensions/extension-instance.test.ts | 14 +- .../models/extensions/extension-instance.ts | 2 +- .../app/src/cli/models/extensions/schemas.ts | 5 + .../cli/models/extensions/specification.ts | 12 +- .../specifications/function.test.ts | 1 + .../extensions/specifications/function.ts | 1 + .../specifications/types/app_config.ts | 1 + .../specifications/ui_extension.test.ts | 171 ++++++- .../extensions/specifications/ui_extension.ts | 85 +++- packages/app/src/cli/models/organization.ts | 7 +- .../admin-link/extension-to-toml.test.ts | 107 ++++- .../services/admin-link/extension-to-toml.ts | 24 +- .../src/cli/services/admin-link/utils.test.ts | 24 +- .../app/src/cli/services/admin-link/utils.ts | 25 +- .../app/src/cli/services/app-context.test.ts | 14 +- packages/app/src/cli/services/app-context.ts | 5 +- .../services/app/config/link-service.test.ts | 7 +- .../src/cli/services/app/config/link.test.ts | 30 +- .../app/src/cli/services/app/config/link.ts | 5 +- .../src/cli/services/app/config/use.test.ts | 4 +- .../app/write-app-configuration-file.test.ts | 47 -- .../app/write-app-configuration-file.ts | 19 +- .../src/cli/services/build/extension.test.ts | 44 +- .../app/src/cli/services/build/extension.ts | 38 +- .../app/src/cli/services/build/theme-check.ts | 9 +- packages/app/src/cli/services/context.test.ts | 3 +- packages/app/src/cli/services/context.ts | 5 +- .../context/breakdown-extensions.test.ts | 1 + .../cli/services/context/id-matching.test.ts | 1 + .../context/identifiers-extensions.test.ts | 1 + .../context/identifiers-extensions.ts | 2 + .../src/cli/services/deploy/bundle.test.ts | 4 +- .../app/src/cli/services/deploy/bundle.ts | 4 +- .../app-events/app-event-watcher-handler.ts | 20 +- .../dev/app-events/app-event-watcher.test.ts | 317 +++++++------ .../dev/app-events/app-event-watcher.ts | 14 +- .../app-events/app-watcher-esbuild.test.ts | 46 +- .../dev/app-events/app-watcher-esbuild.ts | 69 ++- .../dev/app-events/file-watcher.test.ts | 54 ++- .../services/dev/app-events/file-watcher.ts | 272 +++++------ .../services/dev/extension/payload.test.ts | 145 ++++++ .../src/cli/services/dev/extension/payload.ts | 56 ++- .../services/dev/extension/payload/models.ts | 15 +- .../app/src/cli/services/dev/fetch.test.ts | 2 +- .../dev/processes/dev-session.test.ts | 31 +- .../cli/services/dev/processes/dev-session.ts | 17 +- .../dev/processes/draftable-extension.ts | 12 +- .../dev/processes/setup-dev-processes.test.ts | 13 +- .../dev/processes/setup-dev-processes.ts | 3 +- .../dev/processes/uninstall-webhook.ts | 5 + .../src/cli/services/dev/select-app.test.ts | 4 +- .../app/src/cli/services/dev/select-app.ts | 14 +- .../cli/services/dev/update-extension.test.ts | 6 +- .../src/cli/services/dev/update-extension.ts | 6 +- .../cli/services/function/binaries.test.ts | 44 +- .../app/src/cli/services/function/binaries.ts | 55 ++- .../src/cli/services/function/build.test.ts | 53 ++- .../app/src/cli/services/function/build.ts | 80 +++- .../src/cli/services/function/common.test.ts | 4 +- .../app/src/cli/services/function/common.ts | 13 +- .../src/cli/services/function/replay.test.ts | 1 + .../src/cli/services/generate-schema.test.ts | 80 ++-- .../app/src/cli/services/generate-schema.ts | 33 +- .../cli/services/generate/extension.test.ts | 1 + .../app/src/cli/services/import-extensions.ts | 15 +- packages/app/src/cli/services/info.test.ts | 4 +- packages/app/src/cli/services/init/init.ts | 13 +- .../services/init/template/cleanup.test.ts | 43 +- .../src/cli/services/init/template/cleanup.ts | 16 +- .../webhook/request-api-versions.test.ts | 3 +- .../services/webhook/request-api-versions.ts | 8 +- .../services/webhook/request-sample.test.ts | 6 +- .../cli/services/webhook/request-sample.ts | 4 + .../services/webhook/request-topics.test.ts | 3 +- .../cli/services/webhook/request-topics.ts | 4 +- .../send-app-uninstalled-webhook.test.ts | 4 + .../webhook/send-app-uninstalled-webhook.ts | 5 +- .../services/webhook/trigger-options.test.ts | 18 +- .../cli/services/webhook/trigger-options.ts | 11 +- .../src/cli/services/webhook/trigger.test.ts | 46 +- .../app/src/cli/services/webhook/trigger.ts | 9 +- .../src/cli/utilities/app/config/getTomls.ts | 3 +- .../utilities/developer-platform-client.ts | 31 +- .../app-management-client.test.ts | 180 ++++++++ .../app-management-client.ts | 136 ++++-- .../partners-client.ts | 47 +- .../extensions/fetch-product-variant.ts | 14 +- .../extensions/locales-configuration.test.ts | 4 +- .../extensions/locales-configuration.ts | 2 +- packages/app/src/cli/utilities/json-schema.ts | 3 +- packages/cli-kit/CHANGELOG.md | 31 ++ packages/cli-kit/package.json | 7 +- .../metafield_definitions_by_owner_type.ts | 87 ++++ .../admin/generated/theme_files_upsert.ts | 98 ++++ .../api/graphql/admin/generated/types.d.ts | 86 ++++ .../mutations/theme_files_upsert.graphql | 11 + ...etafield_definitions_by_owner_type.graphql | 14 + packages/cli-kit/src/private/node/api.test.ts | 52 +++ packages/cli-kit/src/private/node/api.ts | 28 +- .../cli-kit/src/private/node/constants.ts | 2 + packages/cli-kit/src/private/node/session.ts | 5 +- .../src/private/node/session/exchange.ts | 4 +- .../src/private/node/session/scopes.test.ts | 3 +- .../src/private/node/session/scopes.ts | 8 +- .../ui/components/AutocompletePrompt.test.tsx | 89 ++++ .../node/ui/components/SelectInput.tsx | 9 +- packages/cli-kit/src/public/common/version.ts | 2 +- packages/cli-kit/src/public/node/api/admin.ts | 12 +- .../cli-kit/src/public/node/api/functions.ts | 63 +++ .../src/public/node/api/graphql.test.ts | 3 +- .../cli-kit/src/public/node/api/graphql.ts | 61 ++- .../cli-kit/src/public/node/api/webhooks.ts | 45 ++ packages/cli-kit/src/public/node/cli.ts | 16 +- .../src/public/node/context/local.test.ts | 25 + .../cli-kit/src/public/node/context/local.ts | 10 + .../cli-kit/src/public/node/environment.ts | 12 + packages/cli-kit/src/public/node/error.ts | 4 +- packages/cli-kit/src/public/node/fs.ts | 15 +- packages/cli-kit/src/public/node/git.test.ts | 20 +- packages/cli-kit/src/public/node/git.ts | 14 +- packages/cli-kit/src/public/node/is-global.ts | 29 +- .../src/public/node/json-schema.test.ts | 10 +- .../cli-kit/src/public/node/json-schema.ts | 12 +- .../src/public/node/node-package-manager.ts | 7 + .../public/node/notifications-system.test.ts | 55 ++- .../src/public/node/notifications-system.ts | 12 +- packages/cli-kit/src/public/node/path.ts | 9 +- .../cli-kit/src/public/node/system.test.ts | 32 ++ packages/cli-kit/src/public/node/system.ts | 18 +- .../src/public/node/themes/api.test.ts | 221 +++++---- .../cli-kit/src/public/node/themes/api.ts | 111 ++++- .../src/public/node/themes/factories.ts | 23 +- packages/cli/CHANGELOG.md | 22 + packages/cli/README.md | 190 +++++--- packages/cli/oclif.manifest.json | 430 +++++++++++++++++- packages/cli/package.json | 16 +- packages/cli/src/index.ts | 12 +- packages/create-app/CHANGELOG.md | 14 + packages/create-app/oclif.manifest.json | 2 +- packages/create-app/package.json | 8 +- packages/create-app/src/index.ts | 12 +- .../rules/no-inline-graphql.js | 6 +- packages/plugin-cloudflare/CHANGELOG.md | 47 ++ packages/plugin-cloudflare/package.json | 4 +- packages/plugin-did-you-mean/CHANGELOG.md | 47 ++ packages/plugin-did-you-mean/package.json | 4 +- packages/theme/CHANGELOG.md | 57 +++ packages/theme/package.json | 8 +- .../src/cli/commands/theme/check.test.ts | 6 +- .../theme/src/cli/commands/theme/check.ts | 84 ++-- packages/theme/src/cli/commands/theme/dev.ts | 11 + packages/theme/src/cli/commands/theme/info.ts | 8 +- packages/theme/src/cli/commands/theme/list.ts | 8 +- .../src/cli/commands/theme/metafields/pull.ts | 40 ++ packages/theme/src/cli/commands/theme/pull.ts | 1 - packages/theme/src/cli/commands/theme/push.ts | 14 +- packages/theme/src/cli/services/check.test.ts | 48 +- packages/theme/src/cli/services/check.ts | 38 +- packages/theme/src/cli/services/dev.ts | 4 +- .../src/cli/services/metafields-pull.test.ts | 145 ++++++ .../theme/src/cli/services/metafields-pull.ts | 165 +++++++ packages/theme/src/cli/services/pull.test.ts | 41 +- packages/theme/src/cli/services/pull.ts | 84 ++-- packages/theme/src/cli/services/push.test.ts | 127 ++++++ packages/theme/src/cli/services/push.ts | 25 +- .../storefront-session.test.ts | 80 +++- .../theme-environment/storefront-session.ts | 22 +- .../theme/src/cli/utilities/theme-fs.test.ts | 15 +- packages/theme/src/cli/utilities/theme-fs.ts | 6 +- packages/theme/src/cli/utilities/theme-ui.ts | 7 +- .../src/cli/utilities/theme-uploader.test.ts | 60 +-- .../theme/src/cli/utilities/theme-uploader.ts | 23 +- packages/theme/src/index.ts | 2 + .../ui-extensions-dev-console/CHANGELOG.md | 14 + .../ui-extensions-dev-console/package.json | 2 +- .../ui-extensions-server-kit/src/types.ts | 2 +- pnpm-lock.yaml | 411 +++++++++-------- shipit.stable_3_71.yml | 24 + 918 files changed, 7863 insertions(+), 2732 deletions(-) delete mode 100644 .changeset/dry-rice-guess.md delete mode 100644 .changeset/eight-dragons-grab.md delete mode 100644 .changeset/forty-islands-itch.md delete mode 100644 .changeset/fresh-donkeys-clean.md create mode 100644 .changeset/good-plums-fail.md create mode 100644 .changeset/nervous-terms-invite.md delete mode 100644 .changeset/pink-garlics-act.md create mode 100644 .changeset/quick-eggs-end.md create mode 100644 .changeset/red-tips-mix.md create mode 100644 .changeset/seven-seahorses-bake.md create mode 100644 .changeset/shaggy-cheetahs-think.md create mode 100644 .changeset/silver-mice-thank.md delete mode 100644 .changeset/swift-frogs-fail.md delete mode 100644 .changeset/wet-rats-applaud.md create mode 100644 RELEASE_NOTES/3.71.md create mode 100644 RELEASE_NOTES/3.72.md create mode 100644 docs-shopify.dev/commands/examples/theme-metafields-pull.example.sh create mode 100644 docs-shopify.dev/commands/interfaces/theme-metafields-pull.interface.ts create mode 100644 docs-shopify.dev/commands/theme-metafields-pull.doc.ts create mode 100644 docs/api/cli-kit/classes/node_vendor_dev_server_DevServer.DevServer.html create mode 100644 docs/api/cli-kit/classes/node_vendor_dev_server_DevServer.DevServerCore.html create mode 100644 docs/api/cli-kit/functions/node_api_functions.functionsRequestDoc.html create mode 100644 docs/api/cli-kit/functions/node_api_webhooks.webhooksRequest.html delete mode 100644 docs/api/cli-kit/functions/node_cli.localCliPackage.html delete mode 100644 docs/api/cli-kit/functions/node_cli.useLocalCLIIfDetected.html create mode 100644 docs/api/cli-kit/functions/node_cli_launcher.launchCLI.html create mode 100644 docs/api/cli-kit/functions/node_context_local.isAppManagementEnabled.html create mode 100644 docs/api/cli-kit/functions/node_environment.jsonOutputEnabled.html delete mode 100644 docs/api/cli-kit/functions/node_themes_factories.buildBulkUploadResults.html create mode 100644 docs/api/cli-kit/functions/node_vendor_dev_server_network_interfaces.fromIp.html create mode 100644 docs/api/cli-kit/functions/node_vendor_dev_server_network_interfaces.getInterface.html create mode 100644 docs/api/cli-kit/functions/node_vendor_dev_server_network_interfaces.toIp.html create mode 100644 docs/api/cli-kit/modules/node_api_functions.html create mode 100644 docs/api/cli-kit/modules/node_api_webhooks.html create mode 100644 docs/api/cli-kit/modules/node_cli_launcher.html create mode 100644 docs/api/cli-kit/modules/node_vendor_dev_server_DevServer.html create mode 100644 docs/api/cli-kit/modules/node_vendor_dev_server_network_interfaces.html create mode 100644 docs/api/cli-kit/variables/node_cli.jsonFlag.html create mode 100644 packages/app/src/cli/api/graphql/app-management/generated/active-app-release-from-api-key.ts create mode 100644 packages/app/src/cli/api/graphql/app-management/queries/active-app-release-from-api-key.graphql create mode 100644 packages/app/src/cli/api/graphql/functions/generated/schema-definition-by-api-type.ts create mode 100644 packages/app/src/cli/api/graphql/functions/generated/schema-definition-by-target.ts create mode 100644 packages/app/src/cli/api/graphql/functions/generated/types.d.ts create mode 100644 packages/app/src/cli/api/graphql/functions/queries/schema-definition-by-api-type.graphql create mode 100644 packages/app/src/cli/api/graphql/functions/queries/schema-definition-by-target.graphql create mode 100644 packages/app/src/cli/api/graphql/webhooks/generated/available-topics.ts create mode 100644 packages/app/src/cli/api/graphql/webhooks/generated/cli-testing.ts create mode 100644 packages/app/src/cli/api/graphql/webhooks/generated/public-api-versions.ts create mode 100644 packages/app/src/cli/api/graphql/webhooks/generated/types.d.ts create mode 100644 packages/app/src/cli/api/graphql/webhooks/queries/available-topics.graphql create mode 100644 packages/app/src/cli/api/graphql/webhooks/queries/cli-testing.graphql create mode 100644 packages/app/src/cli/api/graphql/webhooks/queries/public-api-versions.graphql create mode 100644 packages/app/src/cli/models/app/validation/multi-cli-warning.ts create mode 100644 packages/cli-kit/src/cli/api/graphql/admin/generated/metafield_definitions_by_owner_type.ts create mode 100644 packages/cli-kit/src/cli/api/graphql/admin/generated/theme_files_upsert.ts create mode 100644 packages/cli-kit/src/cli/api/graphql/admin/mutations/theme_files_upsert.graphql create mode 100644 packages/cli-kit/src/cli/api/graphql/admin/queries/metafield_definitions_by_owner_type.graphql create mode 100644 packages/cli-kit/src/public/node/api/functions.ts create mode 100644 packages/cli-kit/src/public/node/api/webhooks.ts create mode 100644 packages/cli-kit/src/public/node/system.test.ts create mode 100644 packages/theme/src/cli/commands/theme/metafields/pull.ts create mode 100644 packages/theme/src/cli/services/metafields-pull.test.ts create mode 100644 packages/theme/src/cli/services/metafields-pull.ts create mode 100644 shipit.stable_3_71.yml diff --git a/.changeset/dry-rice-guess.md b/.changeset/dry-rice-guess.md deleted file mode 100644 index 7002377b8b4..00000000000 --- a/.changeset/dry-rice-guess.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@shopify/app': patch ---- - -Update Javy invocation to use Javy plugin diff --git a/.changeset/eight-dragons-grab.md b/.changeset/eight-dragons-grab.md deleted file mode 100644 index d415042bdc8..00000000000 --- a/.changeset/eight-dragons-grab.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@shopify/app': patch ---- - -Update Javy to 3.2.0 and function-runner to 6.3.0 diff --git a/.changeset/forty-islands-itch.md b/.changeset/forty-islands-itch.md deleted file mode 100644 index 33f4dac37ed..00000000000 --- a/.changeset/forty-islands-itch.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@shopify/app': patch -'@shopify/cli': patch ---- - -Remove PHP template from app creation options diff --git a/.changeset/fresh-donkeys-clean.md b/.changeset/fresh-donkeys-clean.md deleted file mode 100644 index 338589b48b5..00000000000 --- a/.changeset/fresh-donkeys-clean.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@shopify/cli-kit': patch ---- - -Improve display of links for terminals that don't support hyperlinks diff --git a/.changeset/good-plums-fail.md b/.changeset/good-plums-fail.md new file mode 100644 index 00000000000..892abf1c4bb --- /dev/null +++ b/.changeset/good-plums-fail.md @@ -0,0 +1,6 @@ +--- +'@shopify/theme': patch +'@shopify/app': patch +--- + +Bump Shopify/theme-tools packages diff --git a/.changeset/nervous-terms-invite.md b/.changeset/nervous-terms-invite.md new file mode 100644 index 00000000000..b3accf4acc2 --- /dev/null +++ b/.changeset/nervous-terms-invite.md @@ -0,0 +1,6 @@ +--- +'@shopify/theme': minor +'@shopify/cli': minor +--- + +Developers can now use the `shopify theme metafields pull` command to download metafields, which can then be used for more refined code completion. diff --git a/.changeset/pink-garlics-act.md b/.changeset/pink-garlics-act.md deleted file mode 100644 index ffabdbb0ec3..00000000000 --- a/.changeset/pink-garlics-act.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@shopify/theme': patch ---- - -Update `shopify theme dev` to no longer display redundant URLs diff --git a/.changeset/quick-eggs-end.md b/.changeset/quick-eggs-end.md new file mode 100644 index 00000000000..02aaa148b7e --- /dev/null +++ b/.changeset/quick-eggs-end.md @@ -0,0 +1,5 @@ +--- +'@shopify/cli-kit': patch +--- + +Introduce method to fetch metafield definitions by ownerType from Admin API diff --git a/.changeset/red-tips-mix.md b/.changeset/red-tips-mix.md new file mode 100644 index 00000000000..788b4ad135b --- /dev/null +++ b/.changeset/red-tips-mix.md @@ -0,0 +1,6 @@ +--- +'@shopify/cli-kit': patch +'@shopify/theme': patch +--- + +Ensure git directory is clean when running `theme pull` diff --git a/.changeset/seven-seahorses-bake.md b/.changeset/seven-seahorses-bake.md new file mode 100644 index 00000000000..9117786fef0 --- /dev/null +++ b/.changeset/seven-seahorses-bake.md @@ -0,0 +1,5 @@ +--- +'@shopify/app': minor +--- + +Use Shopify Functions Javy plugin instead of default Javy plugin for building JS Shopify Functions diff --git a/.changeset/shaggy-cheetahs-think.md b/.changeset/shaggy-cheetahs-think.md new file mode 100644 index 00000000000..e1fef71e286 --- /dev/null +++ b/.changeset/shaggy-cheetahs-think.md @@ -0,0 +1,5 @@ +--- +'@shopify/cli': patch +--- + +Bump cli-hydrogen package to 9.0.3 diff --git a/.changeset/silver-mice-thank.md b/.changeset/silver-mice-thank.md new file mode 100644 index 00000000000..3cb763c622f --- /dev/null +++ b/.changeset/silver-mice-thank.md @@ -0,0 +1,6 @@ +--- +'@shopify/cli-kit': patch +'@shopify/app': patch +--- + +Remove all template lockfiles, except the one used to install dependencies diff --git a/.changeset/swift-frogs-fail.md b/.changeset/swift-frogs-fail.md deleted file mode 100644 index 9ab30173dcc..00000000000 --- a/.changeset/swift-frogs-fail.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@shopify/theme': minor ---- - -Add shortcut keys to theme dev commands diff --git a/.changeset/wet-rats-applaud.md b/.changeset/wet-rats-applaud.md deleted file mode 100644 index 07da0decbc7..00000000000 --- a/.changeset/wet-rats-applaud.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@shopify/theme': patch ---- - -Fix password validation to handle capitalized store names on `shopify theme dev` diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e394f9bdc04..10ca6b6fb99 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -3,12 +3,12 @@ # Theme team and CLI owners should review theme changes packages/cli-kit/src/private/themes/* @shopify/advanced-edits @shopify/app-inner-loop -packages/cli-kit/src/public/themes/* @shopify/advanced-edits @shopify/app-inner-loop +packages/cli-kit/src/public/**/themes/* @shopify/advanced-edits @shopify/app-inner-loop packages/theme/** @shopify/advanced-edits @shopify/app-inner-loop # These are metafiles that can be reviewed by anyone .changeset/* @shopify/advanced-edits @shopify/app-inner-loop .github/CODEOWNERS @shopify/advanced-edits @shopify/app-inner-loop -docs-shopify.dev/* @shopify/advanced-edits @shopify/app-inner-loop +docs-shopify.dev/** @shopify/advanced-edits @shopify/app-inner-loop packages/cli/oclif.manifest.json @shopify/advanced-edits @shopify/app-inner-loop - +packages/cli/README.md @shopify/advanced-edits @shopify/app-inner-loop diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index f95e5f82325..c01d1097939 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -59,7 +59,15 @@ body: attributes: label: Verbose output description: If you're using npm rerun the command with `-- --verbose` or if you're using yarn or pnpm rerun the command with `--verbose` - render: shell + value: |- +
+ Verbose output + + ``` + Paste the output here! + ``` + +
validations: required: true - type: textarea @@ -89,7 +97,7 @@ body: - type: input id: cli_version attributes: - label: Shopify CLI version (check your project's `package.json` if you're not sure) + label: Shopify CLI version (`shopify --version`) validations: required: true - type: input diff --git a/.github/actions/run-and-save-test-coverage/action.yml b/.github/actions/run-and-save-test-coverage/action.yml index a7cab03635c..daab39cb513 100644 --- a/.github/actions/run-and-save-test-coverage/action.yml +++ b/.github/actions/run-and-save-test-coverage/action.yml @@ -28,7 +28,7 @@ runs: SAFE_REF_NAME=${{ env.SAFE_REF_NAME }} SAFE_REF_NAME=${SAFE_REF_NAME//[\/.]/} echo SAFE_REF_NAME=${SAFE_REF_NAME} >> $GITHUB_ENV - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: ${{ env.SAFE_REF_NAME }}--coverage-report path: ./baseline-report.json diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0225c8ca947..182a7cc21dd 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -2,7 +2,9 @@ version: 2 updates: - package-ecosystem: "npm" versioning-strategy: increase - directory: "/" + directories: + - "/" + - "packages/*" schedule: interval: "weekly" labels: @@ -16,6 +18,7 @@ updates: update-types: ["version-update:semver-major"] groups: minor_versions: + dependency-type: "production" update-types: - 'minor' - 'patch' @@ -30,6 +33,11 @@ updates: - "react" - "@babel/*" - "javy-cli" + development_dependencies: + dependency-type: "development" + update-types: + - 'minor' + - 'patch' oclif: patterns: - "oclif" @@ -38,21 +46,3 @@ updates: patterns: - "nx" - "@nx/*" - - package-ecosystem: "bundler" - versioning-strategy: increase - directory: "/" - schedule: - interval: "weekly" - labels: - - "dependencies" - open-pull-requests-limit: 100 - pull-request-branch-name: - separator: "-" - ignore: - - dependency-name: "*" - update-types: ["version-update:semver-major"] - groups: - minor_versions: - update-types: - - 'minor' - - 'patch' diff --git a/.gitignore b/.gitignore index 13df16cc1c8..499fc2c132b 100644 --- a/.gitignore +++ b/.gitignore @@ -155,6 +155,7 @@ packaging/dist cloudflared* function-runner* javy* +shopify_functions_javy_v*.wasm # Vitest vscode extension autogenerated files index.d.ts diff --git a/RELEASE_NOTES/3.71.md b/RELEASE_NOTES/3.71.md new file mode 100644 index 00000000000..1db83edce12 --- /dev/null +++ b/RELEASE_NOTES/3.71.md @@ -0,0 +1,17 @@ +# Themes +* Fix password validation to handle capitalized store names on `shopify theme dev` +* Update `shopify theme dev` to no longer display redundant URLs +* Add shortcut keys to `theme dev` +* Add `--strict` flag to `theme push` to enforce theme check before pushing +* Handle localized URLs in storefront password validation +* Improve storefront password detection for password-protected shops with redirects + +# Apps +* Improve commands startup performance, all app commands run faster now +* Add support to import admin-link extensions +* Add client-id and reset as global flags to all app commands + +# CLI +* Display link as plaintext if link label is nonexistent or just the link itself +* Skip notifications check on CI and tests +* Skip notifications when using --json diff --git a/RELEASE_NOTES/3.72.md b/RELEASE_NOTES/3.72.md new file mode 100644 index 00000000000..9b61143bd5c --- /dev/null +++ b/RELEASE_NOTES/3.72.md @@ -0,0 +1,8 @@ +# Themes +* Allow empty theme files to be uploaded #5015 +* Add support for block liquid files in theme partitioning #5042 + +# Apps +* Fix dest already exists error when running functions #5009 +* Fix dev for Ruby apps #4522 +* Fix an issue with functions in dev #5028 diff --git a/bin/get-graphql-schemas.js b/bin/get-graphql-schemas.js index 886ec935094..9160f554862 100755 --- a/bin/get-graphql-schemas.js +++ b/bin/get-graphql-schemas.js @@ -38,7 +38,19 @@ const schemas = [ repo: 'shopify', pathToFile: 'areas/core/shopify/db/graphql/admin_schema_unstable_public.graphql', localPath: './packages/cli-kit/src/cli/api/graphql/admin/admin_schema.graphql', - } + }, + { + repo: 'shopify', + pathToFile: 'areas/core/shopify/db/graphql/webhooks_schema_unstable_public.graphql', + localPath: './packages/app/src/cli/api/graphql/webhooks/webhooks_schema.graphql', + branch: 'dd', + }, + { + repo: 'shopify', + pathToFile: 'areas/core/shopify/db/graphql/functions_cli_api_schema_unstable_public.graphql', + localPath: './packages/app/src/cli/api/graphql/functions/functions_cli_schema.graphql', + branch: 'dd', + }, ] function runCommand(command, args) { @@ -121,7 +133,7 @@ async function getGithubPasswordFromDev() { } } -async function fetchFiles() { +async function withOctokit(func) { let password = undefined let tokenFromEnv = process.env.GITHUB_TOKEN || process.env.GH_TOKEN if (!tokenFromEnv) { @@ -133,10 +145,15 @@ async function fetchFiles() { const octokit = new Octokit({ auth: authToken, }) + return func(octokit) +} +async function fetchFiles() { let allSuccess = true for (const schema of schemas) { - allSuccess = await fetchFileForSchema(schema, octokit) && allSuccess + allSuccess = allSuccess && await withOctokit(async (octokit) => { + return fetchFileForSchema(schema, octokit) + }) } if (!allSuccess) { @@ -149,7 +166,19 @@ async function fetchFilesFromSpin() { for (const schema of schemas) { const remotePath = `~/src/github.com/Shopify/${schema.repo}/${schema.pathToFile}` const localPath = schema.localPath - await runCommand('spin', ['copy', `${process.env.SPIN_INSTANCE}:${remotePath}`, localPath]) + try { + await runCommand('spin', ['copy', `${process.env.SPIN_INSTANCE}:${remotePath}`, localPath]) + } catch(e) { + if (e.message.match(/scp.*No such file or directory/)) { + // Assume we need to just fetch the file from GitHub + console.log(`Cannot find file for ${schema.repo} in Spin, fetching from GitHub instead...`) + await withOctokit(async (octokit) => { + await fetchFileForSchema(schema, octokit) + }) + } else { + throw e + } + } } } diff --git a/docs-shopify.dev/commands/examples/theme-metafields-pull.example.sh b/docs-shopify.dev/commands/examples/theme-metafields-pull.example.sh new file mode 100644 index 00000000000..808efb44fc4 --- /dev/null +++ b/docs-shopify.dev/commands/examples/theme-metafields-pull.example.sh @@ -0,0 +1 @@ +shopify theme metafields pull [flags] \ No newline at end of file diff --git a/docs-shopify.dev/commands/interfaces/app-build.interface.ts b/docs-shopify.dev/commands/interfaces/app-build.interface.ts index cc24a0645df..b9ad844ccb8 100644 --- a/docs-shopify.dev/commands/interfaces/app-build.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-build.interface.ts @@ -1,7 +1,7 @@ // This is an autogenerated file. Don't edit this file manually. export interface appbuild { /** - * Application's Client ID that will be exposed at build time. + * The Client ID of your app. * @environment SHOPIFY_FLAG_CLIENT_ID */ '--client-id '?: string @@ -24,6 +24,12 @@ export interface appbuild { */ '--path '?: string + /** + * Reset all your settings. + * @environment SHOPIFY_FLAG_RESET + */ + '--reset'?: '' + /** * Skips the installation of dependencies. Deprecated, use workspaces instead. * @environment SHOPIFY_FLAG_SKIP_DEPENDENCIES_INSTALLATION diff --git a/docs-shopify.dev/commands/interfaces/app-config-link.interface.ts b/docs-shopify.dev/commands/interfaces/app-config-link.interface.ts index a9cda363b6b..66f2daca741 100644 --- a/docs-shopify.dev/commands/interfaces/app-config-link.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-config-link.interface.ts @@ -24,6 +24,12 @@ export interface appconfiglink { */ '--path '?: string + /** + * Reset all your settings. + * @environment SHOPIFY_FLAG_RESET + */ + '--reset'?: '' + /** * Increase the verbosity of the output. * @environment SHOPIFY_FLAG_VERBOSE diff --git a/docs-shopify.dev/commands/interfaces/app-config-use.interface.ts b/docs-shopify.dev/commands/interfaces/app-config-use.interface.ts index 604d8203276..067b2ec6e0c 100644 --- a/docs-shopify.dev/commands/interfaces/app-config-use.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-config-use.interface.ts @@ -1,5 +1,11 @@ // This is an autogenerated file. Don't edit this file manually. export interface appconfiguse { + /** + * The Client ID of your app. + * @environment SHOPIFY_FLAG_CLIENT_ID + */ + '--client-id '?: string + /** * Disable color output. * @environment SHOPIFY_FLAG_NO_COLOR @@ -13,7 +19,7 @@ export interface appconfiguse { '--path '?: string /** - * Reset current configuration. + * Reset all your settings. * @environment SHOPIFY_FLAG_RESET */ '--reset'?: '' diff --git a/docs-shopify.dev/commands/interfaces/app-env-pull.interface.ts b/docs-shopify.dev/commands/interfaces/app-env-pull.interface.ts index 13e2b6caa3e..e19d2874d04 100644 --- a/docs-shopify.dev/commands/interfaces/app-env-pull.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-env-pull.interface.ts @@ -1,5 +1,11 @@ // This is an autogenerated file. Don't edit this file manually. export interface appenvpull { + /** + * The Client ID of your app. + * @environment SHOPIFY_FLAG_CLIENT_ID + */ + '--client-id '?: string + /** * The name of the app configuration. * @environment SHOPIFY_FLAG_APP_CONFIG @@ -24,6 +30,12 @@ export interface appenvpull { */ '--path '?: string + /** + * Reset all your settings. + * @environment SHOPIFY_FLAG_RESET + */ + '--reset'?: '' + /** * Increase the verbosity of the output. * @environment SHOPIFY_FLAG_VERBOSE diff --git a/docs-shopify.dev/commands/interfaces/app-env-show.interface.ts b/docs-shopify.dev/commands/interfaces/app-env-show.interface.ts index d18dd6d7952..f425139c38c 100644 --- a/docs-shopify.dev/commands/interfaces/app-env-show.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-env-show.interface.ts @@ -1,5 +1,11 @@ // This is an autogenerated file. Don't edit this file manually. export interface appenvshow { + /** + * The Client ID of your app. + * @environment SHOPIFY_FLAG_CLIENT_ID + */ + '--client-id '?: string + /** * The name of the app configuration. * @environment SHOPIFY_FLAG_APP_CONFIG @@ -18,6 +24,12 @@ export interface appenvshow { */ '--path '?: string + /** + * Reset all your settings. + * @environment SHOPIFY_FLAG_RESET + */ + '--reset'?: '' + /** * Increase the verbosity of the output. * @environment SHOPIFY_FLAG_VERBOSE diff --git a/docs-shopify.dev/commands/interfaces/app-function-build.interface.ts b/docs-shopify.dev/commands/interfaces/app-function-build.interface.ts index 91f71698ba2..c6795e1e713 100644 --- a/docs-shopify.dev/commands/interfaces/app-function-build.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-function-build.interface.ts @@ -1,5 +1,11 @@ // This is an autogenerated file. Don't edit this file manually. export interface appfunctionbuild { + /** + * The Client ID of your app. + * @environment SHOPIFY_FLAG_CLIENT_ID + */ + '--client-id '?: string + /** * The name of the app configuration. * @environment SHOPIFY_FLAG_APP_CONFIG @@ -18,6 +24,12 @@ export interface appfunctionbuild { */ '--path '?: string + /** + * Reset all your settings. + * @environment SHOPIFY_FLAG_RESET + */ + '--reset'?: '' + /** * Increase the verbosity of the output. * @environment SHOPIFY_FLAG_VERBOSE diff --git a/docs-shopify.dev/commands/interfaces/app-function-replay.interface.ts b/docs-shopify.dev/commands/interfaces/app-function-replay.interface.ts index eb67cce1cdc..534052e7fcc 100644 --- a/docs-shopify.dev/commands/interfaces/app-function-replay.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-function-replay.interface.ts @@ -1,7 +1,7 @@ // This is an autogenerated file. Don't edit this file manually. export interface appfunctionreplay { /** - * Application's Client ID + * The Client ID of your app. * @environment SHOPIFY_FLAG_CLIENT_ID */ '--client-id '?: string @@ -13,7 +13,7 @@ export interface appfunctionreplay { '-c, --config '?: string /** - * Output the function run result as a JSON object. + * Output the result as JSON. * @environment SHOPIFY_FLAG_JSON */ '-j, --json'?: '' @@ -36,6 +36,12 @@ export interface appfunctionreplay { */ '--path '?: string + /** + * Reset all your settings. + * @environment SHOPIFY_FLAG_RESET + */ + '--reset'?: '' + /** * Increase the verbosity of the output. * @environment SHOPIFY_FLAG_VERBOSE diff --git a/docs-shopify.dev/commands/interfaces/app-function-run.interface.ts b/docs-shopify.dev/commands/interfaces/app-function-run.interface.ts index 9d1173fc23c..3e13075ee10 100644 --- a/docs-shopify.dev/commands/interfaces/app-function-run.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-function-run.interface.ts @@ -1,5 +1,11 @@ // This is an autogenerated file. Don't edit this file manually. export interface appfunctionrun { + /** + * The Client ID of your app. + * @environment SHOPIFY_FLAG_CLIENT_ID + */ + '--client-id '?: string + /** * The name of the app configuration. * @environment SHOPIFY_FLAG_APP_CONFIG @@ -19,7 +25,7 @@ export interface appfunctionrun { '-i, --input '?: string /** - * Log the run result as a JSON object. + * Output the result as JSON. * @environment SHOPIFY_FLAG_JSON */ '-j, --json'?: '' @@ -36,6 +42,12 @@ export interface appfunctionrun { */ '--path '?: string + /** + * Reset all your settings. + * @environment SHOPIFY_FLAG_RESET + */ + '--reset'?: '' + /** * Increase the verbosity of the output. * @environment SHOPIFY_FLAG_VERBOSE diff --git a/docs-shopify.dev/commands/interfaces/app-function-schema.interface.ts b/docs-shopify.dev/commands/interfaces/app-function-schema.interface.ts index f8552495352..09e8f37c498 100644 --- a/docs-shopify.dev/commands/interfaces/app-function-schema.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-function-schema.interface.ts @@ -1,7 +1,7 @@ // This is an autogenerated file. Don't edit this file manually. export interface appfunctionschema { /** - * The Client ID to fetch the schema with. + * The Client ID of your app. * @environment SHOPIFY_FLAG_CLIENT_ID */ '--client-id '?: string @@ -24,6 +24,12 @@ export interface appfunctionschema { */ '--path '?: string + /** + * Reset all your settings. + * @environment SHOPIFY_FLAG_RESET + */ + '--reset'?: '' + /** * Output the schema to stdout instead of writing to a file. * @environment SHOPIFY_FLAG_STDOUT diff --git a/docs-shopify.dev/commands/interfaces/app-function-typegen.interface.ts b/docs-shopify.dev/commands/interfaces/app-function-typegen.interface.ts index 3d5a1434f3f..aae24d3e95e 100644 --- a/docs-shopify.dev/commands/interfaces/app-function-typegen.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-function-typegen.interface.ts @@ -1,5 +1,11 @@ // This is an autogenerated file. Don't edit this file manually. export interface appfunctiontypegen { + /** + * The Client ID of your app. + * @environment SHOPIFY_FLAG_CLIENT_ID + */ + '--client-id '?: string + /** * The name of the app configuration. * @environment SHOPIFY_FLAG_APP_CONFIG @@ -18,6 +24,12 @@ export interface appfunctiontypegen { */ '--path '?: string + /** + * Reset all your settings. + * @environment SHOPIFY_FLAG_RESET + */ + '--reset'?: '' + /** * Increase the verbosity of the output. * @environment SHOPIFY_FLAG_VERBOSE diff --git a/docs-shopify.dev/commands/interfaces/app-import-extensions.interface.ts b/docs-shopify.dev/commands/interfaces/app-import-extensions.interface.ts index b359945485e..09132bc64a4 100644 --- a/docs-shopify.dev/commands/interfaces/app-import-extensions.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-import-extensions.interface.ts @@ -24,6 +24,12 @@ export interface appimportextensions { */ '--path '?: string + /** + * Reset all your settings. + * @environment SHOPIFY_FLAG_RESET + */ + '--reset'?: '' + /** * Increase the verbosity of the output. * @environment SHOPIFY_FLAG_VERBOSE diff --git a/docs-shopify.dev/commands/interfaces/app-info.interface.ts b/docs-shopify.dev/commands/interfaces/app-info.interface.ts index 09989ff2e89..942bc6e9606 100644 --- a/docs-shopify.dev/commands/interfaces/app-info.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-info.interface.ts @@ -1,5 +1,11 @@ // This is an autogenerated file. Don't edit this file manually. export interface appinfo { + /** + * The Client ID of your app. + * @environment SHOPIFY_FLAG_CLIENT_ID + */ + '--client-id '?: string + /** * The name of the app configuration. * @environment SHOPIFY_FLAG_APP_CONFIG @@ -7,10 +13,10 @@ export interface appinfo { '-c, --config '?: string /** - * format output as JSON + * Output the result as JSON. * @environment SHOPIFY_FLAG_JSON */ - '--json'?: '' + '-j, --json'?: '' /** * Disable color output. @@ -24,6 +30,12 @@ export interface appinfo { */ '--path '?: string + /** + * Reset all your settings. + * @environment SHOPIFY_FLAG_RESET + */ + '--reset'?: '' + /** * Increase the verbosity of the output. * @environment SHOPIFY_FLAG_VERBOSE diff --git a/docs-shopify.dev/commands/interfaces/app-logs-sources.interface.ts b/docs-shopify.dev/commands/interfaces/app-logs-sources.interface.ts index 470af31e2c5..f4279a1301a 100644 --- a/docs-shopify.dev/commands/interfaces/app-logs-sources.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-logs-sources.interface.ts @@ -1,5 +1,11 @@ // This is an autogenerated file. Don't edit this file manually. export interface applogssources { + /** + * The Client ID of your app. + * @environment SHOPIFY_FLAG_CLIENT_ID + */ + '--client-id '?: string + /** * The name of the app configuration. * @environment SHOPIFY_FLAG_APP_CONFIG @@ -18,6 +24,12 @@ export interface applogssources { */ '--path '?: string + /** + * Reset all your settings. + * @environment SHOPIFY_FLAG_RESET + */ + '--reset'?: '' + /** * Increase the verbosity of the output. * @environment SHOPIFY_FLAG_VERBOSE diff --git a/docs-shopify.dev/commands/interfaces/app-logs.interface.ts b/docs-shopify.dev/commands/interfaces/app-logs.interface.ts index 954067bdf5e..3ba6d882ff2 100644 --- a/docs-shopify.dev/commands/interfaces/app-logs.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-logs.interface.ts @@ -13,7 +13,7 @@ export interface applogs { '-c, --config '?: string /** - * Log the run result as a JSON object. + * Output the result as JSON. * @environment SHOPIFY_FLAG_JSON */ '-j, --json'?: '' diff --git a/docs-shopify.dev/commands/interfaces/app-versions-list.interface.ts b/docs-shopify.dev/commands/interfaces/app-versions-list.interface.ts index 0b1efb13b83..eda211aa75a 100644 --- a/docs-shopify.dev/commands/interfaces/app-versions-list.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-versions-list.interface.ts @@ -1,7 +1,7 @@ // This is an autogenerated file. Don't edit this file manually. export interface appversionslist { /** - * The Client ID to fetch versions for. + * The Client ID of your app. * @environment SHOPIFY_FLAG_CLIENT_ID */ '--client-id '?: string @@ -13,10 +13,10 @@ export interface appversionslist { '-c, --config '?: string /** - * Output the versions list as JSON. + * Output the result as JSON. * @environment SHOPIFY_FLAG_JSON */ - '--json'?: '' + '-j, --json'?: '' /** * Disable color output. @@ -30,6 +30,12 @@ export interface appversionslist { */ '--path '?: string + /** + * Reset all your settings. + * @environment SHOPIFY_FLAG_RESET + */ + '--reset'?: '' + /** * Increase the verbosity of the output. * @environment SHOPIFY_FLAG_VERBOSE diff --git a/docs-shopify.dev/commands/interfaces/app-webhook-trigger.interface.ts b/docs-shopify.dev/commands/interfaces/app-webhook-trigger.interface.ts index 44e81f1e841..5dc1bba925a 100644 --- a/docs-shopify.dev/commands/interfaces/app-webhook-trigger.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-webhook-trigger.interface.ts @@ -53,6 +53,12 @@ export interface appwebhooktrigger { */ '--path '?: string + /** + * Reset all your settings. + * @environment SHOPIFY_FLAG_RESET + */ + '--reset'?: '' + /** * Deprecated. Please use client-secret. * @environment SHOPIFY_FLAG_SHARED_SECRET diff --git a/docs-shopify.dev/commands/interfaces/theme-info.interface.ts b/docs-shopify.dev/commands/interfaces/theme-info.interface.ts index 5a41b25b932..3c6db433d56 100644 --- a/docs-shopify.dev/commands/interfaces/theme-info.interface.ts +++ b/docs-shopify.dev/commands/interfaces/theme-info.interface.ts @@ -13,10 +13,10 @@ export interface themeinfo { '-e, --environment '?: string /** - * Output the theme info as JSON. + * Output the result as JSON. * @environment SHOPIFY_FLAG_JSON */ - '--json'?: '' + '-j, --json'?: '' /** * Disable color output. diff --git a/docs-shopify.dev/commands/interfaces/theme-list.interface.ts b/docs-shopify.dev/commands/interfaces/theme-list.interface.ts index f8c97259aff..9a50fdf5845 100644 --- a/docs-shopify.dev/commands/interfaces/theme-list.interface.ts +++ b/docs-shopify.dev/commands/interfaces/theme-list.interface.ts @@ -13,10 +13,10 @@ export interface themelist { '--id '?: string /** - * Output the theme list as JSON. + * Output the result as JSON. * @environment SHOPIFY_FLAG_JSON */ - '--json'?: '' + '-j, --json'?: '' /** * Only list themes that contain the given name. diff --git a/docs-shopify.dev/commands/interfaces/theme-metafields-pull.interface.ts b/docs-shopify.dev/commands/interfaces/theme-metafields-pull.interface.ts new file mode 100644 index 00000000000..6c9977f2382 --- /dev/null +++ b/docs-shopify.dev/commands/interfaces/theme-metafields-pull.interface.ts @@ -0,0 +1,38 @@ +// This is an autogenerated file. Don't edit this file manually. +export interface thememetafieldspull { + /** + * The environment to apply to the current command. + * @environment SHOPIFY_FLAG_ENVIRONMENT + */ + '-e, --environment '?: string + + /** + * Disable color output. + * @environment SHOPIFY_FLAG_NO_COLOR + */ + '--no-color'?: '' + + /** + * Password generated from the Theme Access app. + * @environment SHOPIFY_CLI_THEME_TOKEN + */ + '--password '?: string + + /** + * The path to your theme directory. + * @environment SHOPIFY_FLAG_PATH + */ + '--path '?: string + + /** + * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com). + * @environment SHOPIFY_FLAG_STORE + */ + '-s, --store '?: string + + /** + * Increase the verbosity of the output. + * @environment SHOPIFY_FLAG_VERBOSE + */ + '--verbose'?: '' +} diff --git a/docs-shopify.dev/commands/interfaces/theme-push.interface.ts b/docs-shopify.dev/commands/interfaces/theme-push.interface.ts index 8d026193669..24b51d648a3 100644 --- a/docs-shopify.dev/commands/interfaces/theme-push.interface.ts +++ b/docs-shopify.dev/commands/interfaces/theme-push.interface.ts @@ -25,7 +25,7 @@ export interface themepush { '-x, --ignore '?: string /** - * Output JSON instead of a UI. + * Output the result as JSON. * @environment SHOPIFY_FLAG_JSON */ '-j, --json'?: '' @@ -78,6 +78,12 @@ export interface themepush { */ '-s, --store '?: string + /** + * Require theme check to pass without errors before pushing. Warnings are allowed. + * @environment SHOPIFY_FLAG_STRICT_PUSH + */ + '--strict'?: '' + /** * Theme ID or name of the remote theme. * @environment SHOPIFY_FLAG_THEME_ID diff --git a/docs-shopify.dev/commands/theme-metafields-pull.doc.ts b/docs-shopify.dev/commands/theme-metafields-pull.doc.ts new file mode 100644 index 00000000000..fdaaf381aee --- /dev/null +++ b/docs-shopify.dev/commands/theme-metafields-pull.doc.ts @@ -0,0 +1,36 @@ +// This is an autogenerated file. Don't edit this file manually. +import {ReferenceEntityTemplateSchema} from '@shopify/generate-docs' + +const data: ReferenceEntityTemplateSchema = { + name: 'theme metafields pull', + description: `Retrieves metafields from Shopify Admin. + +If the metafields file already exists, it will be overwritten.`, + overviewPreviewDescription: `Download metafields definitions from your shop into a local file.`, + type: 'command', + isVisualComponent: false, + defaultExample: { + codeblock: { + tabs: [ + { + title: 'theme metafields pull', + code: './examples/theme-metafields-pull.example.sh', + language: 'bash', + }, + ], + title: 'theme metafields pull', + }, + }, + definitions: [ + { + title: 'Flags', + description: 'The following flags are available for the `theme metafields pull` command:', + type: 'thememetafieldspull', + }, + ], + category: 'theme', + related: [ + ], +} + +export default data \ No newline at end of file diff --git a/docs-shopify.dev/generated/generated_docs_data.json b/docs-shopify.dev/generated/generated_docs_data.json index bac2f1c5399..a63ead60ab6 100644 --- a/docs-shopify.dev/generated/generated_docs_data.json +++ b/docs-shopify.dev/generated/generated_docs_data.json @@ -33,7 +33,7 @@ "syntaxKind": "PropertySignature", "name": "--client-id ", "value": "string", - "description": "Application's Client ID that will be exposed at build time.", + "description": "The Client ID of your app.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_CLIENT_ID" }, @@ -55,6 +55,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-build.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--reset", + "value": "\"\"", + "description": "Reset all your settings.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_RESET" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-build.interface.ts", "syntaxKind": "PropertySignature", @@ -83,7 +92,7 @@ "environmentValue": "SHOPIFY_FLAG_APP_CONFIG" } ], - "value": "export interface appbuild {\n /**\n * Application's Client ID that will be exposed at build time.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Skips the installation of dependencies. Deprecated, use workspaces instead.\n * @environment SHOPIFY_FLAG_SKIP_DEPENDENCIES_INSTALLATION\n */\n '--skip-dependencies-installation'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface appbuild {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Skips the installation of dependencies. Deprecated, use workspaces instead.\n * @environment SHOPIFY_FLAG_SKIP_DEPENDENCIES_INSTALLATION\n */\n '--skip-dependencies-installation'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } @@ -147,6 +156,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-config-link.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--reset", + "value": "\"\"", + "description": "Reset all your settings.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_RESET" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-config-link.interface.ts", "syntaxKind": "PropertySignature", @@ -166,7 +184,7 @@ "environmentValue": "SHOPIFY_FLAG_APP_CONFIG" } ], - "value": "export interface appconfiglink {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface appconfiglink {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } @@ -203,6 +221,15 @@ "name": "appconfiguse", "description": "", "members": [ + { + "filePath": "docs-shopify.dev/commands/interfaces/app-config-use.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--client-id ", + "value": "string", + "description": "The Client ID of your app.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_CLIENT_ID" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-config-use.interface.ts", "syntaxKind": "PropertySignature", @@ -226,7 +253,7 @@ "syntaxKind": "PropertySignature", "name": "--reset", "value": "\"\"", - "description": "Reset current configuration.", + "description": "Reset all your settings.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_RESET" }, @@ -240,7 +267,7 @@ "environmentValue": "SHOPIFY_FLAG_VERBOSE" } ], - "value": "export interface appconfiguse {\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset current configuration.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface appconfiguse {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } @@ -587,6 +614,15 @@ "name": "appenvpull", "description": "", "members": [ + { + "filePath": "docs-shopify.dev/commands/interfaces/app-env-pull.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--client-id ", + "value": "string", + "description": "The Client ID of your app.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_CLIENT_ID" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-env-pull.interface.ts", "syntaxKind": "PropertySignature", @@ -614,6 +650,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-env-pull.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--reset", + "value": "\"\"", + "description": "Reset all your settings.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_RESET" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-env-pull.interface.ts", "syntaxKind": "PropertySignature", @@ -633,7 +678,7 @@ "environmentValue": "SHOPIFY_FLAG_APP_CONFIG" } ], - "value": "export interface appenvpull {\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Specify an environment file to update if the update flag is set\n * @environment SHOPIFY_FLAG_ENV_FILE\n */\n '--env-file '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface appenvpull {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Specify an environment file to update if the update flag is set\n * @environment SHOPIFY_FLAG_ENV_FILE\n */\n '--env-file '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } @@ -670,6 +715,15 @@ "name": "appenvshow", "description": "", "members": [ + { + "filePath": "docs-shopify.dev/commands/interfaces/app-env-show.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--client-id ", + "value": "string", + "description": "The Client ID of your app.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_CLIENT_ID" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-env-show.interface.ts", "syntaxKind": "PropertySignature", @@ -688,6 +742,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-env-show.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--reset", + "value": "\"\"", + "description": "Reset all your settings.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_RESET" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-env-show.interface.ts", "syntaxKind": "PropertySignature", @@ -707,7 +770,7 @@ "environmentValue": "SHOPIFY_FLAG_APP_CONFIG" } ], - "value": "export interface appenvshow {\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface appenvshow {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } @@ -744,6 +807,15 @@ "name": "appfunctionbuild", "description": "", "members": [ + { + "filePath": "docs-shopify.dev/commands/interfaces/app-function-build.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--client-id ", + "value": "string", + "description": "The Client ID of your app.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_CLIENT_ID" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-function-build.interface.ts", "syntaxKind": "PropertySignature", @@ -762,6 +834,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-function-build.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--reset", + "value": "\"\"", + "description": "Reset all your settings.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_RESET" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-function-build.interface.ts", "syntaxKind": "PropertySignature", @@ -781,7 +862,7 @@ "environmentValue": "SHOPIFY_FLAG_APP_CONFIG" } ], - "value": "export interface appfunctionbuild {\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your function directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface appfunctionbuild {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your function directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } @@ -823,7 +904,7 @@ "syntaxKind": "PropertySignature", "name": "--client-id ", "value": "string", - "description": "Application's Client ID", + "description": "The Client ID of your app.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_CLIENT_ID" }, @@ -845,6 +926,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-function-replay.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--reset", + "value": "\"\"", + "description": "Reset all your settings.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_RESET" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-function-replay.interface.ts", "syntaxKind": "PropertySignature", @@ -868,7 +958,7 @@ "syntaxKind": "PropertySignature", "name": "-j, --json", "value": "\"\"", - "description": "Output the function run result as a JSON object.", + "description": "Output the result as JSON.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_JSON" }, @@ -891,7 +981,7 @@ "environmentValue": "SHOPIFY_FLAG_WATCH" } ], - "value": "export interface appfunctionreplay {\n /**\n * Application's Client ID\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Output the function run result as a JSON object.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Specifies a log identifier to replay instead of selecting from a list. The identifier is provided in the output of `shopify app dev` and is the suffix of the log file name.\n * @environment SHOPIFY_FLAG_LOG\n */\n '-l, --log '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your function directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n\n /**\n * Re-run the function when the source code changes.\n * @environment SHOPIFY_FLAG_WATCH\n */\n '-w, --watch'?: ''\n}" + "value": "export interface appfunctionreplay {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Output the result as JSON.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Specifies a log identifier to replay instead of selecting from a list. The identifier is provided in the output of `shopify app dev` and is the suffix of the log file name.\n * @environment SHOPIFY_FLAG_LOG\n */\n '-l, --log '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your function directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n\n /**\n * Re-run the function when the source code changes.\n * @environment SHOPIFY_FLAG_WATCH\n */\n '-w, --watch'?: ''\n}" } } } @@ -928,6 +1018,15 @@ "name": "appfunctionrun", "description": "", "members": [ + { + "filePath": "docs-shopify.dev/commands/interfaces/app-function-run.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--client-id ", + "value": "string", + "description": "The Client ID of your app.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_CLIENT_ID" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-function-run.interface.ts", "syntaxKind": "PropertySignature", @@ -946,6 +1045,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-function-run.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--reset", + "value": "\"\"", + "description": "Reset all your settings.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_RESET" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-function-run.interface.ts", "syntaxKind": "PropertySignature", @@ -987,12 +1095,12 @@ "syntaxKind": "PropertySignature", "name": "-j, --json", "value": "\"\"", - "description": "Log the run result as a JSON object.", + "description": "Output the result as JSON.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_JSON" } ], - "value": "export interface appfunctionrun {\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Name of the WebAssembly export to invoke.\n * @environment SHOPIFY_FLAG_EXPORT\n */\n '-e, --export '?: string\n\n /**\n * The input JSON to pass to the function. If omitted, standard input is used.\n * @environment SHOPIFY_FLAG_INPUT\n */\n '-i, --input '?: string\n\n /**\n * Log the run result as a JSON object.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your function directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface appfunctionrun {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Name of the WebAssembly export to invoke.\n * @environment SHOPIFY_FLAG_EXPORT\n */\n '-e, --export '?: string\n\n /**\n * The input JSON to pass to the function. If omitted, standard input is used.\n * @environment SHOPIFY_FLAG_INPUT\n */\n '-i, --input '?: string\n\n /**\n * Output the result as JSON.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your function directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } @@ -1034,7 +1142,7 @@ "syntaxKind": "PropertySignature", "name": "--client-id ", "value": "string", - "description": "The Client ID to fetch the schema with.", + "description": "The Client ID of your app.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_CLIENT_ID" }, @@ -1056,6 +1164,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-function-schema.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--reset", + "value": "\"\"", + "description": "Reset all your settings.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_RESET" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-function-schema.interface.ts", "syntaxKind": "PropertySignature", @@ -1084,7 +1201,7 @@ "environmentValue": "SHOPIFY_FLAG_APP_CONFIG" } ], - "value": "export interface appfunctionschema {\n /**\n * The Client ID to fetch the schema with.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your function directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Output the schema to stdout instead of writing to a file.\n * @environment SHOPIFY_FLAG_STDOUT\n */\n '--stdout'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface appfunctionschema {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your function directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Output the schema to stdout instead of writing to a file.\n * @environment SHOPIFY_FLAG_STDOUT\n */\n '--stdout'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } @@ -1121,6 +1238,15 @@ "name": "appfunctiontypegen", "description": "", "members": [ + { + "filePath": "docs-shopify.dev/commands/interfaces/app-function-typegen.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--client-id ", + "value": "string", + "description": "The Client ID of your app.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_CLIENT_ID" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-function-typegen.interface.ts", "syntaxKind": "PropertySignature", @@ -1139,6 +1265,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-function-typegen.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--reset", + "value": "\"\"", + "description": "Reset all your settings.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_RESET" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-function-typegen.interface.ts", "syntaxKind": "PropertySignature", @@ -1158,7 +1293,7 @@ "environmentValue": "SHOPIFY_FLAG_APP_CONFIG" } ], - "value": "export interface appfunctiontypegen {\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your function directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface appfunctiontypegen {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your function directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } @@ -1350,6 +1485,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-import-extensions.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--reset", + "value": "\"\"", + "description": "Reset all your settings.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_RESET" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-import-extensions.interface.ts", "syntaxKind": "PropertySignature", @@ -1369,7 +1513,7 @@ "environmentValue": "SHOPIFY_FLAG_APP_CONFIG" } ], - "value": "export interface appimportextensions {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface appimportextensions {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } @@ -1409,11 +1553,11 @@ { "filePath": "docs-shopify.dev/commands/interfaces/app-info.interface.ts", "syntaxKind": "PropertySignature", - "name": "--json", - "value": "\"\"", - "description": "format output as JSON", + "name": "--client-id ", + "value": "string", + "description": "The Client ID of your app.", "isOptional": true, - "environmentValue": "SHOPIFY_FLAG_JSON" + "environmentValue": "SHOPIFY_FLAG_CLIENT_ID" }, { "filePath": "docs-shopify.dev/commands/interfaces/app-info.interface.ts", @@ -1433,6 +1577,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-info.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--reset", + "value": "\"\"", + "description": "Reset all your settings.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_RESET" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-info.interface.ts", "syntaxKind": "PropertySignature", @@ -1459,9 +1612,18 @@ "description": "The name of the app configuration.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_APP_CONFIG" + }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-info.interface.ts", + "syntaxKind": "PropertySignature", + "name": "-j, --json", + "value": "\"\"", + "description": "Output the result as JSON.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_JSON" } ], - "value": "export interface appinfo {\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * format output as JSON\n * @environment SHOPIFY_FLAG_JSON\n */\n '--json'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n\n /**\n * Outputs environment variables necessary for running and deploying web/.\n * @environment SHOPIFY_FLAG_OUTPUT_WEB_ENV\n */\n '--web-env'?: ''\n}" + "value": "export interface appinfo {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Output the result as JSON.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n\n /**\n * Outputs environment variables necessary for running and deploying web/.\n * @environment SHOPIFY_FLAG_OUTPUT_WEB_ENV\n */\n '--web-env'?: ''\n}" } } } @@ -1608,6 +1770,15 @@ "name": "applogssources", "description": "", "members": [ + { + "filePath": "docs-shopify.dev/commands/interfaces/app-logs-sources.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--client-id ", + "value": "string", + "description": "The Client ID of your app.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_CLIENT_ID" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-logs-sources.interface.ts", "syntaxKind": "PropertySignature", @@ -1626,6 +1797,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-logs-sources.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--reset", + "value": "\"\"", + "description": "Reset all your settings.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_RESET" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-logs-sources.interface.ts", "syntaxKind": "PropertySignature", @@ -1645,7 +1825,7 @@ "environmentValue": "SHOPIFY_FLAG_APP_CONFIG" } ], - "value": "export interface applogssources {\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface applogssources {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } @@ -1759,7 +1939,7 @@ "syntaxKind": "PropertySignature", "name": "-j, --json", "value": "\"\"", - "description": "Log the run result as a JSON object.", + "description": "Output the result as JSON.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_JSON" }, @@ -1773,7 +1953,7 @@ "environmentValue": "SHOPIFY_FLAG_STORE" } ], - "value": "export interface applogs {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Log the run result as a JSON object.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Filters output to the specified log source.\n * @environment SHOPIFY_FLAG_SOURCE\n */\n '--source '?: string\n\n /**\n * Filters output to the specified status (success or failure).\n * @environment SHOPIFY_FLAG_STATUS\n */\n '--status '?: string\n\n /**\n * Store URL. Must be an existing development or Shopify Plus sandbox store.\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface applogs {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Output the result as JSON.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Filters output to the specified log source.\n * @environment SHOPIFY_FLAG_SOURCE\n */\n '--source '?: string\n\n /**\n * Filters output to the specified status (success or failure).\n * @environment SHOPIFY_FLAG_STATUS\n */\n '--status '?: string\n\n /**\n * Store URL. Must be an existing development or Shopify Plus sandbox store.\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } @@ -1924,19 +2104,10 @@ "syntaxKind": "PropertySignature", "name": "--client-id ", "value": "string", - "description": "The Client ID to fetch versions for.", + "description": "The Client ID of your app.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_CLIENT_ID" }, - { - "filePath": "docs-shopify.dev/commands/interfaces/app-versions-list.interface.ts", - "syntaxKind": "PropertySignature", - "name": "--json", - "value": "\"\"", - "description": "Output the versions list as JSON.", - "isOptional": true, - "environmentValue": "SHOPIFY_FLAG_JSON" - }, { "filePath": "docs-shopify.dev/commands/interfaces/app-versions-list.interface.ts", "syntaxKind": "PropertySignature", @@ -1955,6 +2126,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-versions-list.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--reset", + "value": "\"\"", + "description": "Reset all your settings.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_RESET" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-versions-list.interface.ts", "syntaxKind": "PropertySignature", @@ -1972,9 +2152,18 @@ "description": "The name of the app configuration.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_APP_CONFIG" + }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-versions-list.interface.ts", + "syntaxKind": "PropertySignature", + "name": "-j, --json", + "value": "\"\"", + "description": "Output the result as JSON.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_JSON" } ], - "value": "export interface appversionslist {\n /**\n * The Client ID to fetch versions for.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Output the versions list as JSON.\n * @environment SHOPIFY_FLAG_JSON\n */\n '--json'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface appversionslist {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Output the result as JSON.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } @@ -2074,6 +2263,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/app-webhook-trigger.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--reset", + "value": "\"\"", + "description": "Reset all your settings.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_RESET" + }, { "filePath": "docs-shopify.dev/commands/interfaces/app-webhook-trigger.interface.ts", "syntaxKind": "PropertySignature", @@ -2102,7 +2300,7 @@ "environmentValue": "SHOPIFY_FLAG_APP_CONFIG" } ], - "value": "export interface appwebhooktrigger {\n /**\n * The URL where the webhook payload should be sent.\n You will need a different address type for each delivery-method:\n · For remote HTTP testing, use a URL that starts with https://\n · For local HTTP testing, use http://localhost:{port}/{url-path}\n · For Google Pub/Sub, use pubsub://{project-id}:{topic-id}\n · For Amazon EventBridge, use an Amazon Resource Name (ARN) starting with arn:aws:events:\n * @environment SHOPIFY_FLAG_ADDRESS\n */\n '--address '?: string\n\n /**\n * The API Version of the webhook topic.\n * @environment SHOPIFY_FLAG_API_VERSION\n */\n '--api-version '?: string\n\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * Your app's client secret. This secret allows us to return the X-Shopify-Hmac-SHA256 header that lets you validate the origin of the response that you receive.\n * @environment SHOPIFY_FLAG_CLIENT_SECRET\n */\n '--client-secret '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Method chosen to deliver the topic payload. If not passed, it's inferred from the address.\n * @environment SHOPIFY_FLAG_DELIVERY_METHOD\n */\n '--delivery-method '?: string\n\n /**\n * This help. When you run the trigger command the CLI will prompt you for any information that isn't passed using flags.\n * @environment SHOPIFY_FLAG_HELP\n */\n '--help'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Deprecated. Please use client-secret.\n * @environment SHOPIFY_FLAG_SHARED_SECRET\n */\n '--shared-secret '?: string\n\n /**\n * The requested webhook topic.\n * @environment SHOPIFY_FLAG_TOPIC\n */\n '--topic '?: string\n}" + "value": "export interface appwebhooktrigger {\n /**\n * The URL where the webhook payload should be sent.\n You will need a different address type for each delivery-method:\n · For remote HTTP testing, use a URL that starts with https://\n · For local HTTP testing, use http://localhost:{port}/{url-path}\n · For Google Pub/Sub, use pubsub://{project-id}:{topic-id}\n · For Amazon EventBridge, use an Amazon Resource Name (ARN) starting with arn:aws:events:\n * @environment SHOPIFY_FLAG_ADDRESS\n */\n '--address '?: string\n\n /**\n * The API Version of the webhook topic.\n * @environment SHOPIFY_FLAG_API_VERSION\n */\n '--api-version '?: string\n\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * Your app's client secret. This secret allows us to return the X-Shopify-Hmac-SHA256 header that lets you validate the origin of the response that you receive.\n * @environment SHOPIFY_FLAG_CLIENT_SECRET\n */\n '--client-secret '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Method chosen to deliver the topic payload. If not passed, it's inferred from the address.\n * @environment SHOPIFY_FLAG_DELIVERY_METHOD\n */\n '--delivery-method '?: string\n\n /**\n * This help. When you run the trigger command the CLI will prompt you for any information that isn't passed using flags.\n * @environment SHOPIFY_FLAG_HELP\n */\n '--help'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Deprecated. Please use client-secret.\n * @environment SHOPIFY_FLAG_SHARED_SECRET\n */\n '--shared-secret '?: string\n\n /**\n * The requested webhook topic.\n * @environment SHOPIFY_FLAG_TOPIC\n */\n '--topic '?: string\n}" } } } @@ -4993,15 +5191,6 @@ "name": "themeinfo", "description": "", "members": [ - { - "filePath": "docs-shopify.dev/commands/interfaces/theme-info.interface.ts", - "syntaxKind": "PropertySignature", - "name": "--json", - "value": "\"\"", - "description": "Output the theme info as JSON.", - "isOptional": true, - "environmentValue": "SHOPIFY_FLAG_JSON" - }, { "filePath": "docs-shopify.dev/commands/interfaces/theme-info.interface.ts", "syntaxKind": "PropertySignature", @@ -5047,6 +5236,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_ENVIRONMENT" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/theme-info.interface.ts", + "syntaxKind": "PropertySignature", + "name": "-j, --json", + "value": "\"\"", + "description": "Output the result as JSON.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_JSON" + }, { "filePath": "docs-shopify.dev/commands/interfaces/theme-info.interface.ts", "syntaxKind": "PropertySignature", @@ -5066,7 +5264,7 @@ "environmentValue": "SHOPIFY_FLAG_THEME_ID" } ], - "value": "export interface themeinfo {\n /**\n * Retrieve info from your development theme.\n * @environment SHOPIFY_FLAG_DEVELOPMENT\n */\n '-d, --development'?: ''\n\n /**\n * The environment to apply to the current command.\n * @environment SHOPIFY_FLAG_ENVIRONMENT\n */\n '-e, --environment '?: string\n\n /**\n * Output the theme info as JSON.\n * @environment SHOPIFY_FLAG_JSON\n */\n '--json'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Password generated from the Theme Access app.\n * @environment SHOPIFY_CLI_THEME_TOKEN\n */\n '--password '?: string\n\n /**\n * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store '?: string\n\n /**\n * Theme ID or name of the remote theme.\n * @environment SHOPIFY_FLAG_THEME_ID\n */\n '-t, --theme '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface themeinfo {\n /**\n * Retrieve info from your development theme.\n * @environment SHOPIFY_FLAG_DEVELOPMENT\n */\n '-d, --development'?: ''\n\n /**\n * The environment to apply to the current command.\n * @environment SHOPIFY_FLAG_ENVIRONMENT\n */\n '-e, --environment '?: string\n\n /**\n * Output the result as JSON.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Password generated from the Theme Access app.\n * @environment SHOPIFY_CLI_THEME_TOKEN\n */\n '--password '?: string\n\n /**\n * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store '?: string\n\n /**\n * Theme ID or name of the remote theme.\n * @environment SHOPIFY_FLAG_THEME_ID\n */\n '-t, --theme '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } @@ -5251,15 +5449,6 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_ID" }, - { - "filePath": "docs-shopify.dev/commands/interfaces/theme-list.interface.ts", - "syntaxKind": "PropertySignature", - "name": "--json", - "value": "\"\"", - "description": "Output the theme list as JSON.", - "isOptional": true, - "environmentValue": "SHOPIFY_FLAG_JSON" - }, { "filePath": "docs-shopify.dev/commands/interfaces/theme-list.interface.ts", "syntaxKind": "PropertySignature", @@ -5317,6 +5506,107 @@ { "filePath": "docs-shopify.dev/commands/interfaces/theme-list.interface.ts", "syntaxKind": "PropertySignature", + "name": "-j, --json", + "value": "\"\"", + "description": "Output the result as JSON.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_JSON" + }, + { + "filePath": "docs-shopify.dev/commands/interfaces/theme-list.interface.ts", + "syntaxKind": "PropertySignature", + "name": "-s, --store ", + "value": "string", + "description": "Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_STORE" + } + ], + "value": "export interface themelist {\n /**\n * The environment to apply to the current command.\n * @environment SHOPIFY_FLAG_ENVIRONMENT\n */\n '-e, --environment '?: string\n\n /**\n * Only list theme with the given ID.\n * @environment SHOPIFY_FLAG_ID\n */\n '--id '?: string\n\n /**\n * Output the result as JSON.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Only list themes that contain the given name.\n * @environment SHOPIFY_FLAG_NAME\n */\n '--name '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Password generated from the Theme Access app.\n * @environment SHOPIFY_CLI_THEME_TOKEN\n */\n '--password '?: string\n\n /**\n * Only list themes with the given role.\n * @environment SHOPIFY_FLAG_ROLE\n */\n '--role '?: string\n\n /**\n * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + } + } + } + ], + "category": "theme", + "related": [] + }, + { + "name": "theme metafields pull", + "description": "Retrieves metafields from Shopify Admin.\n\nIf the metafields file already exists, it will be overwritten.", + "overviewPreviewDescription": "Download metafields definitions from your shop into a local file.", + "type": "command", + "isVisualComponent": false, + "defaultExample": { + "codeblock": { + "tabs": [ + { + "title": "theme metafields pull", + "code": "shopify theme metafields pull [flags]", + "language": "bash" + } + ], + "title": "theme metafields pull" + } + }, + "definitions": [ + { + "title": "Flags", + "description": "The following flags are available for the `theme metafields pull` command:", + "type": "thememetafieldspull", + "typeDefinitions": { + "thememetafieldspull": { + "filePath": "docs-shopify.dev/commands/interfaces/theme-metafields-pull.interface.ts", + "name": "thememetafieldspull", + "description": "", + "members": [ + { + "filePath": "docs-shopify.dev/commands/interfaces/theme-metafields-pull.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--no-color", + "value": "\"\"", + "description": "Disable color output.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_NO_COLOR" + }, + { + "filePath": "docs-shopify.dev/commands/interfaces/theme-metafields-pull.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--password ", + "value": "string", + "description": "Password generated from the Theme Access app.", + "isOptional": true, + "environmentValue": "SHOPIFY_CLI_THEME_TOKEN" + }, + { + "filePath": "docs-shopify.dev/commands/interfaces/theme-metafields-pull.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--path ", + "value": "string", + "description": "The path to your theme directory.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_PATH" + }, + { + "filePath": "docs-shopify.dev/commands/interfaces/theme-metafields-pull.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--verbose", + "value": "\"\"", + "description": "Increase the verbosity of the output.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_VERBOSE" + }, + { + "filePath": "docs-shopify.dev/commands/interfaces/theme-metafields-pull.interface.ts", + "syntaxKind": "PropertySignature", + "name": "-e, --environment ", + "value": "string", + "description": "The environment to apply to the current command.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_ENVIRONMENT" + }, + { + "filePath": "docs-shopify.dev/commands/interfaces/theme-metafields-pull.interface.ts", + "syntaxKind": "PropertySignature", "name": "-s, --store ", "value": "string", "description": "Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).", @@ -5324,7 +5614,7 @@ "environmentValue": "SHOPIFY_FLAG_STORE" } ], - "value": "export interface themelist {\n /**\n * The environment to apply to the current command.\n * @environment SHOPIFY_FLAG_ENVIRONMENT\n */\n '-e, --environment '?: string\n\n /**\n * Only list theme with the given ID.\n * @environment SHOPIFY_FLAG_ID\n */\n '--id '?: string\n\n /**\n * Output the theme list as JSON.\n * @environment SHOPIFY_FLAG_JSON\n */\n '--json'?: ''\n\n /**\n * Only list themes that contain the given name.\n * @environment SHOPIFY_FLAG_NAME\n */\n '--name '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Password generated from the Theme Access app.\n * @environment SHOPIFY_CLI_THEME_TOKEN\n */\n '--password '?: string\n\n /**\n * Only list themes with the given role.\n * @environment SHOPIFY_FLAG_ROLE\n */\n '--role '?: string\n\n /**\n * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface thememetafieldspull {\n /**\n * The environment to apply to the current command.\n * @environment SHOPIFY_FLAG_ENVIRONMENT\n */\n '-e, --environment '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Password generated from the Theme Access app.\n * @environment SHOPIFY_CLI_THEME_TOKEN\n */\n '--password '?: string\n\n /**\n * The path to your theme directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } @@ -5819,6 +6109,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/theme-push.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--strict", + "value": "\"\"", + "description": "Require theme check to pass without errors before pushing. Warnings are allowed.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_STRICT_PUSH" + }, { "filePath": "docs-shopify.dev/commands/interfaces/theme-push.interface.ts", "syntaxKind": "PropertySignature", @@ -5860,7 +6159,7 @@ "syntaxKind": "PropertySignature", "name": "-j, --json", "value": "\"\"", - "description": "Output JSON instead of a UI.", + "description": "Output the result as JSON.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_JSON" }, @@ -5937,7 +6236,7 @@ "environmentValue": "SHOPIFY_FLAG_IGNORE" } ], - "value": "export interface themepush {\n /**\n * Allow push to a live theme.\n * @environment SHOPIFY_FLAG_ALLOW_LIVE\n */\n '-a, --allow-live'?: ''\n\n /**\n * Push theme files from your remote development theme.\n * @environment SHOPIFY_FLAG_DEVELOPMENT\n */\n '-d, --development'?: ''\n\n /**\n * The environment to apply to the current command.\n * @environment SHOPIFY_FLAG_ENVIRONMENT\n */\n '-e, --environment '?: string\n\n /**\n * Skip downloading the specified files (Multiple flags allowed).\n * @environment SHOPIFY_FLAG_IGNORE\n */\n '-x, --ignore '?: string\n\n /**\n * Output JSON instead of a UI.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Push theme files from your remote live theme.\n * @environment SHOPIFY_FLAG_LIVE\n */\n '-l, --live'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Prevent deleting remote files that don't exist locally.\n * @environment SHOPIFY_FLAG_NODELETE\n */\n '-n, --nodelete'?: ''\n\n /**\n * Download only the specified files (Multiple flags allowed).\n * @environment SHOPIFY_FLAG_ONLY\n */\n '-o, --only '?: string\n\n /**\n * Password generated from the Theme Access app.\n * @environment SHOPIFY_CLI_THEME_TOKEN\n */\n '--password '?: string\n\n /**\n * The path to your theme directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Publish as the live theme after uploading.\n * @environment SHOPIFY_FLAG_PUBLISH\n */\n '-p, --publish'?: ''\n\n /**\n * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store '?: string\n\n /**\n * Theme ID or name of the remote theme.\n * @environment SHOPIFY_FLAG_THEME_ID\n */\n '-t, --theme '?: string\n\n /**\n * Create a new unpublished theme and push to it.\n * @environment SHOPIFY_FLAG_UNPUBLISHED\n */\n '-u, --unpublished'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface themepush {\n /**\n * Allow push to a live theme.\n * @environment SHOPIFY_FLAG_ALLOW_LIVE\n */\n '-a, --allow-live'?: ''\n\n /**\n * Push theme files from your remote development theme.\n * @environment SHOPIFY_FLAG_DEVELOPMENT\n */\n '-d, --development'?: ''\n\n /**\n * The environment to apply to the current command.\n * @environment SHOPIFY_FLAG_ENVIRONMENT\n */\n '-e, --environment '?: string\n\n /**\n * Skip downloading the specified files (Multiple flags allowed).\n * @environment SHOPIFY_FLAG_IGNORE\n */\n '-x, --ignore '?: string\n\n /**\n * Output the result as JSON.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Push theme files from your remote live theme.\n * @environment SHOPIFY_FLAG_LIVE\n */\n '-l, --live'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Prevent deleting remote files that don't exist locally.\n * @environment SHOPIFY_FLAG_NODELETE\n */\n '-n, --nodelete'?: ''\n\n /**\n * Download only the specified files (Multiple flags allowed).\n * @environment SHOPIFY_FLAG_ONLY\n */\n '-o, --only '?: string\n\n /**\n * Password generated from the Theme Access app.\n * @environment SHOPIFY_CLI_THEME_TOKEN\n */\n '--password '?: string\n\n /**\n * The path to your theme directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Publish as the live theme after uploading.\n * @environment SHOPIFY_FLAG_PUBLISH\n */\n '-p, --publish'?: ''\n\n /**\n * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store '?: string\n\n /**\n * Require theme check to pass without errors before pushing. Warnings are allowed.\n * @environment SHOPIFY_FLAG_STRICT_PUSH\n */\n '--strict'?: ''\n\n /**\n * Theme ID or name of the remote theme.\n * @environment SHOPIFY_FLAG_THEME_ID\n */\n '-t, --theme '?: string\n\n /**\n * Create a new unpublished theme and push to it.\n * @environment SHOPIFY_FLAG_UNPUBLISHED\n */\n '-u, --unpublished'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } diff --git a/docs/api/cli-kit/assets/navigation.js b/docs/api/cli-kit/assets/navigation.js index 75b81b63b20..4acadf2f506 100644 --- a/docs/api/cli-kit/assets/navigation.js +++ b/docs/api/cli-kit/assets/navigation.js @@ -1 +1 @@ -window.navigationData = "data:application/octet-stream;base64,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" \ No newline at end of file +window.navigationData = "data:application/octet-stream;base64,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" \ No newline at end of file diff --git a/docs/api/cli-kit/assets/search.js b/docs/api/cli-kit/assets/search.js index be1ae25ab9c..2de20e8afd5 100644 --- a/docs/api/cli-kit/assets/search.js +++ b/docs/api/cli-kit/assets/search.js @@ -1 +1 @@ -window.searchData = "data:application/octet-stream;base64,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"; \ No newline at end of file +window.searchData = "data:application/octet-stream;base64,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"; \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_abort.AbortController.html b/docs/api/cli-kit/classes/node_abort.AbortController.html index 0bd621e5c89..44cdb93f566 100644 --- a/docs/api/cli-kit/classes/node_abort.AbortController.html +++ b/docs/api/cli-kit/classes/node_abort.AbortController.html @@ -4,5 +4,5 @@

This class is necessary because AbortController support was added to Node 15 and the minimum version that we support is Node 14.

-

Hierarchy

  • AbortController
    • AbortController

Constructors

Hierarchy

  • AbortController
    • AbortController

Constructors

Constructors

\ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_abort.AbortSignal.html b/docs/api/cli-kit/classes/node_abort.AbortSignal.html index d261c16ef7a..05f705c90fc 100644 --- a/docs/api/cli-kit/classes/node_abort.AbortSignal.html +++ b/docs/api/cli-kit/classes/node_abort.AbortSignal.html @@ -1,3 +1,3 @@ AbortSignal | @shopify/cli-kit

The AbortSignal interface represents a signal object that allows you to communicate with a DOM request (such as a fetch request) and abort it if required via an AbortController object.

-

Hierarchy

  • AbortSignal
    • AbortSignal

Constructors

Hierarchy

  • AbortSignal
    • AbortSignal

Constructors

Constructors

\ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_base_command.default.html b/docs/api/cli-kit/classes/node_base_command.default.html index eaf4f1117f4..5708c9e8359 100644 --- a/docs/api/cli-kit/classes/node_base_command.default.html +++ b/docs/api/cli-kit/classes/node_base_command.default.html @@ -1,4 +1,4 @@ -default | @shopify/cli-kit

Hierarchy

  • Command
    • default

Constructors

constructor +default | @shopify/cli-kit

Hierarchy

  • Command
    • default

Constructors

  • Parameters

    • argv: string[]
    • config: Config

    Returns default

Properties

baseFlags: FlagInput<{}> = {}

Type declaration

    Methods

    \ No newline at end of file +

    Constructors

    • Parameters

      • argv: string[]
      • config: Config

      Returns default

    Properties

    baseFlags: FlagInput<{}> = {}

    Type declaration

      Methods

      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_custom_oclif_loader.ShopifyConfig.html b/docs/api/cli-kit/classes/node_custom_oclif_loader.ShopifyConfig.html index 4a7acd8adc3..3b8010a537f 100644 --- a/docs/api/cli-kit/classes/node_custom_oclif_loader.ShopifyConfig.html +++ b/docs/api/cli-kit/classes/node_custom_oclif_loader.ShopifyConfig.html @@ -1,3 +1,3 @@ -ShopifyConfig | @shopify/cli-kit

      Hierarchy

      • Config
        • ShopifyConfig

      Constructors

      constructor +ShopifyConfig | @shopify/cli-kit

      Hierarchy

      • Config
        • ShopifyConfig

      Constructors

      Methods

      Constructors

      Methods

      \ No newline at end of file +

      Constructors

      Methods

      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_error.AbortError.html b/docs/api/cli-kit/classes/node_error.AbortError.html index 316e25d6ac4..4e33b2ac2d5 100644 --- a/docs/api/cli-kit/classes/node_error.AbortError.html +++ b/docs/api/cli-kit/classes/node_error.AbortError.html @@ -1,10 +1,10 @@ AbortError | @shopify/cli-kit

      An abort error is a fatal error that shouldn't be reported as a bug. Those usually represent unexpected scenarios that we can't handle and that usually require some action from the developer.

      -

      Hierarchy (view full)

      Constructors

      Hierarchy (view full)

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file +

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_error.AbortSilentError.html b/docs/api/cli-kit/classes/node_error.AbortSilentError.html index d77a6e0b1a4..dd74f7380fe 100644 --- a/docs/api/cli-kit/classes/node_error.AbortSilentError.html +++ b/docs/api/cli-kit/classes/node_error.AbortSilentError.html @@ -1,10 +1,10 @@ AbortSilentError | @shopify/cli-kit

      A fatal error represents an error shouldn't be rescued and that causes the execution to terminate. There shouldn't be code that catches fatal errors.

      -

      Hierarchy (view full)

      Constructors

      Hierarchy (view full)

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file +

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_error.BugError.html b/docs/api/cli-kit/classes/node_error.BugError.html index b8b31fbc5b2..588784c4042 100644 --- a/docs/api/cli-kit/classes/node_error.BugError.html +++ b/docs/api/cli-kit/classes/node_error.BugError.html @@ -1,9 +1,9 @@ BugError | @shopify/cli-kit

      A bug error is an error that represents a bug and therefore should be reported.

      -

      Hierarchy (view full)

      Constructors

      Hierarchy (view full)

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file +

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_error.CancelExecution.html b/docs/api/cli-kit/classes/node_error.CancelExecution.html index 5bcb868b38b..c97a90d983f 100644 --- a/docs/api/cli-kit/classes/node_error.CancelExecution.html +++ b/docs/api/cli-kit/classes/node_error.CancelExecution.html @@ -1,2 +1,2 @@ -CancelExecution | @shopify/cli-kit

      Hierarchy

      • Error
        • CancelExecution

      Constructors

      constructor +CancelExecution | @shopify/cli-kit

      Hierarchy

      • Error
        • CancelExecution

      Constructors

      Constructors

      • Parameters

        • Optional message: string

        Returns CancelExecution

      • Parameters

        • Optional message: string
        • Optional options: ErrorOptions

        Returns CancelExecution

      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_error.ExternalError.html b/docs/api/cli-kit/classes/node_error.ExternalError.html index 139e987ddeb..708c95f2356 100644 --- a/docs/api/cli-kit/classes/node_error.ExternalError.html +++ b/docs/api/cli-kit/classes/node_error.ExternalError.html @@ -1,6 +1,6 @@ ExternalError | @shopify/cli-kit

      An external error is similar to Abort but has extra command and args attributes. This is useful to represent errors coming from external commands, usually executed by execa.

      -

      Hierarchy (view full)

      Constructors

      Hierarchy (view full)

      Constructors

      Properties

      args: string[]
      command: string
      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file +

      Constructors

      Properties

      args: string[]
      command: string
      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_error.FatalError.html b/docs/api/cli-kit/classes/node_error.FatalError.html index 4172b68c31f..195b9ca2ffe 100644 --- a/docs/api/cli-kit/classes/node_error.FatalError.html +++ b/docs/api/cli-kit/classes/node_error.FatalError.html @@ -1,6 +1,6 @@ FatalError | @shopify/cli-kit

      Class FatalErrorAbstract

      A fatal error represents an error shouldn't be rescued and that causes the execution to terminate. There shouldn't be code that catches fatal errors.

      -

      Hierarchy (view full)

      Constructors

      Hierarchy (view full)

      Constructors

      Properties

      customSections? formattedMessage? nextSteps? @@ -15,4 +15,4 @@ if you need to style the message inside the error Banner component.

    • Optional nextSteps: TokenItem<InlineToken>[]

      Message to show as "next steps" with suggestions to solve the issue.

    • Optional customSections: CustomSection[]

      Custom sections to show in the error banner. To be used if nextSteps is not enough.

      -
    • Returns FatalError

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file +

      Returns FatalError

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_git.GitDirectoryNotCleanError.html b/docs/api/cli-kit/classes/node_git.GitDirectoryNotCleanError.html index a0cb75203b8..7e138d0fa53 100644 --- a/docs/api/cli-kit/classes/node_git.GitDirectoryNotCleanError.html +++ b/docs/api/cli-kit/classes/node_git.GitDirectoryNotCleanError.html @@ -1,10 +1,10 @@ GitDirectoryNotCleanError | @shopify/cli-kit

      An abort error is a fatal error that shouldn't be reported as a bug. Those usually represent unexpected scenarios that we can't handle and that usually require some action from the developer.

      -

      Hierarchy (view full)

      Constructors

      Hierarchy (view full)

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file +

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_git.OutsideGitDirectoryError.html b/docs/api/cli-kit/classes/node_git.OutsideGitDirectoryError.html index 51e987ca32f..95c2733bba1 100644 --- a/docs/api/cli-kit/classes/node_git.OutsideGitDirectoryError.html +++ b/docs/api/cli-kit/classes/node_git.OutsideGitDirectoryError.html @@ -1,10 +1,10 @@ OutsideGitDirectoryError | @shopify/cli-kit

      An abort error is a fatal error that shouldn't be reported as a bug. Those usually represent unexpected scenarios that we can't handle and that usually require some action from the developer.

      -

      Hierarchy (view full)

      Constructors

      Hierarchy (view full)

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file +

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_local_storage.LocalStorage.html b/docs/api/cli-kit/classes/node_local_storage.LocalStorage.html index 59290cb8b1c..0d9b704b5c0 100644 --- a/docs/api/cli-kit/classes/node_local_storage.LocalStorage.html +++ b/docs/api/cli-kit/classes/node_local_storage.LocalStorage.html @@ -1,18 +1,18 @@ LocalStorage | @shopify/cli-kit

      A wrapper around the conf package that provides a strongly-typed interface for accessing the local storage.

      -

      Type Parameters

      • T extends {
            [key: string]: any;
        }

      Constructors

      Type Parameters

      • T extends {
            [key: string]: any;
        }

      Constructors

      Properties

      Methods

      Constructors

      Properties

      config: default<T>

      Methods

      • Delete a value from the local storage.

        +

      Constructors

      Properties

      config: default<T>

      Methods

      • Get a value from the local storage.

        +

      Returns void

      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_node_package_manager.FindUpAndReadPackageJsonNotFoundError.html b/docs/api/cli-kit/classes/node_node_package_manager.FindUpAndReadPackageJsonNotFoundError.html index ce604202080..aa2287dc406 100644 --- a/docs/api/cli-kit/classes/node_node_package_manager.FindUpAndReadPackageJsonNotFoundError.html +++ b/docs/api/cli-kit/classes/node_node_package_manager.FindUpAndReadPackageJsonNotFoundError.html @@ -2,11 +2,11 @@ hierarchy up can't find a package.json

      Param: directory

      The directory from which the traverse has been done

      Returns

      An abort error.

      -

      Hierarchy (view full)

      • BugError
        • FindUpAndReadPackageJsonNotFoundError

      Constructors

      Hierarchy (view full)

      • BugError
        • FindUpAndReadPackageJsonNotFoundError

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file +

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_node_package_manager.PackageJsonNotFoundError.html b/docs/api/cli-kit/classes/node_node_package_manager.PackageJsonNotFoundError.html index a9bbd217008..3cfefdc3f8d 100644 --- a/docs/api/cli-kit/classes/node_node_package_manager.PackageJsonNotFoundError.html +++ b/docs/api/cli-kit/classes/node_node_package_manager.PackageJsonNotFoundError.html @@ -2,11 +2,11 @@ a package.json doesn't have it.

      Param: directory

      The path to the directory that should contain a package.json

      Returns

      An abort error.

      -

      Hierarchy (view full)

      Constructors

      Hierarchy (view full)

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file +

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_node_package_manager.UnknownPackageManagerError.html b/docs/api/cli-kit/classes/node_node_package_manager.UnknownPackageManagerError.html index f1b7575d86b..d6e13b49c1e 100644 --- a/docs/api/cli-kit/classes/node_node_package_manager.UnknownPackageManagerError.html +++ b/docs/api/cli-kit/classes/node_node_package_manager.UnknownPackageManagerError.html @@ -1,10 +1,10 @@ UnknownPackageManagerError | @shopify/cli-kit

      Returns an abort error that's thrown when the package manager can't be determined.

      Returns

      An abort error.

      -

      Hierarchy (view full)

      Constructors

      Hierarchy (view full)

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file +

      Constructors

      Properties

      customSections?: CustomSection[]
      formattedMessage?: TokenItem
      nextSteps?: TokenItem<InlineToken>[]
      skipOclifErrorHandling: boolean
      tryMessage: null | TokenItem
      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_output.TokenizedString.html b/docs/api/cli-kit/classes/node_output.TokenizedString.html index 8aee343ebab..c5863d64d75 100644 --- a/docs/api/cli-kit/classes/node_output.TokenizedString.html +++ b/docs/api/cli-kit/classes/node_output.TokenizedString.html @@ -1,3 +1,3 @@ -TokenizedString | @shopify/cli-kit

      Constructors

      constructor +TokenizedString | @shopify/cli-kit

      Constructors

      Properties

      Constructors

      Properties

      value: string
      \ No newline at end of file +

      Constructors

      Properties

      value: string
      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_plugins_tunnel.TunnelError.html b/docs/api/cli-kit/classes/node_plugins_tunnel.TunnelError.html index 8fbe144894b..bd9b35f738c 100644 --- a/docs/api/cli-kit/classes/node_plugins_tunnel.TunnelError.html +++ b/docs/api/cli-kit/classes/node_plugins_tunnel.TunnelError.html @@ -1,3 +1,3 @@ -TunnelError | @shopify/cli-kit

      Hierarchy

      • ExtendableError
        • TunnelError

      Constructors

      constructor +TunnelError | @shopify/cli-kit

      Hierarchy

      • ExtendableError
        • TunnelError

      Constructors

      Properties

      Constructors

      Properties

      \ No newline at end of file +

      Constructors

      Properties

      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_result.Err.html b/docs/api/cli-kit/classes/node_result.Err.html index 1c1be30728d..5e8ccbe94ea 100644 --- a/docs/api/cli-kit/classes/node_result.Err.html +++ b/docs/api/cli-kit/classes/node_result.Err.html @@ -1,4 +1,4 @@ -Err | @shopify/cli-kit

      Class Err<TValue, TError>

      Type Parameters

      • TValue
      • TError

      Constructors

      constructor +Err | @shopify/cli-kit

      Class Err<TValue, TError>

      Type Parameters

      • TValue
      • TError

      Constructors

      Properties

      Methods

      Constructors

      Properties

      error: TError

      Methods

      • Return an unaltered copy of the Error without doing anything.

        +

      Constructors

      Properties

      error: TError

      Methods

      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_result.Ok.html b/docs/api/cli-kit/classes/node_result.Ok.html index 21ea9fb698f..cc3e5c3bef2 100644 --- a/docs/api/cli-kit/classes/node_result.Ok.html +++ b/docs/api/cli-kit/classes/node_result.Ok.html @@ -1,4 +1,4 @@ -Ok | @shopify/cli-kit

      Class Ok<TValue, TError>

      Type Parameters

      • TValue
      • TError

      Constructors

      constructor +Ok | @shopify/cli-kit

      Class Ok<TValue, TError>

      Type Parameters

      • TValue
      • TError

      Constructors

      Properties

      Methods

      Constructors

      Properties

      value: TValue

      Methods

      • Runs the handler method an return the same an unaltered copy of the Result. It could be used to log an +

      Constructors

      Properties

      value: TValue

      Methods

      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_testing_ui.Stdin.html b/docs/api/cli-kit/classes/node_testing_ui.Stdin.html index b004da60c7e..7ac584b3b07 100644 --- a/docs/api/cli-kit/classes/node_testing_ui.Stdin.html +++ b/docs/api/cli-kit/classes/node_testing_ui.Stdin.html @@ -1,4 +1,4 @@ -Stdin | @shopify/cli-kit

      Hierarchy

      • EventEmitter
        • Stdin

      Constructors

      constructor +Stdin | @shopify/cli-kit

      Hierarchy

      • EventEmitter
        • Stdin

      Constructors

      Properties

      data isTTY read @@ -7,4 +7,4 @@ setRawMode unref write -

      Constructors

      Properties

      data: null | string = null
      isTTY: boolean
      read: (() => null | string) = ...

      Type declaration

        • (): null | string
        • Returns null | string

      Methods

      \ No newline at end of file +

      Constructors

      Properties

      data: null | string = null
      isTTY: boolean
      read: (() => null | string) = ...

      Type declaration

        • (): null | string
        • Returns null | string

      Methods

      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_themes_theme_manager.ThemeManager.html b/docs/api/cli-kit/classes/node_themes_theme_manager.ThemeManager.html index 80279213dcc..f7b2593e376 100644 --- a/docs/api/cli-kit/classes/node_themes_theme_manager.ThemeManager.html +++ b/docs/api/cli-kit/classes/node_themes_theme_manager.ThemeManager.html @@ -1,4 +1,4 @@ -ThemeManager | @shopify/cli-kit

      Constructors

      constructor +ThemeManager | @shopify/cli-kit

      Constructors

      Properties

      adminSession: AdminSession
      context: string
      themeId: undefined | string

      Methods

      \ No newline at end of file +

      Constructors

      Properties

      adminSession: AdminSession
      context: string
      themeId: undefined | string

      Methods

      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_vendor_dev_server_DevServer.DevServer.html b/docs/api/cli-kit/classes/node_vendor_dev_server_DevServer.DevServer.html new file mode 100644 index 00000000000..bd7eb2c923e --- /dev/null +++ b/docs/api/cli-kit/classes/node_vendor_dev_server_DevServer.DevServer.html @@ -0,0 +1,7 @@ +DevServer | @shopify/cli-kit

      Constructors

      Properties

      name: string

      Methods

      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_vendor_dev_server_DevServer.DevServerCore.html b/docs/api/cli-kit/classes/node_vendor_dev_server_DevServer.DevServerCore.html new file mode 100644 index 00000000000..893c5503bf5 --- /dev/null +++ b/docs/api/cli-kit/classes/node_vendor_dev_server_DevServer.DevServerCore.html @@ -0,0 +1,7 @@ +DevServerCore | @shopify/cli-kit

      Constructors

      Properties

      name: "shopify" = 'shopify'

      Methods

      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_vendor_otel_js_export_InstantaneousMetricReader.InstantaneousMetricReader.html b/docs/api/cli-kit/classes/node_vendor_otel_js_export_InstantaneousMetricReader.InstantaneousMetricReader.html index baabbabac43..6e93cb40165 100644 --- a/docs/api/cli-kit/classes/node_vendor_otel_js_export_InstantaneousMetricReader.InstantaneousMetricReader.html +++ b/docs/api/cli-kit/classes/node_vendor_otel_js_export_InstantaneousMetricReader.InstantaneousMetricReader.html @@ -1,5 +1,5 @@ -InstantaneousMetricReader | @shopify/cli-kit

      Hierarchy

      • MetricReader
        • InstantaneousMetricReader

      Constructors

      constructor +InstantaneousMetricReader | @shopify/cli-kit

      Hierarchy

      • MetricReader
        • InstantaneousMetricReader

      Constructors

      Properties

      Methods

      Constructors

      Properties

      _exporter: PushMetricExporter

      Methods

      \ No newline at end of file +

      Constructors

      Properties

      _exporter: PushMetricExporter

      Methods

      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_vendor_otel_js_service_BaseOtelService_BaseOtelService.BaseOtelService.html b/docs/api/cli-kit/classes/node_vendor_otel_js_service_BaseOtelService_BaseOtelService.BaseOtelService.html index 1e09f06199f..b0adeded0a9 100644 --- a/docs/api/cli-kit/classes/node_vendor_otel_js_service_BaseOtelService_BaseOtelService.BaseOtelService.html +++ b/docs/api/cli-kit/classes/node_vendor_otel_js_service_BaseOtelService_BaseOtelService.BaseOtelService.html @@ -1,4 +1,4 @@ -BaseOtelService | @shopify/cli-kit

      Hierarchy (view full)

      Implements

      Constructors

      constructor +BaseOtelService | @shopify/cli-kit

      Hierarchy (view full)

      Implements

      Constructors

      Properties

      Constructors

      Properties

      meterProvider: MeterProvider
      metrics: Map<string, RecordMetricFunction> = ...
      prefixMetric: boolean
      recordListeners: Set<OnRecordCallback> = ...
      serviceName: string

      Methods

      Properties

      meterProvider: MeterProvider
      metrics: Map<string, RecordMetricFunction> = ...
      prefixMetric: boolean
      recordListeners: Set<OnRecordCallback> = ...
      serviceName: string

      Methods

      \ No newline at end of file +

      Parameters

      Returns (() => void)

        • (): void
        • Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_vendor_otel_js_service_DefaultOtelService_DefaultMeterProvider.DefaultMeterProvider.html b/docs/api/cli-kit/classes/node_vendor_otel_js_service_DefaultOtelService_DefaultMeterProvider.DefaultMeterProvider.html index 6d9227e58ec..21c8434e111 100644 --- a/docs/api/cli-kit/classes/node_vendor_otel_js_service_DefaultOtelService_DefaultMeterProvider.DefaultMeterProvider.html +++ b/docs/api/cli-kit/classes/node_vendor_otel_js_service_DefaultOtelService_DefaultMeterProvider.DefaultMeterProvider.html @@ -1,2 +1,2 @@ -DefaultMeterProvider | @shopify/cli-kit

      Hierarchy

      • MeterProvider
        • DefaultMeterProvider

      Constructors

      Constructors

      \ No newline at end of file +DefaultMeterProvider | @shopify/cli-kit

      Hierarchy

      • MeterProvider
        • DefaultMeterProvider

      Constructors

      Constructors

      \ No newline at end of file diff --git a/docs/api/cli-kit/classes/node_vendor_otel_js_service_DefaultOtelService_DefaultOtelService.DefaultOtelService.html b/docs/api/cli-kit/classes/node_vendor_otel_js_service_DefaultOtelService_DefaultOtelService.DefaultOtelService.html index 7e7684e7b7b..d759b49c106 100644 --- a/docs/api/cli-kit/classes/node_vendor_otel_js_service_DefaultOtelService_DefaultOtelService.DefaultOtelService.html +++ b/docs/api/cli-kit/classes/node_vendor_otel_js_service_DefaultOtelService_DefaultOtelService.DefaultOtelService.html @@ -1,4 +1,4 @@ -DefaultOtelService | @shopify/cli-kit

      Hierarchy (view full)

      Constructors

      constructor +DefaultOtelService | @shopify/cli-kit

      Hierarchy (view full)

      Constructors

      Properties

      Constructors

      Properties

      meterProvider: MeterProvider
      metrics: Map<string, RecordMetricFunction> = ...
      prefixMetric: boolean
      recordListeners: Set<OnRecordCallback> = ...
      serviceName: string

      Methods

      Properties

      meterProvider: MeterProvider
      metrics: Map<string, RecordMetricFunction> = ...
      prefixMetric: boolean
      recordListeners: Set<OnRecordCallback> = ...
      serviceName: string

      Methods

      \ No newline at end of file +

      Parameters

      Returns (() => void)

        • (): void
        • Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/enums/node_error.FatalErrorType.html b/docs/api/cli-kit/enums/node_error.FatalErrorType.html index 1976acbc4d9..f2b1cf73f88 100644 --- a/docs/api/cli-kit/enums/node_error.FatalErrorType.html +++ b/docs/api/cli-kit/enums/node_error.FatalErrorType.html @@ -1,4 +1,4 @@ -FatalErrorType | @shopify/cli-kit

      Enumeration Members

      Abort +FatalErrorType | @shopify/cli-kit

      Enumeration Members

      Enumeration Members

      Abort: 0
      AbortSilent: 1
      Bug: 2
      \ No newline at end of file +

      Enumeration Members

      Abort: 0
      AbortSilent: 1
      Bug: 2
      \ No newline at end of file diff --git a/docs/api/cli-kit/enums/node_themes_types.Operation.html b/docs/api/cli-kit/enums/node_themes_types.Operation.html index 84abee411fb..e76f642d136 100644 --- a/docs/api/cli-kit/enums/node_themes_types.Operation.html +++ b/docs/api/cli-kit/enums/node_themes_types.Operation.html @@ -1,3 +1,3 @@ -Operation | @shopify/cli-kit

      Enumeration Members

      Delete +Operation | @shopify/cli-kit

      Enumeration Members

      Enumeration Members

      Delete: "DELETE"
      Upload: "UPLOAD"
      \ No newline at end of file +

      Enumeration Members

      Delete: "DELETE"
      Upload: "UPLOAD"
      \ No newline at end of file diff --git a/docs/api/cli-kit/enums/node_vendor_otel_js_service_types.MetricInstrumentType.html b/docs/api/cli-kit/enums/node_vendor_otel_js_service_types.MetricInstrumentType.html index 2f0f4e2008e..96984bf8cc0 100644 --- a/docs/api/cli-kit/enums/node_vendor_otel_js_service_types.MetricInstrumentType.html +++ b/docs/api/cli-kit/enums/node_vendor_otel_js_service_types.MetricInstrumentType.html @@ -1,4 +1,4 @@ -MetricInstrumentType | @shopify/cli-kit

      Enumeration Members

      Counter +MetricInstrumentType | @shopify/cli-kit
      \ No newline at end of file +

      Enumeration Members

      Counter: "Counter"
      Histogram: "Histogram"
      UpDownCounter: "UpDownCounter"
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_array.difference.html b/docs/api/cli-kit/functions/common_array.difference.html index e0569d5fc6d..2e578f47b76 100644 --- a/docs/api/cli-kit/functions/common_array.difference.html +++ b/docs/api/cli-kit/functions/common_array.difference.html @@ -3,4 +3,4 @@

      Type Parameters

      • T

      Parameters

      • array: undefined | null | List<T>

        The array to inspect.

      • Rest ...values: List<T>[]

        The arrays of values to exclude.

      Returns T[]

      Returns the new array of filtered values.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_array.getArrayContainsDuplicates.html b/docs/api/cli-kit/functions/common_array.getArrayContainsDuplicates.html index 7e1d3f4f080..9e8aefd3cf2 100644 --- a/docs/api/cli-kit/functions/common_array.getArrayContainsDuplicates.html +++ b/docs/api/cli-kit/functions/common_array.getArrayContainsDuplicates.html @@ -1,4 +1,4 @@ getArrayContainsDuplicates | @shopify/cli-kit
      • Returns true if an array contains duplicates.

        Type Parameters

        • T

        Parameters

        • array: T[]

          The array to check against.

        Returns boolean

        True if the array contains duplicates.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_array.getArrayRejectingUndefined.html b/docs/api/cli-kit/functions/common_array.getArrayRejectingUndefined.html index 02b99131e5f..9c2fe3682d2 100644 --- a/docs/api/cli-kit/functions/common_array.getArrayRejectingUndefined.html +++ b/docs/api/cli-kit/functions/common_array.getArrayRejectingUndefined.html @@ -1,4 +1,4 @@ getArrayRejectingUndefined | @shopify/cli-kit
      • Returns a copy of the array deleting the elemements that are undefined.

        Type Parameters

        • T

        Parameters

        • array: (undefined | T)[]

          The array whose undefined will be deleted.

        Returns T[]

        A copy of the array with the undefined elements deleted.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_array.takeRandomFromArray.html b/docs/api/cli-kit/functions/common_array.takeRandomFromArray.html index 7cb06ed92ac..6df4f0f7aa5 100644 --- a/docs/api/cli-kit/functions/common_array.takeRandomFromArray.html +++ b/docs/api/cli-kit/functions/common_array.takeRandomFromArray.html @@ -1,4 +1,4 @@ takeRandomFromArray | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_array.uniq.html b/docs/api/cli-kit/functions/common_array.uniq.html index c22a73fc066..9cb7d3289c7 100644 --- a/docs/api/cli-kit/functions/common_array.uniq.html +++ b/docs/api/cli-kit/functions/common_array.uniq.html @@ -1,4 +1,4 @@ uniq | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_array.uniqBy.html b/docs/api/cli-kit/functions/common_array.uniqBy.html index 0d5cbe6f17e..730b4099d5d 100644 --- a/docs/api/cli-kit/functions/common_array.uniqBy.html +++ b/docs/api/cli-kit/functions/common_array.uniqBy.html @@ -4,4 +4,4 @@

      Type Parameters

      • T

      Parameters

      • array: undefined | null | List<T>

        The array to inspect.

      • iteratee: ValueIteratee<T>

        The iteratee invoked per element.

      Returns T[]

      Returns the new duplicate free array.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_collection.groupBy.html b/docs/api/cli-kit/functions/common_collection.groupBy.html index c6c748d6e1a..16ed7d39c60 100644 --- a/docs/api/cli-kit/functions/common_collection.groupBy.html +++ b/docs/api/cli-kit/functions/common_collection.groupBy.html @@ -4,4 +4,4 @@

      Type Parameters

      • T

      Parameters

      • collection: undefined | null | ArrayLike<T>

        The collection to iterate over.

      • Optional iteratee: ValueIteratee<T>

        The function invoked per iteration.

      Returns {
          [index: string]: T[];
      }

      Returns the composed aggregate object.

      -
      • [index: string]: T[]
      \ No newline at end of file +
      • [index: string]: T[]
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_collection.partition.html b/docs/api/cli-kit/functions/common_collection.partition.html index 1f78469ec03..469f85a7910 100644 --- a/docs/api/cli-kit/functions/common_collection.partition.html +++ b/docs/api/cli-kit/functions/common_collection.partition.html @@ -4,4 +4,4 @@

      Type Parameters

      • T

      Parameters

      • collection: undefined | null | List<T>

        The collection to iterate over.

      • callback: ValueIteratee<T>

        The function called per iteration.

      Returns [T[], T[]]

      Returns the array of grouped elements.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_function.debounce.html b/docs/api/cli-kit/functions/common_function.debounce.html index 4b9ad219a24..4d9de773c92 100644 --- a/docs/api/cli-kit/functions/common_function.debounce.html +++ b/docs/api/cli-kit/functions/common_function.debounce.html @@ -10,4 +10,4 @@
    • Optional wait: number

      The number of milliseconds to delay.

    • Optional options: DebounceSettings

      The options object.

    • Returns DebouncedFunc<T>

      Returns the new debounced function.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_function.memoize.html b/docs/api/cli-kit/functions/common_function.memoize.html index 5bc5abeba81..0b2f16bf78c 100644 --- a/docs/api/cli-kit/functions/common_function.memoize.html +++ b/docs/api/cli-kit/functions/common_function.memoize.html @@ -5,4 +5,4 @@

      Type Parameters

      • T extends ((...args) => any)

      Parameters

      • func: T

        The function to have its output memoized.

      • Optional resolver: ((...args) => unknown)

        The function to resolve the cache key.

          • (...args): unknown
          • Parameters

            • Rest ...args: Parameters<T>

            Returns unknown

      Returns T

      Returns the new memoizing function.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_lang.isEqual.html b/docs/api/cli-kit/functions/common_lang.isEqual.html index dde951cd7ca..d7f44e61cdf 100644 --- a/docs/api/cli-kit/functions/common_lang.isEqual.html +++ b/docs/api/cli-kit/functions/common_lang.isEqual.html @@ -8,4 +8,4 @@

      Parameters

      • value: unknown

        The value to compare.

      • other: unknown

        The other value to compare.

      Returns boolean

      Returns true if the values are equivalent, else false.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_object.compact.html b/docs/api/cli-kit/functions/common_object.compact.html index 63c232028a4..69976a4c46d 100644 --- a/docs/api/cli-kit/functions/common_object.compact.html +++ b/docs/api/cli-kit/functions/common_object.compact.html @@ -1,4 +1,4 @@ compact | @shopify/cli-kit
      • Removes the undefined elements.

        Parameters

        • object: object

          The object whose undefined will be deleted.

        Returns object

        A copy of the object with the undefined elements deleted.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_object.deepCompare.html b/docs/api/cli-kit/functions/common_object.deepCompare.html index e4c77d79dae..72cd7bf2afc 100644 --- a/docs/api/cli-kit/functions/common_object.deepCompare.html +++ b/docs/api/cli-kit/functions/common_object.deepCompare.html @@ -2,4 +2,4 @@

      Parameters

      • one: object

        The first object to be compared.

      • two: object

        The second object to be compared.

      Returns boolean

      True if the objects are equal, false otherwise.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_object.deepDifference.html b/docs/api/cli-kit/functions/common_object.deepDifference.html index 123d5dea68e..5900b1e696f 100644 --- a/docs/api/cli-kit/functions/common_object.deepDifference.html +++ b/docs/api/cli-kit/functions/common_object.deepDifference.html @@ -2,4 +2,4 @@

      Parameters

      • one: object

        The first object to be compared.

      • two: object

        The second object to be compared.

      Returns [object, object]

      Two objects containing the fields that are different, each one with the values of one object.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_object.deepMergeObjects.html b/docs/api/cli-kit/functions/common_object.deepMergeObjects.html index 9ebbb76d5e0..ddc9da35ce8 100644 --- a/docs/api/cli-kit/functions/common_object.deepMergeObjects.html +++ b/docs/api/cli-kit/functions/common_object.deepMergeObjects.html @@ -4,4 +4,4 @@
    • arrayMergeStrategy: ((destinationArray, sourceArray) => unknown[]) = unionArrayStrategy

      Strategy used to merge the array typed fields. Union strategy is used by default to avoid duplicated elements.

        • (destinationArray, sourceArray): unknown[]
        • Parameters

          • destinationArray: unknown[]
          • sourceArray: unknown[]

          Returns unknown[]

    • Returns T1 & T2

      A Javascrip tobject with th emerged objects.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_object.getPathValue.html b/docs/api/cli-kit/functions/common_object.getPathValue.html index 6b7d59a5fea..a7a4dacc357 100644 --- a/docs/api/cli-kit/functions/common_object.getPathValue.html +++ b/docs/api/cli-kit/functions/common_object.getPathValue.html @@ -4,4 +4,4 @@

      Returns T | undefined

      • Returns the resolved value.
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_object.isEmpty.html b/docs/api/cli-kit/functions/common_object.isEmpty.html index 5e163b1b174..df0efa5faa0 100644 --- a/docs/api/cli-kit/functions/common_object.isEmpty.html +++ b/docs/api/cli-kit/functions/common_object.isEmpty.html @@ -3,4 +3,4 @@

      Returns boolean

      • Returns true if value is empty, else false.
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_object.mapValues.html b/docs/api/cli-kit/functions/common_object.mapValues.html index a9e29f32021..ced5bcb5320 100644 --- a/docs/api/cli-kit/functions/common_object.mapValues.html +++ b/docs/api/cli-kit/functions/common_object.mapValues.html @@ -4,4 +4,4 @@

      Type Parameters

      • T extends object
      • TResult

      Parameters

      • source: undefined | null | T

        The object to iterate over.

      • callback: ObjectIterator<T, TResult>

        The function invoked per iteration.

      Returns {
          [P in keyof T]: TResult
      }

      Returns the new mapped object.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_object.pickBy.html b/docs/api/cli-kit/functions/common_object.pickBy.html index 4ba3b1932e4..46ff9de32a5 100644 --- a/docs/api/cli-kit/functions/common_object.pickBy.html +++ b/docs/api/cli-kit/functions/common_object.pickBy.html @@ -3,4 +3,4 @@

      Type Parameters

      • T

      Parameters

      • object: undefined | null | Dictionary<T>

        The source object.

      • predicate: ValueKeyIteratee<T>

        The function invoked per property.

      Returns Dictionary<T>

      Returns the new object.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_object.setPathValue.html b/docs/api/cli-kit/functions/common_object.setPathValue.html index b6df7ad0789..3842c710723 100644 --- a/docs/api/cli-kit/functions/common_object.setPathValue.html +++ b/docs/api/cli-kit/functions/common_object.setPathValue.html @@ -5,4 +5,4 @@

      Returns object

      • Returns object.
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_retry.performActionWithRetryAfterRecovery.html b/docs/api/cli-kit/functions/common_retry.performActionWithRetryAfterRecovery.html index 60aa1852b37..977e82a4162 100644 --- a/docs/api/cli-kit/functions/common_retry.performActionWithRetryAfterRecovery.html +++ b/docs/api/cli-kit/functions/common_retry.performActionWithRetryAfterRecovery.html @@ -9,4 +9,4 @@ fails the first time.

        • (): Promise<unknown>
        • Returns Promise<unknown>

    • retries: number = 1

      The number of times to retry the action if an error happens.

    • Returns Promise<T>

      The result of the action.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.camelize.html b/docs/api/cli-kit/functions/common_string.camelize.html index f52c89ad4c5..b61b0c39868 100644 --- a/docs/api/cli-kit/functions/common_string.camelize.html +++ b/docs/api/cli-kit/functions/common_string.camelize.html @@ -1,4 +1,4 @@ camelize | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.capitalize.html b/docs/api/cli-kit/functions/common_string.capitalize.html index 245c1f6b489..f173e3ba012 100644 --- a/docs/api/cli-kit/functions/common_string.capitalize.html +++ b/docs/api/cli-kit/functions/common_string.capitalize.html @@ -1,4 +1,4 @@ capitalize | @shopify/cli-kit
      • Given a string, it returns it with the first letter capitalized.

        Parameters

        • str: string

          String to capitalize.

        Returns string

        String with the first letter capitalized.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.constantize.html b/docs/api/cli-kit/functions/common_string.constantize.html index 635a6ed12fe..231248966ad 100644 --- a/docs/api/cli-kit/functions/common_string.constantize.html +++ b/docs/api/cli-kit/functions/common_string.constantize.html @@ -1,4 +1,4 @@ constantize | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.escapeRegExp.html b/docs/api/cli-kit/functions/common_string.escapeRegExp.html index 7515ad408b4..4a3ad09c606 100644 --- a/docs/api/cli-kit/functions/common_string.escapeRegExp.html +++ b/docs/api/cli-kit/functions/common_string.escapeRegExp.html @@ -2,4 +2,4 @@ More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping.

      Parameters

      • str: string

        String to escape.

      Returns string

      The escaped string.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.formatDate.html b/docs/api/cli-kit/functions/common_string.formatDate.html index 77de46aab21..8b018e86d75 100644 --- a/docs/api/cli-kit/functions/common_string.formatDate.html +++ b/docs/api/cli-kit/functions/common_string.formatDate.html @@ -1,4 +1,4 @@ formatDate | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.formatLocalDate.html b/docs/api/cli-kit/functions/common_string.formatLocalDate.html index 7020f69faf0..a33e0e1304f 100644 --- a/docs/api/cli-kit/functions/common_string.formatLocalDate.html +++ b/docs/api/cli-kit/functions/common_string.formatLocalDate.html @@ -1,4 +1,4 @@ formatLocalDate | @shopify/cli-kit
      • Given a date in UTC ISO String format, return a formatted string in local time like "2021-01-01 12:00:00".

        Parameters

        • dateString: string

          UTC ISO Date String.

        Returns string

        The transformed string in local system time.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.getRandomName.html b/docs/api/cli-kit/functions/common_string.getRandomName.html index c10ce097577..3f236699060 100644 --- a/docs/api/cli-kit/functions/common_string.getRandomName.html +++ b/docs/api/cli-kit/functions/common_string.getRandomName.html @@ -1,4 +1,4 @@ getRandomName | @shopify/cli-kit
      • Generates a random name by combining an adjective and noun.

        Parameters

        • family: RandomNameFamily = 'business'

          Theme to use for the random name (business or creative).

        Returns string

        A random name generated by combining an adjective and noun.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.hyphenate.html b/docs/api/cli-kit/functions/common_string.hyphenate.html index 3183dce3c43..d3fff6cd4b8 100644 --- a/docs/api/cli-kit/functions/common_string.hyphenate.html +++ b/docs/api/cli-kit/functions/common_string.hyphenate.html @@ -1,4 +1,4 @@ hyphenate | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.joinWithAnd.html b/docs/api/cli-kit/functions/common_string.joinWithAnd.html index 37ff03cef15..ba85b3e0560 100644 --- a/docs/api/cli-kit/functions/common_string.joinWithAnd.html +++ b/docs/api/cli-kit/functions/common_string.joinWithAnd.html @@ -3,4 +3,4 @@ For example: ["a", "b", "c"] returns "a", "b" and "c".

      Parameters

      • items: string[]

        List of items.

      Returns string

      The joined string.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.linesToColumns.html b/docs/api/cli-kit/functions/common_string.linesToColumns.html index 99b8c349a69..957d6ecf652 100644 --- a/docs/api/cli-kit/functions/common_string.linesToColumns.html +++ b/docs/api/cli-kit/functions/common_string.linesToColumns.html @@ -1,4 +1,4 @@ linesToColumns | @shopify/cli-kit
      • Transforms a matrix of strings into a single string with the columns aligned.

        Parameters

        • lines: string[][]

          Array of rows, where each row is an array of strings (representing columns).

        Returns string

        A string with the columns aligned.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.normalizeDelimitedString.html b/docs/api/cli-kit/functions/common_string.normalizeDelimitedString.html index 9e0f5f9b946..a28f564e326 100644 --- a/docs/api/cli-kit/functions/common_string.normalizeDelimitedString.html +++ b/docs/api/cli-kit/functions/common_string.normalizeDelimitedString.html @@ -3,4 +3,4 @@

      Parameters

      • Optional delimitedString: string

        String to normalize.

      • delimiter: string = ','

        Delimiter used to split the string into tokens.

      Returns string | undefined

      String with the normalized list of tokens.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.pascalize.html b/docs/api/cli-kit/functions/common_string.pascalize.html index 210ddf33126..06c60837691 100644 --- a/docs/api/cli-kit/functions/common_string.pascalize.html +++ b/docs/api/cli-kit/functions/common_string.pascalize.html @@ -2,4 +2,4 @@ Eg: "pascal_case" returns "PascalCase".

      Parameters

      • str: string

        String to PascalCase.

      Returns string

      String with all the first letter capitalized with no spaces.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.pluralize.html b/docs/api/cli-kit/functions/common_string.pluralize.html index 0ea3ec7cb3a..94ebaad8cf5 100644 --- a/docs/api/cli-kit/functions/common_string.pluralize.html +++ b/docs/api/cli-kit/functions/common_string.pluralize.html @@ -4,4 +4,4 @@
    • singular: ((item) => TokenItem<TSingularToken>)

      Supplier used when the list of items has a single item.

    • Optional none: (() => TokenItem<TNoneToken>)

      Supplier used when the list has no items.

    • Returns TokenItem<TPluralToken | TSingularToken | TNoneToken> | string

      The TokenItem supplied by the plural, singular, or none functions.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.slugify.html b/docs/api/cli-kit/functions/common_string.slugify.html index bd34090397a..cf0a85a7dd5 100644 --- a/docs/api/cli-kit/functions/common_string.slugify.html +++ b/docs/api/cli-kit/functions/common_string.slugify.html @@ -1,4 +1,4 @@ slugify | @shopify/cli-kit
      • Given a string, it transforms it to a slug (lowercase, hyphenated, no special chars, trimmed...).

        Parameters

        • str: string

          String to slugify.

        Returns string

        The slugified string.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.tryParseInt.html b/docs/api/cli-kit/functions/common_string.tryParseInt.html index c908d5fb3c1..2498aca8c54 100644 --- a/docs/api/cli-kit/functions/common_string.tryParseInt.html +++ b/docs/api/cli-kit/functions/common_string.tryParseInt.html @@ -1,4 +1,4 @@ tryParseInt | @shopify/cli-kit
      • Try to convert a string to an int, falling back to undefined if unable to.

        Parameters

        • maybeInt: undefined | string

          String to convert to an int.

        Returns number | undefined

        The int if it was able to convert, otherwise undefined.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_string.underscore.html b/docs/api/cli-kit/functions/common_string.underscore.html index 15a6849b7b4..7078aff4085 100644 --- a/docs/api/cli-kit/functions/common_string.underscore.html +++ b/docs/api/cli-kit/functions/common_string.underscore.html @@ -1,4 +1,4 @@ underscore | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_ts_json_narrowing.assertStringMap.html b/docs/api/cli-kit/functions/common_ts_json_narrowing.assertStringMap.html index bde170bea7e..74c8fd180d7 100644 --- a/docs/api/cli-kit/functions/common_ts_json_narrowing.assertStringMap.html +++ b/docs/api/cli-kit/functions/common_ts_json_narrowing.assertStringMap.html @@ -1,4 +1,4 @@ assertStringMap | @shopify/cli-kit
      • Asserts that the unknownBlob is a string map. Used to validate JSON objects received over the wire.

        Parameters

        • unknownBlob: unknown

          The unknown object to validate.

        Returns asserts unknownBlob is {
            [key: string]: string;
        }

        Throws

        BugError - Thrown if the unknownBlob is not a string map.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_url.isValidURL.html b/docs/api/cli-kit/functions/common_url.isValidURL.html index 1206d16df81..da89f3a9e99 100644 --- a/docs/api/cli-kit/functions/common_url.isValidURL.html +++ b/docs/api/cli-kit/functions/common_url.isValidURL.html @@ -2,4 +2,4 @@

      Parameters

      • url: string

        URL to be checked.

      Returns boolean

      True if the URL is valid, false otherwise.

      Throws

      An error if URL's constructor throws an error other than TypeError.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/common_url.safeParseURL.html b/docs/api/cli-kit/functions/common_url.safeParseURL.html index d367fa8e0cb..a815d56cd3e 100644 --- a/docs/api/cli-kit/functions/common_url.safeParseURL.html +++ b/docs/api/cli-kit/functions/common_url.safeParseURL.html @@ -1,4 +1,4 @@ safeParseURL | @shopify/cli-kit
      • Safely parse a string into a URL.

        Parameters

        • url: string

          The string to parse into a URL.

        Returns URL | undefined

        A URL object if the parsing is successful, undefined otherwise.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_analytics.reportAnalyticsEvent.html b/docs/api/cli-kit/functions/node_analytics.reportAnalyticsEvent.html index 00a394aba26..9b04173cf70 100644 --- a/docs/api/cli-kit/functions/node_analytics.reportAnalyticsEvent.html +++ b/docs/api/cli-kit/functions/node_analytics.reportAnalyticsEvent.html @@ -1,3 +1,3 @@ reportAnalyticsEvent | @shopify/cli-kit
      • Report an analytics event, sending it off to Monorail -- Shopify's internal analytics service.

        The payload for an event includes both generic data, and data gathered from installed plug-ins.

        -

        Parameters

        • options: ReportAnalyticsEventOptions

        Returns Promise<void>

      \ No newline at end of file +

      Parameters

      • options: ReportAnalyticsEventOptions

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_admin.adminRequest.html b/docs/api/cli-kit/functions/node_api_admin.adminRequest.html index 1936eb5f28e..804769759c9 100644 --- a/docs/api/cli-kit/functions/node_api_admin.adminRequest.html +++ b/docs/api/cli-kit/functions/node_api_admin.adminRequest.html @@ -3,4 +3,4 @@
    • session: AdminSession

      Shopify admin session including token and Store FQDN.

    • Optional variables: GraphQLVariables

      GraphQL variables to pass to the query.

    • Returns Promise<T>

      The response of the query of generic type .

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_admin.adminRequestDoc.html b/docs/api/cli-kit/functions/node_api_admin.adminRequestDoc.html index 66baed7d84f..7a159ff85ca 100644 --- a/docs/api/cli-kit/functions/node_api_admin.adminRequestDoc.html +++ b/docs/api/cli-kit/functions/node_api_admin.adminRequestDoc.html @@ -5,4 +5,4 @@
    • Optional version: string

      API version.

    • Optional responseOptions: GraphQLResponseOptions<TResult>

      Control how API responses will be handled.

    • Returns Promise<TResult>

      The response of the query of generic type .

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_admin.adminUrl.html b/docs/api/cli-kit/functions/node_api_admin.adminUrl.html index c3cbb499121..b271aa31da3 100644 --- a/docs/api/cli-kit/functions/node_api_admin.adminUrl.html +++ b/docs/api/cli-kit/functions/node_api_admin.adminUrl.html @@ -5,4 +5,4 @@

      Returns string

      • Admin API URL.
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_admin.restRequest.html b/docs/api/cli-kit/functions/node_api_admin.restRequest.html index 17758cdc716..bd215b2cd19 100644 --- a/docs/api/cli-kit/functions/node_api_admin.restRequest.html +++ b/docs/api/cli-kit/functions/node_api_admin.restRequest.html @@ -8,4 +8,4 @@

      Returns Promise<RestResponse>

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_admin.supportedApiVersions.html b/docs/api/cli-kit/functions/node_api_admin.supportedApiVersions.html index b07aad501c5..8b9138a8402 100644 --- a/docs/api/cli-kit/functions/node_api_admin.supportedApiVersions.html +++ b/docs/api/cli-kit/functions/node_api_admin.supportedApiVersions.html @@ -3,4 +3,4 @@

      Returns Promise<string[]>

      • An array of supported API versions.
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_app_dev.appDevRequest.html b/docs/api/cli-kit/functions/node_api_app_dev.appDevRequest.html index 8dd643c8a5e..d698bb567af 100644 --- a/docs/api/cli-kit/functions/node_api_app_dev.appDevRequest.html +++ b/docs/api/cli-kit/functions/node_api_app_dev.appDevRequest.html @@ -5,4 +5,4 @@
    • token: string

      Partners token.

    • Optional variables: TVariables

      GraphQL variables to pass to the query.

    • Returns Promise<TResult>

      The response of the query of generic type .

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_app_management.appManagementRequestDoc.html b/docs/api/cli-kit/functions/node_api_app_management.appManagementRequestDoc.html index 69c93f1f751..bd2ddb4b3f5 100644 --- a/docs/api/cli-kit/functions/node_api_app_management.appManagementRequestDoc.html +++ b/docs/api/cli-kit/functions/node_api_app_management.appManagementRequestDoc.html @@ -4,4 +4,4 @@
    • token: string

      Partners token.

    • Optional variables: TVariables

      GraphQL variables to pass to the query.

    • Returns Promise<TResult>

      The response of the query of generic type .

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_app_management.handleDeprecations.html b/docs/api/cli-kit/functions/node_api_app_management.handleDeprecations.html index 2057b8e4ed6..64f0ec1ad95 100644 --- a/docs/api/cli-kit/functions/node_api_app_management.handleDeprecations.html +++ b/docs/api/cli-kit/functions/node_api_app_management.handleDeprecations.html @@ -1,4 +1,4 @@ handleDeprecations | @shopify/cli-kit
      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformOrganizationsRequest.html b/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformOrganizationsRequest.html index 47b9c5626b2..eb64ff3a724 100644 --- a/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformOrganizationsRequest.html +++ b/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformOrganizationsRequest.html @@ -4,4 +4,4 @@
    • organizationId: string

      Organization ID as a numeric (non-GID) value.

    • Optional variables: GraphQLVariables

      GraphQL variables to pass to the query.

    • Returns Promise<T>

      The response of the query of generic type .

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformOrganizationsRequestDoc.html b/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformOrganizationsRequestDoc.html index f525d5a7b88..f8f962785ca 100644 --- a/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformOrganizationsRequestDoc.html +++ b/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformOrganizationsRequestDoc.html @@ -4,4 +4,4 @@
    • organizationId: string

      Organization ID as a numeric value.

    • Optional variables: GraphQLVariables

      GraphQL variables to pass to the query.

    • Returns Promise<TResult>

      The response of the query of generic type .

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformRequest.html b/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformRequest.html index 2ecddd2de75..3cc233a6b02 100644 --- a/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformRequest.html +++ b/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformRequest.html @@ -3,4 +3,4 @@
    • token: string

      Business Platform token.

    • Optional variables: GraphQLVariables

      GraphQL variables to pass to the query.

    • Returns Promise<T>

      The response of the query of generic type .

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformRequestDoc.html b/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformRequestDoc.html index b4de432e2be..15bf60308a4 100644 --- a/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformRequestDoc.html +++ b/docs/api/cli-kit/functions/node_api_business_platform.businessPlatformRequestDoc.html @@ -3,4 +3,4 @@
    • token: string

      Business Platform token.

    • Optional variables: TVariables

      GraphQL variables to pass to the query.

    • Returns Promise<TResult>

      The response of the query of generic type .

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_functions.functionsRequestDoc.html b/docs/api/cli-kit/functions/node_api_functions.functionsRequestDoc.html new file mode 100644 index 00000000000..c899f22ed33 --- /dev/null +++ b/docs/api/cli-kit/functions/node_api_functions.functionsRequestDoc.html @@ -0,0 +1,8 @@ +functionsRequestDoc | @shopify/cli-kit
      • Executes a rate-limited GraphQL request against the App Management Functions API.

        +

        Type Parameters

        • TResult
        • TVariables extends Variables

        Parameters

        • orgId: string

          Organization identifier.

          +
        • query: TypedDocumentNode<TResult, TVariables>

          Typed GraphQL document node.

          +
        • token: string

          Authentication token.

          +
        • appId: string

          App identifier.

          +
        • Optional variables: TVariables

          Optional query variables.

          +

        Returns Promise<TResult>

        Promise resolving to the typed query result.

        +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_graphql.graphqlRequest.html b/docs/api/cli-kit/functions/node_api_graphql.graphqlRequest.html index 6801b05a55c..534253a252d 100644 --- a/docs/api/cli-kit/functions/node_api_graphql.graphqlRequest.html +++ b/docs/api/cli-kit/functions/node_api_graphql.graphqlRequest.html @@ -1,4 +1,4 @@ graphqlRequest | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_graphql.graphqlRequestDoc.html b/docs/api/cli-kit/functions/node_api_graphql.graphqlRequestDoc.html index d2e01f975ff..1871065fa49 100644 --- a/docs/api/cli-kit/functions/node_api_graphql.graphqlRequestDoc.html +++ b/docs/api/cli-kit/functions/node_api_graphql.graphqlRequestDoc.html @@ -1,4 +1,4 @@ graphqlRequestDoc | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_partners.handleDeprecations.html b/docs/api/cli-kit/functions/node_api_partners.handleDeprecations.html index 76114ea2f96..cfdde5b62cb 100644 --- a/docs/api/cli-kit/functions/node_api_partners.handleDeprecations.html +++ b/docs/api/cli-kit/functions/node_api_partners.handleDeprecations.html @@ -1,4 +1,4 @@ handleDeprecations | @shopify/cli-kit
      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_partners.partnersRequest.html b/docs/api/cli-kit/functions/node_api_partners.partnersRequest.html index 57e5353510d..fdda1dee1c8 100644 --- a/docs/api/cli-kit/functions/node_api_partners.partnersRequest.html +++ b/docs/api/cli-kit/functions/node_api_partners.partnersRequest.html @@ -3,4 +3,4 @@
    • token: string

      Partners token.

    • Optional variables: GraphQLVariables

      GraphQL variables to pass to the query.

    • Returns Promise<T>

      The response of the query of generic type .

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_partners.partnersRequestDoc.html b/docs/api/cli-kit/functions/node_api_partners.partnersRequestDoc.html index 10ae243cf14..eb04fb561c8 100644 --- a/docs/api/cli-kit/functions/node_api_partners.partnersRequestDoc.html +++ b/docs/api/cli-kit/functions/node_api_partners.partnersRequestDoc.html @@ -3,4 +3,4 @@
    • token: string

      Partners token.

    • Optional variables: TVariables

      GraphQL variables to pass to the query.

    • Returns Promise<TResult>

      The response of the query of generic type .

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_rest_api_throttler.delayAwareRetry.html b/docs/api/cli-kit/functions/node_api_rest_api_throttler.delayAwareRetry.html index c630914377f..57081d40f8b 100644 --- a/docs/api/cli-kit/functions/node_api_rest_api_throttler.delayAwareRetry.html +++ b/docs/api/cli-kit/functions/node_api_rest_api_throttler.delayAwareRetry.html @@ -4,4 +4,4 @@

      Returns Promise<RestResponse>

      • The response of the operation.
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_rest_api_throttler.throttle.html b/docs/api/cli-kit/functions/node_api_rest_api_throttler.throttle.html index 64de93edd06..d80f561f1a6 100644 --- a/docs/api/cli-kit/functions/node_api_rest_api_throttler.throttle.html +++ b/docs/api/cli-kit/functions/node_api_rest_api_throttler.throttle.html @@ -4,4 +4,4 @@
        • (): T
        • Returns T

      Returns Promise<T>

      • The result of the request, once it eventually runs.
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_rest_api_throttler.updateApiCallLimitFromResponse.html b/docs/api/cli-kit/functions/node_api_rest_api_throttler.updateApiCallLimitFromResponse.html index 7406b511e83..57dad63f26d 100644 --- a/docs/api/cli-kit/functions/node_api_rest_api_throttler.updateApiCallLimitFromResponse.html +++ b/docs/api/cli-kit/functions/node_api_rest_api_throttler.updateApiCallLimitFromResponse.html @@ -1,3 +1,3 @@ updateApiCallLimitFromResponse | @shopify/cli-kit
      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_api_webhooks.webhooksRequest.html b/docs/api/cli-kit/functions/node_api_webhooks.webhooksRequest.html new file mode 100644 index 00000000000..b8c95dfd0f2 --- /dev/null +++ b/docs/api/cli-kit/functions/node_api_webhooks.webhooksRequest.html @@ -0,0 +1,8 @@ +webhooksRequest | @shopify/cli-kit
      • Executes an org-scoped GraphQL query against the App Management API. +Uses typed documents.

        +

        Type Parameters

        • TResult
        • TVariables extends Variables

        Parameters

        • organizationId: string

          Organization ID required to check permissions.

          +
        • query: TypedDocumentNode<TResult, TVariables>

          GraphQL query to execute.

          +
        • token: string

          Partners token.

          +
        • Optional variables: TVariables

          GraphQL variables to pass to the query.

          +

        Returns Promise<TResult>

        The response of the query of generic type .

        +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_archiver.zip.html b/docs/api/cli-kit/functions/node_archiver.zip.html index 8a7ca4edeb3..22e3571c07f 100644 --- a/docs/api/cli-kit/functions/node_archiver.zip.html +++ b/docs/api/cli-kit/functions/node_archiver.zip.html @@ -2,4 +2,4 @@ Even with forward-slash paths, zip files should still be able to be opened on Windows.

      Parameters

      • options: ZipOptions

        ZipOptions.

        -

      Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_base_command.addFromParsedFlags.html b/docs/api/cli-kit/functions/node_base_command.addFromParsedFlags.html index 3ef6381df5c..5cdca20ec01 100644 --- a/docs/api/cli-kit/functions/node_base_command.addFromParsedFlags.html +++ b/docs/api/cli-kit/functions/node_base_command.addFromParsedFlags.html @@ -1 +1 @@ -addFromParsedFlags | @shopify/cli-kit
      \ No newline at end of file +addFromParsedFlags | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_cli.clearCache.html b/docs/api/cli-kit/functions/node_cli.clearCache.html index 3c3a397fce0..bb48b18f094 100644 --- a/docs/api/cli-kit/functions/node_cli.clearCache.html +++ b/docs/api/cli-kit/functions/node_cli.clearCache.html @@ -1,2 +1,2 @@ clearCache | @shopify/cli-kit
      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_cli.localCliPackage.html b/docs/api/cli-kit/functions/node_cli.localCliPackage.html deleted file mode 100644 index 09cd567ac73..00000000000 --- a/docs/api/cli-kit/functions/node_cli.localCliPackage.html +++ /dev/null @@ -1 +0,0 @@ -localCliPackage | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_cli.runCLI.html b/docs/api/cli-kit/functions/node_cli.runCLI.html index 0f581c8ef91..27dece879c0 100644 --- a/docs/api/cli-kit/functions/node_cli.runCLI.html +++ b/docs/api/cli-kit/functions/node_cli.runCLI.html @@ -1,4 +1,4 @@ -runCLI | @shopify/cli-kit
      • A function that abstracts away setting up the environment and running +runCLI | @shopify/cli-kit

        • A function that abstracts away setting up the environment and running a CLI

          -

          Parameters

          • options: RunCLIOptions

            Options.

            -

          Returns Promise<void>

        \ No newline at end of file +

        Parameters

        • options: RunCLIOptions & {
              runInCreateMode?: boolean;
          }

          Options.

          +
        • launchCLI: ((options) => Promise<void>) = defaultLaunchCli
            • (options): Promise<void>
            • Parameters

              • options: {
                    moduleURL: string;
                }
                • moduleURL: string

              Returns Promise<void>

        • argv: string[] = process.argv
        • env: ProcessEnv = process.env
        • versions: ProcessVersions = process.versions

        Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_cli.runCreateCLI.html b/docs/api/cli-kit/functions/node_cli.runCreateCLI.html index 843d72f9d86..ff0ef89ce92 100644 --- a/docs/api/cli-kit/functions/node_cli.runCreateCLI.html +++ b/docs/api/cli-kit/functions/node_cli.runCreateCLI.html @@ -1,2 +1,2 @@ -runCreateCLI | @shopify/cli-kit
      • A function for create-x CLIs that automatically runs the "init" command.

        -

        Parameters

        • options: RunCLIOptions

        Returns Promise<void>

      \ No newline at end of file +runCreateCLI | @shopify/cli-kit
      • A function for create-x CLIs that automatically runs the "init" command.

        +

        Parameters

        • options: RunCLIOptions
        • launchCLI: ((options) => Promise<void>) = defaultLaunchCli
            • (options): Promise<void>
            • Parameters

              • options: {
                    moduleURL: string;
                }
                • moduleURL: string

              Returns Promise<void>

        • argv: string[] = process.argv
        • env: ProcessEnv = process.env
        • versions: ProcessVersions = process.versions

        Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_cli.useLocalCLIIfDetected.html b/docs/api/cli-kit/functions/node_cli.useLocalCLIIfDetected.html deleted file mode 100644 index e7d99ffc9a4..00000000000 --- a/docs/api/cli-kit/functions/node_cli.useLocalCLIIfDetected.html +++ /dev/null @@ -1 +0,0 @@ -useLocalCLIIfDetected | @shopify/cli-kit

      Function useLocalCLIIfDetected

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_cli_launcher.launchCLI.html b/docs/api/cli-kit/functions/node_cli_launcher.launchCLI.html new file mode 100644 index 00000000000..62e2944744a --- /dev/null +++ b/docs/api/cli-kit/functions/node_cli_launcher.launchCLI.html @@ -0,0 +1,4 @@ +launchCLI | @shopify/cli-kit
      • Launches the CLI through our custom OCLIF loader.

        +

        Parameters

        • options: Options

          Options.

          +

        Returns Promise<void>

        A promise that resolves when the CLI has been launched.

        +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_fqdn.appManagementFqdn.html b/docs/api/cli-kit/functions/node_context_fqdn.appManagementFqdn.html index 067a2b1f6d8..a87d347da09 100644 --- a/docs/api/cli-kit/functions/node_context_fqdn.appManagementFqdn.html +++ b/docs/api/cli-kit/functions/node_context_fqdn.appManagementFqdn.html @@ -1,3 +1,3 @@ appManagementFqdn | @shopify/cli-kit
      • It returns the App Management API service we should interact with.

        Returns Promise<string>

        Fully-qualified domain of the App Management service we should interact with.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_fqdn.businessPlatformFqdn.html b/docs/api/cli-kit/functions/node_context_fqdn.businessPlatformFqdn.html index a60e7a953f9..30bc5f0e943 100644 --- a/docs/api/cli-kit/functions/node_context_fqdn.businessPlatformFqdn.html +++ b/docs/api/cli-kit/functions/node_context_fqdn.businessPlatformFqdn.html @@ -1,3 +1,3 @@ businessPlatformFqdn | @shopify/cli-kit
      • It returns the BusinessPlatform' API service we should interact with.

        Returns Promise<string>

        Fully-qualified domain of the partners service we should interact with.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_fqdn.developerDashboardFqdn.html b/docs/api/cli-kit/functions/node_context_fqdn.developerDashboardFqdn.html index e6d5310d13a..35a83e20a15 100644 --- a/docs/api/cli-kit/functions/node_context_fqdn.developerDashboardFqdn.html +++ b/docs/api/cli-kit/functions/node_context_fqdn.developerDashboardFqdn.html @@ -1,3 +1,3 @@ developerDashboardFqdn | @shopify/cli-kit
      • It returns the Developer Dashboard domain we should interact with.

        Returns Promise<string>

        Fully-qualified domain of the Developer Dashboard we should interact with.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_fqdn.identityFqdn.html b/docs/api/cli-kit/functions/node_context_fqdn.identityFqdn.html index 36d50236900..0ce556b43b4 100644 --- a/docs/api/cli-kit/functions/node_context_fqdn.identityFqdn.html +++ b/docs/api/cli-kit/functions/node_context_fqdn.identityFqdn.html @@ -1,3 +1,3 @@ identityFqdn | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_fqdn.normalizeStoreFqdn.html b/docs/api/cli-kit/functions/node_context_fqdn.normalizeStoreFqdn.html index 4727e29e0e1..fd7488c6942 100644 --- a/docs/api/cli-kit/functions/node_context_fqdn.normalizeStoreFqdn.html +++ b/docs/api/cli-kit/functions/node_context_fqdn.normalizeStoreFqdn.html @@ -3,4 +3,4 @@ It will add the spin domain if it's not present and we're in a Spin environment.

      Parameters

      • store: string

        Store name.

      Returns Promise<string>

      Normalized store name.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_fqdn.partnersFqdn.html b/docs/api/cli-kit/functions/node_context_fqdn.partnersFqdn.html index c498d2b797b..beea285c866 100644 --- a/docs/api/cli-kit/functions/node_context_fqdn.partnersFqdn.html +++ b/docs/api/cli-kit/functions/node_context_fqdn.partnersFqdn.html @@ -1,3 +1,3 @@ partnersFqdn | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.alwaysLogAnalytics.html b/docs/api/cli-kit/functions/node_context_local.alwaysLogAnalytics.html index f2e296de685..47af77c94f8 100644 --- a/docs/api/cli-kit/functions/node_context_local.alwaysLogAnalytics.html +++ b/docs/api/cli-kit/functions/node_context_local.alwaysLogAnalytics.html @@ -1,4 +1,4 @@ alwaysLogAnalytics | @shopify/cli-kit
      • Returns true if reporting analytics should always happen, regardless of DEBUG mode etc.

        Parameters

        • env: ProcessEnv = process.env

          The environment variables from the environment of the current process.

        Returns boolean

        True if SHOPIFY_CLI_ALWAYS_LOG_ANALYTICS is truthy.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.alwaysLogMetrics.html b/docs/api/cli-kit/functions/node_context_local.alwaysLogMetrics.html index ec4539d32dc..6be357ad08b 100644 --- a/docs/api/cli-kit/functions/node_context_local.alwaysLogMetrics.html +++ b/docs/api/cli-kit/functions/node_context_local.alwaysLogMetrics.html @@ -1,4 +1,4 @@ alwaysLogMetrics | @shopify/cli-kit
      • Returns true if reporting metrics should always happen, regardless of DEBUG mode etc.

        Parameters

        • env: ProcessEnv = process.env

          The environment variables from the environment of the current process.

        Returns boolean

        True if SHOPIFY_CLI_ALWAYS_LOG_METRICS is truthy.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.analyticsDisabled.html b/docs/api/cli-kit/functions/node_context_local.analyticsDisabled.html index 2e915645bbb..c80bc05d402 100644 --- a/docs/api/cli-kit/functions/node_context_local.analyticsDisabled.html +++ b/docs/api/cli-kit/functions/node_context_local.analyticsDisabled.html @@ -1,4 +1,4 @@ analyticsDisabled | @shopify/cli-kit
      • Returns true if reporting analytics is enabled.

        Parameters

        • env: ProcessEnv = process.env

          The environment variables from the environment of the current process.

        Returns boolean

        True unless SHOPIFY_CLI_NO_ANALYTICS is truthy or debug mode is enabled.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.ciPlatform.html b/docs/api/cli-kit/functions/node_context_local.ciPlatform.html index 556d4a74d28..d2f1d8b8c18 100644 --- a/docs/api/cli-kit/functions/node_context_local.ciPlatform.html +++ b/docs/api/cli-kit/functions/node_context_local.ciPlatform.html @@ -1,4 +1,4 @@ ciPlatform | @shopify/cli-kit
      • Gets info on the CI platform the CLI is running on, if applicable.

        Parameters

        • env: ProcessEnv = process.env

          The environment variables from the environment of the current process.

        Returns {
            isCI: true;
            metadata: Metadata;
            name: string;
        } | {
            isCI: false;
            metadata?: undefined;
            name?: undefined;
        }

        The CI platform info.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.cloudEnvironment.html b/docs/api/cli-kit/functions/node_context_local.cloudEnvironment.html index 5dc99e2f949..a47bf59a01c 100644 --- a/docs/api/cli-kit/functions/node_context_local.cloudEnvironment.html +++ b/docs/api/cli-kit/functions/node_context_local.cloudEnvironment.html @@ -2,4 +2,4 @@ them. Platform name 'localhost' is returned otherwise.

      Parameters

      • env: ProcessEnv = process.env

        Environment variables used when the cli is launched.

      Returns {
          editor: boolean;
          platform: "spin" | "codespaces" | "gitpod" | "cloudShell" | "localhost";
      }

      Cloud platform information.

      -
      • editor: boolean
      • platform: "spin" | "codespaces" | "gitpod" | "cloudShell" | "localhost"
      \ No newline at end of file +
      • editor: boolean
      • platform: "spin" | "codespaces" | "gitpod" | "cloudShell" | "localhost"
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.codespacePortForwardingDomain.html b/docs/api/cli-kit/functions/node_context_local.codespacePortForwardingDomain.html index 58c879a0fe1..7fdca2672fd 100644 --- a/docs/api/cli-kit/functions/node_context_local.codespacePortForwardingDomain.html +++ b/docs/api/cli-kit/functions/node_context_local.codespacePortForwardingDomain.html @@ -2,4 +2,4 @@ Https://docs.github.com/en/codespaces/developing-in-codespaces/default-environment-variables-for-your-codespace#list-of-default-environment-variables.

      Parameters

      • env: ProcessEnv = process.env

        The environment variables from the environment of the current process.

      Returns string | undefined

      The codespace port forwarding domain.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.codespaceURL.html b/docs/api/cli-kit/functions/node_context_local.codespaceURL.html index f4d7c60e5fe..6fbcf0d5bab 100644 --- a/docs/api/cli-kit/functions/node_context_local.codespaceURL.html +++ b/docs/api/cli-kit/functions/node_context_local.codespaceURL.html @@ -2,4 +2,4 @@ Https://docs.github.com/en/codespaces/developing-in-codespaces/default-environment-variables-for-your-codespace#list-of-default-environment-variables.

      Parameters

      • env: ProcessEnv = process.env

        The environment variables from the environment of the current process.

      Returns string | undefined

      The codespace URL.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.firstPartyDev.html b/docs/api/cli-kit/functions/node_context_local.firstPartyDev.html index 63039fabf24..3dc094aabe5 100644 --- a/docs/api/cli-kit/functions/node_context_local.firstPartyDev.html +++ b/docs/api/cli-kit/functions/node_context_local.firstPartyDev.html @@ -1,4 +1,4 @@ firstPartyDev | @shopify/cli-kit
      • Returns true if the CLI User is 1P.

        Parameters

        • env: ProcessEnv = process.env

          The environment variables from the environment of the current process.

        Returns boolean

        True if SHOPIFY_CLI_1P is truthy.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.gitpodURL.html b/docs/api/cli-kit/functions/node_context_local.gitpodURL.html index e717c3e9b15..d616221194e 100644 --- a/docs/api/cli-kit/functions/node_context_local.gitpodURL.html +++ b/docs/api/cli-kit/functions/node_context_local.gitpodURL.html @@ -2,4 +2,4 @@ Https://www.gitpod.io/docs/environment-variables#default-environment-variables.

      Parameters

      • env: ProcessEnv = process.env

        The environment variables from the environment of the current process.

      Returns string | undefined

      The gitpod URL.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.hasGit.html b/docs/api/cli-kit/functions/node_context_local.hasGit.html index ea8f47f702c..60b9f48efe1 100644 --- a/docs/api/cli-kit/functions/node_context_local.hasGit.html +++ b/docs/api/cli-kit/functions/node_context_local.hasGit.html @@ -1,3 +1,3 @@ hasGit | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.homeDirectory.html b/docs/api/cli-kit/functions/node_context_local.homeDirectory.html index 025d8a1abc4..b7ff91228d1 100644 --- a/docs/api/cli-kit/functions/node_context_local.homeDirectory.html +++ b/docs/api/cli-kit/functions/node_context_local.homeDirectory.html @@ -1,3 +1,3 @@ homeDirectory | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.isAppManagementEnabled.html b/docs/api/cli-kit/functions/node_context_local.isAppManagementEnabled.html new file mode 100644 index 00000000000..f49d9a6a52c --- /dev/null +++ b/docs/api/cli-kit/functions/node_context_local.isAppManagementEnabled.html @@ -0,0 +1,4 @@ +isAppManagementEnabled | @shopify/cli-kit
      • It returns true if the App Management API is available.

        +

        Parameters

        • env: ProcessEnv = process.env

          The environment variables from the environment of the current process.

          +

        Returns boolean

        True if the App Management API is available.

        +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.isCloudEnvironment.html b/docs/api/cli-kit/functions/node_context_local.isCloudEnvironment.html index ea70d284cc1..884b5bd37a8 100644 --- a/docs/api/cli-kit/functions/node_context_local.isCloudEnvironment.html +++ b/docs/api/cli-kit/functions/node_context_local.isCloudEnvironment.html @@ -1,4 +1,4 @@ isCloudEnvironment | @shopify/cli-kit
      • Checks if the CLI is run from a cloud environment.

        Parameters

        • env: ProcessEnv = process.env

          Environment variables used when the cli is launched.

        Returns boolean

        True in case the CLI is run from a cloud environment.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.isDevelopment.html b/docs/api/cli-kit/functions/node_context_local.isDevelopment.html index f193de4533f..2b3531d02ab 100644 --- a/docs/api/cli-kit/functions/node_context_local.isDevelopment.html +++ b/docs/api/cli-kit/functions/node_context_local.isDevelopment.html @@ -1,4 +1,4 @@ isDevelopment | @shopify/cli-kit
      • Returns true if the CLI is running in debug mode.

        Parameters

        • env: ProcessEnv = process.env

          The environment variables from the environment of the current process.

        Returns boolean

        True if SHOPIFY_ENV is development.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.isShopify.html b/docs/api/cli-kit/functions/node_context_local.isShopify.html index 7fae39c0537..be16ed54065 100644 --- a/docs/api/cli-kit/functions/node_context_local.isShopify.html +++ b/docs/api/cli-kit/functions/node_context_local.isShopify.html @@ -2,4 +2,4 @@ a local environment (where dev is present) or a cloud environment (spin).

      Parameters

      • env: ProcessEnv = process.env

        The environment variables from the environment of the current process.

      Returns Promise<boolean>

      True if the CLI is used in a Shopify environment.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.isTerminalInteractive.html b/docs/api/cli-kit/functions/node_context_local.isTerminalInteractive.html index 2459358ebcb..9b518e321a1 100644 --- a/docs/api/cli-kit/functions/node_context_local.isTerminalInteractive.html +++ b/docs/api/cli-kit/functions/node_context_local.isTerminalInteractive.html @@ -1,3 +1,3 @@ isTerminalInteractive | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.isUnitTest.html b/docs/api/cli-kit/functions/node_context_local.isUnitTest.html index da480f7a970..c10d8f10955 100644 --- a/docs/api/cli-kit/functions/node_context_local.isUnitTest.html +++ b/docs/api/cli-kit/functions/node_context_local.isUnitTest.html @@ -3,4 +3,4 @@ the standard streams.

      Parameters

      • env: ProcessEnv = process.env

        The environment variables from the environment of the current process.

      Returns boolean

      True if the SHOPIFY_UNIT_TEST environment variable is truthy.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.isVerbose.html b/docs/api/cli-kit/functions/node_context_local.isVerbose.html index 9beacffa423..2449edcb89d 100644 --- a/docs/api/cli-kit/functions/node_context_local.isVerbose.html +++ b/docs/api/cli-kit/functions/node_context_local.isVerbose.html @@ -1,4 +1,4 @@ isVerbose | @shopify/cli-kit
      • Returns true if the CLI is running in verbose mode.

        Parameters

        • env: ProcessEnv = process.env

          The environment variables from the environment of the current process.

        Returns boolean

        True if SHOPIFY_FLAG_VERBOSE is truthy or the flag --verbose has been passed.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.macAddress.html b/docs/api/cli-kit/functions/node_context_local.macAddress.html index ed4bf200247..2b100091b55 100644 --- a/docs/api/cli-kit/functions/node_context_local.macAddress.html +++ b/docs/api/cli-kit/functions/node_context_local.macAddress.html @@ -1,3 +1,3 @@ macAddress | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.opentelemetryDomain.html b/docs/api/cli-kit/functions/node_context_local.opentelemetryDomain.html index 93f2d6b7b09..c024895fa1d 100644 --- a/docs/api/cli-kit/functions/node_context_local.opentelemetryDomain.html +++ b/docs/api/cli-kit/functions/node_context_local.opentelemetryDomain.html @@ -2,4 +2,4 @@

      It can be overridden via the SHOPIFY_CLI_OTEL_EXPORTER_OTLP_ENDPOINT environment variable.

      Parameters

      • env: ProcessEnv = process.env

        The environment variables from the environment of the current process.

      Returns string | undefined

      The domain to send OTEL metrics to.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.themeToken.html b/docs/api/cli-kit/functions/node_context_local.themeToken.html index d56396e80ef..3034330b06d 100644 --- a/docs/api/cli-kit/functions/node_context_local.themeToken.html +++ b/docs/api/cli-kit/functions/node_context_local.themeToken.html @@ -1,4 +1,4 @@ themeToken | @shopify/cli-kit
      • The token used to run a theme command with a custom password.

        Parameters

        • env: ProcessEnv = process.env

          Environment variables used when the cli is launched.

        Returns string | undefined

        A string with the token.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.useEmbeddedThemeCLI.html b/docs/api/cli-kit/functions/node_context_local.useEmbeddedThemeCLI.html index 6a6d6782ee0..0d2f724cc5f 100644 --- a/docs/api/cli-kit/functions/node_context_local.useEmbeddedThemeCLI.html +++ b/docs/api/cli-kit/functions/node_context_local.useEmbeddedThemeCLI.html @@ -1,4 +1,4 @@ useEmbeddedThemeCLI | @shopify/cli-kit
      • Returns true if the embedded CLI will be used for theme commands.

        Parameters

        • env: ProcessEnv = process.env

          The environment variables from the environment of the current process.

        Returns boolean

        False if SHOPIFY_CLI_BUNDLED_THEME_CLI is truthy.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_local.useThemebundling.html b/docs/api/cli-kit/functions/node_context_local.useThemebundling.html index 0014f77644e..4bc4562a6e3 100644 --- a/docs/api/cli-kit/functions/node_context_local.useThemebundling.html +++ b/docs/api/cli-kit/functions/node_context_local.useThemebundling.html @@ -1,4 +1,4 @@ useThemebundling | @shopify/cli-kit
      • Returns true if the CLI should use theme bundling.

        Parameters

        • env: ProcessEnv = process.env

          The environment variables from the environment of the current process.

        Returns boolean

        False if SHOPIFY_CLI_NO_THEME_BUNDLING is truthy.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_spin.appHost.html b/docs/api/cli-kit/functions/node_context_spin.appHost.html index 1bac1d371aa..37f8dad7cc3 100644 --- a/docs/api/cli-kit/functions/node_context_spin.appHost.html +++ b/docs/api/cli-kit/functions/node_context_spin.appHost.html @@ -1,4 +1,4 @@ appHost | @shopify/cli-kit
      • Returns the value of the SPIN_APP_HOST environment variable.

        Parameters

        • env: ProcessEnv = process.env

          Environment variables.

        Returns string | undefined

        The value of the SPIN_APP_HOST environment variable.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_spin.appPort.html b/docs/api/cli-kit/functions/node_context_spin.appPort.html index b7e969def88..06086a83434 100644 --- a/docs/api/cli-kit/functions/node_context_spin.appPort.html +++ b/docs/api/cli-kit/functions/node_context_spin.appPort.html @@ -1,4 +1,4 @@ appPort | @shopify/cli-kit
      • Returns the value of the SERVER_PORT environment variable.

        Parameters

        • env: ProcessEnv = process.env

          Environment variables.

        Returns number | undefined

        The value of the SERVER_PORT environment variable.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_spin.fetchSpinPort.html b/docs/api/cli-kit/functions/node_context_spin.fetchSpinPort.html index b00e188871f..76c7bd0a0b0 100644 --- a/docs/api/cli-kit/functions/node_context_spin.fetchSpinPort.html +++ b/docs/api/cli-kit/functions/node_context_spin.fetchSpinPort.html @@ -3,4 +3,4 @@
    • portEnvName: string

      The name of the environment variable to fetch the port from.

    • basePath: string = '/run'

      The base path to look for the port file.

    • Returns Promise<number | undefined>

      The port number or undefined if the port could not be found.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_spin.instance.html b/docs/api/cli-kit/functions/node_context_spin.instance.html index ff37929d393..d7805a287cc 100644 --- a/docs/api/cli-kit/functions/node_context_spin.instance.html +++ b/docs/api/cli-kit/functions/node_context_spin.instance.html @@ -1,4 +1,4 @@ instance | @shopify/cli-kit
      • Returns the value of the SPIN_INSTANCE environment variable.

        Parameters

        • env: ProcessEnv = process.env

          Environment variables.

        Returns string | undefined

        The value of the SPIN_INSTANCE environment variable.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_spin.isSpin.html b/docs/api/cli-kit/functions/node_context_spin.isSpin.html index 25c61ede84e..9a287c9c179 100644 --- a/docs/api/cli-kit/functions/node_context_spin.isSpin.html +++ b/docs/api/cli-kit/functions/node_context_spin.isSpin.html @@ -1,4 +1,4 @@ isSpin | @shopify/cli-kit
      • Returns true if the CLI is running in a Spin environment.

        Parameters

        • env: ProcessEnv = process.env

          Environment variables.

        Returns boolean

        True if the CLI is running in a Spin environment.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_spin.isSpinEnvironment.html b/docs/api/cli-kit/functions/node_context_spin.isSpinEnvironment.html index f63dd60a689..b43f1eb74d9 100644 --- a/docs/api/cli-kit/functions/node_context_spin.isSpinEnvironment.html +++ b/docs/api/cli-kit/functions/node_context_spin.isSpinEnvironment.html @@ -1,4 +1,4 @@ isSpinEnvironment | @shopify/cli-kit
      • Returns true if the CLI is running in a Spin environment.

        Parameters

        • env: ProcessEnv = process.env

          Environment variables.

        Returns boolean

        True if the CLI is running in a Spin environment.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_spin.show.html b/docs/api/cli-kit/functions/node_context_spin.show.html index 5e70ae4b677..5c9649136ef 100644 --- a/docs/api/cli-kit/functions/node_context_spin.show.html +++ b/docs/api/cli-kit/functions/node_context_spin.show.html @@ -3,4 +3,4 @@
    • env: ProcessEnv = process.env

      Environment variables.

    • Returns Promise<{
          fqdn: string;
      }>

      The JSON-parsed output of the Spin CLI.

      Throws

      Any error raised from the underlying Spin CLI.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_spin.spinFqdn.html b/docs/api/cli-kit/functions/node_context_spin.spinFqdn.html index 15302d334ff..b69c87dd02b 100644 --- a/docs/api/cli-kit/functions/node_context_spin.spinFqdn.html +++ b/docs/api/cli-kit/functions/node_context_spin.spinFqdn.html @@ -3,4 +3,4 @@ To avoid multiple calls to readSync or show.

      Parameters

      • env: ProcessEnv = process.env

        Environment variables.

      Returns Promise<string>

      Fqdn of the Spin environment.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_context_utilities.isTruthy.html b/docs/api/cli-kit/functions/node_context_utilities.isTruthy.html index 9495154d2ea..0087bfec5a4 100644 --- a/docs/api/cli-kit/functions/node_context_utilities.isTruthy.html +++ b/docs/api/cli-kit/functions/node_context_utilities.isTruthy.html @@ -1,4 +1,4 @@ isTruthy | @shopify/cli-kit
      • Returns whether an environment variable value represents a truthy value.

        Parameters

        • variable: undefined | string

          Environment variable value to check.

        Returns boolean

        True when the value is truthy, e.g. '1', 'true', etc.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_crypto.base64URLEncode.html b/docs/api/cli-kit/functions/node_crypto.base64URLEncode.html index b2035154949..26dddaf8bf7 100644 --- a/docs/api/cli-kit/functions/node_crypto.base64URLEncode.html +++ b/docs/api/cli-kit/functions/node_crypto.base64URLEncode.html @@ -1,4 +1,4 @@ base64URLEncode | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_crypto.fileHash.html b/docs/api/cli-kit/functions/node_crypto.fileHash.html index 0653512b53c..aa5f72c4cdb 100644 --- a/docs/api/cli-kit/functions/node_crypto.fileHash.html +++ b/docs/api/cli-kit/functions/node_crypto.fileHash.html @@ -1,4 +1,4 @@ fileHash | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_crypto.hashString.html b/docs/api/cli-kit/functions/node_crypto.hashString.html index 61da35fd206..a2bb4924144 100644 --- a/docs/api/cli-kit/functions/node_crypto.hashString.html +++ b/docs/api/cli-kit/functions/node_crypto.hashString.html @@ -1,4 +1,4 @@ hashString | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_crypto.nonRandomUUID.html b/docs/api/cli-kit/functions/node_crypto.nonRandomUUID.html index 45cb9e0daa7..ce2ac5905d2 100644 --- a/docs/api/cli-kit/functions/node_crypto.nonRandomUUID.html +++ b/docs/api/cli-kit/functions/node_crypto.nonRandomUUID.html @@ -3,4 +3,4 @@ across different runs of the CLI.

      Parameters

      • subject: string

        The subject to generate the UUID from.

      Returns string

      A non-random UUID string.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_crypto.randomBytes.html b/docs/api/cli-kit/functions/node_crypto.randomBytes.html index 668f21abf8b..2e97e0a6287 100644 --- a/docs/api/cli-kit/functions/node_crypto.randomBytes.html +++ b/docs/api/cli-kit/functions/node_crypto.randomBytes.html @@ -1,4 +1,4 @@ randomBytes | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_crypto.randomHex.html b/docs/api/cli-kit/functions/node_crypto.randomHex.html index 0d03e1a6dea..efd047291fa 100644 --- a/docs/api/cli-kit/functions/node_crypto.randomHex.html +++ b/docs/api/cli-kit/functions/node_crypto.randomHex.html @@ -1,4 +1,4 @@ randomHex | @shopify/cli-kit
      • Generate a random string in Hex format of the provided size.

        Parameters

        • size: number

          Number of bytes to be generated.

        Returns string

        A random string in Hex format.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_crypto.randomUUID.html b/docs/api/cli-kit/functions/node_crypto.randomUUID.html index 8cbf94fb0ac..4c6a76c6374 100644 --- a/docs/api/cli-kit/functions/node_crypto.randomUUID.html +++ b/docs/api/cli-kit/functions/node_crypto.randomUUID.html @@ -1,3 +1,3 @@ randomUUID | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_crypto.sha256.html b/docs/api/cli-kit/functions/node_crypto.sha256.html index 56d1705ac2d..201c0da8ac6 100644 --- a/docs/api/cli-kit/functions/node_crypto.sha256.html +++ b/docs/api/cli-kit/functions/node_crypto.sha256.html @@ -1,4 +1,4 @@ sha256 | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_dot_env.createDotEnvFileLine.html b/docs/api/cli-kit/functions/node_dot_env.createDotEnvFileLine.html index f780136c96c..62c7b38ce3f 100644 --- a/docs/api/cli-kit/functions/node_dot_env.createDotEnvFileLine.html +++ b/docs/api/cli-kit/functions/node_dot_env.createDotEnvFileLine.html @@ -1 +1 @@ -createDotEnvFileLine | @shopify/cli-kit
      \ No newline at end of file +createDotEnvFileLine | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_dot_env.patchEnvFile.html b/docs/api/cli-kit/functions/node_dot_env.patchEnvFile.html index c11f86703a6..d2719111044 100644 --- a/docs/api/cli-kit/functions/node_dot_env.patchEnvFile.html +++ b/docs/api/cli-kit/functions/node_dot_env.patchEnvFile.html @@ -2,4 +2,4 @@ without removing already existing lines.

      Parameters

      • envFileContent: null | string

        .env file contents.

      • updatedValues: {
            [key: string]: string | undefined;
        }

        object containing new env variables values.

        -
        • [key: string]: string | undefined

      Returns string

      \ No newline at end of file +
      • [key: string]: string | undefined

      Returns string

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_dot_env.readAndParseDotEnv.html b/docs/api/cli-kit/functions/node_dot_env.readAndParseDotEnv.html index d9298d6c359..7cca71bd84d 100644 --- a/docs/api/cli-kit/functions/node_dot_env.readAndParseDotEnv.html +++ b/docs/api/cli-kit/functions/node_dot_env.readAndParseDotEnv.html @@ -1,4 +1,4 @@ readAndParseDotEnv | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_dot_env.writeDotEnv.html b/docs/api/cli-kit/functions/node_dot_env.writeDotEnv.html index 5c0550c17ab..f3fa275cfba 100644 --- a/docs/api/cli-kit/functions/node_dot_env.writeDotEnv.html +++ b/docs/api/cli-kit/functions/node_dot_env.writeDotEnv.html @@ -1,3 +1,3 @@ writeDotEnv | @shopify/cli-kit
      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_environment.getBackendPort.html b/docs/api/cli-kit/functions/node_environment.getBackendPort.html index a61bb81ad3a..6ae3ca84f41 100644 --- a/docs/api/cli-kit/functions/node_environment.getBackendPort.html +++ b/docs/api/cli-kit/functions/node_environment.getBackendPort.html @@ -1,3 +1,3 @@ getBackendPort | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_environment.getEnvironmentVariables.html b/docs/api/cli-kit/functions/node_environment.getEnvironmentVariables.html index 7c5cb71eefc..d28d7dd9c00 100644 --- a/docs/api/cli-kit/functions/node_environment.getEnvironmentVariables.html +++ b/docs/api/cli-kit/functions/node_environment.getEnvironmentVariables.html @@ -4,4 +4,4 @@ global variable which is discouraged via the no-process-env ESLint rule.

      Returns NodeJS.ProcessEnv

      Current process environment variables.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_environment.getIdentityTokenInformation.html b/docs/api/cli-kit/functions/node_environment.getIdentityTokenInformation.html index abdbd9d5892..7419190a7c9 100644 --- a/docs/api/cli-kit/functions/node_environment.getIdentityTokenInformation.html +++ b/docs/api/cli-kit/functions/node_environment.getIdentityTokenInformation.html @@ -1,3 +1,3 @@ getIdentityTokenInformation | @shopify/cli-kit
      • Returns the information of the identity & refresh tokens, provided by environment variables.

        Returns {
            accessToken: string;
            refreshToken: string;
            userId: string;
        } | undefined

        The identity token information in case it exists.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_environment.getOrganization.html b/docs/api/cli-kit/functions/node_environment.getOrganization.html index 79033100f00..79493ec05af 100644 --- a/docs/api/cli-kit/functions/node_environment.getOrganization.html +++ b/docs/api/cli-kit/functions/node_environment.getOrganization.html @@ -1,3 +1,3 @@ getOrganization | @shopify/cli-kit
      • Returns the value of the organization id from the environment variables.

        Returns string | undefined

        True if the current proccess is running using the partners token.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_environment.getPartnersToken.html b/docs/api/cli-kit/functions/node_environment.getPartnersToken.html index a6df266090d..17271c94e7e 100644 --- a/docs/api/cli-kit/functions/node_environment.getPartnersToken.html +++ b/docs/api/cli-kit/functions/node_environment.getPartnersToken.html @@ -1,3 +1,3 @@ getPartnersToken | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_environment.jsonOutputEnabled.html b/docs/api/cli-kit/functions/node_environment.jsonOutputEnabled.html new file mode 100644 index 00000000000..ea0aa95818c --- /dev/null +++ b/docs/api/cli-kit/functions/node_environment.jsonOutputEnabled.html @@ -0,0 +1,4 @@ +jsonOutputEnabled | @shopify/cli-kit
      • Checks if the JSON output is enabled via flag (--json or -j) or environment variable (SHOPIFY_FLAG_JSON).

        +

        Parameters

        • environment: ProcessEnv = ...

          Process environment variables.

          +

        Returns boolean

        True if the JSON output is enabled, false otherwise.

        +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_environment.usePartnersToken.html b/docs/api/cli-kit/functions/node_environment.usePartnersToken.html index df5898988ef..be0aaecd1d8 100644 --- a/docs/api/cli-kit/functions/node_environment.usePartnersToken.html +++ b/docs/api/cli-kit/functions/node_environment.usePartnersToken.html @@ -1,3 +1,3 @@ usePartnersToken | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_environments.loadEnvironment.html b/docs/api/cli-kit/functions/node_environments.loadEnvironment.html index a687f6f4002..e0f073971f0 100644 --- a/docs/api/cli-kit/functions/node_environments.loadEnvironment.html +++ b/docs/api/cli-kit/functions/node_environments.loadEnvironment.html @@ -1,3 +1,3 @@ loadEnvironment | @shopify/cli-kit
      • Loads environments from a file.

        Parameters

        • environmentName: string
        • fileName: string
        • Optional options: LoadEnvironmentOptions

        Returns Promise<JsonMap | undefined>

        The loaded environments.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_error.cleanSingleStackTracePath.html b/docs/api/cli-kit/functions/node_error.cleanSingleStackTracePath.html index 14d46f9c969..27d07f322bf 100644 --- a/docs/api/cli-kit/functions/node_error.cleanSingleStackTracePath.html +++ b/docs/api/cli-kit/functions/node_error.cleanSingleStackTracePath.html @@ -1,4 +1,4 @@ cleanSingleStackTracePath | @shopify/cli-kit

      Function cleanSingleStackTracePath

      • Stack traces usually have file:// - we strip that and also remove the Windows drive designation.

        Parameters

        • filePath: string

          Path to be cleaned.

        Returns string

        The cleaned path.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_error.errorMapper.html b/docs/api/cli-kit/functions/node_error.errorMapper.html index 8769a02c270..f4c8d79d774 100644 --- a/docs/api/cli-kit/functions/node_error.errorMapper.html +++ b/docs/api/cli-kit/functions/node_error.errorMapper.html @@ -1,4 +1,4 @@ errorMapper | @shopify/cli-kit
      • A function that maps an error to an Abort with the stack trace when coming from the CLI.

        Parameters

        • error: unknown

          Error to be mapped.

        Returns Promise<unknown>

        A promise that resolves with the new error object.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_error.handler.html b/docs/api/cli-kit/functions/node_error.handler.html index 21edf75fc04..433e6a937cb 100644 --- a/docs/api/cli-kit/functions/node_error.handler.html +++ b/docs/api/cli-kit/functions/node_error.handler.html @@ -1,4 +1,4 @@ handler | @shopify/cli-kit
      • A function that handles errors that blow up in the CLI.

        Parameters

        • error: unknown

          Error to be handled.

        Returns Promise<unknown>

        A promise that resolves with the error passed.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_error.shouldReportErrorAsUnexpected.html b/docs/api/cli-kit/functions/node_error.shouldReportErrorAsUnexpected.html index d5f344c9d1f..daa7df83347 100644 --- a/docs/api/cli-kit/functions/node_error.shouldReportErrorAsUnexpected.html +++ b/docs/api/cli-kit/functions/node_error.shouldReportErrorAsUnexpected.html @@ -1,4 +1,4 @@ shouldReportErrorAsUnexpected | @shopify/cli-kit

      Function shouldReportErrorAsUnexpected

      • A function that checks if an error should be reported as unexpected.

        Parameters

        • error: unknown

          Error to be checked.

        Returns boolean

        A boolean indicating if the error should be reported as unexpected.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_error_handler.addBugsnagMetadata.html b/docs/api/cli-kit/functions/node_error_handler.addBugsnagMetadata.html index 511fe966c55..0bd1cd22912 100644 --- a/docs/api/cli-kit/functions/node_error_handler.addBugsnagMetadata.html +++ b/docs/api/cli-kit/functions/node_error_handler.addBugsnagMetadata.html @@ -1 +1 @@ -addBugsnagMetadata | @shopify/cli-kit
      \ No newline at end of file +addBugsnagMetadata | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_error_handler.cleanStackFrameFilePath.html b/docs/api/cli-kit/functions/node_error_handler.cleanStackFrameFilePath.html index 2756821cad2..a4f673415e9 100644 --- a/docs/api/cli-kit/functions/node_error_handler.cleanStackFrameFilePath.html +++ b/docs/api/cli-kit/functions/node_error_handler.cleanStackFrameFilePath.html @@ -1,4 +1,4 @@ cleanStackFrameFilePath | @shopify/cli-kit
      • If the given file path is within a node_modules folder, remove prefix up to and including the node_modules folder.

        This gives us very consistent paths for errors generated by the CLI.

        -

        Parameters

        • __namedParameters: {
              currentFilePath: string;
              pluginLocations: {
                  name: string;
                  pluginPath: string;
              }[];
              projectRoot: string;
          }
          • currentFilePath: string
          • pluginLocations: {
                name: string;
                pluginPath: string;
            }[]
          • projectRoot: string

        Returns string

      \ No newline at end of file +

      Parameters

      • __namedParameters: {
            currentFilePath: string;
            pluginLocations: {
                name: string;
                pluginPath: string;
            }[];
            projectRoot: string;
        }
        • currentFilePath: string
        • pluginLocations: {
              name: string;
              pluginPath: string;
          }[]
        • projectRoot: string

      Returns string

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_error_handler.errorHandler.html b/docs/api/cli-kit/functions/node_error_handler.errorHandler.html index 9a58711d58e..deaf0f1c179 100644 --- a/docs/api/cli-kit/functions/node_error_handler.errorHandler.html +++ b/docs/api/cli-kit/functions/node_error_handler.errorHandler.html @@ -1 +1 @@ -errorHandler | @shopify/cli-kit
      \ No newline at end of file +errorHandler | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_error_handler.registerCleanBugsnagErrorsFromWithinPlugins.html b/docs/api/cli-kit/functions/node_error_handler.registerCleanBugsnagErrorsFromWithinPlugins.html index 765331d25f2..57360832628 100644 --- a/docs/api/cli-kit/functions/node_error_handler.registerCleanBugsnagErrorsFromWithinPlugins.html +++ b/docs/api/cli-kit/functions/node_error_handler.registerCleanBugsnagErrorsFromWithinPlugins.html @@ -1,2 +1,2 @@ registerCleanBugsnagErrorsFromWithinPlugins | @shopify/cli-kit

      Function registerCleanBugsnagErrorsFromWithinPlugins

      • Register a Bugsnag error listener to clean up stack traces for errors within plugin code.

        -

        Parameters

        • config: Config

        Returns Promise<void>

      \ No newline at end of file +

      Parameters

      • config: Config

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_error_handler.sendErrorToBugsnag.html b/docs/api/cli-kit/functions/node_error_handler.sendErrorToBugsnag.html index 826d8fd0540..2f6de672220 100644 --- a/docs/api/cli-kit/functions/node_error_handler.sendErrorToBugsnag.html +++ b/docs/api/cli-kit/functions/node_error_handler.sendErrorToBugsnag.html @@ -1,3 +1,3 @@ sendErrorToBugsnag | @shopify/cli-kit
      • Sends an error to Bugsnag. This is configured automatically for uncaught errors from CLI commands, but can also be used to manually record an error.

        Parameters

        Returns Promise<{
            error: unknown;
            reported: false;
            unhandled: unknown;
        } | {
            error: Error;
            reported: true;
            unhandled: boolean;
        }>

        the reported error (this may have been tweaked for better reporting), and a bool to indicate if the error was actually submitted or not

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_framework.resolveFramework.html b/docs/api/cli-kit/functions/node_framework.resolveFramework.html index 86d03af5c87..463a42e66f6 100644 --- a/docs/api/cli-kit/functions/node_framework.resolveFramework.html +++ b/docs/api/cli-kit/functions/node_framework.resolveFramework.html @@ -2,4 +2,4 @@ specific directory.

      Parameters

      • rootDirectory: string

        Directory from which the files required for each framework are searched

      Returns Promise<string>

      The name of the framework used or 'unknown' otherwise

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.appendFile.html b/docs/api/cli-kit/functions/node_fs.appendFile.html index a41ef98ad5b..d2eb43a40fb 100644 --- a/docs/api/cli-kit/functions/node_fs.appendFile.html +++ b/docs/api/cli-kit/functions/node_fs.appendFile.html @@ -1,4 +1,4 @@ appendFile | @shopify/cli-kit
      • Appnds content to file at path.

        Parameters

        • path: string

          Path to the file to be appended.

        • content: string

          Content to be appended.

          -

        Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.appendFileSync.html b/docs/api/cli-kit/functions/node_fs.appendFileSync.html index 0baeee58b44..4c3e759c17c 100644 --- a/docs/api/cli-kit/functions/node_fs.appendFileSync.html +++ b/docs/api/cli-kit/functions/node_fs.appendFileSync.html @@ -1,4 +1,4 @@ appendFileSync | @shopify/cli-kit
      • Synchronously appends content to file at path.

        Parameters

        • path: string

          Path to the file to be appended.

        • data: string

          Content to be appended.

          -

        Returns void

      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.chmod.html b/docs/api/cli-kit/functions/node_fs.chmod.html index ee709718f69..9039030ff2e 100644 --- a/docs/api/cli-kit/functions/node_fs.chmod.html +++ b/docs/api/cli-kit/functions/node_fs.chmod.html @@ -1,4 +1,4 @@ chmod | @shopify/cli-kit
      • Changes the permissions of a directory or file.

        Parameters

        • path: string

          Path to the file or directory whose permissions will be modified.

        • mode: string | number

          Permissions to set to the file or directory.

          -

        Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.copyFile.html b/docs/api/cli-kit/functions/node_fs.copyFile.html index e67d6b112fe..00a4cde1b33 100644 --- a/docs/api/cli-kit/functions/node_fs.copyFile.html +++ b/docs/api/cli-kit/functions/node_fs.copyFile.html @@ -1,4 +1,4 @@ copyFile | @shopify/cli-kit
      • Copies a file.

        Parameters

        • from: string

          Path to the directory or file to be copied.

        • to: string

          Destination path.

          -

        Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.createFileReadStream.html b/docs/api/cli-kit/functions/node_fs.createFileReadStream.html index d1858e0045a..f03010475d6 100644 --- a/docs/api/cli-kit/functions/node_fs.createFileReadStream.html +++ b/docs/api/cli-kit/functions/node_fs.createFileReadStream.html @@ -2,4 +2,4 @@

      Parameters

      • path: string

        Path to the file.

      • Optional options: {
            encoding?: BufferEncoding;
            end?: number;
            start?: number;
        }

        Options for the read stream.

        • Optional encoding?: BufferEncoding
        • Optional end?: number
        • Optional start?: number

      Returns ReadStream

      A read stream for the file.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.createFileWriteStream.html b/docs/api/cli-kit/functions/node_fs.createFileWriteStream.html index bbc931845d6..3642cfea122 100644 --- a/docs/api/cli-kit/functions/node_fs.createFileWriteStream.html +++ b/docs/api/cli-kit/functions/node_fs.createFileWriteStream.html @@ -1,4 +1,4 @@ createFileWriteStream | @shopify/cli-kit

      Function createFileWriteStream

      • Create a write stream for a file.

        Parameters

        • path: string

          Path to the file.

        Returns WriteStream

        A write stream for the file.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.fileExists.html b/docs/api/cli-kit/functions/node_fs.fileExists.html index 77e59b12956..48ac2b8679b 100644 --- a/docs/api/cli-kit/functions/node_fs.fileExists.html +++ b/docs/api/cli-kit/functions/node_fs.fileExists.html @@ -1,4 +1,4 @@ fileExists | @shopify/cli-kit
      • Returns true if a file or directory exists.

        Parameters

        • path: string

          Path to the directory or file.

        Returns Promise<boolean>

        True if it exists.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.fileExistsSync.html b/docs/api/cli-kit/functions/node_fs.fileExistsSync.html index a37180db01b..0b92811b7ca 100644 --- a/docs/api/cli-kit/functions/node_fs.fileExistsSync.html +++ b/docs/api/cli-kit/functions/node_fs.fileExistsSync.html @@ -1 +1 @@ -fileExistsSync | @shopify/cli-kit
      \ No newline at end of file +fileExistsSync | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.fileHasExecutablePermissions.html b/docs/api/cli-kit/functions/node_fs.fileHasExecutablePermissions.html index b902a9087d7..3107c56eedd 100644 --- a/docs/api/cli-kit/functions/node_fs.fileHasExecutablePermissions.html +++ b/docs/api/cli-kit/functions/node_fs.fileHasExecutablePermissions.html @@ -1,3 +1,3 @@ fileHasExecutablePermissions | @shopify/cli-kit

      Function fileHasExecutablePermissions

      • Checks if a file has executable permissions.

        Parameters

        • path: string

          Path to the file whose permissions will be checked.

          -

        Returns Promise<boolean>

      \ No newline at end of file +

      Returns Promise<boolean>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.fileLastUpdated.html b/docs/api/cli-kit/functions/node_fs.fileLastUpdated.html index 81eacecd5dd..32ee9a3580b 100644 --- a/docs/api/cli-kit/functions/node_fs.fileLastUpdated.html +++ b/docs/api/cli-kit/functions/node_fs.fileLastUpdated.html @@ -1,4 +1,4 @@ fileLastUpdated | @shopify/cli-kit
      • Returns the Date object for the last modification of a file.

        Parameters

        • path: string

          Path to the directory or file.

        Returns Promise<Date>

        A unix timestamp.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.fileLastUpdatedTimestamp.html b/docs/api/cli-kit/functions/node_fs.fileLastUpdatedTimestamp.html index 9e44dfd22c7..d1e2f175e56 100644 --- a/docs/api/cli-kit/functions/node_fs.fileLastUpdatedTimestamp.html +++ b/docs/api/cli-kit/functions/node_fs.fileLastUpdatedTimestamp.html @@ -1,4 +1,4 @@ fileLastUpdatedTimestamp | @shopify/cli-kit

      Function fileLastUpdatedTimestamp

      • Returns the unix timestamp of the last modification of a file.

        Parameters

        • path: string

          Path to the directory or file.

        Returns Promise<number | undefined>

        A unix timestamp.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.fileRealPath.html b/docs/api/cli-kit/functions/node_fs.fileRealPath.html index 19ee856a015..a0b7b5d7486 100644 --- a/docs/api/cli-kit/functions/node_fs.fileRealPath.html +++ b/docs/api/cli-kit/functions/node_fs.fileRealPath.html @@ -1,4 +1,4 @@ fileRealPath | @shopify/cli-kit
      • Given a path, it determines the actual path. This is useful when working with paths that represent symlinks.

        Parameters

        • path: string

          Path whose real path will be returned.

          -

        Returns Promise<string>

      \ No newline at end of file +

      Returns Promise<string>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.fileSize.html b/docs/api/cli-kit/functions/node_fs.fileSize.html index bc642f702ed..f43ea477627 100644 --- a/docs/api/cli-kit/functions/node_fs.fileSize.html +++ b/docs/api/cli-kit/functions/node_fs.fileSize.html @@ -1,4 +1,4 @@ fileSize | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.fileSizeSync.html b/docs/api/cli-kit/functions/node_fs.fileSizeSync.html index 4c4d27c7c26..e2a4e9b17dd 100644 --- a/docs/api/cli-kit/functions/node_fs.fileSizeSync.html +++ b/docs/api/cli-kit/functions/node_fs.fileSizeSync.html @@ -1,4 +1,4 @@ fileSizeSync | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.findPathUp.html b/docs/api/cli-kit/functions/node_fs.findPathUp.html index e236ea6abec..ffe88403359 100644 --- a/docs/api/cli-kit/functions/node_fs.findPathUp.html +++ b/docs/api/cli-kit/functions/node_fs.findPathUp.html @@ -2,4 +2,4 @@

      Parameters

      • matcher: string | readonly string[] | ((directory) => Match | Promise<Match>)

        A pattern or an array of patterns to match a file name.

      • options: undefined | Options

        Options for the search.

      Returns ReturnType<typeof internalFindUp>

      The first path found that matches or undefined if none could be found.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.generateRandomNameForSubdirectory.html b/docs/api/cli-kit/functions/node_fs.generateRandomNameForSubdirectory.html index 0deabe8047b..d9ed749bd52 100644 --- a/docs/api/cli-kit/functions/node_fs.generateRandomNameForSubdirectory.html +++ b/docs/api/cli-kit/functions/node_fs.generateRandomNameForSubdirectory.html @@ -2,4 +2,4 @@ It ensures that the returned directory name doesn't exist.

      Parameters

      • options: GenerateRandomDirectoryOptions

        Options to generate the random directory name.

      Returns Promise<string>

      It returns the name of the directory.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.glob.html b/docs/api/cli-kit/functions/node_fs.glob.html index 8d3f9416dc6..db953db3dea 100644 --- a/docs/api/cli-kit/functions/node_fs.glob.html +++ b/docs/api/cli-kit/functions/node_fs.glob.html @@ -2,4 +2,4 @@

      Parameters

      • pattern: string | string[]

        A glob pattern or an array of glob patterns.

      • Optional options: Options

        Options for the glob.

      Returns Promise<string[]>

      A promise that resolves to an array of pathnames that match the given pattern.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.inTemporaryDirectory.html b/docs/api/cli-kit/functions/node_fs.inTemporaryDirectory.html index d42e61fb72a..03e338d3630 100644 --- a/docs/api/cli-kit/functions/node_fs.inTemporaryDirectory.html +++ b/docs/api/cli-kit/functions/node_fs.inTemporaryDirectory.html @@ -1,3 +1,3 @@ inTemporaryDirectory | @shopify/cli-kit

      Function inTemporaryDirectory

      • Creates a temporary directory and ties its lifecycle to the lifecycle of the callback.

        Type Parameters

        • T

        Parameters

        • callback: ((tmpDir) => T | Promise<T>)

          The callback that receives the temporary directory.

          -
            • (tmpDir): T | Promise<T>
            • Parameters

              • tmpDir: string

              Returns T | Promise<T>

        Returns Promise<T>

      \ No newline at end of file +
        • (tmpDir): T | Promise<T>
        • Parameters

          • tmpDir: string

          Returns T | Promise<T>

      Returns Promise<T>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.isDirectory.html b/docs/api/cli-kit/functions/node_fs.isDirectory.html index 109827802da..57402052c93 100644 --- a/docs/api/cli-kit/functions/node_fs.isDirectory.html +++ b/docs/api/cli-kit/functions/node_fs.isDirectory.html @@ -1,4 +1,4 @@ isDirectory | @shopify/cli-kit
      • Check whether a path is a directory.

        Parameters

        • path: string

          Path to check.

        Returns Promise<boolean>

        True if the path is a directory, false otherwise.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.matchGlob.html b/docs/api/cli-kit/functions/node_fs.matchGlob.html index 8a180cb3940..cc2a961d66d 100644 --- a/docs/api/cli-kit/functions/node_fs.matchGlob.html +++ b/docs/api/cli-kit/functions/node_fs.matchGlob.html @@ -3,4 +3,4 @@
    • pattern: string

      The glob pattern to match against.

    • Optional options: MatchGlobOptions

      The options to refine the matching approach.

    • Returns boolean

      true if the key matches the pattern, false otherwise.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.mkTmpDir.html b/docs/api/cli-kit/functions/node_fs.mkTmpDir.html index 024410c8204..6ff8f1b90d4 100644 --- a/docs/api/cli-kit/functions/node_fs.mkTmpDir.html +++ b/docs/api/cli-kit/functions/node_fs.mkTmpDir.html @@ -1,3 +1,3 @@ mkTmpDir | @shopify/cli-kit
      • Create a temporary directory within the OS provided location for temp directories

        Returns Promise<string>

        Path to the temporary directory.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.mkdir.html b/docs/api/cli-kit/functions/node_fs.mkdir.html index ad7d3af0ea0..d53dd217421 100644 --- a/docs/api/cli-kit/functions/node_fs.mkdir.html +++ b/docs/api/cli-kit/functions/node_fs.mkdir.html @@ -1,3 +1,3 @@ mkdir | @shopify/cli-kit
      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.mkdirSync.html b/docs/api/cli-kit/functions/node_fs.mkdirSync.html index 03c72a68d7b..7f60237fec1 100644 --- a/docs/api/cli-kit/functions/node_fs.mkdirSync.html +++ b/docs/api/cli-kit/functions/node_fs.mkdirSync.html @@ -1,3 +1,3 @@ mkdirSync | @shopify/cli-kit
      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.moveFile.html b/docs/api/cli-kit/functions/node_fs.moveFile.html index 2e3892300af..6bcfe6b6278 100644 --- a/docs/api/cli-kit/functions/node_fs.moveFile.html +++ b/docs/api/cli-kit/functions/node_fs.moveFile.html @@ -2,4 +2,4 @@

      Parameters

      • src: string

        File to be moved.

      • dest: string

        Path to be moved to.

      • options: MoveFileOptions = {}

        Moving options.

        -

      Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.pathToFileURL.html b/docs/api/cli-kit/functions/node_fs.pathToFileURL.html index 3963685b63c..4479dcac710 100644 --- a/docs/api/cli-kit/functions/node_fs.pathToFileURL.html +++ b/docs/api/cli-kit/functions/node_fs.pathToFileURL.html @@ -1,4 +1,4 @@ pathToFileURL | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.readFile.html b/docs/api/cli-kit/functions/node_fs.readFile.html index dfef2210b13..89cce31a0e9 100644 --- a/docs/api/cli-kit/functions/node_fs.readFile.html +++ b/docs/api/cli-kit/functions/node_fs.readFile.html @@ -3,9 +3,9 @@

      Parameters

      • path: string

        Path to the file to read.

      • Optional options: ReadOptions

        Options to read the file with (defaults to utf-8 encoding).

      Returns Promise<string>

      A promise that resolves with the content of the file.

      -
    • It reads a file and returns its content as a string. +

    • It reads a file and returns its content as a string. Uses utf-8 encoding by default.

      Parameters

      • path: string

        Path to the file to read.

      • Optional options: ReadOptions

        Options to read the file with (defaults to utf-8 encoding).

      Returns Promise<Buffer>

      A promise that resolves with the content of the file.

      -
    • \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.readFileSync.html b/docs/api/cli-kit/functions/node_fs.readFileSync.html index a2336ed0391..110b7c4a3eb 100644 --- a/docs/api/cli-kit/functions/node_fs.readFileSync.html +++ b/docs/api/cli-kit/functions/node_fs.readFileSync.html @@ -1,4 +1,4 @@ readFileSync | @shopify/cli-kit
      • Synchronously reads a file and returns its content as a buffer.

        Parameters

        • path: string

          Path to the file to read.

        Returns Buffer

        The content of the file.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.removeFile.html b/docs/api/cli-kit/functions/node_fs.removeFile.html index 2c39e8334bc..5caf5d4a9ad 100644 --- a/docs/api/cli-kit/functions/node_fs.removeFile.html +++ b/docs/api/cli-kit/functions/node_fs.removeFile.html @@ -1,3 +1,3 @@ removeFile | @shopify/cli-kit
      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.removeFileSync.html b/docs/api/cli-kit/functions/node_fs.removeFileSync.html index 8d16840911f..d9445a72410 100644 --- a/docs/api/cli-kit/functions/node_fs.removeFileSync.html +++ b/docs/api/cli-kit/functions/node_fs.removeFileSync.html @@ -1,3 +1,3 @@ removeFileSync | @shopify/cli-kit
      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.renameFile.html b/docs/api/cli-kit/functions/node_fs.renameFile.html index e793bff1205..1f0b20d7328 100644 --- a/docs/api/cli-kit/functions/node_fs.renameFile.html +++ b/docs/api/cli-kit/functions/node_fs.renameFile.html @@ -1,4 +1,4 @@ renameFile | @shopify/cli-kit
      • Renames a file.

        Parameters

        • from: string

          Path to the file to be renamed.

        • to: string

          New path for the file.

          -

        Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.rmdir.html b/docs/api/cli-kit/functions/node_fs.rmdir.html index 4ad82f86e76..3b604732239 100644 --- a/docs/api/cli-kit/functions/node_fs.rmdir.html +++ b/docs/api/cli-kit/functions/node_fs.rmdir.html @@ -1,4 +1,4 @@ rmdir | @shopify/cli-kit
      • Removes a directory at the given path.

        Parameters

        • path: string

          Path to the directory to be removed.

        • options: RmDirOptions = {}

          Options to remove the directory with.

          -

        Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.stripUpPath.html b/docs/api/cli-kit/functions/node_fs.stripUpPath.html index 5d3832d86b1..59957eae117 100644 --- a/docs/api/cli-kit/functions/node_fs.stripUpPath.html +++ b/docs/api/cli-kit/functions/node_fs.stripUpPath.html @@ -2,4 +2,4 @@

      Parameters

      • path: string

        Path to strip.

      • strip: number

        Number of parts to strip.

      Returns string

      The stripped path.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.tempDirectory.html b/docs/api/cli-kit/functions/node_fs.tempDirectory.html index 04e877a6de3..493db53cf35 100644 --- a/docs/api/cli-kit/functions/node_fs.tempDirectory.html +++ b/docs/api/cli-kit/functions/node_fs.tempDirectory.html @@ -2,4 +2,4 @@

      Returns string

      • The path to the temporary directory.
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.touchFile.html b/docs/api/cli-kit/functions/node_fs.touchFile.html index d05f04d7e32..c7f06947392 100644 --- a/docs/api/cli-kit/functions/node_fs.touchFile.html +++ b/docs/api/cli-kit/functions/node_fs.touchFile.html @@ -1,3 +1,3 @@ touchFile | @shopify/cli-kit
      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.touchFileSync.html b/docs/api/cli-kit/functions/node_fs.touchFileSync.html index b6d0fdfa014..0c6d79893eb 100644 --- a/docs/api/cli-kit/functions/node_fs.touchFileSync.html +++ b/docs/api/cli-kit/functions/node_fs.touchFileSync.html @@ -1,3 +1,3 @@ touchFileSync | @shopify/cli-kit
      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.unlinkFileSync.html b/docs/api/cli-kit/functions/node_fs.unlinkFileSync.html index 76a83d19325..7bc10420db4 100644 --- a/docs/api/cli-kit/functions/node_fs.unlinkFileSync.html +++ b/docs/api/cli-kit/functions/node_fs.unlinkFileSync.html @@ -1,4 +1,4 @@ unlinkFileSync | @shopify/cli-kit
      • Unlink a file at the given path.

        Parameters

        • path: string

          Path to the file.

        Returns void

        A promise that resolves when the file is unlinked.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.writeFile.html b/docs/api/cli-kit/functions/node_fs.writeFile.html index df1d405a2b6..15e16764378 100644 --- a/docs/api/cli-kit/functions/node_fs.writeFile.html +++ b/docs/api/cli-kit/functions/node_fs.writeFile.html @@ -2,4 +2,4 @@

      Parameters

      • path: string

        Path to the file to be written.

      • data: string | Buffer

        Content to be written.

      • options: WriteOptions = ...

        Options to write the file with (defaults to utf-8 encoding).

        -

      Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_fs.writeFileSync.html b/docs/api/cli-kit/functions/node_fs.writeFileSync.html index 585d9b09136..a7d830bc507 100644 --- a/docs/api/cli-kit/functions/node_fs.writeFileSync.html +++ b/docs/api/cli-kit/functions/node_fs.writeFileSync.html @@ -1,4 +1,4 @@ writeFileSync | @shopify/cli-kit
      • Synchronously writes content to file at path.

        Parameters

        • path: string

          Path to the file to be written.

        • data: string

          Content to be written.

          -

        Returns void

      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_git.addAllToGitFromDirectory.html b/docs/api/cli-kit/functions/node_git.addAllToGitFromDirectory.html index 27798a89756..778cfeb17fe 100644 --- a/docs/api/cli-kit/functions/node_git.addAllToGitFromDirectory.html +++ b/docs/api/cli-kit/functions/node_git.addAllToGitFromDirectory.html @@ -1,4 +1,4 @@ addAllToGitFromDirectory | @shopify/cli-kit

      Function addAllToGitFromDirectory

      • Add all files to the git index from the given directory.

        Parameters

        • Optional directory: string

          The directory where the git repository is located.

        Returns Promise<void>

        A promise that resolves when the files are added to the index.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_git.checkIfIgnoredInGitRepository.html b/docs/api/cli-kit/functions/node_git.checkIfIgnoredInGitRepository.html index 0bf7acc0853..2befc1435f6 100644 --- a/docs/api/cli-kit/functions/node_git.checkIfIgnoredInGitRepository.html +++ b/docs/api/cli-kit/functions/node_git.checkIfIgnoredInGitRepository.html @@ -4,4 +4,4 @@

      Parameters

      • directory: string

        The absolute path to the directory containing the files.

      • files: string[]

        The list of files to check against.

      Returns Promise<string[]>

      Files ignored by the lockfile.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_git.createGitCommit.html b/docs/api/cli-kit/functions/node_git.createGitCommit.html index f2bf9b57eee..2d4d1f3e176 100644 --- a/docs/api/cli-kit/functions/node_git.createGitCommit.html +++ b/docs/api/cli-kit/functions/node_git.createGitCommit.html @@ -2,4 +2,4 @@

      Parameters

      • message: string

        The message of the commit.

      • Optional options: CreateGitCommitOptions

        The options to use to create the commit.

      Returns Promise<string>

      The hash of the created commit.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_git.createGitIgnore.html b/docs/api/cli-kit/functions/node_git.createGitIgnore.html index 1f7e733f7e2..f1b3efa0724 100644 --- a/docs/api/cli-kit/functions/node_git.createGitIgnore.html +++ b/docs/api/cli-kit/functions/node_git.createGitIgnore.html @@ -1,4 +1,4 @@ createGitIgnore | @shopify/cli-kit
      • Create a .gitignore file in the given directory.

        Parameters

        • directory: string

          The directory where the .gitignore file will be created.

        • template: GitIgnoreTemplate

          The template to use to create the .gitignore file.

          -

        Returns void

      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_git.downloadGitRepository.html b/docs/api/cli-kit/functions/node_git.downloadGitRepository.html index b94b280470a..0af16d8d234 100644 --- a/docs/api/cli-kit/functions/node_git.downloadGitRepository.html +++ b/docs/api/cli-kit/functions/node_git.downloadGitRepository.html @@ -1,4 +1,4 @@ downloadGitRepository | @shopify/cli-kit

      Function downloadGitRepository

      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_git.ensureGitIsPresentOrAbort.html b/docs/api/cli-kit/functions/node_git.ensureGitIsPresentOrAbort.html index 72578192549..914fc80cb44 100644 --- a/docs/api/cli-kit/functions/node_git.ensureGitIsPresentOrAbort.html +++ b/docs/api/cli-kit/functions/node_git.ensureGitIsPresentOrAbort.html @@ -1,3 +1,3 @@ ensureGitIsPresentOrAbort | @shopify/cli-kit

      Function ensureGitIsPresentOrAbort

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_git.ensureInsideGitDirectory.html b/docs/api/cli-kit/functions/node_git.ensureInsideGitDirectory.html index 11c773906e7..77610047f05 100644 --- a/docs/api/cli-kit/functions/node_git.ensureInsideGitDirectory.html +++ b/docs/api/cli-kit/functions/node_git.ensureInsideGitDirectory.html @@ -1,4 +1,4 @@ ensureInsideGitDirectory | @shopify/cli-kit

      Function ensureInsideGitDirectory

      • If command run from outside a .git directory tree it throws an abort error.

        Parameters

        • Optional directory: string

          The directory to check.

          -

        Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_git.ensureIsClean.html b/docs/api/cli-kit/functions/node_git.ensureIsClean.html index f4a5ca61497..dcce7e82fc7 100644 --- a/docs/api/cli-kit/functions/node_git.ensureIsClean.html +++ b/docs/api/cli-kit/functions/node_git.ensureIsClean.html @@ -1,4 +1,4 @@ ensureIsClean | @shopify/cli-kit
      • If the .git directory tree is not clean (has uncommitted changes) it throws an abort error.

        Parameters

        • Optional directory: string

          The directory to check.

          -

        Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_git.getHeadSymbolicRef.html b/docs/api/cli-kit/functions/node_git.getHeadSymbolicRef.html index 23e6083151c..ae748392c04 100644 --- a/docs/api/cli-kit/functions/node_git.getHeadSymbolicRef.html +++ b/docs/api/cli-kit/functions/node_git.getHeadSymbolicRef.html @@ -1,4 +1,4 @@ getHeadSymbolicRef | @shopify/cli-kit
      • Get the HEAD symbolic reference of a git repository.

        Parameters

        • Optional directory: string

          The directory of the git repository.

        Returns Promise<string>

        The HEAD symbolic reference of the repository.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_git.getLatestGitCommit.html b/docs/api/cli-kit/functions/node_git.getLatestGitCommit.html index e736e808ccd..fe82bc5e4b0 100644 --- a/docs/api/cli-kit/functions/node_git.getLatestGitCommit.html +++ b/docs/api/cli-kit/functions/node_git.getLatestGitCommit.html @@ -1,4 +1,4 @@ getLatestGitCommit | @shopify/cli-kit
      • Get the latest commit of a git repository.

        Parameters

        • Optional directory: string

          The directory of the git repository.

        Returns Promise<DefaultLogFields & ListLogLine>

        The latest commit of the repository.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_git.initializeGitRepository.html b/docs/api/cli-kit/functions/node_git.initializeGitRepository.html index ac9272f1aa4..abc9c37ec1b 100644 --- a/docs/api/cli-kit/functions/node_git.initializeGitRepository.html +++ b/docs/api/cli-kit/functions/node_git.initializeGitRepository.html @@ -1,4 +1,4 @@ initializeGitRepository | @shopify/cli-kit

      Function initializeGitRepository

      • Initialize a git repository at the given directory.

        Parameters

        • directory: string

          The directory where the git repository will be initialized.

        • initialBranch: string = 'main'

          The name of the initial branch.

          -

        Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_git.isClean.html b/docs/api/cli-kit/functions/node_git.isClean.html index 1b889c1b112..b450e8dc3b4 100644 --- a/docs/api/cli-kit/functions/node_git.isClean.html +++ b/docs/api/cli-kit/functions/node_git.isClean.html @@ -1,4 +1,4 @@ isClean | @shopify/cli-kit
      • Returns true if the .git directory tree is clean (no uncommitted changes).

        Parameters

        • Optional directory: string

          The directory to check.

        Returns Promise<boolean>

        True is the .git directory is clean.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_github.getLatestGitHubRelease.html b/docs/api/cli-kit/functions/node_github.getLatestGitHubRelease.html index 9e698b571ac..67fc09f3912 100644 --- a/docs/api/cli-kit/functions/node_github.getLatestGitHubRelease.html +++ b/docs/api/cli-kit/functions/node_github.getLatestGitHubRelease.html @@ -2,4 +2,4 @@

      Parameters

      • owner: string

        Repository owner (e.g., shopify)

      • repo: string

        Repository name (e.g., cli)

      • options: GetLatestGitHubReleaseOptions = ...

        Options

        -

      Returns Promise<GithubRelease>

      \ No newline at end of file +

      Returns Promise<GithubRelease>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_github.parseGitHubRepositoryReference.html b/docs/api/cli-kit/functions/node_github.parseGitHubRepositoryReference.html index 79f0b85f364..881fe6602f0 100644 --- a/docs/api/cli-kit/functions/node_github.parseGitHubRepositoryReference.html +++ b/docs/api/cli-kit/functions/node_github.parseGitHubRepositoryReference.html @@ -1,4 +1,4 @@ parseGitHubRepositoryReference | @shopify/cli-kit

      Function parseGitHubRepositoryReference

      \ No newline at end of file +

      Returns GithubRepositoryReference

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_github.parseGitHubRepositoryURL.html b/docs/api/cli-kit/functions/node_github.parseGitHubRepositoryURL.html index f8e3abd0404..fa80f9e61ca 100644 --- a/docs/api/cli-kit/functions/node_github.parseGitHubRepositoryURL.html +++ b/docs/api/cli-kit/functions/node_github.parseGitHubRepositoryURL.html @@ -1,3 +1,3 @@ parseGitHubRepositoryURL | @shopify/cli-kit
      • Given a GitHub repository URL, it parses it and returns its coomponents.

        Parameters

        • url: string

          The GitHub repository URL

          -

        Returns Result<ParseRepositoryURLOutput, Error>

      \ No newline at end of file +

      Returns Result<ParseRepositoryURLOutput, Error>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_global_context.getCurrentCommandId.html b/docs/api/cli-kit/functions/node_global_context.getCurrentCommandId.html index e3569446374..0c06fb162d1 100644 --- a/docs/api/cli-kit/functions/node_global_context.getCurrentCommandId.html +++ b/docs/api/cli-kit/functions/node_global_context.getCurrentCommandId.html @@ -1,3 +1,3 @@ getCurrentCommandId | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_global_context.setCurrentCommandId.html b/docs/api/cli-kit/functions/node_global_context.setCurrentCommandId.html index 60606d48329..1c095041327 100644 --- a/docs/api/cli-kit/functions/node_global_context.setCurrentCommandId.html +++ b/docs/api/cli-kit/functions/node_global_context.setCurrentCommandId.html @@ -1,3 +1,3 @@ setCurrentCommandId | @shopify/cli-kit
      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_hooks_deprecations.postrun.html b/docs/api/cli-kit/functions/node_hooks_deprecations.postrun.html index 739a33ddd47..37f8ba82d3f 100644 --- a/docs/api/cli-kit/functions/node_hooks_deprecations.postrun.html +++ b/docs/api/cli-kit/functions/node_hooks_deprecations.postrun.html @@ -1,3 +1,3 @@ postrun | @shopify/cli-kit
      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_hooks_postrun.hook.html b/docs/api/cli-kit/functions/node_hooks_postrun.hook.html index ef5cb9ac6e0..7a72cc8feb9 100644 --- a/docs/api/cli-kit/functions/node_hooks_postrun.hook.html +++ b/docs/api/cli-kit/functions/node_hooks_postrun.hook.html @@ -1 +1 @@ -hook | @shopify/cli-kit
      \ No newline at end of file +hook | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_hooks_prerun.hook.html b/docs/api/cli-kit/functions/node_hooks_prerun.hook.html index abb1e02b8c8..e57b4daa064 100644 --- a/docs/api/cli-kit/functions/node_hooks_prerun.hook.html +++ b/docs/api/cli-kit/functions/node_hooks_prerun.hook.html @@ -1 +1 @@ -hook | @shopify/cli-kit
      \ No newline at end of file +hook | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_hooks_prerun.parseCommandContent.html b/docs/api/cli-kit/functions/node_hooks_prerun.parseCommandContent.html index 22f868096c5..92872401972 100644 --- a/docs/api/cli-kit/functions/node_hooks_prerun.parseCommandContent.html +++ b/docs/api/cli-kit/functions/node_hooks_prerun.parseCommandContent.html @@ -1 +1 @@ -parseCommandContent | @shopify/cli-kit
      \ No newline at end of file +parseCommandContent | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_hooks_prerun.warnOnAvailableUpgrade.html b/docs/api/cli-kit/functions/node_hooks_prerun.warnOnAvailableUpgrade.html index e096be49c01..02f1a0a7898 100644 --- a/docs/api/cli-kit/functions/node_hooks_prerun.warnOnAvailableUpgrade.html +++ b/docs/api/cli-kit/functions/node_hooks_prerun.warnOnAvailableUpgrade.html @@ -1,2 +1,2 @@ warnOnAvailableUpgrade | @shopify/cli-kit
      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_hrtime.endHRTimeInMs.html b/docs/api/cli-kit/functions/node_hrtime.endHRTimeInMs.html index 258b4748f37..c0ee153c234 100644 --- a/docs/api/cli-kit/functions/node_hrtime.endHRTimeInMs.html +++ b/docs/api/cli-kit/functions/node_hrtime.endHRTimeInMs.html @@ -1,4 +1,4 @@ endHRTimeInMs | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_hrtime.startHRTime.html b/docs/api/cli-kit/functions/node_hrtime.startHRTime.html index 72143c23f47..560d5691179 100644 --- a/docs/api/cli-kit/functions/node_hrtime.startHRTime.html +++ b/docs/api/cli-kit/functions/node_hrtime.startHRTime.html @@ -1,3 +1,3 @@ startHRTime | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_http.downloadFile.html b/docs/api/cli-kit/functions/node_http.downloadFile.html index 4dc36bea382..6caccfd3fae 100644 --- a/docs/api/cli-kit/functions/node_http.downloadFile.html +++ b/docs/api/cli-kit/functions/node_http.downloadFile.html @@ -4,4 +4,4 @@

      Returns Promise<string>

      • A promise that resolves with the local path.
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_http.fetch.html b/docs/api/cli-kit/functions/node_http.fetch.html index 073ad865e6c..e8a7f5fccaf 100644 --- a/docs/api/cli-kit/functions/node_http.fetch.html +++ b/docs/api/cli-kit/functions/node_http.fetch.html @@ -7,4 +7,4 @@

      Parameters

      • url: RequestInfo

        This defines the resource that you wish to fetch.

      • Optional init: RequestInit

        An object containing any custom settings that you want to apply to the request.

      Returns Promise<Response>

      A promise that resolves with the response.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_http.formData.html b/docs/api/cli-kit/functions/node_http.formData.html index caa4e99de29..7320f2672a6 100644 --- a/docs/api/cli-kit/functions/node_http.formData.html +++ b/docs/api/cli-kit/functions/node_http.formData.html @@ -1,3 +1,3 @@ formData | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_http.shopifyFetch.html b/docs/api/cli-kit/functions/node_http.shopifyFetch.html index b56a9c85c3f..127f033fafb 100644 --- a/docs/api/cli-kit/functions/node_http.shopifyFetch.html +++ b/docs/api/cli-kit/functions/node_http.shopifyFetch.html @@ -4,4 +4,4 @@

      Parameters

      • url: RequestInfo

        This defines the resource that you wish to fetch.

      • Optional init: RequestInit

        An object containing any custom settings that you want to apply to the request.

      Returns Promise<Response>

      A promise that resolves with the response.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_is_global.currentProcessIsGlobal.html b/docs/api/cli-kit/functions/node_is_global.currentProcessIsGlobal.html index e9e0edfcf07..be32ecdd045 100644 --- a/docs/api/cli-kit/functions/node_is_global.currentProcessIsGlobal.html +++ b/docs/api/cli-kit/functions/node_is_global.currentProcessIsGlobal.html @@ -1,4 +1,4 @@ currentProcessIsGlobal | @shopify/cli-kit
      • Returns true if the current process is running in a global context.

        Parameters

        • argv: string[] = process.argv

          The arguments passed to the process.

        Returns boolean

        true if the current process is running in a global context.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_is_global.inferPackageManagerForGlobalCLI.html b/docs/api/cli-kit/functions/node_is_global.inferPackageManagerForGlobalCLI.html index a9e1decb444..7a5b0c07cf7 100644 --- a/docs/api/cli-kit/functions/node_is_global.inferPackageManagerForGlobalCLI.html +++ b/docs/api/cli-kit/functions/node_is_global.inferPackageManagerForGlobalCLI.html @@ -1,4 +1,4 @@ inferPackageManagerForGlobalCLI | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_is_global.installGlobalCLIPrompt.html b/docs/api/cli-kit/functions/node_is_global.installGlobalCLIPrompt.html index e95c83d7d20..231f766fc3f 100644 --- a/docs/api/cli-kit/functions/node_is_global.installGlobalCLIPrompt.html +++ b/docs/api/cli-kit/functions/node_is_global.installGlobalCLIPrompt.html @@ -1,3 +1,3 @@ installGlobalCLIPrompt | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_is_global.installGlobalShopifyCLI.html b/docs/api/cli-kit/functions/node_is_global.installGlobalShopifyCLI.html index 4d691974335..60ae5d39cfa 100644 --- a/docs/api/cli-kit/functions/node_is_global.installGlobalShopifyCLI.html +++ b/docs/api/cli-kit/functions/node_is_global.installGlobalShopifyCLI.html @@ -1,3 +1,3 @@ installGlobalShopifyCLI | @shopify/cli-kit
      • Installs the global Shopify CLI, using the provided package manager.

        Parameters

        • packageManager: "yarn" | "npm" | "pnpm" | "bun" | "unknown"

          The package manager to use.

          -

        Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_is_global.isGlobalCLIInstalled.html b/docs/api/cli-kit/functions/node_is_global.isGlobalCLIInstalled.html index 67ec91a5553..81d4914d126 100644 --- a/docs/api/cli-kit/functions/node_is_global.isGlobalCLIInstalled.html +++ b/docs/api/cli-kit/functions/node_is_global.isGlobalCLIInstalled.html @@ -1,3 +1,3 @@ isGlobalCLIInstalled | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_json_schema.jsonSchemaValidate.html b/docs/api/cli-kit/functions/node_json_schema.jsonSchemaValidate.html index c527c0da442..252e9607354 100644 --- a/docs/api/cli-kit/functions/node_json_schema.jsonSchemaValidate.html +++ b/docs/api/cli-kit/functions/node_json_schema.jsonSchemaValidate.html @@ -1,6 +1,7 @@ -jsonSchemaValidate | @shopify/cli-kit
      • Given a subject object and a JSON schema contract, validate the subject against the contract.

        +jsonSchemaValidate | @shopify/cli-kit
        • Given a subject object and a JSON schema contract, validate the subject against the contract.

          Errors are returned in a zod-like format, and processed to better handle unions.

          Parameters

          • subject: object

            The object to validate.

          • schema: SchemaObject

            The JSON schema to validate against.

            +
          • identifier: string

            The identifier of the schema being validated, used to cache the validator.

          Returns ParseConfigurationResult<unknown> & {
              rawErrors?: AjvError[];
          }

          The result of the validation. If the state is 'error', the errors will be in a zod-like format.

          -
        \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_json_schema.normaliseJsonSchema.html b/docs/api/cli-kit/functions/node_json_schema.normaliseJsonSchema.html index 9dcea79a960..ffcceb5fe2d 100644 --- a/docs/api/cli-kit/functions/node_json_schema.normaliseJsonSchema.html +++ b/docs/api/cli-kit/functions/node_json_schema.normaliseJsonSchema.html @@ -2,4 +2,4 @@

      We prefer to not use $ref elements in our schemas, so we inline them; it's easier then to process errors.

      Parameters

      • schema: string

        The JSON schema (as a string) to normalise.

      Returns Promise<SchemaObject>

      The normalised JSON schema.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_liquid.recursiveLiquidTemplateCopy.html b/docs/api/cli-kit/functions/node_liquid.recursiveLiquidTemplateCopy.html index e625dbc1fdc..1a17e3c45b1 100644 --- a/docs/api/cli-kit/functions/node_liquid.recursiveLiquidTemplateCopy.html +++ b/docs/api/cli-kit/functions/node_liquid.recursiveLiquidTemplateCopy.html @@ -5,4 +5,4 @@

      Parameters

      • from: string

        Directory that contains the template.

      • to: string

        Output directory.

      • data: object

        Data to feed the template engine.

        -

      Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_liquid.renderLiquidTemplate.html b/docs/api/cli-kit/functions/node_liquid.renderLiquidTemplate.html index 9991c592e13..fd2dac52052 100644 --- a/docs/api/cli-kit/functions/node_liquid.renderLiquidTemplate.html +++ b/docs/api/cli-kit/functions/node_liquid.renderLiquidTemplate.html @@ -2,4 +2,4 @@

      Parameters

      • templateContent: string

        Template content.

      • data: object

        Data to feed the template engine.

      Returns Promise<string>

      Rendered template.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_logs.createLogsDir.html b/docs/api/cli-kit/functions/node_logs.createLogsDir.html index 0546756df52..3ea52e8d000 100644 --- a/docs/api/cli-kit/functions/node_logs.createLogsDir.html +++ b/docs/api/cli-kit/functions/node_logs.createLogsDir.html @@ -1 +1 @@ -createLogsDir | @shopify/cli-kit
      \ No newline at end of file +createLogsDir | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_logs.getLogsDir.html b/docs/api/cli-kit/functions/node_logs.getLogsDir.html index 4a186ac8ae1..31f8b2d5a27 100644 --- a/docs/api/cli-kit/functions/node_logs.getLogsDir.html +++ b/docs/api/cli-kit/functions/node_logs.getLogsDir.html @@ -1 +1 @@ -getLogsDir | @shopify/cli-kit
      \ No newline at end of file +getLogsDir | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_logs.writeLog.html b/docs/api/cli-kit/functions/node_logs.writeLog.html index 1efbe85fbb3..8a7c0eac30b 100644 --- a/docs/api/cli-kit/functions/node_logs.writeLog.html +++ b/docs/api/cli-kit/functions/node_logs.writeLog.html @@ -1 +1 @@ -writeLog | @shopify/cli-kit
      \ No newline at end of file +writeLog | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_metadata.addPublicMetadata.html b/docs/api/cli-kit/functions/node_metadata.addPublicMetadata.html index 595f7e206c1..5c4d4b8a5cc 100644 --- a/docs/api/cli-kit/functions/node_metadata.addPublicMetadata.html +++ b/docs/api/cli-kit/functions/node_metadata.addPublicMetadata.html @@ -1 +1 @@ -addPublicMetadata | @shopify/cli-kit
      \ No newline at end of file +addPublicMetadata | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_metadata.addSensitiveMetadata.html b/docs/api/cli-kit/functions/node_metadata.addSensitiveMetadata.html index e1d13fc3b8a..b5b7e961a13 100644 --- a/docs/api/cli-kit/functions/node_metadata.addSensitiveMetadata.html +++ b/docs/api/cli-kit/functions/node_metadata.addSensitiveMetadata.html @@ -1 +1 @@ -addSensitiveMetadata | @shopify/cli-kit
      • Parameters

        • getData: ProvideMetadata<{
              commandStartOptions: {
                  startArgs: string[];
                  startCommand: string;
                  startTime: number;
                  startTopic?: string;
              };
          } & {
              environmentFlags: string;
          }>
        • Optional onError: MetadataErrorHandling

        Returns Promise<void>

      \ No newline at end of file +addSensitiveMetadata | @shopify/cli-kit
      • Parameters

        • getData: ProvideMetadata<{
              commandStartOptions: {
                  startArgs: string[];
                  startCommand: string;
                  startTime: number;
                  startTopic?: string;
              };
          } & {
              environmentFlags: string;
          }>
        • Optional onError: MetadataErrorHandling

        Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_metadata.createRuntimeMetadataContainer.html b/docs/api/cli-kit/functions/node_metadata.createRuntimeMetadataContainer.html index 115174c4246..7beb704f763 100644 --- a/docs/api/cli-kit/functions/node_metadata.createRuntimeMetadataContainer.html +++ b/docs/api/cli-kit/functions/node_metadata.createRuntimeMetadataContainer.html @@ -2,4 +2,4 @@ The container provides async-safe functions for extracting the gathered metadata, and for setting it.

      Type Parameters

      • TPublic extends AnyJson
      • TSensitive extends AnyJson = {
            [key: string]: never;
        }

      Parameters

      • defaultPublicMetadata: Partial<TPublic> = {}

        Optional, default data for the container.

      Returns RuntimeMetadataManager<TPublic, TSensitive>

      A container for the metadata.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_metadata.getAllPublicMetadata.html b/docs/api/cli-kit/functions/node_metadata.getAllPublicMetadata.html index 5cd1f4270f1..2a6a3f1db65 100644 --- a/docs/api/cli-kit/functions/node_metadata.getAllPublicMetadata.html +++ b/docs/api/cli-kit/functions/node_metadata.getAllPublicMetadata.html @@ -1 +1 @@ -getAllPublicMetadata | @shopify/cli-kit
      \ No newline at end of file +getAllPublicMetadata | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_metadata.getAllSensitiveMetadata.html b/docs/api/cli-kit/functions/node_metadata.getAllSensitiveMetadata.html index 8050cedf4ab..afd2aeae747 100644 --- a/docs/api/cli-kit/functions/node_metadata.getAllSensitiveMetadata.html +++ b/docs/api/cli-kit/functions/node_metadata.getAllSensitiveMetadata.html @@ -1 +1 @@ -getAllSensitiveMetadata | @shopify/cli-kit
      • Returns Partial<{
            commandStartOptions: {
                startArgs: string[];
                startCommand: string;
                startTime: number;
                startTopic?: string;
            };
        } & {
            environmentFlags: string;
        }>

      \ No newline at end of file +getAllSensitiveMetadata | @shopify/cli-kit
      • Returns Partial<{
            commandStartOptions: {
                startArgs: string[];
                startCommand: string;
                startTime: number;
                startTopic?: string;
            };
        } & {
            environmentFlags: string;
        }>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_metadata.runWithTimer.html b/docs/api/cli-kit/functions/node_metadata.runWithTimer.html index e423e3c3537..873f2903dab 100644 --- a/docs/api/cli-kit/functions/node_metadata.runWithTimer.html +++ b/docs/api/cli-kit/functions/node_metadata.runWithTimer.html @@ -1 +1 @@ -runWithTimer | @shopify/cli-kit
      • Parameters

        • field: NumericKeyOf<CmdFieldsFromMonorail>

        Returns (<T>(fn) => Promise<T>)

          • <T>(fn): Promise<T>
          • Type Parameters

            • T

            Parameters

            • fn: (() => Promise<T>)
                • (): Promise<T>
                • Returns Promise<T>

            Returns Promise<T>

      \ No newline at end of file +runWithTimer | @shopify/cli-kit
      • Parameters

        • field: NumericKeyOf<CmdFieldsFromMonorail>

        Returns (<T>(fn) => Promise<T>)

          • <T>(fn): Promise<T>
          • Type Parameters

            • T

            Parameters

            • fn: (() => Promise<T>)
                • (): Promise<T>
                • Returns Promise<T>

            Returns Promise<T>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_mimes.lookupMimeType.html b/docs/api/cli-kit/functions/node_mimes.lookupMimeType.html index 0f9527de285..9035eac23a4 100644 --- a/docs/api/cli-kit/functions/node_mimes.lookupMimeType.html +++ b/docs/api/cli-kit/functions/node_mimes.lookupMimeType.html @@ -1,4 +1,4 @@ lookupMimeType | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_mimes.setMimeTypes.html b/docs/api/cli-kit/functions/node_mimes.setMimeTypes.html index e3c6428155c..9f337328096 100644 --- a/docs/api/cli-kit/functions/node_mimes.setMimeTypes.html +++ b/docs/api/cli-kit/functions/node_mimes.setMimeTypes.html @@ -1,3 +1,3 @@ setMimeTypes | @shopify/cli-kit
      • Adds MIME type(s) to the dictionary.

        Parameters

        • newTypes: {
              [key: string]: string;
          }

          Object of key-values where key is extension and value is mime type.

          -
          • [key: string]: string

        Returns void

      \ No newline at end of file +
      • [key: string]: string

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_monorail.publishMonorailEvent.html b/docs/api/cli-kit/functions/node_monorail.publishMonorailEvent.html index 4603a1b4344..55cf98aa95a 100644 --- a/docs/api/cli-kit/functions/node_monorail.publishMonorailEvent.html +++ b/docs/api/cli-kit/functions/node_monorail.publishMonorailEvent.html @@ -3,4 +3,4 @@
    • publicData: TPayload["public"]

      The public data to publish.

    • sensitiveData: TPayload["sensitive"]

      The sensitive data to publish.

    • Returns Promise<MonorailResult>

      A result indicating whether the event was successfully published.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.addNPMDependencies.html b/docs/api/cli-kit/functions/node_node_package_manager.addNPMDependencies.html index a3caeeb268b..a5f5154f844 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.addNPMDependencies.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.addNPMDependencies.html @@ -1 +1 @@ -addNPMDependencies | @shopify/cli-kit
      \ No newline at end of file +addNPMDependencies | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.addNPMDependenciesIfNeeded.html b/docs/api/cli-kit/functions/node_node_package_manager.addNPMDependenciesIfNeeded.html index 1775eedb3f0..fe513522b23 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.addNPMDependenciesIfNeeded.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.addNPMDependenciesIfNeeded.html @@ -1,4 +1,4 @@ addNPMDependenciesIfNeeded | @shopify/cli-kit
      • Adds dependencies to a Node project (i.e. a project that has a package.json)

        Parameters

        • dependencies: DependencyVersion[]

          List of dependencies to be added.

        • options: AddNPMDependenciesIfNeededOptions

          Options for adding dependencies.

          -

        Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.addNPMDependenciesWithoutVersionIfNeeded.html b/docs/api/cli-kit/functions/node_node_package_manager.addNPMDependenciesWithoutVersionIfNeeded.html index 5d60d7c3833..b5f07937948 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.addNPMDependenciesWithoutVersionIfNeeded.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.addNPMDependenciesWithoutVersionIfNeeded.html @@ -1 +1 @@ -addNPMDependenciesWithoutVersionIfNeeded | @shopify/cli-kit
      \ No newline at end of file +addNPMDependenciesWithoutVersionIfNeeded | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.addResolutionOrOverride.html b/docs/api/cli-kit/functions/node_node_package_manager.addResolutionOrOverride.html index a10bfb8ddb5..8444c07e67d 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.addResolutionOrOverride.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.addResolutionOrOverride.html @@ -1 +1 @@ -addResolutionOrOverride | @shopify/cli-kit
      \ No newline at end of file +addResolutionOrOverride | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.checkForCachedNewVersion.html b/docs/api/cli-kit/functions/node_node_package_manager.checkForCachedNewVersion.html index 478d252ef69..dc1ed4d8e0f 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.checkForCachedNewVersion.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.checkForCachedNewVersion.html @@ -2,4 +2,4 @@

      Parameters

      • dependency: string

        The dependency name (e.g. react)

      • currentVersion: string

        The current version.

      Returns string | undefined

      A more recent version or undefined if there's no more recent version.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.checkForNewVersion.html b/docs/api/cli-kit/functions/node_node_package_manager.checkForNewVersion.html index 1ec287294ac..b61d6478154 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.checkForNewVersion.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.checkForNewVersion.html @@ -4,4 +4,4 @@
    • cacheExpiryInHours: {
          cacheExpiryInHours: undefined | number;
      } = {}

      If the last check was done more than this amount of hours ago, it will refresh the cache. Defaults to always refreshing.

      • cacheExpiryInHours: undefined | number
    • Returns Promise<string | undefined>

      A promise that resolves with a more recent version or undefined if there's no more recent version.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.findUpAndReadPackageJson.html b/docs/api/cli-kit/functions/node_node_package_manager.findUpAndReadPackageJson.html index a2129c7b9e2..e714934b512 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.findUpAndReadPackageJson.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.findUpAndReadPackageJson.html @@ -2,4 +2,4 @@ decodes the JSON, and returns its content as a Javascript object.

      Parameters

      • fromDirectory: string

      Returns Promise<{
          content: PackageJson;
          path: string;
      }>

      If found, the promise resolves with the path to the package.json and its content. If not found, it throws a FindUpAndReadPackageJsonNotFoundError error.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.getDependencies.html b/docs/api/cli-kit/functions/node_node_package_manager.getDependencies.html index 508f149ace8..f89ca1bf456 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.getDependencies.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.getDependencies.html @@ -1,4 +1,4 @@ getDependencies | @shopify/cli-kit
      • Returns the list of production and dev dependencies of a package.json

        Parameters

        • packageJsonPath: string

          Path to the package.json file

        Returns Promise<{
            [key: string]: string;
        }>

        A promise that resolves with the list of dependencies.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.getPackageManager.html b/docs/api/cli-kit/functions/node_node_package_manager.getPackageManager.html index 371125525ce..023c866babf 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.getPackageManager.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.getPackageManager.html @@ -1,4 +1,4 @@ getPackageManager | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.getPackageName.html b/docs/api/cli-kit/functions/node_node_package_manager.getPackageName.html index 39eeb5e29f9..41f4a1b18f2 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.getPackageName.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.getPackageName.html @@ -1,4 +1,4 @@ getPackageName | @shopify/cli-kit
      • Returns the name of the package configured in its package.json

        Parameters

        • packageJsonPath: string

          Path to the package.json file

        Returns Promise<string | undefined>

        A promise that resolves with the name.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.getPackageVersion.html b/docs/api/cli-kit/functions/node_node_package_manager.getPackageVersion.html index 68e62fb3471..cfd98e3bb5e 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.getPackageVersion.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.getPackageVersion.html @@ -1,4 +1,4 @@ getPackageVersion | @shopify/cli-kit
      • Returns the version of the package configured in its package.json

        Parameters

        • packageJsonPath: string

          Path to the package.json file

        Returns Promise<string | undefined>

        A promise that resolves with the version.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.inferPackageManager.html b/docs/api/cli-kit/functions/node_node_package_manager.inferPackageManager.html index 649dc830707..af9be7844ad 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.inferPackageManager.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.inferPackageManager.html @@ -8,4 +8,4 @@

      Parameters

      • optionsPackageManager: undefined | string

        The package manager specified in the options (if any).

      • env: ProcessEnv = process.env

      Returns PackageManager

      The inferred package manager as a PackageManager type.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.installNPMDependenciesRecursively.html b/docs/api/cli-kit/functions/node_node_package_manager.installNPMDependenciesRecursively.html index 091821aba39..b19dea7dc63 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.installNPMDependenciesRecursively.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.installNPMDependenciesRecursively.html @@ -2,4 +2,4 @@ and installs the dependencies if needed. To know if it's needed, it uses the "check" command provided by dependency managers.

      Parameters

      • options: InstallNPMDependenciesRecursivelyOptions

        Options to install dependencies recursively.

        -

      Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.installNodeModules.html b/docs/api/cli-kit/functions/node_node_package_manager.installNodeModules.html index bee2db71dc9..d0d6afe493a 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.installNodeModules.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.installNodeModules.html @@ -1 +1 @@ -installNodeModules | @shopify/cli-kit
      \ No newline at end of file +installNodeModules | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.packageManagerFromUserAgent.html b/docs/api/cli-kit/functions/node_node_package_manager.packageManagerFromUserAgent.html index f046c3fbfe5..2f4fbde4edd 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.packageManagerFromUserAgent.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.packageManagerFromUserAgent.html @@ -1,4 +1,4 @@ packageManagerFromUserAgent | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.readAndParsePackageJson.html b/docs/api/cli-kit/functions/node_node_package_manager.readAndParsePackageJson.html index cd0bfa1dc7c..4a51afe5b6e 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.readAndParsePackageJson.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.readAndParsePackageJson.html @@ -3,4 +3,4 @@

      Returns Promise<PackageJson>

      An promise that resolves with an in-memory representation of the package.json or rejects with an error if the file is not found or the content is not decodable.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.usesWorkspaces.html b/docs/api/cli-kit/functions/node_node_package_manager.usesWorkspaces.html index bc523fc3ac5..fb71e5610b6 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.usesWorkspaces.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.usesWorkspaces.html @@ -1,3 +1,3 @@ usesWorkspaces | @shopify/cli-kit
      • Returns true if the app uses workspaces, false otherwise.

        Parameters

        • appDirectory: string

        Returns Promise<boolean>

        A promise that resolves with true if the app uses workspaces, false otherwise.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.versionSatisfies.html b/docs/api/cli-kit/functions/node_node_package_manager.versionSatisfies.html index b0c6a1d5a04..aa5908184f9 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.versionSatisfies.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.versionSatisfies.html @@ -2,4 +2,4 @@

      Parameters

      Returns boolean

      A boolean indicating whether the version satisfies the requirements

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_node_package_manager.writePackageJSON.html b/docs/api/cli-kit/functions/node_node_package_manager.writePackageJSON.html index 7239065fbb9..c40c8e5613f 100644 --- a/docs/api/cli-kit/functions/node_node_package_manager.writePackageJSON.html +++ b/docs/api/cli-kit/functions/node_node_package_manager.writePackageJSON.html @@ -1,4 +1,4 @@ writePackageJSON | @shopify/cli-kit
      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_notifications_system.filterNotifications.html b/docs/api/cli-kit/functions/node_notifications_system.filterNotifications.html index c415c82cae0..e27597fac4c 100644 --- a/docs/api/cli-kit/functions/node_notifications_system.filterNotifications.html +++ b/docs/api/cli-kit/functions/node_notifications_system.filterNotifications.html @@ -7,4 +7,4 @@

      Returns Notification[]

      • The filtered notifications.
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_notifications_system.getNotifications.html b/docs/api/cli-kit/functions/node_notifications_system.getNotifications.html index b20c868de10..ed1041dd87d 100644 --- a/docs/api/cli-kit/functions/node_notifications_system.getNotifications.html +++ b/docs/api/cli-kit/functions/node_notifications_system.getNotifications.html @@ -1,3 +1,3 @@ getNotifications | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_notifications_system.showNotificationsIfNeeded.html b/docs/api/cli-kit/functions/node_notifications_system.showNotificationsIfNeeded.html index c2bb8578da1..08c4d7e9f15 100644 --- a/docs/api/cli-kit/functions/node_notifications_system.showNotificationsIfNeeded.html +++ b/docs/api/cli-kit/functions/node_notifications_system.showNotificationsIfNeeded.html @@ -1,6 +1,7 @@ -showNotificationsIfNeeded | @shopify/cli-kit
      • Shows notifications to the user if they meet the criteria specified in the notifications.json file.

        +showNotificationsIfNeeded | @shopify/cli-kit
        • Shows notifications to the user if they meet the criteria specified in the notifications.json file.

          Parameters

          • Optional currentSurfaces: string[]

            The surfaces present in the current project (usually for app extensions).

            +
          • environment: ProcessEnv = process.env

            Process environment variables.

          Returns Promise<void>

          • A promise that resolves when the notifications have been shown.
          -
        \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_notifications_system.stringifyFilters.html b/docs/api/cli-kit/functions/node_notifications_system.stringifyFilters.html index 4b08f8c18a9..7505f77ddc2 100644 --- a/docs/api/cli-kit/functions/node_notifications_system.stringifyFilters.html +++ b/docs/api/cli-kit/functions/node_notifications_system.stringifyFilters.html @@ -1,4 +1,4 @@ stringifyFilters | @shopify/cli-kit
      • Returns a string with the filters from a notification, one by line.

        Parameters

        • notification: {
              commands?: string[];
              cta?: {
                  label: string;
                  url: string;
              };
              frequency: "always" | "once" | "once_a_day" | "once_a_week";
              id: string;
              maxDate?: string;
              maxVersion?: string;
              message: string;
              minDate?: string;
              minVersion?: string;
              ownerChannel: string;
              surface?: string;
              title?: string;
              type: "error" | "info" | "warning";
          }

          The notification to get the filters from.

          • Optional commands?: string[]
          • Optional cta?: {
                label: string;
                url: string;
            }
            • label: string
            • url: string
          • frequency: "always" | "once" | "once_a_day" | "once_a_week"
          • id: string
          • Optional maxDate?: string
          • Optional maxVersion?: string
          • message: string
          • Optional minDate?: string
          • Optional minVersion?: string
          • ownerChannel: string
          • Optional surface?: string
          • Optional title?: string
          • type: "error" | "info" | "warning"

        Returns string

        A string with human-readable filters from the notification.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_os.platformAndArch.html b/docs/api/cli-kit/functions/node_os.platformAndArch.html index e1b2328a67c..008fb5b8c9f 100644 --- a/docs/api/cli-kit/functions/node_os.platformAndArch.html +++ b/docs/api/cli-kit/functions/node_os.platformAndArch.html @@ -1,3 +1,3 @@ platformAndArch | @shopify/cli-kit
      • Returns the platform and architecture.

        Parameters

        • platform: Platform = process.platform
        • arch: Architecture = process.arch

        Returns {
            arch: PlatformArch;
            platform: PlatformStrings;
        }

        Returns the current platform and architecture.

        -
        • arch: PlatformArch
        • platform: PlatformStrings
      \ No newline at end of file +
      • arch: PlatformArch
      • platform: PlatformStrings
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_os.username.html b/docs/api/cli-kit/functions/node_os.username.html index 7f5364c6395..697389d3d71 100644 --- a/docs/api/cli-kit/functions/node_os.username.html +++ b/docs/api/cli-kit/functions/node_os.username.html @@ -1,3 +1,3 @@ username | @shopify/cli-kit
      • Parameters

        • platform: Platform = process.platform

          The platform to get the username for. Defaults to the current platform.

        Returns Promise<string | null>

        The username of the current user.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.clearCollectedLogs.html b/docs/api/cli-kit/functions/node_output.clearCollectedLogs.html index 104e36d5f72..41ca6e18883 100644 --- a/docs/api/cli-kit/functions/node_output.clearCollectedLogs.html +++ b/docs/api/cli-kit/functions/node_output.clearCollectedLogs.html @@ -1 +1 @@ -clearCollectedLogs | @shopify/cli-kit
      \ No newline at end of file +clearCollectedLogs | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.collectLog.html b/docs/api/cli-kit/functions/node_output.collectLog.html index db64734686a..67c467ce0f7 100644 --- a/docs/api/cli-kit/functions/node_output.collectLog.html +++ b/docs/api/cli-kit/functions/node_output.collectLog.html @@ -3,4 +3,4 @@ we will store them in a variable that can be accessed from the tests.

      Parameters

      • key: string

        The key of the log.

      • content: OutputMessage

        The content of the log.

        -

      Returns void

      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.consoleError.html b/docs/api/cli-kit/functions/node_output.consoleError.html index 5eef9ab5d49..2abd1b3e343 100644 --- a/docs/api/cli-kit/functions/node_output.consoleError.html +++ b/docs/api/cli-kit/functions/node_output.consoleError.html @@ -1,3 +1,3 @@ consoleError | @shopify/cli-kit
      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.consoleLog.html b/docs/api/cli-kit/functions/node_output.consoleLog.html index 417fd62a244..eff1fea42bc 100644 --- a/docs/api/cli-kit/functions/node_output.consoleLog.html +++ b/docs/api/cli-kit/functions/node_output.consoleLog.html @@ -1,3 +1,3 @@ consoleLog | @shopify/cli-kit
      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.consoleWarn.html b/docs/api/cli-kit/functions/node_output.consoleWarn.html index 249884957fa..6bee092b136 100644 --- a/docs/api/cli-kit/functions/node_output.consoleWarn.html +++ b/docs/api/cli-kit/functions/node_output.consoleWarn.html @@ -1,3 +1,3 @@ consoleWarn | @shopify/cli-kit
      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.formatPackageManagerCommand.html b/docs/api/cli-kit/functions/node_output.formatPackageManagerCommand.html index c344e9b633e..1d707a3f5d7 100644 --- a/docs/api/cli-kit/functions/node_output.formatPackageManagerCommand.html +++ b/docs/api/cli-kit/functions/node_output.formatPackageManagerCommand.html @@ -3,4 +3,4 @@
    • scriptName: string

      The name of the script to run.

    • Rest ...scriptArgs: string[]

      The arguments to pass to the script.

    • Returns string

      The formatted command.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.formatSection.html b/docs/api/cli-kit/functions/node_output.formatSection.html index f26f1cbd43c..bd3285dc929 100644 --- a/docs/api/cli-kit/functions/node_output.formatSection.html +++ b/docs/api/cli-kit/functions/node_output.formatSection.html @@ -2,4 +2,4 @@

      Parameters

      • title: string

        The title of the message. Will be formatted as a heading.

      • body: string

        The body of the message. Will respect the original formatting.

      Returns string

      The formatted message.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.itemToString.html b/docs/api/cli-kit/functions/node_output.itemToString.html index 626b3ab5555..e376e99b142 100644 --- a/docs/api/cli-kit/functions/node_output.itemToString.html +++ b/docs/api/cli-kit/functions/node_output.itemToString.html @@ -1,4 +1,4 @@ itemToString | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.outputCompleted.html b/docs/api/cli-kit/functions/node_output.outputCompleted.html index 60edd73b5e6..ce40ee2f380 100644 --- a/docs/api/cli-kit/functions/node_output.outputCompleted.html +++ b/docs/api/cli-kit/functions/node_output.outputCompleted.html @@ -3,4 +3,4 @@ Note: Completed messages are sent through the standard output.

      Parameters

      • content: OutputMessage

        The content to be output to the user.

      • logger: Logger = consoleLog

        The logging function to use to output to the user.

        -

      Returns void

      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.outputContent.html b/docs/api/cli-kit/functions/node_output.outputContent.html index 13d0d96bdeb..704201dc936 100644 --- a/docs/api/cli-kit/functions/node_output.outputContent.html +++ b/docs/api/cli-kit/functions/node_output.outputContent.html @@ -2,4 +2,4 @@

      Parameters

      • strings: TemplateStringsArray

        The strings to join.

      • Rest ...keys: (string | ContentToken<unknown>)[]

        Array of tokens or strings to join.

      Returns TokenizedString

      The tokenized string.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.outputDebug.html b/docs/api/cli-kit/functions/node_output.outputDebug.html index 899bda5ed3d..ae9b6555191 100644 --- a/docs/api/cli-kit/functions/node_output.outputDebug.html +++ b/docs/api/cli-kit/functions/node_output.outputDebug.html @@ -3,4 +3,4 @@ Note: Debug messages are sent through the standard output.

      Parameters

      • content: OutputMessage

        The content to be output to the user.

      • logger: Logger = consoleLog

        The logging function to use to output to the user.

        -

      Returns void

      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.outputInfo.html b/docs/api/cli-kit/functions/node_output.outputInfo.html index aceff573037..adca7e69680 100644 --- a/docs/api/cli-kit/functions/node_output.outputInfo.html +++ b/docs/api/cli-kit/functions/node_output.outputInfo.html @@ -3,4 +3,4 @@ Note: Info messages are sent through the standard output.

      Parameters

      • content: OutputMessage

        The content to be output to the user.

      • logger: Logger = consoleLog

        The logging function to use to output to the user.

        -

      Returns void

      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.outputNewline.html b/docs/api/cli-kit/functions/node_output.outputNewline.html index 2f32efd2f76..aa32ed098d6 100644 --- a/docs/api/cli-kit/functions/node_output.outputNewline.html +++ b/docs/api/cli-kit/functions/node_output.outputNewline.html @@ -1,2 +1,2 @@ outputNewline | @shopify/cli-kit
      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.outputSuccess.html b/docs/api/cli-kit/functions/node_output.outputSuccess.html index 9febf3cb185..fdeafe5857c 100644 --- a/docs/api/cli-kit/functions/node_output.outputSuccess.html +++ b/docs/api/cli-kit/functions/node_output.outputSuccess.html @@ -3,4 +3,4 @@ Note: Success messages are sent through the standard output.

      Parameters

      • content: OutputMessage

        The content to be output to the user.

      • logger: Logger = consoleLog

        The logging function to use to output to the user.

        -

      Returns void

      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.outputWarn.html b/docs/api/cli-kit/functions/node_output.outputWarn.html index 770fc7614bc..1d4ea69a53e 100644 --- a/docs/api/cli-kit/functions/node_output.outputWarn.html +++ b/docs/api/cli-kit/functions/node_output.outputWarn.html @@ -3,4 +3,4 @@ Note: Warning messages are sent through the standard output.

      Parameters

      • content: OutputMessage

        The content to be output to the user.

      • logger: Logger = consoleWarn

        The logging function to use to output to the user.

        -

      Returns void

      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.outputWhereAppropriate.html b/docs/api/cli-kit/functions/node_output.outputWhereAppropriate.html index 810cf96777e..5b237e9b335 100644 --- a/docs/api/cli-kit/functions/node_output.outputWhereAppropriate.html +++ b/docs/api/cli-kit/functions/node_output.outputWhereAppropriate.html @@ -1,6 +1,5 @@ -outputWhereAppropriate | @shopify/cli-kit
      • Writes a message to the appropiated logger.

        +outputWhereAppropriate | @shopify/cli-kit
        • Writes a message to the appropiated logger.

          Parameters

          • logLevel: LogLevel

            The log level to use to determine if the message should be output.

          • logger: Logger

            The logger to use to output the message.

          • message: string

            The message to output.

            -
          • options: OutputWhereAppropriateOptions = ...

            Additional options.

            -

          Returns void

        \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.shouldDisplayColors.html b/docs/api/cli-kit/functions/node_output.shouldDisplayColors.html index 4d2a7212d83..6b6f309f993 100644 --- a/docs/api/cli-kit/functions/node_output.shouldDisplayColors.html +++ b/docs/api/cli-kit/functions/node_output.shouldDisplayColors.html @@ -1,4 +1,4 @@ shouldDisplayColors | @shopify/cli-kit
      • Checks if the console outputs should display colors or not.

        Parameters

        • _process: Process = process

          Optional, the process-like object to use to check if the console should display colors. Defaults to the global process.

        Returns boolean

        True if the console outputs should display colors, false otherwise.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.stringifyMessage.html b/docs/api/cli-kit/functions/node_output.stringifyMessage.html index b55626055ef..0634633ac96 100644 --- a/docs/api/cli-kit/functions/node_output.stringifyMessage.html +++ b/docs/api/cli-kit/functions/node_output.stringifyMessage.html @@ -1,4 +1,4 @@ stringifyMessage | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_output.unstyled.html b/docs/api/cli-kit/functions/node_output.unstyled.html index 772a731dc51..827c4410fdc 100644 --- a/docs/api/cli-kit/functions/node_output.unstyled.html +++ b/docs/api/cli-kit/functions/node_output.unstyled.html @@ -1,4 +1,4 @@ unstyled | @shopify/cli-kit
      • Returns a message without styles (colors or any ANSI escape codes).

        Parameters

        • message: string

          The message to remove styles from.

        Returns string

        The message without styles.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_path.basename.html b/docs/api/cli-kit/functions/node_path.basename.html index 8323383325f..85941d519b2 100644 --- a/docs/api/cli-kit/functions/node_path.basename.html +++ b/docs/api/cli-kit/functions/node_path.basename.html @@ -2,4 +2,4 @@

      Parameters

      • path: string

        Path to get the base name of.

      • Optional ext: string

        Optional extension to remove from the result.

      Returns string

      Base name.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_path.cwd.html b/docs/api/cli-kit/functions/node_path.cwd.html index 795d232224f..6ef37064611 100644 --- a/docs/api/cli-kit/functions/node_path.cwd.html +++ b/docs/api/cli-kit/functions/node_path.cwd.html @@ -4,4 +4,4 @@ process.cwd() to that folder, while the actual path is stored in the INIT_CWD environment variable (see here: https://docs.npmjs.com/cli/v9/commands/npm-run-script#description).

      Returns string

      The path to the current working directory.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_path.dirname.html b/docs/api/cli-kit/functions/node_path.dirname.html index 0c6739b607d..277ffd734c3 100644 --- a/docs/api/cli-kit/functions/node_path.dirname.html +++ b/docs/api/cli-kit/functions/node_path.dirname.html @@ -1,4 +1,4 @@ dirname | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_path.extname.html b/docs/api/cli-kit/functions/node_path.extname.html index 0c01a01691a..ea3602bc9c7 100644 --- a/docs/api/cli-kit/functions/node_path.extname.html +++ b/docs/api/cli-kit/functions/node_path.extname.html @@ -1,4 +1,4 @@ extname | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_path.isAbsolutePath.html b/docs/api/cli-kit/functions/node_path.isAbsolutePath.html index f168937e4d9..291c1ba7881 100644 --- a/docs/api/cli-kit/functions/node_path.isAbsolutePath.html +++ b/docs/api/cli-kit/functions/node_path.isAbsolutePath.html @@ -1,4 +1,4 @@ isAbsolutePath | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_path.isSubpath.html b/docs/api/cli-kit/functions/node_path.isSubpath.html index 78dc59b1e2c..100fe101337 100644 --- a/docs/api/cli-kit/functions/node_path.isSubpath.html +++ b/docs/api/cli-kit/functions/node_path.isSubpath.html @@ -2,4 +2,4 @@

      Parameters

      • mainPath: string

        The main path.

      • subpath: string

        The subpath.

      Returns boolean

      Whether the subpath is a subpath of the main path.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_path.joinPath.html b/docs/api/cli-kit/functions/node_path.joinPath.html index a77494cf473..22bd05764f8 100644 --- a/docs/api/cli-kit/functions/node_path.joinPath.html +++ b/docs/api/cli-kit/functions/node_path.joinPath.html @@ -1,4 +1,4 @@ joinPath | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_path.moduleDirectory.html b/docs/api/cli-kit/functions/node_path.moduleDirectory.html index 02bfe92f799..2ee909d8a58 100644 --- a/docs/api/cli-kit/functions/node_path.moduleDirectory.html +++ b/docs/api/cli-kit/functions/node_path.moduleDirectory.html @@ -1,4 +1,4 @@ moduleDirectory | @shopify/cli-kit
      • Given a module's import.meta.url it returns the directory containing the module.

        Parameters

        • moduleURL: string | URL

          The value of import.meta.url in the context of the caller module.

        Returns string

        The path to the directory containing the caller module.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_path.normalizePath.html b/docs/api/cli-kit/functions/node_path.normalizePath.html index 176f064fe8e..7f5c77c0bf9 100644 --- a/docs/api/cli-kit/functions/node_path.normalizePath.html +++ b/docs/api/cli-kit/functions/node_path.normalizePath.html @@ -1,4 +1,4 @@ normalizePath | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_path.relativePath.html b/docs/api/cli-kit/functions/node_path.relativePath.html index dc6f6d13be0..8a610008629 100644 --- a/docs/api/cli-kit/functions/node_path.relativePath.html +++ b/docs/api/cli-kit/functions/node_path.relativePath.html @@ -2,4 +2,4 @@

      Parameters

      • from: string

        Path to resolve from.

      • to: string

        Path to resolve to.

      Returns string

      Relative path.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_path.relativizePath.html b/docs/api/cli-kit/functions/node_path.relativizePath.html index 35a576ce28a..55f51819ad7 100644 --- a/docs/api/cli-kit/functions/node_path.relativizePath.html +++ b/docs/api/cli-kit/functions/node_path.relativizePath.html @@ -5,4 +5,4 @@

      Parameters

      • path: string

        Path to relativize.

      • dir: string = ...

        Current working directory.

      Returns string

      Relativized path.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_path.resolvePath.html b/docs/api/cli-kit/functions/node_path.resolvePath.html index 7359405477e..4b5dd3a7e97 100644 --- a/docs/api/cli-kit/functions/node_path.resolvePath.html +++ b/docs/api/cli-kit/functions/node_path.resolvePath.html @@ -1,4 +1,4 @@ resolvePath | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_path.sniffForJson.html b/docs/api/cli-kit/functions/node_path.sniffForJson.html index 34a028c7eb4..cc5fa72fe92 100644 --- a/docs/api/cli-kit/functions/node_path.sniffForJson.html +++ b/docs/api/cli-kit/functions/node_path.sniffForJson.html @@ -1,4 +1,4 @@ -sniffForJson | @shopify/cli-kit
      • Returns whether the --json flag is present in the arguments.

        -

        Parameters

        • argv: string[] = process.argv

          The arguments to search for the --json flag.

          -

        Returns boolean

        Whether the --json flag is present in the arguments.

        -
      \ No newline at end of file +sniffForJson | @shopify/cli-kit
      • Returns whether the --json or -j flags are present in the arguments.

        +

        Parameters

        • argv: string[] = process.argv

          The arguments to search for the --json and -j flags.

          +

        Returns boolean

        Whether the --json or -j flag is present in the arguments.

        +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_path.sniffForPath.html b/docs/api/cli-kit/functions/node_path.sniffForPath.html index 5d0874c3244..72bd53bf869 100644 --- a/docs/api/cli-kit/functions/node_path.sniffForPath.html +++ b/docs/api/cli-kit/functions/node_path.sniffForPath.html @@ -1,4 +1,4 @@ sniffForPath | @shopify/cli-kit
      • Tries to get the value of the --path argument, if provided.

        Parameters

        • argv: string[] = process.argv

          The arguments to search for the --path argument.

        Returns string | undefined

        The value of the --path argument, if provided.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_plugins.fanoutHooks.html b/docs/api/cli-kit/functions/node_plugins.fanoutHooks.html index 167aa013b4a..c503e807dde 100644 --- a/docs/api/cli-kit/functions/node_plugins.fanoutHooks.html +++ b/docs/api/cli-kit/functions/node_plugins.fanoutHooks.html @@ -6,4 +6,4 @@
    • options: TPluginMap[TEvent]["options"]

      The options to pass to the hook.

    • Optional timeout: number

      The timeout to use for the hook.

    • Returns Promise<Partial<TPluginMap[typeof event]["pluginReturns"]>>

      A dictionary of plug-in names to the response from the hook.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_plugins.getListOfTunnelPlugins.html b/docs/api/cli-kit/functions/node_plugins.getListOfTunnelPlugins.html index a3c0a9fdfe8..97941f996ba 100644 --- a/docs/api/cli-kit/functions/node_plugins.getListOfTunnelPlugins.html +++ b/docs/api/cli-kit/functions/node_plugins.getListOfTunnelPlugins.html @@ -2,4 +2,4 @@ Fail if there are multiple plugins for the same provider.

      Parameters

      • config: Config

        Oclif config used to execute hooks.

      Returns Promise<{
          error?: string;
          plugins: string[];
      }>

      List of available tunnel plugins.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_plugins_tunnel.defineProvider.html b/docs/api/cli-kit/functions/node_plugins_tunnel.defineProvider.html index fc80953a9ca..d2a8b6a15cb 100644 --- a/docs/api/cli-kit/functions/node_plugins_tunnel.defineProvider.html +++ b/docs/api/cli-kit/functions/node_plugins_tunnel.defineProvider.html @@ -1 +1 @@ -defineProvider | @shopify/cli-kit
      \ No newline at end of file +defineProvider | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_plugins_tunnel.startTunnel.html b/docs/api/cli-kit/functions/node_plugins_tunnel.startTunnel.html index 4b9a48a3aff..a04b8943503 100644 --- a/docs/api/cli-kit/functions/node_plugins_tunnel.startTunnel.html +++ b/docs/api/cli-kit/functions/node_plugins_tunnel.startTunnel.html @@ -1 +1 @@ -startTunnel | @shopify/cli-kit
      \ No newline at end of file +startTunnel | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_promises.flushPromises.html b/docs/api/cli-kit/functions/node_promises.flushPromises.html index b435200a51e..299cc861fb4 100644 --- a/docs/api/cli-kit/functions/node_promises.flushPromises.html +++ b/docs/api/cli-kit/functions/node_promises.flushPromises.html @@ -1,3 +1,3 @@ flushPromises | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_result.err-1.html b/docs/api/cli-kit/functions/node_result.err-1.html index 552144adf77..f1530c5d44c 100644 --- a/docs/api/cli-kit/functions/node_result.err-1.html +++ b/docs/api/cli-kit/functions/node_result.err-1.html @@ -1,4 +1,4 @@ err | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_result.ok-1.html b/docs/api/cli-kit/functions/node_result.ok-1.html index 12464bd1658..9be28bd45d1 100644 --- a/docs/api/cli-kit/functions/node_result.ok-1.html +++ b/docs/api/cli-kit/functions/node_result.ok-1.html @@ -1,4 +1,4 @@ ok | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_schema.deepStrict.html b/docs/api/cli-kit/functions/node_schema.deepStrict.html index 980159eb734..4fa54849e25 100644 --- a/docs/api/cli-kit/functions/node_schema.deepStrict.html +++ b/docs/api/cli-kit/functions/node_schema.deepStrict.html @@ -1,4 +1,4 @@ deepStrict | @shopify/cli-kit
      • Returns a new schema that is the same as the input schema, but with all nested schemas set to strict.

        Type Parameters

        • T

        Parameters

        • schema: T

          The schema to make strict.

        Returns T

        The result strict schema.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_schema.errorsToString.html b/docs/api/cli-kit/functions/node_schema.errorsToString.html index 06876049326..5845076af0f 100644 --- a/docs/api/cli-kit/functions/node_schema.errorsToString.html +++ b/docs/api/cli-kit/functions/node_schema.errorsToString.html @@ -1,4 +1,4 @@ errorsToString | @shopify/cli-kit
      • Returns a human-readable string of the list of zod errors.

        Parameters

        • errors: ZodIssueBase[]

          The list of zod errors.

        Returns string

        The human-readable string.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_session.ensureAuthenticatedAdmin.html b/docs/api/cli-kit/functions/node_session.ensureAuthenticatedAdmin.html index 62dc0e25b5c..fb7cbc82516 100644 --- a/docs/api/cli-kit/functions/node_session.ensureAuthenticatedAdmin.html +++ b/docs/api/cli-kit/functions/node_session.ensureAuthenticatedAdmin.html @@ -4,4 +4,4 @@
    • forceRefresh: boolean = false

      Optional flag to force a refresh of the token.

    • options: EnsureAuthenticatedAdditionalOptions = {}

      Optional extra options to use.

    • Returns Promise<AdminSession>

      The access token for the Admin API.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_session.ensureAuthenticatedAppManagement.html b/docs/api/cli-kit/functions/node_session.ensureAuthenticatedAppManagement.html index e9a4ee4eaf4..d3b0eb0bfdd 100644 --- a/docs/api/cli-kit/functions/node_session.ensureAuthenticatedAppManagement.html +++ b/docs/api/cli-kit/functions/node_session.ensureAuthenticatedAppManagement.html @@ -3,4 +3,4 @@
    • env: ProcessEnv = process.env

      Optional environment variables to use.

    • options: EnsureAuthenticatedAdditionalOptions = {}

      Optional extra options to use.

    • Returns Promise<{
          token: string;
          userId: string;
      }>

      The access token for the App Management API.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_session.ensureAuthenticatedBusinessPlatform.html b/docs/api/cli-kit/functions/node_session.ensureAuthenticatedBusinessPlatform.html index ac9a46512e9..058cf1d2a7f 100644 --- a/docs/api/cli-kit/functions/node_session.ensureAuthenticatedBusinessPlatform.html +++ b/docs/api/cli-kit/functions/node_session.ensureAuthenticatedBusinessPlatform.html @@ -1,4 +1,4 @@ ensureAuthenticatedBusinessPlatform | @shopify/cli-kit

      Function ensureAuthenticatedBusinessPlatform

      • Ensure that we have a valid session to access the Business Platform API.

        Parameters

        • scopes: "destinations"[] = []

          Optional array of extra scopes to authenticate with.

        Returns Promise<string>

        The access token for the Business Platform API.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_session.ensureAuthenticatedPartners.html b/docs/api/cli-kit/functions/node_session.ensureAuthenticatedPartners.html index f1aa688633c..cf793d6ba16 100644 --- a/docs/api/cli-kit/functions/node_session.ensureAuthenticatedPartners.html +++ b/docs/api/cli-kit/functions/node_session.ensureAuthenticatedPartners.html @@ -5,4 +5,4 @@
    • env: ProcessEnv = process.env

      Optional environment variables to use.

    • options: EnsureAuthenticatedAdditionalOptions = {}

      Optional extra options to use.

    • Returns Promise<{
          token: string;
          userId: string;
      }>

      The access token for the Partners API.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_session.ensureAuthenticatedStorefront.html b/docs/api/cli-kit/functions/node_session.ensureAuthenticatedStorefront.html index 6eb43f043e4..037344c5102 100644 --- a/docs/api/cli-kit/functions/node_session.ensureAuthenticatedStorefront.html +++ b/docs/api/cli-kit/functions/node_session.ensureAuthenticatedStorefront.html @@ -3,4 +3,4 @@
    • password: undefined | string = undefined

      Optional password to use.

    • forceRefresh: boolean = false

      Optional flag to force a refresh of the token.

    • Returns Promise<string>

      The access token for the Storefront API.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_session.ensureAuthenticatedThemes.html b/docs/api/cli-kit/functions/node_session.ensureAuthenticatedThemes.html index 7be525b93b4..0ec4c28e088 100644 --- a/docs/api/cli-kit/functions/node_session.ensureAuthenticatedThemes.html +++ b/docs/api/cli-kit/functions/node_session.ensureAuthenticatedThemes.html @@ -6,4 +6,4 @@
    • scopes: AdminAPIScope[] = []

      Optional array of extra scopes to authenticate with.

    • forceRefresh: boolean = false

      Optional flag to force a refresh of the token.

    • Returns Promise<AdminSession>

      The access token and store.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_session.logout.html b/docs/api/cli-kit/functions/node_session.logout.html index f778850bcee..ae0d1f7baff 100644 --- a/docs/api/cli-kit/functions/node_session.logout.html +++ b/docs/api/cli-kit/functions/node_session.logout.html @@ -1,3 +1,3 @@ logout | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_system.captureOutput.html b/docs/api/cli-kit/functions/node_system.captureOutput.html index 394009213a8..0319158aba6 100644 --- a/docs/api/cli-kit/functions/node_system.captureOutput.html +++ b/docs/api/cli-kit/functions/node_system.captureOutput.html @@ -3,4 +3,4 @@
    • args: string[]

      Arguments to pass to the command.

    • Optional options: ExecOptions

      Optional settings for how to run the command.

    • Returns Promise<string>

      A promise that resolves with the aggregatted stdout of the command.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_system.exec.html b/docs/api/cli-kit/functions/node_system.exec.html index f5b10b94874..36ec3a86e42 100644 --- a/docs/api/cli-kit/functions/node_system.exec.html +++ b/docs/api/cli-kit/functions/node_system.exec.html @@ -2,4 +2,4 @@

      Parameters

      • command: string

        Command to be executed.

      • args: string[]

        Arguments to pass to the command.

      • Optional options: ExecOptions

        Optional settings for how to run the command.

        -

      Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_system.openURL.html b/docs/api/cli-kit/functions/node_system.openURL.html index d969597b622..45d71501830 100644 --- a/docs/api/cli-kit/functions/node_system.openURL.html +++ b/docs/api/cli-kit/functions/node_system.openURL.html @@ -1,3 +1,3 @@ openURL | @shopify/cli-kit
      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_system.sleep.html b/docs/api/cli-kit/functions/node_system.sleep.html index 185080fc6e9..50b1b03e3eb 100644 --- a/docs/api/cli-kit/functions/node_system.sleep.html +++ b/docs/api/cli-kit/functions/node_system.sleep.html @@ -1,4 +1,4 @@ sleep | @shopify/cli-kit
      • Waits for a given number of seconds.

        Parameters

        • seconds: number

          Number of seconds to wait.

        Returns Promise<void>

        A Promise resolving after the number of seconds.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_system.terminalSupportsPrompting.html b/docs/api/cli-kit/functions/node_system.terminalSupportsPrompting.html index 7050244b83a..50ec5c8b519 100644 --- a/docs/api/cli-kit/functions/node_system.terminalSupportsPrompting.html +++ b/docs/api/cli-kit/functions/node_system.terminalSupportsPrompting.html @@ -1,3 +1,3 @@ terminalSupportsPrompting | @shopify/cli-kit
      • Check if the standard input and output streams support prompting.

        Returns boolean

        True if the standard input and output streams support prompting.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_tcp.checkPortAvailability.html b/docs/api/cli-kit/functions/node_tcp.checkPortAvailability.html index 0d7ac573cf9..609e473e33a 100644 --- a/docs/api/cli-kit/functions/node_tcp.checkPortAvailability.html +++ b/docs/api/cli-kit/functions/node_tcp.checkPortAvailability.html @@ -1,4 +1,4 @@ checkPortAvailability | @shopify/cli-kit

      Function checkPortAvailability

      • Checks if a port is available.

        Parameters

        • portNumber: number

          The port number to check.

        Returns Promise<boolean>

        A promise that resolves with a boolean indicating if the port is available.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_tcp.getAvailableTCPPort.html b/docs/api/cli-kit/functions/node_tcp.getAvailableTCPPort.html index 5f340647e79..19f0a094f81 100644 --- a/docs/api/cli-kit/functions/node_tcp.getAvailableTCPPort.html +++ b/docs/api/cli-kit/functions/node_tcp.getAvailableTCPPort.html @@ -2,4 +2,4 @@

      Parameters

      • Optional preferredPort: number

        Number of the preferred port to be used if available.

      • Optional options: GetTCPPortOptions

        Extra configuration for getting TCP ports.

      Returns Promise<number>

      A promise that resolves with an availabe port.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_testing_output.mockAndCaptureOutput.html b/docs/api/cli-kit/functions/node_testing_output.mockAndCaptureOutput.html index 27aba495f4b..d87a6a9995e 100644 --- a/docs/api/cli-kit/functions/node_testing_output.mockAndCaptureOutput.html +++ b/docs/api/cli-kit/functions/node_testing_output.mockAndCaptureOutput.html @@ -1,3 +1,3 @@ mockAndCaptureOutput | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_testing_ui.getLastFrameAfterUnmount.html b/docs/api/cli-kit/functions/node_testing_ui.getLastFrameAfterUnmount.html index 316bfa7f74f..e6cc5f65639 100644 --- a/docs/api/cli-kit/functions/node_testing_ui.getLastFrameAfterUnmount.html +++ b/docs/api/cli-kit/functions/node_testing_ui.getLastFrameAfterUnmount.html @@ -1,3 +1,3 @@ getLastFrameAfterUnmount | @shopify/cli-kit
      • Function that is useful when you want to check the last frame of a component that unmounted.

        The reason this function exists is that in CI Ink will clear the last frame on unmount.

        -

        Parameters

        • renderInstance: Instance

        Returns undefined | string

      \ No newline at end of file +

      Parameters

      • renderInstance: Instance

      Returns undefined | string

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_testing_ui.render.html b/docs/api/cli-kit/functions/node_testing_ui.render.html index 50a958d8324..ce8e9d380f9 100644 --- a/docs/api/cli-kit/functions/node_testing_ui.render.html +++ b/docs/api/cli-kit/functions/node_testing_ui.render.html @@ -1 +1 @@ -render | @shopify/cli-kit
      \ No newline at end of file +render | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_testing_ui.sendInputAndWait.html b/docs/api/cli-kit/functions/node_testing_ui.sendInputAndWait.html index 3686c0a52b1..18426c5afd0 100644 --- a/docs/api/cli-kit/functions/node_testing_ui.sendInputAndWait.html +++ b/docs/api/cli-kit/functions/node_testing_ui.sendInputAndWait.html @@ -2,4 +2,4 @@

      Useful if you know some what will happen after input will take a certain amount of time and it will not cause any visible change so you can't use sendInputAndWaitForChange. This function can also be used if you want to test that nothing changes after some input has been sent.

      -

      Parameters

      • renderInstance: Instance
      • waitTime: number
      • Rest ...inputs: string[]

      Returns Promise<void>

      \ No newline at end of file +

      Parameters

      • renderInstance: Instance
      • waitTime: number
      • Rest ...inputs: string[]

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_testing_ui.sendInputAndWaitForChange.html b/docs/api/cli-kit/functions/node_testing_ui.sendInputAndWaitForChange.html index e3ad632fa5c..1c6e3ad5e2e 100644 --- a/docs/api/cli-kit/functions/node_testing_ui.sendInputAndWaitForChange.html +++ b/docs/api/cli-kit/functions/node_testing_ui.sendInputAndWaitForChange.html @@ -1,4 +1,4 @@ sendInputAndWaitForChange | @shopify/cli-kit
      • Send input and wait for the last frame to change.

        Useful when you want to send some input and wait for anything to change in the interface. If you need to wait for a specific change instead, you can use sendInputAndWaitForContent.

        -

        Parameters

        • renderInstance: Instance
        • Rest ...inputs: string[]

        Returns Promise<void>

      \ No newline at end of file +

      Parameters

      • renderInstance: Instance
      • Rest ...inputs: string[]

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_testing_ui.sendInputAndWaitForContent.html b/docs/api/cli-kit/functions/node_testing_ui.sendInputAndWaitForContent.html index 2682c344df2..13da6c4988f 100644 --- a/docs/api/cli-kit/functions/node_testing_ui.sendInputAndWaitForContent.html +++ b/docs/api/cli-kit/functions/node_testing_ui.sendInputAndWaitForContent.html @@ -1,4 +1,4 @@ sendInputAndWaitForContent | @shopify/cli-kit
      • Send input and wait for the last frame to contain specific text.

        Useful when you want to send some input and wait for a specific change to happen. If you need to wait for any change instead, you can use sendInputAndWaitForChange.

        -

        Parameters

        • renderInstance: Instance
        • content: string
        • Rest ...inputs: string[]

        Returns Promise<void>

      \ No newline at end of file +

      Parameters

      • renderInstance: Instance
      • content: string
      • Rest ...inputs: string[]

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_testing_ui.waitForContent.html b/docs/api/cli-kit/functions/node_testing_ui.waitForContent.html index 2673c69e2f8..15f757a22a7 100644 --- a/docs/api/cli-kit/functions/node_testing_ui.waitForContent.html +++ b/docs/api/cli-kit/functions/node_testing_ui.waitForContent.html @@ -1,2 +1,2 @@ waitForContent | @shopify/cli-kit
      • Wait for the last frame to contain specific text.

        -

        Parameters

        • renderInstance: Instance
        • content: string
        • func: (() => void) = ...
            • (): void
            • Returns void

        Returns Promise<void>

      \ No newline at end of file +

      Parameters

      • renderInstance: Instance
      • content: string
      • func: (() => void) = ...
          • (): void
          • Returns void

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_testing_ui.waitForInputsToBeReady.html b/docs/api/cli-kit/functions/node_testing_ui.waitForInputsToBeReady.html index 2cb30628a6d..0b9f527155e 100644 --- a/docs/api/cli-kit/functions/node_testing_ui.waitForInputsToBeReady.html +++ b/docs/api/cli-kit/functions/node_testing_ui.waitForInputsToBeReady.html @@ -1,2 +1,2 @@ waitForInputsToBeReady | @shopify/cli-kit
      \ No newline at end of file +

      Returns Promise<unknown>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_api.bulkUploadThemeAssets.html b/docs/api/cli-kit/functions/node_themes_api.bulkUploadThemeAssets.html index 8eda8a79309..236dc7c77f2 100644 --- a/docs/api/cli-kit/functions/node_themes_api.bulkUploadThemeAssets.html +++ b/docs/api/cli-kit/functions/node_themes_api.bulkUploadThemeAssets.html @@ -1 +1 @@ -bulkUploadThemeAssets | @shopify/cli-kit
      \ No newline at end of file +bulkUploadThemeAssets | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_api.createTheme.html b/docs/api/cli-kit/functions/node_themes_api.createTheme.html index a7268173103..557d4b2e7d6 100644 --- a/docs/api/cli-kit/functions/node_themes_api.createTheme.html +++ b/docs/api/cli-kit/functions/node_themes_api.createTheme.html @@ -1 +1 @@ -createTheme | @shopify/cli-kit
      \ No newline at end of file +createTheme | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_api.deleteThemeAsset.html b/docs/api/cli-kit/functions/node_themes_api.deleteThemeAsset.html index 5d67169811d..67de96da2d6 100644 --- a/docs/api/cli-kit/functions/node_themes_api.deleteThemeAsset.html +++ b/docs/api/cli-kit/functions/node_themes_api.deleteThemeAsset.html @@ -1 +1 @@ -deleteThemeAsset | @shopify/cli-kit
      \ No newline at end of file +deleteThemeAsset | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_api.fetchChecksums.html b/docs/api/cli-kit/functions/node_themes_api.fetchChecksums.html index f67b4b2677d..fe03547b9ac 100644 --- a/docs/api/cli-kit/functions/node_themes_api.fetchChecksums.html +++ b/docs/api/cli-kit/functions/node_themes_api.fetchChecksums.html @@ -1 +1 @@ -fetchChecksums | @shopify/cli-kit
      \ No newline at end of file +fetchChecksums | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_api.fetchTheme.html b/docs/api/cli-kit/functions/node_themes_api.fetchTheme.html index 001eb85a3f9..303831024cb 100644 --- a/docs/api/cli-kit/functions/node_themes_api.fetchTheme.html +++ b/docs/api/cli-kit/functions/node_themes_api.fetchTheme.html @@ -1 +1 @@ -fetchTheme | @shopify/cli-kit
      \ No newline at end of file +fetchTheme | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_api.fetchThemeAssets.html b/docs/api/cli-kit/functions/node_themes_api.fetchThemeAssets.html index 0c8378966cd..c503d015465 100644 --- a/docs/api/cli-kit/functions/node_themes_api.fetchThemeAssets.html +++ b/docs/api/cli-kit/functions/node_themes_api.fetchThemeAssets.html @@ -1 +1 @@ -fetchThemeAssets | @shopify/cli-kit
      \ No newline at end of file +fetchThemeAssets | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_api.fetchThemes.html b/docs/api/cli-kit/functions/node_themes_api.fetchThemes.html index 8d720d484ff..358387d9c76 100644 --- a/docs/api/cli-kit/functions/node_themes_api.fetchThemes.html +++ b/docs/api/cli-kit/functions/node_themes_api.fetchThemes.html @@ -1 +1 @@ -fetchThemes | @shopify/cli-kit
      \ No newline at end of file +fetchThemes | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_api.themeDelete.html b/docs/api/cli-kit/functions/node_themes_api.themeDelete.html index a7926b4ce2b..bbf9740b314 100644 --- a/docs/api/cli-kit/functions/node_themes_api.themeDelete.html +++ b/docs/api/cli-kit/functions/node_themes_api.themeDelete.html @@ -1 +1 @@ -themeDelete | @shopify/cli-kit
      \ No newline at end of file +themeDelete | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_api.themePublish.html b/docs/api/cli-kit/functions/node_themes_api.themePublish.html index 78c6c1a0195..e89d159091a 100644 --- a/docs/api/cli-kit/functions/node_themes_api.themePublish.html +++ b/docs/api/cli-kit/functions/node_themes_api.themePublish.html @@ -1 +1 @@ -themePublish | @shopify/cli-kit
      \ No newline at end of file +themePublish | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_api.themeUpdate.html b/docs/api/cli-kit/functions/node_themes_api.themeUpdate.html index 1827fe16150..924a9230417 100644 --- a/docs/api/cli-kit/functions/node_themes_api.themeUpdate.html +++ b/docs/api/cli-kit/functions/node_themes_api.themeUpdate.html @@ -1 +1 @@ -themeUpdate | @shopify/cli-kit
      \ No newline at end of file +themeUpdate | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_conf.getHostTheme.html b/docs/api/cli-kit/functions/node_themes_conf.getHostTheme.html index 6492efd28e8..02bb9f7673b 100644 --- a/docs/api/cli-kit/functions/node_themes_conf.getHostTheme.html +++ b/docs/api/cli-kit/functions/node_themes_conf.getHostTheme.html @@ -1 +1 @@ -getHostTheme | @shopify/cli-kit
      \ No newline at end of file +getHostTheme | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_conf.hostThemeLocalStorage.html b/docs/api/cli-kit/functions/node_themes_conf.hostThemeLocalStorage.html index bad83ea49c0..89d3a76e246 100644 --- a/docs/api/cli-kit/functions/node_themes_conf.hostThemeLocalStorage.html +++ b/docs/api/cli-kit/functions/node_themes_conf.hostThemeLocalStorage.html @@ -1 +1 @@ -hostThemeLocalStorage | @shopify/cli-kit
      \ No newline at end of file +hostThemeLocalStorage | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_conf.removeHostTheme.html b/docs/api/cli-kit/functions/node_themes_conf.removeHostTheme.html index 8b2b8aff507..19d46131f6b 100644 --- a/docs/api/cli-kit/functions/node_themes_conf.removeHostTheme.html +++ b/docs/api/cli-kit/functions/node_themes_conf.removeHostTheme.html @@ -1 +1 @@ -removeHostTheme | @shopify/cli-kit
      \ No newline at end of file +removeHostTheme | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_conf.setHostTheme.html b/docs/api/cli-kit/functions/node_themes_conf.setHostTheme.html index 22ce3ef5d00..e15b750e1ed 100644 --- a/docs/api/cli-kit/functions/node_themes_conf.setHostTheme.html +++ b/docs/api/cli-kit/functions/node_themes_conf.setHostTheme.html @@ -1 +1 @@ -setHostTheme | @shopify/cli-kit
      \ No newline at end of file +setHostTheme | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_factories.buildBulkUploadResults.html b/docs/api/cli-kit/functions/node_themes_factories.buildBulkUploadResults.html deleted file mode 100644 index 9b29f7e60dd..00000000000 --- a/docs/api/cli-kit/functions/node_themes_factories.buildBulkUploadResults.html +++ /dev/null @@ -1 +0,0 @@ -buildBulkUploadResults | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_factories.buildChecksum.html b/docs/api/cli-kit/functions/node_themes_factories.buildChecksum.html index 909fc89e934..2e0bcb445ae 100644 --- a/docs/api/cli-kit/functions/node_themes_factories.buildChecksum.html +++ b/docs/api/cli-kit/functions/node_themes_factories.buildChecksum.html @@ -1 +1 @@ -buildChecksum | @shopify/cli-kit
      \ No newline at end of file +buildChecksum | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_factories.buildTheme.html b/docs/api/cli-kit/functions/node_themes_factories.buildTheme.html index 670a7a46972..6ec948e231f 100644 --- a/docs/api/cli-kit/functions/node_themes_factories.buildTheme.html +++ b/docs/api/cli-kit/functions/node_themes_factories.buildTheme.html @@ -1 +1 @@ -buildTheme | @shopify/cli-kit
      \ No newline at end of file +buildTheme | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_factories.buildThemeAsset.html b/docs/api/cli-kit/functions/node_themes_factories.buildThemeAsset.html index 2158b74ea3e..e56453ebfc1 100644 --- a/docs/api/cli-kit/functions/node_themes_factories.buildThemeAsset.html +++ b/docs/api/cli-kit/functions/node_themes_factories.buildThemeAsset.html @@ -1 +1 @@ -buildThemeAsset | @shopify/cli-kit
      \ No newline at end of file +buildThemeAsset | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_urls.codeEditorUrl.html b/docs/api/cli-kit/functions/node_themes_urls.codeEditorUrl.html index c7872d387bc..a82ec5aafcb 100644 --- a/docs/api/cli-kit/functions/node_themes_urls.codeEditorUrl.html +++ b/docs/api/cli-kit/functions/node_themes_urls.codeEditorUrl.html @@ -1 +1 @@ -codeEditorUrl | @shopify/cli-kit
      \ No newline at end of file +codeEditorUrl | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_urls.storeAdminUrl.html b/docs/api/cli-kit/functions/node_themes_urls.storeAdminUrl.html index 311e9a1c58a..cbbc542efc2 100644 --- a/docs/api/cli-kit/functions/node_themes_urls.storeAdminUrl.html +++ b/docs/api/cli-kit/functions/node_themes_urls.storeAdminUrl.html @@ -1 +1 @@ -storeAdminUrl | @shopify/cli-kit
      \ No newline at end of file +storeAdminUrl | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_urls.storePasswordPage.html b/docs/api/cli-kit/functions/node_themes_urls.storePasswordPage.html index 2463b1a9a28..e922e4f7043 100644 --- a/docs/api/cli-kit/functions/node_themes_urls.storePasswordPage.html +++ b/docs/api/cli-kit/functions/node_themes_urls.storePasswordPage.html @@ -1 +1 @@ -storePasswordPage | @shopify/cli-kit
      \ No newline at end of file +storePasswordPage | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_urls.themeEditorUrl.html b/docs/api/cli-kit/functions/node_themes_urls.themeEditorUrl.html index c735238f6ae..5f9ece96561 100644 --- a/docs/api/cli-kit/functions/node_themes_urls.themeEditorUrl.html +++ b/docs/api/cli-kit/functions/node_themes_urls.themeEditorUrl.html @@ -1 +1 @@ -themeEditorUrl | @shopify/cli-kit
      \ No newline at end of file +themeEditorUrl | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_urls.themePreviewUrl.html b/docs/api/cli-kit/functions/node_themes_urls.themePreviewUrl.html index 9180de9070b..5226c15c292 100644 --- a/docs/api/cli-kit/functions/node_themes_urls.themePreviewUrl.html +++ b/docs/api/cli-kit/functions/node_themes_urls.themePreviewUrl.html @@ -1 +1 @@ -themePreviewUrl | @shopify/cli-kit
      \ No newline at end of file +themePreviewUrl | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_utils.composeThemeGid.html b/docs/api/cli-kit/functions/node_themes_utils.composeThemeGid.html index 301bfbb1428..5a04c69e0fe 100644 --- a/docs/api/cli-kit/functions/node_themes_utils.composeThemeGid.html +++ b/docs/api/cli-kit/functions/node_themes_utils.composeThemeGid.html @@ -1 +1 @@ -composeThemeGid | @shopify/cli-kit
      \ No newline at end of file +composeThemeGid | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_utils.isDevelopmentTheme.html b/docs/api/cli-kit/functions/node_themes_utils.isDevelopmentTheme.html index 4509d185ef6..f1941c28c9d 100644 --- a/docs/api/cli-kit/functions/node_themes_utils.isDevelopmentTheme.html +++ b/docs/api/cli-kit/functions/node_themes_utils.isDevelopmentTheme.html @@ -1 +1 @@ -isDevelopmentTheme | @shopify/cli-kit
      \ No newline at end of file +isDevelopmentTheme | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_utils.parseGid.html b/docs/api/cli-kit/functions/node_themes_utils.parseGid.html index 06cc5699607..9482cef7861 100644 --- a/docs/api/cli-kit/functions/node_themes_utils.parseGid.html +++ b/docs/api/cli-kit/functions/node_themes_utils.parseGid.html @@ -1 +1 @@ -parseGid | @shopify/cli-kit
      \ No newline at end of file +parseGid | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_themes_utils.promptThemeName.html b/docs/api/cli-kit/functions/node_themes_utils.promptThemeName.html index 2f26ca439d6..00a8fcb93ea 100644 --- a/docs/api/cli-kit/functions/node_themes_utils.promptThemeName.html +++ b/docs/api/cli-kit/functions/node_themes_utils.promptThemeName.html @@ -1 +1 @@ -promptThemeName | @shopify/cli-kit
      \ No newline at end of file +promptThemeName | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_toml.decodeToml.html b/docs/api/cli-kit/functions/node_toml.decodeToml.html index fc8649c9ff2..87638d109b6 100644 --- a/docs/api/cli-kit/functions/node_toml.decodeToml.html +++ b/docs/api/cli-kit/functions/node_toml.decodeToml.html @@ -1,4 +1,4 @@ decodeToml | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_toml.encodeToml.html b/docs/api/cli-kit/functions/node_toml.encodeToml.html index e6b8acbd606..de8eb63b9f8 100644 --- a/docs/api/cli-kit/functions/node_toml.encodeToml.html +++ b/docs/api/cli-kit/functions/node_toml.encodeToml.html @@ -1,4 +1,4 @@ encodeToml | @shopify/cli-kit
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_tree_kill.treeKill.html b/docs/api/cli-kit/functions/node_tree_kill.treeKill.html index 05cef5207aa..acaed4db1d8 100644 --- a/docs/api/cli-kit/functions/node_tree_kill.treeKill.html +++ b/docs/api/cli-kit/functions/node_tree_kill.treeKill.html @@ -3,4 +3,4 @@
    • killSignal: string = 'SIGTERM'

      Type of kill signal to be used.

    • killRoot: boolean = true

      Whether to kill the root process.

    • Optional callback: AfterKillCallback

      Optional callback to run after killing the processes.

      -
    • Returns void

      \ No newline at end of file +

      Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.handleCtrlC.html b/docs/api/cli-kit/functions/node_ui.handleCtrlC.html index 4ee28f10148..228b05c41c9 100644 --- a/docs/api/cli-kit/functions/node_ui.handleCtrlC.html +++ b/docs/api/cli-kit/functions/node_ui.handleCtrlC.html @@ -1 +1 @@ -handleCtrlC | @shopify/cli-kit
      \ No newline at end of file +handleCtrlC | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.isTTY.html b/docs/api/cli-kit/functions/node_ui.isTTY.html index b35139821a5..f9f384e9df6 100644 --- a/docs/api/cli-kit/functions/node_ui.isTTY.html +++ b/docs/api/cli-kit/functions/node_ui.isTTY.html @@ -1 +1 @@ -isTTY | @shopify/cli-kit
      \ No newline at end of file +isTTY | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.keypress.html b/docs/api/cli-kit/functions/node_ui.keypress.html index 055177d5e5e..77af85aaa86 100644 --- a/docs/api/cli-kit/functions/node_ui.keypress.html +++ b/docs/api/cli-kit/functions/node_ui.keypress.html @@ -1,2 +1,2 @@ keypress | @shopify/cli-kit
      • Waits for any key to be pressed except Ctrl+C which will terminate the process.

        -

        Parameters

        • stdin: ReadStream & {} = process.stdin
        • uiDebugOptions: UIDebugOptions = defaultUIDebugOptions

        Returns Promise<unknown>

      \ No newline at end of file +

      Parameters

      • stdin: ReadStream & {} = process.stdin
      • uiDebugOptions: UIDebugOptions = defaultUIDebugOptions

      Returns Promise<unknown>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.render.html b/docs/api/cli-kit/functions/node_ui.render.html index b7929f2b2f8..a9b2c3ebc71 100644 --- a/docs/api/cli-kit/functions/node_ui.render.html +++ b/docs/api/cli-kit/functions/node_ui.render.html @@ -1 +1 @@ -render | @shopify/cli-kit
      \ No newline at end of file +render | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.renderAutocompletePrompt.html b/docs/api/cli-kit/functions/node_ui.renderAutocompletePrompt.html index adb1a06f4c8..510a8aaf904 100644 --- a/docs/api/cli-kit/functions/node_ui.renderAutocompletePrompt.html +++ b/docs/api/cli-kit/functions/node_ui.renderAutocompletePrompt.html @@ -1,4 +1,4 @@ renderAutocompletePrompt | @shopify/cli-kit

      Function renderAutocompletePrompt

      • Renders an autocomplete prompt to the console.

        Type Parameters

        • T

        Parameters

        Returns Promise<T>

        Example

        ?  Select a template:   Type to search...

        Info message title

        Info message body

        > first
        second
        third
        fourth
        fifth
        sixth
        seventh
        eighth
        ninth
        tenth
        eleventh
        twelfth
        thirteenth
        fourteenth
        fifteenth
        sixteenth
        seventeenth
        eighteenth
        nineteenth (disabled)
        twentieth
        twenty-first
        twenty-second
        twenty-third
        twenty-fourth
        twenty-fifth

        Press ↑↓ arrows to select, enter to confirm.
        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.renderConcurrent.html b/docs/api/cli-kit/functions/node_ui.renderConcurrent.html index 83ba2dfc3d7..da9aa58425b 100644 --- a/docs/api/cli-kit/functions/node_ui.renderConcurrent.html +++ b/docs/api/cli-kit/functions/node_ui.renderConcurrent.html @@ -1,4 +1,4 @@ renderConcurrent | @shopify/cli-kit
      • Renders output from concurrent processes to the terminal with ConcurrentOutput.

        Parameters

        Returns Promise<unknown>

        Example

        00:00:00backendfirst backend message
        00:00:00backendsecond backend message
        00:00:00backendthird backend message
        00:00:00frontendfirst frontend message
        00:00:00frontendsecond frontend message
        00:00:00frontendthird frontend message
        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.renderConfirmationPrompt.html b/docs/api/cli-kit/functions/node_ui.renderConfirmationPrompt.html index b602e0592e2..164b9411600 100644 --- a/docs/api/cli-kit/functions/node_ui.renderConfirmationPrompt.html +++ b/docs/api/cli-kit/functions/node_ui.renderConfirmationPrompt.html @@ -1,4 +1,4 @@ renderConfirmationPrompt | @shopify/cli-kit

      Function renderConfirmationPrompt

      • Renders a confirmation prompt to the console.

        Parameters

        Returns Promise<boolean>

        Example

        ?  Delete the following themes from the store?

        Info message title

        Info message body

        ┃ • first theme (#1)
        ┃ • second theme (#2)

        > (y) Yes, confirm changes
        (n) Cancel

        Press ↑↓ arrows to select, enter or a shortcut to
        confirm.
        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.renderDangerousConfirmationPrompt.html b/docs/api/cli-kit/functions/node_ui.renderDangerousConfirmationPrompt.html index 6b9889347c3..238fc2d6fcd 100644 --- a/docs/api/cli-kit/functions/node_ui.renderDangerousConfirmationPrompt.html +++ b/docs/api/cli-kit/functions/node_ui.renderDangerousConfirmationPrompt.html @@ -2,4 +2,4 @@ type a confirmation string to proceed.

      Parameters

      Returns Promise<boolean>

      Example

      ?  Release a new version of nightly-app-2023-06-19?

      Includes:
      ┃ + web-px (new)
      ┃ + sub-ui-ext
      ┃ + theme-app-ext
      ┃ + paymentify (from Partner Dashboard)

      Removes:
      ┃ - prod-discount-fun

      This can permanently delete app user data.

      Type nightly-app-2023-06-19 to confirm, or press Escape
      to cancel.
      > █
      ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.renderError.html b/docs/api/cli-kit/functions/node_ui.renderError.html index ddbc70e531b..bb1e3c72bc2 100644 --- a/docs/api/cli-kit/functions/node_ui.renderError.html +++ b/docs/api/cli-kit/functions/node_ui.renderError.html @@ -1,4 +1,4 @@ renderError | @shopify/cli-kit
      • Renders an error banner to the console.

        Parameters

        Returns undefined | string

        Example

        ╭─ error ──────────────────────────────────────────────────╮
        │ │
        Version couldn't be released.
        │ │
        This version needs to be submitted for review and
        approved by Shopify before it can be released. │
        │ │
        ╰──────────────────────────────────────────────────────────╯
        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.renderFatalError.html b/docs/api/cli-kit/functions/node_ui.renderFatalError.html index 32b4b0f741e..431e111e2b3 100644 --- a/docs/api/cli-kit/functions/node_ui.renderFatalError.html +++ b/docs/api/cli-kit/functions/node_ui.renderFatalError.html @@ -3,4 +3,4 @@

      Example

      Complete
      ╭─ error ──────────────────────────────────────────────────╮
      │ │
      No Organization found
      │ │
      Next steps
      │ • Have you created a Shopify Partners organization
      │ [1]? │
      │ • Have you confirmed your accounts from the emails
      you received? │
      │ • Need to connect to a different App or
      organization? Run the command again with `--reset`
      │ │
      amortizable-marketplace-ext
      │ • Some other error
      Validation errors
      │ • Missing expected key(s). │
      │ │
      amortizable-marketplace-ext-2
      │ • Something was not found
      │ │
      ╰──────────────────────────────────────────────────────────╯
      [1] https://partners.shopify.com/signup
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.renderInfo.html b/docs/api/cli-kit/functions/node_ui.renderInfo.html index a24ce97f163..1483d2a5219 100644 --- a/docs/api/cli-kit/functions/node_ui.renderInfo.html +++ b/docs/api/cli-kit/functions/node_ui.renderInfo.html @@ -3,4 +3,4 @@

      Example

      Complete
      ╭─ info ───────────────────────────────────────────────────╮
      │ │
      my-app initialized and ready to build. │
      │ │
      Next steps
      │ • Run `cd verification-app`
      │ • To preview your project, run `npm app dev`
      │ • To add extensions, run `npm generate extension`
      │ │
      Reference
      │ • Run `npm shopify help`
      │ • Dev docs [1] │
      │ │
      Custom section
      │ • Item 1 [2] │
      │ • Item 2
      │ • Item 3 [3] │
      │ │
      ╰──────────────────────────────────────────────────────────╯
      [1] https://shopify.dev
      [2] https://www.google.com/search?q=jh56t9l34kpo35tw8s28hn7s
      9s2xvzla01d8cn6j7yq&rlz=1C1GCEU_enUS832US832&oq=jh56t9l34kpo
      35tw8s28hn7s9s2xvzla01d8cn6j7yq&aqs=chrome.0.35i39l2j0l4j46j
      69i60.2711j0j7&sourceid=chrome&ie=UTF-8
      [3] https://shopify.com
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.renderSelectPrompt.html b/docs/api/cli-kit/functions/node_ui.renderSelectPrompt.html index d1662b53a5e..6e8156faad6 100644 --- a/docs/api/cli-kit/functions/node_ui.renderSelectPrompt.html +++ b/docs/api/cli-kit/functions/node_ui.renderSelectPrompt.html @@ -1,4 +1,4 @@ renderSelectPrompt | @shopify/cli-kit
      • Renders a select prompt to the console.

        Type Parameters

        • T

        Parameters

        Returns Promise<T>

        Example

        ?  Associate your project with the org Castile Ventures?

        Add
        ┃ • new-ext

        Remove
        ┃ • integrated-demand-ext
        ┃ • order-discount

        Automations
        > fifth
        sixth

        Merchant Admin
        eighth
        ninth

        Other
        first
        second
        third (limit reached)
        fourth
        seventh
        tenth

        Press ↑↓ arrows to select, enter to confirm.
        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.renderSuccess.html b/docs/api/cli-kit/functions/node_ui.renderSuccess.html index 9662e3b885a..b6926930afd 100644 --- a/docs/api/cli-kit/functions/node_ui.renderSuccess.html +++ b/docs/api/cli-kit/functions/node_ui.renderSuccess.html @@ -3,4 +3,4 @@

      Example

      Complete
      ╭─ success ────────────────────────────────────────────────╮
      │ │
      Deployment successful. │
      │ │
      Your extensions have been uploaded to your Shopify
      Partners Dashboard. │
      │ │
      Next steps
      │ • See your deployment and set it live [1] │
      │ │
      ╰──────────────────────────────────────────────────────────╯
      [1] https://partners.shopify.com/1797046/apps/4523695/deploy
      ments
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.renderTable.html b/docs/api/cli-kit/functions/node_ui.renderTable.html index 7373fe4f148..73308aee38f 100644 --- a/docs/api/cli-kit/functions/node_ui.renderTable.html +++ b/docs/api/cli-kit/functions/node_ui.renderTable.html @@ -1,4 +1,4 @@ renderTable | @shopify/cli-kit
      • Renders a table to the console.

        Type Parameters

        • T extends default

        Parameters

        • __namedParameters: RenderTableOptions<T>

        Returns undefined | string

        Example

        ID  Name        email
        ── ────────── ─────────────
        1 John Doe jon@doe.com
        2 Jane Doe jane@doe.com
        3 John Smith jon@smith.com
        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.renderTasks.html b/docs/api/cli-kit/functions/node_ui.renderTasks.html index 8f81ab40df3..bf99bf2c11b 100644 --- a/docs/api/cli-kit/functions/node_ui.renderTasks.html +++ b/docs/api/cli-kit/functions/node_ui.renderTasks.html @@ -1,4 +1,4 @@ renderTasks | @shopify/cli-kit
      • Runs async tasks and displays their progress to the console.

        Type Parameters

        • TContext

        Parameters

        • tasks: Task<TContext>[]
        • __namedParameters: RenderTasksOptions = {}

        Returns Promise<TContext>

        Example

        ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
        Installing dependencies ...
        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.renderText.html b/docs/api/cli-kit/functions/node_ui.renderText.html index 1f02b21524e..9d7a21b4b89 100644 --- a/docs/api/cli-kit/functions/node_ui.renderText.html +++ b/docs/api/cli-kit/functions/node_ui.renderText.html @@ -2,4 +2,4 @@ Using this function makes sure that correct spacing is applied among the various components.

      Parameters

      • __namedParameters: RenderTextOptions

      Returns string

      Example

      Hello world!
       
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.renderTextPrompt.html b/docs/api/cli-kit/functions/node_ui.renderTextPrompt.html index d84b78376ba..9df8eaf6a40 100644 --- a/docs/api/cli-kit/functions/node_ui.renderTextPrompt.html +++ b/docs/api/cli-kit/functions/node_ui.renderTextPrompt.html @@ -1,4 +1,4 @@ renderTextPrompt | @shopify/cli-kit
      • Renders a text prompt to the console.

        Parameters

        Returns Promise<string>

        Example

        ?  App project name (can be changed later):
        > expansive commerce app
        ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui.renderWarning.html b/docs/api/cli-kit/functions/node_ui.renderWarning.html index 35e61aa074c..1cbafebcac6 100644 --- a/docs/api/cli-kit/functions/node_ui.renderWarning.html +++ b/docs/api/cli-kit/functions/node_ui.renderWarning.html @@ -3,4 +3,4 @@

      Example

      Complete
      ╭─ warning ────────────────────────────────────────────────╮
      │ │
      Required access scope update. │
      │ │
      The deadline for re-selecting your app scopes is May
      1, 2022.
      │ │
      Reference
      │ • Dev docs [1] │
      │ │
      ╰──────────────────────────────────────────────────────────╯
      [1] https://shopify.dev/app/scopes
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui_components.ConcurrentOutput.html b/docs/api/cli-kit/functions/node_ui_components.ConcurrentOutput.html index 2572817e251..c0bf3df55c2 100644 --- a/docs/api/cli-kit/functions/node_ui_components.ConcurrentOutput.html +++ b/docs/api/cli-kit/functions/node_ui_components.ConcurrentOutput.html @@ -7,4 +7,4 @@

      For example running shopify app dev:

      2022-10-10 13:11:03 | backend    | npm
      2022-10-10 13:11:03 | backend | WARN ignoring workspace config at ...
      2022-10-10 13:11:03 | backend |
      2022-10-10 13:11:03 | backend |
      2022-10-10 13:11:03 | backend | > shopify-app-template-node@0.1.0 dev
      2022-10-10 13:11:03 | backend | > cross-env NODE_ENV=development nodemon backend/index.js --watch ./backend
      2022-10-10 13:11:03 | backend |
      2022-10-10 13:11:03 | backend |
      2022-10-10 13:11:03 | frontend |
      2022-10-10 13:11:03 | frontend | > starter-react-frontend-app@0.1.0 dev
      2022-10-10 13:11:03 | frontend | > cross-env NODE_ENV=development node vite-server.js
      2022-10-10 13:11:03 | frontend |
      2022-10-10 13:11:03 | frontend |
      2022-10-10 13:11:03 | backend |
      2022-10-10 13:11:03 | backend | [nodemon] to restart at any time, enter `rs`
      2022-10-10 13:11:03 | backend | [nodemon] watching path(s): backend/
      2022-10-10 13:11:03 | backend | [nodemon] watching extensions: js,mjs,json
      2022-10-10 13:11:03 | backend | [nodemon] starting `node backend/index.js`
      2022-10-10 13:11:03 | backend |
      -

      Parameters

      • props: PropsWithChildren<ConcurrentOutputProps>
      • Optional context: any

      Returns null | ReactElement<any, any>

      \ No newline at end of file +

      Parameters

      • props: PropsWithChildren<ConcurrentOutputProps>
      • Optional context: any

      Returns null | ReactElement<any, any>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui_components.useConcurrentOutputContext.html b/docs/api/cli-kit/functions/node_ui_components.useConcurrentOutputContext.html index d60b48cc2ce..a05deb63de0 100644 --- a/docs/api/cli-kit/functions/node_ui_components.useConcurrentOutputContext.html +++ b/docs/api/cli-kit/functions/node_ui_components.useConcurrentOutputContext.html @@ -1 +1 @@ -useConcurrentOutputContext | @shopify/cli-kit
      \ No newline at end of file +useConcurrentOutputContext | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_ui_hooks.useAbortSignal.html b/docs/api/cli-kit/functions/node_ui_hooks.useAbortSignal.html index 4b780293915..f0ffba4dc34 100644 --- a/docs/api/cli-kit/functions/node_ui_hooks.useAbortSignal.html +++ b/docs/api/cli-kit/functions/node_ui_hooks.useAbortSignal.html @@ -1 +1 @@ -useAbortSignal | @shopify/cli-kit
      \ No newline at end of file +useAbortSignal | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_upgrade.cliInstallCommand.html b/docs/api/cli-kit/functions/node_upgrade.cliInstallCommand.html index 91e3f961df9..c10ee866ca8 100644 --- a/docs/api/cli-kit/functions/node_upgrade.cliInstallCommand.html +++ b/docs/api/cli-kit/functions/node_upgrade.cliInstallCommand.html @@ -1,4 +1,4 @@ cliInstallCommand | @shopify/cli-kit
      • Utility function for generating an install command for the user to run to install an updated version of Shopify CLI.

        Returns string

        A string with the command to run.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_upgrade.getOutputUpdateCLIReminder.html b/docs/api/cli-kit/functions/node_upgrade.getOutputUpdateCLIReminder.html index 127412385da..7bb8ecdbd54 100644 --- a/docs/api/cli-kit/functions/node_upgrade.getOutputUpdateCLIReminder.html +++ b/docs/api/cli-kit/functions/node_upgrade.getOutputUpdateCLIReminder.html @@ -1,4 +1,4 @@ getOutputUpdateCLIReminder | @shopify/cli-kit
      • Generates a message to remind the user to update the CLI.

        Parameters

        • version: string

          The version to update to.

        Returns string

        The message to remind the user to update the CLI.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_vendor_dev_server_network_interfaces.fromIp.html b/docs/api/cli-kit/functions/node_vendor_dev_server_network_interfaces.fromIp.html new file mode 100644 index 00000000000..40d3521bed0 --- /dev/null +++ b/docs/api/cli-kit/functions/node_vendor_dev_server_network_interfaces.fromIp.html @@ -0,0 +1 @@ +fromIp | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_vendor_dev_server_network_interfaces.getInterface.html b/docs/api/cli-kit/functions/node_vendor_dev_server_network_interfaces.getInterface.html new file mode 100644 index 00000000000..480f3c8b4f6 --- /dev/null +++ b/docs/api/cli-kit/functions/node_vendor_dev_server_network_interfaces.getInterface.html @@ -0,0 +1 @@ +getInterface | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_vendor_dev_server_network_interfaces.toIp.html b/docs/api/cli-kit/functions/node_vendor_dev_server_network_interfaces.toIp.html new file mode 100644 index 00000000000..1e8ec57cf3a --- /dev/null +++ b/docs/api/cli-kit/functions/node_vendor_dev_server_network_interfaces.toIp.html @@ -0,0 +1 @@ +toIp | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_vendor_otel_js_utils_throttle.throttle.html b/docs/api/cli-kit/functions/node_vendor_otel_js_utils_throttle.throttle.html index 1182f4147e9..f9c4e9c9146 100644 --- a/docs/api/cli-kit/functions/node_vendor_otel_js_utils_throttle.throttle.html +++ b/docs/api/cli-kit/functions/node_vendor_otel_js_utils_throttle.throttle.html @@ -1 +1 @@ -throttle | @shopify/cli-kit
      \ No newline at end of file +throttle | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_vendor_otel_js_utils_validators.isValidMetricName.html b/docs/api/cli-kit/functions/node_vendor_otel_js_utils_validators.isValidMetricName.html index eab62d4995f..3092880dbcf 100644 --- a/docs/api/cli-kit/functions/node_vendor_otel_js_utils_validators.isValidMetricName.html +++ b/docs/api/cli-kit/functions/node_vendor_otel_js_utils_validators.isValidMetricName.html @@ -1 +1 @@ -isValidMetricName | @shopify/cli-kit
      \ No newline at end of file +isValidMetricName | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_version.globalCLIVersion.html b/docs/api/cli-kit/functions/node_version.globalCLIVersion.html index 0c7df9ffe3f..438a848ae7a 100644 --- a/docs/api/cli-kit/functions/node_version.globalCLIVersion.html +++ b/docs/api/cli-kit/functions/node_version.globalCLIVersion.html @@ -1,3 +1,3 @@ globalCLIVersion | @shopify/cli-kit
      • Returns the version of the globally installed CLI, only if it's greater than 3.59.0 (when the global CLI was introduced).

        Returns Promise<string | undefined>

        The version of the CLI if it is globally installed or undefined.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_version.localCLIVersion.html b/docs/api/cli-kit/functions/node_version.localCLIVersion.html index 67aa359a09b..77bd601c33d 100644 --- a/docs/api/cli-kit/functions/node_version.localCLIVersion.html +++ b/docs/api/cli-kit/functions/node_version.localCLIVersion.html @@ -1,4 +1,4 @@ localCLIVersion | @shopify/cli-kit
      • Returns the version of the local dependency of the CLI if it's installed in the provided directory.

        Parameters

        • directory: string

          Path of the project to look for the dependency.

        Returns Promise<string | undefined>

        The CLI version or undefined if the dependency is not installed.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_vscode.addRecommendedExtensions.html b/docs/api/cli-kit/functions/node_vscode.addRecommendedExtensions.html index 3293a6576eb..4c5d73b8c23 100644 --- a/docs/api/cli-kit/functions/node_vscode.addRecommendedExtensions.html +++ b/docs/api/cli-kit/functions/node_vscode.addRecommendedExtensions.html @@ -1,4 +1,4 @@ addRecommendedExtensions | @shopify/cli-kit
      • Add VSCode extension recommendations.

        Parameters

        • directory: string

          Directory that contains the .vscode folder.

        • recommendations: string[]

          List of VSCode extensions to recommend.

          -

        Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/functions/node_vscode.isVSCode.html b/docs/api/cli-kit/functions/node_vscode.isVSCode.html index 16853d742c4..8b3172f7475 100644 --- a/docs/api/cli-kit/functions/node_vscode.isVSCode.html +++ b/docs/api/cli-kit/functions/node_vscode.isVSCode.html @@ -1,4 +1,4 @@ isVSCode | @shopify/cli-kit
      • Check if user editor is VS Code.

        Parameters

        • root: string = ...

          Root directory to start searching for .vscode directory.

        Returns Promise<boolean>

        True if user editor is VS Code.

        -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/index.html b/docs/api/cli-kit/index.html index 3d14282917f..d4a3417fb25 100644 --- a/docs/api/cli-kit/index.html +++ b/docs/api/cli-kit/index.html @@ -16,13 +16,16 @@ node/api/app-dev node/api/app-management node/api/business-platform +node/api/functions node/api/graphql node/api/http node/api/partners node/api/rest-api-throttler +node/api/webhooks node/archiver node/base-command node/cli +node/cli-launcher node/colors node/context/fqdn node/context/local @@ -83,6 +86,8 @@ node/ui/components node/ui/hooks node/upgrade +node/vendor/dev_server/DevServer +node/vendor/dev_server/network-interfaces node/vendor/otel-js/export/InstantaneousMetricReader node/vendor/otel-js/service/BaseOtelService/BaseOtelService node/vendor/otel-js/service/DefaultOtelService/DefaultMeterProvider diff --git a/docs/api/cli-kit/interfaces/node_api_admin.RestResponse.html b/docs/api/cli-kit/interfaces/node_api_admin.RestResponse.html index dd1eae1238d..a86ebf7d063 100644 --- a/docs/api/cli-kit/interfaces/node_api_admin.RestResponse.html +++ b/docs/api/cli-kit/interfaces/node_api_admin.RestResponse.html @@ -1,8 +1,8 @@ RestResponse | @shopify/cli-kit

      Respose of a REST request.

      -
      interface RestResponse {
          headers: {
              [key: string]: string[];
          };
          json: any;
          status: number;
      }

      Properties

      interface RestResponse {
          headers: {
              [key: string]: string[];
          };
          json: any;
          status: number;
      }

      Properties

      Properties

      headers: {
          [key: string]: string[];
      }

      HTTP response headers.

      -

      Type declaration

      • [key: string]: string[]
      json: any

      REST JSON respose.

      -
      status: number

      HTTP response status.

      -
      \ No newline at end of file +

      Type declaration

      • [key: string]: string[]
      json: any

      REST JSON respose.

      +
      status: number

      HTTP response status.

      +
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_api_graphql.GraphQLResponseOptions.html b/docs/api/cli-kit/interfaces/node_api_graphql.GraphQLResponseOptions.html index 35b0918f277..6229e826476 100644 --- a/docs/api/cli-kit/interfaces/node_api_graphql.GraphQLResponseOptions.html +++ b/docs/api/cli-kit/interfaces/node_api_graphql.GraphQLResponseOptions.html @@ -1,3 +1,3 @@ -GraphQLResponseOptions | @shopify/cli-kit
      interface GraphQLResponseOptions<T> {
          handleErrors?: boolean;
          onResponse?: ((response) => void);
      }

      Type Parameters

      • T

      Properties

      handleErrors? +GraphQLResponseOptions | @shopify/cli-kit
      interface GraphQLResponseOptions<T> {
          handleErrors?: boolean;
          onResponse?: ((response) => void);
      }

      Type Parameters

      • T

      Properties

      handleErrors?: boolean
      onResponse?: ((response) => void)

      Type declaration

        • (response): void
        • Parameters

          • response: Response<T>

          Returns void

      \ No newline at end of file +

      Properties

      handleErrors?: boolean
      onResponse?: ((response) => void)

      Type declaration

        • (response): void
        • Parameters

          • response: Response<T>

          Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_api_graphql.GraphQLVariables.html b/docs/api/cli-kit/interfaces/node_api_graphql.GraphQLVariables.html index 63e0e09cc0f..09ecd5cc00a 100644 --- a/docs/api/cli-kit/interfaces/node_api_graphql.GraphQLVariables.html +++ b/docs/api/cli-kit/interfaces/node_api_graphql.GraphQLVariables.html @@ -1 +1 @@ -GraphQLVariables | @shopify/cli-kit
      interface GraphQLVariables {
          [key: string]: any;
      }

      Indexable

      [key: string]: any
      \ No newline at end of file +GraphQLVariables | @shopify/cli-kit
      interface GraphQLVariables {
          [key: string]: any;
      }

      Indexable

      [key: string]: any
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_dot_env.DotEnvFile.html b/docs/api/cli-kit/interfaces/node_dot_env.DotEnvFile.html index 88d9f2f76ed..786c78d02f1 100644 --- a/docs/api/cli-kit/interfaces/node_dot_env.DotEnvFile.html +++ b/docs/api/cli-kit/interfaces/node_dot_env.DotEnvFile.html @@ -1,6 +1,6 @@ DotEnvFile | @shopify/cli-kit

      This interface represents a .env file.

      -
      interface DotEnvFile {
          path: string;
          variables: {
              [name: string]: string;
          };
      }

      Properties

      interface DotEnvFile {
          path: string;
          variables: {
              [name: string]: string;
          };
      }

      Properties

      Properties

      path: string

      Path to the .env file.

      -
      variables: {
          [name: string]: string;
      }

      Variables of the .env file.

      -

      Type declaration

      • [name: string]: string
      \ No newline at end of file +
      variables: {
          [name: string]: string;
      }

      Variables of the .env file.

      +

      Type declaration

      • [name: string]: string
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_environments.Environments.html b/docs/api/cli-kit/interfaces/node_environments.Environments.html index 368a9b55e68..9b8c2c0ad30 100644 --- a/docs/api/cli-kit/interfaces/node_environments.Environments.html +++ b/docs/api/cli-kit/interfaces/node_environments.Environments.html @@ -1 +1 @@ -Environments | @shopify/cli-kit
      interface Environments {
          [name: string]: JsonMap;
      }

      Indexable

      [name: string]: JsonMap
      \ No newline at end of file +Environments | @shopify/cli-kit
      interface Environments {
          [name: string]: JsonMap;
      }

      Indexable

      [name: string]: JsonMap
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_fs.MatchGlobOptions.html b/docs/api/cli-kit/interfaces/node_fs.MatchGlobOptions.html index ee3283920ac..130cf5adef3 100644 --- a/docs/api/cli-kit/interfaces/node_fs.MatchGlobOptions.html +++ b/docs/api/cli-kit/interfaces/node_fs.MatchGlobOptions.html @@ -1,3 +1,3 @@ -MatchGlobOptions | @shopify/cli-kit

      Interface MatchGlobOptions

      interface MatchGlobOptions {
          matchBase: boolean;
          noglobstar: boolean;
      }

      Properties

      matchBase +MatchGlobOptions | @shopify/cli-kit

      Interface MatchGlobOptions

      interface MatchGlobOptions {
          matchBase: boolean;
          noglobstar: boolean;
      }

      Properties

      Properties

      matchBase: boolean
      noglobstar: boolean
      \ No newline at end of file +

      Properties

      matchBase: boolean
      noglobstar: boolean
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_fs.WriteOptions.html b/docs/api/cli-kit/interfaces/node_fs.WriteOptions.html index 01d2acb23a3..509bb95043e 100644 --- a/docs/api/cli-kit/interfaces/node_fs.WriteOptions.html +++ b/docs/api/cli-kit/interfaces/node_fs.WriteOptions.html @@ -1,2 +1,2 @@ -WriteOptions | @shopify/cli-kit
      interface WriteOptions {
          encoding: BufferEncoding;
      }

      Properties

      Properties

      encoding: BufferEncoding
      \ No newline at end of file +WriteOptions | @shopify/cli-kit
      interface WriteOptions {
          encoding: BufferEncoding;
      }

      Properties

      Properties

      encoding: BufferEncoding
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_git.CreateGitCommitOptions.html b/docs/api/cli-kit/interfaces/node_git.CreateGitCommitOptions.html index 5ca93b19960..45ba605ff2d 100644 --- a/docs/api/cli-kit/interfaces/node_git.CreateGitCommitOptions.html +++ b/docs/api/cli-kit/interfaces/node_git.CreateGitCommitOptions.html @@ -1,3 +1,3 @@ -CreateGitCommitOptions | @shopify/cli-kit

      Interface CreateGitCommitOptions

      interface CreateGitCommitOptions {
          author?: string;
          directory?: string;
      }

      Properties

      author? +CreateGitCommitOptions | @shopify/cli-kit

      Interface CreateGitCommitOptions

      interface CreateGitCommitOptions {
          author?: string;
          directory?: string;
      }

      Properties

      Properties

      author?: string
      directory?: string
      \ No newline at end of file +

      Properties

      author?: string
      directory?: string
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_git.GitCloneOptions.html b/docs/api/cli-kit/interfaces/node_git.GitCloneOptions.html index 05150a88586..90b1c1c06a7 100644 --- a/docs/api/cli-kit/interfaces/node_git.GitCloneOptions.html +++ b/docs/api/cli-kit/interfaces/node_git.GitCloneOptions.html @@ -4,9 +4,9 @@

      Param: destination

      The directory where the repository will be cloned.

      Param: progressUpdater

      A function that will be called with the progress of the clone.

      Param: shallow

      Whether to clone the repository shallowly.

      Param: latestTag

      Whether to clone the latest tag instead of the default branch.

      -
      interface GitCloneOptions {
          destination: string;
          latestTag?: boolean;
          progressUpdater?: ((statusString) => void);
          repoUrl: string;
          shallow?: boolean;
      }

      Properties

      interface GitCloneOptions {
          destination: string;
          latestTag?: boolean;
          progressUpdater?: ((statusString) => void);
          repoUrl: string;
          shallow?: boolean;
      }

      Properties

      destination: string
      latestTag?: boolean
      progressUpdater?: ((statusString) => void)

      Type declaration

        • (statusString): void
        • Parameters

          • statusString: string

          Returns void

      repoUrl: string
      shallow?: boolean
      \ No newline at end of file +

      Properties

      destination: string
      latestTag?: boolean
      progressUpdater?: ((statusString) => void)

      Type declaration

        • (statusString): void
        • Parameters

          • statusString: string

          Returns void

      repoUrl: string
      shallow?: boolean
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_git.GitIgnoreTemplate.html b/docs/api/cli-kit/interfaces/node_git.GitIgnoreTemplate.html index 356759302cb..71fe1fe4f53 100644 --- a/docs/api/cli-kit/interfaces/node_git.GitIgnoreTemplate.html +++ b/docs/api/cli-kit/interfaces/node_git.GitIgnoreTemplate.html @@ -1 +1 @@ -GitIgnoreTemplate | @shopify/cli-kit
      interface GitIgnoreTemplate {
          [section: string]: string[];
      }

      Indexable

      [section: string]: string[]
      \ No newline at end of file +GitIgnoreTemplate | @shopify/cli-kit
      interface GitIgnoreTemplate {
          [section: string]: string[];
      }

      Indexable

      [section: string]: string[]
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_github.GithubRelease.html b/docs/api/cli-kit/interfaces/node_github.GithubRelease.html index 97484bee9c3..17e80bc5aea 100644 --- a/docs/api/cli-kit/interfaces/node_github.GithubRelease.html +++ b/docs/api/cli-kit/interfaces/node_github.GithubRelease.html @@ -1,4 +1,4 @@ -GithubRelease | @shopify/cli-kit
      interface GithubRelease {
          body: string;
          created_at: string;
          draft: boolean;
          id: number;
          name: string;
          prerelease: boolean;
          published_at: string;
          tag_name: string;
          tarball_url: string;
          url: string;
      }

      Properties

      body +GithubRelease | @shopify/cli-kit
      interface GithubRelease {
          body: string;
          created_at: string;
          draft: boolean;
          id: number;
          name: string;
          prerelease: boolean;
          published_at: string;
          tag_name: string;
          tarball_url: string;
          url: string;
      }

      Properties

      Properties

      body: string
      created_at: string
      draft: boolean
      id: number
      name: string
      prerelease: boolean
      published_at: string
      tag_name: string
      tarball_url: string
      url: string
      \ No newline at end of file +

      Properties

      body: string
      created_at: string
      draft: boolean
      id: number
      name: string
      prerelease: boolean
      published_at: string
      tag_name: string
      tarball_url: string
      url: string
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_github.GithubRepositoryReference.html b/docs/api/cli-kit/interfaces/node_github.GithubRepositoryReference.html index 58601bd9342..8fa241e78e7 100644 --- a/docs/api/cli-kit/interfaces/node_github.GithubRepositoryReference.html +++ b/docs/api/cli-kit/interfaces/node_github.GithubRepositoryReference.html @@ -1,4 +1,4 @@ -GithubRepositoryReference | @shopify/cli-kit

      Interface GithubRepositoryReference

      interface GithubRepositoryReference {
          baseURL: string;
          branch?: string;
          filePath?: string;
      }

      Properties

      baseURL +GithubRepositoryReference | @shopify/cli-kit

      Interface GithubRepositoryReference

      interface GithubRepositoryReference {
          baseURL: string;
          branch?: string;
          filePath?: string;
      }

      Properties

      baseURL: string
      branch?: string
      filePath?: string
      \ No newline at end of file +

      Properties

      baseURL: string
      branch?: string
      filePath?: string
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_global_context.GlobalContext.html b/docs/api/cli-kit/interfaces/node_global_context.GlobalContext.html index 2148776607c..7d25d19ca76 100644 --- a/docs/api/cli-kit/interfaces/node_global_context.GlobalContext.html +++ b/docs/api/cli-kit/interfaces/node_global_context.GlobalContext.html @@ -1,2 +1,2 @@ -GlobalContext | @shopify/cli-kit
      interface GlobalContext {
          currentCommandId: string;
      }

      Properties

      Properties

      currentCommandId: string
      \ No newline at end of file +GlobalContext | @shopify/cli-kit
      interface GlobalContext {
          currentCommandId: string;
      }

      Properties

      Properties

      currentCommandId: string
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_hooks_prerun.CommandContent.html b/docs/api/cli-kit/interfaces/node_hooks_prerun.CommandContent.html index 207c6748f4e..2054b893a03 100644 --- a/docs/api/cli-kit/interfaces/node_hooks_prerun.CommandContent.html +++ b/docs/api/cli-kit/interfaces/node_hooks_prerun.CommandContent.html @@ -1,4 +1,4 @@ -CommandContent | @shopify/cli-kit
      interface CommandContent {
          alias?: string;
          command: string;
          topic?: string;
      }

      Properties

      alias? +CommandContent | @shopify/cli-kit
      interface CommandContent {
          alias?: string;
          command: string;
          topic?: string;
      }

      Properties

      Properties

      alias?: string
      command: string
      topic?: string
      \ No newline at end of file +

      Properties

      alias?: string
      command: string
      topic?: string
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_is_global.InstallGlobalCLIPromptResult.html b/docs/api/cli-kit/interfaces/node_is_global.InstallGlobalCLIPromptResult.html index b3f830576eb..402c882c84f 100644 --- a/docs/api/cli-kit/interfaces/node_is_global.InstallGlobalCLIPromptResult.html +++ b/docs/api/cli-kit/interfaces/node_is_global.InstallGlobalCLIPromptResult.html @@ -1,3 +1,3 @@ -InstallGlobalCLIPromptResult | @shopify/cli-kit
      interface InstallGlobalCLIPromptResult {
          alreadyInstalled: boolean;
          install: boolean;
      }

      Properties

      alreadyInstalled +InstallGlobalCLIPromptResult | @shopify/cli-kit
      interface InstallGlobalCLIPromptResult {
          alreadyInstalled: boolean;
          install: boolean;
      }

      Properties

      alreadyInstalled: boolean
      install: boolean
      \ No newline at end of file +

      Properties

      alreadyInstalled: boolean
      install: boolean
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_metadata.RuntimeMetadataManager.html b/docs/api/cli-kit/interfaces/node_metadata.RuntimeMetadataManager.html index ad09d1873d4..9adcbc34e21 100644 --- a/docs/api/cli-kit/interfaces/node_metadata.RuntimeMetadataManager.html +++ b/docs/api/cli-kit/interfaces/node_metadata.RuntimeMetadataManager.html @@ -1,12 +1,12 @@ -RuntimeMetadataManager | @shopify/cli-kit

      Interface RuntimeMetadataManager<TPublic, TSensitive>

      interface RuntimeMetadataManager<TPublic, TSensitive> {
          addPublicMetadata: ((getData, onError?) => Promise<void>);
          addSensitiveMetadata: ((getData, onError?) => Promise<void>);
          getAllPublicMetadata: (() => Partial<TPublic>);
          getAllSensitiveMetadata: (() => Partial<TSensitive>);
          runWithTimer: ((field) => (<T>(fn) => Promise<T>));
      }

      Type Parameters

      • TPublic extends AnyJson
      • TSensitive extends AnyJson

      Properties

      addPublicMetadata +RuntimeMetadataManager | @shopify/cli-kit

      Interface RuntimeMetadataManager<TPublic, TSensitive>

      interface RuntimeMetadataManager<TPublic, TSensitive> {
          addPublicMetadata: ((getData, onError?) => Promise<void>);
          addSensitiveMetadata: ((getData, onError?) => Promise<void>);
          getAllPublicMetadata: (() => Partial<TPublic>);
          getAllSensitiveMetadata: (() => Partial<TSensitive>);
          runWithTimer: ((field) => (<T>(fn) => Promise<T>));
      }

      Type Parameters

      • TPublic extends AnyJson
      • TSensitive extends AnyJson

      Properties

      addPublicMetadata: ((getData, onError?) => Promise<void>)

      Add some public metadata -- this should not contain any PII.

      -

      Type declaration

        • (getData, onError?): Promise<void>
        • Parameters

          • getData: ProvideMetadata<TPublic>
          • Optional onError: MetadataErrorHandling

          Returns Promise<void>

      addSensitiveMetadata: ((getData, onError?) => Promise<void>)

      Add some potentially sensitive metadata -- this may include PII, but unnecessary data should never be tracked +

      Type declaration

        • (getData, onError?): Promise<void>
        • Parameters

          • getData: ProvideMetadata<TPublic>
          • Optional onError: MetadataErrorHandling

          Returns Promise<void>

      addSensitiveMetadata: ((getData, onError?) => Promise<void>)

      Add some potentially sensitive metadata -- this may include PII, but unnecessary data should never be tracked (this is a good fit for command args for instance).

      -

      Type declaration

        • (getData, onError?): Promise<void>
        • Parameters

          • getData: ProvideMetadata<TSensitive>
          • Optional onError: MetadataErrorHandling

          Returns Promise<void>

      getAllPublicMetadata: (() => Partial<TPublic>)

      Get a snapshot of the tracked public data.

      -

      Type declaration

      getAllSensitiveMetadata: (() => Partial<TSensitive>)

      Get a snapshot of the tracked sensitive data.

      -

      Type declaration

      runWithTimer: ((field) => (<T>(fn) => Promise<T>))

      Run a function, monitoring how long it takes, and adding the elapsed time to a running total.

      -

      Type declaration

        • (field): (<T>(fn) => Promise<T>)
        • Parameters

          Returns (<T>(fn) => Promise<T>)

            • <T>(fn): Promise<T>
            • Type Parameters

              • T

              Parameters

              • fn: (() => Promise<T>)
                  • (): Promise<T>
                  • Returns Promise<T>

              Returns Promise<T>

      \ No newline at end of file +

      Type declaration

        • (getData, onError?): Promise<void>
        • Parameters

          • getData: ProvideMetadata<TSensitive>
          • Optional onError: MetadataErrorHandling

          Returns Promise<void>

      getAllPublicMetadata: (() => Partial<TPublic>)

      Get a snapshot of the tracked public data.

      +

      Type declaration

      getAllSensitiveMetadata: (() => Partial<TSensitive>)

      Get a snapshot of the tracked sensitive data.

      +

      Type declaration

      runWithTimer: ((field) => (<T>(fn) => Promise<T>))

      Run a function, monitoring how long it takes, and adding the elapsed time to a running total.

      +

      Type declaration

        • (field): (<T>(fn) => Promise<T>)
        • Parameters

          Returns (<T>(fn) => Promise<T>)

            • <T>(fn): Promise<T>
            • Type Parameters

              • T

              Parameters

              • fn: (() => Promise<T>)
                  • (): Promise<T>
                  • Returns Promise<T>

              Returns Promise<T>

      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_monorail.Schemas.html b/docs/api/cli-kit/interfaces/node_monorail.Schemas.html index 89a0d29ccb6..aa7bf3c0659 100644 --- a/docs/api/cli-kit/interfaces/node_monorail.Schemas.html +++ b/docs/api/cli-kit/interfaces/node_monorail.Schemas.html @@ -1,2 +1,2 @@ -Schemas | @shopify/cli-kit
      interface Schemas {
          app_cli3_command/1.15: {
              public: {
                  api_key?: Optional<string>;
                  app_extensions_any?: Optional<boolean>;
                  app_extensions_breakdown?: Optional<string>;
                  app_extensions_count?: Optional<number>;
                  app_extensions_custom_layout?: Optional<boolean>;
                  app_extensions_function_any?: Optional<boolean>;
                  app_extensions_function_count?: Optional<number>;
                  app_extensions_function_custom_layout?: Optional<boolean>;
                  app_extensions_theme_any?: Optional<boolean>;
                  app_extensions_theme_count?: Optional<number>;
                  app_extensions_theme_custom_layout?: Optional<boolean>;
                  app_extensions_ui_any?: Optional<boolean>;
                  app_extensions_ui_count?: Optional<number>;
                  app_extensions_ui_custom_layout?: Optional<boolean>;
                  app_name_hash?: Optional<string>;
                  app_path_hash?: Optional<string>;
                  app_scopes?: Optional<string>;
                  app_web_backend_any?: Optional<boolean>;
                  app_web_backend_count?: Optional<number>;
                  app_web_custom_layout?: Optional<boolean>;
                  app_web_framework?: Optional<string>;
                  app_web_frontend_any?: Optional<boolean>;
                  app_web_frontend_count?: Optional<number>;
                  cli_version: string;
                  cmd_all_alias_used?: Optional<string>;
                  cmd_all_exit?: Optional<string>;
                  cmd_all_force?: Optional<boolean>;
                  cmd_all_last_graphql_request_id?: Optional<string>;
                  cmd_all_launcher?: Optional<string>;
                  cmd_all_path_override?: Optional<boolean>;
                  cmd_all_path_override_hash?: Optional<string>;
                  cmd_all_plugin?: Optional<string>;
                  cmd_all_timing_active_ms?: Optional<number>;
                  cmd_all_timing_network_ms?: Optional<number>;
                  cmd_all_timing_prompts_ms?: Optional<number>;
                  cmd_all_topic?: Optional<string>;
                  cmd_all_verbose?: Optional<boolean>;
                  cmd_app_all_configs_any?: Optional<boolean>;
                  cmd_app_all_configs_clients?: Optional<string>;
                  cmd_app_dependency_installation_skipped?: Optional<boolean>;
                  cmd_app_deployment_mode?: Optional<string>;
                  cmd_app_linked_config_git_tracked?: Optional<boolean>;
                  cmd_app_linked_config_name?: Optional<string>;
                  cmd_app_linked_config_source?: Optional<string>;
                  cmd_app_linked_config_used?: Optional<boolean>;
                  cmd_app_linked_config_uses_cli_managed_urls?: Optional<boolean>;
                  cmd_app_reset_used?: Optional<boolean>;
                  cmd_app_warning_api_key_deprecation_displayed?: Optional<boolean>;
                  cmd_create_app_template?: Optional<string>;
                  cmd_create_app_template_url?: Optional<string>;
                  cmd_deploy_config_modules_added?: Optional<string>;
                  cmd_deploy_config_modules_breakdown?: Optional<string>;
                  cmd_deploy_config_modules_deleted?: Optional<string>;
                  cmd_deploy_config_modules_updated?: Optional<string>;
                  cmd_deploy_confirm_cancelled?: Optional<boolean>;
                  cmd_deploy_confirm_include_config_used?: Optional<boolean>;
                  cmd_deploy_confirm_new_registrations?: Optional<number>;
                  cmd_deploy_confirm_removed_registrations?: Optional<number>;
                  cmd_deploy_confirm_time_to_complete_ms?: Optional<number>;
                  cmd_deploy_confirm_updated_registrations?: Optional<number>;
                  cmd_deploy_flag_message_used?: Optional<boolean>;
                  cmd_deploy_flag_source_url_used?: Optional<boolean>;
                  cmd_deploy_flag_version_used?: Optional<boolean>;
                  cmd_deploy_include_config_used?: Optional<boolean>;
                  cmd_deploy_prompt_upgrade_to_unified_displayed?: Optional<boolean>;
                  cmd_deploy_prompt_upgrade_to_unified_response?: Optional<string>;
                  cmd_dev_dev_preview_toggle_used?: Optional<boolean>;
                  cmd_dev_graphiql_opened?: Optional<boolean>;
                  cmd_dev_preview_url_opened?: Optional<boolean>;
                  cmd_dev_tunnel_custom_hash?: Optional<string>;
                  cmd_dev_tunnel_type?: Optional<string>;
                  cmd_dev_urls_updated?: Optional<boolean>;
                  cmd_extensions_binary_from_source?: Optional<boolean>;
                  cmd_release_confirm_cancelled?: Optional<boolean>;
                  cmd_scaffold_required_auth?: Optional<boolean>;
                  cmd_scaffold_template_custom?: Optional<boolean>;
                  cmd_scaffold_template_flavor?: Optional<string>;
                  cmd_scaffold_type?: Optional<string>;
                  cmd_scaffold_type_category?: Optional<string>;
                  cmd_scaffold_type_gated?: Optional<boolean>;
                  cmd_scaffold_type_owner?: Optional<string>;
                  cmd_scaffold_used_prompts_for_type?: Optional<boolean>;
                  command: string;
                  env_auth_method?: Optional<string>;
                  env_ci?: Optional<boolean>;
                  env_ci_platform?: Optional<string>;
                  env_cloud?: Optional<string>;
                  env_device_id?: Optional<string>;
                  env_is_global?: Optional<boolean>;
                  env_package_manager?: Optional<string>;
                  env_package_manager_workspaces?: Optional<boolean>;
                  env_plugin_installed_any_custom?: Optional<boolean>;
                  env_plugin_installed_shopify?: Optional<string>;
                  env_shell?: Optional<string>;
                  env_web_ide?: Optional<string>;
                  is_employee: boolean;
                  node_version: string;
                  partner_id?: Optional<number>;
                  project_type?: Optional<string>;
                  ruby_version: string;
                  store_fqdn_hash?: Optional<string>;
                  success: boolean;
                  time_end: number;
                  time_start: number;
                  total_time: number;
                  uname: string;
                  user_id: string;
              };
              sensitive: {
                  app_name?: Optional<string>;
                  args: string;
                  cmd_all_environment_flags?: Optional<string>;
                  cmd_dev_tunnel_custom?: Optional<string>;
                  env_plugin_installed_all?: Optional<string>;
                  error_message?: Optional<string>;
                  metadata?: Optional<string>;
                  store_fqdn?: Optional<string>;
              };
          };
          [schemaId: string]: {
              public: JsonMap;
              sensitive: JsonMap;
          };
      }

      Indexable

      [schemaId: string]: {
          public: JsonMap;
          sensitive: JsonMap;
      }
      • public: JsonMap
      • sensitive: JsonMap

      Properties

      app_cli3_command/1.15: {
          public: {
              api_key?: Optional<string>;
              app_extensions_any?: Optional<boolean>;
              app_extensions_breakdown?: Optional<string>;
              app_extensions_count?: Optional<number>;
              app_extensions_custom_layout?: Optional<boolean>;
              app_extensions_function_any?: Optional<boolean>;
              app_extensions_function_count?: Optional<number>;
              app_extensions_function_custom_layout?: Optional<boolean>;
              app_extensions_theme_any?: Optional<boolean>;
              app_extensions_theme_count?: Optional<number>;
              app_extensions_theme_custom_layout?: Optional<boolean>;
              app_extensions_ui_any?: Optional<boolean>;
              app_extensions_ui_count?: Optional<number>;
              app_extensions_ui_custom_layout?: Optional<boolean>;
              app_name_hash?: Optional<string>;
              app_path_hash?: Optional<string>;
              app_scopes?: Optional<string>;
              app_web_backend_any?: Optional<boolean>;
              app_web_backend_count?: Optional<number>;
              app_web_custom_layout?: Optional<boolean>;
              app_web_framework?: Optional<string>;
              app_web_frontend_any?: Optional<boolean>;
              app_web_frontend_count?: Optional<number>;
              cli_version: string;
              cmd_all_alias_used?: Optional<string>;
              cmd_all_exit?: Optional<string>;
              cmd_all_force?: Optional<boolean>;
              cmd_all_last_graphql_request_id?: Optional<string>;
              cmd_all_launcher?: Optional<string>;
              cmd_all_path_override?: Optional<boolean>;
              cmd_all_path_override_hash?: Optional<string>;
              cmd_all_plugin?: Optional<string>;
              cmd_all_timing_active_ms?: Optional<number>;
              cmd_all_timing_network_ms?: Optional<number>;
              cmd_all_timing_prompts_ms?: Optional<number>;
              cmd_all_topic?: Optional<string>;
              cmd_all_verbose?: Optional<boolean>;
              cmd_app_all_configs_any?: Optional<boolean>;
              cmd_app_all_configs_clients?: Optional<string>;
              cmd_app_dependency_installation_skipped?: Optional<boolean>;
              cmd_app_deployment_mode?: Optional<string>;
              cmd_app_linked_config_git_tracked?: Optional<boolean>;
              cmd_app_linked_config_name?: Optional<string>;
              cmd_app_linked_config_source?: Optional<string>;
              cmd_app_linked_config_used?: Optional<boolean>;
              cmd_app_linked_config_uses_cli_managed_urls?: Optional<boolean>;
              cmd_app_reset_used?: Optional<boolean>;
              cmd_app_warning_api_key_deprecation_displayed?: Optional<boolean>;
              cmd_create_app_template?: Optional<string>;
              cmd_create_app_template_url?: Optional<string>;
              cmd_deploy_config_modules_added?: Optional<string>;
              cmd_deploy_config_modules_breakdown?: Optional<string>;
              cmd_deploy_config_modules_deleted?: Optional<string>;
              cmd_deploy_config_modules_updated?: Optional<string>;
              cmd_deploy_confirm_cancelled?: Optional<boolean>;
              cmd_deploy_confirm_include_config_used?: Optional<boolean>;
              cmd_deploy_confirm_new_registrations?: Optional<number>;
              cmd_deploy_confirm_removed_registrations?: Optional<number>;
              cmd_deploy_confirm_time_to_complete_ms?: Optional<number>;
              cmd_deploy_confirm_updated_registrations?: Optional<number>;
              cmd_deploy_flag_message_used?: Optional<boolean>;
              cmd_deploy_flag_source_url_used?: Optional<boolean>;
              cmd_deploy_flag_version_used?: Optional<boolean>;
              cmd_deploy_include_config_used?: Optional<boolean>;
              cmd_deploy_prompt_upgrade_to_unified_displayed?: Optional<boolean>;
              cmd_deploy_prompt_upgrade_to_unified_response?: Optional<string>;
              cmd_dev_dev_preview_toggle_used?: Optional<boolean>;
              cmd_dev_graphiql_opened?: Optional<boolean>;
              cmd_dev_preview_url_opened?: Optional<boolean>;
              cmd_dev_tunnel_custom_hash?: Optional<string>;
              cmd_dev_tunnel_type?: Optional<string>;
              cmd_dev_urls_updated?: Optional<boolean>;
              cmd_extensions_binary_from_source?: Optional<boolean>;
              cmd_release_confirm_cancelled?: Optional<boolean>;
              cmd_scaffold_required_auth?: Optional<boolean>;
              cmd_scaffold_template_custom?: Optional<boolean>;
              cmd_scaffold_template_flavor?: Optional<string>;
              cmd_scaffold_type?: Optional<string>;
              cmd_scaffold_type_category?: Optional<string>;
              cmd_scaffold_type_gated?: Optional<boolean>;
              cmd_scaffold_type_owner?: Optional<string>;
              cmd_scaffold_used_prompts_for_type?: Optional<boolean>;
              command: string;
              env_auth_method?: Optional<string>;
              env_ci?: Optional<boolean>;
              env_ci_platform?: Optional<string>;
              env_cloud?: Optional<string>;
              env_device_id?: Optional<string>;
              env_is_global?: Optional<boolean>;
              env_package_manager?: Optional<string>;
              env_package_manager_workspaces?: Optional<boolean>;
              env_plugin_installed_any_custom?: Optional<boolean>;
              env_plugin_installed_shopify?: Optional<string>;
              env_shell?: Optional<string>;
              env_web_ide?: Optional<string>;
              is_employee: boolean;
              node_version: string;
              partner_id?: Optional<number>;
              project_type?: Optional<string>;
              ruby_version: string;
              store_fqdn_hash?: Optional<string>;
              success: boolean;
              time_end: number;
              time_start: number;
              total_time: number;
              uname: string;
              user_id: string;
          };
          sensitive: {
              app_name?: Optional<string>;
              args: string;
              cmd_all_environment_flags?: Optional<string>;
              cmd_dev_tunnel_custom?: Optional<string>;
              env_plugin_installed_all?: Optional<string>;
              error_message?: Optional<string>;
              metadata?: Optional<string>;
              store_fqdn?: Optional<string>;
          };
      }

      Type declaration

      • public: {
            api_key?: Optional<string>;
            app_extensions_any?: Optional<boolean>;
            app_extensions_breakdown?: Optional<string>;
            app_extensions_count?: Optional<number>;
            app_extensions_custom_layout?: Optional<boolean>;
            app_extensions_function_any?: Optional<boolean>;
            app_extensions_function_count?: Optional<number>;
            app_extensions_function_custom_layout?: Optional<boolean>;
            app_extensions_theme_any?: Optional<boolean>;
            app_extensions_theme_count?: Optional<number>;
            app_extensions_theme_custom_layout?: Optional<boolean>;
            app_extensions_ui_any?: Optional<boolean>;
            app_extensions_ui_count?: Optional<number>;
            app_extensions_ui_custom_layout?: Optional<boolean>;
            app_name_hash?: Optional<string>;
            app_path_hash?: Optional<string>;
            app_scopes?: Optional<string>;
            app_web_backend_any?: Optional<boolean>;
            app_web_backend_count?: Optional<number>;
            app_web_custom_layout?: Optional<boolean>;
            app_web_framework?: Optional<string>;
            app_web_frontend_any?: Optional<boolean>;
            app_web_frontend_count?: Optional<number>;
            cli_version: string;
            cmd_all_alias_used?: Optional<string>;
            cmd_all_exit?: Optional<string>;
            cmd_all_force?: Optional<boolean>;
            cmd_all_last_graphql_request_id?: Optional<string>;
            cmd_all_launcher?: Optional<string>;
            cmd_all_path_override?: Optional<boolean>;
            cmd_all_path_override_hash?: Optional<string>;
            cmd_all_plugin?: Optional<string>;
            cmd_all_timing_active_ms?: Optional<number>;
            cmd_all_timing_network_ms?: Optional<number>;
            cmd_all_timing_prompts_ms?: Optional<number>;
            cmd_all_topic?: Optional<string>;
            cmd_all_verbose?: Optional<boolean>;
            cmd_app_all_configs_any?: Optional<boolean>;
            cmd_app_all_configs_clients?: Optional<string>;
            cmd_app_dependency_installation_skipped?: Optional<boolean>;
            cmd_app_deployment_mode?: Optional<string>;
            cmd_app_linked_config_git_tracked?: Optional<boolean>;
            cmd_app_linked_config_name?: Optional<string>;
            cmd_app_linked_config_source?: Optional<string>;
            cmd_app_linked_config_used?: Optional<boolean>;
            cmd_app_linked_config_uses_cli_managed_urls?: Optional<boolean>;
            cmd_app_reset_used?: Optional<boolean>;
            cmd_app_warning_api_key_deprecation_displayed?: Optional<boolean>;
            cmd_create_app_template?: Optional<string>;
            cmd_create_app_template_url?: Optional<string>;
            cmd_deploy_config_modules_added?: Optional<string>;
            cmd_deploy_config_modules_breakdown?: Optional<string>;
            cmd_deploy_config_modules_deleted?: Optional<string>;
            cmd_deploy_config_modules_updated?: Optional<string>;
            cmd_deploy_confirm_cancelled?: Optional<boolean>;
            cmd_deploy_confirm_include_config_used?: Optional<boolean>;
            cmd_deploy_confirm_new_registrations?: Optional<number>;
            cmd_deploy_confirm_removed_registrations?: Optional<number>;
            cmd_deploy_confirm_time_to_complete_ms?: Optional<number>;
            cmd_deploy_confirm_updated_registrations?: Optional<number>;
            cmd_deploy_flag_message_used?: Optional<boolean>;
            cmd_deploy_flag_source_url_used?: Optional<boolean>;
            cmd_deploy_flag_version_used?: Optional<boolean>;
            cmd_deploy_include_config_used?: Optional<boolean>;
            cmd_deploy_prompt_upgrade_to_unified_displayed?: Optional<boolean>;
            cmd_deploy_prompt_upgrade_to_unified_response?: Optional<string>;
            cmd_dev_dev_preview_toggle_used?: Optional<boolean>;
            cmd_dev_graphiql_opened?: Optional<boolean>;
            cmd_dev_preview_url_opened?: Optional<boolean>;
            cmd_dev_tunnel_custom_hash?: Optional<string>;
            cmd_dev_tunnel_type?: Optional<string>;
            cmd_dev_urls_updated?: Optional<boolean>;
            cmd_extensions_binary_from_source?: Optional<boolean>;
            cmd_release_confirm_cancelled?: Optional<boolean>;
            cmd_scaffold_required_auth?: Optional<boolean>;
            cmd_scaffold_template_custom?: Optional<boolean>;
            cmd_scaffold_template_flavor?: Optional<string>;
            cmd_scaffold_type?: Optional<string>;
            cmd_scaffold_type_category?: Optional<string>;
            cmd_scaffold_type_gated?: Optional<boolean>;
            cmd_scaffold_type_owner?: Optional<string>;
            cmd_scaffold_used_prompts_for_type?: Optional<boolean>;
            command: string;
            env_auth_method?: Optional<string>;
            env_ci?: Optional<boolean>;
            env_ci_platform?: Optional<string>;
            env_cloud?: Optional<string>;
            env_device_id?: Optional<string>;
            env_is_global?: Optional<boolean>;
            env_package_manager?: Optional<string>;
            env_package_manager_workspaces?: Optional<boolean>;
            env_plugin_installed_any_custom?: Optional<boolean>;
            env_plugin_installed_shopify?: Optional<string>;
            env_shell?: Optional<string>;
            env_web_ide?: Optional<string>;
            is_employee: boolean;
            node_version: string;
            partner_id?: Optional<number>;
            project_type?: Optional<string>;
            ruby_version: string;
            store_fqdn_hash?: Optional<string>;
            success: boolean;
            time_end: number;
            time_start: number;
            total_time: number;
            uname: string;
            user_id: string;
        }
        • Optional api_key?: Optional<string>
        • Optional app_extensions_any?: Optional<boolean>
        • Optional app_extensions_breakdown?: Optional<string>
        • Optional app_extensions_count?: Optional<number>
        • Optional app_extensions_custom_layout?: Optional<boolean>
        • Optional app_extensions_function_any?: Optional<boolean>
        • Optional app_extensions_function_count?: Optional<number>
        • Optional app_extensions_function_custom_layout?: Optional<boolean>
        • Optional app_extensions_theme_any?: Optional<boolean>
        • Optional app_extensions_theme_count?: Optional<number>
        • Optional app_extensions_theme_custom_layout?: Optional<boolean>
        • Optional app_extensions_ui_any?: Optional<boolean>
        • Optional app_extensions_ui_count?: Optional<number>
        • Optional app_extensions_ui_custom_layout?: Optional<boolean>
        • Optional app_name_hash?: Optional<string>
        • Optional app_path_hash?: Optional<string>
        • Optional app_scopes?: Optional<string>
        • Optional app_web_backend_any?: Optional<boolean>
        • Optional app_web_backend_count?: Optional<number>
        • Optional app_web_custom_layout?: Optional<boolean>
        • Optional app_web_framework?: Optional<string>
        • Optional app_web_frontend_any?: Optional<boolean>
        • Optional app_web_frontend_count?: Optional<number>
        • cli_version: string
        • Optional cmd_all_alias_used?: Optional<string>
        • Optional cmd_all_exit?: Optional<string>
        • Optional cmd_all_force?: Optional<boolean>
        • Optional cmd_all_last_graphql_request_id?: Optional<string>
        • Optional cmd_all_launcher?: Optional<string>
        • Optional cmd_all_path_override?: Optional<boolean>
        • Optional cmd_all_path_override_hash?: Optional<string>
        • Optional cmd_all_plugin?: Optional<string>
        • Optional cmd_all_timing_active_ms?: Optional<number>
        • Optional cmd_all_timing_network_ms?: Optional<number>
        • Optional cmd_all_timing_prompts_ms?: Optional<number>
        • Optional cmd_all_topic?: Optional<string>
        • Optional cmd_all_verbose?: Optional<boolean>
        • Optional cmd_app_all_configs_any?: Optional<boolean>
        • Optional cmd_app_all_configs_clients?: Optional<string>
        • Optional cmd_app_dependency_installation_skipped?: Optional<boolean>
        • Optional cmd_app_deployment_mode?: Optional<string>
        • Optional cmd_app_linked_config_git_tracked?: Optional<boolean>
        • Optional cmd_app_linked_config_name?: Optional<string>
        • Optional cmd_app_linked_config_source?: Optional<string>
        • Optional cmd_app_linked_config_used?: Optional<boolean>
        • Optional cmd_app_linked_config_uses_cli_managed_urls?: Optional<boolean>
        • Optional cmd_app_reset_used?: Optional<boolean>
        • Optional cmd_app_warning_api_key_deprecation_displayed?: Optional<boolean>
        • Optional cmd_create_app_template?: Optional<string>
        • Optional cmd_create_app_template_url?: Optional<string>
        • Optional cmd_deploy_config_modules_added?: Optional<string>
        • Optional cmd_deploy_config_modules_breakdown?: Optional<string>
        • Optional cmd_deploy_config_modules_deleted?: Optional<string>
        • Optional cmd_deploy_config_modules_updated?: Optional<string>
        • Optional cmd_deploy_confirm_cancelled?: Optional<boolean>
        • Optional cmd_deploy_confirm_include_config_used?: Optional<boolean>
        • Optional cmd_deploy_confirm_new_registrations?: Optional<number>
        • Optional cmd_deploy_confirm_removed_registrations?: Optional<number>
        • Optional cmd_deploy_confirm_time_to_complete_ms?: Optional<number>
        • Optional cmd_deploy_confirm_updated_registrations?: Optional<number>
        • Optional cmd_deploy_flag_message_used?: Optional<boolean>
        • Optional cmd_deploy_flag_source_url_used?: Optional<boolean>
        • Optional cmd_deploy_flag_version_used?: Optional<boolean>
        • Optional cmd_deploy_include_config_used?: Optional<boolean>
        • Optional cmd_deploy_prompt_upgrade_to_unified_displayed?: Optional<boolean>
        • Optional cmd_deploy_prompt_upgrade_to_unified_response?: Optional<string>
        • Optional cmd_dev_dev_preview_toggle_used?: Optional<boolean>
        • Optional cmd_dev_graphiql_opened?: Optional<boolean>
        • Optional cmd_dev_preview_url_opened?: Optional<boolean>
        • Optional cmd_dev_tunnel_custom_hash?: Optional<string>
        • Optional cmd_dev_tunnel_type?: Optional<string>
        • Optional cmd_dev_urls_updated?: Optional<boolean>
        • Optional cmd_extensions_binary_from_source?: Optional<boolean>
        • Optional cmd_release_confirm_cancelled?: Optional<boolean>
        • Optional cmd_scaffold_required_auth?: Optional<boolean>
        • Optional cmd_scaffold_template_custom?: Optional<boolean>
        • Optional cmd_scaffold_template_flavor?: Optional<string>
        • Optional cmd_scaffold_type?: Optional<string>
        • Optional cmd_scaffold_type_category?: Optional<string>
        • Optional cmd_scaffold_type_gated?: Optional<boolean>
        • Optional cmd_scaffold_type_owner?: Optional<string>
        • Optional cmd_scaffold_used_prompts_for_type?: Optional<boolean>
        • command: string
        • Optional env_auth_method?: Optional<string>
        • Optional env_ci?: Optional<boolean>
        • Optional env_ci_platform?: Optional<string>
        • Optional env_cloud?: Optional<string>
        • Optional env_device_id?: Optional<string>
        • Optional env_is_global?: Optional<boolean>
        • Optional env_package_manager?: Optional<string>
        • Optional env_package_manager_workspaces?: Optional<boolean>
        • Optional env_plugin_installed_any_custom?: Optional<boolean>
        • Optional env_plugin_installed_shopify?: Optional<string>
        • Optional env_shell?: Optional<string>
        • Optional env_web_ide?: Optional<string>
        • is_employee: boolean
        • node_version: string
        • Optional partner_id?: Optional<number>
        • Optional project_type?: Optional<string>
        • ruby_version: string
        • Optional store_fqdn_hash?: Optional<string>
        • success: boolean
        • time_end: number
        • time_start: number
        • total_time: number
        • uname: string
        • user_id: string
      • sensitive: {
            app_name?: Optional<string>;
            args: string;
            cmd_all_environment_flags?: Optional<string>;
            cmd_dev_tunnel_custom?: Optional<string>;
            env_plugin_installed_all?: Optional<string>;
            error_message?: Optional<string>;
            metadata?: Optional<string>;
            store_fqdn?: Optional<string>;
        }
        • Optional app_name?: Optional<string>
        • args: string
        • Optional cmd_all_environment_flags?: Optional<string>
        • Optional cmd_dev_tunnel_custom?: Optional<string>
        • Optional env_plugin_installed_all?: Optional<string>
        • Optional error_message?: Optional<string>
        • Optional metadata?: Optional<string>
        • Optional store_fqdn?: Optional<string>
      \ No newline at end of file +Schemas | @shopify/cli-kit
      interface Schemas {
          app_cli3_command/1.15: {
              public: {
                  api_key?: Optional<string>;
                  app_extensions_any?: Optional<boolean>;
                  app_extensions_breakdown?: Optional<string>;
                  app_extensions_count?: Optional<number>;
                  app_extensions_custom_layout?: Optional<boolean>;
                  app_extensions_function_any?: Optional<boolean>;
                  app_extensions_function_count?: Optional<number>;
                  app_extensions_function_custom_layout?: Optional<boolean>;
                  app_extensions_theme_any?: Optional<boolean>;
                  app_extensions_theme_count?: Optional<number>;
                  app_extensions_theme_custom_layout?: Optional<boolean>;
                  app_extensions_ui_any?: Optional<boolean>;
                  app_extensions_ui_count?: Optional<number>;
                  app_extensions_ui_custom_layout?: Optional<boolean>;
                  app_name_hash?: Optional<string>;
                  app_path_hash?: Optional<string>;
                  app_scopes?: Optional<string>;
                  app_web_backend_any?: Optional<boolean>;
                  app_web_backend_count?: Optional<number>;
                  app_web_custom_layout?: Optional<boolean>;
                  app_web_framework?: Optional<string>;
                  app_web_frontend_any?: Optional<boolean>;
                  app_web_frontend_count?: Optional<number>;
                  cli_version: string;
                  cmd_all_alias_used?: Optional<string>;
                  cmd_all_exit?: Optional<string>;
                  cmd_all_force?: Optional<boolean>;
                  cmd_all_last_graphql_request_id?: Optional<string>;
                  cmd_all_launcher?: Optional<string>;
                  cmd_all_path_override?: Optional<boolean>;
                  cmd_all_path_override_hash?: Optional<string>;
                  cmd_all_plugin?: Optional<string>;
                  cmd_all_timing_active_ms?: Optional<number>;
                  cmd_all_timing_network_ms?: Optional<number>;
                  cmd_all_timing_prompts_ms?: Optional<number>;
                  cmd_all_topic?: Optional<string>;
                  cmd_all_verbose?: Optional<boolean>;
                  cmd_app_all_configs_any?: Optional<boolean>;
                  cmd_app_all_configs_clients?: Optional<string>;
                  cmd_app_dependency_installation_skipped?: Optional<boolean>;
                  cmd_app_deployment_mode?: Optional<string>;
                  cmd_app_linked_config_git_tracked?: Optional<boolean>;
                  cmd_app_linked_config_name?: Optional<string>;
                  cmd_app_linked_config_source?: Optional<string>;
                  cmd_app_linked_config_used?: Optional<boolean>;
                  cmd_app_linked_config_uses_cli_managed_urls?: Optional<boolean>;
                  cmd_app_reset_used?: Optional<boolean>;
                  cmd_app_warning_api_key_deprecation_displayed?: Optional<boolean>;
                  cmd_create_app_template?: Optional<string>;
                  cmd_create_app_template_url?: Optional<string>;
                  cmd_deploy_config_modules_added?: Optional<string>;
                  cmd_deploy_config_modules_breakdown?: Optional<string>;
                  cmd_deploy_config_modules_deleted?: Optional<string>;
                  cmd_deploy_config_modules_updated?: Optional<string>;
                  cmd_deploy_confirm_cancelled?: Optional<boolean>;
                  cmd_deploy_confirm_include_config_used?: Optional<boolean>;
                  cmd_deploy_confirm_new_registrations?: Optional<number>;
                  cmd_deploy_confirm_removed_registrations?: Optional<number>;
                  cmd_deploy_confirm_time_to_complete_ms?: Optional<number>;
                  cmd_deploy_confirm_updated_registrations?: Optional<number>;
                  cmd_deploy_flag_message_used?: Optional<boolean>;
                  cmd_deploy_flag_source_url_used?: Optional<boolean>;
                  cmd_deploy_flag_version_used?: Optional<boolean>;
                  cmd_deploy_include_config_used?: Optional<boolean>;
                  cmd_deploy_prompt_upgrade_to_unified_displayed?: Optional<boolean>;
                  cmd_deploy_prompt_upgrade_to_unified_response?: Optional<string>;
                  cmd_dev_dev_preview_toggle_used?: Optional<boolean>;
                  cmd_dev_graphiql_opened?: Optional<boolean>;
                  cmd_dev_preview_url_opened?: Optional<boolean>;
                  cmd_dev_tunnel_custom_hash?: Optional<string>;
                  cmd_dev_tunnel_type?: Optional<string>;
                  cmd_dev_urls_updated?: Optional<boolean>;
                  cmd_extensions_binary_from_source?: Optional<boolean>;
                  cmd_release_confirm_cancelled?: Optional<boolean>;
                  cmd_scaffold_required_auth?: Optional<boolean>;
                  cmd_scaffold_template_custom?: Optional<boolean>;
                  cmd_scaffold_template_flavor?: Optional<string>;
                  cmd_scaffold_type?: Optional<string>;
                  cmd_scaffold_type_category?: Optional<string>;
                  cmd_scaffold_type_gated?: Optional<boolean>;
                  cmd_scaffold_type_owner?: Optional<string>;
                  cmd_scaffold_used_prompts_for_type?: Optional<boolean>;
                  command: string;
                  env_auth_method?: Optional<string>;
                  env_ci?: Optional<boolean>;
                  env_ci_platform?: Optional<string>;
                  env_cloud?: Optional<string>;
                  env_device_id?: Optional<string>;
                  env_is_global?: Optional<boolean>;
                  env_package_manager?: Optional<string>;
                  env_package_manager_workspaces?: Optional<boolean>;
                  env_plugin_installed_any_custom?: Optional<boolean>;
                  env_plugin_installed_shopify?: Optional<string>;
                  env_shell?: Optional<string>;
                  env_web_ide?: Optional<string>;
                  is_employee: boolean;
                  node_version: string;
                  partner_id?: Optional<number>;
                  project_type?: Optional<string>;
                  ruby_version: string;
                  store_fqdn_hash?: Optional<string>;
                  success: boolean;
                  time_end: number;
                  time_start: number;
                  total_time: number;
                  uname: string;
                  user_id: string;
              };
              sensitive: {
                  app_name?: Optional<string>;
                  args: string;
                  cmd_all_environment_flags?: Optional<string>;
                  cmd_dev_tunnel_custom?: Optional<string>;
                  env_plugin_installed_all?: Optional<string>;
                  error_message?: Optional<string>;
                  metadata?: Optional<string>;
                  store_fqdn?: Optional<string>;
              };
          };
          [schemaId: string]: {
              public: JsonMap;
              sensitive: JsonMap;
          };
      }

      Indexable

      [schemaId: string]: {
          public: JsonMap;
          sensitive: JsonMap;
      }
      • public: JsonMap
      • sensitive: JsonMap

      Properties

      app_cli3_command/1.15: {
          public: {
              api_key?: Optional<string>;
              app_extensions_any?: Optional<boolean>;
              app_extensions_breakdown?: Optional<string>;
              app_extensions_count?: Optional<number>;
              app_extensions_custom_layout?: Optional<boolean>;
              app_extensions_function_any?: Optional<boolean>;
              app_extensions_function_count?: Optional<number>;
              app_extensions_function_custom_layout?: Optional<boolean>;
              app_extensions_theme_any?: Optional<boolean>;
              app_extensions_theme_count?: Optional<number>;
              app_extensions_theme_custom_layout?: Optional<boolean>;
              app_extensions_ui_any?: Optional<boolean>;
              app_extensions_ui_count?: Optional<number>;
              app_extensions_ui_custom_layout?: Optional<boolean>;
              app_name_hash?: Optional<string>;
              app_path_hash?: Optional<string>;
              app_scopes?: Optional<string>;
              app_web_backend_any?: Optional<boolean>;
              app_web_backend_count?: Optional<number>;
              app_web_custom_layout?: Optional<boolean>;
              app_web_framework?: Optional<string>;
              app_web_frontend_any?: Optional<boolean>;
              app_web_frontend_count?: Optional<number>;
              cli_version: string;
              cmd_all_alias_used?: Optional<string>;
              cmd_all_exit?: Optional<string>;
              cmd_all_force?: Optional<boolean>;
              cmd_all_last_graphql_request_id?: Optional<string>;
              cmd_all_launcher?: Optional<string>;
              cmd_all_path_override?: Optional<boolean>;
              cmd_all_path_override_hash?: Optional<string>;
              cmd_all_plugin?: Optional<string>;
              cmd_all_timing_active_ms?: Optional<number>;
              cmd_all_timing_network_ms?: Optional<number>;
              cmd_all_timing_prompts_ms?: Optional<number>;
              cmd_all_topic?: Optional<string>;
              cmd_all_verbose?: Optional<boolean>;
              cmd_app_all_configs_any?: Optional<boolean>;
              cmd_app_all_configs_clients?: Optional<string>;
              cmd_app_dependency_installation_skipped?: Optional<boolean>;
              cmd_app_deployment_mode?: Optional<string>;
              cmd_app_linked_config_git_tracked?: Optional<boolean>;
              cmd_app_linked_config_name?: Optional<string>;
              cmd_app_linked_config_source?: Optional<string>;
              cmd_app_linked_config_used?: Optional<boolean>;
              cmd_app_linked_config_uses_cli_managed_urls?: Optional<boolean>;
              cmd_app_reset_used?: Optional<boolean>;
              cmd_app_warning_api_key_deprecation_displayed?: Optional<boolean>;
              cmd_create_app_template?: Optional<string>;
              cmd_create_app_template_url?: Optional<string>;
              cmd_deploy_config_modules_added?: Optional<string>;
              cmd_deploy_config_modules_breakdown?: Optional<string>;
              cmd_deploy_config_modules_deleted?: Optional<string>;
              cmd_deploy_config_modules_updated?: Optional<string>;
              cmd_deploy_confirm_cancelled?: Optional<boolean>;
              cmd_deploy_confirm_include_config_used?: Optional<boolean>;
              cmd_deploy_confirm_new_registrations?: Optional<number>;
              cmd_deploy_confirm_removed_registrations?: Optional<number>;
              cmd_deploy_confirm_time_to_complete_ms?: Optional<number>;
              cmd_deploy_confirm_updated_registrations?: Optional<number>;
              cmd_deploy_flag_message_used?: Optional<boolean>;
              cmd_deploy_flag_source_url_used?: Optional<boolean>;
              cmd_deploy_flag_version_used?: Optional<boolean>;
              cmd_deploy_include_config_used?: Optional<boolean>;
              cmd_deploy_prompt_upgrade_to_unified_displayed?: Optional<boolean>;
              cmd_deploy_prompt_upgrade_to_unified_response?: Optional<string>;
              cmd_dev_dev_preview_toggle_used?: Optional<boolean>;
              cmd_dev_graphiql_opened?: Optional<boolean>;
              cmd_dev_preview_url_opened?: Optional<boolean>;
              cmd_dev_tunnel_custom_hash?: Optional<string>;
              cmd_dev_tunnel_type?: Optional<string>;
              cmd_dev_urls_updated?: Optional<boolean>;
              cmd_extensions_binary_from_source?: Optional<boolean>;
              cmd_release_confirm_cancelled?: Optional<boolean>;
              cmd_scaffold_required_auth?: Optional<boolean>;
              cmd_scaffold_template_custom?: Optional<boolean>;
              cmd_scaffold_template_flavor?: Optional<string>;
              cmd_scaffold_type?: Optional<string>;
              cmd_scaffold_type_category?: Optional<string>;
              cmd_scaffold_type_gated?: Optional<boolean>;
              cmd_scaffold_type_owner?: Optional<string>;
              cmd_scaffold_used_prompts_for_type?: Optional<boolean>;
              command: string;
              env_auth_method?: Optional<string>;
              env_ci?: Optional<boolean>;
              env_ci_platform?: Optional<string>;
              env_cloud?: Optional<string>;
              env_device_id?: Optional<string>;
              env_is_global?: Optional<boolean>;
              env_package_manager?: Optional<string>;
              env_package_manager_workspaces?: Optional<boolean>;
              env_plugin_installed_any_custom?: Optional<boolean>;
              env_plugin_installed_shopify?: Optional<string>;
              env_shell?: Optional<string>;
              env_web_ide?: Optional<string>;
              is_employee: boolean;
              node_version: string;
              partner_id?: Optional<number>;
              project_type?: Optional<string>;
              ruby_version: string;
              store_fqdn_hash?: Optional<string>;
              success: boolean;
              time_end: number;
              time_start: number;
              total_time: number;
              uname: string;
              user_id: string;
          };
          sensitive: {
              app_name?: Optional<string>;
              args: string;
              cmd_all_environment_flags?: Optional<string>;
              cmd_dev_tunnel_custom?: Optional<string>;
              env_plugin_installed_all?: Optional<string>;
              error_message?: Optional<string>;
              metadata?: Optional<string>;
              store_fqdn?: Optional<string>;
          };
      }

      Type declaration

      • public: {
            api_key?: Optional<string>;
            app_extensions_any?: Optional<boolean>;
            app_extensions_breakdown?: Optional<string>;
            app_extensions_count?: Optional<number>;
            app_extensions_custom_layout?: Optional<boolean>;
            app_extensions_function_any?: Optional<boolean>;
            app_extensions_function_count?: Optional<number>;
            app_extensions_function_custom_layout?: Optional<boolean>;
            app_extensions_theme_any?: Optional<boolean>;
            app_extensions_theme_count?: Optional<number>;
            app_extensions_theme_custom_layout?: Optional<boolean>;
            app_extensions_ui_any?: Optional<boolean>;
            app_extensions_ui_count?: Optional<number>;
            app_extensions_ui_custom_layout?: Optional<boolean>;
            app_name_hash?: Optional<string>;
            app_path_hash?: Optional<string>;
            app_scopes?: Optional<string>;
            app_web_backend_any?: Optional<boolean>;
            app_web_backend_count?: Optional<number>;
            app_web_custom_layout?: Optional<boolean>;
            app_web_framework?: Optional<string>;
            app_web_frontend_any?: Optional<boolean>;
            app_web_frontend_count?: Optional<number>;
            cli_version: string;
            cmd_all_alias_used?: Optional<string>;
            cmd_all_exit?: Optional<string>;
            cmd_all_force?: Optional<boolean>;
            cmd_all_last_graphql_request_id?: Optional<string>;
            cmd_all_launcher?: Optional<string>;
            cmd_all_path_override?: Optional<boolean>;
            cmd_all_path_override_hash?: Optional<string>;
            cmd_all_plugin?: Optional<string>;
            cmd_all_timing_active_ms?: Optional<number>;
            cmd_all_timing_network_ms?: Optional<number>;
            cmd_all_timing_prompts_ms?: Optional<number>;
            cmd_all_topic?: Optional<string>;
            cmd_all_verbose?: Optional<boolean>;
            cmd_app_all_configs_any?: Optional<boolean>;
            cmd_app_all_configs_clients?: Optional<string>;
            cmd_app_dependency_installation_skipped?: Optional<boolean>;
            cmd_app_deployment_mode?: Optional<string>;
            cmd_app_linked_config_git_tracked?: Optional<boolean>;
            cmd_app_linked_config_name?: Optional<string>;
            cmd_app_linked_config_source?: Optional<string>;
            cmd_app_linked_config_used?: Optional<boolean>;
            cmd_app_linked_config_uses_cli_managed_urls?: Optional<boolean>;
            cmd_app_reset_used?: Optional<boolean>;
            cmd_app_warning_api_key_deprecation_displayed?: Optional<boolean>;
            cmd_create_app_template?: Optional<string>;
            cmd_create_app_template_url?: Optional<string>;
            cmd_deploy_config_modules_added?: Optional<string>;
            cmd_deploy_config_modules_breakdown?: Optional<string>;
            cmd_deploy_config_modules_deleted?: Optional<string>;
            cmd_deploy_config_modules_updated?: Optional<string>;
            cmd_deploy_confirm_cancelled?: Optional<boolean>;
            cmd_deploy_confirm_include_config_used?: Optional<boolean>;
            cmd_deploy_confirm_new_registrations?: Optional<number>;
            cmd_deploy_confirm_removed_registrations?: Optional<number>;
            cmd_deploy_confirm_time_to_complete_ms?: Optional<number>;
            cmd_deploy_confirm_updated_registrations?: Optional<number>;
            cmd_deploy_flag_message_used?: Optional<boolean>;
            cmd_deploy_flag_source_url_used?: Optional<boolean>;
            cmd_deploy_flag_version_used?: Optional<boolean>;
            cmd_deploy_include_config_used?: Optional<boolean>;
            cmd_deploy_prompt_upgrade_to_unified_displayed?: Optional<boolean>;
            cmd_deploy_prompt_upgrade_to_unified_response?: Optional<string>;
            cmd_dev_dev_preview_toggle_used?: Optional<boolean>;
            cmd_dev_graphiql_opened?: Optional<boolean>;
            cmd_dev_preview_url_opened?: Optional<boolean>;
            cmd_dev_tunnel_custom_hash?: Optional<string>;
            cmd_dev_tunnel_type?: Optional<string>;
            cmd_dev_urls_updated?: Optional<boolean>;
            cmd_extensions_binary_from_source?: Optional<boolean>;
            cmd_release_confirm_cancelled?: Optional<boolean>;
            cmd_scaffold_required_auth?: Optional<boolean>;
            cmd_scaffold_template_custom?: Optional<boolean>;
            cmd_scaffold_template_flavor?: Optional<string>;
            cmd_scaffold_type?: Optional<string>;
            cmd_scaffold_type_category?: Optional<string>;
            cmd_scaffold_type_gated?: Optional<boolean>;
            cmd_scaffold_type_owner?: Optional<string>;
            cmd_scaffold_used_prompts_for_type?: Optional<boolean>;
            command: string;
            env_auth_method?: Optional<string>;
            env_ci?: Optional<boolean>;
            env_ci_platform?: Optional<string>;
            env_cloud?: Optional<string>;
            env_device_id?: Optional<string>;
            env_is_global?: Optional<boolean>;
            env_package_manager?: Optional<string>;
            env_package_manager_workspaces?: Optional<boolean>;
            env_plugin_installed_any_custom?: Optional<boolean>;
            env_plugin_installed_shopify?: Optional<string>;
            env_shell?: Optional<string>;
            env_web_ide?: Optional<string>;
            is_employee: boolean;
            node_version: string;
            partner_id?: Optional<number>;
            project_type?: Optional<string>;
            ruby_version: string;
            store_fqdn_hash?: Optional<string>;
            success: boolean;
            time_end: number;
            time_start: number;
            total_time: number;
            uname: string;
            user_id: string;
        }
        • Optional api_key?: Optional<string>
        • Optional app_extensions_any?: Optional<boolean>
        • Optional app_extensions_breakdown?: Optional<string>
        • Optional app_extensions_count?: Optional<number>
        • Optional app_extensions_custom_layout?: Optional<boolean>
        • Optional app_extensions_function_any?: Optional<boolean>
        • Optional app_extensions_function_count?: Optional<number>
        • Optional app_extensions_function_custom_layout?: Optional<boolean>
        • Optional app_extensions_theme_any?: Optional<boolean>
        • Optional app_extensions_theme_count?: Optional<number>
        • Optional app_extensions_theme_custom_layout?: Optional<boolean>
        • Optional app_extensions_ui_any?: Optional<boolean>
        • Optional app_extensions_ui_count?: Optional<number>
        • Optional app_extensions_ui_custom_layout?: Optional<boolean>
        • Optional app_name_hash?: Optional<string>
        • Optional app_path_hash?: Optional<string>
        • Optional app_scopes?: Optional<string>
        • Optional app_web_backend_any?: Optional<boolean>
        • Optional app_web_backend_count?: Optional<number>
        • Optional app_web_custom_layout?: Optional<boolean>
        • Optional app_web_framework?: Optional<string>
        • Optional app_web_frontend_any?: Optional<boolean>
        • Optional app_web_frontend_count?: Optional<number>
        • cli_version: string
        • Optional cmd_all_alias_used?: Optional<string>
        • Optional cmd_all_exit?: Optional<string>
        • Optional cmd_all_force?: Optional<boolean>
        • Optional cmd_all_last_graphql_request_id?: Optional<string>
        • Optional cmd_all_launcher?: Optional<string>
        • Optional cmd_all_path_override?: Optional<boolean>
        • Optional cmd_all_path_override_hash?: Optional<string>
        • Optional cmd_all_plugin?: Optional<string>
        • Optional cmd_all_timing_active_ms?: Optional<number>
        • Optional cmd_all_timing_network_ms?: Optional<number>
        • Optional cmd_all_timing_prompts_ms?: Optional<number>
        • Optional cmd_all_topic?: Optional<string>
        • Optional cmd_all_verbose?: Optional<boolean>
        • Optional cmd_app_all_configs_any?: Optional<boolean>
        • Optional cmd_app_all_configs_clients?: Optional<string>
        • Optional cmd_app_dependency_installation_skipped?: Optional<boolean>
        • Optional cmd_app_deployment_mode?: Optional<string>
        • Optional cmd_app_linked_config_git_tracked?: Optional<boolean>
        • Optional cmd_app_linked_config_name?: Optional<string>
        • Optional cmd_app_linked_config_source?: Optional<string>
        • Optional cmd_app_linked_config_used?: Optional<boolean>
        • Optional cmd_app_linked_config_uses_cli_managed_urls?: Optional<boolean>
        • Optional cmd_app_reset_used?: Optional<boolean>
        • Optional cmd_app_warning_api_key_deprecation_displayed?: Optional<boolean>
        • Optional cmd_create_app_template?: Optional<string>
        • Optional cmd_create_app_template_url?: Optional<string>
        • Optional cmd_deploy_config_modules_added?: Optional<string>
        • Optional cmd_deploy_config_modules_breakdown?: Optional<string>
        • Optional cmd_deploy_config_modules_deleted?: Optional<string>
        • Optional cmd_deploy_config_modules_updated?: Optional<string>
        • Optional cmd_deploy_confirm_cancelled?: Optional<boolean>
        • Optional cmd_deploy_confirm_include_config_used?: Optional<boolean>
        • Optional cmd_deploy_confirm_new_registrations?: Optional<number>
        • Optional cmd_deploy_confirm_removed_registrations?: Optional<number>
        • Optional cmd_deploy_confirm_time_to_complete_ms?: Optional<number>
        • Optional cmd_deploy_confirm_updated_registrations?: Optional<number>
        • Optional cmd_deploy_flag_message_used?: Optional<boolean>
        • Optional cmd_deploy_flag_source_url_used?: Optional<boolean>
        • Optional cmd_deploy_flag_version_used?: Optional<boolean>
        • Optional cmd_deploy_include_config_used?: Optional<boolean>
        • Optional cmd_deploy_prompt_upgrade_to_unified_displayed?: Optional<boolean>
        • Optional cmd_deploy_prompt_upgrade_to_unified_response?: Optional<string>
        • Optional cmd_dev_dev_preview_toggle_used?: Optional<boolean>
        • Optional cmd_dev_graphiql_opened?: Optional<boolean>
        • Optional cmd_dev_preview_url_opened?: Optional<boolean>
        • Optional cmd_dev_tunnel_custom_hash?: Optional<string>
        • Optional cmd_dev_tunnel_type?: Optional<string>
        • Optional cmd_dev_urls_updated?: Optional<boolean>
        • Optional cmd_extensions_binary_from_source?: Optional<boolean>
        • Optional cmd_release_confirm_cancelled?: Optional<boolean>
        • Optional cmd_scaffold_required_auth?: Optional<boolean>
        • Optional cmd_scaffold_template_custom?: Optional<boolean>
        • Optional cmd_scaffold_template_flavor?: Optional<string>
        • Optional cmd_scaffold_type?: Optional<string>
        • Optional cmd_scaffold_type_category?: Optional<string>
        • Optional cmd_scaffold_type_gated?: Optional<boolean>
        • Optional cmd_scaffold_type_owner?: Optional<string>
        • Optional cmd_scaffold_used_prompts_for_type?: Optional<boolean>
        • command: string
        • Optional env_auth_method?: Optional<string>
        • Optional env_ci?: Optional<boolean>
        • Optional env_ci_platform?: Optional<string>
        • Optional env_cloud?: Optional<string>
        • Optional env_device_id?: Optional<string>
        • Optional env_is_global?: Optional<boolean>
        • Optional env_package_manager?: Optional<string>
        • Optional env_package_manager_workspaces?: Optional<boolean>
        • Optional env_plugin_installed_any_custom?: Optional<boolean>
        • Optional env_plugin_installed_shopify?: Optional<string>
        • Optional env_shell?: Optional<string>
        • Optional env_web_ide?: Optional<string>
        • is_employee: boolean
        • node_version: string
        • Optional partner_id?: Optional<number>
        • Optional project_type?: Optional<string>
        • ruby_version: string
        • Optional store_fqdn_hash?: Optional<string>
        • success: boolean
        • time_end: number
        • time_start: number
        • total_time: number
        • uname: string
        • user_id: string
      • sensitive: {
            app_name?: Optional<string>;
            args: string;
            cmd_all_environment_flags?: Optional<string>;
            cmd_dev_tunnel_custom?: Optional<string>;
            env_plugin_installed_all?: Optional<string>;
            error_message?: Optional<string>;
            metadata?: Optional<string>;
            store_fqdn?: Optional<string>;
        }
        • Optional app_name?: Optional<string>
        • args: string
        • Optional cmd_all_environment_flags?: Optional<string>
        • Optional cmd_dev_tunnel_custom?: Optional<string>
        • Optional env_plugin_installed_all?: Optional<string>
        • Optional error_message?: Optional<string>
        • Optional metadata?: Optional<string>
        • Optional store_fqdn?: Optional<string>
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_node_package_manager.DependencyVersion.html b/docs/api/cli-kit/interfaces/node_node_package_manager.DependencyVersion.html index 232200cb96b..7bff34ac2b6 100644 --- a/docs/api/cli-kit/interfaces/node_node_package_manager.DependencyVersion.html +++ b/docs/api/cli-kit/interfaces/node_node_package_manager.DependencyVersion.html @@ -1,12 +1,12 @@ DependencyVersion | @shopify/cli-kit

      An interface that represents a dependency name with its version

      -
      interface DependencyVersion {
          name: string;
          version: undefined | string;
      }

      Properties

      interface DependencyVersion {
          name: string;
          version: undefined | string;
      }

      Properties

      Properties

      name: string

      The name of the NPM dependency as it's reflected in the package.json:

      Example

      In the example below name would be "react"

      {
      "react": "1.2.3"
      }
      -
      version: undefined | string

      The version of the NPM dependency as it's reflected in the package.json:

      +
      version: undefined | string

      The version of the NPM dependency as it's reflected in the package.json:

      Example

      In the example below version would be "1.2.3"

      {
      "react": "1.2.3"
      }
      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_node_package_manager.PackageJson.html b/docs/api/cli-kit/interfaces/node_node_package_manager.PackageJson.html index 04b734147d1..49243f6e166 100644 --- a/docs/api/cli-kit/interfaces/node_node_package_manager.PackageJson.html +++ b/docs/api/cli-kit/interfaces/node_node_package_manager.PackageJson.html @@ -1,5 +1,5 @@ PackageJson | @shopify/cli-kit

      An interface that represents a package.json

      -
      interface PackageJson {
          author?: string;
          dependencies?: {
              [key: string]: string;
          };
          devDependencies?: {
              [key: string]: string;
          };
          name?: string;
          oclif?: {
              plugins?: string[];
          };
          overrides?: {
              [key: string]: string;
          };
          peerDependencies?: {
              [key: string]: string;
          };
          prettier?: string;
          private?: boolean;
          resolutions?: {
              [key: string]: string;
          };
          scripts?: {
              [key: string]: string;
          };
          version?: string;
          workspaces?: string[];
      }

      Properties

      interface PackageJson {
          author?: string;
          dependencies?: {
              [key: string]: string;
          };
          devDependencies?: {
              [key: string]: string;
          };
          name?: string;
          oclif?: {
              plugins?: string[];
          };
          overrides?: {
              [key: string]: string;
          };
          peerDependencies?: {
              [key: string]: string;
          };
          prettier?: string;
          private?: boolean;
          resolutions?: {
              [key: string]: string;
          };
          scripts?: {
              [key: string]: string;
          };
          version?: string;
          workspaces?: string[];
      }

      Properties

      author?: string

      The author attribute of the package.json

      -
      dependencies?: {
          [key: string]: string;
      }

      The dependencies attribute of the package.json

      -

      Type declaration

      • [key: string]: string
      devDependencies?: {
          [key: string]: string;
      }

      The devDependencies attribute of the package.json

      -

      Type declaration

      • [key: string]: string
      name?: string

      The name attribute of the package.json

      -
      oclif?: {
          plugins?: string[];
      }

      The optional oclif settings attribute of the package.json

      -

      Type declaration

      • Optional plugins?: string[]
      overrides?: {
          [key: string]: string;
      }

      The overrides attribute of the package.json. Only useful when using npm o npmn as package managers

      -

      Type declaration

      • [key: string]: string
      peerDependencies?: {
          [key: string]: string;
      }

      The peerDependencies attribute of the package.json

      -

      Type declaration

      • [key: string]: string
      prettier?: string

      The prettier attribute of the package.json

      -
      private?: boolean

      The private attribute of the package.json. +

      dependencies?: {
          [key: string]: string;
      }

      The dependencies attribute of the package.json

      +

      Type declaration

      • [key: string]: string
      devDependencies?: {
          [key: string]: string;
      }

      The devDependencies attribute of the package.json

      +

      Type declaration

      • [key: string]: string
      name?: string

      The name attribute of the package.json

      +
      oclif?: {
          plugins?: string[];
      }

      The optional oclif settings attribute of the package.json

      +

      Type declaration

      • Optional plugins?: string[]
      overrides?: {
          [key: string]: string;
      }

      The overrides attribute of the package.json. Only useful when using npm o npmn as package managers

      +

      Type declaration

      • [key: string]: string
      peerDependencies?: {
          [key: string]: string;
      }

      The peerDependencies attribute of the package.json

      +

      Type declaration

      • [key: string]: string
      prettier?: string

      The prettier attribute of the package.json

      +
      private?: boolean

      The private attribute of the package.json. https://docs.npmjs.com/cli/v9/configuring-npm/package-json#private

      -
      resolutions?: {
          [key: string]: string;
      }

      The resolutions attribute of the package.json. Only useful when using yarn as package manager

      -

      Type declaration

      • [key: string]: string
      scripts?: {
          [key: string]: string;
      }

      The scripts attribute of the package.json

      -

      Type declaration

      • [key: string]: string
      version?: string

      The version attribute of the package.json

      -
      workspaces?: string[]

      The workspaces attribute of the package.json

      -
      \ No newline at end of file +
      resolutions?: {
          [key: string]: string;
      }

      The resolutions attribute of the package.json. Only useful when using yarn as package manager

      +

      Type declaration

      • [key: string]: string
      scripts?: {
          [key: string]: string;
      }

      The scripts attribute of the package.json

      +

      Type declaration

      • [key: string]: string
      version?: string

      The version attribute of the package.json

      +
      workspaces?: string[]

      The workspaces attribute of the package.json

      +
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_output.OutputProcess.html b/docs/api/cli-kit/interfaces/node_output.OutputProcess.html index 199a6aa59a0..b218765d89d 100644 --- a/docs/api/cli-kit/interfaces/node_output.OutputProcess.html +++ b/docs/api/cli-kit/interfaces/node_output.OutputProcess.html @@ -1,8 +1,8 @@ -OutputProcess | @shopify/cli-kit
      interface OutputProcess {
          action: ((stdout, stderr, signal) => Promise<void>);
          prefix: string;
      }

      Properties

      action +OutputProcess | @shopify/cli-kit
      interface OutputProcess {
          action: ((stdout, stderr, signal) => Promise<void>);
          prefix: string;
      }

      Properties

      Properties

      action: ((stdout, stderr, signal) => Promise<void>)

      A callback to invoke the process. Stdout and stderr should be used to send standard output and error data that gets formatted with the right prefix.

      -

      Type declaration

        • (stdout, stderr, signal): Promise<void>
        • Parameters

          Returns Promise<void>

      prefix: string

      The prefix to include in the logs +

      Type declaration

        • (stdout, stderr, signal): Promise<void>
        • Parameters

          Returns Promise<void>

      prefix: string

      The prefix to include in the logs [vite] Output coming from Vite.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_plugins.HookReturnsPerPlugin.html b/docs/api/cli-kit/interfaces/node_plugins.HookReturnsPerPlugin.html index da399eba7be..6def4c3e584 100644 --- a/docs/api/cli-kit/interfaces/node_plugins.HookReturnsPerPlugin.html +++ b/docs/api/cli-kit/interfaces/node_plugins.HookReturnsPerPlugin.html @@ -1,7 +1,7 @@ HookReturnsPerPlugin | @shopify/cli-kit

      Tunnel Plugins types

      Any plugin that provides tunnel functionality should implement defineProviderand startTunnel

      -
      interface HookReturnsPerPlugin {
          public_command_metadata: {
              options: {
                  [key: string]: never;
              };
              pluginReturns: {
                  @shopify/app: Partial<AppSpecificMonorailFields>;
                  [pluginName: string]: JsonMap;
              };
          };
          sensitive_command_metadata: {
              options: {
                  [key: string]: never;
              };
              pluginReturns: {
                  @shopify/app: Partial<PickByPrefix<{
                      app_name?: Optional<string>;
                      args: string;
                      cmd_all_environment_flags?: Optional<string>;
                      cmd_dev_tunnel_custom?: Optional<string>;
                      env_plugin_installed_all?: Optional<string>;
                      error_message?: Optional<string>;
                      metadata?: Optional<string>;
                      store_fqdn?: Optional<string>;
                  }, "app_", never>>;
                  [pluginName: string]: JsonMap;
              };
          };
          tunnel_provider: {
              options: {
                  [key: string]: never;
              };
              pluginReturns: {
                  [pluginName: string]: {
                      name: string;
                  };
              };
          };
          tunnel_start: {
              options: {
                  port: number;
                  provider: string;
              };
              pluginReturns: {
                  [key: string]: Result<TunnelClient, TunnelError>;
              };
          };
          [hookName: string]: {
              options: {
                  [key: string]: unknown;
              };
              pluginReturns: {
                  [key: string]: unknown;
              };
          };
      }

      Hierarchy (view full)

      Indexable

      [hookName: string]: {
          options: {
              [key: string]: unknown;
          };
          pluginReturns: {
              [key: string]: unknown;
          };
      }
      • options: {
            [key: string]: unknown;
        }
        • [key: string]: unknown
      • pluginReturns: {
            [key: string]: unknown;
        }
        • [key: string]: unknown

      Properties

      interface HookReturnsPerPlugin {
          public_command_metadata: {
              options: {
                  [key: string]: never;
              };
              pluginReturns: {
                  @shopify/app: Partial<AppSpecificMonorailFields>;
                  [pluginName: string]: JsonMap;
              };
          };
          sensitive_command_metadata: {
              options: {
                  [key: string]: never;
              };
              pluginReturns: {
                  @shopify/app: Partial<PickByPrefix<{
                      app_name?: Optional<string>;
                      args: string;
                      cmd_all_environment_flags?: Optional<string>;
                      cmd_dev_tunnel_custom?: Optional<string>;
                      env_plugin_installed_all?: Optional<string>;
                      error_message?: Optional<string>;
                      metadata?: Optional<string>;
                      store_fqdn?: Optional<string>;
                  }, "app_", never>>;
                  [pluginName: string]: JsonMap;
              };
          };
          tunnel_provider: {
              options: {
                  [key: string]: never;
              };
              pluginReturns: {
                  [pluginName: string]: {
                      name: string;
                  };
              };
          };
          tunnel_start: {
              options: {
                  port: number;
                  provider: string;
              };
              pluginReturns: {
                  [key: string]: Result<TunnelClient, TunnelError>;
              };
          };
          [hookName: string]: {
              options: {
                  [key: string]: unknown;
              };
              pluginReturns: {
                  [key: string]: unknown;
              };
          };
      }

      Hierarchy (view full)

      Indexable

      [hookName: string]: {
          options: {
              [key: string]: unknown;
          };
          pluginReturns: {
              [key: string]: unknown;
          };
      }
      • options: {
            [key: string]: unknown;
        }
        • [key: string]: unknown
      • pluginReturns: {
            [key: string]: unknown;
        }
        • [key: string]: unknown

      Properties

      public_command_metadata: {
          options: {
              [key: string]: never;
          };
          pluginReturns: {
              @shopify/app: Partial<AppSpecificMonorailFields>;
              [pluginName: string]: JsonMap;
          };
      }

      Type declaration

      • options: {
            [key: string]: never;
        }
        • [key: string]: never
      • pluginReturns: {
            @shopify/app: Partial<AppSpecificMonorailFields>;
            [pluginName: string]: JsonMap;
        }
        • [pluginName: string]: JsonMap
        • @shopify/app: Partial<AppSpecificMonorailFields>
      sensitive_command_metadata: {
          options: {
              [key: string]: never;
          };
          pluginReturns: {
              @shopify/app: Partial<PickByPrefix<{
                  app_name?: Optional<string>;
                  args: string;
                  cmd_all_environment_flags?: Optional<string>;
                  cmd_dev_tunnel_custom?: Optional<string>;
                  env_plugin_installed_all?: Optional<string>;
                  error_message?: Optional<string>;
                  metadata?: Optional<string>;
                  store_fqdn?: Optional<string>;
              }, "app_", never>>;
              [pluginName: string]: JsonMap;
          };
      }

      Type declaration

      • options: {
            [key: string]: never;
        }
        • [key: string]: never
      • pluginReturns: {
            @shopify/app: Partial<PickByPrefix<{
                app_name?: Optional<string>;
                args: string;
                cmd_all_environment_flags?: Optional<string>;
                cmd_dev_tunnel_custom?: Optional<string>;
                env_plugin_installed_all?: Optional<string>;
                error_message?: Optional<string>;
                metadata?: Optional<string>;
                store_fqdn?: Optional<string>;
            }, "app_", never>>;
            [pluginName: string]: JsonMap;
        }
        • [pluginName: string]: JsonMap
        • @shopify/app: Partial<PickByPrefix<{
              app_name?: Optional<string>;
              args: string;
              cmd_all_environment_flags?: Optional<string>;
              cmd_dev_tunnel_custom?: Optional<string>;
              env_plugin_installed_all?: Optional<string>;
              error_message?: Optional<string>;
              metadata?: Optional<string>;
              store_fqdn?: Optional<string>;
          }, "app_", never>>
      tunnel_provider: {
          options: {
              [key: string]: never;
          };
          pluginReturns: {
              [pluginName: string]: {
                  name: string;
              };
          };
      }

      Type declaration

      • options: {
            [key: string]: never;
        }
        • [key: string]: never
      • pluginReturns: {
            [pluginName: string]: {
                name: string;
            };
        }
        • [pluginName: string]: {
              name: string;
          }
          • name: string
      tunnel_start: {
          options: {
              port: number;
              provider: string;
          };
          pluginReturns: {
              [key: string]: Result<TunnelClient, TunnelError>;
          };
      }

      Type declaration

      \ No newline at end of file +

      Properties

      public_command_metadata: {
          options: {
              [key: string]: never;
          };
          pluginReturns: {
              @shopify/app: Partial<AppSpecificMonorailFields>;
              [pluginName: string]: JsonMap;
          };
      }

      Type declaration

      • options: {
            [key: string]: never;
        }
        • [key: string]: never
      • pluginReturns: {
            @shopify/app: Partial<AppSpecificMonorailFields>;
            [pluginName: string]: JsonMap;
        }
        • [pluginName: string]: JsonMap
        • @shopify/app: Partial<AppSpecificMonorailFields>
      sensitive_command_metadata: {
          options: {
              [key: string]: never;
          };
          pluginReturns: {
              @shopify/app: Partial<PickByPrefix<{
                  app_name?: Optional<string>;
                  args: string;
                  cmd_all_environment_flags?: Optional<string>;
                  cmd_dev_tunnel_custom?: Optional<string>;
                  env_plugin_installed_all?: Optional<string>;
                  error_message?: Optional<string>;
                  metadata?: Optional<string>;
                  store_fqdn?: Optional<string>;
              }, "app_", never>>;
              [pluginName: string]: JsonMap;
          };
      }

      Type declaration

      • options: {
            [key: string]: never;
        }
        • [key: string]: never
      • pluginReturns: {
            @shopify/app: Partial<PickByPrefix<{
                app_name?: Optional<string>;
                args: string;
                cmd_all_environment_flags?: Optional<string>;
                cmd_dev_tunnel_custom?: Optional<string>;
                env_plugin_installed_all?: Optional<string>;
                error_message?: Optional<string>;
                metadata?: Optional<string>;
                store_fqdn?: Optional<string>;
            }, "app_", never>>;
            [pluginName: string]: JsonMap;
        }
        • [pluginName: string]: JsonMap
        • @shopify/app: Partial<PickByPrefix<{
              app_name?: Optional<string>;
              args: string;
              cmd_all_environment_flags?: Optional<string>;
              cmd_dev_tunnel_custom?: Optional<string>;
              env_plugin_installed_all?: Optional<string>;
              error_message?: Optional<string>;
              metadata?: Optional<string>;
              store_fqdn?: Optional<string>;
          }, "app_", never>>
      tunnel_provider: {
          options: {
              [key: string]: never;
          };
          pluginReturns: {
              [pluginName: string]: {
                  name: string;
              };
          };
      }

      Type declaration

      • options: {
            [key: string]: never;
        }
        • [key: string]: never
      • pluginReturns: {
            [pluginName: string]: {
                name: string;
            };
        }
        • [pluginName: string]: {
              name: string;
          }
          • name: string
      tunnel_start: {
          options: {
              port: number;
              provider: string;
          };
          pluginReturns: {
              [key: string]: Result<TunnelClient, TunnelError>;
          };
      }

      Type declaration

      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_plugins.TunnelPluginError.html b/docs/api/cli-kit/interfaces/node_plugins.TunnelPluginError.html index 88b18bfe30d..579182f54ee 100644 --- a/docs/api/cli-kit/interfaces/node_plugins.TunnelPluginError.html +++ b/docs/api/cli-kit/interfaces/node_plugins.TunnelPluginError.html @@ -1,4 +1,4 @@ -TunnelPluginError | @shopify/cli-kit
      interface TunnelPluginError {
          message?: string;
          provider: string;
          type: "unknown" | "multiple-providers" | "handled-error" | "no-provider";
      }

      Properties

      message? +TunnelPluginError | @shopify/cli-kit
      interface TunnelPluginError {
          message?: string;
          provider: string;
          type: "unknown" | "multiple-providers" | "handled-error" | "no-provider";
      }

      Properties

      Properties

      message?: string
      provider: string
      type: "unknown" | "multiple-providers" | "handled-error" | "no-provider"
      \ No newline at end of file +

      Properties

      message?: string
      provider: string
      type: "unknown" | "multiple-providers" | "handled-error" | "no-provider"
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_plugins_tunnel.HookReturnPerTunnelPlugin.html b/docs/api/cli-kit/interfaces/node_plugins_tunnel.HookReturnPerTunnelPlugin.html index c75d077f113..4590e55cd4f 100644 --- a/docs/api/cli-kit/interfaces/node_plugins_tunnel.HookReturnPerTunnelPlugin.html +++ b/docs/api/cli-kit/interfaces/node_plugins_tunnel.HookReturnPerTunnelPlugin.html @@ -1,5 +1,5 @@ HookReturnPerTunnelPlugin | @shopify/cli-kit

      Tunnel Plugins types

      Any plugin that provides tunnel functionality should implement defineProviderand startTunnel

      -
      interface HookReturnPerTunnelPlugin {
          tunnel_provider: {
              options: {
                  [key: string]: never;
              };
              pluginReturns: {
                  [pluginName: string]: {
                      name: string;
                  };
              };
          };
          tunnel_start: {
              options: {
                  port: number;
                  provider: string;
              };
              pluginReturns: {
                  [key: string]: Result<TunnelClient, TunnelError>;
              };
          };
      }

      Hierarchy (view full)

      Properties

      interface HookReturnPerTunnelPlugin {
          tunnel_provider: {
              options: {
                  [key: string]: never;
              };
              pluginReturns: {
                  [pluginName: string]: {
                      name: string;
                  };
              };
          };
          tunnel_start: {
              options: {
                  port: number;
                  provider: string;
              };
              pluginReturns: {
                  [key: string]: Result<TunnelClient, TunnelError>;
              };
          };
      }

      Hierarchy (view full)

      Properties

      tunnel_provider: {
          options: {
              [key: string]: never;
          };
          pluginReturns: {
              [pluginName: string]: {
                  name: string;
              };
          };
      }

      Type declaration

      • options: {
            [key: string]: never;
        }
        • [key: string]: never
      • pluginReturns: {
            [pluginName: string]: {
                name: string;
            };
        }
        • [pluginName: string]: {
              name: string;
          }
          • name: string
      tunnel_start: {
          options: {
              port: number;
              provider: string;
          };
          pluginReturns: {
              [key: string]: Result<TunnelClient, TunnelError>;
          };
      }

      Type declaration

      \ No newline at end of file +

      Properties

      tunnel_provider: {
          options: {
              [key: string]: never;
          };
          pluginReturns: {
              [pluginName: string]: {
                  name: string;
              };
          };
      }

      Type declaration

      • options: {
            [key: string]: never;
        }
        • [key: string]: never
      • pluginReturns: {
            [pluginName: string]: {
                name: string;
            };
        }
        • [pluginName: string]: {
              name: string;
          }
          • name: string
      tunnel_start: {
          options: {
              port: number;
              provider: string;
          };
          pluginReturns: {
              [key: string]: Result<TunnelClient, TunnelError>;
          };
      }

      Type declaration

      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_plugins_tunnel.TunnelClient.html b/docs/api/cli-kit/interfaces/node_plugins_tunnel.TunnelClient.html index 77b8a5e62d7..c81a165e2aa 100644 --- a/docs/api/cli-kit/interfaces/node_plugins_tunnel.TunnelClient.html +++ b/docs/api/cli-kit/interfaces/node_plugins_tunnel.TunnelClient.html @@ -1,5 +1,5 @@ -TunnelClient | @shopify/cli-kit
      interface TunnelClient {
          getTunnelStatus: (() => TunnelStatusType);
          port: number;
          provider: string;
          stopTunnel: (() => void);
      }

      Properties

      getTunnelStatus +TunnelClient | @shopify/cli-kit
      interface TunnelClient {
          getTunnelStatus: (() => TunnelStatusType);
          port: number;
          provider: string;
          stopTunnel: (() => void);
      }

      Properties

      getTunnelStatus: (() => TunnelStatusType)

      Type declaration

      port: number
      provider: string
      stopTunnel: (() => void)

      Type declaration

        • (): void
        • Returns void

      \ No newline at end of file +

      Properties

      getTunnelStatus: (() => TunnelStatusType)

      Type declaration

      port: number
      provider: string
      stopTunnel: (() => void)

      Type declaration

        • (): void
        • Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_session.AdminSession.html b/docs/api/cli-kit/interfaces/node_session.AdminSession.html index 3e1428736f9..83f4b45e24c 100644 --- a/docs/api/cli-kit/interfaces/node_session.AdminSession.html +++ b/docs/api/cli-kit/interfaces/node_session.AdminSession.html @@ -1,4 +1,4 @@ AdminSession | @shopify/cli-kit

      Session Object to access the Admin API, includes the token and the store FQDN.

      -
      interface AdminSession {
          storeFqdn: string;
          token: string;
      }

      Properties

      interface AdminSession {
          storeFqdn: string;
          token: string;
      }

      Properties

      Properties

      storeFqdn: string
      token: string
      \ No newline at end of file +

      Properties

      storeFqdn: string
      token: string
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_system.ExecOptions.html b/docs/api/cli-kit/interfaces/node_system.ExecOptions.html index ecde70fa802..90e440e4810 100644 --- a/docs/api/cli-kit/interfaces/node_system.ExecOptions.html +++ b/docs/api/cli-kit/interfaces/node_system.ExecOptions.html @@ -1,4 +1,4 @@ -ExecOptions | @shopify/cli-kit
      interface ExecOptions {
          cwd?: string;
          env?: {
              [key: string]: string | undefined;
          };
          externalErrorHandler?: ((error) => Promise<void>);
          input?: string;
          signal?: AbortSignal;
          stderr?: "inherit" | Writable;
          stdin?: "inherit" | Readable;
          stdio?: "inherit";
          stdout?: "inherit" | Writable;
      }

      Properties

      cwd? +ExecOptions | @shopify/cli-kit
      interface ExecOptions {
          cwd?: string;
          env?: {
              [key: string]: string | undefined;
          };
          externalErrorHandler?: ((error) => Promise<void>);
          input?: string;
          signal?: AbortSignal;
          stderr?: "inherit" | Writable;
          stdin?: "inherit" | Readable;
          stdio?: "inherit";
          stdout?: "inherit" | Writable;
      }

      Properties

      cwd?: string
      env?: {
          [key: string]: string | undefined;
      }

      Type declaration

      • [key: string]: string | undefined
      externalErrorHandler?: ((error) => Promise<void>)

      Type declaration

        • (error): Promise<void>
        • Parameters

          • error: unknown

          Returns Promise<void>

      input?: string
      signal?: AbortSignal
      stderr?: "inherit" | Writable
      stdin?: "inherit" | Readable
      stdio?: "inherit"
      stdout?: "inherit" | Writable
      \ No newline at end of file +

      Properties

      cwd?: string
      env?: {
          [key: string]: string | undefined;
      }

      Type declaration

      • [key: string]: string | undefined
      externalErrorHandler?: ((error) => Promise<void>)

      Type declaration

        • (error): Promise<void>
        • Parameters

          • error: unknown

          Returns Promise<void>

      input?: string
      signal?: AbortSignal
      stderr?: "inherit" | Writable
      stdin?: "inherit" | Readable
      stdio?: "inherit"
      stdout?: "inherit" | Writable
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_themes_factories.RemoteBulkUploadResponse.html b/docs/api/cli-kit/interfaces/node_themes_factories.RemoteBulkUploadResponse.html index 0cc25d5a88a..a5bed175670 100644 --- a/docs/api/cli-kit/interfaces/node_themes_factories.RemoteBulkUploadResponse.html +++ b/docs/api/cli-kit/interfaces/node_themes_factories.RemoteBulkUploadResponse.html @@ -1,3 +1,3 @@ -RemoteBulkUploadResponse | @shopify/cli-kit
      interface RemoteBulkUploadResponse {
          body: {
              asset?: RemoteAssetResponse;
              errors?: {
                  asset: string[];
              };
          };
          code: number;
      }

      Properties

      body +RemoteBulkUploadResponse | @shopify/cli-kit
      interface RemoteBulkUploadResponse {
          body: {
              asset?: RemoteAssetResponse;
              errors?: {
                  asset: string[];
              };
          };
          code: number;
      }

      Properties

      Properties

      body: {
          asset?: RemoteAssetResponse;
          errors?: {
              asset: string[];
          };
      }

      Type declaration

      • Optional asset?: RemoteAssetResponse
      • Optional errors?: {
            asset: string[];
        }
        • asset: string[]
      code: number
      \ No newline at end of file +

      Properties

      body: {
          asset?: RemoteAssetResponse;
          errors?: {
              asset: string[];
          };
      }

      Type declaration

      • Optional asset?: RemoteAssetResponse
      • Optional errors?: {
            asset: string[];
        }
        • asset: string[]
      code: number
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_themes_types.Checksum.html b/docs/api/cli-kit/interfaces/node_themes_types.Checksum.html index 8d033e29533..6f84d824419 100644 --- a/docs/api/cli-kit/interfaces/node_themes_types.Checksum.html +++ b/docs/api/cli-kit/interfaces/node_themes_types.Checksum.html @@ -1,6 +1,6 @@ Checksum | @shopify/cli-kit

      Represents the remote checksum for a file in a theme.

      -
      interface Checksum {
          checksum: string;
          key: string;
      }

      Hierarchy (view full)

      Properties

      interface Checksum {
          checksum: string;
          key: string;
      }

      Hierarchy (view full)

      Properties

      Properties

      checksum: string

      Represents the checksum value of the theme file.

      -
      key: string

      Identifier of the theme file.

      -
      \ No newline at end of file +
      key: string

      Identifier of the theme file.

      +
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_themes_types.Result.html b/docs/api/cli-kit/interfaces/node_themes_types.Result.html index 642134cc08e..97fce83eab1 100644 --- a/docs/api/cli-kit/interfaces/node_themes_types.Result.html +++ b/docs/api/cli-kit/interfaces/node_themes_types.Result.html @@ -1,14 +1,14 @@ Result | @shopify/cli-kit

      Represents a single result for an upload or delete operation on a single file Each result includes the unique identifier for the file, the type of the operation, the success status of the operation, any errors that occurred, and the asset value of the file.

      -
      interface Result {
          asset?: Omit<ThemeAsset, "stats">;
          errors?: {
              asset?: string[];
          };
          key: string;
          operation: Operation;
          success: boolean;
      }

      Properties

      interface Result {
          asset?: Omit<ThemeAsset, "stats">;
          errors?: {
              asset?: string[];
          };
          key: string;
          operation: Operation;
          success: boolean;
      }

      Properties

      asset?: Omit<ThemeAsset, "stats">

      The asset that was uploaded as part of the upload operation for this file.

      -
      errors?: {
          asset?: string[];
      }

      Error message that was generated during the upload operation for this file.

      -

      Type declaration

      • Optional asset?: string[]
      key: string

      The unique identifier for the file being uploaded.

      -
      operation: Operation

      The operation associated with the result.

      -
      success: boolean

      Indicates whether the upload operation for this file was successful.

      -
      \ No newline at end of file +
      errors?: {
          asset?: string[];
      }

      Error message that was generated during the upload operation for this file.

      +

      Type declaration

      • Optional asset?: string[]
      key: string

      The unique identifier for the file being uploaded.

      +
      operation: Operation

      The operation associated with the result.

      +
      success: boolean

      Indicates whether the upload operation for this file was successful.

      +
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_themes_types.Theme.html b/docs/api/cli-kit/interfaces/node_themes_types.Theme.html index 7af91d82ed5..7265e203dfd 100644 --- a/docs/api/cli-kit/interfaces/node_themes_types.Theme.html +++ b/docs/api/cli-kit/interfaces/node_themes_types.Theme.html @@ -1,14 +1,14 @@ Theme | @shopify/cli-kit

      Represents a theme.

      -
      interface Theme {
          createdAtRuntime: boolean;
          id: number;
          name: string;
          processing: boolean;
          role: string;
          src?: string;
      }

      Properties

      interface Theme {
          createdAtRuntime: boolean;
          id: number;
          name: string;
          processing: boolean;
          role: string;
          src?: string;
      }

      Properties

      createdAtRuntime: boolean

      A boolean determining whether or not the theme was created at runtime.

      -
      id: number

      The remote ID of the theme.

      -
      name: string

      The remote name of the theme.

      -
      processing: boolean

      A boolean determining if the theme is processing at the theme library.

      -
      role: string

      The remote role of the theme.

      -
      src?: string

      A public URL where Shopify can access the theme code.

      -
      \ No newline at end of file +
      id: number

      The remote ID of the theme.

      +
      name: string

      The remote name of the theme.

      +
      processing: boolean

      A boolean determining if the theme is processing at the theme library.

      +
      role: string

      The remote role of the theme.

      +
      src?: string

      A public URL where Shopify can access the theme code.

      +
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_themes_types.ThemeAsset.html b/docs/api/cli-kit/interfaces/node_themes_types.ThemeAsset.html index bbbe788e450..09fe5ae97b0 100644 --- a/docs/api/cli-kit/interfaces/node_themes_types.ThemeAsset.html +++ b/docs/api/cli-kit/interfaces/node_themes_types.ThemeAsset.html @@ -1,12 +1,12 @@ ThemeAsset | @shopify/cli-kit

      Represents a theme or theme extension asset.

      -
      interface ThemeAsset {
          attachment?: string;
          checksum: string;
          key: string;
          stats?: {
              mtime: number;
              size: number;
          };
          value?: string;
      }

      Hierarchy (view full)

      Properties

      interface ThemeAsset {
          attachment?: string;
          checksum: string;
          key: string;
          stats?: {
              mtime: number;
              size: number;
          };
          value?: string;
      }

      Hierarchy (view full)

      Properties

      attachment?: string

      A base64-encoded image.

      -
      checksum: string

      Represents the checksum value of the theme file.

      -
      key: string

      Identifier of the theme file.

      -
      stats?: {
          mtime: number;
          size: number;
      }

      File stats at time of last modification. For attachments, this is the size of the base64 string.

      -

      Type declaration

      • mtime: number
      • size: number
      value?: string

      The text content of the asset, such as the HTML and Liquid markup of a template file.

      -
      \ No newline at end of file +
      checksum: string

      Represents the checksum value of the theme file.

      +
      key: string

      Identifier of the theme file.

      +
      stats?: {
          mtime: number;
          size: number;
      }

      File stats at time of last modification. For attachments, this is the size of the base64 string.

      +

      Type declaration

      • mtime: number
      • size: number
      value?: string

      The text content of the asset, such as the HTML and Liquid markup of a template file.

      +
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_themes_types.ThemeExtensionFileSystem.html b/docs/api/cli-kit/interfaces/node_themes_types.ThemeExtensionFileSystem.html index a41dc4a2d1f..31eb7e36153 100644 --- a/docs/api/cli-kit/interfaces/node_themes_types.ThemeExtensionFileSystem.html +++ b/docs/api/cli-kit/interfaces/node_themes_types.ThemeExtensionFileSystem.html @@ -1,5 +1,5 @@ ThemeExtensionFileSystem | @shopify/cli-kit

      Represents a theme on the file system.

      -
      interface ThemeExtensionFileSystem {
          addEventListener: (<T>(eventName, cb) => void);
          delete: ((fileKey) => Promise<void>);
          files: Map<string, ThemeAsset>;
          read: ((fileKey) => Promise<undefined | string | Buffer>);
          ready: (() => Promise<void>);
          root: string;
          startWatcher: (() => Promise<void>);
          unsyncedFileKeys: Set<string>;
          write: ((asset) => Promise<void>);
      }

      Hierarchy (view full)

      Properties

      interface ThemeExtensionFileSystem {
          addEventListener: (<T>(eventName, cb) => void);
          delete: ((fileKey) => Promise<void>);
          files: Map<string, ThemeAsset>;
          read: ((fileKey) => Promise<undefined | string | Buffer>);
          ready: (() => Promise<void>);
          root: string;
          startWatcher: (() => Promise<void>);
          unsyncedFileKeys: Set<string>;
          write: ((asset) => Promise<void>);
      }

      Hierarchy (view full)

      Properties

      addEventListener: (<T>(eventName, cb) => void)

      Add callbacks to run after certain events are fired.

      -

      Type declaration

      delete: ((fileKey) => Promise<void>)

      Removes a file from the local disk and updates the file system

      +

      Type declaration

      delete: ((fileKey) => Promise<void>)

      Removes a file from the local disk and updates the file system

      Type declaration

        • (fileKey): Promise<void>
        • Parameters

          • fileKey: string

            The key of the file to remove

            -

          Returns Promise<void>

      files: Map<string, ThemeAsset>

      Local files.

      -
      read: ((fileKey) => Promise<undefined | string | Buffer>)

      Reads a file from the local disk and updates the file system +

      Returns Promise<void>

      files: Map<string, ThemeAsset>

      Local files.

      +
      read: ((fileKey) => Promise<undefined | string | Buffer>)

      Reads a file from the local disk and updates the file system Returns a ThemeAsset representing the file that was read Returns undefined if the file does not exist

      Type declaration

        • (fileKey): Promise<undefined | string | Buffer>
        • Parameters

          • fileKey: string

            The key of the file to read

            -

          Returns Promise<undefined | string | Buffer>

      ready: (() => Promise<void>)

      Promise that resolves when all the initial files are found.

      -

      Type declaration

        • (): Promise<void>
        • Returns Promise<void>

      root: string

      The root path of the theme.

      -
      startWatcher: (() => Promise<void>)

      Starts a file watcher for the theme extension directory.

      -

      Type declaration

        • (): Promise<void>
        • Returns Promise<void>

      unsyncedFileKeys: Set<string>

      File keys that have been modified in memory and are not uploaded yet.

      -
      write: ((asset) => Promise<void>)

      Writes a file to the local disk and updates the file system

      +

      Returns Promise<undefined | string | Buffer>

      ready: (() => Promise<void>)

      Promise that resolves when all the initial files are found.

      +

      Type declaration

        • (): Promise<void>
        • Returns Promise<void>

      root: string

      The root path of the theme.

      +
      startWatcher: (() => Promise<void>)

      Starts a file watcher for the theme extension directory.

      +

      Type declaration

        • (): Promise<void>
        • Returns Promise<void>

      unsyncedFileKeys: Set<string>

      File keys that have been modified in memory and are not uploaded yet.

      +
      write: ((asset) => Promise<void>)

      Writes a file to the local disk and updates the file system

      Type declaration

        • (asset): Promise<void>
        • Parameters

          • asset: ThemeAsset

            The ThemeAsset representing the file to write

            -

          Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_themes_types.ThemeFileSystem.html b/docs/api/cli-kit/interfaces/node_themes_types.ThemeFileSystem.html index 9fa3130cb82..86a68ea6917 100644 --- a/docs/api/cli-kit/interfaces/node_themes_types.ThemeFileSystem.html +++ b/docs/api/cli-kit/interfaces/node_themes_types.ThemeFileSystem.html @@ -1,5 +1,5 @@ ThemeFileSystem | @shopify/cli-kit

      Represents a theme on the file system.

      -
      interface ThemeFileSystem {
          addEventListener: (<T>(eventName, cb) => void);
          applyIgnoreFilters: (<T>(files) => T[]);
          delete: ((fileKey) => Promise<void>);
          files: Map<string, ThemeAsset>;
          read: ((fileKey) => Promise<undefined | string | Buffer>);
          ready: (() => Promise<void>);
          root: string;
          startWatcher: ((themeId, adminSession) => Promise<void>);
          unsyncedFileKeys: Set<string>;
          write: ((asset) => Promise<void>);
      }

      Hierarchy (view full)

      Properties

      interface ThemeFileSystem {
          addEventListener: (<T>(eventName, cb) => void);
          applyIgnoreFilters: (<T>(files) => T[]);
          delete: ((fileKey) => Promise<void>);
          files: Map<string, ThemeAsset>;
          read: ((fileKey) => Promise<undefined | string | Buffer>);
          ready: (() => Promise<void>);
          root: string;
          startWatcher: ((themeId, adminSession) => Promise<void>);
          unsyncedFileKeys: Set<string>;
          write: ((asset) => Promise<void>);
      }

      Hierarchy (view full)

      Properties

      addEventListener: (<T>(eventName, cb) => void)

      Add callbacks to run after certain events are fired.

      -

      Type declaration

      applyIgnoreFilters: (<T>(files) => T[])

      Applies filters to ignore files from .shopifyignore file, --ignore and --only flags.

      -

      Type declaration

        • <T>(files): T[]
        • Type Parameters

          • T extends {
                key: string;
            }

          Parameters

          • files: T[]

          Returns T[]

      delete: ((fileKey) => Promise<void>)

      Removes a file from the local disk and updates the file system

      +

      Type declaration

      applyIgnoreFilters: (<T>(files) => T[])

      Applies filters to ignore files from .shopifyignore file, --ignore and --only flags.

      +

      Type declaration

        • <T>(files): T[]
        • Type Parameters

          • T extends {
                key: string;
            }

          Parameters

          • files: T[]

          Returns T[]

      delete: ((fileKey) => Promise<void>)

      Removes a file from the local disk and updates the file system

      Type declaration

        • (fileKey): Promise<void>
        • Parameters

          • fileKey: string

            The key of the file to remove

            -

          Returns Promise<void>

      files: Map<string, ThemeAsset>

      Local files.

      -
      read: ((fileKey) => Promise<undefined | string | Buffer>)

      Reads a file from the local disk and updates the file system +

      Returns Promise<void>

      files: Map<string, ThemeAsset>

      Local files.

      +
      read: ((fileKey) => Promise<undefined | string | Buffer>)

      Reads a file from the local disk and updates the file system Returns a ThemeAsset representing the file that was read Returns undefined if the file does not exist

      Type declaration

        • (fileKey): Promise<undefined | string | Buffer>
        • Parameters

          • fileKey: string

            The key of the file to read

            -

          Returns Promise<undefined | string | Buffer>

      ready: (() => Promise<void>)

      Promise that resolves when all the initial files are found.

      -

      Type declaration

        • (): Promise<void>
        • Returns Promise<void>

      root: string

      The root path of the theme.

      -
      startWatcher: ((themeId, adminSession) => Promise<void>)

      Starts a file watcher for the theme directory.

      +

      Returns Promise<undefined | string | Buffer>

      ready: (() => Promise<void>)

      Promise that resolves when all the initial files are found.

      +

      Type declaration

        • (): Promise<void>
        • Returns Promise<void>

      root: string

      The root path of the theme.

      +
      startWatcher: ((themeId, adminSession) => Promise<void>)

      Starts a file watcher for the theme directory.

      Type declaration

        • (themeId, adminSession): Promise<void>
        • Parameters

          • themeId: string

            The ID of the theme being watched.

          • adminSession: AdminSession

            The admin session for API communication.

          Returns Promise<void>

      Returns

      A Promise that resolves to an FSWatcher instance.

      -
      unsyncedFileKeys: Set<string>

      File keys that have been modified in memory and are not uploaded yet.

      -
      write: ((asset) => Promise<void>)

      Writes a file to the local disk and updates the file system

      +
      unsyncedFileKeys: Set<string>

      File keys that have been modified in memory and are not uploaded yet.

      +
      write: ((asset) => Promise<void>)

      Writes a file to the local disk and updates the file system

      Type declaration

        • (asset): Promise<void>
        • Parameters

          • asset: ThemeAsset

            The ThemeAsset representing the file to write

            -

          Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_themes_types.ThemeFileSystemOptions.html b/docs/api/cli-kit/interfaces/node_themes_types.ThemeFileSystemOptions.html index 3dddcb1f2be..54249935cf2 100644 --- a/docs/api/cli-kit/interfaces/node_themes_types.ThemeFileSystemOptions.html +++ b/docs/api/cli-kit/interfaces/node_themes_types.ThemeFileSystemOptions.html @@ -1,4 +1,4 @@ -ThemeFileSystemOptions | @shopify/cli-kit
      interface ThemeFileSystemOptions {
          filters?: {
              ignore?: string[];
              only?: string[];
          };
          noDelete?: boolean;
          notify?: string;
      }

      Properties

      filters? +ThemeFileSystemOptions | @shopify/cli-kit
      interface ThemeFileSystemOptions {
          filters?: {
              ignore?: string[];
              only?: string[];
          };
          noDelete?: boolean;
          notify?: string;
      }

      Properties

      filters?: {
          ignore?: string[];
          only?: string[];
      }

      Type declaration

      • Optional ignore?: string[]
      • Optional only?: string[]
      noDelete?: boolean
      notify?: string
      \ No newline at end of file +

      Properties

      filters?: {
          ignore?: string[];
          only?: string[];
      }

      Type declaration

      • Optional ignore?: string[]
      • Optional only?: string[]
      noDelete?: boolean
      notify?: string
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_themes_types.VirtualFileSystem.html b/docs/api/cli-kit/interfaces/node_themes_types.VirtualFileSystem.html index 6a5293a9d2b..686bcdab486 100644 --- a/docs/api/cli-kit/interfaces/node_themes_types.VirtualFileSystem.html +++ b/docs/api/cli-kit/interfaces/node_themes_types.VirtualFileSystem.html @@ -1,5 +1,5 @@ VirtualFileSystem | @shopify/cli-kit

      Represents a theme on the file system.

      -
      interface VirtualFileSystem {
          addEventListener: (<T>(eventName, cb) => void);
          delete: ((fileKey) => Promise<void>);
          files: Map<string, ThemeAsset>;
          read: ((fileKey) => Promise<undefined | string | Buffer>);
          ready: (() => Promise<void>);
          root: string;
          unsyncedFileKeys: Set<string>;
          write: ((asset) => Promise<void>);
      }

      Hierarchy (view full)

      Properties

      interface VirtualFileSystem {
          addEventListener: (<T>(eventName, cb) => void);
          delete: ((fileKey) => Promise<void>);
          files: Map<string, ThemeAsset>;
          read: ((fileKey) => Promise<undefined | string | Buffer>);
          ready: (() => Promise<void>);
          root: string;
          unsyncedFileKeys: Set<string>;
          write: ((asset) => Promise<void>);
      }

      Hierarchy (view full)

      Properties

      addEventListener: (<T>(eventName, cb) => void)

      Add callbacks to run after certain events are fired.

      -

      Type declaration

      delete: ((fileKey) => Promise<void>)

      Removes a file from the local disk and updates the file system

      +

      Type declaration

      delete: ((fileKey) => Promise<void>)

      Removes a file from the local disk and updates the file system

      Type declaration

        • (fileKey): Promise<void>
        • Parameters

          • fileKey: string

            The key of the file to remove

            -

          Returns Promise<void>

      files: Map<string, ThemeAsset>

      Local files.

      -
      read: ((fileKey) => Promise<undefined | string | Buffer>)

      Reads a file from the local disk and updates the file system +

      Returns Promise<void>

      files: Map<string, ThemeAsset>

      Local files.

      +
      read: ((fileKey) => Promise<undefined | string | Buffer>)

      Reads a file from the local disk and updates the file system Returns a ThemeAsset representing the file that was read Returns undefined if the file does not exist

      Type declaration

        • (fileKey): Promise<undefined | string | Buffer>
        • Parameters

          • fileKey: string

            The key of the file to read

            -

          Returns Promise<undefined | string | Buffer>

      ready: (() => Promise<void>)

      Promise that resolves when all the initial files are found.

      -

      Type declaration

        • (): Promise<void>
        • Returns Promise<void>

      root: string

      The root path of the theme.

      -
      unsyncedFileKeys: Set<string>

      File keys that have been modified in memory and are not uploaded yet.

      -
      write: ((asset) => Promise<void>)

      Writes a file to the local disk and updates the file system

      +

      Returns Promise<undefined | string | Buffer>

      ready: (() => Promise<void>)

      Promise that resolves when all the initial files are found.

      +

      Type declaration

        • (): Promise<void>
        • Returns Promise<void>

      root: string

      The root path of the theme.

      +
      unsyncedFileKeys: Set<string>

      File keys that have been modified in memory and are not uploaded yet.

      +
      write: ((asset) => Promise<void>)

      Writes a file to the local disk and updates the file system

      Type declaration

        • (asset): Promise<void>
        • Parameters

          • asset: ThemeAsset

            The ThemeAsset representing the file to write

            -

          Returns Promise<void>

      \ No newline at end of file +

      Returns Promise<void>

      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_ui.InfoTableSection.html b/docs/api/cli-kit/interfaces/node_ui.InfoTableSection.html index c191240247b..09854292a7f 100644 --- a/docs/api/cli-kit/interfaces/node_ui.InfoTableSection.html +++ b/docs/api/cli-kit/interfaces/node_ui.InfoTableSection.html @@ -1,7 +1,7 @@ -InfoTableSection | @shopify/cli-kit

      Interface InfoTableSection

      interface InfoTableSection {
          bullet?: string;
          color?: LiteralUnion<(keyof ForegroundColor), string>;
          emptyItemsText?: string;
          header: string;
          helperText?: string;
          items: Items;
      }

      Properties

      bullet? +InfoTableSection | @shopify/cli-kit

      Interface InfoTableSection

      interface InfoTableSection {
          bullet?: string;
          color?: LiteralUnion<(keyof ForegroundColor), string>;
          emptyItemsText?: string;
          header: string;
          helperText?: string;
          items: Items;
      }

      Properties

      bullet?: string
      color?: LiteralUnion<(keyof ForegroundColor), string>
      emptyItemsText?: string
      header: string
      helperText?: string
      items: Items
      \ No newline at end of file +

      Properties

      bullet?: string
      color?: LiteralUnion<(keyof ForegroundColor), string>
      emptyItemsText?: string
      header: string
      helperText?: string
      items: Items
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_ui.LinkToken.html b/docs/api/cli-kit/interfaces/node_ui.LinkToken.html index 6c9d9180c5e..4e5098f1265 100644 --- a/docs/api/cli-kit/interfaces/node_ui.LinkToken.html +++ b/docs/api/cli-kit/interfaces/node_ui.LinkToken.html @@ -1,2 +1,2 @@ -LinkToken | @shopify/cli-kit
      interface LinkToken {
          link: {
              label?: string;
              url: string;
          };
      }

      Properties

      Properties

      link: {
          label?: string;
          url: string;
      }

      Type declaration

      • Optional label?: string
      • url: string
      \ No newline at end of file +LinkToken | @shopify/cli-kit
      interface LinkToken {
          link: {
              label?: string;
              url: string;
          };
      }

      Properties

      Properties

      link: {
          label?: string;
          url: string;
      }

      Type declaration

      • Optional label?: string
      • url: string
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_ui.ListToken.html b/docs/api/cli-kit/interfaces/node_ui.ListToken.html index d878fb28d8c..02ffcda2f9e 100644 --- a/docs/api/cli-kit/interfaces/node_ui.ListToken.html +++ b/docs/api/cli-kit/interfaces/node_ui.ListToken.html @@ -1,2 +1,2 @@ -ListToken | @shopify/cli-kit
      interface ListToken {
          list: {
              items: TokenItem<InlineToken>[];
              ordered?: boolean;
              title?: TokenItem<InlineToken>;
          };
      }

      Properties

      Properties

      list: {
          items: TokenItem<InlineToken>[];
          ordered?: boolean;
          title?: TokenItem<InlineToken>;
      }

      Type declaration

      \ No newline at end of file +ListToken | @shopify/cli-kit
      interface ListToken {
          list: {
              items: TokenItem<InlineToken>[];
              ordered?: boolean;
              title?: TokenItem<InlineToken>;
          };
      }

      Properties

      Properties

      list: {
          items: TokenItem<InlineToken>[];
          ordered?: boolean;
          title?: TokenItem<InlineToken>;
      }

      Type declaration

      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_ui.RenderAutocompleteOptions.html b/docs/api/cli-kit/interfaces/node_ui.RenderAutocompleteOptions.html index 4f127d2a856..c8a0ee776c3 100644 --- a/docs/api/cli-kit/interfaces/node_ui.RenderAutocompleteOptions.html +++ b/docs/api/cli-kit/interfaces/node_ui.RenderAutocompleteOptions.html @@ -1,4 +1,4 @@ -RenderAutocompleteOptions | @shopify/cli-kit

      Interface RenderAutocompleteOptions<T>

      interface RenderAutocompleteOptions<T> {
          abortSignal?: AbortSignal;
          choices: Item<T>[];
          hasMorePages?: boolean;
          infoMessage?: {
              body: TokenItem;
              title: {
                  color?: LiteralUnion<(keyof ForegroundColor), string>;
                  text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
              };
          };
          infoTable?: {
              [header: string]: Items;
          } | InfoTableSection[];
          message: Message;
          renderOptions?: RenderOptions;
          search?: ((term) => Promise<SearchResults<T>>);
      }

      Type Parameters

      • T

      Hierarchy

      • PartialBy<Omit<AutocompletePromptProps<T>, "onSubmit">, "search">
        • RenderAutocompleteOptions

      Properties

      abortSignal? +RenderAutocompleteOptions | @shopify/cli-kit

      Interface RenderAutocompleteOptions<T>

      interface RenderAutocompleteOptions<T> {
          abortSignal?: AbortSignal;
          choices: Item<T>[];
          hasMorePages?: boolean;
          infoMessage?: {
              body: TokenItem;
              title: {
                  color?: LiteralUnion<(keyof ForegroundColor), string>;
                  text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
              };
          };
          infoTable?: {
              [header: string]: Items;
          } | InfoTableSection[];
          message: Message;
          renderOptions?: RenderOptions;
          search?: ((term) => Promise<SearchResults<T>>);
      }

      Type Parameters

      • T

      Hierarchy

      • PartialBy<Omit<AutocompletePromptProps<T>, "onSubmit">, "search">
        • RenderAutocompleteOptions

      Properties

      abortSignal?: AbortSignal
      choices: Item<T>[]
      hasMorePages?: boolean
      infoMessage?: {
          body: TokenItem;
          title: {
              color?: LiteralUnion<(keyof ForegroundColor), string>;
              text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
          };
      }

      Type declaration

      • body: TokenItem
      • title: {
            color?: LiteralUnion<(keyof ForegroundColor), string>;
            text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
        }
        • Optional color?: LiteralUnion<(keyof ForegroundColor), string>
        • text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>
      infoTable?: {
          [header: string]: Items;
      } | InfoTableSection[]

      Type declaration

      • [header: string]: Items
      message: Message
      renderOptions?: RenderOptions
      search?: ((term) => Promise<SearchResults<T>>)

      Type declaration

        • (term): Promise<SearchResults<T>>
        • Parameters

          • term: string

          Returns Promise<SearchResults<T>>

      \ No newline at end of file +

      Properties

      abortSignal?: AbortSignal
      choices: Item<T>[]
      hasMorePages?: boolean
      infoMessage?: {
          body: TokenItem;
          title: {
              color?: LiteralUnion<(keyof ForegroundColor), string>;
              text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
          };
      }

      Type declaration

      • body: TokenItem
      • title: {
            color?: LiteralUnion<(keyof ForegroundColor), string>;
            text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
        }
        • Optional color?: LiteralUnion<(keyof ForegroundColor), string>
        • text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>
      infoTable?: {
          [header: string]: Items;
      } | InfoTableSection[]

      Type declaration

      • [header: string]: Items
      message: Message
      renderOptions?: RenderOptions
      search?: ((term) => Promise<SearchResults<T>>)

      Type declaration

        • (term): Promise<SearchResults<T>>
        • Parameters

          • term: string

          Returns Promise<SearchResults<T>>

      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_ui.RenderConcurrentOptions.html b/docs/api/cli-kit/interfaces/node_ui.RenderConcurrentOptions.html index 20628367042..cb21266b540 100644 --- a/docs/api/cli-kit/interfaces/node_ui.RenderConcurrentOptions.html +++ b/docs/api/cli-kit/interfaces/node_ui.RenderConcurrentOptions.html @@ -1,8 +1,8 @@ -RenderConcurrentOptions | @shopify/cli-kit

      Interface RenderConcurrentOptions

      interface RenderConcurrentOptions {
          abortSignal?: AbortSignal;
          keepRunningAfterProcessesResolve?: boolean;
          prefixColumnSize?: number;
          processes: OutputProcess[];
          renderOptions?: RenderOptions;
          showTimestamps?: boolean;
          useAlternativeColorPalette?: boolean;
      }

      Hierarchy

      • PartialBy<ConcurrentOutputProps, "abortSignal">
        • RenderConcurrentOptions

      Properties

      abortSignal? +RenderConcurrentOptions | @shopify/cli-kit

      Interface RenderConcurrentOptions

      interface RenderConcurrentOptions {
          abortSignal?: AbortSignal;
          keepRunningAfterProcessesResolve?: boolean;
          prefixColumnSize?: number;
          processes: OutputProcess[];
          renderOptions?: RenderOptions;
          showTimestamps?: boolean;
          useAlternativeColorPalette?: boolean;
      }

      Hierarchy

      • PartialBy<ConcurrentOutputProps, "abortSignal">
        • RenderConcurrentOptions

      Properties

      abortSignal?: AbortSignal
      keepRunningAfterProcessesResolve?: boolean
      prefixColumnSize?: number
      processes: OutputProcess[]
      renderOptions?: RenderOptions
      showTimestamps?: boolean
      useAlternativeColorPalette?: boolean
      \ No newline at end of file +

      Properties

      abortSignal?: AbortSignal
      keepRunningAfterProcessesResolve?: boolean
      prefixColumnSize?: number
      processes: OutputProcess[]
      renderOptions?: RenderOptions
      showTimestamps?: boolean
      useAlternativeColorPalette?: boolean
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_ui.RenderConfirmationPromptOptions.html b/docs/api/cli-kit/interfaces/node_ui.RenderConfirmationPromptOptions.html index 42bfc2e9128..3a568038791 100644 --- a/docs/api/cli-kit/interfaces/node_ui.RenderConfirmationPromptOptions.html +++ b/docs/api/cli-kit/interfaces/node_ui.RenderConfirmationPromptOptions.html @@ -1,4 +1,4 @@ -RenderConfirmationPromptOptions | @shopify/cli-kit

      Interface RenderConfirmationPromptOptions

      interface RenderConfirmationPromptOptions {
          abortSignal?: AbortSignal;
          cancellationMessage?: string;
          confirmationMessage?: string;
          defaultValue?: boolean;
          infoMessage?: {
              body: TokenItem;
              title: {
                  color?: LiteralUnion<(keyof ForegroundColor), string>;
                  text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
              };
          };
          infoTable?: {
              [header: string]: Items;
          } | InfoTableSection[];
          message: Message;
          renderOptions?: RenderOptions;
      }

      Hierarchy

      • Pick<SelectPromptProps<boolean>, "message" | "infoTable" | "infoMessage" | "abortSignal">
        • RenderConfirmationPromptOptions

      Properties

      abortSignal? +RenderConfirmationPromptOptions | @shopify/cli-kit

      Interface RenderConfirmationPromptOptions

      interface RenderConfirmationPromptOptions {
          abortSignal?: AbortSignal;
          cancellationMessage?: string;
          confirmationMessage?: string;
          defaultValue?: boolean;
          infoMessage?: {
              body: TokenItem;
              title: {
                  color?: LiteralUnion<(keyof ForegroundColor), string>;
                  text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
              };
          };
          infoTable?: {
              [header: string]: Items;
          } | InfoTableSection[];
          message: Message;
          renderOptions?: RenderOptions;
      }

      Hierarchy

      • Pick<SelectPromptProps<boolean>, "message" | "infoTable" | "infoMessage" | "abortSignal">
        • RenderConfirmationPromptOptions

      Properties

      abortSignal?: AbortSignal
      cancellationMessage?: string
      confirmationMessage?: string
      defaultValue?: boolean
      infoMessage?: {
          body: TokenItem;
          title: {
              color?: LiteralUnion<(keyof ForegroundColor), string>;
              text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
          };
      }

      Type declaration

      • body: TokenItem
      • title: {
            color?: LiteralUnion<(keyof ForegroundColor), string>;
            text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
        }
        • Optional color?: LiteralUnion<(keyof ForegroundColor), string>
        • text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>
      infoTable?: {
          [header: string]: Items;
      } | InfoTableSection[]

      Type declaration

      • [header: string]: Items
      message: Message
      renderOptions?: RenderOptions
      \ No newline at end of file +

      Properties

      abortSignal?: AbortSignal
      cancellationMessage?: string
      confirmationMessage?: string
      defaultValue?: boolean
      infoMessage?: {
          body: TokenItem;
          title: {
              color?: LiteralUnion<(keyof ForegroundColor), string>;
              text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
          };
      }

      Type declaration

      • body: TokenItem
      • title: {
            color?: LiteralUnion<(keyof ForegroundColor), string>;
            text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
        }
        • Optional color?: LiteralUnion<(keyof ForegroundColor), string>
        • text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>
      infoTable?: {
          [header: string]: Items;
      } | InfoTableSection[]

      Type declaration

      • [header: string]: Items
      message: Message
      renderOptions?: RenderOptions
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_ui.RenderDangerousConfirmationPromptOptions.html b/docs/api/cli-kit/interfaces/node_ui.RenderDangerousConfirmationPromptOptions.html index d4ead42319b..b57e331e715 100644 --- a/docs/api/cli-kit/interfaces/node_ui.RenderDangerousConfirmationPromptOptions.html +++ b/docs/api/cli-kit/interfaces/node_ui.RenderDangerousConfirmationPromptOptions.html @@ -1,6 +1,6 @@ -RenderDangerousConfirmationPromptOptions | @shopify/cli-kit

      Interface RenderDangerousConfirmationPromptOptions

      interface RenderDangerousConfirmationPromptOptions {
          abortSignal?: AbortSignal;
          confirmation: string;
          infoTable?: {
              [header: string]: Items;
          } | InfoTableSection[];
          message: string;
          renderOptions?: RenderOptions;
      }

      Hierarchy

      • Omit<DangerousConfirmationPromptProps, "onSubmit">
        • RenderDangerousConfirmationPromptOptions

      Properties

      abortSignal? +RenderDangerousConfirmationPromptOptions | @shopify/cli-kit

      Interface RenderDangerousConfirmationPromptOptions

      interface RenderDangerousConfirmationPromptOptions {
          abortSignal?: AbortSignal;
          confirmation: string;
          infoTable?: {
              [header: string]: Items;
          } | InfoTableSection[];
          message: string;
          renderOptions?: RenderOptions;
      }

      Hierarchy

      • Omit<DangerousConfirmationPromptProps, "onSubmit">
        • RenderDangerousConfirmationPromptOptions

      Properties

      abortSignal?: AbortSignal
      confirmation: string
      infoTable?: {
          [header: string]: Items;
      } | InfoTableSection[]

      Type declaration

      • [header: string]: Items
      message: string
      renderOptions?: RenderOptions
      \ No newline at end of file +

      Properties

      abortSignal?: AbortSignal
      confirmation: string
      infoTable?: {
          [header: string]: Items;
      } | InfoTableSection[]

      Type declaration

      • [header: string]: Items
      message: string
      renderOptions?: RenderOptions
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_ui.RenderSelectPromptOptions.html b/docs/api/cli-kit/interfaces/node_ui.RenderSelectPromptOptions.html index c3e1224f916..926664ad974 100644 --- a/docs/api/cli-kit/interfaces/node_ui.RenderSelectPromptOptions.html +++ b/docs/api/cli-kit/interfaces/node_ui.RenderSelectPromptOptions.html @@ -1,4 +1,4 @@ -RenderSelectPromptOptions | @shopify/cli-kit

      Interface RenderSelectPromptOptions<T>

      interface RenderSelectPromptOptions<T> {
          abortSignal?: AbortSignal;
          choices: Item<T>[];
          defaultValue?: T;
          infoMessage?: {
              body: TokenItem;
              title: {
                  color?: LiteralUnion<(keyof ForegroundColor), string>;
                  text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
              };
          };
          infoTable?: {
              [header: string]: Items;
          } | InfoTableSection[];
          isConfirmationPrompt?: boolean;
          message: Message;
          renderOptions?: RenderOptions;
      }

      Type Parameters

      • T

      Hierarchy

      • Omit<SelectPromptProps<T>, "onSubmit">
        • RenderSelectPromptOptions

      Properties

      abortSignal? +RenderSelectPromptOptions | @shopify/cli-kit

      Interface RenderSelectPromptOptions<T>

      interface RenderSelectPromptOptions<T> {
          abortSignal?: AbortSignal;
          choices: Item<T>[];
          defaultValue?: T;
          infoMessage?: {
              body: TokenItem;
              title: {
                  color?: LiteralUnion<(keyof ForegroundColor), string>;
                  text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
              };
          };
          infoTable?: {
              [header: string]: Items;
          } | InfoTableSection[];
          isConfirmationPrompt?: boolean;
          message: Message;
          renderOptions?: RenderOptions;
      }

      Type Parameters

      • T

      Hierarchy

      • Omit<SelectPromptProps<T>, "onSubmit">
        • RenderSelectPromptOptions

      Properties

      abortSignal?: AbortSignal
      choices: Item<T>[]
      defaultValue?: T
      infoMessage?: {
          body: TokenItem;
          title: {
              color?: LiteralUnion<(keyof ForegroundColor), string>;
              text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
          };
      }

      Type declaration

      • body: TokenItem
      • title: {
            color?: LiteralUnion<(keyof ForegroundColor), string>;
            text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
        }
        • Optional color?: LiteralUnion<(keyof ForegroundColor), string>
        • text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>
      infoTable?: {
          [header: string]: Items;
      } | InfoTableSection[]

      Type declaration

      • [header: string]: Items
      isConfirmationPrompt?: boolean
      message: Message
      renderOptions?: RenderOptions
      \ No newline at end of file +

      Properties

      abortSignal?: AbortSignal
      choices: Item<T>[]
      defaultValue?: T
      infoMessage?: {
          body: TokenItem;
          title: {
              color?: LiteralUnion<(keyof ForegroundColor), string>;
              text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
          };
      }

      Type declaration

      • body: TokenItem
      • title: {
            color?: LiteralUnion<(keyof ForegroundColor), string>;
            text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>;
        }
        • Optional color?: LiteralUnion<(keyof ForegroundColor), string>
        • text: TokenItem<string | CommandToken | CharToken | SubduedToken | FilePathToken | BoldToken | InfoToken | WarnToken | ErrorToken>
      infoTable?: {
          [header: string]: Items;
      } | InfoTableSection[]

      Type declaration

      • [header: string]: Items
      isConfirmationPrompt?: boolean
      message: Message
      renderOptions?: RenderOptions
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_ui.RenderTextPromptOptions.html b/docs/api/cli-kit/interfaces/node_ui.RenderTextPromptOptions.html index 7978fe9f9a4..c819e2f9c90 100644 --- a/docs/api/cli-kit/interfaces/node_ui.RenderTextPromptOptions.html +++ b/docs/api/cli-kit/interfaces/node_ui.RenderTextPromptOptions.html @@ -1,4 +1,4 @@ -RenderTextPromptOptions | @shopify/cli-kit

      Interface RenderTextPromptOptions

      interface RenderTextPromptOptions {
          abortSignal?: AbortSignal;
          allowEmpty?: boolean;
          defaultValue?: string;
          emptyDisplayedValue?: string;
          initialAnswer?: string;
          message: TokenItem;
          password?: boolean;
          preview?: ((value) => TokenItem<InlineToken>);
          renderOptions?: RenderOptions;
          validate?: ((value) => undefined | string);
      }

      Hierarchy

      • Omit<TextPromptProps, "onSubmit">
        • RenderTextPromptOptions

      Properties

      abortSignal? +RenderTextPromptOptions | @shopify/cli-kit

      Interface RenderTextPromptOptions

      interface RenderTextPromptOptions {
          abortSignal?: AbortSignal;
          allowEmpty?: boolean;
          defaultValue?: string;
          emptyDisplayedValue?: string;
          initialAnswer?: string;
          message: TokenItem;
          password?: boolean;
          preview?: ((value) => TokenItem<InlineToken>);
          renderOptions?: RenderOptions;
          validate?: ((value) => undefined | string);
      }

      Hierarchy

      • Omit<TextPromptProps, "onSubmit">
        • RenderTextPromptOptions

      Properties

      abortSignal?: AbortSignal
      allowEmpty?: boolean
      defaultValue?: string
      emptyDisplayedValue?: string
      initialAnswer?: string
      message: TokenItem
      password?: boolean
      preview?: ((value) => TokenItem<InlineToken>)

      Type declaration

      renderOptions?: RenderOptions
      validate?: ((value) => undefined | string)

      Type declaration

        • (value): undefined | string
        • Parameters

          • value: string

          Returns undefined | string

      \ No newline at end of file +

      Properties

      abortSignal?: AbortSignal
      allowEmpty?: boolean
      defaultValue?: string
      emptyDisplayedValue?: string
      initialAnswer?: string
      message: TokenItem
      password?: boolean
      preview?: ((value) => TokenItem<InlineToken>)

      Type declaration

      renderOptions?: RenderOptions
      validate?: ((value) => undefined | string)

      Type declaration

        • (value): undefined | string
        • Parameters

          • value: string

          Returns undefined | string

      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_ui.Task.html b/docs/api/cli-kit/interfaces/node_ui.Task.html index bac43dd253b..b864ffa05ec 100644 --- a/docs/api/cli-kit/interfaces/node_ui.Task.html +++ b/docs/api/cli-kit/interfaces/node_ui.Task.html @@ -1,7 +1,7 @@ -Task | @shopify/cli-kit

      Interface Task<TContext>

      interface Task<TContext> {
          errors?: Error[];
          retry?: number;
          retryCount?: number;
          skip?: ((ctx) => boolean);
          task: ((ctx, task) => Promise<void | Task<TContext>[]>);
          title: string;
      }

      Type Parameters

      • TContext = unknown

      Properties

      errors? +Task | @shopify/cli-kit

      Interface Task<TContext>

      interface Task<TContext> {
          errors?: Error[];
          retry?: number;
          retryCount?: number;
          skip?: ((ctx) => boolean);
          task: ((ctx, task) => Promise<void | Task<TContext>[]>);
          title: string;
      }

      Type Parameters

      • TContext = unknown

      Properties

      errors?: Error[]
      retry?: number
      retryCount?: number
      skip?: ((ctx) => boolean)

      Type declaration

        • (ctx): boolean
        • Parameters

          Returns boolean

      task: ((ctx, task) => Promise<void | Task<TContext>[]>)

      Type declaration

      title: string
      \ No newline at end of file +

      Properties

      errors?: Error[]
      retry?: number
      retryCount?: number
      skip?: ((ctx) => boolean)

      Type declaration

        • (ctx): boolean
        • Parameters

          Returns boolean

      task: ((ctx, task) => Promise<void | Task<TContext>[]>)

      Type declaration

      title: string
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_ui_components.ConcurrentOutputContext.html b/docs/api/cli-kit/interfaces/node_ui_components.ConcurrentOutputContext.html index 6011a4cc0ab..4abfd0175ae 100644 --- a/docs/api/cli-kit/interfaces/node_ui_components.ConcurrentOutputContext.html +++ b/docs/api/cli-kit/interfaces/node_ui_components.ConcurrentOutputContext.html @@ -1,3 +1,3 @@ -ConcurrentOutputContext | @shopify/cli-kit
      interface ConcurrentOutputContext {
          outputPrefix?: string;
          stripAnsi?: boolean;
      }

      Properties

      outputPrefix? +ConcurrentOutputContext | @shopify/cli-kit
      interface ConcurrentOutputContext {
          outputPrefix?: string;
          stripAnsi?: boolean;
      }

      Properties

      outputPrefix?: string
      stripAnsi?: boolean
      \ No newline at end of file +

      Properties

      outputPrefix?: string
      stripAnsi?: boolean
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_vendor_otel_js_export_InstantaneousMetricReader.InstantaneousMetricReaderOptions.html b/docs/api/cli-kit/interfaces/node_vendor_otel_js_export_InstantaneousMetricReader.InstantaneousMetricReaderOptions.html index d7d9f42f16f..f4e8abeae9e 100644 --- a/docs/api/cli-kit/interfaces/node_vendor_otel_js_export_InstantaneousMetricReader.InstantaneousMetricReaderOptions.html +++ b/docs/api/cli-kit/interfaces/node_vendor_otel_js_export_InstantaneousMetricReader.InstantaneousMetricReaderOptions.html @@ -1,5 +1,5 @@ -InstantaneousMetricReaderOptions | @shopify/cli-kit
      interface InstantaneousMetricReaderOptions {
          exporter: PushMetricExporter;
          throttleLimit: number;
      }

      Properties

      exporter +InstantaneousMetricReaderOptions | @shopify/cli-kit
      interface InstantaneousMetricReaderOptions {
          exporter: PushMetricExporter;
          throttleLimit: number;
      }

      Properties

      exporter: PushMetricExporter

      The backing exporter for the metric reader.

      -
      throttleLimit: number

      How much the export should be throttled in milliseconds.

      -
      \ No newline at end of file +
      throttleLimit: number

      How much the export should be throttled in milliseconds.

      +
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_BaseOtelService_BaseOtelService.BaseOtelServiceOptions.html b/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_BaseOtelService_BaseOtelService.BaseOtelServiceOptions.html index 3c8fdd55bd6..f40ddd401c1 100644 --- a/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_BaseOtelService_BaseOtelService.BaseOtelServiceOptions.html +++ b/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_BaseOtelService_BaseOtelService.BaseOtelServiceOptions.html @@ -1,12 +1,12 @@ -BaseOtelServiceOptions | @shopify/cli-kit
      interface BaseOtelServiceOptions {
          meterProvider?: MeterProvider;
          metrics?: MetricsConfig;
          onRecord?: OnRecordCallback;
          prefixMetric?: boolean;
          serviceName: string;
      }

      Hierarchy (view full)

      Properties

      meterProvider? +BaseOtelServiceOptions | @shopify/cli-kit
      interface BaseOtelServiceOptions {
          meterProvider?: MeterProvider;
          metrics?: MetricsConfig;
          onRecord?: OnRecordCallback;
          prefixMetric?: boolean;
          serviceName: string;
      }

      Hierarchy (view full)

      Properties

      meterProvider?: MeterProvider

      Override the default meter provider.

      -
      metrics?: MetricsConfig

      Metrics to register on startup.

      -
      onRecord?: OnRecordCallback

      Called when a metric is recorded. addOnRecord can also be used to add +

      metrics?: MetricsConfig

      Metrics to register on startup.

      +
      onRecord?: OnRecordCallback

      Called when a metric is recorded. addOnRecord can also be used to add listeners anytime.

      -
      prefixMetric?: boolean

      If this is set to true then the service name is prefixed to every metric.

      -
      serviceName: string

      Service name is a unique name for an application/service.

      -
      \ No newline at end of file +
      prefixMetric?: boolean

      If this is set to true then the service name is prefixed to every metric.

      +
      serviceName: string

      Service name is a unique name for an application/service.

      +
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_DefaultOtelService_DefaultOtelService.DefaultOtelServiceOptions.html b/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_DefaultOtelService_DefaultOtelService.DefaultOtelServiceOptions.html index f4050b71018..242eb54f775 100644 --- a/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_DefaultOtelService_DefaultOtelService.DefaultOtelServiceOptions.html +++ b/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_DefaultOtelService_DefaultOtelService.DefaultOtelServiceOptions.html @@ -1,4 +1,4 @@ -DefaultOtelServiceOptions | @shopify/cli-kit
      interface DefaultOtelServiceOptions {
          env?: string;
          meterProvider?: MeterProvider;
          metrics?: MetricsConfig;
          onRecord?: OnRecordCallback;
          otelEndpoint: string;
          prefixMetric?: boolean;
          serviceName: string;
          throttleLimit?: number;
          useXhr?: boolean;
      }

      Hierarchy (view full)

      Properties

      env? +DefaultOtelServiceOptions | @shopify/cli-kit
      interface DefaultOtelServiceOptions {
          env?: string;
          meterProvider?: MeterProvider;
          metrics?: MetricsConfig;
          onRecord?: OnRecordCallback;
          otelEndpoint: string;
          prefixMetric?: boolean;
          serviceName: string;
          throttleLimit?: number;
          useXhr?: boolean;
      }

      Hierarchy (view full)

      Properties

      env?: string

      What environment is being deployed (production, staging)

      -
      meterProvider?: MeterProvider

      Override the default meter provider.

      -
      metrics?: MetricsConfig

      Metrics to register on startup.

      -
      onRecord?: OnRecordCallback

      Called when a metric is recorded. addOnRecord can also be used to add +

      meterProvider?: MeterProvider

      Override the default meter provider.

      +
      metrics?: MetricsConfig

      Metrics to register on startup.

      +
      onRecord?: OnRecordCallback

      Called when a metric is recorded. addOnRecord can also be used to add listeners anytime.

      -
      otelEndpoint: string
      prefixMetric?: boolean

      If this is set to true then the service name is prefixed to every metric.

      -
      serviceName: string

      Service name is a unique name for an application/service.

      -
      throttleLimit?: number

      How much the export should be throttled in milliseconds.

      -
      useXhr?: boolean

      Determines whether to send metrics via XHR or beacon. Defaults to false.

      -
      \ No newline at end of file +
      otelEndpoint: string
      prefixMetric?: boolean

      If this is set to true then the service name is prefixed to every metric.

      +
      serviceName: string

      Service name is a unique name for an application/service.

      +
      throttleLimit?: number

      How much the export should be throttled in milliseconds.

      +
      useXhr?: boolean

      Determines whether to send metrics via XHR or beacon. Defaults to false.

      +
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_types.MetricsConfig.html b/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_types.MetricsConfig.html index 4d3d53fd017..fc9b36b16a1 100644 --- a/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_types.MetricsConfig.html +++ b/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_types.MetricsConfig.html @@ -1 +1 @@ -MetricsConfig | @shopify/cli-kit
      interface MetricsConfig {
          [key: string]: MetricDescriptor;
      }

      Indexable

      [key: string]: MetricDescriptor
      \ No newline at end of file +MetricsConfig | @shopify/cli-kit
      interface MetricsConfig {
          [key: string]: MetricDescriptor;
      }

      Indexable

      [key: string]: MetricDescriptor
      \ No newline at end of file diff --git a/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_types.OtelService.html b/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_types.OtelService.html index 2a5267726b6..d23f5690708 100644 --- a/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_types.OtelService.html +++ b/docs/api/cli-kit/interfaces/node_vendor_otel_js_service_types.OtelService.html @@ -1,4 +1,4 @@ -OtelService | @shopify/cli-kit
      interface OtelService {
          serviceName: string;
          addOnRecord(onRecord): (() => void);
          addView(viewOptions): void;
          getMeterProvider(): MeterProvider;
          record<TAttributes>(...args): void;
          register(metrics): void;
          registerMetric(metricName, options): void;
          removeOnRecord(onRecord): void;
          shutdown(): Promise<void>;
      }

      Implemented by

      Properties

      serviceName +OtelService | @shopify/cli-kit
      interface OtelService {
          serviceName: string;
          addOnRecord(onRecord): (() => void);
          addView(viewOptions): void;
          getMeterProvider(): MeterProvider;
          record<TAttributes>(...args): void;
          register(metrics): void;
          registerMetric(metricName, options): void;
          removeOnRecord(onRecord): void;
          shutdown(): Promise<void>;
      }

      Implemented by

      Properties

      serviceName: string

      Methods

      • onRecord callback is called when a metric is recorded. +

      Properties

      serviceName: string

      Methods

      \ No newline at end of file +

      Parameters

      Returns (() => void)

        • (): void
        • Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/common_array.html b/docs/api/cli-kit/modules/common_array.html index 3e4b2f62c83..7521b9869e9 100644 --- a/docs/api/cli-kit/modules/common_array.html +++ b/docs/api/cli-kit/modules/common_array.html @@ -1,4 +1,4 @@ -common/array | @shopify/cli-kit

      Module common/array

      Index

      Functions

      difference +common/array | @shopify/cli-kit

      Module common/array

      Index

      Functions

      difference getArrayContainsDuplicates getArrayRejectingUndefined takeRandomFromArray diff --git a/docs/api/cli-kit/modules/common_collection.html b/docs/api/cli-kit/modules/common_collection.html index 348f185a42b..09246c98050 100644 --- a/docs/api/cli-kit/modules/common_collection.html +++ b/docs/api/cli-kit/modules/common_collection.html @@ -1,3 +1,3 @@ -common/collection | @shopify/cli-kit

      Module common/collection

      Index

      Functions

      groupBy +common/collection | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/common_function.html b/docs/api/cli-kit/modules/common_function.html index ab11d82e9ee..3e99454afd8 100644 --- a/docs/api/cli-kit/modules/common_function.html +++ b/docs/api/cli-kit/modules/common_function.html @@ -1,3 +1,3 @@ -common/function | @shopify/cli-kit

      Module common/function

      Index

      Functions

      debounce +common/function | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/common_lang.html b/docs/api/cli-kit/modules/common_lang.html index 5b61401bef2..ac46bef9e75 100644 --- a/docs/api/cli-kit/modules/common_lang.html +++ b/docs/api/cli-kit/modules/common_lang.html @@ -1,2 +1,2 @@ -common/lang | @shopify/cli-kit

      Module common/lang

      Index

      Functions

      isEqual +common/lang | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/common_object.html b/docs/api/cli-kit/modules/common_object.html index 038da9b4e7b..2bad905c53a 100644 --- a/docs/api/cli-kit/modules/common_object.html +++ b/docs/api/cli-kit/modules/common_object.html @@ -1,4 +1,4 @@ -common/object | @shopify/cli-kit

      Module common/object

      Index

      Functions

      compact +common/object | @shopify/cli-kit

      Module common/object

      Index

      Functions

      compact deepCompare deepDifference deepMergeObjects diff --git a/docs/api/cli-kit/modules/common_retry.html b/docs/api/cli-kit/modules/common_retry.html index a4c808029cc..ca117f40b81 100644 --- a/docs/api/cli-kit/modules/common_retry.html +++ b/docs/api/cli-kit/modules/common_retry.html @@ -1,2 +1,2 @@ -common/retry | @shopify/cli-kit

      Module common/retry

      Index

      Functions

      performActionWithRetryAfterRecovery +common/retry | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/common_string.html b/docs/api/cli-kit/modules/common_string.html index c34db7df961..064faa8938d 100644 --- a/docs/api/cli-kit/modules/common_string.html +++ b/docs/api/cli-kit/modules/common_string.html @@ -1,4 +1,4 @@ -common/string | @shopify/cli-kit

      Module common/string

      Index

      Type Aliases

      RandomNameFamily +common/string | @shopify/cli-kit

      Module common/string

      Index

      Type Aliases

      Functions

      camelize capitalize constantize diff --git a/docs/api/cli-kit/modules/common_ts_deep_required.html b/docs/api/cli-kit/modules/common_ts_deep_required.html index ef080d1dab7..b6e3853fbab 100644 --- a/docs/api/cli-kit/modules/common_ts_deep_required.html +++ b/docs/api/cli-kit/modules/common_ts_deep_required.html @@ -1,2 +1,2 @@ -common/ts/deep-required | @shopify/cli-kit

      Module common/ts/deep-required

      Index

      Type Aliases

      DeepRequired +common/ts/deep-required | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/common_ts_json_narrowing.html b/docs/api/cli-kit/modules/common_ts_json_narrowing.html index 5360d26b8eb..1b2cd740e3b 100644 --- a/docs/api/cli-kit/modules/common_ts_json_narrowing.html +++ b/docs/api/cli-kit/modules/common_ts_json_narrowing.html @@ -1,2 +1,2 @@ -common/ts/json-narrowing | @shopify/cli-kit

      Module common/ts/json-narrowing

      Index

      Functions

      assertStringMap +common/ts/json-narrowing | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/common_ts_pick_by_prefix.html b/docs/api/cli-kit/modules/common_ts_pick_by_prefix.html index 7d2175d6cca..0cdf5dcafca 100644 --- a/docs/api/cli-kit/modules/common_ts_pick_by_prefix.html +++ b/docs/api/cli-kit/modules/common_ts_pick_by_prefix.html @@ -1,2 +1,2 @@ -common/ts/pick-by-prefix | @shopify/cli-kit

      Module common/ts/pick-by-prefix

      Index

      Type Aliases

      PickByPrefix +common/ts/pick-by-prefix | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/common_url.html b/docs/api/cli-kit/modules/common_url.html index e4788ec4347..e884f2608a2 100644 --- a/docs/api/cli-kit/modules/common_url.html +++ b/docs/api/cli-kit/modules/common_url.html @@ -1,3 +1,3 @@ -common/url | @shopify/cli-kit

      Index

      Functions

      isValidURL +common/url | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/common_version.html b/docs/api/cli-kit/modules/common_version.html index 1b08de3f799..4c8cbc356af 100644 --- a/docs/api/cli-kit/modules/common_version.html +++ b/docs/api/cli-kit/modules/common_version.html @@ -1,2 +1,2 @@ -common/version | @shopify/cli-kit

      Module common/version

      Index

      Variables

      CLI_KIT_VERSION +common/version | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_abort.html b/docs/api/cli-kit/modules/node_abort.html index d686af9f8ec..a62a47bada8 100644 --- a/docs/api/cli-kit/modules/node_abort.html +++ b/docs/api/cli-kit/modules/node_abort.html @@ -1,3 +1,3 @@ -node/abort | @shopify/cli-kit

      Index

      Classes

      AbortController +node/abort | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_analytics.html b/docs/api/cli-kit/modules/node_analytics.html index 30551fdde3e..23a783ac418 100644 --- a/docs/api/cli-kit/modules/node_analytics.html +++ b/docs/api/cli-kit/modules/node_analytics.html @@ -1,3 +1,3 @@ -node/analytics | @shopify/cli-kit

      Module node/analytics

      Index

      Type Aliases

      CommandExitMode +node/analytics | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_api_admin.html b/docs/api/cli-kit/modules/node_api_admin.html index 9ffd29464e6..a70fea4c1d3 100644 --- a/docs/api/cli-kit/modules/node_api_admin.html +++ b/docs/api/cli-kit/modules/node_api_admin.html @@ -1,4 +1,4 @@ -node/api/admin | @shopify/cli-kit

      Module node/api/admin

      Index

      Interfaces

      RestResponse +node/api/admin | @shopify/cli-kit

      Module node/api/admin

      Index

      Interfaces

      Functions

      adminRequest adminRequestDoc adminUrl diff --git a/docs/api/cli-kit/modules/node_api_app_dev.html b/docs/api/cli-kit/modules/node_api_app_dev.html index bdf1c6c7814..291aba0caf2 100644 --- a/docs/api/cli-kit/modules/node_api_app_dev.html +++ b/docs/api/cli-kit/modules/node_api_app_dev.html @@ -1,2 +1,2 @@ -node/api/app-dev | @shopify/cli-kit

      Module node/api/app-dev

      Index

      Functions

      appDevRequest +node/api/app-dev | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_api_app_management.html b/docs/api/cli-kit/modules/node_api_app_management.html index d58a12c5b3e..f44b8acaa58 100644 --- a/docs/api/cli-kit/modules/node_api_app_management.html +++ b/docs/api/cli-kit/modules/node_api_app_management.html @@ -1,3 +1,3 @@ -node/api/app-management | @shopify/cli-kit

      Module node/api/app-management

      Index

      Functions

      appManagementRequestDoc +node/api/app-management | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_api_business_platform.html b/docs/api/cli-kit/modules/node_api_business_platform.html index 0a27ed2fa14..57496c20403 100644 --- a/docs/api/cli-kit/modules/node_api_business_platform.html +++ b/docs/api/cli-kit/modules/node_api_business_platform.html @@ -1,4 +1,4 @@ -node/api/business-platform | @shopify/cli-kit

      Module node/api/business-platform

      Index

      Functions

      businessPlatformOrganizationsRequest +node/api/business-platform | @shopify/cli-kit

      Module node/api/business-platform

      Index

      Functions

      businessPlatformOrganizationsRequest businessPlatformOrganizationsRequestDoc businessPlatformRequest businessPlatformRequestDoc diff --git a/docs/api/cli-kit/modules/node_api_functions.html b/docs/api/cli-kit/modules/node_api_functions.html new file mode 100644 index 00000000000..24ab22beee3 --- /dev/null +++ b/docs/api/cli-kit/modules/node_api_functions.html @@ -0,0 +1,2 @@ +node/api/functions | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_api_graphql.html b/docs/api/cli-kit/modules/node_api_graphql.html index 9b02949623f..cd1ccfed28e 100644 --- a/docs/api/cli-kit/modules/node_api_graphql.html +++ b/docs/api/cli-kit/modules/node_api_graphql.html @@ -1,4 +1,4 @@ -node/api/graphql | @shopify/cli-kit

      Module node/api/graphql

      Index

      Interfaces

      GraphQLResponseOptions +node/api/graphql | @shopify/cli-kit

      Module node/api/graphql

      Index

      Interfaces

      Type Aliases

      Exact GraphQLRequestDocOptions diff --git a/docs/api/cli-kit/modules/node_api_http.html b/docs/api/cli-kit/modules/node_api_http.html index a0c77ffd56e..56bcdaab8a2 100644 --- a/docs/api/cli-kit/modules/node_api_http.html +++ b/docs/api/cli-kit/modules/node_api_http.html @@ -1 +1 @@ -node/api/http | @shopify/cli-kit
      \ No newline at end of file +node/api/http | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_api_partners.html b/docs/api/cli-kit/modules/node_api_partners.html index c708137a792..c418309f7db 100644 --- a/docs/api/cli-kit/modules/node_api_partners.html +++ b/docs/api/cli-kit/modules/node_api_partners.html @@ -1,4 +1,4 @@ -node/api/partners | @shopify/cli-kit

      Module node/api/partners

      Index

      Functions

      handleDeprecations +node/api/partners | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_api_rest_api_throttler.html b/docs/api/cli-kit/modules/node_api_rest_api_throttler.html index acfbe5ccb7d..966ccb37f2e 100644 --- a/docs/api/cli-kit/modules/node_api_rest_api_throttler.html +++ b/docs/api/cli-kit/modules/node_api_rest_api_throttler.html @@ -1,4 +1,4 @@ -node/api/rest-api-throttler | @shopify/cli-kit

      Module node/api/rest-api-throttler

      Index

      Functions

      delayAwareRetry +node/api/rest-api-throttler | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_api_webhooks.html b/docs/api/cli-kit/modules/node_api_webhooks.html new file mode 100644 index 00000000000..caa9854edf6 --- /dev/null +++ b/docs/api/cli-kit/modules/node_api_webhooks.html @@ -0,0 +1,2 @@ +node/api/webhooks | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_archiver.html b/docs/api/cli-kit/modules/node_archiver.html index c9281cf1f1c..b025d328889 100644 --- a/docs/api/cli-kit/modules/node_archiver.html +++ b/docs/api/cli-kit/modules/node_archiver.html @@ -1,2 +1,2 @@ -node/archiver | @shopify/cli-kit

      Module node/archiver

      Index

      Functions

      zip +node/archiver | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_base_command.html b/docs/api/cli-kit/modules/node_base_command.html index 473d90d7b2e..44f828cace6 100644 --- a/docs/api/cli-kit/modules/node_base_command.html +++ b/docs/api/cli-kit/modules/node_base_command.html @@ -1,3 +1,3 @@ -node/base-command | @shopify/cli-kit

      Module node/base-command

      Index

      Classes

      default +node/base-command | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_cli.html b/docs/api/cli-kit/modules/node_cli.html index 37c2398f348..6f301558351 100644 --- a/docs/api/cli-kit/modules/node_cli.html +++ b/docs/api/cli-kit/modules/node_cli.html @@ -1,7 +1,6 @@ -node/cli | @shopify/cli-kit

      Index

      Variables

      globalFlags +node/cli | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_cli_launcher.html b/docs/api/cli-kit/modules/node_cli_launcher.html new file mode 100644 index 00000000000..5219cac101c --- /dev/null +++ b/docs/api/cli-kit/modules/node_cli_launcher.html @@ -0,0 +1,2 @@ +node/cli-launcher | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_colors.html b/docs/api/cli-kit/modules/node_colors.html index 17225d3ba5b..852e4249c0e 100644 --- a/docs/api/cli-kit/modules/node_colors.html +++ b/docs/api/cli-kit/modules/node_colors.html @@ -1 +1 @@ -node/colors | @shopify/cli-kit
      \ No newline at end of file +node/colors | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_context_fqdn.html b/docs/api/cli-kit/modules/node_context_fqdn.html index 87b68c218de..8770e68b391 100644 --- a/docs/api/cli-kit/modules/node_context_fqdn.html +++ b/docs/api/cli-kit/modules/node_context_fqdn.html @@ -1,4 +1,4 @@ -node/context/fqdn | @shopify/cli-kit

      Module node/context/fqdn

      Index

      Variables

      CouldntObtainIdentitySpinFQDNError +node/context/fqdn | @shopify/cli-kit

      Module node/context/fqdn

      Index

      Variables

      CouldntObtainIdentitySpinFQDNError CouldntObtainPartnersSpinFQDNError CouldntObtainShopifySpinFQDNError NotProvidedStoreFQDNError diff --git a/docs/api/cli-kit/modules/node_context_local.html b/docs/api/cli-kit/modules/node_context_local.html index ef20425ccf9..289ed50b779 100644 --- a/docs/api/cli-kit/modules/node_context_local.html +++ b/docs/api/cli-kit/modules/node_context_local.html @@ -1,4 +1,4 @@ -node/context/local | @shopify/cli-kit

      Module node/context/local

      Index

      Type Aliases

      CIMetadata +node/context/local | @shopify/cli-kit

      Module node/context/local

      Index

      Type Aliases

      Functions

      alwaysLogAnalytics alwaysLogMetrics analyticsDisabled @@ -10,6 +10,7 @@ gitpodURL hasGit homeDirectory +isAppManagementEnabled isCloudEnvironment isDevelopment isShopify diff --git a/docs/api/cli-kit/modules/node_context_spin.html b/docs/api/cli-kit/modules/node_context_spin.html index a7aa95c8035..22485aa5c16 100644 --- a/docs/api/cli-kit/modules/node_context_spin.html +++ b/docs/api/cli-kit/modules/node_context_spin.html @@ -1,4 +1,4 @@ -node/context/spin | @shopify/cli-kit

      Module node/context/spin

      Index

      Variables

      spinVariables +node/context/spin | @shopify/cli-kit

      Module node/context/spin

      Index

      Variables

      Functions

      appHost appPort fetchSpinPort diff --git a/docs/api/cli-kit/modules/node_context_utilities.html b/docs/api/cli-kit/modules/node_context_utilities.html index fc8d6e09239..99c1ed3b9c9 100644 --- a/docs/api/cli-kit/modules/node_context_utilities.html +++ b/docs/api/cli-kit/modules/node_context_utilities.html @@ -1,2 +1,2 @@ -node/context/utilities | @shopify/cli-kit

      Module node/context/utilities

      Index

      Functions

      isTruthy +node/context/utilities | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_crypto.html b/docs/api/cli-kit/modules/node_crypto.html index e41db048611..b759646ad3c 100644 --- a/docs/api/cli-kit/modules/node_crypto.html +++ b/docs/api/cli-kit/modules/node_crypto.html @@ -1,4 +1,4 @@ -node/crypto | @shopify/cli-kit

      Module node/crypto

      Index

      Functions

      base64URLEncode +node/crypto | @shopify/cli-kit

      Module node/crypto

      Index

      Functions

      base64URLEncode fileHash hashString nonRandomUUID diff --git a/docs/api/cli-kit/modules/node_custom_oclif_loader.html b/docs/api/cli-kit/modules/node_custom_oclif_loader.html index e7c8db1dbf3..b82143b9a6f 100644 --- a/docs/api/cli-kit/modules/node_custom_oclif_loader.html +++ b/docs/api/cli-kit/modules/node_custom_oclif_loader.html @@ -1,2 +1,2 @@ -node/custom-oclif-loader | @shopify/cli-kit

      Module node/custom-oclif-loader

      Index

      Classes

      ShopifyConfig +node/custom-oclif-loader | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_dot_env.html b/docs/api/cli-kit/modules/node_dot_env.html index 3a849cba3de..a0cfea97fa4 100644 --- a/docs/api/cli-kit/modules/node_dot_env.html +++ b/docs/api/cli-kit/modules/node_dot_env.html @@ -1,4 +1,4 @@ -node/dot-env | @shopify/cli-kit

      Module node/dot-env

      Index

      Interfaces

      DotEnvFile +node/dot-env | @shopify/cli-kit

      Module node/dot-env

      Index

      Interfaces

      Functions

      createDotEnvFileLine patchEnvFile readAndParseDotEnv diff --git a/docs/api/cli-kit/modules/node_environment.html b/docs/api/cli-kit/modules/node_environment.html index 081fe92c312..470a5b59d88 100644 --- a/docs/api/cli-kit/modules/node_environment.html +++ b/docs/api/cli-kit/modules/node_environment.html @@ -1,7 +1,8 @@ -node/environment | @shopify/cli-kit

      Module node/environment

      Index

      Functions

      getBackendPort +node/environment | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_environments.html b/docs/api/cli-kit/modules/node_environments.html index a6b126158ec..ead15ed542f 100644 --- a/docs/api/cli-kit/modules/node_environments.html +++ b/docs/api/cli-kit/modules/node_environments.html @@ -1,3 +1,3 @@ -node/environments | @shopify/cli-kit

      Module node/environments

      Index

      Interfaces

      Environments +node/environments | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_error.html b/docs/api/cli-kit/modules/node_error.html index 372e9c42950..8f69699246a 100644 --- a/docs/api/cli-kit/modules/node_error.html +++ b/docs/api/cli-kit/modules/node_error.html @@ -1,4 +1,4 @@ -node/error | @shopify/cli-kit

      Index

      Enumerations

      FatalErrorType +node/error | @shopify/cli-kit

      Index

      Enumerations

      Classes

      AbortError AbortSilentError BugError diff --git a/docs/api/cli-kit/modules/node_error_handler.html b/docs/api/cli-kit/modules/node_error_handler.html index d06f8bc5fff..5fc9b1f1f91 100644 --- a/docs/api/cli-kit/modules/node_error_handler.html +++ b/docs/api/cli-kit/modules/node_error_handler.html @@ -1,4 +1,4 @@ -node/error-handler | @shopify/cli-kit

      Module node/error-handler

      Index

      Functions

      addBugsnagMetadata +node/error-handler | @shopify/cli-kit

      Module node/error-handler

      Index

      Functions

      addBugsnagMetadata cleanStackFrameFilePath errorHandler registerCleanBugsnagErrorsFromWithinPlugins diff --git a/docs/api/cli-kit/modules/node_figures.html b/docs/api/cli-kit/modules/node_figures.html index c5aadc249c4..348dce18ca6 100644 --- a/docs/api/cli-kit/modules/node_figures.html +++ b/docs/api/cli-kit/modules/node_figures.html @@ -1 +1 @@ -node/figures | @shopify/cli-kit
      \ No newline at end of file +node/figures | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_framework.html b/docs/api/cli-kit/modules/node_framework.html index 99813a845c7..822bee7de67 100644 --- a/docs/api/cli-kit/modules/node_framework.html +++ b/docs/api/cli-kit/modules/node_framework.html @@ -1,2 +1,2 @@ -node/framework | @shopify/cli-kit

      Module node/framework

      Index

      Functions

      resolveFramework +node/framework | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_fs.html b/docs/api/cli-kit/modules/node_fs.html index 2ef56d4eb83..9ef373b2168 100644 --- a/docs/api/cli-kit/modules/node_fs.html +++ b/docs/api/cli-kit/modules/node_fs.html @@ -1,4 +1,4 @@ -node/fs | @shopify/cli-kit

      Index

      Interfaces

      MatchGlobOptions +node/fs | @shopify/cli-kit

      Index

      Interfaces

      Type Aliases

      Functions

      appendFile diff --git a/docs/api/cli-kit/modules/node_git.html b/docs/api/cli-kit/modules/node_git.html index a1a96fe335e..a8b7eb756fa 100644 --- a/docs/api/cli-kit/modules/node_git.html +++ b/docs/api/cli-kit/modules/node_git.html @@ -1,4 +1,4 @@ -node/git | @shopify/cli-kit

      Index

      Classes

      GitDirectoryNotCleanError +node/git | @shopify/cli-kit

      Index

      Classes

      Interfaces

      CreateGitCommitOptions GitCloneOptions diff --git a/docs/api/cli-kit/modules/node_github.html b/docs/api/cli-kit/modules/node_github.html index da8e92a9fdb..c650a40caff 100644 --- a/docs/api/cli-kit/modules/node_github.html +++ b/docs/api/cli-kit/modules/node_github.html @@ -1,4 +1,4 @@ -node/github | @shopify/cli-kit

      Module node/github

      Index

      Interfaces

      GithubRelease +node/github | @shopify/cli-kit

      Module node/github

      Index

      Interfaces

      Functions

      getLatestGitHubRelease parseGitHubRepositoryReference diff --git a/docs/api/cli-kit/modules/node_global_context.html b/docs/api/cli-kit/modules/node_global_context.html index 33a6104e6ed..dafb63a7a62 100644 --- a/docs/api/cli-kit/modules/node_global_context.html +++ b/docs/api/cli-kit/modules/node_global_context.html @@ -1,4 +1,4 @@ -node/global-context | @shopify/cli-kit

      Module node/global-context

      Index

      Interfaces

      GlobalContext +node/global-context | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_hooks_deprecations.html b/docs/api/cli-kit/modules/node_hooks_deprecations.html index 08d26bb0d38..fc0659bdb5c 100644 --- a/docs/api/cli-kit/modules/node_hooks_deprecations.html +++ b/docs/api/cli-kit/modules/node_hooks_deprecations.html @@ -1,2 +1,2 @@ -node/hooks/deprecations | @shopify/cli-kit

      Module node/hooks/deprecations

      Index

      Functions

      postrun +node/hooks/deprecations | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_hooks_postrun.html b/docs/api/cli-kit/modules/node_hooks_postrun.html index ad04c334e7f..23d6ee59f64 100644 --- a/docs/api/cli-kit/modules/node_hooks_postrun.html +++ b/docs/api/cli-kit/modules/node_hooks_postrun.html @@ -1,2 +1,2 @@ -node/hooks/postrun | @shopify/cli-kit

      Module node/hooks/postrun

      Index

      Functions

      hook +node/hooks/postrun | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_hooks_prerun.html b/docs/api/cli-kit/modules/node_hooks_prerun.html index cae58519e3d..e389cf3836d 100644 --- a/docs/api/cli-kit/modules/node_hooks_prerun.html +++ b/docs/api/cli-kit/modules/node_hooks_prerun.html @@ -1,4 +1,4 @@ -node/hooks/prerun | @shopify/cli-kit

      Module node/hooks/prerun

      Index

      Interfaces

      CommandContent +node/hooks/prerun | @shopify/cli-kit

      Module node/hooks/prerun

      Index

      Interfaces

      Functions

      hook parseCommandContent warnOnAvailableUpgrade diff --git a/docs/api/cli-kit/modules/node_hrtime.html b/docs/api/cli-kit/modules/node_hrtime.html index 413c49c01dc..191811dee4c 100644 --- a/docs/api/cli-kit/modules/node_hrtime.html +++ b/docs/api/cli-kit/modules/node_hrtime.html @@ -1,4 +1,4 @@ -node/hrtime | @shopify/cli-kit

      Module node/hrtime

      Index

      Type Aliases

      StartTime +node/hrtime | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_http.html b/docs/api/cli-kit/modules/node_http.html index f4eaaa56c86..07cf9966f32 100644 --- a/docs/api/cli-kit/modules/node_http.html +++ b/docs/api/cli-kit/modules/node_http.html @@ -1,4 +1,4 @@ -node/http | @shopify/cli-kit

      Index

      Functions

      downloadFile +node/http | @shopify/cli-kit

      Index

      Functions

      downloadFile fetch formData shopifyFetch diff --git a/docs/api/cli-kit/modules/node_ink.html b/docs/api/cli-kit/modules/node_ink.html index b77e777f0a3..5efe3c6dba1 100644 --- a/docs/api/cli-kit/modules/node_ink.html +++ b/docs/api/cli-kit/modules/node_ink.html @@ -1 +1 @@ -node/ink | @shopify/cli-kit
      \ No newline at end of file +node/ink | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_is_global.html b/docs/api/cli-kit/modules/node_is_global.html index cffe250b4e7..b37eb9c3765 100644 --- a/docs/api/cli-kit/modules/node_is_global.html +++ b/docs/api/cli-kit/modules/node_is_global.html @@ -1,4 +1,4 @@ -node/is-global | @shopify/cli-kit

      Module node/is-global

      Index

      Interfaces

      InstallGlobalCLIPromptResult +node/is-global | @shopify/cli-kit

      Module node/is-global

      Index

      Interfaces

      Functions

      currentProcessIsGlobal inferPackageManagerForGlobalCLI installGlobalCLIPrompt diff --git a/docs/api/cli-kit/modules/node_json_schema.html b/docs/api/cli-kit/modules/node_json_schema.html index a148c60eec2..75c63253466 100644 --- a/docs/api/cli-kit/modules/node_json_schema.html +++ b/docs/api/cli-kit/modules/node_json_schema.html @@ -1,3 +1,3 @@ -node/json-schema | @shopify/cli-kit

      Module node/json-schema

      Index

      Functions

      jsonSchemaValidate +node/json-schema | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_liquid.html b/docs/api/cli-kit/modules/node_liquid.html index 635c3ce1fce..9b2ceef8cf4 100644 --- a/docs/api/cli-kit/modules/node_liquid.html +++ b/docs/api/cli-kit/modules/node_liquid.html @@ -1,3 +1,3 @@ -node/liquid | @shopify/cli-kit

      Module node/liquid

      Index

      Functions

      recursiveLiquidTemplateCopy +node/liquid | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_local_storage.html b/docs/api/cli-kit/modules/node_local_storage.html index fbfd84e1c80..f5efbd122fc 100644 --- a/docs/api/cli-kit/modules/node_local_storage.html +++ b/docs/api/cli-kit/modules/node_local_storage.html @@ -1,2 +1,2 @@ -node/local-storage | @shopify/cli-kit

      Module node/local-storage

      Index

      Classes

      LocalStorage +node/local-storage | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_logs.html b/docs/api/cli-kit/modules/node_logs.html index f692bde6dd7..60ec23ba4b4 100644 --- a/docs/api/cli-kit/modules/node_logs.html +++ b/docs/api/cli-kit/modules/node_logs.html @@ -1,4 +1,4 @@ -node/logs | @shopify/cli-kit

      Index

      Functions

      createLogsDir +node/logs | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_metadata.html b/docs/api/cli-kit/modules/node_metadata.html index 6719028b6f3..a4ed8a8fdcb 100644 --- a/docs/api/cli-kit/modules/node_metadata.html +++ b/docs/api/cli-kit/modules/node_metadata.html @@ -1,4 +1,4 @@ -node/metadata | @shopify/cli-kit

      Module node/metadata

      Index

      Interfaces

      RuntimeMetadataManager +node/metadata | @shopify/cli-kit

      Module node/metadata

      Index

      Interfaces

      Type Aliases

      Public PublicSchema Sensitive diff --git a/docs/api/cli-kit/modules/node_mimes.html b/docs/api/cli-kit/modules/node_mimes.html index 704dac3abf7..d795a914cf3 100644 --- a/docs/api/cli-kit/modules/node_mimes.html +++ b/docs/api/cli-kit/modules/node_mimes.html @@ -1,3 +1,3 @@ -node/mimes | @shopify/cli-kit

      Index

      Functions

      lookupMimeType +node/mimes | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_monorail.html b/docs/api/cli-kit/modules/node_monorail.html index 715112b6247..bcb91a76385 100644 --- a/docs/api/cli-kit/modules/node_monorail.html +++ b/docs/api/cli-kit/modules/node_monorail.html @@ -1,4 +1,4 @@ -node/monorail | @shopify/cli-kit

      Module node/monorail

      References

      DeepRequired +node/monorail | @shopify/cli-kit

      Module node/monorail

      References

      Interfaces

      Type Aliases

      MonorailEventPublic MonorailEventSensitive diff --git a/docs/api/cli-kit/modules/node_node_package_manager.html b/docs/api/cli-kit/modules/node_node_package_manager.html index 7a857f38d15..a276e198ddf 100644 --- a/docs/api/cli-kit/modules/node_node_package_manager.html +++ b/docs/api/cli-kit/modules/node_node_package_manager.html @@ -1,4 +1,4 @@ -node/node-package-manager | @shopify/cli-kit

      Module node/node-package-manager

      Index

      Classes

      FindUpAndReadPackageJsonNotFoundError +node/node-package-manager | @shopify/cli-kit

      Module node/node-package-manager

      Index

      Classes

      Interfaces

      DependencyVersion diff --git a/docs/api/cli-kit/modules/node_notifications_system.html b/docs/api/cli-kit/modules/node_notifications_system.html index 8d0d16998ea..ace2e2effc7 100644 --- a/docs/api/cli-kit/modules/node_notifications_system.html +++ b/docs/api/cli-kit/modules/node_notifications_system.html @@ -1,4 +1,4 @@ -node/notifications-system | @shopify/cli-kit

      Module node/notifications-system

      Index

      Type Aliases

      Notification +node/notifications-system | @shopify/cli-kit

      Module node/notifications-system

      Index

      Type Aliases

      Functions

      filterNotifications getNotifications diff --git a/docs/api/cli-kit/modules/node_os.html b/docs/api/cli-kit/modules/node_os.html index b407d9787a0..15430172a2d 100644 --- a/docs/api/cli-kit/modules/node_os.html +++ b/docs/api/cli-kit/modules/node_os.html @@ -1,3 +1,3 @@ -node/os | @shopify/cli-kit

      Index

      Functions

      platformAndArch +node/os | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_output.html b/docs/api/cli-kit/modules/node_output.html index 7ed860f490d..3ea5bf38d36 100644 --- a/docs/api/cli-kit/modules/node_output.html +++ b/docs/api/cli-kit/modules/node_output.html @@ -1,4 +1,4 @@ -node/output | @shopify/cli-kit

      Module node/output

      Index

      Classes

      TokenizedString +node/output | @shopify/cli-kit

      Module node/output

      Index

      Classes

      Interfaces

      Type Aliases

      LogLevel Logger diff --git a/docs/api/cli-kit/modules/node_path.html b/docs/api/cli-kit/modules/node_path.html index 624c149686f..4a337a67226 100644 --- a/docs/api/cli-kit/modules/node_path.html +++ b/docs/api/cli-kit/modules/node_path.html @@ -1,4 +1,4 @@ -node/path | @shopify/cli-kit

      Index

      Functions

      basename +node/path | @shopify/cli-kit

      Index

      Functions

      basename cwd dirname extname diff --git a/docs/api/cli-kit/modules/node_plugins.html b/docs/api/cli-kit/modules/node_plugins.html index 59311ba2f7f..2b0904ca36f 100644 --- a/docs/api/cli-kit/modules/node_plugins.html +++ b/docs/api/cli-kit/modules/node_plugins.html @@ -1,4 +1,4 @@ -node/plugins | @shopify/cli-kit

      Module node/plugins

      Index

      Interfaces

      HookReturnsPerPlugin +node/plugins | @shopify/cli-kit

      Module node/plugins

      Index

      Interfaces

      Type Aliases

      FanoutHookFunction PluginReturnsForHook diff --git a/docs/api/cli-kit/modules/node_plugins_tunnel.html b/docs/api/cli-kit/modules/node_plugins_tunnel.html index 7e821da3f0e..1d835d35d11 100644 --- a/docs/api/cli-kit/modules/node_plugins_tunnel.html +++ b/docs/api/cli-kit/modules/node_plugins_tunnel.html @@ -1,4 +1,4 @@ -node/plugins/tunnel | @shopify/cli-kit

      Module node/plugins/tunnel

      Index

      Classes

      TunnelError +node/plugins/tunnel | @shopify/cli-kit

      Module node/plugins/tunnel

      Index

      Classes

      Interfaces

      Type Aliases

      TunnelErrorType diff --git a/docs/api/cli-kit/modules/node_promises.html b/docs/api/cli-kit/modules/node_promises.html index ec87bf2529f..6d03c7db1e5 100644 --- a/docs/api/cli-kit/modules/node_promises.html +++ b/docs/api/cli-kit/modules/node_promises.html @@ -1,2 +1,2 @@ -node/promises | @shopify/cli-kit

      Module node/promises

      Index

      Functions

      flushPromises +node/promises | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_result.html b/docs/api/cli-kit/modules/node_result.html index 65c23412a2a..6cd06a8f6ac 100644 --- a/docs/api/cli-kit/modules/node_result.html +++ b/docs/api/cli-kit/modules/node_result.html @@ -1,4 +1,4 @@ -node/result | @shopify/cli-kit

      Module node/result

      Index

      Classes

      Err +node/result | @shopify/cli-kit

      Module node/result

      Index

      Classes

      Type Aliases

      Functions

      err diff --git a/docs/api/cli-kit/modules/node_schema.html b/docs/api/cli-kit/modules/node_schema.html index 2975e2bd905..05605408a0b 100644 --- a/docs/api/cli-kit/modules/node_schema.html +++ b/docs/api/cli-kit/modules/node_schema.html @@ -1,4 +1,4 @@ -node/schema | @shopify/cli-kit

      Module node/schema

      Index

      Type Aliases

      ParseConfigurationResult +node/schema | @shopify/cli-kit

      Module node/schema

      Index

      Type Aliases

      Functions

      deepStrict errorsToString diff --git a/docs/api/cli-kit/modules/node_session.html b/docs/api/cli-kit/modules/node_session.html index a7b70367090..68c33e74120 100644 --- a/docs/api/cli-kit/modules/node_session.html +++ b/docs/api/cli-kit/modules/node_session.html @@ -1,4 +1,4 @@ -node/session | @shopify/cli-kit

      Module node/session

      Index

      Interfaces

      AdminSession +node/session | @shopify/cli-kit

      Module node/session

      Index

      Interfaces

      Functions

      ensureAuthenticatedAdmin ensureAuthenticatedAppManagement ensureAuthenticatedBusinessPlatform diff --git a/docs/api/cli-kit/modules/node_system.html b/docs/api/cli-kit/modules/node_system.html index 19820ccb82e..a6663a6d374 100644 --- a/docs/api/cli-kit/modules/node_system.html +++ b/docs/api/cli-kit/modules/node_system.html @@ -1,4 +1,4 @@ -node/system | @shopify/cli-kit

      Module node/system

      Index

      Interfaces

      ExecOptions +node/system | @shopify/cli-kit

      Module node/system

      Index

      Interfaces

      Functions

      captureOutput exec openURL diff --git a/docs/api/cli-kit/modules/node_tcp.html b/docs/api/cli-kit/modules/node_tcp.html index 48020115d36..05fe505b11b 100644 --- a/docs/api/cli-kit/modules/node_tcp.html +++ b/docs/api/cli-kit/modules/node_tcp.html @@ -1,3 +1,3 @@ -node/tcp | @shopify/cli-kit

      Index

      Functions

      checkPortAvailability +node/tcp | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_testing_output.html b/docs/api/cli-kit/modules/node_testing_output.html index 673504ce23f..3146af204fa 100644 --- a/docs/api/cli-kit/modules/node_testing_output.html +++ b/docs/api/cli-kit/modules/node_testing_output.html @@ -1,2 +1,2 @@ -node/testing/output | @shopify/cli-kit

      Module node/testing/output

      Index

      Functions

      mockAndCaptureOutput +node/testing/output | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_testing_ui.html b/docs/api/cli-kit/modules/node_testing_ui.html index 2f5f1f0d8c4..82fbec18f27 100644 --- a/docs/api/cli-kit/modules/node_testing_ui.html +++ b/docs/api/cli-kit/modules/node_testing_ui.html @@ -1,4 +1,4 @@ -node/testing/ui | @shopify/cli-kit

      Module node/testing/ui

      Index

      Classes

      Stdin +node/testing/ui | @shopify/cli-kit

      Module node/testing/ui

      Index

      Classes

      Functions

      getLastFrameAfterUnmount render sendInputAndWait diff --git a/docs/api/cli-kit/modules/node_themes_api.html b/docs/api/cli-kit/modules/node_themes_api.html index 11c994aa46a..e21899eaf5c 100644 --- a/docs/api/cli-kit/modules/node_themes_api.html +++ b/docs/api/cli-kit/modules/node_themes_api.html @@ -1,4 +1,4 @@ -node/themes/api | @shopify/cli-kit

      Module node/themes/api

      Index

      Type Aliases

      AssetParams +node/themes/api | @shopify/cli-kit

      Module node/themes/api

      Index

      Type Aliases

      Functions

      bulkUploadThemeAssets createTheme diff --git a/docs/api/cli-kit/modules/node_themes_conf.html b/docs/api/cli-kit/modules/node_themes_conf.html index 14618969f22..8e4ffd70c0a 100644 --- a/docs/api/cli-kit/modules/node_themes_conf.html +++ b/docs/api/cli-kit/modules/node_themes_conf.html @@ -1,4 +1,4 @@ -node/themes/conf | @shopify/cli-kit

      Module node/themes/conf

      Index

      Functions

      getHostTheme +node/themes/conf | @shopify/cli-kit

      Module node/themes/conf

      Index

      Functions

      getHostTheme hostThemeLocalStorage removeHostTheme setHostTheme diff --git a/docs/api/cli-kit/modules/node_themes_factories.html b/docs/api/cli-kit/modules/node_themes_factories.html index 521deba0471..e17bbef3ac5 100644 --- a/docs/api/cli-kit/modules/node_themes_factories.html +++ b/docs/api/cli-kit/modules/node_themes_factories.html @@ -1,6 +1,5 @@ -node/themes/factories | @shopify/cli-kit

      Module node/themes/factories

      Index

      Interfaces

      Functions

      buildBulkUploadResults -buildChecksum +node/themes/factories | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_themes_theme_manager.html b/docs/api/cli-kit/modules/node_themes_theme_manager.html index 7bd189adc46..ad6cb704052 100644 --- a/docs/api/cli-kit/modules/node_themes_theme_manager.html +++ b/docs/api/cli-kit/modules/node_themes_theme_manager.html @@ -1,2 +1,2 @@ -node/themes/theme-manager | @shopify/cli-kit

      Module node/themes/theme-manager

      Index

      Classes

      ThemeManager +node/themes/theme-manager | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_themes_types.html b/docs/api/cli-kit/modules/node_themes_types.html index 040ce563d2e..5779754e59e 100644 --- a/docs/api/cli-kit/modules/node_themes_types.html +++ b/docs/api/cli-kit/modules/node_themes_types.html @@ -1,4 +1,4 @@ -node/themes/types | @shopify/cli-kit

      Module node/themes/types

      Index

      Enumerations

      Operation +node/themes/types | @shopify/cli-kit

      Module node/themes/types

      Index

      Enumerations

      Interfaces

      Checksum Result Theme diff --git a/docs/api/cli-kit/modules/node_themes_urls.html b/docs/api/cli-kit/modules/node_themes_urls.html index f1df6466332..7776456fb80 100644 --- a/docs/api/cli-kit/modules/node_themes_urls.html +++ b/docs/api/cli-kit/modules/node_themes_urls.html @@ -1,4 +1,4 @@ -node/themes/urls | @shopify/cli-kit

      Module node/themes/urls

      Index

      Functions

      codeEditorUrl +node/themes/urls | @shopify/cli-kit

      Module node/themes/urls

      Index

      Functions

      codeEditorUrl storeAdminUrl storePasswordPage themeEditorUrl diff --git a/docs/api/cli-kit/modules/node_themes_utils.html b/docs/api/cli-kit/modules/node_themes_utils.html index 80b3a9d5100..6480bb9bb12 100644 --- a/docs/api/cli-kit/modules/node_themes_utils.html +++ b/docs/api/cli-kit/modules/node_themes_utils.html @@ -1,4 +1,4 @@ -node/themes/utils | @shopify/cli-kit

      Module node/themes/utils

      Index

      Type Aliases

      Role +node/themes/utils | @shopify/cli-kit

      Module node/themes/utils

      Index

      Type Aliases

      Variables

      DEVELOPMENT_THEME_ROLE LIVE_THEME_ROLE UNPUBLISHED_THEME_ROLE diff --git a/docs/api/cli-kit/modules/node_toml.html b/docs/api/cli-kit/modules/node_toml.html index cba8aba6ce5..31553373dce 100644 --- a/docs/api/cli-kit/modules/node_toml.html +++ b/docs/api/cli-kit/modules/node_toml.html @@ -1,4 +1,4 @@ -node/toml | @shopify/cli-kit

      Index

      Type Aliases

      JsonMapType +node/toml | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_tree_kill.html b/docs/api/cli-kit/modules/node_tree_kill.html index 98ef4b9073c..e2e33e7c0e2 100644 --- a/docs/api/cli-kit/modules/node_tree_kill.html +++ b/docs/api/cli-kit/modules/node_tree_kill.html @@ -1,2 +1,2 @@ -node/tree-kill | @shopify/cli-kit

      Module node/tree-kill

      Index

      Functions

      treeKill +node/tree-kill | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_ui.html b/docs/api/cli-kit/modules/node_ui.html index 89fba07b65a..8ccba1b317c 100644 --- a/docs/api/cli-kit/modules/node_ui.html +++ b/docs/api/cli-kit/modules/node_ui.html @@ -1,4 +1,4 @@ -node/ui | @shopify/cli-kit

      Index

      Interfaces

      InfoTableSection +node/ui | @shopify/cli-kit

      Index

      Interfaces

      InfoTableSection LinkToken ListToken RenderAutocompleteOptions diff --git a/docs/api/cli-kit/modules/node_ui_components.html b/docs/api/cli-kit/modules/node_ui_components.html index e8312710042..d5c0a609159 100644 --- a/docs/api/cli-kit/modules/node_ui_components.html +++ b/docs/api/cli-kit/modules/node_ui_components.html @@ -1,4 +1,4 @@ -node/ui/components | @shopify/cli-kit

      Module node/ui/components

      Index

      Interfaces

      ConcurrentOutputContext +node/ui/components | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_ui_hooks.html b/docs/api/cli-kit/modules/node_ui_hooks.html index 7df93b5ec6f..3cc3cb2ce69 100644 --- a/docs/api/cli-kit/modules/node_ui_hooks.html +++ b/docs/api/cli-kit/modules/node_ui_hooks.html @@ -1,2 +1,2 @@ -node/ui/hooks | @shopify/cli-kit

      Module node/ui/hooks

      Index

      Functions

      useAbortSignal +node/ui/hooks | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_upgrade.html b/docs/api/cli-kit/modules/node_upgrade.html index 5eec5958afb..f4c9aa34f0e 100644 --- a/docs/api/cli-kit/modules/node_upgrade.html +++ b/docs/api/cli-kit/modules/node_upgrade.html @@ -1,3 +1,3 @@ -node/upgrade | @shopify/cli-kit

      Module node/upgrade

      Index

      Functions

      cliInstallCommand +node/upgrade | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_vendor_dev_server_DevServer.html b/docs/api/cli-kit/modules/node_vendor_dev_server_DevServer.html new file mode 100644 index 00000000000..0035ced11eb --- /dev/null +++ b/docs/api/cli-kit/modules/node_vendor_dev_server_DevServer.html @@ -0,0 +1,3 @@ +node/vendor/dev_server/DevServer | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_vendor_dev_server_network_interfaces.html b/docs/api/cli-kit/modules/node_vendor_dev_server_network_interfaces.html new file mode 100644 index 00000000000..c356b2cacfc --- /dev/null +++ b/docs/api/cli-kit/modules/node_vendor_dev_server_network_interfaces.html @@ -0,0 +1,4 @@ +node/vendor/dev_server/network-interfaces | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_vendor_otel_js_export_InstantaneousMetricReader.html b/docs/api/cli-kit/modules/node_vendor_otel_js_export_InstantaneousMetricReader.html index 76bf117321d..40b15f03ebd 100644 --- a/docs/api/cli-kit/modules/node_vendor_otel_js_export_InstantaneousMetricReader.html +++ b/docs/api/cli-kit/modules/node_vendor_otel_js_export_InstantaneousMetricReader.html @@ -1,3 +1,3 @@ -node/vendor/otel-js/export/InstantaneousMetricReader | @shopify/cli-kit

      Module node/vendor/otel-js/export/InstantaneousMetricReader

      Index

      Classes

      InstantaneousMetricReader +node/vendor/otel-js/export/InstantaneousMetricReader | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_vendor_otel_js_service_BaseOtelService_BaseOtelService.html b/docs/api/cli-kit/modules/node_vendor_otel_js_service_BaseOtelService_BaseOtelService.html index 3c088c5df86..7809f01e8e0 100644 --- a/docs/api/cli-kit/modules/node_vendor_otel_js_service_BaseOtelService_BaseOtelService.html +++ b/docs/api/cli-kit/modules/node_vendor_otel_js_service_BaseOtelService_BaseOtelService.html @@ -1,3 +1,3 @@ -node/vendor/otel-js/service/BaseOtelService/BaseOtelService | @shopify/cli-kit

      Module node/vendor/otel-js/service/BaseOtelService/BaseOtelService

      Index

      Classes

      BaseOtelService +node/vendor/otel-js/service/BaseOtelService/BaseOtelService | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_vendor_otel_js_service_DefaultOtelService_DefaultMeterProvider.html b/docs/api/cli-kit/modules/node_vendor_otel_js_service_DefaultOtelService_DefaultMeterProvider.html index f492ce682b7..b87f7ec227f 100644 --- a/docs/api/cli-kit/modules/node_vendor_otel_js_service_DefaultOtelService_DefaultMeterProvider.html +++ b/docs/api/cli-kit/modules/node_vendor_otel_js_service_DefaultOtelService_DefaultMeterProvider.html @@ -1,3 +1,3 @@ -node/vendor/otel-js/service/DefaultOtelService/DefaultMeterProvider | @shopify/cli-kit

      Module node/vendor/otel-js/service/DefaultOtelService/DefaultMeterProvider

      Index

      Classes

      DefaultMeterProvider +node/vendor/otel-js/service/DefaultOtelService/DefaultMeterProvider | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_vendor_otel_js_service_DefaultOtelService_DefaultOtelService.html b/docs/api/cli-kit/modules/node_vendor_otel_js_service_DefaultOtelService_DefaultOtelService.html index 774c543faca..ae52934b0ca 100644 --- a/docs/api/cli-kit/modules/node_vendor_otel_js_service_DefaultOtelService_DefaultOtelService.html +++ b/docs/api/cli-kit/modules/node_vendor_otel_js_service_DefaultOtelService_DefaultOtelService.html @@ -1,3 +1,3 @@ -node/vendor/otel-js/service/DefaultOtelService/DefaultOtelService | @shopify/cli-kit

      Module node/vendor/otel-js/service/DefaultOtelService/DefaultOtelService

      Index

      Classes

      DefaultOtelService +node/vendor/otel-js/service/DefaultOtelService/DefaultOtelService | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_vendor_otel_js_service_types.html b/docs/api/cli-kit/modules/node_vendor_otel_js_service_types.html index c628ece4b9f..1343bcaaf96 100644 --- a/docs/api/cli-kit/modules/node_vendor_otel_js_service_types.html +++ b/docs/api/cli-kit/modules/node_vendor_otel_js_service_types.html @@ -1,4 +1,4 @@ -node/vendor/otel-js/service/types | @shopify/cli-kit

      Module node/vendor/otel-js/service/types

      Index

      Enumerations

      MetricInstrumentType +node/vendor/otel-js/service/types | @shopify/cli-kit

      Module node/vendor/otel-js/service/types

      Index

      Enumerations

      Interfaces

      Type Aliases

      CustomMetricLabels diff --git a/docs/api/cli-kit/modules/node_vendor_otel_js_utils_throttle.html b/docs/api/cli-kit/modules/node_vendor_otel_js_utils_throttle.html index 180938a1fe0..5c028d1aa30 100644 --- a/docs/api/cli-kit/modules/node_vendor_otel_js_utils_throttle.html +++ b/docs/api/cli-kit/modules/node_vendor_otel_js_utils_throttle.html @@ -1,2 +1,2 @@ -node/vendor/otel-js/utils/throttle | @shopify/cli-kit

      Module node/vendor/otel-js/utils/throttle

      Index

      Functions

      throttle +node/vendor/otel-js/utils/throttle | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_vendor_otel_js_utils_validators.html b/docs/api/cli-kit/modules/node_vendor_otel_js_utils_validators.html index 88dd5dfe84c..c8c5c141ee8 100644 --- a/docs/api/cli-kit/modules/node_vendor_otel_js_utils_validators.html +++ b/docs/api/cli-kit/modules/node_vendor_otel_js_utils_validators.html @@ -1,2 +1,2 @@ -node/vendor/otel-js/utils/validators | @shopify/cli-kit

      Module node/vendor/otel-js/utils/validators

      Index

      Functions

      isValidMetricName +node/vendor/otel-js/utils/validators | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_version.html b/docs/api/cli-kit/modules/node_version.html index 12c5515e0d4..d879c7bce2b 100644 --- a/docs/api/cli-kit/modules/node_version.html +++ b/docs/api/cli-kit/modules/node_version.html @@ -1,3 +1,3 @@ -node/version | @shopify/cli-kit

      Module node/version

      Index

      Functions

      globalCLIVersion +node/version | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/modules/node_vscode.html b/docs/api/cli-kit/modules/node_vscode.html index 4b1dd80a769..a1f1197d450 100644 --- a/docs/api/cli-kit/modules/node_vscode.html +++ b/docs/api/cli-kit/modules/node_vscode.html @@ -1,3 +1,3 @@ -node/vscode | @shopify/cli-kit

      Module node/vscode

      Index

      Functions

      addRecommendedExtensions +node/vscode | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/common_string.RandomNameFamily.html b/docs/api/cli-kit/types/common_string.RandomNameFamily.html index 6ce19b78c31..f01ed2c0c73 100644 --- a/docs/api/cli-kit/types/common_string.RandomNameFamily.html +++ b/docs/api/cli-kit/types/common_string.RandomNameFamily.html @@ -1 +1 @@ -RandomNameFamily | @shopify/cli-kit
      RandomNameFamily: "business" | "creative"
      \ No newline at end of file +RandomNameFamily | @shopify/cli-kit
      RandomNameFamily: "business" | "creative"
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/common_ts_deep_required.DeepRequired.html b/docs/api/cli-kit/types/common_ts_deep_required.DeepRequired.html index 118884e501a..44ac9ce0f4c 100644 --- a/docs/api/cli-kit/types/common_ts_deep_required.DeepRequired.html +++ b/docs/api/cli-kit/types/common_ts_deep_required.DeepRequired.html @@ -1,4 +1,4 @@ DeepRequired | @shopify/cli-kit
      DeepRequired<T>: {
          [TKey in keyof Required<T>]: NonNullable<Required<T>[TKey]>
      }

      Converts a mapping type to be non-optional.

      type T = DeepRequired<{optionalKey?: string, nullableValue: string | null, undefinableValue: string | undefined}>
      T = {optionalKey: string, nullableValue: string, undefinableValue: string}
      -

      Type Parameters

      • T
      \ No newline at end of file +

      Type Parameters

      • T
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/common_ts_pick_by_prefix.PickByPrefix.html b/docs/api/cli-kit/types/common_ts_pick_by_prefix.PickByPrefix.html index bd29b4bd347..b8501a03acc 100644 --- a/docs/api/cli-kit/types/common_ts_pick_by_prefix.PickByPrefix.html +++ b/docs/api/cli-kit/types/common_ts_pick_by_prefix.PickByPrefix.html @@ -1,4 +1,4 @@ PickByPrefix | @shopify/cli-kit

      Type alias PickByPrefix<TMapping, TPrefix, TKeys>

      PickByPrefix<TMapping, TPrefix, TKeys>: {
          [TKey in keyof TMapping as TKey extends `${TPrefix}${infer _TSuffix}` | TKeys
              ? TKey
              : never]: TMapping[TKey]
      }

      Produces a subset of a mapping type, where the keys either match some prefix string, or are in a list of exact matches.

      type T = PickByPrefix<{foo_1: number, foo_2: number, nope: string, included: string, also: number}, 'foo_', 'included' | 'also'>.

      T = {foo_1: number, foo_2: number, included: string, also: number}
      -

      Type Parameters

      • TMapping
      • TPrefix extends string
      • TKeys extends keyof TMapping = never
      \ No newline at end of file +

      Type Parameters

      • TMapping
      • TPrefix extends string
      • TKeys extends keyof TMapping = never
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_analytics.CommandExitMode.html b/docs/api/cli-kit/types/node_analytics.CommandExitMode.html index 56af1f2f846..3ecef131ac5 100644 --- a/docs/api/cli-kit/types/node_analytics.CommandExitMode.html +++ b/docs/api/cli-kit/types/node_analytics.CommandExitMode.html @@ -1 +1 @@ -CommandExitMode | @shopify/cli-kit
      CommandExitMode: "ok" | "unexpected_error" | "expected_error"
      \ No newline at end of file +CommandExitMode | @shopify/cli-kit
      CommandExitMode: "ok" | "unexpected_error" | "expected_error"
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_api_graphql.Exact.html b/docs/api/cli-kit/types/node_api_graphql.Exact.html index 8a03e1d38d4..09e517d5464 100644 --- a/docs/api/cli-kit/types/node_api_graphql.Exact.html +++ b/docs/api/cli-kit/types/node_api_graphql.Exact.html @@ -1 +1 @@ -Exact | @shopify/cli-kit
      Exact<T>: {
          [K in keyof T]: T[K]
      }

      Type Parameters

      • T extends {
            [key: string]: unknown;
        }
      \ No newline at end of file +Exact | @shopify/cli-kit
      Exact<T>: {
          [K in keyof T]: T[K]
      }

      Type Parameters

      • T extends {
            [key: string]: unknown;
        }
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_api_graphql.GraphQLRequestDocOptions.html b/docs/api/cli-kit/types/node_api_graphql.GraphQLRequestDocOptions.html index 8459fba78f7..316cec7e022 100644 --- a/docs/api/cli-kit/types/node_api_graphql.GraphQLRequestDocOptions.html +++ b/docs/api/cli-kit/types/node_api_graphql.GraphQLRequestDocOptions.html @@ -1 +1 @@ -GraphQLRequestDocOptions | @shopify/cli-kit

      Type alias GraphQLRequestDocOptions<TResult, TVariables>

      GraphQLRequestDocOptions<TResult, TVariables>: GraphQLRequestBaseOptions<TResult> & {
          query: TypedDocumentNode<TResult, TVariables> | TypedDocumentNode<TResult, Exact<{
              [key: string]: never;
          }>>;
          variables?: TVariables;
      }

      Type Parameters

      • TResult
      • TVariables

      Type declaration

      \ No newline at end of file +GraphQLRequestDocOptions | @shopify/cli-kit

      Type alias GraphQLRequestDocOptions<TResult, TVariables>

      GraphQLRequestDocOptions<TResult, TVariables>: GraphQLRequestBaseOptions<TResult> & {
          query: TypedDocumentNode<TResult, TVariables> | TypedDocumentNode<TResult, Exact<{
              [key: string]: never;
          }>>;
          unauthorizedHandler?: (() => Promise<void>);
          variables?: TVariables;
      }

      Type Parameters

      • TResult
      • TVariables

      Type declaration

      • query: TypedDocumentNode<TResult, TVariables> | TypedDocumentNode<TResult, Exact<{
            [key: string]: never;
        }>>
      • Optional unauthorizedHandler?: (() => Promise<void>)
          • (): Promise<void>
          • Returns Promise<void>

      • Optional variables?: TVariables
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_api_graphql.GraphQLRequestOptions.html b/docs/api/cli-kit/types/node_api_graphql.GraphQLRequestOptions.html index 15488489138..7c67b8a6df8 100644 --- a/docs/api/cli-kit/types/node_api_graphql.GraphQLRequestOptions.html +++ b/docs/api/cli-kit/types/node_api_graphql.GraphQLRequestOptions.html @@ -1 +1 @@ -GraphQLRequestOptions | @shopify/cli-kit
      GraphQLRequestOptions<T>: GraphQLRequestBaseOptions<T> & {
          query: RequestDocument;
          variables?: Variables;
      }

      Type Parameters

      • T

      Type declaration

      • query: RequestDocument
      • Optional variables?: Variables
      \ No newline at end of file +GraphQLRequestOptions | @shopify/cli-kit
      GraphQLRequestOptions<T>: GraphQLRequestBaseOptions<T> & {
          query: RequestDocument;
          unauthorizedHandler?: (() => Promise<void>);
          variables?: Variables;
      }

      Type Parameters

      • T

      Type declaration

      • query: RequestDocument
      • Optional unauthorizedHandler?: (() => Promise<void>)
          • (): Promise<void>
          • Returns Promise<void>

      • Optional variables?: Variables
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_api_graphql.GraphQLResponse.html b/docs/api/cli-kit/types/node_api_graphql.GraphQLResponse.html index c2bf8f56df3..b0e1782ccc0 100644 --- a/docs/api/cli-kit/types/node_api_graphql.GraphQLResponse.html +++ b/docs/api/cli-kit/types/node_api_graphql.GraphQLResponse.html @@ -1 +1 @@ -GraphQLResponse | @shopify/cli-kit
      GraphQLResponse<T>: Awaited<ReturnType<typeof rawRequest>>

      Type Parameters

      • T
      \ No newline at end of file +GraphQLResponse | @shopify/cli-kit
      GraphQLResponse<T>: Awaited<ReturnType<typeof rawRequest>>

      Type Parameters

      • T
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_context_local.CIMetadata.html b/docs/api/cli-kit/types/node_context_local.CIMetadata.html index bcc1771bd15..b2a4062bcfd 100644 --- a/docs/api/cli-kit/types/node_context_local.CIMetadata.html +++ b/docs/api/cli-kit/types/node_context_local.CIMetadata.html @@ -1 +1 @@ -CIMetadata | @shopify/cli-kit
      \ No newline at end of file +CIMetadata | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_fs.ReadOptions.html b/docs/api/cli-kit/types/node_fs.ReadOptions.html index dc5bb9ca2bf..da733323ed0 100644 --- a/docs/api/cli-kit/types/node_fs.ReadOptions.html +++ b/docs/api/cli-kit/types/node_fs.ReadOptions.html @@ -2,4 +2,4 @@ utf-8 encoding.

      Type declaration

      • Optional flag?: string

      Type declaration

      • encoding: string
      • Optional flag?: string

      Param: path

      Path to the file to read.

      Returns

      A promise that resolves with the content of the file.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_hrtime.StartTime.html b/docs/api/cli-kit/types/node_hrtime.StartTime.html index 19460fcabe9..eec8d59bbb5 100644 --- a/docs/api/cli-kit/types/node_hrtime.StartTime.html +++ b/docs/api/cli-kit/types/node_hrtime.StartTime.html @@ -1 +1 @@ -StartTime | @shopify/cli-kit
      StartTime: [number, number]
      \ No newline at end of file +StartTime | @shopify/cli-kit
      StartTime: [number, number]
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_metadata.Public.html b/docs/api/cli-kit/types/node_metadata.Public.html index aced81802e6..cfd3037bd41 100644 --- a/docs/api/cli-kit/types/node_metadata.Public.html +++ b/docs/api/cli-kit/types/node_metadata.Public.html @@ -1 +1 @@ -Public | @shopify/cli-kit
      \ No newline at end of file +Public | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_metadata.PublicSchema.html b/docs/api/cli-kit/types/node_metadata.PublicSchema.html index e6a759d486a..8cd4d2d47ea 100644 --- a/docs/api/cli-kit/types/node_metadata.PublicSchema.html +++ b/docs/api/cli-kit/types/node_metadata.PublicSchema.html @@ -1 +1 @@ -PublicSchema | @shopify/cli-kit
      PublicSchema<T>: T extends RuntimeMetadataManager<infer TPublic, infer _TSensitive>
          ? TPublic
          : never

      Type Parameters

      • T
      \ No newline at end of file +PublicSchema | @shopify/cli-kit
      PublicSchema<T>: T extends RuntimeMetadataManager<infer TPublic, infer _TSensitive>
          ? TPublic
          : never

      Type Parameters

      • T
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_metadata.Sensitive.html b/docs/api/cli-kit/types/node_metadata.Sensitive.html index 1e3ca947fa3..1799df37e51 100644 --- a/docs/api/cli-kit/types/node_metadata.Sensitive.html +++ b/docs/api/cli-kit/types/node_metadata.Sensitive.html @@ -1 +1 @@ -Sensitive | @shopify/cli-kit
      \ No newline at end of file +Sensitive | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_metadata.SensitiveSchema.html b/docs/api/cli-kit/types/node_metadata.SensitiveSchema.html index c187bf948dc..fd7e4c857ee 100644 --- a/docs/api/cli-kit/types/node_metadata.SensitiveSchema.html +++ b/docs/api/cli-kit/types/node_metadata.SensitiveSchema.html @@ -1 +1 @@ -SensitiveSchema | @shopify/cli-kit
      SensitiveSchema<T>: T extends RuntimeMetadataManager<infer _TPublic, infer TSensitive>
          ? TSensitive
          : never

      Type Parameters

      • T
      \ No newline at end of file +SensitiveSchema | @shopify/cli-kit
      SensitiveSchema<T>: T extends RuntimeMetadataManager<infer _TPublic, infer TSensitive>
          ? TSensitive
          : never

      Type Parameters

      • T
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_monorail.MonorailEventPublic.html b/docs/api/cli-kit/types/node_monorail.MonorailEventPublic.html index 5fc20c425f5..8bb9623e9e8 100644 --- a/docs/api/cli-kit/types/node_monorail.MonorailEventPublic.html +++ b/docs/api/cli-kit/types/node_monorail.MonorailEventPublic.html @@ -1 +1 @@ -MonorailEventPublic | @shopify/cli-kit
      \ No newline at end of file +MonorailEventPublic | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_monorail.MonorailEventSensitive.html b/docs/api/cli-kit/types/node_monorail.MonorailEventSensitive.html index 2c291a10c42..4b304c216c0 100644 --- a/docs/api/cli-kit/types/node_monorail.MonorailEventSensitive.html +++ b/docs/api/cli-kit/types/node_monorail.MonorailEventSensitive.html @@ -1 +1 @@ -MonorailEventSensitive | @shopify/cli-kit
      MonorailEventSensitive: Schemas[typeof MONORAIL_COMMAND_TOPIC]["sensitive"]
      \ No newline at end of file +MonorailEventSensitive | @shopify/cli-kit
      MonorailEventSensitive: Schemas[typeof MONORAIL_COMMAND_TOPIC]["sensitive"]
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_node_package_manager.DependencyType.html b/docs/api/cli-kit/types/node_node_package_manager.DependencyType.html index 87f486af636..c3a1fe0b8f2 100644 --- a/docs/api/cli-kit/types/node_node_package_manager.DependencyType.html +++ b/docs/api/cli-kit/types/node_node_package_manager.DependencyType.html @@ -4,4 +4,4 @@
    • prod: dependencies
    • peer: peerDependencies
    • -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_node_package_manager.Lockfile.html b/docs/api/cli-kit/types/node_node_package_manager.Lockfile.html index a8a01ab5711..3952cba9138 100644 --- a/docs/api/cli-kit/types/node_node_package_manager.Lockfile.html +++ b/docs/api/cli-kit/types/node_node_package_manager.Lockfile.html @@ -1 +1 @@ -Lockfile | @shopify/cli-kit
      Lockfile: "yarn.lock" | "package-lock.json" | "pnpm-lock.yaml" | "bun.lockb"
      \ No newline at end of file +Lockfile | @shopify/cli-kit
      Lockfile: "yarn.lock" | "package-lock.json" | "pnpm-lock.yaml" | "bun.lockb"
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_node_package_manager.PackageManager.html b/docs/api/cli-kit/types/node_node_package_manager.PackageManager.html index f9a8141a7e0..00f37b71483 100644 --- a/docs/api/cli-kit/types/node_node_package_manager.PackageManager.html +++ b/docs/api/cli-kit/types/node_node_package_manager.PackageManager.html @@ -1 +1 @@ -PackageManager | @shopify/cli-kit
      \ No newline at end of file +PackageManager | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_notifications_system.Notification.html b/docs/api/cli-kit/types/node_notifications_system.Notification.html index 1a10b178694..745932c16d6 100644 --- a/docs/api/cli-kit/types/node_notifications_system.Notification.html +++ b/docs/api/cli-kit/types/node_notifications_system.Notification.html @@ -1 +1 @@ -Notification | @shopify/cli-kit
      Notification: zod.infer<typeof NotificationSchema>
      \ No newline at end of file +Notification | @shopify/cli-kit
      Notification: zod.infer<typeof NotificationSchema>
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_notifications_system.Notifications.html b/docs/api/cli-kit/types/node_notifications_system.Notifications.html index e27f7fa9f17..8527d784ff1 100644 --- a/docs/api/cli-kit/types/node_notifications_system.Notifications.html +++ b/docs/api/cli-kit/types/node_notifications_system.Notifications.html @@ -1 +1 @@ -Notifications | @shopify/cli-kit
      Notifications: zod.infer<typeof NotificationsSchema>
      \ No newline at end of file +Notifications | @shopify/cli-kit
      Notifications: zod.infer<typeof NotificationsSchema>
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_output.LogLevel.html b/docs/api/cli-kit/types/node_output.LogLevel.html index 56ae83077fd..8ca041a7d3c 100644 --- a/docs/api/cli-kit/types/node_output.LogLevel.html +++ b/docs/api/cli-kit/types/node_output.LogLevel.html @@ -1,2 +1,2 @@ LogLevel | @shopify/cli-kit
      LogLevel: "fatal" | "error" | "warn" | "info" | "debug" | "trace" | "silent"

      Log levels.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_output.Logger.html b/docs/api/cli-kit/types/node_output.Logger.html index 474ecf37c6b..c897c76259b 100644 --- a/docs/api/cli-kit/types/node_output.Logger.html +++ b/docs/api/cli-kit/types/node_output.Logger.html @@ -1 +1 @@ -Logger | @shopify/cli-kit
      Logger: Writable | ((message, logLevel?) => void)

      Type declaration

        • (message, logLevel?): void
        • Parameters

          • message: string
          • Optional logLevel: LogLevel

          Returns void

      \ No newline at end of file +Logger | @shopify/cli-kit
      Logger: Writable | ((message, logLevel?) => void)

      Type declaration

        • (message, logLevel?): void
        • Parameters

          • message: string
          • Optional logLevel: LogLevel

          Returns void

      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_output.OutputMessage.html b/docs/api/cli-kit/types/node_output.OutputMessage.html index 5274a088140..2fe79eaf7e0 100644 --- a/docs/api/cli-kit/types/node_output.OutputMessage.html +++ b/docs/api/cli-kit/types/node_output.OutputMessage.html @@ -1 +1 @@ -OutputMessage | @shopify/cli-kit
      \ No newline at end of file +OutputMessage | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_plugins.FanoutHookFunction.html b/docs/api/cli-kit/types/node_plugins.FanoutHookFunction.html index eac6eced359..a646cf057d4 100644 --- a/docs/api/cli-kit/types/node_plugins.FanoutHookFunction.html +++ b/docs/api/cli-kit/types/node_plugins.FanoutHookFunction.html @@ -1 +1 @@ -FanoutHookFunction | @shopify/cli-kit

      Type alias FanoutHookFunction<TEvent, TPluginName, TPluginMap>

      FanoutHookFunction<TEvent, TPluginName, TPluginMap>: ((this, options) => Promise<PluginReturnsForHook<TEvent, TPluginName, TPluginMap>>)

      Type Parameters

      Type declaration

      \ No newline at end of file +FanoutHookFunction | @shopify/cli-kit

      Type alias FanoutHookFunction<TEvent, TPluginName, TPluginMap>

      FanoutHookFunction<TEvent, TPluginName, TPluginMap>: ((this, options) => Promise<PluginReturnsForHook<TEvent, TPluginName, TPluginMap>>)

      Type Parameters

      Type declaration

      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_plugins.PluginReturnsForHook.html b/docs/api/cli-kit/types/node_plugins.PluginReturnsForHook.html index c0b04efc1fb..2875d5c96a4 100644 --- a/docs/api/cli-kit/types/node_plugins.PluginReturnsForHook.html +++ b/docs/api/cli-kit/types/node_plugins.PluginReturnsForHook.html @@ -1 +1 @@ -PluginReturnsForHook | @shopify/cli-kit

      Type alias PluginReturnsForHook<TEvent, TPluginName, TPluginMap>

      PluginReturnsForHook<TEvent, TPluginName, TPluginMap>: TPluginMap[TEvent]["pluginReturns"][TPluginName]

      Type Parameters

      \ No newline at end of file +PluginReturnsForHook | @shopify/cli-kit

      Type alias PluginReturnsForHook<TEvent, TPluginName, TPluginMap>

      PluginReturnsForHook<TEvent, TPluginName, TPluginMap>: TPluginMap[TEvent]["pluginReturns"][TPluginName]

      Type Parameters

      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_plugins_tunnel.TunnelErrorType.html b/docs/api/cli-kit/types/node_plugins_tunnel.TunnelErrorType.html index f181385b8fa..cb1a5803feb 100644 --- a/docs/api/cli-kit/types/node_plugins_tunnel.TunnelErrorType.html +++ b/docs/api/cli-kit/types/node_plugins_tunnel.TunnelErrorType.html @@ -1 +1 @@ -TunnelErrorType | @shopify/cli-kit
      TunnelErrorType: "invalid-provider" | "tunnel-already-running" | "wrong-credentials" | "unknown"
      \ No newline at end of file +TunnelErrorType | @shopify/cli-kit
      TunnelErrorType: "invalid-provider" | "tunnel-already-running" | "wrong-credentials" | "unknown"
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_plugins_tunnel.TunnelProviderFunction.html b/docs/api/cli-kit/types/node_plugins_tunnel.TunnelProviderFunction.html index d0f074b8b75..035b09a1d7d 100644 --- a/docs/api/cli-kit/types/node_plugins_tunnel.TunnelProviderFunction.html +++ b/docs/api/cli-kit/types/node_plugins_tunnel.TunnelProviderFunction.html @@ -1 +1 @@ -TunnelProviderFunction | @shopify/cli-kit
      TunnelProviderFunction: FanoutHookFunction<"tunnel_provider", "">
      \ No newline at end of file +TunnelProviderFunction | @shopify/cli-kit
      TunnelProviderFunction: FanoutHookFunction<"tunnel_provider", "">
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStartAction.html b/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStartAction.html index b4c76ce4081..94d755c98b6 100644 --- a/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStartAction.html +++ b/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStartAction.html @@ -1 +1 @@ -TunnelStartAction | @shopify/cli-kit
      TunnelStartAction: ((port) => Promise<TunnelStartReturn>)

      Type declaration

      \ No newline at end of file +TunnelStartAction | @shopify/cli-kit
      TunnelStartAction: ((port) => Promise<TunnelStartReturn>)

      Type declaration

      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStartFunction.html b/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStartFunction.html index 0323cc378bd..f3699e0431c 100644 --- a/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStartFunction.html +++ b/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStartFunction.html @@ -1 +1 @@ -TunnelStartFunction | @shopify/cli-kit
      \ No newline at end of file +TunnelStartFunction | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStartReturn.html b/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStartReturn.html index 778611d3a38..319efa64b1a 100644 --- a/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStartReturn.html +++ b/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStartReturn.html @@ -1 +1 @@ -TunnelStartReturn | @shopify/cli-kit
      \ No newline at end of file +TunnelStartReturn | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStatusType.html b/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStatusType.html index e5aef9341aa..23c32e7e8f9 100644 --- a/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStatusType.html +++ b/docs/api/cli-kit/types/node_plugins_tunnel.TunnelStatusType.html @@ -1 +1 @@ -TunnelStatusType | @shopify/cli-kit
      TunnelStatusType: {
          status: "not-started";
      } | {
          status: "starting";
      } | {
          status: "connected";
          url: string;
      } | {
          message: TokenItem | OutputMessage;
          status: "error";
          tryMessage?: TokenItem | OutputMessage | null;
      }

      Type declaration

      • status: "not-started"

      Type declaration

      • status: "starting"

      Type declaration

      • status: "connected"
      • url: string

      Type declaration

      \ No newline at end of file +TunnelStatusType | @shopify/cli-kit
      TunnelStatusType: {
          status: "not-started";
      } | {
          status: "starting";
      } | {
          status: "connected";
          url: string;
      } | {
          message: TokenItem | OutputMessage;
          status: "error";
          tryMessage?: TokenItem | OutputMessage | null;
      }

      Type declaration

      • status: "not-started"

      Type declaration

      • status: "starting"

      Type declaration

      • status: "connected"
      • url: string

      Type declaration

      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_result.Result.html b/docs/api/cli-kit/types/node_result.Result.html index 8f91985c5da..94867075d38 100644 --- a/docs/api/cli-kit/types/node_result.Result.html +++ b/docs/api/cli-kit/types/node_result.Result.html @@ -1 +1 @@ -Result | @shopify/cli-kit

      Type alias Result<TValue, TError>

      Type Parameters

      • TValue
      • TError
      \ No newline at end of file +Result | @shopify/cli-kit

      Type alias Result<TValue, TError>

      Type Parameters

      • TValue
      • TError
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_schema.ParseConfigurationResult.html b/docs/api/cli-kit/types/node_schema.ParseConfigurationResult.html index e50e3fe212e..313c10460f8 100644 --- a/docs/api/cli-kit/types/node_schema.ParseConfigurationResult.html +++ b/docs/api/cli-kit/types/node_schema.ParseConfigurationResult.html @@ -1,4 +1,4 @@ ParseConfigurationResult | @shopify/cli-kit

      Type alias ParseConfigurationResult<TConfiguration>

      ParseConfigurationResult<TConfiguration>: {
          data: TConfiguration;
          errors: undefined;
          state: "ok";
      } | {
          data: undefined;
          errors: Pick<z.ZodIssueBase, "path" | "message">[];
          state: "error";
      }

      A neutral type for the result of a parsing/validation operation.

      As some validation can happen via JSON Schema, we prefer to use a type that isn't wholly dependent on Zod (or JSON Schema).

      -

      Type Parameters

      • TConfiguration

      Type declaration

      Type declaration

      • data: undefined
      • errors: Pick<z.ZodIssueBase, "path" | "message">[]
      • state: "error"
      \ No newline at end of file +

      Type Parameters

      • TConfiguration

      Type declaration

      Type declaration

      • data: undefined
      • errors: Pick<z.ZodIssueBase, "path" | "message">[]
      • state: "error"
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_schema.ZodObjectOf.html b/docs/api/cli-kit/types/node_schema.ZodObjectOf.html index 32079d71ad8..2c2a6cb5929 100644 --- a/docs/api/cli-kit/types/node_schema.ZodObjectOf.html +++ b/docs/api/cli-kit/types/node_schema.ZodObjectOf.html @@ -1,2 +1,2 @@ ZodObjectOf | @shopify/cli-kit
      ZodObjectOf<T>: ZodObject<any, any, any, T>

      Type alias for a zod object schema that produces a given shape once parsed.

      -

      Type Parameters

      • T
      \ No newline at end of file +

      Type Parameters

      • T
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_themes_api.AssetParams.html b/docs/api/cli-kit/types/node_themes_api.AssetParams.html index 3647a5abe17..fd923646e61 100644 --- a/docs/api/cli-kit/types/node_themes_api.AssetParams.html +++ b/docs/api/cli-kit/types/node_themes_api.AssetParams.html @@ -1 +1 @@ -AssetParams | @shopify/cli-kit
      AssetParams: Pick<ThemeAsset, "key"> & Partial<Pick<ThemeAsset, "value" | "attachment">>
      \ No newline at end of file +AssetParams | @shopify/cli-kit
      AssetParams: Pick<ThemeAsset, "key"> & Partial<Pick<ThemeAsset, "value" | "attachment">>
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_themes_api.ThemeParams.html b/docs/api/cli-kit/types/node_themes_api.ThemeParams.html index f16dc7aa7e4..e4f6e209942 100644 --- a/docs/api/cli-kit/types/node_themes_api.ThemeParams.html +++ b/docs/api/cli-kit/types/node_themes_api.ThemeParams.html @@ -1 +1 @@ -ThemeParams | @shopify/cli-kit
      ThemeParams: Partial<Pick<Theme, "name" | "role" | "processing" | "src">>
      \ No newline at end of file +ThemeParams | @shopify/cli-kit
      ThemeParams: Partial<Pick<Theme, "name" | "role" | "processing" | "src">>
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_themes_types.Key.html b/docs/api/cli-kit/types/node_themes_types.Key.html index 13c7257bbdf..62674471f54 100644 --- a/docs/api/cli-kit/types/node_themes_types.Key.html +++ b/docs/api/cli-kit/types/node_themes_types.Key.html @@ -1,2 +1,2 @@ Key | @shopify/cli-kit
      Key: string

      Key represents the unique identifier of a file in a theme.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_themes_types.ThemeFSEventName.html b/docs/api/cli-kit/types/node_themes_types.ThemeFSEventName.html index 8a83cfdb903..67af01d989f 100644 --- a/docs/api/cli-kit/types/node_themes_types.ThemeFSEventName.html +++ b/docs/api/cli-kit/types/node_themes_types.ThemeFSEventName.html @@ -1 +1 @@ -ThemeFSEventName | @shopify/cli-kit
      ThemeFSEventName: "add" | "change" | "unlink"
      \ No newline at end of file +ThemeFSEventName | @shopify/cli-kit
      ThemeFSEventName: "add" | "change" | "unlink"
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_themes_types.ThemeFSEventPayload.html b/docs/api/cli-kit/types/node_themes_types.ThemeFSEventPayload.html index f112034a2cd..f81d88e0d3f 100644 --- a/docs/api/cli-kit/types/node_themes_types.ThemeFSEventPayload.html +++ b/docs/api/cli-kit/types/node_themes_types.ThemeFSEventPayload.html @@ -1 +1 @@ -ThemeFSEventPayload | @shopify/cli-kit
      ThemeFSEventPayload<T>: (ThemeFSEvent & {
          type: T;
      })["payload"]

      Type Parameters

      \ No newline at end of file +ThemeFSEventPayload | @shopify/cli-kit
      ThemeFSEventPayload<T>: (ThemeFSEvent & {
          type: T;
      })["payload"]

      Type Parameters

      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_themes_utils.Role.html b/docs/api/cli-kit/types/node_themes_utils.Role.html index 5463729c2e9..964b55fcc8f 100644 --- a/docs/api/cli-kit/types/node_themes_utils.Role.html +++ b/docs/api/cli-kit/types/node_themes_utils.Role.html @@ -1 +1 @@ -Role | @shopify/cli-kit
      \ No newline at end of file +Role | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_toml.JsonMapType.html b/docs/api/cli-kit/types/node_toml.JsonMapType.html index bd111194c6b..e37c269d0c9 100644 --- a/docs/api/cli-kit/types/node_toml.JsonMapType.html +++ b/docs/api/cli-kit/types/node_toml.JsonMapType.html @@ -1 +1 @@ -JsonMapType | @shopify/cli-kit
      JsonMapType: JsonMap
      \ No newline at end of file +JsonMapType | @shopify/cli-kit
      JsonMapType: JsonMap
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_ui.AlertCustomSection.html b/docs/api/cli-kit/types/node_ui.AlertCustomSection.html index 0eddb1b71ec..ddc54c173cc 100644 --- a/docs/api/cli-kit/types/node_ui.AlertCustomSection.html +++ b/docs/api/cli-kit/types/node_ui.AlertCustomSection.html @@ -1 +1 @@ -AlertCustomSection | @shopify/cli-kit

      Type alias AlertCustomSection

      AlertCustomSection: CustomSection
      \ No newline at end of file +AlertCustomSection | @shopify/cli-kit

      Type alias AlertCustomSection

      AlertCustomSection: CustomSection
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_ui.InfoMessage.html b/docs/api/cli-kit/types/node_ui.InfoMessage.html index 6a8c68aab99..9c792831ea8 100644 --- a/docs/api/cli-kit/types/node_ui.InfoMessage.html +++ b/docs/api/cli-kit/types/node_ui.InfoMessage.html @@ -1 +1 @@ -InfoMessage | @shopify/cli-kit
      InfoMessage: InfoMessageProps["message"]
      \ No newline at end of file +InfoMessage | @shopify/cli-kit
      InfoMessage: InfoMessageProps["message"]
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_ui.InlineToken.html b/docs/api/cli-kit/types/node_ui.InlineToken.html index 69491b020d8..48acaf8e70e 100644 --- a/docs/api/cli-kit/types/node_ui.InlineToken.html +++ b/docs/api/cli-kit/types/node_ui.InlineToken.html @@ -1 +1 @@ -InlineToken | @shopify/cli-kit
      \ No newline at end of file +InlineToken | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_ui.Key.html b/docs/api/cli-kit/types/node_ui.Key.html index 241202e1c5b..f172d5ec525 100644 --- a/docs/api/cli-kit/types/node_ui.Key.html +++ b/docs/api/cli-kit/types/node_ui.Key.html @@ -1 +1 @@ -Key | @shopify/cli-kit
      \ No newline at end of file +Key | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_ui.RenderAlertOptions.html b/docs/api/cli-kit/types/node_ui.RenderAlertOptions.html index 6d24054a9b9..023b19c263c 100644 --- a/docs/api/cli-kit/types/node_ui.RenderAlertOptions.html +++ b/docs/api/cli-kit/types/node_ui.RenderAlertOptions.html @@ -1 +1 @@ -RenderAlertOptions | @shopify/cli-kit

      Type alias RenderAlertOptions

      RenderAlertOptions: Omit<AlertOptions, "type">
      \ No newline at end of file +RenderAlertOptions | @shopify/cli-kit

      Type alias RenderAlertOptions

      RenderAlertOptions: Omit<AlertOptions, "type">
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_ui.TableColumn.html b/docs/api/cli-kit/types/node_ui.TableColumn.html index bdd43ebe13b..f217a03937e 100644 --- a/docs/api/cli-kit/types/node_ui.TableColumn.html +++ b/docs/api/cli-kit/types/node_ui.TableColumn.html @@ -1 +1 @@ -TableColumn | @shopify/cli-kit

      Type alias TableColumn<T>

      TableColumn<T>: {
          [column in keyof T]: {
              color?: ForegroundColor | "dim";
              header?: string;
          }
      }

      Type Parameters

      • T
      \ No newline at end of file +TableColumn | @shopify/cli-kit

      Type alias TableColumn<T>

      TableColumn<T>: {
          [column in keyof T]: {
              color?: ForegroundColor | "dim";
              header?: string;
          }
      }

      Type Parameters

      • T
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_ui.Token.html b/docs/api/cli-kit/types/node_ui.Token.html index 84bbac25e3e..2d703f71c33 100644 --- a/docs/api/cli-kit/types/node_ui.Token.html +++ b/docs/api/cli-kit/types/node_ui.Token.html @@ -1 +1 @@ -Token | @shopify/cli-kit
      Token: string | CommandToken | LinkToken | CharToken | UserInputToken | SubduedToken | FilePathToken | ListToken | BoldToken | InfoToken | WarnToken | ErrorToken
      \ No newline at end of file +Token | @shopify/cli-kit
      Token: string | CommandToken | LinkToken | CharToken | UserInputToken | SubduedToken | FilePathToken | ListToken | BoldToken | InfoToken | WarnToken | ErrorToken
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_ui.TokenItem.html b/docs/api/cli-kit/types/node_ui.TokenItem.html index 5528a8e1a8f..56998a817a4 100644 --- a/docs/api/cli-kit/types/node_ui.TokenItem.html +++ b/docs/api/cli-kit/types/node_ui.TokenItem.html @@ -1 +1 @@ -TokenItem | @shopify/cli-kit

      Type alias TokenItem<T>

      TokenItem<T>: T | T[]

      Type Parameters

      \ No newline at end of file +TokenItem | @shopify/cli-kit

      Type alias TokenItem<T>

      TokenItem<T>: T | T[]

      Type Parameters

      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_vendor_otel_js_service_DefaultOtelService_DefaultMeterProvider.Environment.html b/docs/api/cli-kit/types/node_vendor_otel_js_service_DefaultOtelService_DefaultMeterProvider.Environment.html index c6b85f90ad7..a1775de11ff 100644 --- a/docs/api/cli-kit/types/node_vendor_otel_js_service_DefaultOtelService_DefaultMeterProvider.Environment.html +++ b/docs/api/cli-kit/types/node_vendor_otel_js_service_DefaultOtelService_DefaultMeterProvider.Environment.html @@ -1 +1 @@ -Environment | @shopify/cli-kit
      \ No newline at end of file +Environment | @shopify/cli-kit
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_vendor_otel_js_service_types.CustomMetricLabels.html b/docs/api/cli-kit/types/node_vendor_otel_js_service_types.CustomMetricLabels.html index b6199c10fbc..0ae9465420f 100644 --- a/docs/api/cli-kit/types/node_vendor_otel_js_service_types.CustomMetricLabels.html +++ b/docs/api/cli-kit/types/node_vendor_otel_js_service_types.CustomMetricLabels.html @@ -1 +1 @@ -CustomMetricLabels | @shopify/cli-kit

      Type alias CustomMetricLabels<TLabels, TKeys>

      CustomMetricLabels<TLabels, TKeys>: {
          [P in TKeys]: TLabels[P] extends MetricAttributes
              ? TLabels[P]
              : never
      }

      Type Parameters

      • TLabels extends {
            [key in TKeys]: MetricAttributes
        }
      • TKeys extends string = keyof TLabels & string
      \ No newline at end of file +CustomMetricLabels | @shopify/cli-kit

      Type alias CustomMetricLabels<TLabels, TKeys>

      CustomMetricLabels<TLabels, TKeys>: {
          [P in TKeys]: TLabels[P] extends MetricAttributes
              ? TLabels[P]
              : never
      }

      Type Parameters

      • TLabels extends {
            [key in TKeys]: MetricAttributes
        }
      • TKeys extends string = keyof TLabels & string
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_vendor_otel_js_service_types.MetricDescriptor.html b/docs/api/cli-kit/types/node_vendor_otel_js_service_types.MetricDescriptor.html index b76c7905938..b6a8a28689d 100644 --- a/docs/api/cli-kit/types/node_vendor_otel_js_service_types.MetricDescriptor.html +++ b/docs/api/cli-kit/types/node_vendor_otel_js_service_types.MetricDescriptor.html @@ -1 +1 @@ -MetricDescriptor | @shopify/cli-kit
      MetricDescriptor: MetricOptions & ({
          boundaries: number[];
          type: Histogram;
      } | {
          type: Counter | UpDownCounter;
      })
      \ No newline at end of file +MetricDescriptor | @shopify/cli-kit
      MetricDescriptor: MetricOptions & ({
          boundaries: number[];
          type: Histogram;
      } | {
          type: Counter | UpDownCounter;
      })
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_vendor_otel_js_service_types.MetricInstrument.html b/docs/api/cli-kit/types/node_vendor_otel_js_service_types.MetricInstrument.html index e6d70bf196b..55a19b8a0ef 100644 --- a/docs/api/cli-kit/types/node_vendor_otel_js_service_types.MetricInstrument.html +++ b/docs/api/cli-kit/types/node_vendor_otel_js_service_types.MetricInstrument.html @@ -1 +1 @@ -MetricInstrument | @shopify/cli-kit
      MetricInstrument: Histogram | Counter | UpDownCounter
      \ No newline at end of file +MetricInstrument | @shopify/cli-kit
      MetricInstrument: Histogram | Counter | UpDownCounter
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_vendor_otel_js_service_types.MetricRecording.html b/docs/api/cli-kit/types/node_vendor_otel_js_service_types.MetricRecording.html index 210d865cfdf..244fd453bec 100644 --- a/docs/api/cli-kit/types/node_vendor_otel_js_service_types.MetricRecording.html +++ b/docs/api/cli-kit/types/node_vendor_otel_js_service_types.MetricRecording.html @@ -1 +1 @@ -MetricRecording | @shopify/cli-kit
      MetricRecording<TAttributes>: [value: number, labels?: TAttributes]

      Type Parameters

      • TAttributes extends MetricAttributes = any
      \ No newline at end of file +MetricRecording | @shopify/cli-kit
      MetricRecording<TAttributes>: [value: number, labels?: TAttributes]

      Type Parameters

      • TAttributes extends MetricAttributes = any
      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_vendor_otel_js_service_types.OnRecordCallback.html b/docs/api/cli-kit/types/node_vendor_otel_js_service_types.OnRecordCallback.html index 252890ff781..c662e6ebe6b 100644 --- a/docs/api/cli-kit/types/node_vendor_otel_js_service_types.OnRecordCallback.html +++ b/docs/api/cli-kit/types/node_vendor_otel_js_service_types.OnRecordCallback.html @@ -1 +1 @@ -OnRecordCallback | @shopify/cli-kit
      OnRecordCallback<TAttributes>: ((metricName, ...args) => MetricRecording<TAttributes> | void)

      Type Parameters

      • TAttributes extends MetricAttributes = any

      Type declaration

      \ No newline at end of file +OnRecordCallback | @shopify/cli-kit
      OnRecordCallback<TAttributes>: ((metricName, ...args) => MetricRecording<TAttributes> | void)

      Type Parameters

      • TAttributes extends MetricAttributes = any

      Type declaration

      \ No newline at end of file diff --git a/docs/api/cli-kit/types/node_vendor_otel_js_service_types.RecordMetricFunction.html b/docs/api/cli-kit/types/node_vendor_otel_js_service_types.RecordMetricFunction.html index 6105ab61ceb..84514b7c073 100644 --- a/docs/api/cli-kit/types/node_vendor_otel_js_service_types.RecordMetricFunction.html +++ b/docs/api/cli-kit/types/node_vendor_otel_js_service_types.RecordMetricFunction.html @@ -1 +1 @@ -RecordMetricFunction | @shopify/cli-kit
      RecordMetricFunction<TAttributes>: ((...args) => void)

      Type Parameters

      • TAttributes extends MetricAttributes = any

      Type declaration

      \ No newline at end of file +RecordMetricFunction | @shopify/cli-kit
      RecordMetricFunction<TAttributes>: ((...args) => void)

      Type Parameters

      • TAttributes extends MetricAttributes = any

      Type declaration

      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/common_version.CLI_KIT_VERSION.html b/docs/api/cli-kit/variables/common_version.CLI_KIT_VERSION.html index ad404b4f780..2bff06f7d82 100644 --- a/docs/api/cli-kit/variables/common_version.CLI_KIT_VERSION.html +++ b/docs/api/cli-kit/variables/common_version.CLI_KIT_VERSION.html @@ -1 +1 @@ -CLI_KIT_VERSION | @shopify/cli-kit

      Variable CLI_KIT_VERSIONConst

      CLI_KIT_VERSION: "3.70.0" = '3.70.0'
      \ No newline at end of file +CLI_KIT_VERSION | @shopify/cli-kit

      Variable CLI_KIT_VERSIONConst

      CLI_KIT_VERSION: "3.72.0" = '3.72.0'
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_cli.globalFlags.html b/docs/api/cli-kit/variables/node_cli.globalFlags.html index 00afea867b1..6926826e6a0 100644 --- a/docs/api/cli-kit/variables/node_cli.globalFlags.html +++ b/docs/api/cli-kit/variables/node_cli.globalFlags.html @@ -1,3 +1,3 @@ globalFlags | @shopify/cli-kit

      Variable globalFlagsConst

      globalFlags: {
          no-color: BooleanFlag<boolean>;
          verbose: BooleanFlag<boolean>;
      } = ...

      An object that contains the flags that are shared across all the commands.

      -

      Type declaration

      • no-color: BooleanFlag<boolean>
      • verbose: BooleanFlag<boolean>
      \ No newline at end of file +

      Type declaration

      • no-color: BooleanFlag<boolean>
      • verbose: BooleanFlag<boolean>
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_cli.jsonFlag.html b/docs/api/cli-kit/variables/node_cli.jsonFlag.html new file mode 100644 index 00000000000..34ed396d617 --- /dev/null +++ b/docs/api/cli-kit/variables/node_cli.jsonFlag.html @@ -0,0 +1 @@ +jsonFlag | @shopify/cli-kit

      Variable jsonFlagConst

      jsonFlag: {
          json: BooleanFlag<boolean>;
      } = ...

      Type declaration

      • json: BooleanFlag<boolean>
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_context_fqdn.CouldntObtainIdentitySpinFQDNError.html b/docs/api/cli-kit/variables/node_context_fqdn.CouldntObtainIdentitySpinFQDNError.html index bd3be5f0c78..92730117cd2 100644 --- a/docs/api/cli-kit/variables/node_context_fqdn.CouldntObtainIdentitySpinFQDNError.html +++ b/docs/api/cli-kit/variables/node_context_fqdn.CouldntObtainIdentitySpinFQDNError.html @@ -1 +1 @@ -CouldntObtainIdentitySpinFQDNError | @shopify/cli-kit

      Variable CouldntObtainIdentitySpinFQDNErrorConst

      CouldntObtainIdentitySpinFQDNError: AbortError = ...
      \ No newline at end of file +CouldntObtainIdentitySpinFQDNError | @shopify/cli-kit

      Variable CouldntObtainIdentitySpinFQDNErrorConst

      CouldntObtainIdentitySpinFQDNError: AbortError = ...
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_context_fqdn.CouldntObtainPartnersSpinFQDNError.html b/docs/api/cli-kit/variables/node_context_fqdn.CouldntObtainPartnersSpinFQDNError.html index bf3d90b95c1..0813e940608 100644 --- a/docs/api/cli-kit/variables/node_context_fqdn.CouldntObtainPartnersSpinFQDNError.html +++ b/docs/api/cli-kit/variables/node_context_fqdn.CouldntObtainPartnersSpinFQDNError.html @@ -1 +1 @@ -CouldntObtainPartnersSpinFQDNError | @shopify/cli-kit

      Variable CouldntObtainPartnersSpinFQDNErrorConst

      CouldntObtainPartnersSpinFQDNError: AbortError = ...
      \ No newline at end of file +CouldntObtainPartnersSpinFQDNError | @shopify/cli-kit

      Variable CouldntObtainPartnersSpinFQDNErrorConst

      CouldntObtainPartnersSpinFQDNError: AbortError = ...
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_context_fqdn.CouldntObtainShopifySpinFQDNError.html b/docs/api/cli-kit/variables/node_context_fqdn.CouldntObtainShopifySpinFQDNError.html index 386720764b7..5aeb1f6cdc9 100644 --- a/docs/api/cli-kit/variables/node_context_fqdn.CouldntObtainShopifySpinFQDNError.html +++ b/docs/api/cli-kit/variables/node_context_fqdn.CouldntObtainShopifySpinFQDNError.html @@ -1 +1 @@ -CouldntObtainShopifySpinFQDNError | @shopify/cli-kit

      Variable CouldntObtainShopifySpinFQDNErrorConst

      CouldntObtainShopifySpinFQDNError: AbortError = ...
      \ No newline at end of file +CouldntObtainShopifySpinFQDNError | @shopify/cli-kit

      Variable CouldntObtainShopifySpinFQDNErrorConst

      CouldntObtainShopifySpinFQDNError: AbortError = ...
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_context_fqdn.NotProvidedStoreFQDNError.html b/docs/api/cli-kit/variables/node_context_fqdn.NotProvidedStoreFQDNError.html index 4cb22735448..b5a5de193a8 100644 --- a/docs/api/cli-kit/variables/node_context_fqdn.NotProvidedStoreFQDNError.html +++ b/docs/api/cli-kit/variables/node_context_fqdn.NotProvidedStoreFQDNError.html @@ -1 +1 @@ -NotProvidedStoreFQDNError | @shopify/cli-kit

      Variable NotProvidedStoreFQDNErrorConst

      NotProvidedStoreFQDNError: AbortError = ...
      \ No newline at end of file +NotProvidedStoreFQDNError | @shopify/cli-kit

      Variable NotProvidedStoreFQDNErrorConst

      NotProvidedStoreFQDNError: AbortError = ...
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_context_spin.spinVariables.html b/docs/api/cli-kit/variables/node_context_spin.spinVariables.html index 13074ae7e7e..336c1c3f8c6 100644 --- a/docs/api/cli-kit/variables/node_context_spin.spinVariables.html +++ b/docs/api/cli-kit/variables/node_context_spin.spinVariables.html @@ -1 +1 @@ -spinVariables | @shopify/cli-kit
      spinVariables: {
          manualCliSpinPortName: string;
          partnersSpinService: string;
      } = ...

      Type declaration

      • manualCliSpinPortName: string
      • partnersSpinService: string
      \ No newline at end of file +spinVariables | @shopify/cli-kit
      spinVariables: {
          manualCliSpinPortName: string;
          partnersSpinService: string;
      } = ...

      Type declaration

      • manualCliSpinPortName: string
      • partnersSpinService: string
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_monorail.MONORAIL_COMMAND_TOPIC.html b/docs/api/cli-kit/variables/node_monorail.MONORAIL_COMMAND_TOPIC.html index 42b2bedfb03..9733d502de5 100644 --- a/docs/api/cli-kit/variables/node_monorail.MONORAIL_COMMAND_TOPIC.html +++ b/docs/api/cli-kit/variables/node_monorail.MONORAIL_COMMAND_TOPIC.html @@ -1 +1 @@ -MONORAIL_COMMAND_TOPIC | @shopify/cli-kit

      Variable MONORAIL_COMMAND_TOPICConst

      MONORAIL_COMMAND_TOPIC: "app_cli3_command/1.15" = 'app_cli3_command/1.15'
      \ No newline at end of file +MONORAIL_COMMAND_TOPIC | @shopify/cli-kit

      Variable MONORAIL_COMMAND_TOPICConst

      MONORAIL_COMMAND_TOPIC: "app_cli3_command/1.15" = 'app_cli3_command/1.15'
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_node_package_manager.bunLockfile.html b/docs/api/cli-kit/variables/node_node_package_manager.bunLockfile.html index 3c5864955c6..5c86e167aae 100644 --- a/docs/api/cli-kit/variables/node_node_package_manager.bunLockfile.html +++ b/docs/api/cli-kit/variables/node_node_package_manager.bunLockfile.html @@ -1,2 +1,2 @@ bunLockfile | @shopify/cli-kit
      bunLockfile: "bun.lockb" = 'bun.lockb'

      The name of the bun lock file

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_node_package_manager.lockfiles.html b/docs/api/cli-kit/variables/node_node_package_manager.lockfiles.html index db13d6359fc..44a81ef666d 100644 --- a/docs/api/cli-kit/variables/node_node_package_manager.lockfiles.html +++ b/docs/api/cli-kit/variables/node_node_package_manager.lockfiles.html @@ -1,2 +1,2 @@ lockfiles | @shopify/cli-kit
      lockfiles: Lockfile[] = ...

      An array containing the lockfiles from all the package managers

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_node_package_manager.npmLockfile.html b/docs/api/cli-kit/variables/node_node_package_manager.npmLockfile.html index 3f4a347e7a8..74aeb7a28ab 100644 --- a/docs/api/cli-kit/variables/node_node_package_manager.npmLockfile.html +++ b/docs/api/cli-kit/variables/node_node_package_manager.npmLockfile.html @@ -1,2 +1,2 @@ npmLockfile | @shopify/cli-kit
      npmLockfile: "package-lock.json" = 'package-lock.json'

      The name of the npm lock file

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_node_package_manager.packageManager-1.html b/docs/api/cli-kit/variables/node_node_package_manager.packageManager-1.html index f73bd329e09..9b53334e600 100644 --- a/docs/api/cli-kit/variables/node_node_package_manager.packageManager-1.html +++ b/docs/api/cli-kit/variables/node_node_package_manager.packageManager-1.html @@ -1,2 +1,2 @@ packageManager | @shopify/cli-kit
      packageManager: readonly ["yarn", "npm", "pnpm", "bun", "unknown"] = ...

      A union that represents the package managers available.

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_node_package_manager.pnpmLockfile.html b/docs/api/cli-kit/variables/node_node_package_manager.pnpmLockfile.html index d6ba289751a..a20cb630052 100644 --- a/docs/api/cli-kit/variables/node_node_package_manager.pnpmLockfile.html +++ b/docs/api/cli-kit/variables/node_node_package_manager.pnpmLockfile.html @@ -1,2 +1,2 @@ pnpmLockfile | @shopify/cli-kit
      pnpmLockfile: "pnpm-lock.yaml" = 'pnpm-lock.yaml'

      The name of the pnpm lock file

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_node_package_manager.pnpmWorkspaceFile.html b/docs/api/cli-kit/variables/node_node_package_manager.pnpmWorkspaceFile.html index 59c7d940d22..493e6e41f23 100644 --- a/docs/api/cli-kit/variables/node_node_package_manager.pnpmWorkspaceFile.html +++ b/docs/api/cli-kit/variables/node_node_package_manager.pnpmWorkspaceFile.html @@ -1,2 +1,2 @@ pnpmWorkspaceFile | @shopify/cli-kit
      pnpmWorkspaceFile: "pnpm-workspace.yaml" = 'pnpm-workspace.yaml'

      The name of the pnpm workspace file

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_node_package_manager.yarnLockfile.html b/docs/api/cli-kit/variables/node_node_package_manager.yarnLockfile.html index ce79077ed88..1a04d192ce2 100644 --- a/docs/api/cli-kit/variables/node_node_package_manager.yarnLockfile.html +++ b/docs/api/cli-kit/variables/node_node_package_manager.yarnLockfile.html @@ -1,2 +1,2 @@ yarnLockfile | @shopify/cli-kit
      yarnLockfile: "yarn.lock" = 'yarn.lock'

      The name of the Yarn lock file

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_output.collectedLogs.html b/docs/api/cli-kit/variables/node_output.collectedLogs.html index 06dd96eaf0e..2f6ca3b6221 100644 --- a/docs/api/cli-kit/variables/node_output.collectedLogs.html +++ b/docs/api/cli-kit/variables/node_output.collectedLogs.html @@ -1 +1 @@ -collectedLogs | @shopify/cli-kit
      collectedLogs: {
          [key: string]: string[];
      } = {}

      Type declaration

      • [key: string]: string[]
      \ No newline at end of file +collectedLogs | @shopify/cli-kit
      collectedLogs: {
          [key: string]: string[];
      } = {}

      Type declaration

      • [key: string]: string[]
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_output.outputToken.html b/docs/api/cli-kit/variables/node_output.outputToken.html index f833cc4fd9a..dc686eacbe4 100644 --- a/docs/api/cli-kit/variables/node_output.outputToken.html +++ b/docs/api/cli-kit/variables/node_output.outputToken.html @@ -1 +1 @@ -outputToken | @shopify/cli-kit

      Variable outputTokenConst

      outputToken: {
          cyan(value): ColorContentToken;
          errorText(value): ErrorContentToken;
          failIcon(): ErrorContentToken;
          genericShellCommand(value): CommandContentToken;
          gray(value): ColorContentToken;
          green(value): ColorContentToken;
          heading(value): HeadingContentToken;
          italic(value): ItalicContentToken;
          json(value): JsonContentToken;
          linesDiff(value): LinesDiffContentToken;
          link(value, link?, fallback?): LinkContentToken;
          magenta(value): ColorContentToken;
          packagejsonScript(packageManager, scriptName, ...scriptArgs): CommandContentToken;
          path(value): PathContentToken;
          raw(value): RawContentToken;
          subheading(value): SubHeadingContentToken;
          successIcon(): ColorContentToken;
          yellow(value): ColorContentToken;
      } = ...

      Type declaration

      \ No newline at end of file +outputToken | @shopify/cli-kit

      Variable outputTokenConst

      outputToken: {
          cyan(value): ColorContentToken;
          errorText(value): ErrorContentToken;
          failIcon(): ErrorContentToken;
          genericShellCommand(value): CommandContentToken;
          gray(value): ColorContentToken;
          green(value): ColorContentToken;
          heading(value): HeadingContentToken;
          italic(value): ItalicContentToken;
          json(value): JsonContentToken;
          linesDiff(value): LinesDiffContentToken;
          link(value, link?, fallback?): LinkContentToken;
          magenta(value): ColorContentToken;
          packagejsonScript(packageManager, scriptName, ...scriptArgs): CommandContentToken;
          path(value): PathContentToken;
          raw(value): RawContentToken;
          subheading(value): SubHeadingContentToken;
          successIcon(): ColorContentToken;
          yellow(value): ColorContentToken;
      } = ...

      Type declaration

      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_themes_utils.DEVELOPMENT_THEME_ROLE.html b/docs/api/cli-kit/variables/node_themes_utils.DEVELOPMENT_THEME_ROLE.html index c6f2576b4f3..02395fe725d 100644 --- a/docs/api/cli-kit/variables/node_themes_utils.DEVELOPMENT_THEME_ROLE.html +++ b/docs/api/cli-kit/variables/node_themes_utils.DEVELOPMENT_THEME_ROLE.html @@ -1 +1 @@ -DEVELOPMENT_THEME_ROLE | @shopify/cli-kit

      Variable DEVELOPMENT_THEME_ROLEConst

      DEVELOPMENT_THEME_ROLE: "development" = 'development'
      \ No newline at end of file +DEVELOPMENT_THEME_ROLE | @shopify/cli-kit

      Variable DEVELOPMENT_THEME_ROLEConst

      DEVELOPMENT_THEME_ROLE: "development" = 'development'
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_themes_utils.LIVE_THEME_ROLE.html b/docs/api/cli-kit/variables/node_themes_utils.LIVE_THEME_ROLE.html index 466038f0670..4f569f01478 100644 --- a/docs/api/cli-kit/variables/node_themes_utils.LIVE_THEME_ROLE.html +++ b/docs/api/cli-kit/variables/node_themes_utils.LIVE_THEME_ROLE.html @@ -1 +1 @@ -LIVE_THEME_ROLE | @shopify/cli-kit
      LIVE_THEME_ROLE: "live" = 'live'
      \ No newline at end of file +LIVE_THEME_ROLE | @shopify/cli-kit
      LIVE_THEME_ROLE: "live" = 'live'
      \ No newline at end of file diff --git a/docs/api/cli-kit/variables/node_themes_utils.UNPUBLISHED_THEME_ROLE.html b/docs/api/cli-kit/variables/node_themes_utils.UNPUBLISHED_THEME_ROLE.html index ff713671d57..51b2e0aa215 100644 --- a/docs/api/cli-kit/variables/node_themes_utils.UNPUBLISHED_THEME_ROLE.html +++ b/docs/api/cli-kit/variables/node_themes_utils.UNPUBLISHED_THEME_ROLE.html @@ -1 +1 @@ -UNPUBLISHED_THEME_ROLE | @shopify/cli-kit

      Variable UNPUBLISHED_THEME_ROLEConst

      UNPUBLISHED_THEME_ROLE: "unpublished" = 'unpublished'
      \ No newline at end of file +UNPUBLISHED_THEME_ROLE | @shopify/cli-kit

      Variable UNPUBLISHED_THEME_ROLEConst

      UNPUBLISHED_THEME_ROLE: "unpublished" = 'unpublished'
      \ No newline at end of file diff --git a/graphql.config.ts b/graphql.config.ts index b1a5c631f2d..c3b9243b3ec 100644 --- a/graphql.config.ts +++ b/graphql.config.ts @@ -1,7 +1,10 @@ function projectFactory(name: string, schemaName: string, project: string = 'app') { return { schema: `./packages/${project}/src/cli/api/graphql/${name}/${schemaName}`, - documents: [`./packages/${project}/src/cli/api/graphql/${name}/queries/**/*.graphql`,`./packages/${project}/src/cli/api/graphql/${name}/mutations/**/*.graphql`], + documents: [ + `./packages/${project}/src/cli/api/graphql/${name}/queries/**/*.graphql`, + `./packages/${project}/src/cli/api/graphql/${name}/mutations/**/*.graphql`, + ], extensions: { codegen: { generates: { @@ -78,5 +81,7 @@ export default { appDev: projectFactory('app-dev', 'app_dev_schema.graphql'), appManagement: projectFactory('app-management', 'app_management_schema.graphql'), admin: projectFactory('admin', 'admin_schema.graphql', 'cli-kit'), + webhooks: projectFactory('webhooks', 'webhooks_schema.graphql'), + functions: projectFactory('functions', 'functions_cli_schema.graphql', 'app'), }, } diff --git a/nx.json b/nx.json index c824586b865..ec761c37fc1 100644 --- a/nx.json +++ b/nx.json @@ -54,6 +54,7 @@ "build:types", "graphql-codegen:generate:business-platform", "graphql-codegen:generate:partners", + "graphql-codegen:generate:webhooks", "graphql-codegen:postfix", "graphql-codegen:formatting" ], diff --git a/package.json b/package.json index 538d421af1b..a8781c388a8 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "bugsnag-build-reporter": "^2.0.0", "commander": "^9.4.0", "cross-env": "^7.0.3", - "esbuild": "0.19.8", + "esbuild": "0.24.0", "eslint": "^8.48.0", "execa": "^7.2.0", "fast-glob": "^3.3.1", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 16bff023378..484c76396b6 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,86 @@ # @shopify/app +## 3.72.0 + +### Minor Changes + +- 178c17e820: Bump minor version + +### Patch Changes + +- @shopify/cli-kit@3.72.0 +- @shopify/theme@3.72.0 +- @shopify/plugin-cloudflare@3.72.0 + +## 3.71.5 + +### Patch Changes + +- 44844a7752: Update function-runner to v6.4.0 +- 78cbc67c26: Download Javy plugin ahead of time with Javy CLI +- Updated dependencies [94a7d4ce4f] + - @shopify/cli-kit@3.71.5 + - @shopify/plugin-cloudflare@3.71.5 + - @shopify/theme@3.71.5 + +## 3.71.4 + +### Patch Changes + +- Updated dependencies [94953a671e] + - @shopify/cli-kit@3.71.4 + - @shopify/plugin-cloudflare@3.71.4 + - @shopify/theme@3.71.4 + +## 3.71.3 + +### Patch Changes + +- d5b0856f78: Increase extension localization file size limit +- 73eb727757: Fix function drafts not working during dev + - @shopify/cli-kit@3.71.3 + - @shopify/theme@3.71.3 + - @shopify/plugin-cloudflare@3.71.3 + +## 3.71.2 + +### Patch Changes + +- Updated dependencies [a395820e7b] + - @shopify/cli-kit@3.71.2 + - @shopify/plugin-cloudflare@3.71.2 + - @shopify/theme@3.71.2 + +## 3.71.1 + +### Patch Changes + +- 4b93d76290: Fix error when downloading Javy plugin in parallel + - @shopify/cli-kit@3.71.1 + - @shopify/theme@3.71.1 + - @shopify/plugin-cloudflare@3.71.1 + +## 3.71.0 + +### Patch Changes + +- 1c9d74988e: Update Javy invocation to use Javy plugin +- 08f3ddba1f: Update Javy to 3.2.0 and function-runner to 6.3.0 +- 93d65a6c38: Remove PHP template from app creation options +- 33f713e06e: Bump @shopify/theme-check-node & @shopify/theme-language-server +- Updated dependencies [5107f4e805] +- Updated dependencies [5fd19d2920] +- Updated dependencies [ff994c34d3] +- Updated dependencies [1e267a2e04] +- Updated dependencies [7017b9e31c] +- Updated dependencies [5531731c11] +- Updated dependencies [057e2c6189] +- Updated dependencies [9548a34471] +- Updated dependencies [33f713e06e] + - @shopify/theme@3.71.0 + - @shopify/cli-kit@3.71.0 + - @shopify/plugin-cloudflare@3.71.0 + ## 3.70.0 ### Minor Changes diff --git a/packages/app/package.json b/packages/app/package.json index e7c24740eed..7c7c7347f47 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@shopify/app", - "version": "3.70.0", + "version": "3.72.0", "description": "Utilities for loading, building, and publishing apps.", "homepage": "https://github.com/shopify/cli#readme", "private": true, @@ -51,23 +51,23 @@ "@graphql-typed-document-node/core": "3.2.0", "@luckycatfactory/esbuild-graphql-loader": "3.8.1", "@oclif/core": "3.26.5", - "@shopify/cli-kit": "3.70.0", + "@shopify/cli-kit": "3.72.0", "@shopify/function-runner": "4.1.1", - "@shopify/plugin-cloudflare": "3.70.0", + "@shopify/plugin-cloudflare": "3.72.0", "@shopify/polaris": "12.10.0", "@shopify/polaris-icons": "8.0.0", - "@shopify/theme": "3.70.0", - "@shopify/theme-check-node": "2.9.2", + "@shopify/theme": "3.72.0", + "@shopify/theme-check-node": "3.4.0", "body-parser": "1.20.2", "camelcase-keys": "9.1.3", "chokidar": "3.5.3", "diff": "5.1.0", - "esbuild": "0.19.8", + "esbuild": "0.24.0", "express": "4.19.2", "graphql-request": "5.2.0", "h3": "0.7.21", "http-proxy": "1.18.1", - "micromatch": "4.0.8", + "ignore": "6.0.2", "proper-lockfile": "4.1.2", "react": "^18.2.0", "react-dom": "18.2.0", @@ -78,7 +78,6 @@ "@types/diff": "^5.0.3", "@types/express": "^4.17.17", "@types/http-proxy": "^1.17.11", - "@types/micromatch": "^4.0.8", "@types/node": "18.19.3", "@types/proper-lockfile": "4.1.4", "@types/react": "18.2.0", diff --git a/packages/app/project.json b/packages/app/project.json index 9bf718c9f18..429b55fb968 100644 --- a/packages/app/project.json +++ b/packages/app/project.json @@ -80,7 +80,9 @@ "{projectRoot}/src/cli/api/graphql/business-platform-destinations/generated/**/*.ts", "{projectRoot}/src/cli/api/graphql/business-platform-organizations/generated/**/*.ts", "{projectRoot}/src/cli/api/graphql/app-dev/generated/**/*.ts", - "{projectRoot}/src/cli/api/graphql/app-management/generated/**/*.ts" + "{projectRoot}/src/cli/api/graphql/app-management/generated/**/*.ts", + "{projectRoot}/src/cli/api/graphql/webhooks/generated/**/*.ts", + "{projectRoot}/src/cli/api/graphql/functions/generated/**/*.ts" ], "options": { "commands": [ @@ -88,7 +90,9 @@ "pnpm eslint 'src/cli/api/graphql/business-platform-destinations/generated/**/*.{ts,tsx}' --fix", "pnpm eslint 'src/cli/api/graphql/business-platform-organizations/generated/**/*.{ts,tsx}' --fix", "pnpm eslint 'src/cli/api/graphql/app-dev/generated/**/*.{ts,tsx}' --fix", - "pnpm eslint 'src/cli/api/graphql/app-management/generated/**/*.{ts,tsx}' --fix" + "pnpm eslint 'src/cli/api/graphql/app-management/generated/**/*.{ts,tsx}' --fix", + "pnpm eslint 'src/cli/api/graphql/webhooks/generated/**/*.{ts,tsx}' --fix", + "pnpm eslint 'src/cli/api/graphql/functions/generated/**/*.{ts,tsx}' --fix" ], "cwd": "packages/app" } @@ -137,6 +141,17 @@ "cwd": "{workspaceRoot}" } }, + "graphql-codegen:generate:webhooks": { + "executor": "nx:run-commands", + "inputs": ["{workspaceRoot}/graphql.config.ts", "{projectRoot}/src/cli/api/graphql/webhooks/**/*.graphql"], + "outputs": ["{projectRoot}/src/cli/api/graphql/webhooks/generated/**/*.ts"], + "options": { + "commands": [ + "pnpm exec graphql-codegen --project=webhooks" + ], + "cwd": "{workspaceRoot}" + } + }, "graphql-codegen:generate:app-management": { "executor": "nx:run-commands", "inputs": ["{workspaceRoot}/graphql.config.ts", "{projectRoot}/src/cli/api/graphql/app-management/**/*.graphql"], @@ -148,6 +163,17 @@ "cwd": "{workspaceRoot}" } }, + "graphql-codegen:generate:functions": { + "executor": "nx:run-commands", + "inputs": ["{workspaceRoot}/graphql.config.ts", "{projectRoot}/src/cli/api/graphql/functions/**/*.graphql"], + "outputs": ["{projectRoot}/src/cli/api/graphql/functions/generated/**/*.ts"], + "options": { + "commands": [ + "pnpm exec graphql-codegen --project=functions" + ], + "cwd": "{workspaceRoot}" + } + }, "graphql-codegen:postfix": { "executor": "nx:run-commands", "dependsOn": [ @@ -155,7 +181,9 @@ "graphql-codegen:generate:business-platform-destinations", "graphql-codegen:generate:business-platform-organizations", "graphql-codegen:generate:app-dev", - "graphql-codegen:generate:app-management" + "graphql-codegen:generate:app-management", + "graphql-codegen:generate:webhooks", + "graphql-codegen:generate:functions" ], "inputs": [{ "dependentTasksOutputFiles": "**/*.ts" }], "outputs": [ @@ -163,7 +191,9 @@ "{projectRoot}/src/cli/api/graphql/business-platform-destinations/generated/**/*.ts", "{projectRoot}/src/cli/api/graphql/business-platform-organizations/generated/**/*.ts", "{projectRoot}/src/cli/api/graphql/app-dev/generated/**/*.ts", - "{projectRoot}/src/cli/api/graphql/app-management/generated/**/*.ts" + "{projectRoot}/src/cli/api/graphql/app-management/generated/**/*.ts", + "{projectRoot}/src/cli/api/graphql/webhooks/generated/**/*.ts", + "{projectRoot}/src/cli/api/graphql/functions/generated/**/*.ts" ], "options": { "commands": [ @@ -171,7 +201,9 @@ "find ./packages/app/src/cli/api/graphql/business-platform-destinations/generated/ -type f -name '*.ts' -exec sh -c 'sed -i \"\" \"s|import \\* as Types from '\\''./types'\\'';|import \\* as Types from '\\''./types.js'\\'';|g; s|export const \\([A-Za-z0-9_]*\\)Document =|export const \\1 =|g\" \"$0\"' {} \\;", "find ./packages/app/src/cli/api/graphql/business-platform-organizations/generated/ -type f -name '*.ts' -exec sh -c 'sed -i \"\" \"s|import \\* as Types from '\\''./types'\\'';|import \\* as Types from '\\''./types.js'\\'';|g; s|export const \\([A-Za-z0-9_]*\\)Document =|export const \\1 =|g\" \"$0\"' {} \\;", "find ./packages/app/src/cli/api/graphql/app-dev/generated/ -type f -name '*.ts' -exec sh -c 'sed -i \"\" \"s|import \\* as Types from '\\''./types'\\'';|import \\* as Types from '\\''./types.js'\\'';|g; s|export const \\([A-Za-z0-9_]*\\)Document =|export const \\1 =|g\" \"$0\"' {} \\;", - "find ./packages/app/src/cli/api/graphql/app-management/generated/ -type f -name '*.ts' -exec sh -c 'sed -i \"\" \"s|import \\* as Types from '\\''./types'\\'';|import \\* as Types from '\\''./types.js'\\'';|g; s|export const \\([A-Za-z0-9_]*\\)Document =|export const \\1 =|g\" \"$0\"' {} \\;" + "find ./packages/app/src/cli/api/graphql/app-management/generated/ -type f -name '*.ts' -exec sh -c 'sed -i \"\" \"s|import \\* as Types from '\\''./types'\\'';|import \\* as Types from '\\''./types.js'\\'';|g; s|export const \\([A-Za-z0-9_]*\\)Document =|export const \\1 =|g\" \"$0\"' {} \\;", + "find ./packages/app/src/cli/api/graphql/webhooks/generated/ -type f -name '*.ts' -exec sh -c 'sed -i \"\" \"s|import \\* as Types from '\\''./types'\\'';|import \\* as Types from '\\''./types.js'\\'';|g; s|export const \\([A-Za-z0-9_]*\\)Document =|export const \\1 =|g\" \"$0\"' {} \\;", + "find ./packages/app/src/cli/api/graphql/functions/generated/ -type f -name '*.ts' -exec sh -c 'sed -i \"\" \"s|import \\* as Types from '\\''./types'\\'';|import \\* as Types from '\\''./types.js'\\'';|g; s|export const \\([A-Za-z0-9_]*\\)Document =|export const \\1 =|g\" \"$0\"' {} \\;" ], "cwd": "{workspaceRoot}" } diff --git a/packages/app/src/cli/api/graphql/app-management/generated/active-app-release-from-api-key.ts b/packages/app/src/cli/api/graphql/app-management/generated/active-app-release-from-api-key.ts new file mode 100644 index 00000000000..afacbe0f56c --- /dev/null +++ b/packages/app/src/cli/api/graphql/app-management/generated/active-app-release-from-api-key.ts @@ -0,0 +1,164 @@ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ +import * as Types from './types.js' +import {JsonMapType} from '@shopify/cli-kit/node/toml' + +import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core' + +export type ActiveAppReleaseFromApiKeyQueryVariables = Types.Exact<{ + apiKey: Types.Scalars['String']['input'] +}> + +export type ActiveAppReleaseFromApiKeyQuery = { + app: { + id: string + key: string + activeRoot: {clientCredentials: {secrets: {key: string}[]}} + activeRelease: { + id: string + version: { + name: string + appModules: { + uuid: string + userIdentifier: string + handle: string + config: JsonMapType + specification: {identifier: string; externalIdentifier: string; name: string} + }[] + } + } + } +} + +export const ActiveAppReleaseFromApiKey = { + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'query', + name: {kind: 'Name', value: 'ActiveAppReleaseFromApiKey'}, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'apiKey'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + alias: {kind: 'Name', value: 'app'}, + name: {kind: 'Name', value: 'appByKey'}, + arguments: [ + { + kind: 'Argument', + name: {kind: 'Name', value: 'key'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'apiKey'}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'FragmentSpread', name: {kind: 'Name', value: 'AppVersionInfo'}}, + {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, + ], + }, + }, + ], + }, + }, + { + kind: 'FragmentDefinition', + name: {kind: 'Name', value: 'ReleasedAppModule'}, + typeCondition: {kind: 'NamedType', name: {kind: 'Name', value: 'AppModule'}}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'uuid'}}, + {kind: 'Field', name: {kind: 'Name', value: 'userIdentifier'}}, + {kind: 'Field', name: {kind: 'Name', value: 'handle'}}, + {kind: 'Field', name: {kind: 'Name', value: 'config'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'specification'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'identifier'}}, + {kind: 'Field', name: {kind: 'Name', value: 'externalIdentifier'}}, + {kind: 'Field', name: {kind: 'Name', value: 'name'}}, + ], + }, + }, + ], + }, + }, + { + kind: 'FragmentDefinition', + name: {kind: 'Name', value: 'AppVersionInfo'}, + typeCondition: {kind: 'NamedType', name: {kind: 'Name', value: 'App'}}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'id'}}, + {kind: 'Field', name: {kind: 'Name', value: 'key'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'activeRoot'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'clientCredentials'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'secrets'}, + selectionSet: { + kind: 'SelectionSet', + selections: [{kind: 'Field', name: {kind: 'Name', value: 'key'}}], + }, + }, + ], + }, + }, + ], + }, + }, + { + kind: 'Field', + name: {kind: 'Name', value: 'activeRelease'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'id'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'version'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'name'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'appModules'}, + selectionSet: { + kind: 'SelectionSet', + selections: [{kind: 'FragmentSpread', name: {kind: 'Name', value: 'ReleasedAppModule'}}], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode diff --git a/packages/app/src/cli/api/graphql/app-management/generated/active-app-release.ts b/packages/app/src/cli/api/graphql/app-management/generated/active-app-release.ts index 3f6ed301e94..18ca4c2fd29 100644 --- a/packages/app/src/cli/api/graphql/app-management/generated/active-app-release.ts +++ b/packages/app/src/cli/api/graphql/app-management/generated/active-app-release.ts @@ -29,6 +29,25 @@ export type ActiveAppReleaseQuery = { } } +export type AppVersionInfoFragment = { + id: string + key: string + activeRoot: {clientCredentials: {secrets: {key: string}[]}} + activeRelease: { + id: string + version: { + name: string + appModules: { + uuid: string + userIdentifier: string + handle: string + config: JsonMapType + specification: {identifier: string; externalIdentifier: string; name: string} + }[] + } + } +} + export type ReleasedAppModuleFragment = { uuid: string userIdentifier: string @@ -68,102 +87,134 @@ export const ReleasedAppModuleFragmentDoc = { }, ], } as unknown as DocumentNode -export const ActiveAppRelease = { +export const AppVersionInfoFragmentDoc = { kind: 'Document', definitions: [ { - kind: 'OperationDefinition', - operation: 'query', - name: {kind: 'Name', value: 'activeAppRelease'}, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: {kind: 'Variable', name: {kind: 'Name', value: 'appId'}}, - type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'ID'}}}, - }, - ], + kind: 'FragmentDefinition', + name: {kind: 'Name', value: 'AppVersionInfo'}, + typeCondition: {kind: 'NamedType', name: {kind: 'Name', value: 'App'}}, selectionSet: { kind: 'SelectionSet', selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'id'}}, + {kind: 'Field', name: {kind: 'Name', value: 'key'}}, { kind: 'Field', - name: {kind: 'Name', value: 'app'}, - arguments: [ - { - kind: 'Argument', - name: {kind: 'Name', value: 'id'}, - value: {kind: 'Variable', name: {kind: 'Name', value: 'appId'}}, - }, - ], + name: {kind: 'Name', value: 'activeRoot'}, selectionSet: { kind: 'SelectionSet', selections: [ - {kind: 'Field', name: {kind: 'Name', value: 'id'}}, - {kind: 'Field', name: {kind: 'Name', value: 'key'}}, { kind: 'Field', - name: {kind: 'Name', value: 'activeRoot'}, + name: {kind: 'Name', value: 'clientCredentials'}, selectionSet: { kind: 'SelectionSet', selections: [ { kind: 'Field', - name: {kind: 'Name', value: 'clientCredentials'}, + name: {kind: 'Name', value: 'secrets'}, selectionSet: { kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: {kind: 'Name', value: 'secrets'}, - selectionSet: { - kind: 'SelectionSet', - selections: [ - {kind: 'Field', name: {kind: 'Name', value: 'key'}}, - {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, - ], - }, - }, - {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, - ], + selections: [{kind: 'Field', name: {kind: 'Name', value: 'key'}}], }, }, - {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, ], }, }, + ], + }, + }, + { + kind: 'Field', + name: {kind: 'Name', value: 'activeRelease'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'id'}}, { kind: 'Field', - name: {kind: 'Name', value: 'activeRelease'}, + name: {kind: 'Name', value: 'version'}, selectionSet: { kind: 'SelectionSet', selections: [ - {kind: 'Field', name: {kind: 'Name', value: 'id'}}, + {kind: 'Field', name: {kind: 'Name', value: 'name'}}, { kind: 'Field', - name: {kind: 'Name', value: 'version'}, + name: {kind: 'Name', value: 'appModules'}, selectionSet: { kind: 'SelectionSet', - selections: [ - {kind: 'Field', name: {kind: 'Name', value: 'name'}}, - { - kind: 'Field', - name: {kind: 'Name', value: 'appModules'}, - selectionSet: { - kind: 'SelectionSet', - selections: [ - {kind: 'FragmentSpread', name: {kind: 'Name', value: 'ReleasedAppModule'}}, - {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, - ], - }, - }, - {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, - ], + selections: [{kind: 'FragmentSpread', name: {kind: 'Name', value: 'ReleasedAppModule'}}], }, }, - {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, ], }, }, + ], + }, + }, + ], + }, + }, + { + kind: 'FragmentDefinition', + name: {kind: 'Name', value: 'ReleasedAppModule'}, + typeCondition: {kind: 'NamedType', name: {kind: 'Name', value: 'AppModule'}}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'uuid'}}, + {kind: 'Field', name: {kind: 'Name', value: 'userIdentifier'}}, + {kind: 'Field', name: {kind: 'Name', value: 'handle'}}, + {kind: 'Field', name: {kind: 'Name', value: 'config'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'specification'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'identifier'}}, + {kind: 'Field', name: {kind: 'Name', value: 'externalIdentifier'}}, + {kind: 'Field', name: {kind: 'Name', value: 'name'}}, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode +export const ActiveAppRelease = { + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'query', + name: {kind: 'Name', value: 'activeAppRelease'}, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'appId'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'ID'}}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'app'}, + arguments: [ + { + kind: 'Argument', + name: {kind: 'Name', value: 'id'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'appId'}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'FragmentSpread', name: {kind: 'Name', value: 'AppVersionInfo'}}, {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, ], }, @@ -197,5 +248,71 @@ export const ActiveAppRelease = { ], }, }, + { + kind: 'FragmentDefinition', + name: {kind: 'Name', value: 'AppVersionInfo'}, + typeCondition: {kind: 'NamedType', name: {kind: 'Name', value: 'App'}}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'id'}}, + {kind: 'Field', name: {kind: 'Name', value: 'key'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'activeRoot'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'clientCredentials'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'secrets'}, + selectionSet: { + kind: 'SelectionSet', + selections: [{kind: 'Field', name: {kind: 'Name', value: 'key'}}], + }, + }, + ], + }, + }, + ], + }, + }, + { + kind: 'Field', + name: {kind: 'Name', value: 'activeRelease'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'id'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'version'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'name'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'appModules'}, + selectionSet: { + kind: 'SelectionSet', + selections: [{kind: 'FragmentSpread', name: {kind: 'Name', value: 'ReleasedAppModule'}}], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, ], } as unknown as DocumentNode diff --git a/packages/app/src/cli/api/graphql/app-management/generated/app-version-by-id.ts b/packages/app/src/cli/api/graphql/app-management/generated/app-version-by-id.ts index e2c2fd6978c..b6ac1af4998 100644 --- a/packages/app/src/cli/api/graphql/app-management/generated/app-version-by-id.ts +++ b/packages/app/src/cli/api/graphql/app-management/generated/app-version-by-id.ts @@ -11,7 +11,7 @@ export type AppVersionByIdQueryVariables = Types.Exact<{ export type AppVersionByIdQuery = { version: { id: string - metadata: {versionTag?: string | null} + metadata: {message?: string | null; versionTag?: string | null} appModules: { uuid: string userIdentifier: string @@ -59,6 +59,7 @@ export const AppVersionById = { selectionSet: { kind: 'SelectionSet', selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'message'}}, {kind: 'Field', name: {kind: 'Name', value: 'versionTag'}}, {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, ], diff --git a/packages/app/src/cli/api/graphql/app-management/queries/active-app-release-from-api-key.graphql b/packages/app/src/cli/api/graphql/app-management/queries/active-app-release-from-api-key.graphql new file mode 100644 index 00000000000..bc0d1e9b092 --- /dev/null +++ b/packages/app/src/cli/api/graphql/app-management/queries/active-app-release-from-api-key.graphql @@ -0,0 +1,5 @@ +query ActiveAppReleaseFromApiKey($apiKey: String!) { + app: appByKey(key: $apiKey) { + ...AppVersionInfo + } +} diff --git a/packages/app/src/cli/api/graphql/app-management/queries/active-app-release.graphql b/packages/app/src/cli/api/graphql/app-management/queries/active-app-release.graphql index 3408adc4edc..22c1a3e0bc7 100644 --- a/packages/app/src/cli/api/graphql/app-management/queries/active-app-release.graphql +++ b/packages/app/src/cli/api/graphql/app-management/queries/active-app-release.graphql @@ -1,22 +1,26 @@ query activeAppRelease($appId: ID!) { app(id: $appId) { - id - key - activeRoot { - clientCredentials { - secrets { - key - } + ...AppVersionInfo + } +} + +fragment AppVersionInfo on App { + id + key + activeRoot { + clientCredentials { + secrets { + key } } - activeRelease { - id - version { - name + } + activeRelease { + id + version { + name appModules { ...ReleasedAppModule } - } } } } diff --git a/packages/app/src/cli/api/graphql/app-management/queries/app-version-by-id.graphql b/packages/app/src/cli/api/graphql/app-management/queries/app-version-by-id.graphql index 2170abb4407..61817c7b402 100644 --- a/packages/app/src/cli/api/graphql/app-management/queries/app-version-by-id.graphql +++ b/packages/app/src/cli/api/graphql/app-management/queries/app-version-by-id.graphql @@ -2,6 +2,7 @@ query AppVersionById($versionId: ID!) { version(id: $versionId) { id metadata { + message versionTag } appModules { diff --git a/packages/app/src/cli/api/graphql/functions/api_schema_definition.ts b/packages/app/src/cli/api/graphql/functions/api_schema_definition.ts index 09a3806b3de..bf6be02a5dc 100644 --- a/packages/app/src/cli/api/graphql/functions/api_schema_definition.ts +++ b/packages/app/src/cli/api/graphql/functions/api_schema_definition.ts @@ -9,9 +9,3 @@ export const ApiSchemaDefinitionQuery = gql` export interface ApiSchemaDefinitionQuerySchema { definition: string | null } - -export interface ApiSchemaDefinitionQueryVariables { - apiKey: string - version: string - type: string -} diff --git a/packages/app/src/cli/api/graphql/functions/generated/schema-definition-by-api-type.ts b/packages/app/src/cli/api/graphql/functions/generated/schema-definition-by-api-type.ts new file mode 100644 index 00000000000..59d66f3461a --- /dev/null +++ b/packages/app/src/cli/api/graphql/functions/generated/schema-definition-by-api-type.ts @@ -0,0 +1,74 @@ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ +import * as Types from './types.js' + +import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core' + +export type SchemaDefinitionByApiTypeQueryVariables = Types.Exact<{ + type: Types.Scalars['String']['input'] + version: Types.Scalars['String']['input'] +}> + +export type SchemaDefinitionByApiTypeQuery = {api?: {schema?: {definition: string} | null} | null} + +export const SchemaDefinitionByApiType = { + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'query', + name: {kind: 'Name', value: 'SchemaDefinitionByApiType'}, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'type'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}}, + }, + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'version'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'api'}, + arguments: [ + { + kind: 'Argument', + name: {kind: 'Name', value: 'type'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'type'}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'schema'}, + arguments: [ + { + kind: 'Argument', + name: {kind: 'Name', value: 'version'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'version'}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'definition'}}, + {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, + ], + }, + }, + {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode diff --git a/packages/app/src/cli/api/graphql/functions/generated/schema-definition-by-target.ts b/packages/app/src/cli/api/graphql/functions/generated/schema-definition-by-target.ts new file mode 100644 index 00000000000..f7dadf4593a --- /dev/null +++ b/packages/app/src/cli/api/graphql/functions/generated/schema-definition-by-target.ts @@ -0,0 +1,84 @@ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ +import * as Types from './types.js' + +import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core' + +export type SchemaDefinitionByTargetQueryVariables = Types.Exact<{ + handle: Types.Scalars['String']['input'] + version: Types.Scalars['String']['input'] +}> + +export type SchemaDefinitionByTargetQuery = {target?: {api: {schema?: {definition: string} | null}} | null} + +export const SchemaDefinitionByTarget = { + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'query', + name: {kind: 'Name', value: 'SchemaDefinitionByTarget'}, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'handle'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}}, + }, + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'version'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'target'}, + arguments: [ + { + kind: 'Argument', + name: {kind: 'Name', value: 'handle'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'handle'}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'api'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'schema'}, + arguments: [ + { + kind: 'Argument', + name: {kind: 'Name', value: 'version'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'version'}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'definition'}}, + {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, + ], + }, + }, + {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, + ], + }, + }, + {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode diff --git a/packages/app/src/cli/api/graphql/functions/generated/types.d.ts b/packages/app/src/cli/api/graphql/functions/generated/types.d.ts new file mode 100644 index 00000000000..2d85fa63eea --- /dev/null +++ b/packages/app/src/cli/api/graphql/functions/generated/types.d.ts @@ -0,0 +1,24 @@ +/* eslint-disable @typescript-eslint/consistent-type-definitions, @typescript-eslint/naming-convention */ +export type Maybe = T | null +export type InputMaybe = Maybe +export type Exact = {[K in keyof T]: T[K]} +export type MakeOptional = Omit & {[SubKey in K]?: Maybe} +export type MakeMaybe = Omit & {[SubKey in K]: Maybe} +export type MakeEmpty = {[_ in K]?: never} +export type Incremental = T | {[P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never} +/** All built-in and custom scalars, mapped to their actual values */ +export type Scalars = { + ID: {input: string; output: string} + String: {input: string; output: string} + Boolean: {input: boolean; output: boolean} + Int: {input: number; output: number} + Float: {input: number; output: number} + /** + * Represents an [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) and + * [RFC 3987](https://datatracker.ietf.org/doc/html/rfc3987)-compliant URI string. + * + * For example, `"https://example.myshopify.com"` is a valid URL. It includes a scheme (`https`) and a host + * (`example.myshopify.com`). + */ + URL: {input: string; output: string} +} diff --git a/packages/app/src/cli/api/graphql/functions/queries/schema-definition-by-api-type.graphql b/packages/app/src/cli/api/graphql/functions/queries/schema-definition-by-api-type.graphql new file mode 100644 index 00000000000..c9b493ba7ce --- /dev/null +++ b/packages/app/src/cli/api/graphql/functions/queries/schema-definition-by-api-type.graphql @@ -0,0 +1,7 @@ +query SchemaDefinitionByApiType($type: String!, $version: String!) { + api(type: $type) { + schema(version: $version) { + definition + } + } +} diff --git a/packages/app/src/cli/api/graphql/functions/queries/schema-definition-by-target.graphql b/packages/app/src/cli/api/graphql/functions/queries/schema-definition-by-target.graphql new file mode 100644 index 00000000000..fd220b53fa3 --- /dev/null +++ b/packages/app/src/cli/api/graphql/functions/queries/schema-definition-by-target.graphql @@ -0,0 +1,9 @@ +query SchemaDefinitionByTarget($handle: String!, $version: String!) { + target(handle: $handle) { + api { + schema(version: $version) { + definition + } + } + } +} diff --git a/packages/app/src/cli/api/graphql/functions/target_schema_definition.ts b/packages/app/src/cli/api/graphql/functions/target_schema_definition.ts index dbf2ee2eacd..a957d03d65f 100644 --- a/packages/app/src/cli/api/graphql/functions/target_schema_definition.ts +++ b/packages/app/src/cli/api/graphql/functions/target_schema_definition.ts @@ -9,9 +9,3 @@ export const TargetSchemaDefinitionQuery = gql` export interface TargetSchemaDefinitionQuerySchema { definition: string | null } - -export interface TargetSchemaDefinitionQueryVariables { - apiKey: string - version: string - target: string -} diff --git a/packages/app/src/cli/api/graphql/webhooks/generated/available-topics.ts b/packages/app/src/cli/api/graphql/webhooks/generated/available-topics.ts new file mode 100644 index 00000000000..5d800b5bdf6 --- /dev/null +++ b/packages/app/src/cli/api/graphql/webhooks/generated/available-topics.ts @@ -0,0 +1,44 @@ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ +import * as Types from './types.js' + +import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core' + +export type AvailableTopicsQueryVariables = Types.Exact<{ + apiVersion: Types.Scalars['String']['input'] +}> + +export type AvailableTopicsQuery = {availableTopics?: string[] | null} + +export const AvailableTopics = { + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'query', + name: {kind: 'Name', value: 'availableTopics'}, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'apiVersion'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'availableTopics'}, + arguments: [ + { + kind: 'Argument', + name: {kind: 'Name', value: 'apiVersion'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'apiVersion'}}, + }, + ], + }, + ], + }, + }, + ], +} as unknown as DocumentNode diff --git a/packages/app/src/cli/api/graphql/webhooks/generated/cli-testing.ts b/packages/app/src/cli/api/graphql/webhooks/generated/cli-testing.ts new file mode 100644 index 00000000000..a15253d2cc6 --- /dev/null +++ b/packages/app/src/cli/api/graphql/webhooks/generated/cli-testing.ts @@ -0,0 +1,111 @@ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ +import * as Types from './types.js' + +import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core' + +export type CliTestingMutationVariables = Types.Exact<{ + address: Types.Scalars['String']['input'] + apiKey?: Types.InputMaybe + apiVersion: Types.Scalars['String']['input'] + deliveryMethod: Types.Scalars['String']['input'] + sharedSecret: Types.Scalars['String']['input'] + topic: Types.Scalars['String']['input'] +}> + +export type CliTestingMutation = { + cliTesting?: {headers?: string | null; samplePayload?: string | null; success: boolean; errors: string[]} | null +} + +export const CliTesting = { + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'mutation', + name: {kind: 'Name', value: 'CliTesting'}, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'address'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}}, + }, + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'apiKey'}}, + type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}, + }, + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'apiVersion'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}}, + }, + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'deliveryMethod'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}}, + }, + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'sharedSecret'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}}, + }, + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'topic'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'cliTesting'}, + arguments: [ + { + kind: 'Argument', + name: {kind: 'Name', value: 'address'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'address'}}, + }, + { + kind: 'Argument', + name: {kind: 'Name', value: 'apiKey'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'apiKey'}}, + }, + { + kind: 'Argument', + name: {kind: 'Name', value: 'apiVersion'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'apiVersion'}}, + }, + { + kind: 'Argument', + name: {kind: 'Name', value: 'deliveryMethod'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'deliveryMethod'}}, + }, + { + kind: 'Argument', + name: {kind: 'Name', value: 'sharedSecret'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'sharedSecret'}}, + }, + { + kind: 'Argument', + name: {kind: 'Name', value: 'topic'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'topic'}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'headers'}}, + {kind: 'Field', name: {kind: 'Name', value: 'samplePayload'}}, + {kind: 'Field', name: {kind: 'Name', value: 'success'}}, + {kind: 'Field', name: {kind: 'Name', value: 'errors'}}, + {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode diff --git a/packages/app/src/cli/api/graphql/webhooks/generated/public-api-versions.ts b/packages/app/src/cli/api/graphql/webhooks/generated/public-api-versions.ts new file mode 100644 index 00000000000..c5cc702cd1f --- /dev/null +++ b/packages/app/src/cli/api/graphql/webhooks/generated/public-api-versions.ts @@ -0,0 +1,35 @@ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ +import * as Types from './types.js' + +import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core' + +export type PublicApiVersionsQueryVariables = Types.Exact<{[key: string]: never}> + +export type PublicApiVersionsQuery = {publicApiVersions: {handle: string}[]} + +export const PublicApiVersions = { + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'query', + name: {kind: 'Name', value: 'publicApiVersions'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'publicApiVersions'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'handle'}}, + {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode diff --git a/packages/app/src/cli/api/graphql/webhooks/generated/types.d.ts b/packages/app/src/cli/api/graphql/webhooks/generated/types.d.ts new file mode 100644 index 00000000000..2b9d2b25a6f --- /dev/null +++ b/packages/app/src/cli/api/graphql/webhooks/generated/types.d.ts @@ -0,0 +1,16 @@ +/* eslint-disable @typescript-eslint/consistent-type-definitions, @typescript-eslint/naming-convention */ +export type Maybe = T | null +export type InputMaybe = Maybe +export type Exact = {[K in keyof T]: T[K]} +export type MakeOptional = Omit & {[SubKey in K]?: Maybe} +export type MakeMaybe = Omit & {[SubKey in K]: Maybe} +export type MakeEmpty = {[_ in K]?: never} +export type Incremental = T | {[P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never} +/** All built-in and custom scalars, mapped to their actual values */ +export type Scalars = { + ID: {input: string; output: string} + String: {input: string; output: string} + Boolean: {input: boolean; output: boolean} + Int: {input: number; output: number} + Float: {input: number; output: number} +} diff --git a/packages/app/src/cli/api/graphql/webhooks/queries/available-topics.graphql b/packages/app/src/cli/api/graphql/webhooks/queries/available-topics.graphql new file mode 100644 index 00000000000..5fea722e663 --- /dev/null +++ b/packages/app/src/cli/api/graphql/webhooks/queries/available-topics.graphql @@ -0,0 +1,3 @@ +query availableTopics($apiVersion: String!) { + availableTopics(apiVersion: $apiVersion) +} diff --git a/packages/app/src/cli/api/graphql/webhooks/queries/cli-testing.graphql b/packages/app/src/cli/api/graphql/webhooks/queries/cli-testing.graphql new file mode 100644 index 00000000000..06b29c75bd8 --- /dev/null +++ b/packages/app/src/cli/api/graphql/webhooks/queries/cli-testing.graphql @@ -0,0 +1,8 @@ +mutation CliTesting($address: String!, $apiKey: String, $apiVersion: String!, $deliveryMethod: String!, $sharedSecret: String!, $topic: String!) { + cliTesting(address: $address, apiKey: $apiKey, apiVersion: $apiVersion, deliveryMethod: $deliveryMethod, sharedSecret: $sharedSecret, topic: $topic) { + headers + samplePayload + success + errors + } +} diff --git a/packages/app/src/cli/api/graphql/webhooks/queries/public-api-versions.graphql b/packages/app/src/cli/api/graphql/webhooks/queries/public-api-versions.graphql new file mode 100644 index 00000000000..03da5ff5ff4 --- /dev/null +++ b/packages/app/src/cli/api/graphql/webhooks/queries/public-api-versions.graphql @@ -0,0 +1,5 @@ +query publicApiVersions { + publicApiVersions { + handle + } +} diff --git a/packages/app/src/cli/commands/app/app-logs/sources.ts b/packages/app/src/cli/commands/app/app-logs/sources.ts index 2937b18dc9a..dcdaa8c414b 100644 --- a/packages/app/src/cli/commands/app/app-logs/sources.ts +++ b/packages/app/src/cli/commands/app/app-logs/sources.ts @@ -21,8 +21,8 @@ export default class Sources extends AppCommand { const {app} = await linkedAppContext({ directory: flags.path, - clientId: undefined, - forceRelink: false, + clientId: flags['client-id'], + forceRelink: flags.reset, userProvidedConfigName: flags.config, }) diff --git a/packages/app/src/cli/commands/app/build.ts b/packages/app/src/cli/commands/app/build.ts index 854fe961a58..1bdc49fe906 100644 --- a/packages/app/src/cli/commands/app/build.ts +++ b/packages/app/src/cli/commands/app/build.ts @@ -31,12 +31,6 @@ export default class Build extends AppCommand { env: 'SHOPIFY_FLAG_API_KEY', exclusive: ['config'], }), - 'client-id': Flags.string({ - hidden: false, - description: "Application's Client ID that will be exposed at build time.", - env: 'SHOPIFY_FLAG_CLIENT_ID', - exclusive: ['config'], - }), } async run(): Promise { @@ -44,7 +38,7 @@ export default class Build extends AppCommand { if (flags['api-key']) { await showApiKeyDeprecationWarning() } - const apiKey = flags['client-id'] || flags['api-key'] + const apiKey = flags['client-id'] ?? flags['api-key'] await addPublicMetadata(() => ({ cmd_app_dependency_installation_skipped: flags['skip-dependencies-installation'], @@ -52,8 +46,8 @@ export default class Build extends AppCommand { const {app} = await linkedAppContext({ directory: flags.path, - clientId: flags['client-id'], - forceRelink: false, + clientId: apiKey, + forceRelink: flags.reset, userProvidedConfigName: flags.config, }) diff --git a/packages/app/src/cli/commands/app/config/link.ts b/packages/app/src/cli/commands/app/config/link.ts index 58ab864e7e6..ba7884b76ce 100644 --- a/packages/app/src/cli/commands/app/config/link.ts +++ b/packages/app/src/cli/commands/app/config/link.ts @@ -2,7 +2,6 @@ import {appFlags} from '../../../flags.js' import {linkedAppContext} from '../../../services/app-context.js' import link, {LinkOptions} from '../../../services/app/config/link.js' import AppCommand, {AppCommandOutput} from '../../../utilities/app-command.js' -import {Flags} from '@oclif/core' import {globalFlags} from '@shopify/cli-kit/node/cli' export default class ConfigLink extends AppCommand { @@ -18,11 +17,6 @@ export default class ConfigLink extends AppCommand { static flags = { ...globalFlags, ...appFlags, - 'client-id': Flags.string({ - hidden: false, - description: 'The Client ID of your app.', - env: 'SHOPIFY_FLAG_CLIENT_ID', - }), } public async run(): Promise { diff --git a/packages/app/src/cli/commands/app/config/use.ts b/packages/app/src/cli/commands/app/config/use.ts index 9a7330121bb..4958acd88c5 100644 --- a/packages/app/src/cli/commands/app/config/use.ts +++ b/packages/app/src/cli/commands/app/config/use.ts @@ -3,7 +3,7 @@ import {checkFolderIsValidApp} from '../../../models/app/loader.js' import {linkedAppContext} from '../../../services/app-context.js' import use from '../../../services/app/config/use.js' import AppCommand, {AppCommandOutput} from '../../../utilities/app-command.js' -import {Args, Flags} from '@oclif/core' +import {Args} from '@oclif/core' import {globalFlags} from '@shopify/cli-kit/node/cli' // This is one of the few commands where we don't need a @@ -20,12 +20,6 @@ export default class ConfigUse extends AppCommand { static flags = { ...globalFlags, ...appFlagsWithoutConfig, - reset: Flags.boolean({ - hidden: false, - description: 'Reset current configuration.', - env: 'SHOPIFY_FLAG_RESET', - default: false, - }), } static args = { diff --git a/packages/app/src/cli/commands/app/demo/watcher.ts b/packages/app/src/cli/commands/app/demo/watcher.ts index 538a18df98d..454b08d4fcc 100644 --- a/packages/app/src/cli/commands/app/demo/watcher.ts +++ b/packages/app/src/cli/commands/app/demo/watcher.ts @@ -21,8 +21,8 @@ export default class DemoWatcher extends AppCommand { const {app} = await linkedAppContext({ directory: flags.path, - clientId: undefined, - forceRelink: false, + clientId: flags['client-id'], + forceRelink: flags.reset, userProvidedConfigName: flags.config, }) diff --git a/packages/app/src/cli/commands/app/deploy.ts b/packages/app/src/cli/commands/app/deploy.ts index 3f7489a7bec..507cbee2e11 100644 --- a/packages/app/src/cli/commands/app/deploy.ts +++ b/packages/app/src/cli/commands/app/deploy.ts @@ -32,19 +32,6 @@ export default class Deploy extends AppCommand { env: 'SHOPIFY_FLAG_APP_API_KEY', exclusive: ['config'], }), - 'client-id': Flags.string({ - hidden: false, - description: 'The Client ID of your app.', - env: 'SHOPIFY_FLAG_CLIENT_ID', - exclusive: ['config'], - }), - reset: Flags.boolean({ - hidden: false, - description: 'Reset all your settings.', - env: 'SHOPIFY_FLAG_RESET', - default: false, - exclusive: ['config'], - }), force: Flags.boolean({ hidden: false, description: 'Deploy without asking for confirmation.', diff --git a/packages/app/src/cli/commands/app/dev.ts b/packages/app/src/cli/commands/app/dev.ts index 9836115591a..18265a5cb0f 100644 --- a/packages/app/src/cli/commands/app/dev.ts +++ b/packages/app/src/cli/commands/app/dev.ts @@ -49,12 +49,6 @@ If you're using the Ruby app template, then you need to complete the following s env: 'SHOPIFY_FLAG_APP_API_KEY', exclusive: ['config'], }), - 'client-id': Flags.string({ - hidden: false, - description: 'The Client ID of your app.', - env: 'SHOPIFY_FLAG_CLIENT_ID', - exclusive: ['config'], - }), store: Flags.string({ hidden: false, char: 's', @@ -62,13 +56,6 @@ If you're using the Ruby app template, then you need to complete the following s env: 'SHOPIFY_FLAG_STORE', parse: async (input) => normalizeStoreFqdn(input), }), - reset: Flags.boolean({ - hidden: false, - description: 'Reset all your settings.', - env: 'SHOPIFY_FLAG_RESET', - default: false, - exclusive: ['config'], - }), 'skip-dependencies-installation': Flags.boolean({ hidden: false, description: 'Skips the installation of dependencies. Deprecated, use workspaces instead.', diff --git a/packages/app/src/cli/commands/app/env/pull.ts b/packages/app/src/cli/commands/app/env/pull.ts index c641ede970e..60fb0defa35 100644 --- a/packages/app/src/cli/commands/app/env/pull.ts +++ b/packages/app/src/cli/commands/app/env/pull.ts @@ -32,8 +32,8 @@ export default class EnvPull extends AppCommand { const {app, remoteApp} = await linkedAppContext({ directory: flags.path, - clientId: undefined, - forceRelink: false, + clientId: flags['client-id'], + forceRelink: flags.reset, userProvidedConfigName: flags.config, }) const envFile = joinPath(app.directory, flags['env-file'] ?? getDotEnvFileName(app.configuration.path)) diff --git a/packages/app/src/cli/commands/app/env/show.ts b/packages/app/src/cli/commands/app/env/show.ts index 0474c471c30..67ec0d3e2a1 100644 --- a/packages/app/src/cli/commands/app/env/show.ts +++ b/packages/app/src/cli/commands/app/env/show.ts @@ -21,8 +21,8 @@ export default class EnvShow extends AppCommand { const {flags} = await this.parse(EnvShow) const {app, remoteApp} = await linkedAppContext({ directory: flags.path, - clientId: undefined, - forceRelink: false, + clientId: flags['client-id'], + forceRelink: flags.reset, userProvidedConfigName: flags.config, }) outputInfo(await showEnv(app, remoteApp)) diff --git a/packages/app/src/cli/commands/app/function/build.ts b/packages/app/src/cli/commands/app/function/build.ts index d720443b623..0ac57587ab4 100644 --- a/packages/app/src/cli/commands/app/function/build.ts +++ b/packages/app/src/cli/commands/app/function/build.ts @@ -24,6 +24,8 @@ export default class FunctionBuild extends AppCommand { const app = await inFunctionContext({ path: flags.path, userProvidedConfigName: flags.config, + apiKey: flags['client-id'], + reset: flags.reset, callback: async (app, _, ourFunction) => { await buildFunctionExtension(ourFunction, { app, diff --git a/packages/app/src/cli/commands/app/function/replay.ts b/packages/app/src/cli/commands/app/function/replay.ts index 8352d9a71a1..f5fdd019a77 100644 --- a/packages/app/src/cli/commands/app/function/replay.ts +++ b/packages/app/src/cli/commands/app/function/replay.ts @@ -3,7 +3,7 @@ import {replay} from '../../../services/function/replay.js' import {appFlags} from '../../../flags.js' import {showApiKeyDeprecationWarning} from '../../../prompts/deprecation-warnings.js' import AppCommand, {AppCommandOutput} from '../../../utilities/app-command.js' -import {globalFlags} from '@shopify/cli-kit/node/cli' +import {globalFlags, jsonFlag} from '@shopify/cli-kit/node/cli' import {Flags} from '@oclif/core' export default class FunctionReplay extends AppCommand { @@ -17,30 +17,19 @@ export default class FunctionReplay extends AppCommand { ...globalFlags, ...appFlags, ...functionFlags, + ...jsonFlag, 'api-key': Flags.string({ hidden: true, description: "Application's API key", env: 'SHOPIFY_FLAG_API_KEY', exclusive: ['config'], }), - 'client-id': Flags.string({ - hidden: false, - description: "Application's Client ID", - env: 'SHOPIFY_FLAG_CLIENT_ID', - exclusive: ['config'], - }), log: Flags.string({ char: 'l', description: 'Specifies a log identifier to replay instead of selecting from a list. The identifier is provided in the output of `shopify app dev` and is the suffix of the log file name.', env: 'SHOPIFY_FLAG_LOG', }), - json: Flags.boolean({ - char: 'j', - hidden: false, - description: 'Output the function run result as a JSON object.', - env: 'SHOPIFY_FLAG_JSON', - }), watch: Flags.boolean({ char: 'w', hidden: false, @@ -56,12 +45,13 @@ export default class FunctionReplay extends AppCommand { if (flags['api-key']) { await showApiKeyDeprecationWarning() } - const apiKey = flags['client-id'] || flags['api-key'] + const apiKey = flags['client-id'] ?? flags['api-key'] const app = await inFunctionContext({ path: flags.path, apiKey, userProvidedConfigName: flags.config, + reset: flags.reset, callback: async (app, _, ourFunction) => { await replay({ app, diff --git a/packages/app/src/cli/commands/app/function/run.ts b/packages/app/src/cli/commands/app/function/run.ts index 2c8d352f4d6..5e4cd99db3e 100644 --- a/packages/app/src/cli/commands/app/function/run.ts +++ b/packages/app/src/cli/commands/app/function/run.ts @@ -2,7 +2,7 @@ import {functionFlags, inFunctionContext, getOrGenerateSchemaPath} from '../../. import {runFunction} from '../../../services/function/runner.js' import {appFlags} from '../../../flags.js' import AppCommand, {AppCommandOutput} from '../../../utilities/app-command.js' -import {globalFlags} from '@shopify/cli-kit/node/cli' +import {globalFlags, jsonFlag} from '@shopify/cli-kit/node/cli' import {Flags} from '@oclif/core' import {renderAutocompletePrompt, isTTY} from '@shopify/cli-kit/node/ui' import {outputDebug} from '@shopify/cli-kit/node/output' @@ -20,6 +20,7 @@ export default class FunctionRun extends AppCommand { ...globalFlags, ...appFlags, ...functionFlags, + ...jsonFlag, input: Flags.string({ char: 'i', description: 'The input JSON to pass to the function. If omitted, standard input is used.', @@ -31,12 +32,6 @@ export default class FunctionRun extends AppCommand { description: 'Name of the WebAssembly export to invoke.', env: 'SHOPIFY_FLAG_EXPORT', }), - json: Flags.boolean({ - char: 'j', - hidden: false, - description: 'Log the run result as a JSON object.', - env: 'SHOPIFY_FLAG_JSON', - }), } public async run(): Promise { @@ -44,7 +39,9 @@ export default class FunctionRun extends AppCommand { const app = await inFunctionContext({ path: flags.path, userProvidedConfigName: flags.config, - callback: async (app, developerPlatformClient, ourFunction) => { + apiKey: flags['client-id'], + reset: flags.reset, + callback: async (app, developerPlatformClient, ourFunction, orgId) => { let functionExport = DEFAULT_FUNCTION_EXPORT if (flags.export !== undefined) { @@ -80,7 +77,7 @@ export default class FunctionRun extends AppCommand { const inputQueryPath = ourFunction?.configuration.targeting?.[0]?.input_query const queryPath = inputQueryPath && `${ourFunction?.directory}/${inputQueryPath}` - const schemaPath = await getOrGenerateSchemaPath(ourFunction, app, developerPlatformClient) + const schemaPath = await getOrGenerateSchemaPath(ourFunction, app, developerPlatformClient, orgId) await runFunction({ functionExtension: ourFunction, diff --git a/packages/app/src/cli/commands/app/function/schema.ts b/packages/app/src/cli/commands/app/function/schema.ts index 3b6ab786396..50819647eb5 100644 --- a/packages/app/src/cli/commands/app/function/schema.ts +++ b/packages/app/src/cli/commands/app/function/schema.ts @@ -26,12 +26,6 @@ export default class FetchSchema extends AppCommand { env: 'SHOPIFY_FLAG_APP_API_KEY', exclusive: ['config'], }), - 'client-id': Flags.string({ - hidden: false, - description: 'The Client ID to fetch the schema with.', - env: 'SHOPIFY_FLAG_CLIENT_ID', - exclusive: ['config'], - }), stdout: Flags.boolean({ description: 'Output the schema to stdout instead of writing to a file.', required: false, @@ -45,19 +39,21 @@ export default class FetchSchema extends AppCommand { if (flags['api-key']) { await showApiKeyDeprecationWarning() } - const apiKey = flags['client-id'] || flags['api-key'] + const apiKey = flags['client-id'] ?? flags['api-key'] const app = await inFunctionContext({ path: flags.path, apiKey, + reset: flags.reset, userProvidedConfigName: flags.config, - callback: async (app, developerPlatformClient, ourFunction) => { + callback: async (app, developerPlatformClient, ourFunction, orgId) => { await generateSchemaService({ app, extension: ourFunction, developerPlatformClient, stdout: flags.stdout, path: flags.path, + orgId, }) return app }, diff --git a/packages/app/src/cli/commands/app/function/typegen.ts b/packages/app/src/cli/commands/app/function/typegen.ts index db99a7b78e7..29dbbf0c559 100644 --- a/packages/app/src/cli/commands/app/function/typegen.ts +++ b/packages/app/src/cli/commands/app/function/typegen.ts @@ -22,6 +22,8 @@ export default class FunctionTypegen extends AppCommand { const {flags} = await this.parse(FunctionTypegen) const app = await inFunctionContext({ path: flags.path, + apiKey: flags['client-id'], + reset: flags.reset, userProvidedConfigName: flags.config, callback: async (app, _, ourFunction) => { await buildGraphqlTypes(ourFunction, {stdout: process.stdout, stderr: process.stderr, app}) diff --git a/packages/app/src/cli/commands/app/generate/extension.ts b/packages/app/src/cli/commands/app/generate/extension.ts index 8d1374e13cd..d932fe6cb3f 100644 --- a/packages/app/src/cli/commands/app/generate/extension.ts +++ b/packages/app/src/cli/commands/app/generate/extension.ts @@ -54,25 +54,12 @@ export default class AppGenerateExtension extends AppCommand { options: ['vanilla-js', 'react', 'typescript', 'typescript-react', 'wasm', 'rust'], env: 'SHOPIFY_FLAG_FLAVOR', }), - reset: Flags.boolean({ - hidden: false, - description: 'Reset all your settings.', - env: 'SHOPIFY_FLAG_RESET', - default: false, - exclusive: ['config'], - }), 'api-key': Flags.string({ hidden: true, description: 'The API key of your app.', env: 'SHOPIFY_FLAG_APP_API_KEY', exclusive: ['config'], }), - 'client-id': Flags.string({ - hidden: false, - description: 'The Client ID of your app.', - env: 'SHOPIFY_FLAG_CLIENT_ID', - exclusive: ['config'], - }), } static args = { @@ -107,7 +94,7 @@ export default class AppGenerateExtension extends AppCommand { const {app, specifications, remoteApp, developerPlatformClient} = await linkedAppContext({ directory: flags.path, - clientId: flags['client-id'] || flags['api-key'], + clientId: flags['client-id'] ?? flags['api-key'], forceRelink: flags.reset, userProvidedConfigName: flags.config, }) diff --git a/packages/app/src/cli/commands/app/import-extensions.ts b/packages/app/src/cli/commands/app/import-extensions.ts index e2b05631cf1..87f1b4bcb46 100644 --- a/packages/app/src/cli/commands/app/import-extensions.ts +++ b/packages/app/src/cli/commands/app/import-extensions.ts @@ -8,6 +8,7 @@ import {appFlags} from '../../flags.js' import {importExtensions} from '../../services/import-extensions.js' import AppCommand, {AppCommandOutput} from '../../utilities/app-command.js' import {linkedAppContext} from '../../services/app-context.js' +import {CurrentAppConfiguration} from '../../models/app/app.js' import {renderSelectPrompt, renderFatalError} from '@shopify/cli-kit/node/ui' import {Flags} from '@oclif/core' import {globalFlags} from '@shopify/cli-kit/node/cli' @@ -17,7 +18,11 @@ interface MigrationChoice { label: string value: string extensionTypes: string[] - buildTomlObject: (ext: ExtensionRegistration, allExtensions: ExtensionRegistration[]) => string + buildTomlObject: ( + ext: ExtensionRegistration, + allExtensions: ExtensionRegistration[], + appConfiguration: CurrentAppConfiguration, + ) => string } const getMigrationChoices = (): MigrationChoice[] => [ @@ -79,7 +84,7 @@ export default class ImportExtensions extends AppCommand { const appContext = await linkedAppContext({ directory: flags.path, clientId: flags['client-id'], - forceRelink: false, + forceRelink: flags.reset, userProvidedConfigName: flags.config, }) diff --git a/packages/app/src/cli/commands/app/info.ts b/packages/app/src/cli/commands/app/info.ts index 36ee9a08871..5de3daa4b58 100644 --- a/packages/app/src/cli/commands/app/info.ts +++ b/packages/app/src/cli/commands/app/info.ts @@ -3,7 +3,7 @@ import {Format, info} from '../../services/info.js' import AppCommand, {AppCommandOutput} from '../../utilities/app-command.js' import {linkedAppContext} from '../../services/app-context.js' import {Flags} from '@oclif/core' -import {globalFlags} from '@shopify/cli-kit/node/cli' +import {globalFlags, jsonFlag} from '@shopify/cli-kit/node/cli' import {outputInfo} from '@shopify/cli-kit/node/output' export default class AppInfo extends AppCommand { @@ -21,11 +21,7 @@ export default class AppInfo extends AppCommand { static flags = { ...globalFlags, ...appFlags, - json: Flags.boolean({ - hidden: false, - description: 'format output as JSON', - env: 'SHOPIFY_FLAG_JSON', - }), + ...jsonFlag, 'web-env': Flags.boolean({ hidden: false, description: 'Outputs environment variables necessary for running and deploying web/.', @@ -39,8 +35,8 @@ export default class AppInfo extends AppCommand { const {app, remoteApp, developerPlatformClient} = await linkedAppContext({ directory: flags.path, - clientId: undefined, - forceRelink: false, + clientId: flags['client-id'], + forceRelink: flags.reset, userProvidedConfigName: flags.config, unsafeReportMode: true, }) diff --git a/packages/app/src/cli/commands/app/init.ts b/packages/app/src/cli/commands/app/init.ts index f8d9b7b1fac..39bacacb70f 100644 --- a/packages/app/src/cli/commands/app/init.ts +++ b/packages/app/src/cli/commands/app/init.ts @@ -1,13 +1,12 @@ import initPrompt, {visibleTemplates} from '../../prompts/init/init.js' import initService from '../../services/init/init.js' import {DeveloperPlatformClient, selectDeveloperPlatformClient} from '../../utilities/developer-platform-client.js' -import {appFromId, selectOrg} from '../../services/context.js' +import {appFromIdentifiers, selectOrg} from '../../services/context.js' import AppCommand, {AppCommandOutput} from '../../utilities/app-command.js' import {validateFlavorValue, validateTemplateValue} from '../../services/init/validate.js' import {MinimalOrganizationApp, Organization, OrganizationApp} from '../../models/organization.js' import {appNamePrompt, createAsNewAppPrompt, selectAppPrompt} from '../../prompts/dev.js' import {searchForAppsByNameFactory} from '../../services/dev/prompt-helpers.js' -import {linkedAppContext} from '../../services/app-context.js' import {Flags} from '@oclif/core' import {globalFlags} from '@shopify/cli-kit/node/cli' import {resolvePath, cwd} from '@shopify/cli-kit/node/path' @@ -88,7 +87,7 @@ export default class Init extends AppCommand { let appName: string if (flags['client-id']) { // If a client-id is provided we don't need to prompt the user and can link directly to that app. - const selectedApp = await appFromId({apiKey: flags['client-id'], developerPlatformClient}) + const selectedApp = await appFromIdentifiers({apiKey: flags['client-id'], developerPlatformClient}) appName = selectedApp.title developerPlatformClient = selectedApp.developerPlatformClient ?? developerPlatformClient selectAppResult = {result: 'existing', app: selectedApp} @@ -109,7 +108,7 @@ export default class Init extends AppCommand { cmd_create_app_template_url: promptAnswers.template, })) - const result = await initService({ + const {app} = await initService({ name: appName, selectedAppOrNameResult: selectAppResult, packageManager: inferredPackageManager, @@ -123,14 +122,6 @@ export default class Init extends AppCommand { }, }) - const {app} = await linkedAppContext({ - directory: result.outputDirectory, - clientId: undefined, - forceRelink: false, - userProvidedConfigName: undefined, - unsafeReportMode: false, - }) - return {app} } } @@ -167,7 +158,7 @@ async function selectAppOrNewAppName( } else { const app = await selectAppPrompt(searchForAppsByNameFactory(developerPlatformClient, org.id), apps, hasMorePages) - const fullSelectedApp = await developerPlatformClient.appFromId(app) + const fullSelectedApp = await developerPlatformClient.appFromIdentifiers(app) if (!fullSelectedApp) throw new AbortError(`App with id ${app.id} not found`) return {result: 'existing', app: fullSelectedApp} } diff --git a/packages/app/src/cli/commands/app/logs.ts b/packages/app/src/cli/commands/app/logs.ts index 0e089f6d028..30f3ddbd815 100644 --- a/packages/app/src/cli/commands/app/logs.ts +++ b/packages/app/src/cli/commands/app/logs.ts @@ -7,7 +7,7 @@ import {linkedAppContext} from '../../services/app-context.js' import {storeContext} from '../../services/store-context.js' import {Flags} from '@oclif/core' import {normalizeStoreFqdn} from '@shopify/cli-kit/node/context/fqdn' -import {globalFlags} from '@shopify/cli-kit/node/cli' +import {globalFlags, jsonFlag} from '@shopify/cli-kit/node/cli' export default class Logs extends AppCommand { static summary = 'Stream detailed logs for your Shopify app.' @@ -26,8 +26,8 @@ export default class Logs extends AppCommand { static flags = { ...globalFlags, ...appFlags, + ...jsonFlag, 'api-key': Dev.flags['api-key'], - 'client-id': Dev.flags['client-id'], store: Flags.string({ char: 's', description: 'Store URL. Must be an existing development or Shopify Plus sandbox store.', @@ -35,7 +35,6 @@ export default class Logs extends AppCommand { multiple: true, parse: async (input) => normalizeStoreFqdn(input), }), - reset: Dev.flags.reset, source: Flags.string({ description: 'Filters output to the specified log source.', env: 'SHOPIFY_FLAG_SOURCE', @@ -46,17 +45,12 @@ export default class Logs extends AppCommand { options: ['success', 'failure'], env: 'SHOPIFY_FLAG_STATUS', }), - json: Flags.boolean({ - char: 'j', - description: 'Log the run result as a JSON object.', - env: 'SHOPIFY_FLAG_JSON', - }), } public async run(): Promise { const {flags} = await this.parse(Logs) - const apiKey = flags['client-id'] || flags['api-key'] + const apiKey = flags['client-id'] ?? flags['api-key'] await checkFolderIsValidApp(flags.path) diff --git a/packages/app/src/cli/commands/app/release.ts b/packages/app/src/cli/commands/app/release.ts index b2ca3dfeef7..9713a20d60e 100644 --- a/packages/app/src/cli/commands/app/release.ts +++ b/packages/app/src/cli/commands/app/release.ts @@ -26,18 +26,6 @@ export default class Release extends AppCommand { env: 'SHOPIFY_FLAG_APP_API_KEY', exclusive: ['config'], }), - 'client-id': Flags.string({ - hidden: false, - description: 'The Client ID of your app.', - env: 'SHOPIFY_FLAG_CLIENT_ID', - exclusive: ['config'], - }), - reset: Flags.boolean({ - hidden: false, - description: 'Reset all your settings.', - env: 'SHOPIFY_FLAG_RESET', - default: false, - }), force: Flags.boolean({ hidden: false, description: 'Release without asking for confirmation.', @@ -57,7 +45,7 @@ export default class Release extends AppCommand { if (flags['api-key']) { await showApiKeyDeprecationWarning() } - const apiKey = flags['client-id'] || flags['api-key'] + const apiKey = flags['client-id'] ?? flags['api-key'] await addPublicMetadata(() => ({ cmd_app_reset_used: flags.reset, diff --git a/packages/app/src/cli/commands/app/versions/list.ts b/packages/app/src/cli/commands/app/versions/list.ts index 700673819a8..e484d6029c3 100644 --- a/packages/app/src/cli/commands/app/versions/list.ts +++ b/packages/app/src/cli/commands/app/versions/list.ts @@ -3,7 +3,7 @@ import versionList from '../../../services/versions-list.js' import {showApiKeyDeprecationWarning} from '../../../prompts/deprecation-warnings.js' import AppCommand, {AppCommandOutput} from '../../../utilities/app-command.js' import {linkedAppContext} from '../../../services/app-context.js' -import {globalFlags} from '@shopify/cli-kit/node/cli' +import {globalFlags, jsonFlag} from '@shopify/cli-kit/node/cli' import {Args, Flags} from '@oclif/core' export default class VersionsList extends AppCommand { @@ -18,23 +18,13 @@ export default class VersionsList extends AppCommand { static flags = { ...globalFlags, ...appFlags, + ...jsonFlag, 'api-key': Flags.string({ hidden: true, description: "Application's API key to fetch versions for.", env: 'SHOPIFY_FLAG_API_KEY', exclusive: ['config'], }), - 'client-id': Flags.string({ - hidden: false, - description: 'The Client ID to fetch versions for.', - env: 'SHOPIFY_FLAG_CLIENT_ID', - exclusive: ['config'], - }), - json: Flags.boolean({ - description: 'Output the versions list as JSON.', - default: false, - env: 'SHOPIFY_FLAG_JSON', - }), } static args = { @@ -46,12 +36,12 @@ export default class VersionsList extends AppCommand { if (flags['api-key']) { await showApiKeyDeprecationWarning() } - const apiKey = flags['client-id'] || flags['api-key'] + const apiKey = flags['client-id'] ?? flags['api-key'] const {app, remoteApp, developerPlatformClient, organization} = await linkedAppContext({ directory: flags.path, clientId: apiKey, - forceRelink: false, + forceRelink: flags.reset, userProvidedConfigName: flags.config, }) diff --git a/packages/app/src/cli/commands/app/webhook/trigger.ts b/packages/app/src/cli/commands/app/webhook/trigger.ts index d6500fd8e22..20a8f76e7f3 100644 --- a/packages/app/src/cli/commands/app/webhook/trigger.ts +++ b/packages/app/src/cli/commands/app/webhook/trigger.ts @@ -56,12 +56,6 @@ export default class WebhookTrigger extends AppCommand { env: 'SHOPIFY_FLAG_DELIVERY_METHOD', description: `Method chosen to deliver the topic payload. If not passed, it's inferred from the address.`, }), - 'client-id': Flags.string({ - hidden: false, - description: 'The Client ID of your app.', - env: 'SHOPIFY_FLAG_CLIENT_ID', - exclusive: ['config'], - }), 'shared-secret': Flags.string({ required: false, hidden: false, @@ -101,7 +95,7 @@ export default class WebhookTrigger extends AppCommand { const appContextResult = await linkedAppContext({ directory: flags.path, clientId: flags['client-id'], - forceRelink: false, + forceRelink: flags.reset, userProvidedConfigName: flags.config, }) @@ -115,6 +109,7 @@ export default class WebhookTrigger extends AppCommand { clientSecret: flags['client-secret'] || flags['shared-secret'], path: flags.path, config: flags.config, + organizationId: appContextResult.organization.id, } await webhookTriggerService(usedFlags) diff --git a/packages/app/src/cli/flags.ts b/packages/app/src/cli/flags.ts index 7781611b85c..bf6944a81ea 100644 --- a/packages/app/src/cli/flags.ts +++ b/packages/app/src/cli/flags.ts @@ -19,4 +19,17 @@ export const appFlags = { description: 'The name of the app configuration.', env: 'SHOPIFY_FLAG_APP_CONFIG', }), + 'client-id': Flags.string({ + hidden: false, + description: 'The Client ID of your app.', + env: 'SHOPIFY_FLAG_CLIENT_ID', + exclusive: ['config'], + }), + reset: Flags.boolean({ + hidden: false, + description: 'Reset all your settings.', + env: 'SHOPIFY_FLAG_RESET', + default: false, + exclusive: ['config'], + }), } diff --git a/packages/app/src/cli/models/app/app.test-data.ts b/packages/app/src/cli/models/app/app.test-data.ts index f9933958bfc..2ea50a349d8 100644 --- a/packages/app/src/cli/models/app/app.test-data.ts +++ b/packages/app/src/cli/models/app/app.test-data.ts @@ -17,6 +17,7 @@ import { MinimalAppIdentifiers, OrganizationApp, MinimalOrganizationApp, + AppApiKeyAndOrgId, } from '../organization.js' import {RemoteSpecification} from '../../api/graphql/extension_specifications.js' import {ExtensionInstance} from '../extensions/extension-instance.js' @@ -55,8 +56,6 @@ import { } from '../../api/graphql/extension_migrate_flow_extension.js' import {UpdateURLsSchema, UpdateURLsVariables} from '../../api/graphql/update_urls.js' import {CurrentAccountInfoSchema} from '../../api/graphql/current_account_info.js' -import {TargetSchemaDefinitionQueryVariables} from '../../api/graphql/functions/target_schema_definition.js' -import {ApiSchemaDefinitionQueryVariables} from '../../api/graphql/functions/api_schema_definition.js' import { MigrateToUiExtensionSchema, MigrateToUiExtensionVariables, @@ -69,6 +68,8 @@ import { ExtensionUpdateDraftMutation, ExtensionUpdateDraftMutationVariables, } from '../../api/graphql/partners/generated/update-draft.js' +import {SchemaDefinitionByTargetQueryVariables} from '../../api/graphql/functions/generated/schema-definition-by-target.js' +import {SchemaDefinitionByApiTypeQueryVariables} from '../../api/graphql/functions/generated/schema-definition-by-api-type.js' import {vi} from 'vitest' import {joinPath} from '@shopify/cli-kit/node/path' @@ -219,8 +220,30 @@ export async function testUIExtension( }, }, extension_points: [ - {target: 'target1', module: 'module1'}, - {target: 'target2', module: 'module2'}, + { + target: 'target1', + module: 'module1', + build_manifest: { + assets: { + main: { + module: 'module1', + filepath: uiExtension?.handle ? `/${uiExtension.handle}.js` : '/test-ui-extension.js', + }, + }, + }, + }, + { + target: 'target2', + module: 'module2', + build_manifest: { + assets: { + main: { + module: 'module2', + filepath: uiExtension?.handle ? `/${uiExtension.handle}.js` : '/test-ui-extension.js', + }, + }, + }, + }, ], } const configurationPath = uiExtension?.configurationPath ?? `${directory}/shopify.ui.extension.toml` @@ -478,6 +501,8 @@ function defaultFunctionConfiguration(): FunctionConfigType { type: 'product_discounts', build: { command: 'echo "hello world"', + watch: ['src/**/*.rs'], + wasm_opt: true, }, api_version: '2022-07', configuration_ui: true, @@ -1294,7 +1319,7 @@ export function testDeveloperPlatformClient(stubs: Partial Promise.resolve(testPartnersUserSession), refreshToken: () => Promise.resolve(testPartnersUserSession.token), accountInfo: () => Promise.resolve(testPartnersUserSession.accountInfo), - appFromId: (_app: MinimalAppIdentifiers) => Promise.resolve(testOrganizationApp()), + appFromIdentifiers: (_app: AppApiKeyAndOrgId) => Promise.resolve(testOrganizationApp()), organizations: () => Promise.resolve(organizationsResponse), orgFromId: (_organizationId: string) => Promise.resolve(testOrganization()), appsForOrg: (_organizationId: string) => Promise.resolve({apps: [testOrganizationApp()], hasMorePages: false}), @@ -1328,8 +1353,10 @@ export function testDeveloperPlatformClient(stubs: Partial Promise.resolve(migrateAppModuleResponse), updateURLs: (_input: UpdateURLsVariables) => Promise.resolve(updateURLsResponse), currentAccountInfo: () => Promise.resolve(currentAccountInfoResponse), - targetSchemaDefinition: (_input: TargetSchemaDefinitionQueryVariables) => Promise.resolve('schema'), - apiSchemaDefinition: (_input: ApiSchemaDefinitionQueryVariables) => Promise.resolve('schema'), + targetSchemaDefinition: (_input: SchemaDefinitionByTargetQueryVariables & {apiKey?: string}, _orgId: string) => + Promise.resolve('schema'), + apiSchemaDefinition: (_input: SchemaDefinitionByApiTypeQueryVariables & {apiKey?: string}, _orgId: string) => + Promise.resolve('schema'), migrateToUiExtension: (_input: MigrateToUiExtensionVariables) => Promise.resolve(migrateToUiExtensionResponse), toExtensionGraphQLType: (input: string) => input, subscribeToAppLogs: (_input: AppLogsSubscribeVariables) => Promise.resolve(appLogsSubscribeResponse), diff --git a/packages/app/src/cli/models/app/app.test.ts b/packages/app/src/cli/models/app/app.test.ts index 7c4534a09a1..da46653b30c 100644 --- a/packages/app/src/cli/models/app/app.test.ts +++ b/packages/app/src/cli/models/app/app.test.ts @@ -39,6 +39,7 @@ const CORRECT_CURRENT_APP_SCHEMA: CurrentAppConfiguration = { }, }, application_url: 'http://example.com', + embedded: false, auth: { redirect_urls: ['https://google.com'], }, @@ -204,6 +205,7 @@ describe('validateFunctionExtensionsWithUiHandle', () => { description: 'description', build: { command: 'echo "hello world"', + wasm_opt: true, }, api_version: '2022-07', configuration_ui: true, diff --git a/packages/app/src/cli/models/app/app.ts b/packages/app/src/cli/models/app/app.ts index a1867ff40ff..712a8d20c48 100644 --- a/packages/app/src/cli/models/app/app.ts +++ b/packages/app/src/cli/models/app/app.ts @@ -55,7 +55,6 @@ function removeTrailingPathSeparator(value: string[] | undefined) { */ export const AppSchema = zod.object({ client_id: zod.string(), - app_id: zod.string().optional(), organization_id: zod.string().optional(), build: zod .object({ diff --git a/packages/app/src/cli/models/app/loader.test.ts b/packages/app/src/cli/models/app/loader.test.ts index 8525ad56684..e4b5fc32519 100644 --- a/packages/app/src/cli/models/app/loader.test.ts +++ b/packages/app/src/cli/models/app/loader.test.ts @@ -38,6 +38,7 @@ import {mockAndCaptureOutput} from '@shopify/cli-kit/node/testing/output' import colors from '@shopify/cli-kit/node/colors' import {globalCLIVersion, localCLIVersion} from '@shopify/cli-kit/node/version' +import {CLI_KIT_VERSION} from '@shopify/cli-kit/common/version' vi.mock('../../services/local-storage.js') vi.mock('../../services/app/config/use.js') @@ -329,7 +330,6 @@ wrong = "property" test('shows warning if using global CLI but app has local dependency', async () => { // Given vi.mocked(globalCLIVersion).mockResolvedValue('3.68.0') - vi.mocked(localCLIVersion).mockResolvedValue('3.65.0') const mockOutput = mockAndCaptureOutput() await writeConfig(appConfiguration, { workspaces: ['packages/*'], @@ -347,7 +347,7 @@ wrong = "property" │ │ │ Two Shopify CLI installations found – using local dependency │ │ │ - │ A global installation (v3.68.0) and a local dependency (v3.65.0) were │ + │ A global installation (v3.68.0) and a local dependency (v${CLI_KIT_VERSION}) were │ │ detected. │ │ We recommend removing the @shopify/cli and @shopify/app dependencies from │ │ your package.json, unless you want to use different versions across │ @@ -2353,6 +2353,7 @@ wrong = "property" devDependencies: {}, }) await writeFile(joinPath(webDirectory, 'package.json'), JSON.stringify({})) + await writeFile(joinPath(tmpDir, '.gitignore'), '') await loadTestingApp() @@ -2364,7 +2365,7 @@ wrong = "property" cmd_app_all_configs_any: true, cmd_app_all_configs_clients: JSON.stringify({'shopify.app.toml': '1234567890'}), cmd_app_linked_config_name: 'shopify.app.toml', - cmd_app_linked_config_git_tracked: false, + cmd_app_linked_config_git_tracked: true, cmd_app_linked_config_source: 'cached', cmd_app_warning_api_key_deprecation_displayed: false, app_extensions_any: false, @@ -2388,6 +2389,43 @@ wrong = "property" app_web_frontend_count: 0, }) }) + + test.skipIf(runningOnWindows)(`git_tracked metadata is false when ignored by the gitignore`, async () => { + const {webDirectory} = await writeConfig(linkedAppConfiguration, { + workspaces: ['packages/*'], + name: 'my_app', + dependencies: {}, + devDependencies: {}, + }) + await writeFile(joinPath(webDirectory, 'package.json'), JSON.stringify({})) + await writeFile(joinPath(tmpDir, '.gitignore'), 'shopify.app.toml') + + await loadTestingApp() + + expect(metadata.getAllPublicMetadata()).toEqual( + expect.objectContaining({ + cmd_app_linked_config_git_tracked: false, + }), + ) + }) + + test.skipIf(runningOnWindows)(`git_tracked metadata is true when there is no gitignore`, async () => { + const {webDirectory} = await writeConfig(linkedAppConfiguration, { + workspaces: ['packages/*'], + name: 'my_app', + dependencies: {}, + devDependencies: {}, + }) + await writeFile(joinPath(webDirectory, 'package.json'), JSON.stringify({})) + + await loadTestingApp() + + expect(metadata.getAllPublicMetadata()).toEqual( + expect.objectContaining({ + cmd_app_linked_config_git_tracked: true, + }), + ) + }) }) describe('getAppConfigurationFileName', () => { diff --git a/packages/app/src/cli/models/app/loader.ts b/packages/app/src/cli/models/app/loader.ts index e8d04662e97..52170020453 100644 --- a/packages/app/src/cli/models/app/loader.ts +++ b/packages/app/src/cli/models/app/loader.ts @@ -16,7 +16,9 @@ import { BasicAppConfigurationWithoutModules, SchemaForConfig, AppCreationDefaultOptions, + AppLinkedInterface, } from './app.js' +import {showMultipleCLIWarningIfNeeded} from './validation/multi-cli-warning.js' import {configurationFileNames, dotEnvFileNames} from '../../constants.js' import metadata from '../../metadata.js' import {ExtensionInstance} from '../extensions/extension-instance.js' @@ -42,16 +44,13 @@ import { import {resolveFramework} from '@shopify/cli-kit/node/framework' import {hashString} from '@shopify/cli-kit/node/crypto' import {JsonMapType, decodeToml} from '@shopify/cli-kit/node/toml' -import {joinPath, dirname, basename, relativePath, relativizePath, sniffForJson} from '@shopify/cli-kit/node/path' +import {joinPath, dirname, basename, relativePath, relativizePath} from '@shopify/cli-kit/node/path' import {AbortError} from '@shopify/cli-kit/node/error' import {outputContent, outputDebug, OutputMessage, outputToken} from '@shopify/cli-kit/node/output' import {joinWithAnd, slugify} from '@shopify/cli-kit/common/string' import {getArrayRejectingUndefined} from '@shopify/cli-kit/common/array' -import {checkIfIgnoredInGitRepository} from '@shopify/cli-kit/node/git' -import {renderInfo} from '@shopify/cli-kit/node/ui' -import {currentProcessIsGlobal} from '@shopify/cli-kit/node/is-global' import {showNotificationsIfNeeded} from '@shopify/cli-kit/node/notifications-system' -import {globalCLIVersion, localCLIVersion} from '@shopify/cli-kit/node/version' +import ignore from 'ignore' const defaultExtensionDirectory = 'extensions/*' @@ -202,6 +201,8 @@ export class AppErrors { interface AppLoaderConstructorArgs { mode?: AppLoaderMode loadedConfiguration: ConfigurationLoaderResult + // Used when reloading an app, to avoid some expensive steps during loading. + previousApp?: AppLinkedInterface } export async function checkFolderIsValidApp(directory: string) { @@ -251,6 +252,21 @@ export async function loadApp { + const state = await getAppConfigurationState(app.directory, basename(app.configuration.path)) + if (state.state !== 'connected-app') { + throw new AbortError('Error loading the app, please check your app configuration.') + } + const loadedConfiguration = await loadAppConfigurationFromState(state, app.specifications, app.remoteFlags ?? []) + + const loader = new AppLoader({ + loadedConfiguration, + previousApp: app, + }) + + return loader.loaded() +} + export async function loadAppUsingConfigurationState( configState: TConfig, { @@ -293,20 +309,20 @@ export async function loadDotEnv(appDirectory: string, configurationPath: string return dotEnvFile } -let alreadyShownCLIWarning = false - class AppLoader { private readonly mode: AppLoaderMode private readonly errors: AppErrors = new AppErrors() private readonly specifications: TModuleSpec[] private readonly remoteFlags: Flag[] private readonly loadedConfiguration: ConfigurationLoaderResult + private readonly previousApp: AppLinkedInterface | undefined - constructor({mode, loadedConfiguration}: AppLoaderConstructorArgs) { + constructor({mode, loadedConfiguration, previousApp}: AppLoaderConstructorArgs) { this.mode = mode ?? 'strict' this.specifications = loadedConfiguration.specifications this.remoteFlags = loadedConfiguration.remoteFlags this.loadedConfiguration = loadedConfiguration + this.previousApp = previousApp } async loaded() { @@ -319,15 +335,21 @@ class AppLoader { const websOfType = webs.filter((web) => web.configuration.roles.includes(webType)) @@ -647,6 +640,7 @@ We recommend removing the @shopify/cli and @shopify/app dependencies from your p ) // get all the keys from appConfiguration that aren't used by any of the results + const unusedKeys = Object.keys(appConfiguration) .filter((key) => !extensionInstancesWithKeys.some(([_, keys]) => keys.includes(key))) .filter((key) => { @@ -945,9 +939,7 @@ async function loadAppConfigurationFromState< case 'connected-app': { let gitTracked = false try { - gitTracked = !( - await checkIfIgnoredInGitRepository(configState.appDirectory, [configState.configurationPath]) - )[0] + gitTracked = await checkIfGitTracked(configState.appDirectory, configState.configurationPath) // eslint-disable-next-line no-catch-all/no-catch-all } catch { // leave as false @@ -975,6 +967,16 @@ async function loadAppConfigurationFromState< } } +async function checkIfGitTracked(appDirectory: string, configurationPath: string) { + const gitIgnorePath = joinPath(appDirectory, '.gitignore') + if (!fileExistsSync(gitIgnorePath)) return true + const gitIgnoreContent = await readFile(gitIgnorePath) + const ignored = ignore.default().add(gitIgnoreContent) + const relative = relativePath(appDirectory, configurationPath) + const isTracked = !ignored.ignores(relative) + return isTracked +} + async function getConfigurationPath(appDirectory: string, configName: string | undefined) { const configurationFileName = getAppConfigurationFileName(configName) const configurationPath = joinPath(appDirectory, configurationFileName) diff --git a/packages/app/src/cli/models/app/validation/multi-cli-warning.ts b/packages/app/src/cli/models/app/validation/multi-cli-warning.ts new file mode 100644 index 00000000000..6c94429040a --- /dev/null +++ b/packages/app/src/cli/models/app/validation/multi-cli-warning.ts @@ -0,0 +1,43 @@ +import {renderInfo} from '@shopify/cli-kit/node/ui' +import {currentProcessIsGlobal} from '@shopify/cli-kit/node/is-global' +import {globalCLIVersion, localCLIVersion} from '@shopify/cli-kit/node/version' +import {jsonOutputEnabled} from '@shopify/cli-kit/node/environment' +import {CLI_KIT_VERSION} from '@shopify/cli-kit/common/version' + +/** + * Shows a warning if there are two Shopify CLI installations found (global and local). + * Won't show anything if the user included the --json flag + * + * @param directory - The directory of the project. + * @param dependencies - The dependencies of the project. + */ +export async function showMultipleCLIWarningIfNeeded(directory: string, dependencies: {[key: string]: string}) { + if (!dependencies['@shopify/cli'] || jsonOutputEnabled()) return + + const isGlobal = currentProcessIsGlobal() + + // If running globally, use the current CLI version, otherwise fetch the global CLI version + // Exit early if we can't get the global version + const globalVersion = isGlobal ? CLI_KIT_VERSION : await globalCLIVersion() + if (!globalVersion) return + + // If running globally, fetch the local version from npm list, otherwise use current CLI version + // Exit early if we can't get the local version + const localVersion = isGlobal ? await localCLIVersion(directory) : CLI_KIT_VERSION + if (!localVersion) return + + const currentInstallation = isGlobal ? 'global installation' : 'local dependency' + + const warningContent = { + headline: `Two Shopify CLI installations found – using ${currentInstallation}`, + body: [ + `A global installation (v${globalVersion}) and a local dependency (v${localVersion}) were detected. +We recommend removing the @shopify/cli and @shopify/app dependencies from your package.json, unless you want to use different versions across multiple apps.`, + ], + link: { + label: 'See Shopify CLI documentation.', + url: 'https://shopify.dev/docs/apps/build/cli-for-apps#switch-to-a-global-executable-or-local-dependency', + }, + } + renderInfo(warningContent) +} diff --git a/packages/app/src/cli/models/extensions/extension-instance.test.ts b/packages/app/src/cli/models/extensions/extension-instance.test.ts index 4df163e4cd3..2faab64263d 100644 --- a/packages/app/src/cli/models/extensions/extension-instance.test.ts +++ b/packages/app/src/cli/models/extensions/extension-instance.test.ts @@ -32,7 +32,9 @@ function functionConfiguration(): FunctionConfigType { api_version: '2023-07', configuration_ui: true, metafields: [], - build: {}, + build: { + wasm_opt: true, + }, } } @@ -41,6 +43,7 @@ describe('watchPaths', async () => { const config = functionConfiguration() config.build = { watch: 'src/single-path.foo', + wasm_opt: true, } const extensionInstance = await testFunctionExtension({ config, @@ -54,7 +57,9 @@ describe('watchPaths', async () => { test('returns default paths for javascript', async () => { const config = functionConfiguration() - config.build = {} + config.build = { + wasm_opt: true, + } const extensionInstance = await testFunctionExtension({ config, entryPath: 'src/index.js', @@ -86,6 +91,7 @@ describe('watchPaths', async () => { const config = functionConfiguration() config.build = { watch: ['src/**/*.rs', 'src/**/*.foo'], + wasm_opt: true, } const extensionInstance = await testFunctionExtension({ config, @@ -103,7 +109,9 @@ describe('watchPaths', async () => { test('returns null if not javascript and not configured', async () => { const config = functionConfiguration() - config.build = {} + config.build = { + wasm_opt: true, + } const extensionInstance = await testFunctionExtension({ config, }) diff --git a/packages/app/src/cli/models/extensions/extension-instance.ts b/packages/app/src/cli/models/extensions/extension-instance.ts index 902c7e5562b..959e7323f66 100644 --- a/packages/app/src/cli/models/extensions/extension-instance.ts +++ b/packages/app/src/cli/models/extensions/extension-instance.ts @@ -255,7 +255,7 @@ export class ExtensionInstance string + getBundleExtensionStdinContent?: (config: TConfiguration) => {main: string; assets?: Asset[]} deployConfig?: ( config: TConfiguration, directory: string, diff --git a/packages/app/src/cli/models/extensions/specifications/function.test.ts b/packages/app/src/cli/models/extensions/specifications/function.test.ts index 7ab0c36a714..3dd0061228c 100644 --- a/packages/app/src/cli/models/extensions/specifications/function.test.ts +++ b/packages/app/src/cli/models/extensions/specifications/function.test.ts @@ -20,6 +20,7 @@ describe('functionConfiguration', () => { build: { command: 'make build', path: 'dist/index.wasm', + wasm_opt: true, }, ui: { paths: { diff --git a/packages/app/src/cli/models/extensions/specifications/function.ts b/packages/app/src/cli/models/extensions/specifications/function.ts index 9f900625701..3250c960d3d 100644 --- a/packages/app/src/cli/models/extensions/specifications/function.ts +++ b/packages/app/src/cli/models/extensions/specifications/function.ts @@ -25,6 +25,7 @@ const FunctionExtensionSchema = BaseSchema.extend({ .optional(), path: zod.string().optional(), watch: zod.union([zod.string(), zod.string().array()]).optional(), + wasm_opt: zod.boolean().optional().default(true), }), configuration_ui: zod.boolean().optional().default(true), ui: zod diff --git a/packages/app/src/cli/models/extensions/specifications/types/app_config.ts b/packages/app/src/cli/models/extensions/specifications/types/app_config.ts index 8ef18e65bff..a0b154f18df 100644 --- a/packages/app/src/cli/models/extensions/specifications/types/app_config.ts +++ b/packages/app/src/cli/models/extensions/specifications/types/app_config.ts @@ -13,6 +13,7 @@ import {WebhooksConfig} from './app_config_webhook.js' export interface AppConfigurationUsedByCli { name: string application_url: string + embedded: boolean app_proxy?: { url: string prefix: string diff --git a/packages/app/src/cli/models/extensions/specifications/ui_extension.test.ts b/packages/app/src/cli/models/extensions/specifications/ui_extension.test.ts index bd489a84ac3..2a7c88dced4 100644 --- a/packages/app/src/cli/models/extensions/specifications/ui_extension.test.ts +++ b/packages/app/src/cli/models/extensions/specifications/ui_extension.test.ts @@ -11,7 +11,27 @@ import {describe, expect, test, vi} from 'vitest' describe('ui_extension', async () => { interface GetUIExtensionProps { directory: string - extensionPoints?: {target: string; module: string; label?: string; default_placement_reference?: string}[] + extensionPoints?: { + target: string + module: string + label?: string + default_placement_reference?: string + should_render?: { + module: string + } + build_manifest?: { + assets: { + main: { + filepath: string + module: string + } + should_render?: { + filepath: string + module: string + } + } + } + }[] } async function getTestUIExtension({directory, extensionPoints}: GetUIExtensionProps) { @@ -82,9 +102,13 @@ describe('ui_extension', async () => { { target: 'EXTENSION::POINT::A', module: './src/ExtensionPointA.js', + should_render: { + module: './src/ShouldRender.js', + }, }, ], api_version: '2023-01' as const, + handle: 'test-ui-extension', name: 'UI Extension', description: 'This is an ordinary test extension', type: 'ui_extension', @@ -121,6 +145,18 @@ describe('ui_extension', async () => { default_placement_reference: undefined, capabilities: undefined, preloads: {}, + build_manifest: { + assets: { + main: { + filepath: 'test-ui-extension.js', + module: './src/ExtensionPointA.js', + }, + should_render: { + filepath: 'test-ui-extension-conditions.js', + module: './src/ShouldRender.js', + }, + }, + }, }, ]) }) @@ -140,6 +176,7 @@ describe('ui_extension', async () => { name: 'UI Extension', description: 'This is an ordinary test extension', type: 'ui_extension', + handle: 'test-ui-extension', capabilities: { block_progress: false, network_access: false, @@ -172,6 +209,14 @@ describe('ui_extension', async () => { default_placement_reference: 'PLACEMENT_REFERENCE1', capabilities: undefined, preloads: {}, + build_manifest: { + assets: { + main: { + filepath: 'test-ui-extension.js', + module: './src/ExtensionPointA.js', + }, + }, + }, }, ]) }) @@ -191,6 +236,7 @@ describe('ui_extension', async () => { name: 'UI Extension', description: 'This is an ordinary test extension', type: 'ui_extension', + handle: 'test-ui-extension', capabilities: { block_progress: false, network_access: false, @@ -223,6 +269,14 @@ describe('ui_extension', async () => { default_placement_reference: undefined, capabilities: {allow_direct_linking: true}, preloads: {}, + build_manifest: { + assets: { + main: { + filepath: 'test-ui-extension.js', + module: './src/ExtensionPointA.js', + }, + }, + }, }, ]) }) @@ -242,6 +296,70 @@ describe('ui_extension', async () => { name: 'UI Extension', description: 'This is an ordinary test extension', type: 'ui_extension', + handle: 'test-ui-extension', + capabilities: { + block_progress: false, + network_access: false, + api_access: false, + collect_buyer_consent: { + customer_privacy: true, + sms_marketing: false, + }, + iframe: { + sources: [], + }, + }, + settings: {}, + } + + // When + const parsed = specification.parseConfigurationObject(configuration) + if (parsed.state !== 'ok') { + throw new Error("Couldn't parse configuration") + } + + const got = parsed.data + + // Then + expect(got.extension_points).toStrictEqual([ + { + target: 'EXTENSION::POINT::A', + module: './src/ExtensionPointA.js', + metafields: [], + default_placement_reference: undefined, + capabilities: undefined, + preloads: {chat: '/chat'}, + build_manifest: { + assets: { + main: { + filepath: 'test-ui-extension.js', + module: './src/ExtensionPointA.js', + }, + }, + }, + }, + ]) + }) + + test('build_manifest includes should_render asset when should_render.module is present', async () => { + const allSpecs = await loadLocalExtensionsSpecifications() + const specification = allSpecs.find((spec) => spec.identifier === 'ui_extension')! + const configuration = { + targeting: [ + { + target: 'EXTENSION::POINT::A', + module: './src/ExtensionPointA.js', + should_render: { + module: './src/ShouldRender.js', + }, + preloads: {chat: '/chat', not_supported: '/hello'}, + }, + ], + api_version: '2023-01' as const, + name: 'UI Extension', + description: 'This is an ordinary test extension', + type: 'ui_extension', + handle: 'test-ui-extension', capabilities: { block_progress: false, network_access: false, @@ -274,6 +392,18 @@ describe('ui_extension', async () => { default_placement_reference: undefined, capabilities: undefined, preloads: {chat: '/chat'}, + build_manifest: { + assets: { + main: { + filepath: 'test-ui-extension.js', + module: './src/ExtensionPointA.js', + }, + should_render: { + filepath: 'test-ui-extension-conditions.js', + module: './src/ShouldRender.js', + }, + }, + }, }, ]) }) @@ -392,6 +522,14 @@ Please check the configuration in ${uiExtension.configurationPath}`), { target: 'EXTENSION::POINT::A', module: './src/ExtensionPointA.js', + build_manifest: { + assets: { + main: { + filepath: 'test-ui-extension.js', + module: './src/ExtensionPointA.js', + }, + }, + }, }, ], }) @@ -406,7 +544,18 @@ Please check the configuration in ${uiExtension.configurationPath}`), expect(loadLocales.loadLocalesConfig).toBeCalledWith(tmpDir, uiExtension.configuration.type) expect(deployConfig).toStrictEqual({ localization, - extension_points: uiExtension.configuration.extension_points, + extension_points: uiExtension.configuration.extension_points?.map((extPoint) => ({ + ...extPoint, + build_manifest: { + ...extPoint.build_manifest, + assets: { + main: { + filepath: 'dist/test-ui-extension.js', + module: extPoint.module, + }, + }, + }, + })), // Ensure nested capabilities are updated capabilities: { @@ -437,16 +586,32 @@ Please check the configuration in ${uiExtension.configurationPath}`), { target: 'EXTENSION::POINT::A', module: './src/ExtensionPointA.js', + build_manifest: { + assets: { + main: { + module: './src/ExtensionPointA.js', + filepath: '/test-ui-extension.js', + }, + }, + }, }, { target: 'EXTENSION::POINT::B', module: './src/ExtensionPointB.js', + build_manifest: { + assets: { + main: { + module: './src/ExtensionPointB.js', + filepath: '/test-ui-extension.js', + }, + }, + }, }, ], }) // When - const stdInContent = uiExtension.getBundleExtensionStdinContent() + const stdInContent = uiExtension.getBundleExtensionStdinContent().main // Then expect(stdInContent).toContain(`import './src/ExtensionPointA.js';`) diff --git a/packages/app/src/cli/models/extensions/specifications/ui_extension.ts b/packages/app/src/cli/models/extensions/specifications/ui_extension.ts index a36c6a8a0d1..36d03f35199 100644 --- a/packages/app/src/cli/models/extensions/specifications/ui_extension.ts +++ b/packages/app/src/cli/models/extensions/specifications/ui_extension.ts @@ -1,4 +1,4 @@ -import {ExtensionFeature, createExtensionSpecification} from '../specification.js' +import {Asset, AssetIdentifier, ExtensionFeature, createExtensionSpecification} from '../specification.js' import {NewExtensionPointSchemaType, NewExtensionPointsSchema, BaseSchema} from '../schemas.js' import {loadLocalesConfig} from '../../../utilities/extensions/locales-configuration.js' import {getExtensionPointTargetSurface} from '../../../services/dev/extension/utilities.js' @@ -14,6 +14,21 @@ const validatePoints = (config: {extension_points?: unknown[]; targeting?: unkno return config.extension_points !== undefined || config.targeting !== undefined } +export interface BuildManifest { + assets: { + // Main asset is always required + [AssetIdentifier.Main]: { + filepath: string + module?: string + } + } & { + [key in AssetIdentifier]?: { + filepath: string + module?: string + } + } +} + const missingExtensionPointsMessage = 'No extension targets defined, add a `targeting` field to your configuration' export type UIExtensionSchemaType = zod.infer @@ -25,6 +40,23 @@ export const UIExtensionSchema = BaseSchema.extend({ .refine((config) => validatePoints(config), missingExtensionPointsMessage) .transform((config) => { const extensionPoints = (config.targeting ?? config.extension_points ?? []).map((targeting) => { + const buildManifest: BuildManifest = { + assets: { + [AssetIdentifier.Main]: { + filepath: `${config.handle}.js`, + module: targeting.module, + }, + ...(targeting.should_render?.module + ? { + [AssetIdentifier.ShouldRender]: { + filepath: `${config.handle}-conditions.js`, + module: targeting.should_render.module, + }, + } + : null), + }, + } + return { target: targeting.target, module: targeting.module, @@ -32,6 +64,7 @@ export const UIExtensionSchema = BaseSchema.extend({ default_placement_reference: targeting.default_placement, capabilities: targeting.capabilities, preloads: targeting.preloads ?? {}, + build_manifest: buildManifest, } }) return {...config, extension_points: extensionPoints} @@ -53,9 +86,11 @@ const uiExtensionSpec = createExtensionSpecification({ return validateUIExtensionPointConfig(directory, config.extension_points, path) }, deployConfig: async (config, directory) => { + const transformedExtensionPoints = config.extension_points.map(addDistPathToAssets) + return { api_version: config.api_version, - extension_points: config.extension_points, + extension_points: transformedExtensionPoints, capabilities: config.capabilities, name: config.name, description: config.description, @@ -64,7 +99,33 @@ const uiExtensionSpec = createExtensionSpecification({ } }, getBundleExtensionStdinContent: (config) => { - return config.extension_points.map(({module}) => `import '${module}';`).join('\n') + const main = config.extension_points + .map(({module}) => { + return `import '${module}'; ` + }) + .join('\n') + + const assets: {[key: string]: Asset} = {} + config.extension_points.forEach((extensionPoint) => { + // Start of Selection + Object.entries(extensionPoint.build_manifest.assets).forEach(([identifier, asset]) => { + if (identifier === AssetIdentifier.Main) { + return + } + + assets[identifier] = { + identifier: identifier as AssetIdentifier, + outputFileName: asset.filepath, + content: `import '${asset.module}'`, + } + }) + }) + + const assetsArray = Object.values(assets) + return { + main, + ...(assetsArray.length ? {assets: assetsArray} : {}), + } }, hasExtensionPointTarget: (config, requestedTarget) => { return ( @@ -75,6 +136,24 @@ const uiExtensionSpec = createExtensionSpecification({ }, }) +function addDistPathToAssets(extP: NewExtensionPointSchemaType & {build_manifest: BuildManifest}) { + return { + ...extP, + build_manifest: { + ...extP.build_manifest, + assets: Object.fromEntries( + Object.entries(extP.build_manifest.assets).map(([key, value]) => [ + key as AssetIdentifier, + { + ...value, + filepath: joinPath('dist', value.filepath), + }, + ]), + ), + }, + } +} + async function validateUIExtensionPointConfig( directory: string, extensionPoints: NewExtensionPointSchemaType[], diff --git a/packages/app/src/cli/models/organization.ts b/packages/app/src/cli/models/organization.ts index dee33504d99..65c46185273 100644 --- a/packages/app/src/cli/models/organization.ts +++ b/packages/app/src/cli/models/organization.ts @@ -12,12 +12,15 @@ export interface Organization { source?: OrganizationSource } -export interface MinimalAppIdentifiers { - id: string +export interface AppApiKeyAndOrgId { apiKey: string organizationId: string } +export type MinimalAppIdentifiers = AppApiKeyAndOrgId & { + id: string +} + export type MinimalOrganizationApp = MinimalAppIdentifiers & { title: string } diff --git a/packages/app/src/cli/services/admin-link/extension-to-toml.test.ts b/packages/app/src/cli/services/admin-link/extension-to-toml.test.ts index eed9408d858..e9dde53e4ec 100644 --- a/packages/app/src/cli/services/admin-link/extension-to-toml.test.ts +++ b/packages/app/src/cli/services/admin-link/extension-to-toml.test.ts @@ -3,8 +3,16 @@ import {ExtensionRegistration} from '../../api/graphql/all_app_extension_registr import {describe, expect, test} from 'vitest' describe('extension-to-toml', () => { - test('correctly builds a toml string for a app_link', () => { + test('correctly builds a toml string for a app_link extension on a non embedded app', () => { // Given + const appConfig = { + path: '', + name: 'app 1', + client_id: '12345', + application_url: 'http://example.com', + embedded: false, + } + const extension1: ExtensionRegistration = { id: '26237698049', uuid: 'ad9947a9-bc0b-4855-82da-008aefbc1c71', @@ -12,28 +20,34 @@ describe('extension-to-toml', () => { type: 'app_link', draftVersion: { context: 'COLLECTIONS#SHOW', - config: '{"text":"admin link label","url":"https://google.es"}', + config: '{"text":"Admin link label","url":"https://google.es"}', }, } // When - const got = buildTomlObject(extension1) + const got = buildTomlObject(extension1, [], appConfig) // Then expect(got).toEqual(`[[extensions]] type = "admin_link" -name = "Admin link title" +name = "Admin link label" handle = "admin-link-title" [[extensions.targeting]] - text = "admin link label" url = "https://google.es" - target = "admin.collection.item.link" + target = "admin.collection-details.action.link" `) }) - test('correctly builds a toml string for a bulk_action', () => { + test('correctly builds a toml string for bulk_action extension with path in an embedded app', () => { // Given + const appConfig = { + path: '', + name: 'app 1', + client_id: '12345', + application_url: 'http://example.com', + embedded: true, + } const extension1: ExtensionRegistration = { id: '26237698049', uuid: 'ad9947a9-bc0b-4855-82da-008aefbc1c71', @@ -41,23 +55,90 @@ handle = "admin-link-title" type: 'bulk_action', draftVersion: { context: 'PRODUCTS#ACTION', - config: '{"text":"bulk action label","url":"https://google.es"}', + config: '{"text":"Bulk action label","url":"https://google.es/action/product?product_id=123#hash"}', }, } // When - const got = buildTomlObject(extension1) + const got = buildTomlObject(extension1, [], appConfig) // Then expect(got).toEqual(`[[extensions]] type = "admin_link" -name = "Bulk action title" +name = "Bulk action label" handle = "bulk-action-title" [[extensions.targeting]] - text = "bulk action label" - url = "https://google.es" - target = "admin.product.selection.link" + url = "app://action/product?product_id=123#hash" + target = "admin.product-index.selection-action.link" +`) + }) + test('correctly builds a toml string for bulk_action extension with no path in an embedded app', () => { + // Given + const appConfig = { + path: '', + name: 'app 1', + client_id: '12345', + application_url: 'http://example.com', + embedded: true, + } + const extension1: ExtensionRegistration = { + id: '26237698049', + uuid: 'ad9947a9-bc0b-4855-82da-008aefbc1c71', + title: 'Bulk action title', + type: 'bulk_action', + draftVersion: { + context: 'PRODUCTS#ACTION', + config: '{"text":"Bulk action label","url":"https://google.es/"}', + }, + } + + // When + const got = buildTomlObject(extension1, [], appConfig) + + // Then + expect(got).toEqual(`[[extensions]] +type = "admin_link" +name = "Bulk action label" +handle = "bulk-action-title" + + [[extensions.targeting]] + url = "app://" + target = "admin.product-index.selection-action.link" +`) + }) + test('correctly builds a toml string for bulk_action extension with no path but search query in an embedded app', () => { + // Given + const appConfig = { + path: '', + name: 'app 1', + client_id: '12345', + application_url: 'http://example.com', + embedded: true, + } + const extension1: ExtensionRegistration = { + id: '26237698049', + uuid: 'ad9947a9-bc0b-4855-82da-008aefbc1c71', + title: 'Bulk action title', + type: 'bulk_action', + draftVersion: { + context: 'PRODUCTS#ACTION', + config: '{"text":"Bulk action label","url":"https://google.es?foo=bar"}', + }, + } + + // When + const got = buildTomlObject(extension1, [], appConfig) + + // Then + expect(got).toEqual(`[[extensions]] +type = "admin_link" +name = "Bulk action label" +handle = "bulk-action-title" + + [[extensions.targeting]] + url = "app://?foo=bar" + target = "admin.product-index.selection-action.link" `) }) }) diff --git a/packages/app/src/cli/services/admin-link/extension-to-toml.ts b/packages/app/src/cli/services/admin-link/extension-to-toml.ts index 319fc00d8ff..7c0d5faa7ac 100644 --- a/packages/app/src/cli/services/admin-link/extension-to-toml.ts +++ b/packages/app/src/cli/services/admin-link/extension-to-toml.ts @@ -1,6 +1,7 @@ import {contextToTarget} from './utils.js' import {ExtensionRegistration} from '../../api/graphql/all_app_extension_registrations.js' import {MAX_EXTENSION_HANDLE_LENGTH} from '../../models/extensions/schemas.js' +import {CurrentAppConfiguration} from '../../models/app/app.js' import {encodeToml} from '@shopify/cli-kit/node/toml' import {slugify} from '@shopify/cli-kit/common/string' @@ -12,7 +13,11 @@ interface AdminLinkConfig { /** * Given an app_link or bulk_action extension config file, convert it to toml */ -export function buildTomlObject(extension: ExtensionRegistration): string { +export function buildTomlObject( + extension: ExtensionRegistration, + _: ExtensionRegistration[], + appConfiguration: CurrentAppConfiguration, +): string { const versionConfig = extension.activeVersion?.config ?? extension.draftVersion?.config if (!versionConfig) throw new Error('No config found for extension') @@ -21,15 +26,28 @@ export function buildTomlObject(extension: ExtensionRegistration): string { const config: AdminLinkConfig = JSON.parse(versionConfig) + if (appConfiguration.embedded) { + try { + const linkUrl = new URL(config.url) + const linkPath = linkUrl.pathname.startsWith('/') ? linkUrl.pathname.substring(1) : linkUrl.pathname + const fullUrl = new URL(`app://${linkPath}`) + fullUrl.search = linkUrl.search + fullUrl.hash = linkUrl.hash + config.url = fullUrl.toString() + // eslint-disable-next-line no-catch-all/no-catch-all + } catch (error) { + // Keep original URL if parsing fails + } + } + const localExtensionRepresentation = { extensions: [ { type: 'admin_link', - name: extension.title, + name: config.text, handle: slugify(extension.title.substring(0, MAX_EXTENSION_HANDLE_LENGTH)), targeting: [ { - text: config.text, url: config.url, target: contextToTarget(context), }, diff --git a/packages/app/src/cli/services/admin-link/utils.test.ts b/packages/app/src/cli/services/admin-link/utils.test.ts index a1c0441a14c..e15053d0791 100644 --- a/packages/app/src/cli/services/admin-link/utils.test.ts +++ b/packages/app/src/cli/services/admin-link/utils.test.ts @@ -10,7 +10,7 @@ describe('admin link utils', () => { const target = contextToTarget(context) // Then - expect(target).toEqual('admin.collection.item.link') + expect(target).toEqual('admin.collection-details.action.link') }) test('correctly parses from context `ORDERS#INDEX` to target', () => { // Given @@ -20,6 +20,26 @@ describe('admin link utils', () => { const target = contextToTarget(context) // Then - expect(target).toEqual('admin.order.index.link') + expect(target).toEqual('admin.order-index.action.link') + }) + test('correctly parses from context `CUSTOMERS#ACTION` to target', () => { + // Given + const context = 'CUSTOMERS#ACTION' + + // When + const target = contextToTarget(context) + + // Then + expect(target).toEqual('admin.customer-index.selection-action.link') + }) + test('correctly parses from context `DRAFT_ORDERS#SHOW` to target', () => { + // Given + const context = 'DRAFT_ORDERS#SHOW' + + // When + const target = contextToTarget(context) + + // Then + expect(target).toEqual('admin.draft-order-details.action.link') }) }) diff --git a/packages/app/src/cli/services/admin-link/utils.ts b/packages/app/src/cli/services/admin-link/utils.ts index 544828e09ae..67b064f194b 100644 --- a/packages/app/src/cli/services/admin-link/utils.ts +++ b/packages/app/src/cli/services/admin-link/utils.ts @@ -1,30 +1,41 @@ +import {hyphenate} from '@shopify/cli-kit/common/string' + export const contextToTarget = (context: string) => { const splitContext = context.split('#') if (splitContext.length !== 2 || splitContext.some((part) => part === '' || part === undefined)) { throw new Error('Invalid context') } const domain = 'admin' - const subDomain = typeToSubDomain(splitContext[0] || '') - const entity = locationToEntity(splitContext[1] || '') + const subDomain = typeToSubDomain(splitContext[0] ?? '') + const entity = locationToEntity(splitContext[1] ?? '') const action = 'link' - return [domain, subDomain, entity, action].join('.') + if (entity === 'selection') { + return [domain, `${subDomain}-index`, `${entity}-action`, action].join('.') + } else { + return [domain, `${subDomain}-${entity}`, 'action', action].join('.') + } } const locationToEntity = (location: string) => { switch (location.toLocaleLowerCase()) { case 'show': - return 'item' + return 'details' case 'index': return 'index' case 'action': return 'selection' case 'fulfilled_card': - return 'fulfilled_card' + return 'fulfilled-card' default: throw new Error(`Invalid context location: ${location}`) } } -const typeToSubDomain = (word: string) => { - return word.toLocaleLowerCase().replace(new RegExp(`(s)$`), '') +const typeToSubDomain = (type: string) => { + switch (type.toLocaleLowerCase()) { + case 'variants': + return 'product-variant' + default: + return hyphenate(type.toLocaleLowerCase().replace(new RegExp(`(s)$`), '')) + } } diff --git a/packages/app/src/cli/services/app-context.test.ts b/packages/app/src/cli/services/app-context.test.ts index 91ef8dfae20..c6bc55bbcd5 100644 --- a/packages/app/src/cli/services/app-context.test.ts +++ b/packages/app/src/cli/services/app-context.test.ts @@ -1,7 +1,7 @@ import {linkedAppContext} from './app-context.js' import {fetchSpecifications} from './generate/fetch-extension-specifications.js' import link from './app/config/link.js' -import {appFromId} from './context.js' +import {appFromIdentifiers} from './context.js' import * as localStorage from './local-storage.js' import {fetchOrgFromId} from './dev/fetch.js' @@ -13,10 +13,12 @@ import {inTemporaryDirectory, writeFile} from '@shopify/cli-kit/node/fs' import {joinPath} from '@shopify/cli-kit/node/path' import {tryParseInt} from '@shopify/cli-kit/common/string' +vi.mock('../models/app/validation/multi-cli-warning.js') vi.mock('./generate/fetch-extension-specifications.js') vi.mock('./app/config/link.js') vi.mock('./context.js') vi.mock('./dev/fetch.js') + async function writeAppConfig(tmp: string, content: string) { const appConfigPath = joinPath(tmp, 'shopify.app.toml') const packageJsonPath = joinPath(tmp, 'package.json') @@ -35,7 +37,7 @@ const mockRemoteApp = testOrganizationApp({ beforeEach(() => { vi.mocked(fetchSpecifications).mockResolvedValue([]) - vi.mocked(appFromId).mockResolvedValue(mockRemoteApp) + vi.mocked(appFromIdentifiers).mockResolvedValue(mockRemoteApp) vi.mocked(fetchOrgFromId).mockResolvedValue(mockOrganization) }) @@ -92,6 +94,7 @@ describe('linkedAppContext', () => { name: 'test-app', application_url: 'https://test-app.com', path: joinPath(tmp, 'shopify.app.toml'), + embedded: false, }, }) @@ -118,7 +121,7 @@ describe('linkedAppContext', () => { test('updates cached app info when remoteApp matches', async () => { await inTemporaryDirectory(async (tmp) => { // Given - vi.mocked(appFromId).mockResolvedValue({...mockRemoteApp, apiKey: 'test-api-key-new'}) + vi.mocked(appFromIdentifiers).mockResolvedValue({...mockRemoteApp, apiKey: 'test-api-key-new'}) const content = `client_id="test-api-key-new"` await writeAppConfig(tmp, content) localStorage.setCachedAppInfo({ @@ -156,7 +159,7 @@ describe('linkedAppContext', () => { await writeAppConfig(tmp, content) const newClientId = 'new-api-key' - vi.mocked(appFromId).mockResolvedValue({...mockRemoteApp, apiKey: newClientId}) + vi.mocked(appFromIdentifiers).mockResolvedValue({...mockRemoteApp, apiKey: newClientId}) // When const result = await linkedAppContext({ @@ -170,7 +173,7 @@ describe('linkedAppContext', () => { expect(link).not.toHaveBeenCalled() expect(result.remoteApp.apiKey).toBe(newClientId) expect(result.app.configuration.client_id).toEqual('new-api-key') - expect(appFromId).toHaveBeenCalledWith(expect.objectContaining({apiKey: newClientId})) + expect(appFromIdentifiers).toHaveBeenCalledWith(expect.objectContaining({apiKey: newClientId})) }) }) @@ -195,6 +198,7 @@ describe('linkedAppContext', () => { name: 'test-app', application_url: 'https://test-app.com', path: joinPath(tmp, 'shopify.app.toml'), + embedded: false, }, }) diff --git a/packages/app/src/cli/services/app-context.ts b/packages/app/src/cli/services/app-context.ts index 47b0dc08741..db2888d3f58 100644 --- a/packages/app/src/cli/services/app-context.ts +++ b/packages/app/src/cli/services/app-context.ts @@ -1,4 +1,4 @@ -import {appFromId} from './context.js' +import {appFromIdentifiers} from './context.js' import {getCachedAppInfo, setCachedAppInfo} from './local-storage.js' import {fetchSpecifications} from './generate/fetch-extension-specifications.js' import link from './app/config/link.js' @@ -74,8 +74,7 @@ export async function linkedAppContext({ if (!remoteApp) { const apiKey = configState.basicConfiguration.client_id const organizationId = configState.basicConfiguration.organization_id - const id = configState.basicConfiguration.app_id - remoteApp = await appFromId({apiKey, developerPlatformClient, organizationId, id}) + remoteApp = await appFromIdentifiers({apiKey, developerPlatformClient, organizationId}) } developerPlatformClient = remoteApp.developerPlatformClient ?? developerPlatformClient diff --git a/packages/app/src/cli/services/app/config/link-service.test.ts b/packages/app/src/cli/services/app/config/link-service.test.ts index e1f400e47e5..258ede171dc 100644 --- a/packages/app/src/cli/services/app/config/link-service.test.ts +++ b/packages/app/src/cli/services/app/config/link-service.test.ts @@ -1,7 +1,7 @@ import link from './link.js' import {testOrganizationApp, testDeveloperPlatformClient} from '../../../models/app/app.test-data.js' import {DeveloperPlatformClient, selectDeveloperPlatformClient} from '../../../utilities/developer-platform-client.js' -import {MinimalAppIdentifiers, OrganizationApp} from '../../../models/organization.js' +import {AppApiKeyAndOrgId, OrganizationApp} from '../../../models/organization.js' import {appNamePrompt, createAsNewAppPrompt, selectOrganizationPrompt} from '../../../prompts/dev.js' import {beforeEach, describe, expect, test, vi} from 'vitest' import {inTemporaryDirectory, readFile, writeFileSync} from '@shopify/cli-kit/node/fs' @@ -13,12 +13,12 @@ vi.mock('../../local-storage') vi.mock('@shopify/cli-kit/node/ui') vi.mock('../../dev/fetch.js') vi.mock('../../../utilities/developer-platform-client.js') - +vi.mock('../../../models/app/validation/multi-cli-warning.js') beforeEach(async () => {}) function buildDeveloperPlatformClient(): DeveloperPlatformClient { return testDeveloperPlatformClient({ - async appFromId({apiKey}: MinimalAppIdentifiers): Promise { + async appFromIdentifiers({apiKey}: AppApiKeyAndOrgId): Promise { switch (apiKey) { case 'api-key': return testOrganizationApp({developerPlatformClient: this as DeveloperPlatformClient}) @@ -89,7 +89,6 @@ embedded = false ` expect(configuration).toEqual({ client_id: 'api-key', - app_id: '1', name: 'app1', application_url: '', embedded: true, diff --git a/packages/app/src/cli/services/app/config/link.test.ts b/packages/app/src/cli/services/app/config/link.test.ts index 0c560693bfa..7bc7f61bc81 100644 --- a/packages/app/src/cli/services/app/config/link.test.ts +++ b/packages/app/src/cli/services/app/config/link.test.ts @@ -8,12 +8,12 @@ import { } from '../../../models/app/app.test-data.js' import {selectConfigName} from '../../../prompts/config.js' import {loadApp} from '../../../models/app/loader.js' -import {InvalidApiKeyErrorMessage, fetchOrCreateOrganizationApp, appFromId} from '../../context.js' +import {InvalidApiKeyErrorMessage, fetchOrCreateOrganizationApp, appFromIdentifiers} from '../../context.js' import {getCachedCommandInfo} from '../../local-storage.js' import {AppInterface, CurrentAppConfiguration} from '../../../models/app/app.js' import {fetchAppRemoteConfiguration} from '../select-app.js' import {DeveloperPlatformClient} from '../../../utilities/developer-platform-client.js' -import {MinimalAppIdentifiers, OrganizationApp} from '../../../models/organization.js' +import {MinimalAppIdentifiers, AppApiKeyAndOrgId, OrganizationApp} from '../../../models/organization.js' import {beforeEach, describe, expect, test, vi} from 'vitest' import {fileExistsSync, inTemporaryDirectory, readFile, writeFileSync} from '@shopify/cli-kit/node/fs' import {joinPath} from '@shopify/cli-kit/node/path' @@ -49,7 +49,7 @@ const DEFAULT_REMOTE_CONFIGURATION = { function buildDeveloperPlatformClient(): DeveloperPlatformClient { return testDeveloperPlatformClient({ - async appFromId({apiKey}: MinimalAppIdentifiers): Promise { + async appFromIdentifiers({apiKey}: AppApiKeyAndOrgId): Promise { switch (apiKey) { case 'api-key': return testOrganizationApp({developerPlatformClient: this as DeveloperPlatformClient}) @@ -85,7 +85,6 @@ describe('link', () => { expect(fileExistsSync(joinPath(tmp, 'shopify.app.default-value.toml'))).toBeTruthy() expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', extension_directories: [], application_url: 'https://example.com', @@ -165,7 +164,6 @@ embedded = false ` expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', extension_directories: [], application_url: 'https://example.com', @@ -274,7 +272,6 @@ embedded = false }) expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', application_url: 'https://example.com', embedded: true, @@ -407,7 +404,6 @@ url = "https://api-client-config.com/preferences" }) expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'new-title', application_url: 'https://api-client-config.com', embedded: false, @@ -539,7 +535,6 @@ embedded = false }) expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'my app', application_url: 'https://myapp.com', embedded: true, @@ -582,11 +577,12 @@ test('the local configuration is discarded if the client_id is different from th scopes: 'write_products', webhooks: {api_version: '2023-04'}, application_url: 'https://myapp.com', + embedded: false, build: { automatically_update_urls_on_dev: true, dev_store_url: 'my-store.myshopify.com', }, - } as CurrentAppConfiguration, + }, } vi.mocked(loadApp).mockResolvedValue(await mockApp(tmp, localApp, [], 'current')) vi.mocked(fetchOrCreateOrganizationApp).mockResolvedValue( @@ -631,7 +627,6 @@ embedded = false ` expect(configuration).toEqual({ client_id: 'different-api-key', - app_id: '1', name: 'my app', application_url: 'https://myapp.com', embedded: true, @@ -712,7 +707,6 @@ embedded = false }) expect(configuration).toEqual({ client_id: '12345', - app_id: '1', extension_directories: [], name: 'app1', application_url: 'https://example.com', @@ -779,7 +773,6 @@ embedded = false expect(renderSuccess).not.toHaveBeenCalled() expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', application_url: 'https://example.com', embedded: true, @@ -813,8 +806,8 @@ test('fetches the remote app when an api key is provided', async () => { } vi.mocked(loadApp).mockResolvedValue(await mockApp(tmp)) vi.mocked(selectConfigName).mockResolvedValue('shopify.app.staging.toml') - vi.mocked(appFromId).mockImplementation(async ({apiKey}: {apiKey: string}) => { - return (await developerPlatformClient.appFromId({id: apiKey, apiKey, organizationId: '1'}))! + vi.mocked(appFromIdentifiers).mockImplementation(async ({apiKey}: {apiKey: string}) => { + return (await developerPlatformClient.appFromIdentifiers({apiKey, organizationId: '1'}))! }) // When @@ -825,7 +818,6 @@ test('fetches the remote app when an api key is provided', async () => { expect(content).toContain('name = "app1"') expect(configuration).toEqual({ client_id: 'api-key', - app_id: '1', extension_directories: [], name: 'app1', application_url: 'https://example.com', @@ -933,7 +925,6 @@ embedded = false ` expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', application_url: 'https://example.com', embedded: true, @@ -995,7 +986,6 @@ embedded = false expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', application_url: 'https://example.com', embedded: true, @@ -1062,7 +1052,6 @@ embedded = false expect(configuration).toEqual({ client_id: '12345', - app_id: '1', extension_directories: [], name: 'app1', application_url: 'https://example.com', @@ -1185,7 +1174,6 @@ embedded = false }) expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', application_url: 'https://example.com', embedded: true, @@ -1310,7 +1298,6 @@ embedded = false expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', application_url: 'https://my-app-url.com', embedded: true, @@ -1358,7 +1345,8 @@ test('the api client configuration is deep merged with the remote app_config ext api_version: '2023-04', }, application_url: 'https://myapp.com', - } as CurrentAppConfiguration, + embedded: true, + }, } vi.mocked(loadApp).mockResolvedValue(await mockApp(tmp, localApp, [], 'current')) vi.mocked(fetchOrCreateOrganizationApp).mockResolvedValue( diff --git a/packages/app/src/cli/services/app/config/link.ts b/packages/app/src/cli/services/app/config/link.ts index a10bc64ed5a..2d147f594b7 100644 --- a/packages/app/src/cli/services/app/config/link.ts +++ b/packages/app/src/cli/services/app/config/link.ts @@ -20,7 +20,7 @@ import { import { fetchOrCreateOrganizationApp, logMetadataForLoadedContext, - appFromId, + appFromIdentifiers, InvalidApiKeyErrorMessage, } from '../../context.js' import { @@ -135,7 +135,7 @@ async function selectOrCreateRemoteAppToLinkTo(options: LinkOptions): Promise<{ if (options.apiKey) { // Remote API Key provided by the caller, so use that app specifically - const remoteApp = await appFromId({ + const remoteApp = await appFromIdentifiers({ apiKey: options.apiKey, id: options.appId, developerPlatformClient, @@ -387,7 +387,6 @@ async function overwriteLocalConfigFileWithRemoteAppConfiguration(options: { ...(localAppOptions.existingConfig ?? {}), }, { - app_id: remoteApp.id, client_id: remoteApp.apiKey, path: configFilePath, ...(developerPlatformClient.requiresOrganization ? {organization_id: remoteApp.organizationId} : {}), diff --git a/packages/app/src/cli/services/app/config/use.test.ts b/packages/app/src/cli/services/app/config/use.test.ts index 0adddfb0b4a..d8069bc188c 100644 --- a/packages/app/src/cli/services/app/config/use.test.ts +++ b/packages/app/src/cli/services/app/config/use.test.ts @@ -9,7 +9,7 @@ import { import {getAppConfigurationFileName, loadAppConfiguration} from '../../../models/app/loader.js' import {clearCurrentConfigFile, setCachedAppInfo} from '../../local-storage.js' import {selectConfigFile} from '../../../prompts/config.js' -import {appFromId, logMetadataForLoadedContext} from '../../context.js' +import {appFromIdentifiers, logMetadataForLoadedContext} from '../../context.js' import {describe, expect, test, vi} from 'vitest' import {inTemporaryDirectory, writeFileSync} from '@shopify/cli-kit/node/fs' import {joinPath} from '@shopify/cli-kit/node/path' @@ -303,7 +303,7 @@ describe('use', () => { remoteFlags: [], }) vi.mocked(getAppConfigurationFileName).mockReturnValue('shopify.app.something.toml') - vi.mocked(appFromId).mockResolvedValue(REMOTE_APP) + vi.mocked(appFromIdentifiers).mockResolvedValue(REMOTE_APP) createConfigFile(directory, 'shopify.app.something.toml') const options = {directory, configName: 'something', developerPlatformClient: testDeveloperPlatformClient()} diff --git a/packages/app/src/cli/services/app/write-app-configuration-file.test.ts b/packages/app/src/cli/services/app/write-app-configuration-file.test.ts index 2931fb28139..2506dc3cbd8 100644 --- a/packages/app/src/cli/services/app/write-app-configuration-file.test.ts +++ b/packages/app/src/cli/services/app/write-app-configuration-file.test.ts @@ -149,51 +149,4 @@ url = "https://example.com/prefs" expect(content).toContain('redirect_urls') }) }) - - test('includes app_id if organization_id is present', async () => { - await inTemporaryDirectory(async (tmp) => { - // Given - const filePath = joinPath(tmp, 'shopify.app.toml') - const {schema} = await buildVersionedAppSchema() - - // When - await writeAppConfigurationFile( - { - ...FULL_CONFIGURATION, - app_id: '1234', - organization_id: '1', - path: filePath, - } as CurrentAppConfiguration, - schema, - ) - - // Then - const content = await readFile(filePath) - expect(content).toContain('app_id') - expect(content).toContain('organization_id') - }) - }) - - test('does not include app_id if organization_id is absent', async () => { - await inTemporaryDirectory(async (tmp) => { - // Given - const filePath = joinPath(tmp, 'shopify.app.toml') - const {schema} = await buildVersionedAppSchema() - - // When - await writeAppConfigurationFile( - { - ...FULL_CONFIGURATION, - app_id: '1234', - path: filePath, - } as CurrentAppConfiguration, - schema, - ) - - // Then - const content = await readFile(filePath) - expect(content).not.toContain('app_id') - expect(content).not.toContain('organization_id') - }) - }) }) diff --git a/packages/app/src/cli/services/app/write-app-configuration-file.ts b/packages/app/src/cli/services/app/write-app-configuration-file.ts index 7d5b3f848b0..4dd48d98454 100644 --- a/packages/app/src/cli/services/app/write-app-configuration-file.ts +++ b/packages/app/src/cli/services/app/write-app-configuration-file.ts @@ -28,29 +28,18 @@ export async function writeAppConfigurationFile(configuration: CurrentAppConfigu } export const rewriteConfiguration = (schema: T, config: unknown): unknown => { - // Remove app_id if organization_id is not present. - // This will become unnecessary when we remove app_id from App Management apps. - let configCopy = config - if (typeof config === 'object' && config !== null && config !== undefined) { - if ('app_id' in config && !('organization_id' in config)) { - // eslint-disable-next-line @typescript-eslint/naming-convention - const {app_id, ...rest} = config - configCopy = rest - } - } - if (schema === null || schema === undefined) return null if (schema instanceof zod.ZodNullable || schema instanceof zod.ZodOptional) - return rewriteConfiguration(schema.unwrap(), configCopy) + return rewriteConfiguration(schema.unwrap(), config) if (schema instanceof zod.ZodArray) { - return (configCopy as unknown[]).map((item) => rewriteConfiguration(schema.element, item)) + return (config as unknown[]).map((item) => rewriteConfiguration(schema.element, item)) } if (schema instanceof zod.ZodEffects) { - return rewriteConfiguration(schema._def.schema, configCopy) + return rewriteConfiguration(schema._def.schema, config) } if (schema instanceof zod.ZodObject) { const entries = Object.entries(schema.shape) - const confObj = configCopy as {[key: string]: unknown} + const confObj = config as {[key: string]: unknown} let result: {[key: string]: unknown} = {} entries.forEach(([key, subSchema]) => { if (confObj !== undefined && confObj[key] !== undefined) { diff --git a/packages/app/src/cli/services/build/extension.test.ts b/packages/app/src/cli/services/build/extension.test.ts index 628c3095aa6..83df6888c73 100644 --- a/packages/app/src/cli/services/build/extension.test.ts +++ b/packages/app/src/cli/services/build/extension.test.ts @@ -1,16 +1,18 @@ import {buildFunctionExtension} from './extension.js' import {testFunctionExtension} from '../../models/app/app.test-data.js' -import {buildJSFunction} from '../function/build.js' +import {buildJSFunction, runWasmOpt} from '../function/build.js' import {ExtensionInstance} from '../../models/extensions/extension-instance.js' import {FunctionConfigType} from '../../models/extensions/specifications/function.js' import {beforeEach, describe, expect, test, vi} from 'vitest' import {exec} from '@shopify/cli-kit/node/system' import lockfile from 'proper-lockfile' import {AbortError} from '@shopify/cli-kit/node/error' +import {fileExistsSync} from '@shopify/cli-kit/node/fs' vi.mock('@shopify/cli-kit/node/system') vi.mock('../function/build.js') vi.mock('proper-lockfile') +vi.mock('@shopify/cli-kit/node/fs') describe('buildFunctionExtension', () => { let extension: ExtensionInstance @@ -26,6 +28,7 @@ describe('buildFunctionExtension', () => { build: { command: 'make build', path: 'dist/index.wasm', + wasm_opt: true, }, configuration_ui: true, api_version: '2022-07', @@ -138,6 +141,45 @@ describe('buildFunctionExtension', () => { expect(releaseLock).toHaveBeenCalled() }) + test('performs wasm-opt execution by default', async () => { + // Given + vi.mocked(fileExistsSync).mockResolvedValue(true) + + // When + await expect( + buildFunctionExtension(extension, { + stdout, + stderr, + signal, + app, + environment: 'production', + }), + ).resolves.toBeUndefined() + + // Then + expect(runWasmOpt).toHaveBeenCalled() + }) + + test('skips wasm-opt execution when the disable-wasm-opt is true', async () => { + // Given + vi.mocked(fileExistsSync).mockResolvedValue(true) + extension.configuration.build.wasm_opt = false + + // When + await expect( + buildFunctionExtension(extension, { + stdout, + stderr, + signal, + app, + environment: 'production', + }), + ).resolves.toBeUndefined() + + // Then + expect(runWasmOpt).not.toHaveBeenCalled() + }) + test('fails when build lock cannot be acquired', async () => { // Given vi.mocked(lockfile.lock).mockRejectedValue('failed to acquire lock') diff --git a/packages/app/src/cli/services/build/extension.ts b/packages/app/src/cli/services/build/extension.ts index a694375c5d3..a6aa0920f43 100644 --- a/packages/app/src/cli/services/build/extension.ts +++ b/packages/app/src/cli/services/build/extension.ts @@ -1,14 +1,14 @@ import {runThemeCheck} from './theme-check.js' import {AppInterface} from '../../models/app/app.js' import {bundleExtension, bundleFlowTemplateExtension} from '../extensions/bundle.js' -import {buildJSFunction} from '../function/build.js' +import {buildJSFunction, runWasmOpt} from '../function/build.js' import {ExtensionInstance} from '../../models/extensions/extension-instance.js' import {FunctionConfigType} from '../../models/extensions/specifications/function.js' import {exec} from '@shopify/cli-kit/node/system' import {AbortSignal} from '@shopify/cli-kit/node/abort' import {AbortError, AbortSilentError} from '@shopify/cli-kit/node/error' import lockfile from 'proper-lockfile' -import {joinPath} from '@shopify/cli-kit/node/path' +import {dirname, joinPath} from '@shopify/cli-kit/node/path' import {outputDebug} from '@shopify/cli-kit/node/output' import {readFile, touchFile, writeFile, fileExistsSync} from '@shopify/cli-kit/node/fs' import {Writable} from 'stream' @@ -91,12 +91,14 @@ export async function buildUIExtension(extension: ExtensionInstance, options: Ex env.APP_URL = options.appURL } + const {main, assets} = extension.getBundleExtensionStdinContent() + try { await bundleExtension({ minify: true, outputPath: extension.outputPath, stdin: { - contents: extension.getBundleExtensionStdinContent(), + contents: main, resolveDir: extension.directory, loader: 'tsx', }, @@ -106,6 +108,25 @@ export async function buildUIExtension(extension: ExtensionInstance, options: Ex stdout: options.stdout, sourceMaps: extension.isSourceMapGeneratingExtension, }) + if (assets) { + await Promise.all( + assets.map(async (asset) => { + await bundleExtension({ + minify: true, + outputPath: joinPath(dirname(extension.outputPath), asset.outputFileName), + stdin: { + contents: asset.content, + resolveDir: extension.directory, + loader: 'tsx', + }, + environment: options.environment, + env, + stderr: options.stderr, + stdout: options.stdout, + }) + }), + ) + } } catch (extensionBundlingError) { // this fails if the app's own source code is broken; wrap such that this isn't flagged as a CLI bug throw new AbortError( @@ -118,7 +139,7 @@ export async function buildUIExtension(extension: ExtensionInstance, options: Ex options.stdout.write(`${extension.localIdentifier} successfully built`) } -export type BuildFunctionExtensionOptions = ExtensionBuildOptions +type BuildFunctionExtensionOptions = ExtensionBuildOptions /** * Builds a function extension @@ -154,11 +175,20 @@ export async function buildFunctionExtension( } else { await buildOtherFunction(extension, options) } + + const wasmOpt = (extension as ExtensionInstance).configuration.build.wasm_opt + if (fileExistsSync(extension.outputPath) && wasmOpt) { + await runWasmOpt(extension.outputPath) + } + if (fileExistsSync(extension.outputPath) && bundlePath !== extension.outputPath) { const base64Contents = await readFile(extension.outputPath, {encoding: 'base64'}) await touchFile(bundlePath) await writeFile(bundlePath, base64Contents) } + } catch (error) { + const errorMessage = (error as Error).message ?? 'Unknown error occurred' + throw new AbortError('Failed to build function.', errorMessage) } finally { await releaseLock() } diff --git a/packages/app/src/cli/services/build/theme-check.ts b/packages/app/src/cli/services/build/theme-check.ts index 3851078d73f..53a00faebd0 100644 --- a/packages/app/src/cli/services/build/theme-check.ts +++ b/packages/app/src/cli/services/build/theme-check.ts @@ -1,12 +1,13 @@ import {readFileSync} from '@shopify/cli-kit/node/fs' import {itemToString} from '@shopify/cli-kit/node/output' import {TokenItem} from '@shopify/cli-kit/node/ui' -import {Severity, type Offense, check} from '@shopify/theme-check-node' +import {Severity, type Offense, check, path as pathUtils} from '@shopify/theme-check-node' /** * Returns a code snippet from a file. All line numbers given MUST be zero indexed */ -function getSnippet(absolutePath: string, startLine: number, endLine: number) { +function getSnippet(uri: string, startLine: number, endLine: number) { + const absolutePath = pathUtils.fsPath(uri) const fileContent = readFileSync(absolutePath).toString() const lines = fileContent.split('\n') const snippetLines = lines.slice(startLine, endLine + 1) @@ -45,9 +46,9 @@ function severityToToken(severity: Severity) { */ function formatOffenses(offenses: Offense[]): TokenItem { const offenseBodies = offenses.map((offense, index) => { - const {message, absolutePath, start, end, check, severity} = offense + const {message, uri, start, end, check, severity} = offense // Theme check line numbers are zero indexed, but intuitively 1-indexed - const codeSnippet = getSnippet(absolutePath, start.line, end.line) + const codeSnippet = getSnippet(uri, start.line, end.line) // Ensure enough padding between offenses const offensePadding = index === offenses.length - 1 ? '' : '\n\n' diff --git a/packages/app/src/cli/services/context.test.ts b/packages/app/src/cli/services/context.test.ts index f9881da95b9..9cd9a9be202 100644 --- a/packages/app/src/cli/services/context.test.ts +++ b/packages/app/src/cli/services/context.test.ts @@ -11,6 +11,7 @@ import * as patchAppConfigurationFile from './app/patch-app-configuration-file.j import {DeployOptions} from './deploy.js' import { MinimalAppIdentifiers, + AppApiKeyAndOrgId, Organization, OrganizationApp, OrganizationSource, @@ -100,7 +101,7 @@ const deployOptions = (app: AppLinkedInterface, reset = false, force = false): D function buildDeveloperPlatformClient(extras?: Partial): DeveloperPlatformClient { return testDeveloperPlatformClient({ ...extras, - async appFromId({apiKey}: MinimalAppIdentifiers) { + async appFromIdentifiers({apiKey}: AppApiKeyAndOrgId) { for (const app of [APP1, APP2]) { if (apiKey === app.apiKey) return app } diff --git a/packages/app/src/cli/services/context.ts b/packages/app/src/cli/services/context.ts index baf45d2de21..f82af5c9b1b 100644 --- a/packages/app/src/cli/services/context.ts +++ b/packages/app/src/cli/services/context.ts @@ -51,7 +51,7 @@ interface AppFromIdOptions { developerPlatformClient: DeveloperPlatformClient } -export const appFromId = async (options: AppFromIdOptions): Promise => { +export const appFromIdentifiers = async (options: AppFromIdOptions): Promise => { let organizationId = options.organizationId let developerPlatformClient = options.developerPlatformClient if (!organizationId) { @@ -62,8 +62,7 @@ export const appFromId = async (options: AppFromIdOptions): Promise { build: { command: 'make build', path: 'dist/index.wasm', + wasm_opt: true, }, configuration_ui: false, api_version: '2022-07', diff --git a/packages/app/src/cli/services/context/identifiers-extensions.test.ts b/packages/app/src/cli/services/context/identifiers-extensions.test.ts index 29fb2f9f6b0..43265d8555a 100644 --- a/packages/app/src/cli/services/context/identifiers-extensions.test.ts +++ b/packages/app/src/cli/services/context/identifiers-extensions.test.ts @@ -263,6 +263,7 @@ beforeAll(async () => { build: { command: 'make build', path: 'dist/index.wasm', + wasm_opt: true, }, metafields: [], configuration_ui: false, diff --git a/packages/app/src/cli/services/context/identifiers-extensions.ts b/packages/app/src/cli/services/context/identifiers-extensions.ts index ce3ba72a8d0..5a1da59d433 100644 --- a/packages/app/src/cli/services/context/identifiers-extensions.ts +++ b/packages/app/src/cli/services/context/identifiers-extensions.ts @@ -124,6 +124,7 @@ export async function ensureExtensionsIds( options.developerPlatformClient, ) remoteExtensions = remoteExtensions.concat(newRemoteExtensions) + didMigrateDashboardExtensions = true } if (adminLinkExtensionsToMigrate.length > 0) { @@ -137,6 +138,7 @@ export async function ensureExtensionsIds( options.developerPlatformClient, ) remoteExtensions = remoteExtensions.concat(newRemoteExtensions) + didMigrateDashboardExtensions = true } const matchExtensions = await automaticMatchmaking( diff --git a/packages/app/src/cli/services/deploy/bundle.test.ts b/packages/app/src/cli/services/deploy/bundle.test.ts index 1552f4b02dc..72c1faa0ab7 100644 --- a/packages/app/src/cli/services/deploy/bundle.test.ts +++ b/packages/app/src/cli/services/deploy/bundle.test.ts @@ -8,7 +8,7 @@ import {joinPath} from '@shopify/cli-kit/node/path' describe('bundleAndBuildExtensions', () => { let app: AppInterface - test('generates a manifest.json when USE_APP_MANAGEMENT_API is enabled', async () => { + test('generates a manifest.json when App Management is enabled', async () => { await file.inTemporaryDirectory(async (tmpDir: string) => { // Given vi.spyOn(file, 'writeFileSync').mockResolvedValue(undefined) @@ -73,7 +73,7 @@ describe('bundleAndBuildExtensions', () => { }) }) - test('does not generate the manifest.json when USE_APP_MANAGEMENT_API is disabled', async () => { + test('does not generate the manifest.json when App Management is disabled', async () => { await file.inTemporaryDirectory(async (tmpDir: string) => { // Given vi.spyOn(file, 'writeFileSync').mockResolvedValue(undefined) diff --git a/packages/app/src/cli/services/deploy/bundle.ts b/packages/app/src/cli/services/deploy/bundle.ts index e3a240ca701..691d74820b6 100644 --- a/packages/app/src/cli/services/deploy/bundle.ts +++ b/packages/app/src/cli/services/deploy/bundle.ts @@ -5,8 +5,8 @@ import {zip} from '@shopify/cli-kit/node/archiver' import {AbortSignal} from '@shopify/cli-kit/node/abort' import {inTemporaryDirectory, mkdirSync, touchFile, writeFileSync} from '@shopify/cli-kit/node/fs' import {joinPath} from '@shopify/cli-kit/node/path' -import {isTruthy} from '@shopify/cli-kit/node/context/utilities' import {renderConcurrent} from '@shopify/cli-kit/node/ui' +import {isAppManagementEnabled} from '@shopify/cli-kit/node/context/local' import {Writable} from 'stream' interface BundleOptions { @@ -21,7 +21,7 @@ export async function bundleAndBuildExtensions(options: BundleOptions, systemEnv mkdirSync(bundleDirectory) await touchFile(joinPath(bundleDirectory, '.shopify')) - if (isTruthy(systemEnvironment.USE_APP_MANAGEMENT_API)) { + if (isAppManagementEnabled(systemEnvironment)) { // Include manifest in bundle const appManifest = await options.app.manifest(options.identifiers) const manifestPath = joinPath(bundleDirectory, 'manifest.json') diff --git a/packages/app/src/cli/services/dev/app-events/app-event-watcher-handler.ts b/packages/app/src/cli/services/dev/app-events/app-event-watcher-handler.ts index 00770aa1521..c0ed7dc56a8 100644 --- a/packages/app/src/cli/services/dev/app-events/app-event-watcher-handler.ts +++ b/packages/app/src/cli/services/dev/app-events/app-event-watcher-handler.ts @@ -3,11 +3,10 @@ import {AppEvent, EventType, ExtensionEvent} from './app-event-watcher.js' import {appDiff} from './app-diffing.js' import {AppLinkedInterface} from '../../../models/app/app.js' import {ExtensionInstance} from '../../../models/extensions/extension-instance.js' -import {loadApp} from '../../../models/app/loader.js' -import {outputDebug} from '@shopify/cli-kit/node/output' +import {reloadApp} from '../../../models/app/loader.js' import {AbortError} from '@shopify/cli-kit/node/error' import {endHRTimeInMs, startHRTime} from '@shopify/cli-kit/node/hrtime' -import {basename} from '@shopify/cli-kit/node/path' +import {outputDebug} from '@shopify/cli-kit/node/output' /** * Transforms an array of WatcherEvents from the file system into a processed AppEvent. @@ -114,30 +113,25 @@ function AppConfigDeletedHandler(_input: HandlerInput): AppEvent { * - When an extension toml is updated */ async function ReloadAppHandler({event, app}: HandlerInput): Promise { - const newApp = await reloadApp(app) + const newApp = await reload(app) const diff = appDiff(app, newApp, true) const createdEvents = diff.created.map((ext) => ({type: EventType.Created, extension: ext})) const deletedEvents = diff.deleted.map((ext) => ({type: EventType.Deleted, extension: ext})) const updatedEvents = diff.updated.map((ext) => ({type: EventType.Updated, extension: ext})) const extensionEvents = [...createdEvents, ...deletedEvents, ...updatedEvents] - return {app: newApp, extensionEvents, startTime: event.startTime, path: event.path} + return {app: newApp, extensionEvents, startTime: event.startTime, path: event.path, appWasReloaded: true} } /* * Reload the app and returns it * Prints the time to reload the app to stdout */ -export async function reloadApp(app: AppLinkedInterface): Promise { +async function reload(app: AppLinkedInterface): Promise { const start = startHRTime() try { - const newApp = await loadApp({ - specifications: app.specifications, - directory: app.directory, - userProvidedConfigName: basename(app.configuration.path), - remoteFlags: app.remoteFlags, - }) + const newApp = await reloadApp(app) outputDebug(`App reloaded [${endHRTimeInMs(start)}ms]`) - return newApp as AppLinkedInterface + return newApp // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { throw new Error(`Error reloading app: ${error.message}`) diff --git a/packages/app/src/cli/services/dev/app-events/app-event-watcher.test.ts b/packages/app/src/cli/services/dev/app-events/app-event-watcher.test.ts index eb1fbeb4865..0423ea1d963 100644 --- a/packages/app/src/cli/services/dev/app-events/app-event-watcher.test.ts +++ b/packages/app/src/cli/services/dev/app-events/app-event-watcher.test.ts @@ -1,8 +1,7 @@ import {AppEvent, AppEventWatcher, EventType, ExtensionEvent} from './app-event-watcher.js' -import {OutputContextOptions, WatcherEvent, startFileWatcher} from './file-watcher.js' +import {OutputContextOptions, WatcherEvent, FileWatcher} from './file-watcher.js' import {ESBuildContextManager} from './app-watcher-esbuild.js' import { - testApp, testAppAccessConfigExtension, testAppConfigExtensions, testAppLinked, @@ -11,15 +10,15 @@ import { testUIExtension, } from '../../../models/app/app.test-data.js' import {ExtensionInstance} from '../../../models/extensions/extension-instance.js' -import {loadApp} from '../../../models/app/loader.js' -import {describe, expect, test, vi} from 'vitest' -import {AbortSignal} from '@shopify/cli-kit/node/abort' +import {loadApp, reloadApp} from '../../../models/app/loader.js' +import {AppLinkedInterface} from '../../../models/app/app.js' +import {afterEach, beforeEach, describe, expect, test, vi} from 'vitest' +import {AbortSignal, AbortController} from '@shopify/cli-kit/node/abort' import {flushPromises} from '@shopify/cli-kit/node/promises' import {inTemporaryDirectory} from '@shopify/cli-kit/node/fs' import {joinPath} from '@shopify/cli-kit/node/path' import {Writable} from 'stream' -vi.mock('./file-watcher.js') vi.mock('../../../models/app/loader.js') vi.mock('./app-watcher-esbuild.js') @@ -227,177 +226,189 @@ const testCases: TestCase[] = [ }, ] -describe('app-event-watcher when receiving a file event', () => { - test.each(testCases)( - 'The event $name returns the expected AppEvent', - async ({fileWatchEvent, initialExtensions, finalExtensions, extensionEvents, needsAppReload}) => { - // Given - await inTemporaryDirectory(async (tmpDir) => { - vi.mocked(loadApp).mockResolvedValue(testApp({allExtensions: finalExtensions})) - vi.mocked(startFileWatcher).mockImplementation(async (app, options, onChange) => onChange([fileWatchEvent])) +describe('app-event-watcher', () => { + let abortController: AbortController + let stdout: any + let stderr: any - const buildOutputPath = joinPath(tmpDir, '.shopify', 'bundle') + beforeEach(() => { + stdout = {write: vi.fn()} + stderr = {write: vi.fn()} + abortController = new AbortController() + }) - // When - const app = testAppLinked({ - allExtensions: initialExtensions, - configuration: {scopes: '', extension_directories: [], path: 'shopify.app.custom.toml'}, - }) + afterEach(() => { + abortController.abort() + }) + describe('when receiving a file event', () => { + test.each(testCases)( + 'The event $name returns the expected AppEvent', + async ({fileWatchEvent, initialExtensions, finalExtensions, extensionEvents, needsAppReload}) => { + // Given + await inTemporaryDirectory(async (tmpDir) => { + const mockedApp = testAppLinked({allExtensions: finalExtensions}) + vi.mocked(loadApp).mockResolvedValue(mockedApp) + vi.mocked(reloadApp).mockResolvedValue(mockedApp) + + const buildOutputPath = joinPath(tmpDir, '.shopify', 'bundle') + + // When + const app = testAppLinked({ + allExtensions: initialExtensions, + configuration: {scopes: '', extension_directories: [], path: 'shopify.app.custom.toml'}, + }) - const watcher = new AppEventWatcher(app, 'url', buildOutputPath, new MockESBuildContextManager()) - const emitSpy = vi.spyOn(watcher, 'emit') - await watcher.start() + const mockManager = new MockESBuildContextManager() + const mockFileWatcher = new MockFileWatcher(app, outputOptions, [fileWatchEvent]) + const watcher = new AppEventWatcher(app, 'url', buildOutputPath, mockManager, mockFileWatcher) + const emitSpy = vi.spyOn(watcher, 'emit') + await watcher.start({stdout, stderr, signal: abortController.signal}) + + await flushPromises() + + // Wait until emitSpy has been called at least once + // We need this because there are I/O operations that make the test finish before the event is emitted + await new Promise((resolve, reject) => { + const initialTime = Date.now() + const checkEmitSpy = () => { + const allCalled = emitSpy.mock.calls.some((call) => call[0] === 'all') + const readyCalled = emitSpy.mock.calls.some((call) => call[0] === 'ready') + if (allCalled && readyCalled) { + resolve() + } else if (Date.now() - initialTime < 3000) { + setTimeout(checkEmitSpy, 100) + } else { + reject(new Error('Timeout waiting for emitSpy to be called')) + } + } + checkEmitSpy() + }) - await flushPromises() + expect(emitSpy).toHaveBeenCalledWith('all', { + app: expect.objectContaining({realExtensions: finalExtensions}), + extensionEvents: expect.arrayContaining(extensionEvents), + startTime: expect.anything(), + path: expect.anything(), + appWasReloaded: needsAppReload, + }) - // Wait until emitSpy has been called at least once - // We need this because there are I/O operations that make the test finish before the event is emitted - await new Promise((resolve, reject) => { - const initialTime = Date.now() - const checkEmitSpy = () => { - const allCalled = emitSpy.mock.calls.some((call) => call[0] === 'all') - const readyCalled = emitSpy.mock.calls.some((call) => call[0] === 'ready') - if (allCalled && readyCalled) { - resolve() - } else if (Date.now() - initialTime < 3000) { - setTimeout(checkEmitSpy, 100) - } else { - reject(new Error('Timeout waiting for emitSpy to be called')) - } - } - checkEmitSpy() - }) + const initialEvents = app.realExtensions.map((eve) => ({ + type: EventType.Updated, + extension: eve, + buildResult: {status: 'ok', handle: eve.handle}, + })) + expect(emitSpy).toHaveBeenCalledWith('ready', { + app, + extensionEvents: expect.arrayContaining(initialEvents), + }) - expect(emitSpy).toHaveBeenCalledWith('all', { - app: expect.objectContaining({realExtensions: finalExtensions}), - extensionEvents: expect.arrayContaining(extensionEvents), - startTime: expect.anything(), - path: expect.anything(), + if (needsAppReload) { + expect(reloadApp).toHaveBeenCalled() + } else { + expect(reloadApp).not.toHaveBeenCalled() + } }) + }, + ) + }) - const initialEvents = app.realExtensions.map((eve) => ({ - type: EventType.Updated, - extension: eve, - buildResult: {status: 'ok', handle: eve.handle}, - })) - expect(emitSpy).toHaveBeenCalledWith('ready', { - app, - extensionEvents: expect.arrayContaining(initialEvents), - }) + describe('app-event-watcher build extension errors', () => { + test('esbuild errors are logged with a custom format', async () => { + await inTemporaryDirectory(async (tmpDir) => { + const fileWatchEvent: WatcherEvent = { + type: 'file_updated', + path: '/extensions/ui_extension_1/src/file.js', + extensionPath: '/extensions/ui_extension_1', + startTime: [0, 0], + } - if (needsAppReload) { - expect(loadApp).toHaveBeenCalledWith({ - specifications: expect.anything(), - directory: expect.anything(), - // The app is loaded with the same configuration file - userProvidedConfigName: 'shopify.app.custom.toml', - remoteFlags: expect.anything(), - }) - } else { - expect(loadApp).not.toHaveBeenCalled() + // Given + const esbuildError = { + errors: [ + { + text: 'Syntax error', + location: {file: 'test.js', line: 1, column: 2, lineText: 'console.log(aa);'}, + }, + ], } - }) - }, - ) -}) -describe('app-event-watcher build extension errors', () => { - test('esbuild errors are logged with a custom format', async () => { - await inTemporaryDirectory(async (tmpDir) => { - const fileWatchEvent: WatcherEvent = { - type: 'file_updated', - path: '/extensions/ui_extension_1/src/file.js', - extensionPath: '/extensions/ui_extension_1', - startTime: [0, 0], - } - vi.mocked(startFileWatcher).mockImplementation(async (app, options, onChange) => onChange([fileWatchEvent])) - - // Given - const esbuildError = { - errors: [ - { - text: 'Syntax error', - location: {file: 'test.js', line: 1, column: 2, lineText: 'console.log(aa);'}, - }, - ], - } - - const mockManager = new MockESBuildContextManager() - mockManager.rebuildContext = vi.fn().mockRejectedValueOnce(esbuildError) - - const buildOutputPath = joinPath(tmpDir, '.shopify', 'bundle') - const app = testAppLinked({ - allExtensions: [extension1], - configuration: {scopes: '', extension_directories: [], path: 'shopify.app.custom.toml'}, - }) + const mockManager = new MockESBuildContextManager() + mockManager.rebuildContext = vi.fn().mockRejectedValueOnce(esbuildError) - // When - const watcher = new AppEventWatcher(app, 'url', buildOutputPath, mockManager) - const stderr = {write: vi.fn()} as unknown as Writable - const stdout = {write: vi.fn()} as unknown as Writable + const buildOutputPath = joinPath(tmpDir, '.shopify', 'bundle') + const app = testAppLinked({ + allExtensions: [extension1], + configuration: {scopes: '', extension_directories: [], path: 'shopify.app.custom.toml'}, + }) + const mockFileWatcher = new MockFileWatcher(app, outputOptions, [fileWatchEvent]) - await watcher.start({stdout, stderr, signal: new AbortSignal()}) + // When + const watcher = new AppEventWatcher(app, 'url', buildOutputPath, mockManager, mockFileWatcher) + const stderr = {write: vi.fn()} as unknown as Writable + const stdout = {write: vi.fn()} as unknown as Writable + await watcher.start({stdout, stderr, signal: abortController.signal}) - await flushPromises() + await flushPromises() - // Then - expect(stderr.write).toHaveBeenCalledWith( - expect.stringContaining( - `[ERROR] Syntax error + // Then + expect(stderr.write).toHaveBeenCalledWith( + expect.stringContaining( + `[ERROR] Syntax error test.js:1:2: 1 │ console.log(aa); ╵ ^ `, - ), - ) + ), + ) + }) }) - }) - test('general build errors are logged as plain messages', async () => { - await inTemporaryDirectory(async (tmpDir) => { - const fileWatchEvent: WatcherEvent = { - type: 'file_updated', - path: '/extensions/flow_action/src/file.js', - extensionPath: '/extensions/flow_action', - startTime: [0, 0], - } - vi.mocked(startFileWatcher).mockImplementation(async (app, options, onChange) => onChange([fileWatchEvent])) - - // Given - const esbuildError = {message: 'Build failed'} - flowExtension.buildForBundle = vi.fn().mockRejectedValueOnce(esbuildError) - - const buildOutputPath = joinPath(tmpDir, '.shopify', 'bundle') - const app = testAppLinked({ - allExtensions: [flowExtension], - configuration: {scopes: '', extension_directories: [], path: 'shopify.app.custom.toml'}, - }) + test('general build errors are logged as plain messages', async () => { + await inTemporaryDirectory(async (tmpDir) => { + const fileWatchEvent: WatcherEvent = { + type: 'file_updated', + path: '/extensions/flow_action/src/file.js', + extensionPath: '/extensions/flow_action', + startTime: [0, 0], + } + + // Given + const esbuildError = {message: 'Build failed'} + flowExtension.buildForBundle = vi.fn().mockRejectedValueOnce(esbuildError) + + const buildOutputPath = joinPath(tmpDir, '.shopify', 'bundle') + const app = testAppLinked({ + allExtensions: [flowExtension], + configuration: {scopes: '', extension_directories: [], path: 'shopify.app.custom.toml'}, + }) - // When - const watcher = new AppEventWatcher(app, 'url', buildOutputPath, new MockESBuildContextManager()) - const stderr = {write: vi.fn()} as unknown as Writable - const stdout = {write: vi.fn()} as unknown as Writable + // When + const mockManager = new MockESBuildContextManager() + const mockFileWatcher = new MockFileWatcher(app, outputOptions, [fileWatchEvent]) + const watcher = new AppEventWatcher(app, 'url', buildOutputPath, mockManager, mockFileWatcher) + const stderr = {write: vi.fn()} as unknown as Writable + const stdout = {write: vi.fn()} as unknown as Writable - await watcher.start({stdout, stderr, signal: new AbortSignal()}) + await watcher.start({stdout, stderr, signal: abortController.signal}) - await flushPromises() + await flushPromises() - // Then - expect(stderr.write).toHaveBeenCalledWith(`Build failed`) + // Then + expect(stderr.write).toHaveBeenCalledWith(`Build failed`) + }) }) }) }) - // Mock class for ESBuildContextManager // It handles the ESBuild contexts for the extensions that are being watched class MockESBuildContextManager extends ESBuildContextManager { contexts = { // The keys are the extension handles, the values are the ESBuild contexts mocked - h1: {rebuild: vi.fn(), watch: vi.fn(), serve: vi.fn(), cancel: vi.fn(), dispose: vi.fn()}, - h2: {rebuild: vi.fn(), watch: vi.fn(), serve: vi.fn(), cancel: vi.fn(), dispose: vi.fn()}, - 'test-ui-extension': {rebuild: vi.fn(), watch: vi.fn(), serve: vi.fn(), cancel: vi.fn(), dispose: vi.fn()}, + h1: [{rebuild: vi.fn(), watch: vi.fn(), serve: vi.fn(), cancel: vi.fn(), dispose: vi.fn()}], + h2: [{rebuild: vi.fn(), watch: vi.fn(), serve: vi.fn(), cancel: vi.fn(), dispose: vi.fn()}], + 'test-ui-extension': [{rebuild: vi.fn(), watch: vi.fn(), serve: vi.fn(), cancel: vi.fn(), dispose: vi.fn()}], } constructor() { @@ -408,3 +419,25 @@ class MockESBuildContextManager extends ESBuildContextManager { async updateContexts(appEvent: AppEvent) {} async deleteContexts(extensions: ExtensionInstance[]) {} } + +// Mock class for FileWatcher +// Used to trigger mocked file system events immediately after the watcher is started. +class MockFileWatcher extends FileWatcher { + private readonly events: WatcherEvent[] + private listener?: (events: WatcherEvent[]) => void + + constructor(app: AppLinkedInterface, options: OutputContextOptions, events: WatcherEvent[]) { + super(app, options) + this.events = events + } + + async start(): Promise { + if (this.listener) { + this.listener(this.events) + } + } + + onChange(listener: (events: WatcherEvent[]) => void) { + this.listener = listener + } +} diff --git a/packages/app/src/cli/services/dev/app-events/app-event-watcher.ts b/packages/app/src/cli/services/dev/app-events/app-event-watcher.ts index 2657bd38c35..c281fa350e3 100644 --- a/packages/app/src/cli/services/dev/app-events/app-event-watcher.ts +++ b/packages/app/src/cli/services/dev/app-events/app-event-watcher.ts @@ -1,5 +1,5 @@ /* eslint-disable tsdoc/syntax */ -import {OutputContextOptions, startFileWatcher} from './file-watcher.js' +import {FileWatcher, OutputContextOptions} from './file-watcher.js' import {ESBuildContextManager} from './app-watcher-esbuild.js' import {handleWatcherEvents} from './app-event-watcher-handler.js' import {AppLinkedInterface} from '../../../models/app/app.js' @@ -80,6 +80,7 @@ export interface AppEvent { extensionEvents: ExtensionEvent[] path: string startTime: [number, number] + appWasReloaded?: boolean } type ExtensionBuildResult = {status: 'ok'; handle: string} | {status: 'error'; error: string; handle: string} @@ -96,12 +97,14 @@ export class AppEventWatcher extends EventEmitter { private started = false private ready = false private initialEvents: ExtensionEvent[] = [] + private fileWatcher?: FileWatcher constructor( app: AppLinkedInterface, appURL?: string, buildOutputPath?: string, esbuildManager?: ESBuildContextManager, + fileWatcher?: FileWatcher, ) { super() this.app = app @@ -117,6 +120,7 @@ export class AppEventWatcher extends EventEmitter { url: this.appURL ?? '', ...this.options, }) + this.fileWatcher = fileWatcher } async start(options?: OutputContextOptions, buildExtensionsFirst = true) { @@ -139,14 +143,15 @@ export class AppEventWatcher extends EventEmitter { await this.buildExtensions(this.initialEvents) } - // Start the file system watcher - await startFileWatcher(this.app, this.options, (events) => { + this.fileWatcher = this.fileWatcher ?? new FileWatcher(this.app, this.options) + this.fileWatcher.onChange((events) => { handleWatcherEvents(events, this.app, this.options) .then(async (appEvent) => { if (appEvent?.extensionEvents.length === 0) outputDebug('Change detected, but no extensions were affected') if (!appEvent || appEvent.extensionEvents.length === 0) return this.app = appEvent.app + if (appEvent.appWasReloaded) this.fileWatcher?.updateApp(this.app) await this.esbuildManager.updateContexts(appEvent) // Find affected created/updated extensions and build them @@ -163,6 +168,7 @@ export class AppEventWatcher extends EventEmitter { this.options.stderr.write(`Error handling event: ${error.message}`) }) }) + await this.fileWatcher.start() this.ready = true this.emit('ready', {app: this.app, extensionEvents: this.initialEvents}) @@ -224,7 +230,7 @@ export class AppEventWatcher extends EventEmitter { const ext = extEvent.extension return useConcurrentOutputContext({outputPrefix: ext.handle, stripAnsi: false}, async () => { try { - if (this.esbuildManager.contexts[ext.handle]) { + if (this.esbuildManager.contexts?.[ext.handle]?.length) { await this.esbuildManager.rebuildContext(ext) } else { await this.buildExtension(ext) diff --git a/packages/app/src/cli/services/dev/app-events/app-watcher-esbuild.test.ts b/packages/app/src/cli/services/dev/app-events/app-watcher-esbuild.test.ts index 800f6d78c5a..4c1867eb43d 100644 --- a/packages/app/src/cli/services/dev/app-events/app-watcher-esbuild.test.ts +++ b/packages/app/src/cli/services/dev/app-events/app-watcher-esbuild.test.ts @@ -35,6 +35,50 @@ describe('app-watcher-esbuild', () => { expect(manager.contexts).toHaveProperty('test-ui-extension') }) + test('creating multiple contexts for the same extension', async () => { + // Given + const options: DevAppWatcherOptions = { + dotEnvVariables: {key: 'value'}, + url: 'http://localhost:3000', + outputPath: '/path/to/output', + } + const manager = new ESBuildContextManager(options) + const extension = await testUIExtension({ + configuration: { + ...extension2.configuration, + handle: 'conditional-extension', + extension_points: [ + { + target: 'target1', + module: 'module1', + should_render: { + module: 'shouldRenderModule1', + }, + build_manifest: { + assets: { + main: { + module: 'module1', + filepath: '/conditional-extension.js', + }, + should_render: { + module: 'shouldRenderModule1', + filepath: '/conditional-extension-conditions.js', + }, + }, + }, + }, + ], + }, + }) + + // When + await manager.createContexts([extension]) + + // Then + expect(manager.contexts).toHaveProperty('conditional-extension') + expect(manager.contexts['conditional-extension']).toHaveLength(2) + }) + test('deleting contexts', async () => { // Given const manager = new ESBuildContextManager(options) @@ -76,7 +120,7 @@ describe('app-watcher-esbuild', () => { // Given const manager = new ESBuildContextManager(options) await manager.createContexts([extension1]) - const spyContext = vi.spyOn(manager.contexts.h1!, 'rebuild').mockResolvedValue({} as any) + const spyContext = vi.spyOn(manager.contexts.h1![0]!, 'rebuild').mockResolvedValue({} as any) const spyCopy = vi.spyOn(fs, 'copyFile').mockResolvedValue() // When diff --git a/packages/app/src/cli/services/dev/app-events/app-watcher-esbuild.ts b/packages/app/src/cli/services/dev/app-events/app-watcher-esbuild.ts index 2dc89991fb4..c456e4ba83a 100644 --- a/packages/app/src/cli/services/dev/app-events/app-watcher-esbuild.ts +++ b/packages/app/src/cli/services/dev/app-events/app-watcher-esbuild.ts @@ -1,10 +1,10 @@ import {AppEvent, EventType} from './app-event-watcher.js' import {ExtensionInstance} from '../../../models/extensions/extension-instance.js' import {getESBuildOptions} from '../../extensions/bundle.js' -import {BuildContext, context as esContext} from 'esbuild' +import {BuildContext, context as esContext, StdinOptions} from 'esbuild' import {AbortSignal} from '@shopify/cli-kit/node/abort' import {copyFile} from '@shopify/cli-kit/node/fs' -import {dirname} from '@shopify/cli-kit/node/path' +import {dirname, joinPath} from '@shopify/cli-kit/node/path' export interface DevAppWatcherOptions { dotEnvVariables: {[key: string]: string} @@ -17,7 +17,7 @@ export interface DevAppWatcherOptions { * Has a list of all active contexts and methods to create, update and delete them. */ export class ESBuildContextManager { - contexts: {[key: string]: BuildContext} + contexts: {[key: string]: BuildContext[]} outputPath: string dotEnvVariables: {[key: string]: string} url: string @@ -33,35 +33,40 @@ export class ESBuildContextManager { setAbortSignal(signal: AbortSignal) { this.signal = signal this.signal?.addEventListener('abort', async () => { - const allDispose = Object.values(this.contexts).map((context) => context.dispose()) + const allDispose = Object.values(this.contexts) + .map((context) => context.map((ctxt) => ctxt.dispose())) + .flat() await Promise.all(allDispose) }) } async createContexts(extensions: ExtensionInstance[]) { const promises = extensions.map(async (extension) => { - const esbuildOptions = getESBuildOptions({ - minify: false, - outputPath: extension.getOutputPathForDirectory(this.outputPath), - environment: 'development', - env: { - ...this.dotEnvVariables, - APP_URL: this.url, - }, - stdin: { - contents: extension.getBundleExtensionStdinContent(), + const {main, assets} = extension.getBundleExtensionStdinContent() + const mainOutputPath = extension.getOutputPathForDirectory(this.outputPath) + const esbuildOptions = await this.extensionEsBuildOptions( + { + contents: main, resolveDir: extension.directory, loader: 'tsx', }, - logLevel: 'silent', - // stdout and stderr are mandatory, but not actually used - stderr: process.stderr, - stdout: process.stdout, - sourceMaps: true, + mainOutputPath, + ) + const mainContextPromise = esContext(esbuildOptions) + + const assetContextPromises = (assets ?? []).map(async (asset) => { + const esbuildOptions = await this.extensionEsBuildOptions( + { + contents: asset.content, + resolveDir: extension.directory, + loader: 'ts', + }, + joinPath(dirname(mainOutputPath), asset.outputFileName), + ) + return esContext(esbuildOptions) }) - const context = await esContext(esbuildOptions) - this.contexts[extension.handle] = context + this.contexts[extension.handle] = await Promise.all(assetContextPromises.concat(mainContextPromise)) }) await Promise.all(promises) @@ -70,7 +75,7 @@ export class ESBuildContextManager { async rebuildContext(extension: ExtensionInstance) { const context = this.contexts[extension.handle] if (!context) return - await context.rebuild() + await Promise.all(context.map((ctxt) => ctxt.rebuild())) // The default output path for a extension is now inside `.shopify/bundle//dist`, // all extensions output need to be under the same directory so that it can all be zipped together. @@ -97,11 +102,29 @@ export class ESBuildContextManager { } async deleteContexts(extensions: ExtensionInstance[]) { - const promises = extensions.map((ext) => this.contexts[ext.handle]?.dispose()) + const promises = extensions.map((ext) => this.contexts[ext.handle]?.map((context) => context.dispose())).flat() await Promise.all(promises) extensions.forEach((ext) => { const {[ext.handle]: _, ...rest} = this.contexts this.contexts = rest }) } + + private async extensionEsBuildOptions(stdin: StdinOptions, outputPath: string) { + return getESBuildOptions({ + minify: false, + outputPath, + environment: 'development', + env: { + ...this.dotEnvVariables, + APP_URL: this.url, + }, + stdin, + logLevel: 'silent', + // stdout and stderr are mandatory, but not actually used + stderr: process.stderr, + stdout: process.stdout, + sourceMaps: true, + }) + } } diff --git a/packages/app/src/cli/services/dev/app-events/file-watcher.test.ts b/packages/app/src/cli/services/dev/app-events/file-watcher.test.ts index 0f461635f79..ddd76656f2c 100644 --- a/packages/app/src/cli/services/dev/app-events/file-watcher.test.ts +++ b/packages/app/src/cli/services/dev/app-events/file-watcher.test.ts @@ -1,9 +1,9 @@ -import {OutputContextOptions, WatcherEvent, startFileWatcher} from './file-watcher.js' +import {FileWatcher, OutputContextOptions, WatcherEvent} from './file-watcher.js' import { - testApp, testAppAccessConfigExtension, testAppConfigExtensions, testAppLinked, + testFunctionExtension, testUIExtension, } from '../../../models/app/app.test-data.js' import {flushPromises} from '@shopify/cli-kit/node/promises' @@ -12,10 +12,12 @@ import chokidar from 'chokidar' import {AbortSignal} from '@shopify/cli-kit/node/abort' import {inTemporaryDirectory, mkdir, writeFile} from '@shopify/cli-kit/node/fs' import {joinPath} from '@shopify/cli-kit/node/path' +import {sleep} from '@shopify/cli-kit/node/system' const extension1 = await testUIExtension({type: 'ui_extension', handle: 'h1', directory: '/extensions/ui_extension_1'}) const extension1B = await testUIExtension({type: 'ui_extension', handle: 'h2', directory: '/extensions/ui_extension_1'}) const extension2 = await testUIExtension({type: 'ui_extension', directory: '/extensions/ui_extension_2'}) +const functionExtension = await testFunctionExtension({dir: '/extensions/my-function'}) const posExtension = await testAppConfigExtensions() const appAccessExtension = await testAppAccessConfigExtension() @@ -30,7 +32,7 @@ interface TestCaseSingleEvent { name: string fileSystemEvent: string path: string - expectedEvent: WatcherEvent + expectedEvent?: WatcherEvent } /** @@ -127,6 +129,12 @@ const singleEventTestCases: TestCaseSingleEvent[] = [ startTime: expect.any(Array), }, }, + { + name: 'change in function extension is ignored if not in watch list', + fileSystemEvent: 'change', + path: '/extensions/my-function/src/cargo.lock', + expectedEvent: undefined, + }, ] const multiEventTestCases: TestCaseMultiEvent[] = [ @@ -167,8 +175,8 @@ const multiEventTestCases: TestCaseMultiEvent[] = [ ] const outputOptions: OutputContextOptions = {stdout: process.stdout, stderr: process.stderr, signal: new AbortSignal()} -const defaultApp = testApp({ - allExtensions: [extension1, extension1B, extension2, posExtension, appAccessExtension], +const defaultApp = testAppLinked({ + allExtensions: [extension1, extension1B, extension2, posExtension, appAccessExtension, functionExtension], directory: '/', configuration: {scopes: '', extension_directories: ['/extensions'], path: '/shopify.app.toml'}, }) @@ -198,7 +206,10 @@ describe('file-watcher events', () => { }) // When - await startFileWatcher(app, outputOptions, vi.fn()) + const fileWatcher = new FileWatcher(app, outputOptions) + fileWatcher.onChange(vi.fn()) + + await fileWatcher.start() // Then expect(watchSpy).toHaveBeenCalledWith([joinPath(dir, '/shopify.app.toml'), joinPath(dir, '/extensions')], { @@ -209,9 +220,7 @@ describe('file-watcher events', () => { '**/dist/**', '**/*.swp', '**/generated/**', - joinPath(dir, '/extensions/ext1/a_folder'), - joinPath(dir, '/extensions/ext1/a_file.txt'), - joinPath(dir, '/extensions/ext1/**/nested/**'), + '**/.gitignore', ], ignoreInitial: true, persistent: true, @@ -232,18 +241,26 @@ describe('file-watcher events', () => { // When const onChange = vi.fn() - await startFileWatcher(defaultApp, outputOptions, onChange) + const fileWatcher = new FileWatcher(defaultApp, outputOptions) + fileWatcher.onChange(onChange) + + await fileWatcher.start() // Then await flushPromises() // use waitFor to so that we can test the debouncers and timeouts - await vi.waitFor( - () => { - expect(onChange).toHaveBeenCalledWith([expectedEvent]) - }, - {timeout: 2000, interval: 100}, - ) + if (expectedEvent) { + await vi.waitFor( + () => { + expect(onChange).toHaveBeenCalledWith([expectedEvent]) + }, + {timeout: 2000, interval: 100}, + ) + } else { + await sleep(0.01) + expect(onChange).not.toHaveBeenCalled() + } }, ) @@ -260,7 +277,10 @@ describe('file-watcher events', () => { // When const onChange = vi.fn() - await startFileWatcher(defaultApp, outputOptions, onChange) + const fileWatcher = new FileWatcher(defaultApp, outputOptions) + fileWatcher.onChange(onChange) + + await fileWatcher.start() // Then await flushPromises() diff --git a/packages/app/src/cli/services/dev/app-events/file-watcher.ts b/packages/app/src/cli/services/dev/app-events/file-watcher.ts index 44123c86b65..b4bec20c58d 100644 --- a/packages/app/src/cli/services/dev/app-events/file-watcher.ts +++ b/packages/app/src/cli/services/dev/app-events/file-watcher.ts @@ -1,15 +1,21 @@ /* eslint-disable no-case-declarations */ -import {AppInterface} from '../../../models/app/app.js' +import {AppLinkedInterface} from '../../../models/app/app.js' import {configurationFileNames} from '../../../constants.js' -import {dirname, isSubpath, joinPath, normalizePath} from '@shopify/cli-kit/node/path' +import {dirname, isSubpath, joinPath, normalizePath, relativePath} from '@shopify/cli-kit/node/path' import {FSWatcher} from 'chokidar' import {outputDebug} from '@shopify/cli-kit/node/output' import {AbortSignal} from '@shopify/cli-kit/node/abort' import {startHRTime, StartTime} from '@shopify/cli-kit/node/hrtime' import {fileExistsSync, matchGlob, readFileSync} from '@shopify/cli-kit/node/fs' import {debounce} from '@shopify/cli-kit/common/function' +import ignore from 'ignore' import {Writable} from 'stream' +const DEFAULT_DEBOUNCE_TIME_IN_MS = 200 +const EXTENSION_CREATION_TIMEOUT_IN_MS = 60000 +const EXTENSION_CREATION_CHECK_INTERVAL_IN_MS = 200 +const FILE_DELETE_TIMEOUT_IN_MS = 500 + /** * Event emitted by the file watcher * @@ -41,48 +47,83 @@ export interface OutputContextOptions { signal: AbortSignal } -/** - * Watch for changes in the given app directory. - * - * It will watch for changes in the active config file and the extension directories. - * When possible, changes will be interpreted to detect new/deleted extensions - * - * Changes to toml files will be reported as different events to other file changes. - * - * @param app - The app to watch - * @param options - The output options - * @param onChange - The callback to call when a change is detected - */ -export async function startFileWatcher( - app: AppInterface, - options: OutputContextOptions, - onChange: (events: WatcherEvent[]) => void, -) { - const {default: chokidar} = await import('chokidar') +export class FileWatcher { + private currentEvents: WatcherEvent[] = [] + private extensionPaths: string[] = [] + private app: AppLinkedInterface + private readonly options: OutputContextOptions + private onChangeCallback?: (events: WatcherEvent[]) => void + private watcher?: FSWatcher + private readonly debouncedEmit: () => void + private readonly ignored: {[key: string]: ignore.Ignore | undefined} = {} - const appConfigurationPath = app.configuration.path - const extensionDirectories = [...(app.configuration.extension_directories ?? ['extensions'])].map((directory) => { - return joinPath(app.directory, directory) - }) + constructor( + app: AppLinkedInterface, + options: OutputContextOptions, + debounceTime: number = DEFAULT_DEBOUNCE_TIME_IN_MS, + ) { + this.app = app + this.options = options - let currentEvents: WatcherEvent[] = [] + /** + * Debounced function to emit the accumulated events. + * This function will be called at most once every DEFAULT_DEBOUNCE_TIME_IN_MS + * to avoid emitting too many events in a short period. + */ + this.debouncedEmit = debounce(this.emitEvents.bind(this), debounceTime, {leading: true, trailing: true}) + this.updateApp(app) + } - /** - * Debounced function to emit the accumulated events. - * This function will be called at most once every 500ms to avoid emitting too many events in a short period. - */ - const debouncedEmit = debounce(emitEvents, 500) + onChange(listener: (events: WatcherEvent[]) => void) { + this.onChangeCallback = listener + } + + async start(): Promise { + const {default: chokidar} = await import('chokidar') + + const extensionDirectories = [...(this.app.configuration.extension_directories ?? ['extensions'])] + const fullExtensionDirectories = extensionDirectories.map((directory) => joinPath(this.app.directory, directory)) + + const watchPaths = [this.app.configuration.path, ...fullExtensionDirectories] + + this.watcher = chokidar.watch(watchPaths, { + ignored: [ + '**/node_modules/**', + '**/.git/**', + '**/*.test.*', + '**/dist/**', + '**/*.swp', + '**/generated/**', + '**/.gitignore', + ], + persistent: true, + ignoreInitial: true, + }) + + this.watcher.on('all', this.handleFileEvent) + this.options.signal.addEventListener('abort', this.close) + } + + updateApp(app: AppLinkedInterface) { + this.app = app + this.extensionPaths = this.app.realExtensions + .map((ext) => normalizePath(ext.directory)) + .filter((dir) => dir !== this.app.directory) + this.extensionPaths.forEach((path) => { + this.ignored[path] ??= this.createIgnoreInstance(path) + }) + } /** * Emits the accumulated events and resets the current events list. * It also logs the number of events emitted and their paths for debugging purposes. */ - function emitEvents() { - const events = currentEvents - currentEvents = [] + private readonly emitEvents = () => { + const events = this.currentEvents + this.currentEvents = [] const message = `🔉 ${events.length} EVENTS EMITTED in files: ${events.map((event) => event.path).join('\n')}` - outputDebug(message, options.stdout) - onChange(events) + outputDebug(message, this.options.stdout) + this.onChangeCallback?.(events) } /** @@ -91,62 +132,44 @@ export async function startFileWatcher( * * @param event - The event to be added */ - function pushEvent(event: WatcherEvent) { - const extension = app.realExtensions.find((ext) => ext.directory === event.extensionPath) + private pushEvent(event: WatcherEvent) { + const extension = this.app.realExtensions.find((ext) => ext.directory === event.extensionPath) const watchPaths = extension?.devSessionWatchPaths + const ignoreInstance = this.ignored[event.extensionPath] + // If the affected extension defines custom watch paths, ignore the event if it's not in the list + // ELSE, if the extension has a custom gitignore file, ignore the event if it matches the patterns + // Explicit watch paths have priority over custom gitignore files if (watchPaths) { const isAValidWatchedPath = watchPaths.some((pattern) => matchGlob(event.path, pattern)) if (!isAValidWatchedPath) return + } else if (ignoreInstance) { + const relative = relativePath(event.extensionPath, event.path) + if (ignoreInstance.ignores(relative)) return + } + + // If the event is for a new extension folder, create a new ignore instance + if (event.type === 'extension_folder_created') { + this.ignored[event.path] = this.createIgnoreInstance(event.path) } + // If the event is already in the list, don't push it again - if (currentEvents.some((extEvent) => extEvent.path === event.path && extEvent.type === event.type)) return - currentEvents.push(event) - debouncedEmit() + if (this.currentEvents.some((extEvent) => extEvent.path === event.path && extEvent.type === event.type)) return + this.currentEvents.push(event) + this.debouncedEmit() } - // Current active extension paths (not defined in the main app configuration file) - // If a change happens outside of these paths, it will be ignored unless is for a new extension being created - // When a new extension is created, the path is added to this list - // When an extension is deleted, the path is removed from this list - // For every change, the corresponding extensionPath will be also reported in the event - let extensionPaths = app.realExtensions - .map((ext) => normalizePath(ext.directory)) - .filter((dir) => dir !== app.directory) - - // Watch the extensions root directories and the app configuration file, nothing else. - const watchPaths = [appConfigurationPath, ...extensionDirectories] - - // Read .gitignore files from extension directories and add the patterns to the ignored list - const customGitIgnoredPatterns = getCustomGitIgnorePatterns(extensionPaths) - - // Create watcher ignoring node_modules, git, test files, dist folders, vim swap files - // PENDING: Use .gitgnore from app and extensions to ignore files. - const watcher = chokidar.watch(watchPaths, { - ignored: [ - '**/node_modules/**', - '**/.git/**', - '**/*.test.*', - '**/dist/**', - '**/*.swp', - '**/generated/**', - ...customGitIgnoredPatterns, - ], - persistent: true, - ignoreInitial: true, - }) - - // Start chokidar watcher for 'all' events - watcher.on('all', (event, path) => { + private readonly handleFileEvent = (event: string, path: string) => { const startTime = startHRTime() - const isConfigAppPath = path === appConfigurationPath + const isConfigAppPath = path === this.app.configuration.path const extensionPath = - extensionPaths.find((dir) => isSubpath(dir, path)) ?? (isConfigAppPath ? app.directory : 'unknown') - const isToml = path.endsWith('.toml') + this.extensionPaths.find((dir) => isSubpath(dir, path)) ?? (isConfigAppPath ? this.app.directory : 'unknown') + const isExtensionToml = path.endsWith('.extension.toml') + const isUnknownExtension = extensionPath === 'unknown' - outputDebug(`🌀: ${event} ${path.replace(app.directory, '')}\n`) + outputDebug(`🌀: ${event} ${path.replace(this.app.directory, '')}\n`) - if (extensionPath === 'unknown' && !isToml) { + if (isUnknownExtension && !isExtensionToml && !isConfigAppPath) { // Ignore an event if it's not part of an existing extension // Except if it is a toml file (either app config or extension config) return @@ -154,18 +177,23 @@ export async function startFileWatcher( switch (event) { case 'change': - if (isToml) { - pushEvent({type: 'extensions_config_updated', path, extensionPath, startTime}) + if (isUnknownExtension) { + // If the extension path is unknown, it means the extension was just created. + // We need to wait for the lock file to disappear before triggering the event. + return + } + if (isExtensionToml || isConfigAppPath) { + this.pushEvent({type: 'extensions_config_updated', path, extensionPath, startTime}) } else { - pushEvent({type: 'file_updated', path, extensionPath, startTime}) + this.pushEvent({type: 'file_updated', path, extensionPath, startTime}) } break case 'add': // If it's a normal non-toml file, just report a file_created event. // If a toml file was added, a new extension(s) is being created. // We need to wait for the lock file to disappear before triggering the event. - if (!isToml) { - pushEvent({type: 'file_created', path, extensionPath, startTime}) + if (!isExtensionToml) { + this.pushEvent({type: 'file_created', path, extensionPath, startTime}) break } let totalWaitedTime = 0 @@ -173,35 +201,34 @@ export async function startFileWatcher( const intervalId = setInterval(() => { if (fileExistsSync(joinPath(realPath, configurationFileNames.lockFile))) { outputDebug(`Waiting for extension to complete creation: ${path}\n`) - totalWaitedTime += 500 + totalWaitedTime += EXTENSION_CREATION_CHECK_INTERVAL_IN_MS } else { clearInterval(intervalId) - extensionPaths.push(realPath) - pushEvent({type: 'extension_folder_created', path: realPath, extensionPath, startTime}) + this.extensionPaths.push(realPath) + this.pushEvent({type: 'extension_folder_created', path: realPath, extensionPath, startTime}) } - if (totalWaitedTime >= 20000) { + if (totalWaitedTime >= EXTENSION_CREATION_TIMEOUT_IN_MS) { clearInterval(intervalId) - options.stderr.write(`Extension creation detection timeout at path: ${path}\nYou might need to restart dev`) + this.options.stderr.write(`Error loading new extension at path: ${path}.\n Please restart the process.`) } - }, 200) + }, EXTENSION_CREATION_CHECK_INTERVAL_IN_MS) break case 'unlink': // Ignore shoplock files if (path.endsWith(configurationFileNames.lockFile)) break if (isConfigAppPath) { - pushEvent({type: 'app_config_deleted', path, extensionPath, startTime}) - } else if (isToml) { + this.pushEvent({type: 'app_config_deleted', path, extensionPath, startTime}) + } else if (isExtensionToml) { // When a toml is deleted, we can consider every extension in that folder was deleted. - extensionPaths = extensionPaths.filter((extPath) => extPath !== extensionPath) - pushEvent({type: 'extension_folder_deleted', path: extensionPath, extensionPath, startTime}) + this.extensionPaths = this.extensionPaths.filter((extPath) => extPath !== extensionPath) + this.pushEvent({type: 'extension_folder_deleted', path: extensionPath, extensionPath, startTime}) } else { - // This could be an extension delete event, Wait 500ms to see if the toml is deleted or not. setTimeout(() => { // If the extensionPath is not longer in the list, the extension was deleted while the timeout was running. - if (!extensionPaths.includes(extensionPath)) return - pushEvent({type: 'file_deleted', path, extensionPath, startTime}) - }, 500) + if (!this.extensionPaths.includes(extensionPath)) return + this.pushEvent({type: 'file_deleted', path, extensionPath, startTime}) + }, FILE_DELETE_TIMEOUT_IN_MS) } break // These events are ignored @@ -209,38 +236,25 @@ export async function startFileWatcher( case 'unlinkDir': break } - }) - - listenForAbortOnWatcher(watcher, options) -} + } -const listenForAbortOnWatcher = (watcher: FSWatcher, options: OutputContextOptions) => { - options.signal.addEventListener('abort', () => { - outputDebug(`Closing file watcher`, options.stdout) - watcher - .close() - .then(() => outputDebug(`File watching closed`, options.stdout)) - .catch((error: Error) => outputDebug(`File watching failed to close: ${error.message}`, options.stderr)) - }) -} + private readonly close = () => { + outputDebug(`Closing file watcher`, this.options.stdout) + this.watcher + ?.close() + .then(() => outputDebug(`File watching closed`, this.options.stdout)) + .catch((error: Error) => outputDebug(`File watching failed to close: ${error.message}`, this.options.stderr)) + } -/** - * Returns the custom gitignore patterns for the given extension directories. - * - * @param extensionDirectories - The extension directories to get the custom gitignore patterns from - * @returns The custom gitignore patterns - */ -function getCustomGitIgnorePatterns(extensionDirectories: string[]): string[] { - return extensionDirectories - .map((dir) => { - const gitIgnorePath = joinPath(dir, '.gitignore') - if (!fileExistsSync(gitIgnorePath)) return [] - const gitIgnoreContent = readFileSync(gitIgnorePath).toString() - return gitIgnoreContent - .split('\n') - .map((pattern) => pattern.trim()) - .filter((pattern) => pattern !== '' && !pattern.startsWith('#')) - .map((pattern) => joinPath(dir, pattern)) - }) - .flat() + // Creates an "Ignore" instance for the given path if a .gitignore file exists, otherwise undefined + private createIgnoreInstance(path: string): ignore.Ignore | undefined { + const gitIgnorePath = joinPath(path, '.gitignore') + if (!fileExistsSync(gitIgnorePath)) return undefined + const gitIgnoreContent = readFileSync(gitIgnorePath) + .toString() + .split('\n') + .map((pattern) => pattern.trim()) + .filter((pattern) => pattern !== '' && !pattern.startsWith('#')) + return ignore.default().add(gitIgnoreContent) + } } diff --git a/packages/app/src/cli/services/dev/extension/payload.test.ts b/packages/app/src/cli/services/dev/extension/payload.test.ts index 285759d9b21..e3312657e3b 100644 --- a/packages/app/src/cli/services/dev/extension/payload.test.ts +++ b/packages/app/src/cli/services/dev/extension/payload.test.ts @@ -120,6 +120,151 @@ describe('getUIExtensionPayload', () => { }) }) + test('returns the right payload for UI Extensions with build_manifest', async () => { + await inTemporaryDirectory(async (tmpDir) => { + // Given + const outputPath = joinPath(tmpDir, 'test-ui-extension.js') + await touchFile(outputPath) + const signal: any = vi.fn() + const stdout: any = vi.fn() + const stderr: any = vi.fn() + vi.spyOn(appModel, 'getUIExtensionRendererVersion').mockResolvedValue({ + name: 'extension-renderer', + version: '1.2.3', + }) + + const buildManifest = { + assets: { + main: {identifier: 'main', module: './src/ExtensionPointA.js', filepath: '/test-ui-extension.js'}, + should_render: { + identifier: 'should_render', + module: './src/ShouldRender.js', + filepath: '/test-ui-extension-conditions.js', + }, + }, + } + + const uiExtension = await testUIExtension({ + outputPath, + directory: tmpDir, + configuration: { + name: 'test-ui-extension', + type: 'ui_extension', + metafields: [], + capabilities: { + network_access: true, + api_access: true, + block_progress: false, + collect_buyer_consent: { + sms_marketing: false, + customer_privacy: false, + }, + iframe: { + sources: ['https://my-iframe.com'], + }, + }, + extension_points: [ + { + target: 'CUSTOM_EXTENSION_POINT', + build_manifest: buildManifest, + }, + ], + }, + devUUID: 'devUUID', + }) + + const options: Omit = { + signal, + stdout, + stderr, + apiKey: 'api-key', + appName: 'foobar', + appDirectory: '/tmp', + extensions: [uiExtension], + grantedScopes: ['scope-a'], + port: 123, + url: 'http://tunnel-url.com', + storeFqdn: 'my-domain.com', + storeId: '123456789', + buildDirectory: tmpDir, + checkoutCartUrl: 'https://my-domain.com/cart', + subscriptionProductUrl: 'https://my-domain.com/subscription', + manifestVersion: '3', + } + const development: Partial = { + hidden: true, + status: 'success', + } + + // When + const got = await getUIExtensionPayload(uiExtension, 'mock-bundle-path', { + ...options, + currentDevelopmentPayload: development, + }) + + // Then + expect(got).toMatchObject({ + assets: { + main: { + lastUpdated: expect.any(Number), + name: 'main', + url: 'http://tunnel-url.com/extensions/devUUID/assets/test-ui-extension.js', + }, + }, + capabilities: { + blockProgress: false, + networkAccess: true, + apiAccess: true, + collectBuyerConsent: { + smsMarketing: false, + }, + iframe: { + sources: ['https://my-iframe.com'], + }, + }, + development: { + hidden: true, + localizationStatus: '', + resource: { + url: '', + }, + root: { + url: 'http://tunnel-url.com/extensions/devUUID', + }, + status: 'success', + }, + extensionPoints: [ + { + target: 'CUSTOM_EXTENSION_POINT', + build_manifest: buildManifest, + assets: { + main: { + lastUpdated: expect.any(Number), + name: 'main', + url: 'http://tunnel-url.com/extensions/devUUID/assets/test-ui-extension.js', + }, + should_render: { + lastUpdated: expect.any(Number), + name: 'should_render', + url: 'http://tunnel-url.com/extensions/devUUID/assets/test-ui-extension-conditions.js', + }, + }, + }, + ], + externalType: 'ui_extension_external', + localization: null, + metafields: null, + // as surfaces come from remote specs, we dont' have real values here + surface: 'test-surface', + title: 'test-ui-extension', + type: 'ui_extension', + uuid: 'devUUID', + version: '1.2.3', + approvalScopes: ['scope-a'], + }) + }) + }) + test('default values', async () => { await inTemporaryDirectory(async (tmpDir) => { // Given diff --git a/packages/app/src/cli/services/dev/extension/payload.ts b/packages/app/src/cli/services/dev/extension/payload.ts index 5cbd10f9155..c721f8bbed5 100644 --- a/packages/app/src/cli/services/dev/extension/payload.ts +++ b/packages/app/src/cli/services/dev/extension/payload.ts @@ -1,12 +1,14 @@ import {getLocalization} from './localization.js' -import {DevNewExtensionPointSchema, UIExtensionPayload} from './payload/models.js' +import {Asset, DevNewExtensionPointSchema, UIExtensionPayload} from './payload/models.js' import {getExtensionPointTargetSurface} from './utilities.js' import {getUIExtensionResourceURL} from '../../../utilities/extensions/configuration.js' import {ExtensionDevOptions} from '../extension.js' import {getUIExtensionRendererVersion} from '../../../models/app/app.js' import {ExtensionInstance} from '../../../models/extensions/extension-instance.js' +import {BuildManifest} from '../../../models/extensions/specifications/ui_extension.js' import {fileLastUpdatedTimestamp} from '@shopify/cli-kit/node/fs' import {useConcurrentOutputContext} from '@shopify/cli-kit/node/ui/components' +import {dirname, joinPath} from '@shopify/cli-kit/node/path' export type GetUIExtensionPayloadOptions = Omit & { currentDevelopmentPayload?: Partial @@ -24,6 +26,9 @@ export async function getUIExtensionPayload( const {localization, status: localizationStatus} = await getLocalization(extension, options) const renderer = await getUIExtensionRendererVersion(extension) + + const extensionPoints = await getExtensionPoints(extension, url) + const defaultConfig = { assets: { main: { @@ -55,7 +60,7 @@ export async function getUIExtensionPayload( status: options.currentDevelopmentPayload?.status || 'success', ...(options.currentDevelopmentPayload || {status: 'success'}), }, - extensionPoints: getExtensionPoints(extension.configuration.extension_points, url), + extensionPoints, localization: localization ?? null, metafields: extension.configuration.metafields.length === 0 ? null : extension.configuration.metafields, type: extension.configuration.type, @@ -80,25 +85,48 @@ export async function getUIExtensionPayload( }) } -function getExtensionPoints(extensionPoints: ExtensionInstance['configuration']['extension_points'], url: string) { +async function getExtensionPoints(extension: ExtensionInstance, url: string) { + const extensionPoints = extension.configuration.extension_points as DevNewExtensionPointSchema[] + if (isNewExtensionPointsSchema(extensionPoints)) { - return extensionPoints.map((extensionPoint) => { - const {target, resource} = extensionPoint + return Promise.all( + extensionPoints.map(async (extensionPoint) => { + const {target, resource} = extensionPoint - return { - ...extensionPoint, - surface: getExtensionPointTargetSurface(target), - root: { - url: `${url}/${target}`, - }, - resource: resource || {url: ''}, - } - }) + return { + ...extensionPoint, + ...(extensionPoint.build_manifest + ? {assets: await extractAssetsFromBuildManifest(extensionPoint.build_manifest, url, extension)} + : {}), + surface: getExtensionPointTargetSurface(target), + root: { + url: `${url}/${target}`, + }, + resource: resource || {url: ''}, + } + }), + ) } return extensionPoints } +async function extractAssetsFromBuildManifest(buildManifest: BuildManifest, url: string, extension: ExtensionInstance) { + if (!buildManifest?.assets) return {} + const assets: {[key: string]: Asset} = {} + + for (const [name, asset] of Object.entries(buildManifest.assets)) { + assets[name] = { + name, + url: `${url}${joinPath('/assets/', asset.filepath)}`, + // eslint-disable-next-line no-await-in-loop + lastUpdated: (await fileLastUpdatedTimestamp(joinPath(dirname(extension.outputPath), asset.filepath))) ?? 0, + } + } + + return assets +} + export function isNewExtensionPointsSchema(extensionPoints: unknown): extensionPoints is DevNewExtensionPointSchema[] { return ( Array.isArray(extensionPoints) && diff --git a/packages/app/src/cli/services/dev/extension/payload/models.ts b/packages/app/src/cli/services/dev/extension/payload/models.ts index 154a64ee4ce..e2716f29e6f 100644 --- a/packages/app/src/cli/services/dev/extension/payload/models.ts +++ b/packages/app/src/cli/services/dev/extension/payload/models.ts @@ -1,4 +1,5 @@ import {Localization} from '../localization.js' +import {BuildManifest} from '../../../../models/extensions/specifications/ui_extension.js' import type {NewExtensionPointSchemaType, ApiVersionSchemaType} from '../../../../models/extensions/schemas.js' interface ExtensionsPayloadInterface { @@ -25,8 +26,17 @@ export interface ExtensionsEndpointPayload extends ExtensionsPayloadInterface { url: string } } +export interface Asset { + name: string + url: string + lastUpdated: number +} export interface DevNewExtensionPointSchema extends NewExtensionPointSchemaType { + build_manifest: BuildManifest + assets: { + [name: string]: Asset + } root: { url: string } @@ -37,10 +47,7 @@ export interface DevNewExtensionPointSchema extends NewExtensionPointSchemaType export interface UIExtensionPayload { assets: { - main: { - url: string - lastUpdated: number - } + main: Asset } capabilities?: Capabilities development: { diff --git a/packages/app/src/cli/services/dev/fetch.test.ts b/packages/app/src/cli/services/dev/fetch.test.ts index 24195dc5225..6fed784317b 100644 --- a/packages/app/src/cli/services/dev/fetch.test.ts +++ b/packages/app/src/cli/services/dev/fetch.test.ts @@ -65,7 +65,7 @@ afterEach(() => { }) describe('fetchOrganizations', async () => { - test('returns fetched organizations from Partners without USE_APP_MANAGEMENT_API', async () => { + test('returns fetched organizations from Partners when App Management is disabled', async () => { // Given const partnersClient: PartnersClient = testDeveloperPlatformClient({ diff --git a/packages/app/src/cli/services/dev/processes/dev-session.test.ts b/packages/app/src/cli/services/dev/processes/dev-session.test.ts index e16ccd17c1a..bb6787b2c10 100644 --- a/packages/app/src/cli/services/dev/processes/dev-session.test.ts +++ b/packages/app/src/cli/services/dev/processes/dev-session.test.ts @@ -11,8 +11,8 @@ import { testWebhookExtensions, } from '../../../models/app/app.test-data.js' import {formData} from '@shopify/cli-kit/node/http' -import {describe, expect, test, vi, beforeEach} from 'vitest' -import {AbortSignal} from '@shopify/cli-kit/node/abort' +import {describe, expect, test, vi, beforeEach, afterEach} from 'vitest' +import {AbortSignal, AbortController} from '@shopify/cli-kit/node/abort' import {flushPromises} from '@shopify/cli-kit/node/promises' import {writeFile} from '@shopify/cli-kit/node/fs' import * as outputContext from '@shopify/cli-kit/node/ui/components' @@ -66,6 +66,7 @@ describe('pushUpdatesForDevSession', () => { let developerPlatformClient: any let appWatcher: AppEventWatcher let app: AppLinkedInterface + let abortController: AbortController beforeEach(() => { vi.mocked(formData).mockReturnValue({append: vi.fn(), getHeaders: vi.fn()} as any) @@ -75,7 +76,7 @@ describe('pushUpdatesForDevSession', () => { developerPlatformClient = testDeveloperPlatformClient() app = testAppLinked() appWatcher = new AppEventWatcher(app) - + abortController = new AbortController() options = { developerPlatformClient, appWatcher, @@ -85,10 +86,14 @@ describe('pushUpdatesForDevSession', () => { } }) + afterEach(() => { + abortController.abort() + }) + test('creates a new dev session successfully when receiving the app watcher start event', async () => { // When - await pushUpdatesForDevSession({stderr, stdout, abortSignal: new AbortSignal()}, options) - await appWatcher.start() + await pushUpdatesForDevSession({stderr, stdout, abortSignal: abortController.signal}, options) + await appWatcher.start({stdout, stderr, signal: abortController.signal}) await flushPromises() // Then @@ -100,8 +105,8 @@ describe('pushUpdatesForDevSession', () => { // When const spyContext = vi.spyOn(outputContext, 'useConcurrentOutputContext') - await pushUpdatesForDevSession({stderr, stdout, abortSignal: new AbortSignal()}, options) - await appWatcher.start() + await pushUpdatesForDevSession({stderr, stdout, abortSignal: abortController.signal}, options) + await appWatcher.start({stdout, stderr, signal: abortController.signal}) await flushPromises() const extension = await testUIExtension() @@ -123,7 +128,7 @@ describe('pushUpdatesForDevSession', () => { developerPlatformClient.devSessionCreate = vi.fn().mockResolvedValue({devSessionCreate: {userErrors}}) // When - await appWatcher.start() + await appWatcher.start({stdout, stderr, signal: abortController.signal}) await pushUpdatesForDevSession({stderr, stdout, abortSignal: new AbortSignal()}, options) await flushPromises() @@ -134,7 +139,7 @@ describe('pushUpdatesForDevSession', () => { test('handles receiving an event before session is ready', async () => { // When - await pushUpdatesForDevSession({stderr, stdout, abortSignal: new AbortSignal()}, options) + await pushUpdatesForDevSession({stderr, stdout, abortSignal: abortController.signal}, options) appWatcher.emit('all', {app, extensionEvents: [{type: 'updated', extension: testWebhookExtensions()}]}) await flushPromises() @@ -152,8 +157,8 @@ describe('pushUpdatesForDevSession', () => { developerPlatformClient.devSessionUpdate = vi.fn().mockResolvedValue({devSessionUpdate: {userErrors}}) // When - await pushUpdatesForDevSession({stderr, stdout, abortSignal: new AbortSignal()}, options) - await appWatcher.start() + await pushUpdatesForDevSession({stderr, stdout, abortSignal: abortController.signal}, options) + await appWatcher.start({stdout, stderr, signal: abortController.signal}) await flushPromises() appWatcher.emit('all', {app, extensionEvents: [{type: 'updated', extension: testWebhookExtensions()}]}) await flushPromises() @@ -171,8 +176,8 @@ describe('pushUpdatesForDevSession', () => { const contextSpy = vi.spyOn(outputContext, 'useConcurrentOutputContext') // When - await pushUpdatesForDevSession({stderr, stdout, abortSignal: new AbortSignal()}, options) - await appWatcher.start() + await pushUpdatesForDevSession({stderr, stdout, abortSignal: abortController.signal}, options) + await appWatcher.start({stdout, stderr, signal: abortController.signal}) await flushPromises() appWatcher.emit('all', event) await flushPromises() diff --git a/packages/app/src/cli/services/dev/processes/dev-session.ts b/packages/app/src/cli/services/dev/processes/dev-session.ts index d9e25d1c8a5..aae1946a4a0 100644 --- a/packages/app/src/cli/services/dev/processes/dev-session.ts +++ b/packages/app/src/cli/services/dev/processes/dev-session.ts @@ -109,11 +109,20 @@ export const pushUpdatesForDevSession: DevProcessFunction = a // Remove aborted controllers from array: bundleControllers = bundleControllers.filter((controller) => !controller.signal.aborted) - // For each extension event, print a message to the terminal + const appConfigEvents = event.extensionEvents.filter((eve) => eve.extension.isAppConfigExtension) + const nonAppConfigEvents = event.extensionEvents.filter((eve) => !eve.extension.isAppConfigExtension) + + if (appConfigEvents.length) { + const outputPrefix = 'app-config' + const message = `App config updated` + await useConcurrentOutputContext({outputPrefix, stripAnsi: false}, () => processOptions.stdout.write(message)) + } + + // For each (non app config) extension event, print a message to the terminal // eslint-disable-next-line @typescript-eslint/no-misused-promises - event.extensionEvents.forEach(async (eve) => { - const outputPrefix = eve.extension.isAppConfigExtension ? 'app-config' : eve.extension.handle - const message = `${eve.extension.isAppConfigExtension ? 'App config' : 'Extension'} ${eve.type}` + nonAppConfigEvents.forEach(async (eve) => { + const outputPrefix = eve.extension.handle + const message = `Extension ${eve.type}` await useConcurrentOutputContext({outputPrefix, stripAnsi: false}, () => processOptions.stdout.write(message)) }) diff --git a/packages/app/src/cli/services/dev/processes/draftable-extension.ts b/packages/app/src/cli/services/dev/processes/draftable-extension.ts index ef64e9fad97..96fd40fc011 100644 --- a/packages/app/src/cli/services/dev/processes/draftable-extension.ts +++ b/packages/app/src/cli/services/dev/processes/draftable-extension.ts @@ -33,20 +33,23 @@ export const pushUpdatesForDraftableExtensions: DevProcessFunction ext.handle) + async function refreshToken() { await developerPlatformClient.refreshToken() } - const handleAppEvent = (event: AppEvent) => { + const handleAppEvent = async (event: AppEvent) => { const extensionEvents = event.extensionEvents .filter((ev) => ev.type === EventType.Updated) .filter((ev) => ev.buildResult?.status === 'ok') + .filter((ev) => draftableExtensions.includes(ev.extension.handle)) - for (const extensionEvent of extensionEvents) { + const promises = extensionEvents.map(async (extensionEvent) => { const extension = extensionEvent.extension const registrationId = remoteExtensions[extension.localIdentifier] if (!registrationId) throw new AbortError(`Extension ${extension.localIdentifier} not found on remote app.`) - return useConcurrentOutputContext({outputPrefix: extension.outputPrefix}, async () => { + await useConcurrentOutputContext({outputPrefix: extension.outputPrefix}, async () => { return performActionWithRetryAfterRecovery( async () => updateExtensionDraft({ @@ -62,7 +65,8 @@ export const pushUpdatesForDraftableExtensions: DevProcessFunction { // mocked for draft extensions @@ -68,7 +67,6 @@ beforeEach(() => { role: 'theme', processing: false, }) - vi.mocked(reloadApp).mockResolvedValue(testAppLinked()) }) const appContextResult = { @@ -130,7 +128,7 @@ describe('setup-dev-processes', () => { allExtensions: [previewable, draftable, theme], }, }) - vi.mocked(reloadApp).mockResolvedValue(localApp) + vi.spyOn(loader, 'reloadApp').mockResolvedValue(localApp) const remoteApp: DevConfig['remoteApp'] = { apiKey: 'api-key', @@ -313,6 +311,7 @@ describe('setup-dev-processes', () => { }, } const localApp = testAppWithConfig() + vi.spyOn(loader, 'reloadApp').mockResolvedValue(localApp) const remoteApp: DevConfig['remoteApp'] = { apiKey: 'api-key', @@ -406,7 +405,7 @@ describe('setup-dev-processes', () => { allExtensions: [previewable, draftable, theme, functionExtension], }, }) - vi.mocked(reloadApp).mockResolvedValue(localApp) + vi.spyOn(loader, 'reloadApp').mockResolvedValue(localApp) const remoteApp: DevConfig['remoteApp'] = { apiKey: 'api-key', @@ -502,6 +501,8 @@ describe('setup-dev-processes', () => { }, }) + vi.spyOn(loader, 'reloadApp').mockResolvedValue(localApp) + const remoteApp: DevConfig['remoteApp'] = { apiKey: 'api-key', apiSecretKeys: [{secret: 'api-secret'}], @@ -594,7 +595,7 @@ describe('setup-dev-processes', () => { ], }, }) - vi.mocked(reloadApp).mockResolvedValue(localApp) + vi.spyOn(loader, 'reloadApp').mockResolvedValue(localApp) const remoteApp: DevConfig['remoteApp'] = { apiKey: 'api-key', diff --git a/packages/app/src/cli/services/dev/processes/setup-dev-processes.ts b/packages/app/src/cli/services/dev/processes/setup-dev-processes.ts index 27c528eef38..84b40b17d63 100644 --- a/packages/app/src/cli/services/dev/processes/setup-dev-processes.ts +++ b/packages/app/src/cli/services/dev/processes/setup-dev-processes.ts @@ -17,8 +17,8 @@ import {getProxyingWebServer} from '../../../utilities/app/http-reverse-proxy.js import {buildAppURLForWeb} from '../../../utilities/app/app-url.js' import {PartnersURLs} from '../urls.js' import {DeveloperPlatformClient} from '../../../utilities/developer-platform-client.js' -import {reloadApp} from '../app-events/app-event-watcher-handler.js' import {AppEventWatcher} from '../app-events/app-event-watcher.js' +import {reloadApp} from '../../../models/app/loader.js' import {getAvailableTCPPort} from '@shopify/cli-kit/node/tcp' import {isTruthy} from '@shopify/cli-kit/node/context/utilities' import {getEnvironmentVariables} from '@shopify/cli-kit/node/environment' @@ -156,6 +156,7 @@ export async function setupDevProcesses({ webs: reloadedApp.webs, backendPort: network.backendPort, frontendPort: network.frontendPort, + organizationId: remoteApp.organizationId, developerPlatformClient, storeFqdn, apiSecret, diff --git a/packages/app/src/cli/services/dev/processes/uninstall-webhook.ts b/packages/app/src/cli/services/dev/processes/uninstall-webhook.ts index f7d4cad2681..af73a463a70 100644 --- a/packages/app/src/cli/services/dev/processes/uninstall-webhook.ts +++ b/packages/app/src/cli/services/dev/processes/uninstall-webhook.ts @@ -10,6 +10,7 @@ interface SendWebhookOptions { storeFqdn: string apiSecret: string webhooksPath: string + organizationId: string } export interface SendWebhookProcess extends BaseProcess { @@ -23,6 +24,7 @@ export const sendWebhook: DevProcessFunction = async ({stdou address: `http://localhost:${options.deliveryPort}${options.webhooksPath}`, sharedSecret: options.apiSecret, storeFqdn: options.storeFqdn, + organizationId: options.organizationId, }) } @@ -31,12 +33,14 @@ export function setupSendUninstallWebhookProcess({ remoteAppUpdated, backendPort, frontendPort, + organizationId, ...options }: Pick & { remoteAppUpdated: boolean backendPort: number frontendPort: number webs: Web[] + organizationId: string }): SendWebhookProcess | undefined { const {backendConfig, frontendConfig} = frontAndBackendConfig(webs) const webhooksPath = @@ -52,6 +56,7 @@ export function setupSendUninstallWebhookProcess({ options: { deliveryPort: backendConfig ? backendPort : frontendPort, webhooksPath, + organizationId, ...options, }, } diff --git a/packages/app/src/cli/services/dev/select-app.test.ts b/packages/app/src/cli/services/dev/select-app.test.ts index 753cd4e0dfb..e00841fc1d6 100644 --- a/packages/app/src/cli/services/dev/select-app.test.ts +++ b/packages/app/src/cli/services/dev/select-app.test.ts @@ -1,6 +1,6 @@ import {selectOrCreateApp} from './select-app.js' import {AppInterface, WebType} from '../../models/app/app.js' -import {MinimalAppIdentifiers, Organization} from '../../models/organization.js' +import {AppApiKeyAndOrgId, Organization} from '../../models/organization.js' import {appNamePrompt, createAsNewAppPrompt, selectAppPrompt} from '../../prompts/dev.js' import {testApp, testOrganizationApp, testDeveloperPlatformClient} from '../../models/app/app.test-data.js' import {describe, expect, vi, test} from 'vitest' @@ -41,7 +41,7 @@ const APPS = [ function mockDeveloperPlatformClient() { const developerPlatformClient = testDeveloperPlatformClient({ createApp: async () => ({...APP1, newApp: true}), - async appFromId({apiKey}: MinimalAppIdentifiers) { + async appFromIdentifiers({apiKey}: AppApiKeyAndOrgId) { if (apiKey === APP1.apiKey) return APP1 if (apiKey === APP2.apiKey) return APP2 throw new Error(`App with client ID ${apiKey} not found`) diff --git a/packages/app/src/cli/services/dev/select-app.ts b/packages/app/src/cli/services/dev/select-app.ts index 72f3b81b542..41e1aabaea0 100644 --- a/packages/app/src/cli/services/dev/select-app.ts +++ b/packages/app/src/cli/services/dev/select-app.ts @@ -4,6 +4,7 @@ import {Organization, MinimalOrganizationApp, OrganizationApp} from '../../model import {getCachedCommandInfo, setCachedCommandTomlPreference} from '../local-storage.js' import {DeveloperPlatformClient} from '../../utilities/developer-platform-client.js' import {AppConfigurationFileName} from '../../models/app/loader.js' +import {BugError} from '@shopify/cli-kit/node/error' /** * Select an app from env, list or create a new one: @@ -44,8 +45,15 @@ export async function selectOrCreateApp( if (selectedToml) setCachedCommandTomlPreference(selectedToml) - const fullSelectedApp = await developerPlatformClient.appFromId(app) - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return fullSelectedApp! + const fullSelectedApp = await developerPlatformClient.appFromIdentifiers(app) + + if (!fullSelectedApp) { + // This is unlikely, and a bug. But we still want a nice user facing message plus appropriate context logged. + throw new BugError( + `Unable to fetch app ${app.apiKey} from Shopify`, + 'Try running `shopify app config link` to connect to an app you have access to.', + ) + } + return fullSelectedApp } } diff --git a/packages/app/src/cli/services/dev/update-extension.test.ts b/packages/app/src/cli/services/dev/update-extension.test.ts index 8bc3971ebbf..6a2f0ac6fd2 100644 --- a/packages/app/src/cli/services/dev/update-extension.test.ts +++ b/packages/app/src/cli/services/dev/update-extension.test.ts @@ -13,7 +13,7 @@ import {ExtensionUpdateDraftMutationVariables} from '../../api/graphql/partners/ import {inTemporaryDirectory, mkdir, writeFile} from '@shopify/cli-kit/node/fs' import {outputInfo} from '@shopify/cli-kit/node/output' import {describe, expect, vi, test} from 'vitest' -import {joinPath} from '@shopify/cli-kit/node/path' +import {dirname, joinPath} from '@shopify/cli-kit/node/path' import {platformAndArch} from '@shopify/cli-kit/node/os' import {randomUUID} from '@shopify/cli-kit/node/crypto' @@ -206,7 +206,9 @@ describe('updateExtensionDraft()', () => { const content = 'test content' const base64Content = Buffer.from(content).toString('base64') await mkdir(joinPath(mockExtension.directory, 'dist')) - await writeFile(joinPath(mockExtension.directory, 'dist', filepath), content) + const outputPath = mockExtension.outputPath + await mkdir(dirname(outputPath)) + await writeFile(outputPath, content) await updateExtensionDraft({ extension: mockExtension, diff --git a/packages/app/src/cli/services/dev/update-extension.ts b/packages/app/src/cli/services/dev/update-extension.ts index 7227be9774b..d1f93186414 100644 --- a/packages/app/src/cli/services/dev/update-extension.ts +++ b/packages/app/src/cli/services/dev/update-extension.ts @@ -38,8 +38,8 @@ export async function updateExtensionDraft({ bundlePath, }: UpdateExtensionDraftOptions) { let encodedFile: string | undefined + const outputPath = extension.getOutputPathForDirectory(bundlePath) if (extension.features.includes('esbuild')) { - const outputPath = extension.getOutputPathForDirectory(bundlePath) const content = await readFile(outputPath) if (!content) return encodedFile = Buffer.from(content).toString('base64') @@ -50,7 +50,7 @@ export async function updateExtensionDraft({ // When updating just the theme extension draft, upload the files as part of the config. config = await themeExtensionConfig(extension) } else { - config = (await extension.deployConfig({apiKey, appConfiguration})) || {} + config = (await extension.deployConfig({apiKey, appConfiguration})) ?? {} } const draftableConfig: {[key: string]: unknown} = { @@ -58,6 +58,8 @@ export async function updateExtensionDraft({ serialized_script: encodedFile, } if (extension.isFunctionExtension) { + // For function drafts we need to use the `extension.outputPath` instead of `bundlePath` + // The wasm in the bundle path is encoded in base64. const compiledFiles = await readFile(extension.outputPath, {encoding: 'base64'}) draftableConfig.uploaded_files = {'dist/index.wasm': compiledFiles} } diff --git a/packages/app/src/cli/services/function/binaries.test.ts b/packages/app/src/cli/services/function/binaries.test.ts index 7656cd9e2f0..67667461063 100644 --- a/packages/app/src/cli/services/function/binaries.test.ts +++ b/packages/app/src/cli/services/function/binaries.test.ts @@ -1,4 +1,4 @@ -import {javyBinary, functionRunnerBinary, downloadBinary, javyPluginBinary} from './binaries.js' +import {javyBinary, functionRunnerBinary, downloadBinary, javyPluginBinary, wasmOptBinary} from './binaries.js' import {fetch, Response} from '@shopify/cli-kit/node/http' import {fileExists, removeFile} from '@shopify/cli-kit/node/fs' import {describe, expect, test, vi} from 'vitest' @@ -135,9 +135,9 @@ describe('javy', () => { describe('javy-plugin', () => { test('properties are set correctly', () => { - expect(javyPlugin.name).toBe('javy_quickjs_provider_v3') - expect(javyPlugin.version).match(/^v\d.\d.\d$/) - expect(javyPlugin.path).toMatch(/(\/|\\)javy_quickjs_provider_v3.wasm$/) + expect(javyPlugin.name).toBe('shopify_functions_javy_v1') + expect(javyPlugin.version).match(/^v\d+$/) + expect(javyPlugin.path).toMatch(/(\/|\\)shopify_functions_javy_v1.wasm$/) }) test('downloadUrl returns the correct URL', () => { @@ -145,7 +145,9 @@ describe('javy-plugin', () => { const url = javyPlugin.downloadUrl('', '') // Then - expect(url).toMatch(/https:\/\/github.com\/bytecodealliance\/javy\/releases\/download\/v\d\.\d\.\d\/plugin.wasm.gz/) + expect(url).toMatch( + /^https:\/\/cdn\.shopify\.com\/shopifycloud\/shopify-functions-javy-plugin\/shopify_functions_javy_v\d+\.wasm$/, + ) }) test('downloads javy-plugin', async () => { @@ -279,3 +281,35 @@ describe('functionRunner', () => { await expect(fileExists(functionRunner.path)).resolves.toBeTruthy() }) }) + +describe('wasm-opt', () => { + const wasmOpt = wasmOptBinary() + + test('properties are set correctly', () => { + expect(wasmOpt.name).toBe('wasm-opt.cjs') + expect(wasmOpt.version).match(/\d.\d.\d$/) + expect(wasmOpt.path).toMatch(/(\/|\\)wasm-opt.cjs$/) + }) + + test('downloadUrl returns the correct URL', () => { + // When + const url = wasmOpt.downloadUrl('', '') + + // Then + expect(url).toMatch(/https:\/\/cdn.jsdelivr.net\/npm\/binaryen@\d{3}\.\d\.\d\/bin\/wasm-opt/) + }) + + test('downloads wasm-opt', async () => { + // Given + await removeFile(wasmOpt.path) + await expect(fileExists(wasmOpt.path)).resolves.toBeFalsy() + vi.mocked(fetch).mockResolvedValue(new Response('wasm-opt')) + + // When + await downloadBinary(wasmOpt) + + // Then + expect(fetch).toHaveBeenCalledOnce() + await expect(fileExists(wasmOpt.path)).resolves.toBeTruthy() + }) +}) diff --git a/packages/app/src/cli/services/function/binaries.ts b/packages/app/src/cli/services/function/binaries.ts index 034d28e18f3..88b5ee9a386 100644 --- a/packages/app/src/cli/services/function/binaries.ts +++ b/packages/app/src/cli/services/function/binaries.ts @@ -4,16 +4,19 @@ import {outputDebug} from '@shopify/cli-kit/node/output' import {performActionWithRetryAfterRecovery} from '@shopify/cli-kit/common/retry' import {fetch} from '@shopify/cli-kit/node/http' import {PipelineSource} from 'stream' +import {pipeline} from 'stream/promises' import stream from 'node:stream/promises' import fs from 'node:fs' import * as gzip from 'node:zlib' import {fileURLToPath} from 'node:url' -const FUNCTION_RUNNER_VERSION = 'v6.3.0' +const FUNCTION_RUNNER_VERSION = 'v6.5.0' const JAVY_VERSION = 'v4.0.0' -// The Javy plugin version does not need to match the Javy version. It should -// match the plugin version used in the function-runner version specified above. -const JAVY_PLUGIN_VERSION = 'v3.2.0' +// The Javy plugin version should match the plugin version used in the +// function-runner version specified above. +const JAVY_PLUGIN_VERSION = 'v1' + +const BINARYEN_VERSION = '120.0.0' interface DownloadableBinary { path: string @@ -93,23 +96,49 @@ class JavyPlugin implements DownloadableBinary { readonly path: string constructor() { - this.name = 'javy_quickjs_provider_v3' + this.name = `shopify_functions_javy_${JAVY_PLUGIN_VERSION}` this.version = JAVY_PLUGIN_VERSION - this.path = joinPath(dirname(fileURLToPath(import.meta.url)), '..', 'bin', 'javy_quickjs_provider_v3.wasm') + this.path = joinPath( + dirname(fileURLToPath(import.meta.url)), + '..', + 'bin', + `shopify_functions_javy_${JAVY_PLUGIN_VERSION}.wasm`, + ) } downloadUrl(_processPlatform: string, _processArch: string) { - return `https://github.com/bytecodealliance/javy/releases/download/${this.version}/plugin.wasm.gz` + return `https://cdn.shopify.com/shopifycloud/shopify-functions-javy-plugin/shopify_functions_javy_${JAVY_PLUGIN_VERSION}.wasm` } async processResponse(responseStream: PipelineSource, outputStream: fs.WriteStream): Promise { - return gunzipResponse(responseStream, outputStream) + return pipeline(responseStream, outputStream) + } +} + +class WasmOptExecutable implements DownloadableBinary { + readonly name: string + readonly version: string + readonly path: string + + constructor(name: string, version: string) { + this.name = name + this.version = version + this.path = joinPath(dirname(fileURLToPath(import.meta.url)), '..', 'bin', name) + } + + downloadUrl(_processPlatform: string, _processArch: string) { + return `https://cdn.jsdelivr.net/npm/binaryen@${this.version}/bin/wasm-opt` + } + + async processResponse(responseStream: PipelineSource, outputStream: fs.WriteStream): Promise { + await stream.pipeline(responseStream, outputStream) } } let _javy: DownloadableBinary let _javyPlugin: DownloadableBinary let _functionRunner: DownloadableBinary +let _wasmOpt: DownloadableBinary export function javyBinary() { if (!_javy) { @@ -132,6 +161,14 @@ export function functionRunnerBinary() { return _functionRunner } +export function wasmOptBinary() { + if (!_wasmOpt) { + _wasmOpt = new WasmOptExecutable('wasm-opt.cjs', BINARYEN_VERSION) + } + + return _wasmOpt +} + export async function downloadBinary(bin: DownloadableBinary) { const isDownloaded = await fileExists(bin.path) if (isDownloaded) { @@ -164,7 +201,7 @@ export async function downloadBinary(bin: DownloadableBinary) { const outputStream = createFileWriteStream(tmpFile) await bin.processResponse(responseStream, outputStream) await chmod(tmpFile, 0o775) - await moveFile(tmpFile, bin.path) + await moveFile(tmpFile, bin.path, {overwrite: true}) }) }, async () => {}, diff --git a/packages/app/src/cli/services/function/build.test.ts b/packages/app/src/cli/services/function/build.test.ts index b1ca9f3f7ea..af07517f4b2 100644 --- a/packages/app/src/cli/services/function/build.test.ts +++ b/packages/app/src/cli/services/function/build.test.ts @@ -1,10 +1,10 @@ -import {buildGraphqlTypes, bundleExtension, runJavy, ExportJavyBuilder, jsExports} from './build.js' -import {javyBinary, javyPluginBinary} from './binaries.js' +import {buildGraphqlTypes, bundleExtension, runJavy, ExportJavyBuilder, jsExports, runWasmOpt} from './build.js' +import {javyBinary, javyPluginBinary, wasmOptBinary} from './binaries.js' import {testApp, testFunctionExtension} from '../../models/app/app.test-data.js' import {beforeEach, describe, expect, test, vi} from 'vitest' import {exec} from '@shopify/cli-kit/node/system' -import {joinPath} from '@shopify/cli-kit/node/path' -import {inTemporaryDirectory, mkdir, writeFile} from '@shopify/cli-kit/node/fs' +import {dirname, joinPath} from '@shopify/cli-kit/node/path' +import {inTemporaryDirectory, mkdir, writeFile, removeFile} from '@shopify/cli-kit/node/fs' import {build as esBuild} from 'esbuild' vi.mock('@shopify/cli-kit/node/system') @@ -63,6 +63,10 @@ async function installShopifyLibrary(tmpDir: string) { const shopifyFunction = joinPath(shopifyFunctionDir, 'index.ts') await mkdir(shopifyFunctionDir) await writeFile(shopifyFunction, '') + + const runModule = joinPath(shopifyFunctionDir, 'run.ts') + await writeFile(runModule, '') + return shopifyFunction } @@ -112,7 +116,23 @@ describe('bundleExtension', () => { const got = bundleExtension(ourFunction, {stdout, stderr, signal, app}) // Then - await expect(got).rejects.toThrow(/Could not find the Shopify Function runtime/) + await expect(got).rejects.toThrow(/Could not find the Shopify Functions JavaScript library/) + }) + }) + + test('errors if shopify library lacks the run module', async () => { + await inTemporaryDirectory(async (tmpDir) => { + // Given + const ourFunction = await testFunctionExtension({dir: tmpDir}) + ourFunction.entrySourceFilePath = joinPath(tmpDir, 'src/index.ts') + const shopifyFunction = await installShopifyLibrary(tmpDir) + await removeFile(joinPath(shopifyFunction, '..', 'run.ts')) + + // When + const got = bundleExtension(ourFunction, {stdout, stderr, signal, app}) + + // Then + await expect(got).rejects.toThrow(/Could not find the Shopify Functions JavaScript library/) }) }) @@ -163,6 +183,27 @@ describe('runJavy', () => { }) }) +describe('runWasmOpt', () => { + test('runs wasm-opt on the module', async () => { + // Given + const ourFunction = await testFunctionExtension() + const modulePath = ourFunction.outputPath + + // When + const got = runWasmOpt(modulePath) + + // Then + await expect(got).resolves.toBeUndefined() + expect(exec).toHaveBeenCalledWith( + 'node', + [wasmOptBinary().name, modulePath, '-Oz', '--enable-bulk-memory', '--strip-debug', '-o', modulePath], + { + cwd: dirname(wasmOptBinary().path), + }, + ) + }) +}) + describe('ExportJavyBuilder', () => { const exports = ['foo-bar', 'foo-baz'] const builder = new ExportJavyBuilder(exports) @@ -173,6 +214,7 @@ describe('ExportJavyBuilder', () => { // Given const ourFunction = await testFunctionExtension({dir: tmpDir}) ourFunction.entrySourceFilePath = joinPath(tmpDir, 'src/index.ts') + const shopifyFunction = await installShopifyLibrary(tmpDir) // When const got = builder.bundle( @@ -210,6 +252,7 @@ describe('ExportJavyBuilder', () => { await inTemporaryDirectory(async (tmpDir) => { // Given const ourFunction = await testFunctionExtension({dir: tmpDir}) + const shopifyFunction = await installShopifyLibrary(tmpDir) // When const got = builder.bundle(ourFunction, {stdout, stderr, signal, app}) diff --git a/packages/app/src/cli/services/function/build.ts b/packages/app/src/cli/services/function/build.ts index 59179aeaca7..8d86c1ba643 100644 --- a/packages/app/src/cli/services/function/build.ts +++ b/packages/app/src/cli/services/function/build.ts @@ -1,19 +1,20 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import {downloadBinary, javyBinary, javyPluginBinary} from './binaries.js' +import {downloadBinary, javyBinary, javyPluginBinary, wasmOptBinary} from './binaries.js' import {ExtensionInstance} from '../../models/extensions/extension-instance.js' import {FunctionConfigType} from '../../models/extensions/specifications/function.js' import {AppInterface} from '../../models/app/app.js' import {EsbuildEnvVarRegex} from '../../constants.js' import {hyphenate, camelize} from '@shopify/cli-kit/common/string' -import {outputDebug} from '@shopify/cli-kit/node/output' +import {outputContent, outputDebug, outputToken} from '@shopify/cli-kit/node/output' import {exec} from '@shopify/cli-kit/node/system' -import {joinPath} from '@shopify/cli-kit/node/path' +import {dirname, joinPath} from '@shopify/cli-kit/node/path' import {build as esBuild, BuildResult} from 'esbuild' import {findPathUp, inTemporaryDirectory, writeFile} from '@shopify/cli-kit/node/fs' import {AbortSignal} from '@shopify/cli-kit/node/abort' import {renderTasks} from '@shopify/cli-kit/node/ui' import {pickBy} from '@shopify/cli-kit/common/object' import {runWithTimer} from '@shopify/cli-kit/node/metadata' +import {AbortError} from '@shopify/cli-kit/node/error' import {Writable} from 'stream' interface JSFunctionBuildOptions { @@ -104,24 +105,47 @@ export async function buildGraphqlTypes( }) } -export async function bundleExtension( - fun: ExtensionInstance, - options: JSFunctionBuildOptions, - processEnv = process.env, -) { +async function checkForShopifyFunctionRuntimeEntrypoint(fun: ExtensionInstance) { const entryPoint = await findPathUp('node_modules/@shopify/shopify_function/index.ts', { type: 'file', cwd: fun.directory, }) - if (!entryPoint) { - throw new Error( - "Could not find the Shopify Function runtime. Make sure you have '@shopify/shopify_function' installed", + + const runModule = await findPathUp('node_modules/@shopify/shopify_function/run.ts', { + type: 'file', + cwd: fun.directory, + }) + + if (!entryPoint || !runModule) { + throw new AbortError( + 'Could not find the Shopify Functions JavaScript library.', + outputContent`Make sure you have the latest ${outputToken.yellow( + '@shopify/shopify_function', + )} library installed.`, + [ + outputContent`Add ${outputToken.green( + '"@shopify/shopify_function": "1.0.0"', + )} to the dependencies section of the package.json file in your function's directory, if not already present.` + .value, + `Run your package manager's install command to update dependencies.`, + ], ) } + if (!fun.entrySourceFilePath) { - throw new Error('Could not find your function entry point. It must be in src/index.js or src/index.ts') + throw new AbortError('Could not find your function entry point. It must be in src/index.js or src/index.ts') } + return entryPoint +} + +export async function bundleExtension( + fun: ExtensionInstance, + options: JSFunctionBuildOptions, + processEnv = process.env, +) { + const entryPoint = await checkForShopifyFunctionRuntimeEntrypoint(fun) + const esbuildOptions = { ...getESBuildOptions(fun.directory, fun.entrySourceFilePath, options.app.dotenv?.variables ?? {}, processEnv), entryPoints: [entryPoint], @@ -162,6 +186,31 @@ function getESBuildOptions( return esbuildOptions } +export async function runWasmOpt(modulePath: string) { + const wasmOpt = wasmOptBinary() + await downloadBinary(wasmOpt) + + const wasmOptDir = dirname(wasmOptBinary().path) + + const command = `node` + const args = [ + // invoke the js-wrapped wasm-opt binary + wasmOptBinary().name, + modulePath, + // pass these options to wasm-opt + '-Oz', + '--enable-bulk-memory', + '--strip-debug', + // overwrite our existing module with the optimized version + '-o', + modulePath, + ] + + outputDebug(`Wasm binary: ${wasmOptBinary().name}`) + outputDebug('Optimizing this wasm binary using wasm-opt.') + await exec(command, args, {cwd: wasmOptDir}) +} + export async function runJavy( fun: ExtensionInstance, options: JSFunctionBuildOptions, @@ -198,7 +247,8 @@ export async function installJavy(app: AppInterface) { const javyRequired = app.allExtensions.some((ext) => ext.features.includes('function') && ext.isJavaScript) if (javyRequired) { const javy = javyBinary() - await downloadBinary(javy) + const plugin = javyPluginBinary() + await Promise.all([downloadBinary(javy), downloadBinary(plugin)]) } } @@ -226,9 +276,7 @@ export class ExportJavyBuilder implements JavyBuilder { } async bundle(fun: ExtensionInstance, options: JSFunctionBuildOptions, processEnv = process.env) { - if (!fun.entrySourceFilePath) { - throw new Error('Could not find your function entry point. It must be in src/index.js or src/index.ts') - } + await checkForShopifyFunctionRuntimeEntrypoint(fun) const contents = this.entrypointContents outputDebug('Generating dist/function.js using generated module:') diff --git a/packages/app/src/cli/services/function/common.test.ts b/packages/app/src/cli/services/function/common.test.ts index 1fd0719823e..c338f1356eb 100644 --- a/packages/app/src/cli/services/function/common.test.ts +++ b/packages/app/src/cli/services/function/common.test.ts @@ -118,7 +118,7 @@ describe('getOrGenerateSchemaPath', () => { vi.mocked(fileExists).mockResolvedValue(true) // When - const result = await getOrGenerateSchemaPath(extension, app, developerPlatformClient) + const result = await getOrGenerateSchemaPath(extension, app, developerPlatformClient, '123') // Then expect(result).toBe(expectedPath) @@ -133,7 +133,7 @@ describe('getOrGenerateSchemaPath', () => { vi.mocked(fileExists).mockResolvedValueOnce(true) // When - const result = await getOrGenerateSchemaPath(extension, app, developerPlatformClient) + const result = await getOrGenerateSchemaPath(extension, app, developerPlatformClient, '123') // Then expect(result).toBe(expectedPath) diff --git a/packages/app/src/cli/services/function/common.ts b/packages/app/src/cli/services/function/common.ts index 49afb3c1ebe..98b0d812981 100644 --- a/packages/app/src/cli/services/function/common.ts +++ b/packages/app/src/cli/services/function/common.ts @@ -27,20 +27,23 @@ export async function inFunctionContext({ userProvidedConfigName, apiKey, callback, + reset, }: { path: string userProvidedConfigName?: string apiKey?: string + reset?: boolean callback: ( app: AppLinkedInterface, developerPlatformClient: DeveloperPlatformClient, ourFunction: ExtensionInstance, + orgId: string, ) => Promise }) { - const {app, developerPlatformClient} = await linkedAppContext({ + const {app, developerPlatformClient, organization} = await linkedAppContext({ directory: path, clientId: apiKey, - forceRelink: false, + forceRelink: reset ?? false, userProvidedConfigName, }) @@ -50,14 +53,14 @@ export async function inFunctionContext({ const ourFunction = allFunctions.find((fun) => fun.directory === path) if (ourFunction) { - return callback(app, developerPlatformClient, ourFunction) + return callback(app, developerPlatformClient, ourFunction, organization.id) } else if (isTerminalInteractive()) { const selectedFunction = await renderAutocompletePrompt({ message: 'Which function?', choices: allFunctions.map((shopifyFunction) => ({label: shopifyFunction.handle, value: shopifyFunction})), }) - return callback(app, developerPlatformClient, selectedFunction) + return callback(app, developerPlatformClient, selectedFunction, organization.id) } else { throw new AbortError('Run this command from a function directory or use `--path` to specify a function directory.') } @@ -67,6 +70,7 @@ export async function getOrGenerateSchemaPath( extension: ExtensionInstance, app: AppLinkedInterface, developerPlatformClient: DeveloperPlatformClient, + orgId: string, ): Promise { const path = joinPath(extension.directory, 'schema.graphql') if (await fileExists(path)) { @@ -79,6 +83,7 @@ export async function getOrGenerateSchemaPath( extension, stdout: false, path: extension.directory, + orgId, }) return (await fileExists(path)) ? path : undefined diff --git a/packages/app/src/cli/services/function/replay.test.ts b/packages/app/src/cli/services/function/replay.test.ts index 0da743c056c..9ffc5f2fe3a 100644 --- a/packages/app/src/cli/services/function/replay.test.ts +++ b/packages/app/src/cli/services/function/replay.test.ts @@ -29,6 +29,7 @@ describe('replay', () => { build: { command: 'make build', path: 'dist/index.wasm', + wasm_opt: true, }, configuration_ui: true, api_version: '2022-07', diff --git a/packages/app/src/cli/services/generate-schema.test.ts b/packages/app/src/cli/services/generate-schema.test.ts index 7a20343e8b5..0551d827763 100644 --- a/packages/app/src/cli/services/generate-schema.test.ts +++ b/packages/app/src/cli/services/generate-schema.test.ts @@ -1,9 +1,8 @@ import {generateSchemaService} from './generate-schema.js' import {testAppLinked, testDeveloperPlatformClient, testFunctionExtension} from '../models/app/app.test-data.js' -import {ApiSchemaDefinitionQueryVariables} from '../api/graphql/functions/api_schema_definition.js' import {describe, expect, vi, test} from 'vitest' import {AbortError} from '@shopify/cli-kit/node/error' -import {inTemporaryDirectory, readFile} from '@shopify/cli-kit/node/fs' +import {inTemporaryDirectory, readFile, mkdir} from '@shopify/cli-kit/node/fs' import {joinPath} from '@shopify/cli-kit/node/path' import * as output from '@shopify/cli-kit/node/output' @@ -28,22 +27,27 @@ describe('generateSchemaService', () => { test('Save the latest GraphQL schema to ./[extension]/schema.graphql when stdout flag is ABSENT', async () => { await inTemporaryDirectory(async (tmpDir) => { // Given + const orgId = 'test' + const extensionDir = joinPath(tmpDir, 'extensions', 'my-function') + await mkdir(extensionDir) + const app = testAppLinked() - const extension = await testFunctionExtension({}) - const apiKey = 'api-key' - const path = tmpDir + const extension = await testFunctionExtension({ + dir: tmpDir, + }) // When await generateSchemaService({ app, extension, - path, + path: tmpDir, stdout: false, developerPlatformClient: testDeveloperPlatformClient(), + orgId, }) // Then - const outputFile = await readFile(joinPath(tmpDir, 'schema.graphql')) + const outputFile = await readFile(joinPath(extension.directory, 'schema.graphql')) expect(outputFile).toEqual('schema') }) }) @@ -55,6 +59,7 @@ describe('generateSchemaService', () => { const extension = await testFunctionExtension() const path = tmpDir const stdout = true + const orgId = '123' const mockOutput = vi.fn() vi.spyOn(output, 'outputInfo').mockImplementation(mockOutput) @@ -65,6 +70,7 @@ describe('generateSchemaService', () => { path, stdout, developerPlatformClient: testDeveloperPlatformClient(), + orgId, }) // Then @@ -75,52 +81,59 @@ describe('generateSchemaService', () => { describe('GraphQL query', () => { test('Uses ApiSchemaDefinitionQuery when not using targets', async () => { await inTemporaryDirectory(async (tmpDir) => { - // Given + const extensionDir = joinPath(tmpDir, 'extensions', 'my-function') + await mkdir(extensionDir) + const app = testAppLinked() const extension = await testFunctionExtension({ + dir: tmpDir, config: { name: 'test function extension', description: 'description', type: 'api_type', build: { command: 'echo "hello world"', + wasm_opt: true, }, api_version: 'unstable', configuration_ui: true, metafields: [], }, }) - const apiKey = 'api-key' + + const orgId = 'test' const path = tmpDir - const { - configuration: {api_version: version}, - type, - } = extension + const version = extension.configuration.api_version const developerPlatformClient = testDeveloperPlatformClient() - // When await generateSchemaService({ app, extension, path, stdout: false, developerPlatformClient, + orgId, }) - // Then - expect(developerPlatformClient.apiSchemaDefinition).toHaveBeenCalledWith({ - apiKey, - version, - type, - }) + expect(developerPlatformClient.apiSchemaDefinition).toHaveBeenCalledWith( + { + version, + type: extension.configuration.type, + }, + app.configuration.client_id, + orgId, + ) }) }) test('Uses TargetSchemaDefinitionQuery when targets present', async () => { await inTemporaryDirectory(async (tmpDir) => { - // Given + const extensionDir = joinPath(tmpDir, 'extensions', 'my-function') + await mkdir(extensionDir) + const app = testAppLinked() const extension = await testFunctionExtension({ + dir: tmpDir, config: { name: 'test function extension', description: 'description', @@ -135,33 +148,37 @@ describe('generateSchemaService', () => { ], build: { command: 'echo "hello world"', + wasm_opt: true, }, api_version: 'unstable', configuration_ui: true, metafields: [], }, }) - const apiKey = 'api-key' + const path = tmpDir const expectedTarget = extension.configuration.targeting![0]!.target const version = extension.configuration.api_version + const orgId = 'test' const developerPlatformClient = testDeveloperPlatformClient() - // When await generateSchemaService({ app, extension, path, stdout: false, developerPlatformClient, + orgId, }) - // Then - expect(developerPlatformClient.targetSchemaDefinition).toHaveBeenCalledWith({ - apiKey, - version, - target: expectedTarget, - }) + expect(developerPlatformClient.targetSchemaDefinition).toHaveBeenCalledWith( + { + handle: expectedTarget, + version, + }, + app.configuration.client_id, + orgId, + ) }) }) }) @@ -170,9 +187,9 @@ describe('generateSchemaService', () => { // Given const app = testAppLinked() const extension = await testFunctionExtension() - const apiKey = 'api-key' + const orgId = '123' const developerPlatformClient = testDeveloperPlatformClient({ - apiSchemaDefinition: (_input: ApiSchemaDefinitionQueryVariables) => Promise.resolve(null), + apiSchemaDefinition: () => Promise.resolve(null), }) // When @@ -182,6 +199,7 @@ describe('generateSchemaService', () => { path: '', stdout: true, developerPlatformClient, + orgId, }) // Then diff --git a/packages/app/src/cli/services/generate-schema.ts b/packages/app/src/cli/services/generate-schema.ts index 8544d50b5b2..4c81daaa679 100644 --- a/packages/app/src/cli/services/generate-schema.ts +++ b/packages/app/src/cli/services/generate-schema.ts @@ -1,6 +1,6 @@ import {DeveloperPlatformClient} from '../utilities/developer-platform-client.js' -import {ApiSchemaDefinitionQueryVariables} from '../api/graphql/functions/api_schema_definition.js' -import {TargetSchemaDefinitionQueryVariables} from '../api/graphql/functions/target_schema_definition.js' +import {SchemaDefinitionByApiTypeQueryVariables} from '../api/graphql/functions/generated/schema-definition-by-api-type.js' +import {SchemaDefinitionByTargetQueryVariables} from '../api/graphql/functions/generated/schema-definition-by-target.js' import {ExtensionInstance} from '../models/extensions/extension-instance.js' import {FunctionConfigType} from '../models/extensions/specifications/function.js' import {AppLinkedInterface} from '../models/app/app.js' @@ -15,12 +15,12 @@ interface GenerateSchemaOptions { stdout: boolean path: string developerPlatformClient: DeveloperPlatformClient + orgId: string } export async function generateSchemaService(options: GenerateSchemaOptions) { - const {extension, stdout, developerPlatformClient, app} = options + const {extension, stdout, developerPlatformClient, app, orgId} = options const apiKey = app.configuration.client_id - const {api_version: version, type, targeting} = extension.configuration const usingTargets = Boolean(targeting?.length) const definition = await (usingTargets @@ -31,19 +31,21 @@ export async function generateSchemaService(options: GenerateSchemaOptions) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion target: targeting![0]!.target, version, + orgId, }) - : generateSchemaFromType({ + : generateSchemaFromApiType({ localIdentifier: extension.localIdentifier, developerPlatformClient, apiKey, type, version, + orgId, })) if (stdout) { outputInfo(definition) } else { - const outputPath = joinPath(options.path, 'schema.graphql') + const outputPath = joinPath(extension.directory, 'schema.graphql') await writeFile(outputPath, definition) outputInfo(`GraphQL Schema for ${extension.localIdentifier} written to ${outputPath}`) } @@ -54,6 +56,7 @@ interface BaseGenerateSchemaOptions { developerPlatformClient: DeveloperPlatformClient apiKey: string version: string + orgId: string } interface GenerateSchemaFromTargetOptions extends BaseGenerateSchemaOptions { @@ -66,13 +69,14 @@ async function generateSchemaFromTarget({ apiKey, target, version, + orgId, }: GenerateSchemaFromTargetOptions): Promise { - const variables: TargetSchemaDefinitionQueryVariables = { - apiKey, - target, + const variables: SchemaDefinitionByTargetQueryVariables = { + handle: target, version, } - const definition = await developerPlatformClient.targetSchemaDefinition(variables) + // Api key required for partners reqs, can be removed once fully migrated to AMF + const definition = await developerPlatformClient.targetSchemaDefinition(variables, apiKey, orgId) if (!definition) { throw new AbortError( @@ -88,19 +92,20 @@ interface GenerateSchemaFromType extends BaseGenerateSchemaOptions { type: string } -async function generateSchemaFromType({ +async function generateSchemaFromApiType({ localIdentifier, developerPlatformClient, apiKey, version, type, + orgId, }: GenerateSchemaFromType): Promise { - const variables: ApiSchemaDefinitionQueryVariables = { - apiKey, + const variables: SchemaDefinitionByApiTypeQueryVariables = { version, type, } - const definition = await developerPlatformClient.apiSchemaDefinition(variables) + + const definition = await developerPlatformClient.apiSchemaDefinition(variables, apiKey, orgId) if (!definition) { throw new AbortError( diff --git a/packages/app/src/cli/services/generate/extension.test.ts b/packages/app/src/cli/services/generate/extension.test.ts index 29b8728d864..4c4cbfc16a3 100644 --- a/packages/app/src/cli/services/generate/extension.test.ts +++ b/packages/app/src/cli/services/generate/extension.test.ts @@ -29,6 +29,7 @@ import * as git from '@shopify/cli-kit/node/git' import {joinPath, dirname} from '@shopify/cli-kit/node/path' import {slugify} from '@shopify/cli-kit/common/string' +vi.mock('../../models/app/validation/multi-cli-warning.js') vi.mock('@shopify/cli-kit/node/node-package-manager', async () => { const actual: any = await vi.importActual('@shopify/cli-kit/node/node-package-manager') return { diff --git a/packages/app/src/cli/services/import-extensions.ts b/packages/app/src/cli/services/import-extensions.ts index 7f94c0d6311..a702c202a2b 100644 --- a/packages/app/src/cli/services/import-extensions.ts +++ b/packages/app/src/cli/services/import-extensions.ts @@ -1,6 +1,6 @@ import {ensureExtensionDirectoryExists} from './extensions/common.js' import {getExtensions} from './fetch-extensions.js' -import {AppLinkedInterface} from '../models/app/app.js' +import {AppLinkedInterface, CurrentAppConfiguration} from '../models/app/app.js' import {updateAppIdentifiers, IdentifiersExtensions} from '../models/app/identifiers.js' import {ExtensionRegistration} from '../api/graphql/all_app_extension_registrations.js' import {DeveloperPlatformClient} from '../utilities/developer-platform-client.js' @@ -17,7 +17,11 @@ interface ImportOptions { remoteApp: OrganizationApp developerPlatformClient: DeveloperPlatformClient extensionTypes: string[] - buildTomlObject: (ext: ExtensionRegistration, allExtensions: ExtensionRegistration[]) => string + buildTomlObject: ( + ext: ExtensionRegistration, + allExtensions: ExtensionRegistration[], + appConfig: CurrentAppConfiguration, + ) => string } export async function importExtensions(options: ImportOptions) { @@ -44,7 +48,10 @@ export async function importExtensions(options: ImportOptions) { const choices = extensions.map((ext) => { return {label: ext.title, value: ext.uuid} }) - choices.push({label: 'All', value: 'All'}) + + if (extensions.length > 1) { + choices.push({label: 'All', value: 'All'}) + } const promptAnswer = await renderSelectPrompt({message: 'Extensions to migrate', choices}) const extensionsToMigrate = @@ -54,7 +61,7 @@ export async function importExtensions(options: ImportOptions) { const extensionUuids: IdentifiersExtensions = {} const importPromises = extensionsToMigrate.map(async (ext) => { const directory = await ensureExtensionDirectoryExists({app: options.app, name: ext.title}) - const tomlObject = options.buildTomlObject(ext, extensionRegistrations) + const tomlObject = options.buildTomlObject(ext, extensionRegistrations, options.app.configuration) const path = joinPath(directory, 'shopify.extension.toml') await writeFile(path, tomlObject) const handle = slugify(ext.title.substring(0, MAX_EXTENSION_HANDLE_LENGTH)) diff --git a/packages/app/src/cli/services/info.test.ts b/packages/app/src/cli/services/info.test.ts index ce2f958712e..15e021e008d 100644 --- a/packages/app/src/cli/services/info.test.ts +++ b/packages/app/src/cli/services/info.test.ts @@ -1,6 +1,6 @@ import {InfoOptions, info} from './info.js' import {AppInterface, AppLinkedInterface} from '../models/app/app.js' -import {MinimalAppIdentifiers, OrganizationApp} from '../models/organization.js' +import {AppApiKeyAndOrgId, OrganizationApp} from '../models/organization.js' import {selectOrganizationPrompt} from '../prompts/dev.js' import { testDeveloperPlatformClient, @@ -34,7 +34,7 @@ const ORG1 = { function buildDeveloperPlatformClient(): DeveloperPlatformClient { return testDeveloperPlatformClient({ - async appFromId({apiKey}: MinimalAppIdentifiers): Promise { + async appFromIdentifiers({apiKey}: AppApiKeyAndOrgId): Promise { switch (apiKey) { case '123': return APP1 diff --git a/packages/app/src/cli/services/init/init.ts b/packages/app/src/cli/services/init/init.ts index 8056d1cbf78..1a3e2659585 100644 --- a/packages/app/src/cli/services/init/init.ts +++ b/packages/app/src/cli/services/init/init.ts @@ -5,6 +5,7 @@ import {OrganizationApp} from '../../models/organization.js' import {DeveloperPlatformClient} from '../../utilities/developer-platform-client.js' import {loadConfigForAppCreation} from '../../models/app/loader.js' import {SelectAppOrNewAppNameResult} from '../../commands/app/init.js' +import {linkedAppContext} from '../app-context.js' import { findUpAndReadPackageJson, lockfiles, @@ -179,7 +180,7 @@ async function init(options: InitOptions) { { title: 'Cleaning up', task: async () => { - await cleanup(templateScaffoldDir) + await cleanup(templateScaffoldDir, packageManager) }, }, { @@ -218,6 +219,14 @@ async function init(options: InitOptions) { false, ) + const appContextResult = await linkedAppContext({ + directory: outputDirectory, + clientId: undefined, + forceRelink: false, + userProvidedConfigName: undefined, + unsafeReportMode: false, + }) + renderSuccess({ headline: [{userInput: hyphenizedName}, 'is ready for you to build!'], nextSteps: [ @@ -234,7 +243,7 @@ async function init(options: InitOptions) { ], }) - return {outputDirectory} + return {app: appContextResult.app} } async function ensureAppDirectoryIsAvailable(directory: string, name: string): Promise { diff --git a/packages/app/src/cli/services/init/template/cleanup.test.ts b/packages/app/src/cli/services/init/template/cleanup.test.ts index 51a4240c06c..37fe613d02e 100644 --- a/packages/app/src/cli/services/init/template/cleanup.test.ts +++ b/packages/app/src/cli/services/init/template/cleanup.test.ts @@ -2,6 +2,7 @@ import cleanup from './cleanup.js' import {describe, expect, test} from 'vitest' import {inTemporaryDirectory, mkdir, writeFile, fileExists} from '@shopify/cli-kit/node/fs' import {joinPath} from '@shopify/cli-kit/node/path' +import {PackageManager} from '@shopify/cli-kit/node/node-package-manager' describe('cleanup', () => { async function mockProjectFolder(tmpDir: string) { @@ -35,7 +36,7 @@ describe('cleanup', () => { await mockProjectFolder(tmpDir) // When - await cleanup(tmpDir) + await cleanup(tmpDir, 'npm') // Then await expect(fileExists(joinPath(tmpDir, '.git'))).resolves.toBe(false) @@ -52,7 +53,7 @@ describe('cleanup', () => { await mockProjectFolder(tmpDir) // When - await cleanup(tmpDir) + await cleanup(tmpDir, 'npm') // Then await expect(fileExists(joinPath(tmpDir, 'server.js'))).resolves.toBe(true) @@ -60,4 +61,42 @@ describe('cleanup', () => { await expect(fileExists(joinPath(tmpDir, 'frontend', 'node_modules'))).resolves.toBe(true) }) }) + + test.each(['npm', 'yarn', 'pnpm', 'bun'])('deletes unused lockfiles for %s', async (packageManager) => { + await inTemporaryDirectory(async (tmpDir) => { + await mockProjectFolder(tmpDir) + await writeFile(joinPath(tmpDir, 'package-lock.json'), '{}') + await writeFile(joinPath(tmpDir, 'yarn.lock'), '{}') + await writeFile(joinPath(tmpDir, 'pnpm-lock.yaml'), '{}') + await writeFile(joinPath(tmpDir, 'bun.lockb'), '{}') + + // When + await cleanup(tmpDir, packageManager as PackageManager) + + // Then + await expect(fileExists(joinPath(tmpDir, 'package-lock.json'))).resolves.toBe(packageManager === 'npm') + await expect(fileExists(joinPath(tmpDir, 'yarn.lock'))).resolves.toBe(packageManager === 'yarn') + await expect(fileExists(joinPath(tmpDir, 'pnpm-lock.yaml'))).resolves.toBe(packageManager === 'pnpm') + await expect(fileExists(joinPath(tmpDir, 'bun.lockb'))).resolves.toBe(packageManager === 'bun') + }) + }) + + test('deletes all lockfiles for unknown package manager', async () => { + await inTemporaryDirectory(async (tmpDir) => { + await mockProjectFolder(tmpDir) + await writeFile(joinPath(tmpDir, 'package-lock.json'), '{}') + await writeFile(joinPath(tmpDir, 'yarn.lock'), '{}') + await writeFile(joinPath(tmpDir, 'pnpm-lock.yaml'), '{}') + await writeFile(joinPath(tmpDir, 'bun.lockb'), '{}') + + // When + await cleanup(tmpDir, 'unknown') + + // Then + await expect(fileExists(joinPath(tmpDir, 'package-lock.json'))).resolves.toBe(false) + await expect(fileExists(joinPath(tmpDir, 'yarn.lock'))).resolves.toBe(false) + await expect(fileExists(joinPath(tmpDir, 'pnpm-lock.yaml'))).resolves.toBe(false) + await expect(fileExists(joinPath(tmpDir, 'bun.lockb'))).resolves.toBe(false) + }) + }) }) diff --git a/packages/app/src/cli/services/init/template/cleanup.ts b/packages/app/src/cli/services/init/template/cleanup.ts index fa46e90b370..fde535065e4 100644 --- a/packages/app/src/cli/services/init/template/cleanup.ts +++ b/packages/app/src/cli/services/init/template/cleanup.ts @@ -1,7 +1,8 @@ -import {rmdir, glob} from '@shopify/cli-kit/node/fs' +import {rmdir, glob, fileExistsSync, unlinkFile} from '@shopify/cli-kit/node/fs' +import {Lockfile, lockfilesByManager, PackageManager} from '@shopify/cli-kit/node/node-package-manager' import {joinPath} from '@shopify/cli-kit/node/path' -export default async function cleanup(webOutputDirectory: string) { +export default async function cleanup(webOutputDirectory: string, packageManager: PackageManager) { const gitPaths = await glob( [ joinPath(webOutputDirectory, '**', '.git'), @@ -20,5 +21,14 @@ export default async function cleanup(webOutputDirectory: string) { }, ) - return Promise.all(gitPaths.map((path) => rmdir(path, {force: true}))).then(() => {}) + const gitPathPromises = gitPaths.map((path) => rmdir(path, {force: true})) + + const lockfilePromises = Object.entries(lockfilesByManager) + .filter(([manager, lockfile]) => manager !== packageManager && lockfile) + .map(([_, lockfile]) => { + const path = joinPath(webOutputDirectory, lockfile as Lockfile) + if (fileExistsSync(path)) return unlinkFile(path) + }, []) + + return Promise.all([...gitPathPromises, ...lockfilePromises]) } diff --git a/packages/app/src/cli/services/webhook/request-api-versions.test.ts b/packages/app/src/cli/services/webhook/request-api-versions.test.ts index 3d071fa90ed..4f3777fc4d4 100644 --- a/packages/app/src/cli/services/webhook/request-api-versions.test.ts +++ b/packages/app/src/cli/services/webhook/request-api-versions.test.ts @@ -5,7 +5,8 @@ import {describe, expect, test} from 'vitest' describe('requestApiVersions', () => { test('calls partners to request data and returns ordered array', async () => { // Given - When - const got = await requestApiVersions(testDeveloperPlatformClient()) + const organizationId = 'organizationId' + const got = await requestApiVersions(testDeveloperPlatformClient(), organizationId) // Then expect(got).toEqual(['2023', '2022', 'unstable']) diff --git a/packages/app/src/cli/services/webhook/request-api-versions.ts b/packages/app/src/cli/services/webhook/request-api-versions.ts index 2e94a9a510e..0a0d1eb9304 100644 --- a/packages/app/src/cli/services/webhook/request-api-versions.ts +++ b/packages/app/src/cli/services/webhook/request-api-versions.ts @@ -14,10 +14,14 @@ export const GetApiVersionsQuery = ` * Requests available api-versions in order to validate flags or present a list of options * * @param developerPlatformClient - The client to access the platform API + * @param organizationId - Organization ID required by the API to verify permissions * @returns List of public api-versions */ -export async function requestApiVersions(developerPlatformClient: DeveloperPlatformClient): Promise { - const {publicApiVersions: result}: PublicApiVersionsSchema = await developerPlatformClient.apiVersions() +export async function requestApiVersions( + developerPlatformClient: DeveloperPlatformClient, + organizationId: string, +): Promise { + const {publicApiVersions: result}: PublicApiVersionsSchema = await developerPlatformClient.apiVersions(organizationId) const unstableIdx = result.indexOf('unstable') if (unstableIdx === -1) { diff --git a/packages/app/src/cli/services/webhook/request-sample.test.ts b/packages/app/src/cli/services/webhook/request-sample.test.ts index 943cafead03..0a675556e34 100644 --- a/packages/app/src/cli/services/webhook/request-sample.test.ts +++ b/packages/app/src/cli/services/webhook/request-sample.test.ts @@ -9,10 +9,12 @@ const inputValues: SendSampleWebhookVariables = { address: 'https://example.org', shared_secret: 'A_SECRET', } +const organizationId = 'organizationId' + describe('getWebhookSample', () => { test('calls partners to request data without api-key', async () => { // Given/When - const got = await getWebhookSample(testDeveloperPlatformClient(), inputValues) + const got = await getWebhookSample(testDeveloperPlatformClient(), inputValues, organizationId) // Then expect(got.samplePayload).toEqual('{ "sampleField": "SampleValue" }') @@ -29,7 +31,7 @@ describe('getWebhookSample', () => { } // When - const got = await getWebhookSample(testDeveloperPlatformClient(), variables) + const got = await getWebhookSample(testDeveloperPlatformClient(), variables, organizationId) // Then expect(got.samplePayload).toEqual('{ "sampleField": "SampleValue" }') diff --git a/packages/app/src/cli/services/webhook/request-sample.ts b/packages/app/src/cli/services/webhook/request-sample.ts index 68d88edeec4..b6c6ab813c5 100644 --- a/packages/app/src/cli/services/webhook/request-sample.ts +++ b/packages/app/src/cli/services/webhook/request-sample.ts @@ -25,6 +25,7 @@ export interface UserErrors { fields: string[] } +// eslint-disable-next-line @shopify/cli/no-inline-graphql export const sendSampleWebhookMutation = ` mutation samplePayload($topic: String!, $api_version: String!, $address: String!, $delivery_method: String!, $shared_secret: String!, $api_key: String) { sendSampleWebhook(input: {topic: $topic, apiVersion: $api_version, address: $address, deliveryMethod: $delivery_method, sharedSecret: $shared_secret, apiKey: $api_key}) { @@ -53,14 +54,17 @@ export const sendSampleWebhookMutation = ` * - address - A destination for the webhook notification * - shared_secret - A secret to generate the HMAC header apps can use to validate the origin * - api_key - Client Api Key required to validate Event-Bridge addresses (optional) + * @param organizationId - Organization ID required by the API to verify permissions * @returns Empty if a remote delivery was requested, payload data if a local delivery was requested */ export async function getWebhookSample( developerPlatformClient: DeveloperPlatformClient, variables: SendSampleWebhookVariables, + organizationId: string, ): Promise { const {sendSampleWebhook: result}: SendSampleWebhookSchema = await developerPlatformClient.sendSampleWebhook( variables, + organizationId, ) return result diff --git a/packages/app/src/cli/services/webhook/request-topics.test.ts b/packages/app/src/cli/services/webhook/request-topics.test.ts index e0267d856fa..83a680fd428 100644 --- a/packages/app/src/cli/services/webhook/request-topics.test.ts +++ b/packages/app/src/cli/services/webhook/request-topics.test.ts @@ -3,11 +3,12 @@ import {testDeveloperPlatformClient} from '../../models/app/app.test-data.js' import {describe, expect, test} from 'vitest' const aVersion = 'SOME_VERSION' +const anOrganizationId = 'organizationId' describe('requestTopics', () => { test('calls partners to request topics data and returns array', async () => { // Given/When - const got = await requestTopics(testDeveloperPlatformClient(), aVersion) + const got = await requestTopics(testDeveloperPlatformClient(), aVersion, anOrganizationId) // Then expect(got).toEqual(['orders/create', 'shop/redact']) diff --git a/packages/app/src/cli/services/webhook/request-topics.ts b/packages/app/src/cli/services/webhook/request-topics.ts index f8b3bdc9f2d..f93a162e3a7 100644 --- a/packages/app/src/cli/services/webhook/request-topics.ts +++ b/packages/app/src/cli/services/webhook/request-topics.ts @@ -19,14 +19,16 @@ export const getTopicsQuery = ` * * @param developerPlatformClient - The client to access the platform API * @param apiVersion - ApiVersion of the topics + * @param organizationId - Organization ID required by the API to verify permissions * @returns - Available webhook topics for the api-version */ export async function requestTopics( developerPlatformClient: DeveloperPlatformClient, apiVersion: string, + organizationId: string, ): Promise { const variables: WebhookTopicsVariables = {api_version: apiVersion} - const {webhookTopics: result}: WebhookTopicsSchema = await developerPlatformClient.topics(variables) + const {webhookTopics: result}: WebhookTopicsSchema = await developerPlatformClient.topics(variables, organizationId) return result } diff --git a/packages/app/src/cli/services/webhook/send-app-uninstalled-webhook.test.ts b/packages/app/src/cli/services/webhook/send-app-uninstalled-webhook.test.ts index da1d3d3b6c5..025c8ac52dd 100644 --- a/packages/app/src/cli/services/webhook/send-app-uninstalled-webhook.test.ts +++ b/packages/app/src/cli/services/webhook/send-app-uninstalled-webhook.test.ts @@ -10,6 +10,7 @@ vi.mock('@shopify/cli-kit/node/system') const address = 'http://localhost:3000/test/path' const storeFqdn = 'test-store.myshopify.io' +const organizationId = 'organizationId' describe('sendUninstallWebhookToAppServer', () => { test('requests sample and API versions, triggers local webhook', async () => { @@ -22,6 +23,7 @@ describe('sendUninstallWebhookToAppServer', () => { sharedSecret: 'sharedSecret', storeFqdn, developerPlatformClient: testDeveloperPlatformClient(), + organizationId, }) expect(result).toBe(true) @@ -45,6 +47,7 @@ describe('sendUninstallWebhookToAppServer', () => { sharedSecret: 'sharedSecret', storeFqdn, developerPlatformClient, + organizationId, }) expect(result).toBe(false) @@ -68,6 +71,7 @@ describe('sendUninstallWebhookToAppServer', () => { sharedSecret: 'sharedSecret', storeFqdn, developerPlatformClient, + organizationId, }) expect(result).toBe(true) diff --git a/packages/app/src/cli/services/webhook/send-app-uninstalled-webhook.ts b/packages/app/src/cli/services/webhook/send-app-uninstalled-webhook.ts index 38cdc1fc0a7..a8581936c01 100644 --- a/packages/app/src/cli/services/webhook/send-app-uninstalled-webhook.ts +++ b/packages/app/src/cli/services/webhook/send-app-uninstalled-webhook.ts @@ -13,12 +13,13 @@ interface SendUninstallWebhookToAppServerOptions { storeFqdn: string address: string sharedSecret: string + organizationId: string } export async function sendUninstallWebhookToAppServer( options: SendUninstallWebhookToAppServerOptions, ): Promise { - const apiVersions = await requestApiVersions(options.developerPlatformClient) + const apiVersions = await requestApiVersions(options.developerPlatformClient, options.organizationId) const variables: SendSampleWebhookVariables = { topic: 'app/uninstalled', // eslint-disable-next-line @typescript-eslint/no-non-null-assertion @@ -27,7 +28,7 @@ export async function sendUninstallWebhookToAppServer( delivery_method: DELIVERY_METHOD.LOCALHOST, shared_secret: options.sharedSecret, } - const sample = await getWebhookSample(options.developerPlatformClient, variables) + const sample = await getWebhookSample(options.developerPlatformClient, variables, options.organizationId) options.stdout.write('Sending APP_UNINSTALLED webhook to app server') diff --git a/packages/app/src/cli/services/webhook/trigger-options.test.ts b/packages/app/src/cli/services/webhook/trigger-options.test.ts index 3dcc2c25dcb..ab8a5afb562 100644 --- a/packages/app/src/cli/services/webhook/trigger-options.test.ts +++ b/packages/app/src/cli/services/webhook/trigger-options.test.ts @@ -18,6 +18,7 @@ const API_KEY = 'AN_API_KEY' const APP = testAppLinked() const ORGANIZATION_APP = testOrganizationApp() const developerPlatformClient = testDeveloperPlatformClient() +const organizationId = ORGANIZATION_APP.organizationId afterEach(() => { mockAndCaptureOutput().clear() @@ -30,7 +31,7 @@ describe('collectApiVersion', () => { vi.mocked(apiVersionPrompt) // When - const version = await collectApiVersion(developerPlatformClient, '2023-01') + const version = await collectApiVersion(developerPlatformClient, '2023-01', organizationId) // Then expect(version).toEqual('2023-01') @@ -43,7 +44,7 @@ describe('collectApiVersion', () => { vi.mocked(requestApiVersions).mockResolvedValue(['2023-01', 'unstable']) // When - const version = await collectApiVersion(developerPlatformClient, undefined) + const version = await collectApiVersion(developerPlatformClient, undefined, organizationId) // Then expect(version).toEqual('2023-01') @@ -59,7 +60,12 @@ describe('collectTopic', () => { vi.mocked(requestTopics).mockResolvedValue(['shop/redact', 'orders/create']) // When - const method = await collectTopic(developerPlatformClient, '2023-01', 'shop/redact') + const method = await collectTopic( + developerPlatformClient, + '2023-01', + 'shop/redact', + ORGANIZATION_APP.organizationId, + ) // Then expect(method).toEqual('shop/redact') @@ -72,7 +78,9 @@ describe('collectTopic', () => { vi.mocked(requestTopics).mockResolvedValue(['shop/redact', 'orders/create']) // When then - await expect(collectTopic(developerPlatformClient, '2023-01', 'unknown/topic')).rejects.toThrow(AbortError) + await expect(collectTopic(developerPlatformClient, '2023-01', 'unknown/topic', organizationId)).rejects.toThrow( + AbortError, + ) expect(topicPrompt).toHaveBeenCalledTimes(0) }) @@ -82,7 +90,7 @@ describe('collectTopic', () => { vi.mocked(requestTopics).mockResolvedValue(['shop/redact', 'orders/create']) // When - const topic = await collectTopic(developerPlatformClient, 'unstable', undefined) + const topic = await collectTopic(developerPlatformClient, 'unstable', undefined, organizationId) // Then expect(topic).toEqual('orders/create') diff --git a/packages/app/src/cli/services/webhook/trigger-options.ts b/packages/app/src/cli/services/webhook/trigger-options.ts index b7181bf98dc..26ca2da3838 100644 --- a/packages/app/src/cli/services/webhook/trigger-options.ts +++ b/packages/app/src/cli/services/webhook/trigger-options.ts @@ -59,13 +59,15 @@ export async function collectCredentials( * * @param developerPlatformClient - The client to access the platform API * @param apiVersion - VALID or undefined api-version + * @param organizationId - Organization ID required by the API to verify permissions * @returns api-version */ export async function collectApiVersion( developerPlatformClient: DeveloperPlatformClient, apiVersion: string | undefined, + organizationId: string, ): Promise { - const apiVersions = await requestApiVersions(developerPlatformClient) + const apiVersions = await requestApiVersions(developerPlatformClient, organizationId) if (apiVersion) return parseApiVersionFlag(apiVersion, apiVersions) return apiVersionPrompt(apiVersions) } @@ -76,18 +78,19 @@ export async function collectApiVersion( * @param developerPlatformClient - The client to access the platform API * @param apiVersion - VALID api-version * @param topic - topic or undefined + * @param organizationId - Organization ID required by the API to verify permissions * @returns topic */ export async function collectTopic( developerPlatformClient: DeveloperPlatformClient, apiVersion: string, topic: string | undefined, + organizationId: string, ): Promise { + const topics = await requestTopics(developerPlatformClient, apiVersion, organizationId) if (topic) { - return parseTopicFlag(topic, apiVersion, await requestTopics(developerPlatformClient, apiVersion)) + return parseTopicFlag(topic, apiVersion, topics) } - - const topics = await requestTopics(developerPlatformClient, apiVersion) return topicPrompt(topics) } diff --git a/packages/app/src/cli/services/webhook/trigger.test.ts b/packages/app/src/cli/services/webhook/trigger.test.ts index 26541d4559d..b17e1d22be1 100644 --- a/packages/app/src/cli/services/webhook/trigger.test.ts +++ b/packages/app/src/cli/services/webhook/trigger.test.ts @@ -23,6 +23,7 @@ const aPort = '1234' const aUrlPath = '/a/url/path' const anAddress = 'https://example.org' const anEventBridgeAddress = 'arn:aws:events:us-east-3::event-source/aws.partner/shopify.com/12/source' +const anOrganizationId = 'anOrganizationId' vi.mock('@shopify/cli-kit') vi.mock('@shopify/cli-kit/node/output') @@ -81,7 +82,7 @@ describe('webhookTriggerService', () => { await webhookTriggerService(sampleFlags()) // Then - expectCalls(aVersion) + expectCalls(aVersion, anOrganizationId) expect(consoleError).toHaveBeenCalledWith(`Request errors:\n · Some error\n · Another error`) }) @@ -104,7 +105,7 @@ describe('webhookTriggerService', () => { await webhookTriggerService(sampleFlags()) // Then - expectCalls(aVersion) + expectCalls(aVersion, anOrganizationId) expect(consoleError).toHaveBeenCalledWith(`Request errors:\n${JSON.stringify(response.userErrors)}`) }) @@ -125,8 +126,12 @@ describe('webhookTriggerService', () => { await webhookTriggerService(sampleFlags()) // Then - expectCalls(aVersion) - expect(getWebhookSample).toHaveBeenCalledWith(developerPlatformClient, expectedSampleWebhookVariables) + expectCalls(aVersion, anOrganizationId) + expect(getWebhookSample).toHaveBeenCalledWith( + developerPlatformClient, + expectedSampleWebhookVariables, + anOrganizationId, + ) expect(triggerLocalWebhook).toHaveBeenCalledTimes(0) expect(outputSuccess).toHaveBeenCalledWith('Webhook has been enqueued for delivery') }) @@ -174,8 +179,12 @@ describe('webhookTriggerService', () => { await webhookTriggerService(flags) // Then - expectCalls(aVersion) - expect(getWebhookSample).toHaveBeenCalledWith(developerPlatformClient, expectedSampleWebhookVariables) + expectCalls(aVersion, anOrganizationId) + expect(getWebhookSample).toHaveBeenCalledWith( + developerPlatformClient, + expectedSampleWebhookVariables, + anOrganizationId, + ) expect(outputSuccess).toHaveBeenCalledWith('Webhook has been enqueued for delivery') }) @@ -197,8 +206,12 @@ describe('webhookTriggerService', () => { await webhookTriggerService(sampleLocalhostFlags()) // Then - expectCalls(aVersion) - expect(getWebhookSample).toHaveBeenCalledWith(developerPlatformClient, expectedSampleWebhookVariables) + expectCalls(aVersion, anOrganizationId) + expect(getWebhookSample).toHaveBeenCalledWith( + developerPlatformClient, + expectedSampleWebhookVariables, + anOrganizationId, + ) expect(triggerLocalWebhook).toHaveBeenCalledWith(aFullLocalAddress, samplePayload, sampleHeaders) expect(outputSuccess).toHaveBeenCalledWith('Localhost delivery sucessful') }) @@ -220,8 +233,12 @@ describe('webhookTriggerService', () => { await webhookTriggerService(sampleLocalhostFlags()) // Then - expectCalls(aVersion) - expect(getWebhookSample).toHaveBeenCalledWith(developerPlatformClient, expectedSampleWebhookVariables) + expectCalls(aVersion, anOrganizationId) + expect(getWebhookSample).toHaveBeenCalledWith( + developerPlatformClient, + expectedSampleWebhookVariables, + anOrganizationId, + ) expect(triggerLocalWebhook).toHaveBeenCalledWith(aFullLocalAddress, samplePayload, sampleHeaders) expect(consoleError).toHaveBeenCalledWith('Localhost delivery failed') }) @@ -232,9 +249,9 @@ describe('webhookTriggerService', () => { vi.mocked(requestTopics).mockResolvedValue([topic]) } - function expectCalls(version: string) { - expect(requestApiVersions).toHaveBeenCalledWith(developerPlatformClient) - expect(requestTopics).toHaveBeenCalledWith(developerPlatformClient, version) + function expectCalls(version: string, organizationId: string) { + expect(requestApiVersions).toHaveBeenCalledWith(developerPlatformClient, organizationId) + expect(requestTopics).toHaveBeenCalledWith(developerPlatformClient, version, organizationId) } function sampleFlags(): WebhookTriggerInput { @@ -247,6 +264,7 @@ describe('webhookTriggerService', () => { address: anAddress, developerPlatformClient, path: '.', + organizationId: anOrganizationId, } return flags @@ -262,6 +280,7 @@ describe('webhookTriggerService', () => { address: anEventBridgeAddress, developerPlatformClient, path: '.', + organizationId: anOrganizationId, } return flags @@ -277,6 +296,7 @@ describe('webhookTriggerService', () => { address: aFullLocalAddress, developerPlatformClient, path: '.', + organizationId: anOrganizationId, } return flags diff --git a/packages/app/src/cli/services/webhook/trigger.ts b/packages/app/src/cli/services/webhook/trigger.ts index cac19d272dc..035dbb6d0fd 100644 --- a/packages/app/src/cli/services/webhook/trigger.ts +++ b/packages/app/src/cli/services/webhook/trigger.ts @@ -19,6 +19,7 @@ export interface WebhookTriggerInput { clientSecret?: string path: string config?: string + organizationId: string } interface WebhookTriggerOptions { @@ -29,6 +30,7 @@ interface WebhookTriggerOptions { clientSecret: string apiKey?: string developerPlatformClient: DeveloperPlatformClient + organizationId: string } /** @@ -45,8 +47,8 @@ export async function webhookTriggerService(input: WebhookTriggerInput) { } async function validateAndCollectFlags(input: WebhookTriggerInput): Promise { - const apiVersion = await collectApiVersion(input.developerPlatformClient, input.apiVersion) - const topic = await collectTopic(input.developerPlatformClient, apiVersion, input.topic) + const apiVersion = await collectApiVersion(input.developerPlatformClient, input.apiVersion, input.organizationId) + const topic = await collectTopic(input.developerPlatformClient, apiVersion, input.topic, input.organizationId) const [address, deliveryMethod] = await collectAddressAndMethod(input.deliveryMethod, input.address) const clientCredentials = await collectCredentials(input, deliveryMethod) @@ -58,6 +60,7 @@ async function validateAndCollectFlags(input: WebhookTriggerInput): Promise { - if (!appDirectory) { + if (!appDirectory || !(await isDirectory(appDirectory))) { return {} } diff --git a/packages/app/src/cli/utilities/developer-platform-client.ts b/packages/app/src/cli/utilities/developer-platform-client.ts index 4dc65d191e4..8d53c67070a 100644 --- a/packages/app/src/cli/utilities/developer-platform-client.ts +++ b/packages/app/src/cli/utilities/developer-platform-client.ts @@ -3,6 +3,7 @@ import {AppManagementClient} from './developer-platform-client/app-management-cl import {PartnersSession} from '../../cli/services/context/partner-account-info.js' import { MinimalAppIdentifiers, + AppApiKeyAndOrgId, MinimalOrganizationApp, Organization, OrganizationApp, @@ -36,8 +37,8 @@ import { import {UpdateURLsSchema, UpdateURLsVariables} from '../api/graphql/update_urls.js' import {CurrentAccountInfoSchema} from '../api/graphql/current_account_info.js' import {ExtensionTemplate} from '../models/app/template.js' -import {TargetSchemaDefinitionQueryVariables} from '../api/graphql/functions/target_schema_definition.js' -import {ApiSchemaDefinitionQueryVariables} from '../api/graphql/functions/api_schema_definition.js' +import {SchemaDefinitionByTargetQueryVariables} from '../api/graphql/functions/generated/schema-definition-by-target.js' +import {SchemaDefinitionByApiTypeQueryVariables} from '../api/graphql/functions/generated/schema-definition-by-api-type.js' import { MigrateToUiExtensionSchema, MigrateToUiExtensionVariables, @@ -54,7 +55,7 @@ import { import {DevSessionCreateMutation} from '../api/graphql/app-dev/generated/dev-session-create.js' import {DevSessionUpdateMutation} from '../api/graphql/app-dev/generated/dev-session-update.js' import {DevSessionDeleteMutation} from '../api/graphql/app-dev/generated/dev-session-delete.js' -import {isTruthy} from '@shopify/cli-kit/node/context/utilities' +import {isAppManagementEnabled} from '@shopify/cli-kit/node/context/local' export enum ClientName { AppManagement = 'app-management', @@ -77,7 +78,7 @@ export interface AppVersionIdentifiers { export function allDeveloperPlatformClients(): DeveloperPlatformClient[] { const clients: DeveloperPlatformClient[] = [new PartnersClient()] - if (isTruthy(process.env.USE_APP_MANAGEMENT_API)) clients.unshift(new AppManagementClient()) + if (isAppManagementEnabled()) clients.unshift(new AppManagementClient()) return clients } @@ -117,7 +118,7 @@ export function selectDeveloperPlatformClient({ configuration, organization, }: SelectDeveloperPlatformClientOptions = {}): DeveloperPlatformClient { - if (isTruthy(process.env.USE_APP_MANAGEMENT_API)) { + if (isAppManagementEnabled()) { if (organization) return selectDeveloperPlatformClientByOrg(organization) return selectDeveloperPlatformClientByConfig(configuration) } @@ -213,7 +214,7 @@ export interface DeveloperPlatformClient { session: () => Promise refreshToken: () => Promise accountInfo: () => Promise - appFromId: (app: MinimalAppIdentifiers) => Promise + appFromIdentifiers: (app: AppApiKeyAndOrgId) => Promise organizations: () => Promise orgFromId: (orgId: string) => Promise orgAndApps: (orgId: string) => Promise> @@ -241,15 +242,23 @@ export interface DeveloperPlatformClient { ) => Promise updateDeveloperPreview: (input: DevelopmentStorePreviewUpdateInput) => Promise appPreviewMode: (input: FindAppPreviewModeVariables) => Promise - sendSampleWebhook: (input: SendSampleWebhookVariables) => Promise - apiVersions: () => Promise - topics: (input: WebhookTopicsVariables) => Promise + sendSampleWebhook: (input: SendSampleWebhookVariables, organizationId: string) => Promise + apiVersions: (organizationId: string) => Promise + topics: (input: WebhookTopicsVariables, organizationId: string) => Promise migrateFlowExtension: (input: MigrateFlowExtensionVariables) => Promise migrateAppModule: (input: MigrateAppModuleVariables) => Promise updateURLs: (input: UpdateURLsVariables) => Promise currentAccountInfo: () => Promise - targetSchemaDefinition: (input: TargetSchemaDefinitionQueryVariables) => Promise - apiSchemaDefinition: (input: ApiSchemaDefinitionQueryVariables) => Promise + targetSchemaDefinition: ( + input: SchemaDefinitionByTargetQueryVariables, + apiKey: string, + organizationId: string, + ) => Promise + apiSchemaDefinition: ( + input: SchemaDefinitionByApiTypeQueryVariables, + apiKey: string, + organizationId: string, + ) => Promise migrateToUiExtension: (input: MigrateToUiExtensionVariables) => Promise toExtensionGraphQLType: (input: string) => string subscribeToAppLogs: (input: AppLogsSubscribeVariables) => Promise diff --git a/packages/app/src/cli/utilities/developer-platform-client/app-management-client.test.ts b/packages/app/src/cli/utilities/developer-platform-client/app-management-client.test.ts index c49525391d7..84f17cb74b5 100644 --- a/packages/app/src/cli/utilities/developer-platform-client/app-management-client.test.ts +++ b/packages/app/src/cli/utilities/developer-platform-client/app-management-client.test.ts @@ -10,6 +10,10 @@ import {OrganizationBetaFlagsQuerySchema} from './app-management-client/graphql/ import {testUIExtension, testRemoteExtensionTemplates, testOrganizationApp} from '../../models/app/app.test-data.js' import {ExtensionInstance} from '../../models/extensions/extension-instance.js' import {ListApps} from '../../api/graphql/app-management/generated/apps.js' +import {PublicApiVersionsQuery} from '../../api/graphql/webhooks/generated/public-api-versions.js' +import {AvailableTopicsQuery} from '../../api/graphql/webhooks/generated/available-topics.js' +import {CliTesting, CliTestingMutation} from '../../api/graphql/webhooks/generated/cli-testing.js' +import {SendSampleWebhookVariables} from '../../services/webhook/request-sample.js' import {describe, expect, test, vi} from 'vitest' import {CLI_KIT_VERSION} from '@shopify/cli-kit/common/version' import {fetch} from '@shopify/cli-kit/node/http' @@ -17,10 +21,12 @@ import {businessPlatformOrganizationsRequest} from '@shopify/cli-kit/node/api/bu import {appManagementRequestDoc} from '@shopify/cli-kit/node/api/app-management' import {BugError} from '@shopify/cli-kit/node/error' import {randomUUID} from '@shopify/cli-kit/node/crypto' +import {webhooksRequest} from '@shopify/cli-kit/node/api/webhooks' vi.mock('@shopify/cli-kit/node/http') vi.mock('@shopify/cli-kit/node/api/business-platform') vi.mock('@shopify/cli-kit/node/api/app-management') +vi.mock('@shopify/cli-kit/node/api/webhooks') const extensionA = await testUIExtension({uid: 'extension-a-uuid'}) const extensionB = await testUIExtension({uid: 'extension-b-uuid'}) @@ -288,3 +294,177 @@ describe('searching for apps', () => { await expect(client.appsForOrg(orgId)).rejects.toThrow(BugError) }) }) + +describe('apiVersions', () => { + test('fetches available public API versions', async () => { + // Given + const orgId = '1' + const mockedResponse: PublicApiVersionsQuery = { + publicApiVersions: [{handle: '2024-07'}, {handle: '2024-10'}, {handle: '2025-01'}, {handle: 'unstable'}], + } + vi.mocked(webhooksRequest).mockResolvedValueOnce(mockedResponse) + + // When + const client = new AppManagementClient() + client.token = () => Promise.resolve('token') + const apiVersions = await client.apiVersions(orgId) + + // Then + expect(apiVersions.publicApiVersions.length).toEqual(mockedResponse.publicApiVersions.length) + expect(apiVersions.publicApiVersions).toEqual(mockedResponse.publicApiVersions.map((version) => version.handle)) + }) +}) + +describe('topics', () => { + test('fetches available topics for a valid API version', async () => { + // Given + const orgId = '1' + const mockedResponse: AvailableTopicsQuery = {availableTopics: ['app/uninstalled', 'products/created']} + vi.mocked(webhooksRequest).mockResolvedValueOnce(mockedResponse) + + // When + const client = new AppManagementClient() + client.token = () => Promise.resolve('token') + const topics = await client.topics({api_version: '2024-07'}, orgId) + + // Then + expect(topics.webhookTopics.length).toEqual(mockedResponse.availableTopics?.length) + expect(topics.webhookTopics).toEqual(mockedResponse.availableTopics) + }) + + test('returns an empty list when failing', async () => { + // Given + const orgId = '1' + const mockedResponse: AvailableTopicsQuery = {availableTopics: null} + vi.mocked(webhooksRequest).mockResolvedValueOnce(mockedResponse) + + // When + const client = new AppManagementClient() + client.token = () => Promise.resolve('token') + const topics = await client.topics({api_version: 'invalid'}, orgId) + + // Then + expect(topics.webhookTopics.length).toEqual(0) + }) +}) + +describe('sendSampleWebhook', () => { + test('succeeds for local delivery', async () => { + // Given + const orgId = '1' + const input: SendSampleWebhookVariables = { + address: 'http://localhost:3000/webhooks', + api_key: 'abc123', + api_version: '2025-01', + delivery_method: 'localhost', + shared_secret: 'secret', + topic: 'app/uninstalled', + } + const mockedResponse: CliTestingMutation = { + cliTesting: { + headers: `{"Content-Type":"application/json"}`, + samplePayload: `{"id": 42,"name":"test"}`, + success: true, + errors: [], + }, + } + const expectedVariables = { + address: input.address, + apiKey: input.api_key, + apiVersion: input.api_version, + deliveryMethod: input.delivery_method, + sharedSecret: input.shared_secret, + topic: input.topic, + } + const token = 'token' + vi.mocked(webhooksRequest).mockResolvedValueOnce(mockedResponse) + + // When + const client = new AppManagementClient() + client.token = () => Promise.resolve(token) + const result = await client.sendSampleWebhook(input, orgId) + + // Then + expect(webhooksRequest).toHaveBeenCalledWith(orgId, CliTesting, token, expectedVariables) + expect(result.sendSampleWebhook.samplePayload).toEqual(mockedResponse.cliTesting?.samplePayload) + expect(result.sendSampleWebhook.headers).toEqual(mockedResponse.cliTesting?.headers) + expect(result.sendSampleWebhook.success).toEqual(true) + expect(result.sendSampleWebhook.userErrors).toEqual([]) + }) + + test('succeeds for remote delivery', async () => { + // Given + const orgId = '1' + const input: SendSampleWebhookVariables = { + address: 'https://webhooks.test', + api_key: 'abc123', + api_version: '2025-01', + delivery_method: 'http', + shared_secret: 'secret', + topic: 'app/uninstalled', + } + const mockedResponse: CliTestingMutation = { + cliTesting: { + headers: '{}', + samplePayload: '{}', + success: true, + errors: [], + }, + } + const expectedVariables = { + address: input.address, + apiKey: input.api_key, + apiVersion: input.api_version, + deliveryMethod: input.delivery_method, + sharedSecret: input.shared_secret, + topic: input.topic, + } + const token = 'token' + vi.mocked(webhooksRequest).mockResolvedValueOnce(mockedResponse) + + // When + const client = new AppManagementClient() + client.token = () => Promise.resolve(token) + const result = await client.sendSampleWebhook(input, orgId) + + // Then + expect(webhooksRequest).toHaveBeenCalledWith(orgId, CliTesting, token, expectedVariables) + expect(result.sendSampleWebhook.samplePayload).toEqual('{}') + expect(result.sendSampleWebhook.headers).toEqual('{}') + expect(result.sendSampleWebhook.success).toEqual(true) + expect(result.sendSampleWebhook.userErrors).toEqual([]) + }) + + test('handles API failures', async () => { + // Given + const orgId = '1' + const input: SendSampleWebhookVariables = { + address: 'https://webhooks.test', + api_key: 'abc123', + api_version: 'invalid', + delivery_method: 'http', + shared_secret: 'secret', + topic: 'app/uninstalled', + } + const mockedResponse: CliTestingMutation = { + cliTesting: { + headers: '{}', + samplePayload: '{}', + success: false, + errors: ['Invalid api_version'], + }, + } + vi.mocked(webhooksRequest).mockResolvedValueOnce(mockedResponse) + + // When + const client = new AppManagementClient() + client.token = () => Promise.resolve('token') + const result = await client.sendSampleWebhook(input, orgId) + + // Then + expect(result.sendSampleWebhook.samplePayload).toEqual('{}') + expect(result.sendSampleWebhook.headers).toEqual('{}') + expect(result.sendSampleWebhook.success).toEqual(false) + expect(result.sendSampleWebhook.userErrors).toEqual([{message: 'Invalid api_version', fields: []}]) + }) +}) diff --git a/packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts b/packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts index ccb72142ec5..d5be4c74d31 100644 --- a/packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts +++ b/packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts @@ -21,6 +21,7 @@ import { import {PartnersSession} from '../../services/context/partner-account-info.js' import { MinimalAppIdentifiers, + AppApiKeyAndOrgId, MinimalOrganizationApp, Organization, OrganizationApp, @@ -46,7 +47,11 @@ import { } from '../../api/graphql/development_preview.js' import {AppReleaseSchema} from '../../api/graphql/app_release.js' import {AppVersionsDiffSchema} from '../../api/graphql/app_versions_diff.js' -import {SendSampleWebhookSchema, SendSampleWebhookVariables} from '../../services/webhook/request-sample.js' +import { + SampleWebhook, + SendSampleWebhookSchema, + SendSampleWebhookVariables, +} from '../../services/webhook/request-sample.js' import {PublicApiVersionsSchema} from '../../services/webhook/request-api-versions.js' import {WebhookTopicsSchema, WebhookTopicsVariables} from '../../services/webhook/request-topics.js' import { @@ -56,8 +61,6 @@ import { import {UpdateURLsSchema, UpdateURLsVariables} from '../../api/graphql/update_urls.js' import {CurrentAccountInfoSchema} from '../../api/graphql/current_account_info.js' import {ExtensionTemplate} from '../../models/app/template.js' -import {TargetSchemaDefinitionQueryVariables} from '../../api/graphql/functions/target_schema_definition.js' -import {ApiSchemaDefinitionQueryVariables} from '../../api/graphql/functions/api_schema_definition.js' import { MigrateToUiExtensionVariables, MigrateToUiExtensionSchema, @@ -86,10 +89,10 @@ import { ListAppDevStoresQuery, } from '../../api/graphql/business-platform-organizations/generated/list_app_dev_stores.js' import { - ActiveAppRelease, ActiveAppReleaseQuery, ReleasedAppModuleFragment, } from '../../api/graphql/app-management/generated/active-app-release.js' +import {ActiveAppReleaseFromApiKey} from '../../api/graphql/app-management/generated/active-app-release-from-api-key.js' import {ReleaseVersion} from '../../api/graphql/app-management/generated/release-version.js' import {CreateAppVersion} from '../../api/graphql/app-management/generated/create-app-version.js' import {CreateAssetUrl} from '../../api/graphql/app-management/generated/create-asset-url.js' @@ -100,6 +103,19 @@ import {FetchSpecifications} from '../../api/graphql/app-management/generated/sp import {ListApps} from '../../api/graphql/app-management/generated/apps.js' import {FindOrganizations} from '../../api/graphql/business-platform-destinations/generated/find-organizations.js' import {UserInfo} from '../../api/graphql/business-platform-destinations/generated/user-info.js' +import {AvailableTopics} from '../../api/graphql/webhooks/generated/available-topics.js' +import {CliTesting} from '../../api/graphql/webhooks/generated/cli-testing.js' +import {PublicApiVersions} from '../../api/graphql/webhooks/generated/public-api-versions.js' +import { + SchemaDefinitionByTarget, + SchemaDefinitionByTargetQuery, + SchemaDefinitionByTargetQueryVariables, +} from '../../api/graphql/functions/generated/schema-definition-by-target.js' +import { + SchemaDefinitionByApiType, + SchemaDefinitionByApiTypeQuery, + SchemaDefinitionByApiTypeQueryVariables, +} from '../../api/graphql/functions/generated/schema-definition-by-api-type.js' import {ensureAuthenticatedAppManagement, ensureAuthenticatedBusinessPlatform} from '@shopify/cli-kit/node/session' import {isUnitTest} from '@shopify/cli-kit/node/context/local' import {AbortError, BugError} from '@shopify/cli-kit/node/error' @@ -115,6 +131,8 @@ import {CLI_KIT_VERSION} from '@shopify/cli-kit/common/version' import {versionSatisfies} from '@shopify/cli-kit/node/node-package-manager' import {outputDebug} from '@shopify/cli-kit/node/output' import {developerDashboardFqdn} from '@shopify/cli-kit/node/context/fqdn' +import {webhooksRequest} from '@shopify/cli-kit/node/api/webhooks' +import {functionsRequestDoc} from '@shopify/cli-kit/node/api/functions' const TEMPLATE_JSON_URL = 'https://cdn.shopify.com/static/cli/extensions/templates.json' @@ -200,7 +218,7 @@ export class AppManagementClient implements DeveloperPlatformClient { return (await this.session()).accountInfo } - async appFromId(appIdentifiers: MinimalAppIdentifiers): Promise { + async appFromIdentifiers(appIdentifiers: AppApiKeyAndOrgId): Promise { const {app} = await this.activeAppVersionRawResult(appIdentifiers) const {name, appModules} = app.activeRelease.version const appAccessModule = appModules.find((mod) => mod.specification.externalIdentifier === 'app_access') @@ -475,7 +493,7 @@ export class AppManagementClient implements DeveloperPlatformClient { uuid: versionInfo.id, versionTag: versionInfo.metadata.versionTag, location: [await appDeepLink({organizationId, id: appId}), 'versions', numberFromGid(versionInfo.id)].join('/'), - message: '', + message: versionInfo.metadata.message ?? '', appModuleVersions: versionInfo.appModules.map(appModuleVersion), } } @@ -560,6 +578,7 @@ export class AppManagementClient implements DeveloperPlatformClient { appModules, organizationId, versionTag, + message, bundleUrl, skipPublish: noRelease, }: AppDeployOptions): Promise { @@ -572,6 +591,7 @@ export class AppManagementClient implements DeveloperPlatformClient { if (brandingModule) { updatedName = JSON.parse(brandingModule.config).name } + const variables = { appId, name: updatedName, @@ -587,7 +607,7 @@ export class AppManagementClient implements DeveloperPlatformClient { } }), }, - metadata: versionTag ? {versionTag} : {}, + metadata: {versionTag, message}, } const result = await appManagementRequestDoc(organizationId, CreateAppVersion, await this.token(), variables) @@ -726,25 +746,46 @@ export class AppManagementClient implements DeveloperPlatformClient { throw new BugError('Not implemented: appPreviewMode') } - async sendSampleWebhook(_input: SendSampleWebhookVariables): Promise { - outputDebug('⚠️ sendSampleWebhook is not implemented') - return { - sendSampleWebhook: { - samplePayload: '', - headers: '{}', - success: true, - userErrors: [], - }, + async sendSampleWebhook(input: SendSampleWebhookVariables, organizationId: string): Promise { + const query = CliTesting + const variables = { + address: input.address, + apiKey: input.api_key, + apiVersion: input.api_version, + deliveryMethod: input.delivery_method, + sharedSecret: input.shared_secret, + topic: input.topic, } + const result = await webhooksRequest(organizationId, query, await this.token(), variables) + let sendSampleWebhook: SampleWebhook = {samplePayload: '{}', headers: '{}', success: false, userErrors: []} + const cliTesting = result.cliTesting + if (cliTesting) { + sendSampleWebhook = { + samplePayload: cliTesting.samplePayload ?? '{}', + headers: cliTesting.headers ?? '{}', + success: cliTesting.success, + userErrors: cliTesting.errors.map((error) => ({message: error, fields: []})), + } + } + return {sendSampleWebhook} } - async apiVersions(): Promise { - outputDebug('⚠️ apiVersions is not implemented') - return {publicApiVersions: ['unstable']} + async apiVersions(organizationId: string): Promise { + const result = await webhooksRequest(organizationId, PublicApiVersions, await this.token(), {}) + return {publicApiVersions: result.publicApiVersions.map((version) => version.handle)} } - async topics(_input: WebhookTopicsVariables): Promise { - throw new BugError('Not implemented: topics') + async topics( + {api_version: apiVersion}: WebhookTopicsVariables, + organizationId: string, + ): Promise { + const query = AvailableTopics + const variables = {apiVersion} + const result = await webhooksRequest(organizationId, query, await this.token(), variables) + + return { + webhookTopics: result.availableTopics ?? [], + } } async migrateFlowExtension(_input: MigrateFlowExtensionVariables): Promise { @@ -764,12 +805,53 @@ export class AppManagementClient implements DeveloperPlatformClient { throw new BugError('Not implemented: currentAccountInfo') } - async targetSchemaDefinition(_input: TargetSchemaDefinitionQueryVariables): Promise { - throw new BugError('Not implemented: targetSchemaDefinition') + async targetSchemaDefinition( + input: SchemaDefinitionByTargetQueryVariables, + apiKey: string, + organizationId: string, + ): Promise { + try { + const {app} = await this.activeAppVersionRawResult({apiKey, organizationId}) + const appIdNumber = String(numberFromGid(app.id)) + const token = await this.token() + const result = await functionsRequestDoc( + organizationId, + SchemaDefinitionByTarget, + token, + appIdNumber, + { + handle: input.handle, + version: input.version, + }, + ) + + return result?.target?.api?.schema?.definition ?? null + } catch (error) { + throw new AbortError(`Failed to fetch schema definition: ${error}`) + } } - async apiSchemaDefinition(_input: ApiSchemaDefinitionQueryVariables): Promise { - throw new BugError('Not implemented: apiSchemaDefinition') + async apiSchemaDefinition( + input: SchemaDefinitionByApiTypeQueryVariables, + apiKey: string, + organizationId: string, + ): Promise { + try { + const {app} = await this.activeAppVersionRawResult({apiKey, organizationId}) + const appIdNumber = String(numberFromGid(app.id)) + const token = await this.token() + const result = await functionsRequestDoc( + organizationId, + SchemaDefinitionByApiType, + token, + appIdNumber, + input, + ) + + return result?.api?.schema?.definition ?? null + } catch (error) { + throw new AbortError(`Failed to fetch schema definition: ${error}`) + } } async migrateToUiExtension(_input: MigrateToUiExtensionVariables): Promise { @@ -807,8 +889,8 @@ export class AppManagementClient implements DeveloperPlatformClient { ) } - private async activeAppVersionRawResult({id, organizationId}: MinimalAppIdentifiers): Promise { - return appManagementRequestDoc(organizationId, ActiveAppRelease, await this.token(), {appId: id}) + private async activeAppVersionRawResult({organizationId, apiKey}: AppApiKeyAndOrgId): Promise { + return appManagementRequestDoc(organizationId, ActiveAppReleaseFromApiKey, await this.token(), {apiKey}) } private async organizationBetaFlags( diff --git a/packages/app/src/cli/utilities/developer-platform-client/partners-client.ts b/packages/app/src/cli/utilities/developer-platform-client/partners-client.ts index f25f50b35d0..4255903a0d7 100644 --- a/packages/app/src/cli/utilities/developer-platform-client/partners-client.ts +++ b/packages/app/src/cli/utilities/developer-platform-client/partners-client.ts @@ -15,6 +15,7 @@ import { import {fetchCurrentAccountInformation, PartnersSession} from '../../../cli/services/context/partner-account-info.js' import { MinimalAppIdentifiers, + AppApiKeyAndOrgId, MinimalOrganizationApp, Organization, OrganizationApp, @@ -99,12 +100,10 @@ import { } from '../../api/graphql/template_specifications.js' import {ExtensionTemplate} from '../../models/app/template.js' import { - TargetSchemaDefinitionQueryVariables, TargetSchemaDefinitionQuerySchema, TargetSchemaDefinitionQuery, } from '../../api/graphql/functions/target_schema_definition.js' import { - ApiSchemaDefinitionQueryVariables, ApiSchemaDefinitionQuerySchema, ApiSchemaDefinitionQuery, } from '../../api/graphql/functions/api_schema_definition.js' @@ -153,6 +152,8 @@ import { DevStoresByOrgQuery, DevStoresByOrgQueryVariables, } from '../../api/graphql/partners/generated/dev-stores-by-org.js' +import {SchemaDefinitionByTargetQueryVariables} from '../../api/graphql/functions/generated/schema-definition-by-target.js' +import {SchemaDefinitionByApiTypeQueryVariables} from '../../api/graphql/functions/generated/schema-definition-by-api-type.js' import {TypedDocumentNode} from '@graphql-typed-document-node/core' import {isUnitTest} from '@shopify/cli-kit/node/context/local' import {AbortError} from '@shopify/cli-kit/node/error' @@ -263,7 +264,7 @@ export class PartnersClient implements DeveloperPlatformClient { return (await this.session()).accountInfo } - async appFromId({apiKey}: MinimalAppIdentifiers): Promise { + async appFromIdentifiers({apiKey}: AppApiKeyAndOrgId): Promise { const variables: FindAppQueryVariables = {apiKey} const res: FindAppQuerySchema = await this.request(FindAppQuery, variables) const app = res.app @@ -474,15 +475,18 @@ export class PartnersClient implements DeveloperPlatformClient { return this.request(FindAppPreviewModeQuery, input) } - async sendSampleWebhook(input: SendSampleWebhookVariables): Promise { + async sendSampleWebhook( + input: SendSampleWebhookVariables, + _organizationId: string, + ): Promise { return this.request(sendSampleWebhookMutation, input) } - async apiVersions(): Promise { + async apiVersions(_organizationId: string): Promise { return this.request(GetApiVersionsQuery) } - async topics(input: WebhookTopicsVariables): Promise { + async topics(input: WebhookTopicsVariables, _organizationId: string): Promise { return this.request(getTopicsQuery, input) } @@ -502,13 +506,36 @@ export class PartnersClient implements DeveloperPlatformClient { return this.request(CurrentAccountInfoQuery) } - async targetSchemaDefinition(input: TargetSchemaDefinitionQueryVariables): Promise { - const response: TargetSchemaDefinitionQuerySchema = await this.request(TargetSchemaDefinitionQuery, input) + async targetSchemaDefinition( + input: SchemaDefinitionByTargetQueryVariables, + apiKey: string, + _organizationId: string, + ): Promise { + // Ensures compatibility with existing partners requests + // Can remove once migrated to AMF + const transformedInput = { + target: input.handle, + version: input.version, + apiKey, + } + + const response: TargetSchemaDefinitionQuerySchema = await this.request( + TargetSchemaDefinitionQuery, + transformedInput, + ) return response.definition } - async apiSchemaDefinition(input: ApiSchemaDefinitionQueryVariables): Promise { - const response: ApiSchemaDefinitionQuerySchema = await this.request(ApiSchemaDefinitionQuery, input) + async apiSchemaDefinition( + input: SchemaDefinitionByApiTypeQueryVariables & {apiKey?: string}, + apiKey: string, + _organizationId: string, + _appId?: string, + ): Promise { + const response: ApiSchemaDefinitionQuerySchema = await this.request(ApiSchemaDefinitionQuery, { + ...input, + apiKey, + }) return response.definition } diff --git a/packages/app/src/cli/utilities/extensions/fetch-product-variant.ts b/packages/app/src/cli/utilities/extensions/fetch-product-variant.ts index 0f7aa1d1032..b0901e7f351 100644 --- a/packages/app/src/cli/utilities/extensions/fetch-product-variant.ts +++ b/packages/app/src/cli/utilities/extensions/fetch-product-variant.ts @@ -2,6 +2,8 @@ import {FindProductVariantQuery, FindProductVariantSchema} from '../../api/graph import {adminRequest} from '@shopify/cli-kit/node/api/admin' import {ensureAuthenticatedAdmin} from '@shopify/cli-kit/node/session' import {AbortError} from '@shopify/cli-kit/node/error' +import {normalizeStoreFqdn} from '@shopify/cli-kit/node/context/fqdn' +import {outputContent, outputToken} from '@shopify/cli-kit/node/output' /** * Retrieve the first variant of the first product of the given store @@ -12,12 +14,18 @@ export async function fetchProductVariant(store: string) { const adminSession = await ensureAuthenticatedAdmin(store) const result: FindProductVariantSchema = await adminRequest(FindProductVariantQuery, adminSession) const products = result.products.edges - if (products.length === 0) + if (products.length === 0) { + const normalizedUrl = `https://${await normalizeStoreFqdn(store)}/admin/products/new` + const addProductLink = outputContent`${outputToken.link( + 'Add a product', + normalizedUrl, + `You can add a new product here: ${normalizedUrl}`, + )}`.value throw new AbortError( 'Could not find a product variant', - `Your store needs to have at least one product to test a 'checkout_ui' extension\n -You can add a new product here: https://${store}/admin/products/new`, + `Your store needs to have at least one product to test a 'checkout_ui' extension.\n\n${addProductLink}`, ) + } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const variantURL = result.products.edges[0]!.node.variants.edges[0]!.node.id const variantId = variantURL.split('/').pop() diff --git a/packages/app/src/cli/utilities/extensions/locales-configuration.test.ts b/packages/app/src/cli/utilities/extensions/locales-configuration.test.ts index bdc33cb9f99..2e261d3c2c2 100644 --- a/packages/app/src/cli/utilities/extensions/locales-configuration.test.ts +++ b/packages/app/src/cli/utilities/extensions/locales-configuration.test.ts @@ -50,7 +50,7 @@ describe('loadLocalesConfig', () => { await mkdir(localesPath) await writeFile(enDefault, JSON.stringify({hello: 'Hello'})) - const bigArray = new Array(5000).fill('a') + const bigArray = new Array(6000).fill('a') await writeFile(es, JSON.stringify(bigArray)) // When @@ -101,7 +101,7 @@ describe('loadLocalesConfig', () => { const es = joinPath(localesPath, 'es.json') await mkdir(localesPath) - const bigArray = JSON.stringify(new Array(3000).fill('a')) + const bigArray = JSON.stringify(new Array(4000).fill('a')) await writeFile(en, JSON.stringify(bigArray)) await writeFile(es, JSON.stringify(bigArray)) diff --git a/packages/app/src/cli/utilities/extensions/locales-configuration.ts b/packages/app/src/cli/utilities/extensions/locales-configuration.ts index 2cfb707bed5..7ff92dc83a9 100644 --- a/packages/app/src/cli/utilities/extensions/locales-configuration.ts +++ b/packages/app/src/cli/utilities/extensions/locales-configuration.ts @@ -3,7 +3,7 @@ import {glob} from '@shopify/cli-kit/node/fs' import {AbortError, BugError} from '@shopify/cli-kit/node/error' import fs from 'fs' -const L10N_FILE_SIZE_LIMIT = 16 * 1024 +const L10N_FILE_SIZE_LIMIT = 20 * 1024 const L10N_BUNDLE_SIZE_LIMIT = 256 * 1024 export async function loadLocalesConfig(extensionPath: string, extensionIdentifier: string) { diff --git a/packages/app/src/cli/utilities/json-schema.ts b/packages/app/src/cli/utilities/json-schema.ts index 20cbc09e40a..33f2b3bf589 100644 --- a/packages/app/src/cli/utilities/json-schema.ts +++ b/packages/app/src/cli/utilities/json-schema.ts @@ -19,6 +19,7 @@ export async function unifiedConfigurationParserFactory( return merged.parseConfigurationObject } const contract = await normaliseJsonSchema(contractJsonSchema) + const extensionIdentifier = merged.identifier const parseConfigurationObject = (config: object): ParseConfigurationResult => { // First we parse with zod. This may also change the format of the data. @@ -29,7 +30,7 @@ export async function unifiedConfigurationParserFactory( const subjectForAjv = zodValidatedData ?? (config as JsonMapType) const subjectForAjvWithoutFirstClassFields = configWithoutFirstClassFields(subjectForAjv) - const jsonSchemaParse = jsonSchemaValidate(subjectForAjvWithoutFirstClassFields, contract) + const jsonSchemaParse = jsonSchemaValidate(subjectForAjvWithoutFirstClassFields, contract, extensionIdentifier) // Finally, we de-duplicate the error set from both validations -- identical messages for identical paths are removed let errors = zodParse.errors || [] diff --git a/packages/cli-kit/CHANGELOG.md b/packages/cli-kit/CHANGELOG.md index b284697b610..81c2fd64eff 100644 --- a/packages/cli-kit/CHANGELOG.md +++ b/packages/cli-kit/CHANGELOG.md @@ -1,5 +1,36 @@ # @shopify/cli-kit +## 3.72.0 + +## 3.71.5 + +### Patch Changes + +- 94a7d4ce4f: Fix bug preventing empty theme files from uploading + +## 3.71.4 + +### Patch Changes + +- 94953a671e: Fix bug preventing empty theme files from uploading + +## 3.71.3 + +## 3.71.2 + +### Patch Changes + +- a395820e7b: Fix dev for Ruby apps by avoiding the command safety check to raise an error when not found + +## 3.71.1 + +## 3.71.0 + +### Patch Changes + +- 5fd19d2920: Improve display of links for terminals that don't support hyperlinks +- 5531731c11: Skip notifications when using --json, -j or SHOPIFY_FLAG_JSON + ## 3.70.0 ### Minor Changes diff --git a/packages/cli-kit/package.json b/packages/cli-kit/package.json index 720d2d14ba5..0a27f8d7e1b 100644 --- a/packages/cli-kit/package.json +++ b/packages/cli-kit/package.json @@ -1,6 +1,6 @@ { "name": "@shopify/cli-kit", - "version": "3.70.0", + "version": "3.72.0", "private": false, "description": "A set of utilities, interfaces, and models that are common across all the platform features", "keywords": [ @@ -82,7 +82,6 @@ "./context/local.js", "./custom-oclif-loader.js", "@oclif/core", - "../../private/node/constants.js", "./path.js", "./system.js", "./ui.js" @@ -91,7 +90,9 @@ "@oclif/core", "./context/utilities.js", "../../private/node/conf-store.js", - "url" + "../../private/node/constants.js", + "url", + "./cli-launcher.js" ] } ] diff --git a/packages/cli-kit/src/cli/api/graphql/admin/generated/metafield_definitions_by_owner_type.ts b/packages/cli-kit/src/cli/api/graphql/admin/generated/metafield_definitions_by_owner_type.ts new file mode 100644 index 00000000000..339337b472e --- /dev/null +++ b/packages/cli-kit/src/cli/api/graphql/admin/generated/metafield_definitions_by_owner_type.ts @@ -0,0 +1,87 @@ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ +import * as Types from './types.js' + +import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core' + +export type MetafieldDefinitionsByOwnerTypeQueryVariables = Types.Exact<{ + ownerType: Types.MetafieldOwnerType +}> + +export type MetafieldDefinitionsByOwnerTypeQuery = { + metafieldDefinitions: { + nodes: { + key: string + name: string + namespace: string + description?: string | null + type: {category: string; name: string} + }[] + } +} + +export const MetafieldDefinitionsByOwnerType = { + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'query', + name: {kind: 'Name', value: 'metafieldDefinitionsByOwnerType'}, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'ownerType'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'MetafieldOwnerType'}}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'metafieldDefinitions'}, + arguments: [ + { + kind: 'Argument', + name: {kind: 'Name', value: 'ownerType'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'ownerType'}}, + }, + {kind: 'Argument', name: {kind: 'Name', value: 'first'}, value: {kind: 'IntValue', value: '250'}}, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'nodes'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'key'}}, + {kind: 'Field', name: {kind: 'Name', value: 'name'}}, + {kind: 'Field', name: {kind: 'Name', value: 'namespace'}}, + {kind: 'Field', name: {kind: 'Name', value: 'description'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'type'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'category'}}, + {kind: 'Field', name: {kind: 'Name', value: 'name'}}, + {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, + ], + }, + }, + {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, + ], + }, + }, + {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode diff --git a/packages/cli-kit/src/cli/api/graphql/admin/generated/theme_files_upsert.ts b/packages/cli-kit/src/cli/api/graphql/admin/generated/theme_files_upsert.ts new file mode 100644 index 00000000000..f7bd095c8f5 --- /dev/null +++ b/packages/cli-kit/src/cli/api/graphql/admin/generated/theme_files_upsert.ts @@ -0,0 +1,98 @@ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ +import * as Types from './types.js' + +import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core' + +export type ThemeFilesUpsertMutationVariables = Types.Exact<{ + files: Types.OnlineStoreThemeFilesUpsertFileInput[] | Types.OnlineStoreThemeFilesUpsertFileInput + themeId: Types.Scalars['ID']['input'] +}> + +export type ThemeFilesUpsertMutation = { + themeFilesUpsert?: { + upsertedThemeFiles?: {filename: string}[] | null + userErrors: {filename?: string | null; message: string}[] + } | null +} + +export const ThemeFilesUpsert = { + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'mutation', + name: {kind: 'Name', value: 'themeFilesUpsert'}, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'files'}}, + type: { + kind: 'NonNullType', + type: { + kind: 'ListType', + type: { + kind: 'NonNullType', + type: {kind: 'NamedType', name: {kind: 'Name', value: 'OnlineStoreThemeFilesUpsertFileInput'}}, + }, + }, + }, + }, + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'themeId'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'ID'}}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'themeFilesUpsert'}, + arguments: [ + { + kind: 'Argument', + name: {kind: 'Name', value: 'files'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'files'}}, + }, + { + kind: 'Argument', + name: {kind: 'Name', value: 'themeId'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'themeId'}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'upsertedThemeFiles'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'filename'}}, + {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, + ], + }, + }, + { + kind: 'Field', + name: {kind: 'Name', value: 'userErrors'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'filename'}}, + {kind: 'Field', name: {kind: 'Name', value: 'message'}}, + {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, + ], + }, + }, + {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode diff --git a/packages/cli-kit/src/cli/api/graphql/admin/generated/types.d.ts b/packages/cli-kit/src/cli/api/graphql/admin/generated/types.d.ts index 910af7f7831..ab109b34c12 100644 --- a/packages/cli-kit/src/cli/api/graphql/admin/generated/types.d.ts +++ b/packages/cli-kit/src/cli/api/graphql/admin/generated/types.d.ts @@ -120,6 +120,84 @@ export type Scalars = { UtcOffset: {input: any; output: any} } +/** Possible types of a metafield's owner resource. */ +export type MetafieldOwnerType = + /** The Api Permission metafield owner type. */ + | 'API_PERMISSION' + /** The Article metafield owner type. */ + | 'ARTICLE' + /** The Blog metafield owner type. */ + | 'BLOG' + /** The Brand metafield owner type. */ + | 'BRAND' + /** The Cart Transform metafield owner type. */ + | 'CARTTRANSFORM' + /** The Collection metafield owner type. */ + | 'COLLECTION' + /** The Company metafield owner type. */ + | 'COMPANY' + /** The Company Location metafield owner type. */ + | 'COMPANY_LOCATION' + /** The Customer metafield owner type. */ + | 'CUSTOMER' + /** The Delivery Customization metafield owner type. */ + | 'DELIVERY_CUSTOMIZATION' + /** The Delivery Method metafield owner type. */ + | 'DELIVERY_METHOD' + /** The Delivery Option Generator metafield owner type. */ + | 'DELIVERY_OPTION_GENERATOR' + /** The Discount metafield owner type. */ + | 'DISCOUNT' + /** The draft order metafield owner type. */ + | 'DRAFTORDER' + /** The Fulfillment Constraint Rule metafield owner type. */ + | 'FULFILLMENT_CONSTRAINT_RULE' + /** The Gate Configuration metafield owner type. */ + | 'GATE_CONFIGURATION' + /** The GiftCardTransaction metafield owner type. */ + | 'GIFT_CARD_TRANSACTION' + /** The Location metafield owner type. */ + | 'LOCATION' + /** The Market metafield owner type. */ + | 'MARKET' + /** The Media Image metafield owner type. */ + | 'MEDIA_IMAGE' + /** The Order metafield owner type. */ + | 'ORDER' + /** The Order Routing Location Rule metafield owner type. */ + | 'ORDER_ROUTING_LOCATION_RULE' + /** The Page metafield owner type. */ + | 'PAGE' + /** The Payment Customization metafield owner type. */ + | 'PAYMENT_CUSTOMIZATION' + /** The Product metafield owner type. */ + | 'PRODUCT' + /** The Product Variant metafield owner type. */ + | 'PRODUCTVARIANT' + /** The Selling Plan metafield owner type. */ + | 'SELLING_PLAN' + /** The Shop metafield owner type. */ + | 'SHOP' + /** The Validation metafield owner type. */ + | 'VALIDATION' + +/** The input fields for the theme file body. */ +export type OnlineStoreThemeFileBodyInput = { + /** The input type of the theme file body. */ + type: OnlineStoreThemeFileBodyInputType + /** The body of the theme file. */ + value: Scalars['String']['input'] +} + +/** The input type for a theme file body. */ +export type OnlineStoreThemeFileBodyInputType = + /** The base64 encoded body of a theme file. */ + | 'BASE64' + /** The text body of the theme file. */ + | 'TEXT' + /** The url of the body of a theme file. */ + | 'URL' + /** Type of a theme file operation result. */ export type OnlineStoreThemeFileResultType = /** Operation was malformed or invalid. */ @@ -137,6 +215,14 @@ export type OnlineStoreThemeFileResultType = /** Operation could not be processed due to issues with input data. */ | 'UNPROCESSABLE_ENTITY' +/** The input fields for the file to create or update. */ +export type OnlineStoreThemeFilesUpsertFileInput = { + /** The body of the theme file. */ + body: OnlineStoreThemeFileBodyInput + /** The filename of the theme file. */ + filename: Scalars['String']['input'] +} + /** The input fields for Theme attributes to update. */ export type OnlineStoreThemeInput = { /** The new name of the theme. */ diff --git a/packages/cli-kit/src/cli/api/graphql/admin/mutations/theme_files_upsert.graphql b/packages/cli-kit/src/cli/api/graphql/admin/mutations/theme_files_upsert.graphql new file mode 100644 index 00000000000..1106e4addc2 --- /dev/null +++ b/packages/cli-kit/src/cli/api/graphql/admin/mutations/theme_files_upsert.graphql @@ -0,0 +1,11 @@ +mutation themeFilesUpsert($files: [OnlineStoreThemeFilesUpsertFileInput!]!, $themeId: ID!) { + themeFilesUpsert(files: $files, themeId: $themeId) { + upsertedThemeFiles { + filename + } + userErrors { + filename + message + } + } +} diff --git a/packages/cli-kit/src/cli/api/graphql/admin/queries/metafield_definitions_by_owner_type.graphql b/packages/cli-kit/src/cli/api/graphql/admin/queries/metafield_definitions_by_owner_type.graphql new file mode 100644 index 00000000000..f05b01b3d06 --- /dev/null +++ b/packages/cli-kit/src/cli/api/graphql/admin/queries/metafield_definitions_by_owner_type.graphql @@ -0,0 +1,14 @@ +query metafieldDefinitionsByOwnerType($ownerType: MetafieldOwnerType!) { + metafieldDefinitions(ownerType: $ownerType, first: 250) { + nodes { + key + name + namespace + description + type { + category + name + } + } + } +} diff --git a/packages/cli-kit/src/private/node/api.test.ts b/packages/cli-kit/src/private/node/api.test.ts index eb61b6fb01f..b3836edf778 100644 --- a/packages/cli-kit/src/private/node/api.test.ts +++ b/packages/cli-kit/src/private/node/api.test.ts @@ -55,6 +55,7 @@ describe('retryAwareRequest', () => { url: 'https://example.com', }, undefined, + undefined, { defaultDelayMs: 500, scheduleDelay: mockScheduleDelayFn, @@ -100,6 +101,7 @@ describe('retryAwareRequest', () => { url: 'https://example.com', }, undefined, + undefined, { limitRetriesTo: 7, scheduleDelay: mockScheduleDelayFn, @@ -110,4 +112,54 @@ describe('retryAwareRequest', () => { expect(mockRequestFn).toHaveBeenCalledTimes(8) expect(mockScheduleDelayFn).toHaveBeenCalledTimes(7) }) + + test('calls unauthorizedHandler when receiving 401', async () => { + const unauthorizedResponse = { + status: 401, + errors: [ + { + extensions: { + code: '401', + }, + } as any, + ], + headers: new Headers(), + } + + const mockRequestFn = vi + .fn() + .mockImplementationOnce(() => { + throw new ClientError(unauthorizedResponse, {query: ''}) + }) + .mockImplementationOnce(() => { + return Promise.resolve({ + status: 200, + data: {hello: 'world!'}, + headers: new Headers(), + }) + }) + + const mockUnauthorizedHandler = vi.fn() + + await expect( + retryAwareRequest( + { + request: mockRequestFn, + url: 'https://example.com', + }, + undefined, + mockUnauthorizedHandler, + { + scheduleDelay: vi.fn((fn) => fn()), + }, + ), + ).resolves.toEqual({ + headers: expect.anything(), + status: 200, + data: {hello: 'world!'}, + }) + + expect(mockRequestFn).toHaveBeenCalledTimes(2) + expect(mockUnauthorizedHandler).toHaveBeenCalledTimes(1) + }) }) diff --git a/packages/cli-kit/src/private/node/api.ts b/packages/cli-kit/src/private/node/api.ts index 2327fcafb79..e04810d6ac8 100644 --- a/packages/cli-kit/src/private/node/api.ts +++ b/packages/cli-kit/src/private/node/api.ts @@ -40,6 +40,7 @@ type VerboseResponse = { | {status: 'client-error'; clientError: ClientError} | {status: 'unknown-error'; error: unknown} | {status: 'can-retry'; clientError: ClientError; delayMs: number | undefined} + | {status: 'unauthorized'; clientError: ClientError; delayMs: number | undefined} ) async function makeVerboseRequest({ @@ -88,6 +89,16 @@ async function makeVerboseRequest( requestId: responseHeaders['x-request-id'], delayMs, } + } else if (err.response.status === 401) { + return { + status: 'unauthorized', + clientError: err, + duration, + sanitizedHeaders, + sanitizedUrl, + requestId: responseHeaders['x-request-id'], + delayMs: 500, + } } return { @@ -126,7 +137,7 @@ function errorsIncludeStatus429(error: ClientError): boolean { } // GraphQL returns a 401 with a string error message when auth fails - // Therefore error.response.errros can be a string or GraphQLError[] + // Therefore error.response.errors can be a string or GraphQLError[] if (typeof error.response.errors === 'string') { return false } @@ -169,12 +180,20 @@ ${result.sanitizedHeaders} throw result.clientError } } + case 'unauthorized': { + if (errorHandler) { + throw errorHandler(result.clientError, result.requestId) + } else { + throw result.clientError + } + } } } export async function retryAwareRequest( {request, url}: RequestOptions, errorHandler?: (error: unknown, requestId: string | undefined) => unknown, + unauthorizedHandler?: () => Promise, retryOptions: { limitRetriesTo?: number defaultDelayMs?: number @@ -211,6 +230,13 @@ ${result.sanitizedHeaders} } else { throw result.error } + } else if (result.status === 'unauthorized') { + if (unauthorizedHandler) { + // eslint-disable-next-line no-await-in-loop + await unauthorizedHandler() + } else { + throw result.clientError + } } if (limitRetriesTo <= retriesUsed) { diff --git a/packages/cli-kit/src/private/node/constants.ts b/packages/cli-kit/src/private/node/constants.ts index 6337664367c..c9a4ab91517 100644 --- a/packages/cli-kit/src/private/node/constants.ts +++ b/packages/cli-kit/src/private/node/constants.ts @@ -44,6 +44,8 @@ export const environmentVariables = { refreshToken: 'SHOPIFY_CLI_REFRESH_TOKEN', otelURL: 'SHOPIFY_CLI_OTEL_EXPORTER_OTLP_ENDPOINT', themeKitAccessDomain: 'SHOPIFY_CLI_THEME_KIT_ACCESS_DOMAIN', + json: 'SHOPIFY_FLAG_JSON', + useAppManagement: 'USE_APP_MANAGEMENT_API', } export const defaultThemeKitAccessDomain = 'theme-kit-access.shopifyapps.com' diff --git a/packages/cli-kit/src/private/node/session.ts b/packages/cli-kit/src/private/node/session.ts index cb1d1d7b028..041df38d971 100644 --- a/packages/cli-kit/src/private/node/session.ts +++ b/packages/cli-kit/src/private/node/session.ts @@ -16,7 +16,7 @@ import {RequestClientError} from './api/headers.js' import {getCachedPartnerAccountStatus, setCachedPartnerAccountStatus} from './conf-store.js' import {isThemeAccessSession} from './api/rest.js' import {outputContent, outputToken, outputDebug} from '../../public/node/output.js' -import {firstPartyDev, themeToken} from '../../public/node/context/local.js' +import {firstPartyDev, isAppManagementEnabled, themeToken} from '../../public/node/context/local.js' import {AbortError, BugError} from '../../public/node/error.js' import {partnersRequest} from '../../public/node/api/partners.js' import {normalizeStoreFqdn, partnersFqdn, identityFqdn} from '../../public/node/context/fqdn.js' @@ -26,7 +26,6 @@ import {getIdentityTokenInformation, getPartnersToken} from '../../public/node/e import {gql} from 'graphql-request' import {AdminSession} from '@shopify/cli-kit/node/session' import {outputCompleted, outputInfo, outputWarn} from '@shopify/cli-kit/node/output' -import {isTruthy} from '@shopify/cli-kit/node/context/utilities' import {isSpin} from '@shopify/cli-kit/node/context/spin' import {nonRandomUUID} from '@shopify/cli-kit/node/crypto' @@ -310,7 +309,7 @@ async function executeCompleteFlow(applications: OAuthApplications, identityFqdn * @param partnersToken - Partners token. */ async function ensureUserHasPartnerAccount(partnersToken: string, userId: string | undefined) { - if (isTruthy(process.env.USE_APP_MANAGEMENT_API)) return + if (isAppManagementEnabled()) return outputDebug(outputContent`Verifying that the user has a Partner organization`) if (!(await hasPartnerAccount(partnersToken, userId))) { diff --git a/packages/cli-kit/src/private/node/session/exchange.ts b/packages/cli-kit/src/private/node/session/exchange.ts index 10185d532d0..2e3b8a540a4 100644 --- a/packages/cli-kit/src/private/node/session/exchange.ts +++ b/packages/cli-kit/src/private/node/session/exchange.ts @@ -5,8 +5,8 @@ import {identityFqdn} from '../../../public/node/context/fqdn.js' import {shopifyFetch} from '../../../public/node/http.js' import {err, ok, Result} from '../../../public/node/result.js' import {AbortError, BugError, ExtendableError} from '../../../public/node/error.js' +import {isAppManagementEnabled} from '../../../public/node/context/local.js' import {setLastSeenAuthMethod, setLastSeenUserIdAfterAuth} from '../session.js' -import {isTruthy} from '@shopify/cli-kit/node/context/utilities' import * as jose from 'jose' import {nonRandomUUID} from '@shopify/cli-kit/node/crypto' @@ -34,7 +34,7 @@ export async function exchangeAccessForApplicationTokens( store?: string, ): Promise<{[x: string]: ApplicationToken}> { const token = identityToken.accessToken - const appManagementEnabled = isTruthy(process.env.USE_APP_MANAGEMENT_API) + const appManagementEnabled = isAppManagementEnabled() const [partners, storefront, businessPlatform, admin, appManagement] = await Promise.all([ requestAppToken('partners', token, scopes.partners), diff --git a/packages/cli-kit/src/private/node/session/scopes.test.ts b/packages/cli-kit/src/private/node/session/scopes.test.ts index fee1ba818c0..d7f88fd9b53 100644 --- a/packages/cli-kit/src/private/node/session/scopes.test.ts +++ b/packages/cli-kit/src/private/node/session/scopes.test.ts @@ -1,4 +1,5 @@ import {allDefaultScopes, apiScopes} from './scopes.js' +import {environmentVariables} from '../constants.js' import {describe, expect, test} from 'vitest' describe('allDefaultScopes', () => { @@ -25,7 +26,7 @@ describe('allDefaultScopes', () => { test('includes App Management and Store Management when the required env var is defined', async () => { // Given - const envVars = {USE_APP_MANAGEMENT_API: 'true'} + const envVars = {[environmentVariables.useAppManagement]: 'true'} // When const got = allDefaultScopes([], envVars) diff --git a/packages/cli-kit/src/private/node/session/scopes.ts b/packages/cli-kit/src/private/node/session/scopes.ts index fc8a313fb30..072fb29d2fc 100644 --- a/packages/cli-kit/src/private/node/session/scopes.ts +++ b/packages/cli-kit/src/private/node/session/scopes.ts @@ -1,6 +1,6 @@ import {allAPIs, API} from '../api.js' import {BugError} from '../../../public/node/error.js' -import {isTruthy} from '@shopify/cli-kit/node/context/utilities' +import {isAppManagementEnabled} from '../../../public/node/context/local.js' /** * Generate a flat array with all the default scopes for all the APIs plus @@ -35,11 +35,9 @@ function defaultApiScopes(api: API, systemEnvironment = process.env): string[] { case 'partners': return ['cli'] case 'business-platform': - return isTruthy(systemEnvironment.USE_APP_MANAGEMENT_API) - ? ['destinations', 'store-management'] - : ['destinations'] + return isAppManagementEnabled(systemEnvironment) ? ['destinations', 'store-management'] : ['destinations'] case 'app-management': - return isTruthy(systemEnvironment.USE_APP_MANAGEMENT_API) ? ['app-management'] : [] + return isAppManagementEnabled(systemEnvironment) ? ['app-management'] : [] default: throw new BugError(`Unknown API: ${api}`) } diff --git a/packages/cli-kit/src/private/node/ui/components/AutocompletePrompt.test.tsx b/packages/cli-kit/src/private/node/ui/components/AutocompletePrompt.test.tsx index 738b9b3b674..44386351e15 100644 --- a/packages/cli-kit/src/private/node/ui/components/AutocompletePrompt.test.tsx +++ b/packages/cli-kit/src/private/node/ui/components/AutocompletePrompt.test.tsx @@ -530,6 +530,95 @@ describe('AutocompletePrompt', async () => { expect(onEnter).toHaveBeenCalledWith('fifth') }) + test('allows searching with malformed regex', async () => { + const onEnter = vi.fn() + const db = [...DATABASE, {label: 'with\\slash', value: 'with\\slash'}] + + const search = async (term: string) => { + return { + data: db.filter((item) => item.label.includes(term)), + } + } + + const renderInstance = render( + , + ) + + expect(renderInstance.lastFrame()).toMatchInlineSnapshot(` + "? Associate your project with the org Castile Ventures? Type to search... + + > first   + second   + third   + fourth   + fifth   + sixth   + seventh   + eighth   + ninth   + tenth   + eleventh   + twelfth   + thirteenth   + fourteenth   + fifteenth   + sixteenth   + seventeenth   + eighteenth   + nineteenth   + twentieth   + twenty-first   + twenty-second   + twenty-third   + twenty-fourth   + twenty-fifth   + + Press ↑↓ arrows to select, enter to confirm. + " + `) + + await waitForInputsToBeReady() + await sendInputAndWaitForContent(renderInstance, 'slash', '\\') + + expect(renderInstance.lastFrame()).toMatchInlineSnapshot(` + "? Associate your project with the org Castile Ventures? \\\\█ + + > with\\\\slash + + + + + + + + + + + + + + + + + + + + + + + + + + Press ↑↓ arrows to select, enter to confirm. + " + `) + }) + test('displays an error message if the search fails', async () => { const search = (_term: string) => { return Promise.reject(new Error('Something went wrong')) diff --git a/packages/cli-kit/src/private/node/ui/components/SelectInput.tsx b/packages/cli-kit/src/private/node/ui/components/SelectInput.tsx index 0698df0aea8..73d8203ad2e 100644 --- a/packages/cli-kit/src/private/node/ui/components/SelectInput.tsx +++ b/packages/cli-kit/src/private/node/ui/components/SelectInput.tsx @@ -45,7 +45,14 @@ function highlightedLabel(label: string, term: string | undefined) { return label } - const regex = new RegExp(term, 'i') + let regex + try { + regex = new RegExp(term, 'i') + // eslint-disable-next-line no-catch-all/no-catch-all + } catch (error) { + // term is user provided and could be an invalid regex at that moment (e.g. ending in '\') + return label + } return label.replace(regex, (match) => { return chalk.bold(match) }) diff --git a/packages/cli-kit/src/public/common/version.ts b/packages/cli-kit/src/public/common/version.ts index 1280ca544ae..01a6cad2473 100644 --- a/packages/cli-kit/src/public/common/version.ts +++ b/packages/cli-kit/src/public/common/version.ts @@ -1 +1 @@ -export const CLI_KIT_VERSION = '3.70.0' +export const CLI_KIT_VERSION = '3.72.0' diff --git a/packages/cli-kit/src/public/node/api/admin.ts b/packages/cli-kit/src/public/node/api/admin.ts index 58d3ede497d..10a9b92fa19 100644 --- a/packages/cli-kit/src/public/node/api/admin.ts +++ b/packages/cli-kit/src/public/node/api/admin.ts @@ -63,7 +63,17 @@ export async function adminRequestDoc( token: session.token, addedHeaders, } - const result = graphqlRequestDoc({...opts, query, variables, responseOptions}) + let unauthorizedHandler + if ('refresh' in session) { + unauthorizedHandler = session.refresh as () => Promise + } + const result = graphqlRequestDoc({ + ...opts, + query, + variables, + responseOptions, + unauthorizedHandler, + }) return result } diff --git a/packages/cli-kit/src/public/node/api/functions.ts b/packages/cli-kit/src/public/node/api/functions.ts new file mode 100644 index 00000000000..65c07fc766c --- /dev/null +++ b/packages/cli-kit/src/public/node/api/functions.ts @@ -0,0 +1,63 @@ +import {graphqlRequestDoc} from './graphql.js' +import {handleDeprecations} from './app-management.js' +import {appManagementFqdn} from '../context/fqdn.js' +import {TypedDocumentNode} from '@graphql-typed-document-node/core' +import {Variables} from 'graphql-request' +import Bottleneck from 'bottleneck' + +// API Rate limiter for partners API (Limit is 10 requests per second) +// Jobs are launched every 150ms to add an extra 50ms margin per request. +// Only 10 requests can be executed concurrently. +const limiter = new Bottleneck({ + minTime: 150, + maxConcurrent: 10, +}) + +/** + * Prepares the request configuration for the App Management Functions API. + * + * @param orgId - Organization identifier. + * @param token - Authentication token. + * @param appId - App identifier. + * @returns Request configuration object. + */ +async function setupRequest(orgId: string, token: string, appId: string) { + const api = 'Functions' + const fqdn = await appManagementFqdn() + const url = `https://${fqdn}/functions/unstable/organizations/${orgId}/${appId}/graphql` + + return { + token, + api, + url, + responseOptions: {onResponse: handleDeprecations}, + } +} + +/** + * Executes a rate-limited GraphQL request against the App Management Functions API. + * + * @param orgId - Organization identifier. + * @param query - Typed GraphQL document node. + * @param token - Authentication token. + * @param appId - App identifier. + * @param variables - Optional query variables. + * @returns Promise resolving to the typed query result. + */ +export async function functionsRequestDoc( + orgId: string, + query: TypedDocumentNode, + token: string, + appId: string, + variables?: TVariables, +): Promise { + const result = await limiter.schedule(async () => { + return graphqlRequestDoc({ + ...(await setupRequest(orgId, token, appId)), + query, + variables, + }) + }) + + return result +} diff --git a/packages/cli-kit/src/public/node/api/graphql.test.ts b/packages/cli-kit/src/public/node/api/graphql.test.ts index 4e5e4d2f178..33db86c421e 100644 --- a/packages/cli-kit/src/public/node/api/graphql.test.ts +++ b/packages/cli-kit/src/public/node/api/graphql.test.ts @@ -54,7 +54,7 @@ describe('graphqlRequest', () => { request: expect.any(Function), url: mockedAddress, } - expect(retryAwareRequest).toHaveBeenCalledWith(receivedObject, expect.any(Function)) + expect(retryAwareRequest).toHaveBeenCalledWith(receivedObject, expect.any(Function), undefined) }) }) @@ -95,6 +95,7 @@ describe('graphqlRequestDoc', () => { url: mockedAddress, }, expect.any(Function), + undefined, ) expect(debugRequest.debugLogRequestInfo).toHaveBeenCalledWith( 'mockApi', diff --git a/packages/cli-kit/src/public/node/api/graphql.ts b/packages/cli-kit/src/public/node/api/graphql.ts index bb6f788d8d4..453481a7b99 100644 --- a/packages/cli-kit/src/public/node/api/graphql.ts +++ b/packages/cli-kit/src/public/node/api/graphql.ts @@ -2,7 +2,14 @@ import {buildHeaders, httpsAgent} from '../../../private/node/api/headers.js' import {debugLogRequestInfo, errorHandler} from '../../../private/node/api/graphql.js' import {addPublicMetadata, runWithTimer} from '../metadata.js' import {retryAwareRequest} from '../../../private/node/api.js' -import {GraphQLClient, rawRequest, RequestDocument, resolveRequestDocument, Variables} from 'graphql-request' +import { + GraphQLClient, + rawRequest, + RequestDocument, + resolveRequestDocument, + Variables, + ClientError, +} from 'graphql-request' import {TypedDocumentNode} from '@graphql-typed-document-node/core' // to replace TVariable type when there graphql query has no variables @@ -26,16 +33,19 @@ interface GraphQLRequestBaseOptions { type PerformGraphQLRequestOptions = GraphQLRequestBaseOptions & { queryAsString: string variables?: Variables + unauthorizedHandler?: () => Promise } export type GraphQLRequestOptions = GraphQLRequestBaseOptions & { query: RequestDocument variables?: Variables + unauthorizedHandler?: () => Promise } export type GraphQLRequestDocOptions = GraphQLRequestBaseOptions & { query: TypedDocumentNode | TypedDocumentNode> variables?: TVariables + unauthorizedHandler?: () => Promise } export interface GraphQLResponseOptions { @@ -49,7 +59,7 @@ export interface GraphQLResponseOptions { * @param options - GraphQL request options. */ async function performGraphQLRequest(options: PerformGraphQLRequestOptions) { - const {token, addedHeaders, queryAsString, variables, api, url, responseOptions} = options + const {token, addedHeaders, queryAsString, variables, api, url, responseOptions, unauthorizedHandler} = options const headers = { ...addedHeaders, ...buildHeaders(token), @@ -59,32 +69,53 @@ async function performGraphQLRequest(options: PerformGraphQLRequestOpti const clientOptions = {agent: await httpsAgent(), headers} const client = new GraphQLClient(url, clientOptions) + const performRequest = async () => { + let fullResponse: GraphQLResponse + // there is a errorPolicy option which returns rather than throwing on errors, but we _do_ ultimately want to + // throw. + try { + fullResponse = await client.rawRequest(queryAsString, variables) + await logLastRequestIdFromResponse(fullResponse) + return fullResponse + } catch (error) { + if (error instanceof ClientError) { + // error.response does have a headers property like a normal response, but it's not typed as such. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + await logLastRequestIdFromResponse(error.response as any) + } + throw error + } + } + return runWithTimer('cmd_all_timing_network_ms')(async () => { const response = await retryAwareRequest( - {request: () => client.rawRequest(queryAsString, variables), url}, + {request: performRequest, url}, responseOptions?.handleErrors === false ? undefined : errorHandler(api), + unauthorizedHandler, ) if (responseOptions?.onResponse) { responseOptions.onResponse(response) } - try { - const requestId = response.headers.get('x-request-id') - await addPublicMetadata(async () => { - return { - cmd_all_last_graphql_request_id: requestId ?? undefined, - } - }) - // eslint-disable-next-line no-catch-all/no-catch-all - } catch { - // no problem if unable to get request ID. - } - return response.data }) } +async function logLastRequestIdFromResponse(response: GraphQLResponse) { + try { + const requestId = response.headers.get('x-request-id') + await addPublicMetadata(async () => { + return { + cmd_all_last_graphql_request_id: requestId ?? undefined, + } + }) + // eslint-disable-next-line no-catch-all/no-catch-all + } catch { + // no problem if unable to get request ID. + } +} + /** * Executes a GraphQL query to an endpoint. * diff --git a/packages/cli-kit/src/public/node/api/webhooks.ts b/packages/cli-kit/src/public/node/api/webhooks.ts new file mode 100644 index 00000000000..07f67cf6e19 --- /dev/null +++ b/packages/cli-kit/src/public/node/api/webhooks.ts @@ -0,0 +1,45 @@ +import {graphqlRequestDoc} from './graphql.js' +import {appManagementFqdn} from '../context/fqdn.js' +import Bottleneck from 'bottleneck' +import {Variables} from 'graphql-request' +import {TypedDocumentNode} from '@graphql-typed-document-node/core' + +// API Rate limiter +// Jobs are launched every 150ms +// Only 10 requests can be executed concurrently. +const limiter = new Bottleneck({ + minTime: 150, + maxConcurrent: 10, +}) + +/** + * Executes an org-scoped GraphQL query against the App Management API. + * Uses typed documents. + * + * @param organizationId - Organization ID required to check permissions. + * @param query - GraphQL query to execute. + * @param token - Partners token. + * @param variables - GraphQL variables to pass to the query. + * @returns The response of the query of generic type . + */ +export async function webhooksRequest( + organizationId: string, + query: TypedDocumentNode, + token: string, + variables?: TVariables, +): Promise { + const api = 'Webhooks' + const fqdn = await appManagementFqdn() + const url = `https://${fqdn}/webhooks/unstable/organizations/${organizationId}/graphql.json` + const result = limiter.schedule(() => + graphqlRequestDoc({ + query, + api, + url, + token, + variables, + }), + ) + + return result +} diff --git a/packages/cli-kit/src/public/node/cli.ts b/packages/cli-kit/src/public/node/cli.ts index 999cdae5184..43def980f66 100644 --- a/packages/cli-kit/src/public/node/cli.ts +++ b/packages/cli-kit/src/public/node/cli.ts @@ -1,5 +1,7 @@ import {isTruthy} from './context/utilities.js' +import {launchCLI as defaultLaunchCli} from './cli-launcher.js' import {cacheClear} from '../../private/node/conf-store.js' +import {environmentVariables} from '../../private/node/constants.js' import {Flags} from '@oclif/core' /** @@ -73,7 +75,7 @@ function forceNoColor(argv: string[] = process.argv, env: NodeJS.ProcessEnv = pr */ export async function runCLI( options: RunCLIOptions & {runInCreateMode?: boolean}, - launchCLI: (options: {moduleURL: string}) => Promise, + launchCLI: (options: {moduleURL: string}) => Promise = defaultLaunchCli, argv: string[] = process.argv, env: NodeJS.ProcessEnv = process.env, versions: NodeJS.ProcessVersions = process.versions, @@ -110,7 +112,7 @@ async function addInitToArgvWhenRunningCreateCLI( */ export async function runCreateCLI( options: RunCLIOptions, - launchCLI: (options: {moduleURL: string}) => Promise, + launchCLI: (options: {moduleURL: string}) => Promise = defaultLaunchCli, argv: string[] = process.argv, env: NodeJS.ProcessEnv = process.env, versions: NodeJS.ProcessVersions = process.versions, @@ -135,6 +137,16 @@ export const globalFlags = { }), } +export const jsonFlag = { + json: Flags.boolean({ + char: 'j', + description: 'Output the result as JSON.', + hidden: false, + default: false, + env: environmentVariables.json, + }), +} + /** * Clear the CLI cache, used to store some API responses and handle notifications status */ diff --git a/packages/cli-kit/src/public/node/context/local.test.ts b/packages/cli-kit/src/public/node/context/local.test.ts index 2c687428e11..14c69b10fbe 100644 --- a/packages/cli-kit/src/public/node/context/local.test.ts +++ b/packages/cli-kit/src/public/node/context/local.test.ts @@ -4,6 +4,7 @@ import { isDevelopment, isShopify, isUnitTest, + isAppManagementEnabled, analyticsDisabled, cloudEnvironment, macAddress, @@ -99,6 +100,30 @@ describe('hasGit', () => { }) }) +describe('isAppManagementEnabled', () => { + test('returns true when USE_APP_MANAGEMENT_API is truthy', () => { + // Given + const env = {USE_APP_MANAGEMENT_API: '1'} + + // When + const got = isAppManagementEnabled(env) + + // Then + expect(got).toBe(true) + }) + + test('returns false when USE_APP_MANAGEMENT_API is falsy', () => { + // Given + const env = {USE_APP_MANAGEMENT_API: '0'} + + // When + const got = isAppManagementEnabled(env) + + // Then + expect(got).toBe(false) + }) +}) + describe('analitycsDisabled', () => { test('returns true when SHOPIFY_CLI_NO_ANALYTICS is truthy', () => { // Given diff --git a/packages/cli-kit/src/public/node/context/local.ts b/packages/cli-kit/src/public/node/context/local.ts index cc8a73b2db2..d4c1de54eee 100644 --- a/packages/cli-kit/src/public/node/context/local.ts +++ b/packages/cli-kit/src/public/node/context/local.ts @@ -46,6 +46,16 @@ export function isVerbose(env = process.env): boolean { return isTruthy(env[environmentVariables.verbose]) || process.argv.includes('--verbose') } +/** + * It returns true if the App Management API is available. + * + * @param env - The environment variables from the environment of the current process. + * @returns True if the App Management API is available. + */ +export function isAppManagementEnabled(env = process.env): boolean { + return isTruthy(env[environmentVariables.useAppManagement]) +} + /** * Returns true if the environment in which the CLI is running is either * a local environment (where dev is present) or a cloud environment (spin). diff --git a/packages/cli-kit/src/public/node/environment.ts b/packages/cli-kit/src/public/node/environment.ts index 549338baf3d..43dd9d465f8 100644 --- a/packages/cli-kit/src/public/node/environment.ts +++ b/packages/cli-kit/src/public/node/environment.ts @@ -1,4 +1,6 @@ import {nonRandomUUID} from './crypto.js' +import {isTruthy} from './context/utilities.js' +import {sniffForJson} from './path.js' import {environmentVariables, systemEnvironmentVariables} from '../../private/node/constants.js' /** @@ -70,3 +72,13 @@ export function getIdentityTokenInformation(): {accessToken: string; refreshToke userId: nonRandomUUID(identityToken), } } + +/** + * Checks if the JSON output is enabled via flag (--json or -j) or environment variable (SHOPIFY_FLAG_JSON). + * + * @param environment - Process environment variables. + * @returns True if the JSON output is enabled, false otherwise. + */ +export function jsonOutputEnabled(environment = getEnvironmentVariables()): boolean { + return sniffForJson() || isTruthy(environment[environmentVariables.json]) +} diff --git a/packages/cli-kit/src/public/node/error.ts b/packages/cli-kit/src/public/node/error.ts index af348c4d854..c8ada6f48e8 100644 --- a/packages/cli-kit/src/public/node/error.ts +++ b/packages/cli-kit/src/public/node/error.ts @@ -222,10 +222,12 @@ export function cleanSingleStackTracePath(filePath: string): string { function errorMessageImpliesEnvironmentIssue(message: string): boolean { const environmentIssueMessages = [ 'EPERM: operation not permitted, scandir', + 'EPERM: operation not permitted, rename', 'EACCES: permission denied', 'EPERM: operation not permitted, symlink', 'This version of npm supports the following node versions', - 'EBUSY: resource busy or locked, rmdir', + 'EBUSY: resource busy or locked', + 'ENOTEMPTY: directory not empty', 'getaddrinfo ENOTFOUND', 'Client network socket disconnected before secure TLS connection was established', 'spawn EPERM', diff --git a/packages/cli-kit/src/public/node/fs.ts b/packages/cli-kit/src/public/node/fs.ts index b5fa2c441bb..ed5a772c57c 100644 --- a/packages/cli-kit/src/public/node/fs.ts +++ b/packages/cli-kit/src/public/node/fs.ts @@ -43,6 +43,7 @@ import { chmod as fsChmod, access as fsAccess, rename as fsRename, + unlink as fsUnlink, } from 'fs/promises' import {pathToFileURL as pathToFile} from 'url' import * as os from 'os' @@ -329,14 +330,24 @@ export function fileSizeSync(path: string): number { } /** - * Unlink a file at the given path. + * Synchronously unlink a file at the given path. + * * @param path - Path to the file. - * @returns A promise that resolves when the file is unlinked. */ export function unlinkFileSync(path: string): void { fsUnlinkSync(path) } +/** + * Unlink a file at the given path. + * + * @param path - Path to the file. + * @returns A promise that resolves when the file is unlinked. + */ +export function unlinkFile(path: string): Promise { + return fsUnlink(path) +} + /** * Create a read stream for a file with optional options. * diff --git a/packages/cli-kit/src/public/node/git.test.ts b/packages/cli-kit/src/public/node/git.test.ts index 87b68ef15db..767cef09b7f 100644 --- a/packages/cli-kit/src/public/node/git.test.ts +++ b/packages/cli-kit/src/public/node/git.test.ts @@ -296,6 +296,24 @@ describe('ensureInsideGitDirectory()', () => { // Then await expect(git.ensureInsideGitDirectory()).resolves.toBeUndefined() }) +}) + +describe('insideGitDirectory()', () => { + test('returns true if inside a git directory', async () => { + // Given + mockedCheckIsRepo.mockResolvedValue(true) + + // Then + await expect(git.insideGitDirectory()).resolves.toBe(true) + }) + + test('returns false if not inside a git directory', async () => { + // Given + mockedCheckIsRepo.mockResolvedValue(false) + + // Then + await expect(git.insideGitDirectory()).resolves.toBe(false) + }) test('passes the directory option to simple git', async () => { // Given @@ -303,7 +321,7 @@ describe('ensureInsideGitDirectory()', () => { mockedCheckIsRepo.mockResolvedValue(true) // When - await git.ensureInsideGitDirectory(directory) + await git.insideGitDirectory(directory) // Then expect(simpleGit).toHaveBeenCalledWith({baseDir: directory}) diff --git a/packages/cli-kit/src/public/node/git.ts b/packages/cli-kit/src/public/node/git.ts index 060c9d4a254..5b1455a064b 100644 --- a/packages/cli-kit/src/public/node/git.ts +++ b/packages/cli-kit/src/public/node/git.ts @@ -268,11 +268,23 @@ export class OutsideGitDirectoryError extends AbortError {} export async function ensureInsideGitDirectory(directory?: string): Promise { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - if (!(await git({baseDir: directory}).checkIsRepo())) { + if (!(await insideGitDirectory(directory))) { throw new OutsideGitDirectoryError(`${outputToken.path(directory || cwd())} is not a Git directory`) } } +/** + * Returns true if the given directory is inside a .git directory tree. + * + * @param directory - The directory to check. + * @returns True if the directory is inside a .git directory tree. + */ +export async function insideGitDirectory(directory?: string): Promise { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + return git({baseDir: directory}).checkIsRepo() +} + export class GitDirectoryNotCleanError extends AbortError {} /** * If the .git directory tree is not clean (has uncommitted changes) diff --git a/packages/cli-kit/src/public/node/is-global.ts b/packages/cli-kit/src/public/node/is-global.ts index 8e7b8e6f0a8..324ddc0bc6e 100644 --- a/packages/cli-kit/src/public/node/is-global.ts +++ b/packages/cli-kit/src/public/node/is-global.ts @@ -16,23 +16,28 @@ let _isGlobal: boolean | undefined */ export function currentProcessIsGlobal(argv = process.argv): boolean { // If we are running tests, we need to disable the cache - if (_isGlobal !== undefined && !isUnitTest()) return _isGlobal + try { + if (_isGlobal !== undefined && !isUnitTest()) return _isGlobal - // Path where the current project is (app/hydrogen) - const path = sniffForPath() ?? cwd() + // Path where the current project is (app/hydrogen) + const path = sniffForPath() ?? cwd() - // Closest parent directory to contain a package.json file or node_modules directory - // https://docs.npmjs.com/cli/v8/commands/npm-prefix#description - const npmPrefix = execaSync('npm', ['prefix'], {cwd: path}).stdout.trim() + // Closest parent directory to contain a package.json file or node_modules directory + // https://docs.npmjs.com/cli/v8/commands/npm-prefix#description + const npmPrefix = execaSync('npm', ['prefix'], {cwd: path}).stdout.trim() - // From node docs: "The second element [of the array] will be the path to the JavaScript file being executed" - const binDir = argv[1] ?? '' + // From node docs: "The second element [of the array] will be the path to the JavaScript file being executed" + const binDir = argv[1] ?? '' - // If binDir starts with npmPrefix, then we are running a local CLI - const isLocal = binDir.startsWith(npmPrefix.trim()) + // If binDir starts with npmPrefix, then we are running a local CLI + const isLocal = binDir.startsWith(npmPrefix.trim()) - _isGlobal = !isLocal - return _isGlobal + _isGlobal = !isLocal + return _isGlobal + // eslint-disable-next-line no-catch-all/no-catch-all + } catch (error) { + return false + } } /** diff --git a/packages/cli-kit/src/public/node/json-schema.test.ts b/packages/cli-kit/src/public/node/json-schema.test.ts index fe83c8424d6..6b67c081ad4 100644 --- a/packages/cli-kit/src/public/node/json-schema.test.ts +++ b/packages/cli-kit/src/public/node/json-schema.test.ts @@ -52,7 +52,7 @@ describe('jsonSchemaValidate', () => { zod.object({foo: zod.number().max(99)}), {foo: 100}, ], - ])('matches the zod behaviour for %s', (_name, contract, zodVersion, subject) => { + ])('matches the zod behaviour for %s', (name, contract, zodVersion, subject) => { const zodParsed = zodVersion.safeParse(subject) expect(zodParsed.success).toBe(false) if (zodParsed.success) { @@ -61,7 +61,7 @@ describe('jsonSchemaValidate', () => { const zodErrors = zodParsed.error.errors.map((error) => ({path: error.path, message: error.message})) - const schemaParsed = jsonSchemaValidate(subject, contract) + const schemaParsed = jsonSchemaValidate(subject, contract, `test-${name}`) expect(schemaParsed.state).toBe('error') expect(schemaParsed.errors, `Converting ${JSON.stringify(schemaParsed.rawErrors)}`).toEqual(zodErrors) }) @@ -77,7 +77,7 @@ describe('jsonSchemaValidate', () => { }, 'x-taplo': {foo: 'bar'}, } - const schemaParsed = jsonSchemaValidate(subject, contract) + const schemaParsed = jsonSchemaValidate(subject, contract, 'test2') expect(schemaParsed.state).toBe('ok') }) @@ -121,7 +121,7 @@ describe('jsonSchemaValidate', () => { }, }, } - const schemaParsed = jsonSchemaValidate(subject, contract) + const schemaParsed = jsonSchemaValidate(subject, contract, 'test3') expect(schemaParsed.state).toBe('error') expect(schemaParsed.errors).toEqual([ { @@ -175,7 +175,7 @@ describe('jsonSchemaValidate', () => { }, }, } - const schemaParsed = jsonSchemaValidate(subject, contract) + const schemaParsed = jsonSchemaValidate(subject, contract, 'test4') expect(schemaParsed.state).toBe('error') expect(schemaParsed.errors).toEqual([ { diff --git a/packages/cli-kit/src/public/node/json-schema.ts b/packages/cli-kit/src/public/node/json-schema.ts index 2c740a3550f..4ffdea4d91f 100644 --- a/packages/cli-kit/src/public/node/json-schema.ts +++ b/packages/cli-kit/src/public/node/json-schema.ts @@ -2,7 +2,7 @@ import {ParseConfigurationResult} from './schema.js' import {getPathValue} from '../common/object.js' import {capitalize} from '../common/string.js' -import {Ajv, ErrorObject, SchemaObject} from 'ajv' +import {Ajv, ErrorObject, SchemaObject, ValidateFunction} from 'ajv' import $RefParser from '@apidevtools/json-schema-ref-parser' type AjvError = ErrorObject @@ -22,6 +22,8 @@ export async function normaliseJsonSchema(schema: string): Promise return parsedSchema } +const validatorsCache = new Map() + /** * Given a subject object and a JSON schema contract, validate the subject against the contract. * @@ -29,15 +31,21 @@ export async function normaliseJsonSchema(schema: string): Promise * * @param subject - The object to validate. * @param schema - The JSON schema to validate against. + * @param identifier - The identifier of the schema being validated, used to cache the validator. * @returns The result of the validation. If the state is 'error', the errors will be in a zod-like format. */ export function jsonSchemaValidate( subject: object, schema: SchemaObject, + identifier: string, ): ParseConfigurationResult & {rawErrors?: AjvError[]} { const ajv = new Ajv({allowUnionTypes: true}) + ajv.addKeyword('x-taplo') - const validator = ajv.compile(schema) + + const validator = validatorsCache.get(identifier) ?? ajv.compile(schema) + validatorsCache.set(identifier, validator) + validator(subject) // Errors from the contract are post-processed to be more zod-like and to deal with unions better diff --git a/packages/cli-kit/src/public/node/node-package-manager.ts b/packages/cli-kit/src/public/node/node-package-manager.ts index 99094948dd1..89dcb0ca417 100644 --- a/packages/cli-kit/src/public/node/node-package-manager.ts +++ b/packages/cli-kit/src/public/node/node-package-manager.ts @@ -29,6 +29,13 @@ export const pnpmWorkspaceFile = 'pnpm-workspace.yaml' /** An array containing the lockfiles from all the package managers */ export const lockfiles: Lockfile[] = [yarnLockfile, pnpmLockfile, npmLockfile, bunLockfile] +export const lockfilesByManager: {[key in PackageManager]: Lockfile | undefined} = { + yarn: yarnLockfile, + npm: npmLockfile, + pnpm: pnpmLockfile, + bun: bunLockfile, + unknown: undefined, +} export type Lockfile = 'yarn.lock' | 'package-lock.json' | 'pnpm-lock.yaml' | 'bun.lockb' /** diff --git a/packages/cli-kit/src/public/node/notifications-system.test.ts b/packages/cli-kit/src/public/node/notifications-system.test.ts index 974d522cc45..c7b44ec34ce 100644 --- a/packages/cli-kit/src/public/node/notifications-system.test.ts +++ b/packages/cli-kit/src/public/node/notifications-system.test.ts @@ -1,10 +1,12 @@ import {Notification, filterNotifications, showNotificationsIfNeeded} from './notifications-system.js' import {renderError, renderInfo, renderWarning} from './ui.js' +import {sniffForJson} from './path.js' import {cacheRetrieve, cacheRetrieveOrRepopulate} from '../../private/node/conf-store.js' import {afterEach, describe, expect, test, vi} from 'vitest' vi.mock('./ui.js') vi.mock('../../private/node/conf-store.js') +vi.mock('./path.js') const betweenVersins1and2: Notification = { id: 'betweenVersins1and2', @@ -258,7 +260,7 @@ afterEach(() => { vi.useRealTimers() }) -describe('notifications-system filter notifications', () => { +describe('filterNotifications', () => { test.each(testCases)('Filter for %name', ({input, commandId, version, date, surfaces, output}) => { // When const result = filterNotifications(input, commandId, surfaces, new Date(date), version) @@ -327,7 +329,7 @@ describe('notifications-system filter notifications', () => { }) }) -describe('notifications-system', () => { +describe('showNotificationsIfNeeded', () => { test('an info notification triggers a renderInfo call', async () => { // Given const notifications = [infoNotification] @@ -363,4 +365,53 @@ describe('notifications-system', () => { // Then expect(renderError).toHaveBeenCalled() }) + + test('notifications are skipped on CI', async () => { + // Given + const notifications = [infoNotification] + vi.mocked(cacheRetrieveOrRepopulate).mockResolvedValue(JSON.stringify({notifications})) + + // When + await showNotificationsIfNeeded(undefined, {SHOPIFY_UNIT_TEST: 'false', CI: 'true'}) + + // Then + expect(renderInfo).not.toHaveBeenCalled() + }) + + test('notifications are skipped on tests', async () => { + // Given + const notifications = [infoNotification] + vi.mocked(cacheRetrieveOrRepopulate).mockResolvedValue(JSON.stringify({notifications})) + + // When + await showNotificationsIfNeeded(undefined, {SHOPIFY_UNIT_TEST: 'true'}) + + // Then + expect(renderInfo).not.toHaveBeenCalled() + }) + + test('notifications are skipped when using --json flag', async () => { + // Given + const notifications = [infoNotification] + vi.mocked(cacheRetrieveOrRepopulate).mockResolvedValue(JSON.stringify({notifications})) + vi.mocked(sniffForJson).mockReturnValue(true) + + // When + await showNotificationsIfNeeded(undefined, {SHOPIFY_UNIT_TEST: 'false'}) + + // Then + expect(renderInfo).not.toHaveBeenCalled() + }) + + test('notifications are skipped when using SHOPIFY_FLAG_JSON', async () => { + // Given + const notifications = [infoNotification] + vi.mocked(cacheRetrieveOrRepopulate).mockResolvedValue(JSON.stringify({notifications})) + + // When + await showNotificationsIfNeeded(undefined, {SHOPIFY_UNIT_TEST: 'false', SHOPIFY_FLAG_JSON: 'true'}) + + // Then + expect(renderInfo).not.toHaveBeenCalled() + }) }) diff --git a/packages/cli-kit/src/public/node/notifications-system.ts b/packages/cli-kit/src/public/node/notifications-system.ts index b382dafb2a6..8ca472a5d82 100644 --- a/packages/cli-kit/src/public/node/notifications-system.ts +++ b/packages/cli-kit/src/public/node/notifications-system.ts @@ -5,6 +5,7 @@ import {outputDebug} from './output.js' import {zod} from './schema.js' import {AbortSilentError} from './error.js' import {isTruthy} from './context/utilities.js' +import {jsonOutputEnabled} from './environment.js' import {CLI_KIT_VERSION} from '../common/version.js' import { NotificationKey, @@ -54,9 +55,12 @@ export type Notifications = zod.infer * @param environment - Process environment variables. * @returns - A promise that resolves when the notifications have been shown. */ -export async function showNotificationsIfNeeded(currentSurfaces?: string[], environment = process.env): Promise { +export async function showNotificationsIfNeeded( + currentSurfaces?: string[], + environment: NodeJS.ProcessEnv = process.env, +): Promise { try { - if (isTruthy(environment.CI) || isTruthy(environment.SHOPIFY_UNIT_TEST)) return + if (skipNotifications(environment)) return const notifications = await getNotifications() const commandId = getCurrentCommandId() @@ -74,6 +78,10 @@ export async function showNotificationsIfNeeded(currentSurfaces?: string[], envi } } +function skipNotifications(environment: NodeJS.ProcessEnv): boolean { + return isTruthy(environment.CI) || isTruthy(environment.SHOPIFY_UNIT_TEST) || jsonOutputEnabled(environment) +} + /** * Renders the first 2 notifications to the user. * diff --git a/packages/cli-kit/src/public/node/path.ts b/packages/cli-kit/src/public/node/path.ts index 41fbcda42dd..1b064805c9c 100644 --- a/packages/cli-kit/src/public/node/path.ts +++ b/packages/cli-kit/src/public/node/path.ts @@ -172,12 +172,11 @@ export function sniffForPath(argv = process.argv): string | undefined { } /** - * Returns whether the `--json` flag is present in the arguments. + * Returns whether the `--json` or `-j` flags are present in the arguments. * - * @param argv - The arguments to search for the `--json` flag. - * @returns Whether the `--json` flag is present in the arguments. + * @param argv - The arguments to search for the `--json` and `-j` flags. + * @returns Whether the `--json` or `-j` flag is present in the arguments. */ export function sniffForJson(argv = process.argv): boolean { - const jsonFlagIndex = argv.indexOf('--json') - return jsonFlagIndex !== -1 + return argv.includes('--json') || argv.includes('-j') } diff --git a/packages/cli-kit/src/public/node/system.test.ts b/packages/cli-kit/src/public/node/system.test.ts new file mode 100644 index 00000000000..2c266263ec8 --- /dev/null +++ b/packages/cli-kit/src/public/node/system.test.ts @@ -0,0 +1,32 @@ +import * as system from './system.js' +import {execa} from 'execa' +import {describe, expect, test, vi} from 'vitest' +import which from 'which' + +vi.mock('which') +vi.mock('execa') + +describe('captureOutput', () => { + test('runs the command when it is not found in the current directory', async () => { + // Given + vi.mocked(which.sync).mockReturnValueOnce('/system/command') + vi.mocked(execa).mockResolvedValueOnce({stdout: undefined} as any) + + // When + const got = await system.captureOutput('command', [], {cwd: '/currentDirectory'}) + + // Then + expect(got).toEqual(undefined) + }) + + test('raises an error if the command to run is found in the current directory', async () => { + // Given + vi.mocked(which.sync).mockReturnValueOnce('/currentDirectory/command') + + // When + const got = system.captureOutput('command', [], {cwd: '/currentDirectory'}) + + // Then + await expect(got).rejects.toThrowError('Skipped run of unsecure binary command found in the current directory.') + }) +}) diff --git a/packages/cli-kit/src/public/node/system.ts b/packages/cli-kit/src/public/node/system.ts index fe77bdb0600..673fba6c422 100644 --- a/packages/cli-kit/src/public/node/system.ts +++ b/packages/cli-kit/src/public/node/system.ts @@ -7,6 +7,7 @@ import {renderWarning} from './ui.js' import {shouldDisplayColors, outputDebug} from '../../public/node/output.js' import {execa, ExecaChildProcess} from 'execa' import which from 'which' +import {delimiter} from 'pathe' import type {Writable, Readable} from 'stream' export interface ExecOptions { @@ -99,10 +100,11 @@ function buildExec(command: string, args: string[], options?: ExecOptions): Exec if (shouldDisplayColors()) { env.FORCE_COLOR = '1' } - checkCommandSafety(command) + const executionCwd = options?.cwd ?? cwd() + checkCommandSafety(command, {cwd: executionCwd}) const commandProcess = execa(command, args, { env, - cwd: options?.cwd, + cwd: executionCwd, input: options?.input, stdio: options?.stdio, stdin: options?.stdin, @@ -115,14 +117,18 @@ function buildExec(command: string, args: string[], options?: ExecOptions): Exec outputDebug(` Running system process: · Command: ${command} ${args.join(' ')} - · Working directory: ${options?.cwd ?? cwd()} + · Working directory: ${executionCwd} `) return commandProcess } -function checkCommandSafety(command: string) { - const commandDirectory = dirname(which.sync(command)) - if (commandDirectory === cwd()) { +function checkCommandSafety(command: string, _options: {cwd: string}): void { + const pathIncludingLocal = `${_options.cwd}${delimiter}${process.env.PATH}` + const commandPath = which.sync(command, { + nothrow: true, + path: pathIncludingLocal, + }) + if (commandPath && dirname(commandPath) === _options.cwd) { const headline = ['Skipped run of unsecure binary', {command}, 'found in the current directory.'] const body = 'Please remove that file or review your current PATH.' renderWarning({headline, body}) diff --git a/packages/cli-kit/src/public/node/themes/api.test.ts b/packages/cli-kit/src/public/node/themes/api.test.ts index abc6da31925..e74ba0159ba 100644 --- a/packages/cli-kit/src/public/node/themes/api.test.ts +++ b/packages/cli-kit/src/public/node/themes/api.test.ts @@ -10,11 +10,13 @@ import { AssetParams, deleteThemeAsset, } from './api.js' -import {RemoteBulkUploadResponse} from './factories.js' +import {Operation} from './types.js' import {ThemeDelete} from '../../../cli/api/graphql/admin/generated/theme_delete.js' import {ThemeUpdate} from '../../../cli/api/graphql/admin/generated/theme_update.js' import {ThemePublish} from '../../../cli/api/graphql/admin/generated/theme_publish.js' import {GetThemeFileChecksums} from '../../../cli/api/graphql/admin/generated/get_theme_file_checksums.js' +import {ThemeFilesUpsert} from '../../../cli/api/graphql/admin/generated/theme_files_upsert.js' +import {OnlineStoreThemeFileBodyInputType} from '../../../cli/api/graphql/admin/generated/types.js' import {test, vi, expect, describe} from 'vitest' import {adminRequestDoc, restRequest, supportedApiVersions} from '@shopify/cli-kit/node/api/admin' import {AbortError} from '@shopify/cli-kit/node/error' @@ -112,19 +114,18 @@ describe('createTheme', () => { test('creates a theme', async () => { // Given - vi.mocked(restRequest) - .mockResolvedValueOnce({ - json: {theme: {id, name, role, processing}}, - status: 200, - headers: {}, - }) - .mockResolvedValueOnce({ - json: { - results: [], - }, - status: 207, - headers: {}, - }) + vi.mocked(restRequest).mockResolvedValueOnce({ + json: {theme: {id, name, role, processing}}, + status: 200, + headers: {}, + }) + + vi.mocked(adminRequestDoc).mockResolvedValue({ + themeFilesUpsert: { + upsertedThemeFiles: [], + userErrors: [], + }, + }) // When const theme = await createTheme(params, session) @@ -355,7 +356,6 @@ describe('themeDelete', () => { describe('request errors', () => { test(`returns AbortError when graphql returns user error`, async () => { // Given - vi.mocked(adminRequestDoc).mockResolvedValue({ themeDelete: { deletedThemeId: null, @@ -370,147 +370,132 @@ describe('request errors', () => { // Then }).rejects.toThrowError(AbortError) }) - - test(`refresh the session when 401 errors happen`, async () => { - // Given - const id = 123 - const assets: AssetParams[] = [] - - vi.spyOn(session, 'refresh').mockImplementation(vi.fn()) - vi.mocked(restRequest) - .mockResolvedValueOnce({ - json: {}, - status: 401, - headers: {}, - }) - .mockResolvedValueOnce({ - json: {}, - status: 207, - headers: {}, - }) - - // When - await bulkUploadThemeAssets(id, assets, session) - - // Then - expect(session.refresh).toHaveBeenCalledOnce() - }) }) describe('bulkUploadThemeAssets', async () => { - test('uploads multiple assets', async () => { + test('uploads multiple TEXT and BASE64 assets', async () => { const id = 123 const assets: AssetParams[] = [ {key: 'snippets/product-variant-picker.liquid', value: 'content'}, - {key: 'templates/404.json', value: 'to_be_replaced_with_hash'}, - ] - - const mockResults: RemoteBulkUploadResponse[] = [ - { - code: 200, - body: { - asset: { - key: 'assets/test.liquid', - checksum: '3f26c8569292ce6f1cc991c5fa7d3fcb', - attachment: '', - value: '', - }, - }, - }, { - code: 400, - body: { - errors: {asset: ['expected Hash to be a String']}, - }, + key: 'templates/404.json', + value: 'to_be_replaced_with_hash', }, ] - vi.mocked(restRequest).mockResolvedValue({ - json: {results: mockResults}, - status: 207, - headers: {}, + vi.mocked(adminRequestDoc).mockResolvedValue({ + themeFilesUpsert: { + upsertedThemeFiles: [{filename: 'snippets/product-variant-picker.liquid'}, {filename: 'templates/404.json'}], + userErrors: [], + }, }) // When const bulkUploadresults = await bulkUploadThemeAssets(id, assets, session) // Then - expect(restRequest).toHaveBeenCalledWith( - 'PUT', - `/themes/${id}/assets/bulk`, - session, + expect(adminRequestDoc).toHaveBeenCalledWith(ThemeFilesUpsert, session, { + themeId: `gid://shopify/OnlineStoreTheme/${id}`, + files: [ + { + filename: 'snippets/product-variant-picker.liquid', + body: {value: 'content', type: 'TEXT' as OnlineStoreThemeFileBodyInputType}, + }, + { + filename: 'templates/404.json', + body: {value: 'to_be_replaced_with_hash', type: 'TEXT' as OnlineStoreThemeFileBodyInputType}, + }, + ], + }) + + expect(bulkUploadresults).toEqual([ { - assets: [ - {key: 'snippets/product-variant-picker.liquid', value: 'content'}, - {key: 'templates/404.json', value: 'to_be_replaced_with_hash'}, - ], + key: 'snippets/product-variant-picker.liquid', + success: true, + operation: Operation.Upload, }, - {}, - ) - expect(bulkUploadresults).toHaveLength(2) - expect(bulkUploadresults[0]).toEqual({ - key: 'snippets/product-variant-picker.liquid', - success: true, - errors: {}, - operation: 'UPLOAD', - asset: { - attachment: '', - key: 'assets/test.liquid', - checksum: '3f26c8569292ce6f1cc991c5fa7d3fcb', - value: '', + { + key: 'templates/404.json', + success: true, + operation: Operation.Upload, }, - }) - expect(bulkUploadresults[1]).toEqual({ - key: 'templates/404.json', - operation: 'UPLOAD', - success: false, - errors: {asset: ['expected Hash to be a String']}, - asset: undefined, - }) + ]) }) - test('throws an error when the server responds with a 404', async () => { + test('throws an error when returns userErrors with filenames', async () => { const id = 123 const assets: AssetParams[] = [ {key: 'snippets/product-variant-picker.liquid', value: 'content'}, - {key: 'templates/404.json', value: 'to_be_replaced_with_hash'}, + { + key: 'templates/404.json', + value: 'to_be_replaced_with_hash', + }, ] - vi.mocked(restRequest).mockResolvedValue({ - json: {}, - status: 404, - headers: {}, + vi.mocked(adminRequestDoc).mockResolvedValue({ + themeFilesUpsert: { + upsertedThemeFiles: [], + userErrors: [ + {filename: 'snippets/product-variant-picker.liquid', message: 'Something went wrong'}, + {filename: 'templates/404.json', message: 'Something went wrong'}, + ], + }, }) // When - await expect(async () => { - return bulkUploadThemeAssets(id, assets, session) - // Then - }).rejects.toThrowError(AbortError) + const bulkUploadresults = await bulkUploadThemeAssets(id, assets, session) + + // Then + expect(adminRequestDoc).toHaveBeenCalledWith(ThemeFilesUpsert, session, { + themeId: `gid://shopify/OnlineStoreTheme/${id}`, + files: [ + { + filename: 'snippets/product-variant-picker.liquid', + body: {value: 'content', type: 'TEXT' as OnlineStoreThemeFileBodyInputType}, + }, + { + filename: 'templates/404.json', + body: {value: 'to_be_replaced_with_hash', type: 'TEXT' as OnlineStoreThemeFileBodyInputType}, + }, + ], + }) + + expect(bulkUploadresults).toEqual([ + { + key: 'snippets/product-variant-picker.liquid', + success: false, + operation: Operation.Upload, + errors: {asset: ['Something went wrong']}, + }, + { + key: 'templates/404.json', + success: false, + operation: Operation.Upload, + errors: {asset: ['Something went wrong']}, + }, + ]) }) - test('throws an error when the server responds with a 403', async () => { - // Given + test('throws an error when returns userErrors with no filename', async () => { const id = 123 const assets: AssetParams[] = [ {key: 'snippets/product-variant-picker.liquid', value: 'content'}, - {key: 'templates/404.json', value: 'to_be_replaced_with_hash'}, + { + key: 'templates/404.json', + value: 'to_be_replaced_with_hash', + }, ] - const message = `Cannot delete generated asset 'assets/bla.css'. Delete 'assets/bla.css.liquid' instead.` - vi.mocked(restRequest).mockResolvedValue({ - json: { - message, + vi.mocked(adminRequestDoc).mockResolvedValue({ + themeFilesUpsert: { + upsertedThemeFiles: [], + userErrors: [{message: 'Something went wrong'}], }, - status: 403, - headers: {}, }) - // When - await expect(async () => { - return bulkUploadThemeAssets(id, assets, session) - - // Then - }).rejects.toThrowError(new AbortError(message)) + await expect(bulkUploadThemeAssets(id, assets, session)).rejects.toThrow(AbortError) + await expect(bulkUploadThemeAssets(id, assets, session)).rejects.toThrow( + 'Error uploading theme files: Something went wrong', + ) }) }) diff --git a/packages/cli-kit/src/public/node/themes/api.ts b/packages/cli-kit/src/public/node/themes/api.ts index 61a6fc4d183..32fba672c97 100644 --- a/packages/cli-kit/src/public/node/themes/api.ts +++ b/packages/cli-kit/src/public/node/themes/api.ts @@ -6,11 +6,21 @@ import {ThemeDelete} from '../../../cli/api/graphql/admin/generated/theme_delete import {ThemePublish} from '../../../cli/api/graphql/admin/generated/theme_publish.js' import {GetThemeFileBodies} from '../../../cli/api/graphql/admin/generated/get_theme_file_bodies.js' import {GetThemeFileChecksums} from '../../../cli/api/graphql/admin/generated/get_theme_file_checksums.js' +import { + ThemeFilesUpsert, + ThemeFilesUpsertMutation, +} from '../../../cli/api/graphql/admin/generated/theme_files_upsert.js' +import { + OnlineStoreThemeFileBodyInputType, + OnlineStoreThemeFilesUpsertFileInput, + MetafieldOwnerType, +} from '../../../cli/api/graphql/admin/generated/types.js' +import {MetafieldDefinitionsByOwnerType} from '../../../cli/api/graphql/admin/generated/metafield_definitions_by_owner_type.js' import {restRequest, RestResponse, adminRequestDoc} from '@shopify/cli-kit/node/api/admin' import {AdminSession} from '@shopify/cli-kit/node/session' import {AbortError} from '@shopify/cli-kit/node/error' -import {buildBulkUploadResults, buildTheme} from '@shopify/cli-kit/node/themes/factories' -import {Result, Checksum, Key, Theme, ThemeAsset} from '@shopify/cli-kit/node/themes/types' +import {buildTheme} from '@shopify/cli-kit/node/themes/factories' +import {Result, Checksum, Key, Theme, ThemeAsset, Operation} from '@shopify/cli-kit/node/themes/types' import {outputDebug} from '@shopify/cli-kit/node/output' import {sleep} from '@shopify/cli-kit/node/system' @@ -59,7 +69,7 @@ export async function fetchThemeAssets(id: number, filenames: Key[], session: Ad if (!response.theme?.files?.nodes || !response.theme?.files?.pageInfo) { const userErrors = response.theme?.files?.userErrors.map((error) => error.filename).join(', ') - throw new AbortError(`Error fetching assets: ${userErrors}`) + unexpectedGraphQLError(`Error fetching assets: ${userErrors}`) } const {nodes, pageInfo} = response.theme.files @@ -98,11 +108,79 @@ export async function bulkUploadThemeAssets( assets: AssetParams[], session: AdminSession, ): Promise { - const response = await request('PUT', `/themes/${id}/assets/bulk`, session, {assets}) - if (response.status !== 207) { - throw new AbortError('Upload failed, could not reach the server') + const results: Result[] = [] + for (let i = 0; i < assets.length; i += 50) { + const chunk = assets.slice(i, i + 50) + const files = prepareFilesForUpload(chunk) + // eslint-disable-next-line no-await-in-loop + const uploadResults = await uploadFiles(id, files, session) + results.push(...processUploadResults(uploadResults)) + } + return results +} + +function prepareFilesForUpload(assets: AssetParams[]): OnlineStoreThemeFilesUpsertFileInput[] { + return assets.map((asset) => { + if (asset.attachment) { + return { + filename: asset.key, + body: { + type: 'BASE64' as const, + value: asset.attachment, + }, + } + } else { + return { + filename: asset.key, + body: { + type: 'TEXT' as const, + value: asset.value ?? '', + }, + } + } + }) +} + +async function uploadFiles( + themeId: number, + files: {filename: string; body: {type: OnlineStoreThemeFileBodyInputType; value: string}}[], + session: AdminSession, +): Promise { + return adminRequestDoc(ThemeFilesUpsert, session, {themeId: themeGid(themeId), files}) +} + +function processUploadResults(uploadResults: ThemeFilesUpsertMutation): Result[] { + const {themeFilesUpsert} = uploadResults + + if (!themeFilesUpsert) { + unexpectedGraphQLError('Failed to upload theme files') } - return buildBulkUploadResults(response.json.results, assets) + + const {upsertedThemeFiles, userErrors} = themeFilesUpsert + + const results: Result[] = [] + + upsertedThemeFiles?.forEach((file) => { + results.push({ + key: file.filename, + success: true, + operation: Operation.Upload, + }) + }) + + userErrors.forEach((error) => { + if (!error.filename) { + unexpectedGraphQLError(`Error uploading theme files: ${error.message}`) + } + results.push({ + key: error.filename, + success: false, + operation: Operation.Upload, + errors: {asset: [error.message]}, + }) + }) + + return results } export async function fetchChecksums(id: number, session: AdminSession): Promise { @@ -212,6 +290,23 @@ export async function themeDelete(id: number, session: AdminSession): Promise ({ + key: definition.key, + namespace: definition.namespace, + name: definition.name, + description: definition.description, + type: { + name: definition.type.name, + category: definition.type.category, + }, + })) +} + async function request( method: string, path: string, @@ -354,10 +449,8 @@ async function parseThemeFileContent(body: OnlineStoreThemeFileBody): Promise { - return { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - key: assets[index]!.key, - success: bulkUpload.code === 200, - errors: bulkUpload.body.errors || {}, - asset: bulkUpload.body.asset, - operation: Operation.Upload, - } - }) -} diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index ce82380e66b..e8d595b587d 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,27 @@ # @shopify/cli +## 3.72.0 + +## 3.71.5 + +## 3.71.4 + +## 3.71.3 + +### Patch Changes + +- 05a1eda9eb: Updated link extension import to match a target format similar to action extesions + +## 3.71.2 + +## 3.71.1 + +## 3.71.0 + +### Patch Changes + +- 93d65a6c38: Remove PHP template from app creation options + ## 3.70.0 ### Minor Changes diff --git a/packages/cli/README.md b/packages/cli/README.md index 9ec6d84f714..587e511fb83 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -70,6 +70,7 @@ * [`shopify theme init [name]`](#shopify-theme-init-name) * [`shopify theme language-server`](#shopify-theme-language-server) * [`shopify theme list`](#shopify-theme-list) +* [`shopify theme metafields pull`](#shopify-theme-metafields-pull) * [`shopify theme open`](#shopify-theme-open) * [`shopify theme package`](#shopify-theme-package) * [`shopify theme publish`](#shopify-theme-publish) @@ -86,14 +87,15 @@ Build the app, including extensions. ``` USAGE - $ shopify app build [--client-id | -c ] [--no-color] [--path ] + $ shopify app build [--client-id | -c ] [--no-color] [--path ] [--reset | ] [--skip-dependencies-installation] [--verbose] FLAGS -c, --config= The name of the app configuration. - --client-id= Application's Client ID that will be exposed at build time. + --client-id= The Client ID of your app. --no-color Disable color output. --path= The path to your app directory. + --reset Reset all your settings. --skip-dependencies-installation Skips the installation of dependencies. Deprecated, use workspaces instead. --verbose Increase the verbosity of the output. @@ -115,13 +117,14 @@ Fetch your app configuration from the Partner Dashboard. ``` USAGE - $ shopify app config link [--client-id ] [-c ] [--no-color] [--path ] [--verbose] + $ shopify app config link [--client-id | -c ] [--no-color] [--path ] [--reset | ] [--verbose] FLAGS -c, --config= The name of the app configuration. --client-id= The Client ID of your app. --no-color Disable color output. --path= The path to your app directory. + --reset Reset all your settings. --verbose Increase the verbosity of the output. DESCRIPTION @@ -140,16 +143,17 @@ Activate an app configuration. ``` USAGE - $ shopify app config use [CONFIG] [--no-color] [--path ] [--reset] [--verbose] + $ shopify app config use [CONFIG] [--client-id | ] [--no-color] [--path ] [--reset | ] [--verbose] ARGUMENTS CONFIG The name of the app configuration. Can be 'shopify.app.staging.toml' or simply 'staging'. FLAGS - --no-color Disable color output. - --path= The path to your app directory. - --reset Reset current configuration. - --verbose Increase the verbosity of the output. + --client-id= The Client ID of your app. + --no-color Disable color output. + --path= The path to your app directory. + --reset Reset all your settings. + --verbose Increase the verbosity of the output. DESCRIPTION Activate an app configuration. @@ -275,14 +279,17 @@ Pull app and extensions environment variables. ``` USAGE - $ shopify app env pull [-c ] [--env-file ] [--no-color] [--path ] [--verbose] + $ shopify app env pull [--client-id | -c ] [--env-file ] [--no-color] [--path ] + [--reset | ] [--verbose] FLAGS - -c, --config= The name of the app configuration. - --env-file= Specify an environment file to update if the update flag is set - --no-color Disable color output. - --path= The path to your app directory. - --verbose Increase the verbosity of the output. + -c, --config= The name of the app configuration. + --client-id= The Client ID of your app. + --env-file= Specify an environment file to update if the update flag is set + --no-color Disable color output. + --path= The path to your app directory. + --reset Reset all your settings. + --verbose Increase the verbosity of the output. DESCRIPTION Pull app and extensions environment variables. @@ -299,13 +306,15 @@ Display app and extensions environment variables. ``` USAGE - $ shopify app env show [-c ] [--no-color] [--path ] [--verbose] + $ shopify app env show [--client-id | -c ] [--no-color] [--path ] [--reset | ] [--verbose] FLAGS - -c, --config= The name of the app configuration. - --no-color Disable color output. - --path= The path to your app directory. - --verbose Increase the verbosity of the output. + -c, --config= The name of the app configuration. + --client-id= The Client ID of your app. + --no-color Disable color output. + --path= The path to your app directory. + --reset Reset all your settings. + --verbose Increase the verbosity of the output. DESCRIPTION Display app and extensions environment variables. @@ -319,13 +328,15 @@ Compile a function to wasm. ``` USAGE - $ shopify app function build [-c ] [--no-color] [--path ] [--verbose] + $ shopify app function build [--client-id | -c ] [--no-color] [--path ] [--reset | ] [--verbose] FLAGS - -c, --config= The name of the app configuration. - --no-color Disable color output. - --path= The path to your function directory. - --verbose Increase the verbosity of the output. + -c, --config= The name of the app configuration. + --client-id= The Client ID of your app. + --no-color Disable color output. + --path= The path to your function directory. + --reset Reset all your settings. + --verbose Increase the verbosity of the output. DESCRIPTION Compile a function to wasm. @@ -340,17 +351,18 @@ Replays a function run from an app log. ``` USAGE $ shopify app function replay [--client-id | -c ] [-j] [-l ] [--no-color] [--path ] - [--verbose] [-w] + [--reset | ] [--verbose] [-w] FLAGS -c, --config= The name of the app configuration. - -j, --json Output the function run result as a JSON object. + -j, --json Output the result as JSON. -l, --log= Specifies a log identifier to replay instead of selecting from a list. The identifier is provided in the output of `shopify app dev` and is the suffix of the log file name. -w, --[no-]watch Re-run the function when the source code changes. - --client-id= Application's Client ID + --client-id= The Client ID of your app. --no-color Disable color output. --path= The path to your function directory. + --reset Reset all your settings. --verbose Increase the verbosity of the output. DESCRIPTION @@ -367,16 +379,19 @@ Run a function locally for testing. ``` USAGE - $ shopify app function run [-c ] [-e ] [-i ] [-j] [--no-color] [--path ] [--verbose] + $ shopify app function run [--client-id | -c ] [-e ] [-i ] [-j] [--no-color] [--path + ] [--reset | ] [--verbose] FLAGS - -c, --config= The name of the app configuration. - -e, --export= Name of the WebAssembly export to invoke. - -i, --input= The input JSON to pass to the function. If omitted, standard input is used. - -j, --json Log the run result as a JSON object. - --no-color Disable color output. - --path= The path to your function directory. - --verbose Increase the verbosity of the output. + -c, --config= The name of the app configuration. + -e, --export= Name of the WebAssembly export to invoke. + -i, --input= The input JSON to pass to the function. If omitted, standard input is used. + -j, --json Output the result as JSON. + --client-id= The Client ID of your app. + --no-color Disable color output. + --path= The path to your function directory. + --reset Reset all your settings. + --verbose Increase the verbosity of the output. DESCRIPTION Run a function locally for testing. @@ -392,13 +407,15 @@ Fetch the latest GraphQL schema for a function. ``` USAGE - $ shopify app function schema [--client-id | -c ] [--no-color] [--path ] [--stdout] [--verbose] + $ shopify app function schema [--client-id | -c ] [--no-color] [--path ] [--reset | ] [--stdout] + [--verbose] FLAGS -c, --config= The name of the app configuration. - --client-id= The Client ID to fetch the schema with. + --client-id= The Client ID of your app. --no-color Disable color output. --path= The path to your function directory. + --reset Reset all your settings. --stdout Output the schema to stdout instead of writing to a file. --verbose Increase the verbosity of the output. @@ -418,13 +435,16 @@ Generate GraphQL types for a JavaScript function. ``` USAGE - $ shopify app function typegen [-c ] [--no-color] [--path ] [--verbose] + $ shopify app function typegen [--client-id | -c ] [--no-color] [--path ] [--reset | ] + [--verbose] FLAGS - -c, --config= The name of the app configuration. - --no-color Disable color output. - --path= The path to your function directory. - --verbose Increase the verbosity of the output. + -c, --config= The name of the app configuration. + --client-id= The Client ID of your app. + --no-color Disable color output. + --path= The path to your function directory. + --reset Reset all your settings. + --verbose Increase the verbosity of the output. DESCRIPTION Generate GraphQL types for a JavaScript function. @@ -477,13 +497,15 @@ Import dashboard-managed extensions into your app. ``` USAGE - $ shopify app import-extensions [--client-id | -c ] [--no-color] [--path ] [--verbose] + $ shopify app import-extensions [--client-id | -c ] [--no-color] [--path ] [--reset | ] + [--verbose] FLAGS -c, --config= The name of the app configuration. --client-id= The Client ID of your app. --no-color Disable color output. --path= The path to your app directory. + --reset Reset all your settings. --verbose Increase the verbosity of the output. DESCRIPTION @@ -496,15 +518,18 @@ Print basic information about your app and extensions. ``` USAGE - $ shopify app info [-c ] [--json] [--no-color] [--path ] [--verbose] [--web-env] + $ shopify app info [--client-id | -c ] [-j] [--no-color] [--path ] [--reset | ] + [--verbose] [--web-env] FLAGS - -c, --config= The name of the app configuration. - --json format output as JSON - --no-color Disable color output. - --path= The path to your app directory. - --verbose Increase the verbosity of the output. - --web-env Outputs environment variables necessary for running and deploying web/. + -c, --config= The name of the app configuration. + -j, --json Output the result as JSON. + --client-id= The Client ID of your app. + --no-color Disable color output. + --path= The path to your app directory. + --reset Reset all your settings. + --verbose Increase the verbosity of the output. + --web-env Outputs environment variables necessary for running and deploying web/. DESCRIPTION Print basic information about your app and extensions. @@ -554,7 +579,7 @@ USAGE FLAGS -c, --config= The name of the app configuration. - -j, --json Log the run result as a JSON object. + -j, --json Output the result as JSON. -s, --store=... Store URL. Must be an existing development or Shopify Plus sandbox store. --client-id= The Client ID of your app. --no-color Disable color output. @@ -584,13 +609,15 @@ Print out a list of sources that may be used with the logs command. ``` USAGE - $ shopify app logs sources [-c ] [--no-color] [--path ] [--verbose] + $ shopify app logs sources [--client-id | -c ] [--no-color] [--path ] [--reset | ] [--verbose] FLAGS - -c, --config= The name of the app configuration. - --no-color Disable color output. - --path= The path to your app directory. - --verbose Increase the verbosity of the output. + -c, --config= The name of the app configuration. + --client-id= The Client ID of your app. + --no-color Disable color output. + --path= The path to your app directory. + --reset Reset all your settings. + --verbose Increase the verbosity of the output. DESCRIPTION Print out a list of sources that may be used with the logs command. @@ -629,15 +656,16 @@ List deployed versions of your app. ``` USAGE - $ shopify app versions list [FILE] [--client-id | -c ] [--json] [--no-color] [--path ] + $ shopify app versions list [FILE] [--client-id | -c ] [-j] [--no-color] [--path ] [--reset | ] [--verbose] FLAGS -c, --config= The name of the app configuration. - --client-id= The Client ID to fetch versions for. - --json Output the versions list as JSON. + -j, --json Output the result as JSON. + --client-id= The Client ID of your app. --no-color Disable color output. --path= The path to your app directory. + --reset Reset all your settings. --verbose Increase the verbosity of the output. DESCRIPTION @@ -656,8 +684,8 @@ Trigger delivery of a sample webhook topic payload to a designated address. ``` USAGE $ shopify app webhook trigger [--address ] [--api-version ] [--client-id | -c ] - [--client-secret ] [--delivery-method http|google-pub-sub|event-bridge] [--help] [--path ] - [--shared-secret ] [--topic ] + [--client-secret ] [--delivery-method http|google-pub-sub|event-bridge] [--help] [--path ] [--reset | + ] [--shared-secret ] [--topic ] FLAGS -c, --config= @@ -692,6 +720,9 @@ FLAGS --path= The path to your app directory. + --reset + Reset all your settings. + --shared-secret= Deprecated. Please use client-secret. @@ -1871,16 +1902,16 @@ Displays information about your theme environment, including your current store. ``` USAGE - $ shopify theme info [-d] [-e ] [--json] [--no-color] [--password ] [-s ] [-t ] + $ shopify theme info [-d] [-e ] [-j] [--no-color] [--password ] [-s ] [-t ] [--verbose] FLAGS -d, --development Retrieve info from your development theme. -e, --environment= The environment to apply to the current command. + -j, --json Output the result as JSON. -s, --store= Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com). -t, --theme= Theme ID or name of the remote theme. - --json Output the theme info as JSON. --no-color Disable color output. --password= Password generated from the Theme Access app. --verbose Increase the verbosity of the output. @@ -1948,15 +1979,15 @@ Lists the themes in your store, along with their IDs and statuses. ``` USAGE - $ shopify theme list [-e ] [--id ] [--json] [--name ] [--no-color] [--password ] + $ shopify theme list [-e ] [--id ] [-j] [--name ] [--no-color] [--password ] [--role live|unpublished|development] [-s ] [--verbose] FLAGS -e, --environment= The environment to apply to the current command. + -j, --json Output the result as JSON. -s, --store= Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com). --id= Only list theme with the given ID. - --json Output the theme list as JSON. --name= Only list themes that contain the given name. --no-color Disable color output. --password= Password generated from the Theme Access app. @@ -1968,6 +1999,32 @@ DESCRIPTION Lists the themes in your store, along with their IDs and statuses. ``` +## `shopify theme metafields pull` + +Download metafields definitions from your shop into a local file. + +``` +USAGE + $ shopify theme metafields pull [-e ] [--no-color] [--password ] [--path ] [-s ] + [--verbose] + +FLAGS + -e, --environment= The environment to apply to the current command. + -s, --store= Store URL. It can be the store prefix (example) or the full myshopify.com URL + (example.myshopify.com, https://example.myshopify.com). + --no-color Disable color output. + --password= Password generated from the Theme Access app. + --path= The path to your theme directory. + --verbose Increase the verbosity of the output. + +DESCRIPTION + Download metafields definitions from your shop into a local file. + + Retrieves metafields from Shopify Admin. + + If the metafields file already exists, it will be overwritten. +``` + ## `shopify theme open` Opens the preview of your remote theme. @@ -2106,7 +2163,7 @@ FLAGS -a, --allow-live Allow push to a live theme. -d, --development Push theme files from your remote development theme. -e, --environment= The environment to apply to the current command. - -j, --json Output JSON instead of a UI. + -j, --json Output the result as JSON. -l, --live Push theme files from your remote live theme. -n, --nodelete Prevent deleting remote files that don't exist locally. -o, --only=... Download only the specified files (Multiple flags allowed). @@ -2119,6 +2176,7 @@ FLAGS --no-color Disable color output. --password= Password generated from the Theme Access app. --path= The path to your theme directory. + --strict Require theme check to pass without errors before pushing. Warnings are allowed. --verbose Increase the verbosity of the output. DESCRIPTION diff --git a/packages/cli/oclif.manifest.json b/packages/cli/oclif.manifest.json index f0485425515..78bfbc0e701 100644 --- a/packages/cli/oclif.manifest.json +++ b/packages/cli/oclif.manifest.json @@ -22,7 +22,7 @@ "type": "option" }, "client-id": { - "description": "Application's Client ID that will be exposed at build time.", + "description": "The Client ID of your app.", "env": "SHOPIFY_FLAG_CLIENT_ID", "exclusive": [ "config" @@ -60,6 +60,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "skip-dependencies-installation": { "allowNo": false, "description": "Skips the installation of dependencies. Deprecated, use workspaces instead.", @@ -99,6 +110,9 @@ "client-id": { "description": "The Client ID of your app.", "env": "SHOPIFY_FLAG_CLIENT_ID", + "exclusive": [ + "config" + ], "hasDynamicHelp": false, "hidden": false, "multiple": false, @@ -132,6 +146,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "verbose": { "allowNo": false, "description": "Increase the verbosity of the output.", @@ -164,6 +189,18 @@ "description": "Sets default configuration when you run app-related CLI commands. If you omit the `config-name` parameter, then you'll be prompted to choose from the configuration files in your project.", "descriptionWithMarkdown": "Sets default configuration when you run app-related CLI commands. If you omit the `config-name` parameter, then you'll be prompted to choose from the configuration files in your project.", "flags": { + "client-id": { + "description": "The Client ID of your app.", + "env": "SHOPIFY_FLAG_CLIENT_ID", + "exclusive": [ + "config" + ], + "hasDynamicHelp": false, + "hidden": false, + "multiple": false, + "name": "client-id", + "type": "option" + }, "no-color": { "allowNo": false, "description": "Disable color output.", @@ -183,8 +220,11 @@ }, "reset": { "allowNo": false, - "description": "Reset current configuration.", + "description": "Reset all your settings.", "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], "hidden": false, "name": "reset", "type": "boolean" @@ -555,6 +595,18 @@ "description": "Creates or updates an `.env` files that contains app and app extension environment variables.\n\n When an existing `.env` file is updated, changes to the variables are displayed in the terminal output. Existing variables and commented variables are preserved.", "descriptionWithMarkdown": "Creates or updates an `.env` files that contains app and app extension environment variables.\n\n When an existing `.env` file is updated, changes to the variables are displayed in the terminal output. Existing variables and commented variables are preserved.", "flags": { + "client-id": { + "description": "The Client ID of your app.", + "env": "SHOPIFY_FLAG_CLIENT_ID", + "exclusive": [ + "config" + ], + "hasDynamicHelp": false, + "hidden": false, + "multiple": false, + "name": "client-id", + "type": "option" + }, "config": { "char": "c", "description": "The name of the app configuration.", @@ -591,6 +643,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "verbose": { "allowNo": false, "description": "Increase the verbosity of the output.", @@ -619,6 +682,18 @@ "description": "Displays environment variables that can be used to deploy apps and app extensions.", "descriptionWithMarkdown": "Displays environment variables that can be used to deploy apps and app extensions.", "flags": { + "client-id": { + "description": "The Client ID of your app.", + "env": "SHOPIFY_FLAG_CLIENT_ID", + "exclusive": [ + "config" + ], + "hasDynamicHelp": false, + "hidden": false, + "multiple": false, + "name": "client-id", + "type": "option" + }, "config": { "char": "c", "description": "The name of the app configuration.", @@ -646,6 +721,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "verbose": { "allowNo": false, "description": "Increase the verbosity of the output.", @@ -674,6 +760,18 @@ "description": "Compiles the function in your current directory to WebAssembly (Wasm) for testing purposes.", "descriptionWithMarkdown": "Compiles the function in your current directory to WebAssembly (Wasm) for testing purposes.", "flags": { + "client-id": { + "description": "The Client ID of your app.", + "env": "SHOPIFY_FLAG_CLIENT_ID", + "exclusive": [ + "config" + ], + "hasDynamicHelp": false, + "hidden": false, + "multiple": false, + "name": "client-id", + "type": "option" + }, "config": { "char": "c", "description": "The name of the app configuration.", @@ -702,6 +800,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "verbose": { "allowNo": false, "description": "Increase the verbosity of the output.", @@ -743,7 +852,7 @@ "type": "option" }, "client-id": { - "description": "Application's Client ID", + "description": "The Client ID of your app.", "env": "SHOPIFY_FLAG_CLIENT_ID", "exclusive": [ "config" @@ -767,7 +876,7 @@ "json": { "allowNo": false, "char": "j", - "description": "Output the function run result as a JSON object.", + "description": "Output the result as JSON.", "env": "SHOPIFY_FLAG_JSON", "hidden": false, "name": "json", @@ -800,6 +909,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "verbose": { "allowNo": false, "description": "Increase the verbosity of the output.", @@ -837,6 +957,18 @@ "description": "Runs the function from your current directory for \"testing purposes\" (https://shopify.dev/docs/apps/functions/testing-and-debugging). To learn how you can monitor and debug functions when errors occur, refer to \"Shopify Functions error handling\" (https://shopify.dev/docs/api/functions/errors).", "descriptionWithMarkdown": "Runs the function from your current directory for [testing purposes](https://shopify.dev/docs/apps/functions/testing-and-debugging). To learn how you can monitor and debug functions when errors occur, refer to [Shopify Functions error handling](https://shopify.dev/docs/api/functions/errors).", "flags": { + "client-id": { + "description": "The Client ID of your app.", + "env": "SHOPIFY_FLAG_CLIENT_ID", + "exclusive": [ + "config" + ], + "hasDynamicHelp": false, + "hidden": false, + "multiple": false, + "name": "client-id", + "type": "option" + }, "config": { "char": "c", "description": "The name of the app configuration.", @@ -869,7 +1001,7 @@ "json": { "allowNo": false, "char": "j", - "description": "Log the run result as a JSON object.", + "description": "Output the result as JSON.", "env": "SHOPIFY_FLAG_JSON", "hidden": false, "name": "json", @@ -893,6 +1025,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "verbose": { "allowNo": false, "description": "Increase the verbosity of the output.", @@ -934,7 +1077,7 @@ "type": "option" }, "client-id": { - "description": "The Client ID to fetch the schema with.", + "description": "The Client ID of your app.", "env": "SHOPIFY_FLAG_CLIENT_ID", "exclusive": [ "config" @@ -973,6 +1116,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "stdout": { "allowNo": false, "description": "Output the schema to stdout instead of writing to a file.", @@ -1009,6 +1163,18 @@ "description": "Creates GraphQL types based on your \"input query\" (https://shopify.dev/docs/apps/functions/input-output#input) for a function written in JavaScript.", "descriptionWithMarkdown": "Creates GraphQL types based on your [input query](https://shopify.dev/docs/apps/functions/input-output#input) for a function written in JavaScript.", "flags": { + "client-id": { + "description": "The Client ID of your app.", + "env": "SHOPIFY_FLAG_CLIENT_ID", + "exclusive": [ + "config" + ], + "hasDynamicHelp": false, + "hidden": false, + "multiple": false, + "name": "client-id", + "type": "option" + }, "config": { "char": "c", "description": "The name of the app configuration.", @@ -1037,6 +1203,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "verbose": { "allowNo": false, "description": "Increase the verbosity of the output.", @@ -1231,7 +1408,7 @@ "type": "option" }, "client-id": { - "description": "The Client ID to fetch the schema with.", + "description": "The Client ID of your app.", "env": "SHOPIFY_FLAG_CLIENT_ID", "exclusive": [ "config" @@ -1270,6 +1447,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "stdout": { "allowNo": false, "description": "Output the schema to stdout instead of writing to a file.", @@ -1344,6 +1532,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "verbose": { "allowNo": false, "description": "Increase the verbosity of the output.", @@ -1371,6 +1570,18 @@ "description": "The information returned includes the following:\n\n - The app and development store or Plus sandbox store that's used when you run the \"dev\" (https://shopify.dev/docs/api/shopify-cli/app/app-dev) command. You can reset these configurations using \"`dev --reset`\" (https://shopify.dev/docs/api/shopify-cli/app/app-dev#flags-propertydetail-reset).\n - The \"structure\" (https://shopify.dev/docs/apps/tools/cli/structure) of your app project.\n - The \"access scopes\" (https://shopify.dev/docs/api/usage) your app has requested.\n - System information, including the package manager and version of Shopify CLI used in the project.", "descriptionWithMarkdown": "The information returned includes the following:\n\n - The app and development store or Plus sandbox store that's used when you run the [dev](https://shopify.dev/docs/api/shopify-cli/app/app-dev) command. You can reset these configurations using [`dev --reset`](https://shopify.dev/docs/api/shopify-cli/app/app-dev#flags-propertydetail-reset).\n - The [structure](https://shopify.dev/docs/apps/tools/cli/structure) of your app project.\n - The [access scopes](https://shopify.dev/docs/api/usage) your app has requested.\n - System information, including the package manager and version of Shopify CLI used in the project.", "flags": { + "client-id": { + "description": "The Client ID of your app.", + "env": "SHOPIFY_FLAG_CLIENT_ID", + "exclusive": [ + "config" + ], + "hasDynamicHelp": false, + "hidden": false, + "multiple": false, + "name": "client-id", + "type": "option" + }, "config": { "char": "c", "description": "The name of the app configuration.", @@ -1383,7 +1594,8 @@ }, "json": { "allowNo": false, - "description": "format output as JSON", + "char": "j", + "description": "Output the result as JSON.", "env": "SHOPIFY_FLAG_JSON", "hidden": false, "name": "json", @@ -1406,6 +1618,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "verbose": { "allowNo": false, "description": "Increase the verbosity of the output.", @@ -1583,8 +1806,9 @@ "json": { "allowNo": false, "char": "j", - "description": "Log the run result as a JSON object.", + "description": "Output the result as JSON.", "env": "SHOPIFY_FLAG_JSON", + "hidden": false, "name": "json", "type": "boolean" }, @@ -1673,6 +1897,18 @@ "description": "The output source names can be used with the `--source` argument of `shopify app logs` to filter log output. Currently only function extensions are supported as sources.", "descriptionWithMarkdown": "The output source names can be used with the `--source` argument of `shopify app logs` to filter log output. Currently only function extensions are supported as sources.", "flags": { + "client-id": { + "description": "The Client ID of your app.", + "env": "SHOPIFY_FLAG_CLIENT_ID", + "exclusive": [ + "config" + ], + "hasDynamicHelp": false, + "hidden": false, + "multiple": false, + "name": "client-id", + "type": "option" + }, "config": { "char": "c", "description": "The name of the app configuration.", @@ -1700,6 +1936,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "verbose": { "allowNo": false, "description": "Increase the verbosity of the output.", @@ -1792,6 +2039,9 @@ "allowNo": false, "description": "Reset all your settings.", "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], "hidden": false, "name": "reset", "type": "boolean" @@ -1854,7 +2104,7 @@ "type": "option" }, "client-id": { - "description": "The Client ID to fetch versions for.", + "description": "The Client ID of your app.", "env": "SHOPIFY_FLAG_CLIENT_ID", "exclusive": [ "config" @@ -1877,8 +2127,10 @@ }, "json": { "allowNo": false, - "description": "Output the versions list as JSON.", + "char": "j", + "description": "Output the result as JSON.", "env": "SHOPIFY_FLAG_JSON", + "hidden": false, "name": "json", "type": "boolean" }, @@ -1899,6 +2151,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "verbose": { "allowNo": false, "description": "Increase the verbosity of the output.", @@ -2012,6 +2275,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "shared-secret": { "description": "Deprecated. Please use client-secret.", "env": "SHOPIFY_FLAG_SHARED_SECRET", @@ -2304,6 +2578,18 @@ }, "customPluginName": "@shopify/app", "flags": { + "client-id": { + "description": "The Client ID of your app.", + "env": "SHOPIFY_FLAG_CLIENT_ID", + "exclusive": [ + "config" + ], + "hasDynamicHelp": false, + "hidden": false, + "multiple": false, + "name": "client-id", + "type": "option" + }, "config": { "char": "c", "description": "The name of the app configuration.", @@ -2331,6 +2617,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "verbose": { "allowNo": false, "description": "Increase the verbosity of the output.", @@ -5047,8 +5344,10 @@ }, "json": { "allowNo": false, - "description": "Output the theme info as JSON.", + "char": "j", + "description": "Output the result as JSON.", "env": "SHOPIFY_FLAG_JSON", + "hidden": false, "name": "json", "type": "boolean" }, @@ -5236,8 +5535,10 @@ }, "json": { "allowNo": false, - "description": "Output the theme list as JSON.", + "char": "j", + "description": "Output the result as JSON.", "env": "SHOPIFY_FLAG_JSON", + "hidden": false, "name": "json", "type": "boolean" }, @@ -5305,6 +5606,86 @@ "pluginType": "core", "strict": true }, + "theme:metafields:pull": { + "aliases": [ + ], + "args": { + }, + "customPluginName": "@shopify/theme", + "description": "Retrieves metafields from Shopify Admin.\n\nIf the metafields file already exists, it will be overwritten.", + "descriptionWithMarkdown": "Retrieves metafields from Shopify Admin.\n\nIf the metafields file already exists, it will be overwritten.", + "flags": { + "environment": { + "char": "e", + "description": "The environment to apply to the current command.", + "env": "SHOPIFY_FLAG_ENVIRONMENT", + "hasDynamicHelp": false, + "multiple": false, + "name": "environment", + "type": "option" + }, + "force": { + "allowNo": false, + "char": "f", + "description": "Proceed without confirmation, if current directory does not seem to be theme directory.", + "env": "SHOPIFY_FLAG_FORCE", + "hidden": true, + "name": "force", + "type": "boolean" + }, + "no-color": { + "allowNo": false, + "description": "Disable color output.", + "env": "SHOPIFY_FLAG_NO_COLOR", + "hidden": false, + "name": "no-color", + "type": "boolean" + }, + "password": { + "description": "Password generated from the Theme Access app.", + "env": "SHOPIFY_CLI_THEME_TOKEN", + "hasDynamicHelp": false, + "multiple": false, + "name": "password", + "type": "option" + }, + "path": { + "description": "The path to your theme directory.", + "env": "SHOPIFY_FLAG_PATH", + "hasDynamicHelp": false, + "multiple": false, + "name": "path", + "noCacheDefault": true, + "type": "option" + }, + "store": { + "char": "s", + "description": "Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).", + "env": "SHOPIFY_FLAG_STORE", + "hasDynamicHelp": false, + "multiple": false, + "name": "store", + "type": "option" + }, + "verbose": { + "allowNo": false, + "description": "Increase the verbosity of the output.", + "env": "SHOPIFY_FLAG_VERBOSE", + "hidden": false, + "name": "verbose", + "type": "boolean" + } + }, + "hasDynamicHelp": false, + "hiddenAliases": [ + ], + "id": "theme:metafields:pull", + "pluginAlias": "@shopify/cli", + "pluginName": "@shopify/cli", + "pluginType": "core", + "strict": true, + "summary": "Download metafields definitions from your shop into a local file." + }, "theme:open": { "aliases": [ ], @@ -5710,8 +6091,9 @@ "json": { "allowNo": false, "char": "j", - "description": "Output JSON instead of a UI.", + "description": "Output the result as JSON.", "env": "SHOPIFY_FLAG_JSON", + "hidden": false, "name": "json", "type": "boolean" }, @@ -5782,6 +6164,13 @@ "name": "store", "type": "option" }, + "strict": { + "allowNo": false, + "description": "Require theme check to pass without errors before pushing. Warnings are allowed.", + "env": "SHOPIFY_FLAG_STRICT_PUSH", + "name": "strict", + "type": "boolean" + }, "theme": { "char": "t", "description": "Theme ID or name of the remote theme.", @@ -6317,6 +6706,17 @@ "noCacheDefault": true, "type": "option" }, + "reset": { + "allowNo": false, + "description": "Reset all your settings.", + "env": "SHOPIFY_FLAG_RESET", + "exclusive": [ + "config" + ], + "hidden": false, + "name": "reset", + "type": "boolean" + }, "shared-secret": { "description": "Deprecated. Please use client-secret.", "env": "SHOPIFY_FLAG_SHARED_SECRET", @@ -6349,5 +6749,5 @@ "summary": "Trigger delivery of a sample webhook topic payload to a designated address." } }, - "version": "3.70.0" + "version": "3.72.0" } \ No newline at end of file diff --git a/packages/cli/package.json b/packages/cli/package.json index eb8e73f6ee3..8cce6f3c2ae 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@shopify/cli", - "version": "3.70.0", + "version": "3.72.0", "private": false, "description": "A CLI tool to build for the Shopify platform", "keywords": [ @@ -102,18 +102,18 @@ }, "dependencies": { "@ast-grep/napi": "0.11.0", - "esbuild": "0.19.8" + "esbuild": "0.24.0" }, "devDependencies": { "@oclif/core": "3.26.5", "@oclif/plugin-commands": "3.3.2", "@oclif/plugin-plugins": "5.1.2", - "@shopify/app": "3.70.0", - "@shopify/cli-kit": "3.70.0", - "@shopify/plugin-cloudflare": "3.70.0", - "@shopify/plugin-did-you-mean": "3.70.0", - "@shopify/theme": "3.70.0", - "@shopify/cli-hydrogen": "9.0.2", + "@shopify/app": "3.72.0", + "@shopify/cli-kit": "3.72.0", + "@shopify/plugin-cloudflare": "3.72.0", + "@shopify/plugin-did-you-mean": "3.72.0", + "@shopify/theme": "3.72.0", + "@shopify/cli-hydrogen": "9.0.3", "@types/node": "18.19.3", "@typescript-eslint/eslint-plugin": "7.13.1", "@vitest/coverage-istanbul": "^1.6.0", diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index d21f65c0290..3d36993ec5e 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -20,7 +20,6 @@ import {commands as PluginCommandsCommands} from '@oclif/plugin-commands' import {commands as PluginPluginsCommands} from '@oclif/plugin-plugins' import {DidYouMeanCommands} from '@shopify/plugin-did-you-mean' import {runCLI} from '@shopify/cli-kit/node/cli' -import {launchCLI} from '@shopify/cli-kit/node/cli-launcher' import {renderFatalError} from '@shopify/cli-kit/node/ui' import {FatalError} from '@shopify/cli-kit/node/error' import fs from 'fs' @@ -67,13 +66,10 @@ interface RunShopifyCLIOptions { } async function runShopifyCLI({development}: RunShopifyCLIOptions) { - await runCLI( - { - moduleURL: import.meta.url, - development, - }, - launchCLI, - ) + await runCLI({ + moduleURL: import.meta.url, + development, + }) } // Hide plugins command diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index a01c6f21fa7..fbf1c6466cd 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,19 @@ # @shopify/create-app +## 3.72.0 + +## 3.71.5 + +## 3.71.4 + +## 3.71.3 + +## 3.71.2 + +## 3.71.1 + +## 3.71.0 + ## 3.70.0 ## 3.69.0 diff --git a/packages/create-app/oclif.manifest.json b/packages/create-app/oclif.manifest.json index eb5ca74a3e8..def529171b3 100644 --- a/packages/create-app/oclif.manifest.json +++ b/packages/create-app/oclif.manifest.json @@ -104,5 +104,5 @@ "summary": "Create a new app project" } }, - "version": "3.70.0" + "version": "3.72.0" } \ No newline at end of file diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 846c9d14032..135113b619a 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,6 +1,6 @@ { "name": "@shopify/create-app", - "version": "3.70.0", + "version": "3.72.0", "private": false, "description": "A CLI tool to create a new Shopify app.", "keywords": [ @@ -55,11 +55,11 @@ ] }, "dependencies": { - "esbuild": "0.19.8" + "esbuild": "0.24.0" }, "devDependencies": { - "@shopify/cli-kit": "3.70.0", - "@shopify/app": "3.70.0", + "@shopify/cli-kit": "3.72.0", + "@shopify/app": "3.72.0", "@types/node": "18.19.3", "esbuild-plugin-copy": "^2.1.1", "@vitest/coverage-istanbul": "^1.6.0" diff --git a/packages/create-app/src/index.ts b/packages/create-app/src/index.ts index 20478c3ccfe..b3bdbcce8a0 100644 --- a/packages/create-app/src/index.ts +++ b/packages/create-app/src/index.ts @@ -1,15 +1,11 @@ import {commands} from '@shopify/app' import {runCreateCLI} from '@shopify/cli-kit/node/cli' -import {launchCLI} from '@shopify/cli-kit/node/cli-launcher' async function runCreateAppCLI(development: boolean) { - await runCreateCLI( - { - moduleURL: import.meta.url, - development, - }, - launchCLI, - ) + await runCreateCLI({ + moduleURL: import.meta.url, + development, + }) } export const COMMANDS: unknown = { diff --git a/packages/eslint-plugin-cli/rules/no-inline-graphql.js b/packages/eslint-plugin-cli/rules/no-inline-graphql.js index 0c3e5991a33..9287a1ca65d 100644 --- a/packages/eslint-plugin-cli/rules/no-inline-graphql.js +++ b/packages/eslint-plugin-cli/rules/no-inline-graphql.js @@ -152,10 +152,10 @@ const knownFailures = { '867f01113c20386d6a438dd56a6d241199e407eab928ab1ad9a7f233cd35c1be', 'packages/app/src/cli/api/graphql/find_store_by_domain.ts': '0824f5baaab1ad419a7fa1d64824e306bd369430da47c7457ed72e74a1e94a9a', - 'packages/app/src/cli/api/graphql/functions/api_schema_definition.ts': - '9ebbab831a66a2e49a8c2dac3185bb58c4688655040c6d14a9b2fb41a004bca8', + 'packages/app/src/cli/api/graphql/functions/api_schema_definition.ts': + 'e71100cf61919831681da1be8f12cd9067c4e3f2faf04c1b88b764fd8a275b82', 'packages/app/src/cli/api/graphql/functions/target_schema_definition.ts': - '0469c1fe724568f031a52c5bda54d56d8c3b23d7e8a54a86a684f72028d71b46', + 'd338c5d187ca8a1e1e68892987d780e540426faeba89df2dd9d8c96e193f5c13', 'packages/app/src/cli/api/graphql/generate_signed_upload_url.ts': '848e40bf6b44331de0fe1dc1b0753593c1d47f9705ebe988a1b8ad5638d267ef', 'packages/app/src/cli/api/graphql/get_variant_id.ts': diff --git a/packages/plugin-cloudflare/CHANGELOG.md b/packages/plugin-cloudflare/CHANGELOG.md index b08221a90cc..c37f469613c 100644 --- a/packages/plugin-cloudflare/CHANGELOG.md +++ b/packages/plugin-cloudflare/CHANGELOG.md @@ -1,5 +1,52 @@ # @shopify/plugin-cloudflare +## 3.72.0 + +### Patch Changes + +- @shopify/cli-kit@3.72.0 + +## 3.71.5 + +### Patch Changes + +- Updated dependencies [94a7d4ce4f] + - @shopify/cli-kit@3.71.5 + +## 3.71.4 + +### Patch Changes + +- Updated dependencies [94953a671e] + - @shopify/cli-kit@3.71.4 + +## 3.71.3 + +### Patch Changes + +- @shopify/cli-kit@3.71.3 + +## 3.71.2 + +### Patch Changes + +- Updated dependencies [a395820e7b] + - @shopify/cli-kit@3.71.2 + +## 3.71.1 + +### Patch Changes + +- @shopify/cli-kit@3.71.1 + +## 3.71.0 + +### Patch Changes + +- Updated dependencies [5fd19d2920] +- Updated dependencies [5531731c11] + - @shopify/cli-kit@3.71.0 + ## 3.70.0 ### Patch Changes diff --git a/packages/plugin-cloudflare/package.json b/packages/plugin-cloudflare/package.json index c950078656e..2084f66581b 100644 --- a/packages/plugin-cloudflare/package.json +++ b/packages/plugin-cloudflare/package.json @@ -1,6 +1,6 @@ { "name": "@shopify/plugin-cloudflare", - "version": "3.70.0", + "version": "3.72.0", "description": "Enables the creation of Cloudflare tunnels from `shopify app dev`, allowing previews from any device", "keywords": [ "shopify", @@ -47,7 +47,7 @@ }, "dependencies": { "@oclif/core": "3.26.5", - "@shopify/cli-kit": "3.70.0" + "@shopify/cli-kit": "3.72.0" }, "devDependencies": { "@vitest/coverage-istanbul": "^1.6.0" diff --git a/packages/plugin-did-you-mean/CHANGELOG.md b/packages/plugin-did-you-mean/CHANGELOG.md index b2e1db1ac8e..ed749c59352 100644 --- a/packages/plugin-did-you-mean/CHANGELOG.md +++ b/packages/plugin-did-you-mean/CHANGELOG.md @@ -1,5 +1,52 @@ # @shopify/plugin-did-you-mean +## 3.72.0 + +### Patch Changes + +- @shopify/cli-kit@3.72.0 + +## 3.71.5 + +### Patch Changes + +- Updated dependencies [94a7d4ce4f] + - @shopify/cli-kit@3.71.5 + +## 3.71.4 + +### Patch Changes + +- Updated dependencies [94953a671e] + - @shopify/cli-kit@3.71.4 + +## 3.71.3 + +### Patch Changes + +- @shopify/cli-kit@3.71.3 + +## 3.71.2 + +### Patch Changes + +- Updated dependencies [a395820e7b] + - @shopify/cli-kit@3.71.2 + +## 3.71.1 + +### Patch Changes + +- @shopify/cli-kit@3.71.1 + +## 3.71.0 + +### Patch Changes + +- Updated dependencies [5fd19d2920] +- Updated dependencies [5531731c11] + - @shopify/cli-kit@3.71.0 + ## 3.70.0 ### Patch Changes diff --git a/packages/plugin-did-you-mean/package.json b/packages/plugin-did-you-mean/package.json index 81442f95953..157c0e85541 100644 --- a/packages/plugin-did-you-mean/package.json +++ b/packages/plugin-did-you-mean/package.json @@ -1,6 +1,6 @@ { "name": "@shopify/plugin-did-you-mean", - "version": "3.70.0", + "version": "3.72.0", "private": true, "bugs": { "url": "https://github.com/Shopify/cli/issues" @@ -42,7 +42,7 @@ }, "dependencies": { "@oclif/core": "3.26.5", - "@shopify/cli-kit": "3.70.0", + "@shopify/cli-kit": "3.72.0", "n-gram": "2.0.2" }, "devDependencies": { diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md index 08871aef448..f996d9868f2 100644 --- a/packages/theme/CHANGELOG.md +++ b/packages/theme/CHANGELOG.md @@ -1,5 +1,62 @@ # @shopify/theme +## 3.72.0 + +### Patch Changes + +- @shopify/cli-kit@3.72.0 + +## 3.71.5 + +### Patch Changes + +- Updated dependencies [94a7d4ce4f] + - @shopify/cli-kit@3.71.5 + +## 3.71.4 + +### Patch Changes + +- Updated dependencies [94953a671e] + - @shopify/cli-kit@3.71.4 + +## 3.71.3 + +### Patch Changes + +- @shopify/cli-kit@3.71.3 + +## 3.71.2 + +### Patch Changes + +- Updated dependencies [a395820e7b] + - @shopify/cli-kit@3.71.2 + +## 3.71.1 + +### Patch Changes + +- @shopify/cli-kit@3.71.1 + +## 3.71.0 + +### Minor Changes + +- 5107f4e805: Add `--strict` flag to `theme push` command, which will report `theme check` warnings and abort the operation if there are errors. +- 057e2c6189: Add shortcut keys to theme dev commands + +### Patch Changes + +- ff994c34d3: Fix password validation to support localized URLs when authenticating storefronts. +- 1e267a2e04: Update `shopify theme dev` to no longer display redundant URLs +- 7017b9e31c: Improve storefront password detection for password-protected shops with redirects +- 9548a34471: Fix password validation to handle capitalized store names on `shopify theme dev` +- 33f713e06e: Bump @shopify/theme-check-node & @shopify/theme-language-server +- Updated dependencies [5fd19d2920] +- Updated dependencies [5531731c11] + - @shopify/cli-kit@3.71.0 + ## 3.70.0 ### Minor Changes diff --git a/packages/theme/package.json b/packages/theme/package.json index 184502fb3f3..d65d291355c 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,6 +1,6 @@ { "name": "@shopify/theme", - "version": "3.70.0", + "version": "3.72.0", "private": true, "description": "Utilities for building and publishing themes", "homepage": "https://github.com/shopify/cli#readme", @@ -42,9 +42,9 @@ }, "dependencies": { "@oclif/core": "3.26.5", - "@shopify/cli-kit": "3.70.0", - "@shopify/theme-check-node": "2.9.2", - "@shopify/theme-language-server-node": "1.14.0", + "@shopify/cli-kit": "3.72.0", + "@shopify/theme-check-node": "3.4.0", + "@shopify/theme-language-server-node": "2.3.2", "chokidar": "3.5.3", "h3": "1.12.0", "yaml": "2.3.2" diff --git a/packages/theme/src/cli/commands/theme/check.test.ts b/packages/theme/src/cli/commands/theme/check.test.ts index 7a0e1069b96..071158ea1d4 100644 --- a/packages/theme/src/cli/commands/theme/check.test.ts +++ b/packages/theme/src/cli/commands/theme/check.test.ts @@ -35,7 +35,7 @@ describe('Check', () => { context: 'theme', settings: {}, checks: [], - root: '', + rootUri: '', } const mockOffenses: Offense[] = [] @@ -53,7 +53,7 @@ describe('Check', () => { context: 'app', settings: {}, checks: [], - root: '', + rootUri: '', } const mockOffenses: Offense[] = [] @@ -72,7 +72,7 @@ describe('Check', () => { context: 'theme', settings: {}, checks: [], - root: '', + rootUri: '', } const mockOffenses: Offense[] = [] diff --git a/packages/theme/src/cli/commands/theme/check.ts b/packages/theme/src/cli/commands/theme/check.ts index 32cbd5c30a2..e8eb94793db 100644 --- a/packages/theme/src/cli/commands/theme/check.ts +++ b/packages/theme/src/cli/commands/theme/check.ts @@ -111,7 +111,7 @@ export default class Check extends ThemeCommand { let version = 'unknown' if (pkgJsonPath) { - version = (await getPackageVersion(pkgJsonPath)) || 'unknown' + version = (await getPackageVersion(pkgJsonPath)) ?? 'unknown' } outputInfo(version) @@ -134,52 +134,58 @@ export default class Check extends ThemeCommand { return } - const {offenses, theme} = await themeCheckRun(path, config, (message) => { - // We should replace this with outputDebug when it logs to STDERR by default. - // We need this right now because the --verbose flags pollutes STDOUT - // when used with --output=json with the current outputDebug defaults. - if (process.env.SHOPIFY_TMP_FLAG_DEBUG) { - consoleError(message) - } - }) - - const offensesByFile = sortOffenses(offenses) + const {offenses, theme} = await runThemeCheck(path, flags.output, config) - if (flags.output === 'text') { - renderOffensesText(offensesByFile, path) + if (flags['auto-correct']) { + await performAutoFixes(theme, offenses) + } - // Use renderSuccess when theres no offenses - const render = offenses.length ? renderInfo : renderSuccess + return handleExit(offenses, flags['fail-level'] as FailLevel) + } +} - render({ - headline: 'Theme Check Summary.', - body: formatSummary(offenses, offensesByFile, theme), - }) +export async function runThemeCheck(path: string, outputFormat: string, config?: string) { + const {offenses, theme} = await themeCheckRun(path, config, (message) => { + // We should replace this with outputDebug when it logs to STDERR by default. + // We need this right now because the --verbose flags pollutes STDOUT + // when used with --output=json with the current outputDebug defaults. + if (process.env.SHOPIFY_TMP_FLAG_DEBUG) { + consoleError(message) } + }) - if (flags.output === 'json') { - /** - * Workaround: - * Force stdout to be blocking so that the JSON output is not broken when piped to another process. - * ie: ` | jq .` - * It turns out that console.log is technically asynchronous, and when we call process.exit(), - * node doesn't wait on all the output being sent to stdout and instead closes the process immediately - * - * https://github.com/pnp/cli-microsoft365/issues/1266#issuecomment-727254264 - * - */ - const stdout = process.stdout - if (isExtendedWriteStream(stdout)) { - stdout._handle.setBlocking(true) - } + const offensesByFile = sortOffenses(offenses) - outputInfo(JSON.stringify(formatOffensesJson(offensesByFile))) - } + if (outputFormat === 'text') { + renderOffensesText(offensesByFile, path) - if (flags['auto-correct']) { - await performAutoFixes(theme, offenses) + // Use renderSuccess when theres no offenses + const render = offenses.length ? renderInfo : renderSuccess + + render({ + headline: 'Theme Check Summary.', + body: formatSummary(offenses, offensesByFile, theme), + }) + } + + if (outputFormat === 'json') { + /** + * Workaround: + * Force stdout to be blocking so that the JSON output is not broken when piped to another process. + * ie: ` | jq .` + * It turns out that console.log is technically asynchronous, and when we call process.exit(), + * node doesn't wait on all the output being sent to stdout and instead closes the process immediately + * + * https://github.com/pnp/cli-microsoft365/issues/1266#issuecomment-727254264 + * + */ + const stdout = process.stdout + if (isExtendedWriteStream(stdout)) { + stdout._handle.setBlocking(true) } - return handleExit(offenses, flags['fail-level'] as FailLevel) + outputInfo(JSON.stringify(formatOffensesJson(offensesByFile))) } + + return {offenses, theme} } diff --git a/packages/theme/src/cli/commands/theme/dev.ts b/packages/theme/src/cli/commands/theme/dev.ts index c137bf671a7..c0fedeaf24d 100644 --- a/packages/theme/src/cli/commands/theme/dev.ts +++ b/packages/theme/src/cli/commands/theme/dev.ts @@ -4,6 +4,7 @@ import ThemeCommand, {FlagValues} from '../../utilities/theme-command.js' import {dev} from '../../services/dev.js' import {DevelopmentThemeManager} from '../../utilities/development-theme-manager.js' import {findOrSelectTheme} from '../../utilities/theme-selector.js' +import {metafieldsPull} from '../../services/metafields-pull.js' import {Flags} from '@oclif/core' import {globalFlags} from '@shopify/cli-kit/node/cli' import {Theme} from '@shopify/cli-kit/node/themes/types' @@ -154,5 +155,15 @@ You can run this command only in a directory that matches the [default Shopify t only, notify: flags.notify, }) + + await metafieldsPull({ + path: flags.path, + password: flags.password, + store: flags.store, + force: flags.force, + verbose: flags.verbose, + noColor: flags['no-color'], + silent: true, + }) } } diff --git a/packages/theme/src/cli/commands/theme/info.ts b/packages/theme/src/cli/commands/theme/info.ts index 18525ac49df..009715f7342 100644 --- a/packages/theme/src/cli/commands/theme/info.ts +++ b/packages/theme/src/cli/commands/theme/info.ts @@ -5,7 +5,7 @@ import ThemeCommand from '../../utilities/theme-command.js' import {Flags} from '@oclif/core' import {ensureAuthenticatedThemes} from '@shopify/cli-kit/node/session' import {AbortError} from '@shopify/cli-kit/node/error' -import {globalFlags} from '@shopify/cli-kit/node/cli' +import {globalFlags, jsonFlag} from '@shopify/cli-kit/node/cli' import {formatSection, outputInfo} from '@shopify/cli-kit/node/output' export default class Info extends ThemeCommand { @@ -14,6 +14,7 @@ export default class Info extends ThemeCommand { static flags = { ...globalFlags, + ...jsonFlag, store: themeFlags.store, password: themeFlags.password, environment: themeFlags.environment, @@ -27,11 +28,6 @@ export default class Info extends ThemeCommand { description: 'Theme ID or name of the remote theme.', env: 'SHOPIFY_FLAG_THEME_ID', }), - json: Flags.boolean({ - description: 'Output the theme info as JSON.', - default: false, - env: 'SHOPIFY_FLAG_JSON', - }), } public async run(): Promise { diff --git a/packages/theme/src/cli/commands/theme/list.ts b/packages/theme/src/cli/commands/theme/list.ts index 24167e2e6b2..916fa8517eb 100644 --- a/packages/theme/src/cli/commands/theme/list.ts +++ b/packages/theme/src/cli/commands/theme/list.ts @@ -5,13 +5,14 @@ import {themeFlags} from '../../flags.js' import ThemeCommand from '../../utilities/theme-command.js' import {Flags} from '@oclif/core' import {ensureAuthenticatedThemes} from '@shopify/cli-kit/node/session' -import {globalFlags} from '@shopify/cli-kit/node/cli' +import {globalFlags, jsonFlag} from '@shopify/cli-kit/node/cli' export default class List extends ThemeCommand { static description = 'Lists the themes in your store, along with their IDs and statuses.' static flags = { ...globalFlags, + ...jsonFlag, password: themeFlags.password, store: themeFlags.store, role: Flags.custom({ @@ -27,11 +28,6 @@ export default class List extends ThemeCommand { description: 'Only list theme with the given ID.', env: 'SHOPIFY_FLAG_ID', }), - json: Flags.boolean({ - description: 'Output the theme list as JSON.', - default: false, - env: 'SHOPIFY_FLAG_JSON', - }), environment: themeFlags.environment, } diff --git a/packages/theme/src/cli/commands/theme/metafields/pull.ts b/packages/theme/src/cli/commands/theme/metafields/pull.ts new file mode 100644 index 00000000000..8b0922d1283 --- /dev/null +++ b/packages/theme/src/cli/commands/theme/metafields/pull.ts @@ -0,0 +1,40 @@ +import {themeFlags} from '../../../flags.js' +import {metafieldsPull, MetafieldsPullFlags} from '../../../services/metafields-pull.js' +import ThemeCommand from '../../../utilities/theme-command.js' +import {globalFlags} from '@shopify/cli-kit/node/cli' +import {Flags} from '@oclif/core' + +export default class MetafieldsPull extends ThemeCommand { + static summary = 'Download metafields definitions from your shop into a local file.' + + static descriptionWithMarkdown = `Retrieves metafields from Shopify Admin. + +If the metafields file already exists, it will be overwritten.` + + static description = this.descriptionWithoutMarkdown() + + static flags = { + ...globalFlags, + ...themeFlags, + force: Flags.boolean({ + hidden: true, + char: 'f', + description: 'Proceed without confirmation, if current directory does not seem to be theme directory.', + env: 'SHOPIFY_FLAG_FORCE', + }), + } + + async run(): Promise { + const {flags} = await this.parse(MetafieldsPull) + const args: MetafieldsPullFlags = { + path: flags.path, + password: flags.password, + store: flags.store, + force: flags.force, + verbose: flags.verbose, + noColor: flags['no-color'], + } + + await metafieldsPull(args) + } +} diff --git a/packages/theme/src/cli/commands/theme/pull.ts b/packages/theme/src/cli/commands/theme/pull.ts index d6a6556c7a5..c7de2dfe2a2 100644 --- a/packages/theme/src/cli/commands/theme/pull.ts +++ b/packages/theme/src/cli/commands/theme/pull.ts @@ -61,7 +61,6 @@ If no theme is specified, then you're prompted to select the theme to pull from const pullFlags: PullFlags = { path: flags.path, password: flags.password, - environment: flags.environment, store: flags.store, theme: flags.theme, development: flags.development, diff --git a/packages/theme/src/cli/commands/theme/push.ts b/packages/theme/src/cli/commands/theme/push.ts index 99cbf83c3c1..0d4cbdec097 100644 --- a/packages/theme/src/cli/commands/theme/push.ts +++ b/packages/theme/src/cli/commands/theme/push.ts @@ -2,7 +2,7 @@ import {themeFlags} from '../../flags.js' import ThemeCommand from '../../utilities/theme-command.js' import {push, PushFlags} from '../../services/push.js' import {Flags} from '@oclif/core' -import {globalFlags} from '@shopify/cli-kit/node/cli' +import {globalFlags, jsonFlag} from '@shopify/cli-kit/node/cli' export default class Push extends ThemeCommand { static summary = 'Uploads your local theme files to the connected store, overwriting the remote version if specified.' @@ -43,6 +43,7 @@ export default class Push extends ThemeCommand { static flags = { ...globalFlags, ...themeFlags, + ...jsonFlag, theme: Flags.string({ char: 't', description: 'Theme ID or name of the remote theme.', @@ -80,11 +81,6 @@ export default class Push extends ThemeCommand { multiple: true, env: 'SHOPIFY_FLAG_IGNORE', }), - json: Flags.boolean({ - char: 'j', - description: 'Output JSON instead of a UI.', - env: 'SHOPIFY_FLAG_JSON', - }), 'allow-live': Flags.boolean({ char: 'a', description: 'Allow push to a live theme.', @@ -101,6 +97,10 @@ export default class Push extends ThemeCommand { description: 'Proceed without confirmation, if current directory does not seem to be theme directory.', env: 'SHOPIFY_FLAG_FORCE', }), + strict: Flags.boolean({ + description: 'Require theme check to pass without errors before pushing. Warnings are allowed.', + env: 'SHOPIFY_FLAG_STRICT_PUSH', + }), } async run(): Promise { @@ -110,7 +110,6 @@ export default class Push extends ThemeCommand { path: flags.path, password: flags.password, store: flags.store, - environment: flags.environment, theme: flags.theme, development: flags.development, live: flags.live, @@ -124,6 +123,7 @@ export default class Push extends ThemeCommand { force: flags.force, noColor: flags['no-color'], verbose: flags.verbose, + strict: flags.strict, } await push(pushFlags) diff --git a/packages/theme/src/cli/services/check.test.ts b/packages/theme/src/cli/services/check.test.ts index 63ffe4c4e6c..74a460aa242 100644 --- a/packages/theme/src/cli/services/check.test.ts +++ b/packages/theme/src/cli/services/check.test.ts @@ -10,7 +10,14 @@ import { import {fileExists, readFileSync, writeFile} from '@shopify/cli-kit/node/fs' import {outputInfo, outputSuccess} from '@shopify/cli-kit/node/output' import {renderInfo} from '@shopify/cli-kit/node/ui' -import {Severity, SourceCodeType, loadConfig, type Offense, type Theme} from '@shopify/theme-check-node' +import { + Severity, + SourceCodeType, + loadConfig, + path as pathUtils, + type Offense, + type Theme, +} from '@shopify/theme-check-node' import {Mock, MockInstance, afterAll, beforeEach, describe, expect, test, vi} from 'vitest' vi.mock('@shopify/cli-kit/node/fs', async () => ({ @@ -52,7 +59,7 @@ describe('formatOffenses', () => { type: SourceCodeType.LiquidHtml, check: 'LiquidHTMLSyntaxError', message: 'Attempting to close HtmlElement', - absolutePath: '/path/to/file', + uri: 'file:///path/to/file', severity: Severity.ERROR, start: {index: 0, line: 1, character: 0}, end: {index: 10, line: 1, character: 10}, @@ -80,7 +87,7 @@ describe('formatOffenses', () => { type: SourceCodeType.LiquidHtml, check: 'LiquidHTMLSyntaxError', message: 'Attempting to close HtmlElement', - absolutePath: '/path/to/file', + uri: 'file:///path/to/file', severity: Severity.ERROR, start: {index: 0, line: 1, character: 0}, end: {index: 10, line: 1, character: 10}, @@ -89,7 +96,7 @@ describe('formatOffenses', () => { type: SourceCodeType.LiquidHtml, check: 'LiquidHTMLSyntaxError', message: 'Attempting to close HtmlElement', - absolutePath: '/path/to/file', + uri: 'file:///path/to/file', severity: Severity.WARNING, start: {index: 0, line: 2, character: 0}, end: {index: 10, line: 2, character: 10}, @@ -115,12 +122,14 @@ describe('formatOffenses', () => { describe('sortOffenses', () => { test('should sort offenses by file path', () => { + const uri1 = pathUtils.normalize('file:///path/to/file1') + const uri2 = pathUtils.normalize('file:///path/to/file2') const offenses: Offense[] = [ { type: SourceCodeType.LiquidHtml, check: 'LiquidHTMLSyntaxError', message: 'Attempting to close HtmlElement', - absolutePath: '/path/to/file2', + uri: uri2, severity: Severity.ERROR, start: {index: 0, line: 1, character: 0}, end: {index: 10, line: 1, character: 10}, @@ -129,7 +138,7 @@ describe('sortOffenses', () => { type: SourceCodeType.LiquidHtml, check: 'LiquidHTMLSyntaxError', message: 'Attempting to close HtmlElement', - absolutePath: '/path/to/file1', + uri: uri1, severity: Severity.WARNING, start: {index: 0, line: 1, character: 0}, end: {index: 10, line: 1, character: 10}, @@ -139,18 +148,19 @@ describe('sortOffenses', () => { const result = sortOffenses(offenses) expect(result).toEqual({ - '/path/to/file1': [offenses[1]], - '/path/to/file2': [offenses[0]], + [pathUtils.fsPath(uri1)]: [offenses[1]], + [pathUtils.fsPath(uri2)]: [offenses[0]], }) }) test('should sort offenses by severity within each file', () => { + const uri = pathUtils.normalize('file:///path/to/file') const offenses: Offense[] = [ { type: SourceCodeType.LiquidHtml, check: 'LiquidHTMLSyntaxError', message: 'Attempting to close HtmlElement', - absolutePath: '/path/to/file', + uri, severity: Severity.WARNING, start: {index: 0, line: 1, character: 0}, end: {index: 10, line: 1, character: 10}, @@ -159,7 +169,7 @@ describe('sortOffenses', () => { type: SourceCodeType.LiquidHtml, check: 'LiquidHTMLSyntaxError', message: 'Attempting to close HtmlElement', - absolutePath: '/path/to/file', + uri, severity: Severity.ERROR, start: {index: 0, line: 2, character: 0}, end: {index: 10, line: 2, character: 10}, @@ -169,7 +179,7 @@ describe('sortOffenses', () => { const result = sortOffenses(offenses) expect(result).toEqual({ - '/path/to/file': [offenses[1], offenses[0]], + [pathUtils.fsPath(uri)]: [offenses[1], offenses[0]], }) }) }) @@ -190,7 +200,7 @@ describe('formatSummary', () => { type: SourceCodeType.LiquidHtml, check: 'LiquidHTMLSyntaxError', message: 'Attempting to close HtmlElement', - absolutePath: '/path/to/file', + uri: 'file:///path/to/file', severity: Severity.ERROR, start: {index: 0, line: 1, character: 0}, end: {index: 10, line: 1, character: 10}, @@ -199,7 +209,7 @@ describe('formatSummary', () => { type: SourceCodeType.LiquidHtml, check: 'LiquidHTMLSyntaxError', message: 'Attempting to close HtmlElement', - absolutePath: '/path/to/file', + uri: 'file:///path/to/file', severity: Severity.WARNING, start: {index: 0, line: 2, character: 0}, end: {index: 10, line: 2, character: 10}, @@ -235,7 +245,7 @@ describe('renderOffensesText', () => { type: SourceCodeType.LiquidHtml, check: 'LiquidHTMLSyntaxError', message: 'Attempting to close HtmlElement', - absolutePath: '/path/to/file', + uri: 'file:///path/to/file', severity: Severity.ERROR, start: {index: 0, line: 1, character: 0}, end: {index: 10, line: 1, character: 10}, @@ -258,7 +268,7 @@ describe('formatOffensesJson', () => { type: SourceCodeType.LiquidHtml, check: 'LiquidHTMLSyntaxError', message: 'Attempting to close HtmlElement', - absolutePath: '/path/to/file', + uri: 'file:///path/to/file', severity: Severity.ERROR, start: {index: 0, line: 1, character: 0}, end: {index: 10, line: 1, character: 10}, @@ -267,7 +277,7 @@ describe('formatOffensesJson', () => { type: SourceCodeType.LiquidHtml, check: 'LiquidHTMLSyntaxError', message: 'Attempting to close HtmlElement', - absolutePath: '/path/to/file', + uri: 'file:///path/to/file', severity: Severity.WARNING, start: {index: 0, line: 2, character: 0}, end: {index: 10, line: 2, character: 10}, @@ -333,7 +343,7 @@ describe('handleExit', () => { type: SourceCodeType.LiquidHtml, check: 'LiquidHTMLSyntaxError', message: 'Attempting to close HtmlElement', - absolutePath: '/path/to/file', + uri: 'file:///path/to/file', severity: Severity.ERROR, start: {index: 0, line: 1, character: 0}, end: {index: 10, line: 1, character: 10}, @@ -349,7 +359,7 @@ describe('handleExit', () => { type: SourceCodeType.LiquidHtml, check: 'LiquidHTMLSyntaxError', message: 'Attempting to close HtmlElement', - absolutePath: '/path/to/file', + uri: 'file:///path/to/file', severity: Severity.ERROR, start: {index: 0, line: 1, character: 0}, end: {index: 10, line: 1, character: 10}, @@ -365,7 +375,7 @@ describe('handleExit', () => { type: SourceCodeType.LiquidHtml, check: 'LiquidHTMLSyntaxError', message: 'Attempting to close HtmlElement', - absolutePath: '/path/to/file', + uri: 'file:///path/to/file', severity: Severity.INFO, start: {index: 0, line: 1, character: 0}, end: {index: 10, line: 1, character: 10}, diff --git a/packages/theme/src/cli/services/check.ts b/packages/theme/src/cli/services/check.ts index 77ef72a9031..e86722f9940 100644 --- a/packages/theme/src/cli/services/check.ts +++ b/packages/theme/src/cli/services/check.ts @@ -11,6 +11,7 @@ import { type FixApplicator, type Offense, type Theme, + path as pathUtils, } from '@shopify/theme-check-node' import YAML from 'yaml' @@ -37,7 +38,9 @@ interface TransformedOffenseMap { } type SeverityCounts = Partial<{ - [K in keyof typeof Severity]: number + [Severity.ERROR]: number + [Severity.WARNING]: number + [Severity.INFO]: number }> export type FailLevel = 'error' | 'suggestion' | 'style' | 'warning' | 'info' | 'crash' @@ -71,8 +74,9 @@ function severityToLabel(severity: Severity) { /** * Returns a code snippet from a file. All line numbers given MUST be zero indexed */ -function getSnippet(absolutePath: string, startLine: number, endLine: number) { - const fileContent = readFileSync(absolutePath).toString() +function getSnippet(uri: string, startLine: number, endLine: number) { + const fsPath = pathUtils.fsPath(uri) + const fileContent = readFileSync(fsPath).toString() const lines = fileContent.split('\n') const snippetLines = lines.slice(startLine, endLine + 1) const isSingleLine = snippetLines.length === 1 @@ -110,9 +114,9 @@ function severityToToken(severity: Severity) { */ export function formatOffenses(offenses: Offense[]) { const offenseBodies = offenses.map((offense, index) => { - const {message, absolutePath, start, end, check, severity} = offense + const {message, uri, start, end, check, severity} = offense // Theme check line numbers are zero indexed, but intuitively 1-indexed - const codeSnippet = getSnippet(absolutePath, start.line, end.line) + const codeSnippet = getSnippet(uri, start.line, end.line) // Ensure enough padding between offenses const offensePadding = index === offenses.length - 1 ? '' : '\n\n' @@ -132,12 +136,13 @@ const offenseSeverityAscending = (offenseA: Offense, offenseB: Offense) => offen export function sortOffenses(offenses: Offense[]): OffenseMap { // Bucket offenses by filename const offensesByFile = offenses.reduce((acc: OffenseMap, offense: Offense) => { - const {absolutePath} = offense - if (!acc[absolutePath]) { - acc[absolutePath] = [] + const {uri} = offense + const filePath = pathUtils.fsPath(uri) + if (!acc[filePath]) { + acc[filePath] = [] } - acc[absolutePath]!.push(offense) + acc[filePath]!.push(offense) return acc }, {}) @@ -222,9 +227,9 @@ export function formatOffensesJson(offensesByFile: OffenseMap): TransformedOffen return { path, offenses: transformedOffenses, - errorCount: counts[Severity.ERROR] || 0, - warningCount: counts[Severity.WARNING] || 0, - infoCount: counts[Severity.INFO] || 0, + errorCount: counts[Severity.ERROR] ?? 0, + warningCount: counts[Severity.WARNING] ?? 0, + infoCount: counts[Severity.INFO] ?? 0, } }) } @@ -274,7 +279,8 @@ export async function initConfig(root: string) { const saveToDiskFixApplicator: FixApplicator = async (sourceCode, fix) => { const updatedSource = applyFixToString(sourceCode.source, fix) - await writeFile(sourceCode.absolutePath, updatedSource) + const absolutePath = pathUtils.fsPath(sourceCode.uri) + await writeFile(absolutePath, updatedSource) } export async function performAutoFixes(sourceCodes: Theme, offenses: Offense[]) { @@ -282,7 +288,7 @@ export async function performAutoFixes(sourceCodes: Theme, offenses: Offense[]) } export async function outputActiveConfig(themeRoot: string, configPath?: string) { - const {ignore, settings, root} = await loadConfig(configPath, themeRoot) + const {ignore, settings, rootUri} = await loadConfig(configPath, themeRoot) const config = { // loadConfig flattens all configs, it doesn't extend anything @@ -292,7 +298,7 @@ export async function outputActiveConfig(themeRoot: string, configPath?: string) // duplicate patterns to ignore. We can clean them before outputting. ignore: [...new Set(ignore)], - root, + rootUri, // Dump out the active settings for all checks. ...settings, @@ -314,7 +320,7 @@ export async function outputActiveChecks(root: string, configPath?: string) { return acc } - const severityLabel = severityToLabel(severity === undefined ? Severity.INFO : severity) + const severityLabel = severityToLabel(severity ?? Severity.INFO) // Map metafields from the check into desired output format const meta = checks.find((check) => check.meta.code === checkCode) diff --git a/packages/theme/src/cli/services/dev.ts b/packages/theme/src/cli/services/dev.ts index 9223b4633df..aec35d21711 100644 --- a/packages/theme/src/cli/services/dev.ts +++ b/packages/theme/src/cli/services/dev.ts @@ -1,5 +1,5 @@ import {hasRequiredThemeDirectories, mountThemeFileSystem} from '../utilities/theme-fs.js' -import {currentDirectoryConfirmed} from '../utilities/theme-ui.js' +import {ensureDirectoryConfirmed} from '../utilities/theme-ui.js' import {setupDevServer} from '../utilities/theme-environment/theme-environment.js' import {DevServerContext, LiveReload} from '../utilities/theme-environment/types.js' import {isStorefrontPasswordProtected} from '../utilities/theme-environment/storefront-session.js' @@ -38,7 +38,7 @@ export interface DevOptions { } export async function dev(options: DevOptions) { - if (!(await hasRequiredThemeDirectories(options.directory)) && !(await currentDirectoryConfirmed(options.force))) { + if (!(await hasRequiredThemeDirectories(options.directory)) && !(await ensureDirectoryConfirmed(options.force))) { return } diff --git a/packages/theme/src/cli/services/metafields-pull.test.ts b/packages/theme/src/cli/services/metafields-pull.test.ts new file mode 100644 index 00000000000..ea96eda111f --- /dev/null +++ b/packages/theme/src/cli/services/metafields-pull.test.ts @@ -0,0 +1,145 @@ +import {setThemeStore} from './local-storage.js' +import {metafieldsPull} from './metafields-pull.js' +import {ensureThemeStore} from '../utilities/theme-store.js' +import {ensureDirectoryConfirmed} from '../utilities/theme-ui.js' +import {AdminSession, ensureAuthenticatedThemes} from '@shopify/cli-kit/node/session' +import {mockAndCaptureOutput} from '@shopify/cli-kit/node/testing/output' +import {metafieldDefinitionsByOwnerType} from '@shopify/cli-kit/node/themes/api' +import {describe, test, vi, beforeEach, expect, afterEach} from 'vitest' +import {fileExists, inTemporaryDirectory, readFile} from '@shopify/cli-kit/node/fs' + +vi.mock('../utilities/theme-store.js') +vi.mock('../utilities/theme-ui.js') +vi.mock('@shopify/cli-kit/node/session') +vi.mock('@shopify/cli-kit/node/themes/api') + +const metafieldDefinitionPath = (path: string) => `${path}/.shopify/metafields.json` + +describe('metafields-pull', () => { + const fakeMetafieldDefinition = { + key: 'fakename', + name: 'fakename', + namespace: 'fakespace', + description: 'fake metafield definition is fake', + type: { + category: 'text', + name: 'string', + }, + } + const capturedOutput = mockAndCaptureOutput() + + beforeEach(() => { + vi.mocked(ensureThemeStore).mockImplementation(() => { + const themeStore = 'example.myshopify.com' + setThemeStore(themeStore) + return themeStore + }) + vi.mocked(ensureAuthenticatedThemes).mockResolvedValue({token: '', storeFqdn: ''}) + vi.mocked(ensureDirectoryConfirmed).mockResolvedValue(true) + }) + + afterEach(() => { + capturedOutput.clear() + }) + + test('should download metafields for each ownerType and write to file', async () => { + // Given + vi.mocked(metafieldDefinitionsByOwnerType).mockImplementation((type: any, _session: AdminSession) => { + if (type !== 'PRODUCT') return Promise.resolve([]) + return Promise.resolve([fakeMetafieldDefinition]) + }) + + await inTemporaryDirectory(async (tmpDir) => { + // When + await metafieldsPull({path: tmpDir}) + + // Then + const filePath = metafieldDefinitionPath(tmpDir) + await expect(fileExists(filePath)).resolves.toBe(true) + await expect(readFile(filePath)).resolves.toBe( + JSON.stringify( + { + article: [], + blog: [], + brand: [], + collection: [], + company: [], + company_location: [], + location: [], + market: [], + order: [], + page: [], + product: [fakeMetafieldDefinition], + variant: [], + shop: [], + }, + null, + 2, + ), + ) + }) + + expect(capturedOutput.info()).toContain('Metafield definitions have been successfully downloaded.') + expect(capturedOutput.error()).toBeFalsy() + }) + + test('should output to debug if some metafield definitions are not found', async () => { + // Given + vi.mocked(metafieldDefinitionsByOwnerType).mockImplementation((type: any, _session: AdminSession) => { + if (type === 'PRODUCT') return Promise.reject(new Error(`Failed to fetch metafield definitions for ${type}`)) + if (type === 'COLLECTION') return Promise.resolve([fakeMetafieldDefinition]) + return Promise.resolve([]) + }) + + await inTemporaryDirectory(async (tmpDir) => { + // When + await metafieldsPull({path: tmpDir}) + + // Then + const filePath = metafieldDefinitionPath(tmpDir) + await expect(fileExists(filePath)).resolves.toBe(true) + await expect(readFile(filePath)).resolves.toBe( + JSON.stringify( + { + article: [], + blog: [], + brand: [], + collection: [fakeMetafieldDefinition], + company: [], + company_location: [], + location: [], + market: [], + order: [], + page: [], + product: [], + variant: [], + shop: [], + }, + null, + 2, + ), + ) + expect(capturedOutput.info()).toContain('Metafield definitions have been successfully downloaded.') + expect(capturedOutput.debug()).toContain('Failed to fetch metafield definitions for the following owner types') + expect(capturedOutput.error()).toBeFalsy() + }) + }) + + test('should render error if no metafield definitions are found', async () => { + // Given + vi.mocked(metafieldDefinitionsByOwnerType).mockImplementation((type: string, _session: AdminSession) => { + return Promise.reject(new Error(`Failed to fetch metafield definitions for ${type}`)) + }) + + await inTemporaryDirectory(async (tmpDir) => { + // When + await metafieldsPull({path: tmpDir}) + + // Then + const filePath = metafieldDefinitionPath(tmpDir) + await expect(fileExists(filePath)).resolves.toBe(false) + expect(capturedOutput.info()).toBeFalsy() + expect(capturedOutput.error()).toContain('Failed to fetch metafield definitions.') + }) + }) +}) diff --git a/packages/theme/src/cli/services/metafields-pull.ts b/packages/theme/src/cli/services/metafields-pull.ts new file mode 100644 index 00000000000..f929770e601 --- /dev/null +++ b/packages/theme/src/cli/services/metafields-pull.ts @@ -0,0 +1,165 @@ +import {hasRequiredThemeDirectories} from '../utilities/theme-fs.js' +import {ensureDirectoryConfirmed} from '../utilities/theme-ui.js' +import {ensureThemeStore} from '../utilities/theme-store.js' +import {configureCLIEnvironment} from '../utilities/cli-config.js' +import {AdminSession, ensureAuthenticatedThemes} from '@shopify/cli-kit/node/session' +import {cwd, joinPath} from '@shopify/cli-kit/node/path' +import {metafieldDefinitionsByOwnerType} from '@shopify/cli-kit/node/themes/api' +import {renderError, renderSuccess} from '@shopify/cli-kit/node/ui' +import {mkdirSync, writeFileSync} from '@shopify/cli-kit/node/fs' +import {outputDebug} from '@shopify/cli-kit/node/output' + +interface MetafieldsPullOptions { + path: string + force: boolean + silent: boolean +} + +export interface MetafieldsPullFlags { + /** + * The directory path of the theme to download the metafield definitions. + */ + path?: string + + /** + * The password for authenticating with the store. + */ + password?: string + + /** + * Store URL. It can be the store prefix (example.myshopify.com) or the full myshopify.com URL (https://example.myshopify.com). + */ + store?: string + + /** + * Proceed without confirmation, if current directory does not seem to be theme directory. + */ + force?: boolean + + /** + * Disable color output. + */ + noColor?: boolean + + /** + * Increase the verbosity of the output. + */ + verbose?: boolean + + /** + * Suppress all output. + */ + silent?: boolean +} + +/** + * Pulls the metafield definitions from an authenticated store. + * + * @param flags - All flags are optional. + */ +export async function metafieldsPull(flags: MetafieldsPullFlags): Promise { + configureCLIEnvironment({verbose: flags.verbose, noColor: flags.noColor}) + + const store = ensureThemeStore({store: flags.store}) + const adminSession = await ensureAuthenticatedThemes(store, flags.password) + + await executeMetafieldsPull(adminSession, { + path: flags.path ?? cwd(), + force: flags.force ?? false, + silent: flags.silent ?? false, + }) +} + +const handleToOwnerType = { + article: 'ARTICLE', + blog: 'BLOG', + brand: 'BRAND', + collection: 'COLLECTION', + company: 'COMPANY', + company_location: 'COMPANY_LOCATION', + location: 'LOCATION', + market: 'MARKET', + order: 'ORDER', + page: 'PAGE', + product: 'PRODUCT', + variant: 'PRODUCTVARIANT', + shop: 'SHOP', +} as const + +/** + * Executes the pullMetafields operation for the shop. + * + * @param session - the admin session to access the API and download the metafield definitions + * @param options - the options that modify where the file gets created + */ +async function executeMetafieldsPull(session: AdminSession, options: MetafieldsPullOptions) { + const {force, path, silent} = options + + if (!(await hasRequiredThemeDirectories(path)) && !(await ensureDirectoryConfirmed(force))) { + return + } + + const promises = [] + const failedFetchByOwnerType: string[] = [] + + for (const [handle, ownerType] of Object.entries(handleToOwnerType)) { + promises.push( + metafieldDefinitionsByOwnerType(ownerType, session) + .catch((_) => { + failedFetchByOwnerType.push(ownerType) + return [] + }) + .then((definitions) => { + return { + [handle]: definitions, + } + }), + ) + } + + const result = (await Promise.all(promises)).reduce((acc, metafieldDefinitionByOwnerType) => ({ + ...acc, + ...metafieldDefinitionByOwnerType, + })) + + if (failedFetchByOwnerType.length === Object.values(handleToOwnerType).length) { + if (!silent) { + renderError({ + body: `Failed to fetch metafield definitions.`, + nextSteps: [ + 'Check your network connection and try again.', + 'Ensure you have the permission to fetch metafield definitions.', + ], + reference: [ + { + link: { + label: 'Metafield Definition API', + url: 'https://shopify.dev/docs/api/admin-graphql/latest/queries/metafieldDefinition', + }, + }, + ], + }) + } + return + } + + writeMetafieldDefinitionsToFile(path, result) + + if (failedFetchByOwnerType.length > 0) { + outputDebug( + `Failed to fetch metafield definitions for the following owner types: ${failedFetchByOwnerType.join(', ')}`, + ) + } + + if (!silent) { + renderSuccess({body: 'Metafield definitions have been successfully downloaded.'}) + } +} + +function writeMetafieldDefinitionsToFile(path: string, content: unknown) { + const shopifyDirectory = joinPath(path, '.shopify') + mkdirSync(shopifyDirectory) + + const filePath = joinPath(shopifyDirectory, 'metafields.json') + writeFileSync(filePath, JSON.stringify(content, null, 2)) +} diff --git a/packages/theme/src/cli/services/pull.test.ts b/packages/theme/src/cli/services/pull.test.ts index 899ddbc603c..6ca5a5c1ab7 100644 --- a/packages/theme/src/cli/services/pull.test.ts +++ b/packages/theme/src/cli/services/pull.test.ts @@ -3,23 +3,27 @@ import {setThemeStore} from './local-storage.js' import {findOrSelectTheme} from '../utilities/theme-selector.js' import {ensureThemeStore} from '../utilities/theme-store.js' import {DevelopmentThemeManager} from '../utilities/development-theme-manager.js' -import {mountThemeFileSystem} from '../utilities/theme-fs.js' +import {hasRequiredThemeDirectories, mountThemeFileSystem} from '../utilities/theme-fs.js' import {fakeThemeFileSystem} from '../utilities/theme-fs/theme-fs-mock-factory.js' import {downloadTheme} from '../utilities/theme-downloader.js' +import {themeComponent, ensureDirectoryConfirmed} from '../utilities/theme-ui.js' import {mkTmpDir, rmdir} from '@shopify/cli-kit/node/fs' import {buildTheme} from '@shopify/cli-kit/node/themes/factories' import {ensureAuthenticatedThemes} from '@shopify/cli-kit/node/session' import {fetchChecksums} from '@shopify/cli-kit/node/themes/api' +import {insideGitDirectory, isClean} from '@shopify/cli-kit/node/git' import {test, describe, expect, vi, beforeEach} from 'vitest' vi.mock('../utilities/theme-selector.js') vi.mock('../utilities/theme-store.js') vi.mock('../utilities/theme-fs.js') vi.mock('../utilities/theme-downloader.js') +vi.mock('../utilities/theme-ui.js') vi.mock('@shopify/cli-kit/node/context/local') vi.mock('@shopify/cli-kit/node/session') vi.mock('@shopify/cli-kit/node/themes/api') vi.mock('@shopify/cli-kit/node/ui') +vi.mock('@shopify/cli-kit/node/git') const adminSession = {token: '', storeFqdn: ''} const path = '/my-theme' @@ -47,6 +51,7 @@ describe('pull', () => { vi.mocked(ensureAuthenticatedThemes).mockResolvedValue(adminSession) vi.mocked(mountThemeFileSystem).mockReturnValue(localThemeFileSystem) vi.mocked(fetchChecksums).mockResolvedValue([]) + vi.mocked(themeComponent).mockReturnValue([]) findDevelopmentThemeSpy.mockClear() fetchDevelopmentThemeSpy.mockClear() }) @@ -82,6 +87,40 @@ describe('pull', () => { ) }) + test('should ask for confirmation if the current directory is a Git directory and is not clean', async () => { + // Given + const theme = buildTheme({id: 1, name: 'Theme', role: 'development'})! + vi.mocked(insideGitDirectory).mockResolvedValue(true) + vi.mocked(isClean).mockResolvedValue(false) + vi.mocked(ensureDirectoryConfirmed).mockResolvedValue(false) + + // When + await pull({...defaultFlags, theme: theme.id.toString()}) + + // Then + expect(vi.mocked(ensureDirectoryConfirmed)).toHaveBeenCalledWith( + false, + 'The current Git directory has uncommitted changes. Do you want to proceed?', + ) + }) + + test('should not ask for confirmation if --force flag is provided', async () => { + // Given + const theme = buildTheme({id: 1, name: 'Theme', role: 'development'})! + vi.mocked(findOrSelectTheme).mockResolvedValue(theme) + vi.mocked(fetchDevelopmentThemeSpy).mockResolvedValue(undefined) + + // When + await pull({...defaultFlags, theme: theme.id.toString(), force: true}) + + // Then + expect(vi.mocked(findOrSelectTheme)).toHaveBeenCalledOnce() + expect(vi.mocked(hasRequiredThemeDirectories)).not.toHaveBeenCalled() + expect(vi.mocked(insideGitDirectory)).not.toHaveBeenCalled() + expect(vi.mocked(isClean)).not.toHaveBeenCalled() + expect(vi.mocked(ensureDirectoryConfirmed)).not.toHaveBeenCalled() + }) + describe('isEmptyDir', () => { test('returns true when directory is empty', async () => { // Given diff --git a/packages/theme/src/cli/services/pull.ts b/packages/theme/src/cli/services/pull.ts index 6b03ba423c8..1d0df3a7559 100644 --- a/packages/theme/src/cli/services/pull.ts +++ b/packages/theme/src/cli/services/pull.ts @@ -1,6 +1,6 @@ import {downloadTheme} from '../utilities/theme-downloader.js' import {hasRequiredThemeDirectories, mountThemeFileSystem} from '../utilities/theme-fs.js' -import {currentDirectoryConfirmed, themeComponent} from '../utilities/theme-ui.js' +import {ensureDirectoryConfirmed, themeComponent} from '../utilities/theme-ui.js' import {rejectGeneratedStaticAssets} from '../utilities/asset-checksum.js' import {showEmbeddedCLIWarning} from '../utilities/embedded-cli-warning.js' import {ensureThemeStore} from '../utilities/theme-store.js' @@ -13,6 +13,7 @@ import {fetchChecksums} from '@shopify/cli-kit/node/themes/api' import {renderSuccess} from '@shopify/cli-kit/node/ui' import {glob} from '@shopify/cli-kit/node/fs' import {cwd} from '@shopify/cli-kit/node/path' +import {insideGitDirectory, isClean} from '@shopify/cli-kit/node/git' interface PullOptions { path: string @@ -33,11 +34,6 @@ export interface PullFlags { */ password?: string - /** - * The environment to apply to the current command. - */ - environment?: string - /** * Store URL. It can be the store prefix (example.myshopify.com) or the full myshopify.com URL (https://example.myshopify.com). */ @@ -107,6 +103,10 @@ export async function pull(flags: PullFlags): Promise { const {path, nodelete, live, development, only, ignore, force} = flags + if (!(await validateDirectory(path ?? cwd(), force ?? false))) { + return + } + const theme = await findOrSelectTheme(adminSession, { header: 'Select a theme to open', filter: { @@ -116,11 +116,11 @@ export async function pull(flags: PullFlags): Promise { }) await executePull(theme, adminSession, { - path: path || cwd(), - nodelete: nodelete || false, - only: only || [], - ignore: ignore || [], - force: force || false, + path: path ?? cwd(), + nodelete: nodelete ?? false, + only: only ?? [], + ignore: ignore ?? [], + force: force ?? false, }) } @@ -132,24 +132,7 @@ export async function pull(flags: PullFlags): Promise { * @param options - the options that modify how the theme gets downloaded */ async function executePull(theme: Theme, session: AdminSession, options: PullOptions) { - const path = options.path - const force = options.force - - /** - * If users are not forcing the `pull` command, the directory is not empty, - * and the directory doesn't look like a theme directory, we ask for - * confirmation, because the `pull` command has the destructive behavior of - * removing local assets that are not present remotely. - */ - if ( - !(await isEmptyDir(path)) && - !(await hasRequiredThemeDirectories(path)) && - !(await currentDirectoryConfirmed(force)) - ) { - return - } - - const themeFileSystem = mountThemeFileSystem(path, {filters: options}) + const themeFileSystem = mountThemeFileSystem(options.path, {filters: options}) const [remoteChecksums] = await Promise.all([fetchChecksums(theme.id, session), themeFileSystem.ready()]) const themeChecksums = rejectGeneratedStaticAssets(remoteChecksums) @@ -196,3 +179,46 @@ export async function isEmptyDir(path: string) { return entries.length === 0 } + +/** + * Validates the directory before pulling the theme. + * + * @param path - The path to the directory. + * @param force - Whether to force the pull operation. + * @returns Whether the directory is valid. + */ +async function validateDirectory(path: string, force: boolean) { + if (force) return true + + /** + * If users are not forcing the `pull` command, the directory is not empty, + * and the directory doesn't look like a theme directory, we ask for + * confirmation, because the `pull` command has the destructive behavior of + * removing local assets that are not present remotely. + */ + if ( + !(await isEmptyDir(path)) && + !(await hasRequiredThemeDirectories(path)) && + !(await ensureDirectoryConfirmed(force)) + ) { + return false + } + + /** + * If users are not forcing the 'pull' command, and the current directory is a + * Git directory and it is not clean, we ask for confirmation before proceeding. + */ + const dirtyDirectory = (await insideGitDirectory(path)) && !(await isClean(path)) + + if ( + dirtyDirectory && + !(await ensureDirectoryConfirmed( + force, + 'The current Git directory has uncommitted changes. Do you want to proceed?', + )) + ) { + return false + } + + return true +} diff --git a/packages/theme/src/cli/services/push.test.ts b/packages/theme/src/cli/services/push.test.ts index eae7a6dfd2c..e83921bfc0a 100644 --- a/packages/theme/src/cli/services/push.test.ts +++ b/packages/theme/src/cli/services/push.test.ts @@ -4,6 +4,7 @@ import {setDevelopmentTheme} from './local-storage.js' import {uploadTheme} from '../utilities/theme-uploader.js' import {ensureThemeStore} from '../utilities/theme-store.js' import {findOrSelectTheme} from '../utilities/theme-selector.js' +import {runThemeCheck} from '../commands/theme/check.js' import {buildTheme} from '@shopify/cli-kit/node/themes/factories' import {test, describe, vi, expect, beforeEach} from 'vitest' import {createTheme, fetchTheme, themePublish} from '@shopify/cli-kit/node/themes/api' @@ -15,6 +16,8 @@ import { UNPUBLISHED_THEME_ROLE, } from '@shopify/cli-kit/node/themes/utils' import {renderConfirmationPrompt} from '@shopify/cli-kit/node/ui' +import {AbortError} from '@shopify/cli-kit/node/error' +import {Severity, SourceCodeType} from '@shopify/theme-check-node' vi.mock('../utilities/theme-uploader.js') vi.mock('../utilities/theme-store.js') @@ -24,6 +27,7 @@ vi.mock('@shopify/cli-kit/node/themes/utils') vi.mock('@shopify/cli-kit/node/session') vi.mock('@shopify/cli-kit/node/themes/api') vi.mock('@shopify/cli-kit/node/ui') +vi.mock('../commands/theme/check.js') const path = '/my-theme' const defaultFlags: PullFlags = { @@ -59,6 +63,129 @@ describe('push', () => { // Then expect(themePublish).toHaveBeenCalledWith(theme.id, adminSession) }) + + describe('strict mode', () => { + beforeEach(() => { + const theme = buildTheme({id: 1, name: 'Theme', role: 'development'})! + vi.mocked(findOrSelectTheme).mockResolvedValue(theme) + }) + + test('skips theme check when strict mode is disabled', async () => { + // Given + const flags = {...defaultFlags, strict: false} + + // When + await push(flags) + + // Then + expect(runThemeCheck).not.toHaveBeenCalled() + }) + + test('blocks push when errors exist', async () => { + // Given + vi.mocked(runThemeCheck).mockResolvedValue({ + offenses: [ + { + severity: Severity.ERROR, + message: 'error message', + type: SourceCodeType.LiquidHtml, + check: 'check', + uri: 'file:///path/to/file.liquid', + start: {index: 0, line: 1, character: 1}, + end: {index: 1, line: 1, character: 1}, + }, + ], + theme: [], + }) + + // When/Then + await expect(push({...defaultFlags, strict: true})).rejects.toThrow(AbortError) + }) + + test('blocks push when both warnings and errors exist', async () => { + // Given + vi.mocked(runThemeCheck).mockResolvedValue({ + offenses: [ + { + severity: Severity.WARNING, + message: 'warning message', + type: SourceCodeType.LiquidHtml, + check: 'check', + uri: 'file:///path/to/file.liquid', + start: {index: 0, line: 1, character: 1}, + end: {index: 1, line: 1, character: 1}, + }, + { + severity: Severity.ERROR, + message: 'error message', + type: SourceCodeType.LiquidHtml, + check: 'check', + uri: 'file:///path/to/file.liquid', + start: {index: 0, line: 1, character: 1}, + end: {index: 1, line: 1, character: 1}, + }, + ], + theme: [], + }) + + // When/Then + await expect(push({...defaultFlags, strict: true})).rejects.toThrow(AbortError) + }) + + test('continues push when no offenses exist', async () => { + // Given + vi.mocked(runThemeCheck).mockResolvedValue({ + offenses: [], + theme: [], + }) + + // When/Then + await expect(push({...defaultFlags, strict: true})).resolves.not.toThrow() + }) + + test('continues push when only warnings exist', async () => { + // Given + vi.mocked(runThemeCheck).mockResolvedValue({ + offenses: [ + { + severity: Severity.WARNING, + message: 'warning message', + check: 'check', + uri: 'file:///path/to/file.liquid', + type: SourceCodeType.LiquidHtml, + start: {index: 0, line: 1, character: 1}, + end: {index: 1, line: 1, character: 1}, + }, + ], + theme: [], + }) + + // When/Then + await expect(push({...defaultFlags, strict: true})).resolves.not.toThrow() + }) + + test('passes the --json flag to theme check as output format', async () => { + // Given + vi.mocked(runThemeCheck).mockResolvedValue({ + offenses: [ + { + severity: Severity.WARNING, + message: 'warning message', + check: 'check', + uri: 'file:///path/to/file.liquid', + type: SourceCodeType.LiquidHtml, + start: {index: 0, line: 1, character: 1}, + end: {index: 1, line: 1, character: 1}, + }, + ], + theme: [], + }) + + // When/Then + await push({...defaultFlags, strict: true, json: true}) + expect(runThemeCheck).toHaveBeenCalledWith(path, 'json') + }) + }) }) describe('createOrSelectTheme', async () => { diff --git a/packages/theme/src/cli/services/push.ts b/packages/theme/src/cli/services/push.ts index 2936c6fc83f..078b9f74825 100644 --- a/packages/theme/src/cli/services/push.ts +++ b/packages/theme/src/cli/services/push.ts @@ -1,12 +1,13 @@ /* eslint-disable tsdoc/syntax */ import {hasRequiredThemeDirectories, mountThemeFileSystem} from '../utilities/theme-fs.js' import {uploadTheme} from '../utilities/theme-uploader.js' -import {currentDirectoryConfirmed, themeComponent} from '../utilities/theme-ui.js' +import {ensureDirectoryConfirmed, themeComponent} from '../utilities/theme-ui.js' import {ensureThemeStore} from '../utilities/theme-store.js' import {DevelopmentThemeManager} from '../utilities/development-theme-manager.js' import {findOrSelectTheme} from '../utilities/theme-selector.js' import {Role} from '../utilities/theme-selector/fetch.js' import {configureCLIEnvironment} from '../utilities/cli-config.js' +import {runThemeCheck} from '../commands/theme/check.js' import {AdminSession, ensureAuthenticatedThemes} from '@shopify/cli-kit/node/session' import {createTheme, fetchChecksums, themePublish} from '@shopify/cli-kit/node/themes/api' import {Result, Theme} from '@shopify/cli-kit/node/themes/types' @@ -20,6 +21,8 @@ import { import {themeEditorUrl, themePreviewUrl} from '@shopify/cli-kit/node/themes/urls' import {cwd, resolvePath} from '@shopify/cli-kit/node/path' import {LIVE_THEME_ROLE, promptThemeName, UNPUBLISHED_THEME_ROLE} from '@shopify/cli-kit/node/themes/utils' +import {AbortError} from '@shopify/cli-kit/node/error' +import {Severity} from '@shopify/theme-check-node' interface PushOptions { path: string @@ -53,9 +56,6 @@ export interface PushFlags { /** Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com). */ store?: string - /** The environment to apply to the current command. */ - environment?: string - /** Theme ID or name of the remote theme. */ theme?: string @@ -94,6 +94,9 @@ export interface PushFlags { /** Increase the verbosity of the output. */ verbose?: boolean + + /** Require theme check to pass without errors before pushing. Warnings are allowed. */ + strict?: boolean } /** @@ -102,6 +105,18 @@ export interface PushFlags { * @param flags - The flags for the push operation. */ export async function push(flags: PushFlags): Promise { + if (flags.strict) { + const outputType = flags.json ? 'json' : 'text' + const {offenses} = await runThemeCheck(flags.path ?? cwd(), outputType) + + if (offenses.length > 0) { + const errorOffenses = offenses.filter((offense) => offense.severity === Severity.ERROR) + if (errorOffenses.length > 0) { + throw new AbortError('Theme check failed. Please fix the errors before pushing.') + } + } + } + const {path} = flags configureCLIEnvironment({ @@ -115,7 +130,7 @@ export async function push(flags: PushFlags): Promise { const adminSession = await ensureAuthenticatedThemes(store, flags.password) const workingDirectory = path ? resolvePath(path) : cwd() - if (!(await hasRequiredThemeDirectories(workingDirectory)) && !(await currentDirectoryConfirmed(force))) { + if (!(await hasRequiredThemeDirectories(workingDirectory)) && !(await ensureDirectoryConfirmed(force))) { return } diff --git a/packages/theme/src/cli/utilities/theme-environment/storefront-session.test.ts b/packages/theme/src/cli/utilities/theme-environment/storefront-session.test.ts index 5d5615b0d28..6727cdfd592 100644 --- a/packages/theme/src/cli/utilities/theme-environment/storefront-session.test.ts +++ b/packages/theme/src/cli/utilities/theme-environment/storefront-session.test.ts @@ -14,9 +14,7 @@ describe('Storefront API', () => { describe('isStorefrontPasswordProtected', () => { test('returns true when the request is redirected to the password page', async () => { // Given - vi.mocked(fetch).mockResolvedValue( - response({status: 302, headers: {location: 'https://store.myshopify.com/password'}}), - ) + vi.mocked(fetch).mockResolvedValue(response({status: 200, url: 'https://store.myshopify.com/password'})) // When const isProtected = await isStorefrontPasswordProtected('store.myshopify.com') @@ -25,13 +23,12 @@ describe('Storefront API', () => { expect(isProtected).toBe(true) expect(fetch).toBeCalledWith('https://store.myshopify.com', { method: 'GET', - redirect: 'manual', }) }) test('returns false when request is not redirected', async () => { // Given - vi.mocked(fetch).mockResolvedValue(response({status: 200})) + vi.mocked(fetch).mockResolvedValue(response({status: 200, url: 'https://store.myshopify.com'})) // When const isProtected = await isStorefrontPasswordProtected('store.myshopify.com') @@ -40,13 +37,12 @@ describe('Storefront API', () => { expect(isProtected).toBe(false) expect(fetch).toBeCalledWith('https://store.myshopify.com', { method: 'GET', - redirect: 'manual', }) }) test('returns false when store redirects to a different domain', async () => { // Given - vi.mocked(fetch).mockResolvedValue(response({status: 302, headers: {location: 'https://store.myshopify.se'}})) + vi.mocked(fetch).mockResolvedValue(response({status: 200, url: 'https://store.myshopify.se'})) // When const isProtected = await isStorefrontPasswordProtected('store.myshopify.com') @@ -57,9 +53,7 @@ describe('Storefront API', () => { test('returns false when store redirects to a different URI', async () => { // Given - vi.mocked(fetch).mockResolvedValue( - response({status: 302, headers: {location: 'https://store.myshopify.com/random'}}), - ) + vi.mocked(fetch).mockResolvedValue(response({status: 200, url: 'https://store.myshopify.com/random'})) // When const isProtected = await isStorefrontPasswordProtected('store.myshopify.com') @@ -70,9 +64,7 @@ describe('Storefront API', () => { test('return true when store redirects to //password', async () => { // Given - vi.mocked(fetch).mockResolvedValue( - response({status: 302, headers: {location: 'https://store.myshopify.com/fr-CA/password'}}), - ) + vi.mocked(fetch).mockResolvedValue(response({status: 200, url: 'https://store.myshopify.com/fr-CA/password'})) // When const isProtected = await isStorefrontPasswordProtected('store.myshopify.com') @@ -83,9 +75,7 @@ describe('Storefront API', () => { test('returns false if response is not a 302', async () => { // Given - vi.mocked(fetch).mockResolvedValue( - response({status: 301, headers: {location: 'https://store.myshopify.com/random'}}), - ) + vi.mocked(fetch).mockResolvedValue(response({status: 200, url: 'https://store.myshopify.com/random'})) // When const isProtected = await isStorefrontPasswordProtected('store.myshopify.com') @@ -93,6 +83,21 @@ describe('Storefront API', () => { // Then expect(isProtected).toBe(false) }) + + test('ignores query params', async () => { + // Given + vi.mocked(fetch) + .mockResolvedValueOnce(response({status: 200, url: 'https://store.myshopify.com/random?a=b'})) + .mockResolvedValueOnce(response({status: 200, url: 'https://store.myshopify.com/password?a=b'})) + + // When + const redirectToRandomPath = await isStorefrontPasswordProtected('store.myshopify.com') + const redirectToPasswordPath = await isStorefrontPasswordProtected('store.myshopify.com') + + // Then + expect(redirectToRandomPath).toBe(false) + expect(redirectToPasswordPath).toBe(true) + }) }) describe('getStorefrontSessionCookies', () => { @@ -195,7 +200,12 @@ describe('Storefront API', () => { // Tests rely on this function because the 'packages/theme' package cannot // directly access node-fetch and they use: new Response('OK', {status: 200}) - function response(mock: {status: number; headers?: {[key: string]: string}; text?: () => Promise}) { + function response(mock: { + status: number + url?: string + headers?: {[key: string]: string} + text?: () => Promise + }) { const setCookieHeader = (mock.headers ?? {})['set-cookie'] ?? '' const setCookieArray = [setCookieHeader] @@ -237,6 +247,24 @@ describe('Storefront API', () => { }) }) + test('returns true when the password is correct and the store redirects to a localized URL', async () => { + // Given + vi.mocked(fetch).mockResolvedValueOnce( + response({ + status: 302, + headers: { + location: 'https://store.myshopify.com/en', + }, + }), + ) + + // When + const result = await isStorefrontPasswordCorrect('correct-password', 'store.myshopify.com') + + // Then + expect(result).toBe(true) + }) + test('returns true when the password is correct and the store name is capitalized', async () => { // Given vi.mocked(fetch).mockResolvedValueOnce( @@ -297,6 +325,24 @@ describe('Storefront API', () => { expect(result).toBe(false) }) + test('returns false when the redirect location has a different origin', async () => { + // Given + vi.mocked(fetch).mockResolvedValueOnce( + response({ + status: 302, + headers: { + location: 'https://another-store.myshopify.com/', + }, + }), + ) + + // When + const result = await isStorefrontPasswordCorrect('correct-password', 'store.myshopify.com') + + // Then + expect(result).toBe(false) + }) + test('throws an error when the server responds with "Too Many Requests"', async () => { // Given vi.mocked(fetch).mockResolvedValueOnce( diff --git a/packages/theme/src/cli/utilities/theme-environment/storefront-session.ts b/packages/theme/src/cli/utilities/theme-environment/storefront-session.ts index 40c68e12e93..b40fd26d605 100644 --- a/packages/theme/src/cli/utilities/theme-environment/storefront-session.ts +++ b/packages/theme/src/cli/utilities/theme-environment/storefront-session.ts @@ -9,12 +9,10 @@ export class ShopifyEssentialError extends Error {} export async function isStorefrontPasswordProtected(storeURL: string): Promise { const response = await fetch(prependHttps(storeURL), { method: 'GET', - redirect: 'manual', }) - if (response.status !== 302) return false - - return response.headers.get('location')?.endsWith('/password') ?? false + const redirectLocation = new URL(response.url) + return redirectLocation.pathname.endsWith('/password') } /** @@ -45,9 +43,21 @@ export async function isStorefrontPasswordCorrect(password: string | undefined, ) } - const isValidRedirect = new RegExp(`^${storeUrl}/?$`, 'i') + const locationHeader = response.headers.get('location') ?? '' + let redirectUrl: URL + + try { + redirectUrl = new URL(locationHeader, storeUrl) + } catch (error) { + if (error instanceof TypeError) { + return false + } + throw error + } + + const storeOrigin = new URL(storeUrl).origin - return response.status === 302 && isValidRedirect.test(response.headers.get('location') ?? '') + return response.status === 302 && redirectUrl.origin === storeOrigin } export async function getStorefrontSessionCookies( diff --git a/packages/theme/src/cli/utilities/theme-fs.test.ts b/packages/theme/src/cli/utilities/theme-fs.test.ts index 09b2b386ff4..9b09633dc77 100644 --- a/packages/theme/src/cli/utilities/theme-fs.test.ts +++ b/packages/theme/src/cli/utilities/theme-fs.test.ts @@ -398,10 +398,19 @@ describe('theme-fs', () => { {key: 'sections/announcement-bar.liquid', checksum: '10'}, {key: 'snippets/language-localization.liquid', checksum: '11'}, {key: 'templates/404.context.uk.json', checksum: '11'}, + {key: 'blocks/block.liquid', checksum: '12'}, ] // When - const {sectionLiquidFiles, otherLiquidFiles, templateJsonFiles, otherJsonFiles, configFiles, staticAssetFiles} = - partitionThemeFiles(files) + const { + sectionLiquidFiles, + otherLiquidFiles, + templateJsonFiles, + otherJsonFiles, + configFiles, + staticAssetFiles, + contextualizedJsonFiles, + blockLiquidFiles, + } = partitionThemeFiles(files) // Then expect(sectionLiquidFiles).toEqual([{key: 'sections/announcement-bar.liquid', checksum: '10'}]) @@ -421,6 +430,8 @@ describe('theme-fs', () => { {key: 'assets/base.css', checksum: '1'}, {key: 'assets/sparkle.gif', checksum: '3'}, ]) + expect(contextualizedJsonFiles).toEqual([{key: 'templates/404.context.uk.json', checksum: '11'}]) + expect(blockLiquidFiles).toEqual([{key: 'blocks/block.liquid', checksum: '12'}]) }) test('should handle empty file array', () => { diff --git a/packages/theme/src/cli/utilities/theme-fs.ts b/packages/theme/src/cli/utilities/theme-fs.ts index 1b6b211f0e7..820a8f68724 100644 --- a/packages/theme/src/cli/utilities/theme-fs.ts +++ b/packages/theme/src/cli/utilities/theme-fs.ts @@ -34,7 +34,7 @@ const THEME_DIRECTORY_PATTERNS = [ const THEME_PARTITION_REGEX = { sectionLiquidRegex: /^sections\/.+\.liquid$/, - liquidRegex: /\.liquid$/, + blockLiquidRegex: /^blocks\/.+\.liquid$/, configRegex: /^config\/(settings_schema|settings_data)\.json$/, sectionJsonRegex: /^sections\/.+\.json$/, templateJsonRegex: /^templates\/.+\.json$/, @@ -318,12 +318,15 @@ export function partitionThemeFiles(files: T[]) { const contextualizedJsonFiles: T[] = [] const configFiles: T[] = [] const staticAssetFiles: T[] = [] + const blockLiquidFiles: T[] = [] files.forEach((file) => { const fileKey = file.key if (fileKey.endsWith('.liquid')) { if (THEME_PARTITION_REGEX.sectionLiquidRegex.test(fileKey)) { sectionLiquidFiles.push(file) + } else if (THEME_PARTITION_REGEX.blockLiquidRegex.test(fileKey)) { + blockLiquidFiles.push(file) } else { otherLiquidFiles.push(file) } @@ -353,6 +356,7 @@ export function partitionThemeFiles(files: T[]) { otherJsonFiles, configFiles, staticAssetFiles, + blockLiquidFiles, } } diff --git a/packages/theme/src/cli/utilities/theme-ui.ts b/packages/theme/src/cli/utilities/theme-ui.ts index 5bd6e534b0e..1505304d1ba 100644 --- a/packages/theme/src/cli/utilities/theme-ui.ts +++ b/packages/theme/src/cli/utilities/theme-ui.ts @@ -16,12 +16,15 @@ export function themesComponent(themes: Theme[]) { return {list: {items}} } -export async function currentDirectoryConfirmed(force: boolean) { +export async function ensureDirectoryConfirmed( + force: boolean, + message = "It doesn't seem like you're running this command in a theme directory.", +) { if (force) { return true } - renderWarning({body: `It doesn't seem like you're running this command in a theme directory.`}) + renderWarning({body: message}) if (!process.stdout.isTTY) { return true diff --git a/packages/theme/src/cli/utilities/theme-uploader.test.ts b/packages/theme/src/cli/utilities/theme-uploader.test.ts index 1d09f7f3db3..eed1e2cae81 100644 --- a/packages/theme/src/cli/utilities/theme-uploader.test.ts +++ b/packages/theme/src/cli/utilities/theme-uploader.test.ts @@ -61,7 +61,7 @@ describe('theme-uploader', () => { ) // When - const {renderThemeSyncProgress} = await uploadTheme(remoteTheme, adminSession, remote, local, uploadOptions) + const {renderThemeSyncProgress} = uploadTheme(remoteTheme, adminSession, remote, local, uploadOptions) await renderThemeSyncProgress() // Then @@ -82,7 +82,7 @@ describe('theme-uploader', () => { ) // When - const {renderThemeSyncProgress} = await uploadTheme(remoteTheme, adminSession, remote, local, uploadOptions) + const {renderThemeSyncProgress} = uploadTheme(remoteTheme, adminSession, remote, local, uploadOptions) await renderThemeSyncProgress() // Then @@ -103,7 +103,7 @@ describe('theme-uploader', () => { ) // When - const {renderThemeSyncProgress} = await uploadTheme(remoteTheme, adminSession, remote, local, { + const {renderThemeSyncProgress} = uploadTheme(remoteTheme, adminSession, remote, local, { ...uploadOptions, nodelete: true, }) @@ -121,7 +121,7 @@ describe('theme-uploader', () => { const themeFileSystem = fakeThemeFileSystem('tmp', new Map([])) // When - const {renderThemeSyncProgress} = await uploadTheme( + const {renderThemeSyncProgress} = uploadTheme( remoteTheme, adminSession, remoteChecksums, @@ -142,7 +142,7 @@ describe('theme-uploader', () => { const themeFileSystem = fakeThemeFileSystem('tmp', new Map([])) // When - const {renderThemeSyncProgress} = await uploadTheme( + const {renderThemeSyncProgress} = uploadTheme( remoteTheme, adminSession, remoteChecksums, @@ -160,7 +160,7 @@ describe('theme-uploader', () => { const themeFileSystem = fakeThemeFileSystem('tmp', new Map([])) // When - const {renderThemeSyncProgress} = await uploadTheme(remoteTheme, adminSession, [], themeFileSystem, uploadOptions) + const {renderThemeSyncProgress} = uploadTheme(remoteTheme, adminSession, [], themeFileSystem, uploadOptions) await renderThemeSyncProgress() // Then @@ -180,7 +180,7 @@ describe('theme-uploader', () => { ) // When - const {renderThemeSyncProgress} = await uploadTheme( + const {renderThemeSyncProgress} = uploadTheme( remoteTheme, adminSession, remoteChecksums, @@ -220,7 +220,7 @@ describe('theme-uploader', () => { ) // When - const {renderThemeSyncProgress} = await uploadTheme( + const {renderThemeSyncProgress} = uploadTheme( remoteTheme, adminSession, remoteChecksums, @@ -256,7 +256,7 @@ describe('theme-uploader', () => { const themeFileSystem = fakeThemeFileSystem('tmp', new Map([])) // When - const {renderThemeSyncProgress} = await uploadTheme( + const {renderThemeSyncProgress} = uploadTheme( remoteTheme, adminSession, remoteChecksums, @@ -296,11 +296,12 @@ describe('theme-uploader', () => { ['templates/product.json', {key: 'templates/product.json', checksum: '6'}], ['assets/image.png', {key: 'assets/image.png', checksum: '7'}], ['templates/product.context.uk.json', {key: 'templates/product.context.uk.json', checksum: '8'}], + ['blocks/block.liquid', {key: 'blocks/block.liquid', checksum: '9'}], ]), ) // When - const {renderThemeSyncProgress} = await uploadTheme( + const {renderThemeSyncProgress} = uploadTheme( remoteTheme, adminSession, remoteChecksums, @@ -310,21 +311,17 @@ describe('theme-uploader', () => { await renderThemeSyncProgress() // Then - expect(bulkUploadThemeAssets).toHaveBeenCalledTimes(7) - // Mininum theme files start first + expect(bulkUploadThemeAssets).toHaveBeenCalledTimes(8) + // Minimum theme files start first expect(bulkUploadThemeAssets).toHaveBeenNthCalledWith(1, remoteTheme.id, MINIMUM_THEME_ASSETS, adminSession) // Dependent assets start second expect(bulkUploadThemeAssets).toHaveBeenNthCalledWith( 2, remoteTheme.id, - [ - { - key: 'sections/header.liquid', - }, - ], + [{key: 'blocks/block.liquid'}], adminSession, ) - // Independent assets start right before dependent assets start + // Independent assets start right after dependent assets start expect(bulkUploadThemeAssets).toHaveBeenNthCalledWith( 3, remoteTheme.id, @@ -347,17 +344,18 @@ describe('theme-uploader', () => { remoteTheme.id, [ { - key: 'sections/header-group.json', + key: 'sections/header.liquid', }, ], adminSession, ) + expect(bulkUploadThemeAssets).toHaveBeenNthCalledWith( 5, remoteTheme.id, [ { - key: 'templates/product.json', + key: 'sections/header-group.json', }, ], adminSession, @@ -367,7 +365,7 @@ describe('theme-uploader', () => { remoteTheme.id, [ { - key: 'templates/product.context.uk.json', + key: 'templates/product.json', }, ], adminSession, @@ -375,6 +373,16 @@ describe('theme-uploader', () => { expect(bulkUploadThemeAssets).toHaveBeenNthCalledWith( 7, remoteTheme.id, + [ + { + key: 'templates/product.context.uk.json', + }, + ], + adminSession, + ) + expect(bulkUploadThemeAssets).toHaveBeenNthCalledWith( + 8, + remoteTheme.id, [ { key: 'config/settings_data.json', @@ -401,7 +409,7 @@ describe('theme-uploader', () => { const themeFileSystem = fakeThemeFileSystem('tmp', files) // When - const {renderThemeSyncProgress} = await uploadTheme( + const {renderThemeSyncProgress} = uploadTheme( remoteTheme, adminSession, remoteChecksums, @@ -434,7 +442,7 @@ describe('theme-uploader', () => { ) // When - const {renderThemeSyncProgress} = await uploadTheme( + const {renderThemeSyncProgress} = uploadTheme( remoteTheme, adminSession, remoteChecksums, @@ -486,7 +494,7 @@ describe('theme-uploader', () => { ]) // When - const {renderThemeSyncProgress} = await uploadTheme( + const {renderThemeSyncProgress} = uploadTheme( remoteTheme, adminSession, remoteChecksums, @@ -543,7 +551,7 @@ describe('theme-uploader', () => { ) // When - const {renderThemeSyncProgress} = await uploadTheme(remoteTheme, adminSession, remote, local, uploadOptions) + const {renderThemeSyncProgress} = uploadTheme(remoteTheme, adminSession, remote, local, uploadOptions) await renderThemeSyncProgress() // Then @@ -576,7 +584,7 @@ describe('theme-uploader', () => { ) // When - const {renderThemeSyncProgress} = await uploadTheme(remoteTheme, adminSession, remote, localTheme, uploadOptions) + const {renderThemeSyncProgress} = uploadTheme(remoteTheme, adminSession, remote, localTheme, uploadOptions) await renderThemeSyncProgress() // Then diff --git a/packages/theme/src/cli/utilities/theme-uploader.ts b/packages/theme/src/cli/utilities/theme-uploader.ts index d720bd6f137..e98f977efe0 100644 --- a/packages/theme/src/cli/utilities/theme-uploader.ts +++ b/packages/theme/src/cli/utilities/theme-uploader.ts @@ -18,9 +18,9 @@ type ChecksumWithSize = Checksum & {size: number} type FileBatch = ChecksumWithSize[] // Limits for Bulk Requests -export const MAX_BATCH_FILE_COUNT = 10 -// 100KB -export const MAX_BATCH_BYTESIZE = 102400 +export const MAX_BATCH_FILE_COUNT = 50 +// 10MB +export const MAX_BATCH_BYTESIZE = 1024 * 1024 * 10 export const MAX_UPLOAD_RETRY_COUNT = 2 export function uploadTheme( @@ -168,6 +168,7 @@ function orderFilesToBeDeleted(files: Checksum[]): Checksum[] { ...fileSets.sectionJsonFiles, ...fileSets.otherJsonFiles, ...fileSets.sectionLiquidFiles, + ...fileSets.blockLiquidFiles, ...fileSets.otherLiquidFiles, ...fileSets.configFiles, ...fileSets.staticAssetFiles, @@ -176,8 +177,14 @@ function orderFilesToBeDeleted(files: Checksum[]): Checksum[] { export const MINIMUM_THEME_ASSETS = [ {key: 'config/settings_schema.json', value: '[]'}, - {key: 'layout/password.liquid', value: '{{ content_for_header }}{{ content_for_layout }}'}, - {key: 'layout/theme.liquid', value: '{{ content_for_header }}{{ content_for_layout }}'}, + { + key: 'layout/password.liquid', + value: '{{ content_for_header }}{{ content_for_layout }}', + }, + { + key: 'layout/theme.liquid', + value: '{{ content_for_header }}{{ content_for_layout }}', + }, ] as const /** * If there's no theme in the remote, we need to create it first so that @@ -231,11 +238,12 @@ function buildUploadJob( (promise, fileType) => promise.then(() => uploadFileBatches(fileType)), Promise.resolve(), ) - // Wait for dependent files upload to be started before starting this one: + + // Dependant and independant files are uploaded concurrently const independentFilesUploadPromise = Promise.resolve().then(() => uploadFileBatches(independentFiles.flat())) const promise = Promise.all([dependentFilesUploadPromise, independentFilesUploadPromise]).then(() => { - progress.current += progress.total + progress.current = progress.total }) return {progress, promise} @@ -283,6 +291,7 @@ function orderFilesToBeUploaded(files: ChecksumWithSize[]): { independentFiles: [fileSets.otherLiquidFiles, fileSets.otherJsonFiles, fileSets.staticAssetFiles], // Follow order of dependencies: dependentFiles: [ + fileSets.blockLiquidFiles, fileSets.sectionLiquidFiles, fileSets.sectionJsonFiles, fileSets.templateJsonFiles, diff --git a/packages/theme/src/index.ts b/packages/theme/src/index.ts index 387acb05db8..8a21dbfda58 100644 --- a/packages/theme/src/index.ts +++ b/packages/theme/src/index.ts @@ -9,6 +9,7 @@ import ListCommnd from './cli/commands/theme/list.js' import Open from './cli/commands/theme/open.js' import Package from './cli/commands/theme/package.js' import Publish from './cli/commands/theme/publish.js' +import MetafieldsPull from './cli/commands/theme/metafields/pull.js' import Pull from './cli/commands/theme/pull.js' import Push from './cli/commands/theme/push.js' import Rename from './cli/commands/theme/rename.js' @@ -24,6 +25,7 @@ const COMMANDS = { 'theme:info': ThemeInfo, 'theme:language-server': LanguageServer, 'theme:list': ListCommnd, + 'theme:metafields:pull': MetafieldsPull, 'theme:open': Open, 'theme:package': Package, 'theme:publish': Publish, diff --git a/packages/ui-extensions-dev-console/CHANGELOG.md b/packages/ui-extensions-dev-console/CHANGELOG.md index fca8a7acfb4..c0de98b4e28 100644 --- a/packages/ui-extensions-dev-console/CHANGELOG.md +++ b/packages/ui-extensions-dev-console/CHANGELOG.md @@ -1,5 +1,19 @@ # @shopify/ui-extensions-dev-console-app +## 3.72.0 + +## 3.71.5 + +## 3.71.4 + +## 3.71.3 + +## 3.71.2 + +## 3.71.1 + +## 3.71.0 + ## 3.70.0 ## 3.69.0 diff --git a/packages/ui-extensions-dev-console/package.json b/packages/ui-extensions-dev-console/package.json index 8ba983a53cd..7209301f40f 100644 --- a/packages/ui-extensions-dev-console/package.json +++ b/packages/ui-extensions-dev-console/package.json @@ -1,6 +1,6 @@ { "name": "@shopify/ui-extensions-dev-console-app", - "version": "3.70.0", + "version": "3.72.0", "private": true, "scripts": { "build": "nx build", diff --git a/packages/ui-extensions-server-kit/src/types.ts b/packages/ui-extensions-server-kit/src/types.ts index 123e052a29a..a17f4d98c9e 100644 --- a/packages/ui-extensions-server-kit/src/types.ts +++ b/packages/ui-extensions-server-kit/src/types.ts @@ -94,7 +94,7 @@ export interface ExtensionPoint { localization?: FlattenedLocalization | Localization | null name: string description?: string - shouldRender?: {scriptUrl?: string} + assets?: {[name: string]: Asset} } export type ExtensionPoints = string[] | ExtensionPoint[] | null diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5fc56655be9..2fd30d4e1b3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -69,8 +69,8 @@ importers: specifier: ^7.0.3 version: 7.0.3 esbuild: - specifier: 0.19.8 - version: 0.19.8 + specifier: 0.24.0 + version: 0.24.0 eslint: specifier: ^8.48.0 version: 8.57.0 @@ -148,18 +148,18 @@ importers: version: 3.2.0(graphql@16.8.1) '@luckycatfactory/esbuild-graphql-loader': specifier: 3.8.1 - version: 3.8.1(esbuild@0.19.8)(graphql-tag@2.12.6)(graphql@16.8.1) + version: 3.8.1(esbuild@0.24.0)(graphql-tag@2.12.6)(graphql@16.8.1) '@oclif/core': specifier: 3.26.5 version: 3.26.5 '@shopify/cli-kit': - specifier: 3.70.0 + specifier: 3.72.0 version: link:../cli-kit '@shopify/function-runner': specifier: 4.1.1 version: 4.1.1 '@shopify/plugin-cloudflare': - specifier: 3.70.0 + specifier: 3.72.0 version: link:../plugin-cloudflare '@shopify/polaris': specifier: 12.10.0 @@ -168,11 +168,11 @@ importers: specifier: 8.0.0 version: 8.0.0 '@shopify/theme': - specifier: 3.70.0 + specifier: 3.72.0 version: link:../theme '@shopify/theme-check-node': - specifier: 2.9.2 - version: 2.9.2 + specifier: 3.4.0 + version: 3.4.0 body-parser: specifier: 1.20.2 version: 1.20.2 @@ -186,8 +186,8 @@ importers: specifier: 5.1.0 version: 5.1.0 esbuild: - specifier: 0.19.8 - version: 0.19.8 + specifier: 0.24.0 + version: 0.24.0 express: specifier: 4.19.2 version: 4.19.2 @@ -200,9 +200,9 @@ importers: http-proxy: specifier: 1.18.1 version: 1.18.1 - micromatch: - specifier: 4.0.8 - version: 4.0.8 + ignore: + specifier: 6.0.2 + version: 6.0.2 proper-lockfile: specifier: 4.1.2 version: 4.1.2 @@ -228,9 +228,6 @@ importers: '@types/http-proxy': specifier: ^1.17.11 version: 1.17.14 - '@types/micromatch': - specifier: ^4.0.8 - version: 4.0.9 '@types/node': specifier: 18.19.3 version: 18.19.3 @@ -262,8 +259,8 @@ importers: specifier: 0.11.0 version: 0.11.0 esbuild: - specifier: 0.19.8 - version: 0.19.8 + specifier: 0.24.0 + version: 0.24.0 devDependencies: '@oclif/core': specifier: 3.26.5 @@ -275,22 +272,22 @@ importers: specifier: 5.1.2 version: 5.1.2 '@shopify/app': - specifier: 3.70.0 + specifier: 3.72.0 version: link:../app '@shopify/cli-hydrogen': - specifier: 9.0.2 - version: 9.0.2(@graphql-codegen/cli@5.0.2)(react-dom@17.0.2)(react@17.0.2) + specifier: 9.0.3 + version: 9.0.3(@graphql-codegen/cli@5.0.2)(react-dom@17.0.2)(react@17.0.2) '@shopify/cli-kit': - specifier: 3.70.0 + specifier: 3.72.0 version: link:../cli-kit '@shopify/plugin-cloudflare': - specifier: 3.70.0 + specifier: 3.72.0 version: link:../plugin-cloudflare '@shopify/plugin-did-you-mean': - specifier: 3.70.0 + specifier: 3.72.0 version: link:../plugin-did-you-mean '@shopify/theme': - specifier: 3.70.0 + specifier: 3.72.0 version: link:../theme '@types/node': specifier: 18.19.3 @@ -303,7 +300,7 @@ importers: version: 1.6.0(vitest@1.6.0) esbuild-plugin-copy: specifier: ^2.1.1 - version: 2.1.1(esbuild@0.19.8) + version: 2.1.1(esbuild@0.24.0) espree: specifier: 9.6.1 version: 9.6.1 @@ -537,14 +534,14 @@ importers: packages/create-app: dependencies: esbuild: - specifier: 0.19.8 - version: 0.19.8 + specifier: 0.24.0 + version: 0.24.0 devDependencies: '@shopify/app': - specifier: 3.70.0 + specifier: 3.72.0 version: link:../app '@shopify/cli-kit': - specifier: 3.70.0 + specifier: 3.72.0 version: link:../cli-kit '@types/node': specifier: 18.19.3 @@ -554,7 +551,7 @@ importers: version: 1.6.0(vitest@1.6.0) esbuild-plugin-copy: specifier: ^2.1.1 - version: 2.1.1(esbuild@0.19.8) + version: 2.1.1(esbuild@0.24.0) packages/eslint-plugin-cli: dependencies: @@ -668,7 +665,7 @@ importers: specifier: 3.26.5 version: 3.26.5 '@shopify/cli-kit': - specifier: 3.70.0 + specifier: 3.72.0 version: link:../cli-kit devDependencies: '@vitest/coverage-istanbul': @@ -681,7 +678,7 @@ importers: specifier: 3.26.5 version: 3.26.5 '@shopify/cli-kit': - specifier: 3.70.0 + specifier: 3.72.0 version: link:../cli-kit n-gram: specifier: 2.0.2 @@ -697,14 +694,14 @@ importers: specifier: 3.26.5 version: 3.26.5 '@shopify/cli-kit': - specifier: 3.70.0 + specifier: 3.72.0 version: link:../cli-kit '@shopify/theme-check-node': - specifier: 2.9.2 - version: 2.9.2 + specifier: 3.4.0 + version: 3.4.0 '@shopify/theme-language-server-node': - specifier: 1.14.0 - version: 1.14.0 + specifier: 2.3.2 + version: 2.3.2 chokidar: specifier: 3.5.3 version: 3.5.3 @@ -3700,11 +3697,11 @@ packages: requiresBuild: true optional: true - /@esbuild/android-arm64@0.19.8: - resolution: {integrity: sha512-B8JbS61bEunhfx8kasogFENgQfr/dIp+ggYXwTqdbMAgGDhRa3AaPpQMuQU0rNxDLECj6FhDzk1cF9WHMVwrtA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] + /@esbuild/aix-ppc64@0.24.0: + resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] requiresBuild: true optional: true @@ -3716,10 +3713,10 @@ packages: requiresBuild: true optional: true - /@esbuild/android-arm@0.19.8: - resolution: {integrity: sha512-31E2lxlGM1KEfivQl8Yf5aYU/mflz9g06H6S15ITUFQueMFtFjESRMoDSkvMo8thYvLBax+VKTPlpnx+sPicOA==} - engines: {node: '>=12'} - cpu: [arm] + /@esbuild/android-arm64@0.24.0: + resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} + engines: {node: '>=18'} + cpu: [arm64] os: [android] requiresBuild: true optional: true @@ -3732,10 +3729,10 @@ packages: requiresBuild: true optional: true - /@esbuild/android-x64@0.19.8: - resolution: {integrity: sha512-rdqqYfRIn4jWOp+lzQttYMa2Xar3OK9Yt2fhOhzFXqg0rVWEfSclJvZq5fZslnz6ypHvVf3CT7qyf0A5pM682A==} - engines: {node: '>=12'} - cpu: [x64] + /@esbuild/android-arm@0.24.0: + resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} + engines: {node: '>=18'} + cpu: [arm] os: [android] requiresBuild: true optional: true @@ -3748,11 +3745,11 @@ packages: requiresBuild: true optional: true - /@esbuild/darwin-arm64@0.19.8: - resolution: {integrity: sha512-RQw9DemMbIq35Bprbboyf8SmOr4UXsRVxJ97LgB55VKKeJOOdvsIPy0nFyF2l8U+h4PtBx/1kRf0BelOYCiQcw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] + /@esbuild/android-x64@0.24.0: + resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] requiresBuild: true optional: true @@ -3764,10 +3761,10 @@ packages: requiresBuild: true optional: true - /@esbuild/darwin-x64@0.19.8: - resolution: {integrity: sha512-3sur80OT9YdeZwIVgERAysAbwncom7b4bCI2XKLjMfPymTud7e/oY4y+ci1XVp5TfQp/bppn7xLw1n/oSQY3/Q==} - engines: {node: '>=12'} - cpu: [x64] + /@esbuild/darwin-arm64@0.24.0: + resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} + engines: {node: '>=18'} + cpu: [arm64] os: [darwin] requiresBuild: true optional: true @@ -3780,11 +3777,11 @@ packages: requiresBuild: true optional: true - /@esbuild/freebsd-arm64@0.19.8: - resolution: {integrity: sha512-WAnPJSDattvS/XtPCTj1tPoTxERjcTpH6HsMr6ujTT+X6rylVe8ggxk8pVxzf5U1wh5sPODpawNicF5ta/9Tmw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] + /@esbuild/darwin-x64@0.24.0: + resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] requiresBuild: true optional: true @@ -3796,10 +3793,10 @@ packages: requiresBuild: true optional: true - /@esbuild/freebsd-x64@0.19.8: - resolution: {integrity: sha512-ICvZyOplIjmmhjd6mxi+zxSdpPTKFfyPPQMQTK/w+8eNK6WV01AjIztJALDtwNNfFhfZLux0tZLC+U9nSyA5Zg==} - engines: {node: '>=12'} - cpu: [x64] + /@esbuild/freebsd-arm64@0.24.0: + resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} + engines: {node: '>=18'} + cpu: [arm64] os: [freebsd] requiresBuild: true optional: true @@ -3812,11 +3809,11 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-arm64@0.19.8: - resolution: {integrity: sha512-z1zMZivxDLHWnyGOctT9JP70h0beY54xDDDJt4VpTX+iwA77IFsE1vCXWmprajJGa+ZYSqkSbRQ4eyLCpCmiCQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] + /@esbuild/freebsd-x64@0.24.0: + resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] requiresBuild: true optional: true @@ -3828,10 +3825,10 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-arm@0.19.8: - resolution: {integrity: sha512-H4vmI5PYqSvosPaTJuEppU9oz1dq2A7Mr2vyg5TF9Ga+3+MGgBdGzcyBP7qK9MrwFQZlvNyJrvz6GuCaj3OukQ==} - engines: {node: '>=12'} - cpu: [arm] + /@esbuild/linux-arm64@0.24.0: + resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} + engines: {node: '>=18'} + cpu: [arm64] os: [linux] requiresBuild: true optional: true @@ -3844,10 +3841,10 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-ia32@0.19.8: - resolution: {integrity: sha512-1a8suQiFJmZz1khm/rDglOc8lavtzEMRo0v6WhPgxkrjcU0LkHj+TwBrALwoz/OtMExvsqbbMI0ChyelKabSvQ==} - engines: {node: '>=12'} - cpu: [ia32] + /@esbuild/linux-arm@0.24.0: + resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} + engines: {node: '>=18'} + cpu: [arm] os: [linux] requiresBuild: true optional: true @@ -3860,10 +3857,10 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-loong64@0.19.8: - resolution: {integrity: sha512-fHZWS2JJxnXt1uYJsDv9+b60WCc2RlvVAy1F76qOLtXRO+H4mjt3Tr6MJ5l7Q78X8KgCFudnTuiQRBhULUyBKQ==} - engines: {node: '>=12'} - cpu: [loong64] + /@esbuild/linux-ia32@0.24.0: + resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} + engines: {node: '>=18'} + cpu: [ia32] os: [linux] requiresBuild: true optional: true @@ -3876,10 +3873,10 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-mips64el@0.19.8: - resolution: {integrity: sha512-Wy/z0EL5qZYLX66dVnEg9riiwls5IYnziwuju2oUiuxVc+/edvqXa04qNtbrs0Ukatg5HEzqT94Zs7J207dN5Q==} - engines: {node: '>=12'} - cpu: [mips64el] + /@esbuild/linux-loong64@0.24.0: + resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} + engines: {node: '>=18'} + cpu: [loong64] os: [linux] requiresBuild: true optional: true @@ -3892,10 +3889,10 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-ppc64@0.19.8: - resolution: {integrity: sha512-ETaW6245wK23YIEufhMQ3HSeHO7NgsLx8gygBVldRHKhOlD1oNeNy/P67mIh1zPn2Hr2HLieQrt6tWrVwuqrxg==} - engines: {node: '>=12'} - cpu: [ppc64] + /@esbuild/linux-mips64el@0.24.0: + resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} + engines: {node: '>=18'} + cpu: [mips64el] os: [linux] requiresBuild: true optional: true @@ -3908,10 +3905,10 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-riscv64@0.19.8: - resolution: {integrity: sha512-T2DRQk55SgoleTP+DtPlMrxi/5r9AeFgkhkZ/B0ap99zmxtxdOixOMI570VjdRCs9pE4Wdkz7JYrsPvsl7eESg==} - engines: {node: '>=12'} - cpu: [riscv64] + /@esbuild/linux-ppc64@0.24.0: + resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} + engines: {node: '>=18'} + cpu: [ppc64] os: [linux] requiresBuild: true optional: true @@ -3924,10 +3921,10 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-s390x@0.19.8: - resolution: {integrity: sha512-NPxbdmmo3Bk7mbNeHmcCd7R7fptJaczPYBaELk6NcXxy7HLNyWwCyDJ/Xx+/YcNH7Im5dHdx9gZ5xIwyliQCbg==} - engines: {node: '>=12'} - cpu: [s390x] + /@esbuild/linux-riscv64@0.24.0: + resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} + engines: {node: '>=18'} + cpu: [riscv64] os: [linux] requiresBuild: true optional: true @@ -3940,10 +3937,10 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-x64@0.19.8: - resolution: {integrity: sha512-lytMAVOM3b1gPypL2TRmZ5rnXl7+6IIk8uB3eLsV1JwcizuolblXRrc5ShPrO9ls/b+RTp+E6gbsuLWHWi2zGg==} - engines: {node: '>=12'} - cpu: [x64] + /@esbuild/linux-s390x@0.24.0: + resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} + engines: {node: '>=18'} + cpu: [s390x] os: [linux] requiresBuild: true optional: true @@ -3956,11 +3953,11 @@ packages: requiresBuild: true optional: true - /@esbuild/netbsd-x64@0.19.8: - resolution: {integrity: sha512-hvWVo2VsXz/8NVt1UhLzxwAfo5sioj92uo0bCfLibB0xlOmimU/DeAEsQILlBQvkhrGjamP0/el5HU76HAitGw==} - engines: {node: '>=12'} + /@esbuild/linux-x64@0.24.0: + resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} + engines: {node: '>=18'} cpu: [x64] - os: [netbsd] + os: [linux] requiresBuild: true optional: true @@ -3972,10 +3969,18 @@ packages: requiresBuild: true optional: true - /@esbuild/openbsd-x64@0.19.8: - resolution: {integrity: sha512-/7Y7u77rdvmGTxR83PgaSvSBJCC2L3Kb1M/+dmSIvRvQPXXCuC97QAwMugBNG0yGcbEGfFBH7ojPzAOxfGNkwQ==} - engines: {node: '>=12'} + /@esbuild/netbsd-x64@0.24.0: + resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} + engines: {node: '>=18'} cpu: [x64] + os: [netbsd] + requiresBuild: true + optional: true + + /@esbuild/openbsd-arm64@0.24.0: + resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} + engines: {node: '>=18'} + cpu: [arm64] os: [openbsd] requiresBuild: true optional: true @@ -3988,11 +3993,11 @@ packages: requiresBuild: true optional: true - /@esbuild/sunos-x64@0.19.8: - resolution: {integrity: sha512-9Lc4s7Oi98GqFA4HzA/W2JHIYfnXbUYgekUP/Sm4BG9sfLjyv6GKKHKKVs83SMicBF2JwAX6A1PuOLMqpD001w==} - engines: {node: '>=12'} + /@esbuild/openbsd-x64@0.24.0: + resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} + engines: {node: '>=18'} cpu: [x64] - os: [sunos] + os: [openbsd] requiresBuild: true optional: true @@ -4004,11 +4009,11 @@ packages: requiresBuild: true optional: true - /@esbuild/win32-arm64@0.19.8: - resolution: {integrity: sha512-rq6WzBGjSzihI9deW3fC2Gqiak68+b7qo5/3kmB6Gvbh/NYPA0sJhrnp7wgV4bNwjqM+R2AApXGxMO7ZoGhIJg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] + /@esbuild/sunos-x64@0.24.0: + resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] requiresBuild: true optional: true @@ -4020,10 +4025,10 @@ packages: requiresBuild: true optional: true - /@esbuild/win32-ia32@0.19.8: - resolution: {integrity: sha512-AIAbverbg5jMvJznYiGhrd3sumfwWs8572mIJL5NQjJa06P8KfCPWZQ0NwZbPQnbQi9OWSZhFVSUWjjIrn4hSw==} - engines: {node: '>=12'} - cpu: [ia32] + /@esbuild/win32-arm64@0.24.0: + resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} + engines: {node: '>=18'} + cpu: [arm64] os: [win32] requiresBuild: true optional: true @@ -4036,10 +4041,10 @@ packages: requiresBuild: true optional: true - /@esbuild/win32-x64@0.19.8: - resolution: {integrity: sha512-bfZ0cQ1uZs2PqpulNL5j/3w+GDhP36k1K5c38QdQg+Swy51jFZWWeIkteNsufkQxp986wnqRRsb/bHbY1WQ7TA==} - engines: {node: '>=12'} - cpu: [x64] + /@esbuild/win32-ia32@0.24.0: + resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} + engines: {node: '>=18'} + cpu: [ia32] os: [win32] requiresBuild: true optional: true @@ -4052,6 +4057,14 @@ packages: requiresBuild: true optional: true + /@esbuild/win32-x64@0.24.0: + resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4962,14 +4975,14 @@ packages: /@kwsites/promise-deferred@1.1.1: resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} - /@luckycatfactory/esbuild-graphql-loader@3.8.1(esbuild@0.19.8)(graphql-tag@2.12.6)(graphql@16.8.1): + /@luckycatfactory/esbuild-graphql-loader@3.8.1(esbuild@0.24.0)(graphql-tag@2.12.6)(graphql@16.8.1): resolution: {integrity: sha512-ovONIUSW6NAlCpiPMaVw4PpdFoO3Kqi8TGQ2hTtjKTQTdPpSOdekPI1ZRnwciTeUn0yCAQk7M2xdrbIZeTh6pw==} peerDependencies: esbuild: '>=0.8.26' graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 graphql-tag: ^2.11.0 dependencies: - esbuild: 0.19.8 + esbuild: 0.24.0 graphql: 16.8.1 graphql-tag: 2.12.6(graphql@16.8.1) dev: false @@ -6026,8 +6039,8 @@ packages: requiresBuild: true optional: true - /@shopify/cli-hydrogen@9.0.2(@graphql-codegen/cli@5.0.2)(react-dom@17.0.2)(react@17.0.2): - resolution: {integrity: sha512-KRlBmgik6fdzIw8z9Xj31swE2dIgTFavCSTS/tonumlu2RX5DrT2M+OTjiQv8s6wLJn5a4Nn6/+5Ds/hKGaKEQ==} + /@shopify/cli-hydrogen@9.0.3(@graphql-codegen/cli@5.0.2)(react-dom@17.0.2)(react@17.0.2): + resolution: {integrity: sha512-xqNx1P9aBao1eqT7nVdsiw8o7j5ZMpuVaZOnYNfVw7Wog2wNtghH8UI6Jb0TklnTon+imQtJKY5ErYlGfgSssQ==} engines: {node: '>=18.0.0'} hasBin: true peerDependencies: @@ -6055,7 +6068,7 @@ packages: '@graphql-codegen/cli': 5.0.2(@types/node@18.19.3)(graphql@16.8.1)(typescript@5.2.2) '@oclif/core': 3.26.5 '@shopify/cli-kit': link:packages/cli-kit - '@shopify/oxygen-cli': 4.5.3(@oclif/core@3.26.5)(@shopify/cli-kit@packages+cli-kit) + '@shopify/oxygen-cli': 4.6.0(@oclif/core@3.26.5)(@shopify/cli-kit@packages+cli-kit) '@shopify/plugin-cloudflare': link:packages/plugin-cloudflare ansi-escapes: 6.2.0 chokidar: 3.5.3 @@ -6156,15 +6169,15 @@ packages: engines: {node: '>=12.14.0'} dev: false - /@shopify/liquid-html-parser@2.0.5: - resolution: {integrity: sha512-MYp/fe3jSjzmRu6HlbaG/1IJpdB39iShdvnc5biDPjlBhLr0PH/2rHXVdthlAcYDhJvd7DTd7TV0kl3erpUNGg==} + /@shopify/liquid-html-parser@2.2.0: + resolution: {integrity: sha512-hD0XV+Re9BC3yMOshHCwU94LagW7LQTWPdtpU0IE/pMbco+ke7Hir1Ad7eloHAgzR+6iw4LzDEFuHFpKZWmGKw==} dependencies: line-column: 1.0.2 ohm-js: 16.6.0 dev: false - /@shopify/oxygen-cli@4.5.3(@oclif/core@3.26.5)(@shopify/cli-kit@packages+cli-kit): - resolution: {integrity: sha512-mCpseNEqDbR26fPmIKL83BDsYSxXu/eeWrRGTG8cdQhq1z+xbDn93w/So/gi0r0MRH2vYsPOzJOIUyiWWVawDQ==} + /@shopify/oxygen-cli@4.6.0(@oclif/core@3.26.5)(@shopify/cli-kit@packages+cli-kit): + resolution: {integrity: sha512-Khph5joWTkwhAjh1Uq7/7widK1AMDnoQkT3JZboeUjzSH1M95XhOY7Hs57l6TNLsMHjkDG/8/nAzLkJ7mHNkkQ==} engines: {node: '>=18.12.0'} os: [darwin, linux, win32] hasBin: true @@ -6275,10 +6288,10 @@ packages: react-reconciler: 0.26.2(react@17.0.2) dev: true - /@shopify/theme-check-common@2.9.2: - resolution: {integrity: sha512-GXlRRNFXKQdYTgLrA3eAamlpDtZVAYr12UeXyiHxmkk0mmoozkpbtw30yX67FgGVdplM0YSAa7MQ7yHeznPfig==} + /@shopify/theme-check-common@3.4.0: + resolution: {integrity: sha512-raBezxKmlqy5sYJO2UYKc5b7hRVDeYPYfL9mBSqCqwa37jTkvy84U8G0IRjL8S/AfZWBHd2dJzhJ5RApONVijA==} dependencies: - '@shopify/liquid-html-parser': 2.0.5 + '@shopify/liquid-html-parser': 2.2.0 cross-fetch: 4.0.0 json-to-ast: 2.1.0 jsonc-parser: 3.2.1 @@ -6286,37 +6299,39 @@ packages: lodash-es: 4.17.21 minimatch: 9.0.3 vscode-json-languageservice: 5.3.11 + vscode-uri: 3.0.8 transitivePeerDependencies: - encoding dev: false - /@shopify/theme-check-docs-updater@2.9.2: - resolution: {integrity: sha512-ZGewVePcYvyeOSAwQOf/K/gYsLENfK0guQB3DZ809btslw0FGQtFL5lhyawcof4UEOkPSl2O/swvA72DPbDYlg==} + /@shopify/theme-check-docs-updater@3.4.0: + resolution: {integrity: sha512-4CdHvM1NhZhAtAe1VTsHfxcq8f17wIQYiq/u5s+niisM7cIYeyx7UfU5+ioIn+zE8K3cN9C/0riTgsZCBpDXJA==} hasBin: true dependencies: - '@shopify/theme-check-common': 2.9.2 + '@shopify/theme-check-common': 3.4.0 env-paths: 2.2.1 node-fetch: 2.7.0 transitivePeerDependencies: - encoding dev: false - /@shopify/theme-check-node@2.9.2: - resolution: {integrity: sha512-mS0gtSsjF9LxavruE3V4eNFLU26kcAuvNPExvFI7oxOpuHDRHOPqaeR74zcgmBBoQwz4XqoI4ZyhBPF6k3Oesw==} + /@shopify/theme-check-node@3.4.0: + resolution: {integrity: sha512-jekHMoktdD5xImSwsIPsFqn8c0TBejwypgjaEWyPqy6XF/QrPqCNtEstfsBRAWHLKqOgt/mFZumtN7Fmh2c4kQ==} dependencies: - '@shopify/theme-check-common': 2.9.2 - '@shopify/theme-check-docs-updater': 2.9.2 + '@shopify/theme-check-common': 3.4.0 + '@shopify/theme-check-docs-updater': 3.4.0 glob: 8.1.0 + vscode-uri: 3.0.8 yaml: 2.3.2 transitivePeerDependencies: - encoding dev: false - /@shopify/theme-language-server-common@1.14.0: - resolution: {integrity: sha512-7wC0Vh+mGIiHxK/eQ0Lef0QslNKXXvEMLh19UMAO/iMdE6m6nXwcyhUuEgEtxI3pcaEC+oeGiyEjrKT64vfQBA==} + /@shopify/theme-language-server-common@2.3.2: + resolution: {integrity: sha512-GjrKjgjIL+QdQMbgcz9Xb4YG4Y6NHgqY0lsKghIhCJr0oedM5ICtFmYobLQE9YXabDnP3FqyfliGUcjVgIeyMA==} dependencies: - '@shopify/liquid-html-parser': 2.0.5 - '@shopify/theme-check-common': 2.9.2 + '@shopify/liquid-html-parser': 2.2.0 + '@shopify/theme-check-common': 3.4.0 '@vscode/web-custom-data': 0.4.9 vscode-json-languageservice: 5.3.11 vscode-languageserver: 8.1.0 @@ -6326,12 +6341,12 @@ packages: - encoding dev: false - /@shopify/theme-language-server-node@1.14.0: - resolution: {integrity: sha512-V7XGrdMyoo5KuZekK+1z9/pPcWjj/Pj1sGAObscm5OqeDGJAxPORunBOhfUFntH149wNVyEhcu3GpLmDMgf2Ow==} + /@shopify/theme-language-server-node@2.3.2: + resolution: {integrity: sha512-LjqTln6NXkN+fIosBdDLrUzec+HsbPtfQ2xXd0cZOq3TMZeFCF4sgHw76L5YDoUp/FnPkJQlkG76g3ZokjkhXw==} dependencies: - '@shopify/theme-check-docs-updater': 2.9.2 - '@shopify/theme-check-node': 2.9.2 - '@shopify/theme-language-server-common': 1.14.0 + '@shopify/theme-check-docs-updater': 3.4.0 + '@shopify/theme-check-node': 3.4.0 + '@shopify/theme-language-server-common': 2.3.2 glob: 8.1.0 node-fetch: 2.7.0 vscode-languageserver: 8.1.0 @@ -6879,10 +6894,6 @@ packages: '@types/node': 18.19.3 dev: true - /@types/braces@3.0.4: - resolution: {integrity: sha512-0WR3b8eaISjEW7RpZnclONaLFDf7buaowRHdqLp4vLj54AsSAYWfh3DRbfiYJY9XDxMgx1B4sE1Afw2PGpuHOA==} - dev: true - /@types/cli-progress@3.11.5: resolution: {integrity: sha512-D4PbNRbviKyppS5ivBGyFO29POlySLmA2HyUFE4p5QGazAMM3CwkKWcvTl8gvElSuxRh6FPKL8XmidX873ou4g==} dependencies: @@ -7004,12 +7015,6 @@ packages: resolution: {integrity: sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==} dev: true - /@types/micromatch@4.0.9: - resolution: {integrity: sha512-7V+8ncr22h4UoYRLnLXSpTxjQrNUXtWHGeMPRJt1nULXI57G9bIcpyrHlmrQ7QK24EyyuXvYcSSWAM8GA9nqCg==} - dependencies: - '@types/braces': 3.0.4 - dev: true - /@types/mime@1.3.5: resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} dev: true @@ -9631,47 +9636,18 @@ packages: is-date-object: 1.0.5 is-symbol: 1.0.4 - /esbuild-plugin-copy@2.1.1(esbuild@0.19.8): + /esbuild-plugin-copy@2.1.1(esbuild@0.24.0): resolution: {integrity: sha512-Bk66jpevTcV8KMFzZI1P7MZKZ+uDcrZm2G2egZ2jNIvVnivDpodZI+/KnpL3Jnap0PBdIHU7HwFGB8r+vV5CVw==} peerDependencies: esbuild: '>= 0.14.0' dependencies: chalk: 4.1.2 chokidar: 3.5.3 - esbuild: 0.19.8 + esbuild: 0.24.0 fs-extra: 10.1.0 globby: 11.1.0 dev: true - /esbuild@0.19.8: - resolution: {integrity: sha512-l7iffQpT2OrZfH2rXIp7/FkmaeZM0vxbxN9KfiCwGYuZqzMg/JdvX26R31Zxn/Pxvsrg3Y9N6XTcnknqDyyv4w==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.19.8 - '@esbuild/android-arm64': 0.19.8 - '@esbuild/android-x64': 0.19.8 - '@esbuild/darwin-arm64': 0.19.8 - '@esbuild/darwin-x64': 0.19.8 - '@esbuild/freebsd-arm64': 0.19.8 - '@esbuild/freebsd-x64': 0.19.8 - '@esbuild/linux-arm': 0.19.8 - '@esbuild/linux-arm64': 0.19.8 - '@esbuild/linux-ia32': 0.19.8 - '@esbuild/linux-loong64': 0.19.8 - '@esbuild/linux-mips64el': 0.19.8 - '@esbuild/linux-ppc64': 0.19.8 - '@esbuild/linux-riscv64': 0.19.8 - '@esbuild/linux-s390x': 0.19.8 - '@esbuild/linux-x64': 0.19.8 - '@esbuild/netbsd-x64': 0.19.8 - '@esbuild/openbsd-x64': 0.19.8 - '@esbuild/sunos-x64': 0.19.8 - '@esbuild/win32-arm64': 0.19.8 - '@esbuild/win32-ia32': 0.19.8 - '@esbuild/win32-x64': 0.19.8 - /esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} @@ -9702,6 +9678,37 @@ packages: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 + /esbuild@0.24.0: + resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} + engines: {node: '>=18'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.24.0 + '@esbuild/android-arm': 0.24.0 + '@esbuild/android-arm64': 0.24.0 + '@esbuild/android-x64': 0.24.0 + '@esbuild/darwin-arm64': 0.24.0 + '@esbuild/darwin-x64': 0.24.0 + '@esbuild/freebsd-arm64': 0.24.0 + '@esbuild/freebsd-x64': 0.24.0 + '@esbuild/linux-arm': 0.24.0 + '@esbuild/linux-arm64': 0.24.0 + '@esbuild/linux-ia32': 0.24.0 + '@esbuild/linux-loong64': 0.24.0 + '@esbuild/linux-mips64el': 0.24.0 + '@esbuild/linux-ppc64': 0.24.0 + '@esbuild/linux-riscv64': 0.24.0 + '@esbuild/linux-s390x': 0.24.0 + '@esbuild/linux-x64': 0.24.0 + '@esbuild/netbsd-x64': 0.24.0 + '@esbuild/openbsd-arm64': 0.24.0 + '@esbuild/openbsd-x64': 0.24.0 + '@esbuild/sunos-x64': 0.24.0 + '@esbuild/win32-arm64': 0.24.0 + '@esbuild/win32-ia32': 0.24.0 + '@esbuild/win32-x64': 0.24.0 + /escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} @@ -11303,6 +11310,11 @@ packages: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} + /ignore@6.0.2: + resolution: {integrity: sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==} + engines: {node: '>= 4'} + dev: false + /immutable@3.7.6: resolution: {integrity: sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==} engines: {node: '>=0.8.0'} @@ -11338,6 +11350,7 @@ packages: /inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. dependencies: once: 1.4.0 wrappy: 1.0.2 diff --git a/shipit.stable_3_71.yml b/shipit.stable_3_71.yml new file mode 100644 index 00000000000..478d2dbd540 --- /dev/null +++ b/shipit.stable_3_71.yml @@ -0,0 +1,24 @@ +ci: + require: [] + +dependencies: + override: + # We are making sure the deploys point to the NPM registry to prevent + # 404 issues like the one described in this comment: + # https://github.com/yarnpkg/yarn/issues/2935#issuecomment-355292633 + - echo 'registry "https://registry.npmjs.org/"' | tee .npmrc .yarnrc + - curl -fsSL https://get.pnpm.io/install.sh | PNPM_VERSION=8.15.7 SHELL=`which bash` bash - + - bash -i -c "pnpm install" +deploy: + override: + - bash -i -c "npm_config_loglevel=verbose pnpm clean" + - bash -i -c "npm_config_loglevel=verbose NODE_ENV=production pnpm bundle" + - bash -i -c "npm_config_loglevel=verbose node bin/create-cli-duplicate-package.js" + - bash -i -c "npm_config_loglevel=verbose pnpm changeset publish" + # When this is no longer the latest stable version, do 2 things: + # 1. Replace the previous line with this, replacing 3.x with the actual version: + # - bash -i -c "npm_config_loglevel=verbose pnpm changeset publish --tag stable-3.x" + # This will prevent publishes from being tagged as latest. + # 2. Remove the following 2 lines, which update Homebrew and Shopify.dev docs + - bash -i -c "./bin/package.js" + - bash -i -c "./bin/create-doc-pr.js"