snow-flow 10.0.1-dev.415 → 10.0.1-dev.417
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.
package/package.json
CHANGED
|
@@ -1261,6 +1261,7 @@ function DialogAuthEnterpriseCombined() {
|
|
|
1261
1261
|
| "code"
|
|
1262
1262
|
| "verifying-enterprise"
|
|
1263
1263
|
| "checking-portal-sn"
|
|
1264
|
+
| "select-sn-instance"
|
|
1264
1265
|
| "sn-method"
|
|
1265
1266
|
| "sn-instance"
|
|
1266
1267
|
| "sn-oauth-clientid"
|
|
@@ -1285,6 +1286,18 @@ function DialogAuthEnterpriseCombined() {
|
|
|
1285
1286
|
clientSecret?: string
|
|
1286
1287
|
} | null>(null)
|
|
1287
1288
|
|
|
1289
|
+
// ServiceNow instances from enterprise portal (for multi-instance selection)
|
|
1290
|
+
const [snInstances, setSnInstances] = createSignal<
|
|
1291
|
+
Array<{
|
|
1292
|
+
id: number
|
|
1293
|
+
instanceName: string
|
|
1294
|
+
instanceUrl: string
|
|
1295
|
+
environmentType: string
|
|
1296
|
+
isDefault: boolean
|
|
1297
|
+
enabled: boolean
|
|
1298
|
+
}>
|
|
1299
|
+
>([])
|
|
1300
|
+
|
|
1288
1301
|
// ServiceNow state
|
|
1289
1302
|
const [snMethod, setSnMethod] = createSignal<"oauth" | "basic">("oauth")
|
|
1290
1303
|
const [snInstance, setSnInstance] = createSignal("")
|
|
@@ -1345,6 +1358,9 @@ function DialogAuthEnterpriseCombined() {
|
|
|
1345
1358
|
setSessionId("")
|
|
1346
1359
|
setAuthCode("")
|
|
1347
1360
|
setTimeout(() => subdomainInput?.focus(), 10)
|
|
1361
|
+
} else if (currentStep === "select-sn-instance") {
|
|
1362
|
+
// Can't re-do enterprise auth, go back to main auth menu
|
|
1363
|
+
dialog.replace(() => <DialogAuth />)
|
|
1348
1364
|
} else if (currentStep === "sn-method") {
|
|
1349
1365
|
// Can't go back to enterprise flow, go to main menu
|
|
1350
1366
|
dialog.replace(() => <DialogAuth />)
|
|
@@ -1533,28 +1549,42 @@ function DialogAuthEnterpriseCombined() {
|
|
|
1533
1549
|
duration: 3000,
|
|
1534
1550
|
})
|
|
1535
1551
|
|
|
1536
|
-
// Check if enterprise portal has ServiceNow
|
|
1552
|
+
// Check if enterprise portal has ServiceNow instances
|
|
1537
1553
|
setStep("checking-portal-sn")
|
|
1538
|
-
const
|
|
1554
|
+
const instances = await fetchPortalSnInstances(portalUrl, data.token)
|
|
1539
1555
|
|
|
1540
|
-
if (
|
|
1541
|
-
//
|
|
1542
|
-
|
|
1556
|
+
if (instances.length === 0) {
|
|
1557
|
+
// No instances — manual setup
|
|
1558
|
+
toast.show({
|
|
1559
|
+
variant: "info",
|
|
1560
|
+
message: "No ServiceNow instances found on portal. Please configure manually.",
|
|
1561
|
+
duration: 3000,
|
|
1562
|
+
})
|
|
1563
|
+
setStep("sn-method")
|
|
1564
|
+
} else if (instances.length === 1) {
|
|
1565
|
+
// Single instance — fetch creds and proceed
|
|
1543
1566
|
toast.show({
|
|
1544
1567
|
variant: "info",
|
|
1545
|
-
message:
|
|
1568
|
+
message: `ServiceNow instance found: ${instances[0].instanceName}`,
|
|
1546
1569
|
duration: 3000,
|
|
1547
1570
|
})
|
|
1548
|
-
|
|
1549
|
-
|
|
1571
|
+
const creds = await fetchPortalSnInstanceById(portalUrl, data.token, instances[0].id)
|
|
1572
|
+
if (creds) {
|
|
1573
|
+
setPortalSnCredentials(creds)
|
|
1574
|
+
await startBothMcpServersWithPortalCreds(portalUrl, data.token, creds, data.user)
|
|
1575
|
+
} else {
|
|
1576
|
+
toast.show({ variant: "error", message: "Failed to fetch instance credentials.", duration: 3000 })
|
|
1577
|
+
setStep("sn-method")
|
|
1578
|
+
}
|
|
1550
1579
|
} else {
|
|
1551
|
-
//
|
|
1580
|
+
// Multiple instances — show selection
|
|
1581
|
+
setSnInstances(instances)
|
|
1552
1582
|
toast.show({
|
|
1553
1583
|
variant: "info",
|
|
1554
|
-
message:
|
|
1584
|
+
message: `${instances.length} ServiceNow instances found. Please select one.`,
|
|
1555
1585
|
duration: 3000,
|
|
1556
1586
|
})
|
|
1557
|
-
setStep("sn-
|
|
1587
|
+
setStep("select-sn-instance")
|
|
1558
1588
|
}
|
|
1559
1589
|
} catch (e) {
|
|
1560
1590
|
toast.show({ variant: "error", message: e instanceof Error ? e.message : "Verification failed" })
|
|
@@ -1565,38 +1595,58 @@ function DialogAuthEnterpriseCombined() {
|
|
|
1565
1595
|
|
|
1566
1596
|
// === Portal ServiceNow Credentials ===
|
|
1567
1597
|
|
|
1568
|
-
const
|
|
1598
|
+
const fetchPortalSnInstances = async (
|
|
1569
1599
|
portalUrl: string,
|
|
1570
|
-
token: string
|
|
1571
|
-
): Promise<
|
|
1600
|
+
token: string,
|
|
1601
|
+
): Promise<
|
|
1602
|
+
Array<{
|
|
1603
|
+
id: number
|
|
1604
|
+
instanceName: string
|
|
1605
|
+
instanceUrl: string
|
|
1606
|
+
environmentType: string
|
|
1607
|
+
isDefault: boolean
|
|
1608
|
+
enabled: boolean
|
|
1609
|
+
}>
|
|
1610
|
+
> => {
|
|
1572
1611
|
try {
|
|
1573
|
-
const response = await fetch(`${portalUrl}/api/user-credentials/servicenow/
|
|
1612
|
+
const response = await fetch(`${portalUrl}/api/user-credentials/servicenow/instances`, {
|
|
1574
1613
|
method: "GET",
|
|
1575
1614
|
headers: {
|
|
1576
1615
|
Authorization: `Bearer ${token}`,
|
|
1577
1616
|
Accept: "application/json",
|
|
1578
1617
|
},
|
|
1579
1618
|
})
|
|
1580
|
-
|
|
1581
|
-
if (!response.ok) {
|
|
1582
|
-
return null
|
|
1583
|
-
}
|
|
1584
|
-
|
|
1619
|
+
if (!response.ok) return []
|
|
1585
1620
|
const data = await response.json()
|
|
1621
|
+
if (!data.success || !Array.isArray(data.instances)) return []
|
|
1622
|
+
return data.instances.filter((i: any) => i.enabled)
|
|
1623
|
+
} catch {
|
|
1624
|
+
return []
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1586
1627
|
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1628
|
+
const fetchPortalSnInstanceById = async (
|
|
1629
|
+
portalUrl: string,
|
|
1630
|
+
token: string,
|
|
1631
|
+
instanceId: number,
|
|
1632
|
+
): Promise<{ instanceUrl: string; clientId: string; clientSecret: string } | null> => {
|
|
1633
|
+
try {
|
|
1634
|
+
const response = await fetch(`${portalUrl}/api/user-credentials/servicenow/instances/${instanceId}`, {
|
|
1635
|
+
method: "GET",
|
|
1636
|
+
headers: {
|
|
1637
|
+
Authorization: `Bearer ${token}`,
|
|
1638
|
+
Accept: "application/json",
|
|
1639
|
+
},
|
|
1640
|
+
})
|
|
1641
|
+
if (!response.ok) return null
|
|
1642
|
+
const data = await response.json()
|
|
1643
|
+
if (!data.success || !data.instance) return null
|
|
1644
|
+
const inst = data.instance
|
|
1645
|
+
if (!inst.instanceUrl || !inst.clientId || !inst.clientSecret) return null
|
|
1596
1646
|
return {
|
|
1597
|
-
instanceUrl:
|
|
1598
|
-
clientId:
|
|
1599
|
-
clientSecret:
|
|
1647
|
+
instanceUrl: inst.instanceUrl,
|
|
1648
|
+
clientId: inst.clientId,
|
|
1649
|
+
clientSecret: inst.clientSecret,
|
|
1600
1650
|
}
|
|
1601
1651
|
} catch {
|
|
1602
1652
|
return null
|
|
@@ -1952,6 +2002,33 @@ function DialogAuthEnterpriseCombined() {
|
|
|
1952
2002
|
</box>
|
|
1953
2003
|
</Show>
|
|
1954
2004
|
|
|
2005
|
+
{/* Step 4c: Select ServiceNow instance */}
|
|
2006
|
+
<Show when={step() === "select-sn-instance"}>
|
|
2007
|
+
<DialogSelect
|
|
2008
|
+
title="Select ServiceNow Instance"
|
|
2009
|
+
options={snInstances().map((inst) => ({
|
|
2010
|
+
title: inst.instanceName,
|
|
2011
|
+
value: String(inst.id),
|
|
2012
|
+
description: inst.instanceUrl,
|
|
2013
|
+
footer: inst.environmentType + (inst.isDefault ? " (default)" : ""),
|
|
2014
|
+
category: "ServiceNow Instances",
|
|
2015
|
+
onSelect: async () => {
|
|
2016
|
+
setStep("completing")
|
|
2017
|
+
const portalUrl = `https://${subdomain().trim().toLowerCase()}.snow-flow.dev`
|
|
2018
|
+
const token = enterpriseData().token!
|
|
2019
|
+
const creds = await fetchPortalSnInstanceById(portalUrl, token, inst.id)
|
|
2020
|
+
if (creds) {
|
|
2021
|
+
setPortalSnCredentials(creds)
|
|
2022
|
+
await startBothMcpServersWithPortalCreds(portalUrl, token, creds, enterpriseData().user)
|
|
2023
|
+
} else {
|
|
2024
|
+
toast.show({ variant: "error", message: "Failed to fetch instance credentials.", duration: 3000 })
|
|
2025
|
+
setStep("sn-method")
|
|
2026
|
+
}
|
|
2027
|
+
},
|
|
2028
|
+
}))}
|
|
2029
|
+
/>
|
|
2030
|
+
</Show>
|
|
2031
|
+
|
|
1955
2032
|
{/* Step 5: Choose ServiceNow method */}
|
|
1956
2033
|
<Show when={step() === "sn-method"}>
|
|
1957
2034
|
<box gap={1}>
|
|
@@ -335,23 +335,39 @@ async function createFlowViaScheduledJob(
|
|
|
335
335
|
" }",
|
|
336
336
|
" } catch(snapRefE) { r.steps.reference_flow.snapshot_error = snapRefE + ''; }",
|
|
337
337
|
" }",
|
|
338
|
-
// Count trigger/action instances for reference flow
|
|
338
|
+
// Count trigger/action instances for reference flow AND its snapshot
|
|
339
339
|
" var refTrig = new GlideAggregate('sys_hub_trigger_instance');",
|
|
340
340
|
" refTrig.addQuery('flow', refId); refTrig.addAggregate('COUNT'); refTrig.query();",
|
|
341
|
-
" r.steps.reference_flow.
|
|
341
|
+
" r.steps.reference_flow.trigger_count_on_flow = refTrig.next() ? parseInt(refTrig.getAggregate('COUNT')) : 0;",
|
|
342
342
|
" var refAct = new GlideAggregate('sys_hub_action_instance');",
|
|
343
343
|
" refAct.addQuery('flow', refId); refAct.addAggregate('COUNT'); refAct.query();",
|
|
344
|
-
" r.steps.reference_flow.
|
|
344
|
+
" r.steps.reference_flow.action_count_on_flow = refAct.next() ? parseInt(refAct.getAggregate('COUNT')) : 0;",
|
|
345
|
+
// KEY: check if snapshot has its OWN action/trigger instances
|
|
346
|
+
" if (refLs !== 'null' && refLs.length === 32) {",
|
|
347
|
+
" var snapTrig = new GlideAggregate('sys_hub_trigger_instance');",
|
|
348
|
+
" snapTrig.addQuery('flow', refLs); snapTrig.addAggregate('COUNT'); snapTrig.query();",
|
|
349
|
+
" r.steps.reference_flow.trigger_count_on_snapshot = snapTrig.next() ? parseInt(snapTrig.getAggregate('COUNT')) : 0;",
|
|
350
|
+
" var snapAct = new GlideAggregate('sys_hub_action_instance');",
|
|
351
|
+
" snapAct.addQuery('flow', refLs); snapAct.addAggregate('COUNT'); snapAct.query();",
|
|
352
|
+
" r.steps.reference_flow.action_count_on_snapshot = snapAct.next() ? parseInt(snapAct.getAggregate('COUNT')) : 0;",
|
|
353
|
+
// Check sys_class_name of the snapshot (to understand table hierarchy)
|
|
354
|
+
" try {",
|
|
355
|
+
" var snapMeta = new GlideRecord('sys_metadata');",
|
|
356
|
+
" if (snapMeta.get(refLs)) {",
|
|
357
|
+
" r.steps.reference_flow.snapshot_sys_class = snapMeta.getValue('sys_class_name') + '';",
|
|
358
|
+
" }",
|
|
359
|
+
" } catch(e) {}",
|
|
360
|
+
// Check table hierarchy: does sys_hub_flow_snapshot extend sys_hub_flow?
|
|
361
|
+
" try {",
|
|
362
|
+
" var td = GlideDBObjectManager.get().getAbsoluteBase('sys_hub_flow_snapshot');",
|
|
363
|
+
" r.steps.reference_flow.snapshot_base_table = td + '';",
|
|
364
|
+
" } catch(e) { r.steps.reference_flow.snapshot_base_table = 'error'; }",
|
|
365
|
+
" }",
|
|
345
366
|
" }",
|
|
346
367
|
" } catch(refE) { r.steps.reference_flow = { error: refE + '' }; }",
|
|
347
368
|
"",
|
|
348
|
-
// ──
|
|
349
|
-
" r.steps.engine = { mode: 'probe_only' };",
|
|
350
|
-
" try {",
|
|
351
|
-
" if (typeof sn_fd !== 'undefined') {",
|
|
352
|
-
" r.steps.engine.sn_fd = 'available';",
|
|
353
|
-
" } else { r.steps.engine.sn_fd = 'unavailable'; }",
|
|
354
|
-
" } catch(engineErr) {}",
|
|
369
|
+
// ── No engine calls — probe only ──
|
|
370
|
+
" r.steps.engine = { mode: 'probe_only', sn_fd: typeof sn_fd !== 'undefined' ? 'available' : 'unavailable' };",
|
|
355
371
|
" }",
|
|
356
372
|
"",
|
|
357
373
|
" r.flow_sys_id = flowSysId ? flowSysId + '' : null;",
|