@oddington/sdk 0.1.36 → 0.1.37
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/README.md +44 -0
- package/dist/browser.js +88 -2
- package/dist/index.js +2 -2
- package/dist/types/packages/sdk/src/public.d.ts +2 -2
- package/dist/types/packages/sdk/src/source.d.ts +19 -0
- package/dist/types/shared/connection-runtime.d.ts +19 -2
- package/dist/types/shared/repository-targets.d.ts +0 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -79,6 +79,12 @@ declared `review` handler crosses the Inbox publication seam as `review`; Inbox
|
|
|
79
79
|
retains the canonical `invoice-import` routine identity separately, without
|
|
80
80
|
deploying or executing that handler.
|
|
81
81
|
|
|
82
|
+
Microsoft Connection configuration has a separate, optional `access` description.
|
|
83
|
+
It preserves supplied strings, including existing `read` and `read-write` labels,
|
|
84
|
+
and does not grant or restrict Microsoft permissions. Management results omit
|
|
85
|
+
this metadata when absent. Setup and safe inspection are documented in the
|
|
86
|
+
[CLI Connections guide](../../apps/cli/README.md#connections).
|
|
87
|
+
|
|
82
88
|
With `access: { ai: true }`, `os.ai.generateText` returns non-empty `{ text }`.
|
|
83
89
|
`os.ai.generateObject` returns `{ object }` validated against the requested
|
|
84
90
|
`schema`, with its inferred type. An invalid answer throws `RoutineAIError`
|
|
@@ -504,6 +510,44 @@ revision and URL facts. Distinct objects and custom provider values remain.
|
|
|
504
510
|
Helpers need no initialization and perform no I/O, choose no ref, and add no
|
|
505
511
|
changes. File retention and Data validation/publication remain explicit.
|
|
506
512
|
|
|
513
|
+
Microsoft helpers are also exported at the package root, with the corresponding
|
|
514
|
+
`OutlookSourceLocation` and `SharePointSourceLocation` types:
|
|
515
|
+
|
|
516
|
+
```ts
|
|
517
|
+
const messageLocation = source.location.outlook({
|
|
518
|
+
connection: 'outlook/invoices', message: message.id, url: message.webLink,
|
|
519
|
+
// attachment: attachment.id, // Include for attachment bytes; omit for message MIME.
|
|
520
|
+
});
|
|
521
|
+
const itemLocation = source.location.sharepoint({
|
|
522
|
+
connection: 'sharepoint/operations', site: siteId, drive: driveId, item: item.id,
|
|
523
|
+
version: version.id, path: lastKnownPath, url: item.webUrl,
|
|
524
|
+
});
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
Construct these only after successful provider reads establish the coordinates
|
|
528
|
+
for the retained bytes, and save them alongside `source.location.os(file)` using
|
|
529
|
+
ordinary Data publication. Request `Prefer: IdType="ImmutableId"` consistently
|
|
530
|
+
when obtaining Outlook message and attachment IDs. These IDs are case-sensitive
|
|
531
|
+
and survive folder moves within the same mailbox, but not archive-mailbox moves
|
|
532
|
+
or export/reimport. Subjects, filenames and `internetMessageId` are not substitutes.
|
|
533
|
+
Omit `attachment` for an exact message MIME File; supply it for an attachment File.
|
|
534
|
+
|
|
535
|
+
For SharePoint, use the saved Graph site ID, the document library's drive ID and
|
|
536
|
+
the file's driveItem ID. Optional `version` is an actual driveItemVersion ID
|
|
537
|
+
established for those bytes, never an eTag or a guessed version. Omit it when no
|
|
538
|
+
such version is established. Names, paths and URLs do not establish identity.
|
|
539
|
+
Optional `path` is last-known context; `url` is the ordinary HTTPS message web
|
|
540
|
+
link or SharePoint webUrl. Never retain temporary download, upload-session or
|
|
541
|
+
copy-monitor URLs, authorization or credentials in Locations.
|
|
542
|
+
|
|
543
|
+
Outlook merge identity is connection/message/attachment, with whole messages
|
|
544
|
+
distinct from attachments. SharePoint identity is connection/site/drive/item/
|
|
545
|
+
version, with absent versions distinct from present ones. Matching observations
|
|
546
|
+
replace path/link context, including removing omitted context; distinct IDs,
|
|
547
|
+
versions and copies remain separate. Incomplete coordinates gain no inferred
|
|
548
|
+
identity. The retained OS File and hash own exact content; external edits do
|
|
549
|
+
not change an existing Source's bytes. These helpers perform no provider I/O.
|
|
550
|
+
|
|
507
551
|
Read a named repository through the authenticated host context:
|
|
508
552
|
|
|
509
553
|
```ts
|
package/dist/browser.js
CHANGED
|
@@ -1960,6 +1960,37 @@ var files = {
|
|
|
1960
1960
|
function validDropboxRootPath(value) {
|
|
1961
1961
|
return typeof value == "string" && value.length <= 2048 && value.startsWith("/") && !/[\\\x00-\x1f\x7f]/.test(value) && value.slice(1).split("/").every((segment) => segment.length > 0 && segment.trim() === segment && segment !== "." && segment !== "..");
|
|
1962
1962
|
}
|
|
1963
|
+
function validMicrosoftId(value) {
|
|
1964
|
+
return typeof value == "string" && /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i.test(value);
|
|
1965
|
+
}
|
|
1966
|
+
function validMicrosoftMailbox(value) {
|
|
1967
|
+
return typeof value == "string" && value.length <= 254 && /^[^\s@/?#\\\x00-\x1f\x7f]+@[^\s@/?#\\\x00-\x1f\x7f]+\.[^\s@/?#\\\x00-\x1f\x7f]+$/.test(value);
|
|
1968
|
+
}
|
|
1969
|
+
function sharePointHost(value) {
|
|
1970
|
+
return /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.sharepoint\.com$/.test(value);
|
|
1971
|
+
}
|
|
1972
|
+
function canonicalSharePointSiteUrl(value) {
|
|
1973
|
+
if (!(typeof value != "string" || value.length > 2048 || /[\s\\?#\x00-\x1f\x7f]/.test(value) || !/^https:\/\/[^/:@]+(?:\/|$)/i.test(value)))
|
|
1974
|
+
try {
|
|
1975
|
+
let url = new URL(value);
|
|
1976
|
+
if (url.protocol !== "https:" || !sharePointHost(url.hostname) || url.username || url.password || url.port) return;
|
|
1977
|
+
let rawPath = value.replace(/^https:\/\/[^/]+/i, "") || "/", path = rawPath.endsWith("/") ? rawPath.slice(0, -1) : rawPath, segments = path.slice(1).split("/");
|
|
1978
|
+
if (path && segments.some((segment) => !segment)) return;
|
|
1979
|
+
let encoded = path ? segments.map((segment) => {
|
|
1980
|
+
let decoded = decodeURIComponent(segment);
|
|
1981
|
+
if (decoded === "." || decoded === ".." || /[/%\\?#\x00-\x1f\x7f]/.test(decoded)) throw new Error();
|
|
1982
|
+
return encodeURIComponent(decoded);
|
|
1983
|
+
}).join("/") : "", canonical = `https://${url.hostname}/${encoded}`;
|
|
1984
|
+
return canonical.length <= 2048 ? canonical : void 0;
|
|
1985
|
+
} catch {
|
|
1986
|
+
return;
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
function validSharePointSiteId(value, siteUrl) {
|
|
1990
|
+
if (typeof value != "string" || value.length > 512) return !1;
|
|
1991
|
+
let [host, collection, site, extra] = value.split(",");
|
|
1992
|
+
return extra === void 0 && host === new URL(siteUrl).hostname && validMicrosoftId(collection) && validMicrosoftId(site);
|
|
1993
|
+
}
|
|
1963
1994
|
function validGoogleScopes(value) {
|
|
1964
1995
|
return Array.isArray(value) && value.length > 0 && value.length <= 32 && value.every((scope) => typeof scope == "string" && scope.length <= 256 && /^(https:\/\/www\.googleapis\.com\/auth\/[A-Za-z0-9._-]+|https:\/\/mail\.google\.com\/|openid|email|profile)$/.test(scope)) && new Set(value).size === value.length;
|
|
1965
1996
|
}
|
|
@@ -1970,13 +2001,32 @@ function validDropboxFileScopes(value) {
|
|
|
1970
2001
|
|
|
1971
2002
|
var ROUTINE_CONNECTION_CREDENTIALS_ENV = "OS_ROUTINE_CONNECTION_CREDENTIALS";
|
|
1972
2003
|
function parseRoutineConnectionNames(value) {
|
|
1973
|
-
if (!Array.isArray(value) || value.some((name2) => typeof name2 != "string" || !/^(gmail|airtable|dropbox)\/[a-z0-9][a-z0-9-]{0,62}$/.test(name2)) || new Set(value).size !== value.length)
|
|
2004
|
+
if (!Array.isArray(value) || value.some((name2) => typeof name2 != "string" || !/^(gmail|airtable|dropbox|outlook|sharepoint)\/[a-z0-9][a-z0-9-]{0,62}$/.test(name2)) || new Set(value).size !== value.length)
|
|
1974
2005
|
throw new Error("Invalid routine connections");
|
|
1975
2006
|
return value;
|
|
1976
2007
|
}
|
|
1977
2008
|
var connectionUuid = (v) => typeof v == "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(v);
|
|
1978
2009
|
function runtimeConnection(lease) {
|
|
1979
2010
|
switch (lease.provider) {
|
|
2011
|
+
case "outlook":
|
|
2012
|
+
return {
|
|
2013
|
+
id: `outlook/${lease.name}`,
|
|
2014
|
+
provider: lease.provider,
|
|
2015
|
+
name: lease.name,
|
|
2016
|
+
mailboxEmail: lease.mailboxEmail,
|
|
2017
|
+
accessToken: lease.accessToken,
|
|
2018
|
+
expiresAt: lease.expiresAt
|
|
2019
|
+
};
|
|
2020
|
+
case "sharepoint":
|
|
2021
|
+
return {
|
|
2022
|
+
id: `sharepoint/${lease.name}`,
|
|
2023
|
+
provider: lease.provider,
|
|
2024
|
+
name: lease.name,
|
|
2025
|
+
siteId: lease.siteId,
|
|
2026
|
+
siteUrl: lease.siteUrl,
|
|
2027
|
+
accessToken: lease.accessToken,
|
|
2028
|
+
expiresAt: lease.expiresAt
|
|
2029
|
+
};
|
|
1980
2030
|
case "gmail":
|
|
1981
2031
|
return {
|
|
1982
2032
|
id: `gmail/${lease.name}`,
|
|
@@ -2014,6 +2064,11 @@ function parseConnectionLease(raw, now = Date.now()) {
|
|
|
2014
2064
|
let v = raw;
|
|
2015
2065
|
if (!v || typeof v != "object" || Array.isArray(v) || !connectionUuid(v.connectionId) || !connectionUuid(v.runId) || typeof v.name != "string" || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(v.name) || typeof v.accessToken != "string" || !/^[A-Za-z0-9._~+/-]{1,8192}={0,2}$/.test(v.accessToken))
|
|
2016
2066
|
throw new Error("Invalid connection credential");
|
|
2067
|
+
if (v.provider === "outlook" || v.provider === "sharepoint") {
|
|
2068
|
+
if (!(v.provider === "outlook" ? Object.keys(v).sort().join(",") === "accessToken,connectionId,expiresAt,mailboxEmail,name,provider,runId" && validMicrosoftMailbox(v.mailboxEmail) : Object.keys(v).sort().join(",") === "accessToken,connectionId,expiresAt,name,provider,runId,siteId,siteUrl" && typeof v.siteUrl == "string" && canonicalSharePointSiteUrl(v.siteUrl) === v.siteUrl && validSharePointSiteId(v.siteId, v.siteUrl)) || typeof v.expiresAt != "string" || !Number.isFinite(Date.parse(v.expiresAt)) || Date.parse(v.expiresAt) <= now + 6e4 || Date.parse(v.expiresAt) > now + 36e5)
|
|
2069
|
+
throw new Error("Invalid connection credential");
|
|
2070
|
+
return v;
|
|
2071
|
+
}
|
|
2017
2072
|
if (v.provider === "gmail") {
|
|
2018
2073
|
if (Object.keys(v).sort().join(",") !== "accessToken,accountEmail,connectionId,expiresAt,name,provider,runId,scopes" || typeof v.accountEmail != "string" || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v.accountEmail) || !validGoogleScopes(v.scopes) || typeof v.expiresAt != "string" || !Number.isFinite(Date.parse(v.expiresAt)) || Date.parse(v.expiresAt) <= now + 6e4 || Date.parse(v.expiresAt) > now + 36e5)
|
|
2019
2074
|
throw new Error("Invalid connection credential");
|
|
@@ -2281,7 +2336,17 @@ var connections = /* @__PURE__ */ runtimeConnections();
|
|
|
2281
2336
|
var LOCAL_ROUTINE_VALUE_BYTES = 256 * 1024;
|
|
2282
2337
|
|
|
2283
2338
|
function locationIdentity(location) {
|
|
2284
|
-
let coordinates = location.provider === "os" ? [location.file] : location.provider === "gmail" ? [location.connection, location.message, location.attachment] : location.provider === "dropbox" ? [location.connection, location.file] :
|
|
2339
|
+
let coordinates = location.provider === "os" ? [location.file] : location.provider === "gmail" ? [location.connection, location.message, location.attachment] : location.provider === "dropbox" ? [location.connection, location.file] : location.provider === "outlook" ? [
|
|
2340
|
+
location.connection,
|
|
2341
|
+
location.message,
|
|
2342
|
+
...location.attachment === void 0 ? [] : [location.attachment]
|
|
2343
|
+
] : location.provider === "sharepoint" ? [
|
|
2344
|
+
location.connection,
|
|
2345
|
+
location.site,
|
|
2346
|
+
location.drive,
|
|
2347
|
+
location.item,
|
|
2348
|
+
...location.version === void 0 ? [] : [location.version]
|
|
2349
|
+
] : void 0;
|
|
2285
2350
|
if (coordinates?.every((value) => typeof value == "string" && value.length > 0))
|
|
2286
2351
|
return JSON.stringify([location.provider, ...coordinates]);
|
|
2287
2352
|
}
|
|
@@ -2320,6 +2385,27 @@ var source = {
|
|
|
2320
2385
|
...input.path === void 0 ? {} : { path: input.path },
|
|
2321
2386
|
...input.url === void 0 ? {} : { url: input.url }
|
|
2322
2387
|
};
|
|
2388
|
+
},
|
|
2389
|
+
outlook(input) {
|
|
2390
|
+
return {
|
|
2391
|
+
provider: "outlook",
|
|
2392
|
+
connection: input.connection,
|
|
2393
|
+
message: input.message,
|
|
2394
|
+
...input.attachment === void 0 ? {} : { attachment: input.attachment },
|
|
2395
|
+
...input.url === void 0 ? {} : { url: input.url }
|
|
2396
|
+
};
|
|
2397
|
+
},
|
|
2398
|
+
sharepoint(input) {
|
|
2399
|
+
return {
|
|
2400
|
+
provider: "sharepoint",
|
|
2401
|
+
connection: input.connection,
|
|
2402
|
+
site: input.site,
|
|
2403
|
+
drive: input.drive,
|
|
2404
|
+
item: input.item,
|
|
2405
|
+
...input.version === void 0 ? {} : { version: input.version },
|
|
2406
|
+
...input.path === void 0 ? {} : { path: input.path },
|
|
2407
|
+
...input.url === void 0 ? {} : { url: input.url }
|
|
2408
|
+
};
|
|
2323
2409
|
}
|
|
2324
2410
|
},
|
|
2325
2411
|
locations: {
|