ionic capacitor-community/sqlite problems - sqlite

Ionic 6 app using capacitor-community/sqlite#3.4.2-3.
Creating connection with
await CapacitorSQLite.createConnection({database:DBNAME,version:DB_VERSION,encrypted:false,mode:"secret"});
I get the following error:
"While parsing a protocol message, the input ended unexpectedly in the middle of a field. This could mean either that the input has been truncated or that an embedded message misreported its own length."
Using 3.4.0 version with same code, the error is:
"Error: Query: Attempt to invoke virtual method 'com.getcapacitor.JSArray com.getcapacitor.community.database.sqlite.CapacitorSQLite.query(java.lang.String, java.lang.String, com.getcapacitor.JSArray)' on a null object reference"
any ideas?
thanks

I am facing 2 million issues but I think you have put a superfluous curly bracket {} in your constructor call and you are calling the object directly.
const db = await this.sqlite.createConnection(this.dbname, true, 'encryption', 1, false); :
where this.sqlite is initiated in the constructor to a service (angular) with a call to initializePlugin
initializePlugin(): Promise<boolean> {
return new Promise(resolve => {
this.platform = Capacitor.getPlatform();
if (this.platform === 'ios' || this.platform === 'android') {
this.native = true;
}
this.sqlite = new SQLiteConnection(CapacitorSQLite);
resolve(true);
});
}
You may also need the following in your import statement:
import { Injectable } from '#angular/core';
import { Capacitor } from '#capacitor/core';
import {
CapacitorSQLite, SQLiteConnection,
capEchoResult
} from '#capacitor-community/sqlite';
import { Platform } from '#ionic/angular';
At least, it works for me.

Related

How To Unit Test NextJS API Route That Uses Repository Pattern?

I am new prisma / nextjs user and I am trying to understand how to unit test an API route that uses prisma. I have read the unit testing guide.
I like the dependency injection approach and have started trying to implement it. However I am struggling with the following development issue. Can anybody help?
With the dependency injection approach the unit testing guide explains how to setup the mock context and use this in the data access layer. Does anyone have any examples of how and where the real context could be initialised and used with an API route that uses a repository pattern? Is it possible to expand the next.js api handler with middleware to include the context to facilitate testing?
import type { NextApiRequest, NextApiResponse } from 'next'
import { PublishRepository } from '../../../repository'
// PUT /api/publish/:id
export default async function handle(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method == 'PUT') {
const postId = req.query.id;
let repo = new PublishRepository( // where does the live context come from and how is it initialised??? )
const post = repo.set_published(postId)
res.json(post);
}
}
Repository - Initialised using Context instance - How is this initialise for development and how is it mocked?
import { Post, PrismaClient } from "#prisma/client"
import { Context } from "../context"
import prisma from "lib/prisma"
export class PublishRepository {
private prisma: PrismaClient
constructor(context: Context) {
this.prisma = context.prisma
}
async set_published(post_id: string | string[]): Promise<Post> {
return await prisma.post.update({
where: { id: Number(post_id) },
data: { published: true },
});
}
}

Angular2 ( 2.2.1 ) Http post request progress bar [duplicate]

