rails_pulse 0.2.5 → 0.2.7
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/app/helpers/rails_pulse/breadcrumbs_helper.rb +18 -9
- data/lib/generators/rails_pulse/upgrade_generator.rb +3 -3
- data/lib/rails_pulse/cleanup_service.rb +27 -31
- data/lib/rails_pulse/version.rb +1 -1
- metadata +2 -5
- data/public/rails-pulse-assets/rails-pulse-icons.js.map +0 -13
- data/public/rails-pulse-assets/rails-pulse.css.map +0 -1
- data/public/rails-pulse-assets/rails-pulse.js.map +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fa27bb069bc0caa54e5fda780981de2b934e74159bcfb56022c4faa56936700f
|
|
4
|
+
data.tar.gz: 1e9964ae760f5ddb6608a7e759877467ffd3511a416cf21bc3c896fd4b8cb452
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 81dbeb827db18b2eb34173c8eb673611dc190ca918b4269068829c8596d6f6fe7c73b66f8275efc7cfc4332838cc46dc48d2764979bab3faaaeb9fec245ee571
|
|
7
|
+
data.tar.gz: d8b6535688dd1ed2ce627f868fd4f992965efc59bfffdaa4666e9b6fe32830a22f2f8ff0ee55348bbea4e87a0b94529558c393ecb8140a0c9d62e9b962c14261
|
|
@@ -1,31 +1,40 @@
|
|
|
1
1
|
module RailsPulse
|
|
2
2
|
module BreadcrumbsHelper
|
|
3
3
|
def breadcrumbs
|
|
4
|
-
# Get the engine's mount point
|
|
5
|
-
|
|
4
|
+
# Get the engine's mount point segments
|
|
5
|
+
mount_segments = RailsPulse::Engine.routes.find_script_name({}).split("/").reject(&:empty?)
|
|
6
6
|
|
|
7
7
|
# Split the full path and remove empty segments
|
|
8
8
|
path_segments = request.path.split("/").reject(&:empty?)
|
|
9
9
|
|
|
10
|
-
# Find
|
|
11
|
-
|
|
10
|
+
# Find where the mount point segments end in the request path
|
|
11
|
+
mount_end_index = nil
|
|
12
|
+
(0..path_segments.length - mount_segments.length).each do |i|
|
|
13
|
+
if path_segments[i, mount_segments.length] == mount_segments
|
|
14
|
+
mount_end_index = i + mount_segments.length - 1
|
|
15
|
+
break
|
|
16
|
+
end
|
|
17
|
+
end
|
|
12
18
|
|
|
13
19
|
# If we can't find the mount point or it's the last segment, return empty
|
|
14
|
-
return [] if
|
|
20
|
+
return [] if mount_end_index.nil? || mount_end_index == path_segments.length - 1
|
|
15
21
|
|
|
16
22
|
# Only keep segments after the mount point
|
|
17
|
-
path_segments = path_segments[(
|
|
23
|
+
path_segments = path_segments[(mount_end_index + 1)..-1]
|
|
24
|
+
|
|
25
|
+
# Build the engine root path directly from mount segments (avoids relying on named route helper)
|
|
26
|
+
engine_root = "/" + mount_segments.join("/")
|
|
18
27
|
|
|
19
28
|
# Start with the Home link
|
|
20
29
|
crumbs = [ {
|
|
21
30
|
title: "Home",
|
|
22
|
-
path:
|
|
31
|
+
path: engine_root,
|
|
23
32
|
current: path_segments.empty?
|
|
24
33
|
} ]
|
|
25
34
|
|
|
26
35
|
return crumbs if path_segments.empty?
|
|
27
36
|
|
|
28
|
-
current_path =
|
|
37
|
+
current_path = engine_root
|
|
29
38
|
|
|
30
39
|
path_segments.each_with_index do |segment, index|
|
|
31
40
|
current_path += "/#{segment}"
|
|
@@ -58,7 +67,7 @@ module RailsPulse
|
|
|
58
67
|
path_segments[index + 1] =~ /^\d+$/
|
|
59
68
|
# This is a nested collection (e.g., /jobs/5/runs/291)
|
|
60
69
|
# Link to parent show page (e.g., /jobs/5)
|
|
61
|
-
path_segments[0..index-1].inject(
|
|
70
|
+
path_segments[0..index-1].inject(engine_root) { |path, seg| path + "/#{seg}" }
|
|
62
71
|
else
|
|
63
72
|
current_path
|
|
64
73
|
end
|
|
@@ -62,12 +62,12 @@ module RailsPulse
|
|
|
62
62
|
return false unless File.exist?(config_path)
|
|
63
63
|
|
|
64
64
|
require "yaml"
|
|
65
|
-
db_config = YAML.
|
|
65
|
+
db_config = YAML.safe_load(File.read(config_path), aliases: true)
|
|
66
66
|
|
|
67
67
|
# Check if any environment has a rails_pulse database configuration
|
|
68
68
|
db_config.values.any? { |env| env.is_a?(Hash) && env.key?("rails_pulse") }
|
|
69
|
-
rescue
|
|
70
|
-
# If we can't read the file, assume single database
|
|
69
|
+
rescue Psych::SyntaxError, Psych::AliasesNotEnabled, Errno::ENOENT
|
|
70
|
+
# If we can't read or parse the file, assume single database
|
|
71
71
|
false
|
|
72
72
|
end
|
|
73
73
|
|
|
@@ -85,32 +85,24 @@ module RailsPulse
|
|
|
85
85
|
def cleanup_queries_by_time(cutoff_time)
|
|
86
86
|
return 0 unless defined?(RailsPulse::Query)
|
|
87
87
|
|
|
88
|
-
# Only delete queries that have no associated operations
|
|
89
|
-
|
|
90
|
-
count = RailsPulse::Query
|
|
88
|
+
# Only delete queries that have no associated operations (atomic subquery avoids race condition)
|
|
89
|
+
scope = RailsPulse::Query
|
|
91
90
|
.where("created_at < ?", cutoff_time)
|
|
92
|
-
.where
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
.where("created_at < ?", cutoff_time)
|
|
96
|
-
.where.not(id: query_ids_with_operations)
|
|
97
|
-
.delete_all
|
|
91
|
+
.where("id NOT IN (SELECT DISTINCT query_id FROM rails_pulse_operations WHERE query_id IS NOT NULL)")
|
|
92
|
+
count = scope.count
|
|
93
|
+
scope.delete_all
|
|
98
94
|
count
|
|
99
95
|
end
|
|
100
96
|
|
|
101
97
|
def cleanup_routes_by_time(cutoff_time)
|
|
102
98
|
return 0 unless defined?(RailsPulse::Route)
|
|
103
99
|
|
|
104
|
-
# Only delete routes that have no associated requests
|
|
105
|
-
|
|
106
|
-
count = RailsPulse::Route
|
|
107
|
-
.where("created_at < ?", cutoff_time)
|
|
108
|
-
.where.not(id: route_ids_with_requests)
|
|
109
|
-
.count
|
|
110
|
-
RailsPulse::Route
|
|
100
|
+
# Only delete routes that have no associated requests (atomic subquery avoids race condition)
|
|
101
|
+
scope = RailsPulse::Route
|
|
111
102
|
.where("created_at < ?", cutoff_time)
|
|
112
|
-
.where
|
|
113
|
-
|
|
103
|
+
.where("id NOT IN (SELECT DISTINCT route_id FROM rails_pulse_requests WHERE route_id IS NOT NULL)")
|
|
104
|
+
count = scope.count
|
|
105
|
+
scope.delete_all
|
|
114
106
|
count
|
|
115
107
|
end
|
|
116
108
|
|
|
@@ -126,12 +118,12 @@ module RailsPulse
|
|
|
126
118
|
def cleanup_jobs_by_time(cutoff_time)
|
|
127
119
|
return 0 unless defined?(RailsPulse::Job)
|
|
128
120
|
|
|
129
|
-
|
|
130
|
-
|
|
121
|
+
# Only delete jobs that have no associated runs (atomic subquery avoids race condition)
|
|
122
|
+
scope = RailsPulse::Job
|
|
131
123
|
.where("created_at < ?", cutoff_time)
|
|
132
|
-
.where
|
|
133
|
-
count =
|
|
134
|
-
|
|
124
|
+
.where("id NOT IN (SELECT DISTINCT job_id FROM rails_pulse_job_runs WHERE job_id IS NOT NULL)")
|
|
125
|
+
count = scope.count
|
|
126
|
+
scope.delete_all
|
|
135
127
|
count
|
|
136
128
|
end
|
|
137
129
|
|
|
@@ -183,9 +175,10 @@ module RailsPulse
|
|
|
183
175
|
max_records = @config.max_table_records[:rails_pulse_queries]
|
|
184
176
|
return 0 unless max_records
|
|
185
177
|
|
|
186
|
-
# Only consider queries that have no associated operations
|
|
187
|
-
|
|
188
|
-
|
|
178
|
+
# Only consider queries that have no associated operations (atomic subquery avoids race condition)
|
|
179
|
+
available_queries = RailsPulse::Query.where(
|
|
180
|
+
"id NOT IN (SELECT DISTINCT query_id FROM rails_pulse_operations WHERE query_id IS NOT NULL)"
|
|
181
|
+
)
|
|
189
182
|
current_count = available_queries.count
|
|
190
183
|
return 0 if current_count <= max_records
|
|
191
184
|
|
|
@@ -205,9 +198,10 @@ module RailsPulse
|
|
|
205
198
|
max_records = @config.max_table_records[:rails_pulse_routes]
|
|
206
199
|
return 0 unless max_records
|
|
207
200
|
|
|
208
|
-
# Only consider routes that have no associated requests
|
|
209
|
-
|
|
210
|
-
|
|
201
|
+
# Only consider routes that have no associated requests (atomic subquery avoids race condition)
|
|
202
|
+
available_routes = RailsPulse::Route.where(
|
|
203
|
+
"id NOT IN (SELECT DISTINCT route_id FROM rails_pulse_requests WHERE route_id IS NOT NULL)"
|
|
204
|
+
)
|
|
211
205
|
current_count = available_routes.count
|
|
212
206
|
return 0 if current_count <= max_records
|
|
213
207
|
|
|
@@ -246,8 +240,10 @@ module RailsPulse
|
|
|
246
240
|
max_records = @config.max_table_records[:rails_pulse_jobs]
|
|
247
241
|
return 0 unless max_records
|
|
248
242
|
|
|
249
|
-
|
|
250
|
-
available_jobs = RailsPulse::Job.where
|
|
243
|
+
# Only consider jobs that have no associated runs (atomic subquery avoids race condition)
|
|
244
|
+
available_jobs = RailsPulse::Job.where(
|
|
245
|
+
"id NOT IN (SELECT DISTINCT job_id FROM rails_pulse_job_runs WHERE job_id IS NOT NULL)"
|
|
246
|
+
)
|
|
251
247
|
current_count = available_jobs.count
|
|
252
248
|
return 0 if current_count <= max_records
|
|
253
249
|
|
data/lib/rails_pulse/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails_pulse
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rails Pulse
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-04-
|
|
11
|
+
date: 2026-04-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -373,11 +373,8 @@ files:
|
|
|
373
373
|
- lib/tasks/rails_pulse_tasks.rake
|
|
374
374
|
- public/rails-pulse-assets/csp-test.js
|
|
375
375
|
- public/rails-pulse-assets/rails-pulse-icons.js
|
|
376
|
-
- public/rails-pulse-assets/rails-pulse-icons.js.map
|
|
377
376
|
- public/rails-pulse-assets/rails-pulse.css
|
|
378
|
-
- public/rails-pulse-assets/rails-pulse.css.map
|
|
379
377
|
- public/rails-pulse-assets/rails-pulse.js
|
|
380
|
-
- public/rails-pulse-assets/rails-pulse.js.map
|
|
381
378
|
- public/rails-pulse-assets/search.svg
|
|
382
379
|
- vendor/VENDORING.md
|
|
383
380
|
- vendor/assets/javascripts/rails-pulse-icons.js
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"file": "rails-pulse-icons.js",
|
|
4
|
-
"sourceRoot": "",
|
|
5
|
-
"sources": [
|
|
6
|
-
"rails-pulse-icons.js"
|
|
7
|
-
],
|
|
8
|
-
"names": [],
|
|
9
|
-
"mappings": "",
|
|
10
|
-
"sourcesContent": [
|
|
11
|
-
"// Rails Pulse Icons Bundle - Auto-generated\n// Contains 35 SVG icons for Rails Pulse\n\n(function() {\n 'use strict';\n\n // Icon data\n const icons = {\n \"menu\": \"<path d=\\\"M4 5h16\\\" /><path d=\\\"M4 12h16\\\" /><path d=\\\"M4 19h16\\\" />\",\n \"sun\": \"<circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"4\\\" /><path d=\\\"M12 2v2\\\" /><path d=\\\"M12 20v2\\\" /><path d=\\\"m4.93 4.93 1.41 1.41\\\" /><path d=\\\"m17.66 17.66 1.41 1.41\\\" /><path d=\\\"M2 12h2\\\" /><path d=\\\"M20 12h2\\\" /><path d=\\\"m6.34 17.66-1.41 1.41\\\" /><path d=\\\"m19.07 4.93-1.41 1.41\\\" />\",\n \"moon\": \"<path d=\\\"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401\\\" />\",\n \"chevron-right\": \"<path d=\\\"m9 18 6-6-6-6\\\" />\",\n \"chevron-left\": \"<path d=\\\"m15 18-6-6 6-6\\\" />\",\n \"chevron-down\": \"<path d=\\\"m6 9 6 6 6-6\\\" />\",\n \"chevron-up\": \"<path d=\\\"m18 15-6-6-6 6\\\" />\",\n \"chevrons-left\": \"<path d=\\\"m11 17-5-5 5-5\\\" /><path d=\\\"m18 17-5-5 5-5\\\" />\",\n \"chevrons-right\": \"<path d=\\\"m6 17 5-5-5-5\\\" /><path d=\\\"m13 17 5-5-5-5\\\" />\",\n \"loader-circle\": \"<path d=\\\"M12 2v4\\\" /><path d=\\\"m16.2 7.8 2.9-2.9\\\" /><path d=\\\"M18 12h4\\\" /><path d=\\\"m16.2 16.2 2.9 2.9\\\" /><path d=\\\"M12 18v4\\\" /><path d=\\\"m4.9 19.1 2.9-2.9\\\" /><path d=\\\"M2 12h4\\\" /><path d=\\\"m4.9 4.9 2.9 2.9\\\" />\",\n \"search\": \"<path d=\\\"m21 21-4.34-4.34\\\" /><circle cx=\\\"11\\\" cy=\\\"11\\\" r=\\\"8\\\" />\",\n \"list-filter\": \"<path d=\\\"M2 5h20\\\" /><path d=\\\"M6 12h12\\\" /><path d=\\\"M9 19h6\\\" />\",\n \"list-filter-plus\": \"<path d=\\\"M12 5H2\\\" /><path d=\\\"M6 12h12\\\" /><path d=\\\"M9 19h6\\\" /><path d=\\\"M16 5h6\\\" /><path d=\\\"M19 8V2\\\" />\",\n \"x\": \"<path d=\\\"M18 6 6 18\\\" /><path d=\\\"m6 6 12 12\\\" />\",\n \"x-circle\": \"<circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"10\\\" /><path d=\\\"m15 9-6 6\\\" /><path d=\\\"m9 9 6 6\\\" />\",\n \"check\": \"<path d=\\\"M20 6 9 17l-5-5\\\" />\",\n \"alert-circle\": \"<circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"10\\\" /><line x1=\\\"12\\\" x2=\\\"12\\\" y1=\\\"8\\\" y2=\\\"12\\\" /><line x1=\\\"12\\\" x2=\\\"12.01\\\" y1=\\\"16\\\" y2=\\\"16\\\" />\",\n \"alert-triangle\": \"<path d=\\\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\\\" /><path d=\\\"M12 9v4\\\" /><path d=\\\"M12 17h.01\\\" />\",\n \"info\": \"<circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"10\\\" /><path d=\\\"M12 16v-4\\\" /><path d=\\\"M12 8h.01\\\" />\",\n \"external-link\": \"<path d=\\\"M15 3h6v6\\\" /><path d=\\\"M10 14 21 3\\\" /><path d=\\\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\\\" />\",\n \"download\": \"<path d=\\\"M12 15V3\\\" /><path d=\\\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\\\" /><path d=\\\"m7 10 5 5 5-5\\\" />\",\n \"refresh-cw\": \"<path d=\\\"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\\\" /><path d=\\\"M21 3v5h-5\\\" /><path d=\\\"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\\\" /><path d=\\\"M8 16H3v5\\\" />\",\n \"clock\": \"<path d=\\\"M12 6v6l4 2\\\" /><circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"10\\\" />\",\n \"database\": \"<ellipse cx=\\\"12\\\" cy=\\\"5\\\" rx=\\\"9\\\" ry=\\\"3\\\" /><path d=\\\"M3 5V19A9 3 0 0 0 21 19V5\\\" /><path d=\\\"M3 12A9 3 0 0 0 21 12\\\" />\",\n \"server\": \"<rect width=\\\"20\\\" height=\\\"8\\\" x=\\\"2\\\" y=\\\"2\\\" rx=\\\"2\\\" ry=\\\"2\\\" /><rect width=\\\"20\\\" height=\\\"8\\\" x=\\\"2\\\" y=\\\"14\\\" rx=\\\"2\\\" ry=\\\"2\\\" /><line x1=\\\"6\\\" x2=\\\"6.01\\\" y1=\\\"6\\\" y2=\\\"6\\\" /><line x1=\\\"6\\\" x2=\\\"6.01\\\" y1=\\\"18\\\" y2=\\\"18\\\" />\",\n \"activity\": \"<path d=\\\"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2\\\" />\",\n \"layout-dashboard\": \"<rect width=\\\"7\\\" height=\\\"9\\\" x=\\\"3\\\" y=\\\"3\\\" rx=\\\"1\\\" /><rect width=\\\"7\\\" height=\\\"5\\\" x=\\\"14\\\" y=\\\"3\\\" rx=\\\"1\\\" /><rect width=\\\"7\\\" height=\\\"9\\\" x=\\\"14\\\" y=\\\"12\\\" rx=\\\"1\\\" /><rect width=\\\"7\\\" height=\\\"5\\\" x=\\\"3\\\" y=\\\"16\\\" rx=\\\"1\\\" />\",\n \"audio-lines\": \"<path d=\\\"M2 10v3\\\" /><path d=\\\"M6 6v11\\\" /><path d=\\\"M10 3v18\\\" /><path d=\\\"M14 8v7\\\" /><path d=\\\"M18 5v13\\\" /><path d=\\\"M22 10v3\\\" />\",\n \"message-circle-question\": \"<path d=\\\"M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719\\\" /><path d=\\\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\\\" /><path d=\\\"M12 17h.01\\\" />\",\n \"route\": \"<circle cx=\\\"6\\\" cy=\\\"19\\\" r=\\\"3\\\" /><path d=\\\"M9 19h8.5a3.5 3.5 0 0 0 0-7h-11a3.5 3.5 0 0 1 0-7H15\\\" /><circle cx=\\\"18\\\" cy=\\\"5\\\" r=\\\"3\\\" />\",\n \"trending-up\": \"<path d=\\\"M16 7h6v6\\\" /><path d=\\\"m22 7-8.5 8.5-5-5L2 17\\\" />\",\n \"trending-down\": \"<path d=\\\"M16 17h6v-6\\\" /><path d=\\\"m22 17-8.5-8.5-5 5L2 7\\\" />\",\n \"move-right\": \"<path d=\\\"M18 8L22 12L18 16\\\" /><path d=\\\"M2 12H22\\\" />\",\n \"eye\": \"<path d=\\\"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\\\" /><circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"3\\\" />\",\n \"zap\": \"<path d=\\\"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z\\\" />\"\n};\n\n // Global icon registry\n window.RailsPulseIcons = {\n icons: icons,\n\n // Get icon SVG content\n get: function(name) {\n return icons[name] || null;\n },\n\n // Check if icon exists\n has: function(name) {\n return name in icons;\n },\n\n // Get all icon names\n list: function() {\n return Object.keys(icons);\n },\n\n // Render icon to element (CSP-safe)\n render: function(name, element, options = {}) {\n const svgContent = this.get(name);\n if (!svgContent || !element) return false;\n\n // Create SVG element\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('width', options.width || '24');\n svg.setAttribute('height', options.height || '24');\n svg.setAttribute('viewBox', '0 0 24 24');\n svg.setAttribute('fill', 'none');\n svg.setAttribute('stroke', 'currentColor');\n svg.setAttribute('stroke-width', '2');\n svg.setAttribute('stroke-linecap', 'round');\n svg.setAttribute('stroke-linejoin', 'round');\n\n // Add icon content\n svg.innerHTML = svgContent;\n\n // Replace element content\n element.innerHTML = '';\n element.appendChild(svg);\n\n return true;\n }\n };\n})();\n"
|
|
12
|
-
]
|
|
13
|
-
}
|