Turning on logging of the Mapnik SQL query during map rendering - node.js

I am using the npm package Mapnik with PostGIS and I want to enable logging to the console of the SQL query that Mapnik is executing, including the value of the bbox parameter, when running the render() function.
import * as mapnik from "mapnik";
async function main() {
mapnik.register_default_input_plugins();
mapnik.settings.log.level = "debug"; // something like that???
...
const vectorTile = new VectorTile(parseInt(z), parseInt(x), parseInt(y));
const map = new Map(256, 256);
new RouteLayer(vectorTile).apply(map);
map.zoomAll();
map.render(vectorTile, (err, vectorTile) => { // how to log executed sql query?
if (err) {
return rej(err);
}
return res(vectorTile.getData());
});
}
main();
...
// RouteLayer
private apply(map: mapnik.Map): void {
const config = this.createPostgisConfig(`
select
id,
geometry
from nordic_sector
where
deleted_at is null
and st_intersects(st_transform(geometry, 3857),!bbox!)
`);
const layer = new (mapnik as any).Layer(
"nordic-sector-back",
PROJECTION_3857
);
layer.datasource = new mapnik.Datasource(config);
(map as any).add_layer(layer);
}
EDIT1:
Unsuccessful attempts:
(mapnik as any).logger.set_severity((mapnik as any).severity_type.Debug);
(mapnik as any).Logger.setSeverity((mapnik as any).Logger.DEBUG);

In Mapnik you can configure the default logging severity level like this:
mapnik.logger.set_severity(mapnik.severity_type.Debug)

Related

How to solve react-hydration-error in Next.js when using `useLocalStorage` and `useDebounce`