Is there currently a way within Angular 2 to retrieve the progress (i.e. percentage done) of an ajax call, using the angular2/http module?
I use the following code to make my HTTP calls:
let body = JSON.stringify(params);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
this.http.post(url, body, options)
.timeout(10000, new Error('Timeout exceeded during login'))
.toPromise()
.then((res) => {
...
}).catch((err) => {
...
});
The goal is to write a synchronisation system. The post will return a lot of data, and I want to give the user an indication on how long the syncing will take.
Currently (from v. 4.3.0, when using new HttpClient from #ngular/common/http) Angular provides listening to progress out of the box. You just need to create HTTPRequest object as below:
import { HttpRequest } from '#angular/common/http';
...
const req = new HttpRequest('POST', '/upload/file', file, {
reportProgress: true,
});
And when you subscribe to to request you will get subscription called on every progress event:
http.request(req).subscribe(event => {
// Via this API, you get access to the raw event stream.
// Look for upload progress events.
if (event.type === HttpEventType.UploadProgress) {
// This is an upload progress event. Compute and show the % done:
const percentDone = Math.round(100 * event.loaded / event.total);
console.log(`File is ${percentDone}% uploaded.`);
} else if (event instanceof HttpResponse) {
console.log('File is completely uploaded!');
}
});
More info here.
You could leverage the onprogress event provided by XHR (see this plunkr: http://plnkr.co/edit/8MDO2GsCGiOJd2y2XbQk?p=preview).
This allows to get hints about the progress of the download. This isn't supported out of the box by Angular2 but you can plug it by extended the BrowserXhr class:
#Injectable()
export class CustomBrowserXhr extends BrowserXhr {
constructor(private service:ProgressService) {}
build(): any {
let xhr = super.build();
xhr.onprogress = (event) => {
service.progressEventObservable.next(event);
};
return <any>(xhr);
}
}
and override the BrowserXhr provider with the extended:
bootstrap(AppComponent, [
HTTP_PROVIDERS,
provide(BrowserXhr, { useClass: CustomBrowserXhr })
]);
See this question for more details:
Angular2 / RxJS - updating variable after getting data from Http observable
When you make http cals in angular2, it returns an Observable of type Response, this response is created inside class called XHRConnection where all the magic happens.
The XHRConnection builds the response by listening to XMLHttpRequest's load event, this means it will return one response at the end of the request.
Now to be able to alter this behavior we need to make our connection class listen to the progress event.
So we need to create custom Connection class, to handle the response as we see fit.
I did it this way,
Take note that my php API returns multi response in a single request and this responses are plain strings.
my_backend.ts
import {Injectable} from "angular2/core";
import {Observable} from "rxjs/Observable";
import {Observer} from "rxjs/Observer";
import {Connection,ConnectionBackend} from "angular2/src/http/interfaces";
import {ReadyState, RequestMethod, ResponseType} from "angular2/src/http/enums";
import {ResponseOptions} from "angular2/src/http/base_response_options";
import {Request} from "angular2/src/http/static_request";
import {Response} from "angular2/src/http/static_response";
import {BrowserXhr} from "angular2/src/http/backends/browser_xhr";
import {Headers} from 'angular2/src/http/headers';
import {isPresent} from 'angular2/src/facade/lang';
import {getResponseURL, isSuccess} from "angular2/src/http/http_utils"
export class MyConnection implements Connection {
readyState: ReadyState;
request: Request;
response: Observable<Response>;
constructor(req: Request, browserXHR: BrowserXhr, baseResponseOptions?: ResponseOptions) {
this.request = req;
this.response = new Observable<Response>((responseObserver: Observer<Response>) => {
let _xhr: XMLHttpRequest = browserXHR.build();
_xhr.open(RequestMethod[req.method].toUpperCase(), req.url);
// save the responses in array
var buffer :string[] = [];
// load event handler
let onLoad = () => {
let body = isPresent(_xhr.response) ? _xhr.response : _xhr.responseText;
//_xhr.respons 1 = "Loading data!"
//_xhr.respons 2 = "Loading data!Ready To Receive Orders."
// we need to fix this proble
// check if the current response text contains the previous then subtract
// NOTE: I think there is better approach to solve this problem.
buffer.push(body);
if(buffer.length>1){
body = buffer[buffer.length-1].replace(buffer[buffer.length-2],'');
}
let headers = Headers.fromResponseHeaderString(_xhr.getAllResponseHeaders());
let url = getResponseURL(_xhr);
let status: number = _xhr.status === 1223 ? 204 : _xhr.status;
let state:number = _xhr.readyState;
if (status === 0) {
status = body ? 200 : 0;
}
var responseOptions = new ResponseOptions({ body, status, headers, url });
if (isPresent(baseResponseOptions)) {
responseOptions = baseResponseOptions.merge(responseOptions);
}
let response = new Response(responseOptions);
//check for the state if not 4 then don't complete the observer
if(state !== 4){
//this will return stream of responses
responseObserver.next(response);
return;
}
else{
responseObserver.complete();
return;
}
responseObserver.error(response);
};
// error event handler
let onError = (err: any) => {
var responseOptions = new ResponseOptions({ body: err, type: ResponseType.Error });
if (isPresent(baseResponseOptions)) {
responseOptions = baseResponseOptions.merge(responseOptions);
}
responseObserver.error(new Response(responseOptions));
};
if (isPresent(req.headers)) {
req.headers.forEach((values, name) => _xhr.setRequestHeader(name, values.join(',')));
}
_xhr.addEventListener('progress', onLoad);
_xhr.addEventListener('load', onLoad);
_xhr.addEventListener('error', onError);
_xhr.send(this.request.text());
return () => {
_xhr.removeEventListener('progress', onLoad);
_xhr.removeEventListener('load', onLoad);
_xhr.removeEventListener('error', onError);
_xhr.abort();
};
});
}
}
#Injectable()
export class MyBackend implements ConnectionBackend {
constructor(private _browserXHR: BrowserXhr, private _baseResponseOptions: ResponseOptions) {}
createConnection(request: Request):MyConnection {
return new MyConnection(request, this._browserXHR, this._baseResponseOptions);
}
}
And in the app.component.ts
import {Component, provide} from 'angular2/core';
import {HTTP_PROVIDERS,XHRBackend} from 'angular2/http';
import {MyBackend} from './my_backend';
#Component({
selector: 'my-app',
providers: [
HTTP_PROVIDERS,
MyBackend,
provide(XHRBackend, {useExisting:MyBackend})
]
.
.
.
Now calling http.get will return a steam of responses.
#Bartek Chichoki's answer is correct but it was not working for my case.
Adding observe: 'events' did the trick for me
const req = new HttpRequest('POST', '/upload/file', file, {
reportProgress: true,
observe: 'events'
});
Hope it helps
I strongly recomend using this
https://www.npmjs.com/package/angular-progress-http
otherwise messing around with xhr will make you miss sessions cookies and other stuffs
besides it'll be more portable and way easier to implement

How do I defer loading a component until my signalr service is initialized?

I have the following types:
DataService - Gets data from the server using signalr hub.
AppComponent - which is the entry point for my main application
The data service constructor is as follows.
constructor(private http: Http) {
var hub = $.connection.spwHub;
hub.client.loadEmployees = this.loadEmployees;
$.connection.hub.start().done(() => {
...
});
}
My AppComponent is as follows:
constructor(service: DataService) {
this.company = service.getCompany();
service.getEmployees().then(employees => this.employees = employees);
this.departments = service.getDepartments();
}
I get the following error of course because the hub async call has not returned before the hub connection is made.
EXCEPTION: Error in ./AppComponent class AppComponent_Host - inline template:0:0 caused by: SignalR: Connection has not been fully initialized. Use .start().done() or .start().fail() to run logic after the connection has started.
What is the best way to deal with this issue in AngularJs2?
You can use the APP_INITIALIZER hook to perform logic, get something prepped, whatever, that you need before the rest of the application runs.
In your app.module.ts (or whatever your main module is):
import { APP_INITIALIZER, NgModule } from "#angular/core";
export function init_app(employeeService: EmployeeService) {
return () => employeeService.getEmployees();
}
#NgModule({
<...>
providers: [EmployeeService, {
provide: APP_INITIALIZER,
useFactory: init_app,
deps: [ EmployeeService ],
multi: true
}]
})
export class AppModule { }
The service is returning a Promise which will be automatically handled:
getEmployees() {
return <...function stuff ...>
.toPromise();
}
And here's the github issue where this is documented (no doc on the angular.io site yet): https://github.com/angular/angular/issues/9047
After searching and finding nothing I gave the idea that components that don't need to be loaded should probably be deferred by default. This means that the answer is a no-brainer.
// start.component.ts
constructor() {
// Start the connection
var hub = $.connection.spwHub;
$.connection.hub.start().done(() => {
// This loads the next component and runs the constructor
this.initialized = true;
});
}
// start.component.html
<div *ngIf="initialized">
<main-component></main-component>
<div>
// This type is lazy loaded as soon as the initialized equals true.
// main.component.ts
constructor(employeeService: EmployeeService) {
// Finally, load the needed data.
this.employees = employeeService.getEmployees();
}

