Sveltekit development with workers KV -- hot reloading - cloudflare

Is it possible to use CloudFlare's Workers KV when developing a Svelte/kit application?
It is possible to build the app then run wrangler dev when using the CloudFlare Workers adapter:
npm build
wrangler dev
However, I haven't gotten hot module reloading working:
npm dev & wrangler dev

As far as I know, there's no way to emulate Workers KV locally. However, I setup a local Redis instance as a substitute.
Then, I created some wrapper functions for the KV store. In development, it talks to Redis, and in production it talks to Workers KV. For instance, here's the wrapper function for get.
import { dev } from '$app/env'
import redis from 'redis'
const client = redis.createClient()
const get = promisify(client.get).bind(client)
export const getKvValue = async (key: string): Promise<string | null> => {
return dev ? await get(key) : await KV.get(key)
}
Update: You can actually make things much simpler by just using an object in JavaScript—no need to download and run a Redis binary. Just make sure to JSON.stringify the values before setting them.
import { dev } from '$app/env'
const devKvStore = {}
const devGetKvValue = (key: string) => {
return new Promise((resolve) => {
resolve(devKvStore[key] ?? null)
})
}
const devSetKvValue = (key: string, value: unknown) => {
return new Promise((resolve) => {
devKvStore[key] = JSON.stringify(value)
resolve()
})
}
export const getKvValue = async (key: string): Promise<string | null> => {
return dev ? await devGetKvValue(key) : await KV.get(key)
}
export const setKvValue = async (key: string, value: unknown): Promise<void> => {
return dev ? await devSetKvValue(key, value) : await KV.put(key, value)
}

Related

Duplicate identifier 'alpha'.deno-ts(2300) Unexpected keyword or identifier

