SharePoint Framework SPFx , no exported memeber SP, PnPJs - sharepoint

Below is my code:
import * as React from 'react';
import styles from './PnpfolderoperationsDemo.module.scss';
import { IPnpfolderoperationsDemoProps } from './IPnpfolderoperationsDemoProps';
import { escape } from '#microsoft/sp-lodash-subset';
import { PrimaryButton } from 'office-ui-fabric-react';
import { sp } from "#pnp/sp/presets/all";
export default class PnpfolderoperationsDemo extends React.Component<IPnpfolderoperationsDemoProps, {}> {
constructor(props){
super(props);
sp.setup({
spfxContext: this.context
});
}
public render(): React.ReactElement<IPnpfolderoperationsDemoProps> {
const {
description,
isDarkTheme,
environmentMessage,
hasTeamsContext,
userDisplayName
} = this.props;
Executed below command for packages
npm install #pnp/logging #pnp/common #pnp/odata #pnp/sp --save
Getting following error with pnpjs:
#Module '"#pnp/sp/presets/all"' has no exported member 'sp'.
Has anyone faced any similar situation?
Thanks

You may be using pnpjs v3.x Your code seems to be valid for v2.x, in v3.x there are changes (global "sp" object has been deprecated). Please check the transition guide, or use v2.x
https://pnp.github.io/pnpjs/transition-guide/
To install the previous version (v2.x) that is known to be compatible with the SPFx examples you seem to be using, try specifying the version explicitly:
npm install #pnp/logging#2.11.0 #pnp/common#2.11.0 #pnp/odata#2.11.0 #pnp/sp#2.11.0 --save

Related

Unable to override CartPageMetaResolver

I am trying to override the CartPageMetaResolver which looks like this
import { Injectable } from '#angular/core';
import { BreadcrumbMeta,
CmsService,
PageBreadcrumbResolver,
Priority,
TranslationService } from '#spartacus/core';
import { CartPageMetaResolver } from '#spartacus/core/src/cart/services/cart-page-meta.resolver';
import { combineLatest, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root',
})
export class NxsCartPageMetaResolver extends CartPageMetaResolver {}
While starting the server I am getting the following error
ERROR in ./src/app/features/nxs-cart/services/nxs-cart-page-meta.resolver.ts
Module not found: Error: Can't resolve '#spartacus/core/src/cart/services/cart-page-meta.resolver'
in 'D:\HYBRIS_SPARTACUS\SPARTACUS\nexus\js-storefront\mystore\src\app\features\nxs-cart\services'
what might be the issue ?
The CartPageMetaResolver is unfortunately not exported as part of the public API, it's a bug. We're fixing it, but you might want to unblock yourself by the following trick:
import { ɵct } from '#spartacus/core';
Note that the exact symbol for this class is different per release. This is why it's a temporary workaround, not something you want to keep. You can find the exact symbol in the node_modules/#spartacus/core/spartacus-core.d.ts.
We're fixing this for 3.0, but if you need a backport for 2.1, please let us know (we can continue the conversation in the ticket).

Git message type on library update

I make my own react boilerplate and come until updating packages. So I've update react across major version (v15x to v16x), and change my code on a module file called injectReducer. So what i've changed in injectReducer is from this:
static contextTypes = {
store: PropTypes.object.isRequired,
};
to this:
static contextType = ReactReduxContext;
Now I think this doesn't do any breaking changes on my boilerplate, because the use of the module still the same (backward compatible). But what about the package I've updated? Should any library updated across major is considered breaking changes? What about minor updates?
Here is my full code of injectReducer:
import React from 'react';
import { ReactReduxContext } from 'react-redux';
import hoistNonReactStatics from 'hoist-non-react-statics';
import getInjectors from './reducerInjectors';
export default ({ key, reducer }) => (WrappedComponent) => {
class ReducerInjector extends React.Component {
static WrappedComponent = WrappedComponent;
static displayName = `withReducer(${(WrappedComponent.displayName || WrappedComponent.name || 'Component')})`;
static contextType = ReactReduxContext;
injectors = getInjectors(this.context.store);
componentWillMount() {
const { injectReducer } = this.injectors;
injectReducer(key, reducer);
}
render() {
return <WrappedComponent {...this.props} />;
}
}
return hoistNonReactStatics(ReducerInjector, WrappedComponent);
};
But what about the package I've updated? Should any library updated across major is considered breaking changes?
That is the idea behing the major version in semver
when you make incompatible API changes
Except I would consider it does not involve just the API.
See as an example "Semantic Versioning, Go Modules, and Databases" (just to illustrate the kind of non-API change which would still warrant a major version bump)
Basically, if any client of your library has work to do in order to adapt to the new version... your change should be considered major.
If not: minor.

Create a custom typings file

I just created a published npm package for the first time, called "Foo". I am trying to consume it in a typescript project, but none of the tutorials about how to declare modules with custom typings, are clear to me. Here are the key parts of the npm package:
news.ts
import { tdsRequest } from "../common/request";
function articles(uri) {
return tdsRequest({ method: "GET" }, uri).then(returnData => console.log(returnData, "return data"));
}
export {
articles,
};
main.ts (main export)
import * as news from "./services/news";
export default {
news
};
in the typescript project that's consuming the npm package:
import { news } from "Foo";
and in the typings file ( Foo.d.ts ) I did:
declare module "Foo" {
export {
news: Object,
};
}
I get the following errors: cannot find module news and Cannot export 'Object'. Only local declarations can be exported from a module.
You are mixing default and named exports.
You can do default export style -
main.ts:
import * as news from "./services/news";
export default {
news
};
ts project import:
import foo from "Foo";
const {news} = foo;
foo.d.ts:
declare module "Foo" {
export default {
news: Object,
};
}
Or you can do named exports:
main.ts:
import * as news from "./services/news";
export {
news
};
ts project import:
import {news} from "Foo";
foo.d.ts:
declare module "Foo" {
export const news: Object;
}
But more importantly, you should add declaration: true to your compilerOptions in tsconfig.json in your npm library.
This will generate the d.ts file for you and will save you lots of work. Then, you need to add in package.json a filed called types that will point to the main.d.ts file that will be generated for you. This will allow any project using your library + typescript to use the generated types automatically.

Get translation text without using FormattedMessage and React ContextTypes

I'm looking for a way to get translation text without using FormattedMessage. Until now, I've found only this solution that provides to use ContextTypes an React's EXPERIMENTAL feature. Are there others ways to accomplish this (or other library/npm module)?
I prefer using context, but react-intl does also provide a higher order component injectIntl you can use instead. This will pass a prop intl that has all the imperative formatting functions.
import React from "react";
import {injectIntl, intlShape} from "react-intl";
class MyComponent extends React.Component {
static propTypes = {
intl: intlShape.isRequired
}
render() {
return <p>{this.props.intl.formatDate(new Date())}</p>;
}
}
export default injectIntl(Component);

Typescript IOC in case of node

I am wondering how would you use typescript IOC specifically node app.
In case of external module-based architecture there is no any classes in the app. Just pure modules because my app heavily depends on node_modules.
How would I integrate IOC solution in such case? Any thoughts?
Here is my specific case I want to use IOC for:
I have mongoose model:
interface IStuffModel extends IStuff, mongoose.Document { }
var Stuff= mongoose.model<IStuffModel>('Stuff', Schemas.stuffSchema);
export = Stuff;
And related fake class:
export class Stuff implements IStuff {
//do stuff
}
How would I integrate IOC solution in such case
Here is a very popular library that I recommend : https://github.com/inversify/InversifyJS
External modules
Using external modules doesn't change the code at all. Instead of
kernel.bind(new TypeBinding<FooBarInterface>("FooBarInterface", FooBar));
Production
You just have
import {ProdFooBar} from "./prodFooBar";
kernel.bind(new TypeBinding<FooBarInterface>("FooBarInterface", ProdFooBar));
Test
import {MockFooBar} from "./mockFooBar";
kernel.bind(new TypeBinding<FooBarInterface>("FooBarInterface", MockFooBar));
As Basarat indicated in his answer, I have developed an IoC container called InversifyJS with advanced dependency injection features like contextual bindings.
You need to follow 3 basic steps to use it:
1. Add annotations
The annotation API is based on Angular 2.0:
import { injectable, inject } from "inversify";
#injectable()
class Katana implements IKatana {
public hit() {
return "cut!";
}
}
#injectable()
class Shuriken implements IShuriken {
public throw() {
return "hit!";
}
}
#injectable()
class Ninja implements INinja {
private _katana: IKatana;
private _shuriken: IShuriken;
public constructor(
#inject("IKatana") katana: IKatana,
#inject("IShuriken") shuriken: IShuriken
) {
this._katana = katana;
this._shuriken = shuriken;
}
public fight() { return this._katana.hit(); };
public sneak() { return this._shuriken.throw(); };
}
2. Declare bindings
The binding API is based on Ninject:
import { Kernel } from "inversify";
import { Ninja } from "./entities/ninja";
import { Katana } from "./entities/katana";
import { Shuriken} from "./entities/shuriken";
var kernel = new Kernel();
kernel.bind<INinja>("INinja").to(Ninja);
kernel.bind<IKatana>("IKatana").to(Katana);
kernel.bind<IShuriken>("IShuriken").to(Shuriken);
export default kernel;
3. Resolve dependencies
The resolution API is based on Ninject:
import kernel = from "./inversify.config";
var ninja = kernel.get<INinja>("INinja");
expect(ninja.fight()).eql("cut!"); // true
expect(ninja.sneak()).eql("hit!"); // true
The latest release (2.0.0) supports many use cases:
Kernel modules
Kernel middleware
Use classes, string literals or Symbols as dependency identifiers
Injection of constant values
Injection of class constructors
Injection of factories
Auto factory
Injection of providers (async factory)
Activation handlers (used to inject proxies)
Multi injections
Tagged bindings
Custom tag decorators
Named bindings
Contextual bindings
Friendly exceptions (e.g. Circular dependencies)
You can learn more about it at https://github.com/inversify/InversifyJS
In the particular context of Node.js there is a hapi.js example that uses InversifyJS.

Resources