@arcgis/coding-components
Version:
ArcGIS Coding Components
967 lines (966 loc) • 46 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.1/LICENSE.txt */
import { g as Z, c as ee } from "../../chunks/runtime.js";
import { css as te, html as d, nothing as z } from "lit";
import { i as se } from "../../chunks/monaco-importer.js";
import { LitElement as ie, createEvent as N, safeClassMap as v } from "@arcgis/lumina";
import { generateGuid as ae } from "@arcgis/toolkit/string";
import { i as y, D as ne, e as K } from "../../chunks/arcade-executor.js";
import { s as oe, a as re } from "../../chunks/arcade-service-accessors.js";
import { b as $ } from "../../chunks/arcade-defaults.js";
import { setArcadeAskAiBinding as B, arcadeAskAiCommandId as ce, arcadeQuickFixKind as le } from "../../chunks/arcade-mode.js";
import { u as de } from "../../chunks/useT9n.js";
import { createRef as H, ref as j } from "lit/directives/ref.js";
import { load as ue } from "@arcgis/lumina/controllers";
import he from "@arcgis/core/config.js";
import Q from "@arcgis/core/identity/IdentityManager.js";
import { log as ge, rethrowError as u } from "@arcgis/toolkit/log";
import { watch as L } from "@arcgis/core/core/reactiveUtils.js";
import f from "@arcgis/core/core/Accessor.js";
import { property as c, subclass as x } from "/core/core/accessorSupport/decorators.js";
import { A as W } from "../../chunks/ArcadeDebuggerPreviewTabsState.js";
import { r as pe } from "../../chunks/utilities.js";
import { Range as V, KeyCode as be, Uri as _e } from "monaco-editor";
const me = te`:host{height:100%}calcite-tooltip:not([calcite-hydrated])>*{display:none}.main-action-bar{calcite-action-group{padding-inline-end:var(--calcite-spacing-sm)}calcite-action-group calcite-action{padding-inline-end:var(--calcite-spacing-sm)}calcite-action-group calcite-action:not(:first-child){padding-inline-start:var(--calcite-spacing-sm)}calcite-action-group:last-child{border-inline-end-width:0px}calcite-action-group:not(:first-child){padding-inline-start:var(--calcite-spacing-sm)}}.bottom-action-bar.is-collapsed{border-bottom:0}.bottom-action-bar{display:flex;.bottom-action-bar__actions{flex:1 1 auto;min-inline-size:0}}`, G = "https://services6.arcgis.com/HXHga6CfMLMBOlBX/ArcGIS/rest/services/survey123_6e349a50b4504ca6b6107216d568db5f_form/FeatureServer/0", h = (t, e) => {
ge(t, "Arcade Assistant", e);
}, X = [
"orgAiAssistantsEnabled",
"betaAppsAllowed",
"serviceUrlAvailable",
"userHasUseAiAssistantsPrivilege"
], fe = X, q = (t, e) => e.every((s) => t[s] === !0), xe = (t) => {
const { aiAssistantsEnabled: e } = t;
return e === void 0 ? (h("warn", "`areAiAssistantsEnabled` is not defined in the organizations settings."), !1) : e;
}, Se = async (t) => (await Q.getCredential(t, { oAuthPopupConfirmation: !1 })).token, Ae = async (t) => {
try {
return !!await Q.checkSignInStatus(t);
} catch {
return h("warn", "User is not signed in."), !1;
}
};
async function Pe({
portalUrl: t
}) {
t && h(
"warn",
"The arcadeAssistant property is deprecated. Set esriConfig.portalUrl instead of arcadeAssistant.portalUrl."
);
const e = t || he.portalUrl;
if (!e)
return h("warn", "Arcade Assistant initialization failed. Reason: missing portal url."), { shouldRender: !1 };
const s = e.replace(/\/sharing\/rest(\/.*)?$/iu, "").replace(/\/$/u, "");
if (!await Ae(s))
return { shouldRender: !1 };
const a = await Se(e), r = `${s}/sharing/rest/portals/self?f=json&token=${a}`, n = `${s}/sharing/rest/portals/self/settings?f=json&token=${a}`, o = `${s}/sharing/rest/portals/self/signinSettings?f=json&token=${a}`, b = await Promise.allSettled([
fetch(r, { credentials: "include" }).then((P) => P.json()),
fetch(n, { credentials: "include" }).then((P) => P.json()),
fetch(o, { credentials: "include" }).then((P) => P.json())
]), [S, R, I] = b, A = S.status === "fulfilled" ? S.value : (h("warn", `Failed to fetch selfUrl. Reason: ${S.reason}.`), {}), T = R.status === "fulfilled" ? R.value : (h("warn", `Failed to fetch settingsUrl. Reason: ${R.reason}.`), {}), J = I.status === "fulfilled" ? I.value : (h("warn", `Failed to fetch signinSettingsUrl. Reason: ${I.reason}.`), {});
if (A.isPortal)
return { shouldRender: !1 };
const M = A.helpBase || "";
if (!T)
return h("warn", "Settings response is not available."), { shouldRender: !1 };
const k = {
orgAiAssistantsEnabled: xe(T),
betaAppsAllowed: J.blockBetaApps !== !0,
serviceUrlAvailable: !!A?.helperServices?.aiAssistantServices?.url,
userHasUseAiAssistantsPrivilege: A?.user?.privileges?.includes("portal:user:useAIAssistants") === !0
};
k.betaAppsAllowed || h(
"warn",
"Arcade Assistant is blocked by the organization settings. To enable it, do not block beta apps in the organization settings."
), k.userHasUseAiAssistantsPrivilege || h("warn", "User does not have the required privileges to use AI Assistants.");
const F = q(k, fe), U = q(k, X), O = A?.helperServices?.aiAssistantServices?.url;
return O ? {
shouldRender: !0,
portalUrl: e,
availableFeatures: {
codeActions: F,
prompting: U
},
serviceUrl: O,
helpBase: M,
feedbackServiceUrl: G
} : {
shouldRender: !0,
portalUrl: e,
availableFeatures: {
codeActions: F,
prompting: U
},
helpBase: M,
feedbackServiceUrl: G
};
}
var ve = Object.defineProperty, $e = Object.getOwnPropertyDescriptor, m = (t, e, s, i) => {
for (var a = i > 1 ? void 0 : i ? $e(e, s) : e, r = t.length - 1, n; r >= 0; r--)
(n = t[r]) && (a = (i ? n(e, s, a) : n(a)) || a);
return i && a && ve(e, s, a), a;
};
const Y = 100;
let g = class extends f {
constructor(t) {
super(t), this.collectionItems = [], this.errorMessage = "", this.expanded = !1, this.requestId = 0, this.status = "idle", this.visibleChildCount = Y;
}
};
m([
c()
], g.prototype, "collectionItems", 2);
m([
c()
], g.prototype, "errorMessage", 2);
m([
c()
], g.prototype, "expanded", 2);
m([
c()
], g.prototype, "requestId", 2);
m([
c()
], g.prototype, "schemaValue", 2);
m([
c()
], g.prototype, "status", 2);
m([
c()
], g.prototype, "visibleChildCount", 2);
g = m([
x("ArcadeDebuggerLazyTreeNodeState")
], g);
let C = class extends f {
constructor(t) {
super(t), this.generation = 0, this.nodes = /* @__PURE__ */ new Map();
}
reset() {
this.generation += 1, this.destroyNodes();
}
ensureNode(t, e = !1, s) {
const i = this.nodes.get(t);
if (i)
return i;
const a = new g();
return a.expanded = e, this.nodes.set(t, a), e && s && this.loadNode(t, s), a;
}
setExpanded(t, e, s) {
const i = this.ensureNode(t, e, s);
if (i.expanded === e) {
e && s && this.loadNode(t, s);
return;
}
i.expanded = e, e && s && this.loadNode(t, s);
}
showMore(t, e) {
const s = this.ensureNode(t);
s.visibleChildCount >= e || (s.visibleChildCount = Math.min(e, s.visibleChildCount + Y));
}
loadNode(t, e) {
switch (e.kind) {
case "collection":
this.runLoad(t, e.load, (s, i) => {
s.collectionItems = i;
});
return;
case "schema":
this.runLoad(t, e.load, (s, i) => {
s.schemaValue = i;
});
return;
}
}
runLoad(t, e, s) {
const i = this.nodes.get(t);
if (!i || i.status === "loading" || i.status === "loaded")
return;
const a = this.generation, r = i.requestId + 1;
i.requestId = r, i.status = "loading", i.errorMessage = "", i.schemaValue = void 0, i.collectionItems = [], e().then((n) => {
const o = this.nodes.get(t);
!o || this.generation !== a || o.requestId !== r || (s(o, n), o.status = "loaded");
}).catch(() => {
const n = this.nodes.get(t);
!n || this.generation !== a || n.requestId !== r || (n.status = "error");
});
}
destroyNodes() {
for (const t of this.nodes.values())
t.destroy();
this.nodes.clear();
}
};
C = m([
x("ArcadeDebuggerLazyTreeState")
], C);
var ye = Object.defineProperty, Ee = Object.getOwnPropertyDescriptor, l = (t, e, s, i) => {
for (var a = i > 1 ? void 0 : i ? Ee(e, s) : e, r = t.length - 1, n; r >= 0; r--)
(n = t[r]) && (a = (i ? n(e, s, a) : n(a)) || a);
return i && a && ye(e, s, a), a;
};
let _ = class extends f {
constructor(t) {
super(t), this.phase = "idle", this.sessionId = 0, this.consoleLogs = [], this.hasExecuted = !1;
}
get isExecuting() {
return this.phase === "running" || this.phase === "debug-running" || this.phase === "debug-paused";
}
get isDebugging() {
return this.phase === "debug-running" || this.phase === "debug-paused";
}
get isPaused() {
return this.phase === "debug-paused";
}
get runResult() {
return this.result?.resultType === "run" ? this.result.result : void 0;
}
get debugResult() {
return this.result?.resultType === "debug" ? this.result.result : void 0;
}
addConsoleLog(t) {
this.consoleLogs = [...this.consoleLogs, t];
}
};
l([
c()
], _.prototype, "phase", 2);
l([
c()
], _.prototype, "mode", 2);
l([
c()
], _.prototype, "sessionId", 2);
l([
c()
], _.prototype, "result", 2);
l([
c()
], _.prototype, "consoleLogs", 2);
l([
c()
], _.prototype, "hasExecuted", 2);
_ = l([
x("ArcadeDebuggerExecutionModel")
], _);
let E = class extends f {
constructor(t) {
super(t), this.editorBreakpoints = [], this.executionBreakpoints = [];
}
setBreakpoints(t, e) {
t === "editor" ? this.editorBreakpoints = Array.from(new Set(e)).sort((s, i) => s - i) : this.executionBreakpoints = Array.from(new Set(e)).sort((s, i) => s - i);
}
toggleBreakpoint(t, e) {
const s = new Set(t === "editor" ? this.editorBreakpoints : this.executionBreakpoints);
s.has(e) ? s.delete(e) : s.add(e), this.setBreakpoints(t, s);
}
clearBreakpoints(t) {
t === "editor" ? this.editorBreakpoints = [] : this.executionBreakpoints = [];
}
syncExecutionBreakpointsFromEditor() {
this.executionBreakpoints = this.editorBreakpoints;
}
};
l([
c()
], E.prototype, "editorBreakpoints", 2);
l([
c()
], E.prototype, "executionBreakpoints", 2);
E = l([
x("ArcadeDebuggerSessionModel")
], E);
let D = class extends f {
constructor(t) {
super(t), this.openedPanel = "output", this.showPanel = !1;
}
};
l([
c()
], D.prototype, "openedPanel", 2);
l([
c()
], D.prototype, "showPanel", 2);
D = l([
x("ArcadeDebuggerUiModel")
], D);
let w = class extends f {
constructor(t) {
super(t);
}
get line() {
return this.pausedState?.line;
}
clearPausedState() {
this.lastPausedState = this.pausedState, this.pausedState = void 0;
}
reset() {
this.pausedState = void 0, this.lastPausedState = void 0;
}
setPausedState(t) {
this.pausedState = t, this.lastPausedState = t;
}
};
l([
c()
], w.prototype, "pausedState", 2);
l([
c()
], w.prototype, "lastPausedState", 2);
w = l([
x("ArcadeDebuggerPausedFrameModel")
], w);
let p = class extends f {
constructor(t) {
super(t), this.execution = new _(), this.lazyTreeState = new C(), this.pausedFrame = new w(), this.previewTabsState = new W(), this.session = new E(), this.ui = new D();
}
get editorBreakpoints() {
return this.session.editorBreakpoints;
}
/** The "displayed" breakpoints within the console. depends on if the debugger is paused or not */
get debuggerBreakpoints() {
return this.isPaused ? this.session.executionBreakpoints.map((t) => ({ line: t })) : this.session.editorBreakpoints.map((t) => ({ line: t }));
}
get executionBreakpoints() {
return this.session.executionBreakpoints;
}
get consoleLogs() {
return this.execution.consoleLogs;
}
get debug() {
if (!(!this.pausedFrame.pausedState && !this.pausedFrame.lastPausedState))
return {
pausedState: this.pausedFrame.pausedState,
lastPausedState: this.pausedFrame.lastPausedState
};
}
get debugResult() {
return this.execution.debugResult;
}
get debuggerLine() {
return this.pausedFrame.pausedState?.line;
}
get executionState() {
return this.pausedFrame.pausedState;
}
get hasExecuted() {
return this.execution.hasExecuted;
}
get isDebugging() {
return this.execution.isDebugging;
}
get isExecuting() {
return this.execution.isExecuting;
}
get isPaused() {
return this.execution.isPaused;
}
get mode() {
return this.execution.mode;
}
get openedPanel() {
return this.ui.openedPanel;
}
get outputRenderer() {
if (this.execution.result)
return this.execution.result.resultType === "debug" ? "debugger" : "legacy";
}
get phase() {
return this.execution.phase;
}
get result() {
return this.execution.result;
}
get runResult() {
return this.execution.runResult;
}
get sessionId() {
return this.execution.sessionId;
}
get showPanel() {
return this.ui.showPanel;
}
addConsoleLog(t) {
this.execution.addConsoleLog(t);
}
clearBreakpoints(t) {
this.session.clearBreakpoints(t);
}
clearForMissingTestData() {
this.stopDebug({ hidePanel: !0 }), this.execution.hasExecuted = !1, this.execution.result = void 0;
}
closePanel() {
this.ui.showPanel = !1;
}
completeDebug(t) {
this.execution.mode = "debug", this.execution.result = { resultType: "debug", result: t }, this.execution.phase = "completed", this.ui.openedPanel = "output", this.pausedFrame.reset(), this.resetTransientDebuggerState();
}
completeRun(t, e = {}) {
this.execution.mode = "run", !e.useDebugRenderer && y(t) ? this.execution.result = { resultType: "run", result: t } : e.useDebugRenderer && !y(t) && (this.execution.result = { resultType: "debug", result: t }), this.execution.phase = "completed", this.pausedFrame.reset(), this.ui.openedPanel = "output", this.resetTransientDebuggerState();
}
continueDebug() {
const t = this.pausedFrame.pausedState?.continue;
t && (this.execution.phase = "debug-running", this.pausedFrame.clearPausedState(), t.resolve());
}
disableDebugger() {
this.stopDebug({ hidePanel: !0 }), this.clearBreakpoints("execution"), this.clearBreakpoints("editor");
}
fail(t) {
this.completeRun(t);
}
pauseDebug(t) {
const e = this.pausedFrame.pausedState ?? this.pausedFrame.lastPausedState;
this.syncPausedState(e, t), this.pausedFrame.setPausedState(t), this.execution.phase = "debug-paused";
}
reset() {
this.execution.phase = "idle", this.execution.mode = void 0, this.execution.result = void 0, this.execution.consoleLogs = [], this.execution.hasExecuted = !1, this.execution.sessionId = 0, this.ui.openedPanel = "output", this.ui.showPanel = !1, this.pausedFrame.reset(), this.clearBreakpoints("execution"), this.clearBreakpoints("editor"), this.replaceTransientDebuggerState();
}
resetDebug() {
this.stopDebug({ hidePanel: !1 }), this.execution.result = void 0, this.execution.consoleLogs = [], this.ui.openedPanel = "debug-console";
}
disconnect() {
this.stopDebug({ hidePanel: !0 });
}
setBreakpoints(t) {
this.session.setBreakpoints("editor", t);
}
setPanel(t) {
this.execution.hasExecuted && (this.ui.openedPanel = t, this.ui.showPanel = !0);
}
startDebug() {
return this.execution.mode = "debug", this.execution.phase = "debug-running", this.execution.hasExecuted = !0, this.execution.result = void 0, this.session.syncExecutionBreakpointsFromEditor(), this.execution.consoleLogs = [], this.ui.openedPanel = "debug-console", this.ui.showPanel = !0, this.execution.sessionId += 1, this.pausedFrame.reset(), this.replaceTransientDebuggerState(), this.execution.sessionId;
}
startRun() {
return this.execution.mode = "run", this.execution.phase = "running", this.execution.hasExecuted = !0, this.execution.result = void 0, this.execution.consoleLogs = [], this.ui.openedPanel = "output", this.ui.showPanel = !0, this.execution.sessionId += 1, this.pausedFrame.reset(), this.replaceTransientDebuggerState(), this.execution.sessionId;
}
stopDebug({ hidePanel: t = !0, invalidateSession: e = !0 } = {}) {
const s = this.pausedFrame.pausedState?.continue;
e && (this.execution.sessionId += 1), this.execution.phase = this.execution.hasExecuted ? "completed" : "idle", this.pausedFrame.reset(), this.resetTransientDebuggerState(), t && (this.ui.showPanel = !1), this.ui.openedPanel === "debug-console" && (this.ui.openedPanel = "output"), s?.resolve();
}
/**
* Resets transient debugger state (paused line, lazy tree state, preview tabs state).
* If the paused state has changed, also invalidates all preview tabs to ensure they are reloaded when next opened.
*/
syncPausedState(t, e) {
this.lazyTreeState.reset(), t && e && t !== e && this.previewTabsState.invalidateAll(), this.pausedLine = e?.line;
}
toggleBreakpoint(t) {
this.session.toggleBreakpoint("editor", t);
}
togglePanel(t) {
if (this.execution.hasExecuted) {
if (t == null) {
this.ui.showPanel = !this.ui.showPanel;
return;
}
if (this.ui.openedPanel === t && this.ui.showPanel) {
this.ui.showPanel = !1;
return;
}
this.setPanel(t);
}
}
resetTransientDebuggerState() {
this.pausedLine = void 0, this.lazyTreeState.reset(), this.previewTabsState.clear();
}
replaceTransientDebuggerState() {
this.pausedLine = void 0, this.lazyTreeState = new C(), this.previewTabsState = new W();
}
};
l([
c()
], p.prototype, "execution", 2);
l([
c()
], p.prototype, "lazyTreeState", 2);
l([
c()
], p.prototype, "pausedLine", 2);
l([
c()
], p.prototype, "pausedFrame", 2);
l([
c()
], p.prototype, "previewTabsState", 2);
l([
c()
], p.prototype, "session", 2);
l([
c()
], p.prototype, "ui", 2);
p = l([
x("ArcadeDebuggerStore")
], p);
const De = {
glyphMargin: !0,
lineNumbersMinChars: 1
};
class we extends ie {
constructor() {
super(...arguments), this._codeEditorElt = H(), this._arcadeAssistantElt = H(), this._componentReadyDefer = Promise.withResolvers(), this._disposables = [], this._editorProfilePromise = Promise.resolve(void 0), this._debuggerState = new p(), this.messages = de(), this._modelId = ae(), this._openArcadeHelp = () => {
window.open(ne, "Arcade Help");
}, this._decorations = void 0, this._monacoEditor = ue(se), this._editorOptions = {}, this._toggleSidePanel = (e) => {
e.currentTarget instanceof HTMLElement && this._setOpenedSidePanel(e.currentTarget.dataset.panelName ?? "none");
}, this._closeSidePanel = () => {
this._setOpenedSidePanel("none");
}, this._updateBreakpointsDecorations = () => {
const e = this.editorInstance;
if (!e)
return;
const s = this._debuggerState.editorBreakpoints.map((i) => ({
range: new V(i, 1, i, 1),
options: {
isWholeLine: !0,
glyphMarginClassName: "arcgis-code-editor__breakpoint-glyph",
// keeps decoration at the same line when typing at the edges of the line or the range gets collapsed. essentially keeps breakpoint decoration as a single-line
stickiness: this._monacoEditor.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
}
}));
this._decorations?.clear(), this._decorations = e.createDecorationsCollection(s);
}, this._clearDebuggerDecorations = () => {
this._decorations?.clear(), this._decorations = void 0, this._debuggerPausedLineDecoration?.clear(), this._debuggerPausedLineDecoration = void 0;
}, this._debuggerPausedLineDecoration = void 0, this._preparingArcade = !1, this._arcadeAssistantRemoteState = { shouldRender: !1 }, this._diagnostics = [], this.enableDebugger = !1, this.hideDocumentationActions = !1, this.hideSideBar = !1, this.openedSidePanel = "none", this.script = "", this.sideActionBarExpanded = !1, this.disableAssistant = !1, this.arcgisDiagnosticsChange = N({ bubbles: !1 }), this.arcgisScriptChange = N({ bubbles: !1 });
}
static {
this.properties = { _apiLibrary: 16, _editorProfile: 16, _preparingArcade: 16, _arcadeAssistantRemoteState: 16, _diagnostics: 16, editorInstance: 32, editorOptions: 0, enableDebugger: 5, hideDocumentationActions: 5, hideSideBar: 5, messageOverrides: 0, openedSidePanel: 3, profile: 0, script: 1, sideActionBarExpanded: 7, snippets: 0, suggestions: 0, testData: 0, customPanels: 0, disableAssistant: 5, arcadeAssistant: 0, externalExecutor: 0 };
}
static {
this.styles = [me];
}
get _canExecute() {
return !!(this.testData || this.externalExecutor);
}
get _usesBottomExecutionDrawer() {
return this._canExecute && (this.enableDebugger || !!this.externalExecutor);
}
get editorInstance() {
return this._codeEditorElt.value?.editorInstance;
}
get editorOptions() {
return {
...De,
...this._editorOptions
};
}
set editorOptions(e) {
this._editorOptions = e ?? {};
}
async getTestResult() {
if (!this.testData)
return { type: "error", value: "Missing test data", error: null };
const e = await this._editorProfilePromise;
if (!e)
return { type: "error", value: "Missing editor profile", error: null };
await this._componentReadyDefer.promise;
const s = this._codeEditorElt.value?.value, i = await K(e.definition, s, this.testData, { mode: "run" });
return y(i) ? i : { type: "error", value: "Unexpected debug result", error: null };
}
async setFocus() {
await this._componentReadyDefer.promise, await this._codeEditorElt.value?.setFocus();
}
async openArcadeAssistant(e) {
if (!this._arcadeAssistantRemoteState.shouldRender)
return !1;
if (this.openedSidePanel = "arcade-assistant", await this.updateComplete, !this._canPromptWithArcadeAssistant())
return !0;
const s = this._arcadeAssistantElt.value;
return e?.prompt && await s?.openPrompt(e.prompt), !0;
}
async load() {
const e = Z("./assets");
oe(e), await this._updateDataModelDeps(), this.manager.onLifecycle(() => (this.hasUpdated && this._connectMonacoCustomizations().catch(u(this)), () => {
for (this._askAiBindingKey && (B(this._askAiBindingKey, void 0), this._askAiBindingKey = void 0); this._disposables.length; )
this._disposables.pop()?.dispose();
this._abortExternalExecution(), this._connectMonacoCustomizationsPromise = void 0, this._executeScriptAction = void 0, this._clearDebuggerDecorations(), this._debuggerState.disconnect();
}));
}
willUpdate(e) {
(e.has("messages") || e.has("profile")) && this._updateDataModelDeps(), (e.has("testData") || e.has("externalExecutor")) && this._executionContextChanged(), e.has("enableDebugger") && !this.enableDebugger && this._debuggerState.disableDebugger(), e.has("snippets") && $.updateApiContextForModel(this._modelId, {
snippets: this.snippets
}), (e.has("arcadeAssistant") || e.has("disableAssistant")) && this._updateArcadeAssistantRemoteState();
}
async loaded() {
await this._connectMonacoCustomizations(), this._componentReadyDefer.resolve();
}
_setOpenedSidePanel(e) {
this.openedSidePanel = e === this.openedSidePanel ? "none" : e;
}
async _connectMonacoCustomizations() {
if (this._connectMonacoCustomizationsPromise)
return await this._connectMonacoCustomizationsPromise;
this._connectMonacoCustomizationsPromise = (async () => {
if (!this.isConnected)
return;
const e = await re();
this._disposables.push(e.onDiagnosticsChange((o) => {
this._preparingArcade || (this._diagnostics = o.diagnostics, this.arcgisDiagnosticsChange.emit(o.diagnostics));
})), this._canExecute && !this._executeScriptAction && this._addExecuteScriptAction(), this._syncAskAiAction();
const s = L(() => this._debuggerState.editorBreakpoints, () => this._updateBreakpointsDecorations(), { sync: !0 }), i = L(() => this._debuggerState.debuggerLine, () => this._updateDebuggerPausedLineDecoration(), { sync: !0 }), a = L(() => this._debuggerState.consoleLogs.length, () => this.requestUpdate(), { sync: !0 });
this._disposables.push({ dispose: () => s.remove() }, { dispose: () => i.remove() }, { dispose: () => a.remove() });
const r = this.editorInstance?.onMouseDown((o) => this._onEditorMouseDown(o));
r && this._disposables.push(r);
const n = this.editorInstance?.onDidChangeModelContent((o) => this._onEditorModelContentChange(o));
n && this._disposables.push(n), this._updateBreakpointsDecorations(), this._updateDebuggerPausedLineDecoration();
})();
try {
await this._connectMonacoCustomizationsPromise;
} finally {
this._connectMonacoCustomizationsPromise = void 0;
}
}
_onEditorMouseDown(e) {
if (!this.enableDebugger || ![this._monacoEditor.MouseTargetType.GUTTER_GLYPH_MARGIN].includes(e.target.type) || e.target.element?.classList.contains("codicon-gutter-lightbulb"))
return;
const s = e.target.position?.lineNumber;
s && this._debuggerState.toggleBreakpoint(s);
}
_onEditorModelContentChange(e) {
if (!this.enableDebugger || !this._debuggerState.editorBreakpoints.length || e.isFlush)
return;
const s = pe(this._debuggerState.editorBreakpoints, e.changes);
s.length === this._debuggerState.editorBreakpoints.length && s.every((i, a) => i === this._debuggerState.editorBreakpoints[a]) || this._debuggerState.setBreakpoints(s);
}
_updateDebuggerPausedLineDecoration() {
const e = this.editorInstance;
if (!e)
return;
this._debuggerPausedLineDecoration?.clear();
const s = this._debuggerState.debuggerLine;
s != null ? this._debuggerPausedLineDecoration = e.createDecorationsCollection([
{
range: new V(s, 1, s, 1),
options: {
isWholeLine: !0,
className: "arcgis-code-editor__debugger-paused-line",
glyphMarginClassName: "arcgis-code-editor__debugger-paused-glyph",
marginClassName: "arcgis-code-editor__debugger-paused-line arcgis-code-editor__debugger-paused-margin",
// keeps decoration at the same line when typing at the edges of the line or the range gets collapsed.
// essentially keeps paused decoration as a single-line no matter what
stickiness: this._monacoEditor.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
}
}
]) : this._debuggerPausedLineDecoration = void 0;
}
_continueDebugSession() {
this._debuggerState.continueDebug();
}
_abortExternalExecution() {
this._externalExecutionAbortController?.abort(), this._externalExecutionAbortController = void 0;
}
_stopDebugSession() {
this._abortExternalExecution(), this._debuggerState.stopDebug({ hidePanel: !1 });
}
_resetDebugSession() {
this._abortExternalExecution(), this._debuggerState.resetDebug(), this._executeScript("debug").catch(u(this));
}
async _handleDebugPause(e, s, i) {
if (!this._debuggerState.isDebugging || e !== this._debuggerState.sessionId)
return;
const a = Promise.withResolvers();
return this._debuggerState.pauseDebug({
line: s.line,
result: i,
continue: a
}), await a.promise;
}
async _updateDataModelDeps() {
await this._updateEditorProfile(), await this._updateApiLibrary();
}
async _executeWithExternalExecutor(e, s, i) {
if (!this.externalExecutor)
return { type: "error", value: "Missing external executor", error: null };
const a = new AbortController();
this._abortExternalExecution(), this._externalExecutionAbortController = a;
const r = i.console ?? (() => {
});
try {
if (e === "debug") {
const { breakpoints: n, onDebugPause: o } = i;
if (!n || !o)
throw new Error("Missing debug execution options");
return await this.externalExecutor.execute({
mode: "debug",
script: s,
console: r,
signal: a.signal,
breakpoints: n,
onDebugPause: o
});
}
return await this.externalExecutor.execute({
mode: "run",
script: s,
console: r,
signal: a.signal
});
} catch (n) {
return {
type: "error",
value: "Execution failed",
error: n instanceof Error ? n : new Error(String(n))
};
} finally {
this._externalExecutionAbortController === a && (this._externalExecutionAbortController = void 0);
}
}
_executionContextChanged() {
!this._canExecute && this._executeScriptAction && (this._disposeSafely(this._executeScriptAction), this._executeScriptAction = void 0), this._canExecute && !this._executeScriptAction && this._addExecuteScriptAction(), !this.testData && this.enableDebugger && this._debuggerState.clearForMissingTestData(), this._debuggerState.openedPanel === "debug-console" && !this.enableDebugger && this._debuggerState.closePanel(), this._debuggerState.showPanel && this._executeScript("run").catch(u(this));
}
async _updateEditorProfile() {
this._preparingArcade = !0;
try {
await $.setProfileForModel(this._modelId, this.profile, {
locale: this.messages._t9nLocale,
snippets: this.snippets
}), this._editorProfile = $.getEditorProfileForModel(this._modelId);
} catch {
this._editorProfile = void 0;
} finally {
this._editorProfilePromise = Promise.resolve(this._editorProfile), this._preparingArcade = !1;
}
}
async _updateApiLibrary() {
this._apiLibrary = await $.getApiLibraryForModel(this._modelId);
}
_setExecutionPanel(e) {
this._debuggerState.setPanel(e);
}
async _executeScript(e) {
const s = this.testData, i = this.externalExecutor;
if (!this._codeEditorElt.value || !s && !i)
return;
const a = e === "debug" ? this._debuggerState.startDebug() : this._debuggerState.startRun();
setTimeout(() => {
(async () => {
const r = this._codeEditorElt.value?.value ?? this.script, n = {
mode: e,
console: (b) => this._debuggerState.addConsoleLog(b),
breakpoints: e === "debug" ? this._debuggerState.debuggerBreakpoints : void 0
};
e === "debug" && (n.onDebugPause = this._handleDebugPause.bind(this, a));
let o;
if (i)
o = await this._executeWithExternalExecutor(e, r, n);
else if (s) {
const b = await this._editorProfilePromise;
if (!b) {
this._debuggerState.fail({ type: "error", value: "Missing editor profile", error: null });
return;
}
o = await K(b.definition, r, s, n);
} else
return;
if (a === this._debuggerState.sessionId) {
if (e === "debug") {
if (y(o)) {
this._debuggerState.fail(o);
return;
}
this._debuggerState.completeDebug(o);
return;
}
y(o) ? this._debuggerState.completeRun(o) : i ? this._debuggerState.completeRun(o, { useDebugRenderer: !0 }) : this._debuggerState.fail({ type: "error", value: "Unexpected debug result", error: null });
}
})();
}, 0);
}
_toggleShowExecutionPanel() {
this._debuggerState.togglePanel();
}
_toggleSideActionBarExpanded() {
this.sideActionBarExpanded = !this.sideActionBarExpanded;
}
_onCodeEditorValueChange(e) {
e.stopPropagation(), this.script = e.detail, this.arcgisScriptChange.emit(e.detail);
}
_insertAsSnippet(e) {
this._codeEditorElt.value?.insertSnippet(e.detail).catch(u(this));
}
_insertAsText(e) {
this._insertText(e.detail);
}
_insertText(e) {
this._codeEditorElt.value?.insertText(e).catch(u(this));
}
_onResultPanelChange(e) {
const s = e.currentTarget;
this._debuggerState.setPanel(s.openedResultPanel);
}
_onExecutionPanelClose() {
this._debuggerState.closePanel();
}
_addExecuteScriptAction() {
const e = this.editorInstance?.addAction({
// An unique identifier for the action.
id: "run-script",
label: "Run Arcade Expression",
keybindings: [be.F5],
contextMenuGroupId: "code",
contextMenuOrder: 1,
run: () => {
this._canExecute && this._executeScript("run").catch(u(this));
}
});
e && (this._executeScriptAction = e, this._disposables.push(e));
}
_getAskAiBindingKey() {
return _e.parse(this._modelId).toString();
}
_canRenderAskAiCodeActions() {
const e = this._arcadeAssistantRemoteState;
return e.shouldRender ? e.availableFeatures.codeActions : !1;
}
_canPromptWithArcadeAssistant() {
const e = this._arcadeAssistantRemoteState;
return e.shouldRender ? e.availableFeatures.prompting : !1;
}
_getAskAiCodeActions(e) {
if (!this._canRenderAskAiCodeActions())
return [];
if (!e.markers.length)
return [];
const s = this.messages.askarcadeassistant ?? "Ask Arcade Assistant", i = this._getAskAiBindingKey();
return [
{
title: s,
kind: le,
diagnostics: e.markers,
isPreferred: !1,
// isAI adds the sparkle and adds it to the hover menu, but it changes the
// behavior in the code editing experience, it shows up as a sparkle next to the error.
// The sparkle doesn't explain what it does, and imo will cause confusion, thus we are opting to not use it for now.
isAI: !1,
command: {
id: ce,
title: s,
arguments: [i, this.messages.askarcadeassistantprompt ?? "Fix the errors in my script"]
}
}
];
}
_syncAskAiAction() {
if (!this.editorInstance)
return;
const s = this._getAskAiBindingKey();
if (!this._arcadeAssistantRemoteState.shouldRender) {
this._askAiBindingKey && (B(this._askAiBindingKey, void 0), this._askAiBindingKey = void 0);
return;
}
this._askAiBindingKey && this._askAiBindingKey !== s && B(this._askAiBindingKey, void 0), B(s, {
provideCodeActions: ({ context: i }) => this._getAskAiCodeActions(i),
run: (i) => {
this.openArcadeAssistant({
prompt: i ?? this.messages.askarcadeassistantprompt ?? "Fix the errors in my script"
}).catch(u(this));
}
}), this._askAiBindingKey = s;
}
_disposeSafely(e) {
const s = this._disposables.indexOf(e);
s !== -1 && this._disposables.splice(s, 1), e.dispose();
}
async _updateArcadeAssistantRemoteState() {
const e = this.arcadeAssistant;
this.disableAssistant ? this._arcadeAssistantRemoteState = { shouldRender: !1 } : this._arcadeAssistantRemoteState = await Pe(e ?? {}), this._syncAskAiAction();
}
renderMainActionBar() {
return this._usesBottomExecutionDrawer || !this._canExecute ? null : d`<calcite-action-bar class="main-action-bar" layout=horizontal scale=s expanded expand-disabled slot=top-action-bar><calcite-action-group scale=s><calcite-action .text=${this.messages.run ?? ""} text-enabled icon=play scale=s .loading=${this._preparingArcade} =${() => {
this._executeScript("run").catch(u(this));
}}></calcite-action>${this._debuggerState.result ? d`<calcite-action .text=${this.messages.lastresults ?? ""} .active=${this._debuggerState.showPanel} text-enabled icon=access-string-results icon-flip-rtl scale=s =${this._toggleShowExecutionPanel}></calcite-action>` : null}</calcite-action-group></calcite-action-bar>`;
}
renderMainPanel() {
return d`<arcgis-code-editor slot=editor .editorOptions=${this.editorOptions} .language=${$.languageId} .value=${this.script ?? ""} .modelId=${this._modelId} =${this._onCodeEditorValueChange} ${j(this._codeEditorElt)}></arcgis-code-editor>`;
}
renderAction({ id: e, label: s, icon: i, active: a, panelName: r, iconFlipRtl: n = !1, onClick: o = this._toggleSidePanel }) {
return d`<calcite-action id=${e ?? z} .text=${s} .textEnabled=${this.sideActionBarExpanded} .icon=${i} .active=${a} =${o} data-panel-name=${r ?? z} .iconFlipRtl=${n}></calcite-action>${!this.sideActionBarExpanded && d`<calcite-tooltip .referenceElement=${e}><span>${s}</span></calcite-tooltip>` || ""}`;
}
renderSideActionBar() {
return this.hideSideBar ? null : d`<calcite-action-bar slot=side-action-bar class="side-action-bar" .expanded=${this.sideActionBarExpanded} position=end =${this._toggleSideActionBarExpanded}><calcite-action-group>${this.renderAction({
id: "profile-variables-action",
label: this.messages.profilevariables ?? "",
icon: "profile-variables",
active: this.openedSidePanel === "variables",
panelName: "variables"
})}${this.renderAction({
id: "function-action",
label: this.messages.constantsandfunctions ?? "",
icon: "function",
active: this.openedSidePanel === "api",
panelName: "api"
})}${this.suggestions?.length ? this.renderAction({
id: "suggestions-action",
label: this.messages.suggestions ?? "",
icon: "lightbulb",
active: this.openedSidePanel === "suggestions",
panelName: "suggestions"
}) : null}${this._arcadeAssistantRemoteState.shouldRender && this.renderAction({
id: "arcade-assistant-action",
label: this.messages.arcadeassistant ?? "Arcade assistant",
icon: "effects",
active: this.openedSidePanel === "arcade-assistant",
panelName: "arcade-assistant"
}) || ""}${this.customPanels?.map((e) => e.enabled === !1 ? null : this.renderAction({
id: e.id,
label: e.name,
icon: e.icon,
active: this.openedSidePanel === e.id,
panelName: e.id
}))}${this.hideDocumentationActions ? null : this.renderAction({
id: "developer-website-action",
label: this.messages.help ?? "",
icon: "question",
active: !1,
panelName: "none",
iconFlipRtl: this.messages._lang === "ar",
onClick: this._openArcadeHelp
})}</calcite-action-group></calcite-action-bar>`;
}
renderSidePanel() {
if (this.hideSideBar)
return null;
const { openedSidePanel: e, _arcadeAssistantRemoteState: s } = this;
return d`<arcgis-language-api-panel slot=side-panel class=${v(e === "api" ? "" : "hidden")} .loading=${this._preparingArcade} .apiLibrary=${this._apiLibrary} .hideDocumentationActions=${this.hideDocumentationActions} =${this._insertAsSnippet} =${this._closeSidePanel} data-panel-name=none .closed=${e !== "api"}></arcgis-language-api-panel><arcgis-editor-variables slot=side-panel class=${v(e === "variables" ? "" : "hidden")} .loading=${this._preparingArcade} .modelId=${this._modelId} =${this._insertAsText} =${this._closeSidePanel} data-panel-name=none .variable=${this._editorProfile} .closed=${e !== "variables"} .messageOverrides=${{
profileempty: this.messages.profileempty,
profilevariables: this.messages.profilevariables
}}></arcgis-editor-variables>${this.suggestions?.length && d`<arcgis-arcade-suggestions slot=side-panel class=${v(e === "suggestions" ? "" : "hidden")} .closed=${e !== "suggestions"} .suggestions=${this.suggestions} =${this._insertAsText} =${this._closeSidePanel} data-panel-name=none></arcgis-arcade-suggestions>` || ""}${s?.shouldRender && d`<arcgis-arcade-coding-assistant slot=side-panel class=${v(e === "arcade-assistant" ? "" : "hidden")} .closed=${e !== "arcade-assistant"} .insertText=${this._insertText.bind(this)} .closePanel=${this._closeSidePanel} .portalUrl=${s.portalUrl} .serviceUrl=${"serviceUrl" in s ? s.serviceUrl : void 0} .helpBase=${s.helpBase} .promptingEnabled=${this._canPromptWithArcadeAssistant()} .feedbackServiceUrl=${s.feedbackServiceUrl} .editorRef=${this.el} .appVersion=${this.arcadeAssistant?.appVersion} .disableQuestionAnswerLogging=${this.arcadeAssistant?.disableQuestionAnswerLogging} .diagnostics=${this._diagnostics} ${j(this._arcadeAssistantElt)}></arcgis-arcade-coding-assistant>` || ""}${this.customPanels?.map((i) => d`<calcite-flow slot=side-panel class=${v(e === i.id ? "" : "hidden")}>${i?.useFlows ? i.renderer?.({
closePanel: this._toggleSidePanel,
insertText: this._insertText.bind(this),
closed: e !== i.id,
/** pass this.el instead of "this" as it is what actually gets attached to the dom */
editorRef: this.el
}) : d`<calcite-flow-item .heading=${i.name} heading-level=2 closable .closed=${e !== i.id} =${this._toggleSidePanel} .description=${i.description}>${i.renderer?.({
closePanel: this._toggleSidePanel,
insertText: this._insertText.bind(this),
closed: e !== i.id,
/** pass this.el instead of "this" as it is what actually gets attached to the dom */
editorRef: this.el
})}</calcite-flow-item>`}</calcite-flow>`)}`;
}
renderResultsPanel() {
if (this._usesBottomExecutionDrawer)
return this.renderBottomExecutionBody();
if (!this._debuggerState.showPanel)
return null;
const e = this._debuggerState.openedPanel === "debug-console" ? "output" : this._debuggerState.openedPanel;
return d`<arcgis-arcade-results slot=results-panel .openedResultPanel=${e} .loading=${this._debuggerState.isExecuting} .result=${this._debuggerState.runResult} .consoleLogs=${this._debuggerState.consoleLogs} =${this._onResultPanelChange} =${this._onExecutionPanelClose}></arcgis-arcade-results>`;
}
renderBottomExecutionBody() {
const { showPanel: e, openedPanel: s, debugResult: i, isExecuting: a, mode: r } = this._debuggerState;
if (!e)
return null;
const n = s === "debug-console" ? "output" : s;
return this.enableDebugger && s === "debug-console" ? d`<arcgis-arcade-debugger-console slot=results-panel .modelId=${this._modelId} .debuggerStore=${this._debuggerState}></arcgis-arcade-debugger-console>` : s === "output" && (r === "debug" || i) ? d`<arcgis-arcade-debugger-output .outputTitle=${this.messages.output} slot=results-panel .debuggerStore=${this._debuggerState} .result=${i}></arcgis-arcade-debugger-output>` : d`<arcgis-arcade-results slot=results-panel class="bottom-results" .openedResultPanel=${n} .loading=${s === "console" && this._debuggerState.isPaused ? !1 : a} .result=${this._debuggerState.runResult} .consoleLogs=${this._debuggerState.consoleLogs} hide-header =${this._onResultPanelChange}></arcgis-arcade-results>`;
}
renderBottomActionBar() {
if (!this._usesBottomExecutionDrawer)
return null;
const { showPanel: e, hasExecuted: s, openedPanel: i, isDebugging: a, isPaused: r, isExecuting: n } = this._debuggerState, o = this.messages.continue ?? "Continue", b = this.messages.reset ?? "Reset", S = this.messages.stop ?? "Stop";
return d`<div slot=bottom-action-bar class=${`main-action-bar bottom-action-bar ${e ? "" : "is-collapsed"}`}><calcite-action-bar class="bottom-action-bar__actions" layout=horizontal scale=s expand-disabled expanded><calcite-action-group scale=s>${this.enableDebugger && a ? d`<calcite-action id=debugger-continue-action .text=${o} icon=forward scale=s .disabled=${!r} =${this._continueDebugSession}></calcite-action><calcite-tooltip reference-element=debugger-continue-action placement=top><span>${o}</span></calcite-tooltip><calcite-action id=debugger-reset-action .text=${b} icon=reset scale=s =${this._resetDebugSession}></calcite-action><calcite-tooltip reference-element=debugger-reset-action placement=top><span>${b}</span></calcite-tooltip><calcite-action id=debugger-stop-action .text=${S} icon=circle-stop scale=s =${this._stopDebugSession}></calcite-action><calcite-tooltip reference-element=debugger-stop-action placement=top><span>${S}</span></calcite-tooltip>` : d`<calcite-action .text=${this.messages.run ?? ""} text-enabled icon=play scale=s .loading=${this._preparingArcade || n} =${() => {
this._executeScript("run").catch(u(this));
}}></calcite-action>${this.enableDebugger && d`<calcite-action .disabled=${this._debuggerState.editorBreakpoints.length === 0} .text=${this.messages.runanddebug ?? "Run and Debug"} text-enabled icon=debug-script scale=s .loading=${this._preparingArcade || n} =${() => {
this._executeScript("debug").catch(u(this));
}}></calcite-action>` || ""}`}</calcite-action-group>${s ? d`<calcite-action-group scale=s><calcite-action .active=${i === "output" && e} .text=${this.messages.output ?? "Output"} text-enabled scale=s icon=list-show-all icon-flip-rtl =${() => this._setExecutionPanel("output")}></calcite-action><calcite-action .active=${i === "console" && e} .text=${this.messages.console ?? "Console"} text-enabled scale=s icon=console icon-flip-rtl =${() => this._setExecutionPanel("console")}></calcite-action><calcite-action .active=${i === "log" && e} .text=${this.messages.log ?? "Log"} text-enabled scale=s icon=list icon-flip-rtl =${() => this._setExecutionPanel("log")} .disabled=${this.enableDebugger && this._debuggerState.mode === "debug"}></calcite-action>${this.enableDebugger && d`<calcite-action .active=${i === "debug-console" && e} .text=${this.messages.debugconsole ?? "Debug Console"} text-enabled scale=s icon=debug-script .disabled=${this._debuggerState.mode !== "debug"} =${() => this._setExecutionPanel("debug-console")}></calcite-action>` || ""}</calcite-action-group>` : null}</calcite-action-bar>${e ? d`<calcite-action .text=${this.messages.close ?? "Close"} scale=s icon=x icon-flip-rtl =${this._onExecutionPanelClose} slot=actions-end></calcite-action>` : null}</div>`;
}
render() {
return d`<arcgis-code-editor-shell>${this.renderMainActionBar()}${this.renderMainPanel()}${this.renderBottomActionBar()}${this.renderResultsPanel()}${this.renderSidePanel()}${this.renderSideActionBar()}</arcgis-code-editor-shell>`;
}
}
ee("arcgis-arcade-editor", we);
export {
we as ArcgisArcadeEditor
};