Skip to content

Commit

Permalink
Merge pull request #3153 from patrick-rodgers/version-4
Browse files Browse the repository at this point in the history
site open extensions, graph pages support, DebugHeaders
  • Loading branch information
patrick-rodgers authored Nov 18, 2024
2 parents a6611e0 + 5e12843 commit d4bb740
Show file tree
Hide file tree
Showing 25 changed files with 603 additions and 131 deletions.
4 changes: 2 additions & 2 deletions debug/launch/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ import { Example } from "./sp.js";
// create a settings file using settings.example.js as a template
import(findup("settings.js")).then((settings: { settings: ITestingSettings }) => {

Logger.activeLogLevel = LogLevel.Info;
Logger.activeLogLevel = LogLevel.Info;

// // setup console logger
Logger.subscribe(ConsoleListener("Debug", {
color: "skyblue",
error: "red",
verbose: "lightslategray",
warning: "yellow",
}));
}));

Example(settings.settings);

Expand Down
30 changes: 17 additions & 13 deletions debug/launch/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@ import { SPDefault, GraphDefault } from "@pnp/nodejs";
import { spfi, SPFI } from "@pnp/sp";
import { GraphFI, graphfi } from "@pnp/graph";
import { LogLevel, PnPLogging } from "@pnp/logging";
import { Queryable } from "@pnp/queryable";
import { Queryable, DebugHeaders } from "@pnp/queryable";

