appmap 0.51.1 → 0.53.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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -1
- data/CHANGELOG.md +38 -0
- data/Rakefile +21 -5
- data/appmap.gemspec +11 -7
- data/exe/appmap-agent-init +19 -0
- data/exe/appmap-inspect +7 -0
- data/lib/appmap.rb +44 -12
- data/lib/appmap/command/agent_setup/init.rb +44 -0
- data/lib/appmap/command/inspect.rb +27 -0
- data/lib/appmap/command_error.rb +13 -0
- data/lib/appmap/config.rb +6 -24
- data/lib/appmap/handler/rails/template.rb +19 -5
- data/lib/appmap/node_cli.rb +59 -0
- data/lib/appmap/service/guesser.rb +19 -0
- data/lib/appmap/trace.rb +4 -2
- data/lib/appmap/util.rb +31 -2
- data/lib/appmap/version.rb +2 -1
- data/package.json +6 -7
- data/spec/fixtures/rails5_users_app/docker-compose.yml +1 -1
- data/spec/fixtures/rails6_users_app/Dockerfile +9 -0
- data/spec/fixtures/rails6_users_app/docker-compose.yml +1 -1
- data/spec/{abstract_controller_base_spec.rb → rails_recording_spec.rb} +2 -21
- data/spec/rails_spec_helper.rb +22 -0
- data/test/agent_setup_init_test.rb +37 -0
- data/test/fixtures/gem_test/Gemfile +1 -0
- data/test/inspect_cli_test.rb +12 -0
- data/yarn.lock +477 -0
- metadata +23 -61
- data/lib/appmap/algorithm/prune_class_map.rb +0 -67
- data/lib/appmap/algorithm/stats.rb +0 -91
- data/lib/appmap/command/record.rb +0 -38
- data/lib/appmap/command/stats.rb +0 -14
- data/lore/pages/2019-05-21-install-and-record/index.pug +0 -51
- data/lore/pages/2019-05-21-install-and-record/install_example_appmap.png +0 -0
- data/lore/pages/2019-05-21-install-and-record/metadata.yml +0 -5
- data/lore/pages/layout.pug +0 -66
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.css +0 -1912
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.css.map +0 -1
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.min.css +0 -7
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.min.css.map +0 -1
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.css +0 -331
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.css.map +0 -1
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.min.css +0 -8
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.min.css.map +0 -1
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap.css +0 -9030
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap.css.map +0 -1
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap.min.css +0 -7
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap.min.css.map +0 -1
- data/lore/public/stylesheets/style.css +0 -8
- data/package-lock.json +0 -1064
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appmap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.53.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Gilpin
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-06-
|
11
|
+
date: 2021-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -24,34 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: faraday
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: gli
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
27
|
- !ruby/object:Gem::Dependency
|
56
28
|
name: method_source
|
57
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,7 +39,7 @@ dependencies:
|
|
67
39
|
- !ruby/object:Gem::Version
|
68
40
|
version: '0'
|
69
41
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
42
|
+
name: rack
|
71
43
|
requirement: !ruby/object:Gem::Requirement
|
72
44
|
requirements:
|
73
45
|
- - ">="
|
@@ -81,7 +53,7 @@ dependencies:
|
|
81
53
|
- !ruby/object:Gem::Version
|
82
54
|
version: '0'
|
83
55
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
56
|
+
name: reverse_markdown
|
85
57
|
requirement: !ruby/object:Gem::Requirement
|
86
58
|
requirements:
|
87
59
|
- - ">="
|
@@ -112,16 +84,16 @@ dependencies:
|
|
112
84
|
name: minitest
|
113
85
|
requirement: !ruby/object:Gem::Requirement
|
114
86
|
requirements:
|
115
|
-
- -
|
87
|
+
- - '='
|
116
88
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
89
|
+
version: 5.14.4
|
118
90
|
type: :development
|
119
91
|
prerelease: false
|
120
92
|
version_requirements: !ruby/object:Gem::Requirement
|
121
93
|
requirements:
|
122
|
-
- -
|
94
|
+
- - '='
|
123
95
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
96
|
+
version: 5.14.4
|
125
97
|
- !ruby/object:Gem::Dependency
|
126
98
|
name: pry-byebug
|
127
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -307,7 +279,9 @@ dependencies:
|
|
307
279
|
description:
|
308
280
|
email:
|
309
281
|
- kgilpin@gmail.com
|
310
|
-
executables:
|
282
|
+
executables:
|
283
|
+
- appmap-agent-init
|
284
|
+
- appmap-inspect
|
311
285
|
extensions:
|
312
286
|
- ext/appmap/extconf.rb
|
313
287
|
extra_rdoc_files: []
|
@@ -335,14 +309,15 @@ files:
|
|
335
309
|
- examples/mock_webapp/lib/mock_webapp/controller.rb
|
336
310
|
- examples/mock_webapp/lib/mock_webapp/request.rb
|
337
311
|
- examples/mock_webapp/lib/mock_webapp/user.rb
|
312
|
+
- exe/appmap-agent-init
|
313
|
+
- exe/appmap-inspect
|
338
314
|
- ext/appmap/appmap.c
|
339
315
|
- ext/appmap/extconf.rb
|
340
316
|
- lib/appmap.rb
|
341
|
-
- lib/appmap/algorithm/prune_class_map.rb
|
342
|
-
- lib/appmap/algorithm/stats.rb
|
343
317
|
- lib/appmap/class_map.rb
|
344
|
-
- lib/appmap/command/
|
345
|
-
- lib/appmap/command/
|
318
|
+
- lib/appmap/command/agent_setup/init.rb
|
319
|
+
- lib/appmap/command/inspect.rb
|
320
|
+
- lib/appmap/command_error.rb
|
346
321
|
- lib/appmap/config.rb
|
347
322
|
- lib/appmap/cucumber.rb
|
348
323
|
- lib/appmap/event.rb
|
@@ -356,34 +331,17 @@ files:
|
|
356
331
|
- lib/appmap/metadata.rb
|
357
332
|
- lib/appmap/middleware/remote_recording.rb
|
358
333
|
- lib/appmap/minitest.rb
|
334
|
+
- lib/appmap/node_cli.rb
|
359
335
|
- lib/appmap/open.rb
|
360
336
|
- lib/appmap/railtie.rb
|
361
337
|
- lib/appmap/record.rb
|
362
338
|
- lib/appmap/rspec.rb
|
339
|
+
- lib/appmap/service/guesser.rb
|
363
340
|
- lib/appmap/trace.rb
|
364
341
|
- lib/appmap/util.rb
|
365
342
|
- lib/appmap/version.rb
|
366
|
-
- lore/pages/2019-05-21-install-and-record/index.pug
|
367
|
-
- lore/pages/2019-05-21-install-and-record/install_example_appmap.png
|
368
|
-
- lore/pages/2019-05-21-install-and-record/metadata.yml
|
369
|
-
- lore/pages/layout.pug
|
370
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.css
|
371
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.css.map
|
372
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.min.css
|
373
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.min.css.map
|
374
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.css
|
375
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.css.map
|
376
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.min.css
|
377
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.min.css.map
|
378
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap.css
|
379
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap.css.map
|
380
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap.min.css
|
381
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap.min.css.map
|
382
|
-
- lore/public/stylesheets/style.css
|
383
|
-
- package-lock.json
|
384
343
|
- package.json
|
385
344
|
- release.sh
|
386
|
-
- spec/abstract_controller_base_spec.rb
|
387
345
|
- spec/class_map_spec.rb
|
388
346
|
- spec/config_spec.rb
|
389
347
|
- spec/fixtures/hook/attr_accessor.rb
|
@@ -548,6 +506,7 @@ files:
|
|
548
506
|
- spec/fixtures/rails6_users_app/users_app/.gitignore
|
549
507
|
- spec/hook_spec.rb
|
550
508
|
- spec/open_spec.rb
|
509
|
+
- spec/rails_recording_spec.rb
|
551
510
|
- spec/rails_spec_helper.rb
|
552
511
|
- spec/railtie_spec.rb
|
553
512
|
- spec/record_net_http_spec.rb
|
@@ -555,6 +514,7 @@ files:
|
|
555
514
|
- spec/remote_recording_spec.rb
|
556
515
|
- spec/spec_helper.rb
|
557
516
|
- spec/util_spec.rb
|
517
|
+
- test/agent_setup_init_test.rb
|
558
518
|
- test/bundle_vendor_test.rb
|
559
519
|
- test/cucumber_test.rb
|
560
520
|
- test/expectations/openssl_test_key_sign1.json
|
@@ -599,11 +559,13 @@ files:
|
|
599
559
|
- test/fixtures/rspec_recorder/spec/labeled_hello_spec.rb
|
600
560
|
- test/fixtures/rspec_recorder/spec/plain_hello_spec.rb
|
601
561
|
- test/gem_test.rb
|
562
|
+
- test/inspect_cli_test.rb
|
602
563
|
- test/minitest_test.rb
|
603
564
|
- test/openssl_test.rb
|
604
565
|
- test/record_process_test.rb
|
605
566
|
- test/rspec_test.rb
|
606
567
|
- test/test_helper.rb
|
568
|
+
- yarn.lock
|
607
569
|
homepage: https://github.com/applandinc/appmap-ruby
|
608
570
|
licenses:
|
609
571
|
- MIT
|
@@ -1,67 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module AppMap
|
4
|
-
module Algorithm
|
5
|
-
# Prune a class map so that only functions, classes and packages which are referenced
|
6
|
-
# by some event are retained.
|
7
|
-
class PruneClassMap
|
8
|
-
attr_reader :class_map
|
9
|
-
# Set this attribute to a function which will log algorithm events.
|
10
|
-
attr_writer :logger
|
11
|
-
attr_accessor :events
|
12
|
-
|
13
|
-
# Construct the algorithm, with a class map that will be pruned in place.
|
14
|
-
def initialize(class_map)
|
15
|
-
@class_map = class_map
|
16
|
-
@logger = ->(msg) {}
|
17
|
-
end
|
18
|
-
|
19
|
-
def perform
|
20
|
-
# This proc counts the number of objects in the class map whose type is 'k'
|
21
|
-
count = proc do |k, e|
|
22
|
-
n = 0
|
23
|
-
n += 1 if e['type'] == k
|
24
|
-
n += (e['children'] || []).map { |child| count.call(k, child) }.reduce(0, :+)
|
25
|
-
n
|
26
|
-
end
|
27
|
-
|
28
|
-
@logger.call "Full classMap contains #{class_map.map { |m| count.call('class', m) }.reduce(0, :+)} classes"
|
29
|
-
|
30
|
-
# Prune all the classes which fail a test.
|
31
|
-
reject = proc do |list, test|
|
32
|
-
list.tap do |_|
|
33
|
-
list.each do |item|
|
34
|
-
children = item['children']
|
35
|
-
next unless children
|
36
|
-
|
37
|
-
reject.call(children, test)
|
38
|
-
end
|
39
|
-
list.reject!(&test)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
if events
|
44
|
-
locations = \
|
45
|
-
Set.new(events.select { |e| e['event'] == 'call' }
|
46
|
-
.map { |e| [ e['path'], e['lineno'] ].join(':') })
|
47
|
-
|
48
|
-
# Prune all functions which aren't called
|
49
|
-
reject.call class_map,
|
50
|
-
->(e) { e['type'] == 'function' && !locations.member?(e['location']) }
|
51
|
-
end
|
52
|
-
|
53
|
-
# Prune all empty classes
|
54
|
-
reject.call class_map,
|
55
|
-
->(e) { e['type'] == 'class' && (e['children'] || []).empty? }
|
56
|
-
|
57
|
-
# Prune all empty packages
|
58
|
-
reject.call class_map,
|
59
|
-
->(e) { e['type'] == 'package' && (e['children'] || []).empty? }
|
60
|
-
|
61
|
-
@logger.call "Pruned classMap contains #{class_map.map { |m| count.call('class', m) }.reduce(0, :+)} classes"
|
62
|
-
|
63
|
-
class_map
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
@@ -1,91 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module AppMap
|
4
|
-
module Algorithm
|
5
|
-
StatsStruct = Struct.new(:appmap)
|
6
|
-
|
7
|
-
# Compute AppMap statistics.
|
8
|
-
class Stats < StatsStruct
|
9
|
-
Result = Struct.new(:class_frequency, :method_frequency) do
|
10
|
-
def merge!(other)
|
11
|
-
merge = lambda do |freq, other_freq|
|
12
|
-
freq_by_name = freq.inject({}) do |table, entry|
|
13
|
-
table.tap do
|
14
|
-
table[entry.name] = entry
|
15
|
-
end
|
16
|
-
end
|
17
|
-
other_freq.each do |other_entry|
|
18
|
-
entry = freq_by_name[other_entry.name]
|
19
|
-
if entry
|
20
|
-
entry.count += other_entry.count
|
21
|
-
else
|
22
|
-
freq << other_entry
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
merge.call(class_frequency, other.class_frequency)
|
27
|
-
merge.call(method_frequency, other.method_frequency)
|
28
|
-
|
29
|
-
self
|
30
|
-
end
|
31
|
-
|
32
|
-
def sort!
|
33
|
-
comparator = ->(a,b) { b.count <=> a.count }
|
34
|
-
class_frequency.sort!(&comparator)
|
35
|
-
method_frequency.sort!(&comparator)
|
36
|
-
|
37
|
-
self
|
38
|
-
end
|
39
|
-
|
40
|
-
def limit!(limit)
|
41
|
-
self.class_frequency = class_frequency[0...limit]
|
42
|
-
self.method_frequency = method_frequency[0...limit]
|
43
|
-
|
44
|
-
self
|
45
|
-
end
|
46
|
-
|
47
|
-
def as_text
|
48
|
-
lines = [
|
49
|
-
"Class frequency:",
|
50
|
-
"----------------",
|
51
|
-
] + class_frequency.map(&:to_a).map(&:reverse).map { |line | line.join("\t") } + [
|
52
|
-
"",
|
53
|
-
"Method frequency:",
|
54
|
-
"----------------",
|
55
|
-
] + method_frequency.map(&:to_a).map(&:reverse).map { |line | line.join("\t") }
|
56
|
-
lines.join("\n")
|
57
|
-
end
|
58
|
-
end
|
59
|
-
Frequency = Struct.new(:name, :count)
|
60
|
-
|
61
|
-
def perform(limit: nil)
|
62
|
-
events = appmap['events'] || []
|
63
|
-
frequency_calc = lambda do |key_func|
|
64
|
-
events_by_key = events.inject(Hash.new(0)) do |memo, event|
|
65
|
-
key = key_func.call(event)
|
66
|
-
memo.tap do
|
67
|
-
memo[key] += 1 if key
|
68
|
-
end
|
69
|
-
end
|
70
|
-
events_by_key.map do |key, count|
|
71
|
-
Frequency.new(key, count)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
class_name_func = ->(event) { event['defined_class'] }
|
76
|
-
full_name_func = lambda do |event|
|
77
|
-
call = event['event'] == 'call'
|
78
|
-
class_name = event['defined_class']
|
79
|
-
static = event['static']
|
80
|
-
function_name = event['method_id']
|
81
|
-
[ class_name, static ? '.' : '#', function_name ].join if call && class_name && !static.nil? && function_name
|
82
|
-
end
|
83
|
-
|
84
|
-
class_frequency = frequency_calc.call(class_name_func)
|
85
|
-
method_frequency = frequency_calc.call(full_name_func)
|
86
|
-
|
87
|
-
Result.new(class_frequency, method_frequency)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module AppMap
|
4
|
-
module Command
|
5
|
-
RecordStruct = Struct.new(:config, :program)
|
6
|
-
|
7
|
-
class Record < RecordStruct
|
8
|
-
def perform(&block)
|
9
|
-
tracer = AppMap.tracing.trace
|
10
|
-
|
11
|
-
events = []
|
12
|
-
quit = false
|
13
|
-
event_thread = Thread.new do
|
14
|
-
while tracer.event? || !quit
|
15
|
-
event = tracer.next_event
|
16
|
-
if event
|
17
|
-
events << event.to_h
|
18
|
-
else
|
19
|
-
sleep 0.0001
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
event_thread.abort_on_exception = true
|
24
|
-
|
25
|
-
at_exit do
|
26
|
-
quit = true
|
27
|
-
event_thread.join
|
28
|
-
yield AppMap::APPMAP_FORMAT_VERSION,
|
29
|
-
AppMap.detect_metadata,
|
30
|
-
AppMap.class_map(tracer.event_methods),
|
31
|
-
events
|
32
|
-
end
|
33
|
-
|
34
|
-
load program if program
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
data/lib/appmap/command/stats.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module AppMap
|
4
|
-
module Command
|
5
|
-
StatsStruct = Struct.new(:appmap)
|
6
|
-
|
7
|
-
class Stats < StatsStruct
|
8
|
-
def perform(limit: nil)
|
9
|
-
require 'appmap/algorithm/stats'
|
10
|
-
AppMap::Algorithm::Stats.new(appmap).perform(limit: limit)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
extends ../layout
|
2
|
-
|
3
|
-
block objective
|
4
|
-
div.
|
5
|
-
Installation of the AppMap client for Ruby is a key step in the user adoption flow.
|
6
|
-
Let's create an example program which installs the #[code appmap] Ruby gem and runs it to record a
|
7
|
-
scenario of a sample app.
|
8
|
-
|
9
|
-
block approach
|
10
|
-
:markdown-it
|
11
|
-
The [examples](https://github.com/applandinc/appmap-ruby/blob/master/examples/) folder in this project contains a sample project called `mock_webapp`, which
|
12
|
-
performs the following:
|
13
|
-
|
14
|
-
* Requests a `User` object by id ("alice").
|
15
|
-
* The request is handled by a `Controller`.
|
16
|
-
* The `Controller` looks up the id in a `User` model.
|
17
|
-
* The `User` model looks up the id and returns a `User` object, or raises an error.
|
18
|
-
* The `Controller` renders the response as a Hash and returns it to the client.
|
19
|
-
|
20
|
-
A test program called `install.rb` installs the `appmap` Ruby gem and then records the `mock_webapp`.
|
21
|
-
To create an appmap of `install.rb`:
|
22
|
-
|
23
|
-
```
|
24
|
-
bundle exec exe/record examples/install.rb
|
25
|
-
```
|
26
|
-
|
27
|
-
To upload the AppMap to AppLand:
|
28
|
-
|
29
|
-
```
|
30
|
-
bundle exec exe/upload appmap.json
|
31
|
-
```
|
32
|
-
|
33
|
-
block results
|
34
|
-
:markdown-it
|
35
|
-
## AppMap of `install.rb`
|
36
|
-
|
37
|
-
[](https://appland-staging.herokuapp.com/scenarios/ba2fc385-a96d-42bf-9ef8-cdbdab8a475d)
|
38
|
-
|
39
|
-
button(onclick="document.querySelector('#show-test-program').style.display = 'block';") Show test program code
|
40
|
-
div#show-test-program(style='display: none;')
|
41
|
-
pre
|
42
|
-
include ../../../examples/install.rb
|
43
|
-
|
44
|
-
block next_steps
|
45
|
-
:markdown-it
|
46
|
-
|
47
|
-
A related feature is the AppLand server receiving the scenario file and displaying it.
|
48
|
-
|
49
|
-
Here is an [AppMap of the server receiving a scenario file](https://appland-staging.herokuapp.com/scenarios/beb49bc7-b2ca-49b6-bac3-5d2eec2df062).
|
50
|
-
|
51
|
-
|