shopify-cli 2.6.2 → 2.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/PULL_REQUEST_TEMPLATE.md +15 -4
- data/.github/workflows/shopify.yml +3 -6
- data/CHANGELOG.md +89 -99
- data/CONTRIBUTING.md +9 -1
- data/Dockerfile +22 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +7 -3
- data/RELEASING.md +17 -30
- data/Rakefile +0 -5
- data/lib/project_types/extension/cli.rb +1 -0
- data/lib/project_types/extension/commands/create.rb +1 -0
- data/lib/project_types/extension/features/argo.rb +9 -10
- data/lib/project_types/extension/features/argo_serve.rb +1 -1
- data/lib/project_types/extension/forms/create.rb +1 -1
- data/lib/project_types/extension/forms/questions/ask_template.rb +2 -1
- data/lib/project_types/extension/messages/messages.rb +1 -0
- data/lib/project_types/extension/models/server_config/extension.rb +2 -0
- data/lib/project_types/extension/models/specification_handlers/checkout_post_purchase.rb +1 -1
- data/lib/project_types/extension/models/specification_handlers/checkout_ui_extension.rb +1 -1
- data/lib/project_types/extension/tasks/converters/server_config_converter.rb +4 -5
- data/lib/project_types/extension/tasks/find_package_from_json.rb +37 -0
- data/lib/project_types/extension/tasks/load_server_config.rb +6 -1
- data/lib/project_types/node/commands/serve.rb +7 -16
- data/lib/project_types/node/messages/messages.rb +0 -5
- data/lib/project_types/php/commands/serve.rb +6 -9
- data/lib/project_types/php/messages/messages.rb +1 -4
- data/lib/project_types/rails/commands/create.rb +45 -16
- data/lib/project_types/rails/commands/serve.rb +7 -8
- data/lib/project_types/rails/forms/create.rb +0 -1
- data/lib/project_types/rails/messages/messages.rb +1 -4
- data/lib/project_types/script/commands/create.rb +4 -5
- data/lib/project_types/script/config/extension_points.yml +10 -0
- data/lib/project_types/script/errors.rb +0 -18
- data/lib/project_types/script/graphql/app_script_set.graphql +2 -0
- data/lib/project_types/script/layers/application/build_script.rb +2 -1
- data/lib/project_types/script/layers/application/create_script.rb +2 -2
- data/lib/project_types/script/layers/application/push_script.rb +15 -1
- data/lib/project_types/script/layers/domain/push_package.rb +5 -2
- data/lib/project_types/script/layers/domain/script_json.rb +1 -1
- data/lib/project_types/script/layers/infrastructure/api_clients/partners_proxy_api_client.rb +0 -4
- data/lib/project_types/script/layers/infrastructure/errors.rb +17 -2
- data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb +29 -13
- data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +29 -13
- data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +4 -2
- data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +3 -4
- data/lib/project_types/script/layers/infrastructure/script_service.rb +7 -2
- data/lib/project_types/script/messages/messages.rb +9 -22
- data/lib/project_types/script/ui/error_handler.rb +16 -26
- data/lib/project_types/theme/commands/serve.rb +2 -0
- data/lib/project_types/theme/messages/messages.rb +6 -0
- data/lib/shopify_cli/app_type_detector.rb +32 -0
- data/lib/shopify_cli/command.rb +6 -1
- data/lib/shopify_cli/command_options/command_serve_options.rb +43 -0
- data/lib/shopify_cli/command_options.rb +7 -0
- data/lib/shopify_cli/commands/login.rb +3 -3
- data/lib/shopify_cli/commands/reporting.rb +38 -0
- data/lib/shopify_cli/commands/switch.rb +1 -1
- data/lib/shopify_cli/commands.rb +1 -0
- data/lib/shopify_cli/constants.rb +7 -3
- data/lib/shopify_cli/core/monorail.rb +9 -20
- data/lib/shopify_cli/environment.rb +15 -1
- data/lib/shopify_cli/exception_reporter.rb +29 -15
- data/lib/shopify_cli/messages/messages.rb +48 -19
- data/lib/shopify_cli/migrator/migration.rb +1 -1
- data/lib/shopify_cli/migrator/migrations/1631709766_noop.rb +1 -1
- data/lib/shopify_cli/migrator/migrations/1633691650_merge_reporting_configuration.rb +41 -0
- data/lib/shopify_cli/migrator.rb +9 -11
- data/lib/shopify_cli/reporting_configuration_controller.rb +64 -0
- data/lib/shopify_cli/services/base_service.rb +13 -0
- data/lib/shopify_cli/services/reporting_service.rb +16 -0
- data/lib/shopify_cli/services.rb +6 -0
- data/lib/shopify_cli/theme/dev_server/watcher.rb +2 -2
- data/lib/shopify_cli/theme/dev_server.rb +3 -2
- data/lib/shopify_cli/version.rb +1 -1
- data/lib/shopify_cli.rb +4 -0
- data/shopify-cli.gemspec +2 -13
- data/utilities/docker/container.rb +97 -0
- data/utilities/docker.rb +45 -3
- metadata +18 -10
- data/ext/shopify-cli/extconf.rb +0 -60
- data/lib/project_types/script/graphql/app_script_update_or_create.graphql +0 -0
- data/lib/shopify_cli/exception_reporter/permission_controller.rb +0 -54
| @@ -63,7 +63,7 @@ module Extension | |
| 63 63 | 
             
                    ShopifyCLI::Tasks::EnsureDevStore.call(context) if required_fields.include?(:shop)
         | 
| 64 64 |  | 
| 65 65 | 
             
                    project = ExtensionProject.current
         | 
