@memberjunction/excel-addin-server 0.0.0 → 6.2.0-edge.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +183 -0
- package/README.md +88 -28
- package/dist/catalog.d.ts +29 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +242 -0
- package/dist/catalog.js.map +1 -0
- package/dist/connection.d.ts +31 -0
- package/dist/connection.d.ts.map +1 -0
- package/dist/connection.js +111 -0
- package/dist/connection.js.map +1 -0
- package/dist/extension.d.ts +46 -0
- package/dist/extension.d.ts.map +1 -0
- package/dist/extension.js +177 -0
- package/dist/extension.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest-builder.d.ts +18 -0
- package/dist/manifest-builder.d.ts.map +1 -0
- package/dist/manifest-builder.js +126 -0
- package/dist/manifest-builder.js.map +1 -0
- package/dist/operations.d.ts +45 -0
- package/dist/operations.d.ts.map +1 -0
- package/dist/operations.js +160 -0
- package/dist/operations.js.map +1 -0
- package/dist/runtime.d.ts +53 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +88 -0
- package/dist/runtime.js.map +1 -0
- package/dist/settings.d.ts +48 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +115 -0
- package/dist/settings.js.map +1 -0
- package/dist/sources.d.ts +31 -0
- package/dist/sources.d.ts.map +1 -0
- package/dist/sources.js +230 -0
- package/dist/sources.js.map +1 -0
- package/dist/workbook-builder.d.ts +21 -0
- package/dist/workbook-builder.d.ts.map +1 -0
- package/dist/workbook-builder.js +122 -0
- package/dist/workbook-builder.js.map +1 -0
- package/package.json +39 -8
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Mints the API key the Excel add-in signs in with.
|
|
3
|
+
*
|
|
4
|
+
* The key belongs to the signed-in user and is created AS that user, so MJ's own permissions decide
|
|
5
|
+
* whether they may connect Excel at all (plan O10). It is limited to the `view:run` and `query:run`
|
|
6
|
+
* scopes; MJ's API keys deny every scope-checked operation outside a key's scopes, so it can't save,
|
|
7
|
+
* delete or mint more keys. It is bound to the `MJAPI` application when one is defined, expires, and
|
|
8
|
+
* shows up on the API Keys page, where it can be revoked.
|
|
9
|
+
*
|
|
10
|
+
* A key is never left without its scopes: if any step after creation fails, the key is revoked
|
|
11
|
+
* before the error is reported.
|
|
12
|
+
*
|
|
13
|
+
* @module @memberjunction/excel-addin-server
|
|
14
|
+
*/
|
|
15
|
+
import { LogError } from '@memberjunction/core';
|
|
16
|
+
import { GetAPIKeyEngine } from '@memberjunction/api-keys';
|
|
17
|
+
import { APIKeysEngineBase } from '@memberjunction/api-keys-base';
|
|
18
|
+
/** The label every Excel connection key carries on the API Keys page. */
|
|
19
|
+
export const EXCEL_CONNECTION_KEY_LABEL = 'Excel add-in';
|
|
20
|
+
/** The only scopes an Excel connection key holds. */
|
|
21
|
+
export const EXCEL_CONNECTION_SCOPES = ['view:run', 'query:run'];
|
|
22
|
+
/** The application a key is bound to, so it works against MJAPI only. */
|
|
23
|
+
export const EXCEL_CONNECTION_APPLICATION = 'MJAPI';
|
|
24
|
+
const MS_PER_DAY = 86400000;
|
|
25
|
+
/** Creates, scopes and binds the user's Excel connection key. Throws with a message fit to show them. */
|
|
26
|
+
export async function CreateExcelConnectionKey(user, provider, lifetimeDays, now = new Date()) {
|
|
27
|
+
if (!user?.ID) {
|
|
28
|
+
throw new Error('Sign in to MemberJunction before connecting Excel.');
|
|
29
|
+
}
|
|
30
|
+
const scopeIDs = await resolveScopeIDs(user, provider);
|
|
31
|
+
const expiresAt = new Date(now.getTime() + lifetimeDays * MS_PER_DAY);
|
|
32
|
+
const engine = GetAPIKeyEngine();
|
|
33
|
+
const created = await engine.CreateAPIKey({
|
|
34
|
+
UserId: user.ID,
|
|
35
|
+
Label: EXCEL_CONNECTION_KEY_LABEL,
|
|
36
|
+
Description: `Lets Microsoft Excel run the views and queries ${user.Name || user.Email} can see, read-only. Created ${now.toISOString().slice(0, 10)} by the MemberJunction Excel add-in.`,
|
|
37
|
+
ExpiresAt: expiresAt,
|
|
38
|
+
}, user, provider);
|
|
39
|
+
if (!created.Success || !created.RawKey || !created.APIKeyId) {
|
|
40
|
+
throw new Error(`Excel couldn't be connected: ${created.Error || 'the key could not be created'}. ` +
|
|
41
|
+
'If your role isn\'t allowed to create API keys, ask an administrator to allow it.');
|
|
42
|
+
}
|
|
43
|
+
await finishKeyOrRevoke(created.APIKeyId, scopeIDs, user, provider);
|
|
44
|
+
return { APIKey: created.RawKey, APIKeyID: created.APIKeyId, ExpiresAt: expiresAt, Label: EXCEL_CONNECTION_KEY_LABEL };
|
|
45
|
+
}
|
|
46
|
+
/** Finds the scope rows before anything is created, so a missing scope creates nothing. */
|
|
47
|
+
async function resolveScopeIDs(user, provider) {
|
|
48
|
+
const base = APIKeysEngineBase.Instance;
|
|
49
|
+
await base.Config(false, user, provider);
|
|
50
|
+
return EXCEL_CONNECTION_SCOPES.map(path => {
|
|
51
|
+
const scope = base.GetScopeByPath(path);
|
|
52
|
+
if (!scope) {
|
|
53
|
+
throw new Error(`Excel can't be connected: this server has no "${path}" API scope.`);
|
|
54
|
+
}
|
|
55
|
+
return scope.ID;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async function finishKeyOrRevoke(apiKeyID, scopeIDs, user, provider) {
|
|
59
|
+
try {
|
|
60
|
+
for (const scopeID of scopeIDs) {
|
|
61
|
+
await addScope(apiKeyID, scopeID, user, provider);
|
|
62
|
+
}
|
|
63
|
+
await bindApplication(apiKeyID, user, provider);
|
|
64
|
+
// APIKeysEngineBase overrides AdditionalLoading, so BaseEngine debounces entity-event cache
|
|
65
|
+
// reloads by 1500ms. Refresh before returning the raw key so the Excel pane's immediate
|
|
66
|
+
// post-sign-in RefreshAll() sees the new key's scopes and MJAPI application binding.
|
|
67
|
+
await APIKeysEngineBase.Instance.Config(true, user, provider);
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
const reason = e instanceof Error ? e.message : String(e);
|
|
71
|
+
await revokeAfterFailure(apiKeyID, user, provider, reason);
|
|
72
|
+
throw new Error(`Excel couldn't be connected: ${reason}. ` +
|
|
73
|
+
'If your role isn\'t allowed to create API keys, ask an administrator to allow it.');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function addScope(apiKeyID, scopeID, user, provider) {
|
|
77
|
+
const keyScope = await provider.GetEntityObject('MJ: API Key Scopes', user);
|
|
78
|
+
keyScope.APIKeyID = apiKeyID;
|
|
79
|
+
keyScope.ScopeID = scopeID;
|
|
80
|
+
keyScope.ResourcePattern = '*';
|
|
81
|
+
keyScope.PatternType = 'Include';
|
|
82
|
+
keyScope.IsDeny = false;
|
|
83
|
+
keyScope.Priority = 0;
|
|
84
|
+
if (!(await keyScope.Save())) {
|
|
85
|
+
throw new Error(`the key's scope could not be saved (${keyScope.LatestResult?.CompleteMessage ?? 'unknown error'})`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async function bindApplication(apiKeyID, user, provider) {
|
|
89
|
+
const application = APIKeysEngineBase.Instance.GetApplicationByName(EXCEL_CONNECTION_APPLICATION);
|
|
90
|
+
if (!application) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const binding = await provider.GetEntityObject('MJ: API Key Applications', user);
|
|
94
|
+
binding.APIKeyID = apiKeyID;
|
|
95
|
+
binding.ApplicationID = application.ID;
|
|
96
|
+
if (!(await binding.Save())) {
|
|
97
|
+
throw new Error(`the key could not be limited to ${EXCEL_CONNECTION_APPLICATION} (${binding.LatestResult?.CompleteMessage ?? 'unknown error'})`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function revokeAfterFailure(apiKeyID, user, provider, reason) {
|
|
101
|
+
try {
|
|
102
|
+
const revoked = await GetAPIKeyEngine().RevokeAPIKey(apiKeyID, user, provider);
|
|
103
|
+
if (!revoked) {
|
|
104
|
+
LogError(`Excel add-in: API key ${apiKeyID} was created but not finished (${reason}) and could NOT be revoked. Revoke it on the API Keys page.`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
LogError(`Excel add-in: API key ${apiKeyID} was created but not finished (${reason}); revoking it threw: ${e instanceof Error ? e.message : String(e)}. Revoke it on the API Keys page.`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Application, Router } from 'express';
|
|
2
|
+
import { BaseServerExtension, ExtensionHealthResult, ExtensionInitResult, ServerExtensionConfig, ServerExtensionInitContext, ServerExtensionPhase } from '@memberjunction/server-extensions-core';
|
|
3
|
+
import { ExcelAddinSettings } from './settings.js';
|
|
4
|
+
/** The `@RegisterClass` key hosts name as `DriverClass`. */
|
|
5
|
+
export declare const EXCEL_ADDIN_EXTENSION_DRIVER = "ExcelAddinServerExtension";
|
|
6
|
+
/** What the pane reads from `config.json`. */
|
|
7
|
+
export interface ExcelAddinPaneConfig {
|
|
8
|
+
ContractVersion: number;
|
|
9
|
+
ServerName: string;
|
|
10
|
+
/** The add-in's public base URL on this host. */
|
|
11
|
+
AddinUrl: string;
|
|
12
|
+
/** Explorer's connect page. */
|
|
13
|
+
ExplorerConnectUrl: string;
|
|
14
|
+
/** The most rows the pane writes for one source. */
|
|
15
|
+
MaxRows: number;
|
|
16
|
+
}
|
|
17
|
+
/** Everything the router needs, resolved at startup. */
|
|
18
|
+
export interface ExcelAddinRouterOptions {
|
|
19
|
+
Settings: ExcelAddinSettings;
|
|
20
|
+
AddinUrl: string;
|
|
21
|
+
/** The directory holding the built pane (`taskpane.html`, `assets/`, ...). */
|
|
22
|
+
WebRoot: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The add-in's public base URL: MJAPI's public URL plus the extension's RootPath relative to MJAPI's
|
|
26
|
+
* base path (guides/SERVER_EXTENSIONS_GUIDE.md: `publicUrl` already carries that prefix, so the
|
|
27
|
+
* composed RootPath is never appended to it whole).
|
|
28
|
+
*/
|
|
29
|
+
export declare function ComputeAddinPublicUrl(publicUrl: string, apiRootPath: string, rootPath: string): string;
|
|
30
|
+
/** The router serving the manifest, the pane's config and the pane's files. */
|
|
31
|
+
export declare function CreateExcelAddinRouter(options: ExcelAddinRouterOptions): Router;
|
|
32
|
+
/** Serves the Excel add-in from this MJ host and turns on the `ExcelAddin.*` operations. */
|
|
33
|
+
export declare class ExcelAddinServerExtension extends BaseServerExtension {
|
|
34
|
+
private routes;
|
|
35
|
+
get DefaultPhase(): ServerExtensionPhase;
|
|
36
|
+
Initialize(contextOrApp: ServerExtensionInitContext | Application, ...legacyConfig: [ServerExtensionConfig?]): Promise<ExtensionInitResult>;
|
|
37
|
+
Shutdown(): Promise<void>;
|
|
38
|
+
HealthCheck(): Promise<ExtensionHealthResult>;
|
|
39
|
+
/**
|
|
40
|
+
* Where the built pane lives: `dist/web` of `@memberjunction/excel-addin`. Protected so a host or
|
|
41
|
+
* a test can serve it from elsewhere. Throws when the pane hasn't been built.
|
|
42
|
+
*/
|
|
43
|
+
protected ResolveWebRoot(): string;
|
|
44
|
+
private mount;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=extension.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AA0BA,OAAgB,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGvD,OAAO,EACH,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,0BAA0B,EAC1B,oBAAoB,EACvB,MAAM,wCAAwC,CAAC;AAIhD,OAAO,EAAE,kBAAkB,EAA2B,MAAM,YAAY,CAAC;AAEzE,4DAA4D;AAC5D,eAAO,MAAM,4BAA4B,8BAA8B,CAAC;AAExE,8CAA8C;AAC9C,MAAM,WAAW,oBAAoB;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,wDAAwD;AACxD,MAAM,WAAW,uBAAuB;IACpC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKtG;AAED,+EAA+E;AAC/E,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAgC/E;AAED,4FAA4F;AAC5F,qBACa,yBAA0B,SAAQ,mBAAmB;IAC9D,OAAO,CAAC,MAAM,CAAgB;IAE9B,IAAoB,YAAY,IAAI,oBAAoB,CAEvD;IAIY,UAAU,CACnB,YAAY,EAAE,0BAA0B,GAAG,WAAW,EACtD,GAAG,YAAY,EAAE,CAAC,qBAAqB,CAAC,CAAC,GAC1C,OAAO,CAAC,mBAAmB,CAAC;IAqBlB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAKzB,WAAW,IAAI,OAAO,CAAC,qBAAqB,CAAC;IAS1D;;;OAGG;IACH,SAAS,CAAC,cAAc,IAAI,MAAM;IAUlC,OAAO,CAAC,KAAK;CAiBhB"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* @fileoverview The Server Extension that serves the Excel add-in from an MJ host.
|
|
9
|
+
*
|
|
10
|
+
* Pre-auth on purpose: Excel loads the manifest, the pane and its sign-in pages without an MJ
|
|
11
|
+
* session. Nothing mounted here returns data or accepts a credential. The pane reads MJ data only
|
|
12
|
+
* through GraphQL, with the API key the person approves in Explorer.
|
|
13
|
+
*
|
|
14
|
+
* Configure it in `mj.config.cjs`:
|
|
15
|
+
*
|
|
16
|
+
* ```js
|
|
17
|
+
* serverExtensions: [{
|
|
18
|
+
* Name: 'ExcelAddin',
|
|
19
|
+
* DriverClass: 'ExcelAddinServerExtension',
|
|
20
|
+
* PackagePath: '@memberjunction/excel-addin-server',
|
|
21
|
+
* RootPath: '/office/excel',
|
|
22
|
+
* Phase: 'pre-auth',
|
|
23
|
+
* Enabled: true,
|
|
24
|
+
* Settings: { ExplorerUrl: 'https://explorer.example.org', ServerName: 'Example Association' },
|
|
25
|
+
* }]
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @module @memberjunction/excel-addin-server
|
|
29
|
+
*/
|
|
30
|
+
import { existsSync } from 'node:fs';
|
|
31
|
+
import { createRequire } from 'node:module';
|
|
32
|
+
import { dirname, join } from 'node:path';
|
|
33
|
+
import express from 'express';
|
|
34
|
+
import { LogError } from '@memberjunction/core';
|
|
35
|
+
import { RegisterClass, TrimTrailingSlashes } from '@memberjunction/global';
|
|
36
|
+
import { BaseServerExtension, } from '@memberjunction/server-extensions-core';
|
|
37
|
+
import { EXCEL_WORKBOOK_CONTRACT_VERSION } from '@memberjunction/excel-addin';
|
|
38
|
+
import { BuildExcelAddinManifest } from './manifest-builder.js';
|
|
39
|
+
import { EXCEL_ADDIN_PATHS, EXCEL_CONNECT_ROUTE, ExcelAddinRuntime } from './runtime.js';
|
|
40
|
+
import { ParseExcelAddinSettings } from './settings.js';
|
|
41
|
+
/** The `@RegisterClass` key hosts name as `DriverClass`. */
|
|
42
|
+
export const EXCEL_ADDIN_EXTENSION_DRIVER = 'ExcelAddinServerExtension';
|
|
43
|
+
/**
|
|
44
|
+
* The add-in's public base URL: MJAPI's public URL plus the extension's RootPath relative to MJAPI's
|
|
45
|
+
* base path (guides/SERVER_EXTENSIONS_GUIDE.md: `publicUrl` already carries that prefix, so the
|
|
46
|
+
* composed RootPath is never appended to it whole).
|
|
47
|
+
*/
|
|
48
|
+
export function ComputeAddinPublicUrl(publicUrl, apiRootPath, rootPath) {
|
|
49
|
+
const base = TrimTrailingSlashes(apiRootPath ?? '');
|
|
50
|
+
const path = normalizeRootPath(rootPath);
|
|
51
|
+
const relative = base && path.toLowerCase().startsWith(base.toLowerCase()) ? path.slice(base.length) : path;
|
|
52
|
+
return `${TrimTrailingSlashes(publicUrl)}${relative.startsWith('/') ? relative : `/${relative}`}`;
|
|
53
|
+
}
|
|
54
|
+
/** The router serving the manifest, the pane's config and the pane's files. */
|
|
55
|
+
export function CreateExcelAddinRouter(options) {
|
|
56
|
+
const manifest = BuildExcelAddinManifest({
|
|
57
|
+
AddinId: options.Settings.AddinId,
|
|
58
|
+
Version: options.Settings.Version,
|
|
59
|
+
ServerName: options.Settings.ServerName,
|
|
60
|
+
AddinUrl: options.AddinUrl,
|
|
61
|
+
ExplorerUrl: options.Settings.ExplorerUrl,
|
|
62
|
+
});
|
|
63
|
+
const config = {
|
|
64
|
+
ContractVersion: EXCEL_WORKBOOK_CONTRACT_VERSION,
|
|
65
|
+
ServerName: options.Settings.ServerName,
|
|
66
|
+
AddinUrl: options.AddinUrl,
|
|
67
|
+
ExplorerConnectUrl: `${TrimTrailingSlashes(options.Settings.ExplorerUrl)}${EXCEL_CONNECT_ROUTE}`,
|
|
68
|
+
MaxRows: options.Settings.MaxRows,
|
|
69
|
+
};
|
|
70
|
+
const router = express.Router();
|
|
71
|
+
router.use((_req, res, next) => {
|
|
72
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
73
|
+
next();
|
|
74
|
+
});
|
|
75
|
+
router.get(EXCEL_ADDIN_PATHS.Manifest, (_req, res) => {
|
|
76
|
+
res.type('application/xml').setHeader('Cache-Control', 'no-store');
|
|
77
|
+
res.send(manifest);
|
|
78
|
+
});
|
|
79
|
+
router.get(EXCEL_ADDIN_PATHS.Config, (_req, res) => {
|
|
80
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
81
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
82
|
+
res.json(config);
|
|
83
|
+
});
|
|
84
|
+
// Excel caches add-in pages hard; no-cache makes it revalidate, so a host's upgrade reaches people.
|
|
85
|
+
router.use(express.static(options.WebRoot, { index: false, setHeaders: res => res.setHeader('Cache-Control', 'no-cache') }));
|
|
86
|
+
return router;
|
|
87
|
+
}
|
|
88
|
+
/** Serves the Excel add-in from this MJ host and turns on the `ExcelAddin.*` operations. */
|
|
89
|
+
let ExcelAddinServerExtension = class ExcelAddinServerExtension extends BaseServerExtension {
|
|
90
|
+
constructor() {
|
|
91
|
+
super(...arguments);
|
|
92
|
+
this.routes = [];
|
|
93
|
+
}
|
|
94
|
+
get DefaultPhase() {
|
|
95
|
+
return 'pre-auth';
|
|
96
|
+
}
|
|
97
|
+
// Keep Function.length === 1 (via rest tuple) so ServerExtensionLoader passes ServerExtensionInitContext
|
|
98
|
+
// instead of treating this class as a legacy 2-arg Initialize(app, config) extension.
|
|
99
|
+
async Initialize(contextOrApp, ...legacyConfig) {
|
|
100
|
+
try {
|
|
101
|
+
if (typeof contextOrApp === 'function') {
|
|
102
|
+
return fail('the Excel add-in needs MJServer\'s extension context to know its public URL; this server called Initialize(app, config).');
|
|
103
|
+
}
|
|
104
|
+
const settings = ParseExcelAddinSettings((legacyConfig[0] ?? contextOrApp.config).Settings);
|
|
105
|
+
if (!settings.Success || !settings.Settings) {
|
|
106
|
+
return fail(settings.ErrorMessage ?? 'its settings are not valid.');
|
|
107
|
+
}
|
|
108
|
+
if (!contextOrApp.publicUrl) {
|
|
109
|
+
return fail('MJAPI has no public URL (MJAPI_PUBLIC_URL), so Excel could not reach the add-in.');
|
|
110
|
+
}
|
|
111
|
+
return this.mount(contextOrApp, settings.Settings);
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
ExcelAddinRuntime.Instance.Reset();
|
|
115
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
116
|
+
LogError(`Excel add-in not started: ${message}`);
|
|
117
|
+
return fail(message);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async Shutdown() {
|
|
121
|
+
ExcelAddinRuntime.Instance.Reset();
|
|
122
|
+
this.routes = [];
|
|
123
|
+
}
|
|
124
|
+
async HealthCheck() {
|
|
125
|
+
const runtime = ExcelAddinRuntime.Instance;
|
|
126
|
+
return {
|
|
127
|
+
Healthy: runtime.IsEnabled,
|
|
128
|
+
Name: EXCEL_ADDIN_EXTENSION_DRIVER,
|
|
129
|
+
Details: { AddinUrl: runtime.AddinUrl, ManifestUrl: runtime.ManifestUrl, Routes: [...this.routes] },
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Where the built pane lives: `dist/web` of `@memberjunction/excel-addin`. Protected so a host or
|
|
134
|
+
* a test can serve it from elsewhere. Throws when the pane hasn't been built.
|
|
135
|
+
*/
|
|
136
|
+
ResolveWebRoot() {
|
|
137
|
+
const require = createRequire(import.meta.url);
|
|
138
|
+
const packageJson = require.resolve('@memberjunction/excel-addin/package.json');
|
|
139
|
+
const webRoot = join(dirname(packageJson), 'dist', 'web');
|
|
140
|
+
if (!existsSync(join(webRoot, 'taskpane.html'))) {
|
|
141
|
+
throw new Error(`the add-in pane isn't built (no ${join(webRoot, 'taskpane.html')}). Build @memberjunction/excel-addin.`);
|
|
142
|
+
}
|
|
143
|
+
return webRoot;
|
|
144
|
+
}
|
|
145
|
+
mount(context, settings) {
|
|
146
|
+
const rootPath = normalizeRootPath(context.config.RootPath);
|
|
147
|
+
const addinUrl = ComputeAddinPublicUrl(context.publicUrl ?? '', context.apiRootPath ?? '', rootPath);
|
|
148
|
+
const router = CreateExcelAddinRouter({ Settings: settings, AddinUrl: addinUrl, WebRoot: this.ResolveWebRoot() });
|
|
149
|
+
context.app.use(rootPath, router);
|
|
150
|
+
ExcelAddinRuntime.Instance.Configure(settings, addinUrl);
|
|
151
|
+
this.routes = [
|
|
152
|
+
`GET ${rootPath}${EXCEL_ADDIN_PATHS.Manifest}`,
|
|
153
|
+
`GET ${rootPath}${EXCEL_ADDIN_PATHS.Config}`,
|
|
154
|
+
`GET ${rootPath}/* (add-in pane)`,
|
|
155
|
+
];
|
|
156
|
+
return {
|
|
157
|
+
Success: true,
|
|
158
|
+
Message: `Excel add-in served at ${addinUrl}; manifest at ${addinUrl}${EXCEL_ADDIN_PATHS.Manifest}`,
|
|
159
|
+
RegisteredRoutes: [...this.routes],
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
ExcelAddinServerExtension = __decorate([
|
|
164
|
+
RegisterClass(BaseServerExtension, 'ExcelAddinServerExtension')
|
|
165
|
+
], ExcelAddinServerExtension);
|
|
166
|
+
export { ExcelAddinServerExtension };
|
|
167
|
+
function normalizeRootPath(rootPath) {
|
|
168
|
+
const trimmed = TrimTrailingSlashes((rootPath ?? '').trim());
|
|
169
|
+
if (!trimmed) {
|
|
170
|
+
return '/office/excel';
|
|
171
|
+
}
|
|
172
|
+
return trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
|
|
173
|
+
}
|
|
174
|
+
function fail(reason) {
|
|
175
|
+
return { Success: false, Message: `Excel add-in not started: ${reason}` };
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=extension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @memberjunction/excel-addin-server — the Excel add-in's server half.
|
|
3
|
+
*
|
|
4
|
+
* - `ExcelAddinServerExtension`: serves the add-in (manifest, pane, sign-in pages) from this host.
|
|
5
|
+
* - The `ExcelAddin.*` Remote Operation bodies: status, connection key, connected workbook.
|
|
6
|
+
* - The manifest and workbook builders they use.
|
|
7
|
+
*
|
|
8
|
+
* The browser-safe half (the workbook contract, the typed operations, the pane) is
|
|
9
|
+
* `@memberjunction/excel-addin`; import its types from there.
|
|
10
|
+
*/
|
|
11
|
+
export * from './settings.js';
|
|
12
|
+
export * from './runtime.js';
|
|
13
|
+
export * from './manifest-builder.js';
|
|
14
|
+
export * from './workbook-builder.js';
|
|
15
|
+
export * from './sources.js';
|
|
16
|
+
export * from './catalog.js';
|
|
17
|
+
export * from './connection.js';
|
|
18
|
+
export * from './operations.js';
|
|
19
|
+
export * from './extension.js';
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @memberjunction/excel-addin-server — the Excel add-in's server half.
|
|
3
|
+
*
|
|
4
|
+
* - `ExcelAddinServerExtension`: serves the add-in (manifest, pane, sign-in pages) from this host.
|
|
5
|
+
* - The `ExcelAddin.*` Remote Operation bodies: status, connection key, connected workbook.
|
|
6
|
+
* - The manifest and workbook builders they use.
|
|
7
|
+
*
|
|
8
|
+
* The browser-safe half (the workbook contract, the typed operations, the pane) is
|
|
9
|
+
* `@memberjunction/excel-addin`; import its types from there.
|
|
10
|
+
*/
|
|
11
|
+
export * from './settings.js';
|
|
12
|
+
export * from './runtime.js';
|
|
13
|
+
export * from './manifest-builder.js';
|
|
14
|
+
export * from './workbook-builder.js';
|
|
15
|
+
export * from './sources.js';
|
|
16
|
+
export * from './catalog.js';
|
|
17
|
+
export * from './connection.js';
|
|
18
|
+
export * from './operations.js';
|
|
19
|
+
export * from './extension.js';
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** What the manifest needs to know about the host. */
|
|
2
|
+
export interface ExcelAddinManifestOptions {
|
|
3
|
+
AddinId: string;
|
|
4
|
+
Version: string;
|
|
5
|
+
/** Shown as the add-in's name and on its ribbon button. */
|
|
6
|
+
ServerName: string;
|
|
7
|
+
/** The add-in's public base URL on this host. */
|
|
8
|
+
AddinUrl: string;
|
|
9
|
+
/** Where MJ Explorer runs; its origin is listed as an app domain. */
|
|
10
|
+
ExplorerUrl: string;
|
|
11
|
+
}
|
|
12
|
+
/** The reserved TaskpaneId that ties a workbook's web-extension part to this pane. */
|
|
13
|
+
export declare const AUTO_SHOW_TASKPANE_ID = "Office.AutoShowTaskpaneWithDocument";
|
|
14
|
+
/** Escapes text for an XML attribute or element. */
|
|
15
|
+
export declare function EscapeXml(value: string): string;
|
|
16
|
+
/** The add-in manifest XML for one host. */
|
|
17
|
+
export declare function BuildExcelAddinManifest(options: ExcelAddinManifestOptions): string;
|
|
18
|
+
//# sourceMappingURL=manifest-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-builder.d.ts","sourceRoot":"","sources":["../src/manifest-builder.ts"],"names":[],"mappings":"AAaA,sDAAsD;AACtD,MAAM,WAAW,yBAAyB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,sFAAsF;AACtF,eAAO,MAAM,qBAAqB,wCAAwC,CAAC;AAI3E,oDAAoD;AACpD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO/C;AAED,4CAA4C;AAC5C,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,yBAAyB,GAAG,MAAM,CAsClF"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Builds the Office add-in manifest each MJ host serves for itself.
|
|
3
|
+
*
|
|
4
|
+
* An add-in-only XML manifest (`TaskPaneApp`). Elements follow the schema's required order, which
|
|
5
|
+
* Office validates strictly. The ribbon button's `ShowTaskpane` action uses the reserved TaskpaneId
|
|
6
|
+
* `Office.AutoShowTaskpaneWithDocument`: that ID is what lets a workbook tagged by the workbook
|
|
7
|
+
* builder open this pane when the file opens.
|
|
8
|
+
*
|
|
9
|
+
* @module @memberjunction/excel-addin-server
|
|
10
|
+
*/
|
|
11
|
+
import { TrimTrailingSlashes } from '@memberjunction/global';
|
|
12
|
+
import { EXCEL_ADDIN_PATHS } from './runtime.js';
|
|
13
|
+
/** The reserved TaskpaneId that ties a workbook's web-extension part to this pane. */
|
|
14
|
+
export const AUTO_SHOW_TASKPANE_ID = 'Office.AutoShowTaskpaneWithDocument';
|
|
15
|
+
const MAX_SHORT_STRING = 125;
|
|
16
|
+
/** Escapes text for an XML attribute or element. */
|
|
17
|
+
export function EscapeXml(value) {
|
|
18
|
+
return value
|
|
19
|
+
.replace(/&/g, '&')
|
|
20
|
+
.replace(/</g, '<')
|
|
21
|
+
.replace(/>/g, '>')
|
|
22
|
+
.replace(/"/g, '"')
|
|
23
|
+
.replace(/'/g, ''');
|
|
24
|
+
}
|
|
25
|
+
/** The add-in manifest XML for one host. */
|
|
26
|
+
export function BuildExcelAddinManifest(options) {
|
|
27
|
+
const base = TrimTrailingSlashes(options.AddinUrl);
|
|
28
|
+
const name = options.ServerName.slice(0, MAX_SHORT_STRING);
|
|
29
|
+
const description = `Load ${name} views and queries into Excel, and refresh them as you.`.slice(0, 250);
|
|
30
|
+
const taskpaneUrl = `${base}${EXCEL_ADDIN_PATHS.Taskpane}`;
|
|
31
|
+
const icon = (size) => `${base}${EXCEL_ADDIN_PATHS.Assets}/icon-${size}.png`;
|
|
32
|
+
return [
|
|
33
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
34
|
+
'<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0" xmlns:ov="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="TaskPaneApp">',
|
|
35
|
+
` <Id>${EscapeXml(options.AddinId)}</Id>`,
|
|
36
|
+
` <Version>${EscapeXml(options.Version)}</Version>`,
|
|
37
|
+
' <ProviderName>MemberJunction</ProviderName>',
|
|
38
|
+
' <DefaultLocale>en-US</DefaultLocale>',
|
|
39
|
+
` <DisplayName DefaultValue="${EscapeXml(name)}"/>`,
|
|
40
|
+
` <Description DefaultValue="${EscapeXml(description)}"/>`,
|
|
41
|
+
` <IconUrl DefaultValue="${EscapeXml(icon(32))}"/>`,
|
|
42
|
+
` <HighResolutionIconUrl DefaultValue="${EscapeXml(icon(64))}"/>`,
|
|
43
|
+
` <SupportUrl DefaultValue="${EscapeXml(TrimTrailingSlashes(options.ExplorerUrl))}"/>`,
|
|
44
|
+
' <AppDomains>',
|
|
45
|
+
` <AppDomain>${EscapeXml(new URL(options.ExplorerUrl).origin)}</AppDomain>`,
|
|
46
|
+
' </AppDomains>',
|
|
47
|
+
' <Hosts>',
|
|
48
|
+
' <Host Name="Workbook"/>',
|
|
49
|
+
' </Hosts>',
|
|
50
|
+
' <Requirements>',
|
|
51
|
+
' <Sets DefaultMinVersion="1.1">',
|
|
52
|
+
' <Set Name="ExcelApi" MinVersion="1.4"/>',
|
|
53
|
+
' <Set Name="DialogApi" MinVersion="1.1"/>',
|
|
54
|
+
' </Sets>',
|
|
55
|
+
' </Requirements>',
|
|
56
|
+
' <DefaultSettings>',
|
|
57
|
+
` <SourceLocation DefaultValue="${EscapeXml(taskpaneUrl)}"/>`,
|
|
58
|
+
' </DefaultSettings>',
|
|
59
|
+
' <Permissions>ReadWriteDocument</Permissions>',
|
|
60
|
+
buildVersionOverrides(name, taskpaneUrl, icon),
|
|
61
|
+
'</OfficeApp>',
|
|
62
|
+
'',
|
|
63
|
+
].join('\n');
|
|
64
|
+
}
|
|
65
|
+
function buildVersionOverrides(name, taskpaneUrl, icon) {
|
|
66
|
+
const icons = '<Icon><bt:Image size="16" resid="Icon.16x16"/><bt:Image size="32" resid="Icon.32x32"/><bt:Image size="80" resid="Icon.80x80"/></Icon>';
|
|
67
|
+
return [
|
|
68
|
+
' <VersionOverrides xmlns="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="VersionOverridesV1_0">',
|
|
69
|
+
' <Hosts>',
|
|
70
|
+
' <Host xsi:type="Workbook">',
|
|
71
|
+
' <DesktopFormFactor>',
|
|
72
|
+
' <GetStarted>',
|
|
73
|
+
' <Title resid="GetStarted.Title"/>',
|
|
74
|
+
' <Description resid="GetStarted.Description"/>',
|
|
75
|
+
' <LearnMoreUrl resid="Taskpane.Url"/>',
|
|
76
|
+
' </GetStarted>',
|
|
77
|
+
// Required by the schema; the pane page is a valid function file and no ExecuteFunction action uses it.
|
|
78
|
+
' <FunctionFile resid="Taskpane.Url"/>',
|
|
79
|
+
' <ExtensionPoint xsi:type="PrimaryCommandSurface">',
|
|
80
|
+
' <OfficeTab id="TabData">',
|
|
81
|
+
' <Group id="MJ.ExcelAddin.Group">',
|
|
82
|
+
' <Label resid="Group.Label"/>',
|
|
83
|
+
` ${icons}`,
|
|
84
|
+
' <Control xsi:type="Button" id="MJ.ExcelAddin.TaskpaneButton">',
|
|
85
|
+
' <Label resid="Button.Label"/>',
|
|
86
|
+
' <Supertip><Title resid="Button.Label"/><Description resid="Button.Tooltip"/></Supertip>',
|
|
87
|
+
` ${icons}`,
|
|
88
|
+
` <Action xsi:type="ShowTaskpane"><TaskpaneId>${AUTO_SHOW_TASKPANE_ID}</TaskpaneId><SourceLocation resid="Taskpane.Url"/></Action>`,
|
|
89
|
+
' </Control>',
|
|
90
|
+
' </Group>',
|
|
91
|
+
' </OfficeTab>',
|
|
92
|
+
' </ExtensionPoint>',
|
|
93
|
+
' </DesktopFormFactor>',
|
|
94
|
+
' </Host>',
|
|
95
|
+
' </Hosts>',
|
|
96
|
+
buildResources(name, taskpaneUrl, icon),
|
|
97
|
+
' </VersionOverrides>',
|
|
98
|
+
].join('\n');
|
|
99
|
+
}
|
|
100
|
+
function buildResources(name, taskpaneUrl, icon) {
|
|
101
|
+
const image = (size) => ` <bt:Image id="Icon.${size}x${size}" DefaultValue="${EscapeXml(icon(size))}"/>`;
|
|
102
|
+
const short = (id, text) => ` <bt:String id="${id}" DefaultValue="${EscapeXml(text.slice(0, MAX_SHORT_STRING))}"/>`;
|
|
103
|
+
const long = (id, text) => ` <bt:String id="${id}" DefaultValue="${EscapeXml(text)}"/>`;
|
|
104
|
+
return [
|
|
105
|
+
' <Resources>',
|
|
106
|
+
' <bt:Images>',
|
|
107
|
+
image(16),
|
|
108
|
+
image(32),
|
|
109
|
+
image(80),
|
|
110
|
+
' </bt:Images>',
|
|
111
|
+
' <bt:Urls>',
|
|
112
|
+
` <bt:Url id="Taskpane.Url" DefaultValue="${EscapeXml(taskpaneUrl)}"/>`,
|
|
113
|
+
' </bt:Urls>',
|
|
114
|
+
' <bt:ShortStrings>',
|
|
115
|
+
short('GetStarted.Title', `Get ${name} data in Excel`),
|
|
116
|
+
short('Group.Label', name),
|
|
117
|
+
short('Button.Label', name),
|
|
118
|
+
' </bt:ShortStrings>',
|
|
119
|
+
' <bt:LongStrings>',
|
|
120
|
+
long('GetStarted.Description', `Open a view or query in ${name} and choose Open in Excel. Sign in here to fill it, and refresh any time.`),
|
|
121
|
+
long('Button.Tooltip', `Open the ${name} pane to sign in and refresh this workbook's data.`),
|
|
122
|
+
' </bt:LongStrings>',
|
|
123
|
+
' </Resources>',
|
|
124
|
+
].join('\n');
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=manifest-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-builder.js","sourceRoot":"","sources":["../src/manifest-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Server bodies of the `ExcelAddin.*` Remote Operations.
|
|
3
|
+
*
|
|
4
|
+
* Each subclass extends the typed base from `@memberjunction/excel-addin` and registers under the
|
|
5
|
+
* same key, so a browser's `new ExcelAddinBuildWorkbookOperation().Execute(...)` or the Excel
|
|
6
|
+
* pane's `ExecuteRemoteOperation` GraphQL mutation lands here. All operations read
|
|
7
|
+
* {@link ExcelAddinRuntime}: on a host whose Server Extension isn't configured, status says the
|
|
8
|
+
* add-in is off and the other operations refuse.
|
|
9
|
+
*
|
|
10
|
+
* @module @memberjunction/excel-addin-server
|
|
11
|
+
*/
|
|
12
|
+
import { IMetadataProvider, UserInfo } from '@memberjunction/core';
|
|
13
|
+
import { ExcelAddinBuildWorkbookInput, ExcelAddinBuildWorkbookOperation, ExcelAddinBuildWorkbookOutput, ExcelAddinCatalogInput, ExcelAddinCatalogOutput, ExcelAddinCreateConnectionInput, ExcelAddinCreateConnectionOperation, ExcelAddinCreateConnectionOutput, ExcelAddinEntityViewsInput, ExcelAddinEntityViewsOutput, ExcelAddinGetCatalogOperation, ExcelAddinGetEntityViewsOperation, ExcelAddinGetStatusOperation, ExcelAddinResolveSourceInput, ExcelAddinResolveSourceOperation, ExcelAddinResolveSourceOutput, ExcelAddinStatusInput, ExcelAddinStatusOutput, ExcelWorkbookSource } from '@memberjunction/excel-addin';
|
|
14
|
+
/** Reports whether this host serves the Excel add-in. */
|
|
15
|
+
export declare class ExcelAddinGetStatusServerOperation extends ExcelAddinGetStatusOperation {
|
|
16
|
+
protected InternalExecute(_input: ExcelAddinStatusInput, _provider: IMetadataProvider, _user: UserInfo): Promise<ExcelAddinStatusOutput>;
|
|
17
|
+
}
|
|
18
|
+
/** Mints the caller's Excel connection key. */
|
|
19
|
+
export declare class ExcelAddinCreateConnectionServerOperation extends ExcelAddinCreateConnectionOperation {
|
|
20
|
+
protected Authorize(_input: ExcelAddinCreateConnectionInput, _user: UserInfo): Promise<boolean>;
|
|
21
|
+
protected InternalExecute(_input: ExcelAddinCreateConnectionInput, provider: IMetadataProvider, user: UserInfo): Promise<ExcelAddinCreateConnectionOutput>;
|
|
22
|
+
}
|
|
23
|
+
/** Builds a connected workbook (headings, no rows) for saved views, entities, and queries the caller can see. */
|
|
24
|
+
export declare class ExcelAddinBuildWorkbookServerOperation extends ExcelAddinBuildWorkbookOperation {
|
|
25
|
+
protected Authorize(_input: ExcelAddinBuildWorkbookInput, _user: UserInfo): Promise<boolean>;
|
|
26
|
+
protected InternalExecute(input: ExcelAddinBuildWorkbookInput, provider: IMetadataProvider, user: UserInfo): Promise<ExcelAddinBuildWorkbookOutput>;
|
|
27
|
+
}
|
|
28
|
+
/** Lists the applications, readable entities, query categories, and runnable queries for the Excel picker. */
|
|
29
|
+
export declare class ExcelAddinGetCatalogServerOperation extends ExcelAddinGetCatalogOperation {
|
|
30
|
+
protected Authorize(_input: ExcelAddinCatalogInput, _user: UserInfo): Promise<boolean>;
|
|
31
|
+
protected InternalExecute(_input: ExcelAddinCatalogInput, provider: IMetadataProvider, user: UserInfo): Promise<ExcelAddinCatalogOutput>;
|
|
32
|
+
}
|
|
33
|
+
/** Lists the accessible saved `MJ: User Views` records on a chosen entity for the Excel picker. */
|
|
34
|
+
export declare class ExcelAddinGetEntityViewsServerOperation extends ExcelAddinGetEntityViewsOperation {
|
|
35
|
+
protected Authorize(_input: ExcelAddinEntityViewsInput, _user: UserInfo): Promise<boolean>;
|
|
36
|
+
protected InternalExecute(input: ExcelAddinEntityViewsInput, provider: IMetadataProvider, user: UserInfo): Promise<ExcelAddinEntityViewsOutput>;
|
|
37
|
+
}
|
|
38
|
+
/** Resolves a single chosen view, entity, or saved query into its canonical columns and checked parameters. */
|
|
39
|
+
export declare class ExcelAddinResolveSourceServerOperation extends ExcelAddinResolveSourceOperation {
|
|
40
|
+
protected Authorize(_input: ExcelAddinResolveSourceInput, _user: UserInfo): Promise<boolean>;
|
|
41
|
+
protected InternalExecute(input: ExcelAddinResolveSourceInput, provider: IMetadataProvider, user: UserInfo): Promise<ExcelAddinResolveSourceOutput>;
|
|
42
|
+
}
|
|
43
|
+
/** A file name safe on every desktop platform, from the first source's name. */
|
|
44
|
+
export declare function MakeWorkbookFileName(sources: Pick<ExcelWorkbookSource, 'Name'>[]): string;
|
|
45
|
+
//# sourceMappingURL=operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../src/operations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAA0B,iBAAiB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAE3F,OAAO,EAEH,4BAA4B,EAC5B,gCAAgC,EAChC,6BAA6B,EAC7B,sBAAsB,EACtB,uBAAuB,EACvB,+BAA+B,EAC/B,mCAAmC,EACnC,gCAAgC,EAChC,0BAA0B,EAC1B,2BAA2B,EAC3B,6BAA6B,EAC7B,iCAAiC,EACjC,4BAA4B,EAC5B,4BAA4B,EAC5B,gCAAgC,EAChC,6BAA6B,EAC7B,qBAAqB,EACrB,sBAAsB,EAEtB,mBAAmB,EACtB,MAAM,6BAA6B,CAAC;AASrC,yDAAyD;AACzD,qBACa,kCAAmC,SAAQ,4BAA4B;cAChE,eAAe,CAAC,MAAM,EAAE,qBAAqB,EAAE,SAAS,EAAE,iBAAiB,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,sBAAsB,CAAC;CAcjJ;AAED,+CAA+C;AAC/C,qBACa,yCAA0C,SAAQ,mCAAmC;cAC9E,SAAS,CAAC,MAAM,EAAE,+BAA+B,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;cAIrF,eAAe,CAAC,MAAM,EAAE,+BAA+B,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,gCAAgC,CAAC;CAKnK;AAED,iHAAiH;AACjH,qBACa,sCAAuC,SAAQ,gCAAgC;cACxE,SAAS,CAAC,MAAM,EAAE,4BAA4B,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;cAIlF,eAAe,CAAC,KAAK,EAAE,4BAA4B,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,6BAA6B,CAAC;CAmB5J;AAED,8GAA8G;AAC9G,qBACa,mCAAoC,SAAQ,6BAA6B;cAClE,SAAS,CAAC,MAAM,EAAE,sBAAsB,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;cAI5E,eAAe,CAAC,MAAM,EAAE,sBAAsB,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAIjJ;AAED,mGAAmG;AACnG,qBACa,uCAAwC,SAAQ,iCAAiC;cAC1E,SAAS,CAAC,MAAM,EAAE,0BAA0B,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;cAIhF,eAAe,CAAC,KAAK,EAAE,0BAA0B,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,2BAA2B,CAAC;CAIxJ;AAED,+GAA+G;AAC/G,qBACa,sCAAuC,SAAQ,gCAAgC;cACxE,SAAS,CAAC,MAAM,EAAE,4BAA4B,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;cAIlF,eAAe,CAAC,KAAK,EAAE,4BAA4B,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,6BAA6B,CAAC;CAK5J;AAED,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,mBAAmB,EAAE,MAAM,CAAC,EAAE,GAAG,MAAM,CAYzF"}
|