daytona 0.165.0 → 0.167.0.alpha.1
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/lib/daytona/common/charts.rb +97 -274
- data/lib/daytona/common/daytona.rb +2 -0
- data/lib/daytona/daytona.rb +11 -37
- data/lib/daytona/process.rb +34 -98
- data/lib/daytona/sandbox.rb +69 -7
- data/lib/daytona/sdk/version.rb +1 -1
- data/lib/daytona/sdk.rb +0 -3
- metadata +5 -8
- data/lib/daytona/code_toolbox/sandbox_js_code_toolbox.rb +0 -21
- data/lib/daytona/code_toolbox/sandbox_python_code_toolbox.rb +0 -438
- data/lib/daytona/code_toolbox/sandbox_ts_code_toolbox.rb +0 -30
data/lib/daytona/process.rb
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'base64'
|
|
4
|
-
require 'json'
|
|
5
3
|
require 'uri'
|
|
6
4
|
|
|
7
5
|
module Daytona
|
|
8
6
|
class Process # rubocop:disable Metrics/ClassLength
|
|
9
7
|
include Instrumentation
|
|
10
8
|
|
|
11
|
-
# @return [Daytona::SandboxPythonCodeToolbox,
|
|
12
|
-
attr_reader :code_toolbox
|
|
13
|
-
|
|
14
9
|
# @return [String] The ID of the Sandbox
|
|
15
10
|
attr_reader :sandbox_id
|
|
16
11
|
|
|
@@ -20,18 +15,21 @@ module Daytona
|
|
|
20
15
|
# @return [Proc] Function to get preview link for a port
|
|
21
16
|
attr_reader :get_preview_link
|
|
22
17
|
|
|
18
|
+
# @return [String] The language for code execution (e.g. 'python', 'typescript', 'javascript')
|
|
19
|
+
attr_reader :language
|
|
20
|
+
|
|
23
21
|
# Initialize a new Process instance
|
|
24
22
|
#
|
|
25
|
-
# @param code_toolbox [Daytona::SandboxPythonCodeToolbox, Daytona::SandboxTsCodeToolbox]
|
|
26
23
|
# @param sandbox_id [String] The ID of the Sandbox
|
|
27
24
|
# @param toolbox_api [DaytonaToolboxApiClient::ProcessApi] API client for Sandbox operations
|
|
28
25
|
# @param get_preview_link [Proc] Function to get preview link for a port
|
|
26
|
+
# @param language [String] The language for code execution
|
|
29
27
|
# @param otel_state [Daytona::OtelState, nil]
|
|
30
|
-
def initialize(
|
|
31
|
-
@code_toolbox = code_toolbox
|
|
28
|
+
def initialize(sandbox_id:, toolbox_api:, get_preview_link:, language: 'python', otel_state: nil)
|
|
32
29
|
@sandbox_id = sandbox_id
|
|
33
30
|
@toolbox_api = toolbox_api
|
|
34
31
|
@get_preview_link = get_preview_link
|
|
32
|
+
@language = language
|
|
35
33
|
@otel_state = otel_state
|
|
36
34
|
end
|
|
37
35
|
|
|
@@ -54,29 +52,16 @@ module Daytona
|
|
|
54
52
|
#
|
|
55
53
|
# # Command with timeout
|
|
56
54
|
# result = sandbox.process.exec("sleep 10", timeout: 5)
|
|
57
|
-
def exec(command:, cwd: nil, env: nil, timeout: nil)
|
|
58
|
-
|
|
59
|
-
env.each_key do |key|
|
|
60
|
-
unless key.match?(/\A[A-Za-z_][A-Za-z0-9_]*\z/)
|
|
61
|
-
raise ArgumentError,
|
|
62
|
-
"Invalid environment variable name: '#{key}'"
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
safe_env_exports = env.map do |key, value|
|
|
66
|
-
"export #{key}=\"$(printf '%s' '#{Base64.strict_encode64(value)}' | base64 -d)\""
|
|
67
|
-
end.join('; ')
|
|
68
|
-
command = "#{safe_env_exports}; #{command}"
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
response = toolbox_api.execute_command(DaytonaToolboxApiClient::ExecuteRequest.new(command:, cwd:, timeout:))
|
|
72
|
-
# Post-process the output to extract ExecutionArtifacts
|
|
73
|
-
artifacts = parse_output(response.result.split("\n", -1))
|
|
55
|
+
def exec(command:, cwd: nil, env: nil, timeout: nil)
|
|
56
|
+
envs = env&.empty? ? nil : env
|
|
74
57
|
|
|
75
|
-
|
|
58
|
+
response = toolbox_api.execute_command(DaytonaToolboxApiClient::ExecuteRequest.new(command:, cwd:, envs:,
|
|
59
|
+
timeout:))
|
|
60
|
+
result = response.result || ''
|
|
76
61
|
ExecuteResponse.new(
|
|
77
62
|
exit_code: response.exit_code,
|
|
78
|
-
result
|
|
79
|
-
artifacts:
|
|
63
|
+
result:,
|
|
64
|
+
artifacts: ExecutionArtifacts.new(result, [])
|
|
80
65
|
)
|
|
81
66
|
end
|
|
82
67
|
|
|
@@ -96,7 +81,19 @@ module Daytona
|
|
|
96
81
|
# CODE
|
|
97
82
|
# puts response.artifacts.stdout # Prints: Sum: 30
|
|
98
83
|
def code_run(code:, params: nil, timeout: nil)
|
|
99
|
-
|
|
84
|
+
response = toolbox_api.code_run(
|
|
85
|
+
DaytonaToolboxApiClient::CodeRunRequest.new(
|
|
86
|
+
code:, language:, argv: params&.argv, envs: params&.env, timeout:
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
ExecuteResponse.new(
|
|
91
|
+
exit_code: response.exit_code,
|
|
92
|
+
result: response.result,
|
|
93
|
+
artifacts: ExecutionArtifacts.new(response.result, (response.artifacts&.charts || []).map do |c|
|
|
94
|
+
Charts.parse_chart(c)
|
|
95
|
+
end)
|
|
96
|
+
)
|
|
100
97
|
end
|
|
101
98
|
|
|
102
99
|
# Creates a new long-running background session in the Sandbox
|
|
@@ -186,15 +183,12 @@ module Daytona
|
|
|
186
183
|
suppress_input_echo: req.suppress_input_echo)
|
|
187
184
|
)
|
|
188
185
|
|
|
189
|
-
stdout, stderr = Util.demux(response.output || '')
|
|
190
|
-
|
|
191
186
|
SessionExecuteResponse.new(
|
|
192
187
|
cmd_id: response.cmd_id,
|
|
193
188
|
output: response.output,
|
|
194
|
-
stdout
|
|
195
|
-
stderr
|
|
189
|
+
stdout: response.stdout || '',
|
|
190
|
+
stderr: response.stderr || '',
|
|
196
191
|
exit_code: response.exit_code,
|
|
197
|
-
# TODO: DaytonaApiClient::SessionExecuteResponse doesn't have additional_properties attribute
|
|
198
192
|
additional_properties: {}
|
|
199
193
|
)
|
|
200
194
|
end
|
|
@@ -210,12 +204,8 @@ module Daytona
|
|
|
210
204
|
# puts "Command stdout: #{logs.stdout}"
|
|
211
205
|
# puts "Command stderr: #{logs.stderr}"
|
|
212
206
|
def get_session_command_logs(session_id:, command_id:)
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
session_id,
|
|
216
|
-
command_id
|
|
217
|
-
)
|
|
218
|
-
)
|
|
207
|
+
response = toolbox_api.get_session_command_logs(session_id, command_id)
|
|
208
|
+
SessionCommandLogsResponse.new(output: response.output, stdout: response.stdout, stderr: response.stderr)
|
|
219
209
|
end
|
|
220
210
|
|
|
221
211
|
# Asynchronously retrieves and processes the logs for a command executed in a session as they become available
|
|
@@ -284,7 +274,10 @@ module Daytona
|
|
|
284
274
|
# logs = sandbox.process.get_entrypoint_logs()
|
|
285
275
|
# puts "Command stdout: #{logs.stdout}"
|
|
286
276
|
# puts "Command stderr: #{logs.stderr}"
|
|
287
|
-
def get_entrypoint_logs
|
|
277
|
+
def get_entrypoint_logs
|
|
278
|
+
response = toolbox_api.get_entrypoint_logs
|
|
279
|
+
SessionCommandLogsResponse.new(output: response.output, stdout: response.stdout, stderr: response.stderr)
|
|
280
|
+
end
|
|
288
281
|
|
|
289
282
|
# Asynchronously retrieves and processes the sandbox entrypoint logs as they become available
|
|
290
283
|
#
|
|
@@ -542,64 +535,7 @@ module Daytona
|
|
|
542
535
|
# @return [Daytona::OtelState, nil]
|
|
543
536
|
attr_reader :otel_state
|
|
544
537
|
|
|
545
|
-
# Parse the output of a command to extract ExecutionArtifacts
|
|
546
|
-
#
|
|
547
|
-
# @param lines [Array<String>] A list of lines of output from a command
|
|
548
|
-
# @return [Daytona::ExecutionArtifacts] The artifacts from the command execution
|
|
549
|
-
def parse_output(lines)
|
|
550
|
-
artifacts = ExecutionArtifacts.new('', [])
|
|
551
|
-
stdout_lines = []
|
|
552
|
-
|
|
553
|
-
lines.each do |line|
|
|
554
|
-
if line.start_with?(ARTIFACT_PREFIX)
|
|
555
|
-
parse_json_line(line:, artifacts:)
|
|
556
|
-
else
|
|
557
|
-
stdout_lines << line
|
|
558
|
-
end
|
|
559
|
-
end
|
|
560
|
-
|
|
561
|
-
artifacts.stdout = stdout_lines.join("\n")
|
|
562
|
-
artifacts
|
|
563
|
-
end
|
|
564
|
-
|
|
565
|
-
# Parse a JSON line to extract artifacts
|
|
566
|
-
#
|
|
567
|
-
# @param line [String] The line to parse
|
|
568
|
-
# @param artifacts [Daytona::ExecutionArtifacts] The artifacts to add to
|
|
569
|
-
# @return [void]
|
|
570
|
-
def parse_json_line(line:, artifacts:)
|
|
571
|
-
data = JSON.parse(line.sub(ARTIFACT_PREFIX, '').strip, symbolize_names: true)
|
|
572
|
-
|
|
573
|
-
case data.fetch(:type, nil)
|
|
574
|
-
when ArtifactType::CHART
|
|
575
|
-
artifacts.charts.append(Charts.parse(data.fetch(:value, {})))
|
|
576
|
-
end
|
|
577
|
-
end
|
|
578
|
-
|
|
579
|
-
# Parse combined stdout/stderr output into separate streams
|
|
580
|
-
#
|
|
581
|
-
# @param data [String] Combined log string with STDOUT_PREFIX and STDERR_PREFIX markers
|
|
582
|
-
# @return [SessionCommandLogsResponse] Response with separated stdout and stderr
|
|
583
|
-
def parse_session_command_logs(data)
|
|
584
|
-
stdout, stderr = Util.demux(data)
|
|
585
|
-
|
|
586
|
-
SessionCommandLogsResponse.new(
|
|
587
|
-
output: data,
|
|
588
|
-
stdout:,
|
|
589
|
-
stderr:
|
|
590
|
-
)
|
|
591
|
-
end
|
|
592
|
-
|
|
593
|
-
ARTIFACT_PREFIX = 'dtn_artifact_k39fd2:'
|
|
594
|
-
private_constant :ARTIFACT_PREFIX
|
|
595
|
-
|
|
596
538
|
WS_PORT = 2280
|
|
597
539
|
private_constant :WS_PORT
|
|
598
|
-
|
|
599
|
-
module ArtifactType
|
|
600
|
-
ALL = [
|
|
601
|
-
CHART = 'chart'
|
|
602
|
-
].freeze
|
|
603
|
-
end
|
|
604
540
|
end
|
|
605
541
|
end
|
data/lib/daytona/sandbox.rb
CHANGED
|
@@ -90,9 +90,6 @@ module Daytona
|
|
|
90
90
|
# @return [String] The version of the daemon running in the sandbox
|
|
91
91
|
attr_reader :daemon_version
|
|
92
92
|
|
|
93
|
-
# @return [Daytona::SandboxPythonCodeToolbox, Daytona::SandboxTsCodeToolbox]
|
|
94
|
-
attr_reader :code_toolbox
|
|
95
|
-
|
|
96
93
|
# @return [Daytona::Config]
|
|
97
94
|
attr_reader :config
|
|
98
95
|
|
|
@@ -114,14 +111,12 @@ module Daytona
|
|
|
114
111
|
# @return [Daytona::CodeInterpreter]
|
|
115
112
|
attr_reader :code_interpreter
|
|
116
113
|
|
|
117
|
-
# @params code_toolbox [Daytona::SandboxPythonCodeToolbox, Daytona::SandboxTsCodeToolbox]
|
|
118
114
|
# @params config [Daytona::Config]
|
|
119
115
|
# @params sandbox_api [DaytonaApiClient::SandboxApi]
|
|
120
116
|
# @params sandbox_dto [DaytonaApiClient::Sandbox]
|
|
121
117
|
# @params otel_state [Daytona::OtelState, nil]
|
|
122
|
-
def initialize(
|
|
118
|
+
def initialize(sandbox_dto:, config:, sandbox_api:, otel_state: nil) # rubocop:disable Metrics/MethodLength
|
|
123
119
|
process_response(sandbox_dto)
|
|
124
|
-
@code_toolbox = code_toolbox
|
|
125
120
|
@config = config
|
|
126
121
|
@sandbox_api = sandbox_api
|
|
127
122
|
@otel_state = otel_state
|
|
@@ -150,9 +145,9 @@ module Daytona
|
|
|
150
145
|
|
|
151
146
|
@process = Process.new(
|
|
152
147
|
sandbox_id: id,
|
|
153
|
-
code_toolbox:,
|
|
154
148
|
toolbox_api: process_api,
|
|
155
149
|
get_preview_link: proc { |port| preview_url(port) },
|
|
150
|
+
language: (labels || {}).fetch(CODE_TOOLBOX_LANGUAGE_LABEL, 'python'),
|
|
156
151
|
otel_state:
|
|
157
152
|
)
|
|
158
153
|
@fs = FileSystem.new(sandbox_id: id, toolbox_api: fs_api, otel_state:)
|
|
@@ -465,12 +460,59 @@ module Daytona
|
|
|
465
460
|
DaytonaApiClient::SandboxState::DESTROYED])
|
|
466
461
|
end
|
|
467
462
|
|
|
463
|
+
# Forks the Sandbox, creating a new Sandbox with an identical filesystem.
|
|
464
|
+
# The forked Sandbox is a copy-on-write clone of the original. It starts
|
|
465
|
+
# with the same disk contents but operates independently from that point on.
|
|
466
|
+
#
|
|
467
|
+
# @param name [String, nil] Optional name for the forked Sandbox
|
|
468
|
+
# @param timeout [Numeric] Maximum wait time in seconds (defaults to 60 s)
|
|
469
|
+
# @return [Daytona::Sandbox] The forked Sandbox
|
|
470
|
+
def experimental_fork(name: nil, timeout: DEFAULT_TIMEOUT) # rubocop:disable Metrics/MethodLength
|
|
471
|
+
forked_dto = nil
|
|
472
|
+
with_timeout(
|
|
473
|
+
timeout:,
|
|
474
|
+
message: "Sandbox #{id} fork failed to become ready within the #{timeout} seconds timeout period",
|
|
475
|
+
setup: proc {
|
|
476
|
+
forked_dto = sandbox_api.fork_sandbox(id, DaytonaApiClient::ForkSandbox.new(name:))
|
|
477
|
+
}
|
|
478
|
+
) do
|
|
479
|
+
forked = Sandbox.new(
|
|
480
|
+
sandbox_dto: forked_dto,
|
|
481
|
+
config:,
|
|
482
|
+
sandbox_api:,
|
|
483
|
+
code_toolbox:,
|
|
484
|
+
otel_state:
|
|
485
|
+
)
|
|
486
|
+
forked.send(:wait_for_states, operation: OPERATION_START,
|
|
487
|
+
target_states: [DaytonaApiClient::SandboxState::STARTED])
|
|
488
|
+
return forked
|
|
489
|
+
end
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
# Creates a snapshot from the current state of the Sandbox.
|
|
493
|
+
# The Sandbox will temporarily enter a 'snapshotting' state and return to its previous state when complete.
|
|
494
|
+
#
|
|
495
|
+
# @param name [String] Name for the new snapshot
|
|
496
|
+
# @param timeout [Numeric] Maximum wait time in seconds (defaults to 60 s)
|
|
497
|
+
# @return [void]
|
|
498
|
+
def experimental_create_snapshot(name:, timeout: DEFAULT_TIMEOUT)
|
|
499
|
+
with_timeout(
|
|
500
|
+
timeout:,
|
|
501
|
+
message: "Sandbox #{id} snapshot failed within the #{timeout} seconds timeout period",
|
|
502
|
+
setup: proc {
|
|
503
|
+
sandbox_api.create_sandbox_snapshot(id, DaytonaApiClient::CreateSandboxSnapshot.new(name:))
|
|
504
|
+
refresh
|
|
505
|
+
}
|
|
506
|
+
) { wait_for_snapshot_complete }
|
|
507
|
+
end
|
|
508
|
+
|
|
468
509
|
instrument :archive, :auto_archive_interval=, :auto_delete_interval=, :auto_stop_interval=,
|
|
469
510
|
:create_ssh_access, :delete, :get_user_home_dir, :get_work_dir, :labels=,
|
|
470
511
|
:preview_url, :create_signed_preview_url, :expire_signed_preview_url,
|
|
471
512
|
:refresh, :refresh_activity, :revoke_ssh_access, :start, :recover, :stop,
|
|
472
513
|
:create_lsp_server, :validate_ssh_access, :wait_for_sandbox_start,
|
|
473
514
|
:wait_for_sandbox_stop, :resize, :wait_for_resize_complete,
|
|
515
|
+
:experimental_fork, :experimental_create_snapshot,
|
|
474
516
|
component: 'Sandbox'
|
|
475
517
|
|
|
476
518
|
private
|
|
@@ -593,5 +635,25 @@ module Daytona
|
|
|
593
635
|
|
|
594
636
|
OPERATION_RESIZE = :resize
|
|
595
637
|
private_constant :OPERATION_RESIZE
|
|
638
|
+
|
|
639
|
+
def wait_for_snapshot_complete
|
|
640
|
+
interval = INITIAL_POLL_INTERVAL
|
|
641
|
+
start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
|
642
|
+
while state == DaytonaApiClient::SandboxState::SNAPSHOTTING
|
|
643
|
+
refresh
|
|
644
|
+
|
|
645
|
+
if [DaytonaApiClient::SandboxState::ERROR, DaytonaApiClient::SandboxState::BUILD_FAILED].include?(state)
|
|
646
|
+
raise Sdk::Error,
|
|
647
|
+
"Sandbox #{id} snapshot failed with state: #{state}, error reason: #{error_reason}"
|
|
648
|
+
end
|
|
649
|
+
|
|
650
|
+
break if state != DaytonaApiClient::SandboxState::SNAPSHOTTING
|
|
651
|
+
|
|
652
|
+
sleep(interval)
|
|
653
|
+
if ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - start_time > 5
|
|
654
|
+
interval = [interval * BACKOFF_MULTIPLIER, MAX_POLL_INTERVAL].min
|
|
655
|
+
end
|
|
656
|
+
end
|
|
657
|
+
end
|
|
596
658
|
end
|
|
597
659
|
end
|
data/lib/daytona/sdk/version.rb
CHANGED
data/lib/daytona/sdk.rb
CHANGED
|
@@ -24,9 +24,6 @@ require_relative 'common/response'
|
|
|
24
24
|
require_relative 'common/snapshot'
|
|
25
25
|
require_relative 'code_interpreter'
|
|
26
26
|
require_relative 'computer_use'
|
|
27
|
-
require_relative 'code_toolbox/sandbox_python_code_toolbox'
|
|
28
|
-
require_relative 'code_toolbox/sandbox_ts_code_toolbox'
|
|
29
|
-
require_relative 'code_toolbox/sandbox_js_code_toolbox'
|
|
30
27
|
require_relative 'daytona'
|
|
31
28
|
require_relative 'file_system'
|
|
32
29
|
require_relative 'git'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: daytona
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.167.0.alpha.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daytona Platforms Inc.
|
|
@@ -85,28 +85,28 @@ dependencies:
|
|
|
85
85
|
requirements:
|
|
86
86
|
- - '='
|
|
87
87
|
- !ruby/object:Gem::Version
|
|
88
|
-
version: 0.
|
|
88
|
+
version: 0.167.0.alpha.1
|
|
89
89
|
type: :runtime
|
|
90
90
|
prerelease: false
|
|
91
91
|
version_requirements: !ruby/object:Gem::Requirement
|
|
92
92
|
requirements:
|
|
93
93
|
- - '='
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
|
-
version: 0.
|
|
95
|
+
version: 0.167.0.alpha.1
|
|
96
96
|
- !ruby/object:Gem::Dependency
|
|
97
97
|
name: daytona_toolbox_api_client
|
|
98
98
|
requirement: !ruby/object:Gem::Requirement
|
|
99
99
|
requirements:
|
|
100
100
|
- - '='
|
|
101
101
|
- !ruby/object:Gem::Version
|
|
102
|
-
version: 0.
|
|
102
|
+
version: 0.167.0.alpha.1
|
|
103
103
|
type: :runtime
|
|
104
104
|
prerelease: false
|
|
105
105
|
version_requirements: !ruby/object:Gem::Requirement
|
|
106
106
|
requirements:
|
|
107
107
|
- - '='
|
|
108
108
|
- !ruby/object:Gem::Version
|
|
109
|
-
version: 0.
|
|
109
|
+
version: 0.167.0.alpha.1
|
|
110
110
|
- !ruby/object:Gem::Dependency
|
|
111
111
|
name: dotenv
|
|
112
112
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -179,9 +179,6 @@ files:
|
|
|
179
179
|
- Rakefile
|
|
180
180
|
- lib/daytona.rb
|
|
181
181
|
- lib/daytona/code_interpreter.rb
|
|
182
|
-
- lib/daytona/code_toolbox/sandbox_js_code_toolbox.rb
|
|
183
|
-
- lib/daytona/code_toolbox/sandbox_python_code_toolbox.rb
|
|
184
|
-
- lib/daytona/code_toolbox/sandbox_ts_code_toolbox.rb
|
|
185
182
|
- lib/daytona/common/charts.rb
|
|
186
183
|
- lib/daytona/common/code_interpreter.rb
|
|
187
184
|
- lib/daytona/common/code_language.rb
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'base64'
|
|
4
|
-
|
|
5
|
-
module Daytona
|
|
6
|
-
class SandboxJsCodeToolbox
|
|
7
|
-
def get_run_command(code, params = nil)
|
|
8
|
-
# Prepend argv fix: node - places '-' at argv[1]; splice it out to match legacy node -e behaviour
|
|
9
|
-
# Encode the provided code in base64
|
|
10
|
-
base64_code = Base64.strict_encode64("process.argv.splice(1, 1);\n" + code)
|
|
11
|
-
|
|
12
|
-
# Build command-line arguments string
|
|
13
|
-
argv = ''
|
|
14
|
-
argv = params.argv.join(' ') if params&.argv && !params.argv.empty?
|
|
15
|
-
|
|
16
|
-
# Pipe the base64-encoded code via stdin to avoid OS ARG_MAX limits on large payloads
|
|
17
|
-
# Use node - to read from stdin (node /dev/stdin does not work when stdin is a pipe)
|
|
18
|
-
"printf '%s' '#{base64_code}' | base64 -d | node - #{argv}"
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|