When I try to use https://usehooks-ts.com/react-hook/use-local-storage in Next.js in the following way, I get
Unhandled Runtime Error Error: Text content does not match
server-rendered HTML.
See more info here:
https://nextjs.org/docs/messages/react-hydration-error
const [toleranceH, setToleranceH] = useLocalStorage<number>('toleranceH', 3);
const [toleranceS, setToleranceS] = useLocalStorage<number>('toleranceS', 3);
const [toleranceL, setToleranceL] = useLocalStorage<number>('toleranceL', 3);
const [results, setResults] = useState<MegaColor[]>([]);
const debouncedToleranceH = useDebounce<number>(toleranceH, 200);
const debouncedToleranceS = useDebounce<number>(toleranceS, 200);
const debouncedToleranceL = useDebounce<number>(toleranceL, 200);
useEffect(() => {
const targetColorDetailsObject = getColorDetailsObject(targetColor);
const degreeTolerance = (360 / 100) * debouncedToleranceH;
const [hueMin, hueMax] = getHueTolerance(targetColorDetailsObject.hue(), degreeTolerance);
const filteredColors = getFilteredColors(targetColorDetailsObject, loadedMegaColors, hueMin, hueMax, debouncedToleranceS, debouncedToleranceL);
setResults(filteredColors);
return () => {
// console.log('cleanup');
};
}, [targetColor, loadedMegaColors, debouncedToleranceH, debouncedToleranceS, debouncedToleranceL]);
From that help page, I still can't figure out what to adjust so that I can use both useLocalStorage and useDebounce.
I found https://stackoverflow.com/a/73411103/470749 but don't want to forcefully set a localStorage value (it should only be set by the user).
I'd suggest checking out this excellent post on rehydration by Josh W Comeau.
Since Next.js pre-renders every page by default you need to ensure that the component in which you are calling window.localstorage is only rendered on the client.
A simple solution is to:
Keep a hasMounted state
const [hasMounted, setHasMounted] = useState(false);
Toggle it inside a useEffect
useEffect(() => {
// This will only be called once the component is mounted inside the browser
setHasMounted(true);
}, []);
Add a check so that Next.js won't complain about prerendering stuff on the server that won't match the stuff that gets rendered on the client
if (!hasMounted) {
return null;
}
Ensure that the client-side stuff comes after the check
To make it more reusable you could use one of these two methods which essentially do the same:
ClientOnly Component
function ClientOnly({ children, ...delegated }) {
const [hasMounted, setHasMounted] = React.useState(false);
React.useEffect(() => {
setHasMounted(true);
}, []);
if (!hasMounted) {
return null;
}
/**
* Could also replace the <div></div> with
* <></> and remove ...delegated if no need
*/
return (
<div {...delegated}>
{children}
</div>
);
}
...
<ClientOnly>
<MyComponent /> // <--- client only stuff, safe to use useLocalStorage in here
</ClientOnly>
or
Custom useHasMounted hook
function useHasMounted() {
const [hasMounted, setHasMounted] = React.useState(false);
React.useEffect(() => {
setHasMounted(true);
}, []);
return hasMounted;
}
...
function ParentComponent() {
const hasMounted = useHasMounted();
if (!hasMounted) {
return null;
}
return (
<MyComponent />
);
}
...
function MyComponent() {
const [toleranceH, setToleranceH] = useLocalStorage<number>('toleranceH', 3);
const [toleranceS, setToleranceS] = useLocalStorage<number>('toleranceS', 3);
const [toleranceL, setToleranceL] = useLocalStorage<number>('toleranceL', 3);
...
}
...
Note:
By overdoing this or using this method at the top level of your component tree, you are killing the Next.js prerendering capabilities and turning your app into more of a "client-side heavy" app (see performance implications). If you are using window.localstorage (outside of components, where you don't have useEffect available), you should always wrap with:
if (typeof window !== 'undefined') {
// client-side code
}

Firebase Cloud Functions with TypeScript: Realtime Database update ends with success but not updates anything, JS works fine

I added Cloud Functions to Firebase project with Firebase CLI. I have started with JavaScript, managed to write working code.
Then I decided to switch to TypeScript. So I decided to delete all Cloud Functions JS related files and start with firebase init cmd from scratch. I copied code from index.js to index.ts, needed only to change how dataMap Map was declared.
So, now whenever I look into console logs on Firebase, everything seems to work fine, everything is logged out, and I'm getting success message on client side.
However nothing happens in Realtime Database, no update, no trace of any data.
I know almost nothing about JS / TS, so every suggestion about code and solution is welcomed.
I'm using node: 14.17.6 and updated firebase-tools to 9.18.0, firebase-admin to 9.11.1 and firebase-functions to 3.15.6.
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
admin.initializeApp();
exports.createItemWithVIP = functions.region("europe-west1").
https.onCall((data, context) => {
// Checking that the user is authenticated.
if (!context.auth) {
console.log("Unauthenticated request");
throw new functions.https.HttpsError("permission-denied", "You have" +
" no permission to perform this operation");
}
// item details
const foo = data.foo;
const bar = data.bar;
console.log(`foo: ${foo}, bar: ${bar}`);
const userUID = context.auth.uid;
console.log(`userUID: ${userUID}`);
const db = admin.database();
// get new item uid
const somePathTableReference = db.ref("somePath/").push();
const itemUID = `${somePathTableReference}`
.split("somePath/")[1];
console.log(`itemUID: ${itemUID}`);
const itemPath = `somePath/${itemUID}`;
const userPath = `users/${userUID}/somePath/${itemUID}`;
const dataMap = new Map<string, unknown>();
dataMap.set(`${itemPath}/vip/${userUID}`, true);
dataMap.set(`${itemPath}/foo`, foo);
dataMap.set(`${itemPath}/bar`, bar);
dataMap.set(`${userPath}/role`, "vip");
dataMap.set(`${userPath}/foo`, foo);
dataMap.set(`${userPath}bar`, bar);
dataMap.forEach((value: unknown, key: string) =>
console.log(key, value));
return db.ref("/").update(dataMap).then(() => {
console.log(`Added new item with key: ${itemUID} ` +
`; added vip role to user ${userUID}`);
return {"message": "Success"};
}).catch((e) => {
console.log(`Error: ${e}`);
throw new functions.https.HttpsError("unknown", "Unknown error" +
"occured");
});
});
I'm not totally sure about the reason but updating with an object directly instead of new Map() seems to be working (and yes, it didn't work for me with a Map):
const dMap = {
[`${itemPath}/vip/${userUID}`]: true,
[`${itemPath}/foo`]: foo,
[`${itemPath}/bar`]: bar,
[`${userPath}/role`]: "vip",
[`${userPath}/foo`]: foo,
[`${userPath}bar`]: bar
}
try {
await db.ref("/").update(dMap);
console.log(`Added new item with key: ${itemUID}; added vip role to user ${userUID}`);
return {"message": "Success"};
} catch (e) {
console.log(`Error: ${e}`);
throw new functions.https.HttpsError("unknown", "Unknown error" +
"occured");
}
This works for me.
const dMap: { [key: string]: any; } = {};
dMap[`${itemPath}/vip/${userUID}`]= true;
dMap[`${itemPath}/foo`]= foo;
dMap[`${itemPath}/bar`]= bar;
dMap[`${userPath}/role`]= "vip";
dMap[`${userPath}/foo`]= foo;
dMap[`${userPath}bar`]= bar;
db.ref().update(dMap);

can not get cascade DDS value for SharedObjectSequence