export function spSetup(settings: ITestingSettings): SPFI {

const sp = spfi(settings.testing.sp.url).using(SPDefault({
msal: {
config: settings.testing.sp.msal.init,
scopes: settings.testing.sp.msal.scopes,
},
})).using(
const sp = spfi(settings.testing.sp.url).using(
SPDefault({
msal: {
config: settings.testing.sp.msal.init,
scopes: settings.testing.sp.msal.scopes,
},
}),
PnPLogging(LogLevel.Verbose),
DebugHeaders(),
function (instance: Queryable) {

instance.on.pre(async (url, init, result) => {
Expand All @@ -29,13 +31,15 @@ export function spSetup(settings: ITestingSettings): SPFI {

export function graphSetup(settings: ITestingSettings): GraphFI {

const graph = graphfi().using(GraphDefault({
msal: {
config: settings.testing.graph.msal.init,
scopes: settings.testing.graph.msal.scopes,
},
})).using(
const graph = graphfi().using(
GraphDefault({
msal: {
config: settings.testing.graph.msal.init,
scopes: settings.testing.graph.msal.scopes,
},
}),
PnPLogging(LogLevel.Verbose),
DebugHeaders(),
function (instance: Queryable) {

instance.on.pre(async (url, init, result) => {
Expand Down
5 changes: 2 additions & 3 deletions debug/launch/sp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,20 @@ import { Logger, LogLevel } from "@pnp/logging";
import { spSetup } from "./setup.js";
import "@pnp/sp/webs";
import "@pnp/sp/lists";
import "@pnp/sp/items";

declare var process: { exit(code?: number): void };

export async function Example(settings: ITestingSettings) {

const sp = spSetup(settings);

const w = await sp.web();
const w = await sp.web.lists();

Logger.log({
data: w,
level: LogLevel.Info,
message: "Web Data",
});

process.exit(0);
}
3 changes: 3 additions & 0 deletions docs/graph/site-openextensions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Site Open Extensions

// TODO
37 changes: 37 additions & 0 deletions docs/queryable/behaviors.md
Original file line number Diff line number Diff line change
Expand Up @@ -491,3 +491,40 @@ setTimeout(() => {
// this is awaiting the results of the request
await p;
```

### DebugHeaders

Adds logging for the request id and timestamp of the request, helpful when contacting Microsoft Support. It works for both Graph and SP libraries.

```TypeScript
import { DebugHeaders } from "@pnp/queryable";
import { spfi } from "@pnp/sp";

const sp = spfi().using(DebugHeaders());

sp.some_action();

// output to log:
// Server Request Id: {guid}
// Server Date: {date}
```

You can also supply additional headers to log from the response:


```TypeScript
import { DebugHeaders } from "@pnp/queryable";
import { spfi } from "@pnp/sp";

const sp = spfi().using(DebugHeaders(["X-MyHeader", "client-request-id"]));

sp.some_action();

// output to log:
// Server Request Id: {guid}
// Server Date: {date}
// X-MyHeader: {value}
// client-request-id: {guid}
```


1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ nav:
- search: 'graph/search.md'
- shares: 'graph/shares.md'
- sites: 'graph/sites.md'
- 'site openextensions': 'graph/site-openextensions.md'
- subscriptions: 'graph/subscriptions.md'
- taxonomy: 'graph/taxonomy.md'
- teams: 'graph/teams.md'
Expand Down
3 changes: 1 addition & 2 deletions packages/core/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ export function combine(...paths: (string | null | undefined)[]): string {

return paths
.filter(path => !stringIsNullOrEmpty(path))
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
.map(path => path!.replace(/^[\\|/]/, "").replace(/[\\|/]$/, ""))
.map(path => path.replace(/^[\\|/]/, "").replace(/[\\|/]$/, ""))
.join("/")
.replace(/\\/g, "/");
}
Expand Down
4 changes: 2 additions & 2 deletions packages/graph/decorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ export function getById<R>(factory: (...args: any[]) => R) {
return function <T extends { new(...args: any[]): {} }>(target: T) {

return class extends target {
public getById(this: IGraphQueryable, id: string): R {
return factory(this, id);
public getById(this: IGraphQueryable, id: any): R {
return factory(this, `${id}`);
}
};
};
Expand Down
29 changes: 9 additions & 20 deletions packages/graph/graphqueryable.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isArray, objectDefinedNotNull } from "@pnp/core";
import { isArray } from "@pnp/core";
import { IInvokable, Queryable, queryableFactory, op, get, post, patch, del, put } from "@pnp/queryable";
import { ConsistencyLevel } from "./behaviors/consistency-level.js";
import { IPagedResult, Paged } from "./behaviors/paged.js";
Expand Down Expand Up @@ -80,17 +80,12 @@ export class _GraphQueryable<GetType = any> extends Queryable<GetType> {
*
* @param factory The contructor for the class to create
*/
protected getParent<T extends _GraphQueryable>(
factory: IGraphConstructor<T>,
base: GraphInit = this.parentUrl,
path?: string): T {
protected getParent<T extends IGraphQueryable>(
factory: IGraphInvokableFactory<any>,
path?: string,
base: string = this.parentUrl): T {

if (typeof base === "string") {
// we need to ensure the parent has observers, even if we are rebasing the url (#2435)
base = [this, base];
}

return new factory(base, path);
return factory([this, base], path);
}
}

Expand Down Expand Up @@ -169,13 +164,9 @@ export class _GraphCollection<GetType = any[]> extends _GraphQueryable<GetType>

const q = GraphCollection(this).using(Paged(), ConsistencyLevel());

const queryParams = ["$search", "$top", "$select", "$expand", "$filter", "$orderby"];

for (let i = 0; i < queryParams.length; i++) {
const param = this.query.get(queryParams[i]);
if (objectDefinedNotNull(param)) {
q.query.set(queryParams[i], param);
}
// Issue #3136, some APIs take other query params that need to persist through the paging, so we just include everything
for (const [key, value] of this.query) {
q.query.set(key, value);
}

return <AsyncIterator<GetType>>{
Expand All @@ -201,7 +192,6 @@ export class _GraphCollection<GetType = any[]> extends _GraphQueryable<GetType>
};
}
}

export interface IGraphCollection<GetType = any[]> extends _GraphCollection<GetType> { }
export const GraphCollection = graphInvokableFactory<IGraphCollection>(_GraphCollection);

Expand All @@ -210,7 +200,6 @@ export const GraphCollection = graphInvokableFactory<IGraphCollection>(_GraphCol
*
*/
export class _GraphInstance<GetType = any> extends _GraphQueryable<GetType> { }

export interface IGraphInstance<GetType = any> extends IInvokable, IGraphQueryable<GetType> { }
export const GraphInstance = graphInvokableFactory<IGraphInstance>(_GraphInstance);

Expand Down
12 changes: 9 additions & 3 deletions packages/graph/onenote/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,21 @@ export {
INotebook,
INotebooks,
IOneNote,
IPages,
IResources,
ISection,
ISections,
Notebook,
Notebooks,
OneNote,
Page,
Pages,
ICopyProps,
IOnenotePage,
IOnenotePages,
ISectionGroup,
ISectionGroups,
OnenotePage,
OnenotePages,
SectionGroup,
SectionGroups,
Resources,
Section,
Sections,
Expand Down
24 changes: 12 additions & 12 deletions packages/graph/onenote/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ export class _OneNote extends _GraphInstance<IOnenoteType> {
return Notebooks(this);
}

public get pages(): IPages {
return Pages(this);
public get pages(): IOnenotePages {
return OnenotePages(this);
}

public get resources(): IResources {
Expand Down Expand Up @@ -107,8 +107,8 @@ export const Notebooks = graphInvokableFactory<INotebooks>(_Notebooks);
*/
export class _Section extends _GraphInstance<IOnenoteSectionType> {

public get pages(): IPages {
return Pages(this);
public get pages(): IOnenotePages {
return OnenotePages(this);
}

/**
Expand Down Expand Up @@ -187,7 +187,7 @@ export const SectionGroups = graphInvokableFactory<ISectionGroups>(_SectionGroup
*
*/
@deleteable()
export class _Page extends _GraphInstance<IOnenotePageType> {
export class _OnenotePage extends _GraphInstance<IOnenotePageType> {
/**
* Copy page to section
* @param props of type ICopyPageProps. groupId (id of group to copy to. Use only when copying to M365 group), id of destination notebook
Expand All @@ -202,7 +202,7 @@ export class _Page extends _GraphInstance<IOnenotePageType> {
* @param includeIDs page html body
*/
public async content(includeIDs = false): Promise<string> {
return Page(this, `content?includeIDs=${includeIDs}`).using(TextParse())();
return OnenotePage(this, `content?includeIDs=${includeIDs}`).using(TextParse())();
}

/**
Expand All @@ -213,16 +213,16 @@ export class _Page extends _GraphInstance<IOnenotePageType> {
return graphPatch(GraphQueryable(this, "content"), body(props));
}
}
export interface IPage extends _Page, IDeleteable { }
export const Page = graphInvokableFactory<IPage>(_Page);
export interface IOnenotePage extends _OnenotePage, IDeleteable { }
export const OnenotePage = graphInvokableFactory<IOnenotePage>(_OnenotePage);

/**
* Describes a collection of page objects
*
*/
@defaultPath("pages")
@getById(Page)
export class _Pages extends _GraphCollection<IOnenotePageType[]> {
@getById(OnenotePage)
export class _OnenotePages extends _GraphCollection<IOnenotePageType[]> {
/**
* Create a new page as specified in the request body.
*
Expand All @@ -237,8 +237,8 @@ export class _Pages extends _GraphCollection<IOnenotePageType[]> {
return graphPost(q, { body: html });
}
}
export interface IPages extends _Pages, IGetById<IPage> { }
export const Pages = graphInvokableFactory<IPages>(_Pages);
export interface IOnenotePages extends _OnenotePages, IGetById<IOnenotePage> { }
export const OnenotePages = graphInvokableFactory<IOnenotePages>(_OnenotePages);

/**
* Describes a resources
Expand Down
9 changes: 9 additions & 0 deletions packages/graph/open-extensions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import "./site.js";

export {
IBaseExtensionData as IBaseOpenExtension,
IOpenExtension,
IOpenExtensions,
OpenExtension,
OpenExtensions,
} from "./types.js";
13 changes: 13 additions & 0 deletions packages/graph/open-extensions/site.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { addProp } from "@pnp/queryable";
import { _Site } from "../sites/types.js";
import { IOpenExtensions, OpenExtensions } from "./types.js";

declare module "../sites/types" {
interface _Site {
readonly extensions: IOpenExtensions;
}
interface ISite {
readonly extensions: IOpenExtensions;
}
}
addProp(_Site, "extensions", OpenExtensions);
40 changes: 40 additions & 0 deletions packages/graph/open-extensions/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { body } from "@pnp/queryable";
import { Extension as ExtensionType } from "@microsoft/microsoft-graph-types";
import { _GraphCollection, graphInvokableFactory, graphPatch, graphPost } from "../graphqueryable.js";
import { getById, IGetById, deleteable, IDeleteable, defaultPath } from "../decorators.js";

export interface IBaseExtensionData {
extensionName: string;
}

/**
* Open Extension
*/
@deleteable()
export class _OpenExtension extends _GraphCollection<ExtensionType> {

public update<T extends IBaseExtensionData>(extension: T): Promise<any> {
return graphPatch(this, body(extension));
}
}
export interface IOpenExtension extends _OpenExtension, IDeleteable { }
export const OpenExtension = graphInvokableFactory<IOpenExtension>(_OpenExtension);

/**
* Open Extensions
*/
@defaultPath("extensions")
@getById(OpenExtension)
export class _OpenExtensions extends _GraphCollection<ExtensionType> {

public create<T extends IBaseExtensionData>(extension: T): Promise<any> {

if (extension.extensionName.length > 30) {
throw Error("Extension id length should be less than or equal to 30 characters.");
}

return graphPost(this, body(extension));
}
}
export interface IOpenExtensions extends _OpenExtensions, IGetById<IOpenExtension> { }
export const OpenExtensions = graphInvokableFactory<IOpenExtensions>(_OpenExtensions);
Loading

0 comments on commit d4bb740

Please sign in to comment.