Aspnet server rendering debugging

I have a react-redux app running on aspnet core, with server side rendering using aspnet prerendering.
Lets say i make a programming error, where in child component I try to access a undefined prop because of a stupid typo.
import {Child} from './child'
export class Parent extends React.Component {
render () {
const someProp = {
something: "something"
};
return <Child someProp={someProp} />;
}
}
export class Child extends React.Component {
render() {
return <div>this.props.someprop.something</div>;
//typo: should be someProp instead of someprop
}
Without server rendering I would have got an error similar to this: cannot access something of undefined at line x:yy
But with serverrendering i get a:
An unhandled exception occurred while processing the request.
Exception: Call to Node module failed with error: Prerendering timed out after 30000ms because the boot function in 'ClientApp/src/boot-server' returned a promise that did not resolve or reject. Make sure that your boot function always resolves or rejects its promise. You can change the timeout value using the 'asp-prerender-timeout' tag helper.
this makes debugging quite hard, when you dont get any feedback on what went wrong.
Any one knows how to setup a reject if something fails ? or is it even possible to debug a server side rendered code ?
here is my boot-server file, tell me if you need some more files.
import * as React from 'react';
import { Provider } from 'react-redux';
import { renderToString } from 'react-dom/server';
import configureStore from './store/configureStore';
import {getFormById} from './actions/getFormActions';
import {updateUserLocale} from './actions/userLocaleActions';
import FormResponder from './components/mainComponents/formResponder';
export default function renderApp (params) {
return new Promise((resolve, reject) => {
const store = configureStore();
store.dispatch(getFormById(params.data.id, params.data.config, params.data.authenticationToken));
store.dispatch(updateUserLocale(params.data.userLocale));
const app = (
<Provider store={ store }>
<FormResponder />
</Provider>
);
// Perform an initial render that will cause any async tasks (e.g., data access) to begin
renderToString(app);
// Once the tasks are done, we can perform the final render
// We also send the redux store state, so the client can continue execution where the server left off
params.domainTasks.then(() => {
resolve({
html: renderToString(app),
globals: {
initialReduxState: store.getState(),
authenticationToken: params.data.authenticationToken,
config: params.data.config
}
});
}, reject); // Also propagate any errors back into the host application
});
}
I have had similar experience working with Visual Studio 2017. I eventually realized that the diagnostic information for the original error(s) was actually in the Output window.
I have done som research and have come to the conclusion that is not possible for the time beeing to debug the initial server rendered code.
what i have done instead is to implement logic, so that i can disable server rendering.
this is how it looks like:
public async Task<IActionResult> Index(string id, string userLocale = "en", bool server = true)
{
Guid positionId;
if (!Guid.TryParse(id, out positionId))
{
throw new Exception("Invalid position id");
}
var token = await _apiClient.GetToken();
var formData = new ApplicationFormViewModel()
{
Id = positionId,
UserLocale = userLocale,
AuthenticationToken = token.AccessToken,
Server = server
};
return View(formData);
}
view.cshtml:
#{if (#Model.Server) {
<div
class="container"
id="react-app"
asp-prerender-module="ClientApp/src/boot-server"
asp-prerender-data="new {
Id = #Model.Id,
UserLocale = #Model.UserLocale,
AuthenticationToken = #Model.AuthenticationToken,
Config = new {
ApplicationPostUrl = #Url.Action("SaveApplication"),
AttachmentPostUrl = #Url.Action("UploadAttachment"),
FormGetUrl = #Url.Action("GetForm")
}
}"
asp-prerender-webpack-config="webpack.config.js" >
Loading...
</div>
}
else {
<script>
var id= '#Model.Id';
var config= {
applicationPostUrl: '#Url.Action("SaveApplication")',
attachmentPostUrl: '#Url.Action("UploadAttachment")',
formGetUrl: '#Url.Action("GetForm")'
};
var userLocale='#Model.UserLocale';
var authenticationToken='#Model.AuthenticationToken';
var server = false;
</script>
<div class="container" id="react-app">loading</div>
}
}
#section scripts {
<script src="~/dist/main.js" asp-append-version="true"></script>
}
boot-server.jsx:
export default function renderApp (params) {
return new Promise((resolve, reject) => {
const store = configureStore();
store.dispatch(getFormById(params.data.id, params.data.config, params.data.authenticationToken));
store.dispatch(updateUserLocale(params.data.userLocale));
const app = (
<Provider store={ store }>
<FormResponder />
</Provider>
);
// Perform an initial render that will cause any async tasks (e.g., data access) to begin
renderToString(app);
// Once the tasks are done, we can perform the final render
// We also send the redux store state, so the client can continue execution where the server left off
params.domainTasks.then(() => {
resolve({
html: renderToString(app),
globals: {
initialReduxState: store.getState(),
authenticationToken: params.data.authenticationToken,
config: params.data.config,
server: true
}
});
}, reject); // Also propagate any errors back into the host application
});
}
boot-client.jsx:
// Grab the state from a global injected into server-generated HTML
const {id, initialReduxState, authenticationToken, config, server, userLocale } = window;
if (server) {
// Get the application-wide store instance, prepopulating with state from the server where available.
const store = configureStore(initialReduxState);
// This code starts up the React app when it runs in a browser.
ReactDOM.render(
<Provider store={ store }>
<FormResponder authenticationToken={authenticationToken} config={config} />
</Provider>,
document.getElementById('react-app')
);
}
else {
const store = configureStore();
store.dispatch(getFormById(id, config, authenticationToken));
store.dispatch(updateUserLocale(userLocale));
render(
<Provider store ={store}>
<FormResponder authenticationToken={authenticationToken} config={config} />
</Provider>,
document.getElementById('react-app')
); // Take our FormBuilder component and attach it with DOM element "app"
}
so now i can simply turn of server rendering by adding a ?server=false at the end of the url, and start debugging :)
Found a solution that works for me:
I inserted a try/catch on final renderToString.
where in catch i send a dispatch with the error.
updated boot-server.jsx
params.domainTasks.then(() => {
let html;
try {
html = renderToString(app);
}
catch (err) {
store.dispatch(loadFormFailed( {message: err.toString() } ));
}
resolve({
html: html,
globals: {
initialReduxState: store.getState(),
authenticationToken: params.data.authenticationToken,
config: params.data.config,
disableReactServerRendring: false
}
});
}, reject);
// Also propagate any errors back into the host application
});

