shoplazza-cli 1.1.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/LICENSE +21 -0
- package/README.md +206 -332
- package/README.zh.md +318 -0
- package/package.json +24 -70
- package/scripts/install.js +144 -0
- package/scripts/jsbuild/dev/index.js +123 -0
- package/scripts/jsbuild/index.js +77 -0
- package/{lib/checkout/build → scripts/jsbuild}/plugin/vite-plugin-add-extension-id.js +4 -2
- package/scripts/jsbuild/vite.config.js +35 -0
- package/scripts/run.js +29 -0
- package/.editorconfig +0 -28
- package/.prettierrc +0 -9
- package/bin/shoplazza +0 -137
- package/fixtures/assets/blog.scss +0 -74
- package/fixtures/assets/cart_modal.scss +0 -450
- package/fixtures/assets/collection_detail.js +0 -234
- package/fixtures/assets/collection_detail.scss +0 -345
- package/fixtures/assets/collection_list.scss +0 -11
- package/fixtures/assets/collection_slider.scss +0 -169
- package/fixtures/assets/feature_columns.scss +0 -26
- package/fixtures/assets/feature_product.scss +0 -109
- package/fixtures/assets/footer.js +0 -58
- package/fixtures/assets/footer.scss +0 -337
- package/fixtures/assets/four_images.scss +0 -29
- package/fixtures/assets/gallery.scss +0 -55
- package/fixtures/assets/header.js +0 -178
- package/fixtures/assets/header.scss +0 -929
- package/fixtures/assets/image_text.scss +0 -72
- package/fixtures/assets/logo_bar.scss +0 -11
- package/fixtures/assets/newsletter.scss +0 -90
- package/fixtures/assets/not_found.scss +0 -39
- package/fixtures/assets/page_detail.scss +0 -16
- package/fixtures/assets/pagination.scss +0 -150
- package/fixtures/assets/postcss.config.js +0 -6
- package/fixtures/assets/product_description.scss +0 -88
- package/fixtures/assets/product_detail.js +0 -634
- package/fixtures/assets/product_detail.scss +0 -1106
- package/fixtures/assets/relative_product.scss +0 -45
- package/fixtures/assets/reviews.scss +0 -70
- package/fixtures/assets/rich_text.scss +0 -71
- package/fixtures/assets/search.js +0 -87
- package/fixtures/assets/search.scss +0 -67
- package/fixtures/assets/slide.scss +0 -51
- package/fixtures/assets/slider.scss +0 -141
- package/fixtures/assets/test.scss +0 -1
- package/fixtures/assets/theme.css +0 -976
- package/fixtures/assets/theme.scss +0 -1100
- package/fixtures/assets/three_images.scss +0 -20
- package/fixtures/assets/tools.scss +0 -23
- package/fixtures/assets/two_images.scss +0 -24
- package/fixtures/assets/video.scss +0 -45
- package/fixtures/assets/video_text.scss +0 -63
- package/fixtures/config/settings_data.json +0 -107
- package/fixtures/config/settings_schema.json +0 -690
- package/fixtures/layout/theme.liquid +0 -76
- package/fixtures/locales/ar-SA.json +0 -212
- package/fixtures/locales/de-DE.json +0 -290
- package/fixtures/locales/en-US.json +0 -290
- package/fixtures/locales/es-ES.json +0 -290
- package/fixtures/locales/fr-FR.json +0 -290
- package/fixtures/locales/id-ID.json +0 -212
- package/fixtures/locales/it-IT.json +0 -212
- package/fixtures/locales/ja-JP.json +0 -289
- package/fixtures/locales/ko-KR.json +0 -290
- package/fixtures/locales/nl-NL.json +0 -290
- package/fixtures/locales/pl-PL.json +0 -290
- package/fixtures/locales/pt-PT.json +0 -212
- package/fixtures/locales/ru-RU.json +0 -212
- package/fixtures/locales/th-TH.json +0 -212
- package/fixtures/locales/zh-CN.json +0 -290
- package/fixtures/locales/zh-TW.json +0 -290
- package/fixtures/sections/apps.liquid +0 -47
- package/fixtures/sections/blog.liquid +0 -137
- package/fixtures/sections/collection_desc.liquid +0 -34
- package/fixtures/sections/collection_detail.liquid +0 -436
- package/fixtures/sections/collection_image.liquid +0 -104
- package/fixtures/sections/collection_list.liquid +0 -161
- package/fixtures/sections/collection_name.liquid +0 -34
- package/fixtures/sections/collection_slider.liquid +0 -330
- package/fixtures/sections/feature_columns.liquid +0 -275
- package/fixtures/sections/feature_product.liquid +0 -227
- package/fixtures/sections/footer.liquid +0 -488
- package/fixtures/sections/four_images.liquid +0 -160
- package/fixtures/sections/gallery.liquid +0 -258
- package/fixtures/sections/header.liquid +0 -1157
- package/fixtures/sections/html.liquid +0 -40
- package/fixtures/sections/image_text.liquid +0 -350
- package/fixtures/sections/instagram_plus.liquid +0 -393
- package/fixtures/sections/logo_bar.liquid +0 -183
- package/fixtures/sections/newsletter.liquid +0 -225
- package/fixtures/sections/not_found.liquid +0 -39
- package/fixtures/sections/overlay_image.liquid +0 -648
- package/fixtures/sections/page_detail.liquid +0 -39
- package/fixtures/sections/photo_collection.liquid +0 -433
- package/fixtures/sections/product_description.liquid +0 -208
- package/fixtures/sections/product_detail.liquid +0 -611
- package/fixtures/sections/products.liquid +0 -216
- package/fixtures/sections/relative_product.liquid +0 -121
- package/fixtures/sections/reviews.liquid +0 -115
- package/fixtures/sections/rich_text.liquid +0 -157
- package/fixtures/sections/search.liquid +0 -163
- package/fixtures/sections/slide.liquid +0 -719
- package/fixtures/sections/three_images.liquid +0 -157
- package/fixtures/sections/two_images.liquid +0 -125
- package/fixtures/sections/video.liquid +0 -95
- package/fixtures/sections/video_text.liquid +0 -128
- package/fixtures/snippets/bgset.liquid +0 -21
- package/fixtures/snippets/card_title.liquid +0 -8
- package/fixtures/snippets/cart_modal.liquid +0 -74
- package/fixtures/snippets/collection.liquid +0 -77
- package/fixtures/snippets/collection_filter_modal.liquid +0 -56
- package/fixtures/snippets/default_image_4.liquid +0 -14
- package/fixtures/snippets/default_image_6.liquid +0 -18
- package/fixtures/snippets/default_image_8.liquid +0 -23
- package/fixtures/snippets/four_images_item.liquid +0 -8
- package/fixtures/snippets/header_ads.liquid +0 -95
- package/fixtures/snippets/hero_image.liquid +0 -94
- package/fixtures/snippets/icon_video_play_large.liquid +0 -1
- package/fixtures/snippets/icon_video_play_medium.liquid +0 -4
- package/fixtures/snippets/icon_video_play_small.liquid +0 -4
- package/fixtures/snippets/lazyimg.liquid +0 -22
- package/fixtures/snippets/lazyimg_art.liquid +0 -36
- package/fixtures/snippets/lazysizes.liquid +0 -41
- package/fixtures/snippets/link.liquid +0 -2
- package/fixtures/snippets/pagination.liquid +0 -48
- package/fixtures/snippets/product.liquid +0 -126
- package/fixtures/snippets/product_art_tpl.liquid +0 -152
- package/fixtures/snippets/product_info_body.liquid +0 -337
- package/fixtures/snippets/product_info_tpl.liquid +0 -423
- package/fixtures/snippets/product_label.liquid +0 -46
- package/fixtures/snippets/settings.liquid +0 -295
- package/fixtures/snippets/social-meta-tags.liquid +0 -106
- package/fixtures/snippets/video_html.liquid +0 -11
- package/fixtures/snippets/video_source.liquid +0 -98
- package/fixtures/snippets/video_thumb_icon.liquid +0 -2
- package/fixtures/templates/404.liquid +0 -1
- package/fixtures/templates/collection.liquid +0 -92
- package/fixtures/templates/index.liquid +0 -206
- package/fixtures/templates/page.liquid +0 -1
- package/fixtures/templates/product.liquid +0 -99
- package/fixtures/templates/search.liquid +0 -1
- package/jest.config.js +0 -192
- package/lib/__tests__/log.test.js +0 -15
- package/lib/__tests__/utils.test.js +0 -69
- package/lib/app/api/cli.js +0 -225
- package/lib/app/api/openapi.js +0 -121
- package/lib/app/api/partnerOpenapi.js +0 -104
- package/lib/app/bin/index.js +0 -20
- package/lib/app/bin/javy/javy-arm-linux-v5.0.1 +0 -0
- package/lib/app/bin/javy/javy-arm-macos-v5.0.1 +0 -0
- package/lib/app/bin/javy/javy-x86_64-linux-v5.0.1 +0 -0
- package/lib/app/bin/javy/javy-x86_64-macos-v5.0.1 +0 -0
- package/lib/app/bin/javy/javy-x86_64-windows-v5.0.1 +0 -0
- package/lib/app/commands/config/actions/link.js +0 -189
- package/lib/app/commands/config/actions/use.js +0 -40
- package/lib/app/commands/config/index.js +0 -25
- package/lib/app/commands/config/link.js +0 -11
- package/lib/app/commands/config/use.js +0 -11
- package/lib/app/commands/deploy/actions/deploy.js +0 -196
- package/lib/app/commands/deploy/index.js +0 -11
- package/lib/app/commands/dev/actions/dev.js +0 -206
- package/lib/app/commands/dev/index.js +0 -11
- package/lib/app/commands/generate/actions/extension.js +0 -97
- package/lib/app/commands/generate/actions/generateCheckout.js +0 -58
- package/lib/app/commands/generate/actions/generateFunction.js +0 -56
- package/lib/app/commands/generate/actions/generateTheme.js +0 -128
- package/lib/app/commands/generate/extension.js +0 -11
- package/lib/app/commands/generate/index.js +0 -22
- package/lib/app/commands/index.js +0 -82
- package/lib/app/commands/info/actions/info.js +0 -168
- package/lib/app/commands/info/index.js +0 -11
- package/lib/app/commands/init/actions/init.js +0 -176
- package/lib/app/commands/init/index.js +0 -14
- package/lib/app/commands/versions/actions/list.js +0 -210
- package/lib/app/commands/versions/index.js +0 -22
- package/lib/app/commands/versions/list.js +0 -14
- package/lib/app/constant/code.js +0 -7
- package/lib/app/constant/color.js +0 -18
- package/lib/app/constant/extension.js +0 -16
- package/lib/app/constant/host.js +0 -23
- package/lib/app/constant/sso.js +0 -7
- package/lib/app/index.js +0 -8
- package/lib/app/services/auth/config.js +0 -33
- package/lib/app/services/auth/index.js +0 -9
- package/lib/app/services/auth/oauth-server.js +0 -70
- package/lib/app/services/auth/partner-token.js +0 -45
- package/lib/app/services/auth/sso-token.js +0 -69
- package/lib/app/services/auth/store-token.js +0 -100
- package/lib/app/services/auth/url-builder.js +0 -23
- package/lib/app/services/config/index.js +0 -41
- package/lib/app/services/devServer/app.js +0 -76
- package/lib/app/services/devServer/index.js +0 -103
- package/lib/app/services/devServer/middleware/hmacValidatorMiddleWare.js +0 -20
- package/lib/app/services/devServer/middleware/index.js +0 -5
- package/lib/app/services/devServer/tunnel/index.js +0 -43
- package/lib/app/services/devServer/tunnel/providers/cloudflare.js +0 -364
- package/lib/app/services/devServer/tunnel/providers/ngrok.js +0 -70
- package/lib/app/services/devServer/utils/index.js +0 -5
- package/lib/app/services/devServer/utils/secureCompare.js +0 -5
- package/lib/app/services/devServer/views/app.ejs +0 -133
- package/lib/app/services/extension-build/buildCheckout.js +0 -47
- package/lib/app/services/extension-build/buildFunction.js +0 -57
- package/lib/app/services/extension-build/buildTheme.js +0 -100
- package/lib/app/services/extension-build/index.js +0 -23
- package/lib/app/services/extension-build/plugins/vite-plugin-add-extension-id.js +0 -26
- package/lib/app/services/extension-diff/index.js +0 -132
- package/lib/app/services/extension-upsert/index.js +0 -21
- package/lib/app/services/extension-upsert/upsertCheckout.js +0 -44
- package/lib/app/services/extension-upsert/upsertFunction.js +0 -52
- package/lib/app/services/extension-upsert/upsertTheme.js +0 -113
- package/lib/app/services/oss/index.js +0 -45
- package/lib/app/services/partner/index.js +0 -52
- package/lib/app/store/base-store.js +0 -37
- package/lib/app/store/config-store.js +0 -55
- package/lib/app/store/config.js +0 -21
- package/lib/app/store/index.js +0 -14
- package/lib/app/store/install-store.js +0 -41
- package/lib/app/store/sso-store.js +0 -55
- package/lib/app/utils/asyncPool.js +0 -42
- package/lib/app/utils/debug/index.js +0 -16
- package/lib/app/utils/env.js +0 -24
- package/lib/app/utils/error.js +0 -20
- package/lib/app/utils/git.js +0 -20
- package/lib/app/utils/json.js +0 -27
- package/lib/app/utils/path.js +0 -33
- package/lib/app/utils/platform.js +0 -37
- package/lib/app/utils/request/cli.js +0 -72
- package/lib/app/utils/request/debug.js +0 -13
- package/lib/app/utils/request/openapi.js +0 -67
- package/lib/app/utils/request/partnerOpenapi.js +0 -47
- package/lib/app/utils/toml.js +0 -56
- package/lib/app/utils/views/message.js +0 -68
- package/lib/app/utils/views/select.js +0 -36
- package/lib/app/utils/withTempDir.js +0 -55
- package/lib/auth/__mocks__/getCode.js +0 -7
- package/lib/auth/__mocks__/index.js +0 -0
- package/lib/auth/child.js +0 -23
- package/lib/auth/getCode.js +0 -39
- package/lib/auth/index.js +0 -134
- package/lib/check.js +0 -28
- package/lib/checkout/api.js +0 -164
- package/lib/checkout/build/plugin/vite-plugin-transform-extension-html.js +0 -207
- package/lib/checkout/build/vite.config.js +0 -34
- package/lib/checkout/build.js +0 -38
- package/lib/checkout/config.js +0 -97
- package/lib/checkout/create.js +0 -132
- package/lib/checkout/delete.js +0 -26
- package/lib/checkout/deploy.js +0 -59
- package/lib/checkout/dev/index.js +0 -143
- package/lib/checkout/fields.js +0 -29
- package/lib/checkout/index.js +0 -63
- package/lib/checkout/preview.js +0 -52
- package/lib/checkout/pull.js +0 -22
- package/lib/checkout/push.js +0 -141
- package/lib/checkout/template/README.md +0 -34
- package/lib/checkout/template/_gitignore +0 -4
- package/lib/checkout/template/extension.config.js +0 -4
- package/lib/checkout/template/extensions/extension-template/extension.json +0 -10
- package/lib/checkout/template/extensions/extension-template/src/content.html +0 -3
- package/lib/checkout/template/extensions/extension-template/src/index.html +0 -5
- package/lib/checkout/template/extensions/extension-template/src/index.js +0 -11
- package/lib/checkout/template/extensions/extension-template/src/script.html +0 -3
- package/lib/checkout/template/extensions/extension-template/src/style.html +0 -3
- package/lib/checkout/template/package.json +0 -17
- package/lib/checkout/undeploy.js +0 -40
- package/lib/checkout/util.js +0 -201
- package/lib/checkout/verify.js +0 -16
- package/lib/checkout/version.js +0 -7
- package/lib/commands/__tests__/login.test.js +0 -77
- package/lib/commands/__tests__/logout.test.js +0 -29
- package/lib/commands/__tests__/store.test.js +0 -44
- package/lib/commands/__tests__/switch.test.js +0 -45
- package/lib/commands/login.js +0 -120
- package/lib/commands/logout.js +0 -23
- package/lib/commands/store.js +0 -14
- package/lib/commands/switch.js +0 -52
- package/lib/commands/theme/__tests__/delete.test.js +0 -49
- package/lib/commands/theme/__tests__/init.test.js +0 -21
- package/lib/commands/theme/__tests__/list.test.js +0 -80
- package/lib/commands/theme/__tests__/package.test.js +0 -17
- package/lib/commands/theme/__tests__/publish.test.js +0 -61
- package/lib/commands/theme/__tests__/pull.test.js +0 -69
- package/lib/commands/theme/__tests__/push.test.js +0 -63
- package/lib/commands/theme/__tests__/serve.test.js +0 -107
- package/lib/commands/theme/delete.js +0 -64
- package/lib/commands/theme/init.js +0 -51
- package/lib/commands/theme/list.js +0 -28
- package/lib/commands/theme/package.js +0 -37
- package/lib/commands/theme/publish.js +0 -56
- package/lib/commands/theme/pull.js +0 -62
- package/lib/commands/theme/push.js +0 -106
- package/lib/commands/theme/serve.js +0 -153
- package/lib/commands/theme/share.js +0 -20
- package/lib/commands/version.js +0 -6
- package/lib/common/constants.js +0 -24
- package/lib/common/db/partner.js +0 -91
- package/lib/common/inquirers/choose-app.js +0 -79
- package/lib/common/inquirers/choose-partner.js +0 -74
- package/lib/common/log.js +0 -15
- package/lib/common/login.js +0 -125
- package/lib/common/logout.js +0 -16
- package/lib/db/__mocks__/index.js +0 -9
- package/lib/db/__tests__/analytics.test.js +0 -19
- package/lib/db/__tests__/user.test.js +0 -20
- package/lib/db/analytics.js +0 -48
- package/lib/db/index.js +0 -9
- package/lib/db/user.js +0 -71
- package/lib/function/bin/index.js +0 -20
- package/lib/function/bin/javy/javy-arm-linux-v5.0.1 +0 -0
- package/lib/function/bin/javy/javy-arm-macos-v5.0.1 +0 -0
- package/lib/function/bin/javy/javy-x86_64-linux-v5.0.1 +0 -0
- package/lib/function/bin/javy/javy-x86_64-macos-v5.0.1 +0 -0
- package/lib/function/bin/javy/javy-x86_64-windows-v5.0.1 +0 -0
- package/lib/function/commands/compile.js +0 -43
- package/lib/function/commands/create.js +0 -77
- package/lib/function/commands/list.js +0 -18
- package/lib/function/commands/release.js +0 -69
- package/lib/function/index.js +0 -24
- package/lib/function/template/js/README.md +0 -37
- package/lib/function/template/js/_gitignore +0 -4
- package/lib/function/template/js/extension.config.json +0 -5
- package/lib/function/template/js/package.json +0 -17
- package/lib/function/template/js/src/index.js +0 -64
- package/lib/function/utils.js +0 -29
- package/lib/log.js +0 -13
- package/lib/openAPI/__mocks__/index.js +0 -20
- package/lib/openAPI/api.js +0 -76
- package/lib/openAPI/index.js +0 -56
- package/lib/oss.js +0 -102
- package/lib/partner-api/axios.js +0 -67
- package/lib/partner-api/index.js +0 -79
- package/lib/report.js +0 -37
- package/lib/theme-extension/api/index.js +0 -96
- package/lib/theme-extension/commands/build.js +0 -114
- package/lib/theme-extension/commands/connect.js +0 -73
- package/lib/theme-extension/commands/create.js +0 -105
- package/lib/theme-extension/commands/deploy.js +0 -56
- package/lib/theme-extension/commands/list.js +0 -35
- package/lib/theme-extension/commands/release.js +0 -59
- package/lib/theme-extension/commands/serve.js +0 -179
- package/lib/theme-extension/commands/versions.js +0 -55
- package/lib/theme-extension/index.js +0 -29
- package/lib/theme-extension/template/basic-app/README.md +0 -125
- package/lib/theme-extension/template/basic-app/extension.config.json +0 -4
- package/lib/theme-extension/template/basic-app/package.json +0 -18
- package/lib/theme-extension/template/basic-app/theme-app/assets/index.css +0 -4
- package/lib/theme-extension/template/basic-app/theme-app/assets-manifest.json +0 -1
- package/lib/theme-extension/template/basic-app/theme-app/blocks/index.liquid +0 -16
- package/lib/theme-extension/template/basic-app/theme-app/locales/ar-SA.json +0 -1
- package/lib/theme-extension/template/basic-app/theme-app/locales/de-DE.json +0 -1
- package/lib/theme-extension/template/basic-app/theme-app/locales/en-US.json +0 -6
- package/lib/theme-extension/template/basic-app/theme-app/locales/es-ES.json +0 -1
- package/lib/theme-extension/template/basic-app/theme-app/locales/fr-FR.json +0 -1
- package/lib/theme-extension/template/basic-app/theme-app/locales/id-ID.json +0 -1
- package/lib/theme-extension/template/basic-app/theme-app/locales/it-IT.json +0 -1
- package/lib/theme-extension/template/basic-app/theme-app/locales/ja-JP.json +0 -1
- package/lib/theme-extension/template/basic-app/theme-app/locales/ko-KR.json +0 -1
- package/lib/theme-extension/template/basic-app/theme-app/locales/nl-NL.json +0 -1
- package/lib/theme-extension/template/basic-app/theme-app/locales/pl-PL.json +0 -1
- package/lib/theme-extension/template/basic-app/theme-app/locales/pt-PT.json +0 -1
- package/lib/theme-extension/template/basic-app/theme-app/locales/ru-RU.json +0 -1
- package/lib/theme-extension/template/basic-app/theme-app/locales/th-TH.json +0 -1
- package/lib/theme-extension/template/basic-app/theme-app/locales/zh-CN.json +0 -6
- package/lib/theme-extension/template/basic-app/theme-app/locales/zh-TW.json +0 -1
- package/lib/theme-extension/template/basic-app/theme-app/snippets/index.liquid +0 -8
- package/lib/theme-extension/template/embed-app/README.md +0 -125
- package/lib/theme-extension/template/embed-app/extension.config.json +0 -4
- package/lib/theme-extension/template/embed-app/package.json +0 -18
- package/lib/theme-extension/template/embed-app/theme-app/assets-manifest.json +0 -1
- package/lib/theme-extension/template/embed-app/theme-app/blocks/index.liquid +0 -18
- package/lib/theme-extension/template/embed-app/theme-app/locales/ar-SA.json +0 -1
- package/lib/theme-extension/template/embed-app/theme-app/locales/de-DE.json +0 -1
- package/lib/theme-extension/template/embed-app/theme-app/locales/en-US.json +0 -6
- package/lib/theme-extension/template/embed-app/theme-app/locales/es-ES.json +0 -1
- package/lib/theme-extension/template/embed-app/theme-app/locales/fr-FR.json +0 -1
- package/lib/theme-extension/template/embed-app/theme-app/locales/id-ID.json +0 -1
- package/lib/theme-extension/template/embed-app/theme-app/locales/it-IT.json +0 -1
- package/lib/theme-extension/template/embed-app/theme-app/locales/ja-JP.json +0 -1
- package/lib/theme-extension/template/embed-app/theme-app/locales/ko-KR.json +0 -1
- package/lib/theme-extension/template/embed-app/theme-app/locales/nl-NL.json +0 -1
- package/lib/theme-extension/template/embed-app/theme-app/locales/pl-PL.json +0 -1
- package/lib/theme-extension/template/embed-app/theme-app/locales/pt-PT.json +0 -1
- package/lib/theme-extension/template/embed-app/theme-app/locales/ru-RU.json +0 -1
- package/lib/theme-extension/template/embed-app/theme-app/locales/th-TH.json +0 -1
- package/lib/theme-extension/template/embed-app/theme-app/locales/zh-CN.json +0 -6
- package/lib/theme-extension/template/embed-app/theme-app/locales/zh-TW.json +0 -1
- package/lib/theme-extension/template/embed-app/theme-app/snippets/index.liquid +0 -8
- package/lib/theme-extension/template/embed-app/theme-app/snippets/index_css.liquid +0 -6
- package/lib/theme-extension/utils/config.js +0 -32
- package/lib/theme-extension/utils/index.js +0 -213
- package/lib/tracing.js +0 -50
- package/lib/utils/config.js +0 -12
- package/lib/utils/console.js +0 -33
- package/lib/utils/env.js +0 -17
- package/lib/utils/file.js +0 -48
- package/lib/utils/platform.js +0 -37
- package/lib/utils/utils.js +0 -165
- /package/{lib/checkout → scripts/jsbuild}/dev/client.js +0 -0
- /package/{lib/app/services/extension-build/plugins → scripts/jsbuild/plugin}/vite-plugin-transform-extension-html.js +0 -0
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
const { configStore } = require('../../store');
|
|
2
|
-
const { parseTomlFile } = require('../../utils/toml');
|
|
3
|
-
const { getAppCompleteInfoRequest } = require('../../api/cli');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @description 获取当前正在使用的 configFile
|
|
8
|
-
* @param {string} projectDir 项目目录,默认使用 process.env.APP_PROJECT_DIR
|
|
9
|
-
* @returns {string} 返回当前正在使用的 configFile
|
|
10
|
-
*/
|
|
11
|
-
function getActiveConfigFile(projectDir = process.env.APP_PROJECT_DIR) {
|
|
12
|
-
const configCache = configStore.getProjectConfig(projectDir);
|
|
13
|
-
return configCache?.configFile ? configCache.configFile : 'shoplazza.app.toml';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @description 获取 config 相关信息
|
|
18
|
-
* @param {string} projectDir 项目目录,默认使用 process.env.APP_PROJECT_DIR
|
|
19
|
-
* @returns {Promise<{app: object, partner: object, user: object, configContent: object}>} 返回 app、partner、user、configContent 信息
|
|
20
|
-
*/
|
|
21
|
-
async function getAppCompleteInfo(projectDir = process.env.APP_PROJECT_DIR) {
|
|
22
|
-
const activeConfigFile = getActiveConfigFile(projectDir);
|
|
23
|
-
|
|
24
|
-
// 获取 configFile 信息
|
|
25
|
-
const configContent = parseTomlFile(path.join(projectDir, activeConfigFile));
|
|
26
|
-
|
|
27
|
-
// 获取 config 相关信息
|
|
28
|
-
const completeInfo = await getAppCompleteInfoRequest(configContent.client_id);
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
app: completeInfo.app,
|
|
32
|
-
partner: completeInfo.partner,
|
|
33
|
-
user: completeInfo.user,
|
|
34
|
-
configContent: configContent
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
module.exports = {
|
|
39
|
-
getActiveConfigFile,
|
|
40
|
-
getAppCompleteInfo
|
|
41
|
-
};
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
// lib/app/services/devServer/app.js
|
|
2
|
-
const express = require('express');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const crypto = require('crypto');
|
|
5
|
-
const axios = require('axios');
|
|
6
|
-
const { hmacValidatorMiddleWare } = require('./middleware');
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* 创建 dev server 应用
|
|
10
|
-
* @param {{ client_id: string, client_secret: string, redirect_uri: string, app_url_path: string, redirect_url_path: string }} config 配置
|
|
11
|
-
* @returns {express.Application} dev server 应用
|
|
12
|
-
*/
|
|
13
|
-
function createApp(config) {
|
|
14
|
-
if (typeof config !== 'object') {
|
|
15
|
-
throw new Error('Dev server config is invalid');
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const { client_id, client_secret, redirect_uri, app_url_path, redirect_url_path, scopes } = config;
|
|
19
|
-
|
|
20
|
-
if (!client_id || !client_secret || !redirect_uri || !app_url_path || !redirect_url_path || !scopes) {
|
|
21
|
-
throw new Error('Dev server config is invalid');
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const app = express();
|
|
25
|
-
|
|
26
|
-
app.set('view engine', 'ejs');
|
|
27
|
-
app.set('views', path.join(__dirname, 'views'));
|
|
28
|
-
|
|
29
|
-
app.use(express.json());
|
|
30
|
-
app.use(express.urlencoded({ extended: true }));
|
|
31
|
-
|
|
32
|
-
// 将 config 挂载到 req.config 上
|
|
33
|
-
app.use((req, res, next) => {
|
|
34
|
-
req.config = { client_id, client_secret, redirect_uri };
|
|
35
|
-
next();
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
app.get('/', (req, res) => {
|
|
39
|
-
res.render('app', {
|
|
40
|
-
title: '插件调试导航',
|
|
41
|
-
preview_url: '/admin/card'
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
app.get(app_url_path, (req, res) => {
|
|
46
|
-
const encodedScopes = encodeURIComponent(scopes);
|
|
47
|
-
const state = crypto.randomBytes(16).toString('hex');
|
|
48
|
-
const { client_id, redirect_uri } = req.config;
|
|
49
|
-
|
|
50
|
-
res.redirect(
|
|
51
|
-
`https://${req.query.shop}/admin/oauth/authorize?client_id=${client_id}&scope=${encodedScopes}&redirect_uri=${redirect_uri}&response_type=code&state=${state}`
|
|
52
|
-
);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
app.get(redirect_url_path, hmacValidatorMiddleWare, async (req, res) => {
|
|
56
|
-
const { code, hmac, state, shop } = req.query;
|
|
57
|
-
const { client_id, client_secret, redirect_uri } = req.config;
|
|
58
|
-
|
|
59
|
-
if (shop && hmac && code) {
|
|
60
|
-
const { data } = await axios.post(`https://${shop}/admin/oauth/token`, {
|
|
61
|
-
client_id,
|
|
62
|
-
client_secret,
|
|
63
|
-
code,
|
|
64
|
-
grant_type: 'authorization_code',
|
|
65
|
-
redirect_uri
|
|
66
|
-
});
|
|
67
|
-
res.redirect('/');
|
|
68
|
-
} else {
|
|
69
|
-
res.status(400).send('Required parameters missing');
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
return app;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
module.exports = createApp;
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
const createApp = require('./app');
|
|
2
|
-
const { CloudflareTunnel, NgrokTunnel, TunnelManager } = require('./tunnel');
|
|
3
|
-
const chalk = require('chalk');
|
|
4
|
-
const net = require('net');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* 检查端口是否可用
|
|
8
|
-
* @param {number} port 要检查的端口
|
|
9
|
-
* @returns {Promise<boolean>} 端口是否可用
|
|
10
|
-
*/
|
|
11
|
-
function isPortAvailable(port) {
|
|
12
|
-
return new Promise((resolve) => {
|
|
13
|
-
const server = net.createServer();
|
|
14
|
-
|
|
15
|
-
server.listen(port, () => {
|
|
16
|
-
server.once('close', () => {
|
|
17
|
-
resolve(true);
|
|
18
|
-
});
|
|
19
|
-
server.close();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
server.on('error', () => {
|
|
23
|
-
resolve(false);
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* 查找可用的端口
|
|
30
|
-
* @param {number} startPort 起始端口,默认3457
|
|
31
|
-
* @param {number} maxAttempts 最大尝试次数,默认100
|
|
32
|
-
* @returns {Promise<number>} 可用的端口号
|
|
33
|
-
*/
|
|
34
|
-
async function findAvailablePort(startPort = 3457, maxAttempts = 100) {
|
|
35
|
-
for (let i = 0; i < maxAttempts; i++) {
|
|
36
|
-
const port = startPort + i;
|
|
37
|
-
if (await isPortAvailable(port)) {
|
|
38
|
-
return port;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
throw new Error(`无法找到可用端口,已尝试端口范围 ${startPort}-${startPort + maxAttempts - 1}`);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// 启动隧道(策略:cloudflare -> ngrok)
|
|
45
|
-
async function startTunnel(port) {
|
|
46
|
-
const manager = new TunnelManager([
|
|
47
|
-
new CloudflareTunnel(port),
|
|
48
|
-
new NgrokTunnel(port, process.env.NGROK_AUTHTOKEN, process.env.NGROK_DOMAIN)
|
|
49
|
-
]);
|
|
50
|
-
|
|
51
|
-
return manager.start();
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const APP_PATH = '/auth';
|
|
55
|
-
const REDIRECT_PATH = '/auth/callback';
|
|
56
|
-
const PORT = 3457;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* 启动 dev 服务
|
|
60
|
-
* @param {Object} params - 请求参数
|
|
61
|
-
* @param {string} params.clientId - 客户端 ID
|
|
62
|
-
* @param {string} params.clientSecret - 客户端密钥
|
|
63
|
-
* @param {string} params.scopes - 权限范围
|
|
64
|
-
*/
|
|
65
|
-
async function startDevServer({ clientId, clientSecret, scopes }) {
|
|
66
|
-
// 查找可用端口
|
|
67
|
-
const availablePort = await findAvailablePort(PORT);
|
|
68
|
-
// 启动隧道
|
|
69
|
-
const { url: publicUrl, close: closeTunnel } = await startTunnel(availablePort);
|
|
70
|
-
|
|
71
|
-
const appUrl = new URL(APP_PATH, publicUrl).toString();
|
|
72
|
-
const redirectUrl = new URL(REDIRECT_PATH, publicUrl).toString();
|
|
73
|
-
|
|
74
|
-
const app = createApp({
|
|
75
|
-
client_id: clientId,
|
|
76
|
-
client_secret: clientSecret,
|
|
77
|
-
redirect_uri: redirectUrl,
|
|
78
|
-
app_url_path: APP_PATH,
|
|
79
|
-
redirect_url_path: REDIRECT_PATH,
|
|
80
|
-
scopes: scopes
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
return new Promise((resolve, reject) => {
|
|
84
|
-
const server = app.listen(availablePort, () => {
|
|
85
|
-
resolve({
|
|
86
|
-
server,
|
|
87
|
-
appUrl,
|
|
88
|
-
redirectUrl,
|
|
89
|
-
closeTunnel
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
console.log(`🔍 dev server port: ${availablePort}`);
|
|
93
|
-
|
|
94
|
-
console.log(chalk.green('Dev server start success 🎉 🎉 🎉'));
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
app.on('error', reject);
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
module.exports = {
|
|
102
|
-
startDevServer
|
|
103
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
const crypto = require('crypto');
|
|
2
|
-
const { secureCompare } = require('../utils');
|
|
3
|
-
|
|
4
|
-
module.exports = function hmacValidatorMiddleWare(req, res, next) {
|
|
5
|
-
const { code, hmac, state, shop } = req.query;
|
|
6
|
-
const map = Object.assign({}, req.query);
|
|
7
|
-
delete map['hmac'];
|
|
8
|
-
const sortedKeys = Object.keys(map).sort();
|
|
9
|
-
const message = sortedKeys.map((key) => `${key}=${map[key]}`).join('&');
|
|
10
|
-
const { client_secret } = req.config;
|
|
11
|
-
|
|
12
|
-
const generated_hash = crypto
|
|
13
|
-
.createHmac('sha256', client_secret)
|
|
14
|
-
.update(message)
|
|
15
|
-
.digest('hex');
|
|
16
|
-
if (!secureCompare(generated_hash, hmac)) {
|
|
17
|
-
return res.status(400).send('HMAC validation failed');
|
|
18
|
-
}
|
|
19
|
-
next();
|
|
20
|
-
};
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
const CloudflareTunnel = require('./providers/cloudflare');
|
|
2
|
-
const NgrokTunnel = require('./providers/ngrok');
|
|
3
|
-
|
|
4
|
-
class TunnelManager {
|
|
5
|
-
constructor(strategies) {
|
|
6
|
-
this.strategies = strategies;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
async start() {
|
|
10
|
-
const errors = []; // 收集所有策略的错误信息
|
|
11
|
-
|
|
12
|
-
for (let i = 0; i < this.strategies.length; i++) {
|
|
13
|
-
const strategy = this.strategies[i];
|
|
14
|
-
const strategyName = strategy.constructor.name;
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
console.log(`🔄 Trying tunnel strategy: ${strategyName}...`);
|
|
18
|
-
const { url, close } = await strategy.start();
|
|
19
|
-
console.log(`✅ ${strategyName} tunnel started successfully!`);
|
|
20
|
-
return { url, close, strategy: strategyName };
|
|
21
|
-
} catch (err) {
|
|
22
|
-
console.error(`❌ ${strategyName} failed:`, err.message);
|
|
23
|
-
errors.push({ strategy: strategyName, error: err.message });
|
|
24
|
-
|
|
25
|
-
// 如果不是最后一个策略,继续尝试下一个
|
|
26
|
-
if (i < this.strategies.length - 1) {
|
|
27
|
-
console.log(`🔄 Falling back to next tunnel strategy...`);
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// 所有策略都失败了
|
|
34
|
-
const errorDetails = errors.map((e) => `${e.strategy}: ${e.error}`).join('; ');
|
|
35
|
-
throw new Error(`All tunnel strategies failed. Errors: ${errorDetails}`);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
module.exports = {
|
|
40
|
-
CloudflareTunnel,
|
|
41
|
-
NgrokTunnel,
|
|
42
|
-
TunnelManager
|
|
43
|
-
};
|
|
@@ -1,364 +0,0 @@
|
|
|
1
|
-
const { exec, spawn } = require('child_process');
|
|
2
|
-
const os = require('os');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const https = require('https');
|
|
6
|
-
|
|
7
|
-
// Cloudflare版本配置
|
|
8
|
-
const CLOUDFLARE_VERSION = '2024.8.2';
|
|
9
|
-
const CLOUDFLARE_BASE_URL = `https://github.com/cloudflare/cloudflared/releases/download/${CLOUDFLARE_VERSION}`;
|
|
10
|
-
|
|
11
|
-
// 不同平台和架构的二进制文件映射配置
|
|
12
|
-
const PLATFORM_CONFIGS = {
|
|
13
|
-
linux: {
|
|
14
|
-
x64: 'cloudflared-linux-amd64',
|
|
15
|
-
arm64: 'cloudflared-linux-arm64',
|
|
16
|
-
arm: 'cloudflared-linux-arm',
|
|
17
|
-
ia32: 'cloudflared-linux-386'
|
|
18
|
-
},
|
|
19
|
-
darwin: {
|
|
20
|
-
x64: 'cloudflared-darwin-amd64.tgz',
|
|
21
|
-
arm64: 'cloudflared-darwin-arm64.tgz'
|
|
22
|
-
},
|
|
23
|
-
win32: {
|
|
24
|
-
x64: 'cloudflared-windows-amd64.exe',
|
|
25
|
-
ia32: 'cloudflared-windows-386.exe',
|
|
26
|
-
arm64: 'cloudflared-windows-amd64.exe'
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
// 根据当前系统平台和架构获取cloudflared二进制文件的下载URL
|
|
31
|
-
function getDownloadUrl() {
|
|
32
|
-
const platform = os.platform();
|
|
33
|
-
const arch = os.arch();
|
|
34
|
-
|
|
35
|
-
const platformConfig = PLATFORM_CONFIGS[platform];
|
|
36
|
-
if (!platformConfig) {
|
|
37
|
-
throw new Error(`Unsupported platform: ${platform}`);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const filename = platformConfig[arch];
|
|
41
|
-
if (!filename) {
|
|
42
|
-
throw new Error(`Unsupported architecture: ${platform}-${arch}`);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
url: `${CLOUDFLARE_BASE_URL}/${filename}`,
|
|
47
|
-
filename,
|
|
48
|
-
isCompressed: filename.endsWith('.tgz')
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// 获取cloudflared二进制文件的本地存储路径
|
|
53
|
-
function getBinaryPath() {
|
|
54
|
-
const platform = os.platform();
|
|
55
|
-
const extension = platform === 'win32' ? '.exe' : '';
|
|
56
|
-
const cloudflaredDir = path.join(process.env.APP_PROJECT_DIR, 'bin', 'cloudflared');
|
|
57
|
-
|
|
58
|
-
// 检查路径状态并确保目录存在
|
|
59
|
-
try {
|
|
60
|
-
const stat = fs.statSync(cloudflaredDir);
|
|
61
|
-
if (!stat.isDirectory()) {
|
|
62
|
-
console.log('⚠️ Removing conflicting file at cloudflared directory path...');
|
|
63
|
-
fs.unlinkSync(cloudflaredDir);
|
|
64
|
-
fs.mkdirSync(cloudflaredDir, { recursive: true });
|
|
65
|
-
}
|
|
66
|
-
// 如果已经是目录,无需处理
|
|
67
|
-
} catch (error) {
|
|
68
|
-
// 路径不存在,直接创建目录
|
|
69
|
-
fs.mkdirSync(cloudflaredDir, { recursive: true });
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return path.join(cloudflaredDir, `cloudflared${extension}`);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// 比较两个版本号,返回值:>0表示versionA更新,<0表示versionB更新,=0表示相同
|
|
76
|
-
function compareVersions(versionA, versionB) {
|
|
77
|
-
const parseVersion = (v) => v.split('.').map(Number);
|
|
78
|
-
const [majorA, minorA, patchA] = parseVersion(versionA);
|
|
79
|
-
const [majorB, minorB, patchB] = parseVersion(versionB);
|
|
80
|
-
|
|
81
|
-
if (majorA !== majorB) return majorA - majorB;
|
|
82
|
-
if (minorA !== minorB) return minorA - minorB;
|
|
83
|
-
return patchA - patchB;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// 检查本地cloudflared版本是否满足要求
|
|
87
|
-
async function checkVersion(binaryPath) {
|
|
88
|
-
return new Promise((resolve) => {
|
|
89
|
-
// 如果二进制文件不存在,返回false
|
|
90
|
-
if (!fs.existsSync(binaryPath)) return resolve(false);
|
|
91
|
-
|
|
92
|
-
// 执行version命令获取当前版本
|
|
93
|
-
exec(`"${binaryPath}" --version`, (error, stdout) => {
|
|
94
|
-
if (error) return resolve(false);
|
|
95
|
-
const versionMatch = stdout.match(/cloudflared version (\d+\.\d+\.\d+)/);
|
|
96
|
-
if (versionMatch) {
|
|
97
|
-
const currentVersion = versionMatch[1];
|
|
98
|
-
const needsUpdate = compareVersions(CLOUDFLARE_VERSION, currentVersion) > 0;
|
|
99
|
-
console.log(`Current version: ${currentVersion}, Target version: ${CLOUDFLARE_VERSION}`);
|
|
100
|
-
resolve(!needsUpdate);
|
|
101
|
-
} else {
|
|
102
|
-
resolve(false);
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// 下载文件,支持总体10秒下载时长限制和HTTP重定向处理
|
|
109
|
-
async function downloadFile(url, destination) {
|
|
110
|
-
return new Promise(async (resolve, reject) => {
|
|
111
|
-
console.log(`📥 Downloading: ${path.basename(url)}`);
|
|
112
|
-
|
|
113
|
-
const file = fs.createWriteStream(destination);
|
|
114
|
-
let isFinished = false;
|
|
115
|
-
|
|
116
|
-
// 设置总体下载时长限制:10秒,不管下载速度如何
|
|
117
|
-
const downloadTimeoutId = setTimeout(() => {
|
|
118
|
-
if (!isFinished) {
|
|
119
|
-
isFinished = true;
|
|
120
|
-
request.destroy();
|
|
121
|
-
file.close();
|
|
122
|
-
if (fs.existsSync(destination)) fs.unlinkSync(destination);
|
|
123
|
-
reject(new Error('Download took too long'));
|
|
124
|
-
}
|
|
125
|
-
}, 10000);
|
|
126
|
-
|
|
127
|
-
const request = https.get(url, (response) => {
|
|
128
|
-
// 处理HTTP重定向
|
|
129
|
-
if (response.statusCode === 301 || response.statusCode === 302) {
|
|
130
|
-
const redirectUrl = response.headers.location;
|
|
131
|
-
if (redirectUrl) {
|
|
132
|
-
clearTimeout(downloadTimeoutId);
|
|
133
|
-
file.close();
|
|
134
|
-
if (fs.existsSync(destination)) fs.unlinkSync(destination);
|
|
135
|
-
// 修复异步错误处理
|
|
136
|
-
downloadFile(redirectUrl, destination)
|
|
137
|
-
.then(() => resolve())
|
|
138
|
-
.catch((error) => reject(error));
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// 检查HTTP状态码
|
|
144
|
-
if (response.statusCode !== 200) {
|
|
145
|
-
clearTimeout(downloadTimeoutId);
|
|
146
|
-
file.close();
|
|
147
|
-
if (fs.existsSync(destination)) fs.unlinkSync(destination);
|
|
148
|
-
return reject(new Error(`Download failed: HTTP ${response.statusCode}`));
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// 将响应数据写入文件
|
|
152
|
-
response.pipe(file);
|
|
153
|
-
|
|
154
|
-
file.on('finish', () => {
|
|
155
|
-
if (!isFinished) {
|
|
156
|
-
isFinished = true;
|
|
157
|
-
clearTimeout(downloadTimeoutId);
|
|
158
|
-
file.close();
|
|
159
|
-
console.log('✅ Download completed');
|
|
160
|
-
resolve();
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
file.on('error', (err) => {
|
|
165
|
-
if (!isFinished) {
|
|
166
|
-
isFinished = true;
|
|
167
|
-
clearTimeout(downloadTimeoutId);
|
|
168
|
-
file.close();
|
|
169
|
-
if (fs.existsSync(destination)) fs.unlinkSync(destination);
|
|
170
|
-
reject(err);
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
// 处理请求错误
|
|
176
|
-
request.on('error', (err) => {
|
|
177
|
-
if (!isFinished) {
|
|
178
|
-
isFinished = true;
|
|
179
|
-
clearTimeout(downloadTimeoutId);
|
|
180
|
-
file.close();
|
|
181
|
-
if (fs.existsSync(destination)) fs.unlinkSync(destination);
|
|
182
|
-
reject(err);
|
|
183
|
-
}
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
// 设置请求超时(服务器无响应):5秒
|
|
187
|
-
request.setTimeout(5000, () => {
|
|
188
|
-
if (!isFinished) {
|
|
189
|
-
request.destroy();
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// 解压tgz文件(仅macOS平台的cloudflared需要解压)
|
|
196
|
-
async function extractTgz(tgzPath, extractDir) {
|
|
197
|
-
return new Promise((resolve, reject) => {
|
|
198
|
-
console.log('📦 Extracting file...');
|
|
199
|
-
const filename = path.basename(tgzPath);
|
|
200
|
-
exec(`tar -xzf "${filename}"`, { cwd: extractDir }, (error) => {
|
|
201
|
-
if (error) return reject(new Error(`Extraction failed: ${error.message}`));
|
|
202
|
-
console.log('✅ Extraction completed');
|
|
203
|
-
resolve();
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// 安装cloudflared(如果不存在或版本过低)
|
|
209
|
-
async function installCloudflared() {
|
|
210
|
-
console.log('🔍 Checking cloudflared...');
|
|
211
|
-
const binaryPath = getBinaryPath();
|
|
212
|
-
|
|
213
|
-
// 检查现有版本是否满足要求
|
|
214
|
-
if (await checkVersion(binaryPath)) {
|
|
215
|
-
console.log('✅ cloudflared is already at target version or higher');
|
|
216
|
-
return; // 成功时不需要返回值
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
console.log('🔄 Installing cloudflared...');
|
|
220
|
-
try {
|
|
221
|
-
const { url, filename, isCompressed } = getDownloadUrl();
|
|
222
|
-
const platform = os.platform();
|
|
223
|
-
|
|
224
|
-
// macOS平台需要解压tgz文件
|
|
225
|
-
if (isCompressed && platform === 'darwin') {
|
|
226
|
-
const tgzPath = path.join(path.dirname(binaryPath), filename);
|
|
227
|
-
await downloadFile(url, tgzPath);
|
|
228
|
-
await extractTgz(tgzPath, path.dirname(binaryPath));
|
|
229
|
-
const extractedPath = path.join(path.dirname(binaryPath), 'cloudflared');
|
|
230
|
-
if (fs.existsSync(extractedPath)) fs.renameSync(extractedPath, binaryPath);
|
|
231
|
-
if (fs.existsSync(tgzPath)) fs.unlinkSync(tgzPath);
|
|
232
|
-
} else {
|
|
233
|
-
// Linux直接下载二进制文件
|
|
234
|
-
await downloadFile(url, binaryPath);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// 为非Windows平台设置可执行权限
|
|
238
|
-
if (platform !== 'win32') {
|
|
239
|
-
fs.chmodSync(binaryPath, '755');
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// 验证安装是否成功
|
|
243
|
-
const isWorking = await new Promise((resolve) => {
|
|
244
|
-
exec(`"${binaryPath}" --version`, (error) => resolve(!error));
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
if (isWorking) {
|
|
248
|
-
console.log('✅ cloudflared installed successfully!');
|
|
249
|
-
return; // 成功时不需要返回值
|
|
250
|
-
}
|
|
251
|
-
throw new Error('Installation verification failed');
|
|
252
|
-
} catch (error) {
|
|
253
|
-
console.error('❌ Installation failed:', error.message);
|
|
254
|
-
// 抛出具体错误而不是返回false,这样上层能获得具体的失败原因
|
|
255
|
-
throw new Error(`cloudflared installation failed: ${error.message}`);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// 启动Cloudflare Quick Tunnel,返回包含url和close方法的对象
|
|
260
|
-
async function startQuickTunnel(port) {
|
|
261
|
-
console.log('🚀 Starting Cloudflare Tunnel...');
|
|
262
|
-
|
|
263
|
-
const binaryPath = getBinaryPath();
|
|
264
|
-
// 启动cloudflared进程,创建快速隧道
|
|
265
|
-
const tunnel = spawn(binaryPath, ['tunnel', '--url', `http://localhost:${port}`, '--no-autoupdate'], {
|
|
266
|
-
stdio: 'pipe'
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
let tunnelUrl = null;
|
|
270
|
-
|
|
271
|
-
// 设置10秒超时
|
|
272
|
-
const timeout = setTimeout(() => {
|
|
273
|
-
if (!tunnelUrl) {
|
|
274
|
-
console.error('❌ Tunnel startup timeout');
|
|
275
|
-
try {
|
|
276
|
-
tunnel.kill();
|
|
277
|
-
} catch {}
|
|
278
|
-
}
|
|
279
|
-
}, 10000);
|
|
280
|
-
|
|
281
|
-
// 从cloudflared输出中解析隧道URL
|
|
282
|
-
const tryParse = (buf) => {
|
|
283
|
-
const output = String(buf);
|
|
284
|
-
const match = output.match(/https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com/);
|
|
285
|
-
if (match && !tunnelUrl) {
|
|
286
|
-
tunnelUrl = match[0];
|
|
287
|
-
}
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
// 监听标准输出和错误输出
|
|
291
|
-
tunnel.stdout.on('data', tryParse);
|
|
292
|
-
tunnel.stderr.on('data', tryParse);
|
|
293
|
-
|
|
294
|
-
return await new Promise((resolve, reject) => {
|
|
295
|
-
const finishIfReady = () => {
|
|
296
|
-
if (tunnelUrl) {
|
|
297
|
-
clearTimeout(timeout);
|
|
298
|
-
resolve({
|
|
299
|
-
url: tunnelUrl,
|
|
300
|
-
close: () => {
|
|
301
|
-
try {
|
|
302
|
-
tunnel.kill('SIGTERM');
|
|
303
|
-
} catch {}
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
// 监听隧道进程事件
|
|
310
|
-
tunnel.on('error', (err) => {
|
|
311
|
-
clearTimeout(timeout);
|
|
312
|
-
reject(new Error(`Tunnel process error: ${err.message}`));
|
|
313
|
-
});
|
|
314
|
-
tunnel.on('close', (code) => {
|
|
315
|
-
clearTimeout(timeout);
|
|
316
|
-
if (!tunnelUrl) return reject(new Error(`Tunnel exited with code=${code}`));
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
// 每100ms检查一次隧道URL是否获取到
|
|
320
|
-
const iv = setInterval(() => {
|
|
321
|
-
if (tunnelUrl) {
|
|
322
|
-
clearInterval(iv);
|
|
323
|
-
finishIfReady();
|
|
324
|
-
}
|
|
325
|
-
}, 100);
|
|
326
|
-
|
|
327
|
-
// 兜底:31秒后停止轮询
|
|
328
|
-
setTimeout(() => {
|
|
329
|
-
clearInterval(iv);
|
|
330
|
-
if (!tunnelUrl) {
|
|
331
|
-
reject(new Error('Tunnel not ready'));
|
|
332
|
-
}
|
|
333
|
-
}, 31000);
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
// Cloudflare隧道管理类
|
|
338
|
-
class CloudflareTunnel {
|
|
339
|
-
constructor(port) {
|
|
340
|
-
this.port = port;
|
|
341
|
-
this._closer = null;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
// 安装cloudflared(如果需要)并启动Quick Tunnel
|
|
345
|
-
async start() {
|
|
346
|
-
// installCloudflared现在会直接抛出错误,不需要检查返回值
|
|
347
|
-
await installCloudflared();
|
|
348
|
-
const { url, close } = await startQuickTunnel(this.port);
|
|
349
|
-
this._closer = close;
|
|
350
|
-
return { url, close };
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// 关闭隧道
|
|
354
|
-
async close() {
|
|
355
|
-
if (this._closer) {
|
|
356
|
-
try {
|
|
357
|
-
await this._closer();
|
|
358
|
-
} catch {}
|
|
359
|
-
this._closer = null;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
module.exports = CloudflareTunnel;
|