stratabi 1.0.0__py3-none-any.whl

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.
Files changed (188) hide show
  1. stratabi/__init__.py +3 -0
  2. stratabi/app.py +327 -0
  3. stratabi/assets/00_monaco_loader.js +1 -0
  4. stratabi/assets/MonkeyHammer-TransparentBckgrnd.png +0 -0
  5. stratabi/assets/favicon.ico +0 -0
  6. stratabi/assets/favicon.png +0 -0
  7. stratabi/assets/logo.png +0 -0
  8. stratabi/assets/main.css +72 -0
  9. stratabi/assets/monaco/vs/_commonjsHelpers-CT9FvmAN.js +1 -0
  10. stratabi/assets/monaco/vs/abap-D-t0cyap.js +1 -0
  11. stratabi/assets/monaco/vs/apex-CcIm7xu6.js +1 -0
  12. stratabi/assets/monaco/vs/assets/css.worker-HnVq6Ewq.js +93 -0
  13. stratabi/assets/monaco/vs/assets/editor.worker-Be8ye1pW.js +26 -0
  14. stratabi/assets/monaco/vs/assets/html.worker-B51mlPHg.js +470 -0
  15. stratabi/assets/monaco/vs/assets/json.worker-DKiEKt88.js +58 -0
  16. stratabi/assets/monaco/vs/assets/ts.worker-CMbG-7ft.js +67731 -0
  17. stratabi/assets/monaco/vs/azcli-BA0tQDCg.js +1 -0
  18. stratabi/assets/monaco/vs/basic-languages/monaco.contribution.js +1 -0
  19. stratabi/assets/monaco/vs/bat-C397hTD6.js +1 -0
  20. stratabi/assets/monaco/vs/bicep-DF5aW17k.js +2 -0
  21. stratabi/assets/monaco/vs/cameligo-plsz8qhj.js +1 -0
  22. stratabi/assets/monaco/vs/clojure-Y2auQMzK.js +1 -0
  23. stratabi/assets/monaco/vs/coffee-Bu45yuWE.js +1 -0
  24. stratabi/assets/monaco/vs/cpp-CkKPQIni.js +1 -0
  25. stratabi/assets/monaco/vs/csharp-CX28MZyh.js +1 -0
  26. stratabi/assets/monaco/vs/csp-D8uWnyxW.js +1 -0
  27. stratabi/assets/monaco/vs/css-CaeNmE3S.js +3 -0
  28. stratabi/assets/monaco/vs/cssMode-CjiAH6dQ.js +1 -0
  29. stratabi/assets/monaco/vs/cypher-DVThT8BS.js +1 -0
  30. stratabi/assets/monaco/vs/dart-CmGfCvrO.js +1 -0
  31. stratabi/assets/monaco/vs/dockerfile-CZqqYdch.js +1 -0
  32. stratabi/assets/monaco/vs/ecl-30fUercY.js +1 -0
  33. stratabi/assets/monaco/vs/editor/editor.main.css +1 -0
  34. stratabi/assets/monaco/vs/editor/editor.main.js +5 -0
  35. stratabi/assets/monaco/vs/editor.api-CalNCsUg.js +903 -0
  36. stratabi/assets/monaco/vs/elixir-xjPaIfzF.js +1 -0
  37. stratabi/assets/monaco/vs/flow9-DqtmStfK.js +1 -0
  38. stratabi/assets/monaco/vs/freemarker2-Cz_sV6Md.js +3 -0
  39. stratabi/assets/monaco/vs/fsharp-BOMdg4U1.js +1 -0
  40. stratabi/assets/monaco/vs/go-D_hbi-Jt.js +1 -0
  41. stratabi/assets/monaco/vs/graphql-CKUU4kLG.js +1 -0
  42. stratabi/assets/monaco/vs/handlebars-OwglfO-1.js +1 -0
  43. stratabi/assets/monaco/vs/hcl-DTaboeZW.js +1 -0
  44. stratabi/assets/monaco/vs/html-Pa1xEWsY.js +1 -0
  45. stratabi/assets/monaco/vs/htmlMode-Bz67EXwp.js +1 -0
  46. stratabi/assets/monaco/vs/ini-CsNwO04R.js +1 -0
  47. stratabi/assets/monaco/vs/java-CI4ZMsH9.js +1 -0
  48. stratabi/assets/monaco/vs/javascript-PczUCGdz.js +1 -0
  49. stratabi/assets/monaco/vs/jsonMode-DULH5oaX.js +7 -0
  50. stratabi/assets/monaco/vs/julia-BwzEvaQw.js +1 -0
  51. stratabi/assets/monaco/vs/kotlin-IUYPiTV8.js +1 -0
  52. stratabi/assets/monaco/vs/language/css/monaco.contribution.js +1 -0
  53. stratabi/assets/monaco/vs/language/html/monaco.contribution.js +1 -0
  54. stratabi/assets/monaco/vs/language/json/monaco.contribution.js +1 -0
  55. stratabi/assets/monaco/vs/language/typescript/monaco.contribution.js +1 -0
  56. stratabi/assets/monaco/vs/less-C0eDYdqa.js +2 -0
  57. stratabi/assets/monaco/vs/lexon-iON-Kj97.js +1 -0
  58. stratabi/assets/monaco/vs/liquid-DqKjdPGy.js +1 -0
  59. stratabi/assets/monaco/vs/loader.js +1368 -0
  60. stratabi/assets/monaco/vs/lspLanguageFeatures-kM9O9rjY.js +4 -0
  61. stratabi/assets/monaco/vs/lua-DtygF91M.js +1 -0
  62. stratabi/assets/monaco/vs/m3-CsR4AuFi.js +1 -0
  63. stratabi/assets/monaco/vs/markdown-C_rD0bIw.js +1 -0
  64. stratabi/assets/monaco/vs/mdx-DEWtB1K5.js +1 -0
  65. stratabi/assets/monaco/vs/mips-CiYP61RB.js +1 -0
  66. stratabi/assets/monaco/vs/monaco.contribution-D2OdxNBt.js +1 -0
  67. stratabi/assets/monaco/vs/monaco.contribution-DO3azKX8.js +1 -0
  68. stratabi/assets/monaco/vs/monaco.contribution-EcChJV6a.js +1 -0
  69. stratabi/assets/monaco/vs/monaco.contribution-qLAYrEOP.js +1 -0
  70. stratabi/assets/monaco/vs/msdax-C38-sJlp.js +1 -0
  71. stratabi/assets/monaco/vs/mysql-CdtbpvbG.js +1 -0
  72. stratabi/assets/monaco/vs/nls.messages-loader.js +1 -0
  73. stratabi/assets/monaco/vs/nls.messages.cs.js.js +17 -0
  74. stratabi/assets/monaco/vs/nls.messages.de.js.js +17 -0
  75. stratabi/assets/monaco/vs/nls.messages.es.js.js +17 -0
  76. stratabi/assets/monaco/vs/nls.messages.fr.js.js +15 -0
  77. stratabi/assets/monaco/vs/nls.messages.it.js.js +15 -0
  78. stratabi/assets/monaco/vs/nls.messages.ja.js.js +17 -0
  79. stratabi/assets/monaco/vs/nls.messages.js.js +10 -0
  80. stratabi/assets/monaco/vs/nls.messages.ko.js.js +25 -0
  81. stratabi/assets/monaco/vs/nls.messages.pl.js.js +17 -0
  82. stratabi/assets/monaco/vs/nls.messages.pt-br.js.js +6 -0
  83. stratabi/assets/monaco/vs/nls.messages.ru.js.js +17 -0
  84. stratabi/assets/monaco/vs/nls.messages.tr.js.js +15 -0
  85. stratabi/assets/monaco/vs/nls.messages.zh-cn.js.js +17 -0
  86. stratabi/assets/monaco/vs/nls.messages.zh-tw.js.js +15 -0
  87. stratabi/assets/monaco/vs/objective-c-CntZFaHX.js +1 -0
  88. stratabi/assets/monaco/vs/pascal-r6kuqfl_.js +1 -0
  89. stratabi/assets/monaco/vs/pascaligo-BiXoTmXh.js +1 -0
  90. stratabi/assets/monaco/vs/perl-DABw_TcH.js +1 -0
  91. stratabi/assets/monaco/vs/pgsql-me_jFXeX.js +1 -0
  92. stratabi/assets/monaco/vs/php-D_kh-9LK.js +1 -0
  93. stratabi/assets/monaco/vs/pla-VfZjczW0.js +1 -0
  94. stratabi/assets/monaco/vs/postiats-BBSzz8Pk.js +1 -0
  95. stratabi/assets/monaco/vs/powerquery-Dt-g_2cc.js +1 -0
  96. stratabi/assets/monaco/vs/powershell-B-7ap1zc.js +1 -0
  97. stratabi/assets/monaco/vs/protobuf-BmtuEB1A.js +2 -0
  98. stratabi/assets/monaco/vs/pug-BRpRNeEb.js +1 -0
  99. stratabi/assets/monaco/vs/python-Cr0UkIbn.js +1 -0
  100. stratabi/assets/monaco/vs/qsharp-BzsFaUU9.js +1 -0
  101. stratabi/assets/monaco/vs/r-f8dDdrp4.js +1 -0
  102. stratabi/assets/monaco/vs/razor-BYAHOTkz.js +1 -0
  103. stratabi/assets/monaco/vs/redis-fvZQY4PI.js +1 -0
  104. stratabi/assets/monaco/vs/redshift-45Et0LQi.js +1 -0
  105. stratabi/assets/monaco/vs/restructuredtext-C7UUFKFD.js +1 -0
  106. stratabi/assets/monaco/vs/ruby-CZO8zYTz.js +1 -0
  107. stratabi/assets/monaco/vs/rust-Bfetafyc.js +1 -0
  108. stratabi/assets/monaco/vs/sb-3GYllVck.js +1 -0
  109. stratabi/assets/monaco/vs/scala-foMgrKo1.js +1 -0
  110. stratabi/assets/monaco/vs/scheme-CHdMtr7p.js +1 -0
  111. stratabi/assets/monaco/vs/scss-C1cmLt9V.js +3 -0
  112. stratabi/assets/monaco/vs/shell-ClXCKCEW.js +1 -0
  113. stratabi/assets/monaco/vs/solidity-MZ6ExpPy.js +1 -0
  114. stratabi/assets/monaco/vs/sophia-DWkuSsPQ.js +1 -0
  115. stratabi/assets/monaco/vs/sparql-AUGFYSyk.js +1 -0
  116. stratabi/assets/monaco/vs/sql-32GpJSV2.js +1 -0
  117. stratabi/assets/monaco/vs/st-CuDFIVZ_.js +1 -0
  118. stratabi/assets/monaco/vs/swift-n-2HociN.js +3 -0
  119. stratabi/assets/monaco/vs/systemverilog-Ch4vA8Yt.js +1 -0
  120. stratabi/assets/monaco/vs/tcl-D74tq1nH.js +1 -0
  121. stratabi/assets/monaco/vs/tsMode-CZz1Umrk.js +11 -0
  122. stratabi/assets/monaco/vs/twig-C6taOxMV.js +1 -0
  123. stratabi/assets/monaco/vs/typescript-DfOrAzoV.js +1 -0
  124. stratabi/assets/monaco/vs/typespec-D-PIh9Xw.js +1 -0
  125. stratabi/assets/monaco/vs/vb-Dyb2648j.js +1 -0
  126. stratabi/assets/monaco/vs/wgsl-BhLXMOR0.js +298 -0
  127. stratabi/assets/monaco/vs/workers-DcJshg-q.js +1 -0
  128. stratabi/assets/monaco/vs/xml-CdsdnY8S.js +1 -0
  129. stratabi/assets/monaco/vs/yaml-DYGvmE88.js +1 -0
  130. stratabi/assets/monaco-init.js +21 -0
  131. stratabi/assets/plotly.min.js +8 -0
  132. stratabi/assets/stratabi_monaco_init.js +127 -0
  133. stratabi/assets/theme_reader.js +1 -0
  134. stratabi/blocks/image.py +32 -0
  135. stratabi/blocks/input_range.py +53 -0
  136. stratabi/blocks/input_select.py +107 -0
  137. stratabi/blocks/markdown.py +26 -0
  138. stratabi/blocks/plotly.py +47 -0
  139. stratabi/blocks/plotly_resampler.py +47 -0
  140. stratabi/blocks/raw_html.py +34 -0
  141. stratabi/blocks/table.py +77 -0
  142. stratabi/cli.py +243 -0
  143. stratabi/components/navbar.py +97 -0
  144. stratabi/core/ai_helpers.py +117 -0
  145. stratabi/core/athena_runner.py +94 -0
  146. stratabi/core/base.py +17 -0
  147. stratabi/core/binder.py +54 -0
  148. stratabi/core/config.py +71 -0
  149. stratabi/core/dynamo_helpers.py +0 -0
  150. stratabi/core/icons.py +5 -0
  151. stratabi/core/lambda_runner.py +125 -0
  152. stratabi/core/layout_engine.py +20 -0
  153. stratabi/core/loader.py +72 -0
  154. stratabi/core/plotly_utils.py +128 -0
  155. stratabi/core/registry.py +21 -0
  156. stratabi/core/renderer.py +28 -0
  157. stratabi/core/runner.py +611 -0
  158. stratabi/core/s3_loader.py +1401 -0
  159. stratabi/core/source_macros.py +535 -0
  160. stratabi/core/source_resolver.py +276 -0
  161. stratabi/core/status_store.py +130 -0
  162. stratabi/core/text_utils.py +18 -0
  163. stratabi/core/theme_loader.py +57 -0
  164. stratabi/data/schemas/dashboard.schema.json +1105 -0
  165. stratabi/data/schemas/module.schema.json +345 -0
  166. stratabi/demo/__init__.py +78 -0
  167. stratabi/demo/athena.py +219 -0
  168. stratabi/demo/cleanup.py +92 -0
  169. stratabi/demo/dashboard.py +187 -0
  170. stratabi/demo/generate.py +238 -0
  171. stratabi/demo/metrics.py +129 -0
  172. stratabi/demo/model.py +92 -0
  173. stratabi/demo/quick.py +129 -0
  174. stratabi/demo/schemas.py +103 -0
  175. stratabi/pages/__init__.py +0 -0
  176. stratabi/pages/builder.py +1231 -0
  177. stratabi/pages/dashboard.py +1196 -0
  178. stratabi/themes/guildmaster.css +12257 -0
  179. stratabi/themes/guildmaster_light.css +69 -0
  180. stratabi/themes/themes.json +4 -0
  181. stratabi-1.0.0.dist-info/METADATA +253 -0
  182. stratabi-1.0.0.dist-info/RECORD +188 -0
  183. stratabi-1.0.0.dist-info/WHEEL +5 -0
  184. stratabi-1.0.0.dist-info/entry_points.txt +3 -0
  185. stratabi-1.0.0.dist-info/licenses/LICENSE.docx +0 -0
  186. stratabi-1.0.0.dist-info/licenses/LICENSE.md +620 -0
  187. stratabi-1.0.0.dist-info/licenses/THIRD_PARTY_NOTICES.md +80 -0
  188. stratabi-1.0.0.dist-info/top_level.txt +1 -0