I have a test like this, but i can not get the 'sharedMap' in 'sharedSeq1' value, i don't know how to get the 'remoteFluidObjectHandle' value.
import {MockContainerRuntimeFactory, MockFluidDataStoreRuntime, MockStorage} from "#fluidframework/test-runtime-utils";
import {SharedObjectSequence, SharedObjectSequenceFactory} from "#fluidframework/sequence";
import * as mocks from "#fluidframework/test-runtime-utils";
import {SharedMap} from "#fluidframework/map";
import {IFluidHandle} from "#fluidframework/core-interfaces";
const mockRuntime: mocks.MockFluidDataStoreRuntime = new mocks.MockFluidDataStoreRuntime();
describe('ShredObjectSequence', function () {
it('should get synchronization data from another shared object', async function () {
const dataStoreRuntime1 = new MockFluidDataStoreRuntime();
const sharedSeq1: SharedObjectSequence<IFluidHandle<SharedMap>> = new SharedObjectSequence(mockRuntime, 'shareObjectSeq1', SharedObjectSequenceFactory.Attributes,)
const containerRuntimeFactory = new MockContainerRuntimeFactory();
dataStoreRuntime1.local = false;
const containerRuntime1 = containerRuntimeFactory.createContainerRuntime(
dataStoreRuntime1,
);
const services1 = {
deltaConnection: containerRuntime1.createDeltaConnection(),
objectStorage: new MockStorage(),
};
sharedSeq1.initializeLocal();
sharedSeq1.connect(services1);
const dataStoreRuntime2 = new MockFluidDataStoreRuntime();
const containerRuntime2 = containerRuntimeFactory.createContainerRuntime(
dataStoreRuntime2,
);
const services2 = {
deltaConnection: containerRuntime2.createDeltaConnection(),
objectStorage: new MockStorage(),
};
const sharedSeq2: SharedObjectSequence<IFluidHandle<SharedMap>> = new SharedObjectSequence(mockRuntime, 'shareObjectSeq2', SharedObjectSequenceFactory.Attributes,)
sharedSeq2.initializeLocal();
sharedSeq2.connect(services2);
// insert a node into sharedSeq2, it will sync to sharedSeq1
sharedSeq2.insert(0, [<IFluidHandle<SharedMap>>new SharedMap('sharedMapId', mockRuntime, SharedMap.getFactory().attributes).handle])
containerRuntimeFactory.processAllMessages();
// next case is passed, it show we got the sharedSeq2 changed
expect(sharedSeq1.getLength()).toBe(1)
const remoteFluidObjectHandle = await sharedSeq1.getRange(0, 1)[0];
// at here, i get error: Cannot read property 'mimeType' of null, it cause by remoteFluidObjectHandle.ts:51:30
const sharedMap = await remoteFluidObjectHandle.get()
expect(sharedMap).not.toBeUndefined()
});
});
run this test will get 'Cannot read property 'mimeType' of null' error, it caused by 'remoteFluidObjectHandle.ts:51:30'
The fluid mocks have very limited and specific behaviors, it looks like you are hitting the limits of them. You'll have better luck with an end-to-end test, see packages\test\end-to-end-tests. These use the same in-memory server as our as the playground on fluidframework dot com. The in-memory server uses the same code as tinylicious, our single process server and routerlicious, our docker based reference implementation.

How to run adonis command in ace command file

const { Command } = require('#adonisjs/ace')
const util = require('util')
const execSync = util.promisify(require('child_process').execSync)
const defaultSeedOrder = []
class SeedSync extends Command {
static get signature () {
return `seed:sync
{
order? : Comma separated of seeds
}`
}
static get description () {
return 'Seeds based on a list instead of running all seeds async.'
}
handle (args, options) {
let seedOrder;
if (args.order !== null) {
seedOrder = args.order.split(/=(.+)/)[1].split(',')
} else {
seedOrder = defaultSeedOrder
}
for (const seed of seedOrder) {
console.log(seed)
execSync(`adonis seed --files='${seed}'`, (e, stdout, stderr) => {
if (!stdout.includes('Seeded database in')) {
this.error(`${this.icon('error')} Error: `)
}
console.log(stdout)
})
}
}
}
module.exports = SeedSync
I want an ace command to run seed sequentially, I have copied this code from here:Link to the original code
But it doesnt seem to work at all for me.
Any help will be much appreciated, Thank you
The problem is with these 2 blocks.
This signature needs to be like this to work and get the order variable correctly:
static get signature () {
return `
seed:sync
{ --order=#value: Run only selected files }
`
}
AND
const exec = execSync(`adonis seed --files='${seed}' --force`, {stdio: 'inherit'})
Remove the commas on --files='${seed}' so that it reads --files=${seed}
Because on the terminal, we call the command using adonis seed:sync --order='' (this single comma is passed to adonis Seed.js and causes the error "Nothing to Seed")

How to solve Converting circular structure to JSON in node?

I was watching a course that showed how to make an console.log with custom configs, like the color or depending on your env mode, you show the log or not.
But i keep getting the error TypeError: Converting circular structure to JSON
and I don't know why this is happening and how to solve it.
In the course, that works fine, but it doesn't to me.
node version => v8.11.2
require('colors')
const _ = require('lodash')
const config = require('../config/config')
const noop = () => { }
const consoleLog = config.logging ? console.log.bind(console) : noop
const logger = {
log: () => {
const args = _.toArray(arguments)
.map(arg => {
if (typeof arg === 'object') {
let str = JSON.stringify(arg, 2)
return str.magenta
} else {
arg += ''
return arg.magenta
}
})
consoleLog.apply(console, args)
}
}
module.exports = logger
Edit1: arguments can be anything, since logger will be used to log things with different colors in the console.
logger.log('some thing you want to log')
logger.log() is an arrow function, so arguments are not arguments of this function (see Arrow functions: No binding of arguments), but arguments of a parent function, in this case — Node.js wrapper function that compiles modules and has arguments with circular dependencies.
Try to use common function here:
const logger = {
log() {
// ...
}
};

Resources