| 66 | 
            -
                    ensure_resource_resource_url! if specification_handler.supplies_resource_url?
         | 
| 66 | 
            +
                    ensure_resource_resource_url! if specification_handler.supplies_resource_url? && !supports_development_server?
         | 
| 67 67 |  | 
| 68 68 | 
             
                    return if required_fields.all? do |field|
         | 
| 69 69 | 
             
                      value = project.env.public_send(field)
         | 
| @@ -24,7 +24,7 @@ module Extension | |
| 24 24 | 
             
                    ShopifyCLI::Result.wrap(ExtensionProjectDetails.new)
         | 
| 25 25 | 
             
                      .then(&Questions::AskApp.new(ctx: ctx, api_key: api_key))
         | 
| 26 26 | 
             
                      .then(&Questions::AskType.new(ctx: ctx, type: type))
         | 
| 27 | 
            -
                      .then(&Questions::AskTemplate.new(ctx: ctx))
         | 
| 27 | 
            +
                      .then(&Questions::AskTemplate.new(ctx: ctx, template: template))
         | 
| 28 28 | 
             
                      .then(&Questions::AskName.new(ctx: ctx, name: name))
         | 
| 29 29 | 
             
                      .unwrap { |e| raise e }
         | 
| 30 30 | 
             
                      .tap do |project_details|
         | 
| @@ -9,13 +9,14 @@ module Extension | |
| 9 9 | 
             
                    ]
         | 
| 10 10 |  | 
| 11 11 | 
             
                    property! :ctx
         | 
| 12 | 
            +
                    property :template, accepts: Models::ServerConfig::Development::VALID_TEMPLATES
         | 
| 12 13 | 
             
                    property :prompt,
         | 
| 13 14 | 
             
                      accepts: ->(prompt) { prompt.respond_to?(:call) },
         | 
| 14 15 | 
             
                      default: -> { CLI::UI::Prompt.method(:ask) }
         | 
| 15 16 |  | 
| 16 17 | 
             
                    def call(project_details)
         | 
| 17 18 | 
             
                      return project_details unless template_required?(project_details)
         | 
| 18 | 
            -
                      project_details.template = choose_interactively
         | 
| 19 | 
            +
                      project_details.template = template || choose_interactively
         | 
| 19 20 | 
             
                      project_details
         | 
| 20 21 | 
             
                    end
         | 
| 21 22 |  | 
| @@ -175,6 +175,7 @@ module Extension | |
| 175 175 | 
             
                  errors: {
         | 
| 176 176 | 
             
                    unknown_type: "Unknown extension type %s",
         | 
| 177 177 | 
             
                    package_not_found: "`%s` package not found.",
         | 
| 178 | 
            +
                    module_not_found: "Unable to find module %s. Ensure your dependencies are up-to-date and try again.",
         | 
| 178 179 | 
             
                  },
         | 