I am trying to use Alpha Vantage NPM package inside my Deno application. I tried to use SkyPack version of it. But it gives me the following error:
Duplicate identifier 'alpha'.deno-ts(2300)
Unexpected keyword or identifier.
This is the code I am using:
import alphavantageTs from 'https://cdn.skypack.dev/alphavantage-ts';
export class StockTimeSeries{
alpha = new alphavantageTs ("ASLDVIWXGEWFWNZG");
alpha.stocks.intraday("msft").then((data: any) => {
console.log(data);
});
alpha.stocks.batch(["msft", "aapl"]).then((data: any) => {
console.log(data);
});
alpha.forex.rate("btc", "usd").then((data: any) => {
console.log(data);
});
alpha.crypto.intraday("btc", "usd").then((data: any) => {
console.log(data);
});
alpha.technicals.sma("msft", "daily", 60, "close").then((data: any) => {
console.log(data);
});
alpha.sectors.performance().then((data: any) => {
console.log(data);
});
}
It looks like SkyPack is responding with a 401 for one of the sub-dependencies for that module. I'm also not even sure it's compatible with Deno.
That said, here's the repo source for the module, and here's the documentation for the API. It looks like it's just a simple REST API which discriminates requests by query parameters, so you can make your own Deno client without too much effort using that module as a template. I'll give you some starter code:
TS Playground
export type Params = NonNullable<ConstructorParameters<typeof URLSearchParams>[0]>;
class AlphaVantageNS { constructor (protected readonly api: AlaphaVantage) {} }
class Forex extends AlphaVantageNS {
rate (from_currency: string, to_currency: string) {
return this.api.query({
function: 'CURRENCY_EXCHANGE_RATE',
from_currency,
to_currency,
});
}
}
export class AlaphaVantage {
#token: string;
constructor (token: string) {
this.#token = token;
}
async query <Result = any>(params: Params): Promise<Result> {
const url = new URL('https://www.alphavantage.co/query');
const usp = new URLSearchParams(params);
usp.set('apikey', this.#token);
url.search = usp.toString();
const request = new Request(url.href);
const response = await fetch(request);
if (!response.ok) throw new Error('Response not OK');
return response.json();
}
forex = new Forex(this);
}
// Use:
const YOUR_API_KEY = 'demo';
const alpha = new AlaphaVantage(YOUR_API_KEY);
alpha.forex.rate('BTC', 'USD').then(data => console.log(data));

How do i install spectron and start scripting on it?

Got a recent Requirement, where i need to do Test Automation of Backend Node js application using the spectron. I would like to know what are programming skills required to approach the same
Find the Spectron documentation at https://electronjs.org/spectron
Installation
npm install --save-dev spectron
Sample test file looks like this
const Application = require('spectron').Application
const assert = require('assert')
const electronPath = require('electron')
const path = require('path')
describe('Application launch', function () {
this.timeout(10000)
beforeEach(function () {
this.app = new Application({
path: electronPath,
args: [path.join(__dirname, '..')]
})
return this.app.start()
})
afterEach(function () {
if (this.app && this.app.isRunning()) {
return this.app.stop()
}
})
it('shows an initial window', function () {
return this.app.client.getWindowCount().then(function (count) {
assert.equal(count, 1)
})
})
})
Spectron can work with any test framework. I prefer using mocha.
Clone this project for more info https://github.com/electron/spectron

What is the best approach to test a HapiJS plugin, with Lab?

What is the best way to test a HapiJS plugin, for example one plugin that add routes and handlers.
Since I have to create an instance of Hapi.Server to run the plugins, should I define all the tests from the app's root, for all the plugins ?
or
should I manage to get THE instance of Hapi.Server in my plugin's local tests ?
If I go for the second option, my server will have registered all the plugins, including those that the plugin to be tested doesn't depends on.
What is the best way to approach this ?
Thanks in advance.
If you're using Glue (and I highly recommend it), you can create a manifest variable for each test (or group of tests) you want to execute. The manifest only needs to include plugins required for that test to execute properly.
And expose some sort of init function to actually start your server. Small example:
import Lab = require("lab");
import Code = require('code');
import Path = require('path');
import Server = require('../path/to/init/server');
export const lab = Lab.script();
const it = lab.it;
const describe = lab.describe;
const config = {...};
const internals = {
manifest: {
connections: [
{
host: 'localhost',
port: 0
}
],
registrations: [
{
plugin: {
register: '../http_routes',
options: config
}
},
{
plugin: {
register: '../business_plugin',
options: config
}
}
]
},
composeOptions: {
relativeTo: 'some_path'
}
};
describe('business plugin', function () {
it('should do some business', function (done) {
Server.init(internals.manifest, internals.composeOptions, function (err, server) {
// run your tests here
});
});
});
init function:
export const init = function (manifest: any, composeOptions: any, next: (err?: any, server?: Hapi.Server) => void) {
Glue.compose(manifest, composeOptions, function (err: any, server: Hapi.Server) {
if (err) {
return next(err);
}
server.start(function (err: any) {
return next(err, server);
});
});
};

React Native - How to see what's stored in AsyncStorage?

I save some items to AsyncStorage in React Native and I am using chrome debugger and iOS simulator.
Without react native, using regular web development localStorage, I was able to see the stored localStorage items under Chrome Debugger > Resources > Local Storage
Any idea how can I view the React Native AsyncStorage stored items?
React Native Debugger has this built in.
Just call showAsyncStorageContentInDev() in the RND console and you'll be able to see a dump of your app's storage.
You can use reactotron i think it has Async Storage explorer ;)
https://github.com/infinitered/reactotron
Following should work,
AsyncStorage.getAllKeys((err, keys) => {
AsyncStorage.multiGet(keys, (error, stores) => {
stores.map((result, i, store) => {
console.log({ [store[i][0]]: store[i][1] });
return true;
});
});
});
I have created a helper method to log all Storage in a single object (more clean to log for example in Reactotron):
import AsyncStorage from '#react-native-community/async-storage';
export function logCurrentStorage() {
AsyncStorage.getAllKeys().then((keyArray) => {
AsyncStorage.multiGet(keyArray).then((keyValArray) => {
let myStorage: any = {};
for (let keyVal of keyValArray) {
myStorage[keyVal[0]] = keyVal[1]
}
console.log('CURRENT STORAGE: ', myStorage);
})
});
}
react native debugger
right click on free space
With bluebird you can do this:
const dumpRaw = () => {
return AsyncStorage.getAllKeys().then(keys => {
return Promise.reduce(keys, (result, key) => {
return AsyncStorage.getItem(key).then(value => {
result[key] = value;
return result;
});
}, {});
});
};
dumpRaw().then(data => console.log(data));
Maybe late, but none of these solutions fit for me.
On android, with Android Studio open file explorer then go to data/data/your_package_name
Inside you should have a folder called database and inside a file RKStorage.
This file is a SQLite3 file so get your favorite SQLite explorer and explore. If you want one this one does the job : DB Browser for SQLite
I did not find Reactotron to have any type of pretty printing enabled and it's also brutally latent so I just wrote a simple function using lodash. You could use underscore too.
Assuming you have a static mapping of all your keys...
const keys = {
key1: 'key1',
key2: 'key2'
}
export function printLocalStorage() {
_.forEach(keys, (k, v) => {
localStore.getAllDataForKey(v).then(tree => {
console.log(k) // Logs key above the object
console.log(tree) // Logs a pretty printed JSON object
})
})
}
It's not performant but it solves the problem.
You can Define function to get all keys by using async and await
getAllkeys = () => {
return new Promise( async (resolve, reject) => {
try {
let keys = await AsyncStorage.getAllKeys();
let items = await AsyncStorage.multiGet(keys)
resolve(items)
} catch (error) {
reject(new Error('Error getting items from AsyncStorage: ' + error.message))
}
});
}
somefunc = async () => {
try {
var items = await getAllkeys();
var someItems = items.filter(function (result, i, item) {
// do filtering stuff
return item;
});
// do something with filtered items
} catch (error) {
// do something with your error
}
}
I have a expo snack that shows this and also performs a "load". So it is useful for doing a dump of the contents and storing it to a file and loading it up later.
Here are they parts.
const keys = await AsyncStorage.getAllKeys();
const stores = await AsyncStorage.multiGet(keys);
const data = stores.reduce(
(acc, row) => ({ ...acc, [row[0]]: row[1] }),
{}
);
// data now contains a JSONable Javascript object that contains all the data
This ammends the data in the AsyncStorage from a JSON string.
// sample is a JSON string
const data = JSON.parse(sample);
const keyValuePairs = Object.entries(data)
.map(([key, value]) => [key, value])
.reduce((acc, row) => [...acc, row], []);
await AsyncStorage.multiSet(keyValuePairs);
import AsyncStorage from "#react-native-async-storage/async-storage";
export const printAsyncStorage = () => {
AsyncStorage.getAllKeys((err, keys) => {
AsyncStorage.multiGet(keys, (error, stores) => {
let asyncStorage = {}
stores.map((result, i, store) => {
asyncStorage[store[i][0]] = store[i][1]
});
console.table(asyncStorage)
});
});
};
enter image description here