stratabi/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ # Versioning is Major.Sprint.Patch (Shaleio ecosystem sprint clock), not SemVer.
2
+ # Sprint 0 begins 2026-07-27. See "Versioning" in the README.
3
+ __version__ = "1.0.0"
stratabi/app.py ADDED
@@ -0,0 +1,327 @@
1
+ '''
2
+ app.py
3
+
4
+ This file defines the app object and app layout
5
+ '''
6
+
7
+ '''Imports'''
8
+ import os
9
+ import json
10
+ import dash
11
+ import flask
12
+ import boto3
13
+ from dash import html, dcc, Input, Output, State, callback, ctx, no_update, clientside_callback
14
+ import dash_bootstrap_components as dbc
15
+ import dash_ag_grid as dag
16
+ from dash.exceptions import PreventUpdate
17
+ from stratabi.components.navbar import navbar
18
+ from stratabi.core.registry import *
19
+ from stratabi.core.s3_loader import resolve_actor_token
20
+ import logging
21
+ from dotenv import load_dotenv
22
+
23
+ # Load AWS creds + STRATABI_* config from a local .env if present (dev convenience).
24
+ load_dotenv()
25
+
26
+ logging.basicConfig(level=logging.INFO)
27
+ logger = logging.getLogger(__name__)
28
+
29
+ logger.info("Starting StrataBI")
30
+ logger.info("STRATABI_SYSTEM_BUCKET=%s", os.getenv("STRATABI_SYSTEM_BUCKET"))
31
+ logger.info("STRATABI_THEME_PREFIX=%s", os.getenv("STRATABI_THEME_PREFIX"))
32
+ logger.info("STRATABI_DASHBOARD_PREFIX=%s", os.getenv("STRATABI_DASHBOARD_PREFIX"))
33
+ logger.info("STRATABI_ATHENA_OUTPUT=%s", os.getenv("STRATABI_ATHENA_OUTPUT"))
34
+
35
+
36
+ #dynamo declaration
37
+ dynamodb = boto3.resource("dynamodb")
38
+
39
+ #define server
40
+ server = flask.Flask(__name__)
41
+
42
+ @server.route("/healthz")
43
+ def healthz():
44
+ return {"status": "ok"}, 200
45
+
46
+
47
+ '''module_utils'''
48
+ def get_module_registry_table():
49
+ table_name = os.getenv("STRATABI_MODULE_REGISTRY_TABLE")
50
+ if not table_name:
51
+ return None
52
+
53
+ return dynamodb.Table(table_name)
54
+
55
+
56
+ def scan_app_modules() -> list[dict]:
57
+ table = get_module_registry_table()
58
+
59
+ if table is None:
60
+ return []
61
+
62
+ items = []
63
+ last_key = None
64
+
65
+ while True:
66
+ kwargs = {}
67
+
68
+ if last_key:
69
+ kwargs["ExclusiveStartKey"] = last_key
70
+
71
+ response = table.scan(**kwargs)
72
+
73
+ for item in response.get("Items", []):
74
+ module_type = item.get("module_type")
75
+
76
+ if module_type in {"app", "multi_page_app"}:
77
+ items.append(item)
78
+
79
+ last_key = response.get("LastEvaluatedKey")
80
+
81
+ if not last_key:
82
+ break
83
+
84
+ items.sort(key=lambda item: str(item.get("label") or item.get("module_id") or "").lower())
85
+
86
+ return items
87
+
88
+ '''App Call'''
89
+ # ---------------------------------------------------------------------
90
+ # Theme delivery
91
+ # ---------------------------------------------------------------------
92
+ # The selected theme (a full Bootstrap/Bootswatch stylesheet) is bundled into
93
+ # the container image at stratabi/themes/ and served from this app's OWN origin
94
+ # at /stratabi-theme.css. Nothing is fetched at runtime -- no S3, no public CDN
95
+ # -- so styling works in a fully air-gapped enclave and cannot fail due to
96
+ # network/IAM. One image carries every theme; STRATABI_THEME just selects which
97
+ # bundled file to serve.
98
+ #
99
+ # Set STRATABI_THEME_URL to a literal URL (a public S3 object, a CloudFront
100
+ # distribution, etc.) to load the theme from there instead, if air-gapping is
101
+ # not a concern.
102
+ STRATABI_THEME = os.getenv("STRATABI_THEME", "guildmaster")
103
+ STRATABI_THEME_URL = os.getenv("STRATABI_THEME_URL", "").strip()
104
+ _THEMES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "themes")
105
+ _theme_css_cache = {}
106
+
107
+
108
+ def _resolve_theme_filename(name):
109
+ # Registry first (handles guildmaster.css vs <name>.min.css), then fall back
110
+ # to whichever bundled file actually exists.
111
+ try:
112
+ with open(os.path.join(_THEMES_DIR, "themes.json"), encoding="utf-8") as f:
113
+ reg = json.load(f)
114
+ fn = reg.get(name)
115
+ if fn and os.path.exists(os.path.join(_THEMES_DIR, fn)):
116
+ return fn
117
+ except Exception:
118
+ pass
119
+ for candidate in (f"{name}.min.css", f"{name}.css"):
120
+ if os.path.exists(os.path.join(_THEMES_DIR, candidate)):
121
+ return candidate
122
+ return f"{name}.min.css"
123
+
124
+
125
+ def _load_theme_css(name):
126
+ if name in _theme_css_cache:
127
+ return _theme_css_cache[name]
128
+ css = ""
129
+ try:
130
+ path = os.path.join(_THEMES_DIR, _resolve_theme_filename(name))
131
+ with open(path, encoding="utf-8", errors="replace") as f:
132
+ css = f.read()
133
+ except Exception as e:
134
+ logger.warning("Theme load failed for %s: %s", name, e)
135
+ _theme_css_cache[name] = css
136
+ return css
137
+
138
+
139
+ @server.route("/stratabi-theme.css")
140
+ def stratabi_theme_css():
141
+ return flask.Response(_load_theme_css(STRATABI_THEME), mimetype="text/css")
142
+
143
+
144
+ THEME_STYLESHEET = STRATABI_THEME_URL or "/stratabi-theme.css"
145
+
146
+ # Monaco editor uses its built-in light ("vs") / dark ("vs-dark") themes.
147
+ # Derive from the app theme so a dark Bootswatch theme gets a dark editor;
148
+ # STRATABI_EDITOR_THEME ("vs" | "vs-dark") forces it explicitly.
149
+ _DARK_THEMES = {"guildmaster", "cyborg", "darkly", "slate", "solar", "superhero", "vapor"}
150
+ STRATABI_EDITOR_THEME = os.getenv("STRATABI_EDITOR_THEME", "").strip() or (
151
+ "vs-dark" if STRATABI_THEME in _DARK_THEMES else "vs"
152
+ )
153
+
154
+
155
+ app = dash.Dash(
156
+ __name__,
157
+ prevent_initial_callbacks = "initial_duplicate",
158
+ use_pages = True,
159
+ # THEME_STYLESHEET first (Bootstrap). dag.themes load the legacy AG Grid CSS
160
+ # (BASE + ALPINE => ag-theme-alpine + ag-theme-alpine-dark) needed by v33
161
+ # legacy themes (see blocks/table.py theme:"legacy").
162
+ external_stylesheets=[THEME_STYLESHEET, dag.themes.BASE, dag.themes.ALPINE],
163
+ suppress_callback_exceptions=True,
164
+ update_title="Building...",
165
+ server = server
166
+ )
167
+ app.title = "ShaleIO StrataBI"
168
+
169
+ '''App Layout'''
170
+ url_bar_navbar_content = html.Div([
171
+ dcc.Location(id='url'),
172
+ html.Div(
173
+ children=[
174
+ navbar
175
+ ]
176
+ ),
177
+ html.Div(id="bootstrap-vars", style={"display": "none"})
178
+ ])
179
+
180
+ app.layout = html.Div([
181
+ url_bar_navbar_content,
182
+ dash.page_container,
183
+ html.Div(id="stratabi-editor-theme",
184
+ **{"data-theme": STRATABI_EDITOR_THEME},
185
+ style={"display": "none"}),
186
+ dcc.Store(id="dashboard-input-store"), # Stores input tile values (future)
187
+ dcc.Store(id="dashboard-status-store"), # Stores Dynamo/Lambda statuses
188
+ dcc.Store(id="dashboard-trigger-store"), # Stores most recent input tile triggered
189
+ dcc.Store(id="dashboard-run-store"), # Per-tile run (▷) button target; separate from the trigger bus
190
+ dcc.Store(id="dashboard-selector-store"),
191
+ dcc.Store(id="current-user-id-store"),
192
+ dcc.Store(id="active-dashboard-key-store"),
193
+ dcc.Store(id="module-active-page-store"),
194
+ dcc.Store(id="builder-selected-module-context-store", data=[]),
195
+ dcc.Store(id="dashboard-config-store"), # Stores parsed dashboard JSON
196
+ dcc.Store(id="dashboard-refresh-store"),
197
+ dcc.Store(id="dashboard-runtime-session-store", storage_type="session"),
198
+ dcc.Store(id="tile-runtime-store", storage_type="session"),
199
+ dcc.Interval(
200
+ id="dashboard-interval",
201
+ interval=60_000,
202
+ disabled=True,
203
+ n_intervals=0,
204
+ ),
205
+ dbc.Modal(
206
+ [
207
+ dbc.ModalHeader(dbc.ModalTitle("Apps")),
208
+ dbc.ModalBody(html.Div(id="apps-modal-body")),
209
+ ],
210
+ id="apps-modal",
211
+ is_open=False,
212
+ size="lg",
213
+ ),
214
+ ])
215
+
216
+ @callback(
217
+ Output("apps-modal", "is_open"),
218
+ Output("apps-modal-body", "children"),
219
+ Input("navbar-apps-button", "n_clicks"),
220
+ Input("url", "pathname"),
221
+ State("apps-modal", "is_open"),
222
+ prevent_initial_call=True,
223
+ )
224
+ def toggle_apps_modal(n_clicks, pathname, is_open):
225
+ if ctx.triggered_id == "url":
226
+ return False, no_update
227
+
228
+ if not n_clicks:
229
+ raise PreventUpdate
230
+
231
+ modules = scan_app_modules()
232
+
233
+ if not modules:
234
+ body = dbc.Alert(
235
+ "No apps found in the module registry.",
236
+ color="warning",
237
+ className="mb-0",
238
+ )
239
+ return True, body
240
+
241
+ rows = []
242
+
243
+ for module in modules:
244
+ module_id = module.get("module_id")
245
+ label = module.get("label") or module_id
246
+ description = module.get("description", "")
247
+ module_type = module.get("module_type", "app")
248
+ version = module.get("version", "")
249
+
250
+ if not module_id:
251
+ continue
252
+
253
+ rows.append(
254
+ dbc.ListGroupItem(
255
+ dcc.Link(
256
+ html.Div(
257
+ [
258
+ html.Div(
259
+ [
260
+ html.Span(label, className="fw-bold"),
261
+ html.Span(
262
+ f" {version}" if version else "",
263
+ className="text-muted small ms-2",
264
+ ),
265
+ ]
266
+ ),
267
+ html.Div(
268
+ description,
269
+ className="small text-muted",
270
+ ) if description else None,
271
+ html.Div(
272
+ module_type,
273
+ className="small text-info mt-1",
274
+ ),
275
+ ]
276
+ ),
277
+ href=f"/dashboard/apps/{module_id}",
278
+ className="text-decoration-none",
279
+ ),
280
+ action=True,
281
+ )
282
+ )
283
+
284
+ body = dbc.ListGroup(rows) if rows else dbc.Alert(
285
+ "Module registry returned no valid app modules.",
286
+ color="warning",
287
+ className="mb-0",
288
+ )
289
+
290
+ return True, body
291
+
292
+
293
+ @callback(
294
+ Output("current-user-id-store", "data"),
295
+ Input("url", "pathname"),
296
+ )
297
+ def hydrate_current_user(_):
298
+ return resolve_actor_token() or "anonymous"
299
+
300
+
301
+ clientside_callback(
302
+ """
303
+ function(pathname, currentSession) {
304
+ if (currentSession && currentSession.runtime_session_id) {
305
+ return currentSession;
306
+ }
307
+
308
+ const randomPart = (
309
+ window.crypto && window.crypto.randomUUID
310
+ )
311
+ ? window.crypto.randomUUID()
312
+ : Math.random().toString(36).slice(2) + Date.now().toString(36);
313
+
314
+ return {
315
+ runtime_session_id: randomPart,
316
+ created_at: new Date().toISOString(),
317
+ pathname: pathname
318
+ };
319
+ }
320
+ """,
321
+ Output("dashboard-runtime-session-store", "data"),
322
+ Input("url", "pathname"),
323
+ State("dashboard-runtime-session-store", "data"),
324
+ )
325
+
326
+ if __name__=='__main__':
327
+ app.run(host="0.0.0.0", port=8050, debug=True)
@@ -0,0 +1 @@
1
+ var require = { paths: { vs: "/assets/monaco/vs" } };
Binary file
Binary file
Binary file
@@ -0,0 +1,72 @@
1
+ /* Make modal body scroll independently */
2
+ .modal-dialog-scrollable .modal-body {
3
+ max-height: calc(100vh - 200px);
4
+ overflow-y: auto;
5
+ }
6
+
7
+ /* ===========================================================================
8
+ Dash Design Kit theming.
9
+
10
+ dcc.Dropdown / DatePicker / Checklist (dash >= 4) are NOT react-select or
11
+ Bootstrap-styled — they render their own markup (.dash-dropdown,
12
+ .dash-options-list-option, .dash-dropdown-content, …) and are themed entirely
13
+ by --Dash-* design tokens. By default --Dash-Fill-Inverse-Strong resolves to
14
+ white and --Dash-Fill-Interactive-Strong to a purple, so on a dark theme you
15
+ get white boxes, barely-visible text, and purple hovers.
16
+
17
+ Instead of overriding every component class, we remap the --Dash-* tokens to
18
+ the active Bootstrap/Bootswatch theme variables. One block themes every Dash
19
+ component, light OR dark, automatically. !important so it wins over the Dash
20
+ bundle regardless of stylesheet load order.
21
+ =========================================================================== */
22
+ :root {
23
+ /* Surfaces + text (component CSS references both Strong/strong casings) */
24
+ --Dash-Fill-Inverse-Strong: var(--bs-body-bg, #212529) !important;
25
+ --Dash-Fill-Inverse-strong: var(--bs-body-bg, #212529) !important;
26
+ --Dash-Text-Strong: var(--bs-body-color, #f8f9fa) !important;
27
+ --Dash-Text-Weak: var(--bs-secondary-color, #adb5bd) !important;
28
+ --Dash-Text-Disabled: var(--bs-secondary-color, #6c757d) !important;
29
+ --Dash-Stroke-Strong: var(--bs-border-color, #495057) !important;
30
+
31
+ /* Interactive accent (focus rings, checkbox accent, search focus) -> brand teal */
32
+ --Dash-Fill-Interactive-Strong: var(--bs-primary, #34b6c4) !important;
33
+ --Dash-Fill-Interactive-Weak: var(--bs-tertiary-bg, rgba(255, 255, 255, 0.08)) !important;
34
+ --Dash-Fill-Disabled: var(--bs-border-color, #495057) !important;
35
+
36
+ /* Menu shadow */
37
+ --Dash-Shading-Strong: rgba(0, 0, 0, 0.5) !important;
38
+ --Dash-Shading-Weak: rgba(0, 0, 0, 0.35) !important;
39
+ }
40
+
41
+ /* Option row hover/keyboard focus -> success (per request), with a subtle fill
42
+ for affordance. Overrides the token-driven text color on the hovered row only,
43
+ so general interactive accents stay brand teal but row hover reads as success. */
44
+ .dash-options-list-option:not(:has(input[disabled])):hover,
45
+ .dash-options-list-option:not(:has(input[disabled])):focus-within {
46
+ color: var(--bs-success, #2faa86) !important;
47
+ background: rgba(var(--bs-success-rgb, 47, 170, 134), 0.12) !important;
48
+ }
49
+
50
+ /* Selected option: keep text readable on the dark menu with a faint brand fill */
51
+ .dash-options-list-option.selected,
52
+ .dash-options-list-option[aria-selected="true"] {
53
+ color: var(--bs-body-color, #f8f9fa) !important;
54
+ background: rgba(var(--bs-primary-rgb, 52, 182, 196), 0.15) !important;
55
+ }
56
+
57
+ /* Placeholder / empty value text stays muted but visible */
58
+ .dash-dropdown-placeholder {
59
+ color: var(--bs-secondary-color, #adb5bd) !important;
60
+ }
61
+
62
+ /* ---------------------------------------------------------------------------
63
+ DatePicker (dash-datepicker-*) — same Dash Design Kit token system, so it is
64
+ already themed by the --Dash-* remap above (dark surfaces, light text, teal
65
+ selected day, faint range fill). This only adds the one consistency touch:
66
+ make calendar DAY HOVER read success, matching the dropdown row hover. The
67
+ selected day keeps the brand-teal token treatment.
68
+ --------------------------------------------------------------------------- */
69
+ .dash-datepicker-calendar td:not(.dash-datepicker-calendar-date-selected):not(.dash-datepicker-calendar-date-disabled):hover {
70
+ background-color: rgba(var(--bs-success-rgb, 47, 170, 134), 0.15) !important;
71
+ color: var(--bs-success, #2faa86) !important;
72
+ }
@@ -0,0 +1 @@
1
+ define("vs/_commonjsHelpers-CT9FvmAN",["exports"],(function(t){"use strict";function o(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}t.getDefaultExportFromCjs=o}));
@@ -0,0 +1 @@
1
+ define("vs/abap-D-t0cyap",["exports"],(function(e){"use strict";const t={comments:{lineComment:"*"},brackets:[["[","]"],["(",")"]]},n={defaultToken:"invalid",ignoreCase:!0,tokenPostfix:".abap",keywords:["abap-source","abbreviated","abstract","accept","accepting","according","activation","actual","add","add-corresponding","adjacent","after","alias","aliases","align","all","allocate","alpha","analysis","analyzer","and","append","appendage","appending","application","archive","area","arithmetic","as","ascending","aspect","assert","assign","assigned","assigning","association","asynchronous","at","attributes","authority","authority-check","avg","back","background","backup","backward","badi","base","before","begin","between","big","binary","bintohex","bit","black","blank","blanks","blob","block","blocks","blue","bound","boundaries","bounds","boxed","break-point","buffer","by","bypassing","byte","byte-order","call","calling","case","cast","casting","catch","center","centered","chain","chain-input","chain-request","change","changing","channels","character","char-to-hex","check","checkbox","ci_","circular","class","class-coding","class-data","class-events","class-methods","class-pool","cleanup","clear","client","clob","clock","close","coalesce","code","coding","col_background","col_group","col_heading","col_key","col_negative","col_normal","col_positive","col_total","collect","color","column","columns","comment","comments","commit","common","communication","comparing","component","components","compression","compute","concat","concat_with_space","concatenate","cond","condense","condition","connect","connection","constants","context","contexts","continue","control","controls","conv","conversion","convert","copies","copy","corresponding","country","cover","cpi","create","creating","critical","currency","currency_conversion","current","cursor","cursor-selection","customer","customer-function","dangerous","data","database","datainfo","dataset","date","dats_add_days","dats_add_months","dats_days_between","dats_is_valid","daylight","dd/mm/yy","dd/mm/yyyy","ddmmyy","deallocate","decimal_shift","decimals","declarations","deep","default","deferred","define","defining","definition","delete","deleting","demand","department","descending","describe","destination","detail","dialog","directory","disconnect","display","display-mode","distinct","divide","divide-corresponding","division","do","dummy","duplicate","duplicates","duration","during","dynamic","dynpro","edit","editor-call","else","elseif","empty","enabled","enabling","encoding","end","endat","endcase","endcatch","endchain","endclass","enddo","endenhancement","end-enhancement-section","endexec","endform","endfunction","endian","endif","ending","endinterface","end-lines","endloop","endmethod","endmodule","end-of-definition","end-of-editing","end-of-file","end-of-page","end-of-selection","endon","endprovide","endselect","end-test-injection","end-test-seam","endtry","endwhile","endwith","engineering","enhancement","enhancement-point","enhancements","enhancement-section","entries","entry","enum","environment","equiv","errormessage","errors","escaping","event","events","exact","except","exception","exceptions","exception-table","exclude","excluding","exec","execute","exists","exit","exit-command","expand","expanding","expiration","explicit","exponent","export","exporting","extend","extended","extension","extract","fail","fetch","field","field-groups","fields","field-symbol","field-symbols","file","filter","filters","filter-table","final","find","first","first-line","fixed-point","fkeq","fkge","flush","font","for","form","format","forward","found","frame","frames","free","friends","from","function","functionality","function-pool","further","gaps","generate","get","giving","gkeq","gkge","global","grant","green","group","groups","handle","handler","harmless","hashed","having","hdb","header","headers","heading","head-lines","help-id","help-request","hextobin","hide","high","hint","hold","hotspot","icon","id","identification","identifier","ids","if","ignore","ignoring","immediately","implementation","implementations","implemented","implicit","import","importing","in","inactive","incl","include","includes","including","increment","index","index-line","infotypes","inheriting","init","initial","initialization","inner","inout","input","insert","instance","instances","instr","intensified","interface","interface-pool","interfaces","internal","intervals","into","inverse","inverted-date","is","iso","job","join","keep","keeping","kernel","key","keys","keywords","kind","language","last","late","layout","leading","leave","left","left-justified","leftplus","leftspace","legacy","length","let","level","levels","like","line","lines","line-count","linefeed","line-selection","line-size","list","listbox","list-processing","little","llang","load","load-of-program","lob","local","locale","locator","logfile","logical","log-point","long","loop","low","lower","lpad","lpi","ltrim","mail","main","major-id","mapping","margin","mark","mask","match","matchcode","max","maximum","medium","members","memory","mesh","message","message-id","messages","messaging","method","methods","min","minimum","minor-id","mm/dd/yy","mm/dd/yyyy","mmddyy","mode","modif","modifier","modify","module","move","move-corresponding","multiply","multiply-corresponding","name","nametab","native","nested","nesting","new","new-line","new-page","new-section","next","no","no-display","no-extension","no-gap","no-gaps","no-grouping","no-heading","no-scrolling","no-sign","no-title","no-topofpage","no-zero","node","nodes","non-unicode","non-unique","not","null","number","object","objects","obligatory","occurrence","occurrences","occurs","of","off","offset","ole","on","only","open","option","optional","options","or","order","other","others","out","outer","output","output-length","overflow","overlay","pack","package","pad","padding","page","pages","parameter","parameters","parameter-table","part","partially","pattern","percentage","perform","performing","person","pf1","pf10","pf11","pf12","pf13","pf14","pf15","pf2","pf3","pf4","pf5","pf6","pf7","pf8","pf9","pf-status","pink","places","pool","pos_high","pos_low","position","pragmas","precompiled","preferred","preserving","primary","print","print-control","priority","private","procedure","process","program","property","protected","provide","public","push","pushbutton","put","queue-only","quickinfo","radiobutton","raise","raising","range","ranges","read","reader","read-only","receive","received","receiver","receiving","red","redefinition","reduce","reduced","ref","reference","refresh","regex","reject","remote","renaming","replace","replacement","replacing","report","request","requested","reserve","reset","resolution","respecting","responsible","result","results","resumable","resume","retry","return","returncode","returning","returns","right","right-justified","rightplus","rightspace","risk","rmc_communication_failure","rmc_invalid_status","rmc_system_failure","role","rollback","rows","rpad","rtrim","run","sap","sap-spool","saving","scale_preserving","scale_preserving_scientific","scan","scientific","scientific_with_leading_zero","scroll","scroll-boundary","scrolling","search","secondary","seconds","section","select","selection","selections","selection-screen","selection-set","selection-sets","selection-table","select-options","send","separate","separated","set","shared","shift","short","shortdump-id","sign_as_postfix","single","size","skip","skipping","smart","some","sort","sortable","sorted","source","specified","split","spool","spots","sql","sqlscript","stable","stamp","standard","starting","start-of-editing","start-of-selection","state","statement","statements","static","statics","statusinfo","step-loop","stop","structure","structures","style","subkey","submatches","submit","subroutine","subscreen","subtract","subtract-corresponding","suffix","sum","summary","summing","supplied","supply","suppress","switch","switchstates","symbol","syncpoints","syntax","syntax-check","syntax-trace","system-call","system-exceptions","system-exit","tab","tabbed","table","tables","tableview","tabstrip","target","task","tasks","test","testing","test-injection","test-seam","text","textpool","then","throw","time","times","timestamp","timezone","tims_is_valid","title","titlebar","title-lines","to","tokenization","tokens","top-lines","top-of-page","trace-file","trace-table","trailing","transaction","transfer","transformation","translate","transporting","trmac","truncate","truncation","try","tstmp_add_seconds","tstmp_current_utctimestamp","tstmp_is_valid","tstmp_seconds_between","type","type-pool","type-pools","types","uline","unassign","under","unicode","union","unique","unit_conversion","unix","unpack","until","unwind","up","update","upper","user","user-command","using","utf-8","valid","value","value-request","values","vary","varying","verification-message","version","via","view","visible","wait","warning","when","whenever","where","while","width","window","windows","with","with-heading","without","with-title","word","work","write","writer","xml","xsd","yellow","yes","yymmdd","zero","zone","abap_system_timezone","abap_user_timezone","access","action","adabas","adjust_numbers","allow_precision_loss","allowed","amdp","applicationuser","as_geo_json","as400","associations","balance","behavior","breakup","bulk","cds","cds_client","check_before_save","child","clients","corr","corr_spearman","cross","cycles","datn_add_days","datn_add_months","datn_days_between","dats_from_datn","dats_tims_to_tstmp","dats_to_datn","db2","db6","ddl","dense_rank","depth","deterministic","discarding","entities","entity","error","failed","finalize","first_value","fltp_to_dec","following","fractional","full","graph","grouping","hierarchy","hierarchy_ancestors","hierarchy_ancestors_aggregate","hierarchy_descendants","hierarchy_descendants_aggregate","hierarchy_siblings","incremental","indicators","lag","last_value","lead","leaves","like_regexpr","link","locale_sap","lock","locks","many","mapped","matched","measures","median","mssqlnt","multiple","nodetype","ntile","nulls","occurrences_regexpr","one","operations","oracle","orphans","over","parent","parents","partition","pcre","period","pfcg_mapping","preceding","privileged","product","projection","rank","redirected","replace_regexpr","reported","response","responses","root","row","row_number","sap_system_date","save","schema","session","sets","shortdump","siblings","spantree","start","stddev","string_agg","subtotal","sybase","tims_from_timn","tims_to_timn","to_blob","to_clob","total","trace-entry","tstmp_to_dats","tstmp_to_dst","tstmp_to_tims","tstmpl_from_utcl","tstmpl_to_utcl","unbounded","utcl_add_seconds","utcl_current","utcl_seconds_between","uuid","var","verbatim"],builtinFunctions:["abs","acos","asin","atan","bit-set","boolc","boolx","ceil","char_off","charlen","cmax","cmin","concat_lines_of","contains","contains_any_not_of","contains_any_of","cos","cosh","count","count_any_not_of","count_any_of","dbmaxlen","distance","escape","exp","find_any_not_of","find_any_of","find_end","floor","frac","from_mixed","ipow","line_exists","line_index","log","log10","matches","nmax","nmin","numofchar","repeat","rescale","reverse","round","segment","shift_left","shift_right","sign","sin","sinh","sqrt","strlen","substring","substring_after","substring_before","substring_from","substring_to","tan","tanh","to_lower","to_mixed","to_upper","trunc","utclong_add","utclong_current","utclong_diff","xsdbool","xstrlen"],typeKeywords:["b","c","d","decfloat16","decfloat34","f","i","int8","n","p","s","string","t","utclong","x","xstring","any","clike","csequence","decfloat","numeric","simple","xsequence","accp","char","clnt","cuky","curr","datn","dats","d16d","d16n","d16r","d34d","d34n","d34r","dec","df16_dec","df16_raw","df34_dec","df34_raw","fltp","geom_ewkb","int1","int2","int4","lang","lchr","lraw","numc","quan","raw","rawstring","sstring","timn","tims","unit","utcl","df16_scl","df34_scl","prec","varc","abap_bool","abap_false","abap_true","abap_undefined","me","screen","space","super","sy","syst","table_line","*sys*"],builtinMethods:["class_constructor","constructor"],derivedTypes:["%CID","%CID_REF","%CONTROL","%DATA","%ELEMENT","%FAIL","%KEY","%MSG","%PARAM","%PID","%PID_ASSOC","%PID_PARENT","%_HINTS"],cdsLanguage:["@AbapAnnotation","@AbapCatalog","@AccessControl","@API","@ClientDependent","@ClientHandling","@CompatibilityContract","@DataAging","@EndUserText","@Environment","@LanguageDependency","@MappingRole","@Metadata","@MetadataExtension","@ObjectModel","@Scope","@Semantics","$EXTENSION","$SELF"],selectors:["->","->*","=>","~","~*"],operators:[" +"," -","/","*","**","div","mod","=","#","@","+=","-=","*=","/=","**=","&&=","?=","&","&&","bit-and","bit-not","bit-or","bit-xor","m","o","z","<"," >","<=",">=","<>","><","=<","=>","bt","byte-ca","byte-cn","byte-co","byte-cs","byte-na","byte-ns","ca","cn","co","cp","cs","eq","ge","gt","le","lt","na","nb","ne","np","ns","*/","*:","--","/*","//"],symbols:/[=><!~?&+\-*\/\^%#@]+/,tokenizer:{root:[[/[a-z_\/$%@]([\w\/$%]|-(?!>))*/,{cases:{"@typeKeywords":"type","@keywords":"keyword","@cdsLanguage":"annotation","@derivedTypes":"type","@builtinFunctions":"type","@builtinMethods":"type","@operators":"key","@default":"identifier"}}],[/<[\w]+>/,"identifier"],[/##[\w|_]+/,"comment"],{include:"@whitespace"},[/[:,.]/,"delimiter"],[/[{}()\[\]]/,"@brackets"],[/@symbols/,{cases:{"@selectors":"tag","@operators":"key","@default":""}}],[/'/,{token:"string",bracket:"@open",next:"@stringquote"}],[/`/,{token:"string",bracket:"@open",next:"@stringping"}],[/\|/,{token:"string",bracket:"@open",next:"@stringtemplate"}],[/\d+/,"number"]],stringtemplate:[[/[^\\\|]+/,"string"],[/\\\|/,"string"],[/\|/,{token:"string",bracket:"@close",next:"@pop"}]],stringping:[[/[^\\`]+/,"string"],[/`/,{token:"string",bracket:"@close",next:"@pop"}]],stringquote:[[/[^\\']+/,"string"],[/'/,{token:"string",bracket:"@close",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,""],[/^\*.*$/,"comment"],[/\".*$/,"comment"]]}};e.conf=t,e.language=n,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})}));
@@ -0,0 +1 @@
1
+ define("vs/apex-CcIm7xu6",["exports"],(function(s){"use strict";const o={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"<",close:">"}],folding:{markers:{start:new RegExp("^\\s*//\\s*(?:(?:#?region\\b)|(?:<editor-fold\\b))"),end:new RegExp("^\\s*//\\s*(?:(?:#?endregion\\b)|(?:</editor-fold>))")}}},n=["abstract","activate","and","any","array","as","asc","assert","autonomous","begin","bigdecimal","blob","boolean","break","bulk","by","case","cast","catch","char","class","collect","commit","const","continue","convertcurrency","decimal","default","delete","desc","do","double","else","end","enum","exception","exit","export","extends","false","final","finally","float","for","from","future","get","global","goto","group","having","hint","if","implements","import","in","inner","insert","instanceof","int","interface","into","join","last_90_days","last_month","last_n_days","last_week","like","limit","list","long","loop","map","merge","native","new","next_90_days","next_month","next_n_days","next_week","not","null","nulls","number","object","of","on","or","outer","override","package","parallel","pragma","private","protected","public","retrieve","return","returning","rollback","savepoint","search","select","set","short","sort","stat","static","strictfp","super","switch","synchronized","system","testmethod","then","this","this_month","this_week","throw","throws","today","tolabel","tomorrow","transaction","transient","trigger","true","try","type","undelete","update","upsert","using","virtual","void","volatile","webservice","when","where","while","yesterday"],i=e=>e.charAt(0).toUpperCase()+e.substr(1);let t=[];n.forEach(e=>{t.push(e),t.push(e.toUpperCase()),t.push(i(e))});const a={defaultToken:"",tokenPostfix:".apex",keywords:t,operators:["=",">","<","!","~","?",":","==","<=",">=","!=","&&","||","++","--","+","-","*","/","&","|","^","%","<<",">>",">>>","+=","-=","*=","/=","&=","|=","^=","%=","<<=",">>=",">>>="],symbols:/[=><!~?:&|+\-*\/\^%]+/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,digits:/\d+(_+\d+)*/,octaldigits:/[0-7]+(_+[0-7]+)*/,binarydigits:/[0-1]+(_+[0-1]+)*/,hexdigits:/[[0-9a-fA-F]+(_+[0-9a-fA-F]+)*/,tokenizer:{root:[[/[a-z_$][\w$]*/,{cases:{"@keywords":{token:"keyword.$0"},"@default":"identifier"}}],[/[A-Z][\w\$]*/,{cases:{"@keywords":{token:"keyword.$0"},"@default":"type.identifier"}}],{include:"@whitespace"},[/[{}()\[\]]/,"@brackets"],[/[<>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/@\s*[a-zA-Z_\$][\w\$]*/,"annotation"],[/(@digits)[eE]([\-+]?(@digits))?[fFdD]?/,"number.float"],[/(@digits)\.(@digits)([eE][\-+]?(@digits))?[fFdD]?/,"number.float"],[/(@digits)[fFdD]/,"number.float"],[/(@digits)[lL]?/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/"/,"string",'@string."'],[/'/,"string","@string.'"],[/'[^\\']'/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@apexdoc"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],apexdoc:[[/[^\/*]+/,"comment.doc"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],string:[[/[^\\"']+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/["']/,{cases:{"$#==$S2":{token:"string",next:"@pop"},"@default":"string"}}]]}};s.conf=o,s.language=a,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"})}));