| 179 180 | 
             
                  warnings: {
         | 
| 180 181 | 
             
                    resource_url_auto_generation_failed: "{{*}} {{yellow:Warning:}} Unable to auto generate " \
         | 
| @@ -5,10 +5,12 @@ module Extension | |
| 5 5 | 
             
                module ServerConfig
         | 
| 6 6 | 
             
                  class Extension < Base
         | 
| 7 7 | 
             
                    include SmartProperties
         | 
| 8 | 
            +
             | 
| 8 9 | 
             
                    property! :uuid, accepts: String
         | 
| 9 10 | 
             
                    property! :type, accepts: String
         | 
| 10 11 | 
             
                    property! :user, accepts: ServerConfig::User
         | 
| 11 12 | 
             
                    property! :development, accepts: ServerConfig::Development
         | 
| 13 | 
            +
                    property :extension_points, accepts: Array
         | 
| 12 14 |  | 
| 13 15 | 
             
                    def self.build(uuid: "", template:, type:, root_dir:)
         | 
| 14 16 | 
             
                      renderer = ServerConfig::DevelopmentRenderer.find(type)
         | 
| @@ -5,13 +5,11 @@ module Extension | |
| 5 5 | 
             
              module Tasks
         | 
| 6 6 | 
             
                module Converters
         | 
| 7 7 | 
             
                  module ServerConfigConverter
         | 
| 8 | 
            -
                    def self.from_hash(hash | 
| 8 | 
            +
                    def self.from_hash(hash:, type:, registration_uuid:)
         | 
| 9 9 | 
             
                      context.abort(context.message("tasks.errors.parse_error")) if hash.nil?
         | 
| 10 10 |  | 
| 11 | 
            -
                      project = ExtensionProject.current
         | 
| 12 | 
            -
             | 
| 13 11 | 
             
                      extension = Models::ServerConfig::Extension.new(
         | 
| 14 | 
            -
                        uuid:  | 
| 12 | 
            +
                        uuid: registration_uuid,
         | 
| 15 13 | 
             
                        type: type.upcase,
         | 
| 16 14 | 
             
                        user: Models::ServerConfig::User.new,
         | 
| 17 15 | 
             
                        development: Models::ServerConfig::Development.new(
         | 
| @@ -20,7 +18,8 @@ module Extension | |
| 20 18 | 
             
                          entries: Models::ServerConfig::DevelopmentEntries.new(
         | 
| 21 19 | 
             
                            main: hash.dig("development", "entries", "main")
         | 
| 22 20 | 
             
                          )
         | 
| 23 | 
            -
                        )
         | 
| 21 | 
            +
                        ),
         | 
| 22 | 
            +
                        extension_points: hash.dig("extension_points")
         | 
| 24 23 | 
             
                      )
         | 
| 25 24 |  | 
| 26 25 | 
             
                      Models::ServerConfig::Root.new(extensions: [extension])
         | 
| @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            require "json"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module Extension
         | 
| 5 | 
            +
              module Tasks
         | 
| 6 | 
            +
                class FindPackageFromJson < ShopifyCLI::Task
         | 
| 7 | 
            +
                  include SmartProperties
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  property! :context, accepts: ShopifyCLI::Context
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  def self.call(package_name, **config)
         | 
| 12 | 
            +
                    new(**config).call(package_name)
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def call(package_name)
         | 
| 16 | 
            +
                    ShopifyCLI::Result.success(resolve_package_json(package_name))
         | 
| 17 | 
            +
                      .then { |file| File.read(file) }
         | 
| 18 | 
            +
                      .then { |file| JSON.parse(file) }
         | 
| 19 | 
            +
                      .then { |file| file.dig("version") }
         | 
| 20 | 
            +
                      .then { |version| return Models::NpmPackage.new(name: package_name, version: version) }
         | 
| 21 | 
            +
                      .unwrap do |error|
         | 
| 22 | 
            +
                        context.debug(error)
         | 
| 23 | 
            +
                        context.abort(context.message("errors.module_not_found", package_name))
         | 
| 24 | 
            +
                      end
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  private
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  def resolve_package_json(package_name)
         | 
| 30 | 
            +
                    path = "path.join(require.resolve('#{package_name}'), '../package.json')"
         | 
| 31 | 
            +
                    package_json, error, _ = CLI::Kit::System.capture3("node", "-p", path)
         | 
| 32 | 
            +
                    return error unless !error.nil?
         | 
| 33 | 
            +
                    package_json.chomp
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
            end
         | 
| @@ -10,7 +10,12 @@ module Extension | |
| 10 10 | 
             
                  class << self
         | 
| 11 11 | 
             
                    def call(file_name:, type:)
         | 
| 12 12 | 
             
                      config = YAML.load_file(file_name)
         | 
| 13 | 
            -
                       | 
| 13 | 
            +
                      project = ExtensionProject.current
         | 
| 14 | 
            +
                      Tasks::Converters::ServerConfigConverter.from_hash(
         | 
| 15 | 
            +
                        hash: config,
         | 
| 16 | 
            +
                        type: type,
         | 
| 17 | 
            +
                        registration_uuid: project.registration_uuid
         | 
| 18 | 
            +
                      )
         | 
| 14 19 | 
             
                    rescue Psych::SyntaxError => e
         | 
| 15 20 | 
             
                      raise(
         | 
| 16 21 | 
             
                        ShopifyCLI::Abort,
         | 
| @@ -2,20 +2,18 @@ | |
| 2 2 | 
             
            module Node
         | 
| 3 3 | 
             
              class Command
         | 
| 4 4 | 
             
                class Serve < ShopifyCLI::SubCommand
         | 
| 5 | 
            +
                  include ShopifyCLI::CommandOptions::CommandServeOptions
         | 
| 6 | 
            +
             | 
| 5 7 | 
             
                  prerequisite_task ensure_project_type: :node
         | 
| 6 8 | 
             
                  prerequisite_task :ensure_env, :ensure_dev_store
         | 
| 7 9 |  | 
| 8 | 
            -
                   | 
| 9 | 
            -
             | 
| 10 | 
            -
                      flags[:host] = h.gsub('"', "")
         | 
| 11 | 
            -
                    end
         | 
| 12 | 
            -
                    parser.on("--port=PORT") { |port| flags[:port] = port }
         | 
| 13 | 
            -
                  end
         | 
| 10 | 
            +
                  parse_host_option
         | 
| 11 | 
            +
                  parse_port_option
         | 
| 14 12 |  | 
| 15 13 | 
             
                  def call(*)
         | 
| 16 14 | 
             
                    project = ShopifyCLI::Project.current
         | 
| 17 | 
            -
                     | 
| 18 | 
            -
                     | 
| 15 | 
            +
                    tunnel_port = port.to_s
         | 
| 16 | 
            +
                    url = host || ShopifyCLI::Tunnel.start(@ctx, port: tunnel_port)
         | 
| 19 17 | 
             
                    project.env.update(@ctx, :host, url)
         | 
| 20 18 | 
             
                    ShopifyCLI::Tasks::UpdateDashboardURLS.call(
         | 
| 21 19 | 
             
                      @ctx,
         | 
| @@ -30,18 +28,11 @@ module Node | |
| 30 28 |  | 
| 31 29 | 
             
                    CLI::UI::Frame.open(@ctx.message("node.serve.running_server")) do
         | 
| 32 30 | 
             
                      env = project.env.to_h
         | 
| 33 | 
            -
                      env["PORT"] =  | 
| 31 | 
            +
                      env["PORT"] = tunnel_port
         | 
| 34 32 | 
             
                      @ctx.system("npm run dev", env: env)
         | 
| 35 33 | 
             
                    end
         | 
| 36 34 | 
             
                  end
         | 
| 37 35 |  | 
| 38 | 
            -
                  def port
         | 
| 39 | 
            -
                    return ShopifyCLI::Tunnel::PORT.to_s unless options.flags.key?(:port)
         | 
| 40 | 
            -
                    port = options.flags[:port].to_i
         | 
| 41 | 
            -
                    @ctx.abort(@ctx.message("node.serve.error.invalid_port", options.flags[:port])) unless port > 0
         | 
| 42 | 
            -
                    port
         | 
| 43 | 
            -
                  end
         | 
| 44 | 
            -
             | 
| 45 36 | 
             
                  def self.help
         | 
| 46 37 | 
             
                    ShopifyCLI::Context.message("node.serve.help", ShopifyCLI::TOOL_NAME)
         | 
| 47 38 | 
             
                  end
         | 
| @@ -122,11 +122,6 @@ module Node | |
| 122 122 | 
             
                          {{cyan:--port=PORT}}: Use custom port.
         | 
| 123 123 | 
             
                      HELP
         | 
| 124 124 |  | 
| 125 | 
            -
                      error: {
         | 
| 126 | 
            -
                        host_must_be_https: "HOST must be a HTTPS url.",
         | 
| 127 | 
            -
                        invalid_port: "%s is not a valid port.",
         | 
| 128 | 
            -
                      },
         | 
| 129 | 
            -
             | 
| 130 125 | 
             
                      open_info: <<~MESSAGE,
         | 
| 131 126 | 
             
                        {{*}} To install and start using your app, open this URL in your browser:
         | 
| 132 127 | 
             
                        {{green:%s}}
         | 
| @@ -2,20 +2,17 @@ | |
| 2 2 | 
             
            module PHP
         | 
| 3 3 | 
             
              class Command
         | 
| 4 4 | 
             
                class Serve < ShopifyCLI::SubCommand
         | 
| 5 | 
            -
                   | 
| 5 | 
            +
                  include ShopifyCLI::CommandOptions::CommandServeOptions
         | 
| 6 6 |  | 
| 7 7 | 
             
                  prerequisite_task :ensure_env, :ensure_dev_store
         | 
| 8 8 |  | 
| 9 | 
            -
                   | 
| 10 | 
            -
             | 
| 11 | 
            -
                      flags[:host] = h.gsub('"', "")
         | 
| 12 | 
            -
                    end
         | 
| 13 | 
            -
                  end
         | 
| 9 | 
            +
                  parse_host_option
         | 
| 10 | 
            +
                  parse_port_option
         | 
| 14 11 |  | 
| 15 12 | 
             
                  def call(*)
         | 
| 16 13 | 
             
                    project = ShopifyCLI::Project.current
         | 
| 17 | 
            -
                     | 
| 18 | 
            -
                     | 
| 14 | 
            +
                    tunnel_port = port.to_s
         | 
| 15 | 
            +
                    url = host || ShopifyCLI::Tunnel.start(@ctx, port: tunnel_port)
         | 
| 19 16 | 
             
                    project.env.update(@ctx, :host, url)
         | 
| 20 17 | 
             
                    ShopifyCLI::Tasks::UpdateDashboardURLS.call(
         | 
| 21 18 | 
             
                      @ctx,
         | 
| @@ -35,7 +32,7 @@ module PHP | |
| 35 32 | 
             
                      ShopifyCLI::ProcessSupervision.start(:npm_watch, "npm run watch", force_spawn: true)
         | 
| 36 33 |  | 
| 37 34 | 
             
                      env = project.env.to_h
         | 
| 38 | 
            -
                      @ctx.system("php", "artisan", "serve", "--port",  | 
| 35 | 
            +
                      @ctx.system("php", "artisan", "serve", "--port", tunnel_port, env: env)
         | 
| 39 36 | 
             
                    end
         | 
| 40 37 | 
             
                  end
         | 
| 41 38 |  | 
| @@ -133,12 +133,9 @@ module PHP | |
| 133 133 | 
             
                      extended_help: <<~HELP,
         | 
| 134 134 | 
             
                        {{bold:Options:}}
         | 
| 135 135 | 
             
                          {{cyan:--host=HOST}}: Bypass running tunnel and use custom host. HOST must be HTTPS url.
         | 
| 136 | 
            +
                          {{cyan:--port=PORT}}: Use custom port.
         | 
| 136 137 | 
             
                        HELP
         | 
| 137 138 |  | 
| 138 | 
            -
                      error: {
         | 
| 139 | 
            -
                        host_must_be_https: "HOST must be a HTTPS url.",
         | 
| 140 | 
            -
                      },
         | 
| 141 | 
            -
             | 
| 142 139 | 
             
                      open_info: <<~MESSAGE,
         | 
| 143 140 | 
             
                        {{*}} To install and start using your app, open this URL in your browser:
         | 
| 144 141 | 
             
                        {{green:%s}}
         | 
| @@ -2,7 +2,9 @@ | |
| 2 2 | 
             
            module Rails
         | 
| 3 3 | 
             
              class Command
         | 
| 4 4 | 
             
                class Create < ShopifyCLI::SubCommand
         | 
| 5 | 
            -
                   | 
| 5 | 
            +
                  unless ShopifyCLI::Environment.acceptance_test?
         | 
| 6 | 
            +
                    prerequisite_task :ensure_authenticated
         | 
| 7 | 
            +
                  end
         | 
| 6 8 |  | 
| 7 9 | 
             
                  USER_AGENT_CODE = <<~USERAGENT
         | 
| 8 10 | 
             
                    module ShopifyAPI
         | 
| @@ -31,8 +33,8 @@ module Rails | |
| 31 33 | 
             
                  end
         | 
| 32 34 |  | 
| 33 35 | 
             
                  def call(args, _name)
         | 
| 34 | 
            -
                     | 
| 35 | 
            -
                    return @ctx.puts(self.class.help) if  | 
| 36 | 
            +
                    form_data = self.form_data(args)
         | 
| 37 | 
            +
                    return @ctx.puts(self.class.help) if form_data.nil?
         | 
| 36 38 |  | 
| 37 39 | 
             
                    ruby_version = Ruby.version(@ctx)
         | 
| 38 40 | 
             
                    @ctx.abort(@ctx.message("rails.create.error.invalid_ruby_version")) unless
         | 
| @@ -41,34 +43,61 @@ module Rails | |
| 41 43 | 
             
                    check_node
         | 
| 42 44 | 
             
                    check_yarn
         | 
| 43 45 |  | 
| 44 | 
            -
                    build( | 
| 46 | 
            +
                    build(form_data.name, form_data.db)
         | 
| 47 | 
            +
             | 
| 45 48 | 
             
                    set_custom_ua
         | 
| 46 49 | 
             
                    ShopifyCLI::Project.write(
         | 
| 47 50 | 
             
                      @ctx,
         | 
| 48 51 | 
             
                      project_type: "rails",
         | 
| 49 | 
            -
                      organization_id:  | 
| 52 | 
            +
                      organization_id: form_data.organization_id,
         | 
| 50 53 | 
             
                    )
         | 
| 51 54 |  | 
| 52 | 
            -
                    api_client = ShopifyCLI:: | 
| 53 | 
            -
                       | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 55 | 
            +
                    api_client = if ShopifyCLI::Environment.acceptance_test?
         | 
| 56 | 
            +
                      {
         | 
| 57 | 
            +
                        "apiKey" => "public_api_key",
         | 
| 58 | 
            +
                        "apiSecretKeys" => [
         | 
| 59 | 
            +
                          {
         | 
| 60 | 
            +
                            "secret" => "api_secret_key",
         | 
| 61 | 
            +
                          },
         | 
| 62 | 
            +
                        ],
         | 
| 63 | 
            +
                      }
         | 
| 64 | 
            +
                    else
         | 
| 65 | 
            +
                      ShopifyCLI::Tasks::CreateApiClient.call(
         | 
| 66 | 
            +
                        @ctx,
         | 
| 67 | 
            +
                        org_id: form_data.organization_id,
         | 
| 68 | 
            +
                        title: form_data.title,
         | 
| 69 | 
            +
                        type: form_data.type,
         | 
| 70 | 
            +
                      )
         | 
| 71 | 
            +
                    end
         | 
| 58 72 |  | 
| 59 73 | 
             
                    ShopifyCLI::Resources::EnvFile.new(
         | 
| 60 74 | 
             
                      api_key: api_client["apiKey"],
         | 
| 61 75 | 
             
                      secret: api_client["apiSecretKeys"].first["secret"],
         | 
| 62 | 
            -
                      shop:  | 
| 76 | 
            +
                      shop: form_data.shop_domain,
         | 
| 63 77 | 
             
                      scopes: "write_products,write_customers,write_draft_orders",
         | 
| 64 78 | 
             
                    ).write(@ctx)
         | 
| 65 79 |  | 
| 66 | 
            -
                    partners_url = ShopifyCLI::PartnersAPI.partners_url_for( | 
| 80 | 
            +
                    partners_url = ShopifyCLI::PartnersAPI.partners_url_for(form_data.organization_id, api_client["id"])
         | 
| 67 81 |  | 
| 68 | 
            -
                    @ctx.puts(@ctx.message("apps.create.info.created",  | 
| 69 | 
            -
                    @ctx.puts(@ctx.message("apps.create.info.serve",  | 
| 82 | 
            +
                    @ctx.puts(@ctx.message("apps.create.info.created", form_data.title, partners_url))
         | 
| 83 | 
            +
                    @ctx.puts(@ctx.message("apps.create.info.serve", form_data.name, ShopifyCLI::TOOL_NAME, "rails"))
         | 
| 70 84 | 
             
                    unless ShopifyCLI::Shopifolk.acting_as_shopify_organization?
         | 
| 71 | 
            -
                      @ctx.puts(@ctx.message("apps.create.info.install", partners_url,  | 
| 85 | 
            +
                      @ctx.puts(@ctx.message("apps.create.info.install", partners_url, form_data.title))
         | 
| 86 | 
            +
                    end
         | 
| 87 | 
            +
                  end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                  def form_data(args)
         | 
| 90 | 
            +
                    if ShopifyCLI::Environment.acceptance_test?
         | 
| 91 | 
            +
                      Struct.new(:title, :name, :organization_id, :type, :shop_domain, :db, keyword_init: true).new(
         | 
| 92 | 
            +
                        title: options.flags[:title],
         | 
| 93 | 
            +
                        name: options.flags[:title],
         | 
| 94 | 
            +
                        organization_id: "123",
         | 
| 95 | 
            +
                        shop_domain: "test.shopify.io",
         | 
| 96 | 
            +
                        type: "public",
         | 
| 97 | 
            +
                        db: options.flags[:db]
         | 
| 98 | 
            +
                      )
         | 
| 99 | 
            +
                    else
         | 
| 100 | 
            +
                      Forms::Create.ask(@ctx, args, options.flags)
         | 
| 72 101 | 
             
                    end
         | 
| 73 102 | 
             
                  end
         | 
| 74 103 |  | 
| @@ -2,19 +2,18 @@ | |
| 2 2 | 
             
            module Rails
         | 
| 3 3 | 
             
              class Command
         | 
| 4 4 | 
             
                class Serve < ShopifyCLI::SubCommand
         | 
| 5 | 
            +
                  include ShopifyCLI::CommandOptions::CommandServeOptions
         | 
| 6 | 
            +
             | 
| 5 7 | 
             
                  prerequisite_task ensure_project_type: :rails
         | 
| 6 8 | 
             
                  prerequisite_task :ensure_env, :ensure_dev_store
         | 
| 7 9 |  | 
| 8 | 
            -
                   | 
| 9 | 
            -
             | 
| 10 | 
            -
                      flags[:host] = h.gsub('"', "")
         | 
| 11 | 
            -
                    end
         | 
| 12 | 
            -
                  end
         | 
| 10 | 
            +
                  parse_host_option
         | 
| 11 | 
            +
                  parse_port_option
         | 
| 13 12 |  | 
| 14 13 | 
             
                  def call(*)
         | 
| 15 14 | 
             
                    project = ShopifyCLI::Project.current
         | 
| 16 | 
            -
                     | 
| 17 | 
            -
                     | 
| 15 | 
            +
                    tunnel_port = port.to_s
         | 
| 16 | 
            +
                    url = host || ShopifyCLI::Tunnel.start(@ctx, port: tunnel_port)
         | 
| 18 17 | 
             
                    project.env.update(@ctx, :host, url)
         | 
| 19 18 | 
             
                    ShopifyCLI::Tasks::UpdateDashboardURLS.call(
         | 
| 20 19 | 
             
                      @ctx,
         | 
| @@ -30,7 +29,7 @@ module Rails | |
| 30 29 | 
             
                    CLI::UI::Frame.open(@ctx.message("rails.serve.running_server")) do
         | 
| 31 30 | 
             
                      env = ShopifyCLI::Project.current.env.to_h
         | 
| 32 31 | 
             
                      env.delete("HOST")
         | 
| 33 | 
            -
                      env["PORT"] =  | 
| 32 | 
            +
                      env["PORT"] = tunnel_port
         | 
| 34 33 | 
             
                      env["GEM_PATH"] = Gem.gem_path(@ctx)
         | 
| 35 34 | 
             
                      if @ctx.windows?
         | 
| 36 35 | 
             
                        @ctx.system("ruby bin\\rails server", env: env)
         | 
| @@ -170,12 +170,9 @@ module Rails | |
| 170 170 | 
             
                      extended_help: <<~HELP,
         | 
| 171 171 | 
             
                        {{bold:Options:}}
         | 
| 172 172 | 
             
                          {{cyan:--host=HOST}}: Bypass running tunnel and use custom host. HOST must be HTTPS url.
         | 
| 173 | 
            +
                          {{cyan:--port=PORT}}: Use custom port.
         | 
| 173 174 | 
             
                      HELP
         | 
| 174 175 |  | 
| 175 | 
            -
                      error: {
         | 
| 176 | 
            -
                        host_must_be_https: "{{red:HOST must be a HTTPS url.}}",
         | 
| 177 | 
            -
                      },
         | 
| 178 | 
            -
             | 
| 179 176 | 
             
                      open_info: <<~MESSAGE,
         | 
| 180 177 | 
             
                        {{*}} To install and start using your app, open this URL in your browser:
         | 
| 181 178 | 
             
                        {{green:%s}}
         | 
| @@ -3,15 +3,15 @@ | |
| 3 3 | 
             
            module Script
         | 
| 4 4 | 
             
              class Command
         | 
| 5 5 | 
             
                class Create < ShopifyCLI::SubCommand
         | 
| 6 | 
            -
                   | 
| 6 | 
            +
                  unless ShopifyCLI::Environment.acceptance_test?
         | 
| 7 | 
            +
                    prerequisite_task :ensure_authenticated
         | 
| 8 | 
            +
                  end
         | 
| 7 9 |  | 
| 8 10 | 
             
                  options do |parser, flags|
         | 
| 9 11 | 
             
                    parser.on("--name=NAME") { |name| flags[:name] = name }
         | 
| 10 | 
            -
                    parser.on("-- | 
| 11 | 
            -
                    parser.on("--extension-point=EP_NAME") { |ep_name| flags[:extension_point] = ep_name }
         | 
| 12 | 
            +
                    parser.on("--api=API_NAME") { |ep_name| flags[:extension_point] = ep_name }
         | 
| 12 13 | 
             
                    parser.on("--language=LANGUAGE") { |language| flags[:language] = language }
         | 
| 13 14 | 
             
                    parser.on("--branch=BRANCH") { |branch| flags[:branch] = branch }
         | 
| 14 | 
            -
                    parser.on("--no-config-ui") { |no_config_ui| flags[:no_config_ui] = no_config_ui }
         | 
| 15 15 | 
             
                  end
         | 
| 16 16 |  | 
| 17 17 | 
             
                  def call(args, _name)
         | 
| @@ -28,7 +28,6 @@ module Script | |
| 28 28 | 
             
                      sparse_checkout_branch: options.flags[:branch] || "master",
         | 
| 29 29 | 
             
                      script_name: form.name,
         | 
| 30 30 | 
             
                      extension_point_type: form.extension_point,
         | 
| 31 | 
            -
                      no_config_ui: options.flags.key?(:no_config_ui)
         | 
| 32 31 | 
             
                    )
         | 
| 33 32 | 
             
                    @ctx.puts(@ctx.message("script.create.change_directory_notice", project.script_name))
         | 
| 34 33 | 
             
                  rescue StandardError => e
         | 
| @@ -32,6 +32,7 @@ payment_methods: | |
| 32 32 | 
             
                  package: "@shopify/scripts-checkout-apis"
         | 
| 33 33 | 
             
                typescript:
         | 
| 34 34 | 
             
                  beta: true
         | 
| 35 | 
            +
                  package: "@shopify/scripts-checkout-apis-temp"
         | 
| 35 36 | 
             
                  repo: "https://github.com/Shopify/scripts-apis-examples"
         | 
| 36 37 | 
             
            shipping_methods:
         | 
| 37 38 | 
             
              domain: 'checkout'
         | 
| @@ -41,4 +42,13 @@ shipping_methods: | |
| 41 42 | 
             
                  package: "@shopify/scripts-checkout-apis"
         | 
| 42 43 | 
             
                typescript:
         | 
| 43 44 | 
             
                  beta: true
         | 
| 45 | 
            +
                  package: "@shopify/scripts-checkout-apis-temp"
         | 
| 46 | 
            +
                  repo: "https://github.com/Shopify/scripts-apis-examples"
         | 
| 47 | 
            +
            discount_types:
         | 
| 48 | 
            +
              beta: true
         | 
| 49 | 
            +
              domain: 'discounts'
         | 
| 50 | 
            +
              libraries:
         | 
| 51 | 
            +
                typescript:
         | 
| 52 | 
            +
                  beta: true
         | 
| 53 | 
            +
                  package: "@shopify/scripts-discount-apis"
         | 
| 44 54 | 
             
                  repo: "https://github.com/Shopify/scripts-apis-examples"
         | 
| @@ -6,23 +6,5 @@ module Script | |
| 6 6 |  | 
| 7 7 | 
             
                class NoExistingAppsError < ScriptProjectError; end
         | 
| 8 8 | 
             
                class NoExistingOrganizationsError < ScriptProjectError; end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                class NoExistingStoresError < ScriptProjectError
         | 
| 11 | 
            -
                  attr_reader :organization_id
         | 
| 12 | 
            -
                  def initialize(organization_id)
         | 
| 13 | 
            -
                    super()
         | 
| 14 | 
            -
                    @organization_id = organization_id
         | 
| 15 | 
            -
                  end
         | 
| 16 | 
            -
                end
         | 
| 17 | 
            -
             | 
| 18 | 
            -
                class InvalidConfigProps < ScriptProjectError; end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                class InvalidConfigYAMLError < ScriptProjectError
         | 
| 21 | 
            -
                  attr_reader :config_file
         | 
| 22 | 
            -
                  def initialize(config_file)
         | 
| 23 | 
            -
                    super()
         | 
| 24 | 
            -
                    @config_file = config_file
         | 
| 25 | 
            -
                  end
         | 
| 26 | 
            -
                end
         | 
| 27 9 | 
             
              end
         | 
| 28 10 | 
             
            end
         | 
| @@ -10,6 +10,7 @@ mutation AppScriptSet( | |
| 10 10 | 
             
              $configurationUi: Boolean!,
         | 
| 11 11 | 
             
              $configurationDefinition: String!,
         | 
| 12 12 | 
             
              $moduleUploadUrl: String!,
         | 
| 13 | 
            +
              $library: LibraryInput,
         | 
| 13 14 | 
             
            ) {
         | 
| 14 15 | 
             
              appScriptSet(
         | 
| 15 16 | 
             
                uuid: $uuid
         | 
| @@ -23,6 +24,7 @@ mutation AppScriptSet( | |
| 23 24 | 
             
                configurationUi: $configurationUi,
         | 
| 24 25 | 
             
                configurationDefinition: $configurationDefinition,
         | 
| 25 26 | 
             
                moduleUploadUrl: $moduleUploadUrl,
         | 
| 27 | 
            +
                library: $library,
         | 
| 26 28 | 
             
            ) {
         | 
| 27 29 | 
             
                userErrors {
         | 
| 28 30 | 
             
                  field
         | 
| @@ -5,7 +5,7 @@ module Script | |
| 5 5 | 
             
                module Application
         | 
| 6 6 | 
             
                  class BuildScript
         | 
| 7 7 | 
             
                    class << self
         | 
| 8 | 
            -
                      def call(ctx:, task_runner:, script_project:)
         | 
| 8 | 
            +
                      def call(ctx:, task_runner:, script_project:, library:)
         | 
| 9 9 | 
             
                        CLI::UI::Frame.open(ctx.message("script.application.building")) do
         | 
| 10 10 | 
             
                          begin
         | 
| 11 11 | 
             
                            UI::StrictSpinner.spin(ctx.message("script.application.building_script")) do |spinner|
         | 
| @@ -14,6 +14,7 @@ module Script | |
| 14 14 | 
             
                                script_content: task_runner.build,
         | 
| 15 15 | 
             
                                compiled_type: task_runner.compiled_type,
         | 
| 16 16 | 
             
                                metadata: task_runner.metadata,
         | 
| 17 | 
            +
                                library: library,
         | 
| 17 18 | 
             
                              )
         | 
| 18 19 | 
             
                              spinner.update_title(ctx.message("script.application.built"))
         | 
| 19 20 | 
             
                            end
         | 
| @@ -7,7 +7,7 @@ module Script | |
| 7 7 | 
             
                module Application
         | 
| 8 8 | 
             
                  class CreateScript
         | 
| 9 9 | 
             
                    class << self
         | 
| 10 | 
            -
                      def call(ctx:, language:, sparse_checkout_branch:, script_name:, extension_point_type | 
| 10 | 
            +
                      def call(ctx:, language:, sparse_checkout_branch:, script_name:, extension_point_type:)
         | 
| 11 11 | 
             
                        raise Infrastructure::Errors::ScriptProjectAlreadyExistsError, script_name if ctx.dir_exist?(script_name)
         | 
| 12 12 |  | 
| 13 13 | 
             
                        in_new_directory_context(ctx, script_name) do
         | 
| @@ -36,7 +36,7 @@ module Script | |
| 36 36 | 
             
                          )
         | 
| 37 37 |  | 
| 38 38 | 
             
                          install_dependencies(ctx, language, script_name, project_creator)
         | 
| 39 | 
            -
                          script_project_repo.update_or_create_script_json(title: script_name | 
| 39 | 
            +
                          script_project_repo.update_or_create_script_json(title: script_name)
         | 
| 40 40 | 
             
                          project
         | 
| 41 41 | 
             
                        end
         | 
| 42 42 | 
             
                      end
         | 
| @@ -11,14 +11,27 @@ module Script | |
| 11 11 | 
             
                        task_runner = Infrastructure::Languages::TaskRunner
         | 
| 12 12 | 
             
                          .for(ctx, script_project.language, script_project.script_name)
         | 
| 13 13 |  | 
| 14 | 
            +
                        extension_point = ExtensionPoints.get(type: script_project.extension_point_type)
         | 
| 15 | 
            +
                        library_name = extension_point.libraries.for(script_project.language)&.package
         | 
| 16 | 
            +
                        raise Infrastructure::Errors::LanguageLibraryForAPINotFoundError.new(
         | 
| 17 | 
            +
                          language: script_project.language,
         | 
| 18 | 
            +
                          api: script_project.extension_point_type
         | 
| 19 | 
            +
                        ) unless library_name
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                        library = {
         | 
| 22 | 
            +
                          language: script_project.language,
         | 
| 23 | 
            +
                          version: task_runner.library_version(library_name),
         | 
| 24 | 
            +
                        }
         | 
| 25 | 
            +
             | 
| 14 26 | 
             
                        ProjectDependencies.install(ctx: ctx, task_runner: task_runner)
         | 
| 15 | 
            -
                        BuildScript.call(ctx: ctx, task_runner: task_runner, script_project: script_project)
         | 
| 27 | 
            +
                        BuildScript.call(ctx: ctx, task_runner: task_runner, script_project: script_project, library: library)
         | 
| 16 28 |  | 
| 17 29 | 
             
                        UI::PrintingSpinner.spin(ctx, ctx.message("script.application.pushing")) do |p_ctx, spinner|
         | 
| 18 30 | 
             
                          package = Infrastructure::PushPackageRepository.new(ctx: p_ctx).get_push_package(
         | 
| 19 31 | 
             
                            script_project: script_project,
         | 
| 20 32 | 
             
                            compiled_type: task_runner.compiled_type,
         | 
| 21 33 | 
             
                            metadata: task_runner.metadata,
         | 
| 34 | 
            +
                            library: library,
         | 
| 22 35 | 
             
                          )
         | 
| 23 36 | 
             
                          script_service = Infrastructure::ServiceLocator.script_service(
         | 
| 24 37 | 
             
                            ctx: p_ctx,
         | 
| @@ -32,6 +45,7 @@ module Script | |
| 32 45 | 
             
                            metadata: package.metadata,
         | 
| 33 46 | 
             
                            script_json: package.script_json,
         | 
| 34 47 | 
             
                            module_upload_url: module_upload_url,
         | 
| 48 | 
            +
                            library: package.library,
         | 
| 35 49 | 
             
                          )
         | 
| 36 50 | 
             
                          script_project_repo.update_env(uuid: uuid)
         | 
| 37 51 | 
             
                          spinner.update_title(p_ctx.message("script.application.pushed"))
         | 
| @@ -10,7 +10,8 @@ module Script | |
| 10 10 | 
             
                      :script_json,
         | 
| 11 11 | 
             
                      :script_content,
         | 
| 12 12 | 
             
                      :compiled_type,
         | 
| 13 | 
            -
                      :metadata
         | 
| 13 | 
            +
                      :metadata,
         | 
| 14 | 
            +
                      :library
         | 
| 14 15 |  | 
| 15 16 | 
             
                    def initialize(
         | 
| 16 17 | 
             
                      id:,
         | 
| @@ -19,7 +20,8 @@ module Script | |
| 19 20 | 
             
                      script_content:,
         | 
| 20 21 | 
             
                      compiled_type: nil,
         | 
| 21 22 | 
             
                      metadata:,
         | 
| 22 | 
            -
                      script_json | 
| 23 | 
            +
                      script_json:,
         | 
| 24 | 
            +
                      library:
         | 
| 23 25 | 
             
                    )
         | 
| 24 26 | 
             
                      @id = id
         | 
| 25 27 | 
             
                      @uuid = uuid
         | 
| @@ -28,6 +30,7 @@ module Script | |
| 28 30 | 
             
                      @compiled_type = compiled_type
         | 
| 29 31 | 
             
                      @metadata = metadata
         | 
| 30 32 | 
             
                      @script_json = script_json
         | 
| 33 | 
            +
                      @library = library
         | 
| 31 34 | 
             
                    end
         | 
| 32 35 | 
             
                  end
         | 
| 33 36 | 
             
                end
         | 
| @@ -15,7 +15,7 @@ module Script | |
| 15 15 | 
             
                      @version = @content["version"].to_s
         | 
| 16 16 | 
             
                      @title = @content["title"]
         | 
| 17 17 | 
             
                      @description = @content["description"]
         | 
| 18 | 
            -
                      @configuration_ui = @content | 
| 18 | 
            +
                      @configuration_ui = @content.fetch("configurationUi", true)
         | 
| 19 19 | 
             
                      @configuration = @content["configuration"]
         | 
| 20 20 | 
             
                    end
         | 
| 21 21 |  | 
    
        data/lib/project_types/script/layers/infrastructure/api_clients/partners_proxy_api_client.rb
    CHANGED
    
    | @@ -27,10 +27,6 @@ module Script | |
| 27 27 | 
             
                        case error_code(response["errors"])
         | 
| 28 28 | 
             
                        when "forbidden"
         | 
| 29 29 | 
             
                          raise Errors::ForbiddenError
         | 
| 30 | 
            -
                        when "forbidden_on_shop"
         | 
| 31 | 
            -
                          raise Errors::ShopAuthenticationError
         | 
| 32 | 
            -
                        when "app_not_installed_on_shop"
         | 
| 33 | 
            -
                          raise Errors::AppNotInstalledError
         | 
| 34 30 | 
             
                        else
         | 
| 35 31 | 
             
                          raise Errors::GraphqlError, response["errors"]
         | 
| 36 32 | 
             
                        end
         |