How to test an Electron app with selenium webdriver

I have read the documentation and I have followed the tutorial step by step and I only have managed to run the app.
Documentation: http://electron.atom.io/docs/tutorial/using-selenium-and-webdriver/
The connection with chromedriver I cannot make it work, when I launch the test and try click a simple button I get this:
Error: ChromeDriver did not start within 5000ms at Error (native)
at node_modules/spectron/lib/chrome-driver.js:58:25 at
Request._callback (node_modules/spectron/lib/chrome-driver.js:116:45)
at Request.self.callback
(node_modules/spectron/node_modules/request/request.js:200:22) at
Request.
(node_modules/spectron/node_modules/request/request.js:1067:10) at
IncomingMessage.
(node_modules/spectron/node_modules/request/request.js:988:12) at
endReadableNT (_stream_readable.js:913:12) at _combinedTickCallback
(internal/process/next_tick.js:74:11) at process._tickCallback
(internal/process/next_tick.js:98:9)
My code:
"use strict";
require("co-mocha");
var Application = require('spectron').Application;
var assert = require('assert');
const webdriver = require('selenium-webdriver');
const driver = new webdriver.Builder()
.usingServer('http://127.0.0.1:9515')
.withCapabilities({
chromeOptions: {
binary: "./appPath/app"
}
})
.forBrowser('electron')
.build();
describe('Application launch', function () {
this.timeout(100000);
var app;
beforeEach(function () {
app = new Application({
path: "./appPath/app"
});
return app.start();
});
afterEach(function () {
if (app && app.isRunning()) {
return app.stop();
}
});
it('click a button', function* () {
yield driver.sleep(5000);
yield driver.findElement(webdriver.By.css(".classSelector")).click();
});
});
Thanks and sorry for my English.
I recommend you to use Spectron. which is a less painful way of testing your electron app. in my opinion perfect combination is using it with Ava test framework, which allows the concurrently test.
async & await is also another big win. which allows you to have so clean test cases.
and also if you have a test which needs to happen serial, you can use test.serial
test.serial('login as new user', async t => {
let app = t.context.app
app = await loginNewUser(app)
await util.screenshotCreateOrCompare(app, t, 'new-user-mission-view-empty')
})
test.serial('Can Navigate to Preference Page', async t => {
let app = t.context.app
await app.client.click('[data-test="preference-button"]')
await util.screenshotCreateOrCompare(app, t, 'new-user-preference-page-empty')
})
and just for reference; my helper test cases.
test.before(async t => {
app = util.createApp()
app = await util.waitForLoad(app, t)
})
test.beforeEach(async t => {
t.context.app = app
})
test.afterEach(async t => {
console.log('test complete')
})
// CleanUp
test.after.always(async t => {
// This runs after each test and other test hooks, even if they
failed
await app.client.localStorage('DELETE', 'user')
console.log('delete all files')
const clean = await exec('rm -rf /tmp/DesktopTest')
await clean.stdout.on('data', data => {
console.log(util.format('clean', data))
})
await app.client.close()
await app.stop()
})
util function,
// Returns a promise that resolves to a Spectron Application once the app has loaded.
// Takes a Ava test. Makes some basic assertions to verify that the app loaded correctly.
function createApp (t) {
return new Application({
path: path.join(__dirname, '..', 'node_modules', '.bin',
'electron' + (process.platform === 'win32' ? '.cmd' : '')),
// args: ['-r', path.join(__dirname, 'mocks.js'), path.join(__dirname, '..')],
env: {NODE_ENV: 'test'},
waitTimeout: 10e3
})
}
First off, Spectron (which is a wrapper for WebdriverIO) and WebdriverJS (which is part of Selenium-Webdriver) are two different frameworks, you only need to use one of them for your tests.
If you are using WebdriverJS, then you need to run ./node_modules/.bin/chromedriver in this step: http://electron.atom.io/docs/tutorial/using-selenium-and-webdriver/#start-chromedriver
I could get ChromeDriver working by adding a proxy exception in my terminal.
export {no_proxy,NO_PROXY}="127.0.0.1"