I have recently started to make a plugin in NativeScript - following the documention. And I made some successfull runs with npm run demo.ios in the src folder.
However when starting to build the actual plugin I intended on - I am encountering the following error:
file:///node_modules/tns-core-modules/ui/builder/builder.js:179:0 JS ERROR Error: Building UI from XML. @app-root.xml:1:1 undefined is not an object (evaluating 'b.prototype')
I have set up an extension method onto ViewBase in my myplugin.common.ts file that I attempt to call from the demo application
The problem could lie in the index.d.ts I believe. According the docs the myplugin.ios.d.ts and myplugin.android.d.ts files should be copied in there or defined manually. I am attempting to copy the myplugin.common.d.ts file content in there instead. Is that valid?
I have also noticed two runs seem to be necceseray - since the first run generates the ...d.ts. Of which content then has to copied into index.d.ts.
some code...
myplugin.common.ts
declare module "tns-core-modules/ui/core/view-base/view-base" {
interface ViewBase {
myExenstionMethod(myNumber: number): void;
}
}
ViewBase.prototype.myExenstionMethod = function(myNumber: number) {
console.log("myNumber: " + myNumber);
}
and index.d.ts (copied from myplugin.common.d.ts):
declare module "tns-core-modules/ui/core/view-base/view-base" {
interface ViewBase {
myExenstionMethod(myNumber: number): void;
}
}
It is shown in the demo project:
And the error comes from simply importing the extension method from the plugin in my demo project:
import "nativescript-myplugin";
Note
I created a new plugin project - only adding the extension method and it worked. So there was something else in the original plugin project that caused the error. Adding declare module in index.d.ts was not needed.
Hitting it again
with the same error as before - when instantiating myplugin.ios.ts/myplugin.android.ts - myplugin class - from inside myplugin.common.ts. I initially thought about creating a platform specific singleton instance to interact with in .common.ts - but that does not seem to work?
import { Gestures as iOSGestures} from "./gestures.ios";
import {Gestures as AndroidGestures} from "./gestures.android";
export abstract class Common extends Observable {
private static _instance = null;
static instance(os: string): Common {
if(Common._instance == null) {
/* crash from instantiating iOSGestures or AndroidGestures */
this._instance = os == "iOS" ? new iOSGestures() : new AndroidGestures();
}
return Common._instance;
}
abstract _attach(viewBase: ViewBase, gesture: string): void;
}
What is strange is that that particular code is never called from anywhere yet. And commenting out that line I can create that error by simply having dead code containing the instantiation:
// still inside .common.ts
import { Gestures } from "./gestures.android";
const object = {
methodInFile() {
const g = new Gestures() // <--
}
}
Here is the android.ts:
export class Gestures extends Common {
_attach(viewBase: ViewBase, gesture: string): void {
console.log("_attach android");
if(gesture == touch.down) {
}
}
}
It could be some sort of conflict with the index.d.ts?:
import { Common } from './gestures.common';
export declare class Gestures extends Common {
// define your typings manually
// or..
// take the ios or android .d.ts files and copy/paste them here
}
This my first time attempting to build a plugin NativeScript - so I might be setting things completely wrong. I hope to provide my plugin as an extension method on ViewBase though - and the extension method defined in common.ts is called successfully.
// inside common.ts
export class Gestures extends Common {
_attach(): void {
console.log("_attach ios");
}
}
const object = {
methodInFile() {
const g = new Gestures() // <--
}
}
... works.
But when the class is imported from another file, having new Gestures() - causes the crash as mentioned. It neither works creating a new file - ios.common.ts. So it could be that npm run demo.ios is generating faulty js files on build? I also removed the content of index.d.ts completely - so it can't involved causing the error.
Making the common.ts an interface - that gets implemented in .ios.ts and android.ts. I encountered a new error;
file:///app/home/home-page.ts:17:27 JS ERROR TypeError: page.addGestureHandler is not a function. (In 'page.addGestureHandler("hello")', 'page.addGestureHandler' is undefined)
My conclusion so far is that I can't have Common as an abstract class or interface - and instantiate ios.ts and android.ts as singletons. The class extending abstract Common - or implementing interface Common - must be in the same file as (common.ts). This can be related to the fact I am using an extension method as entry point into the plugin.

*.d.ts) are just for the sake of IntelliSense support with your IDE. Hence there is nothing called valid or invalid as long you export right definitions you want to expose. Most plugins will just exportindex.d.tsthat will usually expose everything from*-common.ts.ViewBasethen your declarations doesn't look quite right to me. For example you may take a look at camara-plus plugin, the base class is extended to add new methods.npm run demo.ios/npm run demo.androidfrom generatingd.ts,.jsand.js.mapfiles?