How to make an API call in Angular 2?

There are lots of resources out there already but I haven't been able to find one that works for one reason or another. Take a generic example: I want to get the response from http://swapi.co/api/people, which will be a list of people from Star Wars.
import {Injectable } from '#angular/core';
import {Http, Response} from '#angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
#Injectable()
export class OombaDataService {
constructor(private http: Http) {}
private usersUrl = 'http://swapi.co/api/people/';
getData() {
return this.http.get(this.usersUrl)
.map(this.extractData)
}
private extractData(res: Response) {
let body = res.json();
return body.data || { };
}
private handleError (error: any) {
// In a real world app, we might use a remote logging infrastructure
// We'd also dig deeper into the error to get a better message
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg); // log to console instead
return Observable.throw(errMsg);
}
}
A lot of this should be correct since it's based on Angular's own tutorial on the matter. But for whatever reason, when I call it in my components, it just returns an observable object without the JSON data. What am I missing?
At this method:
private extractData(res: Response) {
let body = res.json();
return body.data || { };
}
At the first line, you parse the result of the API call as JSON into a JavaScript object.
Then you return the property data of that object, if it exists. If it doesn't exist, you return an empty object ({ }).
The thing is that the API at http://swapi.co/api/people/ does not bring a response that contains a data property, which means that the extractData() method is always returning an observable of an empty object ({ }).
Besides that, the getData() really returns an Observable, so to get its value, you must subscribe to it, such as:
#Component({
...
providers: [OombaDataService]
})
export class SomeComponent {
constructor(oombaDataService: OombaDataService) {
oombaDataService.getData().subscribe(
x => {
console.log("VALUE RECEIVED: ",x);
},
x => {
console.log("ERROR: ",x);
},
() => {
console.log("Completed");
}
);
}
}
And, since, as said, that API's response does not have any .data property in it, the extractData() should really be (at least until you figure out what you want):
private extractData(res: Response) {
return res.json();
}
That should get things working. Here's a working plunker.

Resources